diff options
| -rw-r--r-- | util-linux/volume_id/util.c | 29 | ||||
| -rw-r--r-- | util-linux/volume_id/volume_id.c | 25 | ||||
| -rw-r--r-- | util-linux/volume_id/volume_id_internal.h | 16 |
3 files changed, 52 insertions, 18 deletions
diff --git a/util-linux/volume_id/util.c b/util-linux/volume_id/util.c index b154f9378..b59aa99b2 100644 --- a/util-linux/volume_id/util.c +++ b/util-linux/volume_id/util.c | |||
| @@ -176,6 +176,12 @@ void *volume_id_get_buffer(struct volume_id *id, uint64_t off, size_t len) | |||
| 176 | unsigned small_off; | 176 | unsigned small_off; |
| 177 | ssize_t read_len; | 177 | ssize_t read_len; |
| 178 | 178 | ||
| 179 | if (id->known_size != UNKNOWN_SIZE | ||
| 180 | && id->known_size < off + len | ||
| 181 | ) { | ||
| 182 | return NULL; | ||
| 183 | } | ||
| 184 | |||
| 179 | dbg("get buffer off 0x%llx(%llu), len 0x%zx", | 185 | dbg("get buffer off 0x%llx(%llu), len 0x%zx", |
| 180 | (unsigned long long) off, (unsigned long long) off, len); | 186 | (unsigned long long) off, (unsigned long long) off, len); |
| 181 | 187 | ||
| @@ -224,20 +230,29 @@ void *volume_id_get_buffer(struct volume_id *id, uint64_t off, size_t len) | |||
| 224 | do_read: | 230 | do_read: |
| 225 | if (lseek(id->fd, off, SEEK_SET) != off) { | 231 | if (lseek(id->fd, off, SEEK_SET) != off) { |
| 226 | dbg("seek(0x%llx) failed", (unsigned long long) off); | 232 | dbg("seek(0x%llx) failed", (unsigned long long) off); |
| 233 | off = lseek(id->fd, 0, SEEK_END); | ||
| 234 | if (off < 0) | ||
| 235 | off = 0; | ||
| 227 | goto err; | 236 | goto err; |
| 228 | } | 237 | } |
| 229 | read_len = full_read(id->fd, dst, len); | 238 | read_len = full_read(id->fd, dst, len); |
| 230 | if (read_len != len) { | 239 | if (read_len != len) { |
| 231 | dbg("requested 0x%x bytes, got 0x%x bytes", | 240 | dbg("requested 0x%x bytes, got 0x%x bytes", |
| 232 | (unsigned) len, (unsigned) read_len); | 241 | (unsigned) len, (unsigned) read_len); |
| 242 | if (read_len > 0) | ||
| 243 | off += read_len; | ||
| 233 | err: | 244 | err: |
| 234 | /* No filesystem can be this tiny. It's most likely | 245 | /* The image is definitely only OFF bytes large */ |
| 235 | * non-associated loop device, empty drive and so on. | 246 | if (off < UNKNOWN_SIZE) { |
| 236 | * Flag it, avoiding future accesses. Rationale: | 247 | /* ...and OFF is small, we can use |
| 237 | * users complained of slow blkid due to empty floppy drives. | 248 | * that knowledge to skip future probes: |
| 238 | */ | 249 | * cases such as non-associated loop devices, |
| 239 | if (off <= 1024) | 250 | * empty (floppy) drives and so on. |
| 240 | id->error = 1; | 251 | * Record it, avoiding future accesses. Users |
| 252 | * complained of slow blkid due to empty floppys. | ||
| 253 | */ | ||
| 254 | id->known_size = off; | ||
| 255 | } | ||
| 241 | /* id->seekbuf_len or id->sbbuf_len is wrong now! Fixing. */ | 256 | /* id->seekbuf_len or id->sbbuf_len is wrong now! Fixing. */ |
| 242 | volume_id_free_buffer(id); | 257 | volume_id_free_buffer(id); |
| 243 | return NULL; | 258 | return NULL; |
diff --git a/util-linux/volume_id/volume_id.c b/util-linux/volume_id/volume_id.c index 8ceb61bde..53715121b 100644 --- a/util-linux/volume_id/volume_id.c +++ b/util-linux/volume_id/volume_id.c | |||
| @@ -180,6 +180,7 @@ static const probe_fptr fs2[] ALIGN_PTR = { | |||
| 180 | 180 | ||
| 181 | int FAST_FUNC volume_id_probe_all(struct volume_id *id, /*uint64_t off,*/ uint64_t size) | 181 | int FAST_FUNC volume_id_probe_all(struct volume_id *id, /*uint64_t off,*/ uint64_t size) |
| 182 | { | 182 | { |
| 183 | int retval = 0; | ||
| 183 | unsigned i; | 184 | unsigned i; |
| 184 | 185 | ||
| 185 | /* probe for raid first, cause fs probes may be successful on raid members */ | 186 | /* probe for raid first, cause fs probes may be successful on raid members */ |
| @@ -187,24 +188,26 @@ int FAST_FUNC volume_id_probe_all(struct volume_id *id, /*uint64_t off,*/ uint64 | |||
| 187 | for (i = 0; i < ARRAY_SIZE(raid1); i++) { | 188 | for (i = 0; i < ARRAY_SIZE(raid1); i++) { |
| 188 | if (raid1[i](id, /*off,*/ size) == 0) | 189 | if (raid1[i](id, /*off,*/ size) == 0) |
| 189 | goto ret; | 190 | goto ret; |
| 190 | if (id->error) | 191 | //if (id->known_size < MIN_VALID_FS_SIZE) |
| 191 | goto ret; | 192 | // goto ret_bad; |
| 193 | //Redundant? none of the subsequent probers will succeed | ||
| 194 | //(or even attempt reads) if the above is true. | ||
| 192 | } | 195 | } |
| 193 | } | 196 | } |
| 194 | 197 | ||
| 195 | for (i = 0; i < ARRAY_SIZE(raid2); i++) { | 198 | for (i = 0; i < ARRAY_SIZE(raid2); i++) { |
| 196 | if (raid2[i](id /*,off*/) == 0) | 199 | if (raid2[i](id /*,off*/) == 0) |
| 197 | goto ret; | 200 | goto ret; |
| 198 | if (id->error) | 201 | //if (id->known_size < MIN_VALID_FS_SIZE) |
| 199 | goto ret; | 202 | // goto ret_bad; |
| 200 | } | 203 | } |
| 201 | 204 | ||
| 202 | /* signature in the first block, only small buffer needed */ | 205 | /* signature in the first block, only small buffer needed */ |
| 203 | for (i = 0; i < ARRAY_SIZE(fs1); i++) { | 206 | for (i = 0; i < ARRAY_SIZE(fs1); i++) { |
| 204 | if (fs1[i](id /*,off*/) == 0) | 207 | if (fs1[i](id /*,off*/) == 0) |
| 205 | goto ret; | 208 | goto ret; |
| 206 | if (id->error) | 209 | //if (id->known_size < MIN_VALID_FS_SIZE) |
| 207 | goto ret; | 210 | // goto ret_bad; |
| 208 | } | 211 | } |
| 209 | 212 | ||
| 210 | /* fill buffer with maximum */ | 213 | /* fill buffer with maximum */ |
| @@ -213,13 +216,14 @@ int FAST_FUNC volume_id_probe_all(struct volume_id *id, /*uint64_t off,*/ uint64 | |||
| 213 | for (i = 0; i < ARRAY_SIZE(fs2); i++) { | 216 | for (i = 0; i < ARRAY_SIZE(fs2); i++) { |
| 214 | if (fs2[i](id /*,off*/) == 0) | 217 | if (fs2[i](id /*,off*/) == 0) |
| 215 | goto ret; | 218 | goto ret; |
| 216 | if (id->error) | 219 | //if (id->known_size < MIN_VALID_FS_SIZE) |
| 217 | goto ret; | 220 | // goto ret_bad; |
| 218 | } | 221 | } |
| 219 | 222 | //ret_bad: | |
| 223 | retval = -1; /* "not found" */ | ||
| 220 | ret: | 224 | ret: |
| 221 | volume_id_free_buffer(id); | 225 | volume_id_free_buffer(id); |
| 222 | return (- id->error); /* 0 or -1 */ | 226 | return retval; |
| 223 | } | 227 | } |
| 224 | 228 | ||
| 225 | /* open volume by device node */ | 229 | /* open volume by device node */ |
| @@ -229,6 +233,7 @@ struct volume_id* FAST_FUNC volume_id_open_node(int fd) | |||
| 229 | 233 | ||
| 230 | id = xzalloc(sizeof(struct volume_id)); | 234 | id = xzalloc(sizeof(struct volume_id)); |
| 231 | id->fd = fd; | 235 | id->fd = fd; |
| 236 | id->known_size = UNKNOWN_SIZE; | ||
| 232 | ///* close fd on device close */ | 237 | ///* close fd on device close */ |
| 233 | //id->fd_close = 1; | 238 | //id->fd_close = 1; |
| 234 | return id; | 239 | return id; |
diff --git a/util-linux/volume_id/volume_id_internal.h b/util-linux/volume_id/volume_id_internal.h index b1e44481f..39699ef72 100644 --- a/util-linux/volume_id/volume_id_internal.h +++ b/util-linux/volume_id/volume_id_internal.h | |||
| @@ -60,7 +60,9 @@ struct volume_id_partition { | |||
| 60 | struct volume_id { | 60 | struct volume_id { |
| 61 | int fd; | 61 | int fd; |
| 62 | // int fd_close:1; | 62 | // int fd_close:1; |
| 63 | int error; | 63 | /* UNKNOWN_SIZE: unknown, N: seek+read stopped at N prematurely */ |
| 64 | unsigned known_size; | ||
| 65 | #define UNKNOWN_SIZE UINT_MAX | ||
| 64 | size_t sbbuf_len; | 66 | size_t sbbuf_len; |
| 65 | size_t seekbuf_len; | 67 | size_t seekbuf_len; |
| 66 | uint8_t *sbbuf; | 68 | uint8_t *sbbuf; |
| @@ -85,6 +87,18 @@ struct volume_id { | |||
| 85 | // const char *usage; | 87 | // const char *usage; |
| 86 | }; | 88 | }; |
| 87 | 89 | ||
| 90 | // Technically, the tiniest possible linux FS image (romfs) with only "." and ".." is: | ||
| 91 | //00000000 2D 72 6F 6D 31 66 73 2D 00 00 00 60 A1 27 1D 06 -rom1fs-...`.'.. | ||
| 92 | //00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ | ||
| 93 | //00000020 00 00 00 49 00 00 00 20 00 00 00 00 D1 FF FF 97 ...I... ........ | ||
| 94 | //00000030 2E 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ | ||
| 95 | //00000040 00 00 00 00 00 00 00 20 00 00 00 00 D1 D1 FF E0 ....... ........ | ||
| 96 | //00000050 2E 2E 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ | ||
| 97 | // but kernel won't mount it unless it's padded to 1K. | ||
| 98 | // Stop trying new FS types in volume_id_probe_all() outright | ||
| 99 | // if a previous probe had a read which stopped before 1K: | ||
| 100 | #define MIN_VALID_FS_SIZE 1024 | ||
| 101 | |||
| 88 | struct volume_id* FAST_FUNC volume_id_open_node(int fd); | 102 | struct volume_id* FAST_FUNC volume_id_open_node(int fd); |
| 89 | int FAST_FUNC volume_id_probe_all(struct volume_id *id, /*uint64_t off,*/ uint64_t size); | 103 | int FAST_FUNC volume_id_probe_all(struct volume_id *id, /*uint64_t off,*/ uint64_t size); |
| 90 | void FAST_FUNC free_volume_id(struct volume_id *id); | 104 | void FAST_FUNC free_volume_id(struct volume_id *id); |
