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