]> git.saurik.com Git - apple/security.git/blob - utilities/SecurityTool/readline.c
Security-55471.14.tar.gz
[apple/security.git] / utilities / SecurityTool / readline.c
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. */
39 char *
40 readline(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. */
84 int
85 read_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
153 loser:
154 if (buffer)
155 free(buffer);
156
157 return result;
158 }
159
160 CFDataRef 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;
204 badFile:
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
216 bool 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;
248 badFile:
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 }