Line data Source code
1 : /*
2 : * Copyright (c) 1997 - 2017 Kungliga Tekniska Högskolan
3 : * (Royal Institute of Technology, Stockholm, Sweden).
4 : * All rights reserved.
5 : *
6 : * Redistribution and use in source and binary forms, with or without
7 : * modification, are permitted provided that the following conditions
8 : * are met:
9 : *
10 : * 1. Redistributions of source code must retain the above copyright
11 : * notice, this list of conditions and the following disclaimer.
12 : *
13 : * 2. Redistributions in binary form must reproduce the above copyright
14 : * notice, this list of conditions and the following disclaimer in the
15 : * documentation and/or other materials provided with the distribution.
16 : *
17 : * 3. Neither the name of the Institute nor the names of its contributors
18 : * may be used to endorse or promote products derived from this software
19 : * without specific prior written permission.
20 : *
21 : * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22 : * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 : * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 : * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25 : * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 : * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 : * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 : * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 : * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 : * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 : * SUCH DAMAGE.
32 : */
33 :
34 : #include "krb5_locl.h"
35 : #include "store-int.h"
36 :
37 : typedef struct fd_storage {
38 : int fd;
39 : } fd_storage;
40 :
41 : #define FD(S) (((fd_storage*)(S)->data)->fd)
42 :
43 : static ssize_t
44 0 : fd_fetch(krb5_storage * sp, void *data, size_t size)
45 : {
46 0 : char *cbuf = (char *)data;
47 0 : ssize_t count;
48 0 : size_t rem = size;
49 :
50 : /* similar pattern to net_read() to support pipes */
51 0 : while (rem > 0) {
52 0 : count = read (FD(sp), cbuf, rem);
53 0 : if (count < 0) {
54 0 : if (errno == EINTR)
55 0 : continue;
56 0 : else if (rem == size)
57 0 : return count;
58 : else
59 0 : return size - rem;
60 0 : } else if (count == 0) {
61 0 : return count;
62 : }
63 0 : cbuf += count;
64 0 : rem -= count;
65 : }
66 0 : return size;
67 : }
68 :
69 : static ssize_t
70 0 : fd_store(krb5_storage * sp, const void *data, size_t size)
71 : {
72 0 : const char *cbuf = (const char *)data;
73 0 : ssize_t count;
74 0 : size_t rem = size;
75 :
76 : /* similar pattern to net_write() to support pipes */
77 0 : while (rem > 0) {
78 0 : count = write(FD(sp), cbuf, rem);
79 0 : if (count < 0) {
80 0 : if (errno == EINTR)
81 0 : continue;
82 : else
83 0 : return size - rem;
84 : }
85 0 : cbuf += count;
86 0 : rem -= count;
87 : }
88 0 : return size;
89 : }
90 :
91 : static off_t
92 0 : fd_seek(krb5_storage * sp, off_t offset, int whence)
93 : {
94 0 : return lseek(FD(sp), offset, whence);
95 : }
96 :
97 : static int
98 0 : fd_trunc(krb5_storage * sp, off_t offset)
99 : {
100 0 : off_t tmpoff;
101 :
102 0 : if (ftruncate(FD(sp), offset) == -1)
103 0 : return errno;
104 :
105 0 : tmpoff = lseek(FD(sp), 0, SEEK_CUR);
106 0 : if (tmpoff == -1)
107 0 : return errno;
108 :
109 0 : if (tmpoff > offset) {
110 0 : tmpoff = lseek(FD(sp), offset, SEEK_SET);
111 0 : if (tmpoff == -1)
112 0 : return errno;
113 : }
114 :
115 0 : return 0;
116 : }
117 :
118 : static int
119 0 : fd_sync(krb5_storage * sp)
120 : {
121 0 : if (fsync(FD(sp)) == -1)
122 0 : return errno;
123 0 : return 0;
124 : }
125 :
126 : static void
127 0 : fd_free(krb5_storage * sp)
128 : {
129 0 : int save_errno = errno;
130 0 : if (close(FD(sp)) == 0)
131 0 : errno = save_errno;
132 0 : }
133 :
134 : /**
135 : *
136 : *
137 : * @return A krb5_storage on success, or NULL on out of memory error.
138 : *
139 : * @ingroup krb5_storage
140 : *
141 : * @sa krb5_storage_emem()
142 : * @sa krb5_storage_from_mem()
143 : * @sa krb5_storage_from_readonly_mem()
144 : * @sa krb5_storage_from_data()
145 : * @sa krb5_storage_from_socket()
146 : */
147 :
148 : KRB5_LIB_FUNCTION krb5_storage * KRB5_LIB_CALL
149 0 : krb5_storage_from_fd(int fd_in)
150 : {
151 0 : krb5_storage *sp;
152 0 : int saved_errno;
153 0 : int fd;
154 :
155 : #ifdef _MSC_VER
156 : /*
157 : * This function used to try to pass the input to
158 : * _get_osfhandle() to test if the value is a HANDLE
159 : * but this doesn't work because doing so throws an
160 : * exception that will result in Watson being triggered
161 : * to file a Windows Error Report.
162 : */
163 : fd = _dup(fd_in);
164 : #else
165 0 : fd = dup(fd_in);
166 : #endif
167 :
168 0 : if (fd < 0)
169 0 : return NULL;
170 :
171 0 : errno = ENOMEM;
172 0 : sp = malloc(sizeof(krb5_storage));
173 0 : if (sp == NULL) {
174 0 : saved_errno = errno;
175 0 : close(fd);
176 0 : errno = saved_errno;
177 0 : return NULL;
178 : }
179 :
180 0 : errno = ENOMEM;
181 0 : sp->data = malloc(sizeof(fd_storage));
182 0 : if (sp->data == NULL) {
183 0 : saved_errno = errno;
184 0 : close(fd);
185 0 : free(sp);
186 0 : errno = saved_errno;
187 0 : return NULL;
188 : }
189 0 : sp->flags = 0;
190 0 : sp->eof_code = HEIM_ERR_EOF;
191 0 : FD(sp) = fd;
192 0 : sp->fetch = fd_fetch;
193 0 : sp->store = fd_store;
194 0 : sp->seek = fd_seek;
195 0 : sp->trunc = fd_trunc;
196 0 : sp->fsync = fd_sync;
197 0 : sp->free = fd_free;
198 0 : sp->max_alloc = UINT32_MAX/64;
199 0 : return sp;
200 : }
|