diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2008-10-12 11:17:49 +0000 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2008-10-12 11:17:49 +0000 |
commit | d5e305944a9db25f57b252cc9f56c18311e68481 (patch) | |
tree | 5f76ea7623209d379a9ea34bfa943ef86af2032a /util-linux/volume_id | |
parent | cdd1f732bc5b8447dd12b59613663b7d08fce20b (diff) | |
download | busybox-w32-d5e305944a9db25f57b252cc9f56c18311e68481.tar.gz busybox-w32-d5e305944a9db25f57b252cc9f56c18311e68481.tar.bz2 busybox-w32-d5e305944a9db25f57b252cc9f56c18311e68481.zip |
findfs: fix LUKS and FAT detection routines; do not exit if corrupted
FAT fs makes us try to seek past volume
function old new delta
volume_id_get_buffer 301 327 +26
volume_id_probe_luks 79 82 +3
get_attr_volume_id 73 65 -8
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 2/1 up/down: 29/-8) Total: 21 bytes
Diffstat (limited to 'util-linux/volume_id')
-rw-r--r-- | util-linux/volume_id/fat.c | 128 | ||||
-rw-r--r-- | util-linux/volume_id/luks.c | 50 | ||||
-rw-r--r-- | util-linux/volume_id/util.c | 15 |
3 files changed, 111 insertions, 82 deletions
diff --git a/util-linux/volume_id/fat.c b/util-linux/volume_id/fat.c index 9ab1cef02..816d69d4c 100644 --- a/util-linux/volume_id/fat.c +++ b/util-linux/volume_id/fat.c | |||
@@ -20,8 +20,11 @@ | |||
20 | 20 | ||
21 | #include "volume_id_internal.h" | 21 | #include "volume_id_internal.h" |
22 | 22 | ||
23 | #define FAT12_MAX 0xff5 | 23 | /* linux/msdos_fs.h says: */ |
24 | #define FAT16_MAX 0xfff5 | 24 | #define FAT12_MAX 0xff4 |
25 | #define FAT16_MAX 0xfff4 | ||
26 | #define FAT32_MAX 0x0ffffff6 | ||
27 | |||
25 | #define FAT_ATTR_VOLUME_ID 0x08 | 28 | #define FAT_ATTR_VOLUME_ID 0x08 |
26 | #define FAT_ATTR_DIR 0x10 | 29 | #define FAT_ATTR_DIR 0x10 |
27 | #define FAT_ATTR_LONG_NAME 0x0f | 30 | #define FAT_ATTR_LONG_NAME 0x0f |
@@ -31,9 +34,9 @@ | |||
31 | struct vfat_super_block { | 34 | struct vfat_super_block { |
32 | uint8_t boot_jump[3]; | 35 | uint8_t boot_jump[3]; |
33 | uint8_t sysid[8]; | 36 | uint8_t sysid[8]; |
34 | uint16_t sector_size; | 37 | uint16_t sector_size_bytes; |
35 | uint8_t sectors_per_cluster; | 38 | uint8_t sectors_per_cluster; |
36 | uint16_t reserved; | 39 | uint16_t reserved_sct; |
37 | uint8_t fats; | 40 | uint8_t fats; |
38 | uint16_t dir_entries; | 41 | uint16_t dir_entries; |
39 | uint16_t sectors; | 42 | uint16_t sectors; |
@@ -84,32 +87,30 @@ struct vfat_dir_entry { | |||
84 | uint32_t size; | 87 | uint32_t size; |
85 | } __attribute__((__packed__)); | 88 | } __attribute__((__packed__)); |
86 | 89 | ||
87 | static uint8_t *get_attr_volume_id(struct vfat_dir_entry *dir, unsigned count) | 90 | static uint8_t *get_attr_volume_id(struct vfat_dir_entry *dir, int count) |
88 | { | 91 | { |
89 | unsigned i; | 92 | for (;--count >= 0; dir++) { |
90 | |||
91 | for (i = 0; i < count; i++) { | ||
92 | /* end marker */ | 93 | /* end marker */ |
93 | if (dir[i].name[0] == 0x00) { | 94 | if (dir->name[0] == 0x00) { |
94 | dbg("end of dir"); | 95 | dbg("end of dir"); |
95 | break; | 96 | break; |
96 | } | 97 | } |
97 | 98 | ||
98 | /* empty entry */ | 99 | /* empty entry */ |
99 | if (dir[i].name[0] == FAT_ENTRY_FREE) | 100 | if (dir->name[0] == FAT_ENTRY_FREE) |
100 | continue; | 101 | continue; |
101 | 102 | ||
102 | /* long name */ | 103 | /* long name */ |
103 | if ((dir[i].attr & FAT_ATTR_MASK) == FAT_ATTR_LONG_NAME) | 104 | if ((dir->attr & FAT_ATTR_MASK) == FAT_ATTR_LONG_NAME) |
104 | continue; | 105 | continue; |
105 | 106 | ||
106 | if ((dir[i].attr & (FAT_ATTR_VOLUME_ID | FAT_ATTR_DIR)) == FAT_ATTR_VOLUME_ID) { | 107 | if ((dir->attr & (FAT_ATTR_VOLUME_ID | FAT_ATTR_DIR)) == FAT_ATTR_VOLUME_ID) { |
107 | /* labels do not have file data */ | 108 | /* labels do not have file data */ |
108 | if (dir[i].cluster_high != 0 || dir[i].cluster_low != 0) | 109 | if (dir->cluster_high != 0 || dir->cluster_low != 0) |
109 | continue; | 110 | continue; |
110 | 111 | ||
111 | dbg("found ATTR_VOLUME_ID id in root dir"); | 112 | dbg("found ATTR_VOLUME_ID id in root dir"); |
112 | return dir[i].name; | 113 | return dir->name; |
113 | } | 114 | } |
114 | 115 | ||
115 | dbg("skip dir entry"); | 116 | dbg("skip dir entry"); |
@@ -118,31 +119,29 @@ static uint8_t *get_attr_volume_id(struct vfat_dir_entry *dir, unsigned count) | |||
118 | return NULL; | 119 | return NULL; |
119 | } | 120 | } |
120 | 121 | ||
121 | int volume_id_probe_vfat(struct volume_id *id, uint64_t off) | 122 | int volume_id_probe_vfat(struct volume_id *id, uint64_t fat_partition_off) |
122 | { | 123 | { |
123 | struct vfat_super_block *vs; | 124 | struct vfat_super_block *vs; |
124 | struct vfat_dir_entry *dir; | 125 | struct vfat_dir_entry *dir; |
125 | uint16_t sector_size; | 126 | uint16_t sector_size_bytes; |
126 | uint16_t dir_entries; | 127 | uint16_t dir_entries; |
127 | uint32_t sect_count; | 128 | uint32_t sect_count; |
128 | uint16_t reserved; | 129 | uint16_t reserved_sct; |
129 | uint32_t fat_size; | 130 | uint32_t fat_size_sct; |
130 | uint32_t root_cluster; | 131 | uint32_t root_cluster; |
131 | uint32_t dir_size; | 132 | uint32_t dir_size_sct; |
132 | uint32_t cluster_count; | 133 | uint32_t cluster_count; |
133 | uint32_t fat_length; | 134 | uint64_t root_start_off; |
134 | uint64_t root_start; | 135 | uint32_t start_data_sct; |
135 | uint32_t start_data_sect; | ||
136 | uint16_t root_dir_entries; | ||
137 | uint8_t *buf; | 136 | uint8_t *buf; |
138 | uint32_t buf_size; | 137 | uint32_t buf_size; |
139 | uint8_t *label = NULL; | 138 | uint8_t *label = NULL; |
140 | uint32_t next; | 139 | uint32_t next_cluster; |
141 | int maxloop; | 140 | int maxloop; |
142 | 141 | ||
143 | dbg("probing at offset 0x%llx", (unsigned long long) off); | 142 | dbg("probing at offset 0x%llx", (unsigned long long) fat_partition_off); |
144 | 143 | ||
145 | vs = volume_id_get_buffer(id, off, 0x200); | 144 | vs = volume_id_get_buffer(id, fat_partition_off, 0x200); |
146 | if (vs == NULL) | 145 | if (vs == NULL) |
147 | return -1; | 146 | return -1; |
148 | 147 | ||
@@ -196,34 +195,34 @@ int volume_id_probe_vfat(struct volume_id *id, uint64_t off) | |||
196 | 195 | ||
197 | valid: | 196 | valid: |
198 | /* sector size check */ | 197 | /* sector size check */ |
199 | sector_size = le16_to_cpu(vs->sector_size); | 198 | sector_size_bytes = le16_to_cpu(vs->sector_size_bytes); |
200 | if (sector_size != 0x200 && sector_size != 0x400 && | 199 | if (sector_size_bytes != 0x200 && sector_size_bytes != 0x400 && |
201 | sector_size != 0x800 && sector_size != 0x1000) | 200 | sector_size_bytes != 0x800 && sector_size_bytes != 0x1000) |
202 | return -1; | 201 | return -1; |
203 | 202 | ||
204 | dbg("sector_size 0x%x", sector_size); | 203 | dbg("sector_size_bytes 0x%x", sector_size_bytes); |
205 | dbg("sectors_per_cluster 0x%x", vs->sectors_per_cluster); | 204 | dbg("sectors_per_cluster 0x%x", vs->sectors_per_cluster); |
206 | 205 | ||
207 | dir_entries = le16_to_cpu(vs->dir_entries); | 206 | reserved_sct = le16_to_cpu(vs->reserved_sct); |
208 | reserved = le16_to_cpu(vs->reserved); | 207 | dbg("reserved_sct 0x%x", reserved_sct); |
209 | dbg("reserved 0x%x", reserved); | ||
210 | 208 | ||
211 | sect_count = le16_to_cpu(vs->sectors); | 209 | sect_count = le16_to_cpu(vs->sectors); |
212 | if (sect_count == 0) | 210 | if (sect_count == 0) |
213 | sect_count = le32_to_cpu(vs->total_sect); | 211 | sect_count = le32_to_cpu(vs->total_sect); |
214 | dbg("sect_count 0x%x", sect_count); | 212 | dbg("sect_count 0x%x", sect_count); |
215 | 213 | ||
216 | fat_length = le16_to_cpu(vs->fat_length); | 214 | fat_size_sct = le16_to_cpu(vs->fat_length); |
217 | if (fat_length == 0) | 215 | if (fat_size_sct == 0) |
218 | fat_length = le32_to_cpu(vs->type.fat32.fat32_length); | 216 | fat_size_sct = le32_to_cpu(vs->type.fat32.fat32_length); |
219 | dbg("fat_length 0x%x", fat_length); | 217 | fat_size_sct *= vs->fats; |
218 | dbg("fat_size_sct 0x%x", fat_size_sct); | ||
220 | 219 | ||
221 | fat_size = fat_length * vs->fats; | 220 | dir_entries = le16_to_cpu(vs->dir_entries); |
222 | dir_size = ((dir_entries * sizeof(struct vfat_dir_entry)) + | 221 | dir_size_sct = ((dir_entries * sizeof(struct vfat_dir_entry)) + |
223 | (sector_size-1)) / sector_size; | 222 | (sector_size_bytes-1)) / sector_size_bytes; |
224 | dbg("dir_size 0x%x", dir_size); | 223 | dbg("dir_size_sct 0x%x", dir_size_sct); |
225 | 224 | ||
226 | cluster_count = sect_count - (reserved + fat_size + dir_size); | 225 | cluster_count = sect_count - (reserved_sct + fat_size_sct + dir_size_sct); |
227 | cluster_count /= vs->sectors_per_cluster; | 226 | cluster_count /= vs->sectors_per_cluster; |
228 | dbg("cluster_count 0x%x", cluster_count); | 227 | dbg("cluster_count 0x%x", cluster_count); |
229 | 228 | ||
@@ -239,21 +238,18 @@ int volume_id_probe_vfat(struct volume_id *id, uint64_t off) | |||
239 | goto fat32; | 238 | goto fat32; |
240 | 239 | ||
241 | /* the label may be an attribute in the root directory */ | 240 | /* the label may be an attribute in the root directory */ |
242 | root_start = (reserved + fat_size) * sector_size; | 241 | root_start_off = (reserved_sct + fat_size_sct) * sector_size_bytes; |
243 | dbg("root dir start 0x%llx", (unsigned long long) root_start); | 242 | dbg("root dir start 0x%llx", (unsigned long long) root_start_off); |
244 | root_dir_entries = le16_to_cpu(vs->dir_entries); | 243 | dbg("expected entries 0x%x", dir_entries); |
245 | dbg("expected entries 0x%x", root_dir_entries); | ||
246 | 244 | ||
247 | buf_size = root_dir_entries * sizeof(struct vfat_dir_entry); | 245 | buf_size = dir_entries * sizeof(struct vfat_dir_entry); |
248 | buf = volume_id_get_buffer(id, off + root_start, buf_size); | 246 | buf = volume_id_get_buffer(id, fat_partition_off + root_start_off, buf_size); |
249 | if (buf == NULL) | 247 | if (buf == NULL) |
250 | goto found; | 248 | goto found; |
251 | 249 | ||
252 | dir = (struct vfat_dir_entry*) buf; | 250 | label = get_attr_volume_id((struct vfat_dir_entry*) buf, dir_entries); |
253 | |||
254 | label = get_attr_volume_id(dir, root_dir_entries); | ||
255 | 251 | ||
256 | vs = volume_id_get_buffer(id, off, 0x200); | 252 | vs = volume_id_get_buffer(id, fat_partition_off, 0x200); |
257 | if (vs == NULL) | 253 | if (vs == NULL) |
258 | return -1; | 254 | return -1; |
259 | 255 | ||
@@ -269,26 +265,25 @@ int volume_id_probe_vfat(struct volume_id *id, uint64_t off) | |||
269 | 265 | ||
270 | fat32: | 266 | fat32: |
271 | /* FAT32 root dir is a cluster chain like any other directory */ | 267 | /* FAT32 root dir is a cluster chain like any other directory */ |
272 | buf_size = vs->sectors_per_cluster * sector_size; | 268 | buf_size = vs->sectors_per_cluster * sector_size_bytes; |
273 | root_cluster = le32_to_cpu(vs->type.fat32.root_cluster); | 269 | root_cluster = le32_to_cpu(vs->type.fat32.root_cluster); |
274 | dbg("root dir cluster %u", root_cluster); | 270 | start_data_sct = reserved_sct + fat_size_sct; |
275 | start_data_sect = reserved + fat_size; | ||
276 | 271 | ||
277 | next = root_cluster; | 272 | next_cluster = root_cluster; |
278 | maxloop = 100; | 273 | maxloop = 100; |
279 | while (--maxloop) { | 274 | while (--maxloop) { |
280 | uint32_t next_sect_off; | 275 | uint32_t next_off_sct; |
281 | uint64_t next_off; | 276 | uint64_t next_off; |
282 | uint64_t fat_entry_off; | 277 | uint64_t fat_entry_off; |
283 | int count; | 278 | int count; |
284 | 279 | ||
285 | dbg("next cluster %u", next); | 280 | dbg("next_cluster 0x%x", (unsigned)next_cluster); |
286 | next_sect_off = (next - 2) * vs->sectors_per_cluster; | 281 | next_off_sct = (next_cluster - 2) * vs->sectors_per_cluster; |
287 | next_off = (start_data_sect + next_sect_off) * sector_size; | 282 | next_off = (start_data_sct + next_off_sct) * sector_size_bytes; |
288 | dbg("cluster offset 0x%llx", (unsigned long long) next_off); | 283 | dbg("cluster offset 0x%llx", (unsigned long long) next_off); |
289 | 284 | ||
290 | /* get cluster */ | 285 | /* get cluster */ |
291 | buf = volume_id_get_buffer(id, off + next_off, buf_size); | 286 | buf = volume_id_get_buffer(id, fat_partition_off + next_off, buf_size); |
292 | if (buf == NULL) | 287 | if (buf == NULL) |
293 | goto found; | 288 | goto found; |
294 | 289 | ||
@@ -301,20 +296,21 @@ int volume_id_probe_vfat(struct volume_id *id, uint64_t off) | |||
301 | break; | 296 | break; |
302 | 297 | ||
303 | /* get FAT entry */ | 298 | /* get FAT entry */ |
304 | fat_entry_off = (reserved * sector_size) + (next * sizeof(uint32_t)); | 299 | fat_entry_off = (reserved_sct * sector_size_bytes) + (next_cluster * sizeof(uint32_t)); |
305 | buf = volume_id_get_buffer(id, off + fat_entry_off, buf_size); | 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); | ||
306 | if (buf == NULL) | 302 | if (buf == NULL) |
307 | goto found; | 303 | goto found; |
308 | 304 | ||
309 | /* set next cluster */ | 305 | /* set next cluster */ |
310 | next = le32_to_cpu(*((uint32_t *) buf) & 0x0fffffff); | 306 | next_cluster = le32_to_cpu(*(uint32_t*)buf) & 0x0fffffff; |
311 | if (next == 0) | 307 | if (next_cluster < 2 || next_cluster > FAT32_MAX) |
312 | break; | 308 | break; |
313 | } | 309 | } |
314 | if (maxloop == 0) | 310 | if (maxloop == 0) |
315 | dbg("reached maximum follow count of root cluster chain, give up"); | 311 | dbg("reached maximum follow count of root cluster chain, give up"); |
316 | 312 | ||
317 | vs = volume_id_get_buffer(id, off, 0x200); | 313 | vs = volume_id_get_buffer(id, fat_partition_off, 0x200); |
318 | if (vs == NULL) | 314 | if (vs == NULL) |
319 | return -1; | 315 | return -1; |
320 | 316 | ||
diff --git a/util-linux/volume_id/luks.c b/util-linux/volume_id/luks.c index 51dda4e79..b0f0f5b21 100644 --- a/util-linux/volume_id/luks.c +++ b/util-linux/volume_id/luks.c | |||
@@ -20,20 +20,16 @@ | |||
20 | 20 | ||
21 | #include "volume_id_internal.h" | 21 | #include "volume_id_internal.h" |
22 | 22 | ||
23 | #define SECTOR_SHIFT 9 | 23 | #define LUKS_MAGIC_L 6 |
24 | #define SECTOR_SIZE (1 << SECTOR_SHIFT) | 24 | #define UUID_STRING_L 40 |
25 | 25 | #define LUKS_CIPHERNAME_L 32 | |
26 | #define LUKS_CIPHERNAME_L 32 | 26 | #define LUKS_CIPHERMODE_L 32 |
27 | #define LUKS_CIPHERMODE_L 32 | 27 | #define LUKS_HASHSPEC_L 32 |
28 | #define LUKS_HASHSPEC_L 32 | 28 | #define LUKS_DIGESTSIZE 20 |
29 | #define LUKS_DIGESTSIZE 20 | 29 | #define LUKS_SALTSIZE 32 |
30 | #define LUKS_SALTSIZE 32 | 30 | #define LUKS_NUMKEYS 8 |
31 | #define LUKS_NUMKEYS 8 | ||
32 | 31 | ||
33 | static const uint8_t LUKS_MAGIC[] = { 'L','U','K','S', 0xba, 0xbe }; | 32 | static const uint8_t LUKS_MAGIC[] = { 'L','U','K','S', 0xba, 0xbe }; |
34 | #define LUKS_MAGIC_L 6 | ||
35 | #define LUKS_PHDR_SIZE (sizeof(struct luks_phdr)/SECTOR_SIZE+1) | ||
36 | #define UUID_STRING_L 40 | ||
37 | 33 | ||
38 | struct luks_phdr { | 34 | struct luks_phdr { |
39 | uint8_t magic[LUKS_MAGIC_L]; | 35 | uint8_t magic[LUKS_MAGIC_L]; |
@@ -56,11 +52,39 @@ struct luks_phdr { | |||
56 | } keyblock[LUKS_NUMKEYS]; | 52 | } keyblock[LUKS_NUMKEYS]; |
57 | }; | 53 | }; |
58 | 54 | ||
55 | enum { | ||
56 | EXPECTED_SIZE_luks_phdr = 0 | ||
57 | + 1 * LUKS_MAGIC_L | ||
58 | + 2 | ||
59 | + 1 * LUKS_CIPHERNAME_L | ||
60 | + 1 * LUKS_CIPHERMODE_L | ||
61 | + 1 * LUKS_HASHSPEC_L | ||
62 | + 4 | ||
63 | + 4 | ||
64 | + 1 * LUKS_DIGESTSIZE | ||
65 | + 1 * LUKS_SALTSIZE | ||
66 | + 4 | ||
67 | + 1 * UUID_STRING_L | ||
68 | + LUKS_NUMKEYS * (0 | ||
69 | + 4 | ||
70 | + 4 | ||
71 | + 1 * LUKS_SALTSIZE | ||
72 | + 4 | ||
73 | + 4 | ||
74 | ) | ||
75 | }; | ||
76 | |||
77 | struct BUG_bad_size_luks_phdr { | ||
78 | char BUG_bad_size_luks_phdr[ | ||
79 | sizeof(struct luks_phdr) == EXPECTED_SIZE_luks_phdr ? | ||
80 | 1 : -1]; | ||
81 | }; | ||
82 | |||
59 | int volume_id_probe_luks(struct volume_id *id, uint64_t off) | 83 | int volume_id_probe_luks(struct volume_id *id, uint64_t off) |
60 | { | 84 | { |
61 | struct luks_phdr *header; | 85 | struct luks_phdr *header; |
62 | 86 | ||
63 | header = volume_id_get_buffer(id, off, LUKS_PHDR_SIZE); | 87 | header = volume_id_get_buffer(id, off, sizeof(*header)); |
64 | if (header == NULL) | 88 | if (header == NULL) |
65 | return -1; | 89 | return -1; |
66 | 90 | ||
diff --git a/util-linux/volume_id/util.c b/util-linux/volume_id/util.c index 315d75ca6..c4d20ba47 100644 --- a/util-linux/volume_id/util.c +++ b/util-linux/volume_id/util.c | |||
@@ -181,7 +181,7 @@ set: | |||
181 | buf[4], buf[5], | 181 | buf[4], buf[5], |
182 | buf[6], buf[7], | 182 | buf[6], buf[7], |
183 | buf[8], buf[9], | 183 | buf[8], buf[9], |
184 | buf[10], buf[11], buf[12], buf[13], buf[14],buf[15]); | 184 | buf[10], buf[11], buf[12], buf[13], buf[14], buf[15]); |
185 | break; | 185 | break; |
186 | case UUID_DCE_STRING: | 186 | case UUID_DCE_STRING: |
187 | memcpy(id->uuid, buf, count); | 187 | memcpy(id->uuid, buf, count); |
@@ -190,6 +190,9 @@ set: | |||
190 | } | 190 | } |
191 | } | 191 | } |
192 | 192 | ||
193 | /* Do not use xlseek here. With it, single corrupted filesystem | ||
194 | * may result in attempt to seek past device -> exit. | ||
195 | * It's better to ignore such fs and continue. */ | ||
193 | 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) |
194 | { | 197 | { |
195 | ssize_t buf_len; | 198 | ssize_t buf_len; |
@@ -204,7 +207,10 @@ void *volume_id_get_buffer(struct volume_id *id, uint64_t off, size_t len) | |||
204 | /* check if we need to read */ | 207 | /* check if we need to read */ |
205 | if ((off + len) > id->sbbuf_len) { | 208 | if ((off + len) > id->sbbuf_len) { |
206 | dbg("read sbbuf len:0x%llx", (unsigned long long) (off + len)); | 209 | dbg("read sbbuf len:0x%llx", (unsigned long long) (off + len)); |
207 | xlseek(id->fd, 0, SEEK_SET); | 210 | if (lseek(id->fd, 0, SEEK_SET) != 0) { |
211 | dbg("seek(0) failed"); | ||
212 | return NULL; | ||
213 | } | ||
208 | buf_len = full_read(id->fd, id->sbbuf, off + len); | 214 | buf_len = full_read(id->fd, id->sbbuf, off + len); |
209 | if (buf_len < 0) { | 215 | if (buf_len < 0) { |
210 | dbg("read failed (%s)", strerror(errno)); | 216 | dbg("read failed (%s)", strerror(errno)); |
@@ -234,7 +240,10 @@ void *volume_id_get_buffer(struct volume_id *id, uint64_t off, size_t len) | |||
234 | /* check if we need to read */ | 240 | /* check if we need to read */ |
235 | if ((off < id->seekbuf_off) || ((off + len) > (id->seekbuf_off + id->seekbuf_len))) { | 241 | if ((off < id->seekbuf_off) || ((off + len) > (id->seekbuf_off + id->seekbuf_len))) { |
236 | dbg("read seekbuf off:0x%llx len:0x%zx", (unsigned long long) off, len); | 242 | dbg("read seekbuf off:0x%llx len:0x%zx", (unsigned long long) off, len); |
237 | xlseek(id->fd, off, SEEK_SET); | 243 | if (lseek(id->fd, off, SEEK_SET) != off) { |
244 | dbg("seek(0x%llx) failed", (unsigned long long) off); | ||
245 | return NULL; | ||
246 | } | ||
238 | buf_len = full_read(id->fd, id->seekbuf, len); | 247 | buf_len = full_read(id->fd, id->seekbuf, len); |
239 | if (buf_len < 0) { | 248 | if (buf_len < 0) { |
240 | dbg("read failed (%s)", strerror(errno)); | 249 | dbg("read failed (%s)", strerror(errno)); |