aboutsummaryrefslogtreecommitdiff
path: root/util-linux/volume_id/util.c
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2008-11-30 17:41:31 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2008-11-30 17:41:31 +0000
commit1e10afcdfb2b3725458d7a245aa0fe2d39f6d812 (patch)
treeed4736d6448b409c0f18b6ea9f94ea4bc4b59da7 /util-linux/volume_id/util.c
parenta34b8a4d305544aaeb6fa3b3576f4fd8a582b082 (diff)
downloadbusybox-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.c96
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. */
196void *volume_id_get_buffer(struct volume_id *id, uint64_t off, size_t len) 196void *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
264void volume_id_free_buffer(struct volume_id *id) 267void 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}