1/* 2 * Copyright (c) 2003-2004,2006-2010 Apple Inc. All Rights Reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. Please obtain a copy of the License at 10 * http://www.opensource.apple.com/apsl/ and read it before using this 11 * file. 12 * 13 * The Original Code and all software distributed under the License are 14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 * Please see the License for the specific language governing rights and 19 * limitations under the License. 20 * 21 * @APPLE_LICENSE_HEADER_END@ 22 * 23 * readline.c 24 */ 25 26#include "readline.h" 27 28#include <errno.h> 29#include <fcntl.h> 30#include <stdio.h> 31#include <stdlib.h> 32#include <string.h> 33#include <unistd.h> 34 35/* Read a line from stdin into buffer as a null terminated string. If buffer is 36 non NULL use at most buffer_size bytes and return a pointer to buffer. Otherwise 37 return a newly malloced buffer. 38 if EOF is read this function returns NULL. */ 39char * 40readline(char *buffer, int buffer_size) 41{ 42 int ix = 0, bytes_malloced = 0; 43 44 if (!buffer) 45 { 46 bytes_malloced = 64; 47 buffer = (char *)malloc(bytes_malloced); 48 buffer_size = bytes_malloced; 49 } 50 51 for (;;++ix) 52 { 53 int ch; 54 55 if (ix == buffer_size - 1) 56 { 57 if (!bytes_malloced) 58 break; 59 bytes_malloced += bytes_malloced; 60 buffer = (char *)realloc(buffer, bytes_malloced); 61 buffer_size = bytes_malloced; 62 } 63 64 ch = getchar(); 65 if (ch == EOF) 66 { 67 if (bytes_malloced) 68 free(buffer); 69 return NULL; 70 } 71 if (ch == '\n') 72 break; 73 buffer[ix] = ch; 74 } 75 76 /* 0 terminate buffer. */ 77 buffer[ix] = '\0'; 78 79 return buffer; 80} 81 82/* Read the file name into buffer. On return buffer contains a newly 83 malloced buffer or length buffer_size. Return 0 on success and -1 on failure. */ 84int 85read_file(const char *name, uint8_t **outData, size_t *outLength) 86{ 87 int fd, result; 88 char *buffer = NULL; 89 off_t off_end; 90 ssize_t bytes_read; 91 size_t length; 92 93 do { 94 fd = open(name, O_RDONLY, 0); 95 } while (fd == -1 && errno == EINTR); 96 97 if (fd == -1) 98 { 99 fprintf(stderr, "open %s: %s", name, strerror(errno)); 100 result = -1; 101 goto loser; 102 } 103 104 off_end = lseek(fd, 0, SEEK_END); 105 if (off_end == -1) 106 { 107 fprintf(stderr, "lseek %s, SEEK_END: %s", name, strerror(errno)); 108 result = -1; 109 goto loser; 110 } 111 112 if (off_end > (off_t)SIZE_MAX) { 113 fprintf(stderr, "file %s too large %llu bytes", name, off_end); 114 result = -1; 115 goto loser; 116 } 117 118 length = (size_t)off_end; 119 buffer = malloc(length); 120 121 do { 122 bytes_read = pread(fd, buffer, length, 0); 123 } while (bytes_read == -1 && errno == EINTR); 124 125 if (bytes_read == -1) 126 { 127 fprintf(stderr, "pread %s: %s", name, strerror(errno)); 128 result = -1; 129 goto loser; 130 } 131 if (bytes_read != (ssize_t)length) 132 { 133 fprintf(stderr, "read %s: only read %zu of %zu bytes", name, bytes_read, length); 134 result = -1; 135 goto loser; 136 } 137 138 do { 139 result = close(fd); 140 } while (result == -1 && errno == EINTR); 141 142 if (result == -1) 143 { 144 fprintf(stderr, "close %s: %s", name, strerror(errno)); 145 goto loser; 146 } 147 148 *outData = (uint8_t *)buffer; 149 *outLength = length; 150 151 return result; 152 153loser: 154 if (buffer) 155 free(buffer); 156 157 return result; 158} 159 160CFDataRef copyFileContents(const char *path) { 161 CFMutableDataRef data = NULL; 162 int fd = open(path, O_RDONLY, 0666); 163 if (fd == -1) { 164 fprintf(stderr, "open %s: %s", path, strerror(errno)); 165 goto badFile; 166 } 167 168 off_t fsize = lseek(fd, 0, SEEK_END); 169 if (fsize == (off_t)-1) { 170 fprintf(stderr, "lseek %s, 0, SEEK_END: %s", path, strerror(errno)); 171 goto badFile; 172 } 173 174 if (fsize > (off_t)INT32_MAX) { 175 fprintf(stderr, "file %s too large %llu bytes", path, fsize); 176 goto badFile; 177 } 178 179 data = CFDataCreateMutable(kCFAllocatorDefault, (CFIndex)fsize); 180 CFDataSetLength(data, (CFIndex)fsize); 181 void *buf = CFDataGetMutableBytePtr(data); 182 off_t total_read = 0; 183 while (total_read < fsize) { 184 ssize_t bytes_read; 185 186 bytes_read = pread(fd, buf, (size_t)(fsize - total_read), total_read); 187 if (bytes_read == -1) { 188 fprintf(stderr, "read %s: %s", path, strerror(errno)); 189 goto badFile; 190 } 191 if (bytes_read == 0) { 192 fprintf(stderr, "read %s: unexpected end of file", path); 193 goto badFile; 194 } 195 total_read += bytes_read; 196 } 197 198 if (close(fd) == -1) { 199 fprintf(stderr, "close %s: %s", path, strerror(errno)); 200 /* Failure to close the file isn't fatal. */ 201 } 202 203 return data; 204badFile: 205 if (fd != -1) { 206 if (close(fd) == -1) { 207 fprintf(stderr, "close %s: %s", path, strerror(errno)); 208 } 209 } 210 if (data) 211 CFRelease(data); 212 return NULL; 213} 214 215 216bool writeFileContents(const char *path, CFDataRef data) { 217 int fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0666); 218 if (fd == -1) { 219 fprintf(stderr, "open %s: %s", path, strerror(errno)); 220 goto badFile; 221 } 222 223 const void *buf = CFDataGetBytePtr(data); 224 off_t fsize = CFDataGetLength(data); 225 226 off_t total_write = 0; 227 while (total_write < fsize) { 228 ssize_t bytes_write; 229 230 bytes_write = pwrite(fd, buf, (size_t)(fsize - total_write), total_write); 231 if (bytes_write == -1) { 232 fprintf(stderr, "write %s: %s", path, strerror(errno)); 233 goto badFile; 234 } 235 if (bytes_write == 0) { 236 fprintf(stderr, "write %s: unexpected end of file", path); 237 goto badFile; 238 } 239 total_write += bytes_write; 240 } 241 242 if (close(fd) == -1) { 243 fprintf(stderr, "close %s: %s", path, strerror(errno)); 244 /* Failure to close the file isn't fatal. */ 245 } 246 247 return true; 248badFile: 249 if (fd != -1) { 250 if (close(fd) == -1) { 251 fprintf(stderr, "close %s: %s", path, strerror(errno)); 252 } 253 } 254 if (data) 255 CFRelease(data); 256 return false; 257} 258