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 | |
| 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')
| -rw-r--r-- | util-linux/volume_id/fat.c | 14 | ||||
| -rw-r--r-- | util-linux/volume_id/util.c | 96 | ||||
| -rw-r--r-- | util-linux/volume_id/volume_id_internal.h | 24 |
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. */ |
| 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 | } |
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 | ||
| 63 | struct volume_id { | 63 | struct 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 | ||
| 90 | struct volume_id *volume_id_open_node(int fd); | 88 | struct volume_id *volume_id_open_node(int fd); |
