aboutsummaryrefslogtreecommitdiff
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
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
-rw-r--r--util-linux/volume_id/fat.c14
-rw-r--r--util-linux/volume_id/util.c96
-rw-r--r--util-linux/volume_id/volume_id_internal.h24
3 files changed, 68 insertions, 66 deletions
diff --git a/util-linux/volume_id/fat.c b/util-linux/volume_id/fat.c
index 816d69d4c..0e0a57d62 100644
--- a/util-linux/volume_id/fat.c
+++ b/util-linux/volume_id/fat.c
@@ -245,7 +245,7 @@ int volume_id_probe_vfat(struct volume_id *id, uint64_t fat_partition_off)
245 buf_size = dir_entries * sizeof(struct vfat_dir_entry); 245 buf_size = dir_entries * sizeof(struct vfat_dir_entry);
246 buf = volume_id_get_buffer(id, fat_partition_off + root_start_off, buf_size); 246 buf = volume_id_get_buffer(id, fat_partition_off + root_start_off, buf_size);
247 if (buf == NULL) 247 if (buf == NULL)
248 goto found; 248 goto ret;
249 249
250 label = get_attr_volume_id((struct vfat_dir_entry*) buf, dir_entries); 250 label = get_attr_volume_id((struct vfat_dir_entry*) buf, dir_entries);
251 251
@@ -261,7 +261,7 @@ int volume_id_probe_vfat(struct volume_id *id, uint64_t fat_partition_off)
261 volume_id_set_label_string(id, vs->type.fat.label, 11); 261 volume_id_set_label_string(id, vs->type.fat.label, 11);
262 } 262 }
263 volume_id_set_uuid(id, vs->type.fat.serno, UUID_DOS); 263 volume_id_set_uuid(id, vs->type.fat.serno, UUID_DOS);
264 goto found; 264 goto ret;
265 265
266 fat32: 266 fat32:
267 /* FAT32 root dir is a cluster chain like any other directory */ 267 /* FAT32 root dir is a cluster chain like any other directory */
@@ -272,20 +272,20 @@ int volume_id_probe_vfat(struct volume_id *id, uint64_t fat_partition_off)
272 next_cluster = root_cluster; 272 next_cluster = root_cluster;
273 maxloop = 100; 273 maxloop = 100;
274 while (--maxloop) { 274 while (--maxloop) {
275 uint32_t next_off_sct; 275 uint64_t next_off_sct;
276 uint64_t next_off; 276 uint64_t next_off;
277 uint64_t fat_entry_off; 277 uint64_t fat_entry_off;
278 int count; 278 int count;
279 279
280 dbg("next_cluster 0x%x", (unsigned)next_cluster); 280 dbg("next_cluster 0x%x", (unsigned)next_cluster);
281 next_off_sct = (next_cluster - 2) * vs->sectors_per_cluster; 281 next_off_sct = (uint64_t)(next_cluster - 2) * vs->sectors_per_cluster;
282 next_off = (start_data_sct + next_off_sct) * sector_size_bytes; 282 next_off = (start_data_sct + next_off_sct) * sector_size_bytes;
283 dbg("cluster offset 0x%llx", (unsigned long long) next_off); 283 dbg("cluster offset 0x%llx", (unsigned long long) next_off);
284 284
285 /* get cluster */ 285 /* get cluster */
286 buf = volume_id_get_buffer(id, fat_partition_off + next_off, buf_size); 286 buf = volume_id_get_buffer(id, fat_partition_off + next_off, buf_size);
287 if (buf == NULL) 287 if (buf == NULL)
288 goto found; 288 goto ret;
289 289
290 dir = (struct vfat_dir_entry*) buf; 290 dir = (struct vfat_dir_entry*) buf;
291 count = buf_size / sizeof(struct vfat_dir_entry); 291 count = buf_size / sizeof(struct vfat_dir_entry);
@@ -300,7 +300,7 @@ int volume_id_probe_vfat(struct volume_id *id, uint64_t fat_partition_off)
300 dbg("fat_entry_off 0x%llx", (unsigned long long)fat_entry_off); 300 dbg("fat_entry_off 0x%llx", (unsigned long long)fat_entry_off);
301 buf = volume_id_get_buffer(id, fat_partition_off + fat_entry_off, buf_size); 301 buf = volume_id_get_buffer(id, fat_partition_off + fat_entry_off, buf_size);
302 if (buf == NULL) 302 if (buf == NULL)
303 goto found; 303 goto ret;
304 304
305 /* set next cluster */ 305 /* set next cluster */
306 next_cluster = le32_to_cpu(*(uint32_t*)buf) & 0x0fffffff; 306 next_cluster = le32_to_cpu(*(uint32_t*)buf) & 0x0fffffff;
@@ -323,7 +323,7 @@ int volume_id_probe_vfat(struct volume_id *id, uint64_t fat_partition_off)
323 } 323 }
324 volume_id_set_uuid(id, vs->type.fat32.serno, UUID_DOS); 324 volume_id_set_uuid(id, vs->type.fat32.serno, UUID_DOS);
325 325
326 found: 326 ret:
327// volume_id_set_usage(id, VOLUME_ID_FILESYSTEM); 327// volume_id_set_usage(id, VOLUME_ID_FILESYSTEM);
328// id->type = "vfat"; 328// id->type = "vfat";
329 329
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}
diff --git a/util-linux/volume_id/volume_id_internal.h b/util-linux/volume_id/volume_id_internal.h
index 075ddb344..fe3547d13 100644
--- a/util-linux/volume_id/volume_id_internal.h
+++ b/util-linux/volume_id/volume_id_internal.h
@@ -61,6 +61,17 @@ struct volume_id_partition {
61#endif 61#endif
62 62
63struct volume_id { 63struct volume_id {
64 int fd;
65// int fd_close:1;
66 size_t sbbuf_len;
67 size_t seekbuf_len;
68 uint8_t *sbbuf;
69 uint8_t *seekbuf;
70 uint64_t seekbuf_off;
71#ifdef UNUSED_PARTITION_CODE
72 struct volume_id_partition *partitions;
73 size_t partition_count;
74#endif
64// uint8_t label_raw[VOLUME_ID_LABEL_SIZE]; 75// uint8_t label_raw[VOLUME_ID_LABEL_SIZE];
65// size_t label_raw_len; 76// size_t label_raw_len;
66 char label[VOLUME_ID_LABEL_SIZE+1]; 77 char label[VOLUME_ID_LABEL_SIZE+1];
@@ -72,19 +83,6 @@ struct volume_id {
72// smallint usage_id; 83// smallint usage_id;
73// const char *usage; 84// const char *usage;
74// const char *type; 85// const char *type;
75
76#ifdef UNUSED_PARTITION_CODE
77 struct volume_id_partition *partitions;
78 size_t partition_count;
79#endif
80
81 int fd;
82 uint8_t *sbbuf;
83 uint8_t *seekbuf;
84 size_t sbbuf_len;
85 uint64_t seekbuf_off;
86 size_t seekbuf_len;
87// int fd_close:1;
88}; 86};
89 87
90struct volume_id *volume_id_open_node(int fd); 88struct volume_id *volume_id_open_node(int fd);