summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@zytor.com>2010-06-13 14:18:23 -0700
committerH. Peter Anvin <hpa@zytor.com>2010-06-13 14:18:23 -0700
commit1ea741be7aad4c77d4fd2a602c3669ac59f1db73 (patch)
treea8965aab4e5d15b76e18185418bacf31d784fdef
parent92d1d619c033353a5e532b7118daee1a403f08ca (diff)
downloadsyslinux-1ea741be7aad4c77d4fd2a602c3669ac59f1db73.tar.gz
fat: handle .. pointing back to the root directory
.. pointing back to the root directory will have a cluster number of 0, even for FAT32 where there is an actual cluster number for the root directory. Handle this as a special case. Signed-off-by: H. Peter Anvin <hpa@zytor.com>
-rw-r--r--core/fs/fat/fat.c36
1 files changed, 27 insertions, 9 deletions
diff --git a/core/fs/fat/fat.c b/core/fs/fat/fat.c
index 6850993a..5902f481 100644
--- a/core/fs/fat/fat.c
+++ b/core/fs/fat/fat.c
@@ -276,26 +276,32 @@ static void mangle_dos_name(char *mangle_buf, const char *src)
int i;
unsigned char c;
- i = 0;
- while (i < 11) {
- c = *src++;
-
+ if (src[0] == '.' && (!src[1] || (src[1] == '.' && !src[2]))) {
+ /* . and .. mangle to their respective zero-padded version */
+ i = stpcpy(mangle_buf, src) - mangle_buf;
+ } else {
+ i = 0;
+ while (i < 11) {
+ c = *src++;
+
if ((c <= ' ') || (c == '/'))
break;
-
+
if (c == '.') {
while (i < 8)
mangle_buf[i++] = ' ';
i = 8;
continue;
}
-
+
c = codepage.upper[c];
if (i == 0 && c == 0xe5)
c = 0x05; /* Special hack for the first byte only! */
-
+
mangle_buf[i++] = c;
+ }
}
+
while (i < 11)
mangle_buf[i++] = ' ';
@@ -408,7 +414,10 @@ static inline sector_t first_sector(struct fs_info *fs,
sector_t sector;
first_clust = (dir->first_cluster_high << 16) + dir->first_cluster_low;
- sector = ((first_clust - 2) << sbi->clust_shift) + sbi->data;
+ if (first_clust == 0)
+ sector = sbi->root; /* first_clust == 0 means root directory */
+ else
+ sector = ((first_clust - 2) << sbi->clust_shift) + sbi->data;
return sector;
}
@@ -533,7 +542,16 @@ found:
inode->size = de->file_size;
PVT(inode)->start_cluster =
(de->first_cluster_high << 16) + de->first_cluster_low;
- PVT(inode)->start = PVT(inode)->here = first_sector(fs, de);
+ if (PVT(inode)->start_cluster == 0) {
+ /* Root directory */
+ int root_size = FAT_SB(fs)->root_size;
+
+ PVT(inode)->start_cluster = FAT_SB(fs)->root_cluster;
+ inode->size = root_size ? root_size << fs->sector_shift : ~0;
+ PVT(inode)->start = PVT(inode)->here = FAT_SB(fs)->root;
+ } else {
+ PVT(inode)->start = PVT(inode)->here = first_sector(fs, de);
+ }
inode->mode = get_inode_mode(de->attr);
return inode;