On 12/02/2011 11:23 PM, OGAWA Hirofumi wrote: > OGAWA Hirofumi<hirofumi@xxxxxxxxxxxxxxxxxx> writes: > >> Kai Meyer<kai@xxxxxxxxxx> 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@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? _______________________________________________ Kernelnewbies mailing list Kernelnewbies@xxxxxxxxxxxxxxxxx http://lists.kernelnewbies.org/mailman/listinfo/kernelnewbies