| 1 | diff -up -r linux-2.6.22.org/fs/fat/dir.c linux-2.6.22/fs/fat/dir.c | 1 | diff -r -u2 -p linux-2.6.22.unpatched/fs/fat/dir.c linux-2.6.22/fs/fat/dir.c | 
| 2 | --- linux-2.6.22.org/fs/fat/dir.c	2007-09-29 15:55:34.000000000 +0200 | 2 | --- linux-2.6.22.unpatched/fs/fat/dir.c	2007-11-06 22:45:27.000000000 +0100 | 
| 3 | +++ linux-2.6.22/fs/fat/dir.c	2007-09-29 15:56:24.000000000 +0200 | 3 | +++ linux-2.6.22/fs/fat/dir.c	2007-11-06 22:59:08.000000000 +0100 | 
| 4 | @@ -241,6 +241,7 @@ static int fat_parse_long(struct inode * | 4 | @@ -242,4 +242,5 @@ static int fat_parse_long(struct inode * | 
| 5 | { |  |  | 
| 6 | struct msdos_dir_slot *ds; | 5 | struct msdos_dir_slot *ds; | 
| 7 | unsigned char id, slot, slots, alias_checksum; | 6 | unsigned char id, slot, slots, alias_checksum; | 
| 8 | +	int epoc = MSDOS_SB(dir->i_sb)->options.epoc; | 7 | +	int epoc = MSDOS_SB(dir->i_sb)->options.epoc; | 
| 9 |  | 8 |  | 
| 10 | if (!*unicode) { | 9 | if (!*unicode) { | 
| 11 | *unicode = (wchar_t *)__get_free_page(GFP_KERNEL); |  |  | 
| 12 | @@ -287,6 +288,8 @@ parse_long: | 10 | @@ -288,4 +289,8 @@ parse_long: | 
| 13 | } |  |  | 
| 14 | if ((*de)->name[0] == DELETED_FLAG) | 11 | if ((*de)->name[0] == DELETED_FLAG) | 
| 15 | return PARSE_INVALID; | 12 | return PARSE_INVALID; | 
| 16 | +	if (epoc && ((*de)->name[0] == EOD_FLAG)) | 13 | +	if (epoc && ((*de)->name[0] == EOD_FLAG)) { | 
|  |  | 14 | +		while (fat_get_entry(dir, pos, bh, de) >= 0); | 
| 17 | +		return PARSE_EOF; | 15 | +		return PARSE_EOF; | 
|  |  | 16 | +	} | 
| 18 | if ((*de)->attr == ATTR_EXT) | 17 | if ((*de)->attr == ATTR_EXT) | 
| 19 | goto parse_long; | 18 | goto parse_long; | 
| 20 | if (IS_FREE((*de)->name) || ((*de)->attr & ATTR_VOLUME)) |  |  | 
| 21 | @@ -320,6 +323,7 @@ int fat_search_long(struct inode *inode, | 19 | @@ -321,4 +326,5 @@ int fat_search_long(struct inode *inode, | 
| 22 | unsigned short opt_shortname = sbi->options.shortname; |  |  | 
| 23 | loff_t cpos = 0; | 20 | loff_t cpos = 0; | 
| 24 | int chl, i, j, last_u, err; | 21 | int chl, i, j, last_u, err; | 
| 25 | +	int epoc = sbi->options.epoc; | 22 | +	int epoc = sbi->options.epoc; | 
| 26 |  | 23 |  | 
| 27 | err = -ENOENT; | 24 | err = -ENOENT; | 
| 28 | while(1) { |  |  | 
| 29 | @@ -329,6 +333,9 @@ parse_record: | 25 | @@ -330,4 +336,8 @@ parse_record: | 
| 30 | nr_slots = 0; |  |  | 
| 31 | if (de->name[0] == DELETED_FLAG) | 26 | if (de->name[0] == DELETED_FLAG) | 
| 32 | continue; | 27 | continue; | 
| 33 | +		if (epoc && (de->name[0] == EOD_FLAG)) | 28 | +		if (epoc && (de->name[0] == EOD_FLAG)) { | 
|  |  | 29 | +			while (fat_get_entry(inode, &cpos, &bh, &de) >= 0); | 
| 34 | +			goto EODir; | 30 | +			goto EODir; | 
| 35 | + | 31 | +		} | 
| 36 | if (de->attr != ATTR_EXT && (de->attr & ATTR_VOLUME)) | 32 | if (de->attr != ATTR_EXT && (de->attr & ATTR_VOLUME)) | 
| 37 | continue; | 33 | continue; | 
| 38 | if (de->attr != ATTR_EXT && IS_FREE(de->name)) |  |  | 
| 39 | @@ -456,6 +463,8 @@ static int __fat_readdir(struct inode *i | 34 | @@ -457,4 +467,6 @@ static int __fat_readdir(struct inode *i | 
| 40 | int chi, chl, i, i2, j, last, last_u, dotoffset = 0; |  |  | 
| 41 | loff_t cpos; | 35 | loff_t cpos; | 
| 42 | int ret = 0; | 36 | int ret = 0; | 
| 43 | +	int epoc = MSDOS_SB(sb)->options.epoc; | 37 | +	int epoc = MSDOS_SB(sb)->options.epoc; | 
| 44 | + | 38 | + | 
| 45 |  | 39 |  | 
| 46 | lock_kernel(); | 40 | lock_kernel(); | 
| 47 |  | 41 | @@ -487,4 +499,8 @@ parse_record: | 
| 48 | @@ -486,6 +495,8 @@ GetNew: |  |  | 
| 49 | parse_record: |  |  | 
| 50 | long_slots = 0; | 42 | long_slots = 0; | 
| 51 | /* Check for long filename entry */ | 43 | /* Check for long filename entry */ | 
| 52 | +	if (epoc && (de->name[0] == EOD_FLAG)) | 44 | +	if (epoc && (de->name[0] == EOD_FLAG)) { | 
|  |  | 45 | +		while (fat_get_entry(inode, &cpos, &bh, &de) >= 0); | 
| 53 | +		goto EODir; | 46 | +		goto EODir; | 
|  |  | 47 | +	} | 
| 54 | if (isvfat) { | 48 | if (isvfat) { | 
| 55 | if (de->name[0] == DELETED_FLAG) | 49 | if (de->name[0] == DELETED_FLAG) | 
| 56 | goto RecEnd; |  |  | 
| 57 | @@ -809,7 +820,10 @@ static int fat_get_short_entry(struct in | 50 | @@ -810,5 +826,10 @@ static int fat_get_short_entry(struct in | 
| 58 | struct buffer_head **bh, |  |  | 
| 59 | struct msdos_dir_entry **de) | 51 | struct msdos_dir_entry **de) | 
| 60 | { | 52 | { | 
| 61 | +	int epoc = MSDOS_SB(dir->i_sb)->options.epoc; | 53 | +	int epoc = MSDOS_SB(dir->i_sb)->options.epoc; | 
| 62 | while (fat_get_entry(dir, pos, bh, de) >= 0) { | 54 | while (fat_get_entry(dir, pos, bh, de) >= 0) { | 
| 63 | +		if (epoc && ((*de)->name[0] == EOD_FLAG)) | 55 | +		if (epoc && ((*de)->name[0] == EOD_FLAG)) { | 
|  |  | 56 | +			while (fat_get_entry(dir, pos, bh, de) >= 0); | 
| 64 | +			return -ENOENT; | 57 | +			return -ENOENT; | 
|  |  | 58 | +		} | 
| 65 | /* free entry or long name entry or volume label */ | 59 | /* free entry or long name entry or volume label */ | 
| 66 | if (!IS_FREE((*de)->name) && !((*de)->attr & ATTR_VOLUME)) | 60 | if (!IS_FREE((*de)->name) && !((*de)->attr & ATTR_VOLUME)) | 
| 67 | return 0; |  |  | 
| 68 | @@ -1187,6 +1201,25 @@ error: | 61 | @@ -1188,4 +1209,23 @@ error: | 
| 69 | return err; |  |  | 
| 70 | } | 62 | } | 
| 71 |  | 63 |  | 
| 72 | +int fat_write_zero_entry(struct inode *dir, loff_t curr) | 64 | +int fat_write_zero_entry(struct inode *dir, loff_t curr) | 
| 73 | +{ | 65 | +{ | 
| 74 | +       struct msdos_dir_entry *de = NULL; | 66 | +       struct msdos_dir_entry *de = NULL; | 
| … |  | … |  | 
| 88 | +       return err; | 80 | +       return err; | 
| 89 | +} | 81 | +} | 
| 90 | + | 82 | + | 
| 91 | int fat_add_entries(struct inode *dir, void *slots, int nr_slots, | 83 | int fat_add_entries(struct inode *dir, void *slots, int nr_slots, | 
| 92 | struct fat_slot_info *sinfo) | 84 | struct fat_slot_info *sinfo) | 
| 93 | { |  |  | 
| 94 | @@ -1196,6 +1229,8 @@ int fat_add_entries(struct inode *dir, v | 85 | @@ -1197,4 +1237,6 @@ int fat_add_entries(struct inode *dir, v | 
| 95 | struct msdos_dir_entry *de; |  |  | 
| 96 | int err, free_slots, i, nr_bhs; | 86 | int err, free_slots, i, nr_bhs; | 
| 97 | loff_t pos, i_pos; | 87 | loff_t pos, i_pos; | 
| 98 | +	int epoc = sbi->options.epoc; | 88 | +	int epoc = sbi->options.epoc; | 
| 99 | +	int last_entry = 0; | 89 | +	int last_entry = 0; | 
| 100 |  | 90 |  | 
| 101 | sinfo->nr_slots = nr_slots; | 91 | sinfo->nr_slots = nr_slots; | 
| 102 |  |  |  | 
| 103 | @@ -1209,7 +1244,9 @@ int fat_add_entries(struct inode *dir, v | 92 | @@ -1210,5 +1252,7 @@ int fat_add_entries(struct inode *dir, v | 
| 104 | if (pos >= FAT_MAX_DIR_SIZE) |  |  | 
| 105 | goto error; | 93 | goto error; | 
| 106 |  | 94 |  | 
| 107 | -		if (IS_FREE(de->name)) { | 95 | -		if (IS_FREE(de->name)) { | 
| 108 | +		if (epoc && (de->name[0] == EOD_FLAG)) | 96 | +		if (epoc && (de->name[0] == EOD_FLAG)) | 
| 109 | +			last_entry = 1; | 97 | +			last_entry = 1; | 
| 110 | +		if (last_entry || IS_FREE(de->name)) { | 98 | +		if (last_entry || IS_FREE(de->name)) { | 
| 111 | if (prev != bh) { | 99 | if (prev != bh) { | 
| 112 | get_bh(bh); | 100 | get_bh(bh); | 
| 113 | bhs[nr_bhs] = prev = bh; |  |  | 
| 114 | @@ -1239,6 +1276,17 @@ found: | 101 | @@ -1240,4 +1284,15 @@ found: | 
| 115 | err = 0; |  |  | 
| 116 | pos -= free_slots * sizeof(*de); | 102 | pos -= free_slots * sizeof(*de); | 
| 117 | nr_slots -= free_slots; | 103 | nr_slots -= free_slots; | 
| 118 | + | 104 | + | 
| 119 | +	/* We need to write an end-of-directory slot. And we do it first, | 105 | +	/* We need to write an end-of-directory slot. And we do it first, | 
| 120 | +         * because we want to keep the directory in a readble state. | 106 | +         * because we want to keep the directory in a readble state. | 
| … |  | … |  | 
| 126 | +	if (err) | 112 | +	if (err) | 
| 127 | +		goto error; | 113 | +		goto error; | 
| 128 | + | 114 | + | 
| 129 | if (free_slots) { | 115 | if (free_slots) { | 
| 130 | /* | 116 | /* | 
| 131 | * Second stage: filling the free entries with new entries. |  |  | 
| 132 | Only in linux-2.6.22/fs/fat: dir.c.orig |  |  | 
| 133 | diff -up -r linux-2.6.22.org/fs/fat/inode.c linux-2.6.22/fs/fat/inode.c | 117 | diff -r -u2 -p linux-2.6.22.unpatched/fs/fat/inode.c linux-2.6.22/fs/fat/inode.c | 
| 134 | --- linux-2.6.22.org/fs/fat/inode.c	2007-09-29 15:55:34.000000000 +0200 | 118 | --- linux-2.6.22.unpatched/fs/fat/inode.c	2007-11-06 22:45:27.000000000 +0100 | 
| 135 | +++ linux-2.6.22/fs/fat/inode.c	2007-09-29 15:56:24.000000000 +0200 | 119 | +++ linux-2.6.22/fs/fat/inode.c	2007-11-06 22:47:36.000000000 +0100 | 
| 136 | @@ -856,6 +856,7 @@ enum { | 120 | @@ -857,4 +857,5 @@ enum { | 
| 137 | Opt_charset, Opt_shortname_lower, Opt_shortname_win95, |  |  | 
| 138 | Opt_shortname_winnt, Opt_shortname_mixed, Opt_utf8_no, Opt_utf8_yes, | 121 | Opt_shortname_winnt, Opt_shortname_mixed, Opt_utf8_no, Opt_utf8_yes, | 
| 139 | Opt_uni_xl_no, Opt_uni_xl_yes, Opt_nonumtail_no, Opt_nonumtail_yes, | 122 | Opt_uni_xl_no, Opt_uni_xl_yes, Opt_nonumtail_no, Opt_nonumtail_yes, | 
| 140 | +	Opt_epoc, | 123 | +	Opt_epoc, | 
| 141 | Opt_obsolate, Opt_flush, Opt_err, | 124 | Opt_obsolate, Opt_flush, Opt_err, | 
| 142 | }; | 125 | }; | 
| 143 |  |  |  | 
| 144 | @@ -878,6 +879,7 @@ static match_table_t fat_tokens = { | 126 | @@ -879,4 +880,5 @@ static match_table_t fat_tokens = { | 
| 145 | {Opt_showexec, "showexec"}, |  |  | 
| 146 | {Opt_debug, "debug"}, | 127 | {Opt_debug, "debug"}, | 
| 147 | {Opt_immutable, "sys_immutable"}, | 128 | {Opt_immutable, "sys_immutable"}, | 
| 148 | +	{Opt_epoc, "epoc"}, | 129 | +	{Opt_epoc, "epoc"}, | 
| 149 | {Opt_obsolate, "conv=binary"}, | 130 | {Opt_obsolate, "conv=binary"}, | 
| 150 | {Opt_obsolate, "conv=text"}, | 131 | {Opt_obsolate, "conv=text"}, | 
| 151 | {Opt_obsolate, "conv=auto"}, |  |  | 
| 152 | @@ -1037,6 +1039,10 @@ static int parse_options(char *options, | 132 | @@ -1038,4 +1040,8 @@ static int parse_options(char *options, | 
| 153 | case Opt_flush: |  |  | 
| 154 | opts->flush = 1; | 133 | opts->flush = 1; | 
| 155 | break; | 134 | break; | 
| 156 | +		case Opt_epoc: | 135 | +		case Opt_epoc: | 
| 157 | +			opts->epoc = 1; | 136 | +			opts->epoc = 1; | 
| 158 | +			break; | 137 | +			break; | 
| 159 | + | 138 | + | 
| 160 |  | 139 |  | 
| 161 | /* msdos specific */ | 140 | /* msdos specific */ | 
| 162 | case Opt_dots: |  |  | 
| 163 | Only in linux-2.6.22/fs/fat: inode.c.orig |  |  | 
| 164 | diff -up -r linux-2.6.22.org/include/linux/msdos_fs.h linux-2.6.22/include/linux/msdos_fs.h | 141 | diff -r -u2 -p linux-2.6.22.unpatched/include/linux/msdos_fs.h linux-2.6.22/include/linux/msdos_fs.h | 
| 165 | --- linux-2.6.22.org/include/linux/msdos_fs.h	2007-09-29 15:55:56.000000000 +0200 | 142 | --- linux-2.6.22.unpatched/include/linux/msdos_fs.h	2007-11-06 22:46:01.000000000 +0100 | 
| 166 | +++ linux-2.6.22/include/linux/msdos_fs.h	2007-09-29 15:57:26.000000000 +0200 | 143 | +++ linux-2.6.22/include/linux/msdos_fs.h	2007-11-06 22:47:36.000000000 +0100 | 
| 167 | @@ -44,6 +44,7 @@ | 144 | @@ -45,4 +45,5 @@ | 
| 168 | #define CASE_LOWER_EXT	16	/* extension is lower case */ |  |  | 
| 169 |  | 145 |  | 
| 170 | #define DELETED_FLAG	0xe5	/* marks file as deleted when in name[0] */ | 146 | #define DELETED_FLAG	0xe5	/* marks file as deleted when in name[0] */ | 
| 171 | +#define EOD_FLAG 0x00 /* marks end of directory when in name[0] for old fats */ | 147 | +#define EOD_FLAG 0x00 /* marks end of directory when in name[0] for old fats */ | 
| 172 | #define IS_FREE(n)	(!*(n) || *(n) == DELETED_FLAG) | 148 | #define IS_FREE(n)	(!*(n) || *(n) == DELETED_FLAG) | 
| 173 |  | 149 |  | 
| 174 | /* valid file mode bits */ |  |  | 
| 175 | @@ -206,6 +207,7 @@ struct fat_mount_options { | 150 | @@ -207,4 +208,5 @@ struct fat_mount_options { | 
| 176 | atari:1,         /* Use Atari GEMDOS variation of MS-DOS fs */ |  |  | 
| 177 | flush:1,	  /* write things quickly */ | 151 | flush:1,	  /* write things quickly */ | 
| 178 | nocase:1,	  /* Does this need case conversion? 0=need case conversion*/ | 152 | nocase:1,	  /* Does this need case conversion? 0=need case conversion*/ | 
| 179 | +		 epoc:1;          /* Filename starting with 0x00 marks end of dir? */ | 153 | +		 epoc:1,          /* Filename starting with 0x00 marks end of dir? */ | 
| 180 | usefree:1;	  /* Use free_clusters for FAT32 */ | 154 | usefree:1;	  /* Use free_clusters for FAT32 */ | 
| 181 | }; | 155 | }; | 
| 182 |  |  |  |