VFAT i_pos value
Kai Meyer
kai at gnukai.com
Thu Dec 8 16:35:56 EST 2011
On 12/02/2011 11:23 PM, OGAWA Hirofumi wrote:
> OGAWA Hirofumi<hirofumi at mail.parknet.co.jp> writes:
>
>> Kai Meyer<kai at gnukai.com> writes:
>>
>>> 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 at 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?
More information about the Kernelnewbies
mailing list