VFAT i_pos value
From: Kai Meyer <hidden>
Date: 2011-12-08 21:35:56
On 12/02/2011 11:23 PM, OGAWA Hirofumi wrote:
OGAWA Hirofumi[off-list ref] writes:quoted
Kai Meyer[off-list ref] writes:quoted
Thanks for the helpful response. I'm not entirely sure I understand the next part though. I hacked a dirty entry dumper tool: #include<stdio.h> #include<linux/msdos_fs.h> #include<sys/types.h> #include<sys/stat.h> #include<fcntl.h> #include<unistd.h> #include<string.h> int main(int argc, char** argv) { off_t pos = atoi(argv[2]); unsigned long block; off_t sector; unsigned int offset; int fd = open(argv[1], O_RDONLY); char buf[512]; struct msdos_dir_entry dirent; block = pos / (4096 / 32); sector = block * 8; offset = pos % (4096 / 32); printf("block %lu, sector %lu, offset %u\n", block, sector, offset); lseek(fd, sector * 512, SEEK_SET); if (read(fd, buf, 512)< 0) { fprintf(stderr, "Unable to read from device %s\n", argv[1]); return -1; } memcpy(&dirent, buf + offset, sizeof(dirent)); printf("name %s\n", dirent.name); printf("attr %u\n", dirent.attr); printf("lcase %u\n", dirent.lcase); printf("ctime_cs %u\n", dirent.ctime_cs); printf("ctime %u\n", dirent.ctime); printf("cdate %u\n", dirent.cdate); printf("adate %u\n", dirent.adate); printf("starthi %u\n", dirent.starthi); printf("time %u\n", dirent.time); printf("date %u\n", dirent.date); printf("start %u\n", dirent.start); printf("size %u\n", dirent.size); } Here's what it outputs: ./vfat_entry /dev/sblsnap0 523793 block 4092, sector 32736, offset 17 name attr 255 lcase 255 ctime_cs 255 ctime 12799 cdate 12670 adate 8224 starthi 8224 time 23072 date 21061 start 32 size 2171155456 So, I take starthi, and shift 16 bits left, then and in the start value. That should give me the byte address of the first cluster of the file, correct? Then I need to follow the cluster chain until I get a bad value.It looks like wrong as dirent. Did you use 523793 really? If so, I think 523791 is correct value. :)And I didn't mention about offset correctly. offset means number of entries, not bytes offset. So, bytes offset is "buf + offset * 32". (32 == sizeof(struct msdos_dir_entry)) Thanks.
Ok, I fixed the buf + offset * 32. I have a new volume, so the error is now:
fat_get_cluster: invalid cluster chain (i_pos 523781)
I added a few lines at the end to print the start value:
pos = dirent.starthi << 16;
pos |= dirent.start;
printf("next pos: %u\n", sector);
[root at dev1 sblsnap]# ./vfat_entry /dev/sblsnap0 523781
block 4092, sector 32736, offset 5
name 3~1 ZER
attr 32
lcase 0
ctime_cs 100
ctime 29092
cdate 16264
adate 16264
starthi 4
time 29092
date 16264
start 7427
size 37748736
next pos: 32736
[root@dev1 sblsnap]# ./vfat_entry /dev/sblsnap0 32736
block 255, sector 2040, offset 96
name
attr 0
lcase 0
ctime_cs 0
ctime 0
cdate 0
adate 0
starthi 0
time 0
date 0
start 0
size 0
next pos: 2040
Does that look like what would be causing my error? meaning, sector 2040
has bad data?