lib/gssapi/krb5: implement GSS_C_CHANNEL_BOUND_FLAG for gss_init_sec_context()
[heimdal.git] / lib / krb5 / store_fd.c
blob9184e593ab68c46fea97d6c4786f9e24b05a905e
1 /*
2 * Copyright (c) 1997 - 2017 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
4 * All rights reserved.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
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.
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.
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.
34 #include "krb5_locl.h"
35 #include "store-int.h"
37 typedef struct fd_storage {
38 int fd;
39 } fd_storage;
41 #define FD(S) (((fd_storage*)(S)->data)->fd)
43 static ssize_t
44 fd_fetch(krb5_storage * sp, void *data, size_t size)
46 char *cbuf = (char *)data;
47 ssize_t count;
48 size_t rem = size;
50 /* similar pattern to net_read() to support pipes */
51 while (rem > 0) {
52 count = read (FD(sp), cbuf, rem);
53 if (count < 0) {
54 if (errno == EINTR)
55 continue;
56 else if (rem == size)
57 return count;
58 else
59 return size - rem;
60 } else if (count == 0) {
61 return count;
63 cbuf += count;
64 rem -= count;
66 return size;
69 static ssize_t
70 fd_store(krb5_storage * sp, const void *data, size_t size)
72 const char *cbuf = (const char *)data;
73 ssize_t count;
74 size_t rem = size;
76 /* similar pattern to net_write() to support pipes */
77 while (rem > 0) {
78 count = write(FD(sp), cbuf, rem);
79 if (count < 0) {
80 if (errno == EINTR)
81 continue;
82 else
83 return size - rem;
85 cbuf += count;
86 rem -= count;
88 return size;
91 static off_t
92 fd_seek(krb5_storage * sp, off_t offset, int whence)
94 return lseek(FD(sp), offset, whence);
97 static int
98 fd_trunc(krb5_storage * sp, off_t offset)
100 off_t tmpoff;
102 if (ftruncate(FD(sp), offset) == -1)
103 return errno;
105 tmpoff = lseek(FD(sp), 0, SEEK_CUR);
106 if (tmpoff == -1)
107 return errno;
109 if (tmpoff > offset) {
110 tmpoff = lseek(FD(sp), offset, SEEK_SET);
111 if (tmpoff == -1)
112 return errno;
115 return 0;
118 static int
119 fd_sync(krb5_storage * sp)
121 if (fsync(FD(sp)) == -1)
122 return errno;
123 return 0;
126 static void
127 fd_free(krb5_storage * sp)
129 int save_errno = errno;
130 if (close(FD(sp)) == 0)
131 errno = save_errno;
137 * @return A krb5_storage on success, or NULL on out of memory error.
139 * @ingroup krb5_storage
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()
148 KRB5_LIB_FUNCTION krb5_storage * KRB5_LIB_CALL
149 krb5_storage_from_fd(int fd_in)
151 krb5_storage *sp;
152 int saved_errno;
153 int fd;
155 #ifdef _MSC_VER
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.
163 fd = _dup(fd_in);
164 #else
165 fd = dup(fd_in);
166 #endif
168 if (fd < 0)
169 return NULL;
171 errno = ENOMEM;
172 sp = malloc(sizeof(krb5_storage));
173 if (sp == NULL) {
174 saved_errno = errno;
175 close(fd);
176 errno = saved_errno;
177 return NULL;
180 errno = ENOMEM;
181 sp->data = malloc(sizeof(fd_storage));
182 if (sp->data == NULL) {
183 saved_errno = errno;
184 close(fd);
185 free(sp);
186 errno = saved_errno;
187 return NULL;
189 sp->flags = 0;
190 sp->eof_code = HEIM_ERR_EOF;
191 FD(sp) = fd;
192 sp->fetch = fd_fetch;
193 sp->store = fd_store;
194 sp->seek = fd_seek;
195 sp->trunc = fd_trunc;
196 sp->fsync = fd_sync;
197 sp->free = fd_free;
198 sp->max_alloc = UINT32_MAX/64;
199 return sp;