diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2008-11-30 17:41:31 +0000 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2008-11-30 17:41:31 +0000 |
commit | 1e10afcdfb2b3725458d7a245aa0fe2d39f6d812 (patch) | |
tree | ed4736d6448b409c0f18b6ea9f94ea4bc4b59da7 /util-linux/volume_id/util.c | |
parent | a34b8a4d305544aaeb6fa3b3576f4fd8a582b082 (diff) | |
download | busybox-w32-1e10afcdfb2b3725458d7a245aa0fe2d39f6d812.tar.gz busybox-w32-1e10afcdfb2b3725458d7a245aa0fe2d39f6d812.tar.bz2 busybox-w32-1e10afcdfb2b3725458d7a245aa0fe2d39f6d812.zip |
volume_id/fat: careful with sector#, it may not fit in 32 bits. +91 bytes
volume_id/*: a bit of code shrink
Diffstat (limited to 'util-linux/volume_id/util.c')
-rw-r--r-- | util-linux/volume_id/util.c | 96 |
1 files changed, 50 insertions, 46 deletions
diff --git a/util-linux/volume_id/util.c b/util-linux/volume_id/util.c index c4d20ba47..1a1b3f92e 100644 --- a/util-linux/volume_id/util.c +++ b/util-linux/volume_id/util.c | |||
@@ -195,70 +195,73 @@ set: | |||
195 | * It's better to ignore such fs and continue. */ | 195 | * It's better to ignore such fs and continue. */ |
196 | void *volume_id_get_buffer(struct volume_id *id, uint64_t off, size_t len) | 196 | void *volume_id_get_buffer(struct volume_id *id, uint64_t off, size_t len) |
197 | { | 197 | { |
198 | ssize_t buf_len; | 198 | uint8_t *dst; |
199 | unsigned small_off; | ||
200 | ssize_t read_len; | ||
201 | |||
202 | dbg("get buffer off 0x%llx(%llu), len 0x%zx", | ||
203 | (unsigned long long) off, (unsigned long long) off, len); | ||
199 | 204 | ||
200 | dbg("get buffer off 0x%llx(%llu), len 0x%zx", (unsigned long long) off, (unsigned long long) off, len); | ||
201 | /* check if requested area fits in superblock buffer */ | 205 | /* check if requested area fits in superblock buffer */ |
202 | if (off + len <= SB_BUFFER_SIZE) { | 206 | if (off + len <= SB_BUFFER_SIZE |
207 | /* && off <= SB_BUFFER_SIZE - want this paranoid overflow check? */ | ||
208 | ) { | ||
203 | if (id->sbbuf == NULL) { | 209 | if (id->sbbuf == NULL) { |
204 | id->sbbuf = xmalloc(SB_BUFFER_SIZE); | 210 | id->sbbuf = xmalloc(SB_BUFFER_SIZE); |
205 | } | 211 | } |
212 | small_off = off; | ||
213 | dst = id->sbbuf; | ||
206 | 214 | ||
207 | /* check if we need to read */ | 215 | /* check if we need to read */ |
208 | if ((off + len) > id->sbbuf_len) { | 216 | len += off; |
209 | dbg("read sbbuf len:0x%llx", (unsigned long long) (off + len)); | 217 | if (len <= id->sbbuf_len) |
210 | if (lseek(id->fd, 0, SEEK_SET) != 0) { | 218 | goto ret; /* we already have it */ |
211 | dbg("seek(0) failed"); | ||
212 | return NULL; | ||
213 | } | ||
214 | buf_len = full_read(id->fd, id->sbbuf, off + len); | ||
215 | if (buf_len < 0) { | ||
216 | dbg("read failed (%s)", strerror(errno)); | ||
217 | return NULL; | ||
218 | } | ||
219 | dbg("got 0x%zx (%zi) bytes", buf_len, buf_len); | ||
220 | id->sbbuf_len = buf_len; | ||
221 | if ((uint64_t)buf_len < off + len) { | ||
222 | dbg("requested 0x%zx bytes, got only 0x%zx bytes", len, buf_len); | ||
223 | return NULL; | ||
224 | } | ||
225 | } | ||
226 | 219 | ||
227 | return &(id->sbbuf[off]); | 220 | dbg("read sbbuf len:0x%x", (unsigned) len); |
221 | id->sbbuf_len = len; | ||
222 | off = 0; | ||
223 | goto do_read; | ||
228 | } | 224 | } |
229 | 225 | ||
230 | if (len > SEEK_BUFFER_SIZE) { | 226 | if (len > SEEK_BUFFER_SIZE) { |
231 | dbg("seek buffer too small %d", SEEK_BUFFER_SIZE); | 227 | dbg("seek buffer too small %d", SEEK_BUFFER_SIZE); |
232 | return NULL; | 228 | return NULL; |
233 | } | 229 | } |
234 | 230 | dst = id->seekbuf; | |
235 | /* get seek buffer */ | ||
236 | if (id->seekbuf == NULL) { | ||
237 | id->seekbuf = xmalloc(SEEK_BUFFER_SIZE); | ||
238 | } | ||
239 | 231 | ||
240 | /* check if we need to read */ | 232 | /* check if we need to read */ |
241 | if ((off < id->seekbuf_off) || ((off + len) > (id->seekbuf_off + id->seekbuf_len))) { | 233 | if ((off >= id->seekbuf_off) |
242 | dbg("read seekbuf off:0x%llx len:0x%zx", (unsigned long long) off, len); | 234 | && ((off + len) <= (id->seekbuf_off + id->seekbuf_len)) |
243 | if (lseek(id->fd, off, SEEK_SET) != off) { | 235 | ) { |
244 | dbg("seek(0x%llx) failed", (unsigned long long) off); | 236 | small_off = off - id->seekbuf_off; /* can't overflow */ |
245 | return NULL; | 237 | goto ret; /* we already have it */ |
246 | } | ||
247 | buf_len = full_read(id->fd, id->seekbuf, len); | ||
248 | if (buf_len < 0) { | ||
249 | dbg("read failed (%s)", strerror(errno)); | ||
250 | return NULL; | ||
251 | } | ||
252 | dbg("got 0x%zx (%zi) bytes", buf_len, buf_len); | ||
253 | id->seekbuf_off = off; | ||
254 | id->seekbuf_len = buf_len; | ||
255 | if ((size_t)buf_len < len) { | ||
256 | dbg("requested 0x%zx bytes, got only 0x%zx bytes", len, buf_len); | ||
257 | return NULL; | ||
258 | } | ||
259 | } | 238 | } |
260 | 239 | ||
261 | return &(id->seekbuf[off - id->seekbuf_off]); | 240 | id->seekbuf_off = off; |
241 | id->seekbuf_len = len; | ||
242 | id->seekbuf = xrealloc(id->seekbuf, len); | ||
243 | small_off = 0; | ||
244 | dst = id->seekbuf; | ||
245 | dbg("read seekbuf off:0x%llx len:0x%zx", | ||
246 | (unsigned long long) off, len); | ||
247 | do_read: | ||
248 | if (lseek(id->fd, off, SEEK_SET) != off) { | ||
249 | dbg("seek(0x%llx) failed", (unsigned long long) off); | ||
250 | goto err; | ||
251 | } | ||
252 | read_len = full_read(id->fd, dst, len); | ||
253 | if (read_len != len) { | ||
254 | dbg("requested 0x%x bytes, got 0x%x bytes", | ||
255 | (unsigned) len, (unsigned) read_len); | ||
256 | err: | ||
257 | /* id->seekbuf_len or id->sbbuf_len is wrong now! Fixing. | ||
258 | * Most likely user will not do any additional | ||
259 | * calls anyway, it's a corrupted fs or something. */ | ||
260 | volume_id_free_buffer(id); | ||
261 | return NULL; | ||
262 | } | ||
263 | ret: | ||
264 | return dst + small_off; | ||
262 | } | 265 | } |
263 | 266 | ||
264 | void volume_id_free_buffer(struct volume_id *id) | 267 | void volume_id_free_buffer(struct volume_id *id) |
@@ -269,4 +272,5 @@ void volume_id_free_buffer(struct volume_id *id) | |||
269 | free(id->seekbuf); | 272 | free(id->seekbuf); |
270 | id->seekbuf = NULL; | 273 | id->seekbuf = NULL; |
271 | id->seekbuf_len = 0; | 274 | id->seekbuf_len = 0; |
275 | id->seekbuf_off = 0; /* paranoia */ | ||
272 | } | 276 | } |