/ SecurityTool / sharedTool / readline.c
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  }