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 39typedef struct fd_storage { 40 int fd; 41} fd_storage; 42 43#define FD(S) (((fd_storage*)(S)->data)->fd) 44 45static ssize_t 46fd_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 69static ssize_t 70fd_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 91static off_t 92fd_seek(krb5_storage * sp, off_t offset, int whence) 93{ 94 return lseek(FD(sp), offset, whence); 95} 96 97static int 98fd_trunc(krb5_storage * sp, off_t offset) 99{ 100 if (ftruncate(FD(sp), offset) == -1) 101 return errno; 102 return 0; 103} 104 105static int 106fd_sync(krb5_storage * sp) 107{ 108 if (fsync(FD(sp)) == -1) 109 return errno; 110 return 0; 111} 112 113static void 114fd_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 135KRB5_LIB_FUNCTION krb5_storage * KRB5_LIB_CALL 136krb5_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