diff options
Diffstat (limited to 'libbb')
-rw-r--r-- | libbb/read.c | 132 |
1 files changed, 56 insertions, 76 deletions
diff --git a/libbb/read.c b/libbb/read.c index 405e216dc..e67bbfb7e 100644 --- a/libbb/read.c +++ b/libbb/read.c @@ -106,7 +106,7 @@ ssize_t FAST_FUNC full_read(int fd, void *buf, size_t len) return total; } -// Die with an error message if we can't read the entire buffer. +/* Die with an error message if we can't read the entire buffer. */ void FAST_FUNC xread(int fd, void *buf, size_t count) { if (count) { @@ -116,7 +116,7 @@ void FAST_FUNC xread(int fd, void *buf, size_t count) } } -// Die with an error message if we can't read one character. +/* Die with an error message if we can't read one character. */ unsigned char FAST_FUNC xread_char(int fd) { char tmp; @@ -124,7 +124,7 @@ unsigned char FAST_FUNC xread_char(int fd) return tmp; } -// Read one line a-la fgets. Works only on seekable streams +/* Read one line a-la fgets. Works only on seekable streams */ char* FAST_FUNC reads(int fd, char *buffer, size_t size) { char *p; @@ -140,9 +140,9 @@ char* FAST_FUNC reads(int fd, char *buffer, size_t size) if (p) { off_t offset; *p++ = '\0'; - // avoid incorrect (unsigned) widening + /* avoid incorrect (unsigned) widening */ offset = (off_t)(p - buffer) - (off_t)size; - // set fd position right after '\n' + /* set fd position right after '\n' */ if (offset && lseek(fd, offset, SEEK_CUR) == (off_t)-1) return NULL; } @@ -203,39 +203,52 @@ ssize_t FAST_FUNC open_read_close(const char *filename, void *buf, size_t size) return read_close(fd, buf, size); } + // Read (potentially big) files in one go. File size is estimated -// by stat. -void* FAST_FUNC xmalloc_open_read_close(const char *filename, size_t *sizep) +// by stat. Extra '\0' byte is appended. +void* FAST_FUNC xmalloc_read(int fd, size_t *sizep) { char *buf; - size_t size; - int fd; - off_t len; + size_t size, rd_size, total; + off_t to_read; struct stat st; - fd = open(filename, O_RDONLY); - if (fd < 0) - return NULL; + to_read = sizep ? *sizep : MAXINT(ssize_t); /* max to read */ - st.st_size = 0; /* in case fstat fail, define to 0 */ + /* Estimate file size */ + st.st_size = 0; /* in case fstat fails, assume 0 */ fstat(fd, &st); - /* /proc/N/stat files report len 0 here */ + /* /proc/N/stat files report st_size 0 */ /* In order to make such files readable, we add small const */ - len = st.st_size | 0x3ff; /* read only 1k on unseekable files */ - size = sizep ? *sizep : INT_MAX; - if (len < size) - size = len; - buf = xmalloc(size + 1); - size = read_close(fd, buf, size); - if ((ssize_t)size < 0) { - free(buf); - return NULL; + size = (st.st_size | 0x3ff) + 1; + + total = 0; + buf = NULL; + while (1) { + if (to_read < size) + size = to_read; + buf = xrealloc(buf, total + size + 1); + rd_size = full_read(fd, buf + total, size); + if ((ssize_t)rd_size < 0) { /* error */ + free(buf); + return NULL; + } + total += rd_size; + if (rd_size < size) /* EOF */ + break; + to_read -= rd_size; + if (to_read <= 0) + break; + /* grow by 1/8, but in [1k..64k] bounds */ + size = ((total / 8) | 0x3ff) + 1; + if (size > 64*1024) + size = 64*1024; } - xrealloc(buf, size + 1); - buf[size] = '\0'; + xrealloc(buf, total + 1); + buf[total] = '\0'; if (sizep) - *sizep = size; + *sizep = total; return buf; } @@ -284,59 +297,26 @@ void* FAST_FUNC xmalloc_open_read_close(const char *filename, size_t *sizep) } #endif -void* FAST_FUNC xmalloc_xopen_read_close(const char *filename, size_t *sizep) -{ - void *buf = xmalloc_open_read_close(filename, sizep); - if (!buf) - bb_perror_msg_and_die("can't read '%s'", filename); - return buf; -} - -/* libbb candidate */ -#if 0 -static void *xmalloc_read(int fd, size_t *sizep) +// Read (potentially big) files in one go. File size is estimated +// by stat. +void* FAST_FUNC xmalloc_open_read_close(const char *filename, size_t *sizep) { char *buf; - size_t size, rd_size, total; - off_t to_read; - struct stat st; - - to_read = sizep ? *sizep : INT_MAX; /* max to read */ + int fd; - /* Estimate file size */ - st.st_size = 0; /* in case fstat fails, assume 0 */ - fstat(fd, &st); - /* /proc/N/stat files report st_size 0 */ - /* In order to make such files readable, we add small const */ - size = (st.st_size | 0x3ff) + 1; + fd = open(filename, O_RDONLY); + if (fd < 0) + return NULL; - total = 0; - buf = NULL; - while (1) { - if (to_read < size) - size = to_read; - buf = xrealloc(buf, total + size + 1); - rd_size = full_read(fd, buf + total, size); - if ((ssize_t)rd_size < 0) { /* error */ - free(buf); - return NULL; - } - total += rd_size; - if (rd_size < size) /* EOF */ - break; - to_read -= rd_size; - if (to_read <= 0) - break; - /* grow by 1/8, but in [1k..64k] bounds */ - size = ((total / 8) | 0x3ff) + 1; - if (size > 64*1024) - size = 64*1024; - } - xrealloc(buf, total + 1); - buf[total] = '\0'; + buf = xmalloc_read(fd, sizep); + close(fd); + return buf; +} - if (sizep) - *sizep = total; +void* FAST_FUNC xmalloc_xopen_read_close(const char *filename, size_t *sizep) +{ + void *buf = xmalloc_open_read_close(filename, sizep); + if (!buf) + bb_perror_msg_and_die("can't read '%s'", filename); return buf; } -#endif |