diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2007-06-13 06:47:47 +0000 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2007-06-13 06:47:47 +0000 |
commit | d67cef2425fb5e75b75d52d9a308da6d29cd7a0d (patch) | |
tree | 5d034f518dfae9a933a701e8c42da4acbf0cb42d /libbb | |
parent | f5f75c5e82d47613847c356664e47c4be69e73aa (diff) | |
download | busybox-w32-d67cef2425fb5e75b75d52d9a308da6d29cd7a0d.tar.gz busybox-w32-d67cef2425fb5e75b75d52d9a308da6d29cd7a0d.tar.bz2 busybox-w32-d67cef2425fb5e75b75d52d9a308da6d29cd7a0d.zip |
hush: fix read builtin to not read ahead past eol and to not use
insane amounts of stack. Testsuite updated.
Diffstat (limited to 'libbb')
-rw-r--r-- | libbb/read.c | 53 |
1 files changed, 42 insertions, 11 deletions
diff --git a/libbb/read.c b/libbb/read.c index c05b26b50..05bf754e0 100644 --- a/libbb/read.c +++ b/libbb/read.c | |||
@@ -38,10 +38,8 @@ ssize_t full_read(int fd, void *buf, size_t len) | |||
38 | 38 | ||
39 | if (cc < 0) | 39 | if (cc < 0) |
40 | return cc; /* read() returns -1 on failure. */ | 40 | return cc; /* read() returns -1 on failure. */ |
41 | |||
42 | if (cc == 0) | 41 | if (cc == 0) |
43 | break; | 42 | break; |
44 | |||
45 | buf = ((char *)buf) + cc; | 43 | buf = ((char *)buf) + cc; |
46 | total += cc; | 44 | total += cc; |
47 | len -= cc; | 45 | len -= cc; |
@@ -64,9 +62,7 @@ void xread(int fd, void *buf, size_t count) | |||
64 | unsigned char xread_char(int fd) | 62 | unsigned char xread_char(int fd) |
65 | { | 63 | { |
66 | char tmp; | 64 | char tmp; |
67 | |||
68 | xread(fd, &tmp, 1); | 65 | xread(fd, &tmp, 1); |
69 | |||
70 | return tmp; | 66 | return tmp; |
71 | } | 67 | } |
72 | 68 | ||
@@ -95,6 +91,37 @@ char *reads(int fd, char *buffer, size_t size) | |||
95 | return buffer; | 91 | return buffer; |
96 | } | 92 | } |
97 | 93 | ||
94 | // Read one line a-la fgets. Reads byte-by-byte. | ||
95 | // Useful when it is important to not read ahead. | ||
96 | char *xmalloc_reads(int fd, char *buf) | ||
97 | { | ||
98 | char *p; | ||
99 | int sz = buf ? strlen(buf) : 0; | ||
100 | |||
101 | goto jump_in; | ||
102 | while (1) { | ||
103 | if (p - buf == sz) { | ||
104 | jump_in: | ||
105 | buf = xrealloc(buf, sz + 128); | ||
106 | p = buf + sz; | ||
107 | sz += 128; | ||
108 | } | ||
109 | if (safe_read(fd, p, 1) != 1) { /* EOF/error */ | ||
110 | if (p == buf) { | ||
111 | /* we read nothing [and buf was NULL initially] */ | ||
112 | free(buf); | ||
113 | return NULL; | ||
114 | } | ||
115 | break; | ||
116 | } | ||
117 | if (*p == '\n') | ||
118 | break; | ||
119 | p++; | ||
120 | } | ||
121 | *p++ = '\0'; | ||
122 | return xrealloc(buf, p - buf); | ||
123 | } | ||
124 | |||
98 | ssize_t read_close(int fd, void *buf, size_t size) | 125 | ssize_t read_close(int fd, void *buf, size_t size) |
99 | { | 126 | { |
100 | int e; | 127 | int e; |
@@ -113,25 +140,29 @@ ssize_t open_read_close(const char *filename, void *buf, size_t size) | |||
113 | return read_close(fd, buf, size); | 140 | return read_close(fd, buf, size); |
114 | } | 141 | } |
115 | 142 | ||
143 | // Read (potentially big) files in one go. File size is estimated by | ||
144 | // lseek to end. | ||
116 | void *xmalloc_open_read_close(const char *filename, size_t *sizep) | 145 | void *xmalloc_open_read_close(const char *filename, size_t *sizep) |
117 | { | 146 | { |
118 | char *buf; | 147 | char *buf; |
119 | size_t size = sizep ? *sizep : INT_MAX; | 148 | size_t size = sizep ? *sizep : INT_MAX; |
120 | int fd = xopen(filename, O_RDONLY); | 149 | int fd; |
150 | off_t len; | ||
151 | |||
152 | fd = xopen(filename, O_RDONLY); | ||
121 | /* /proc/N/stat files report len 0 here */ | 153 | /* /proc/N/stat files report len 0 here */ |
122 | /* In order to make such files readable, we add small const */ | 154 | /* In order to make such files readable, we add small const */ |
123 | off_t len = xlseek(fd, 0, SEEK_END) + 256; | 155 | len = xlseek(fd, 0, SEEK_END) | 0x3ff; /* + up to 1k */ |
124 | xlseek(fd, 0, SEEK_SET); | 156 | xlseek(fd, 0, SEEK_SET); |
125 | 157 | if (len < size) | |
126 | if (len > size) | 158 | size = len; |
127 | bb_error_msg_and_die("file '%s' is too big", filename); | ||
128 | size = len; | ||
129 | buf = xmalloc(size + 1); | 159 | buf = xmalloc(size + 1); |
130 | size = read_close(fd, buf, size); | 160 | size = read_close(fd, buf, size); |
131 | if ((ssize_t)size < 0) | 161 | if ((ssize_t)size < 0) |
132 | bb_perror_msg_and_die("'%s'", filename); | 162 | bb_perror_msg_and_die("'%s'", filename); |
133 | xrealloc(buf, size + 1); | 163 | xrealloc(buf, size + 1); |
134 | buf[size] = '\0'; | 164 | buf[size] = '\0'; |
135 | if (sizep) *sizep = size; | 165 | if (sizep) |
166 | *sizep = size; | ||
136 | return buf; | 167 | return buf; |
137 | } | 168 | } |