summaryrefslogtreecommitdiff
path: root/core
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@zytor.com>2010-02-01 18:21:08 -0800
committerH. Peter Anvin <hpa@zytor.com>2010-02-01 18:21:08 -0800
commitd151fabc36d0076a4e7ca375fa32fb4755018e2d (patch)
tree24963e140a2bf4ce4c8d27a4920725311f1cdb62 /core
parent4ea1dfba92844dd53b66bb706f6f9c02962ad03a (diff)
downloadsyslinux-d151fabc36d0076a4e7ca375fa32fb4755018e2d.tar.gz
FAT: For FAT32, the root directory is a cluster chainsyslinux-4.00-pre15
The old code would set the FAT32 root directory right after the FAT like everything else... which would just happen to work if the root directory was in cluster 2. This is very common for a newly formatted filesystem, but isn't guaranteed! Reported-by: Gert Huselmans <gerth@zytor.com> Signed-off-by: H. Peter Anvin <hpa@zytor.com>
Diffstat (limited to 'core')
-rw-r--r--core/fs/fat/fat.c20
1 files changed, 13 insertions, 7 deletions
diff --git a/core/fs/fat/fat.c b/core/fs/fat/fat.c
index ea692a4a..bdfc8d01 100644
--- a/core/fs/fat/fat.c
+++ b/core/fs/fat/fat.c
@@ -391,7 +391,7 @@ static struct inode *vfat_find_entry(char *dname, struct inode *dir)
struct fat_long_name_entry *long_de;
struct cache_struct *cs;
- char mangled_name[12] = {0, };
+ char mangled_name[12];
sector_t dir_sector = *(sector_t *)dir->pvt;
uint8_t vfat_init, vfat_next, vfat_csum = 0;
@@ -405,6 +405,9 @@ static struct inode *vfat_find_entry(char *dname, struct inode *dir)
slots |= 0x40;
vfat_init = vfat_next = slots;
+ /* Produce the shortname version, if appropriate. */
+ mangle_dos_name(mangled_name, dname);
+
while (1) {
cs = get_cache_block(fs->fs_dev, dir_sector);
de = (struct fat_dir_entry *)cs->data;
@@ -472,11 +475,6 @@ static struct inode *vfat_find_entry(char *dname, struct inode *dir)
if (checksum == vfat_csum)
goto found; /* Got it */
} else {
- if (mangled_name[0] == 0) {
- /* We haven't mangled it, mangle it first. */
- mangle_dos_name(mangled_name, dname);
- }
-
if (!strncmp(mangled_name, de->name, 11))
goto found;
}
@@ -507,7 +505,11 @@ static struct inode *vfat_iget_root(struct fs_info *fs)
struct inode *inode = new_fat_inode(fs);
int root_size = FAT_SB(fs)->root_size;
- inode->size = root_size << fs->sector_shift;
+ /*
+ * For FAT32, the only way to get the root directory size is to
+ * follow the entire FAT chain to the end... which seems pointless.
+ */
+ inode->size = root_size ? root_size << fs->sector_shift : ~0;
*(sector_t *)inode->pvt = FAT_SB(fs)->root;
inode->mode = I_DIR;
@@ -744,6 +746,10 @@ static int vfat_fs_init(struct fs_info *fs)
/* Non-mirrored FATs, we need to read the active one */
sbi->fat += (fat.fat32.extended_flags & 0x0f) * sectors_per_fat;
}
+
+ /* FAT32: root directory is a cluster chain */
+ sbi->root = sbi->data
+ + ((fat.fat32.root_cluster-2) << sbi->clust_shift);
}
sbi->clusters = clusters;