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