]> git.saurik.com Git - apple/security.git/blob - SecurityTool/sharedTool/readline.c
Security-59754.80.3.tar.gz
[apple/security.git] / SecurityTool / sharedTool / readline.c
1 /*
2 * Copyright (c) 2003-2004,2006-2010,2013-2014 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 /* Inspects a file's existence and size. Returns a file handle or -1 on failure */
36 int inspect_file_and_size(const char* name, off_t *out_off_end) {
37
38 int fd, result;
39 off_t off_end;
40
41 do {
42 fd = open(name, O_RDONLY, 0);
43 } while (fd == -1 && errno == EINTR);
44
45 if (fd == -1)
46 {
47 fprintf(stderr, "open %s: %s", name, strerror(errno));
48 result = -1;
49 goto loser;
50 }
51
52 off_end = lseek(fd, 0, SEEK_END);
53 if (off_end == -1)
54 {
55 fprintf(stderr, "lseek %s, SEEK_END: %s", name, strerror(errno));
56 result = -1;
57 goto loser;
58 }
59
60 if (off_end > (unsigned)SIZE_MAX) {
61 fprintf(stderr, "file %s too large %llu bytes", name, off_end);
62 result = -1;
63 goto loser;
64 }
65
66 if (out_off_end) {
67 *out_off_end = off_end;
68 }
69
70 return fd;
71
72 loser:
73 return result;
74 }
75
76
77 /* Read a line from stdin into buffer as a null terminated string. If buffer is
78 non NULL use at most buffer_size bytes and return a pointer to buffer. Otherwise
79 return a newly malloced buffer.
80 if EOF is read this function returns NULL. */
81 char *
82 readline(char *buffer, int buffer_size)
83 {
84 int ix = 0, bytes_malloced = 0;
85
86 if (!buffer)
87 {
88 bytes_malloced = 64;
89 buffer = (char *)malloc(bytes_malloced);
90 buffer_size = bytes_malloced;
91 }
92
93 for (;;++ix)
94 {
95 int ch;
96
97 if (ix == buffer_size - 1)
98 {
99 if (!bytes_malloced)
100 break;
101 bytes_malloced += bytes_malloced;
102 buffer = (char *)realloc(buffer, bytes_malloced);
103 buffer_size = bytes_malloced;
104 }
105
106 ch = getchar();
107 if (ch == EOF)
108 {
109 if (bytes_malloced)
110 free(buffer);
111 return NULL;
112 }
113 if (ch == '\n')
114 break;
115 buffer[ix] = ch;
116 }
117
118 /* 0 terminate buffer. */
119 buffer[ix] = '\0';
120
121 return buffer;
122 }
123
124 /* Read the file name into buffer. On return buffer contains a newly
125 malloced buffer or length buffer_size. Return 0 on success and -1 on failure. */
126 int
127 read_file(const char *name, uint8_t **outData, size_t *outLength)
128 {
129 int fd, result;
130 char *buffer = NULL;
131 off_t off_end;
132 ssize_t bytes_read;
133 size_t length;
134
135 if( (fd = inspect_file_and_size(name, &off_end)) == -1 ){
136 result = -1;
137 goto loser;
138 }
139
140 length = (size_t)off_end;
141 buffer = malloc(length);
142 if (buffer == NULL) {
143 result = -1;
144 goto loser;
145 }
146
147 do {
148 bytes_read = pread(fd, buffer, length, 0);
149 } while (bytes_read == -1 && errno == EINTR);
150
151 if (bytes_read == -1)
152 {
153 fprintf(stderr, "pread %s: %s", name, strerror(errno));
154 result = -1;
155 goto loser;
156 }
157 if (bytes_read != (ssize_t)length)
158 {
159 fprintf(stderr, "read %s: only read %zu of %zu bytes", name, bytes_read, length);
160 result = -1;
161 goto loser;
162 }
163
164 do {
165 result = close(fd);
166 } while (result == -1 && errno == EINTR);
167
168 if (result == -1)
169 {
170 fprintf(stderr, "close %s: %s", name, strerror(errno));
171 goto loser;
172 }
173
174 *outData = (uint8_t *)buffer;
175 *outLength = length;
176
177 return result;
178
179 loser:
180 if (buffer)
181 free(buffer);
182
183 return result;
184 }
185
186 CFDataRef copyFileContents(const char *path) {
187 CFMutableDataRef data = NULL;
188 int fd = open(path, O_RDONLY, 0666);
189 if (fd == -1) {
190 fprintf(stderr, "open %s: %s", path, strerror(errno));
191 goto badFile;
192 }
193
194 off_t fsize = lseek(fd, 0, SEEK_END);
195 if (fsize == (off_t)-1) {
196 fprintf(stderr, "lseek %s, 0, SEEK_END: %s", path, strerror(errno));
197 goto badFile;
198 }
199
200 if (fsize > (off_t)INT32_MAX) {
201 fprintf(stderr, "file %s too large %llu bytes", path, fsize);
202 goto badFile;
203 }
204
205 data = CFDataCreateMutable(kCFAllocatorDefault, (CFIndex)fsize);
206 CFDataSetLength(data, (CFIndex)fsize);
207 void *buf = CFDataGetMutableBytePtr(data);
208 off_t total_read = 0;
209 while (total_read < fsize) {
210 ssize_t bytes_read;
211
212 bytes_read = pread(fd, buf, (size_t)(fsize - total_read), total_read);
213 if (bytes_read == -1) {
214 fprintf(stderr, "read %s: %s", path, strerror(errno));
215 goto badFile;
216 }
217 if (bytes_read == 0) {
218 fprintf(stderr, "read %s: unexpected end of file", path);
219 goto badFile;
220 }
221 total_read += bytes_read;
222 }
223
224 if (close(fd) == -1) {
225 fprintf(stderr, "close %s: %s", path, strerror(errno));
226 /* Failure to close the file isn't fatal. */
227 }
228
229 return data;
230 badFile:
231 if (fd != -1) {
232 if (close(fd) == -1) {
233 fprintf(stderr, "close %s: %s", path, strerror(errno));
234 }
235 }
236 if (data)
237 CFRelease(data);
238 return NULL;
239 }
240
241
242 bool writeFileContents(const char *path, CFDataRef data) {
243 int fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0666);
244 if (fd == -1) {
245 fprintf(stderr, "open %s: %s", path, strerror(errno));
246 goto badFile;
247 }
248
249 const void *buf = CFDataGetBytePtr(data);
250 off_t fsize = CFDataGetLength(data);
251
252 off_t total_write = 0;
253 while (total_write < fsize) {
254 ssize_t bytes_write;
255
256 bytes_write = pwrite(fd, buf, (size_t)(fsize - total_write), total_write);
257 if (bytes_write == -1) {
258 fprintf(stderr, "write %s: %s", path, strerror(errno));
259 goto badFile;
260 }
261 if (bytes_write == 0) {
262 fprintf(stderr, "write %s: unexpected end of file", path);
263 goto badFile;
264 }
265 total_write += bytes_write;
266 }
267
268 if (close(fd) == -1) {
269 fprintf(stderr, "close %s: %s", path, strerror(errno));
270 /* Failure to close the file isn't fatal. */
271 }
272
273 return true;
274 badFile:
275 if (fd != -1) {
276 if (close(fd) == -1) {
277 fprintf(stderr, "close %s: %s", path, strerror(errno));
278 }
279 }
280 if (data)
281 CFRelease(data);
282 return false;
283 }