Commit 4de151d8cd2553e7e89044ab5d72fcad4eb04afb
Committed by
Adrian Bunk
1 parent
e0f4ab8a17
Exists in
master
and in
4 other branches
It's UTF-8
Fix some comments to "UTF-8". Signed-off-by: Alexey Dobriyan <adobriyan@gmail.com> Signed-off-by: Adrian Bunk <bunk@stusta.de>
Showing 11 changed files with 14 additions and 14 deletions Inline Diff
Documentation/filesystems/isofs.txt
1 | Mount options that are the same as for msdos and vfat partitions. | 1 | Mount options that are the same as for msdos and vfat partitions. |
2 | 2 | ||
3 | gid=nnn All files in the partition will be in group nnn. | 3 | gid=nnn All files in the partition will be in group nnn. |
4 | uid=nnn All files in the partition will be owned by user id nnn. | 4 | uid=nnn All files in the partition will be owned by user id nnn. |
5 | umask=nnn The permission mask (see umask(1)) for the partition. | 5 | umask=nnn The permission mask (see umask(1)) for the partition. |
6 | 6 | ||
7 | Mount options that are the same as vfat partitions. These are only useful | 7 | Mount options that are the same as vfat partitions. These are only useful |
8 | when using discs encoded using Microsoft's Joliet extensions. | 8 | when using discs encoded using Microsoft's Joliet extensions. |
9 | iocharset=name Character set to use for converting from Unicode to | 9 | iocharset=name Character set to use for converting from Unicode to |
10 | ASCII. Joliet filenames are stored in Unicode format, but | 10 | ASCII. Joliet filenames are stored in Unicode format, but |
11 | Unix for the most part doesn't know how to deal with Unicode. | 11 | Unix for the most part doesn't know how to deal with Unicode. |
12 | There is also an option of doing UTF8 translations with the | 12 | There is also an option of doing UTF-8 translations with the |
13 | utf8 option. | 13 | utf8 option. |
14 | utf8 Encode Unicode names in UTF8 format. Default is no. | 14 | utf8 Encode Unicode names in UTF-8 format. Default is no. |
15 | 15 | ||
16 | Mount options unique to the isofs filesystem. | 16 | Mount options unique to the isofs filesystem. |
17 | block=512 Set the block size for the disk to 512 bytes | 17 | block=512 Set the block size for the disk to 512 bytes |
18 | block=1024 Set the block size for the disk to 1024 bytes | 18 | block=1024 Set the block size for the disk to 1024 bytes |
19 | block=2048 Set the block size for the disk to 2048 bytes | 19 | block=2048 Set the block size for the disk to 2048 bytes |
20 | check=relaxed Matches filenames with different cases | 20 | check=relaxed Matches filenames with different cases |
21 | check=strict Matches only filenames with the exact same case | 21 | check=strict Matches only filenames with the exact same case |
22 | cruft Try to handle badly formatted CDs. | 22 | cruft Try to handle badly formatted CDs. |
23 | map=off Do not map non-Rock Ridge filenames to lower case | 23 | map=off Do not map non-Rock Ridge filenames to lower case |
24 | map=normal Map non-Rock Ridge filenames to lower case | 24 | map=normal Map non-Rock Ridge filenames to lower case |
25 | map=acorn As map=normal but also apply Acorn extensions if present | 25 | map=acorn As map=normal but also apply Acorn extensions if present |
26 | mode=xxx Sets the permissions on files to xxx | 26 | mode=xxx Sets the permissions on files to xxx |
27 | nojoliet Ignore Joliet extensions if they are present. | 27 | nojoliet Ignore Joliet extensions if they are present. |
28 | norock Ignore Rock Ridge extensions if they are present. | 28 | norock Ignore Rock Ridge extensions if they are present. |
29 | hide Completely strip hidden files from the file system. | 29 | hide Completely strip hidden files from the file system. |
30 | showassoc Show files marked with the 'associated' bit | 30 | showassoc Show files marked with the 'associated' bit |
31 | unhide Deprecated; showing hidden files is now default; | 31 | unhide Deprecated; showing hidden files is now default; |
32 | If given, it is a synonym for 'showassoc' which will | 32 | If given, it is a synonym for 'showassoc' which will |
33 | recreate previous unhide behavior | 33 | recreate previous unhide behavior |
34 | session=x Select number of session on multisession CD | 34 | session=x Select number of session on multisession CD |
35 | sbsector=xxx Session begins from sector xxx | 35 | sbsector=xxx Session begins from sector xxx |
36 | 36 | ||
37 | Recommended documents about ISO 9660 standard are located at: | 37 | Recommended documents about ISO 9660 standard are located at: |
38 | http://www.y-adagio.com/public/standards/iso_cdromr/tocont.htm | 38 | http://www.y-adagio.com/public/standards/iso_cdromr/tocont.htm |
39 | ftp://ftp.ecma.ch/ecma-st/Ecma-119.pdf | 39 | ftp://ftp.ecma.ch/ecma-st/Ecma-119.pdf |
40 | Quoting from the PDF "This 2nd Edition of Standard ECMA-119 is technically | 40 | Quoting from the PDF "This 2nd Edition of Standard ECMA-119 is technically |
41 | identical with ISO 9660.", so it is a valid and gratis substitute of the | 41 | identical with ISO 9660.", so it is a valid and gratis substitute of the |
42 | official ISO specification. | 42 | official ISO specification. |
43 | 43 |
Documentation/filesystems/jfs.txt
1 | IBM's Journaled File System (JFS) for Linux | 1 | IBM's Journaled File System (JFS) for Linux |
2 | 2 | ||
3 | JFS Homepage: http://jfs.sourceforge.net/ | 3 | JFS Homepage: http://jfs.sourceforge.net/ |
4 | 4 | ||
5 | The following mount options are supported: | 5 | The following mount options are supported: |
6 | 6 | ||
7 | iocharset=name Character set to use for converting from Unicode to | 7 | iocharset=name Character set to use for converting from Unicode to |
8 | ASCII. The default is to do no conversion. Use | 8 | ASCII. The default is to do no conversion. Use |
9 | iocharset=utf8 for UTF8 translations. This requires | 9 | iocharset=utf8 for UTF-8 translations. This requires |
10 | CONFIG_NLS_UTF8 to be set in the kernel .config file. | 10 | CONFIG_NLS_UTF8 to be set in the kernel .config file. |
11 | iocharset=none specifies the default behavior explicitly. | 11 | iocharset=none specifies the default behavior explicitly. |
12 | 12 | ||
13 | resize=value Resize the volume to <value> blocks. JFS only supports | 13 | resize=value Resize the volume to <value> blocks. JFS only supports |
14 | growing a volume, not shrinking it. This option is only | 14 | growing a volume, not shrinking it. This option is only |
15 | valid during a remount, when the volume is mounted | 15 | valid during a remount, when the volume is mounted |
16 | read-write. The resize keyword with no value will grow | 16 | read-write. The resize keyword with no value will grow |
17 | the volume to the full size of the partition. | 17 | the volume to the full size of the partition. |
18 | 18 | ||
19 | nointegrity Do not write to the journal. The primary use of this option | 19 | nointegrity Do not write to the journal. The primary use of this option |
20 | is to allow for higher performance when restoring a volume | 20 | is to allow for higher performance when restoring a volume |
21 | from backup media. The integrity of the volume is not | 21 | from backup media. The integrity of the volume is not |
22 | guaranteed if the system abnormally abends. | 22 | guaranteed if the system abnormally abends. |
23 | 23 | ||
24 | integrity Default. Commit metadata changes to the journal. Use this | 24 | integrity Default. Commit metadata changes to the journal. Use this |
25 | option to remount a volume where the nointegrity option was | 25 | option to remount a volume where the nointegrity option was |
26 | previously specified in order to restore normal behavior. | 26 | previously specified in order to restore normal behavior. |
27 | 27 | ||
28 | errors=continue Keep going on a filesystem error. | 28 | errors=continue Keep going on a filesystem error. |
29 | errors=remount-ro Default. Remount the filesystem read-only on an error. | 29 | errors=remount-ro Default. Remount the filesystem read-only on an error. |
30 | errors=panic Panic and halt the machine if an error occurs. | 30 | errors=panic Panic and halt the machine if an error occurs. |
31 | 31 | ||
32 | Please send bugs, comments, cards and letters to shaggy@austin.ibm.com. | 32 | Please send bugs, comments, cards and letters to shaggy@austin.ibm.com. |
33 | 33 | ||
34 | The JFS mailing list can be subscribed to by using the link labeled | 34 | The JFS mailing list can be subscribed to by using the link labeled |
35 | "Mail list Subscribe" at our web page http://jfs.sourceforge.net/ | 35 | "Mail list Subscribe" at our web page http://jfs.sourceforge.net/ |
36 | 36 |
Documentation/filesystems/vfat.txt
1 | USING VFAT | 1 | USING VFAT |
2 | ---------------------------------------------------------------------- | 2 | ---------------------------------------------------------------------- |
3 | To use the vfat filesystem, use the filesystem type 'vfat'. i.e. | 3 | To use the vfat filesystem, use the filesystem type 'vfat'. i.e. |
4 | mount -t vfat /dev/fd0 /mnt | 4 | mount -t vfat /dev/fd0 /mnt |
5 | 5 | ||
6 | No special partition formatter is required. mkdosfs will work fine | 6 | No special partition formatter is required. mkdosfs will work fine |
7 | if you want to format from within Linux. | 7 | if you want to format from within Linux. |
8 | 8 | ||
9 | VFAT MOUNT OPTIONS | 9 | VFAT MOUNT OPTIONS |
10 | ---------------------------------------------------------------------- | 10 | ---------------------------------------------------------------------- |
11 | umask=### -- The permission mask (for files and directories, see umask(1)). | 11 | umask=### -- The permission mask (for files and directories, see umask(1)). |
12 | The default is the umask of current process. | 12 | The default is the umask of current process. |
13 | 13 | ||
14 | dmask=### -- The permission mask for the directory. | 14 | dmask=### -- The permission mask for the directory. |
15 | The default is the umask of current process. | 15 | The default is the umask of current process. |
16 | 16 | ||
17 | fmask=### -- The permission mask for files. | 17 | fmask=### -- The permission mask for files. |
18 | The default is the umask of current process. | 18 | The default is the umask of current process. |
19 | 19 | ||
20 | codepage=### -- Sets the codepage number for converting to shortname | 20 | codepage=### -- Sets the codepage number for converting to shortname |
21 | characters on FAT filesystem. | 21 | characters on FAT filesystem. |
22 | By default, FAT_DEFAULT_CODEPAGE setting is used. | 22 | By default, FAT_DEFAULT_CODEPAGE setting is used. |
23 | 23 | ||
24 | iocharset=name -- Character set to use for converting between the | 24 | iocharset=name -- Character set to use for converting between the |
25 | encoding is used for user visible filename and 16 bit | 25 | encoding is used for user visible filename and 16 bit |
26 | Unicode characters. Long filenames are stored on disk | 26 | Unicode characters. Long filenames are stored on disk |
27 | in Unicode format, but Unix for the most part doesn't | 27 | in Unicode format, but Unix for the most part doesn't |
28 | know how to deal with Unicode. | 28 | know how to deal with Unicode. |
29 | By default, FAT_DEFAULT_IOCHARSET setting is used. | 29 | By default, FAT_DEFAULT_IOCHARSET setting is used. |
30 | 30 | ||
31 | There is also an option of doing UTF8 translations | 31 | There is also an option of doing UTF-8 translations |
32 | with the utf8 option. | 32 | with the utf8 option. |
33 | 33 | ||
34 | NOTE: "iocharset=utf8" is not recommended. If unsure, | 34 | NOTE: "iocharset=utf8" is not recommended. If unsure, |
35 | you should consider the following option instead. | 35 | you should consider the following option instead. |
36 | 36 | ||
37 | utf8=<bool> -- UTF8 is the filesystem safe version of Unicode that | 37 | utf8=<bool> -- UTF-8 is the filesystem safe version of Unicode that |
38 | is used by the console. It can be be enabled for the | 38 | is used by the console. It can be be enabled for the |
39 | filesystem with this option. If 'uni_xlate' gets set, | 39 | filesystem with this option. If 'uni_xlate' gets set, |
40 | UTF8 gets disabled. | 40 | UTF-8 gets disabled. |
41 | 41 | ||
42 | uni_xlate=<bool> -- Translate unhandled Unicode characters to special | 42 | uni_xlate=<bool> -- Translate unhandled Unicode characters to special |
43 | escaped sequences. This would let you backup and | 43 | escaped sequences. This would let you backup and |
44 | restore filenames that are created with any Unicode | 44 | restore filenames that are created with any Unicode |
45 | characters. Until Linux supports Unicode for real, | 45 | characters. Until Linux supports Unicode for real, |
46 | this gives you an alternative. Without this option, | 46 | this gives you an alternative. Without this option, |
47 | a '?' is used when no translation is possible. The | 47 | a '?' is used when no translation is possible. The |
48 | escape character is ':' because it is otherwise | 48 | escape character is ':' because it is otherwise |
49 | illegal on the vfat filesystem. The escape sequence | 49 | illegal on the vfat filesystem. The escape sequence |
50 | that gets used is ':' and the four digits of hexadecimal | 50 | that gets used is ':' and the four digits of hexadecimal |
51 | unicode. | 51 | unicode. |
52 | 52 | ||
53 | nonumtail=<bool> -- When creating 8.3 aliases, normally the alias will | 53 | nonumtail=<bool> -- When creating 8.3 aliases, normally the alias will |
54 | end in '~1' or tilde followed by some number. If this | 54 | end in '~1' or tilde followed by some number. If this |
55 | option is set, then if the filename is | 55 | option is set, then if the filename is |
56 | "longfilename.txt" and "longfile.txt" does not | 56 | "longfilename.txt" and "longfile.txt" does not |
57 | currently exist in the directory, 'longfile.txt' will | 57 | currently exist in the directory, 'longfile.txt' will |
58 | be the short alias instead of 'longfi~1.txt'. | 58 | be the short alias instead of 'longfi~1.txt'. |
59 | 59 | ||
60 | quiet -- Stops printing certain warning messages. | 60 | quiet -- Stops printing certain warning messages. |
61 | 61 | ||
62 | check=s|r|n -- Case sensitivity checking setting. | 62 | check=s|r|n -- Case sensitivity checking setting. |
63 | s: strict, case sensitive | 63 | s: strict, case sensitive |
64 | r: relaxed, case insensitive | 64 | r: relaxed, case insensitive |
65 | n: normal, default setting, currently case insensitive | 65 | n: normal, default setting, currently case insensitive |
66 | 66 | ||
67 | shortname=lower|win95|winnt|mixed | 67 | shortname=lower|win95|winnt|mixed |
68 | -- Shortname display/create setting. | 68 | -- Shortname display/create setting. |
69 | lower: convert to lowercase for display, | 69 | lower: convert to lowercase for display, |
70 | emulate the Windows 95 rule for create. | 70 | emulate the Windows 95 rule for create. |
71 | win95: emulate the Windows 95 rule for display/create. | 71 | win95: emulate the Windows 95 rule for display/create. |
72 | winnt: emulate the Windows NT rule for display/create. | 72 | winnt: emulate the Windows NT rule for display/create. |
73 | mixed: emulate the Windows NT rule for display, | 73 | mixed: emulate the Windows NT rule for display, |
74 | emulate the Windows 95 rule for create. | 74 | emulate the Windows 95 rule for create. |
75 | Default setting is `lower'. | 75 | Default setting is `lower'. |
76 | 76 | ||
77 | <bool>: 0,1,yes,no,true,false | 77 | <bool>: 0,1,yes,no,true,false |
78 | 78 | ||
79 | TODO | 79 | TODO |
80 | ---------------------------------------------------------------------- | 80 | ---------------------------------------------------------------------- |
81 | * Need to get rid of the raw scanning stuff. Instead, always use | 81 | * Need to get rid of the raw scanning stuff. Instead, always use |
82 | a get next directory entry approach. The only thing left that uses | 82 | a get next directory entry approach. The only thing left that uses |
83 | raw scanning is the directory renaming code. | 83 | raw scanning is the directory renaming code. |
84 | 84 | ||
85 | 85 | ||
86 | POSSIBLE PROBLEMS | 86 | POSSIBLE PROBLEMS |
87 | ---------------------------------------------------------------------- | 87 | ---------------------------------------------------------------------- |
88 | * vfat_valid_longname does not properly checked reserved names. | 88 | * vfat_valid_longname does not properly checked reserved names. |
89 | * When a volume name is the same as a directory name in the root | 89 | * When a volume name is the same as a directory name in the root |
90 | directory of the filesystem, the directory name sometimes shows | 90 | directory of the filesystem, the directory name sometimes shows |
91 | up as an empty file. | 91 | up as an empty file. |
92 | * autoconv option does not work correctly. | 92 | * autoconv option does not work correctly. |
93 | 93 | ||
94 | BUG REPORTS | 94 | BUG REPORTS |
95 | ---------------------------------------------------------------------- | 95 | ---------------------------------------------------------------------- |
96 | If you have trouble with the VFAT filesystem, mail bug reports to | 96 | If you have trouble with the VFAT filesystem, mail bug reports to |
97 | chaffee@bmrc.cs.berkeley.edu. Please specify the filename | 97 | chaffee@bmrc.cs.berkeley.edu. Please specify the filename |
98 | and the operation that gave you trouble. | 98 | and the operation that gave you trouble. |
99 | 99 | ||
100 | TEST SUITE | 100 | TEST SUITE |
101 | ---------------------------------------------------------------------- | 101 | ---------------------------------------------------------------------- |
102 | If you plan to make any modifications to the vfat filesystem, please | 102 | If you plan to make any modifications to the vfat filesystem, please |
103 | get the test suite that comes with the vfat distribution at | 103 | get the test suite that comes with the vfat distribution at |
104 | 104 | ||
105 | http://bmrc.berkeley.edu/people/chaffee/vfat.html | 105 | http://bmrc.berkeley.edu/people/chaffee/vfat.html |
106 | 106 | ||
107 | This tests quite a few parts of the vfat filesystem and additional | 107 | This tests quite a few parts of the vfat filesystem and additional |
108 | tests for new features or untested features would be appreciated. | 108 | tests for new features or untested features would be appreciated. |
109 | 109 | ||
110 | NOTES ON THE STRUCTURE OF THE VFAT FILESYSTEM | 110 | NOTES ON THE STRUCTURE OF THE VFAT FILESYSTEM |
111 | ---------------------------------------------------------------------- | 111 | ---------------------------------------------------------------------- |
112 | (This documentation was provided by Galen C. Hunt <gchunt@cs.rochester.edu> | 112 | (This documentation was provided by Galen C. Hunt <gchunt@cs.rochester.edu> |
113 | and lightly annotated by Gordon Chaffee). | 113 | and lightly annotated by Gordon Chaffee). |
114 | 114 | ||
115 | This document presents a very rough, technical overview of my | 115 | This document presents a very rough, technical overview of my |
116 | knowledge of the extended FAT file system used in Windows NT 3.5 and | 116 | knowledge of the extended FAT file system used in Windows NT 3.5 and |
117 | Windows 95. I don't guarantee that any of the following is correct, | 117 | Windows 95. I don't guarantee that any of the following is correct, |
118 | but it appears to be so. | 118 | but it appears to be so. |
119 | 119 | ||
120 | The extended FAT file system is almost identical to the FAT | 120 | The extended FAT file system is almost identical to the FAT |
121 | file system used in DOS versions up to and including 6.223410239847 | 121 | file system used in DOS versions up to and including 6.223410239847 |
122 | :-). The significant change has been the addition of long file names. | 122 | :-). The significant change has been the addition of long file names. |
123 | These names support up to 255 characters including spaces and lower | 123 | These names support up to 255 characters including spaces and lower |
124 | case characters as opposed to the traditional 8.3 short names. | 124 | case characters as opposed to the traditional 8.3 short names. |
125 | 125 | ||
126 | Here is the description of the traditional FAT entry in the current | 126 | Here is the description of the traditional FAT entry in the current |
127 | Windows 95 filesystem: | 127 | Windows 95 filesystem: |
128 | 128 | ||
129 | struct directory { // Short 8.3 names | 129 | struct directory { // Short 8.3 names |
130 | unsigned char name[8]; // file name | 130 | unsigned char name[8]; // file name |
131 | unsigned char ext[3]; // file extension | 131 | unsigned char ext[3]; // file extension |
132 | unsigned char attr; // attribute byte | 132 | unsigned char attr; // attribute byte |
133 | unsigned char lcase; // Case for base and extension | 133 | unsigned char lcase; // Case for base and extension |
134 | unsigned char ctime_ms; // Creation time, milliseconds | 134 | unsigned char ctime_ms; // Creation time, milliseconds |
135 | unsigned char ctime[2]; // Creation time | 135 | unsigned char ctime[2]; // Creation time |
136 | unsigned char cdate[2]; // Creation date | 136 | unsigned char cdate[2]; // Creation date |
137 | unsigned char adate[2]; // Last access date | 137 | unsigned char adate[2]; // Last access date |
138 | unsigned char reserved[2]; // reserved values (ignored) | 138 | unsigned char reserved[2]; // reserved values (ignored) |
139 | unsigned char time[2]; // time stamp | 139 | unsigned char time[2]; // time stamp |
140 | unsigned char date[2]; // date stamp | 140 | unsigned char date[2]; // date stamp |
141 | unsigned char start[2]; // starting cluster number | 141 | unsigned char start[2]; // starting cluster number |
142 | unsigned char size[4]; // size of the file | 142 | unsigned char size[4]; // size of the file |
143 | }; | 143 | }; |
144 | 144 | ||
145 | The lcase field specifies if the base and/or the extension of an 8.3 | 145 | The lcase field specifies if the base and/or the extension of an 8.3 |
146 | name should be capitalized. This field does not seem to be used by | 146 | name should be capitalized. This field does not seem to be used by |
147 | Windows 95 but it is used by Windows NT. The case of filenames is not | 147 | Windows 95 but it is used by Windows NT. The case of filenames is not |
148 | completely compatible from Windows NT to Windows 95. It is not completely | 148 | completely compatible from Windows NT to Windows 95. It is not completely |
149 | compatible in the reverse direction, however. Filenames that fit in | 149 | compatible in the reverse direction, however. Filenames that fit in |
150 | the 8.3 namespace and are written on Windows NT to be lowercase will | 150 | the 8.3 namespace and are written on Windows NT to be lowercase will |
151 | show up as uppercase on Windows 95. | 151 | show up as uppercase on Windows 95. |
152 | 152 | ||
153 | Note that the "start" and "size" values are actually little | 153 | Note that the "start" and "size" values are actually little |
154 | endian integer values. The descriptions of the fields in this | 154 | endian integer values. The descriptions of the fields in this |
155 | structure are public knowledge and can be found elsewhere. | 155 | structure are public knowledge and can be found elsewhere. |
156 | 156 | ||
157 | With the extended FAT system, Microsoft has inserted extra | 157 | With the extended FAT system, Microsoft has inserted extra |
158 | directory entries for any files with extended names. (Any name which | 158 | directory entries for any files with extended names. (Any name which |
159 | legally fits within the old 8.3 encoding scheme does not have extra | 159 | legally fits within the old 8.3 encoding scheme does not have extra |
160 | entries.) I call these extra entries slots. Basically, a slot is a | 160 | entries.) I call these extra entries slots. Basically, a slot is a |
161 | specially formatted directory entry which holds up to 13 characters of | 161 | specially formatted directory entry which holds up to 13 characters of |
162 | a file's extended name. Think of slots as additional labeling for the | 162 | a file's extended name. Think of slots as additional labeling for the |
163 | directory entry of the file to which they correspond. Microsoft | 163 | directory entry of the file to which they correspond. Microsoft |
164 | prefers to refer to the 8.3 entry for a file as its alias and the | 164 | prefers to refer to the 8.3 entry for a file as its alias and the |
165 | extended slot directory entries as the file name. | 165 | extended slot directory entries as the file name. |
166 | 166 | ||
167 | The C structure for a slot directory entry follows: | 167 | The C structure for a slot directory entry follows: |
168 | 168 | ||
169 | struct slot { // Up to 13 characters of a long name | 169 | struct slot { // Up to 13 characters of a long name |
170 | unsigned char id; // sequence number for slot | 170 | unsigned char id; // sequence number for slot |
171 | unsigned char name0_4[10]; // first 5 characters in name | 171 | unsigned char name0_4[10]; // first 5 characters in name |
172 | unsigned char attr; // attribute byte | 172 | unsigned char attr; // attribute byte |
173 | unsigned char reserved; // always 0 | 173 | unsigned char reserved; // always 0 |
174 | unsigned char alias_checksum; // checksum for 8.3 alias | 174 | unsigned char alias_checksum; // checksum for 8.3 alias |
175 | unsigned char name5_10[12]; // 6 more characters in name | 175 | unsigned char name5_10[12]; // 6 more characters in name |
176 | unsigned char start[2]; // starting cluster number | 176 | unsigned char start[2]; // starting cluster number |
177 | unsigned char name11_12[4]; // last 2 characters in name | 177 | unsigned char name11_12[4]; // last 2 characters in name |
178 | }; | 178 | }; |
179 | 179 | ||
180 | If the layout of the slots looks a little odd, it's only | 180 | If the layout of the slots looks a little odd, it's only |
181 | because of Microsoft's efforts to maintain compatibility with old | 181 | because of Microsoft's efforts to maintain compatibility with old |
182 | software. The slots must be disguised to prevent old software from | 182 | software. The slots must be disguised to prevent old software from |
183 | panicking. To this end, a number of measures are taken: | 183 | panicking. To this end, a number of measures are taken: |
184 | 184 | ||
185 | 1) The attribute byte for a slot directory entry is always set | 185 | 1) The attribute byte for a slot directory entry is always set |
186 | to 0x0f. This corresponds to an old directory entry with | 186 | to 0x0f. This corresponds to an old directory entry with |
187 | attributes of "hidden", "system", "read-only", and "volume | 187 | attributes of "hidden", "system", "read-only", and "volume |
188 | label". Most old software will ignore any directory | 188 | label". Most old software will ignore any directory |
189 | entries with the "volume label" bit set. Real volume label | 189 | entries with the "volume label" bit set. Real volume label |
190 | entries don't have the other three bits set. | 190 | entries don't have the other three bits set. |
191 | 191 | ||
192 | 2) The starting cluster is always set to 0, an impossible | 192 | 2) The starting cluster is always set to 0, an impossible |
193 | value for a DOS file. | 193 | value for a DOS file. |
194 | 194 | ||
195 | Because the extended FAT system is backward compatible, it is | 195 | Because the extended FAT system is backward compatible, it is |
196 | possible for old software to modify directory entries. Measures must | 196 | possible for old software to modify directory entries. Measures must |
197 | be taken to ensure the validity of slots. An extended FAT system can | 197 | be taken to ensure the validity of slots. An extended FAT system can |
198 | verify that a slot does in fact belong to an 8.3 directory entry by | 198 | verify that a slot does in fact belong to an 8.3 directory entry by |
199 | the following: | 199 | the following: |
200 | 200 | ||
201 | 1) Positioning. Slots for a file always immediately proceed | 201 | 1) Positioning. Slots for a file always immediately proceed |
202 | their corresponding 8.3 directory entry. In addition, each | 202 | their corresponding 8.3 directory entry. In addition, each |
203 | slot has an id which marks its order in the extended file | 203 | slot has an id which marks its order in the extended file |
204 | name. Here is a very abbreviated view of an 8.3 directory | 204 | name. Here is a very abbreviated view of an 8.3 directory |
205 | entry and its corresponding long name slots for the file | 205 | entry and its corresponding long name slots for the file |
206 | "My Big File.Extension which is long": | 206 | "My Big File.Extension which is long": |
207 | 207 | ||
208 | <proceeding files...> | 208 | <proceeding files...> |
209 | <slot #3, id = 0x43, characters = "h is long"> | 209 | <slot #3, id = 0x43, characters = "h is long"> |
210 | <slot #2, id = 0x02, characters = "xtension whic"> | 210 | <slot #2, id = 0x02, characters = "xtension whic"> |
211 | <slot #1, id = 0x01, characters = "My Big File.E"> | 211 | <slot #1, id = 0x01, characters = "My Big File.E"> |
212 | <directory entry, name = "MYBIGFIL.EXT"> | 212 | <directory entry, name = "MYBIGFIL.EXT"> |
213 | 213 | ||
214 | Note that the slots are stored from last to first. Slots | 214 | Note that the slots are stored from last to first. Slots |
215 | are numbered from 1 to N. The Nth slot is or'ed with 0x40 | 215 | are numbered from 1 to N. The Nth slot is or'ed with 0x40 |
216 | to mark it as the last one. | 216 | to mark it as the last one. |
217 | 217 | ||
218 | 2) Checksum. Each slot has an "alias_checksum" value. The | 218 | 2) Checksum. Each slot has an "alias_checksum" value. The |
219 | checksum is calculated from the 8.3 name using the | 219 | checksum is calculated from the 8.3 name using the |
220 | following algorithm: | 220 | following algorithm: |
221 | 221 | ||
222 | for (sum = i = 0; i < 11; i++) { | 222 | for (sum = i = 0; i < 11; i++) { |
223 | sum = (((sum&1)<<7)|((sum&0xfe)>>1)) + name[i] | 223 | sum = (((sum&1)<<7)|((sum&0xfe)>>1)) + name[i] |
224 | } | 224 | } |
225 | 225 | ||
226 | 3) If there is free space in the final slot, a Unicode NULL (0x0000) | 226 | 3) If there is free space in the final slot, a Unicode NULL (0x0000) |
227 | is stored after the final character. After that, all unused | 227 | is stored after the final character. After that, all unused |
228 | characters in the final slot are set to Unicode 0xFFFF. | 228 | characters in the final slot are set to Unicode 0xFFFF. |
229 | 229 | ||
230 | Finally, note that the extended name is stored in Unicode. Each Unicode | 230 | Finally, note that the extended name is stored in Unicode. Each Unicode |
231 | character takes two bytes. | 231 | character takes two bytes. |
232 | 232 |
fs/befs/linuxvfs.c
1 | /* | 1 | /* |
2 | * linux/fs/befs/linuxvfs.c | 2 | * linux/fs/befs/linuxvfs.c |
3 | * | 3 | * |
4 | * Copyright (C) 2001 Will Dyson <will_dyson@pobox.com | 4 | * Copyright (C) 2001 Will Dyson <will_dyson@pobox.com |
5 | * | 5 | * |
6 | */ | 6 | */ |
7 | 7 | ||
8 | #include <linux/module.h> | 8 | #include <linux/module.h> |
9 | #include <linux/slab.h> | 9 | #include <linux/slab.h> |
10 | #include <linux/fs.h> | 10 | #include <linux/fs.h> |
11 | #include <linux/errno.h> | 11 | #include <linux/errno.h> |
12 | #include <linux/stat.h> | 12 | #include <linux/stat.h> |
13 | #include <linux/nls.h> | 13 | #include <linux/nls.h> |
14 | #include <linux/buffer_head.h> | 14 | #include <linux/buffer_head.h> |
15 | #include <linux/vfs.h> | 15 | #include <linux/vfs.h> |
16 | #include <linux/parser.h> | 16 | #include <linux/parser.h> |
17 | #include <linux/namei.h> | 17 | #include <linux/namei.h> |
18 | 18 | ||
19 | #include "befs.h" | 19 | #include "befs.h" |
20 | #include "btree.h" | 20 | #include "btree.h" |
21 | #include "inode.h" | 21 | #include "inode.h" |
22 | #include "datastream.h" | 22 | #include "datastream.h" |
23 | #include "super.h" | 23 | #include "super.h" |
24 | #include "io.h" | 24 | #include "io.h" |
25 | #include "endian.h" | 25 | #include "endian.h" |
26 | 26 | ||
27 | MODULE_DESCRIPTION("BeOS File System (BeFS) driver"); | 27 | MODULE_DESCRIPTION("BeOS File System (BeFS) driver"); |
28 | MODULE_AUTHOR("Will Dyson"); | 28 | MODULE_AUTHOR("Will Dyson"); |
29 | MODULE_LICENSE("GPL"); | 29 | MODULE_LICENSE("GPL"); |
30 | 30 | ||
31 | /* The units the vfs expects inode->i_blocks to be in */ | 31 | /* The units the vfs expects inode->i_blocks to be in */ |
32 | #define VFS_BLOCK_SIZE 512 | 32 | #define VFS_BLOCK_SIZE 512 |
33 | 33 | ||
34 | static int befs_readdir(struct file *, void *, filldir_t); | 34 | static int befs_readdir(struct file *, void *, filldir_t); |
35 | static int befs_get_block(struct inode *, sector_t, struct buffer_head *, int); | 35 | static int befs_get_block(struct inode *, sector_t, struct buffer_head *, int); |
36 | static int befs_readpage(struct file *file, struct page *page); | 36 | static int befs_readpage(struct file *file, struct page *page); |
37 | static sector_t befs_bmap(struct address_space *mapping, sector_t block); | 37 | static sector_t befs_bmap(struct address_space *mapping, sector_t block); |
38 | static struct dentry *befs_lookup(struct inode *, struct dentry *, struct nameidata *); | 38 | static struct dentry *befs_lookup(struct inode *, struct dentry *, struct nameidata *); |
39 | static void befs_read_inode(struct inode *ino); | 39 | static void befs_read_inode(struct inode *ino); |
40 | static struct inode *befs_alloc_inode(struct super_block *sb); | 40 | static struct inode *befs_alloc_inode(struct super_block *sb); |
41 | static void befs_destroy_inode(struct inode *inode); | 41 | static void befs_destroy_inode(struct inode *inode); |
42 | static int befs_init_inodecache(void); | 42 | static int befs_init_inodecache(void); |
43 | static void befs_destroy_inodecache(void); | 43 | static void befs_destroy_inodecache(void); |
44 | static void *befs_follow_link(struct dentry *, struct nameidata *); | 44 | static void *befs_follow_link(struct dentry *, struct nameidata *); |
45 | static void befs_put_link(struct dentry *, struct nameidata *, void *); | 45 | static void befs_put_link(struct dentry *, struct nameidata *, void *); |
46 | static int befs_utf2nls(struct super_block *sb, const char *in, int in_len, | 46 | static int befs_utf2nls(struct super_block *sb, const char *in, int in_len, |
47 | char **out, int *out_len); | 47 | char **out, int *out_len); |
48 | static int befs_nls2utf(struct super_block *sb, const char *in, int in_len, | 48 | static int befs_nls2utf(struct super_block *sb, const char *in, int in_len, |
49 | char **out, int *out_len); | 49 | char **out, int *out_len); |
50 | static void befs_put_super(struct super_block *); | 50 | static void befs_put_super(struct super_block *); |
51 | static int befs_remount(struct super_block *, int *, char *); | 51 | static int befs_remount(struct super_block *, int *, char *); |
52 | static int befs_statfs(struct super_block *, struct kstatfs *); | 52 | static int befs_statfs(struct super_block *, struct kstatfs *); |
53 | static int parse_options(char *, befs_mount_options *); | 53 | static int parse_options(char *, befs_mount_options *); |
54 | 54 | ||
55 | static const struct super_operations befs_sops = { | 55 | static const struct super_operations befs_sops = { |
56 | .read_inode = befs_read_inode, /* initialize & read inode */ | 56 | .read_inode = befs_read_inode, /* initialize & read inode */ |
57 | .alloc_inode = befs_alloc_inode, /* allocate a new inode */ | 57 | .alloc_inode = befs_alloc_inode, /* allocate a new inode */ |
58 | .destroy_inode = befs_destroy_inode, /* deallocate an inode */ | 58 | .destroy_inode = befs_destroy_inode, /* deallocate an inode */ |
59 | .put_super = befs_put_super, /* uninit super */ | 59 | .put_super = befs_put_super, /* uninit super */ |
60 | .statfs = befs_statfs, /* statfs */ | 60 | .statfs = befs_statfs, /* statfs */ |
61 | .remount_fs = befs_remount, | 61 | .remount_fs = befs_remount, |
62 | }; | 62 | }; |
63 | 63 | ||
64 | /* slab cache for befs_inode_info objects */ | 64 | /* slab cache for befs_inode_info objects */ |
65 | static kmem_cache_t *befs_inode_cachep; | 65 | static kmem_cache_t *befs_inode_cachep; |
66 | 66 | ||
67 | static struct file_operations befs_dir_operations = { | 67 | static struct file_operations befs_dir_operations = { |
68 | .read = generic_read_dir, | 68 | .read = generic_read_dir, |
69 | .readdir = befs_readdir, | 69 | .readdir = befs_readdir, |
70 | }; | 70 | }; |
71 | 71 | ||
72 | static struct inode_operations befs_dir_inode_operations = { | 72 | static struct inode_operations befs_dir_inode_operations = { |
73 | .lookup = befs_lookup, | 73 | .lookup = befs_lookup, |
74 | }; | 74 | }; |
75 | 75 | ||
76 | static struct address_space_operations befs_aops = { | 76 | static struct address_space_operations befs_aops = { |
77 | .readpage = befs_readpage, | 77 | .readpage = befs_readpage, |
78 | .sync_page = block_sync_page, | 78 | .sync_page = block_sync_page, |
79 | .bmap = befs_bmap, | 79 | .bmap = befs_bmap, |
80 | }; | 80 | }; |
81 | 81 | ||
82 | static struct inode_operations befs_symlink_inode_operations = { | 82 | static struct inode_operations befs_symlink_inode_operations = { |
83 | .readlink = generic_readlink, | 83 | .readlink = generic_readlink, |
84 | .follow_link = befs_follow_link, | 84 | .follow_link = befs_follow_link, |
85 | .put_link = befs_put_link, | 85 | .put_link = befs_put_link, |
86 | }; | 86 | }; |
87 | 87 | ||
88 | /* | 88 | /* |
89 | * Called by generic_file_read() to read a page of data | 89 | * Called by generic_file_read() to read a page of data |
90 | * | 90 | * |
91 | * In turn, simply calls a generic block read function and | 91 | * In turn, simply calls a generic block read function and |
92 | * passes it the address of befs_get_block, for mapping file | 92 | * passes it the address of befs_get_block, for mapping file |
93 | * positions to disk blocks. | 93 | * positions to disk blocks. |
94 | */ | 94 | */ |
95 | static int | 95 | static int |
96 | befs_readpage(struct file *file, struct page *page) | 96 | befs_readpage(struct file *file, struct page *page) |
97 | { | 97 | { |
98 | return block_read_full_page(page, befs_get_block); | 98 | return block_read_full_page(page, befs_get_block); |
99 | } | 99 | } |
100 | 100 | ||
101 | static sector_t | 101 | static sector_t |
102 | befs_bmap(struct address_space *mapping, sector_t block) | 102 | befs_bmap(struct address_space *mapping, sector_t block) |
103 | { | 103 | { |
104 | return generic_block_bmap(mapping, block, befs_get_block); | 104 | return generic_block_bmap(mapping, block, befs_get_block); |
105 | } | 105 | } |
106 | 106 | ||
107 | /* | 107 | /* |
108 | * Generic function to map a file position (block) to a | 108 | * Generic function to map a file position (block) to a |
109 | * disk offset (passed back in bh_result). | 109 | * disk offset (passed back in bh_result). |
110 | * | 110 | * |
111 | * Used by many higher level functions. | 111 | * Used by many higher level functions. |
112 | * | 112 | * |
113 | * Calls befs_fblock2brun() in datastream.c to do the real work. | 113 | * Calls befs_fblock2brun() in datastream.c to do the real work. |
114 | * | 114 | * |
115 | * -WD 10-26-01 | 115 | * -WD 10-26-01 |
116 | */ | 116 | */ |
117 | 117 | ||
118 | static int | 118 | static int |
119 | befs_get_block(struct inode *inode, sector_t block, | 119 | befs_get_block(struct inode *inode, sector_t block, |
120 | struct buffer_head *bh_result, int create) | 120 | struct buffer_head *bh_result, int create) |
121 | { | 121 | { |
122 | struct super_block *sb = inode->i_sb; | 122 | struct super_block *sb = inode->i_sb; |
123 | befs_data_stream *ds = &BEFS_I(inode)->i_data.ds; | 123 | befs_data_stream *ds = &BEFS_I(inode)->i_data.ds; |
124 | befs_block_run run = BAD_IADDR; | 124 | befs_block_run run = BAD_IADDR; |
125 | int res = 0; | 125 | int res = 0; |
126 | ulong disk_off; | 126 | ulong disk_off; |
127 | 127 | ||
128 | befs_debug(sb, "---> befs_get_block() for inode %lu, block %ld", | 128 | befs_debug(sb, "---> befs_get_block() for inode %lu, block %ld", |
129 | inode->i_ino, block); | 129 | inode->i_ino, block); |
130 | 130 | ||
131 | if (block < 0) { | 131 | if (block < 0) { |
132 | befs_error(sb, "befs_get_block() was asked for a block " | 132 | befs_error(sb, "befs_get_block() was asked for a block " |
133 | "number less than zero: block %ld in inode %lu", | 133 | "number less than zero: block %ld in inode %lu", |
134 | block, inode->i_ino); | 134 | block, inode->i_ino); |
135 | return -EIO; | 135 | return -EIO; |
136 | } | 136 | } |
137 | 137 | ||
138 | if (create) { | 138 | if (create) { |
139 | befs_error(sb, "befs_get_block() was asked to write to " | 139 | befs_error(sb, "befs_get_block() was asked to write to " |
140 | "block %ld in inode %lu", block, inode->i_ino); | 140 | "block %ld in inode %lu", block, inode->i_ino); |
141 | return -EPERM; | 141 | return -EPERM; |
142 | } | 142 | } |
143 | 143 | ||
144 | res = befs_fblock2brun(sb, ds, block, &run); | 144 | res = befs_fblock2brun(sb, ds, block, &run); |
145 | if (res != BEFS_OK) { | 145 | if (res != BEFS_OK) { |
146 | befs_error(sb, | 146 | befs_error(sb, |
147 | "<--- befs_get_block() for inode %lu, block " | 147 | "<--- befs_get_block() for inode %lu, block " |
148 | "%ld ERROR", inode->i_ino, block); | 148 | "%ld ERROR", inode->i_ino, block); |
149 | return -EFBIG; | 149 | return -EFBIG; |
150 | } | 150 | } |
151 | 151 | ||
152 | disk_off = (ulong) iaddr2blockno(sb, &run); | 152 | disk_off = (ulong) iaddr2blockno(sb, &run); |
153 | 153 | ||
154 | map_bh(bh_result, inode->i_sb, disk_off); | 154 | map_bh(bh_result, inode->i_sb, disk_off); |
155 | 155 | ||
156 | befs_debug(sb, "<--- befs_get_block() for inode %lu, block %ld, " | 156 | befs_debug(sb, "<--- befs_get_block() for inode %lu, block %ld, " |
157 | "disk address %lu", inode->i_ino, block, disk_off); | 157 | "disk address %lu", inode->i_ino, block, disk_off); |
158 | 158 | ||
159 | return 0; | 159 | return 0; |
160 | } | 160 | } |
161 | 161 | ||
162 | static struct dentry * | 162 | static struct dentry * |
163 | befs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd) | 163 | befs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd) |
164 | { | 164 | { |
165 | struct inode *inode = NULL; | 165 | struct inode *inode = NULL; |
166 | struct super_block *sb = dir->i_sb; | 166 | struct super_block *sb = dir->i_sb; |
167 | befs_data_stream *ds = &BEFS_I(dir)->i_data.ds; | 167 | befs_data_stream *ds = &BEFS_I(dir)->i_data.ds; |
168 | befs_off_t offset; | 168 | befs_off_t offset; |
169 | int ret; | 169 | int ret; |
170 | int utfnamelen; | 170 | int utfnamelen; |
171 | char *utfname; | 171 | char *utfname; |
172 | const char *name = dentry->d_name.name; | 172 | const char *name = dentry->d_name.name; |
173 | 173 | ||
174 | befs_debug(sb, "---> befs_lookup() " | 174 | befs_debug(sb, "---> befs_lookup() " |
175 | "name %s inode %ld", dentry->d_name.name, dir->i_ino); | 175 | "name %s inode %ld", dentry->d_name.name, dir->i_ino); |
176 | 176 | ||
177 | /* Convert to UTF-8 */ | 177 | /* Convert to UTF-8 */ |
178 | if (BEFS_SB(sb)->nls) { | 178 | if (BEFS_SB(sb)->nls) { |
179 | ret = | 179 | ret = |
180 | befs_nls2utf(sb, name, strlen(name), &utfname, &utfnamelen); | 180 | befs_nls2utf(sb, name, strlen(name), &utfname, &utfnamelen); |
181 | if (ret < 0) { | 181 | if (ret < 0) { |
182 | befs_debug(sb, "<--- befs_lookup() ERROR"); | 182 | befs_debug(sb, "<--- befs_lookup() ERROR"); |
183 | return ERR_PTR(ret); | 183 | return ERR_PTR(ret); |
184 | } | 184 | } |
185 | ret = befs_btree_find(sb, ds, utfname, &offset); | 185 | ret = befs_btree_find(sb, ds, utfname, &offset); |
186 | kfree(utfname); | 186 | kfree(utfname); |
187 | 187 | ||
188 | } else { | 188 | } else { |
189 | ret = befs_btree_find(sb, ds, dentry->d_name.name, &offset); | 189 | ret = befs_btree_find(sb, ds, dentry->d_name.name, &offset); |
190 | } | 190 | } |
191 | 191 | ||
192 | if (ret == BEFS_BT_NOT_FOUND) { | 192 | if (ret == BEFS_BT_NOT_FOUND) { |
193 | befs_debug(sb, "<--- befs_lookup() %s not found", | 193 | befs_debug(sb, "<--- befs_lookup() %s not found", |
194 | dentry->d_name.name); | 194 | dentry->d_name.name); |
195 | return ERR_PTR(-ENOENT); | 195 | return ERR_PTR(-ENOENT); |
196 | 196 | ||
197 | } else if (ret != BEFS_OK || offset == 0) { | 197 | } else if (ret != BEFS_OK || offset == 0) { |
198 | befs_warning(sb, "<--- befs_lookup() Error"); | 198 | befs_warning(sb, "<--- befs_lookup() Error"); |
199 | return ERR_PTR(-ENODATA); | 199 | return ERR_PTR(-ENODATA); |
200 | } | 200 | } |
201 | 201 | ||
202 | inode = iget(dir->i_sb, (ino_t) offset); | 202 | inode = iget(dir->i_sb, (ino_t) offset); |
203 | if (!inode) | 203 | if (!inode) |
204 | return ERR_PTR(-EACCES); | 204 | return ERR_PTR(-EACCES); |
205 | 205 | ||
206 | d_add(dentry, inode); | 206 | d_add(dentry, inode); |
207 | 207 | ||
208 | befs_debug(sb, "<--- befs_lookup()"); | 208 | befs_debug(sb, "<--- befs_lookup()"); |
209 | 209 | ||
210 | return NULL; | 210 | return NULL; |
211 | } | 211 | } |
212 | 212 | ||
213 | static int | 213 | static int |
214 | befs_readdir(struct file *filp, void *dirent, filldir_t filldir) | 214 | befs_readdir(struct file *filp, void *dirent, filldir_t filldir) |
215 | { | 215 | { |
216 | struct inode *inode = filp->f_dentry->d_inode; | 216 | struct inode *inode = filp->f_dentry->d_inode; |
217 | struct super_block *sb = inode->i_sb; | 217 | struct super_block *sb = inode->i_sb; |
218 | befs_data_stream *ds = &BEFS_I(inode)->i_data.ds; | 218 | befs_data_stream *ds = &BEFS_I(inode)->i_data.ds; |
219 | befs_off_t value; | 219 | befs_off_t value; |
220 | int result; | 220 | int result; |
221 | size_t keysize; | 221 | size_t keysize; |
222 | unsigned char d_type; | 222 | unsigned char d_type; |
223 | char keybuf[BEFS_NAME_LEN + 1]; | 223 | char keybuf[BEFS_NAME_LEN + 1]; |
224 | char *nlsname; | 224 | char *nlsname; |
225 | int nlsnamelen; | 225 | int nlsnamelen; |
226 | const char *dirname = filp->f_dentry->d_name.name; | 226 | const char *dirname = filp->f_dentry->d_name.name; |
227 | 227 | ||
228 | befs_debug(sb, "---> befs_readdir() " | 228 | befs_debug(sb, "---> befs_readdir() " |
229 | "name %s, inode %ld, filp->f_pos %Ld", | 229 | "name %s, inode %ld, filp->f_pos %Ld", |
230 | dirname, inode->i_ino, filp->f_pos); | 230 | dirname, inode->i_ino, filp->f_pos); |
231 | 231 | ||
232 | result = befs_btree_read(sb, ds, filp->f_pos, BEFS_NAME_LEN + 1, | 232 | result = befs_btree_read(sb, ds, filp->f_pos, BEFS_NAME_LEN + 1, |
233 | keybuf, &keysize, &value); | 233 | keybuf, &keysize, &value); |
234 | 234 | ||
235 | if (result == BEFS_ERR) { | 235 | if (result == BEFS_ERR) { |
236 | befs_debug(sb, "<--- befs_readdir() ERROR"); | 236 | befs_debug(sb, "<--- befs_readdir() ERROR"); |
237 | befs_error(sb, "IO error reading %s (inode %lu)", | 237 | befs_error(sb, "IO error reading %s (inode %lu)", |
238 | dirname, inode->i_ino); | 238 | dirname, inode->i_ino); |
239 | return -EIO; | 239 | return -EIO; |
240 | 240 | ||
241 | } else if (result == BEFS_BT_END) { | 241 | } else if (result == BEFS_BT_END) { |
242 | befs_debug(sb, "<--- befs_readdir() END"); | 242 | befs_debug(sb, "<--- befs_readdir() END"); |
243 | return 0; | 243 | return 0; |
244 | 244 | ||
245 | } else if (result == BEFS_BT_EMPTY) { | 245 | } else if (result == BEFS_BT_EMPTY) { |
246 | befs_debug(sb, "<--- befs_readdir() Empty directory"); | 246 | befs_debug(sb, "<--- befs_readdir() Empty directory"); |
247 | return 0; | 247 | return 0; |
248 | } | 248 | } |
249 | 249 | ||
250 | d_type = DT_UNKNOWN; | 250 | d_type = DT_UNKNOWN; |
251 | 251 | ||
252 | /* Convert to NLS */ | 252 | /* Convert to NLS */ |
253 | if (BEFS_SB(sb)->nls) { | 253 | if (BEFS_SB(sb)->nls) { |
254 | result = | 254 | result = |
255 | befs_utf2nls(sb, keybuf, keysize, &nlsname, &nlsnamelen); | 255 | befs_utf2nls(sb, keybuf, keysize, &nlsname, &nlsnamelen); |
256 | if (result < 0) { | 256 | if (result < 0) { |
257 | befs_debug(sb, "<--- befs_readdir() ERROR"); | 257 | befs_debug(sb, "<--- befs_readdir() ERROR"); |
258 | return result; | 258 | return result; |
259 | } | 259 | } |
260 | result = filldir(dirent, nlsname, nlsnamelen, filp->f_pos, | 260 | result = filldir(dirent, nlsname, nlsnamelen, filp->f_pos, |
261 | (ino_t) value, d_type); | 261 | (ino_t) value, d_type); |
262 | kfree(nlsname); | 262 | kfree(nlsname); |
263 | 263 | ||
264 | } else { | 264 | } else { |
265 | result = filldir(dirent, keybuf, keysize, filp->f_pos, | 265 | result = filldir(dirent, keybuf, keysize, filp->f_pos, |
266 | (ino_t) value, d_type); | 266 | (ino_t) value, d_type); |
267 | } | 267 | } |
268 | 268 | ||
269 | filp->f_pos++; | 269 | filp->f_pos++; |
270 | 270 | ||
271 | befs_debug(sb, "<--- befs_readdir() filp->f_pos %Ld", filp->f_pos); | 271 | befs_debug(sb, "<--- befs_readdir() filp->f_pos %Ld", filp->f_pos); |
272 | 272 | ||
273 | return 0; | 273 | return 0; |
274 | } | 274 | } |
275 | 275 | ||
276 | static struct inode * | 276 | static struct inode * |
277 | befs_alloc_inode(struct super_block *sb) | 277 | befs_alloc_inode(struct super_block *sb) |
278 | { | 278 | { |
279 | struct befs_inode_info *bi; | 279 | struct befs_inode_info *bi; |
280 | bi = (struct befs_inode_info *)kmem_cache_alloc(befs_inode_cachep, | 280 | bi = (struct befs_inode_info *)kmem_cache_alloc(befs_inode_cachep, |
281 | SLAB_KERNEL); | 281 | SLAB_KERNEL); |
282 | if (!bi) | 282 | if (!bi) |
283 | return NULL; | 283 | return NULL; |
284 | return &bi->vfs_inode; | 284 | return &bi->vfs_inode; |
285 | } | 285 | } |
286 | 286 | ||
287 | static void | 287 | static void |
288 | befs_destroy_inode(struct inode *inode) | 288 | befs_destroy_inode(struct inode *inode) |
289 | { | 289 | { |
290 | kmem_cache_free(befs_inode_cachep, BEFS_I(inode)); | 290 | kmem_cache_free(befs_inode_cachep, BEFS_I(inode)); |
291 | } | 291 | } |
292 | 292 | ||
293 | static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags) | 293 | static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags) |
294 | { | 294 | { |
295 | struct befs_inode_info *bi = (struct befs_inode_info *) foo; | 295 | struct befs_inode_info *bi = (struct befs_inode_info *) foo; |
296 | 296 | ||
297 | if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) == | 297 | if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) == |
298 | SLAB_CTOR_CONSTRUCTOR) { | 298 | SLAB_CTOR_CONSTRUCTOR) { |
299 | inode_init_once(&bi->vfs_inode); | 299 | inode_init_once(&bi->vfs_inode); |
300 | } | 300 | } |
301 | } | 301 | } |
302 | 302 | ||
303 | static void | 303 | static void |
304 | befs_read_inode(struct inode *inode) | 304 | befs_read_inode(struct inode *inode) |
305 | { | 305 | { |
306 | struct buffer_head *bh = NULL; | 306 | struct buffer_head *bh = NULL; |
307 | befs_inode *raw_inode = NULL; | 307 | befs_inode *raw_inode = NULL; |
308 | 308 | ||
309 | struct super_block *sb = inode->i_sb; | 309 | struct super_block *sb = inode->i_sb; |
310 | befs_sb_info *befs_sb = BEFS_SB(sb); | 310 | befs_sb_info *befs_sb = BEFS_SB(sb); |
311 | befs_inode_info *befs_ino = NULL; | 311 | befs_inode_info *befs_ino = NULL; |
312 | 312 | ||
313 | befs_debug(sb, "---> befs_read_inode() " "inode = %lu", inode->i_ino); | 313 | befs_debug(sb, "---> befs_read_inode() " "inode = %lu", inode->i_ino); |
314 | 314 | ||
315 | befs_ino = BEFS_I(inode); | 315 | befs_ino = BEFS_I(inode); |
316 | 316 | ||
317 | /* convert from vfs's inode number to befs's inode number */ | 317 | /* convert from vfs's inode number to befs's inode number */ |
318 | befs_ino->i_inode_num = blockno2iaddr(sb, inode->i_ino); | 318 | befs_ino->i_inode_num = blockno2iaddr(sb, inode->i_ino); |
319 | 319 | ||
320 | befs_debug(sb, " real inode number [%u, %hu, %hu]", | 320 | befs_debug(sb, " real inode number [%u, %hu, %hu]", |
321 | befs_ino->i_inode_num.allocation_group, | 321 | befs_ino->i_inode_num.allocation_group, |
322 | befs_ino->i_inode_num.start, befs_ino->i_inode_num.len); | 322 | befs_ino->i_inode_num.start, befs_ino->i_inode_num.len); |
323 | 323 | ||
324 | bh = befs_bread(sb, inode->i_ino); | 324 | bh = befs_bread(sb, inode->i_ino); |
325 | if (!bh) { | 325 | if (!bh) { |
326 | befs_error(sb, "unable to read inode block - " | 326 | befs_error(sb, "unable to read inode block - " |
327 | "inode = %lu", inode->i_ino); | 327 | "inode = %lu", inode->i_ino); |
328 | goto unaquire_none; | 328 | goto unaquire_none; |
329 | } | 329 | } |
330 | 330 | ||
331 | raw_inode = (befs_inode *) bh->b_data; | 331 | raw_inode = (befs_inode *) bh->b_data; |
332 | 332 | ||
333 | befs_dump_inode(sb, raw_inode); | 333 | befs_dump_inode(sb, raw_inode); |
334 | 334 | ||
335 | if (befs_check_inode(sb, raw_inode, inode->i_ino) != BEFS_OK) { | 335 | if (befs_check_inode(sb, raw_inode, inode->i_ino) != BEFS_OK) { |
336 | befs_error(sb, "Bad inode: %lu", inode->i_ino); | 336 | befs_error(sb, "Bad inode: %lu", inode->i_ino); |
337 | goto unaquire_bh; | 337 | goto unaquire_bh; |
338 | } | 338 | } |
339 | 339 | ||
340 | inode->i_mode = (umode_t) fs32_to_cpu(sb, raw_inode->mode); | 340 | inode->i_mode = (umode_t) fs32_to_cpu(sb, raw_inode->mode); |
341 | 341 | ||
342 | /* | 342 | /* |
343 | * set uid and gid. But since current BeOS is single user OS, so | 343 | * set uid and gid. But since current BeOS is single user OS, so |
344 | * you can change by "uid" or "gid" options. | 344 | * you can change by "uid" or "gid" options. |
345 | */ | 345 | */ |
346 | 346 | ||
347 | inode->i_uid = befs_sb->mount_opts.use_uid ? | 347 | inode->i_uid = befs_sb->mount_opts.use_uid ? |
348 | befs_sb->mount_opts.uid : (uid_t) fs32_to_cpu(sb, raw_inode->uid); | 348 | befs_sb->mount_opts.uid : (uid_t) fs32_to_cpu(sb, raw_inode->uid); |
349 | inode->i_gid = befs_sb->mount_opts.use_gid ? | 349 | inode->i_gid = befs_sb->mount_opts.use_gid ? |
350 | befs_sb->mount_opts.gid : (gid_t) fs32_to_cpu(sb, raw_inode->gid); | 350 | befs_sb->mount_opts.gid : (gid_t) fs32_to_cpu(sb, raw_inode->gid); |
351 | 351 | ||
352 | inode->i_nlink = 1; | 352 | inode->i_nlink = 1; |
353 | 353 | ||
354 | /* | 354 | /* |
355 | * BEFS's time is 64 bits, but current VFS is 32 bits... | 355 | * BEFS's time is 64 bits, but current VFS is 32 bits... |
356 | * BEFS don't have access time. Nor inode change time. VFS | 356 | * BEFS don't have access time. Nor inode change time. VFS |
357 | * doesn't have creation time. | 357 | * doesn't have creation time. |
358 | * Also, the lower 16 bits of the last_modified_time and | 358 | * Also, the lower 16 bits of the last_modified_time and |
359 | * create_time are just a counter to help ensure uniqueness | 359 | * create_time are just a counter to help ensure uniqueness |
360 | * for indexing purposes. (PFD, page 54) | 360 | * for indexing purposes. (PFD, page 54) |
361 | */ | 361 | */ |
362 | 362 | ||
363 | inode->i_mtime.tv_sec = | 363 | inode->i_mtime.tv_sec = |
364 | fs64_to_cpu(sb, raw_inode->last_modified_time) >> 16; | 364 | fs64_to_cpu(sb, raw_inode->last_modified_time) >> 16; |
365 | inode->i_mtime.tv_nsec = 0; /* lower 16 bits are not a time */ | 365 | inode->i_mtime.tv_nsec = 0; /* lower 16 bits are not a time */ |
366 | inode->i_ctime = inode->i_mtime; | 366 | inode->i_ctime = inode->i_mtime; |
367 | inode->i_atime = inode->i_mtime; | 367 | inode->i_atime = inode->i_mtime; |
368 | inode->i_blksize = befs_sb->block_size; | 368 | inode->i_blksize = befs_sb->block_size; |
369 | 369 | ||
370 | befs_ino->i_inode_num = fsrun_to_cpu(sb, raw_inode->inode_num); | 370 | befs_ino->i_inode_num = fsrun_to_cpu(sb, raw_inode->inode_num); |
371 | befs_ino->i_parent = fsrun_to_cpu(sb, raw_inode->parent); | 371 | befs_ino->i_parent = fsrun_to_cpu(sb, raw_inode->parent); |
372 | befs_ino->i_attribute = fsrun_to_cpu(sb, raw_inode->attributes); | 372 | befs_ino->i_attribute = fsrun_to_cpu(sb, raw_inode->attributes); |
373 | befs_ino->i_flags = fs32_to_cpu(sb, raw_inode->flags); | 373 | befs_ino->i_flags = fs32_to_cpu(sb, raw_inode->flags); |
374 | 374 | ||
375 | if (S_ISLNK(inode->i_mode) && !(befs_ino->i_flags & BEFS_LONG_SYMLINK)){ | 375 | if (S_ISLNK(inode->i_mode) && !(befs_ino->i_flags & BEFS_LONG_SYMLINK)){ |
376 | inode->i_size = 0; | 376 | inode->i_size = 0; |
377 | inode->i_blocks = befs_sb->block_size / VFS_BLOCK_SIZE; | 377 | inode->i_blocks = befs_sb->block_size / VFS_BLOCK_SIZE; |
378 | strncpy(befs_ino->i_data.symlink, raw_inode->data.symlink, | 378 | strncpy(befs_ino->i_data.symlink, raw_inode->data.symlink, |
379 | BEFS_SYMLINK_LEN); | 379 | BEFS_SYMLINK_LEN); |
380 | } else { | 380 | } else { |
381 | int num_blks; | 381 | int num_blks; |
382 | 382 | ||
383 | befs_ino->i_data.ds = | 383 | befs_ino->i_data.ds = |
384 | fsds_to_cpu(sb, raw_inode->data.datastream); | 384 | fsds_to_cpu(sb, raw_inode->data.datastream); |
385 | 385 | ||
386 | num_blks = befs_count_blocks(sb, &befs_ino->i_data.ds); | 386 | num_blks = befs_count_blocks(sb, &befs_ino->i_data.ds); |
387 | inode->i_blocks = | 387 | inode->i_blocks = |
388 | num_blks * (befs_sb->block_size / VFS_BLOCK_SIZE); | 388 | num_blks * (befs_sb->block_size / VFS_BLOCK_SIZE); |
389 | inode->i_size = befs_ino->i_data.ds.size; | 389 | inode->i_size = befs_ino->i_data.ds.size; |
390 | } | 390 | } |
391 | 391 | ||
392 | inode->i_mapping->a_ops = &befs_aops; | 392 | inode->i_mapping->a_ops = &befs_aops; |
393 | 393 | ||
394 | if (S_ISREG(inode->i_mode)) { | 394 | if (S_ISREG(inode->i_mode)) { |
395 | inode->i_fop = &generic_ro_fops; | 395 | inode->i_fop = &generic_ro_fops; |
396 | } else if (S_ISDIR(inode->i_mode)) { | 396 | } else if (S_ISDIR(inode->i_mode)) { |
397 | inode->i_op = &befs_dir_inode_operations; | 397 | inode->i_op = &befs_dir_inode_operations; |
398 | inode->i_fop = &befs_dir_operations; | 398 | inode->i_fop = &befs_dir_operations; |
399 | } else if (S_ISLNK(inode->i_mode)) { | 399 | } else if (S_ISLNK(inode->i_mode)) { |
400 | inode->i_op = &befs_symlink_inode_operations; | 400 | inode->i_op = &befs_symlink_inode_operations; |
401 | } else { | 401 | } else { |
402 | befs_error(sb, "Inode %lu is not a regular file, " | 402 | befs_error(sb, "Inode %lu is not a regular file, " |
403 | "directory or symlink. THAT IS WRONG! BeFS has no " | 403 | "directory or symlink. THAT IS WRONG! BeFS has no " |
404 | "on disk special files", inode->i_ino); | 404 | "on disk special files", inode->i_ino); |
405 | goto unaquire_bh; | 405 | goto unaquire_bh; |
406 | } | 406 | } |
407 | 407 | ||
408 | brelse(bh); | 408 | brelse(bh); |
409 | befs_debug(sb, "<--- befs_read_inode()"); | 409 | befs_debug(sb, "<--- befs_read_inode()"); |
410 | return; | 410 | return; |
411 | 411 | ||
412 | unaquire_bh: | 412 | unaquire_bh: |
413 | brelse(bh); | 413 | brelse(bh); |
414 | 414 | ||
415 | unaquire_none: | 415 | unaquire_none: |
416 | make_bad_inode(inode); | 416 | make_bad_inode(inode); |
417 | befs_debug(sb, "<--- befs_read_inode() - Bad inode"); | 417 | befs_debug(sb, "<--- befs_read_inode() - Bad inode"); |
418 | return; | 418 | return; |
419 | } | 419 | } |
420 | 420 | ||
421 | /* Initialize the inode cache. Called at fs setup. | 421 | /* Initialize the inode cache. Called at fs setup. |
422 | * | 422 | * |
423 | * Taken from NFS implementation by Al Viro. | 423 | * Taken from NFS implementation by Al Viro. |
424 | */ | 424 | */ |
425 | static int | 425 | static int |
426 | befs_init_inodecache(void) | 426 | befs_init_inodecache(void) |
427 | { | 427 | { |
428 | befs_inode_cachep = kmem_cache_create("befs_inode_cache", | 428 | befs_inode_cachep = kmem_cache_create("befs_inode_cache", |
429 | sizeof (struct befs_inode_info), | 429 | sizeof (struct befs_inode_info), |
430 | 0, SLAB_RECLAIM_ACCOUNT, | 430 | 0, SLAB_RECLAIM_ACCOUNT, |
431 | init_once, NULL); | 431 | init_once, NULL); |
432 | if (befs_inode_cachep == NULL) { | 432 | if (befs_inode_cachep == NULL) { |
433 | printk(KERN_ERR "befs_init_inodecache: " | 433 | printk(KERN_ERR "befs_init_inodecache: " |
434 | "Couldn't initalize inode slabcache\n"); | 434 | "Couldn't initalize inode slabcache\n"); |
435 | return -ENOMEM; | 435 | return -ENOMEM; |
436 | } | 436 | } |
437 | 437 | ||
438 | return 0; | 438 | return 0; |
439 | } | 439 | } |
440 | 440 | ||
441 | /* Called at fs teardown. | 441 | /* Called at fs teardown. |
442 | * | 442 | * |
443 | * Taken from NFS implementation by Al Viro. | 443 | * Taken from NFS implementation by Al Viro. |
444 | */ | 444 | */ |
445 | static void | 445 | static void |
446 | befs_destroy_inodecache(void) | 446 | befs_destroy_inodecache(void) |
447 | { | 447 | { |
448 | if (kmem_cache_destroy(befs_inode_cachep)) | 448 | if (kmem_cache_destroy(befs_inode_cachep)) |
449 | printk(KERN_ERR "befs_destroy_inodecache: " | 449 | printk(KERN_ERR "befs_destroy_inodecache: " |
450 | "not all structures were freed\n"); | 450 | "not all structures were freed\n"); |
451 | } | 451 | } |
452 | 452 | ||
453 | /* | 453 | /* |
454 | * The inode of symbolic link is different to data stream. | 454 | * The inode of symbolic link is different to data stream. |
455 | * The data stream become link name. Unless the LONG_SYMLINK | 455 | * The data stream become link name. Unless the LONG_SYMLINK |
456 | * flag is set. | 456 | * flag is set. |
457 | */ | 457 | */ |
458 | static void * | 458 | static void * |
459 | befs_follow_link(struct dentry *dentry, struct nameidata *nd) | 459 | befs_follow_link(struct dentry *dentry, struct nameidata *nd) |
460 | { | 460 | { |
461 | befs_inode_info *befs_ino = BEFS_I(dentry->d_inode); | 461 | befs_inode_info *befs_ino = BEFS_I(dentry->d_inode); |
462 | char *link; | 462 | char *link; |
463 | 463 | ||
464 | if (befs_ino->i_flags & BEFS_LONG_SYMLINK) { | 464 | if (befs_ino->i_flags & BEFS_LONG_SYMLINK) { |
465 | struct super_block *sb = dentry->d_sb; | 465 | struct super_block *sb = dentry->d_sb; |
466 | befs_data_stream *data = &befs_ino->i_data.ds; | 466 | befs_data_stream *data = &befs_ino->i_data.ds; |
467 | befs_off_t len = data->size; | 467 | befs_off_t len = data->size; |
468 | 468 | ||
469 | befs_debug(sb, "Follow long symlink"); | 469 | befs_debug(sb, "Follow long symlink"); |
470 | 470 | ||
471 | link = kmalloc(len, GFP_NOFS); | 471 | link = kmalloc(len, GFP_NOFS); |
472 | if (!link) { | 472 | if (!link) { |
473 | link = ERR_PTR(-ENOMEM); | 473 | link = ERR_PTR(-ENOMEM); |
474 | } else if (befs_read_lsymlink(sb, data, link, len) != len) { | 474 | } else if (befs_read_lsymlink(sb, data, link, len) != len) { |
475 | kfree(link); | 475 | kfree(link); |
476 | befs_error(sb, "Failed to read entire long symlink"); | 476 | befs_error(sb, "Failed to read entire long symlink"); |
477 | link = ERR_PTR(-EIO); | 477 | link = ERR_PTR(-EIO); |
478 | } | 478 | } |
479 | } else { | 479 | } else { |
480 | link = befs_ino->i_data.symlink; | 480 | link = befs_ino->i_data.symlink; |
481 | } | 481 | } |
482 | 482 | ||
483 | nd_set_link(nd, link); | 483 | nd_set_link(nd, link); |
484 | return NULL; | 484 | return NULL; |
485 | } | 485 | } |
486 | 486 | ||
487 | static void befs_put_link(struct dentry *dentry, struct nameidata *nd, void *p) | 487 | static void befs_put_link(struct dentry *dentry, struct nameidata *nd, void *p) |
488 | { | 488 | { |
489 | befs_inode_info *befs_ino = BEFS_I(dentry->d_inode); | 489 | befs_inode_info *befs_ino = BEFS_I(dentry->d_inode); |
490 | if (befs_ino->i_flags & BEFS_LONG_SYMLINK) { | 490 | if (befs_ino->i_flags & BEFS_LONG_SYMLINK) { |
491 | char *p = nd_get_link(nd); | 491 | char *p = nd_get_link(nd); |
492 | if (!IS_ERR(p)) | 492 | if (!IS_ERR(p)) |
493 | kfree(p); | 493 | kfree(p); |
494 | } | 494 | } |
495 | } | 495 | } |
496 | 496 | ||
497 | /* | 497 | /* |
498 | * UTF-8 to NLS charset convert routine | 498 | * UTF-8 to NLS charset convert routine |
499 | * | 499 | * |
500 | * | 500 | * |
501 | * Changed 8/10/01 by Will Dyson. Now use uni2char() / char2uni() rather than | 501 | * Changed 8/10/01 by Will Dyson. Now use uni2char() / char2uni() rather than |
502 | * the nls tables directly | 502 | * the nls tables directly |
503 | */ | 503 | */ |
504 | 504 | ||
505 | static int | 505 | static int |
506 | befs_utf2nls(struct super_block *sb, const char *in, | 506 | befs_utf2nls(struct super_block *sb, const char *in, |
507 | int in_len, char **out, int *out_len) | 507 | int in_len, char **out, int *out_len) |
508 | { | 508 | { |
509 | struct nls_table *nls = BEFS_SB(sb)->nls; | 509 | struct nls_table *nls = BEFS_SB(sb)->nls; |
510 | int i, o; | 510 | int i, o; |
511 | wchar_t uni; | 511 | wchar_t uni; |
512 | int unilen, utflen; | 512 | int unilen, utflen; |
513 | char *result; | 513 | char *result; |
514 | int maxlen = in_len; /* The utf8->nls conversion can't make more chars */ | 514 | int maxlen = in_len; /* The utf8->nls conversion can't make more chars */ |
515 | 515 | ||
516 | befs_debug(sb, "---> utf2nls()"); | 516 | befs_debug(sb, "---> utf2nls()"); |
517 | 517 | ||
518 | if (!nls) { | 518 | if (!nls) { |
519 | befs_error(sb, "befs_utf2nls called with no NLS table loaded"); | 519 | befs_error(sb, "befs_utf2nls called with no NLS table loaded"); |
520 | return -EINVAL; | 520 | return -EINVAL; |
521 | } | 521 | } |
522 | 522 | ||
523 | *out = result = kmalloc(maxlen, GFP_NOFS); | 523 | *out = result = kmalloc(maxlen, GFP_NOFS); |
524 | if (!*out) { | 524 | if (!*out) { |
525 | befs_error(sb, "befs_utf2nls() cannot allocate memory"); | 525 | befs_error(sb, "befs_utf2nls() cannot allocate memory"); |
526 | *out_len = 0; | 526 | *out_len = 0; |
527 | return -ENOMEM; | 527 | return -ENOMEM; |
528 | } | 528 | } |
529 | 529 | ||
530 | for (i = o = 0; i < in_len; i += utflen, o += unilen) { | 530 | for (i = o = 0; i < in_len; i += utflen, o += unilen) { |
531 | 531 | ||
532 | /* convert from UTF-8 to Unicode */ | 532 | /* convert from UTF-8 to Unicode */ |
533 | utflen = utf8_mbtowc(&uni, &in[i], in_len - i); | 533 | utflen = utf8_mbtowc(&uni, &in[i], in_len - i); |
534 | if (utflen < 0) { | 534 | if (utflen < 0) { |
535 | goto conv_err; | 535 | goto conv_err; |
536 | } | 536 | } |
537 | 537 | ||
538 | /* convert from Unicode to nls */ | 538 | /* convert from Unicode to nls */ |
539 | unilen = nls->uni2char(uni, &result[o], in_len - o); | 539 | unilen = nls->uni2char(uni, &result[o], in_len - o); |
540 | if (unilen < 0) { | 540 | if (unilen < 0) { |
541 | goto conv_err; | 541 | goto conv_err; |
542 | } | 542 | } |
543 | } | 543 | } |
544 | result[o] = '\0'; | 544 | result[o] = '\0'; |
545 | *out_len = o; | 545 | *out_len = o; |
546 | 546 | ||
547 | befs_debug(sb, "<--- utf2nls()"); | 547 | befs_debug(sb, "<--- utf2nls()"); |
548 | 548 | ||
549 | return o; | 549 | return o; |
550 | 550 | ||
551 | conv_err: | 551 | conv_err: |
552 | befs_error(sb, "Name using character set %s contains a character that " | 552 | befs_error(sb, "Name using character set %s contains a character that " |
553 | "cannot be converted to unicode.", nls->charset); | 553 | "cannot be converted to unicode.", nls->charset); |
554 | befs_debug(sb, "<--- utf2nls()"); | 554 | befs_debug(sb, "<--- utf2nls()"); |
555 | kfree(result); | 555 | kfree(result); |
556 | return -EILSEQ; | 556 | return -EILSEQ; |
557 | } | 557 | } |
558 | 558 | ||
559 | /** | 559 | /** |
560 | * befs_nls2utf - Convert NLS string to utf8 encodeing | 560 | * befs_nls2utf - Convert NLS string to utf8 encodeing |
561 | * @sb: Superblock | 561 | * @sb: Superblock |
562 | * @src: Input string buffer in NLS format | 562 | * @src: Input string buffer in NLS format |
563 | * @srclen: Length of input string in bytes | 563 | * @srclen: Length of input string in bytes |
564 | * @dest: The output string in UTF8 format | 564 | * @dest: The output string in UTF-8 format |
565 | * @destlen: Length of the output buffer | 565 | * @destlen: Length of the output buffer |
566 | * | 566 | * |
567 | * Converts input string @src, which is in the format of the loaded NLS map, | 567 | * Converts input string @src, which is in the format of the loaded NLS map, |
568 | * into a utf8 string. | 568 | * into a utf8 string. |
569 | * | 569 | * |
570 | * The destination string @dest is allocated by this function and the caller is | 570 | * The destination string @dest is allocated by this function and the caller is |
571 | * responsible for freeing it with kfree() | 571 | * responsible for freeing it with kfree() |
572 | * | 572 | * |
573 | * On return, *@destlen is the length of @dest in bytes. | 573 | * On return, *@destlen is the length of @dest in bytes. |
574 | * | 574 | * |
575 | * On success, the return value is the number of utf8 characters written to | 575 | * On success, the return value is the number of utf8 characters written to |
576 | * the output buffer @dest. | 576 | * the output buffer @dest. |
577 | * | 577 | * |
578 | * On Failure, a negative number coresponding to the error code is returned. | 578 | * On Failure, a negative number coresponding to the error code is returned. |
579 | */ | 579 | */ |
580 | 580 | ||
581 | static int | 581 | static int |
582 | befs_nls2utf(struct super_block *sb, const char *in, | 582 | befs_nls2utf(struct super_block *sb, const char *in, |
583 | int in_len, char **out, int *out_len) | 583 | int in_len, char **out, int *out_len) |
584 | { | 584 | { |
585 | struct nls_table *nls = BEFS_SB(sb)->nls; | 585 | struct nls_table *nls = BEFS_SB(sb)->nls; |
586 | int i, o; | 586 | int i, o; |
587 | wchar_t uni; | 587 | wchar_t uni; |
588 | int unilen, utflen; | 588 | int unilen, utflen; |
589 | char *result; | 589 | char *result; |
590 | int maxlen = 3 * in_len; | 590 | int maxlen = 3 * in_len; |
591 | 591 | ||
592 | befs_debug(sb, "---> nls2utf()\n"); | 592 | befs_debug(sb, "---> nls2utf()\n"); |
593 | 593 | ||
594 | if (!nls) { | 594 | if (!nls) { |
595 | befs_error(sb, "befs_nls2utf called with no NLS table loaded."); | 595 | befs_error(sb, "befs_nls2utf called with no NLS table loaded."); |
596 | return -EINVAL; | 596 | return -EINVAL; |
597 | } | 597 | } |
598 | 598 | ||
599 | *out = result = kmalloc(maxlen, GFP_NOFS); | 599 | *out = result = kmalloc(maxlen, GFP_NOFS); |
600 | if (!*out) { | 600 | if (!*out) { |
601 | befs_error(sb, "befs_nls2utf() cannot allocate memory"); | 601 | befs_error(sb, "befs_nls2utf() cannot allocate memory"); |
602 | *out_len = 0; | 602 | *out_len = 0; |
603 | return -ENOMEM; | 603 | return -ENOMEM; |
604 | } | 604 | } |
605 | 605 | ||
606 | for (i = o = 0; i < in_len; i += unilen, o += utflen) { | 606 | for (i = o = 0; i < in_len; i += unilen, o += utflen) { |
607 | 607 | ||
608 | /* convert from nls to unicode */ | 608 | /* convert from nls to unicode */ |
609 | unilen = nls->char2uni(&in[i], in_len - i, &uni); | 609 | unilen = nls->char2uni(&in[i], in_len - i, &uni); |
610 | if (unilen < 0) { | 610 | if (unilen < 0) { |
611 | goto conv_err; | 611 | goto conv_err; |
612 | } | 612 | } |
613 | 613 | ||
614 | /* convert from unicode to UTF-8 */ | 614 | /* convert from unicode to UTF-8 */ |
615 | utflen = utf8_wctomb(&result[o], uni, 3); | 615 | utflen = utf8_wctomb(&result[o], uni, 3); |
616 | if (utflen <= 0) { | 616 | if (utflen <= 0) { |
617 | goto conv_err; | 617 | goto conv_err; |
618 | } | 618 | } |
619 | } | 619 | } |
620 | 620 | ||
621 | result[o] = '\0'; | 621 | result[o] = '\0'; |
622 | *out_len = o; | 622 | *out_len = o; |
623 | 623 | ||
624 | befs_debug(sb, "<--- nls2utf()"); | 624 | befs_debug(sb, "<--- nls2utf()"); |
625 | 625 | ||
626 | return i; | 626 | return i; |
627 | 627 | ||
628 | conv_err: | 628 | conv_err: |
629 | befs_error(sb, "Name using charecter set %s contains a charecter that " | 629 | befs_error(sb, "Name using charecter set %s contains a charecter that " |
630 | "cannot be converted to unicode.", nls->charset); | 630 | "cannot be converted to unicode.", nls->charset); |
631 | befs_debug(sb, "<--- nls2utf()"); | 631 | befs_debug(sb, "<--- nls2utf()"); |
632 | kfree(result); | 632 | kfree(result); |
633 | return -EILSEQ; | 633 | return -EILSEQ; |
634 | } | 634 | } |
635 | 635 | ||
636 | /** | 636 | /** |
637 | * Use the | 637 | * Use the |
638 | * | 638 | * |
639 | */ | 639 | */ |
640 | enum { | 640 | enum { |
641 | Opt_uid, Opt_gid, Opt_charset, Opt_debug, Opt_err, | 641 | Opt_uid, Opt_gid, Opt_charset, Opt_debug, Opt_err, |
642 | }; | 642 | }; |
643 | 643 | ||
644 | static match_table_t befs_tokens = { | 644 | static match_table_t befs_tokens = { |
645 | {Opt_uid, "uid=%d"}, | 645 | {Opt_uid, "uid=%d"}, |
646 | {Opt_gid, "gid=%d"}, | 646 | {Opt_gid, "gid=%d"}, |
647 | {Opt_charset, "iocharset=%s"}, | 647 | {Opt_charset, "iocharset=%s"}, |
648 | {Opt_debug, "debug"}, | 648 | {Opt_debug, "debug"}, |
649 | {Opt_err, NULL} | 649 | {Opt_err, NULL} |
650 | }; | 650 | }; |
651 | 651 | ||
652 | static int | 652 | static int |
653 | parse_options(char *options, befs_mount_options * opts) | 653 | parse_options(char *options, befs_mount_options * opts) |
654 | { | 654 | { |
655 | char *p; | 655 | char *p; |
656 | substring_t args[MAX_OPT_ARGS]; | 656 | substring_t args[MAX_OPT_ARGS]; |
657 | int option; | 657 | int option; |
658 | 658 | ||
659 | /* Initialize options */ | 659 | /* Initialize options */ |
660 | opts->uid = 0; | 660 | opts->uid = 0; |
661 | opts->gid = 0; | 661 | opts->gid = 0; |
662 | opts->use_uid = 0; | 662 | opts->use_uid = 0; |
663 | opts->use_gid = 0; | 663 | opts->use_gid = 0; |
664 | opts->iocharset = NULL; | 664 | opts->iocharset = NULL; |
665 | opts->debug = 0; | 665 | opts->debug = 0; |
666 | 666 | ||
667 | if (!options) | 667 | if (!options) |
668 | return 1; | 668 | return 1; |
669 | 669 | ||
670 | while ((p = strsep(&options, ",")) != NULL) { | 670 | while ((p = strsep(&options, ",")) != NULL) { |
671 | int token; | 671 | int token; |
672 | if (!*p) | 672 | if (!*p) |
673 | continue; | 673 | continue; |
674 | 674 | ||
675 | token = match_token(p, befs_tokens, args); | 675 | token = match_token(p, befs_tokens, args); |
676 | switch (token) { | 676 | switch (token) { |
677 | case Opt_uid: | 677 | case Opt_uid: |
678 | if (match_int(&args[0], &option)) | 678 | if (match_int(&args[0], &option)) |
679 | return 0; | 679 | return 0; |
680 | if (option < 0) { | 680 | if (option < 0) { |
681 | printk(KERN_ERR "BeFS: Invalid uid %d, " | 681 | printk(KERN_ERR "BeFS: Invalid uid %d, " |
682 | "using default\n", option); | 682 | "using default\n", option); |
683 | break; | 683 | break; |
684 | } | 684 | } |
685 | opts->uid = option; | 685 | opts->uid = option; |
686 | opts->use_uid = 1; | 686 | opts->use_uid = 1; |
687 | break; | 687 | break; |
688 | case Opt_gid: | 688 | case Opt_gid: |
689 | if (match_int(&args[0], &option)) | 689 | if (match_int(&args[0], &option)) |
690 | return 0; | 690 | return 0; |
691 | if (option < 0) { | 691 | if (option < 0) { |
692 | printk(KERN_ERR "BeFS: Invalid gid %d, " | 692 | printk(KERN_ERR "BeFS: Invalid gid %d, " |
693 | "using default\n", option); | 693 | "using default\n", option); |
694 | break; | 694 | break; |
695 | } | 695 | } |
696 | opts->gid = option; | 696 | opts->gid = option; |
697 | opts->use_gid = 1; | 697 | opts->use_gid = 1; |
698 | break; | 698 | break; |
699 | case Opt_charset: | 699 | case Opt_charset: |
700 | kfree(opts->iocharset); | 700 | kfree(opts->iocharset); |
701 | opts->iocharset = match_strdup(&args[0]); | 701 | opts->iocharset = match_strdup(&args[0]); |
702 | if (!opts->iocharset) { | 702 | if (!opts->iocharset) { |
703 | printk(KERN_ERR "BeFS: allocation failure for " | 703 | printk(KERN_ERR "BeFS: allocation failure for " |
704 | "iocharset string\n"); | 704 | "iocharset string\n"); |
705 | return 0; | 705 | return 0; |
706 | } | 706 | } |
707 | break; | 707 | break; |
708 | case Opt_debug: | 708 | case Opt_debug: |
709 | opts->debug = 1; | 709 | opts->debug = 1; |
710 | break; | 710 | break; |
711 | default: | 711 | default: |
712 | printk(KERN_ERR "BeFS: Unrecognized mount option \"%s\" " | 712 | printk(KERN_ERR "BeFS: Unrecognized mount option \"%s\" " |
713 | "or missing value\n", p); | 713 | "or missing value\n", p); |
714 | return 0; | 714 | return 0; |
715 | } | 715 | } |
716 | } | 716 | } |
717 | return 1; | 717 | return 1; |
718 | } | 718 | } |
719 | 719 | ||
720 | /* This function has the responsibiltiy of getting the | 720 | /* This function has the responsibiltiy of getting the |
721 | * filesystem ready for unmounting. | 721 | * filesystem ready for unmounting. |
722 | * Basicly, we free everything that we allocated in | 722 | * Basicly, we free everything that we allocated in |
723 | * befs_read_inode | 723 | * befs_read_inode |
724 | */ | 724 | */ |
725 | static void | 725 | static void |
726 | befs_put_super(struct super_block *sb) | 726 | befs_put_super(struct super_block *sb) |
727 | { | 727 | { |
728 | kfree(BEFS_SB(sb)->mount_opts.iocharset); | 728 | kfree(BEFS_SB(sb)->mount_opts.iocharset); |
729 | BEFS_SB(sb)->mount_opts.iocharset = NULL; | 729 | BEFS_SB(sb)->mount_opts.iocharset = NULL; |
730 | 730 | ||
731 | if (BEFS_SB(sb)->nls) { | 731 | if (BEFS_SB(sb)->nls) { |
732 | unload_nls(BEFS_SB(sb)->nls); | 732 | unload_nls(BEFS_SB(sb)->nls); |
733 | BEFS_SB(sb)->nls = NULL; | 733 | BEFS_SB(sb)->nls = NULL; |
734 | } | 734 | } |
735 | 735 | ||
736 | kfree(sb->s_fs_info); | 736 | kfree(sb->s_fs_info); |
737 | sb->s_fs_info = NULL; | 737 | sb->s_fs_info = NULL; |
738 | return; | 738 | return; |
739 | } | 739 | } |
740 | 740 | ||
741 | /* Allocate private field of the superblock, fill it. | 741 | /* Allocate private field of the superblock, fill it. |
742 | * | 742 | * |
743 | * Finish filling the public superblock fields | 743 | * Finish filling the public superblock fields |
744 | * Make the root directory | 744 | * Make the root directory |
745 | * Load a set of NLS translations if needed. | 745 | * Load a set of NLS translations if needed. |
746 | */ | 746 | */ |
747 | static int | 747 | static int |
748 | befs_fill_super(struct super_block *sb, void *data, int silent) | 748 | befs_fill_super(struct super_block *sb, void *data, int silent) |
749 | { | 749 | { |
750 | struct buffer_head *bh; | 750 | struct buffer_head *bh; |
751 | befs_sb_info *befs_sb; | 751 | befs_sb_info *befs_sb; |
752 | befs_super_block *disk_sb; | 752 | befs_super_block *disk_sb; |
753 | struct inode *root; | 753 | struct inode *root; |
754 | 754 | ||
755 | const unsigned long sb_block = 0; | 755 | const unsigned long sb_block = 0; |
756 | const off_t x86_sb_off = 512; | 756 | const off_t x86_sb_off = 512; |
757 | 757 | ||
758 | sb->s_fs_info = kmalloc(sizeof (*befs_sb), GFP_KERNEL); | 758 | sb->s_fs_info = kmalloc(sizeof (*befs_sb), GFP_KERNEL); |
759 | if (sb->s_fs_info == NULL) { | 759 | if (sb->s_fs_info == NULL) { |
760 | printk(KERN_ERR | 760 | printk(KERN_ERR |
761 | "BeFS(%s): Unable to allocate memory for private " | 761 | "BeFS(%s): Unable to allocate memory for private " |
762 | "portion of superblock. Bailing.\n", sb->s_id); | 762 | "portion of superblock. Bailing.\n", sb->s_id); |
763 | goto unaquire_none; | 763 | goto unaquire_none; |
764 | } | 764 | } |
765 | befs_sb = BEFS_SB(sb); | 765 | befs_sb = BEFS_SB(sb); |
766 | memset(befs_sb, 0, sizeof(befs_sb_info)); | 766 | memset(befs_sb, 0, sizeof(befs_sb_info)); |
767 | 767 | ||
768 | if (!parse_options((char *) data, &befs_sb->mount_opts)) { | 768 | if (!parse_options((char *) data, &befs_sb->mount_opts)) { |
769 | befs_error(sb, "cannot parse mount options"); | 769 | befs_error(sb, "cannot parse mount options"); |
770 | goto unaquire_priv_sbp; | 770 | goto unaquire_priv_sbp; |
771 | } | 771 | } |
772 | 772 | ||
773 | befs_debug(sb, "---> befs_fill_super()"); | 773 | befs_debug(sb, "---> befs_fill_super()"); |
774 | 774 | ||
775 | #ifndef CONFIG_BEFS_RW | 775 | #ifndef CONFIG_BEFS_RW |
776 | if (!(sb->s_flags & MS_RDONLY)) { | 776 | if (!(sb->s_flags & MS_RDONLY)) { |
777 | befs_warning(sb, | 777 | befs_warning(sb, |
778 | "No write support. Marking filesystem read-only"); | 778 | "No write support. Marking filesystem read-only"); |
779 | sb->s_flags |= MS_RDONLY; | 779 | sb->s_flags |= MS_RDONLY; |
780 | } | 780 | } |
781 | #endif /* CONFIG_BEFS_RW */ | 781 | #endif /* CONFIG_BEFS_RW */ |
782 | 782 | ||
783 | /* | 783 | /* |
784 | * Set dummy blocksize to read super block. | 784 | * Set dummy blocksize to read super block. |
785 | * Will be set to real fs blocksize later. | 785 | * Will be set to real fs blocksize later. |
786 | * | 786 | * |
787 | * Linux 2.4.10 and later refuse to read blocks smaller than | 787 | * Linux 2.4.10 and later refuse to read blocks smaller than |
788 | * the hardsect size for the device. But we also need to read at | 788 | * the hardsect size for the device. But we also need to read at |
789 | * least 1k to get the second 512 bytes of the volume. | 789 | * least 1k to get the second 512 bytes of the volume. |
790 | * -WD 10-26-01 | 790 | * -WD 10-26-01 |
791 | */ | 791 | */ |
792 | sb_min_blocksize(sb, 1024); | 792 | sb_min_blocksize(sb, 1024); |
793 | 793 | ||
794 | if (!(bh = sb_bread(sb, sb_block))) { | 794 | if (!(bh = sb_bread(sb, sb_block))) { |
795 | befs_error(sb, "unable to read superblock"); | 795 | befs_error(sb, "unable to read superblock"); |
796 | goto unaquire_priv_sbp; | 796 | goto unaquire_priv_sbp; |
797 | } | 797 | } |
798 | 798 | ||
799 | /* account for offset of super block on x86 */ | 799 | /* account for offset of super block on x86 */ |
800 | disk_sb = (befs_super_block *) bh->b_data; | 800 | disk_sb = (befs_super_block *) bh->b_data; |
801 | if ((le32_to_cpu(disk_sb->magic1) == BEFS_SUPER_MAGIC1) || | 801 | if ((le32_to_cpu(disk_sb->magic1) == BEFS_SUPER_MAGIC1) || |
802 | (be32_to_cpu(disk_sb->magic1) == BEFS_SUPER_MAGIC1)) { | 802 | (be32_to_cpu(disk_sb->magic1) == BEFS_SUPER_MAGIC1)) { |
803 | befs_debug(sb, "Using PPC superblock location"); | 803 | befs_debug(sb, "Using PPC superblock location"); |
804 | } else { | 804 | } else { |
805 | befs_debug(sb, "Using x86 superblock location"); | 805 | befs_debug(sb, "Using x86 superblock location"); |
806 | disk_sb = | 806 | disk_sb = |
807 | (befs_super_block *) ((void *) bh->b_data + x86_sb_off); | 807 | (befs_super_block *) ((void *) bh->b_data + x86_sb_off); |
808 | } | 808 | } |
809 | 809 | ||
810 | if (befs_load_sb(sb, disk_sb) != BEFS_OK) | 810 | if (befs_load_sb(sb, disk_sb) != BEFS_OK) |
811 | goto unaquire_bh; | 811 | goto unaquire_bh; |
812 | 812 | ||
813 | befs_dump_super_block(sb, disk_sb); | 813 | befs_dump_super_block(sb, disk_sb); |
814 | 814 | ||
815 | brelse(bh); | 815 | brelse(bh); |
816 | 816 | ||
817 | if (befs_check_sb(sb) != BEFS_OK) | 817 | if (befs_check_sb(sb) != BEFS_OK) |
818 | goto unaquire_priv_sbp; | 818 | goto unaquire_priv_sbp; |
819 | 819 | ||
820 | if( befs_sb->num_blocks > ~((sector_t)0) ) { | 820 | if( befs_sb->num_blocks > ~((sector_t)0) ) { |
821 | befs_error(sb, "blocks count: %Lu " | 821 | befs_error(sb, "blocks count: %Lu " |
822 | "is larger than the host can use", | 822 | "is larger than the host can use", |
823 | befs_sb->num_blocks); | 823 | befs_sb->num_blocks); |
824 | goto unaquire_priv_sbp; | 824 | goto unaquire_priv_sbp; |
825 | } | 825 | } |
826 | 826 | ||
827 | /* | 827 | /* |
828 | * set up enough so that it can read an inode | 828 | * set up enough so that it can read an inode |
829 | * Fill in kernel superblock fields from private sb | 829 | * Fill in kernel superblock fields from private sb |
830 | */ | 830 | */ |
831 | sb->s_magic = BEFS_SUPER_MAGIC; | 831 | sb->s_magic = BEFS_SUPER_MAGIC; |
832 | /* Set real blocksize of fs */ | 832 | /* Set real blocksize of fs */ |
833 | sb_set_blocksize(sb, (ulong) befs_sb->block_size); | 833 | sb_set_blocksize(sb, (ulong) befs_sb->block_size); |
834 | sb->s_op = (struct super_operations *) &befs_sops; | 834 | sb->s_op = (struct super_operations *) &befs_sops; |
835 | root = iget(sb, iaddr2blockno(sb, &(befs_sb->root_dir))); | 835 | root = iget(sb, iaddr2blockno(sb, &(befs_sb->root_dir))); |
836 | sb->s_root = d_alloc_root(root); | 836 | sb->s_root = d_alloc_root(root); |
837 | if (!sb->s_root) { | 837 | if (!sb->s_root) { |
838 | iput(root); | 838 | iput(root); |
839 | befs_error(sb, "get root inode failed"); | 839 | befs_error(sb, "get root inode failed"); |
840 | goto unaquire_priv_sbp; | 840 | goto unaquire_priv_sbp; |
841 | } | 841 | } |
842 | 842 | ||
843 | /* load nls library */ | 843 | /* load nls library */ |
844 | if (befs_sb->mount_opts.iocharset) { | 844 | if (befs_sb->mount_opts.iocharset) { |
845 | befs_debug(sb, "Loading nls: %s", | 845 | befs_debug(sb, "Loading nls: %s", |
846 | befs_sb->mount_opts.iocharset); | 846 | befs_sb->mount_opts.iocharset); |
847 | befs_sb->nls = load_nls(befs_sb->mount_opts.iocharset); | 847 | befs_sb->nls = load_nls(befs_sb->mount_opts.iocharset); |
848 | if (!befs_sb->nls) { | 848 | if (!befs_sb->nls) { |
849 | befs_warning(sb, "Cannot load nls %s" | 849 | befs_warning(sb, "Cannot load nls %s" |
850 | " loading default nls", | 850 | " loading default nls", |
851 | befs_sb->mount_opts.iocharset); | 851 | befs_sb->mount_opts.iocharset); |
852 | befs_sb->nls = load_nls_default(); | 852 | befs_sb->nls = load_nls_default(); |
853 | } | 853 | } |
854 | /* load default nls if none is specified in mount options */ | 854 | /* load default nls if none is specified in mount options */ |
855 | } else { | 855 | } else { |
856 | befs_debug(sb, "Loading default nls"); | 856 | befs_debug(sb, "Loading default nls"); |
857 | befs_sb->nls = load_nls_default(); | 857 | befs_sb->nls = load_nls_default(); |
858 | } | 858 | } |
859 | 859 | ||
860 | return 0; | 860 | return 0; |
861 | /*****************/ | 861 | /*****************/ |
862 | unaquire_bh: | 862 | unaquire_bh: |
863 | brelse(bh); | 863 | brelse(bh); |
864 | 864 | ||
865 | unaquire_priv_sbp: | 865 | unaquire_priv_sbp: |
866 | kfree(sb->s_fs_info); | 866 | kfree(sb->s_fs_info); |
867 | 867 | ||
868 | unaquire_none: | 868 | unaquire_none: |
869 | sb->s_fs_info = NULL; | 869 | sb->s_fs_info = NULL; |
870 | return -EINVAL; | 870 | return -EINVAL; |
871 | } | 871 | } |
872 | 872 | ||
873 | static int | 873 | static int |
874 | befs_remount(struct super_block *sb, int *flags, char *data) | 874 | befs_remount(struct super_block *sb, int *flags, char *data) |
875 | { | 875 | { |
876 | if (!(*flags & MS_RDONLY)) | 876 | if (!(*flags & MS_RDONLY)) |
877 | return -EINVAL; | 877 | return -EINVAL; |
878 | return 0; | 878 | return 0; |
879 | } | 879 | } |
880 | 880 | ||
881 | static int | 881 | static int |
882 | befs_statfs(struct super_block *sb, struct kstatfs *buf) | 882 | befs_statfs(struct super_block *sb, struct kstatfs *buf) |
883 | { | 883 | { |
884 | 884 | ||
885 | befs_debug(sb, "---> befs_statfs()"); | 885 | befs_debug(sb, "---> befs_statfs()"); |
886 | 886 | ||
887 | buf->f_type = BEFS_SUPER_MAGIC; | 887 | buf->f_type = BEFS_SUPER_MAGIC; |
888 | buf->f_bsize = sb->s_blocksize; | 888 | buf->f_bsize = sb->s_blocksize; |
889 | buf->f_blocks = BEFS_SB(sb)->num_blocks; | 889 | buf->f_blocks = BEFS_SB(sb)->num_blocks; |
890 | buf->f_bfree = BEFS_SB(sb)->num_blocks - BEFS_SB(sb)->used_blocks; | 890 | buf->f_bfree = BEFS_SB(sb)->num_blocks - BEFS_SB(sb)->used_blocks; |
891 | buf->f_bavail = buf->f_bfree; | 891 | buf->f_bavail = buf->f_bfree; |
892 | buf->f_files = 0; /* UNKNOWN */ | 892 | buf->f_files = 0; /* UNKNOWN */ |
893 | buf->f_ffree = 0; /* UNKNOWN */ | 893 | buf->f_ffree = 0; /* UNKNOWN */ |
894 | buf->f_namelen = BEFS_NAME_LEN; | 894 | buf->f_namelen = BEFS_NAME_LEN; |
895 | 895 | ||
896 | befs_debug(sb, "<--- befs_statfs()"); | 896 | befs_debug(sb, "<--- befs_statfs()"); |
897 | 897 | ||
898 | return 0; | 898 | return 0; |
899 | } | 899 | } |
900 | 900 | ||
901 | static struct super_block * | 901 | static struct super_block * |
902 | befs_get_sb(struct file_system_type *fs_type, int flags, const char *dev_name, | 902 | befs_get_sb(struct file_system_type *fs_type, int flags, const char *dev_name, |
903 | void *data) | 903 | void *data) |
904 | { | 904 | { |
905 | return get_sb_bdev(fs_type, flags, dev_name, data, befs_fill_super); | 905 | return get_sb_bdev(fs_type, flags, dev_name, data, befs_fill_super); |
906 | } | 906 | } |
907 | 907 | ||
908 | static struct file_system_type befs_fs_type = { | 908 | static struct file_system_type befs_fs_type = { |
909 | .owner = THIS_MODULE, | 909 | .owner = THIS_MODULE, |
910 | .name = "befs", | 910 | .name = "befs", |
911 | .get_sb = befs_get_sb, | 911 | .get_sb = befs_get_sb, |
912 | .kill_sb = kill_block_super, | 912 | .kill_sb = kill_block_super, |
913 | .fs_flags = FS_REQUIRES_DEV, | 913 | .fs_flags = FS_REQUIRES_DEV, |
914 | }; | 914 | }; |
915 | 915 | ||
916 | static int __init | 916 | static int __init |
917 | init_befs_fs(void) | 917 | init_befs_fs(void) |
918 | { | 918 | { |
919 | int err; | 919 | int err; |
920 | 920 | ||
921 | printk(KERN_INFO "BeFS version: %s\n", BEFS_VERSION); | 921 | printk(KERN_INFO "BeFS version: %s\n", BEFS_VERSION); |
922 | 922 | ||
923 | err = befs_init_inodecache(); | 923 | err = befs_init_inodecache(); |
924 | if (err) | 924 | if (err) |
925 | goto unaquire_none; | 925 | goto unaquire_none; |
926 | 926 | ||
927 | err = register_filesystem(&befs_fs_type); | 927 | err = register_filesystem(&befs_fs_type); |
928 | if (err) | 928 | if (err) |
929 | goto unaquire_inodecache; | 929 | goto unaquire_inodecache; |
930 | 930 | ||
931 | return 0; | 931 | return 0; |
932 | 932 | ||
933 | unaquire_inodecache: | 933 | unaquire_inodecache: |
934 | befs_destroy_inodecache(); | 934 | befs_destroy_inodecache(); |
935 | 935 | ||
936 | unaquire_none: | 936 | unaquire_none: |
937 | return err; | 937 | return err; |
938 | } | 938 | } |
939 | 939 | ||
940 | static void __exit | 940 | static void __exit |
941 | exit_befs_fs(void) | 941 | exit_befs_fs(void) |
942 | { | 942 | { |
943 | befs_destroy_inodecache(); | 943 | befs_destroy_inodecache(); |
944 | 944 | ||
945 | unregister_filesystem(&befs_fs_type); | 945 | unregister_filesystem(&befs_fs_type); |
946 | } | 946 | } |
947 | 947 | ||
948 | /* | 948 | /* |
949 | Macros that typecheck the init and exit functions, | 949 | Macros that typecheck the init and exit functions, |
950 | ensures that they are called at init and cleanup, | 950 | ensures that they are called at init and cleanup, |
951 | and eliminates warnings about unused functions. | 951 | and eliminates warnings about unused functions. |
952 | */ | 952 | */ |
953 | module_init(init_befs_fs) | 953 | module_init(init_befs_fs) |
954 | module_exit(exit_befs_fs) | 954 | module_exit(exit_befs_fs) |
955 | 955 |
fs/cifs/CHANGES
1 | Version 1.40 | 1 | Version 1.40 |
2 | ------------ | 2 | ------------ |
3 | Use fsuid (fsgid) more consistently instead of uid (gid). Improve performance | 3 | Use fsuid (fsgid) more consistently instead of uid (gid). Improve performance |
4 | of readpages by eliminating one extra memcpy. Allow update of file size | 4 | of readpages by eliminating one extra memcpy. Allow update of file size |
5 | from remote server even if file is open for write as long as mount is | 5 | from remote server even if file is open for write as long as mount is |
6 | directio. Recognize share mode security and send NTLM encrypted password | 6 | directio. Recognize share mode security and send NTLM encrypted password |
7 | on tree connect if share mode negotiated. | 7 | on tree connect if share mode negotiated. |
8 | 8 | ||
9 | Version 1.39 | 9 | Version 1.39 |
10 | ------------ | 10 | ------------ |
11 | Defer close of a file handle slightly if pending writes depend on that handle | 11 | Defer close of a file handle slightly if pending writes depend on that handle |
12 | (this reduces the EBADF bad file handle errors that can be logged under heavy | 12 | (this reduces the EBADF bad file handle errors that can be logged under heavy |
13 | stress on writes). Modify cifs Kconfig options to expose CONFIG_CIFS_STATS2 | 13 | stress on writes). Modify cifs Kconfig options to expose CONFIG_CIFS_STATS2 |
14 | Fix SFU style symlinks and mknod needed for servers which do not support the | 14 | Fix SFU style symlinks and mknod needed for servers which do not support the |
15 | CIFS Unix Extensions. Fix setfacl/getfacl on bigendian. Timeout negative | 15 | CIFS Unix Extensions. Fix setfacl/getfacl on bigendian. Timeout negative |
16 | dentries so files that the client sees as deleted but that later get created | 16 | dentries so files that the client sees as deleted but that later get created |
17 | on the server will be recognized. Add client side permission check on setattr. | 17 | on the server will be recognized. Add client side permission check on setattr. |
18 | Timeout stuck requests better (where server has never responded or sent corrupt | 18 | Timeout stuck requests better (where server has never responded or sent corrupt |
19 | responses) | 19 | responses) |
20 | 20 | ||
21 | Version 1.38 | 21 | Version 1.38 |
22 | ------------ | 22 | ------------ |
23 | Fix tcp socket retransmission timeouts (e.g. on ENOSPACE from the socket) | 23 | Fix tcp socket retransmission timeouts (e.g. on ENOSPACE from the socket) |
24 | to be smaller at first (but increasing) so large write performance performance | 24 | to be smaller at first (but increasing) so large write performance performance |
25 | over GigE is better. Do not hang thread on illegal byte range lock response | 25 | over GigE is better. Do not hang thread on illegal byte range lock response |
26 | from Windows (Windows can send an RFC1001 size which does not match smb size) by | 26 | from Windows (Windows can send an RFC1001 size which does not match smb size) by |
27 | allowing an SMBs TCP length to be up to a few bytes longer than it should be. | 27 | allowing an SMBs TCP length to be up to a few bytes longer than it should be. |
28 | wsize and rsize can now be larger than negotiated buffer size if server | 28 | wsize and rsize can now be larger than negotiated buffer size if server |
29 | supports large readx/writex, even when directio mount flag not specified. | 29 | supports large readx/writex, even when directio mount flag not specified. |
30 | Write size will in many cases now be 16K instead of 4K which greatly helps | 30 | Write size will in many cases now be 16K instead of 4K which greatly helps |
31 | file copy performance on lightly loaded networks. Fix oops in dnotify | 31 | file copy performance on lightly loaded networks. Fix oops in dnotify |
32 | when experimental config flag enabled. Make cifsFYI more granular. | 32 | when experimental config flag enabled. Make cifsFYI more granular. |
33 | 33 | ||
34 | Version 1.37 | 34 | Version 1.37 |
35 | ------------ | 35 | ------------ |
36 | Fix readdir caching when unlink removes file in current search buffer, | 36 | Fix readdir caching when unlink removes file in current search buffer, |
37 | and this is followed by a rewind search to just before the deleted entry. | 37 | and this is followed by a rewind search to just before the deleted entry. |
38 | Do not attempt to set ctime unless atime and/or mtime change requested | 38 | Do not attempt to set ctime unless atime and/or mtime change requested |
39 | (most servers throw it away anyway). Fix length check of received smbs | 39 | (most servers throw it away anyway). Fix length check of received smbs |
40 | to be more accurate. Fix big endian problem with mapchars mount option, | 40 | to be more accurate. Fix big endian problem with mapchars mount option, |
41 | and with a field returned by statfs. | 41 | and with a field returned by statfs. |
42 | 42 | ||
43 | Version 1.36 | 43 | Version 1.36 |
44 | ------------ | 44 | ------------ |
45 | Add support for mounting to older pre-CIFS servers such as Windows9x and ME. | 45 | Add support for mounting to older pre-CIFS servers such as Windows9x and ME. |
46 | For these older servers, add option for passing netbios name of server in | 46 | For these older servers, add option for passing netbios name of server in |
47 | on mount (servernetbiosname). Add suspend support for power management, to | 47 | on mount (servernetbiosname). Add suspend support for power management, to |
48 | avoid cifsd thread preventing software suspend from working. | 48 | avoid cifsd thread preventing software suspend from working. |
49 | Add mount option for disabling the default behavior of sending byte range lock | 49 | Add mount option for disabling the default behavior of sending byte range lock |
50 | requests to the server (necessary for certain applications which break with | 50 | requests to the server (necessary for certain applications which break with |
51 | mandatory lock behavior such as Evolution), and also mount option for | 51 | mandatory lock behavior such as Evolution), and also mount option for |
52 | requesting case insensitive matching for path based requests (requesting | 52 | requesting case insensitive matching for path based requests (requesting |
53 | case sensitive is the default). | 53 | case sensitive is the default). |
54 | 54 | ||
55 | Version 1.35 | 55 | Version 1.35 |
56 | ------------ | 56 | ------------ |
57 | Add writepage performance improvements. Fix path name conversions | 57 | Add writepage performance improvements. Fix path name conversions |
58 | for long filenames on mounts which were done with "mapchars" mount option | 58 | for long filenames on mounts which were done with "mapchars" mount option |
59 | specified. Ensure multiplex ids do not collide. Fix case in which | 59 | specified. Ensure multiplex ids do not collide. Fix case in which |
60 | rmmod can oops if done soon after last unmount. Fix truncated | 60 | rmmod can oops if done soon after last unmount. Fix truncated |
61 | search (readdir) output when resume filename was a long filename. | 61 | search (readdir) output when resume filename was a long filename. |
62 | Fix filename conversion when mapchars mount option was specified and | 62 | Fix filename conversion when mapchars mount option was specified and |
63 | filename was a long filename. | 63 | filename was a long filename. |
64 | 64 | ||
65 | Version 1.34 | 65 | Version 1.34 |
66 | ------------ | 66 | ------------ |
67 | Fix error mapping of the TOO_MANY_LINKS (hardlinks) case. | 67 | Fix error mapping of the TOO_MANY_LINKS (hardlinks) case. |
68 | Do not oops if root user kills cifs oplock kernel thread or | 68 | Do not oops if root user kills cifs oplock kernel thread or |
69 | kills the cifsd thread (NB: killing the cifs kernel threads is not | 69 | kills the cifsd thread (NB: killing the cifs kernel threads is not |
70 | recommended, unmount and rmmod cifs will kill them when they are | 70 | recommended, unmount and rmmod cifs will kill them when they are |
71 | no longer needed). Fix readdir to ASCII servers (ie older servers | 71 | no longer needed). Fix readdir to ASCII servers (ie older servers |
72 | which do not support Unicode) and also require asterisk. | 72 | which do not support Unicode) and also require asterisk. |
73 | Fix out of memory case in which data could be written one page | 73 | Fix out of memory case in which data could be written one page |
74 | off in the page cache. | 74 | off in the page cache. |
75 | 75 | ||
76 | Version 1.33 | 76 | Version 1.33 |
77 | ------------ | 77 | ------------ |
78 | Fix caching problem, in which readdir of directory containing a file | 78 | Fix caching problem, in which readdir of directory containing a file |
79 | which was cached could cause the file's time stamp to be updated | 79 | which was cached could cause the file's time stamp to be updated |
80 | without invalidating the readahead data (so we could get stale | 80 | without invalidating the readahead data (so we could get stale |
81 | file data on the client for that file even as the server copy changed). | 81 | file data on the client for that file even as the server copy changed). |
82 | Cleanup response processing so cifsd can not loop when abnormally | 82 | Cleanup response processing so cifsd can not loop when abnormally |
83 | terminated. | 83 | terminated. |
84 | 84 | ||
85 | 85 | ||
86 | Version 1.32 | 86 | Version 1.32 |
87 | ------------ | 87 | ------------ |
88 | Fix oops in ls when Transact2 FindFirst (or FindNext) returns more than one | 88 | Fix oops in ls when Transact2 FindFirst (or FindNext) returns more than one |
89 | transact response for an SMB request and search entry split across two frames. | 89 | transact response for an SMB request and search entry split across two frames. |
90 | Add support for lsattr (getting ext2/ext3/reiserfs attr flags from the server) | 90 | Add support for lsattr (getting ext2/ext3/reiserfs attr flags from the server) |
91 | as new protocol extensions. Do not send Get/Set calls for POSIX ACLs | 91 | as new protocol extensions. Do not send Get/Set calls for POSIX ACLs |
92 | unless server explicitly claims to support them in CIFS Unix extensions | 92 | unless server explicitly claims to support them in CIFS Unix extensions |
93 | POSIX ACL capability bit. Fix packet signing when multiuser mounting with | 93 | POSIX ACL capability bit. Fix packet signing when multiuser mounting with |
94 | different users from the same client to the same server. Fix oops in | 94 | different users from the same client to the same server. Fix oops in |
95 | cifs_close. Add mount option for remapping reserved characters in | 95 | cifs_close. Add mount option for remapping reserved characters in |
96 | filenames (also allow recognizing files with created by SFU which have any | 96 | filenames (also allow recognizing files with created by SFU which have any |
97 | of these seven reserved characters, except backslash, to be recognized). | 97 | of these seven reserved characters, except backslash, to be recognized). |
98 | Fix invalid transact2 message (we were sometimes trying to interpret | 98 | Fix invalid transact2 message (we were sometimes trying to interpret |
99 | oplock breaks as SMB responses). Add ioctl for checking that the | 99 | oplock breaks as SMB responses). Add ioctl for checking that the |
100 | current uid matches the uid of the mounter (needed by umount.cifs). | 100 | current uid matches the uid of the mounter (needed by umount.cifs). |
101 | Reduce the number of large buffer allocations in cifs response processing | 101 | Reduce the number of large buffer allocations in cifs response processing |
102 | (significantly reduces memory pressure under heavy stress with multiple | 102 | (significantly reduces memory pressure under heavy stress with multiple |
103 | processes accessing the same server at the same time). | 103 | processes accessing the same server at the same time). |
104 | 104 | ||
105 | Version 1.31 | 105 | Version 1.31 |
106 | ------------ | 106 | ------------ |
107 | Fix updates of DOS attributes and time fields so that files on NT4 servers | 107 | Fix updates of DOS attributes and time fields so that files on NT4 servers |
108 | do not get marked delete on close. Display sizes of cifs buffer pools in | 108 | do not get marked delete on close. Display sizes of cifs buffer pools in |
109 | cifs stats. Fix oops in unmount when cifsd thread being killed by | 109 | cifs stats. Fix oops in unmount when cifsd thread being killed by |
110 | shutdown. Add generic readv/writev and aio support. Report inode numbers | 110 | shutdown. Add generic readv/writev and aio support. Report inode numbers |
111 | consistently in readdir and lookup (when serverino mount option is | 111 | consistently in readdir and lookup (when serverino mount option is |
112 | specified use the inode number that the server reports - for both lookup | 112 | specified use the inode number that the server reports - for both lookup |
113 | and readdir, otherwise by default the locally generated inode number is used | 113 | and readdir, otherwise by default the locally generated inode number is used |
114 | for inodes created in either path since servers are not always able to | 114 | for inodes created in either path since servers are not always able to |
115 | provide unique inode numbers when exporting multiple volumes from under one | 115 | provide unique inode numbers when exporting multiple volumes from under one |
116 | sharename). | 116 | sharename). |
117 | 117 | ||
118 | Version 1.30 | 118 | Version 1.30 |
119 | ------------ | 119 | ------------ |
120 | Allow new nouser_xattr mount parm to disable xattr support for user namespace. | 120 | Allow new nouser_xattr mount parm to disable xattr support for user namespace. |
121 | Do not flag user_xattr mount parm in dmesg. Retry failures setting file time | 121 | Do not flag user_xattr mount parm in dmesg. Retry failures setting file time |
122 | (mostly affects NT4 servers) by retry with handle based network operation. | 122 | (mostly affects NT4 servers) by retry with handle based network operation. |
123 | Add new POSIX Query FS Info for returning statfs info more accurately. | 123 | Add new POSIX Query FS Info for returning statfs info more accurately. |
124 | Handle passwords with multiple commas in them. | 124 | Handle passwords with multiple commas in them. |
125 | 125 | ||
126 | Version 1.29 | 126 | Version 1.29 |
127 | ------------ | 127 | ------------ |
128 | Fix default mode in sysfs of cifs module parms. Remove old readdir routine. | 128 | Fix default mode in sysfs of cifs module parms. Remove old readdir routine. |
129 | Fix capabilities flags for large readx so as to allow reads larger than 64K. | 129 | Fix capabilities flags for large readx so as to allow reads larger than 64K. |
130 | 130 | ||
131 | Version 1.28 | 131 | Version 1.28 |
132 | ------------ | 132 | ------------ |
133 | Add module init parm for large SMB buffer size (to allow it to be changed | 133 | Add module init parm for large SMB buffer size (to allow it to be changed |
134 | from its default of 16K) which is especially useful for large file copy | 134 | from its default of 16K) which is especially useful for large file copy |
135 | when mounting with the directio mount option. Fix oops after | 135 | when mounting with the directio mount option. Fix oops after |
136 | returning from mount when experimental ExtendedSecurity enabled and | 136 | returning from mount when experimental ExtendedSecurity enabled and |
137 | SpnegoNegotiated returning invalid error. Fix case to retry better when | 137 | SpnegoNegotiated returning invalid error. Fix case to retry better when |
138 | peek returns from 1 to 3 bytes on socket which should have more data. | 138 | peek returns from 1 to 3 bytes on socket which should have more data. |
139 | Fixed path based calls (such as cifs lookup) to handle path names | 139 | Fixed path based calls (such as cifs lookup) to handle path names |
140 | longer than 530 (now can handle PATH_MAX). Fix pass through authentication | 140 | longer than 530 (now can handle PATH_MAX). Fix pass through authentication |
141 | from Samba server to DC (Samba required dummy LM password). | 141 | from Samba server to DC (Samba required dummy LM password). |
142 | 142 | ||
143 | Version 1.27 | 143 | Version 1.27 |
144 | ------------ | 144 | ------------ |
145 | Turn off DNOTIFY (directory change notification support) by default | 145 | Turn off DNOTIFY (directory change notification support) by default |
146 | (unless built with the experimental flag) to fix hang with KDE | 146 | (unless built with the experimental flag) to fix hang with KDE |
147 | file browser. Fix DNOTIFY flag mappings. Fix hang (in wait_event | 147 | file browser. Fix DNOTIFY flag mappings. Fix hang (in wait_event |
148 | waiting on an SMB response) in SendReceive when session dies but | 148 | waiting on an SMB response) in SendReceive when session dies but |
149 | reconnects quickly from another task. Add module init parms for | 149 | reconnects quickly from another task. Add module init parms for |
150 | minimum number of large and small network buffers in the buffer pools, | 150 | minimum number of large and small network buffers in the buffer pools, |
151 | and for the maximum number of simultaneous requests. | 151 | and for the maximum number of simultaneous requests. |
152 | 152 | ||
153 | Version 1.26 | 153 | Version 1.26 |
154 | ------------ | 154 | ------------ |
155 | Add setfacl support to allow setting of ACLs remotely to Samba 3.10 and later | 155 | Add setfacl support to allow setting of ACLs remotely to Samba 3.10 and later |
156 | and other POSIX CIFS compliant servers. Fix error mapping for getfacl | 156 | and other POSIX CIFS compliant servers. Fix error mapping for getfacl |
157 | to EOPNOTSUPP when server does not support posix acls on the wire. Fix | 157 | to EOPNOTSUPP when server does not support posix acls on the wire. Fix |
158 | improperly zeroed buffer in CIFS Unix extensions set times call. | 158 | improperly zeroed buffer in CIFS Unix extensions set times call. |
159 | 159 | ||
160 | Version 1.25 | 160 | Version 1.25 |
161 | ------------ | 161 | ------------ |
162 | Fix internationalization problem in cifs readdir with filenames that map to | 162 | Fix internationalization problem in cifs readdir with filenames that map to |
163 | longer UTF8 strings than the string on the wire was in Unicode. Add workaround | 163 | longer UTF-8 strings than the string on the wire was in Unicode. Add workaround |
164 | for readdir to netapp servers. Fix search rewind (seek into readdir to return | 164 | for readdir to netapp servers. Fix search rewind (seek into readdir to return |
165 | non-consecutive entries). Do not do readdir when server negotiates | 165 | non-consecutive entries). Do not do readdir when server negotiates |
166 | buffer size to small to fit filename. Add support for reading POSIX ACLs from | 166 | buffer size to small to fit filename. Add support for reading POSIX ACLs from |
167 | the server (add also acl and noacl mount options). | 167 | the server (add also acl and noacl mount options). |
168 | 168 | ||
169 | Version 1.24 | 169 | Version 1.24 |
170 | ------------ | 170 | ------------ |
171 | Optionally allow using server side inode numbers, rather than client generated | 171 | Optionally allow using server side inode numbers, rather than client generated |
172 | ones by specifying mount option "serverino" - this is required for some apps | 172 | ones by specifying mount option "serverino" - this is required for some apps |
173 | to work which double check hardlinked files and have persistent inode numbers. | 173 | to work which double check hardlinked files and have persistent inode numbers. |
174 | 174 | ||
175 | Version 1.23 | 175 | Version 1.23 |
176 | ------------ | 176 | ------------ |
177 | Multiple bigendian fixes. On little endian systems (for reconnect after | 177 | Multiple bigendian fixes. On little endian systems (for reconnect after |
178 | network failure) fix tcp session reconnect code so we do not try first | 178 | network failure) fix tcp session reconnect code so we do not try first |
179 | to reconnect on reverse of port 445. Treat reparse points (NTFS junctions) | 179 | to reconnect on reverse of port 445. Treat reparse points (NTFS junctions) |
180 | as directories rather than symlinks because we can do follow link on them. | 180 | as directories rather than symlinks because we can do follow link on them. |
181 | 181 | ||
182 | Version 1.22 | 182 | Version 1.22 |
183 | ------------ | 183 | ------------ |
184 | Add config option to enable XATTR (extended attribute) support, mapping | 184 | Add config option to enable XATTR (extended attribute) support, mapping |
185 | xattr names in the "user." namespace space to SMB/CIFS EAs. Lots of | 185 | xattr names in the "user." namespace space to SMB/CIFS EAs. Lots of |
186 | minor fixes pointed out by the Stanford SWAT checker (mostly missing | 186 | minor fixes pointed out by the Stanford SWAT checker (mostly missing |
187 | or out of order NULL pointer checks in little used error paths). | 187 | or out of order NULL pointer checks in little used error paths). |
188 | 188 | ||
189 | Version 1.21 | 189 | Version 1.21 |
190 | ------------ | 190 | ------------ |
191 | Add new mount parm to control whether mode check (generic_permission) is done | 191 | Add new mount parm to control whether mode check (generic_permission) is done |
192 | on the client. If Unix extensions are enabled and the uids on the client | 192 | on the client. If Unix extensions are enabled and the uids on the client |
193 | and server do not match, client permission checks are meaningless on | 193 | and server do not match, client permission checks are meaningless on |
194 | server uids that do not exist on the client (this does not affect the | 194 | server uids that do not exist on the client (this does not affect the |
195 | normal ACL check which occurs on the server). Fix default uid | 195 | normal ACL check which occurs on the server). Fix default uid |
196 | on mknod to match create and mkdir. Add optional mount parm to allow | 196 | on mknod to match create and mkdir. Add optional mount parm to allow |
197 | override of the default uid behavior (in which the server sets the uid | 197 | override of the default uid behavior (in which the server sets the uid |
198 | and gid of newly created files). Normally for network filesystem mounts | 198 | and gid of newly created files). Normally for network filesystem mounts |
199 | user want the server to set the uid/gid on newly created files (rather than | 199 | user want the server to set the uid/gid on newly created files (rather than |
200 | using uid of the client processes you would in a local filesystem). | 200 | using uid of the client processes you would in a local filesystem). |
201 | 201 | ||
202 | Version 1.20 | 202 | Version 1.20 |
203 | ------------ | 203 | ------------ |
204 | Make transaction counts more consistent. Merge /proc/fs/cifs/SimultaneousOps | 204 | Make transaction counts more consistent. Merge /proc/fs/cifs/SimultaneousOps |
205 | info into /proc/fs/cifs/DebugData. Fix oops in rare oops in readdir | 205 | info into /proc/fs/cifs/DebugData. Fix oops in rare oops in readdir |
206 | (in build_wildcard_path_from_dentry). Fix mknod to pass type field | 206 | (in build_wildcard_path_from_dentry). Fix mknod to pass type field |
207 | (block/char/fifo) properly. Remove spurious mount warning log entry when | 207 | (block/char/fifo) properly. Remove spurious mount warning log entry when |
208 | credentials passed as mount argument. Set major/minor device number in | 208 | credentials passed as mount argument. Set major/minor device number in |
209 | inode for block and char devices when unix extensions enabled. | 209 | inode for block and char devices when unix extensions enabled. |
210 | 210 | ||
211 | Version 1.19 | 211 | Version 1.19 |
212 | ------------ | 212 | ------------ |
213 | Fix /proc/fs/cifs/Stats and DebugData display to handle larger | 213 | Fix /proc/fs/cifs/Stats and DebugData display to handle larger |
214 | amounts of return data. Properly limit requests to MAX_REQ (50 | 214 | amounts of return data. Properly limit requests to MAX_REQ (50 |
215 | is the usual maximum active multiplex SMB/CIFS requests per server). | 215 | is the usual maximum active multiplex SMB/CIFS requests per server). |
216 | Do not kill cifsd (and thus hurt the other SMB session) when more than one | 216 | Do not kill cifsd (and thus hurt the other SMB session) when more than one |
217 | session to the same server (but with different userids) exists and one | 217 | session to the same server (but with different userids) exists and one |
218 | of the two user's smb sessions is being removed while leaving the other. | 218 | of the two user's smb sessions is being removed while leaving the other. |
219 | Do not loop reconnecting in cifsd demultiplex thread when admin | 219 | Do not loop reconnecting in cifsd demultiplex thread when admin |
220 | kills the thread without going through unmount. | 220 | kills the thread without going through unmount. |
221 | 221 | ||
222 | Version 1.18 | 222 | Version 1.18 |
223 | ------------ | 223 | ------------ |
224 | Do not rename hardlinked files (since that should be a noop). Flush | 224 | Do not rename hardlinked files (since that should be a noop). Flush |
225 | cached write behind data when reopening a file after session abend, | 225 | cached write behind data when reopening a file after session abend, |
226 | except when already in write. Grab per socket sem during reconnect | 226 | except when already in write. Grab per socket sem during reconnect |
227 | to avoid oops in sendmsg if overlapping with reconnect. Do not | 227 | to avoid oops in sendmsg if overlapping with reconnect. Do not |
228 | reset cached inode file size on readdir for files open for write on | 228 | reset cached inode file size on readdir for files open for write on |
229 | client. | 229 | client. |
230 | 230 | ||
231 | 231 | ||
232 | Version 1.17 | 232 | Version 1.17 |
233 | ------------ | 233 | ------------ |
234 | Update number of blocks in file so du command is happier (in Linux a fake | 234 | Update number of blocks in file so du command is happier (in Linux a fake |
235 | blocksize of 512 is required for calculating number of blocks in inode). | 235 | blocksize of 512 is required for calculating number of blocks in inode). |
236 | Fix prepare write of partial pages to read in data from server if possible. | 236 | Fix prepare write of partial pages to read in data from server if possible. |
237 | Fix race on tcpStatus field between unmount and reconnection code, causing | 237 | Fix race on tcpStatus field between unmount and reconnection code, causing |
238 | cifsd process sometimes to hang around forever. Improve out of memory | 238 | cifsd process sometimes to hang around forever. Improve out of memory |
239 | checks in cifs_filldir | 239 | checks in cifs_filldir |
240 | 240 | ||
241 | Version 1.16 | 241 | Version 1.16 |
242 | ------------ | 242 | ------------ |
243 | Fix incorrect file size in file handle based setattr on big endian hardware. | 243 | Fix incorrect file size in file handle based setattr on big endian hardware. |
244 | Fix oops in build_path_from_dentry when out of memory. Add checks for invalid | 244 | Fix oops in build_path_from_dentry when out of memory. Add checks for invalid |
245 | and closing file structs in writepage/partialpagewrite. Add statistics | 245 | and closing file structs in writepage/partialpagewrite. Add statistics |
246 | for each mounted share (new menuconfig option). Fix endianness problem in | 246 | for each mounted share (new menuconfig option). Fix endianness problem in |
247 | volume information displayed in /proc/fs/cifs/DebugData (only affects | 247 | volume information displayed in /proc/fs/cifs/DebugData (only affects |
248 | affects big endian architectures). Prevent renames while constructing | 248 | affects big endian architectures). Prevent renames while constructing |
249 | path names for open, mkdir and rmdir. | 249 | path names for open, mkdir and rmdir. |
250 | 250 | ||
251 | Version 1.15 | 251 | Version 1.15 |
252 | ------------ | 252 | ------------ |
253 | Change to mempools for alloc smb request buffers and multiplex structs | 253 | Change to mempools for alloc smb request buffers and multiplex structs |
254 | to better handle low memory problems (and potential deadlocks). | 254 | to better handle low memory problems (and potential deadlocks). |
255 | 255 | ||
256 | Version 1.14 | 256 | Version 1.14 |
257 | ------------ | 257 | ------------ |
258 | Fix incomplete listings of large directories on Samba servers when Unix | 258 | Fix incomplete listings of large directories on Samba servers when Unix |
259 | extensions enabled. Fix oops when smb_buffer can not be allocated. Fix | 259 | extensions enabled. Fix oops when smb_buffer can not be allocated. Fix |
260 | rename deadlock when writing out dirty pages at same time. | 260 | rename deadlock when writing out dirty pages at same time. |
261 | 261 | ||
262 | Version 1.13 | 262 | Version 1.13 |
263 | ------------ | 263 | ------------ |
264 | Fix open of files in which O_CREATE can cause the mode to change in | 264 | Fix open of files in which O_CREATE can cause the mode to change in |
265 | some cases. Fix case in which retry of write overlaps file close. | 265 | some cases. Fix case in which retry of write overlaps file close. |
266 | Fix PPC64 build error. Reduce excessive stack usage in smb password | 266 | Fix PPC64 build error. Reduce excessive stack usage in smb password |
267 | hashing. Fix overwrite of Linux user's view of file mode to Windows servers. | 267 | hashing. Fix overwrite of Linux user's view of file mode to Windows servers. |
268 | 268 | ||
269 | Version 1.12 | 269 | Version 1.12 |
270 | ------------ | 270 | ------------ |
271 | Fixes for large file copy, signal handling, socket retry, buffer | 271 | Fixes for large file copy, signal handling, socket retry, buffer |
272 | allocation and low memory situations. | 272 | allocation and low memory situations. |
273 | 273 | ||
274 | Version 1.11 | 274 | Version 1.11 |
275 | ------------ | 275 | ------------ |
276 | Better port 139 support to Windows servers (RFC1001/RFC1002 Session_Initialize) | 276 | Better port 139 support to Windows servers (RFC1001/RFC1002 Session_Initialize) |
277 | also now allowing support for specifying client netbiosname. NT4 support added. | 277 | also now allowing support for specifying client netbiosname. NT4 support added. |
278 | 278 | ||
279 | Version 1.10 | 279 | Version 1.10 |
280 | ------------ | 280 | ------------ |
281 | Fix reconnection (and certain failed mounts) to properly wake up the | 281 | Fix reconnection (and certain failed mounts) to properly wake up the |
282 | blocked users thread so it does not seem hung (in some cases was blocked | 282 | blocked users thread so it does not seem hung (in some cases was blocked |
283 | until the cifs receive timeout expired). Fix spurious error logging | 283 | until the cifs receive timeout expired). Fix spurious error logging |
284 | to kernel log when application with open network files killed. | 284 | to kernel log when application with open network files killed. |
285 | 285 | ||
286 | Version 1.09 | 286 | Version 1.09 |
287 | ------------ | 287 | ------------ |
288 | Fix /proc/fs module unload warning message (that could be logged | 288 | Fix /proc/fs module unload warning message (that could be logged |
289 | to the kernel log). Fix intermittent failure in connectathon | 289 | to the kernel log). Fix intermittent failure in connectathon |
290 | test7 (hardlink count not immediately refreshed in case in which | 290 | test7 (hardlink count not immediately refreshed in case in which |
291 | inode metadata can be incorrectly kept cached when time near zero) | 291 | inode metadata can be incorrectly kept cached when time near zero) |
292 | 292 | ||
293 | Version 1.08 | 293 | Version 1.08 |
294 | ------------ | 294 | ------------ |
295 | Allow file_mode and dir_mode (specified at mount time) to be enforced | 295 | Allow file_mode and dir_mode (specified at mount time) to be enforced |
296 | locally (the server already enforced its own ACLs too) for servers | 296 | locally (the server already enforced its own ACLs too) for servers |
297 | that do not report the correct mode (do not support the | 297 | that do not report the correct mode (do not support the |
298 | CIFS Unix Extensions). | 298 | CIFS Unix Extensions). |
299 | 299 | ||
300 | Version 1.07 | 300 | Version 1.07 |
301 | ------------ | 301 | ------------ |
302 | Fix some small memory leaks in some unmount error paths. Fix major leak | 302 | Fix some small memory leaks in some unmount error paths. Fix major leak |
303 | of cache pages in readpages causing multiple read oriented stress | 303 | of cache pages in readpages causing multiple read oriented stress |
304 | testcases (including fsx, and even large file copy) to fail over time. | 304 | testcases (including fsx, and even large file copy) to fail over time. |
305 | 305 | ||
306 | Version 1.06 | 306 | Version 1.06 |
307 | ------------ | 307 | ------------ |
308 | Send NTCreateX with ATTR_POSIX if Linux/Unix extensions negotiated with server. | 308 | Send NTCreateX with ATTR_POSIX if Linux/Unix extensions negotiated with server. |
309 | This allows files that differ only in case and improves performance of file | 309 | This allows files that differ only in case and improves performance of file |
310 | creation and file open to such servers. Fix semaphore conflict which causes | 310 | creation and file open to such servers. Fix semaphore conflict which causes |
311 | slow delete of open file to Samba (which unfortunately can cause an oplock | 311 | slow delete of open file to Samba (which unfortunately can cause an oplock |
312 | break to self while vfs_unlink held i_sem) which can hang for 20 seconds. | 312 | break to self while vfs_unlink held i_sem) which can hang for 20 seconds. |
313 | 313 | ||
314 | Version 1.05 | 314 | Version 1.05 |
315 | ------------ | 315 | ------------ |
316 | fixes to cifs_readpages for fsx test case | 316 | fixes to cifs_readpages for fsx test case |
317 | 317 | ||
318 | Version 1.04 | 318 | Version 1.04 |
319 | ------------ | 319 | ------------ |
320 | Fix caching data integrity bug when extending file size especially when no | 320 | Fix caching data integrity bug when extending file size especially when no |
321 | oplock on file. Fix spurious logging of valid already parsed mount options | 321 | oplock on file. Fix spurious logging of valid already parsed mount options |
322 | that are parsed outside of the cifs vfs such as nosuid. | 322 | that are parsed outside of the cifs vfs such as nosuid. |
323 | 323 | ||
324 | 324 | ||
325 | Version 1.03 | 325 | Version 1.03 |
326 | ------------ | 326 | ------------ |
327 | Connect to server when port number override not specified, and tcp port | 327 | Connect to server when port number override not specified, and tcp port |
328 | unitialized. Reset search to restart at correct file when kernel routine | 328 | unitialized. Reset search to restart at correct file when kernel routine |
329 | filldir returns error during large directory searches (readdir). | 329 | filldir returns error during large directory searches (readdir). |
330 | 330 | ||
331 | Version 1.02 | 331 | Version 1.02 |
332 | ------------ | 332 | ------------ |
333 | Fix caching problem when files opened by multiple clients in which | 333 | Fix caching problem when files opened by multiple clients in which |
334 | page cache could contain stale data, and write through did | 334 | page cache could contain stale data, and write through did |
335 | not occur often enough while file was still open when read ahead | 335 | not occur often enough while file was still open when read ahead |
336 | (read oplock) not allowed. Treat "sep=" when first mount option | 336 | (read oplock) not allowed. Treat "sep=" when first mount option |
337 | as an override of comma as the default separator between mount | 337 | as an override of comma as the default separator between mount |
338 | options. | 338 | options. |
339 | 339 | ||
340 | Version 1.01 | 340 | Version 1.01 |
341 | ------------ | 341 | ------------ |
342 | Allow passwords longer than 16 bytes. Allow null password string. | 342 | Allow passwords longer than 16 bytes. Allow null password string. |
343 | 343 | ||
344 | Version 1.00 | 344 | Version 1.00 |
345 | ------------ | 345 | ------------ |
346 | Gracefully clean up failed mounts when attempting to mount to servers such as | 346 | Gracefully clean up failed mounts when attempting to mount to servers such as |
347 | Windows 98 that terminate tcp sessions during protocol negotiation. Handle | 347 | Windows 98 that terminate tcp sessions during protocol negotiation. Handle |
348 | embedded commas in mount parsing of passwords. | 348 | embedded commas in mount parsing of passwords. |
349 | 349 | ||
350 | Version 0.99 | 350 | Version 0.99 |
351 | ------------ | 351 | ------------ |
352 | Invalidate local inode cached pages on oplock break and when last file | 352 | Invalidate local inode cached pages on oplock break and when last file |
353 | instance is closed so that the client does not continue using stale local | 353 | instance is closed so that the client does not continue using stale local |
354 | copy rather than later modified server copy of file. Do not reconnect | 354 | copy rather than later modified server copy of file. Do not reconnect |
355 | when server drops the tcp session prematurely before negotiate | 355 | when server drops the tcp session prematurely before negotiate |
356 | protocol response. Fix oops in reopen_file when dentry freed. Allow | 356 | protocol response. Fix oops in reopen_file when dentry freed. Allow |
357 | the support for CIFS Unix Extensions to be disabled via proc interface. | 357 | the support for CIFS Unix Extensions to be disabled via proc interface. |
358 | 358 | ||
359 | Version 0.98 | 359 | Version 0.98 |
360 | ------------ | 360 | ------------ |
361 | Fix hang in commit_write during reconnection of open files under heavy load. | 361 | Fix hang in commit_write during reconnection of open files under heavy load. |
362 | Fix unload_nls oops in a mount failure path. Serialize writes to same socket | 362 | Fix unload_nls oops in a mount failure path. Serialize writes to same socket |
363 | which also fixes any possible races when cifs signatures are enabled in SMBs | 363 | which also fixes any possible races when cifs signatures are enabled in SMBs |
364 | being sent out of signature sequence number order. | 364 | being sent out of signature sequence number order. |
365 | 365 | ||
366 | Version 0.97 | 366 | Version 0.97 |
367 | ------------ | 367 | ------------ |
368 | Fix byte range locking bug (endian problem) causing bad offset and | 368 | Fix byte range locking bug (endian problem) causing bad offset and |
369 | length. | 369 | length. |
370 | 370 | ||
371 | Version 0.96 | 371 | Version 0.96 |
372 | ------------ | 372 | ------------ |
373 | Fix oops (in send_sig) caused by CIFS unmount code trying to | 373 | Fix oops (in send_sig) caused by CIFS unmount code trying to |
374 | wake up the demultiplex thread after it had exited. Do not log | 374 | wake up the demultiplex thread after it had exited. Do not log |
375 | error on harmless oplock release of closed handle. | 375 | error on harmless oplock release of closed handle. |
376 | 376 | ||
377 | Version 0.95 | 377 | Version 0.95 |
378 | ------------ | 378 | ------------ |
379 | Fix unsafe global variable usage and password hash failure on gcc 3.3.1 | 379 | Fix unsafe global variable usage and password hash failure on gcc 3.3.1 |
380 | Fix problem reconnecting secondary mounts to same server after session | 380 | Fix problem reconnecting secondary mounts to same server after session |
381 | failure. Fix invalid dentry - race in mkdir when directory gets created | 381 | failure. Fix invalid dentry - race in mkdir when directory gets created |
382 | by another client between the lookup and mkdir. | 382 | by another client between the lookup and mkdir. |
383 | 383 | ||
384 | Version 0.94 | 384 | Version 0.94 |
385 | ------------ | 385 | ------------ |
386 | Fix to list processing in reopen_files. Fix reconnection when server hung | 386 | Fix to list processing in reopen_files. Fix reconnection when server hung |
387 | but tcpip session still alive. Set proper timeout on socket read. | 387 | but tcpip session still alive. Set proper timeout on socket read. |
388 | 388 | ||
389 | Version 0.93 | 389 | Version 0.93 |
390 | ------------ | 390 | ------------ |
391 | Add missing mount options including iocharset. SMP fixes in write and open. | 391 | Add missing mount options including iocharset. SMP fixes in write and open. |
392 | Fix errors in reconnecting after TCP session failure. Fix module unloading | 392 | Fix errors in reconnecting after TCP session failure. Fix module unloading |
393 | of default nls codepage | 393 | of default nls codepage |
394 | 394 | ||
395 | Version 0.92 | 395 | Version 0.92 |
396 | ------------ | 396 | ------------ |
397 | Active smb transactions should never go negative (fix double FreeXid). Fix | 397 | Active smb transactions should never go negative (fix double FreeXid). Fix |
398 | list processing in file routines. Check return code on kmalloc in open. | 398 | list processing in file routines. Check return code on kmalloc in open. |
399 | Fix spinlock usage for SMP. | 399 | Fix spinlock usage for SMP. |
400 | 400 | ||
401 | Version 0.91 | 401 | Version 0.91 |
402 | ------------ | 402 | ------------ |
403 | Fix oops in reopen_files when invalid dentry. drop dentry on server rename | 403 | Fix oops in reopen_files when invalid dentry. drop dentry on server rename |
404 | and on revalidate errors. Fix cases where pid is now tgid. Fix return code | 404 | and on revalidate errors. Fix cases where pid is now tgid. Fix return code |
405 | on create hard link when server does not support them. | 405 | on create hard link when server does not support them. |
406 | 406 | ||
407 | Version 0.90 | 407 | Version 0.90 |
408 | ------------ | 408 | ------------ |
409 | Fix scheduling while atomic error in getting inode info on newly created file. | 409 | Fix scheduling while atomic error in getting inode info on newly created file. |
410 | Fix truncate of existing files opened with O_CREAT but not O_TRUNC set. | 410 | Fix truncate of existing files opened with O_CREAT but not O_TRUNC set. |
411 | 411 | ||
412 | Version 0.89 | 412 | Version 0.89 |
413 | ------------ | 413 | ------------ |
414 | Fix oops on write to dead tcp session. Remove error log write for case when file open | 414 | Fix oops on write to dead tcp session. Remove error log write for case when file open |
415 | O_CREAT but not O_EXCL | 415 | O_CREAT but not O_EXCL |
416 | 416 | ||
417 | Version 0.88 | 417 | Version 0.88 |
418 | ------------ | 418 | ------------ |
419 | Fix non-POSIX behavior on rename of open file and delete of open file by taking | 419 | Fix non-POSIX behavior on rename of open file and delete of open file by taking |
420 | advantage of trans2 SetFileInfo rename facility if available on target server. | 420 | advantage of trans2 SetFileInfo rename facility if available on target server. |
421 | Retry on ENOSPC and EAGAIN socket errors. | 421 | Retry on ENOSPC and EAGAIN socket errors. |
422 | 422 | ||
423 | Version 0.87 | 423 | Version 0.87 |
424 | ------------ | 424 | ------------ |
425 | Fix oops on big endian readdir. Set blksize to be even power of two (2**blkbits) to fix | 425 | Fix oops on big endian readdir. Set blksize to be even power of two (2**blkbits) to fix |
426 | allocation size miscalculation. After oplock token lost do not read through | 426 | allocation size miscalculation. After oplock token lost do not read through |
427 | cache. | 427 | cache. |
428 | 428 | ||
429 | Version 0.86 | 429 | Version 0.86 |
430 | ------------ | 430 | ------------ |
431 | Fix oops on empty file readahead. Fix for file size handling for locally cached files. | 431 | Fix oops on empty file readahead. Fix for file size handling for locally cached files. |
432 | 432 | ||
433 | Version 0.85 | 433 | Version 0.85 |
434 | ------------ | 434 | ------------ |
435 | Fix oops in mkdir when server fails to return inode info. Fix oops in reopen_files | 435 | Fix oops in mkdir when server fails to return inode info. Fix oops in reopen_files |
436 | during auto reconnection to server after server recovered from failure. | 436 | during auto reconnection to server after server recovered from failure. |
437 | 437 | ||
438 | Version 0.84 | 438 | Version 0.84 |
439 | ------------ | 439 | ------------ |
440 | Finish support for Linux 2.5 open/create changes, which removes the | 440 | Finish support for Linux 2.5 open/create changes, which removes the |
441 | redundant NTCreate/QPathInfo/close that was sent during file create. | 441 | redundant NTCreate/QPathInfo/close that was sent during file create. |
442 | Enable oplock by default. Enable packet signing by default (needed to | 442 | Enable oplock by default. Enable packet signing by default (needed to |
443 | access many recent Windows servers) | 443 | access many recent Windows servers) |
444 | 444 | ||
445 | Version 0.83 | 445 | Version 0.83 |
446 | ------------ | 446 | ------------ |
447 | Fix oops when mounting to long server names caused by inverted parms to kmalloc. | 447 | Fix oops when mounting to long server names caused by inverted parms to kmalloc. |
448 | Fix MultiuserMount (/proc/fs/cifs configuration setting) so that when enabled | 448 | Fix MultiuserMount (/proc/fs/cifs configuration setting) so that when enabled |
449 | we will choose a cifs user session (smb uid) that better matches the local | 449 | we will choose a cifs user session (smb uid) that better matches the local |
450 | uid if a) the mount uid does not match the current uid and b) we have another | 450 | uid if a) the mount uid does not match the current uid and b) we have another |
451 | session to the same server (ip address) for a different mount which | 451 | session to the same server (ip address) for a different mount which |
452 | matches the current local uid. | 452 | matches the current local uid. |
453 | 453 | ||
454 | Version 0.82 | 454 | Version 0.82 |
455 | ------------ | 455 | ------------ |
456 | Add support for mknod of block or character devices. Fix oplock | 456 | Add support for mknod of block or character devices. Fix oplock |
457 | code (distributed caching) to properly send response to oplock | 457 | code (distributed caching) to properly send response to oplock |
458 | break from server. | 458 | break from server. |
459 | 459 | ||
460 | Version 0.81 | 460 | Version 0.81 |
461 | ------------ | 461 | ------------ |
462 | Finish up CIFS packet digital signing for the default | 462 | Finish up CIFS packet digital signing for the default |
463 | NTLM security case. This should help Windows 2003 | 463 | NTLM security case. This should help Windows 2003 |
464 | network interoperability since it is common for | 464 | network interoperability since it is common for |
465 | packet signing to be required now. Fix statfs (stat -f) | 465 | packet signing to be required now. Fix statfs (stat -f) |
466 | which recently started returning errors due to | 466 | which recently started returning errors due to |
467 | invalid value (-1 instead of 0) being set in the | 467 | invalid value (-1 instead of 0) being set in the |
468 | struct kstatfs f_ffiles field. | 468 | struct kstatfs f_ffiles field. |
469 | 469 | ||
470 | Version 0.80 | 470 | Version 0.80 |
471 | ----------- | 471 | ----------- |
472 | Fix oops on stopping oplock thread when removing cifs when | 472 | Fix oops on stopping oplock thread when removing cifs when |
473 | built as module. | 473 | built as module. |
474 | 474 | ||
475 | Version 0.79 | 475 | Version 0.79 |
476 | ------------ | 476 | ------------ |
477 | Fix mount options for ro (readonly), uid, gid and file and directory mode. | 477 | Fix mount options for ro (readonly), uid, gid and file and directory mode. |
478 | 478 | ||
479 | Version 0.78 | 479 | Version 0.78 |
480 | ------------ | 480 | ------------ |
481 | Fix errors displayed on failed mounts to be more understandable. | 481 | Fix errors displayed on failed mounts to be more understandable. |
482 | Fixed various incorrect or misleading smb to posix error code mappings. | 482 | Fixed various incorrect or misleading smb to posix error code mappings. |
483 | 483 | ||
484 | Version 0.77 | 484 | Version 0.77 |
485 | ------------ | 485 | ------------ |
486 | Fix display of NTFS DFS junctions to display as symlinks. | 486 | Fix display of NTFS DFS junctions to display as symlinks. |
487 | They are the network equivalent. Fix oops in | 487 | They are the network equivalent. Fix oops in |
488 | cifs_partialpagewrite caused by missing spinlock protection | 488 | cifs_partialpagewrite caused by missing spinlock protection |
489 | of openfile linked list. Allow writebehind caching errors to | 489 | of openfile linked list. Allow writebehind caching errors to |
490 | be returned to the application at file close. | 490 | be returned to the application at file close. |
491 | 491 | ||
492 | Version 0.76 | 492 | Version 0.76 |
493 | ------------ | 493 | ------------ |
494 | Clean up options displayed in /proc/mounts by show_options to | 494 | Clean up options displayed in /proc/mounts by show_options to |
495 | be more consistent with other filesystems. | 495 | be more consistent with other filesystems. |
496 | 496 | ||
497 | Version 0.75 | 497 | Version 0.75 |
498 | ------------ | 498 | ------------ |
499 | Fix delete of readonly file to Windows servers. Reflect | 499 | Fix delete of readonly file to Windows servers. Reflect |
500 | presence or absence of read only dos attribute in mode | 500 | presence or absence of read only dos attribute in mode |
501 | bits for servers that do not support CIFS Unix extensions. | 501 | bits for servers that do not support CIFS Unix extensions. |
502 | Fix shortened results on readdir of large directories to | 502 | Fix shortened results on readdir of large directories to |
503 | servers supporting CIFS Unix extensions (caused by | 503 | servers supporting CIFS Unix extensions (caused by |
504 | incorrect resume key). | 504 | incorrect resume key). |
505 | 505 | ||
506 | Version 0.74 | 506 | Version 0.74 |
507 | ------------ | 507 | ------------ |
508 | Fix truncate bug (set file size) that could cause hangs e.g. running fsx | 508 | Fix truncate bug (set file size) that could cause hangs e.g. running fsx |
509 | 509 | ||
510 | Version 0.73 | 510 | Version 0.73 |
511 | ------------ | 511 | ------------ |
512 | unload nls if mount fails. | 512 | unload nls if mount fails. |
513 | 513 | ||
514 | Version 0.72 | 514 | Version 0.72 |
515 | ------------ | 515 | ------------ |
516 | Add resume key support to search (readdir) code to workaround | 516 | Add resume key support to search (readdir) code to workaround |
517 | Windows bug. Add /proc/fs/cifs/LookupCacheEnable which | 517 | Windows bug. Add /proc/fs/cifs/LookupCacheEnable which |
518 | allows disabling caching of attribute information for | 518 | allows disabling caching of attribute information for |
519 | lookups. | 519 | lookups. |
520 | 520 | ||
521 | Version 0.71 | 521 | Version 0.71 |
522 | ------------ | 522 | ------------ |
523 | Add more oplock handling (distributed caching code). Remove | 523 | Add more oplock handling (distributed caching code). Remove |
524 | dead code. Remove excessive stack space utilization from | 524 | dead code. Remove excessive stack space utilization from |
525 | symlink routines. | 525 | symlink routines. |
526 | 526 | ||
527 | Version 0.70 | 527 | Version 0.70 |
528 | ------------ | 528 | ------------ |
529 | Fix oops in get dfs referral (triggered when null path sent in to | 529 | Fix oops in get dfs referral (triggered when null path sent in to |
530 | mount). Add support for overriding rsize at mount time. | 530 | mount). Add support for overriding rsize at mount time. |
531 | 531 | ||
532 | Version 0.69 | 532 | Version 0.69 |
533 | ------------ | 533 | ------------ |
534 | Fix buffer overrun in readdir which caused intermittent kernel oopses. | 534 | Fix buffer overrun in readdir which caused intermittent kernel oopses. |
535 | Fix writepage code to release kmap on write data. Allow "-ip=" new | 535 | Fix writepage code to release kmap on write data. Allow "-ip=" new |
536 | mount option to be passed in on parameter distinct from the first part | 536 | mount option to be passed in on parameter distinct from the first part |
537 | (server name portion of) the UNC name. Allow override of the | 537 | (server name portion of) the UNC name. Allow override of the |
538 | tcp port of the target server via new mount option "-port=" | 538 | tcp port of the target server via new mount option "-port=" |
539 | 539 | ||
540 | Version 0.68 | 540 | Version 0.68 |
541 | ------------ | 541 | ------------ |
542 | Fix search handle leak on rewind. Fix setuid and gid so that they are | 542 | Fix search handle leak on rewind. Fix setuid and gid so that they are |
543 | reflected in the local inode immediately. Cleanup of whitespace | 543 | reflected in the local inode immediately. Cleanup of whitespace |
544 | to make 2.4 and 2.5 versions more consistent. | 544 | to make 2.4 and 2.5 versions more consistent. |
545 | 545 | ||
546 | 546 | ||
547 | Version 0.67 | 547 | Version 0.67 |
548 | ------------ | 548 | ------------ |
549 | Fix signal sending so that captive thread (cifsd) exits on umount | 549 | Fix signal sending so that captive thread (cifsd) exits on umount |
550 | (which was causing the warning in kmem_cache_free of the request buffers | 550 | (which was causing the warning in kmem_cache_free of the request buffers |
551 | at rmmod time). This had broken as a sideeffect of the recent global | 551 | at rmmod time). This had broken as a sideeffect of the recent global |
552 | kernel change to daemonize. Fix memory leak in readdir code which | 552 | kernel change to daemonize. Fix memory leak in readdir code which |
553 | showed up in "ls -R" (and applications that did search rewinding). | 553 | showed up in "ls -R" (and applications that did search rewinding). |
554 | 554 | ||
555 | Version 0.66 | 555 | Version 0.66 |
556 | ------------ | 556 | ------------ |
557 | Reconnect tids and fids after session reconnection (still do not | 557 | Reconnect tids and fids after session reconnection (still do not |
558 | reconnect byte range locks though). Fix problem caching | 558 | reconnect byte range locks though). Fix problem caching |
559 | lookup information for directory inodes, improving performance, | 559 | lookup information for directory inodes, improving performance, |
560 | especially in deep directory trees. Fix various build warnings. | 560 | especially in deep directory trees. Fix various build warnings. |
561 | 561 | ||
562 | Version 0.65 | 562 | Version 0.65 |
563 | ------------ | 563 | ------------ |
564 | Finish fixes to commit write for caching/readahead consistency. fsx | 564 | Finish fixes to commit write for caching/readahead consistency. fsx |
565 | now works to Samba servers. Fix oops caused when readahead | 565 | now works to Samba servers. Fix oops caused when readahead |
566 | was interrupted by a signal. | 566 | was interrupted by a signal. |
567 | 567 | ||
568 | Version 0.64 | 568 | Version 0.64 |
569 | ------------ | 569 | ------------ |
570 | Fix data corruption (in partial page after truncate) that caused fsx to | 570 | Fix data corruption (in partial page after truncate) that caused fsx to |
571 | fail to Windows servers. Cleaned up some extraneous error logging in | 571 | fail to Windows servers. Cleaned up some extraneous error logging in |
572 | common error paths. Add generic sendfile support. | 572 | common error paths. Add generic sendfile support. |
573 | 573 | ||
574 | Version 0.63 | 574 | Version 0.63 |
575 | ------------ | 575 | ------------ |
576 | Fix memory leak in AllocMidQEntry. | 576 | Fix memory leak in AllocMidQEntry. |
577 | Finish reconnection logic, so connection with server can be dropped | 577 | Finish reconnection logic, so connection with server can be dropped |
578 | (or server rebooted) and the cifs client will reconnect. | 578 | (or server rebooted) and the cifs client will reconnect. |
579 | 579 | ||
580 | Version 0.62 | 580 | Version 0.62 |
581 | ------------ | 581 | ------------ |
582 | Fix temporary socket leak when bad userid or password specified | 582 | Fix temporary socket leak when bad userid or password specified |
583 | (or other SMBSessSetup failure). Increase maximum buffer size to slightly | 583 | (or other SMBSessSetup failure). Increase maximum buffer size to slightly |
584 | over 16K to allow negotiation of up to Samba and Windows server default read | 584 | over 16K to allow negotiation of up to Samba and Windows server default read |
585 | sizes. Add support for readpages | 585 | sizes. Add support for readpages |
586 | 586 | ||
587 | Version 0.61 | 587 | Version 0.61 |
588 | ------------ | 588 | ------------ |
589 | Fix oops when username not passed in on mount. Extensive fixes and improvements | 589 | Fix oops when username not passed in on mount. Extensive fixes and improvements |
590 | to error logging (strip redundant newlines, change debug macros to ensure newline | 590 | to error logging (strip redundant newlines, change debug macros to ensure newline |
591 | passed in and to be more consistent). Fix writepage wrong file handle problem, | 591 | passed in and to be more consistent). Fix writepage wrong file handle problem, |
592 | a readonly file handle could be incorrectly used to attempt to write out | 592 | a readonly file handle could be incorrectly used to attempt to write out |
593 | file updates through the page cache to multiply open files. This could cause | 593 | file updates through the page cache to multiply open files. This could cause |
594 | the iozone benchmark to fail on the fwrite test. Fix bug mounting two different | 594 | the iozone benchmark to fail on the fwrite test. Fix bug mounting two different |
595 | shares to the same Windows server when using different usernames | 595 | shares to the same Windows server when using different usernames |
596 | (doing this to Samba servers worked but Windows was rejecting it) - now it is | 596 | (doing this to Samba servers worked but Windows was rejecting it) - now it is |
597 | possible to use different userids when connecting to the same server from a | 597 | possible to use different userids when connecting to the same server from a |
598 | Linux client. Fix oops when treeDisconnect called during unmount on | 598 | Linux client. Fix oops when treeDisconnect called during unmount on |
599 | previously freed socket. | 599 | previously freed socket. |
600 | 600 | ||
601 | Version 0.60 | 601 | Version 0.60 |
602 | ------------ | 602 | ------------ |
603 | Fix oops in readpages caused by not setting address space operations in inode in | 603 | Fix oops in readpages caused by not setting address space operations in inode in |
604 | rare code path. | 604 | rare code path. |
605 | 605 | ||
606 | Version 0.59 | 606 | Version 0.59 |
607 | ------------ | 607 | ------------ |
608 | Includes support for deleting of open files and renaming over existing files (per POSIX | 608 | Includes support for deleting of open files and renaming over existing files (per POSIX |
609 | requirement). Add readlink support for Windows junction points (directory symlinks). | 609 | requirement). Add readlink support for Windows junction points (directory symlinks). |
610 | 610 | ||
611 | Version 0.58 | 611 | Version 0.58 |
612 | ------------ | 612 | ------------ |
613 | Changed read and write to go through pagecache. Added additional address space operations. | 613 | Changed read and write to go through pagecache. Added additional address space operations. |
614 | Memory mapped operations now working. | 614 | Memory mapped operations now working. |
615 | 615 | ||
616 | Version 0.57 | 616 | Version 0.57 |
617 | ------------ | 617 | ------------ |
618 | Added writepage code for additional memory mapping support. Fixed leak in xids causing | 618 | Added writepage code for additional memory mapping support. Fixed leak in xids causing |
619 | the simultaneous operations counter (/proc/fs/cifs/SimultaneousOps) to increase on | 619 | the simultaneous operations counter (/proc/fs/cifs/SimultaneousOps) to increase on |
620 | every stat call. Additional formatting cleanup. | 620 | every stat call. Additional formatting cleanup. |
621 | 621 | ||
622 | Version 0.56 | 622 | Version 0.56 |
623 | ------------ | 623 | ------------ |
624 | Fix bigendian bug in order of time conversion. Merge 2.5 to 2.4 version. Formatting cleanup. | 624 | Fix bigendian bug in order of time conversion. Merge 2.5 to 2.4 version. Formatting cleanup. |
625 | 625 | ||
626 | Version 0.55 | 626 | Version 0.55 |
627 | ------------ | 627 | ------------ |
628 | Fixes from Zwane Mwaikambo for adding missing return code checking in a few places. | 628 | Fixes from Zwane Mwaikambo for adding missing return code checking in a few places. |
629 | Also included a modified version of his fix to protect global list manipulation of | 629 | Also included a modified version of his fix to protect global list manipulation of |
630 | the smb session and tree connection and mid related global variables. | 630 | the smb session and tree connection and mid related global variables. |
631 | 631 | ||
632 | Version 0.54 | 632 | Version 0.54 |
633 | ------------ | 633 | ------------ |
634 | Fix problem with captive thread hanging around at unmount time. Adjust to 2.5.42-pre | 634 | Fix problem with captive thread hanging around at unmount time. Adjust to 2.5.42-pre |
635 | changes to superblock layout. Remove wasteful allocation of smb buffers (now the send | 635 | changes to superblock layout. Remove wasteful allocation of smb buffers (now the send |
636 | buffer is reused for responses). Add more oplock handling. Additional minor cleanup. | 636 | buffer is reused for responses). Add more oplock handling. Additional minor cleanup. |
637 | 637 | ||
638 | Version 0.53 | 638 | Version 0.53 |
639 | ------------ | 639 | ------------ |
640 | More stylistic updates to better match kernel style. Add additional statistics | 640 | More stylistic updates to better match kernel style. Add additional statistics |
641 | for filesystem which can be viewed via /proc/fs/cifs. Add more pieces of NTLMv2 | 641 | for filesystem which can be viewed via /proc/fs/cifs. Add more pieces of NTLMv2 |
642 | and CIFS Packet Signing enablement. | 642 | and CIFS Packet Signing enablement. |
643 | 643 | ||
644 | Version 0.52 | 644 | Version 0.52 |
645 | ------------ | 645 | ------------ |
646 | Replace call to sleep_on with safer wait_on_event. | 646 | Replace call to sleep_on with safer wait_on_event. |
647 | Make stylistic changes to better match kernel style recommendations. | 647 | Make stylistic changes to better match kernel style recommendations. |
648 | Remove most typedef usage (except for the PDUs themselves). | 648 | Remove most typedef usage (except for the PDUs themselves). |
649 | 649 | ||
650 | Version 0.51 | 650 | Version 0.51 |
651 | ------------ | 651 | ------------ |
652 | Update mount so the -unc mount option is no longer required (the ip address can be specified | 652 | Update mount so the -unc mount option is no longer required (the ip address can be specified |
653 | in a UNC style device name. Implementation of readpage/writepage started. | 653 | in a UNC style device name. Implementation of readpage/writepage started. |
654 | 654 | ||
655 | Version 0.50 | 655 | Version 0.50 |
656 | ------------ | 656 | ------------ |
657 | Fix intermittent problem with incorrect smb header checking on badly | 657 | Fix intermittent problem with incorrect smb header checking on badly |
658 | fragmented tcp responses | 658 | fragmented tcp responses |
659 | 659 | ||
660 | Version 0.49 | 660 | Version 0.49 |
661 | ------------ | 661 | ------------ |
662 | Fixes to setting of allocation size and file size. | 662 | Fixes to setting of allocation size and file size. |
663 | 663 | ||
664 | Version 0.48 | 664 | Version 0.48 |
665 | ------------ | 665 | ------------ |
666 | Various 2.5.38 fixes. Now works on 2.5.38 | 666 | Various 2.5.38 fixes. Now works on 2.5.38 |
667 | 667 | ||
668 | Version 0.47 | 668 | Version 0.47 |
669 | ------------ | 669 | ------------ |
670 | Prepare for 2.5 kernel merge. Remove ifdefs. | 670 | Prepare for 2.5 kernel merge. Remove ifdefs. |
671 | 671 | ||
672 | Version 0.46 | 672 | Version 0.46 |
673 | ------------ | 673 | ------------ |
674 | Socket buffer management fixes. Fix dual free. | 674 | Socket buffer management fixes. Fix dual free. |
675 | 675 | ||
676 | Version 0.45 | 676 | Version 0.45 |
677 | ------------ | 677 | ------------ |
678 | Various big endian fixes for hardlinks and symlinks and also for dfs. | 678 | Various big endian fixes for hardlinks and symlinks and also for dfs. |
679 | 679 | ||
680 | Version 0.44 | 680 | Version 0.44 |
681 | ------------ | 681 | ------------ |
682 | Various big endian fixes for servers with Unix extensions such as Samba | 682 | Various big endian fixes for servers with Unix extensions such as Samba |
683 | 683 | ||
684 | Version 0.43 | 684 | Version 0.43 |
685 | ------------ | 685 | ------------ |
686 | Various FindNext fixes for incorrect filenames on large directory searches on big endian | 686 | Various FindNext fixes for incorrect filenames on large directory searches on big endian |
687 | clients. basic posix file i/o tests now work on big endian machines, not just le | 687 | clients. basic posix file i/o tests now work on big endian machines, not just le |
688 | 688 | ||
689 | Version 0.42 | 689 | Version 0.42 |
690 | ------------ | 690 | ------------ |
691 | SessionSetup and NegotiateProtocol now work from Big Endian machines. | 691 | SessionSetup and NegotiateProtocol now work from Big Endian machines. |
692 | Various Big Endian fixes found during testing on the Linux on 390. Various fixes for compatibility with older | 692 | Various Big Endian fixes found during testing on the Linux on 390. Various fixes for compatibility with older |
693 | versions of 2.4 kernel (now builds and works again on kernels at least as early as 2.4.7). | 693 | versions of 2.4 kernel (now builds and works again on kernels at least as early as 2.4.7). |
694 | 694 | ||
695 | Version 0.41 | 695 | Version 0.41 |
696 | ------------ | 696 | ------------ |
697 | Various minor fixes for Connectathon Posix "basic" file i/o test suite. Directory caching fixed so hardlinked | 697 | Various minor fixes for Connectathon Posix "basic" file i/o test suite. Directory caching fixed so hardlinked |
698 | files now return the correct number of links on fstat as they are repeatedly linked and unlinked. | 698 | files now return the correct number of links on fstat as they are repeatedly linked and unlinked. |
699 | 699 | ||
700 | Version 0.40 | 700 | Version 0.40 |
701 | ------------ | 701 | ------------ |
702 | Implemented "Raw" (i.e. not encapsulated in SPNEGO) NTLMSSP (i.e. the Security Provider Interface used to negotiate | 702 | Implemented "Raw" (i.e. not encapsulated in SPNEGO) NTLMSSP (i.e. the Security Provider Interface used to negotiate |
703 | session advanced session authentication). Raw NTLMSSP is preferred by Windows 2000 Professional and Windows XP. | 703 | session advanced session authentication). Raw NTLMSSP is preferred by Windows 2000 Professional and Windows XP. |
704 | Began implementing support for SPNEGO encapsulation of NTLMSSP based session authentication blobs | 704 | Began implementing support for SPNEGO encapsulation of NTLMSSP based session authentication blobs |
705 | (which is the mechanism preferred by Windows 2000 server in the absence of Kerberos). | 705 | (which is the mechanism preferred by Windows 2000 server in the absence of Kerberos). |
706 | 706 | ||
707 | Version 0.38 | 707 | Version 0.38 |
708 | ------------ | 708 | ------------ |
709 | Introduced optional mount helper utility mount.cifs and made coreq changes to cifs vfs to enable | 709 | Introduced optional mount helper utility mount.cifs and made coreq changes to cifs vfs to enable |
710 | it. Fixed a few bugs in the DFS code (e.g. bcc two bytes too short and incorrect uid in PDU). | 710 | it. Fixed a few bugs in the DFS code (e.g. bcc two bytes too short and incorrect uid in PDU). |
711 | 711 | ||
712 | Version 0.37 | 712 | Version 0.37 |
713 | ------------ | 713 | ------------ |
714 | Rewrote much of connection and mount/unmount logic to handle bugs with | 714 | Rewrote much of connection and mount/unmount logic to handle bugs with |
715 | multiple uses to same share, multiple users to same server etc. | 715 | multiple uses to same share, multiple users to same server etc. |
716 | 716 | ||
717 | Version 0.36 | 717 | Version 0.36 |
718 | ------------ | 718 | ------------ |
719 | Fixed major problem with dentry corruption (missing call to dput) | 719 | Fixed major problem with dentry corruption (missing call to dput) |
720 | 720 | ||
721 | Version 0.35 | 721 | Version 0.35 |
722 | ------------ | 722 | ------------ |
723 | Rewrite of readdir code to fix bug. Various fixes for bigendian machines. | 723 | Rewrite of readdir code to fix bug. Various fixes for bigendian machines. |
724 | Begin adding oplock support. Multiusermount and oplockEnabled flags added to /proc/fs/cifs | 724 | Begin adding oplock support. Multiusermount and oplockEnabled flags added to /proc/fs/cifs |
725 | although corresponding function not fully implemented in the vfs yet | 725 | although corresponding function not fully implemented in the vfs yet |
726 | 726 | ||
727 | Version 0.34 | 727 | Version 0.34 |
728 | ------------ | 728 | ------------ |
729 | Fixed dentry caching bug, misc. cleanup | 729 | Fixed dentry caching bug, misc. cleanup |
730 | 730 | ||
731 | Version 0.33 | 731 | Version 0.33 |
732 | ------------ | 732 | ------------ |
733 | Fixed 2.5 support to handle build and configure changes as well as misc. 2.5 changes. Now can build | 733 | Fixed 2.5 support to handle build and configure changes as well as misc. 2.5 changes. Now can build |
734 | on current 2.5 beta version (2.5.24) of the Linux kernel as well as on 2.4 Linux kernels. | 734 | on current 2.5 beta version (2.5.24) of the Linux kernel as well as on 2.4 Linux kernels. |
735 | Support for STATUS codes (newer 32 bit NT error codes) added. DFS support begun to be added. | 735 | Support for STATUS codes (newer 32 bit NT error codes) added. DFS support begun to be added. |
736 | 736 | ||
737 | Version 0.32 | 737 | Version 0.32 |
738 | ------------ | 738 | ------------ |
739 | Unix extensions (symlink, readlink, hardlink, chmod and some chgrp and chown) implemented | 739 | Unix extensions (symlink, readlink, hardlink, chmod and some chgrp and chown) implemented |
740 | and tested against Samba 2.2.5 | 740 | and tested against Samba 2.2.5 |
741 | 741 | ||
742 | 742 | ||
743 | Version 0.31 | 743 | Version 0.31 |
744 | ------------ | 744 | ------------ |
745 | 1) Fixed lockrange to be correct (it was one byte too short) | 745 | 1) Fixed lockrange to be correct (it was one byte too short) |
746 | 746 | ||
747 | 2) Fixed GETLK (i.e. the fcntl call to test a range of bytes in a file to see if locked) to correctly | 747 | 2) Fixed GETLK (i.e. the fcntl call to test a range of bytes in a file to see if locked) to correctly |
748 | show range as locked when there is a conflict with an existing lock. | 748 | show range as locked when there is a conflict with an existing lock. |
749 | 749 | ||
750 | 3) default file perms are now 2767 (indicating support for mandatory locks) instead of 777 for directories | 750 | 3) default file perms are now 2767 (indicating support for mandatory locks) instead of 777 for directories |
751 | in most cases. Eventually will offer optional ability to query server for the correct perms. | 751 | in most cases. Eventually will offer optional ability to query server for the correct perms. |
752 | 752 | ||
753 | 3) Fixed eventual trap when mounting twice to different shares on the same server when the first succeeded | 753 | 3) Fixed eventual trap when mounting twice to different shares on the same server when the first succeeded |
754 | but the second one was invalid and failed (the second one was incorrectly disconnecting the tcp and smb | 754 | but the second one was invalid and failed (the second one was incorrectly disconnecting the tcp and smb |
755 | session) | 755 | session) |
756 | 756 | ||
757 | 4) Fixed error logging of valid mount options | 757 | 4) Fixed error logging of valid mount options |
758 | 758 | ||
759 | 5) Removed logging of password field. | 759 | 5) Removed logging of password field. |
760 | 760 | ||
761 | 6) Moved negotiate, treeDisconnect and uloggoffX (only tConx and SessSetup remain in connect.c) to cifssmb.c | 761 | 6) Moved negotiate, treeDisconnect and uloggoffX (only tConx and SessSetup remain in connect.c) to cifssmb.c |
762 | and cleaned them up and made them more consistent with other cifs functions. | 762 | and cleaned them up and made them more consistent with other cifs functions. |
763 | 763 | ||
764 | 7) Server support for Unix extensions is now fully detected and FindFirst is implemented both ways | 764 | 7) Server support for Unix extensions is now fully detected and FindFirst is implemented both ways |
765 | (with or without Unix extensions) but FindNext and QueryPathInfo with the Unix extensions are not completed, | 765 | (with or without Unix extensions) but FindNext and QueryPathInfo with the Unix extensions are not completed, |
766 | nor is the symlink support using the Unix extensions | 766 | nor is the symlink support using the Unix extensions |
767 | 767 | ||
768 | 8) Started adding the readlink and follow_link code | 768 | 8) Started adding the readlink and follow_link code |
769 | 769 | ||
770 | Version 0.3 | 770 | Version 0.3 |
771 | ----------- | 771 | ----------- |
772 | Initial drop | 772 | Initial drop |
773 | 773 | ||
774 | 774 |
fs/fat/dir.c
1 | /* | 1 | /* |
2 | * linux/fs/fat/dir.c | 2 | * linux/fs/fat/dir.c |
3 | * | 3 | * |
4 | * directory handling functions for fat-based filesystems | 4 | * directory handling functions for fat-based filesystems |
5 | * | 5 | * |
6 | * Written 1992,1993 by Werner Almesberger | 6 | * Written 1992,1993 by Werner Almesberger |
7 | * | 7 | * |
8 | * Hidden files 1995 by Albert Cahalan <albert@ccs.neu.edu> <adc@coe.neu.edu> | 8 | * Hidden files 1995 by Albert Cahalan <albert@ccs.neu.edu> <adc@coe.neu.edu> |
9 | * | 9 | * |
10 | * VFAT extensions by Gordon Chaffee <chaffee@plateau.cs.berkeley.edu> | 10 | * VFAT extensions by Gordon Chaffee <chaffee@plateau.cs.berkeley.edu> |
11 | * Merged with msdos fs by Henrik Storner <storner@osiris.ping.dk> | 11 | * Merged with msdos fs by Henrik Storner <storner@osiris.ping.dk> |
12 | * Rewritten for constant inumbers. Plugged buffer overrun in readdir(). AV | 12 | * Rewritten for constant inumbers. Plugged buffer overrun in readdir(). AV |
13 | * Short name translation 1999, 2001 by Wolfram Pienkoss <wp@bszh.de> | 13 | * Short name translation 1999, 2001 by Wolfram Pienkoss <wp@bszh.de> |
14 | */ | 14 | */ |
15 | 15 | ||
16 | #include <linux/module.h> | 16 | #include <linux/module.h> |
17 | #include <linux/slab.h> | 17 | #include <linux/slab.h> |
18 | #include <linux/time.h> | 18 | #include <linux/time.h> |
19 | #include <linux/msdos_fs.h> | 19 | #include <linux/msdos_fs.h> |
20 | #include <linux/dirent.h> | 20 | #include <linux/dirent.h> |
21 | #include <linux/smp_lock.h> | 21 | #include <linux/smp_lock.h> |
22 | #include <linux/buffer_head.h> | 22 | #include <linux/buffer_head.h> |
23 | #include <asm/uaccess.h> | 23 | #include <asm/uaccess.h> |
24 | 24 | ||
25 | static inline loff_t fat_make_i_pos(struct super_block *sb, | 25 | static inline loff_t fat_make_i_pos(struct super_block *sb, |
26 | struct buffer_head *bh, | 26 | struct buffer_head *bh, |
27 | struct msdos_dir_entry *de) | 27 | struct msdos_dir_entry *de) |
28 | { | 28 | { |
29 | return ((loff_t)bh->b_blocknr << MSDOS_SB(sb)->dir_per_block_bits) | 29 | return ((loff_t)bh->b_blocknr << MSDOS_SB(sb)->dir_per_block_bits) |
30 | | (de - (struct msdos_dir_entry *)bh->b_data); | 30 | | (de - (struct msdos_dir_entry *)bh->b_data); |
31 | } | 31 | } |
32 | 32 | ||
33 | static inline void fat_dir_readahead(struct inode *dir, sector_t iblock, | 33 | static inline void fat_dir_readahead(struct inode *dir, sector_t iblock, |
34 | sector_t phys) | 34 | sector_t phys) |
35 | { | 35 | { |
36 | struct super_block *sb = dir->i_sb; | 36 | struct super_block *sb = dir->i_sb; |
37 | struct msdos_sb_info *sbi = MSDOS_SB(sb); | 37 | struct msdos_sb_info *sbi = MSDOS_SB(sb); |
38 | struct buffer_head *bh; | 38 | struct buffer_head *bh; |
39 | int sec; | 39 | int sec; |
40 | 40 | ||
41 | /* This is not a first sector of cluster, or sec_per_clus == 1 */ | 41 | /* This is not a first sector of cluster, or sec_per_clus == 1 */ |
42 | if ((iblock & (sbi->sec_per_clus - 1)) || sbi->sec_per_clus == 1) | 42 | if ((iblock & (sbi->sec_per_clus - 1)) || sbi->sec_per_clus == 1) |
43 | return; | 43 | return; |
44 | /* root dir of FAT12/FAT16 */ | 44 | /* root dir of FAT12/FAT16 */ |
45 | if ((sbi->fat_bits != 32) && (dir->i_ino == MSDOS_ROOT_INO)) | 45 | if ((sbi->fat_bits != 32) && (dir->i_ino == MSDOS_ROOT_INO)) |
46 | return; | 46 | return; |
47 | 47 | ||
48 | bh = sb_find_get_block(sb, phys); | 48 | bh = sb_find_get_block(sb, phys); |
49 | if (bh == NULL || !buffer_uptodate(bh)) { | 49 | if (bh == NULL || !buffer_uptodate(bh)) { |
50 | for (sec = 0; sec < sbi->sec_per_clus; sec++) | 50 | for (sec = 0; sec < sbi->sec_per_clus; sec++) |
51 | sb_breadahead(sb, phys + sec); | 51 | sb_breadahead(sb, phys + sec); |
52 | } | 52 | } |
53 | brelse(bh); | 53 | brelse(bh); |
54 | } | 54 | } |
55 | 55 | ||
56 | /* Returns the inode number of the directory entry at offset pos. If bh is | 56 | /* Returns the inode number of the directory entry at offset pos. If bh is |
57 | non-NULL, it is brelse'd before. Pos is incremented. The buffer header is | 57 | non-NULL, it is brelse'd before. Pos is incremented. The buffer header is |
58 | returned in bh. | 58 | returned in bh. |
59 | AV. Most often we do it item-by-item. Makes sense to optimize. | 59 | AV. Most often we do it item-by-item. Makes sense to optimize. |
60 | AV. OK, there we go: if both bh and de are non-NULL we assume that we just | 60 | AV. OK, there we go: if both bh and de are non-NULL we assume that we just |
61 | AV. want the next entry (took one explicit de=NULL in vfat/namei.c). | 61 | AV. want the next entry (took one explicit de=NULL in vfat/namei.c). |
62 | AV. It's done in fat_get_entry() (inlined), here the slow case lives. | 62 | AV. It's done in fat_get_entry() (inlined), here the slow case lives. |
63 | AV. Additionally, when we return -1 (i.e. reached the end of directory) | 63 | AV. Additionally, when we return -1 (i.e. reached the end of directory) |
64 | AV. we make bh NULL. | 64 | AV. we make bh NULL. |
65 | */ | 65 | */ |
66 | static int fat__get_entry(struct inode *dir, loff_t *pos, | 66 | static int fat__get_entry(struct inode *dir, loff_t *pos, |
67 | struct buffer_head **bh, struct msdos_dir_entry **de) | 67 | struct buffer_head **bh, struct msdos_dir_entry **de) |
68 | { | 68 | { |
69 | struct super_block *sb = dir->i_sb; | 69 | struct super_block *sb = dir->i_sb; |
70 | sector_t phys, iblock; | 70 | sector_t phys, iblock; |
71 | unsigned long mapped_blocks; | 71 | unsigned long mapped_blocks; |
72 | int err, offset; | 72 | int err, offset; |
73 | 73 | ||
74 | next: | 74 | next: |
75 | if (*bh) | 75 | if (*bh) |
76 | brelse(*bh); | 76 | brelse(*bh); |
77 | 77 | ||
78 | *bh = NULL; | 78 | *bh = NULL; |
79 | iblock = *pos >> sb->s_blocksize_bits; | 79 | iblock = *pos >> sb->s_blocksize_bits; |
80 | err = fat_bmap(dir, iblock, &phys, &mapped_blocks); | 80 | err = fat_bmap(dir, iblock, &phys, &mapped_blocks); |
81 | if (err || !phys) | 81 | if (err || !phys) |
82 | return -1; /* beyond EOF or error */ | 82 | return -1; /* beyond EOF or error */ |
83 | 83 | ||
84 | fat_dir_readahead(dir, iblock, phys); | 84 | fat_dir_readahead(dir, iblock, phys); |
85 | 85 | ||
86 | *bh = sb_bread(sb, phys); | 86 | *bh = sb_bread(sb, phys); |
87 | if (*bh == NULL) { | 87 | if (*bh == NULL) { |
88 | printk(KERN_ERR "FAT: Directory bread(block %llu) failed\n", | 88 | printk(KERN_ERR "FAT: Directory bread(block %llu) failed\n", |
89 | (unsigned long long)phys); | 89 | (unsigned long long)phys); |
90 | /* skip this block */ | 90 | /* skip this block */ |
91 | *pos = (iblock + 1) << sb->s_blocksize_bits; | 91 | *pos = (iblock + 1) << sb->s_blocksize_bits; |
92 | goto next; | 92 | goto next; |
93 | } | 93 | } |
94 | 94 | ||
95 | offset = *pos & (sb->s_blocksize - 1); | 95 | offset = *pos & (sb->s_blocksize - 1); |
96 | *pos += sizeof(struct msdos_dir_entry); | 96 | *pos += sizeof(struct msdos_dir_entry); |
97 | *de = (struct msdos_dir_entry *)((*bh)->b_data + offset); | 97 | *de = (struct msdos_dir_entry *)((*bh)->b_data + offset); |
98 | 98 | ||
99 | return 0; | 99 | return 0; |
100 | } | 100 | } |
101 | 101 | ||
102 | static inline int fat_get_entry(struct inode *dir, loff_t *pos, | 102 | static inline int fat_get_entry(struct inode *dir, loff_t *pos, |
103 | struct buffer_head **bh, | 103 | struct buffer_head **bh, |
104 | struct msdos_dir_entry **de) | 104 | struct msdos_dir_entry **de) |
105 | { | 105 | { |
106 | /* Fast stuff first */ | 106 | /* Fast stuff first */ |
107 | if (*bh && *de && | 107 | if (*bh && *de && |
108 | (*de - (struct msdos_dir_entry *)(*bh)->b_data) < MSDOS_SB(dir->i_sb)->dir_per_block - 1) { | 108 | (*de - (struct msdos_dir_entry *)(*bh)->b_data) < MSDOS_SB(dir->i_sb)->dir_per_block - 1) { |
109 | *pos += sizeof(struct msdos_dir_entry); | 109 | *pos += sizeof(struct msdos_dir_entry); |
110 | (*de)++; | 110 | (*de)++; |
111 | return 0; | 111 | return 0; |
112 | } | 112 | } |
113 | return fat__get_entry(dir, pos, bh, de); | 113 | return fat__get_entry(dir, pos, bh, de); |
114 | } | 114 | } |
115 | 115 | ||
116 | /* | 116 | /* |
117 | * Convert Unicode 16 to UTF8, translated Unicode, or ASCII. | 117 | * Convert Unicode 16 to UTF-8, translated Unicode, or ASCII. |
118 | * If uni_xlate is enabled and we can't get a 1:1 conversion, use a | 118 | * If uni_xlate is enabled and we can't get a 1:1 conversion, use a |
119 | * colon as an escape character since it is normally invalid on the vfat | 119 | * colon as an escape character since it is normally invalid on the vfat |
120 | * filesystem. The following four characters are the hexadecimal digits | 120 | * filesystem. The following four characters are the hexadecimal digits |
121 | * of Unicode value. This lets us do a full dump and restore of Unicode | 121 | * of Unicode value. This lets us do a full dump and restore of Unicode |
122 | * filenames. We could get into some trouble with long Unicode names, | 122 | * filenames. We could get into some trouble with long Unicode names, |
123 | * but ignore that right now. | 123 | * but ignore that right now. |
124 | * Ahem... Stack smashing in ring 0 isn't fun. Fixed. | 124 | * Ahem... Stack smashing in ring 0 isn't fun. Fixed. |
125 | */ | 125 | */ |
126 | static int uni16_to_x8(unsigned char *ascii, wchar_t *uni, int uni_xlate, | 126 | static int uni16_to_x8(unsigned char *ascii, wchar_t *uni, int uni_xlate, |
127 | struct nls_table *nls) | 127 | struct nls_table *nls) |
128 | { | 128 | { |
129 | wchar_t *ip, ec; | 129 | wchar_t *ip, ec; |
130 | unsigned char *op, nc; | 130 | unsigned char *op, nc; |
131 | int charlen; | 131 | int charlen; |
132 | int k; | 132 | int k; |
133 | 133 | ||
134 | ip = uni; | 134 | ip = uni; |
135 | op = ascii; | 135 | op = ascii; |
136 | 136 | ||
137 | while (*ip) { | 137 | while (*ip) { |
138 | ec = *ip++; | 138 | ec = *ip++; |
139 | if ( (charlen = nls->uni2char(ec, op, NLS_MAX_CHARSET_SIZE)) > 0) { | 139 | if ( (charlen = nls->uni2char(ec, op, NLS_MAX_CHARSET_SIZE)) > 0) { |
140 | op += charlen; | 140 | op += charlen; |
141 | } else { | 141 | } else { |
142 | if (uni_xlate == 1) { | 142 | if (uni_xlate == 1) { |
143 | *op = ':'; | 143 | *op = ':'; |
144 | for (k = 4; k > 0; k--) { | 144 | for (k = 4; k > 0; k--) { |
145 | nc = ec & 0xF; | 145 | nc = ec & 0xF; |
146 | op[k] = nc > 9 ? nc + ('a' - 10) | 146 | op[k] = nc > 9 ? nc + ('a' - 10) |
147 | : nc + '0'; | 147 | : nc + '0'; |
148 | ec >>= 4; | 148 | ec >>= 4; |
149 | } | 149 | } |
150 | op += 5; | 150 | op += 5; |
151 | } else { | 151 | } else { |
152 | *op++ = '?'; | 152 | *op++ = '?'; |
153 | } | 153 | } |
154 | } | 154 | } |
155 | /* We have some slack there, so it's OK */ | 155 | /* We have some slack there, so it's OK */ |
156 | if (op>ascii+256) { | 156 | if (op>ascii+256) { |
157 | op = ascii + 256; | 157 | op = ascii + 256; |
158 | break; | 158 | break; |
159 | } | 159 | } |
160 | } | 160 | } |
161 | *op = 0; | 161 | *op = 0; |
162 | return (op - ascii); | 162 | return (op - ascii); |
163 | } | 163 | } |
164 | 164 | ||
165 | static inline int | 165 | static inline int |
166 | fat_short2uni(struct nls_table *t, unsigned char *c, int clen, wchar_t *uni) | 166 | fat_short2uni(struct nls_table *t, unsigned char *c, int clen, wchar_t *uni) |
167 | { | 167 | { |
168 | int charlen; | 168 | int charlen; |
169 | 169 | ||
170 | charlen = t->char2uni(c, clen, uni); | 170 | charlen = t->char2uni(c, clen, uni); |
171 | if (charlen < 0) { | 171 | if (charlen < 0) { |
172 | *uni = 0x003f; /* a question mark */ | 172 | *uni = 0x003f; /* a question mark */ |
173 | charlen = 1; | 173 | charlen = 1; |
174 | } | 174 | } |
175 | return charlen; | 175 | return charlen; |
176 | } | 176 | } |
177 | 177 | ||
178 | static inline int | 178 | static inline int |
179 | fat_short2lower_uni(struct nls_table *t, unsigned char *c, int clen, wchar_t *uni) | 179 | fat_short2lower_uni(struct nls_table *t, unsigned char *c, int clen, wchar_t *uni) |
180 | { | 180 | { |
181 | int charlen; | 181 | int charlen; |
182 | wchar_t wc; | 182 | wchar_t wc; |
183 | 183 | ||
184 | charlen = t->char2uni(c, clen, &wc); | 184 | charlen = t->char2uni(c, clen, &wc); |
185 | if (charlen < 0) { | 185 | if (charlen < 0) { |
186 | *uni = 0x003f; /* a question mark */ | 186 | *uni = 0x003f; /* a question mark */ |
187 | charlen = 1; | 187 | charlen = 1; |
188 | } else if (charlen <= 1) { | 188 | } else if (charlen <= 1) { |
189 | unsigned char nc = t->charset2lower[*c]; | 189 | unsigned char nc = t->charset2lower[*c]; |
190 | 190 | ||
191 | if (!nc) | 191 | if (!nc) |
192 | nc = *c; | 192 | nc = *c; |
193 | 193 | ||
194 | if ( (charlen = t->char2uni(&nc, 1, uni)) < 0) { | 194 | if ( (charlen = t->char2uni(&nc, 1, uni)) < 0) { |
195 | *uni = 0x003f; /* a question mark */ | 195 | *uni = 0x003f; /* a question mark */ |
196 | charlen = 1; | 196 | charlen = 1; |
197 | } | 197 | } |
198 | } else | 198 | } else |
199 | *uni = wc; | 199 | *uni = wc; |
200 | 200 | ||
201 | return charlen; | 201 | return charlen; |
202 | } | 202 | } |
203 | 203 | ||
204 | static inline int | 204 | static inline int |
205 | fat_shortname2uni(struct nls_table *nls, unsigned char *buf, int buf_size, | 205 | fat_shortname2uni(struct nls_table *nls, unsigned char *buf, int buf_size, |
206 | wchar_t *uni_buf, unsigned short opt, int lower) | 206 | wchar_t *uni_buf, unsigned short opt, int lower) |
207 | { | 207 | { |
208 | int len = 0; | 208 | int len = 0; |
209 | 209 | ||
210 | if (opt & VFAT_SFN_DISPLAY_LOWER) | 210 | if (opt & VFAT_SFN_DISPLAY_LOWER) |
211 | len = fat_short2lower_uni(nls, buf, buf_size, uni_buf); | 211 | len = fat_short2lower_uni(nls, buf, buf_size, uni_buf); |
212 | else if (opt & VFAT_SFN_DISPLAY_WIN95) | 212 | else if (opt & VFAT_SFN_DISPLAY_WIN95) |
213 | len = fat_short2uni(nls, buf, buf_size, uni_buf); | 213 | len = fat_short2uni(nls, buf, buf_size, uni_buf); |
214 | else if (opt & VFAT_SFN_DISPLAY_WINNT) { | 214 | else if (opt & VFAT_SFN_DISPLAY_WINNT) { |
215 | if (lower) | 215 | if (lower) |
216 | len = fat_short2lower_uni(nls, buf, buf_size, uni_buf); | 216 | len = fat_short2lower_uni(nls, buf, buf_size, uni_buf); |
217 | else | 217 | else |
218 | len = fat_short2uni(nls, buf, buf_size, uni_buf); | 218 | len = fat_short2uni(nls, buf, buf_size, uni_buf); |
219 | } else | 219 | } else |
220 | len = fat_short2uni(nls, buf, buf_size, uni_buf); | 220 | len = fat_short2uni(nls, buf, buf_size, uni_buf); |
221 | 221 | ||
222 | return len; | 222 | return len; |
223 | } | 223 | } |
224 | 224 | ||
225 | enum { PARSE_INVALID = 1, PARSE_NOT_LONGNAME, PARSE_EOF, }; | 225 | enum { PARSE_INVALID = 1, PARSE_NOT_LONGNAME, PARSE_EOF, }; |
226 | 226 | ||
227 | /** | 227 | /** |
228 | * fat_parse_long - Parse extended directory entry. | 228 | * fat_parse_long - Parse extended directory entry. |
229 | * | 229 | * |
230 | * This function returns zero on success, negative value on error, or one of | 230 | * This function returns zero on success, negative value on error, or one of |
231 | * the following: | 231 | * the following: |
232 | * | 232 | * |
233 | * %PARSE_INVALID - Directory entry is invalid. | 233 | * %PARSE_INVALID - Directory entry is invalid. |
234 | * %PARSE_NOT_LONGNAME - Directory entry does not contain longname. | 234 | * %PARSE_NOT_LONGNAME - Directory entry does not contain longname. |
235 | * %PARSE_EOF - Directory has no more entries. | 235 | * %PARSE_EOF - Directory has no more entries. |
236 | */ | 236 | */ |
237 | static int fat_parse_long(struct inode *dir, loff_t *pos, | 237 | static int fat_parse_long(struct inode *dir, loff_t *pos, |
238 | struct buffer_head **bh, struct msdos_dir_entry **de, | 238 | struct buffer_head **bh, struct msdos_dir_entry **de, |
239 | wchar_t **unicode, unsigned char *nr_slots) | 239 | wchar_t **unicode, unsigned char *nr_slots) |
240 | { | 240 | { |
241 | struct msdos_dir_slot *ds; | 241 | struct msdos_dir_slot *ds; |
242 | unsigned char id, slot, slots, alias_checksum; | 242 | unsigned char id, slot, slots, alias_checksum; |
243 | 243 | ||
244 | if (!*unicode) { | 244 | if (!*unicode) { |
245 | *unicode = (wchar_t *)__get_free_page(GFP_KERNEL); | 245 | *unicode = (wchar_t *)__get_free_page(GFP_KERNEL); |
246 | if (!*unicode) { | 246 | if (!*unicode) { |
247 | brelse(*bh); | 247 | brelse(*bh); |
248 | return -ENOMEM; | 248 | return -ENOMEM; |
249 | } | 249 | } |
250 | } | 250 | } |
251 | parse_long: | 251 | parse_long: |
252 | slots = 0; | 252 | slots = 0; |
253 | ds = (struct msdos_dir_slot *)*de; | 253 | ds = (struct msdos_dir_slot *)*de; |
254 | id = ds->id; | 254 | id = ds->id; |
255 | if (!(id & 0x40)) | 255 | if (!(id & 0x40)) |
256 | return PARSE_INVALID; | 256 | return PARSE_INVALID; |
257 | slots = id & ~0x40; | 257 | slots = id & ~0x40; |
258 | if (slots > 20 || !slots) /* ceil(256 * 2 / 26) */ | 258 | if (slots > 20 || !slots) /* ceil(256 * 2 / 26) */ |
259 | return PARSE_INVALID; | 259 | return PARSE_INVALID; |
260 | *nr_slots = slots; | 260 | *nr_slots = slots; |
261 | alias_checksum = ds->alias_checksum; | 261 | alias_checksum = ds->alias_checksum; |
262 | 262 | ||
263 | slot = slots; | 263 | slot = slots; |
264 | while (1) { | 264 | while (1) { |
265 | int offset; | 265 | int offset; |
266 | 266 | ||
267 | slot--; | 267 | slot--; |
268 | offset = slot * 13; | 268 | offset = slot * 13; |
269 | fat16_towchar(*unicode + offset, ds->name0_4, 5); | 269 | fat16_towchar(*unicode + offset, ds->name0_4, 5); |
270 | fat16_towchar(*unicode + offset + 5, ds->name5_10, 6); | 270 | fat16_towchar(*unicode + offset + 5, ds->name5_10, 6); |
271 | fat16_towchar(*unicode + offset + 11, ds->name11_12, 2); | 271 | fat16_towchar(*unicode + offset + 11, ds->name11_12, 2); |
272 | 272 | ||
273 | if (ds->id & 0x40) | 273 | if (ds->id & 0x40) |
274 | (*unicode)[offset + 13] = 0; | 274 | (*unicode)[offset + 13] = 0; |
275 | if (fat_get_entry(dir, pos, bh, de) < 0) | 275 | if (fat_get_entry(dir, pos, bh, de) < 0) |
276 | return PARSE_EOF; | 276 | return PARSE_EOF; |
277 | if (slot == 0) | 277 | if (slot == 0) |
278 | break; | 278 | break; |
279 | ds = (struct msdos_dir_slot *)*de; | 279 | ds = (struct msdos_dir_slot *)*de; |
280 | if (ds->attr != ATTR_EXT) | 280 | if (ds->attr != ATTR_EXT) |
281 | return PARSE_NOT_LONGNAME; | 281 | return PARSE_NOT_LONGNAME; |
282 | if ((ds->id & ~0x40) != slot) | 282 | if ((ds->id & ~0x40) != slot) |
283 | goto parse_long; | 283 | goto parse_long; |
284 | if (ds->alias_checksum != alias_checksum) | 284 | if (ds->alias_checksum != alias_checksum) |
285 | goto parse_long; | 285 | goto parse_long; |
286 | } | 286 | } |
287 | if ((*de)->name[0] == DELETED_FLAG) | 287 | if ((*de)->name[0] == DELETED_FLAG) |
288 | return PARSE_INVALID; | 288 | return PARSE_INVALID; |
289 | if ((*de)->attr == ATTR_EXT) | 289 | if ((*de)->attr == ATTR_EXT) |
290 | goto parse_long; | 290 | goto parse_long; |
291 | if (IS_FREE((*de)->name) || ((*de)->attr & ATTR_VOLUME)) | 291 | if (IS_FREE((*de)->name) || ((*de)->attr & ATTR_VOLUME)) |
292 | return PARSE_INVALID; | 292 | return PARSE_INVALID; |
293 | if (fat_checksum((*de)->name) != alias_checksum) | 293 | if (fat_checksum((*de)->name) != alias_checksum) |
294 | *nr_slots = 0; | 294 | *nr_slots = 0; |
295 | 295 | ||
296 | return 0; | 296 | return 0; |
297 | } | 297 | } |
298 | 298 | ||
299 | /* | 299 | /* |
300 | * Return values: negative -> error, 0 -> not found, positive -> found, | 300 | * Return values: negative -> error, 0 -> not found, positive -> found, |
301 | * value is the total amount of slots, including the shortname entry. | 301 | * value is the total amount of slots, including the shortname entry. |
302 | */ | 302 | */ |
303 | int fat_search_long(struct inode *inode, const unsigned char *name, | 303 | int fat_search_long(struct inode *inode, const unsigned char *name, |
304 | int name_len, struct fat_slot_info *sinfo) | 304 | int name_len, struct fat_slot_info *sinfo) |
305 | { | 305 | { |
306 | struct super_block *sb = inode->i_sb; | 306 | struct super_block *sb = inode->i_sb; |
307 | struct msdos_sb_info *sbi = MSDOS_SB(sb); | 307 | struct msdos_sb_info *sbi = MSDOS_SB(sb); |
308 | struct buffer_head *bh = NULL; | 308 | struct buffer_head *bh = NULL; |
309 | struct msdos_dir_entry *de; | 309 | struct msdos_dir_entry *de; |
310 | struct nls_table *nls_io = sbi->nls_io; | 310 | struct nls_table *nls_io = sbi->nls_io; |
311 | struct nls_table *nls_disk = sbi->nls_disk; | 311 | struct nls_table *nls_disk = sbi->nls_disk; |
312 | wchar_t bufuname[14]; | 312 | wchar_t bufuname[14]; |
313 | unsigned char xlate_len, nr_slots; | 313 | unsigned char xlate_len, nr_slots; |
314 | wchar_t *unicode = NULL; | 314 | wchar_t *unicode = NULL; |
315 | unsigned char work[8], bufname[260]; /* 256 + 4 */ | 315 | unsigned char work[8], bufname[260]; /* 256 + 4 */ |
316 | int uni_xlate = sbi->options.unicode_xlate; | 316 | int uni_xlate = sbi->options.unicode_xlate; |
317 | int utf8 = sbi->options.utf8; | 317 | int utf8 = sbi->options.utf8; |
318 | int anycase = (sbi->options.name_check != 's'); | 318 | int anycase = (sbi->options.name_check != 's'); |
319 | unsigned short opt_shortname = sbi->options.shortname; | 319 | unsigned short opt_shortname = sbi->options.shortname; |
320 | loff_t cpos = 0; | 320 | loff_t cpos = 0; |
321 | int chl, i, j, last_u, err; | 321 | int chl, i, j, last_u, err; |
322 | 322 | ||
323 | err = -ENOENT; | 323 | err = -ENOENT; |
324 | while(1) { | 324 | while(1) { |
325 | if (fat_get_entry(inode, &cpos, &bh, &de) == -1) | 325 | if (fat_get_entry(inode, &cpos, &bh, &de) == -1) |
326 | goto EODir; | 326 | goto EODir; |
327 | parse_record: | 327 | parse_record: |
328 | nr_slots = 0; | 328 | nr_slots = 0; |
329 | if (de->name[0] == DELETED_FLAG) | 329 | if (de->name[0] == DELETED_FLAG) |
330 | continue; | 330 | continue; |
331 | if (de->attr != ATTR_EXT && (de->attr & ATTR_VOLUME)) | 331 | if (de->attr != ATTR_EXT && (de->attr & ATTR_VOLUME)) |
332 | continue; | 332 | continue; |
333 | if (de->attr != ATTR_EXT && IS_FREE(de->name)) | 333 | if (de->attr != ATTR_EXT && IS_FREE(de->name)) |
334 | continue; | 334 | continue; |
335 | if (de->attr == ATTR_EXT) { | 335 | if (de->attr == ATTR_EXT) { |
336 | int status = fat_parse_long(inode, &cpos, &bh, &de, | 336 | int status = fat_parse_long(inode, &cpos, &bh, &de, |
337 | &unicode, &nr_slots); | 337 | &unicode, &nr_slots); |
338 | if (status < 0) | 338 | if (status < 0) |
339 | return status; | 339 | return status; |
340 | else if (status == PARSE_INVALID) | 340 | else if (status == PARSE_INVALID) |
341 | continue; | 341 | continue; |
342 | else if (status == PARSE_NOT_LONGNAME) | 342 | else if (status == PARSE_NOT_LONGNAME) |
343 | goto parse_record; | 343 | goto parse_record; |
344 | else if (status == PARSE_EOF) | 344 | else if (status == PARSE_EOF) |
345 | goto EODir; | 345 | goto EODir; |
346 | } | 346 | } |
347 | 347 | ||
348 | memcpy(work, de->name, sizeof(de->name)); | 348 | memcpy(work, de->name, sizeof(de->name)); |
349 | /* see namei.c, msdos_format_name */ | 349 | /* see namei.c, msdos_format_name */ |
350 | if (work[0] == 0x05) | 350 | if (work[0] == 0x05) |
351 | work[0] = 0xE5; | 351 | work[0] = 0xE5; |
352 | for (i = 0, j = 0, last_u = 0; i < 8;) { | 352 | for (i = 0, j = 0, last_u = 0; i < 8;) { |
353 | if (!work[i]) break; | 353 | if (!work[i]) break; |
354 | chl = fat_shortname2uni(nls_disk, &work[i], 8 - i, | 354 | chl = fat_shortname2uni(nls_disk, &work[i], 8 - i, |
355 | &bufuname[j++], opt_shortname, | 355 | &bufuname[j++], opt_shortname, |
356 | de->lcase & CASE_LOWER_BASE); | 356 | de->lcase & CASE_LOWER_BASE); |
357 | if (chl <= 1) { | 357 | if (chl <= 1) { |
358 | if (work[i] != ' ') | 358 | if (work[i] != ' ') |
359 | last_u = j; | 359 | last_u = j; |
360 | } else { | 360 | } else { |
361 | last_u = j; | 361 | last_u = j; |
362 | } | 362 | } |
363 | i += chl; | 363 | i += chl; |
364 | } | 364 | } |
365 | j = last_u; | 365 | j = last_u; |
366 | fat_short2uni(nls_disk, ".", 1, &bufuname[j++]); | 366 | fat_short2uni(nls_disk, ".", 1, &bufuname[j++]); |
367 | for (i = 0; i < 3;) { | 367 | for (i = 0; i < 3;) { |
368 | if (!de->ext[i]) break; | 368 | if (!de->ext[i]) break; |
369 | chl = fat_shortname2uni(nls_disk, &de->ext[i], 3 - i, | 369 | chl = fat_shortname2uni(nls_disk, &de->ext[i], 3 - i, |
370 | &bufuname[j++], opt_shortname, | 370 | &bufuname[j++], opt_shortname, |
371 | de->lcase & CASE_LOWER_EXT); | 371 | de->lcase & CASE_LOWER_EXT); |
372 | if (chl <= 1) { | 372 | if (chl <= 1) { |
373 | if (de->ext[i] != ' ') | 373 | if (de->ext[i] != ' ') |
374 | last_u = j; | 374 | last_u = j; |
375 | } else { | 375 | } else { |
376 | last_u = j; | 376 | last_u = j; |
377 | } | 377 | } |
378 | i += chl; | 378 | i += chl; |
379 | } | 379 | } |
380 | if (!last_u) | 380 | if (!last_u) |
381 | continue; | 381 | continue; |
382 | 382 | ||
383 | bufuname[last_u] = 0x0000; | 383 | bufuname[last_u] = 0x0000; |
384 | xlate_len = utf8 | 384 | xlate_len = utf8 |
385 | ?utf8_wcstombs(bufname, bufuname, sizeof(bufname)) | 385 | ?utf8_wcstombs(bufname, bufuname, sizeof(bufname)) |
386 | :uni16_to_x8(bufname, bufuname, uni_xlate, nls_io); | 386 | :uni16_to_x8(bufname, bufuname, uni_xlate, nls_io); |
387 | if (xlate_len == name_len) | 387 | if (xlate_len == name_len) |
388 | if ((!anycase && !memcmp(name, bufname, xlate_len)) || | 388 | if ((!anycase && !memcmp(name, bufname, xlate_len)) || |
389 | (anycase && !nls_strnicmp(nls_io, name, bufname, | 389 | (anycase && !nls_strnicmp(nls_io, name, bufname, |
390 | xlate_len))) | 390 | xlate_len))) |
391 | goto Found; | 391 | goto Found; |
392 | 392 | ||
393 | if (nr_slots) { | 393 | if (nr_slots) { |
394 | xlate_len = utf8 | 394 | xlate_len = utf8 |
395 | ?utf8_wcstombs(bufname, unicode, sizeof(bufname)) | 395 | ?utf8_wcstombs(bufname, unicode, sizeof(bufname)) |
396 | :uni16_to_x8(bufname, unicode, uni_xlate, nls_io); | 396 | :uni16_to_x8(bufname, unicode, uni_xlate, nls_io); |
397 | if (xlate_len != name_len) | 397 | if (xlate_len != name_len) |
398 | continue; | 398 | continue; |
399 | if ((!anycase && !memcmp(name, bufname, xlate_len)) || | 399 | if ((!anycase && !memcmp(name, bufname, xlate_len)) || |
400 | (anycase && !nls_strnicmp(nls_io, name, bufname, | 400 | (anycase && !nls_strnicmp(nls_io, name, bufname, |
401 | xlate_len))) | 401 | xlate_len))) |
402 | goto Found; | 402 | goto Found; |
403 | } | 403 | } |
404 | } | 404 | } |
405 | 405 | ||
406 | Found: | 406 | Found: |
407 | nr_slots++; /* include the de */ | 407 | nr_slots++; /* include the de */ |
408 | sinfo->slot_off = cpos - nr_slots * sizeof(*de); | 408 | sinfo->slot_off = cpos - nr_slots * sizeof(*de); |
409 | sinfo->nr_slots = nr_slots; | 409 | sinfo->nr_slots = nr_slots; |
410 | sinfo->de = de; | 410 | sinfo->de = de; |
411 | sinfo->bh = bh; | 411 | sinfo->bh = bh; |
412 | sinfo->i_pos = fat_make_i_pos(sb, sinfo->bh, sinfo->de); | 412 | sinfo->i_pos = fat_make_i_pos(sb, sinfo->bh, sinfo->de); |
413 | err = 0; | 413 | err = 0; |
414 | EODir: | 414 | EODir: |
415 | if (unicode) | 415 | if (unicode) |
416 | free_page((unsigned long)unicode); | 416 | free_page((unsigned long)unicode); |
417 | 417 | ||
418 | return err; | 418 | return err; |
419 | } | 419 | } |
420 | 420 | ||
421 | EXPORT_SYMBOL_GPL(fat_search_long); | 421 | EXPORT_SYMBOL_GPL(fat_search_long); |
422 | 422 | ||
423 | struct fat_ioctl_filldir_callback { | 423 | struct fat_ioctl_filldir_callback { |
424 | struct dirent __user *dirent; | 424 | struct dirent __user *dirent; |
425 | int result; | 425 | int result; |
426 | /* for dir ioctl */ | 426 | /* for dir ioctl */ |
427 | const char *longname; | 427 | const char *longname; |
428 | int long_len; | 428 | int long_len; |
429 | const char *shortname; | 429 | const char *shortname; |
430 | int short_len; | 430 | int short_len; |
431 | }; | 431 | }; |
432 | 432 | ||
433 | static int __fat_readdir(struct inode *inode, struct file *filp, void *dirent, | 433 | static int __fat_readdir(struct inode *inode, struct file *filp, void *dirent, |
434 | filldir_t filldir, int short_only, int both) | 434 | filldir_t filldir, int short_only, int both) |
435 | { | 435 | { |
436 | struct super_block *sb = inode->i_sb; | 436 | struct super_block *sb = inode->i_sb; |
437 | struct msdos_sb_info *sbi = MSDOS_SB(sb); | 437 | struct msdos_sb_info *sbi = MSDOS_SB(sb); |
438 | struct buffer_head *bh; | 438 | struct buffer_head *bh; |
439 | struct msdos_dir_entry *de; | 439 | struct msdos_dir_entry *de; |
440 | struct nls_table *nls_io = sbi->nls_io; | 440 | struct nls_table *nls_io = sbi->nls_io; |
441 | struct nls_table *nls_disk = sbi->nls_disk; | 441 | struct nls_table *nls_disk = sbi->nls_disk; |
442 | unsigned char long_slots; | 442 | unsigned char long_slots; |
443 | const char *fill_name; | 443 | const char *fill_name; |
444 | int fill_len; | 444 | int fill_len; |
445 | wchar_t bufuname[14]; | 445 | wchar_t bufuname[14]; |
446 | wchar_t *unicode = NULL; | 446 | wchar_t *unicode = NULL; |
447 | unsigned char c, work[8], bufname[56], *ptname = bufname; | 447 | unsigned char c, work[8], bufname[56], *ptname = bufname; |
448 | unsigned long lpos, dummy, *furrfu = &lpos; | 448 | unsigned long lpos, dummy, *furrfu = &lpos; |
449 | int uni_xlate = sbi->options.unicode_xlate; | 449 | int uni_xlate = sbi->options.unicode_xlate; |
450 | int isvfat = sbi->options.isvfat; | 450 | int isvfat = sbi->options.isvfat; |
451 | int utf8 = sbi->options.utf8; | 451 | int utf8 = sbi->options.utf8; |
452 | int nocase = sbi->options.nocase; | 452 | int nocase = sbi->options.nocase; |
453 | unsigned short opt_shortname = sbi->options.shortname; | 453 | unsigned short opt_shortname = sbi->options.shortname; |
454 | unsigned long inum; | 454 | unsigned long inum; |
455 | int chi, chl, i, i2, j, last, last_u, dotoffset = 0; | 455 | int chi, chl, i, i2, j, last, last_u, dotoffset = 0; |
456 | loff_t cpos; | 456 | loff_t cpos; |
457 | int ret = 0; | 457 | int ret = 0; |
458 | 458 | ||
459 | lock_kernel(); | 459 | lock_kernel(); |
460 | 460 | ||
461 | cpos = filp->f_pos; | 461 | cpos = filp->f_pos; |
462 | /* Fake . and .. for the root directory. */ | 462 | /* Fake . and .. for the root directory. */ |
463 | if (inode->i_ino == MSDOS_ROOT_INO) { | 463 | if (inode->i_ino == MSDOS_ROOT_INO) { |
464 | while (cpos < 2) { | 464 | while (cpos < 2) { |
465 | if (filldir(dirent, "..", cpos+1, cpos, MSDOS_ROOT_INO, DT_DIR) < 0) | 465 | if (filldir(dirent, "..", cpos+1, cpos, MSDOS_ROOT_INO, DT_DIR) < 0) |
466 | goto out; | 466 | goto out; |
467 | cpos++; | 467 | cpos++; |
468 | filp->f_pos++; | 468 | filp->f_pos++; |
469 | } | 469 | } |
470 | if (cpos == 2) { | 470 | if (cpos == 2) { |
471 | dummy = 2; | 471 | dummy = 2; |
472 | furrfu = &dummy; | 472 | furrfu = &dummy; |
473 | cpos = 0; | 473 | cpos = 0; |
474 | } | 474 | } |
475 | } | 475 | } |
476 | if (cpos & (sizeof(struct msdos_dir_entry)-1)) { | 476 | if (cpos & (sizeof(struct msdos_dir_entry)-1)) { |
477 | ret = -ENOENT; | 477 | ret = -ENOENT; |
478 | goto out; | 478 | goto out; |
479 | } | 479 | } |
480 | 480 | ||
481 | bh = NULL; | 481 | bh = NULL; |
482 | GetNew: | 482 | GetNew: |
483 | if (fat_get_entry(inode, &cpos, &bh, &de) == -1) | 483 | if (fat_get_entry(inode, &cpos, &bh, &de) == -1) |
484 | goto EODir; | 484 | goto EODir; |
485 | parse_record: | 485 | parse_record: |
486 | long_slots = 0; | 486 | long_slots = 0; |
487 | /* Check for long filename entry */ | 487 | /* Check for long filename entry */ |
488 | if (isvfat) { | 488 | if (isvfat) { |
489 | if (de->name[0] == DELETED_FLAG) | 489 | if (de->name[0] == DELETED_FLAG) |
490 | goto RecEnd; | 490 | goto RecEnd; |
491 | if (de->attr != ATTR_EXT && (de->attr & ATTR_VOLUME)) | 491 | if (de->attr != ATTR_EXT && (de->attr & ATTR_VOLUME)) |
492 | goto RecEnd; | 492 | goto RecEnd; |
493 | if (de->attr != ATTR_EXT && IS_FREE(de->name)) | 493 | if (de->attr != ATTR_EXT && IS_FREE(de->name)) |
494 | goto RecEnd; | 494 | goto RecEnd; |
495 | } else { | 495 | } else { |
496 | if ((de->attr & ATTR_VOLUME) || IS_FREE(de->name)) | 496 | if ((de->attr & ATTR_VOLUME) || IS_FREE(de->name)) |
497 | goto RecEnd; | 497 | goto RecEnd; |
498 | } | 498 | } |
499 | 499 | ||
500 | if (isvfat && de->attr == ATTR_EXT) { | 500 | if (isvfat && de->attr == ATTR_EXT) { |
501 | int status = fat_parse_long(inode, &cpos, &bh, &de, | 501 | int status = fat_parse_long(inode, &cpos, &bh, &de, |
502 | &unicode, &long_slots); | 502 | &unicode, &long_slots); |
503 | if (status < 0) { | 503 | if (status < 0) { |
504 | filp->f_pos = cpos; | 504 | filp->f_pos = cpos; |
505 | ret = status; | 505 | ret = status; |
506 | goto out; | 506 | goto out; |
507 | } else if (status == PARSE_INVALID) | 507 | } else if (status == PARSE_INVALID) |
508 | goto RecEnd; | 508 | goto RecEnd; |
509 | else if (status == PARSE_NOT_LONGNAME) | 509 | else if (status == PARSE_NOT_LONGNAME) |
510 | goto parse_record; | 510 | goto parse_record; |
511 | else if (status == PARSE_EOF) | 511 | else if (status == PARSE_EOF) |
512 | goto EODir; | 512 | goto EODir; |
513 | } | 513 | } |
514 | 514 | ||
515 | if (sbi->options.dotsOK) { | 515 | if (sbi->options.dotsOK) { |
516 | ptname = bufname; | 516 | ptname = bufname; |
517 | dotoffset = 0; | 517 | dotoffset = 0; |
518 | if (de->attr & ATTR_HIDDEN) { | 518 | if (de->attr & ATTR_HIDDEN) { |
519 | *ptname++ = '.'; | 519 | *ptname++ = '.'; |
520 | dotoffset = 1; | 520 | dotoffset = 1; |
521 | } | 521 | } |
522 | } | 522 | } |
523 | 523 | ||
524 | memcpy(work, de->name, sizeof(de->name)); | 524 | memcpy(work, de->name, sizeof(de->name)); |
525 | /* see namei.c, msdos_format_name */ | 525 | /* see namei.c, msdos_format_name */ |
526 | if (work[0] == 0x05) | 526 | if (work[0] == 0x05) |
527 | work[0] = 0xE5; | 527 | work[0] = 0xE5; |
528 | for (i = 0, j = 0, last = 0, last_u = 0; i < 8;) { | 528 | for (i = 0, j = 0, last = 0, last_u = 0; i < 8;) { |
529 | if (!(c = work[i])) break; | 529 | if (!(c = work[i])) break; |
530 | chl = fat_shortname2uni(nls_disk, &work[i], 8 - i, | 530 | chl = fat_shortname2uni(nls_disk, &work[i], 8 - i, |
531 | &bufuname[j++], opt_shortname, | 531 | &bufuname[j++], opt_shortname, |
532 | de->lcase & CASE_LOWER_BASE); | 532 | de->lcase & CASE_LOWER_BASE); |
533 | if (chl <= 1) { | 533 | if (chl <= 1) { |
534 | ptname[i++] = (!nocase && c>='A' && c<='Z') ? c+32 : c; | 534 | ptname[i++] = (!nocase && c>='A' && c<='Z') ? c+32 : c; |
535 | if (c != ' ') { | 535 | if (c != ' ') { |
536 | last = i; | 536 | last = i; |
537 | last_u = j; | 537 | last_u = j; |
538 | } | 538 | } |
539 | } else { | 539 | } else { |
540 | last_u = j; | 540 | last_u = j; |
541 | for (chi = 0; chi < chl && i < 8; chi++) { | 541 | for (chi = 0; chi < chl && i < 8; chi++) { |
542 | ptname[i] = work[i]; | 542 | ptname[i] = work[i]; |
543 | i++; last = i; | 543 | i++; last = i; |
544 | } | 544 | } |
545 | } | 545 | } |
546 | } | 546 | } |
547 | i = last; | 547 | i = last; |
548 | j = last_u; | 548 | j = last_u; |
549 | fat_short2uni(nls_disk, ".", 1, &bufuname[j++]); | 549 | fat_short2uni(nls_disk, ".", 1, &bufuname[j++]); |
550 | ptname[i++] = '.'; | 550 | ptname[i++] = '.'; |
551 | for (i2 = 0; i2 < 3;) { | 551 | for (i2 = 0; i2 < 3;) { |
552 | if (!(c = de->ext[i2])) break; | 552 | if (!(c = de->ext[i2])) break; |
553 | chl = fat_shortname2uni(nls_disk, &de->ext[i2], 3 - i2, | 553 | chl = fat_shortname2uni(nls_disk, &de->ext[i2], 3 - i2, |
554 | &bufuname[j++], opt_shortname, | 554 | &bufuname[j++], opt_shortname, |
555 | de->lcase & CASE_LOWER_EXT); | 555 | de->lcase & CASE_LOWER_EXT); |
556 | if (chl <= 1) { | 556 | if (chl <= 1) { |
557 | i2++; | 557 | i2++; |
558 | ptname[i++] = (!nocase && c>='A' && c<='Z') ? c+32 : c; | 558 | ptname[i++] = (!nocase && c>='A' && c<='Z') ? c+32 : c; |
559 | if (c != ' ') { | 559 | if (c != ' ') { |
560 | last = i; | 560 | last = i; |
561 | last_u = j; | 561 | last_u = j; |
562 | } | 562 | } |
563 | } else { | 563 | } else { |
564 | last_u = j; | 564 | last_u = j; |
565 | for (chi = 0; chi < chl && i2 < 3; chi++) { | 565 | for (chi = 0; chi < chl && i2 < 3; chi++) { |
566 | ptname[i++] = de->ext[i2++]; | 566 | ptname[i++] = de->ext[i2++]; |
567 | last = i; | 567 | last = i; |
568 | } | 568 | } |
569 | } | 569 | } |
570 | } | 570 | } |
571 | if (!last) | 571 | if (!last) |
572 | goto RecEnd; | 572 | goto RecEnd; |
573 | 573 | ||
574 | i = last + dotoffset; | 574 | i = last + dotoffset; |
575 | j = last_u; | 575 | j = last_u; |
576 | 576 | ||
577 | lpos = cpos - (long_slots+1)*sizeof(struct msdos_dir_entry); | 577 | lpos = cpos - (long_slots+1)*sizeof(struct msdos_dir_entry); |
578 | if (!memcmp(de->name, MSDOS_DOT, MSDOS_NAME)) | 578 | if (!memcmp(de->name, MSDOS_DOT, MSDOS_NAME)) |
579 | inum = inode->i_ino; | 579 | inum = inode->i_ino; |
580 | else if (!memcmp(de->name, MSDOS_DOTDOT, MSDOS_NAME)) { | 580 | else if (!memcmp(de->name, MSDOS_DOTDOT, MSDOS_NAME)) { |
581 | inum = parent_ino(filp->f_dentry); | 581 | inum = parent_ino(filp->f_dentry); |
582 | } else { | 582 | } else { |
583 | loff_t i_pos = fat_make_i_pos(sb, bh, de); | 583 | loff_t i_pos = fat_make_i_pos(sb, bh, de); |
584 | struct inode *tmp = fat_iget(sb, i_pos); | 584 | struct inode *tmp = fat_iget(sb, i_pos); |
585 | if (tmp) { | 585 | if (tmp) { |
586 | inum = tmp->i_ino; | 586 | inum = tmp->i_ino; |
587 | iput(tmp); | 587 | iput(tmp); |
588 | } else | 588 | } else |
589 | inum = iunique(sb, MSDOS_ROOT_INO); | 589 | inum = iunique(sb, MSDOS_ROOT_INO); |
590 | } | 590 | } |
591 | 591 | ||
592 | if (isvfat) { | 592 | if (isvfat) { |
593 | bufuname[j] = 0x0000; | 593 | bufuname[j] = 0x0000; |
594 | i = utf8 ? utf8_wcstombs(bufname, bufuname, sizeof(bufname)) | 594 | i = utf8 ? utf8_wcstombs(bufname, bufuname, sizeof(bufname)) |
595 | : uni16_to_x8(bufname, bufuname, uni_xlate, nls_io); | 595 | : uni16_to_x8(bufname, bufuname, uni_xlate, nls_io); |
596 | } | 596 | } |
597 | 597 | ||
598 | fill_name = bufname; | 598 | fill_name = bufname; |
599 | fill_len = i; | 599 | fill_len = i; |
600 | if (!short_only && long_slots) { | 600 | if (!short_only && long_slots) { |
601 | /* convert the unicode long name. 261 is maximum size | 601 | /* convert the unicode long name. 261 is maximum size |
602 | * of unicode buffer. (13 * slots + nul) */ | 602 | * of unicode buffer. (13 * slots + nul) */ |
603 | void *longname = unicode + 261; | 603 | void *longname = unicode + 261; |
604 | int buf_size = PAGE_SIZE - (261 * sizeof(unicode[0])); | 604 | int buf_size = PAGE_SIZE - (261 * sizeof(unicode[0])); |
605 | int long_len = utf8 | 605 | int long_len = utf8 |
606 | ? utf8_wcstombs(longname, unicode, buf_size) | 606 | ? utf8_wcstombs(longname, unicode, buf_size) |
607 | : uni16_to_x8(longname, unicode, uni_xlate, nls_io); | 607 | : uni16_to_x8(longname, unicode, uni_xlate, nls_io); |
608 | 608 | ||
609 | if (!both) { | 609 | if (!both) { |
610 | fill_name = longname; | 610 | fill_name = longname; |
611 | fill_len = long_len; | 611 | fill_len = long_len; |
612 | } else { | 612 | } else { |
613 | /* hack for fat_ioctl_filldir() */ | 613 | /* hack for fat_ioctl_filldir() */ |
614 | struct fat_ioctl_filldir_callback *p = dirent; | 614 | struct fat_ioctl_filldir_callback *p = dirent; |
615 | 615 | ||
616 | p->longname = longname; | 616 | p->longname = longname; |
617 | p->long_len = long_len; | 617 | p->long_len = long_len; |
618 | p->shortname = bufname; | 618 | p->shortname = bufname; |
619 | p->short_len = i; | 619 | p->short_len = i; |
620 | fill_name = NULL; | 620 | fill_name = NULL; |
621 | fill_len = 0; | 621 | fill_len = 0; |
622 | } | 622 | } |
623 | } | 623 | } |
624 | if (filldir(dirent, fill_name, fill_len, *furrfu, inum, | 624 | if (filldir(dirent, fill_name, fill_len, *furrfu, inum, |
625 | (de->attr & ATTR_DIR) ? DT_DIR : DT_REG) < 0) | 625 | (de->attr & ATTR_DIR) ? DT_DIR : DT_REG) < 0) |
626 | goto FillFailed; | 626 | goto FillFailed; |
627 | 627 | ||
628 | RecEnd: | 628 | RecEnd: |
629 | furrfu = &lpos; | 629 | furrfu = &lpos; |
630 | filp->f_pos = cpos; | 630 | filp->f_pos = cpos; |
631 | goto GetNew; | 631 | goto GetNew; |
632 | EODir: | 632 | EODir: |
633 | filp->f_pos = cpos; | 633 | filp->f_pos = cpos; |
634 | FillFailed: | 634 | FillFailed: |
635 | brelse(bh); | 635 | brelse(bh); |
636 | if (unicode) | 636 | if (unicode) |
637 | free_page((unsigned long)unicode); | 637 | free_page((unsigned long)unicode); |
638 | out: | 638 | out: |
639 | unlock_kernel(); | 639 | unlock_kernel(); |
640 | return ret; | 640 | return ret; |
641 | } | 641 | } |
642 | 642 | ||
643 | static int fat_readdir(struct file *filp, void *dirent, filldir_t filldir) | 643 | static int fat_readdir(struct file *filp, void *dirent, filldir_t filldir) |
644 | { | 644 | { |
645 | struct inode *inode = filp->f_dentry->d_inode; | 645 | struct inode *inode = filp->f_dentry->d_inode; |
646 | return __fat_readdir(inode, filp, dirent, filldir, 0, 0); | 646 | return __fat_readdir(inode, filp, dirent, filldir, 0, 0); |
647 | } | 647 | } |
648 | 648 | ||
649 | static int fat_ioctl_filldir(void *__buf, const char *name, int name_len, | 649 | static int fat_ioctl_filldir(void *__buf, const char *name, int name_len, |
650 | loff_t offset, ino_t ino, unsigned int d_type) | 650 | loff_t offset, ino_t ino, unsigned int d_type) |
651 | { | 651 | { |
652 | struct fat_ioctl_filldir_callback *buf = __buf; | 652 | struct fat_ioctl_filldir_callback *buf = __buf; |
653 | struct dirent __user *d1 = buf->dirent; | 653 | struct dirent __user *d1 = buf->dirent; |
654 | struct dirent __user *d2 = d1 + 1; | 654 | struct dirent __user *d2 = d1 + 1; |
655 | 655 | ||
656 | if (buf->result) | 656 | if (buf->result) |
657 | return -EINVAL; | 657 | return -EINVAL; |
658 | buf->result++; | 658 | buf->result++; |
659 | 659 | ||
660 | if (name != NULL) { | 660 | if (name != NULL) { |
661 | /* dirent has only short name */ | 661 | /* dirent has only short name */ |
662 | if (name_len >= sizeof(d1->d_name)) | 662 | if (name_len >= sizeof(d1->d_name)) |
663 | name_len = sizeof(d1->d_name) - 1; | 663 | name_len = sizeof(d1->d_name) - 1; |
664 | 664 | ||
665 | if (put_user(0, d2->d_name) || | 665 | if (put_user(0, d2->d_name) || |
666 | put_user(0, &d2->d_reclen) || | 666 | put_user(0, &d2->d_reclen) || |
667 | copy_to_user(d1->d_name, name, name_len) || | 667 | copy_to_user(d1->d_name, name, name_len) || |
668 | put_user(0, d1->d_name + name_len) || | 668 | put_user(0, d1->d_name + name_len) || |
669 | put_user(name_len, &d1->d_reclen)) | 669 | put_user(name_len, &d1->d_reclen)) |
670 | goto efault; | 670 | goto efault; |
671 | } else { | 671 | } else { |
672 | /* dirent has short and long name */ | 672 | /* dirent has short and long name */ |
673 | const char *longname = buf->longname; | 673 | const char *longname = buf->longname; |
674 | int long_len = buf->long_len; | 674 | int long_len = buf->long_len; |
675 | const char *shortname = buf->shortname; | 675 | const char *shortname = buf->shortname; |
676 | int short_len = buf->short_len; | 676 | int short_len = buf->short_len; |
677 | 677 | ||
678 | if (long_len >= sizeof(d1->d_name)) | 678 | if (long_len >= sizeof(d1->d_name)) |
679 | long_len = sizeof(d1->d_name) - 1; | 679 | long_len = sizeof(d1->d_name) - 1; |
680 | if (short_len >= sizeof(d1->d_name)) | 680 | if (short_len >= sizeof(d1->d_name)) |
681 | short_len = sizeof(d1->d_name) - 1; | 681 | short_len = sizeof(d1->d_name) - 1; |
682 | 682 | ||
683 | if (copy_to_user(d2->d_name, longname, long_len) || | 683 | if (copy_to_user(d2->d_name, longname, long_len) || |
684 | put_user(0, d2->d_name + long_len) || | 684 | put_user(0, d2->d_name + long_len) || |
685 | put_user(long_len, &d2->d_reclen) || | 685 | put_user(long_len, &d2->d_reclen) || |
686 | put_user(ino, &d2->d_ino) || | 686 | put_user(ino, &d2->d_ino) || |
687 | put_user(offset, &d2->d_off) || | 687 | put_user(offset, &d2->d_off) || |
688 | copy_to_user(d1->d_name, shortname, short_len) || | 688 | copy_to_user(d1->d_name, shortname, short_len) || |
689 | put_user(0, d1->d_name + short_len) || | 689 | put_user(0, d1->d_name + short_len) || |
690 | put_user(short_len, &d1->d_reclen)) | 690 | put_user(short_len, &d1->d_reclen)) |
691 | goto efault; | 691 | goto efault; |
692 | } | 692 | } |
693 | return 0; | 693 | return 0; |
694 | efault: | 694 | efault: |
695 | buf->result = -EFAULT; | 695 | buf->result = -EFAULT; |
696 | return -EFAULT; | 696 | return -EFAULT; |
697 | } | 697 | } |
698 | 698 | ||
699 | static int fat_dir_ioctl(struct inode * inode, struct file * filp, | 699 | static int fat_dir_ioctl(struct inode * inode, struct file * filp, |
700 | unsigned int cmd, unsigned long arg) | 700 | unsigned int cmd, unsigned long arg) |
701 | { | 701 | { |
702 | struct fat_ioctl_filldir_callback buf; | 702 | struct fat_ioctl_filldir_callback buf; |
703 | struct dirent __user *d1; | 703 | struct dirent __user *d1; |
704 | int ret, short_only, both; | 704 | int ret, short_only, both; |
705 | 705 | ||
706 | switch (cmd) { | 706 | switch (cmd) { |
707 | case VFAT_IOCTL_READDIR_SHORT: | 707 | case VFAT_IOCTL_READDIR_SHORT: |
708 | short_only = 1; | 708 | short_only = 1; |
709 | both = 0; | 709 | both = 0; |
710 | break; | 710 | break; |
711 | case VFAT_IOCTL_READDIR_BOTH: | 711 | case VFAT_IOCTL_READDIR_BOTH: |
712 | short_only = 0; | 712 | short_only = 0; |
713 | both = 1; | 713 | both = 1; |
714 | break; | 714 | break; |
715 | default: | 715 | default: |
716 | return fat_generic_ioctl(inode, filp, cmd, arg); | 716 | return fat_generic_ioctl(inode, filp, cmd, arg); |
717 | } | 717 | } |
718 | 718 | ||
719 | d1 = (struct dirent __user *)arg; | 719 | d1 = (struct dirent __user *)arg; |
720 | if (!access_ok(VERIFY_WRITE, d1, sizeof(struct dirent[2]))) | 720 | if (!access_ok(VERIFY_WRITE, d1, sizeof(struct dirent[2]))) |
721 | return -EFAULT; | 721 | return -EFAULT; |
722 | /* | 722 | /* |
723 | * Yes, we don't need this put_user() absolutely. However old | 723 | * Yes, we don't need this put_user() absolutely. However old |
724 | * code didn't return the right value. So, app use this value, | 724 | * code didn't return the right value. So, app use this value, |
725 | * in order to check whether it is EOF. | 725 | * in order to check whether it is EOF. |
726 | */ | 726 | */ |
727 | if (put_user(0, &d1->d_reclen)) | 727 | if (put_user(0, &d1->d_reclen)) |
728 | return -EFAULT; | 728 | return -EFAULT; |
729 | 729 | ||
730 | buf.dirent = d1; | 730 | buf.dirent = d1; |
731 | buf.result = 0; | 731 | buf.result = 0; |
732 | mutex_lock(&inode->i_mutex); | 732 | mutex_lock(&inode->i_mutex); |
733 | ret = -ENOENT; | 733 | ret = -ENOENT; |
734 | if (!IS_DEADDIR(inode)) { | 734 | if (!IS_DEADDIR(inode)) { |
735 | ret = __fat_readdir(inode, filp, &buf, fat_ioctl_filldir, | 735 | ret = __fat_readdir(inode, filp, &buf, fat_ioctl_filldir, |
736 | short_only, both); | 736 | short_only, both); |
737 | } | 737 | } |
738 | mutex_unlock(&inode->i_mutex); | 738 | mutex_unlock(&inode->i_mutex); |
739 | if (ret >= 0) | 739 | if (ret >= 0) |
740 | ret = buf.result; | 740 | ret = buf.result; |
741 | return ret; | 741 | return ret; |
742 | } | 742 | } |
743 | 743 | ||
744 | struct file_operations fat_dir_operations = { | 744 | struct file_operations fat_dir_operations = { |
745 | .read = generic_read_dir, | 745 | .read = generic_read_dir, |
746 | .readdir = fat_readdir, | 746 | .readdir = fat_readdir, |
747 | .ioctl = fat_dir_ioctl, | 747 | .ioctl = fat_dir_ioctl, |
748 | .fsync = file_fsync, | 748 | .fsync = file_fsync, |
749 | }; | 749 | }; |
750 | 750 | ||
751 | static int fat_get_short_entry(struct inode *dir, loff_t *pos, | 751 | static int fat_get_short_entry(struct inode *dir, loff_t *pos, |
752 | struct buffer_head **bh, | 752 | struct buffer_head **bh, |
753 | struct msdos_dir_entry **de) | 753 | struct msdos_dir_entry **de) |
754 | { | 754 | { |
755 | while (fat_get_entry(dir, pos, bh, de) >= 0) { | 755 | while (fat_get_entry(dir, pos, bh, de) >= 0) { |
756 | /* free entry or long name entry or volume label */ | 756 | /* free entry or long name entry or volume label */ |
757 | if (!IS_FREE((*de)->name) && !((*de)->attr & ATTR_VOLUME)) | 757 | if (!IS_FREE((*de)->name) && !((*de)->attr & ATTR_VOLUME)) |
758 | return 0; | 758 | return 0; |
759 | } | 759 | } |
760 | return -ENOENT; | 760 | return -ENOENT; |
761 | } | 761 | } |
762 | 762 | ||
763 | /* | 763 | /* |
764 | * The ".." entry can not provide the "struct fat_slot_info" informations | 764 | * The ".." entry can not provide the "struct fat_slot_info" informations |
765 | * for inode. So, this function provide the some informations only. | 765 | * for inode. So, this function provide the some informations only. |
766 | */ | 766 | */ |
767 | int fat_get_dotdot_entry(struct inode *dir, struct buffer_head **bh, | 767 | int fat_get_dotdot_entry(struct inode *dir, struct buffer_head **bh, |
768 | struct msdos_dir_entry **de, loff_t *i_pos) | 768 | struct msdos_dir_entry **de, loff_t *i_pos) |
769 | { | 769 | { |
770 | loff_t offset; | 770 | loff_t offset; |
771 | 771 | ||
772 | offset = 0; | 772 | offset = 0; |
773 | *bh = NULL; | 773 | *bh = NULL; |
774 | while (fat_get_short_entry(dir, &offset, bh, de) >= 0) { | 774 | while (fat_get_short_entry(dir, &offset, bh, de) >= 0) { |
775 | if (!strncmp((*de)->name, MSDOS_DOTDOT, MSDOS_NAME)) { | 775 | if (!strncmp((*de)->name, MSDOS_DOTDOT, MSDOS_NAME)) { |
776 | *i_pos = fat_make_i_pos(dir->i_sb, *bh, *de); | 776 | *i_pos = fat_make_i_pos(dir->i_sb, *bh, *de); |
777 | return 0; | 777 | return 0; |
778 | } | 778 | } |
779 | } | 779 | } |
780 | return -ENOENT; | 780 | return -ENOENT; |
781 | } | 781 | } |
782 | 782 | ||
783 | EXPORT_SYMBOL_GPL(fat_get_dotdot_entry); | 783 | EXPORT_SYMBOL_GPL(fat_get_dotdot_entry); |
784 | 784 | ||
785 | /* See if directory is empty */ | 785 | /* See if directory is empty */ |
786 | int fat_dir_empty(struct inode *dir) | 786 | int fat_dir_empty(struct inode *dir) |
787 | { | 787 | { |
788 | struct buffer_head *bh; | 788 | struct buffer_head *bh; |
789 | struct msdos_dir_entry *de; | 789 | struct msdos_dir_entry *de; |
790 | loff_t cpos; | 790 | loff_t cpos; |
791 | int result = 0; | 791 | int result = 0; |
792 | 792 | ||
793 | bh = NULL; | 793 | bh = NULL; |
794 | cpos = 0; | 794 | cpos = 0; |
795 | while (fat_get_short_entry(dir, &cpos, &bh, &de) >= 0) { | 795 | while (fat_get_short_entry(dir, &cpos, &bh, &de) >= 0) { |
796 | if (strncmp(de->name, MSDOS_DOT , MSDOS_NAME) && | 796 | if (strncmp(de->name, MSDOS_DOT , MSDOS_NAME) && |
797 | strncmp(de->name, MSDOS_DOTDOT, MSDOS_NAME)) { | 797 | strncmp(de->name, MSDOS_DOTDOT, MSDOS_NAME)) { |
798 | result = -ENOTEMPTY; | 798 | result = -ENOTEMPTY; |
799 | break; | 799 | break; |
800 | } | 800 | } |
801 | } | 801 | } |
802 | brelse(bh); | 802 | brelse(bh); |
803 | return result; | 803 | return result; |
804 | } | 804 | } |
805 | 805 | ||
806 | EXPORT_SYMBOL_GPL(fat_dir_empty); | 806 | EXPORT_SYMBOL_GPL(fat_dir_empty); |
807 | 807 | ||
808 | /* | 808 | /* |
809 | * fat_subdirs counts the number of sub-directories of dir. It can be run | 809 | * fat_subdirs counts the number of sub-directories of dir. It can be run |
810 | * on directories being created. | 810 | * on directories being created. |
811 | */ | 811 | */ |
812 | int fat_subdirs(struct inode *dir) | 812 | int fat_subdirs(struct inode *dir) |
813 | { | 813 | { |
814 | struct buffer_head *bh; | 814 | struct buffer_head *bh; |
815 | struct msdos_dir_entry *de; | 815 | struct msdos_dir_entry *de; |
816 | loff_t cpos; | 816 | loff_t cpos; |
817 | int count = 0; | 817 | int count = 0; |
818 | 818 | ||
819 | bh = NULL; | 819 | bh = NULL; |
820 | cpos = 0; | 820 | cpos = 0; |
821 | while (fat_get_short_entry(dir, &cpos, &bh, &de) >= 0) { | 821 | while (fat_get_short_entry(dir, &cpos, &bh, &de) >= 0) { |
822 | if (de->attr & ATTR_DIR) | 822 | if (de->attr & ATTR_DIR) |
823 | count++; | 823 | count++; |
824 | } | 824 | } |
825 | brelse(bh); | 825 | brelse(bh); |
826 | return count; | 826 | return count; |
827 | } | 827 | } |
828 | 828 | ||
829 | /* | 829 | /* |
830 | * Scans a directory for a given file (name points to its formatted name). | 830 | * Scans a directory for a given file (name points to its formatted name). |
831 | * Returns an error code or zero. | 831 | * Returns an error code or zero. |
832 | */ | 832 | */ |
833 | int fat_scan(struct inode *dir, const unsigned char *name, | 833 | int fat_scan(struct inode *dir, const unsigned char *name, |
834 | struct fat_slot_info *sinfo) | 834 | struct fat_slot_info *sinfo) |
835 | { | 835 | { |
836 | struct super_block *sb = dir->i_sb; | 836 | struct super_block *sb = dir->i_sb; |
837 | 837 | ||
838 | sinfo->slot_off = 0; | 838 | sinfo->slot_off = 0; |
839 | sinfo->bh = NULL; | 839 | sinfo->bh = NULL; |
840 | while (fat_get_short_entry(dir, &sinfo->slot_off, &sinfo->bh, | 840 | while (fat_get_short_entry(dir, &sinfo->slot_off, &sinfo->bh, |
841 | &sinfo->de) >= 0) { | 841 | &sinfo->de) >= 0) { |
842 | if (!strncmp(sinfo->de->name, name, MSDOS_NAME)) { | 842 | if (!strncmp(sinfo->de->name, name, MSDOS_NAME)) { |
843 | sinfo->slot_off -= sizeof(*sinfo->de); | 843 | sinfo->slot_off -= sizeof(*sinfo->de); |
844 | sinfo->nr_slots = 1; | 844 | sinfo->nr_slots = 1; |
845 | sinfo->i_pos = fat_make_i_pos(sb, sinfo->bh, sinfo->de); | 845 | sinfo->i_pos = fat_make_i_pos(sb, sinfo->bh, sinfo->de); |
846 | return 0; | 846 | return 0; |
847 | } | 847 | } |
848 | } | 848 | } |
849 | return -ENOENT; | 849 | return -ENOENT; |
850 | } | 850 | } |
851 | 851 | ||
852 | EXPORT_SYMBOL_GPL(fat_scan); | 852 | EXPORT_SYMBOL_GPL(fat_scan); |
853 | 853 | ||
854 | static int __fat_remove_entries(struct inode *dir, loff_t pos, int nr_slots) | 854 | static int __fat_remove_entries(struct inode *dir, loff_t pos, int nr_slots) |
855 | { | 855 | { |
856 | struct super_block *sb = dir->i_sb; | 856 | struct super_block *sb = dir->i_sb; |
857 | struct buffer_head *bh; | 857 | struct buffer_head *bh; |
858 | struct msdos_dir_entry *de, *endp; | 858 | struct msdos_dir_entry *de, *endp; |
859 | int err = 0, orig_slots; | 859 | int err = 0, orig_slots; |
860 | 860 | ||
861 | while (nr_slots) { | 861 | while (nr_slots) { |
862 | bh = NULL; | 862 | bh = NULL; |
863 | if (fat_get_entry(dir, &pos, &bh, &de) < 0) { | 863 | if (fat_get_entry(dir, &pos, &bh, &de) < 0) { |
864 | err = -EIO; | 864 | err = -EIO; |
865 | break; | 865 | break; |
866 | } | 866 | } |
867 | 867 | ||
868 | orig_slots = nr_slots; | 868 | orig_slots = nr_slots; |
869 | endp = (struct msdos_dir_entry *)(bh->b_data + sb->s_blocksize); | 869 | endp = (struct msdos_dir_entry *)(bh->b_data + sb->s_blocksize); |
870 | while (nr_slots && de < endp) { | 870 | while (nr_slots && de < endp) { |
871 | de->name[0] = DELETED_FLAG; | 871 | de->name[0] = DELETED_FLAG; |
872 | de++; | 872 | de++; |
873 | nr_slots--; | 873 | nr_slots--; |
874 | } | 874 | } |
875 | mark_buffer_dirty(bh); | 875 | mark_buffer_dirty(bh); |
876 | if (IS_DIRSYNC(dir)) | 876 | if (IS_DIRSYNC(dir)) |
877 | err = sync_dirty_buffer(bh); | 877 | err = sync_dirty_buffer(bh); |
878 | brelse(bh); | 878 | brelse(bh); |
879 | if (err) | 879 | if (err) |
880 | break; | 880 | break; |
881 | 881 | ||
882 | /* pos is *next* de's position, so this does `- sizeof(de)' */ | 882 | /* pos is *next* de's position, so this does `- sizeof(de)' */ |
883 | pos += ((orig_slots - nr_slots) * sizeof(*de)) - sizeof(*de); | 883 | pos += ((orig_slots - nr_slots) * sizeof(*de)) - sizeof(*de); |
884 | } | 884 | } |
885 | 885 | ||
886 | return err; | 886 | return err; |
887 | } | 887 | } |
888 | 888 | ||
889 | int fat_remove_entries(struct inode *dir, struct fat_slot_info *sinfo) | 889 | int fat_remove_entries(struct inode *dir, struct fat_slot_info *sinfo) |
890 | { | 890 | { |
891 | struct msdos_dir_entry *de; | 891 | struct msdos_dir_entry *de; |
892 | struct buffer_head *bh; | 892 | struct buffer_head *bh; |
893 | int err = 0, nr_slots; | 893 | int err = 0, nr_slots; |
894 | 894 | ||
895 | /* | 895 | /* |
896 | * First stage: Remove the shortname. By this, the directory | 896 | * First stage: Remove the shortname. By this, the directory |
897 | * entry is removed. | 897 | * entry is removed. |
898 | */ | 898 | */ |
899 | nr_slots = sinfo->nr_slots; | 899 | nr_slots = sinfo->nr_slots; |
900 | de = sinfo->de; | 900 | de = sinfo->de; |
901 | sinfo->de = NULL; | 901 | sinfo->de = NULL; |
902 | bh = sinfo->bh; | 902 | bh = sinfo->bh; |
903 | sinfo->bh = NULL; | 903 | sinfo->bh = NULL; |
904 | while (nr_slots && de >= (struct msdos_dir_entry *)bh->b_data) { | 904 | while (nr_slots && de >= (struct msdos_dir_entry *)bh->b_data) { |
905 | de->name[0] = DELETED_FLAG; | 905 | de->name[0] = DELETED_FLAG; |
906 | de--; | 906 | de--; |
907 | nr_slots--; | 907 | nr_slots--; |
908 | } | 908 | } |
909 | mark_buffer_dirty(bh); | 909 | mark_buffer_dirty(bh); |
910 | if (IS_DIRSYNC(dir)) | 910 | if (IS_DIRSYNC(dir)) |
911 | err = sync_dirty_buffer(bh); | 911 | err = sync_dirty_buffer(bh); |
912 | brelse(bh); | 912 | brelse(bh); |
913 | if (err) | 913 | if (err) |
914 | return err; | 914 | return err; |
915 | dir->i_version++; | 915 | dir->i_version++; |
916 | 916 | ||
917 | if (nr_slots) { | 917 | if (nr_slots) { |
918 | /* | 918 | /* |
919 | * Second stage: remove the remaining longname slots. | 919 | * Second stage: remove the remaining longname slots. |
920 | * (This directory entry is already removed, and so return | 920 | * (This directory entry is already removed, and so return |
921 | * the success) | 921 | * the success) |
922 | */ | 922 | */ |
923 | err = __fat_remove_entries(dir, sinfo->slot_off, nr_slots); | 923 | err = __fat_remove_entries(dir, sinfo->slot_off, nr_slots); |
924 | if (err) { | 924 | if (err) { |
925 | printk(KERN_WARNING | 925 | printk(KERN_WARNING |
926 | "FAT: Couldn't remove the long name slots\n"); | 926 | "FAT: Couldn't remove the long name slots\n"); |
927 | } | 927 | } |
928 | } | 928 | } |
929 | 929 | ||
930 | dir->i_mtime = dir->i_atime = CURRENT_TIME_SEC; | 930 | dir->i_mtime = dir->i_atime = CURRENT_TIME_SEC; |
931 | if (IS_DIRSYNC(dir)) | 931 | if (IS_DIRSYNC(dir)) |
932 | (void)fat_sync_inode(dir); | 932 | (void)fat_sync_inode(dir); |
933 | else | 933 | else |
934 | mark_inode_dirty(dir); | 934 | mark_inode_dirty(dir); |
935 | 935 | ||
936 | return 0; | 936 | return 0; |
937 | } | 937 | } |
938 | 938 | ||
939 | EXPORT_SYMBOL_GPL(fat_remove_entries); | 939 | EXPORT_SYMBOL_GPL(fat_remove_entries); |
940 | 940 | ||
941 | static int fat_zeroed_cluster(struct inode *dir, sector_t blknr, int nr_used, | 941 | static int fat_zeroed_cluster(struct inode *dir, sector_t blknr, int nr_used, |
942 | struct buffer_head **bhs, int nr_bhs) | 942 | struct buffer_head **bhs, int nr_bhs) |
943 | { | 943 | { |
944 | struct super_block *sb = dir->i_sb; | 944 | struct super_block *sb = dir->i_sb; |
945 | sector_t last_blknr = blknr + MSDOS_SB(sb)->sec_per_clus; | 945 | sector_t last_blknr = blknr + MSDOS_SB(sb)->sec_per_clus; |
946 | int err, i, n; | 946 | int err, i, n; |
947 | 947 | ||
948 | /* Zeroing the unused blocks on this cluster */ | 948 | /* Zeroing the unused blocks on this cluster */ |
949 | blknr += nr_used; | 949 | blknr += nr_used; |
950 | n = nr_used; | 950 | n = nr_used; |
951 | while (blknr < last_blknr) { | 951 | while (blknr < last_blknr) { |
952 | bhs[n] = sb_getblk(sb, blknr); | 952 | bhs[n] = sb_getblk(sb, blknr); |
953 | if (!bhs[n]) { | 953 | if (!bhs[n]) { |
954 | err = -ENOMEM; | 954 | err = -ENOMEM; |
955 | goto error; | 955 | goto error; |
956 | } | 956 | } |
957 | memset(bhs[n]->b_data, 0, sb->s_blocksize); | 957 | memset(bhs[n]->b_data, 0, sb->s_blocksize); |
958 | set_buffer_uptodate(bhs[n]); | 958 | set_buffer_uptodate(bhs[n]); |
959 | mark_buffer_dirty(bhs[n]); | 959 | mark_buffer_dirty(bhs[n]); |
960 | 960 | ||
961 | n++; | 961 | n++; |
962 | blknr++; | 962 | blknr++; |
963 | if (n == nr_bhs) { | 963 | if (n == nr_bhs) { |
964 | if (IS_DIRSYNC(dir)) { | 964 | if (IS_DIRSYNC(dir)) { |
965 | err = fat_sync_bhs(bhs, n); | 965 | err = fat_sync_bhs(bhs, n); |
966 | if (err) | 966 | if (err) |
967 | goto error; | 967 | goto error; |
968 | } | 968 | } |
969 | for (i = 0; i < n; i++) | 969 | for (i = 0; i < n; i++) |
970 | brelse(bhs[i]); | 970 | brelse(bhs[i]); |
971 | n = 0; | 971 | n = 0; |
972 | } | 972 | } |
973 | } | 973 | } |
974 | if (IS_DIRSYNC(dir)) { | 974 | if (IS_DIRSYNC(dir)) { |
975 | err = fat_sync_bhs(bhs, n); | 975 | err = fat_sync_bhs(bhs, n); |
976 | if (err) | 976 | if (err) |
977 | goto error; | 977 | goto error; |
978 | } | 978 | } |
979 | for (i = 0; i < n; i++) | 979 | for (i = 0; i < n; i++) |
980 | brelse(bhs[i]); | 980 | brelse(bhs[i]); |
981 | 981 | ||
982 | return 0; | 982 | return 0; |
983 | 983 | ||
984 | error: | 984 | error: |
985 | for (i = 0; i < n; i++) | 985 | for (i = 0; i < n; i++) |
986 | bforget(bhs[i]); | 986 | bforget(bhs[i]); |
987 | return err; | 987 | return err; |
988 | } | 988 | } |
989 | 989 | ||
990 | int fat_alloc_new_dir(struct inode *dir, struct timespec *ts) | 990 | int fat_alloc_new_dir(struct inode *dir, struct timespec *ts) |
991 | { | 991 | { |
992 | struct super_block *sb = dir->i_sb; | 992 | struct super_block *sb = dir->i_sb; |
993 | struct msdos_sb_info *sbi = MSDOS_SB(sb); | 993 | struct msdos_sb_info *sbi = MSDOS_SB(sb); |
994 | struct buffer_head *bhs[MAX_BUF_PER_PAGE]; | 994 | struct buffer_head *bhs[MAX_BUF_PER_PAGE]; |
995 | struct msdos_dir_entry *de; | 995 | struct msdos_dir_entry *de; |
996 | sector_t blknr; | 996 | sector_t blknr; |
997 | __le16 date, time; | 997 | __le16 date, time; |
998 | int err, cluster; | 998 | int err, cluster; |
999 | 999 | ||
1000 | err = fat_alloc_clusters(dir, &cluster, 1); | 1000 | err = fat_alloc_clusters(dir, &cluster, 1); |
1001 | if (err) | 1001 | if (err) |
1002 | goto error; | 1002 | goto error; |
1003 | 1003 | ||
1004 | blknr = fat_clus_to_blknr(sbi, cluster); | 1004 | blknr = fat_clus_to_blknr(sbi, cluster); |
1005 | bhs[0] = sb_getblk(sb, blknr); | 1005 | bhs[0] = sb_getblk(sb, blknr); |
1006 | if (!bhs[0]) { | 1006 | if (!bhs[0]) { |
1007 | err = -ENOMEM; | 1007 | err = -ENOMEM; |
1008 | goto error_free; | 1008 | goto error_free; |
1009 | } | 1009 | } |
1010 | 1010 | ||
1011 | fat_date_unix2dos(ts->tv_sec, &time, &date); | 1011 | fat_date_unix2dos(ts->tv_sec, &time, &date); |
1012 | 1012 | ||
1013 | de = (struct msdos_dir_entry *)bhs[0]->b_data; | 1013 | de = (struct msdos_dir_entry *)bhs[0]->b_data; |
1014 | /* filling the new directory slots ("." and ".." entries) */ | 1014 | /* filling the new directory slots ("." and ".." entries) */ |
1015 | memcpy(de[0].name, MSDOS_DOT, MSDOS_NAME); | 1015 | memcpy(de[0].name, MSDOS_DOT, MSDOS_NAME); |
1016 | memcpy(de[1].name, MSDOS_DOTDOT, MSDOS_NAME); | 1016 | memcpy(de[1].name, MSDOS_DOTDOT, MSDOS_NAME); |
1017 | de->attr = de[1].attr = ATTR_DIR; | 1017 | de->attr = de[1].attr = ATTR_DIR; |
1018 | de[0].lcase = de[1].lcase = 0; | 1018 | de[0].lcase = de[1].lcase = 0; |
1019 | de[0].time = de[1].time = time; | 1019 | de[0].time = de[1].time = time; |
1020 | de[0].date = de[1].date = date; | 1020 | de[0].date = de[1].date = date; |
1021 | de[0].ctime_cs = de[1].ctime_cs = 0; | 1021 | de[0].ctime_cs = de[1].ctime_cs = 0; |
1022 | if (sbi->options.isvfat) { | 1022 | if (sbi->options.isvfat) { |
1023 | /* extra timestamps */ | 1023 | /* extra timestamps */ |
1024 | de[0].ctime = de[1].ctime = time; | 1024 | de[0].ctime = de[1].ctime = time; |
1025 | de[0].adate = de[0].cdate = de[1].adate = de[1].cdate = date; | 1025 | de[0].adate = de[0].cdate = de[1].adate = de[1].cdate = date; |
1026 | } else { | 1026 | } else { |
1027 | de[0].ctime = de[1].ctime = 0; | 1027 | de[0].ctime = de[1].ctime = 0; |
1028 | de[0].adate = de[0].cdate = de[1].adate = de[1].cdate = 0; | 1028 | de[0].adate = de[0].cdate = de[1].adate = de[1].cdate = 0; |
1029 | } | 1029 | } |
1030 | de[0].start = cpu_to_le16(cluster); | 1030 | de[0].start = cpu_to_le16(cluster); |
1031 | de[0].starthi = cpu_to_le16(cluster >> 16); | 1031 | de[0].starthi = cpu_to_le16(cluster >> 16); |
1032 | de[1].start = cpu_to_le16(MSDOS_I(dir)->i_logstart); | 1032 | de[1].start = cpu_to_le16(MSDOS_I(dir)->i_logstart); |
1033 | de[1].starthi = cpu_to_le16(MSDOS_I(dir)->i_logstart >> 16); | 1033 | de[1].starthi = cpu_to_le16(MSDOS_I(dir)->i_logstart >> 16); |
1034 | de[0].size = de[1].size = 0; | 1034 | de[0].size = de[1].size = 0; |
1035 | memset(de + 2, 0, sb->s_blocksize - 2 * sizeof(*de)); | 1035 | memset(de + 2, 0, sb->s_blocksize - 2 * sizeof(*de)); |
1036 | set_buffer_uptodate(bhs[0]); | 1036 | set_buffer_uptodate(bhs[0]); |
1037 | mark_buffer_dirty(bhs[0]); | 1037 | mark_buffer_dirty(bhs[0]); |
1038 | 1038 | ||
1039 | err = fat_zeroed_cluster(dir, blknr, 1, bhs, MAX_BUF_PER_PAGE); | 1039 | err = fat_zeroed_cluster(dir, blknr, 1, bhs, MAX_BUF_PER_PAGE); |
1040 | if (err) | 1040 | if (err) |
1041 | goto error_free; | 1041 | goto error_free; |
1042 | 1042 | ||
1043 | return cluster; | 1043 | return cluster; |
1044 | 1044 | ||
1045 | error_free: | 1045 | error_free: |
1046 | fat_free_clusters(dir, cluster); | 1046 | fat_free_clusters(dir, cluster); |
1047 | error: | 1047 | error: |
1048 | return err; | 1048 | return err; |
1049 | } | 1049 | } |
1050 | 1050 | ||
1051 | EXPORT_SYMBOL_GPL(fat_alloc_new_dir); | 1051 | EXPORT_SYMBOL_GPL(fat_alloc_new_dir); |
1052 | 1052 | ||
1053 | static int fat_add_new_entries(struct inode *dir, void *slots, int nr_slots, | 1053 | static int fat_add_new_entries(struct inode *dir, void *slots, int nr_slots, |
1054 | int *nr_cluster, struct msdos_dir_entry **de, | 1054 | int *nr_cluster, struct msdos_dir_entry **de, |
1055 | struct buffer_head **bh, loff_t *i_pos) | 1055 | struct buffer_head **bh, loff_t *i_pos) |
1056 | { | 1056 | { |
1057 | struct super_block *sb = dir->i_sb; | 1057 | struct super_block *sb = dir->i_sb; |
1058 | struct msdos_sb_info *sbi = MSDOS_SB(sb); | 1058 | struct msdos_sb_info *sbi = MSDOS_SB(sb); |
1059 | struct buffer_head *bhs[MAX_BUF_PER_PAGE]; | 1059 | struct buffer_head *bhs[MAX_BUF_PER_PAGE]; |
1060 | sector_t blknr, start_blknr, last_blknr; | 1060 | sector_t blknr, start_blknr, last_blknr; |
1061 | unsigned long size, copy; | 1061 | unsigned long size, copy; |
1062 | int err, i, n, offset, cluster[2]; | 1062 | int err, i, n, offset, cluster[2]; |
1063 | 1063 | ||
1064 | /* | 1064 | /* |
1065 | * The minimum cluster size is 512bytes, and maximum entry | 1065 | * The minimum cluster size is 512bytes, and maximum entry |
1066 | * size is 32*slots (672bytes). So, iff the cluster size is | 1066 | * size is 32*slots (672bytes). So, iff the cluster size is |
1067 | * 512bytes, we may need two clusters. | 1067 | * 512bytes, we may need two clusters. |
1068 | */ | 1068 | */ |
1069 | size = nr_slots * sizeof(struct msdos_dir_entry); | 1069 | size = nr_slots * sizeof(struct msdos_dir_entry); |
1070 | *nr_cluster = (size + (sbi->cluster_size - 1)) >> sbi->cluster_bits; | 1070 | *nr_cluster = (size + (sbi->cluster_size - 1)) >> sbi->cluster_bits; |
1071 | BUG_ON(*nr_cluster > 2); | 1071 | BUG_ON(*nr_cluster > 2); |
1072 | 1072 | ||
1073 | err = fat_alloc_clusters(dir, cluster, *nr_cluster); | 1073 | err = fat_alloc_clusters(dir, cluster, *nr_cluster); |
1074 | if (err) | 1074 | if (err) |
1075 | goto error; | 1075 | goto error; |
1076 | 1076 | ||
1077 | /* | 1077 | /* |
1078 | * First stage: Fill the directory entry. NOTE: This cluster | 1078 | * First stage: Fill the directory entry. NOTE: This cluster |
1079 | * is not referenced from any inode yet, so updates order is | 1079 | * is not referenced from any inode yet, so updates order is |
1080 | * not important. | 1080 | * not important. |
1081 | */ | 1081 | */ |
1082 | i = n = copy = 0; | 1082 | i = n = copy = 0; |
1083 | do { | 1083 | do { |
1084 | start_blknr = blknr = fat_clus_to_blknr(sbi, cluster[i]); | 1084 | start_blknr = blknr = fat_clus_to_blknr(sbi, cluster[i]); |
1085 | last_blknr = start_blknr + sbi->sec_per_clus; | 1085 | last_blknr = start_blknr + sbi->sec_per_clus; |
1086 | while (blknr < last_blknr) { | 1086 | while (blknr < last_blknr) { |
1087 | bhs[n] = sb_getblk(sb, blknr); | 1087 | bhs[n] = sb_getblk(sb, blknr); |
1088 | if (!bhs[n]) { | 1088 | if (!bhs[n]) { |
1089 | err = -ENOMEM; | 1089 | err = -ENOMEM; |
1090 | goto error_nomem; | 1090 | goto error_nomem; |
1091 | } | 1091 | } |
1092 | 1092 | ||
1093 | /* fill the directory entry */ | 1093 | /* fill the directory entry */ |
1094 | copy = min(size, sb->s_blocksize); | 1094 | copy = min(size, sb->s_blocksize); |
1095 | memcpy(bhs[n]->b_data, slots, copy); | 1095 | memcpy(bhs[n]->b_data, slots, copy); |
1096 | slots += copy; | 1096 | slots += copy; |
1097 | size -= copy; | 1097 | size -= copy; |
1098 | set_buffer_uptodate(bhs[n]); | 1098 | set_buffer_uptodate(bhs[n]); |
1099 | mark_buffer_dirty(bhs[n]); | 1099 | mark_buffer_dirty(bhs[n]); |
1100 | if (!size) | 1100 | if (!size) |
1101 | break; | 1101 | break; |
1102 | n++; | 1102 | n++; |
1103 | blknr++; | 1103 | blknr++; |
1104 | } | 1104 | } |
1105 | } while (++i < *nr_cluster); | 1105 | } while (++i < *nr_cluster); |
1106 | 1106 | ||
1107 | memset(bhs[n]->b_data + copy, 0, sb->s_blocksize - copy); | 1107 | memset(bhs[n]->b_data + copy, 0, sb->s_blocksize - copy); |
1108 | offset = copy - sizeof(struct msdos_dir_entry); | 1108 | offset = copy - sizeof(struct msdos_dir_entry); |
1109 | get_bh(bhs[n]); | 1109 | get_bh(bhs[n]); |
1110 | *bh = bhs[n]; | 1110 | *bh = bhs[n]; |
1111 | *de = (struct msdos_dir_entry *)((*bh)->b_data + offset); | 1111 | *de = (struct msdos_dir_entry *)((*bh)->b_data + offset); |
1112 | *i_pos = fat_make_i_pos(sb, *bh, *de); | 1112 | *i_pos = fat_make_i_pos(sb, *bh, *de); |
1113 | 1113 | ||
1114 | /* Second stage: clear the rest of cluster, and write outs */ | 1114 | /* Second stage: clear the rest of cluster, and write outs */ |
1115 | err = fat_zeroed_cluster(dir, start_blknr, ++n, bhs, MAX_BUF_PER_PAGE); | 1115 | err = fat_zeroed_cluster(dir, start_blknr, ++n, bhs, MAX_BUF_PER_PAGE); |
1116 | if (err) | 1116 | if (err) |
1117 | goto error_free; | 1117 | goto error_free; |
1118 | 1118 | ||
1119 | return cluster[0]; | 1119 | return cluster[0]; |
1120 | 1120 | ||
1121 | error_free: | 1121 | error_free: |
1122 | brelse(*bh); | 1122 | brelse(*bh); |
1123 | *bh = NULL; | 1123 | *bh = NULL; |
1124 | n = 0; | 1124 | n = 0; |
1125 | error_nomem: | 1125 | error_nomem: |
1126 | for (i = 0; i < n; i++) | 1126 | for (i = 0; i < n; i++) |
1127 | bforget(bhs[i]); | 1127 | bforget(bhs[i]); |
1128 | fat_free_clusters(dir, cluster[0]); | 1128 | fat_free_clusters(dir, cluster[0]); |
1129 | error: | 1129 | error: |
1130 | return err; | 1130 | return err; |
1131 | } | 1131 | } |
1132 | 1132 | ||
1133 | int fat_add_entries(struct inode *dir, void *slots, int nr_slots, | 1133 | int fat_add_entries(struct inode *dir, void *slots, int nr_slots, |
1134 | struct fat_slot_info *sinfo) | 1134 | struct fat_slot_info *sinfo) |
1135 | { | 1135 | { |
1136 | struct super_block *sb = dir->i_sb; | 1136 | struct super_block *sb = dir->i_sb; |
1137 | struct msdos_sb_info *sbi = MSDOS_SB(sb); | 1137 | struct msdos_sb_info *sbi = MSDOS_SB(sb); |
1138 | struct buffer_head *bh, *prev, *bhs[3]; /* 32*slots (672bytes) */ | 1138 | struct buffer_head *bh, *prev, *bhs[3]; /* 32*slots (672bytes) */ |
1139 | struct msdos_dir_entry *de; | 1139 | struct msdos_dir_entry *de; |
1140 | int err, free_slots, i, nr_bhs; | 1140 | int err, free_slots, i, nr_bhs; |
1141 | loff_t pos, i_pos; | 1141 | loff_t pos, i_pos; |
1142 | 1142 | ||
1143 | sinfo->nr_slots = nr_slots; | 1143 | sinfo->nr_slots = nr_slots; |
1144 | 1144 | ||
1145 | /* First stage: search free direcotry entries */ | 1145 | /* First stage: search free direcotry entries */ |
1146 | free_slots = nr_bhs = 0; | 1146 | free_slots = nr_bhs = 0; |
1147 | bh = prev = NULL; | 1147 | bh = prev = NULL; |
1148 | pos = 0; | 1148 | pos = 0; |
1149 | err = -ENOSPC; | 1149 | err = -ENOSPC; |
1150 | while (fat_get_entry(dir, &pos, &bh, &de) > -1) { | 1150 | while (fat_get_entry(dir, &pos, &bh, &de) > -1) { |
1151 | /* check the maximum size of directory */ | 1151 | /* check the maximum size of directory */ |
1152 | if (pos >= FAT_MAX_DIR_SIZE) | 1152 | if (pos >= FAT_MAX_DIR_SIZE) |
1153 | goto error; | 1153 | goto error; |
1154 | 1154 | ||
1155 | if (IS_FREE(de->name)) { | 1155 | if (IS_FREE(de->name)) { |
1156 | if (prev != bh) { | 1156 | if (prev != bh) { |
1157 | get_bh(bh); | 1157 | get_bh(bh); |
1158 | bhs[nr_bhs] = prev = bh; | 1158 | bhs[nr_bhs] = prev = bh; |
1159 | nr_bhs++; | 1159 | nr_bhs++; |
1160 | } | 1160 | } |
1161 | free_slots++; | 1161 | free_slots++; |
1162 | if (free_slots == nr_slots) | 1162 | if (free_slots == nr_slots) |
1163 | goto found; | 1163 | goto found; |
1164 | } else { | 1164 | } else { |
1165 | for (i = 0; i < nr_bhs; i++) | 1165 | for (i = 0; i < nr_bhs; i++) |
1166 | brelse(bhs[i]); | 1166 | brelse(bhs[i]); |
1167 | prev = NULL; | 1167 | prev = NULL; |
1168 | free_slots = nr_bhs = 0; | 1168 | free_slots = nr_bhs = 0; |
1169 | } | 1169 | } |
1170 | } | 1170 | } |
1171 | if (dir->i_ino == MSDOS_ROOT_INO) { | 1171 | if (dir->i_ino == MSDOS_ROOT_INO) { |
1172 | if (sbi->fat_bits != 32) | 1172 | if (sbi->fat_bits != 32) |
1173 | goto error; | 1173 | goto error; |
1174 | } else if (MSDOS_I(dir)->i_start == 0) { | 1174 | } else if (MSDOS_I(dir)->i_start == 0) { |
1175 | printk(KERN_ERR "FAT: Corrupted directory (i_pos %lld)\n", | 1175 | printk(KERN_ERR "FAT: Corrupted directory (i_pos %lld)\n", |
1176 | MSDOS_I(dir)->i_pos); | 1176 | MSDOS_I(dir)->i_pos); |
1177 | err = -EIO; | 1177 | err = -EIO; |
1178 | goto error; | 1178 | goto error; |
1179 | } | 1179 | } |
1180 | 1180 | ||
1181 | found: | 1181 | found: |
1182 | err = 0; | 1182 | err = 0; |
1183 | pos -= free_slots * sizeof(*de); | 1183 | pos -= free_slots * sizeof(*de); |
1184 | nr_slots -= free_slots; | 1184 | nr_slots -= free_slots; |
1185 | if (free_slots) { | 1185 | if (free_slots) { |
1186 | /* | 1186 | /* |
1187 | * Second stage: filling the free entries with new entries. | 1187 | * Second stage: filling the free entries with new entries. |
1188 | * NOTE: If this slots has shortname, first, we write | 1188 | * NOTE: If this slots has shortname, first, we write |
1189 | * the long name slots, then write the short name. | 1189 | * the long name slots, then write the short name. |
1190 | */ | 1190 | */ |
1191 | int size = free_slots * sizeof(*de); | 1191 | int size = free_slots * sizeof(*de); |
1192 | int offset = pos & (sb->s_blocksize - 1); | 1192 | int offset = pos & (sb->s_blocksize - 1); |
1193 | int long_bhs = nr_bhs - (nr_slots == 0); | 1193 | int long_bhs = nr_bhs - (nr_slots == 0); |
1194 | 1194 | ||
1195 | /* Fill the long name slots. */ | 1195 | /* Fill the long name slots. */ |
1196 | for (i = 0; i < long_bhs; i++) { | 1196 | for (i = 0; i < long_bhs; i++) { |
1197 | int copy = min_t(int, sb->s_blocksize - offset, size); | 1197 | int copy = min_t(int, sb->s_blocksize - offset, size); |
1198 | memcpy(bhs[i]->b_data + offset, slots, copy); | 1198 | memcpy(bhs[i]->b_data + offset, slots, copy); |
1199 | mark_buffer_dirty(bhs[i]); | 1199 | mark_buffer_dirty(bhs[i]); |
1200 | offset = 0; | 1200 | offset = 0; |
1201 | slots += copy; | 1201 | slots += copy; |
1202 | size -= copy; | 1202 | size -= copy; |
1203 | } | 1203 | } |
1204 | if (long_bhs && IS_DIRSYNC(dir)) | 1204 | if (long_bhs && IS_DIRSYNC(dir)) |
1205 | err = fat_sync_bhs(bhs, long_bhs); | 1205 | err = fat_sync_bhs(bhs, long_bhs); |
1206 | if (!err && i < nr_bhs) { | 1206 | if (!err && i < nr_bhs) { |
1207 | /* Fill the short name slot. */ | 1207 | /* Fill the short name slot. */ |
1208 | int copy = min_t(int, sb->s_blocksize - offset, size); | 1208 | int copy = min_t(int, sb->s_blocksize - offset, size); |
1209 | memcpy(bhs[i]->b_data + offset, slots, copy); | 1209 | memcpy(bhs[i]->b_data + offset, slots, copy); |
1210 | mark_buffer_dirty(bhs[i]); | 1210 | mark_buffer_dirty(bhs[i]); |
1211 | if (IS_DIRSYNC(dir)) | 1211 | if (IS_DIRSYNC(dir)) |
1212 | err = sync_dirty_buffer(bhs[i]); | 1212 | err = sync_dirty_buffer(bhs[i]); |
1213 | } | 1213 | } |
1214 | for (i = 0; i < nr_bhs; i++) | 1214 | for (i = 0; i < nr_bhs; i++) |
1215 | brelse(bhs[i]); | 1215 | brelse(bhs[i]); |
1216 | if (err) | 1216 | if (err) |
1217 | goto error_remove; | 1217 | goto error_remove; |
1218 | } | 1218 | } |
1219 | 1219 | ||
1220 | if (nr_slots) { | 1220 | if (nr_slots) { |
1221 | int cluster, nr_cluster; | 1221 | int cluster, nr_cluster; |
1222 | 1222 | ||
1223 | /* | 1223 | /* |
1224 | * Third stage: allocate the cluster for new entries. | 1224 | * Third stage: allocate the cluster for new entries. |
1225 | * And initialize the cluster with new entries, then | 1225 | * And initialize the cluster with new entries, then |
1226 | * add the cluster to dir. | 1226 | * add the cluster to dir. |
1227 | */ | 1227 | */ |
1228 | cluster = fat_add_new_entries(dir, slots, nr_slots, &nr_cluster, | 1228 | cluster = fat_add_new_entries(dir, slots, nr_slots, &nr_cluster, |
1229 | &de, &bh, &i_pos); | 1229 | &de, &bh, &i_pos); |
1230 | if (cluster < 0) { | 1230 | if (cluster < 0) { |
1231 | err = cluster; | 1231 | err = cluster; |
1232 | goto error_remove; | 1232 | goto error_remove; |
1233 | } | 1233 | } |
1234 | err = fat_chain_add(dir, cluster, nr_cluster); | 1234 | err = fat_chain_add(dir, cluster, nr_cluster); |
1235 | if (err) { | 1235 | if (err) { |
1236 | fat_free_clusters(dir, cluster); | 1236 | fat_free_clusters(dir, cluster); |
1237 | goto error_remove; | 1237 | goto error_remove; |
1238 | } | 1238 | } |
1239 | if (dir->i_size & (sbi->cluster_size - 1)) { | 1239 | if (dir->i_size & (sbi->cluster_size - 1)) { |
1240 | fat_fs_panic(sb, "Odd directory size"); | 1240 | fat_fs_panic(sb, "Odd directory size"); |
1241 | dir->i_size = (dir->i_size + sbi->cluster_size - 1) | 1241 | dir->i_size = (dir->i_size + sbi->cluster_size - 1) |
1242 | & ~((loff_t)sbi->cluster_size - 1); | 1242 | & ~((loff_t)sbi->cluster_size - 1); |
1243 | } | 1243 | } |
1244 | dir->i_size += nr_cluster << sbi->cluster_bits; | 1244 | dir->i_size += nr_cluster << sbi->cluster_bits; |
1245 | MSDOS_I(dir)->mmu_private += nr_cluster << sbi->cluster_bits; | 1245 | MSDOS_I(dir)->mmu_private += nr_cluster << sbi->cluster_bits; |
1246 | } | 1246 | } |
1247 | sinfo->slot_off = pos; | 1247 | sinfo->slot_off = pos; |
1248 | sinfo->de = de; | 1248 | sinfo->de = de; |
1249 | sinfo->bh = bh; | 1249 | sinfo->bh = bh; |
1250 | sinfo->i_pos = fat_make_i_pos(sb, sinfo->bh, sinfo->de); | 1250 | sinfo->i_pos = fat_make_i_pos(sb, sinfo->bh, sinfo->de); |
1251 | 1251 | ||
1252 | return 0; | 1252 | return 0; |
1253 | 1253 | ||
1254 | error: | 1254 | error: |
1255 | brelse(bh); | 1255 | brelse(bh); |
1256 | for (i = 0; i < nr_bhs; i++) | 1256 | for (i = 0; i < nr_bhs; i++) |
1257 | brelse(bhs[i]); | 1257 | brelse(bhs[i]); |
1258 | return err; | 1258 | return err; |
1259 | 1259 | ||
1260 | error_remove: | 1260 | error_remove: |
1261 | brelse(bh); | 1261 | brelse(bh); |
1262 | if (free_slots) | 1262 | if (free_slots) |
1263 | __fat_remove_entries(dir, pos, free_slots); | 1263 | __fat_remove_entries(dir, pos, free_slots); |
1264 | return err; | 1264 | return err; |
1265 | } | 1265 | } |
1266 | 1266 | ||
1267 | EXPORT_SYMBOL_GPL(fat_add_entries); | 1267 | EXPORT_SYMBOL_GPL(fat_add_entries); |
1268 | 1268 |
fs/fat/inode.c
1 | /* | 1 | /* |
2 | * linux/fs/fat/inode.c | 2 | * linux/fs/fat/inode.c |
3 | * | 3 | * |
4 | * Written 1992,1993 by Werner Almesberger | 4 | * Written 1992,1993 by Werner Almesberger |
5 | * VFAT extensions by Gordon Chaffee, merged with msdos fs by Henrik Storner | 5 | * VFAT extensions by Gordon Chaffee, merged with msdos fs by Henrik Storner |
6 | * Rewritten for the constant inumbers support by Al Viro | 6 | * Rewritten for the constant inumbers support by Al Viro |
7 | * | 7 | * |
8 | * Fixes: | 8 | * Fixes: |
9 | * | 9 | * |
10 | * Max Cohan: Fixed invalid FSINFO offset when info_sector is 0 | 10 | * Max Cohan: Fixed invalid FSINFO offset when info_sector is 0 |
11 | */ | 11 | */ |
12 | 12 | ||
13 | #include <linux/module.h> | 13 | #include <linux/module.h> |
14 | #include <linux/init.h> | 14 | #include <linux/init.h> |
15 | #include <linux/time.h> | 15 | #include <linux/time.h> |
16 | #include <linux/slab.h> | 16 | #include <linux/slab.h> |
17 | #include <linux/smp_lock.h> | 17 | #include <linux/smp_lock.h> |
18 | #include <linux/seq_file.h> | 18 | #include <linux/seq_file.h> |
19 | #include <linux/msdos_fs.h> | 19 | #include <linux/msdos_fs.h> |
20 | #include <linux/pagemap.h> | 20 | #include <linux/pagemap.h> |
21 | #include <linux/mpage.h> | 21 | #include <linux/mpage.h> |
22 | #include <linux/buffer_head.h> | 22 | #include <linux/buffer_head.h> |
23 | #include <linux/mount.h> | 23 | #include <linux/mount.h> |
24 | #include <linux/vfs.h> | 24 | #include <linux/vfs.h> |
25 | #include <linux/parser.h> | 25 | #include <linux/parser.h> |
26 | #include <linux/uio.h> | 26 | #include <linux/uio.h> |
27 | #include <asm/unaligned.h> | 27 | #include <asm/unaligned.h> |
28 | 28 | ||
29 | #ifndef CONFIG_FAT_DEFAULT_IOCHARSET | 29 | #ifndef CONFIG_FAT_DEFAULT_IOCHARSET |
30 | /* if user don't select VFAT, this is undefined. */ | 30 | /* if user don't select VFAT, this is undefined. */ |
31 | #define CONFIG_FAT_DEFAULT_IOCHARSET "" | 31 | #define CONFIG_FAT_DEFAULT_IOCHARSET "" |
32 | #endif | 32 | #endif |
33 | 33 | ||
34 | static int fat_default_codepage = CONFIG_FAT_DEFAULT_CODEPAGE; | 34 | static int fat_default_codepage = CONFIG_FAT_DEFAULT_CODEPAGE; |
35 | static char fat_default_iocharset[] = CONFIG_FAT_DEFAULT_IOCHARSET; | 35 | static char fat_default_iocharset[] = CONFIG_FAT_DEFAULT_IOCHARSET; |
36 | 36 | ||
37 | 37 | ||
38 | static int fat_add_cluster(struct inode *inode) | 38 | static int fat_add_cluster(struct inode *inode) |
39 | { | 39 | { |
40 | int err, cluster; | 40 | int err, cluster; |
41 | 41 | ||
42 | err = fat_alloc_clusters(inode, &cluster, 1); | 42 | err = fat_alloc_clusters(inode, &cluster, 1); |
43 | if (err) | 43 | if (err) |
44 | return err; | 44 | return err; |
45 | /* FIXME: this cluster should be added after data of this | 45 | /* FIXME: this cluster should be added after data of this |
46 | * cluster is writed */ | 46 | * cluster is writed */ |
47 | err = fat_chain_add(inode, cluster, 1); | 47 | err = fat_chain_add(inode, cluster, 1); |
48 | if (err) | 48 | if (err) |
49 | fat_free_clusters(inode, cluster); | 49 | fat_free_clusters(inode, cluster); |
50 | return err; | 50 | return err; |
51 | } | 51 | } |
52 | 52 | ||
53 | static int __fat_get_blocks(struct inode *inode, sector_t iblock, | 53 | static int __fat_get_blocks(struct inode *inode, sector_t iblock, |
54 | unsigned long *max_blocks, | 54 | unsigned long *max_blocks, |
55 | struct buffer_head *bh_result, int create) | 55 | struct buffer_head *bh_result, int create) |
56 | { | 56 | { |
57 | struct super_block *sb = inode->i_sb; | 57 | struct super_block *sb = inode->i_sb; |
58 | struct msdos_sb_info *sbi = MSDOS_SB(sb); | 58 | struct msdos_sb_info *sbi = MSDOS_SB(sb); |
59 | sector_t phys; | 59 | sector_t phys; |
60 | unsigned long mapped_blocks; | 60 | unsigned long mapped_blocks; |
61 | int err, offset; | 61 | int err, offset; |
62 | 62 | ||
63 | err = fat_bmap(inode, iblock, &phys, &mapped_blocks); | 63 | err = fat_bmap(inode, iblock, &phys, &mapped_blocks); |
64 | if (err) | 64 | if (err) |
65 | return err; | 65 | return err; |
66 | if (phys) { | 66 | if (phys) { |
67 | map_bh(bh_result, sb, phys); | 67 | map_bh(bh_result, sb, phys); |
68 | *max_blocks = min(mapped_blocks, *max_blocks); | 68 | *max_blocks = min(mapped_blocks, *max_blocks); |
69 | return 0; | 69 | return 0; |
70 | } | 70 | } |
71 | if (!create) | 71 | if (!create) |
72 | return 0; | 72 | return 0; |
73 | 73 | ||
74 | if (iblock != MSDOS_I(inode)->mmu_private >> sb->s_blocksize_bits) { | 74 | if (iblock != MSDOS_I(inode)->mmu_private >> sb->s_blocksize_bits) { |
75 | fat_fs_panic(sb, "corrupted file size (i_pos %lld, %lld)", | 75 | fat_fs_panic(sb, "corrupted file size (i_pos %lld, %lld)", |
76 | MSDOS_I(inode)->i_pos, MSDOS_I(inode)->mmu_private); | 76 | MSDOS_I(inode)->i_pos, MSDOS_I(inode)->mmu_private); |
77 | return -EIO; | 77 | return -EIO; |
78 | } | 78 | } |
79 | 79 | ||
80 | offset = (unsigned long)iblock & (sbi->sec_per_clus - 1); | 80 | offset = (unsigned long)iblock & (sbi->sec_per_clus - 1); |
81 | if (!offset) { | 81 | if (!offset) { |
82 | /* TODO: multiple cluster allocation would be desirable. */ | 82 | /* TODO: multiple cluster allocation would be desirable. */ |
83 | err = fat_add_cluster(inode); | 83 | err = fat_add_cluster(inode); |
84 | if (err) | 84 | if (err) |
85 | return err; | 85 | return err; |
86 | } | 86 | } |
87 | /* available blocks on this cluster */ | 87 | /* available blocks on this cluster */ |
88 | mapped_blocks = sbi->sec_per_clus - offset; | 88 | mapped_blocks = sbi->sec_per_clus - offset; |
89 | 89 | ||
90 | *max_blocks = min(mapped_blocks, *max_blocks); | 90 | *max_blocks = min(mapped_blocks, *max_blocks); |
91 | MSDOS_I(inode)->mmu_private += *max_blocks << sb->s_blocksize_bits; | 91 | MSDOS_I(inode)->mmu_private += *max_blocks << sb->s_blocksize_bits; |
92 | 92 | ||
93 | err = fat_bmap(inode, iblock, &phys, &mapped_blocks); | 93 | err = fat_bmap(inode, iblock, &phys, &mapped_blocks); |
94 | if (err) | 94 | if (err) |
95 | return err; | 95 | return err; |
96 | BUG_ON(!phys); | 96 | BUG_ON(!phys); |
97 | BUG_ON(*max_blocks != mapped_blocks); | 97 | BUG_ON(*max_blocks != mapped_blocks); |
98 | set_buffer_new(bh_result); | 98 | set_buffer_new(bh_result); |
99 | map_bh(bh_result, sb, phys); | 99 | map_bh(bh_result, sb, phys); |
100 | return 0; | 100 | return 0; |
101 | } | 101 | } |
102 | 102 | ||
103 | static int fat_get_blocks(struct inode *inode, sector_t iblock, | 103 | static int fat_get_blocks(struct inode *inode, sector_t iblock, |
104 | unsigned long max_blocks, | 104 | unsigned long max_blocks, |
105 | struct buffer_head *bh_result, int create) | 105 | struct buffer_head *bh_result, int create) |
106 | { | 106 | { |
107 | struct super_block *sb = inode->i_sb; | 107 | struct super_block *sb = inode->i_sb; |
108 | int err; | 108 | int err; |
109 | 109 | ||
110 | err = __fat_get_blocks(inode, iblock, &max_blocks, bh_result, create); | 110 | err = __fat_get_blocks(inode, iblock, &max_blocks, bh_result, create); |
111 | if (err) | 111 | if (err) |
112 | return err; | 112 | return err; |
113 | bh_result->b_size = max_blocks << sb->s_blocksize_bits; | 113 | bh_result->b_size = max_blocks << sb->s_blocksize_bits; |
114 | return 0; | 114 | return 0; |
115 | } | 115 | } |
116 | 116 | ||
117 | static int fat_get_block(struct inode *inode, sector_t iblock, | 117 | static int fat_get_block(struct inode *inode, sector_t iblock, |
118 | struct buffer_head *bh_result, int create) | 118 | struct buffer_head *bh_result, int create) |
119 | { | 119 | { |
120 | unsigned long max_blocks = 1; | 120 | unsigned long max_blocks = 1; |
121 | return __fat_get_blocks(inode, iblock, &max_blocks, bh_result, create); | 121 | return __fat_get_blocks(inode, iblock, &max_blocks, bh_result, create); |
122 | } | 122 | } |
123 | 123 | ||
124 | static int fat_writepage(struct page *page, struct writeback_control *wbc) | 124 | static int fat_writepage(struct page *page, struct writeback_control *wbc) |
125 | { | 125 | { |
126 | return block_write_full_page(page, fat_get_block, wbc); | 126 | return block_write_full_page(page, fat_get_block, wbc); |
127 | } | 127 | } |
128 | 128 | ||
129 | static int fat_writepages(struct address_space *mapping, | 129 | static int fat_writepages(struct address_space *mapping, |
130 | struct writeback_control *wbc) | 130 | struct writeback_control *wbc) |
131 | { | 131 | { |
132 | return mpage_writepages(mapping, wbc, fat_get_block); | 132 | return mpage_writepages(mapping, wbc, fat_get_block); |
133 | } | 133 | } |
134 | 134 | ||
135 | static int fat_readpage(struct file *file, struct page *page) | 135 | static int fat_readpage(struct file *file, struct page *page) |
136 | { | 136 | { |
137 | return mpage_readpage(page, fat_get_block); | 137 | return mpage_readpage(page, fat_get_block); |
138 | } | 138 | } |
139 | 139 | ||
140 | static int fat_readpages(struct file *file, struct address_space *mapping, | 140 | static int fat_readpages(struct file *file, struct address_space *mapping, |
141 | struct list_head *pages, unsigned nr_pages) | 141 | struct list_head *pages, unsigned nr_pages) |
142 | { | 142 | { |
143 | return mpage_readpages(mapping, pages, nr_pages, fat_get_block); | 143 | return mpage_readpages(mapping, pages, nr_pages, fat_get_block); |
144 | } | 144 | } |
145 | 145 | ||
146 | static int fat_prepare_write(struct file *file, struct page *page, | 146 | static int fat_prepare_write(struct file *file, struct page *page, |
147 | unsigned from, unsigned to) | 147 | unsigned from, unsigned to) |
148 | { | 148 | { |
149 | return cont_prepare_write(page, from, to, fat_get_block, | 149 | return cont_prepare_write(page, from, to, fat_get_block, |
150 | &MSDOS_I(page->mapping->host)->mmu_private); | 150 | &MSDOS_I(page->mapping->host)->mmu_private); |
151 | } | 151 | } |
152 | 152 | ||
153 | static int fat_commit_write(struct file *file, struct page *page, | 153 | static int fat_commit_write(struct file *file, struct page *page, |
154 | unsigned from, unsigned to) | 154 | unsigned from, unsigned to) |
155 | { | 155 | { |
156 | struct inode *inode = page->mapping->host; | 156 | struct inode *inode = page->mapping->host; |
157 | int err = generic_commit_write(file, page, from, to); | 157 | int err = generic_commit_write(file, page, from, to); |
158 | if (!err && !(MSDOS_I(inode)->i_attrs & ATTR_ARCH)) { | 158 | if (!err && !(MSDOS_I(inode)->i_attrs & ATTR_ARCH)) { |
159 | inode->i_mtime = inode->i_ctime = CURRENT_TIME_SEC; | 159 | inode->i_mtime = inode->i_ctime = CURRENT_TIME_SEC; |
160 | MSDOS_I(inode)->i_attrs |= ATTR_ARCH; | 160 | MSDOS_I(inode)->i_attrs |= ATTR_ARCH; |
161 | mark_inode_dirty(inode); | 161 | mark_inode_dirty(inode); |
162 | } | 162 | } |
163 | return err; | 163 | return err; |
164 | } | 164 | } |
165 | 165 | ||
166 | static ssize_t fat_direct_IO(int rw, struct kiocb *iocb, | 166 | static ssize_t fat_direct_IO(int rw, struct kiocb *iocb, |
167 | const struct iovec *iov, | 167 | const struct iovec *iov, |
168 | loff_t offset, unsigned long nr_segs) | 168 | loff_t offset, unsigned long nr_segs) |
169 | { | 169 | { |
170 | struct file *file = iocb->ki_filp; | 170 | struct file *file = iocb->ki_filp; |
171 | struct inode *inode = file->f_mapping->host; | 171 | struct inode *inode = file->f_mapping->host; |
172 | 172 | ||
173 | if (rw == WRITE) { | 173 | if (rw == WRITE) { |
174 | /* | 174 | /* |
175 | * FIXME: blockdev_direct_IO() doesn't use ->prepare_write(), | 175 | * FIXME: blockdev_direct_IO() doesn't use ->prepare_write(), |
176 | * so we need to update the ->mmu_private to block boundary. | 176 | * so we need to update the ->mmu_private to block boundary. |
177 | * | 177 | * |
178 | * But we must fill the remaining area or hole by nul for | 178 | * But we must fill the remaining area or hole by nul for |
179 | * updating ->mmu_private. | 179 | * updating ->mmu_private. |
180 | */ | 180 | */ |
181 | loff_t size = offset + iov_length(iov, nr_segs); | 181 | loff_t size = offset + iov_length(iov, nr_segs); |
182 | if (MSDOS_I(inode)->mmu_private < size) | 182 | if (MSDOS_I(inode)->mmu_private < size) |
183 | return -EINVAL; | 183 | return -EINVAL; |
184 | } | 184 | } |
185 | 185 | ||
186 | /* | 186 | /* |
187 | * FAT need to use the DIO_LOCKING for avoiding the race | 187 | * FAT need to use the DIO_LOCKING for avoiding the race |
188 | * condition of fat_get_block() and ->truncate(). | 188 | * condition of fat_get_block() and ->truncate(). |
189 | */ | 189 | */ |
190 | return blockdev_direct_IO(rw, iocb, inode, inode->i_sb->s_bdev, iov, | 190 | return blockdev_direct_IO(rw, iocb, inode, inode->i_sb->s_bdev, iov, |
191 | offset, nr_segs, fat_get_blocks, NULL); | 191 | offset, nr_segs, fat_get_blocks, NULL); |
192 | } | 192 | } |
193 | 193 | ||
194 | static sector_t _fat_bmap(struct address_space *mapping, sector_t block) | 194 | static sector_t _fat_bmap(struct address_space *mapping, sector_t block) |
195 | { | 195 | { |
196 | return generic_block_bmap(mapping, block, fat_get_block); | 196 | return generic_block_bmap(mapping, block, fat_get_block); |
197 | } | 197 | } |
198 | 198 | ||
199 | static struct address_space_operations fat_aops = { | 199 | static struct address_space_operations fat_aops = { |
200 | .readpage = fat_readpage, | 200 | .readpage = fat_readpage, |
201 | .readpages = fat_readpages, | 201 | .readpages = fat_readpages, |
202 | .writepage = fat_writepage, | 202 | .writepage = fat_writepage, |
203 | .writepages = fat_writepages, | 203 | .writepages = fat_writepages, |
204 | .sync_page = block_sync_page, | 204 | .sync_page = block_sync_page, |
205 | .prepare_write = fat_prepare_write, | 205 | .prepare_write = fat_prepare_write, |
206 | .commit_write = fat_commit_write, | 206 | .commit_write = fat_commit_write, |
207 | .direct_IO = fat_direct_IO, | 207 | .direct_IO = fat_direct_IO, |
208 | .bmap = _fat_bmap | 208 | .bmap = _fat_bmap |
209 | }; | 209 | }; |
210 | 210 | ||
211 | /* | 211 | /* |
212 | * New FAT inode stuff. We do the following: | 212 | * New FAT inode stuff. We do the following: |
213 | * a) i_ino is constant and has nothing with on-disk location. | 213 | * a) i_ino is constant and has nothing with on-disk location. |
214 | * b) FAT manages its own cache of directory entries. | 214 | * b) FAT manages its own cache of directory entries. |
215 | * c) *This* cache is indexed by on-disk location. | 215 | * c) *This* cache is indexed by on-disk location. |
216 | * d) inode has an associated directory entry, all right, but | 216 | * d) inode has an associated directory entry, all right, but |
217 | * it may be unhashed. | 217 | * it may be unhashed. |
218 | * e) currently entries are stored within struct inode. That should | 218 | * e) currently entries are stored within struct inode. That should |
219 | * change. | 219 | * change. |
220 | * f) we deal with races in the following way: | 220 | * f) we deal with races in the following way: |
221 | * 1. readdir() and lookup() do FAT-dir-cache lookup. | 221 | * 1. readdir() and lookup() do FAT-dir-cache lookup. |
222 | * 2. rename() unhashes the F-d-c entry and rehashes it in | 222 | * 2. rename() unhashes the F-d-c entry and rehashes it in |
223 | * a new place. | 223 | * a new place. |
224 | * 3. unlink() and rmdir() unhash F-d-c entry. | 224 | * 3. unlink() and rmdir() unhash F-d-c entry. |
225 | * 4. fat_write_inode() checks whether the thing is unhashed. | 225 | * 4. fat_write_inode() checks whether the thing is unhashed. |
226 | * If it is we silently return. If it isn't we do bread(), | 226 | * If it is we silently return. If it isn't we do bread(), |
227 | * check if the location is still valid and retry if it | 227 | * check if the location is still valid and retry if it |
228 | * isn't. Otherwise we do changes. | 228 | * isn't. Otherwise we do changes. |
229 | * 5. Spinlock is used to protect hash/unhash/location check/lookup | 229 | * 5. Spinlock is used to protect hash/unhash/location check/lookup |
230 | * 6. fat_clear_inode() unhashes the F-d-c entry. | 230 | * 6. fat_clear_inode() unhashes the F-d-c entry. |
231 | * 7. lookup() and readdir() do igrab() if they find a F-d-c entry | 231 | * 7. lookup() and readdir() do igrab() if they find a F-d-c entry |
232 | * and consider negative result as cache miss. | 232 | * and consider negative result as cache miss. |
233 | */ | 233 | */ |
234 | 234 | ||
235 | static void fat_hash_init(struct super_block *sb) | 235 | static void fat_hash_init(struct super_block *sb) |
236 | { | 236 | { |
237 | struct msdos_sb_info *sbi = MSDOS_SB(sb); | 237 | struct msdos_sb_info *sbi = MSDOS_SB(sb); |
238 | int i; | 238 | int i; |
239 | 239 | ||
240 | spin_lock_init(&sbi->inode_hash_lock); | 240 | spin_lock_init(&sbi->inode_hash_lock); |
241 | for (i = 0; i < FAT_HASH_SIZE; i++) | 241 | for (i = 0; i < FAT_HASH_SIZE; i++) |
242 | INIT_HLIST_HEAD(&sbi->inode_hashtable[i]); | 242 | INIT_HLIST_HEAD(&sbi->inode_hashtable[i]); |
243 | } | 243 | } |
244 | 244 | ||
245 | static inline unsigned long fat_hash(struct super_block *sb, loff_t i_pos) | 245 | static inline unsigned long fat_hash(struct super_block *sb, loff_t i_pos) |
246 | { | 246 | { |
247 | unsigned long tmp = (unsigned long)i_pos | (unsigned long) sb; | 247 | unsigned long tmp = (unsigned long)i_pos | (unsigned long) sb; |
248 | tmp = tmp + (tmp >> FAT_HASH_BITS) + (tmp >> FAT_HASH_BITS * 2); | 248 | tmp = tmp + (tmp >> FAT_HASH_BITS) + (tmp >> FAT_HASH_BITS * 2); |
249 | return tmp & FAT_HASH_MASK; | 249 | return tmp & FAT_HASH_MASK; |
250 | } | 250 | } |
251 | 251 | ||
252 | void fat_attach(struct inode *inode, loff_t i_pos) | 252 | void fat_attach(struct inode *inode, loff_t i_pos) |
253 | { | 253 | { |
254 | struct super_block *sb = inode->i_sb; | 254 | struct super_block *sb = inode->i_sb; |
255 | struct msdos_sb_info *sbi = MSDOS_SB(sb); | 255 | struct msdos_sb_info *sbi = MSDOS_SB(sb); |
256 | 256 | ||
257 | spin_lock(&sbi->inode_hash_lock); | 257 | spin_lock(&sbi->inode_hash_lock); |
258 | MSDOS_I(inode)->i_pos = i_pos; | 258 | MSDOS_I(inode)->i_pos = i_pos; |
259 | hlist_add_head(&MSDOS_I(inode)->i_fat_hash, | 259 | hlist_add_head(&MSDOS_I(inode)->i_fat_hash, |
260 | sbi->inode_hashtable + fat_hash(sb, i_pos)); | 260 | sbi->inode_hashtable + fat_hash(sb, i_pos)); |
261 | spin_unlock(&sbi->inode_hash_lock); | 261 | spin_unlock(&sbi->inode_hash_lock); |
262 | } | 262 | } |
263 | 263 | ||
264 | EXPORT_SYMBOL_GPL(fat_attach); | 264 | EXPORT_SYMBOL_GPL(fat_attach); |
265 | 265 | ||
266 | void fat_detach(struct inode *inode) | 266 | void fat_detach(struct inode *inode) |
267 | { | 267 | { |
268 | struct msdos_sb_info *sbi = MSDOS_SB(inode->i_sb); | 268 | struct msdos_sb_info *sbi = MSDOS_SB(inode->i_sb); |
269 | spin_lock(&sbi->inode_hash_lock); | 269 | spin_lock(&sbi->inode_hash_lock); |
270 | MSDOS_I(inode)->i_pos = 0; | 270 | MSDOS_I(inode)->i_pos = 0; |
271 | hlist_del_init(&MSDOS_I(inode)->i_fat_hash); | 271 | hlist_del_init(&MSDOS_I(inode)->i_fat_hash); |
272 | spin_unlock(&sbi->inode_hash_lock); | 272 | spin_unlock(&sbi->inode_hash_lock); |
273 | } | 273 | } |
274 | 274 | ||
275 | EXPORT_SYMBOL_GPL(fat_detach); | 275 | EXPORT_SYMBOL_GPL(fat_detach); |
276 | 276 | ||
277 | struct inode *fat_iget(struct super_block *sb, loff_t i_pos) | 277 | struct inode *fat_iget(struct super_block *sb, loff_t i_pos) |
278 | { | 278 | { |
279 | struct msdos_sb_info *sbi = MSDOS_SB(sb); | 279 | struct msdos_sb_info *sbi = MSDOS_SB(sb); |
280 | struct hlist_head *head = sbi->inode_hashtable + fat_hash(sb, i_pos); | 280 | struct hlist_head *head = sbi->inode_hashtable + fat_hash(sb, i_pos); |
281 | struct hlist_node *_p; | 281 | struct hlist_node *_p; |
282 | struct msdos_inode_info *i; | 282 | struct msdos_inode_info *i; |
283 | struct inode *inode = NULL; | 283 | struct inode *inode = NULL; |
284 | 284 | ||
285 | spin_lock(&sbi->inode_hash_lock); | 285 | spin_lock(&sbi->inode_hash_lock); |
286 | hlist_for_each_entry(i, _p, head, i_fat_hash) { | 286 | hlist_for_each_entry(i, _p, head, i_fat_hash) { |
287 | BUG_ON(i->vfs_inode.i_sb != sb); | 287 | BUG_ON(i->vfs_inode.i_sb != sb); |
288 | if (i->i_pos != i_pos) | 288 | if (i->i_pos != i_pos) |
289 | continue; | 289 | continue; |
290 | inode = igrab(&i->vfs_inode); | 290 | inode = igrab(&i->vfs_inode); |
291 | if (inode) | 291 | if (inode) |
292 | break; | 292 | break; |
293 | } | 293 | } |
294 | spin_unlock(&sbi->inode_hash_lock); | 294 | spin_unlock(&sbi->inode_hash_lock); |
295 | return inode; | 295 | return inode; |
296 | } | 296 | } |
297 | 297 | ||
298 | static int is_exec(unsigned char *extension) | 298 | static int is_exec(unsigned char *extension) |
299 | { | 299 | { |
300 | unsigned char *exe_extensions = "EXECOMBAT", *walk; | 300 | unsigned char *exe_extensions = "EXECOMBAT", *walk; |
301 | 301 | ||
302 | for (walk = exe_extensions; *walk; walk += 3) | 302 | for (walk = exe_extensions; *walk; walk += 3) |
303 | if (!strncmp(extension, walk, 3)) | 303 | if (!strncmp(extension, walk, 3)) |
304 | return 1; | 304 | return 1; |
305 | return 0; | 305 | return 0; |
306 | } | 306 | } |
307 | 307 | ||
308 | static int fat_calc_dir_size(struct inode *inode) | 308 | static int fat_calc_dir_size(struct inode *inode) |
309 | { | 309 | { |
310 | struct msdos_sb_info *sbi = MSDOS_SB(inode->i_sb); | 310 | struct msdos_sb_info *sbi = MSDOS_SB(inode->i_sb); |
311 | int ret, fclus, dclus; | 311 | int ret, fclus, dclus; |
312 | 312 | ||
313 | inode->i_size = 0; | 313 | inode->i_size = 0; |
314 | if (MSDOS_I(inode)->i_start == 0) | 314 | if (MSDOS_I(inode)->i_start == 0) |
315 | return 0; | 315 | return 0; |
316 | 316 | ||
317 | ret = fat_get_cluster(inode, FAT_ENT_EOF, &fclus, &dclus); | 317 | ret = fat_get_cluster(inode, FAT_ENT_EOF, &fclus, &dclus); |
318 | if (ret < 0) | 318 | if (ret < 0) |
319 | return ret; | 319 | return ret; |
320 | inode->i_size = (fclus + 1) << sbi->cluster_bits; | 320 | inode->i_size = (fclus + 1) << sbi->cluster_bits; |
321 | 321 | ||
322 | return 0; | 322 | return 0; |
323 | } | 323 | } |
324 | 324 | ||
325 | /* doesn't deal with root inode */ | 325 | /* doesn't deal with root inode */ |
326 | static int fat_fill_inode(struct inode *inode, struct msdos_dir_entry *de) | 326 | static int fat_fill_inode(struct inode *inode, struct msdos_dir_entry *de) |
327 | { | 327 | { |
328 | struct msdos_sb_info *sbi = MSDOS_SB(inode->i_sb); | 328 | struct msdos_sb_info *sbi = MSDOS_SB(inode->i_sb); |
329 | int error; | 329 | int error; |
330 | 330 | ||
331 | MSDOS_I(inode)->i_pos = 0; | 331 | MSDOS_I(inode)->i_pos = 0; |
332 | inode->i_uid = sbi->options.fs_uid; | 332 | inode->i_uid = sbi->options.fs_uid; |
333 | inode->i_gid = sbi->options.fs_gid; | 333 | inode->i_gid = sbi->options.fs_gid; |
334 | inode->i_version++; | 334 | inode->i_version++; |
335 | inode->i_generation = get_seconds(); | 335 | inode->i_generation = get_seconds(); |
336 | 336 | ||
337 | if ((de->attr & ATTR_DIR) && !IS_FREE(de->name)) { | 337 | if ((de->attr & ATTR_DIR) && !IS_FREE(de->name)) { |
338 | inode->i_generation &= ~1; | 338 | inode->i_generation &= ~1; |
339 | inode->i_mode = MSDOS_MKMODE(de->attr, | 339 | inode->i_mode = MSDOS_MKMODE(de->attr, |
340 | S_IRWXUGO & ~sbi->options.fs_dmask) | S_IFDIR; | 340 | S_IRWXUGO & ~sbi->options.fs_dmask) | S_IFDIR; |
341 | inode->i_op = sbi->dir_ops; | 341 | inode->i_op = sbi->dir_ops; |
342 | inode->i_fop = &fat_dir_operations; | 342 | inode->i_fop = &fat_dir_operations; |
343 | 343 | ||
344 | MSDOS_I(inode)->i_start = le16_to_cpu(de->start); | 344 | MSDOS_I(inode)->i_start = le16_to_cpu(de->start); |
345 | if (sbi->fat_bits == 32) | 345 | if (sbi->fat_bits == 32) |
346 | MSDOS_I(inode)->i_start |= (le16_to_cpu(de->starthi) << 16); | 346 | MSDOS_I(inode)->i_start |= (le16_to_cpu(de->starthi) << 16); |
347 | 347 | ||
348 | MSDOS_I(inode)->i_logstart = MSDOS_I(inode)->i_start; | 348 | MSDOS_I(inode)->i_logstart = MSDOS_I(inode)->i_start; |
349 | error = fat_calc_dir_size(inode); | 349 | error = fat_calc_dir_size(inode); |
350 | if (error < 0) | 350 | if (error < 0) |
351 | return error; | 351 | return error; |
352 | MSDOS_I(inode)->mmu_private = inode->i_size; | 352 | MSDOS_I(inode)->mmu_private = inode->i_size; |
353 | 353 | ||
354 | inode->i_nlink = fat_subdirs(inode); | 354 | inode->i_nlink = fat_subdirs(inode); |
355 | } else { /* not a directory */ | 355 | } else { /* not a directory */ |
356 | inode->i_generation |= 1; | 356 | inode->i_generation |= 1; |
357 | inode->i_mode = MSDOS_MKMODE(de->attr, | 357 | inode->i_mode = MSDOS_MKMODE(de->attr, |
358 | ((sbi->options.showexec && | 358 | ((sbi->options.showexec && |
359 | !is_exec(de->ext)) | 359 | !is_exec(de->ext)) |
360 | ? S_IRUGO|S_IWUGO : S_IRWXUGO) | 360 | ? S_IRUGO|S_IWUGO : S_IRWXUGO) |
361 | & ~sbi->options.fs_fmask) | S_IFREG; | 361 | & ~sbi->options.fs_fmask) | S_IFREG; |
362 | MSDOS_I(inode)->i_start = le16_to_cpu(de->start); | 362 | MSDOS_I(inode)->i_start = le16_to_cpu(de->start); |
363 | if (sbi->fat_bits == 32) | 363 | if (sbi->fat_bits == 32) |
364 | MSDOS_I(inode)->i_start |= (le16_to_cpu(de->starthi) << 16); | 364 | MSDOS_I(inode)->i_start |= (le16_to_cpu(de->starthi) << 16); |
365 | 365 | ||
366 | MSDOS_I(inode)->i_logstart = MSDOS_I(inode)->i_start; | 366 | MSDOS_I(inode)->i_logstart = MSDOS_I(inode)->i_start; |
367 | inode->i_size = le32_to_cpu(de->size); | 367 | inode->i_size = le32_to_cpu(de->size); |
368 | inode->i_op = &fat_file_inode_operations; | 368 | inode->i_op = &fat_file_inode_operations; |
369 | inode->i_fop = &fat_file_operations; | 369 | inode->i_fop = &fat_file_operations; |
370 | inode->i_mapping->a_ops = &fat_aops; | 370 | inode->i_mapping->a_ops = &fat_aops; |
371 | MSDOS_I(inode)->mmu_private = inode->i_size; | 371 | MSDOS_I(inode)->mmu_private = inode->i_size; |
372 | } | 372 | } |
373 | if (de->attr & ATTR_SYS) { | 373 | if (de->attr & ATTR_SYS) { |
374 | if (sbi->options.sys_immutable) | 374 | if (sbi->options.sys_immutable) |
375 | inode->i_flags |= S_IMMUTABLE; | 375 | inode->i_flags |= S_IMMUTABLE; |
376 | } | 376 | } |
377 | MSDOS_I(inode)->i_attrs = de->attr & ATTR_UNUSED; | 377 | MSDOS_I(inode)->i_attrs = de->attr & ATTR_UNUSED; |
378 | /* this is as close to the truth as we can get ... */ | 378 | /* this is as close to the truth as we can get ... */ |
379 | inode->i_blksize = sbi->cluster_size; | 379 | inode->i_blksize = sbi->cluster_size; |
380 | inode->i_blocks = ((inode->i_size + (sbi->cluster_size - 1)) | 380 | inode->i_blocks = ((inode->i_size + (sbi->cluster_size - 1)) |
381 | & ~((loff_t)sbi->cluster_size - 1)) >> 9; | 381 | & ~((loff_t)sbi->cluster_size - 1)) >> 9; |
382 | inode->i_mtime.tv_sec = | 382 | inode->i_mtime.tv_sec = |
383 | date_dos2unix(le16_to_cpu(de->time), le16_to_cpu(de->date)); | 383 | date_dos2unix(le16_to_cpu(de->time), le16_to_cpu(de->date)); |
384 | inode->i_mtime.tv_nsec = 0; | 384 | inode->i_mtime.tv_nsec = 0; |
385 | if (sbi->options.isvfat) { | 385 | if (sbi->options.isvfat) { |
386 | int secs = de->ctime_cs / 100; | 386 | int secs = de->ctime_cs / 100; |
387 | int csecs = de->ctime_cs % 100; | 387 | int csecs = de->ctime_cs % 100; |
388 | inode->i_ctime.tv_sec = | 388 | inode->i_ctime.tv_sec = |
389 | date_dos2unix(le16_to_cpu(de->ctime), | 389 | date_dos2unix(le16_to_cpu(de->ctime), |
390 | le16_to_cpu(de->cdate)) + secs; | 390 | le16_to_cpu(de->cdate)) + secs; |
391 | inode->i_ctime.tv_nsec = csecs * 10000000; | 391 | inode->i_ctime.tv_nsec = csecs * 10000000; |
392 | inode->i_atime.tv_sec = | 392 | inode->i_atime.tv_sec = |
393 | date_dos2unix(le16_to_cpu(0), le16_to_cpu(de->adate)); | 393 | date_dos2unix(le16_to_cpu(0), le16_to_cpu(de->adate)); |
394 | inode->i_atime.tv_nsec = 0; | 394 | inode->i_atime.tv_nsec = 0; |
395 | } else | 395 | } else |
396 | inode->i_ctime = inode->i_atime = inode->i_mtime; | 396 | inode->i_ctime = inode->i_atime = inode->i_mtime; |
397 | 397 | ||
398 | return 0; | 398 | return 0; |
399 | } | 399 | } |
400 | 400 | ||
401 | struct inode *fat_build_inode(struct super_block *sb, | 401 | struct inode *fat_build_inode(struct super_block *sb, |
402 | struct msdos_dir_entry *de, loff_t i_pos) | 402 | struct msdos_dir_entry *de, loff_t i_pos) |
403 | { | 403 | { |
404 | struct inode *inode; | 404 | struct inode *inode; |
405 | int err; | 405 | int err; |
406 | 406 | ||
407 | inode = fat_iget(sb, i_pos); | 407 | inode = fat_iget(sb, i_pos); |
408 | if (inode) | 408 | if (inode) |
409 | goto out; | 409 | goto out; |
410 | inode = new_inode(sb); | 410 | inode = new_inode(sb); |
411 | if (!inode) { | 411 | if (!inode) { |
412 | inode = ERR_PTR(-ENOMEM); | 412 | inode = ERR_PTR(-ENOMEM); |
413 | goto out; | 413 | goto out; |
414 | } | 414 | } |
415 | inode->i_ino = iunique(sb, MSDOS_ROOT_INO); | 415 | inode->i_ino = iunique(sb, MSDOS_ROOT_INO); |
416 | inode->i_version = 1; | 416 | inode->i_version = 1; |
417 | err = fat_fill_inode(inode, de); | 417 | err = fat_fill_inode(inode, de); |
418 | if (err) { | 418 | if (err) { |
419 | iput(inode); | 419 | iput(inode); |
420 | inode = ERR_PTR(err); | 420 | inode = ERR_PTR(err); |
421 | goto out; | 421 | goto out; |
422 | } | 422 | } |
423 | fat_attach(inode, i_pos); | 423 | fat_attach(inode, i_pos); |
424 | insert_inode_hash(inode); | 424 | insert_inode_hash(inode); |
425 | out: | 425 | out: |
426 | return inode; | 426 | return inode; |
427 | } | 427 | } |
428 | 428 | ||
429 | EXPORT_SYMBOL_GPL(fat_build_inode); | 429 | EXPORT_SYMBOL_GPL(fat_build_inode); |
430 | 430 | ||
431 | static void fat_delete_inode(struct inode *inode) | 431 | static void fat_delete_inode(struct inode *inode) |
432 | { | 432 | { |
433 | truncate_inode_pages(&inode->i_data, 0); | 433 | truncate_inode_pages(&inode->i_data, 0); |
434 | 434 | ||
435 | if (!is_bad_inode(inode)) { | 435 | if (!is_bad_inode(inode)) { |
436 | inode->i_size = 0; | 436 | inode->i_size = 0; |
437 | fat_truncate(inode); | 437 | fat_truncate(inode); |
438 | } | 438 | } |
439 | clear_inode(inode); | 439 | clear_inode(inode); |
440 | } | 440 | } |
441 | 441 | ||
442 | static void fat_clear_inode(struct inode *inode) | 442 | static void fat_clear_inode(struct inode *inode) |
443 | { | 443 | { |
444 | struct msdos_sb_info *sbi = MSDOS_SB(inode->i_sb); | 444 | struct msdos_sb_info *sbi = MSDOS_SB(inode->i_sb); |
445 | 445 | ||
446 | if (is_bad_inode(inode)) | 446 | if (is_bad_inode(inode)) |
447 | return; | 447 | return; |
448 | lock_kernel(); | 448 | lock_kernel(); |
449 | spin_lock(&sbi->inode_hash_lock); | 449 | spin_lock(&sbi->inode_hash_lock); |
450 | fat_cache_inval_inode(inode); | 450 | fat_cache_inval_inode(inode); |
451 | hlist_del_init(&MSDOS_I(inode)->i_fat_hash); | 451 | hlist_del_init(&MSDOS_I(inode)->i_fat_hash); |
452 | spin_unlock(&sbi->inode_hash_lock); | 452 | spin_unlock(&sbi->inode_hash_lock); |
453 | unlock_kernel(); | 453 | unlock_kernel(); |
454 | } | 454 | } |
455 | 455 | ||
456 | static void fat_write_super(struct super_block *sb) | 456 | static void fat_write_super(struct super_block *sb) |
457 | { | 457 | { |
458 | sb->s_dirt = 0; | 458 | sb->s_dirt = 0; |
459 | 459 | ||
460 | if (!(sb->s_flags & MS_RDONLY)) | 460 | if (!(sb->s_flags & MS_RDONLY)) |
461 | fat_clusters_flush(sb); | 461 | fat_clusters_flush(sb); |
462 | } | 462 | } |
463 | 463 | ||
464 | static void fat_put_super(struct super_block *sb) | 464 | static void fat_put_super(struct super_block *sb) |
465 | { | 465 | { |
466 | struct msdos_sb_info *sbi = MSDOS_SB(sb); | 466 | struct msdos_sb_info *sbi = MSDOS_SB(sb); |
467 | 467 | ||
468 | if (sbi->nls_disk) { | 468 | if (sbi->nls_disk) { |
469 | unload_nls(sbi->nls_disk); | 469 | unload_nls(sbi->nls_disk); |
470 | sbi->nls_disk = NULL; | 470 | sbi->nls_disk = NULL; |
471 | sbi->options.codepage = fat_default_codepage; | 471 | sbi->options.codepage = fat_default_codepage; |
472 | } | 472 | } |
473 | if (sbi->nls_io) { | 473 | if (sbi->nls_io) { |
474 | unload_nls(sbi->nls_io); | 474 | unload_nls(sbi->nls_io); |
475 | sbi->nls_io = NULL; | 475 | sbi->nls_io = NULL; |
476 | } | 476 | } |
477 | if (sbi->options.iocharset != fat_default_iocharset) { | 477 | if (sbi->options.iocharset != fat_default_iocharset) { |
478 | kfree(sbi->options.iocharset); | 478 | kfree(sbi->options.iocharset); |
479 | sbi->options.iocharset = fat_default_iocharset; | 479 | sbi->options.iocharset = fat_default_iocharset; |
480 | } | 480 | } |
481 | 481 | ||
482 | sb->s_fs_info = NULL; | 482 | sb->s_fs_info = NULL; |
483 | kfree(sbi); | 483 | kfree(sbi); |
484 | } | 484 | } |
485 | 485 | ||
486 | static kmem_cache_t *fat_inode_cachep; | 486 | static kmem_cache_t *fat_inode_cachep; |
487 | 487 | ||
488 | static struct inode *fat_alloc_inode(struct super_block *sb) | 488 | static struct inode *fat_alloc_inode(struct super_block *sb) |
489 | { | 489 | { |
490 | struct msdos_inode_info *ei; | 490 | struct msdos_inode_info *ei; |
491 | ei = kmem_cache_alloc(fat_inode_cachep, SLAB_KERNEL); | 491 | ei = kmem_cache_alloc(fat_inode_cachep, SLAB_KERNEL); |
492 | if (!ei) | 492 | if (!ei) |
493 | return NULL; | 493 | return NULL; |
494 | return &ei->vfs_inode; | 494 | return &ei->vfs_inode; |
495 | } | 495 | } |
496 | 496 | ||
497 | static void fat_destroy_inode(struct inode *inode) | 497 | static void fat_destroy_inode(struct inode *inode) |
498 | { | 498 | { |
499 | kmem_cache_free(fat_inode_cachep, MSDOS_I(inode)); | 499 | kmem_cache_free(fat_inode_cachep, MSDOS_I(inode)); |
500 | } | 500 | } |
501 | 501 | ||
502 | static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags) | 502 | static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags) |
503 | { | 503 | { |
504 | struct msdos_inode_info *ei = (struct msdos_inode_info *)foo; | 504 | struct msdos_inode_info *ei = (struct msdos_inode_info *)foo; |
505 | 505 | ||
506 | if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) == | 506 | if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) == |
507 | SLAB_CTOR_CONSTRUCTOR) { | 507 | SLAB_CTOR_CONSTRUCTOR) { |
508 | spin_lock_init(&ei->cache_lru_lock); | 508 | spin_lock_init(&ei->cache_lru_lock); |
509 | ei->nr_caches = 0; | 509 | ei->nr_caches = 0; |
510 | ei->cache_valid_id = FAT_CACHE_VALID + 1; | 510 | ei->cache_valid_id = FAT_CACHE_VALID + 1; |
511 | INIT_LIST_HEAD(&ei->cache_lru); | 511 | INIT_LIST_HEAD(&ei->cache_lru); |
512 | INIT_HLIST_NODE(&ei->i_fat_hash); | 512 | INIT_HLIST_NODE(&ei->i_fat_hash); |
513 | inode_init_once(&ei->vfs_inode); | 513 | inode_init_once(&ei->vfs_inode); |
514 | } | 514 | } |
515 | } | 515 | } |
516 | 516 | ||
517 | static int __init fat_init_inodecache(void) | 517 | static int __init fat_init_inodecache(void) |
518 | { | 518 | { |
519 | fat_inode_cachep = kmem_cache_create("fat_inode_cache", | 519 | fat_inode_cachep = kmem_cache_create("fat_inode_cache", |
520 | sizeof(struct msdos_inode_info), | 520 | sizeof(struct msdos_inode_info), |
521 | 0, SLAB_RECLAIM_ACCOUNT, | 521 | 0, SLAB_RECLAIM_ACCOUNT, |
522 | init_once, NULL); | 522 | init_once, NULL); |
523 | if (fat_inode_cachep == NULL) | 523 | if (fat_inode_cachep == NULL) |
524 | return -ENOMEM; | 524 | return -ENOMEM; |
525 | return 0; | 525 | return 0; |
526 | } | 526 | } |
527 | 527 | ||
528 | static void __exit fat_destroy_inodecache(void) | 528 | static void __exit fat_destroy_inodecache(void) |
529 | { | 529 | { |
530 | if (kmem_cache_destroy(fat_inode_cachep)) | 530 | if (kmem_cache_destroy(fat_inode_cachep)) |
531 | printk(KERN_INFO "fat_inode_cache: not all structures were freed\n"); | 531 | printk(KERN_INFO "fat_inode_cache: not all structures were freed\n"); |
532 | } | 532 | } |
533 | 533 | ||
534 | static int fat_remount(struct super_block *sb, int *flags, char *data) | 534 | static int fat_remount(struct super_block *sb, int *flags, char *data) |
535 | { | 535 | { |
536 | struct msdos_sb_info *sbi = MSDOS_SB(sb); | 536 | struct msdos_sb_info *sbi = MSDOS_SB(sb); |
537 | *flags |= MS_NODIRATIME | (sbi->options.isvfat ? 0 : MS_NOATIME); | 537 | *flags |= MS_NODIRATIME | (sbi->options.isvfat ? 0 : MS_NOATIME); |
538 | return 0; | 538 | return 0; |
539 | } | 539 | } |
540 | 540 | ||
541 | static int fat_statfs(struct super_block *sb, struct kstatfs *buf) | 541 | static int fat_statfs(struct super_block *sb, struct kstatfs *buf) |
542 | { | 542 | { |
543 | struct msdos_sb_info *sbi = MSDOS_SB(sb); | 543 | struct msdos_sb_info *sbi = MSDOS_SB(sb); |
544 | 544 | ||
545 | /* If the count of free cluster is still unknown, counts it here. */ | 545 | /* If the count of free cluster is still unknown, counts it here. */ |
546 | if (sbi->free_clusters == -1) { | 546 | if (sbi->free_clusters == -1) { |
547 | int err = fat_count_free_clusters(sb); | 547 | int err = fat_count_free_clusters(sb); |
548 | if (err) | 548 | if (err) |
549 | return err; | 549 | return err; |
550 | } | 550 | } |
551 | 551 | ||
552 | buf->f_type = sb->s_magic; | 552 | buf->f_type = sb->s_magic; |
553 | buf->f_bsize = sbi->cluster_size; | 553 | buf->f_bsize = sbi->cluster_size; |
554 | buf->f_blocks = sbi->max_cluster - FAT_START_ENT; | 554 | buf->f_blocks = sbi->max_cluster - FAT_START_ENT; |
555 | buf->f_bfree = sbi->free_clusters; | 555 | buf->f_bfree = sbi->free_clusters; |
556 | buf->f_bavail = sbi->free_clusters; | 556 | buf->f_bavail = sbi->free_clusters; |
557 | buf->f_namelen = sbi->options.isvfat ? 260 : 12; | 557 | buf->f_namelen = sbi->options.isvfat ? 260 : 12; |
558 | 558 | ||
559 | return 0; | 559 | return 0; |
560 | } | 560 | } |
561 | 561 | ||
562 | static int fat_write_inode(struct inode *inode, int wait) | 562 | static int fat_write_inode(struct inode *inode, int wait) |
563 | { | 563 | { |
564 | struct super_block *sb = inode->i_sb; | 564 | struct super_block *sb = inode->i_sb; |
565 | struct msdos_sb_info *sbi = MSDOS_SB(sb); | 565 | struct msdos_sb_info *sbi = MSDOS_SB(sb); |
566 | struct buffer_head *bh; | 566 | struct buffer_head *bh; |
567 | struct msdos_dir_entry *raw_entry; | 567 | struct msdos_dir_entry *raw_entry; |
568 | loff_t i_pos; | 568 | loff_t i_pos; |
569 | int err = 0; | 569 | int err = 0; |
570 | 570 | ||
571 | retry: | 571 | retry: |
572 | i_pos = MSDOS_I(inode)->i_pos; | 572 | i_pos = MSDOS_I(inode)->i_pos; |
573 | if (inode->i_ino == MSDOS_ROOT_INO || !i_pos) | 573 | if (inode->i_ino == MSDOS_ROOT_INO || !i_pos) |
574 | return 0; | 574 | return 0; |
575 | 575 | ||
576 | lock_kernel(); | 576 | lock_kernel(); |
577 | bh = sb_bread(sb, i_pos >> sbi->dir_per_block_bits); | 577 | bh = sb_bread(sb, i_pos >> sbi->dir_per_block_bits); |
578 | if (!bh) { | 578 | if (!bh) { |
579 | printk(KERN_ERR "FAT: unable to read inode block " | 579 | printk(KERN_ERR "FAT: unable to read inode block " |
580 | "for updating (i_pos %lld)\n", i_pos); | 580 | "for updating (i_pos %lld)\n", i_pos); |
581 | err = -EIO; | 581 | err = -EIO; |
582 | goto out; | 582 | goto out; |
583 | } | 583 | } |
584 | spin_lock(&sbi->inode_hash_lock); | 584 | spin_lock(&sbi->inode_hash_lock); |
585 | if (i_pos != MSDOS_I(inode)->i_pos) { | 585 | if (i_pos != MSDOS_I(inode)->i_pos) { |
586 | spin_unlock(&sbi->inode_hash_lock); | 586 | spin_unlock(&sbi->inode_hash_lock); |
587 | brelse(bh); | 587 | brelse(bh); |
588 | unlock_kernel(); | 588 | unlock_kernel(); |
589 | goto retry; | 589 | goto retry; |
590 | } | 590 | } |
591 | 591 | ||
592 | raw_entry = &((struct msdos_dir_entry *) (bh->b_data)) | 592 | raw_entry = &((struct msdos_dir_entry *) (bh->b_data)) |
593 | [i_pos & (sbi->dir_per_block - 1)]; | 593 | [i_pos & (sbi->dir_per_block - 1)]; |
594 | if (S_ISDIR(inode->i_mode)) | 594 | if (S_ISDIR(inode->i_mode)) |
595 | raw_entry->size = 0; | 595 | raw_entry->size = 0; |
596 | else | 596 | else |
597 | raw_entry->size = cpu_to_le32(inode->i_size); | 597 | raw_entry->size = cpu_to_le32(inode->i_size); |
598 | raw_entry->attr = fat_attr(inode); | 598 | raw_entry->attr = fat_attr(inode); |
599 | raw_entry->start = cpu_to_le16(MSDOS_I(inode)->i_logstart); | 599 | raw_entry->start = cpu_to_le16(MSDOS_I(inode)->i_logstart); |
600 | raw_entry->starthi = cpu_to_le16(MSDOS_I(inode)->i_logstart >> 16); | 600 | raw_entry->starthi = cpu_to_le16(MSDOS_I(inode)->i_logstart >> 16); |
601 | fat_date_unix2dos(inode->i_mtime.tv_sec, &raw_entry->time, &raw_entry->date); | 601 | fat_date_unix2dos(inode->i_mtime.tv_sec, &raw_entry->time, &raw_entry->date); |
602 | if (sbi->options.isvfat) { | 602 | if (sbi->options.isvfat) { |
603 | __le16 atime; | 603 | __le16 atime; |
604 | fat_date_unix2dos(inode->i_ctime.tv_sec,&raw_entry->ctime,&raw_entry->cdate); | 604 | fat_date_unix2dos(inode->i_ctime.tv_sec,&raw_entry->ctime,&raw_entry->cdate); |
605 | fat_date_unix2dos(inode->i_atime.tv_sec,&atime,&raw_entry->adate); | 605 | fat_date_unix2dos(inode->i_atime.tv_sec,&atime,&raw_entry->adate); |
606 | raw_entry->ctime_cs = (inode->i_ctime.tv_sec & 1) * 100 + | 606 | raw_entry->ctime_cs = (inode->i_ctime.tv_sec & 1) * 100 + |
607 | inode->i_ctime.tv_nsec / 10000000; | 607 | inode->i_ctime.tv_nsec / 10000000; |
608 | } | 608 | } |
609 | spin_unlock(&sbi->inode_hash_lock); | 609 | spin_unlock(&sbi->inode_hash_lock); |
610 | mark_buffer_dirty(bh); | 610 | mark_buffer_dirty(bh); |
611 | if (wait) | 611 | if (wait) |
612 | err = sync_dirty_buffer(bh); | 612 | err = sync_dirty_buffer(bh); |
613 | brelse(bh); | 613 | brelse(bh); |
614 | out: | 614 | out: |
615 | unlock_kernel(); | 615 | unlock_kernel(); |
616 | return err; | 616 | return err; |
617 | } | 617 | } |
618 | 618 | ||
619 | int fat_sync_inode(struct inode *inode) | 619 | int fat_sync_inode(struct inode *inode) |
620 | { | 620 | { |
621 | return fat_write_inode(inode, 1); | 621 | return fat_write_inode(inode, 1); |
622 | } | 622 | } |
623 | 623 | ||
624 | EXPORT_SYMBOL_GPL(fat_sync_inode); | 624 | EXPORT_SYMBOL_GPL(fat_sync_inode); |
625 | 625 | ||
626 | static int fat_show_options(struct seq_file *m, struct vfsmount *mnt); | 626 | static int fat_show_options(struct seq_file *m, struct vfsmount *mnt); |
627 | static struct super_operations fat_sops = { | 627 | static struct super_operations fat_sops = { |
628 | .alloc_inode = fat_alloc_inode, | 628 | .alloc_inode = fat_alloc_inode, |
629 | .destroy_inode = fat_destroy_inode, | 629 | .destroy_inode = fat_destroy_inode, |
630 | .write_inode = fat_write_inode, | 630 | .write_inode = fat_write_inode, |
631 | .delete_inode = fat_delete_inode, | 631 | .delete_inode = fat_delete_inode, |
632 | .put_super = fat_put_super, | 632 | .put_super = fat_put_super, |
633 | .write_super = fat_write_super, | 633 | .write_super = fat_write_super, |
634 | .statfs = fat_statfs, | 634 | .statfs = fat_statfs, |
635 | .clear_inode = fat_clear_inode, | 635 | .clear_inode = fat_clear_inode, |
636 | .remount_fs = fat_remount, | 636 | .remount_fs = fat_remount, |
637 | 637 | ||
638 | .read_inode = make_bad_inode, | 638 | .read_inode = make_bad_inode, |
639 | 639 | ||
640 | .show_options = fat_show_options, | 640 | .show_options = fat_show_options, |
641 | }; | 641 | }; |
642 | 642 | ||
643 | /* | 643 | /* |
644 | * a FAT file handle with fhtype 3 is | 644 | * a FAT file handle with fhtype 3 is |
645 | * 0/ i_ino - for fast, reliable lookup if still in the cache | 645 | * 0/ i_ino - for fast, reliable lookup if still in the cache |
646 | * 1/ i_generation - to see if i_ino is still valid | 646 | * 1/ i_generation - to see if i_ino is still valid |
647 | * bit 0 == 0 iff directory | 647 | * bit 0 == 0 iff directory |
648 | * 2/ i_pos(8-39) - if ino has changed, but still in cache | 648 | * 2/ i_pos(8-39) - if ino has changed, but still in cache |
649 | * 3/ i_pos(4-7)|i_logstart - to semi-verify inode found at i_pos | 649 | * 3/ i_pos(4-7)|i_logstart - to semi-verify inode found at i_pos |
650 | * 4/ i_pos(0-3)|parent->i_logstart - maybe used to hunt for the file on disc | 650 | * 4/ i_pos(0-3)|parent->i_logstart - maybe used to hunt for the file on disc |
651 | * | 651 | * |
652 | * Hack for NFSv2: Maximum FAT entry number is 28bits and maximum | 652 | * Hack for NFSv2: Maximum FAT entry number is 28bits and maximum |
653 | * i_pos is 40bits (blocknr(32) + dir offset(8)), so two 4bits | 653 | * i_pos is 40bits (blocknr(32) + dir offset(8)), so two 4bits |
654 | * of i_logstart is used to store the directory entry offset. | 654 | * of i_logstart is used to store the directory entry offset. |
655 | */ | 655 | */ |
656 | 656 | ||
657 | static struct dentry * | 657 | static struct dentry * |
658 | fat_decode_fh(struct super_block *sb, __u32 *fh, int len, int fhtype, | 658 | fat_decode_fh(struct super_block *sb, __u32 *fh, int len, int fhtype, |
659 | int (*acceptable)(void *context, struct dentry *de), | 659 | int (*acceptable)(void *context, struct dentry *de), |
660 | void *context) | 660 | void *context) |
661 | { | 661 | { |
662 | if (fhtype != 3) | 662 | if (fhtype != 3) |
663 | return ERR_PTR(-ESTALE); | 663 | return ERR_PTR(-ESTALE); |
664 | if (len < 5) | 664 | if (len < 5) |
665 | return ERR_PTR(-ESTALE); | 665 | return ERR_PTR(-ESTALE); |
666 | 666 | ||
667 | return sb->s_export_op->find_exported_dentry(sb, fh, NULL, acceptable, context); | 667 | return sb->s_export_op->find_exported_dentry(sb, fh, NULL, acceptable, context); |
668 | } | 668 | } |
669 | 669 | ||
670 | static struct dentry *fat_get_dentry(struct super_block *sb, void *inump) | 670 | static struct dentry *fat_get_dentry(struct super_block *sb, void *inump) |
671 | { | 671 | { |
672 | struct inode *inode = NULL; | 672 | struct inode *inode = NULL; |
673 | struct dentry *result; | 673 | struct dentry *result; |
674 | __u32 *fh = inump; | 674 | __u32 *fh = inump; |
675 | 675 | ||
676 | inode = iget(sb, fh[0]); | 676 | inode = iget(sb, fh[0]); |
677 | if (!inode || is_bad_inode(inode) || inode->i_generation != fh[1]) { | 677 | if (!inode || is_bad_inode(inode) || inode->i_generation != fh[1]) { |
678 | if (inode) | 678 | if (inode) |
679 | iput(inode); | 679 | iput(inode); |
680 | inode = NULL; | 680 | inode = NULL; |
681 | } | 681 | } |
682 | if (!inode) { | 682 | if (!inode) { |
683 | loff_t i_pos; | 683 | loff_t i_pos; |
684 | int i_logstart = fh[3] & 0x0fffffff; | 684 | int i_logstart = fh[3] & 0x0fffffff; |
685 | 685 | ||
686 | i_pos = (loff_t)fh[2] << 8; | 686 | i_pos = (loff_t)fh[2] << 8; |
687 | i_pos |= ((fh[3] >> 24) & 0xf0) | (fh[4] >> 28); | 687 | i_pos |= ((fh[3] >> 24) & 0xf0) | (fh[4] >> 28); |
688 | 688 | ||
689 | /* try 2 - see if i_pos is in F-d-c | 689 | /* try 2 - see if i_pos is in F-d-c |
690 | * require i_logstart to be the same | 690 | * require i_logstart to be the same |
691 | * Will fail if you truncate and then re-write | 691 | * Will fail if you truncate and then re-write |
692 | */ | 692 | */ |
693 | 693 | ||
694 | inode = fat_iget(sb, i_pos); | 694 | inode = fat_iget(sb, i_pos); |
695 | if (inode && MSDOS_I(inode)->i_logstart != i_logstart) { | 695 | if (inode && MSDOS_I(inode)->i_logstart != i_logstart) { |
696 | iput(inode); | 696 | iput(inode); |
697 | inode = NULL; | 697 | inode = NULL; |
698 | } | 698 | } |
699 | } | 699 | } |
700 | if (!inode) { | 700 | if (!inode) { |
701 | /* For now, do nothing | 701 | /* For now, do nothing |
702 | * What we could do is: | 702 | * What we could do is: |
703 | * follow the file starting at fh[4], and record | 703 | * follow the file starting at fh[4], and record |
704 | * the ".." entry, and the name of the fh[2] entry. | 704 | * the ".." entry, and the name of the fh[2] entry. |
705 | * The follow the ".." file finding the next step up. | 705 | * The follow the ".." file finding the next step up. |
706 | * This way we build a path to the root of | 706 | * This way we build a path to the root of |
707 | * the tree. If this works, we lookup the path and so | 707 | * the tree. If this works, we lookup the path and so |
708 | * get this inode into the cache. | 708 | * get this inode into the cache. |
709 | * Finally try the fat_iget lookup again | 709 | * Finally try the fat_iget lookup again |
710 | * If that fails, then weare totally out of luck | 710 | * If that fails, then weare totally out of luck |
711 | * But all that is for another day | 711 | * But all that is for another day |
712 | */ | 712 | */ |
713 | } | 713 | } |
714 | if (!inode) | 714 | if (!inode) |
715 | return ERR_PTR(-ESTALE); | 715 | return ERR_PTR(-ESTALE); |
716 | 716 | ||
717 | 717 | ||
718 | /* now to find a dentry. | 718 | /* now to find a dentry. |
719 | * If possible, get a well-connected one | 719 | * If possible, get a well-connected one |
720 | */ | 720 | */ |
721 | result = d_alloc_anon(inode); | 721 | result = d_alloc_anon(inode); |
722 | if (result == NULL) { | 722 | if (result == NULL) { |
723 | iput(inode); | 723 | iput(inode); |
724 | return ERR_PTR(-ENOMEM); | 724 | return ERR_PTR(-ENOMEM); |
725 | } | 725 | } |
726 | result->d_op = sb->s_root->d_op; | 726 | result->d_op = sb->s_root->d_op; |
727 | return result; | 727 | return result; |
728 | } | 728 | } |
729 | 729 | ||
730 | static int | 730 | static int |
731 | fat_encode_fh(struct dentry *de, __u32 *fh, int *lenp, int connectable) | 731 | fat_encode_fh(struct dentry *de, __u32 *fh, int *lenp, int connectable) |
732 | { | 732 | { |
733 | int len = *lenp; | 733 | int len = *lenp; |
734 | struct inode *inode = de->d_inode; | 734 | struct inode *inode = de->d_inode; |
735 | u32 ipos_h, ipos_m, ipos_l; | 735 | u32 ipos_h, ipos_m, ipos_l; |
736 | 736 | ||
737 | if (len < 5) | 737 | if (len < 5) |
738 | return 255; /* no room */ | 738 | return 255; /* no room */ |
739 | 739 | ||
740 | ipos_h = MSDOS_I(inode)->i_pos >> 8; | 740 | ipos_h = MSDOS_I(inode)->i_pos >> 8; |
741 | ipos_m = (MSDOS_I(inode)->i_pos & 0xf0) << 24; | 741 | ipos_m = (MSDOS_I(inode)->i_pos & 0xf0) << 24; |
742 | ipos_l = (MSDOS_I(inode)->i_pos & 0x0f) << 28; | 742 | ipos_l = (MSDOS_I(inode)->i_pos & 0x0f) << 28; |
743 | *lenp = 5; | 743 | *lenp = 5; |
744 | fh[0] = inode->i_ino; | 744 | fh[0] = inode->i_ino; |
745 | fh[1] = inode->i_generation; | 745 | fh[1] = inode->i_generation; |
746 | fh[2] = ipos_h; | 746 | fh[2] = ipos_h; |
747 | fh[3] = ipos_m | MSDOS_I(inode)->i_logstart; | 747 | fh[3] = ipos_m | MSDOS_I(inode)->i_logstart; |
748 | spin_lock(&de->d_lock); | 748 | spin_lock(&de->d_lock); |
749 | fh[4] = ipos_l | MSDOS_I(de->d_parent->d_inode)->i_logstart; | 749 | fh[4] = ipos_l | MSDOS_I(de->d_parent->d_inode)->i_logstart; |
750 | spin_unlock(&de->d_lock); | 750 | spin_unlock(&de->d_lock); |
751 | return 3; | 751 | return 3; |
752 | } | 752 | } |
753 | 753 | ||
754 | static struct dentry *fat_get_parent(struct dentry *child) | 754 | static struct dentry *fat_get_parent(struct dentry *child) |
755 | { | 755 | { |
756 | struct buffer_head *bh; | 756 | struct buffer_head *bh; |
757 | struct msdos_dir_entry *de; | 757 | struct msdos_dir_entry *de; |
758 | loff_t i_pos; | 758 | loff_t i_pos; |
759 | struct dentry *parent; | 759 | struct dentry *parent; |
760 | struct inode *inode; | 760 | struct inode *inode; |
761 | int err; | 761 | int err; |
762 | 762 | ||
763 | lock_kernel(); | 763 | lock_kernel(); |
764 | 764 | ||
765 | err = fat_get_dotdot_entry(child->d_inode, &bh, &de, &i_pos); | 765 | err = fat_get_dotdot_entry(child->d_inode, &bh, &de, &i_pos); |
766 | if (err) { | 766 | if (err) { |
767 | parent = ERR_PTR(err); | 767 | parent = ERR_PTR(err); |
768 | goto out; | 768 | goto out; |
769 | } | 769 | } |
770 | inode = fat_build_inode(child->d_sb, de, i_pos); | 770 | inode = fat_build_inode(child->d_sb, de, i_pos); |
771 | brelse(bh); | 771 | brelse(bh); |
772 | if (IS_ERR(inode)) { | 772 | if (IS_ERR(inode)) { |
773 | parent = ERR_PTR(PTR_ERR(inode)); | 773 | parent = ERR_PTR(PTR_ERR(inode)); |
774 | goto out; | 774 | goto out; |
775 | } | 775 | } |
776 | parent = d_alloc_anon(inode); | 776 | parent = d_alloc_anon(inode); |
777 | if (!parent) { | 777 | if (!parent) { |
778 | iput(inode); | 778 | iput(inode); |
779 | parent = ERR_PTR(-ENOMEM); | 779 | parent = ERR_PTR(-ENOMEM); |
780 | } | 780 | } |
781 | out: | 781 | out: |
782 | unlock_kernel(); | 782 | unlock_kernel(); |
783 | 783 | ||
784 | return parent; | 784 | return parent; |
785 | } | 785 | } |
786 | 786 | ||
787 | static struct export_operations fat_export_ops = { | 787 | static struct export_operations fat_export_ops = { |
788 | .decode_fh = fat_decode_fh, | 788 | .decode_fh = fat_decode_fh, |
789 | .encode_fh = fat_encode_fh, | 789 | .encode_fh = fat_encode_fh, |
790 | .get_dentry = fat_get_dentry, | 790 | .get_dentry = fat_get_dentry, |
791 | .get_parent = fat_get_parent, | 791 | .get_parent = fat_get_parent, |
792 | }; | 792 | }; |
793 | 793 | ||
794 | static int fat_show_options(struct seq_file *m, struct vfsmount *mnt) | 794 | static int fat_show_options(struct seq_file *m, struct vfsmount *mnt) |
795 | { | 795 | { |
796 | struct msdos_sb_info *sbi = MSDOS_SB(mnt->mnt_sb); | 796 | struct msdos_sb_info *sbi = MSDOS_SB(mnt->mnt_sb); |
797 | struct fat_mount_options *opts = &sbi->options; | 797 | struct fat_mount_options *opts = &sbi->options; |
798 | int isvfat = opts->isvfat; | 798 | int isvfat = opts->isvfat; |
799 | 799 | ||
800 | if (opts->fs_uid != 0) | 800 | if (opts->fs_uid != 0) |
801 | seq_printf(m, ",uid=%u", opts->fs_uid); | 801 | seq_printf(m, ",uid=%u", opts->fs_uid); |
802 | if (opts->fs_gid != 0) | 802 | if (opts->fs_gid != 0) |
803 | seq_printf(m, ",gid=%u", opts->fs_gid); | 803 | seq_printf(m, ",gid=%u", opts->fs_gid); |
804 | seq_printf(m, ",fmask=%04o", opts->fs_fmask); | 804 | seq_printf(m, ",fmask=%04o", opts->fs_fmask); |
805 | seq_printf(m, ",dmask=%04o", opts->fs_dmask); | 805 | seq_printf(m, ",dmask=%04o", opts->fs_dmask); |
806 | if (sbi->nls_disk) | 806 | if (sbi->nls_disk) |
807 | seq_printf(m, ",codepage=%s", sbi->nls_disk->charset); | 807 | seq_printf(m, ",codepage=%s", sbi->nls_disk->charset); |
808 | if (isvfat) { | 808 | if (isvfat) { |
809 | if (sbi->nls_io) | 809 | if (sbi->nls_io) |
810 | seq_printf(m, ",iocharset=%s", sbi->nls_io->charset); | 810 | seq_printf(m, ",iocharset=%s", sbi->nls_io->charset); |
811 | 811 | ||
812 | switch (opts->shortname) { | 812 | switch (opts->shortname) { |
813 | case VFAT_SFN_DISPLAY_WIN95 | VFAT_SFN_CREATE_WIN95: | 813 | case VFAT_SFN_DISPLAY_WIN95 | VFAT_SFN_CREATE_WIN95: |
814 | seq_puts(m, ",shortname=win95"); | 814 | seq_puts(m, ",shortname=win95"); |
815 | break; | 815 | break; |
816 | case VFAT_SFN_DISPLAY_WINNT | VFAT_SFN_CREATE_WINNT: | 816 | case VFAT_SFN_DISPLAY_WINNT | VFAT_SFN_CREATE_WINNT: |
817 | seq_puts(m, ",shortname=winnt"); | 817 | seq_puts(m, ",shortname=winnt"); |
818 | break; | 818 | break; |
819 | case VFAT_SFN_DISPLAY_WINNT | VFAT_SFN_CREATE_WIN95: | 819 | case VFAT_SFN_DISPLAY_WINNT | VFAT_SFN_CREATE_WIN95: |
820 | seq_puts(m, ",shortname=mixed"); | 820 | seq_puts(m, ",shortname=mixed"); |
821 | break; | 821 | break; |
822 | case VFAT_SFN_DISPLAY_LOWER | VFAT_SFN_CREATE_WIN95: | 822 | case VFAT_SFN_DISPLAY_LOWER | VFAT_SFN_CREATE_WIN95: |
823 | /* seq_puts(m, ",shortname=lower"); */ | 823 | /* seq_puts(m, ",shortname=lower"); */ |
824 | break; | 824 | break; |
825 | default: | 825 | default: |
826 | seq_puts(m, ",shortname=unknown"); | 826 | seq_puts(m, ",shortname=unknown"); |
827 | break; | 827 | break; |
828 | } | 828 | } |
829 | } | 829 | } |
830 | if (opts->name_check != 'n') | 830 | if (opts->name_check != 'n') |
831 | seq_printf(m, ",check=%c", opts->name_check); | 831 | seq_printf(m, ",check=%c", opts->name_check); |
832 | if (opts->quiet) | 832 | if (opts->quiet) |
833 | seq_puts(m, ",quiet"); | 833 | seq_puts(m, ",quiet"); |
834 | if (opts->showexec) | 834 | if (opts->showexec) |
835 | seq_puts(m, ",showexec"); | 835 | seq_puts(m, ",showexec"); |
836 | if (opts->sys_immutable) | 836 | if (opts->sys_immutable) |
837 | seq_puts(m, ",sys_immutable"); | 837 | seq_puts(m, ",sys_immutable"); |
838 | if (!isvfat) { | 838 | if (!isvfat) { |
839 | if (opts->dotsOK) | 839 | if (opts->dotsOK) |
840 | seq_puts(m, ",dotsOK=yes"); | 840 | seq_puts(m, ",dotsOK=yes"); |
841 | if (opts->nocase) | 841 | if (opts->nocase) |
842 | seq_puts(m, ",nocase"); | 842 | seq_puts(m, ",nocase"); |
843 | } else { | 843 | } else { |
844 | if (opts->utf8) | 844 | if (opts->utf8) |
845 | seq_puts(m, ",utf8"); | 845 | seq_puts(m, ",utf8"); |
846 | if (opts->unicode_xlate) | 846 | if (opts->unicode_xlate) |
847 | seq_puts(m, ",uni_xlate"); | 847 | seq_puts(m, ",uni_xlate"); |
848 | if (!opts->numtail) | 848 | if (!opts->numtail) |
849 | seq_puts(m, ",nonumtail"); | 849 | seq_puts(m, ",nonumtail"); |
850 | } | 850 | } |
851 | 851 | ||
852 | return 0; | 852 | return 0; |
853 | } | 853 | } |
854 | 854 | ||
855 | enum { | 855 | enum { |
856 | Opt_check_n, Opt_check_r, Opt_check_s, Opt_uid, Opt_gid, | 856 | Opt_check_n, Opt_check_r, Opt_check_s, Opt_uid, Opt_gid, |
857 | Opt_umask, Opt_dmask, Opt_fmask, Opt_codepage, Opt_nocase, | 857 | Opt_umask, Opt_dmask, Opt_fmask, Opt_codepage, Opt_nocase, |
858 | Opt_quiet, Opt_showexec, Opt_debug, Opt_immutable, | 858 | Opt_quiet, Opt_showexec, Opt_debug, Opt_immutable, |
859 | Opt_dots, Opt_nodots, | 859 | Opt_dots, Opt_nodots, |
860 | Opt_charset, Opt_shortname_lower, Opt_shortname_win95, | 860 | Opt_charset, Opt_shortname_lower, Opt_shortname_win95, |
861 | Opt_shortname_winnt, Opt_shortname_mixed, Opt_utf8_no, Opt_utf8_yes, | 861 | Opt_shortname_winnt, Opt_shortname_mixed, Opt_utf8_no, Opt_utf8_yes, |
862 | Opt_uni_xl_no, Opt_uni_xl_yes, Opt_nonumtail_no, Opt_nonumtail_yes, | 862 | Opt_uni_xl_no, Opt_uni_xl_yes, Opt_nonumtail_no, Opt_nonumtail_yes, |
863 | Opt_obsolate, Opt_err, | 863 | Opt_obsolate, Opt_err, |
864 | }; | 864 | }; |
865 | 865 | ||
866 | static match_table_t fat_tokens = { | 866 | static match_table_t fat_tokens = { |
867 | {Opt_check_r, "check=relaxed"}, | 867 | {Opt_check_r, "check=relaxed"}, |
868 | {Opt_check_s, "check=strict"}, | 868 | {Opt_check_s, "check=strict"}, |
869 | {Opt_check_n, "check=normal"}, | 869 | {Opt_check_n, "check=normal"}, |
870 | {Opt_check_r, "check=r"}, | 870 | {Opt_check_r, "check=r"}, |
871 | {Opt_check_s, "check=s"}, | 871 | {Opt_check_s, "check=s"}, |
872 | {Opt_check_n, "check=n"}, | 872 | {Opt_check_n, "check=n"}, |
873 | {Opt_uid, "uid=%u"}, | 873 | {Opt_uid, "uid=%u"}, |
874 | {Opt_gid, "gid=%u"}, | 874 | {Opt_gid, "gid=%u"}, |
875 | {Opt_umask, "umask=%o"}, | 875 | {Opt_umask, "umask=%o"}, |
876 | {Opt_dmask, "dmask=%o"}, | 876 | {Opt_dmask, "dmask=%o"}, |
877 | {Opt_fmask, "fmask=%o"}, | 877 | {Opt_fmask, "fmask=%o"}, |
878 | {Opt_codepage, "codepage=%u"}, | 878 | {Opt_codepage, "codepage=%u"}, |
879 | {Opt_nocase, "nocase"}, | 879 | {Opt_nocase, "nocase"}, |
880 | {Opt_quiet, "quiet"}, | 880 | {Opt_quiet, "quiet"}, |
881 | {Opt_showexec, "showexec"}, | 881 | {Opt_showexec, "showexec"}, |
882 | {Opt_debug, "debug"}, | 882 | {Opt_debug, "debug"}, |
883 | {Opt_immutable, "sys_immutable"}, | 883 | {Opt_immutable, "sys_immutable"}, |
884 | {Opt_obsolate, "conv=binary"}, | 884 | {Opt_obsolate, "conv=binary"}, |
885 | {Opt_obsolate, "conv=text"}, | 885 | {Opt_obsolate, "conv=text"}, |
886 | {Opt_obsolate, "conv=auto"}, | 886 | {Opt_obsolate, "conv=auto"}, |
887 | {Opt_obsolate, "conv=b"}, | 887 | {Opt_obsolate, "conv=b"}, |
888 | {Opt_obsolate, "conv=t"}, | 888 | {Opt_obsolate, "conv=t"}, |
889 | {Opt_obsolate, "conv=a"}, | 889 | {Opt_obsolate, "conv=a"}, |
890 | {Opt_obsolate, "fat=%u"}, | 890 | {Opt_obsolate, "fat=%u"}, |
891 | {Opt_obsolate, "blocksize=%u"}, | 891 | {Opt_obsolate, "blocksize=%u"}, |
892 | {Opt_obsolate, "cvf_format=%20s"}, | 892 | {Opt_obsolate, "cvf_format=%20s"}, |
893 | {Opt_obsolate, "cvf_options=%100s"}, | 893 | {Opt_obsolate, "cvf_options=%100s"}, |
894 | {Opt_obsolate, "posix"}, | 894 | {Opt_obsolate, "posix"}, |
895 | {Opt_err, NULL} | 895 | {Opt_err, NULL} |
896 | }; | 896 | }; |
897 | static match_table_t msdos_tokens = { | 897 | static match_table_t msdos_tokens = { |
898 | {Opt_nodots, "nodots"}, | 898 | {Opt_nodots, "nodots"}, |
899 | {Opt_nodots, "dotsOK=no"}, | 899 | {Opt_nodots, "dotsOK=no"}, |
900 | {Opt_dots, "dots"}, | 900 | {Opt_dots, "dots"}, |
901 | {Opt_dots, "dotsOK=yes"}, | 901 | {Opt_dots, "dotsOK=yes"}, |
902 | {Opt_err, NULL} | 902 | {Opt_err, NULL} |
903 | }; | 903 | }; |
904 | static match_table_t vfat_tokens = { | 904 | static match_table_t vfat_tokens = { |
905 | {Opt_charset, "iocharset=%s"}, | 905 | {Opt_charset, "iocharset=%s"}, |
906 | {Opt_shortname_lower, "shortname=lower"}, | 906 | {Opt_shortname_lower, "shortname=lower"}, |
907 | {Opt_shortname_win95, "shortname=win95"}, | 907 | {Opt_shortname_win95, "shortname=win95"}, |
908 | {Opt_shortname_winnt, "shortname=winnt"}, | 908 | {Opt_shortname_winnt, "shortname=winnt"}, |
909 | {Opt_shortname_mixed, "shortname=mixed"}, | 909 | {Opt_shortname_mixed, "shortname=mixed"}, |
910 | {Opt_utf8_no, "utf8=0"}, /* 0 or no or false */ | 910 | {Opt_utf8_no, "utf8=0"}, /* 0 or no or false */ |
911 | {Opt_utf8_no, "utf8=no"}, | 911 | {Opt_utf8_no, "utf8=no"}, |
912 | {Opt_utf8_no, "utf8=false"}, | 912 | {Opt_utf8_no, "utf8=false"}, |
913 | {Opt_utf8_yes, "utf8=1"}, /* empty or 1 or yes or true */ | 913 | {Opt_utf8_yes, "utf8=1"}, /* empty or 1 or yes or true */ |
914 | {Opt_utf8_yes, "utf8=yes"}, | 914 | {Opt_utf8_yes, "utf8=yes"}, |
915 | {Opt_utf8_yes, "utf8=true"}, | 915 | {Opt_utf8_yes, "utf8=true"}, |
916 | {Opt_utf8_yes, "utf8"}, | 916 | {Opt_utf8_yes, "utf8"}, |
917 | {Opt_uni_xl_no, "uni_xlate=0"}, /* 0 or no or false */ | 917 | {Opt_uni_xl_no, "uni_xlate=0"}, /* 0 or no or false */ |
918 | {Opt_uni_xl_no, "uni_xlate=no"}, | 918 | {Opt_uni_xl_no, "uni_xlate=no"}, |
919 | {Opt_uni_xl_no, "uni_xlate=false"}, | 919 | {Opt_uni_xl_no, "uni_xlate=false"}, |
920 | {Opt_uni_xl_yes, "uni_xlate=1"}, /* empty or 1 or yes or true */ | 920 | {Opt_uni_xl_yes, "uni_xlate=1"}, /* empty or 1 or yes or true */ |
921 | {Opt_uni_xl_yes, "uni_xlate=yes"}, | 921 | {Opt_uni_xl_yes, "uni_xlate=yes"}, |
922 | {Opt_uni_xl_yes, "uni_xlate=true"}, | 922 | {Opt_uni_xl_yes, "uni_xlate=true"}, |
923 | {Opt_uni_xl_yes, "uni_xlate"}, | 923 | {Opt_uni_xl_yes, "uni_xlate"}, |
924 | {Opt_nonumtail_no, "nonumtail=0"}, /* 0 or no or false */ | 924 | {Opt_nonumtail_no, "nonumtail=0"}, /* 0 or no or false */ |
925 | {Opt_nonumtail_no, "nonumtail=no"}, | 925 | {Opt_nonumtail_no, "nonumtail=no"}, |
926 | {Opt_nonumtail_no, "nonumtail=false"}, | 926 | {Opt_nonumtail_no, "nonumtail=false"}, |
927 | {Opt_nonumtail_yes, "nonumtail=1"}, /* empty or 1 or yes or true */ | 927 | {Opt_nonumtail_yes, "nonumtail=1"}, /* empty or 1 or yes or true */ |
928 | {Opt_nonumtail_yes, "nonumtail=yes"}, | 928 | {Opt_nonumtail_yes, "nonumtail=yes"}, |
929 | {Opt_nonumtail_yes, "nonumtail=true"}, | 929 | {Opt_nonumtail_yes, "nonumtail=true"}, |
930 | {Opt_nonumtail_yes, "nonumtail"}, | 930 | {Opt_nonumtail_yes, "nonumtail"}, |
931 | {Opt_err, NULL} | 931 | {Opt_err, NULL} |
932 | }; | 932 | }; |
933 | 933 | ||
934 | static int parse_options(char *options, int is_vfat, int silent, int *debug, | 934 | static int parse_options(char *options, int is_vfat, int silent, int *debug, |
935 | struct fat_mount_options *opts) | 935 | struct fat_mount_options *opts) |
936 | { | 936 | { |
937 | char *p; | 937 | char *p; |
938 | substring_t args[MAX_OPT_ARGS]; | 938 | substring_t args[MAX_OPT_ARGS]; |
939 | int option; | 939 | int option; |
940 | char *iocharset; | 940 | char *iocharset; |
941 | 941 | ||
942 | opts->isvfat = is_vfat; | 942 | opts->isvfat = is_vfat; |
943 | 943 | ||
944 | opts->fs_uid = current->uid; | 944 | opts->fs_uid = current->uid; |
945 | opts->fs_gid = current->gid; | 945 | opts->fs_gid = current->gid; |
946 | opts->fs_fmask = opts->fs_dmask = current->fs->umask; | 946 | opts->fs_fmask = opts->fs_dmask = current->fs->umask; |
947 | opts->codepage = fat_default_codepage; | 947 | opts->codepage = fat_default_codepage; |
948 | opts->iocharset = fat_default_iocharset; | 948 | opts->iocharset = fat_default_iocharset; |
949 | if (is_vfat) | 949 | if (is_vfat) |
950 | opts->shortname = VFAT_SFN_DISPLAY_LOWER|VFAT_SFN_CREATE_WIN95; | 950 | opts->shortname = VFAT_SFN_DISPLAY_LOWER|VFAT_SFN_CREATE_WIN95; |
951 | else | 951 | else |
952 | opts->shortname = 0; | 952 | opts->shortname = 0; |
953 | opts->name_check = 'n'; | 953 | opts->name_check = 'n'; |
954 | opts->quiet = opts->showexec = opts->sys_immutable = opts->dotsOK = 0; | 954 | opts->quiet = opts->showexec = opts->sys_immutable = opts->dotsOK = 0; |
955 | opts->utf8 = opts->unicode_xlate = 0; | 955 | opts->utf8 = opts->unicode_xlate = 0; |
956 | opts->numtail = 1; | 956 | opts->numtail = 1; |
957 | opts->nocase = 0; | 957 | opts->nocase = 0; |
958 | *debug = 0; | 958 | *debug = 0; |
959 | 959 | ||
960 | if (!options) | 960 | if (!options) |
961 | return 0; | 961 | return 0; |
962 | 962 | ||
963 | while ((p = strsep(&options, ",")) != NULL) { | 963 | while ((p = strsep(&options, ",")) != NULL) { |
964 | int token; | 964 | int token; |
965 | if (!*p) | 965 | if (!*p) |
966 | continue; | 966 | continue; |
967 | 967 | ||
968 | token = match_token(p, fat_tokens, args); | 968 | token = match_token(p, fat_tokens, args); |
969 | if (token == Opt_err) { | 969 | if (token == Opt_err) { |
970 | if (is_vfat) | 970 | if (is_vfat) |
971 | token = match_token(p, vfat_tokens, args); | 971 | token = match_token(p, vfat_tokens, args); |
972 | else | 972 | else |
973 | token = match_token(p, msdos_tokens, args); | 973 | token = match_token(p, msdos_tokens, args); |
974 | } | 974 | } |
975 | switch (token) { | 975 | switch (token) { |
976 | case Opt_check_s: | 976 | case Opt_check_s: |
977 | opts->name_check = 's'; | 977 | opts->name_check = 's'; |
978 | break; | 978 | break; |
979 | case Opt_check_r: | 979 | case Opt_check_r: |
980 | opts->name_check = 'r'; | 980 | opts->name_check = 'r'; |
981 | break; | 981 | break; |
982 | case Opt_check_n: | 982 | case Opt_check_n: |
983 | opts->name_check = 'n'; | 983 | opts->name_check = 'n'; |
984 | break; | 984 | break; |
985 | case Opt_nocase: | 985 | case Opt_nocase: |
986 | if (!is_vfat) | 986 | if (!is_vfat) |
987 | opts->nocase = 1; | 987 | opts->nocase = 1; |
988 | else { | 988 | else { |
989 | /* for backward compatibility */ | 989 | /* for backward compatibility */ |
990 | opts->shortname = VFAT_SFN_DISPLAY_WIN95 | 990 | opts->shortname = VFAT_SFN_DISPLAY_WIN95 |
991 | | VFAT_SFN_CREATE_WIN95; | 991 | | VFAT_SFN_CREATE_WIN95; |
992 | } | 992 | } |
993 | break; | 993 | break; |
994 | case Opt_quiet: | 994 | case Opt_quiet: |
995 | opts->quiet = 1; | 995 | opts->quiet = 1; |
996 | break; | 996 | break; |
997 | case Opt_showexec: | 997 | case Opt_showexec: |
998 | opts->showexec = 1; | 998 | opts->showexec = 1; |
999 | break; | 999 | break; |
1000 | case Opt_debug: | 1000 | case Opt_debug: |
1001 | *debug = 1; | 1001 | *debug = 1; |
1002 | break; | 1002 | break; |
1003 | case Opt_immutable: | 1003 | case Opt_immutable: |
1004 | opts->sys_immutable = 1; | 1004 | opts->sys_immutable = 1; |
1005 | break; | 1005 | break; |
1006 | case Opt_uid: | 1006 | case Opt_uid: |
1007 | if (match_int(&args[0], &option)) | 1007 | if (match_int(&args[0], &option)) |
1008 | return 0; | 1008 | return 0; |
1009 | opts->fs_uid = option; | 1009 | opts->fs_uid = option; |
1010 | break; | 1010 | break; |
1011 | case Opt_gid: | 1011 | case Opt_gid: |
1012 | if (match_int(&args[0], &option)) | 1012 | if (match_int(&args[0], &option)) |
1013 | return 0; | 1013 | return 0; |
1014 | opts->fs_gid = option; | 1014 | opts->fs_gid = option; |
1015 | break; | 1015 | break; |
1016 | case Opt_umask: | 1016 | case Opt_umask: |
1017 | if (match_octal(&args[0], &option)) | 1017 | if (match_octal(&args[0], &option)) |
1018 | return 0; | 1018 | return 0; |
1019 | opts->fs_fmask = opts->fs_dmask = option; | 1019 | opts->fs_fmask = opts->fs_dmask = option; |
1020 | break; | 1020 | break; |
1021 | case Opt_dmask: | 1021 | case Opt_dmask: |
1022 | if (match_octal(&args[0], &option)) | 1022 | if (match_octal(&args[0], &option)) |
1023 | return 0; | 1023 | return 0; |
1024 | opts->fs_dmask = option; | 1024 | opts->fs_dmask = option; |
1025 | break; | 1025 | break; |
1026 | case Opt_fmask: | 1026 | case Opt_fmask: |
1027 | if (match_octal(&args[0], &option)) | 1027 | if (match_octal(&args[0], &option)) |
1028 | return 0; | 1028 | return 0; |
1029 | opts->fs_fmask = option; | 1029 | opts->fs_fmask = option; |
1030 | break; | 1030 | break; |
1031 | case Opt_codepage: | 1031 | case Opt_codepage: |
1032 | if (match_int(&args[0], &option)) | 1032 | if (match_int(&args[0], &option)) |
1033 | return 0; | 1033 | return 0; |
1034 | opts->codepage = option; | 1034 | opts->codepage = option; |
1035 | break; | 1035 | break; |
1036 | 1036 | ||
1037 | /* msdos specific */ | 1037 | /* msdos specific */ |
1038 | case Opt_dots: | 1038 | case Opt_dots: |
1039 | opts->dotsOK = 1; | 1039 | opts->dotsOK = 1; |
1040 | break; | 1040 | break; |
1041 | case Opt_nodots: | 1041 | case Opt_nodots: |
1042 | opts->dotsOK = 0; | 1042 | opts->dotsOK = 0; |
1043 | break; | 1043 | break; |
1044 | 1044 | ||
1045 | /* vfat specific */ | 1045 | /* vfat specific */ |
1046 | case Opt_charset: | 1046 | case Opt_charset: |
1047 | if (opts->iocharset != fat_default_iocharset) | 1047 | if (opts->iocharset != fat_default_iocharset) |
1048 | kfree(opts->iocharset); | 1048 | kfree(opts->iocharset); |
1049 | iocharset = match_strdup(&args[0]); | 1049 | iocharset = match_strdup(&args[0]); |
1050 | if (!iocharset) | 1050 | if (!iocharset) |
1051 | return -ENOMEM; | 1051 | return -ENOMEM; |
1052 | opts->iocharset = iocharset; | 1052 | opts->iocharset = iocharset; |
1053 | break; | 1053 | break; |
1054 | case Opt_shortname_lower: | 1054 | case Opt_shortname_lower: |
1055 | opts->shortname = VFAT_SFN_DISPLAY_LOWER | 1055 | opts->shortname = VFAT_SFN_DISPLAY_LOWER |
1056 | | VFAT_SFN_CREATE_WIN95; | 1056 | | VFAT_SFN_CREATE_WIN95; |
1057 | break; | 1057 | break; |
1058 | case Opt_shortname_win95: | 1058 | case Opt_shortname_win95: |
1059 | opts->shortname = VFAT_SFN_DISPLAY_WIN95 | 1059 | opts->shortname = VFAT_SFN_DISPLAY_WIN95 |
1060 | | VFAT_SFN_CREATE_WIN95; | 1060 | | VFAT_SFN_CREATE_WIN95; |
1061 | break; | 1061 | break; |
1062 | case Opt_shortname_winnt: | 1062 | case Opt_shortname_winnt: |
1063 | opts->shortname = VFAT_SFN_DISPLAY_WINNT | 1063 | opts->shortname = VFAT_SFN_DISPLAY_WINNT |
1064 | | VFAT_SFN_CREATE_WINNT; | 1064 | | VFAT_SFN_CREATE_WINNT; |
1065 | break; | 1065 | break; |
1066 | case Opt_shortname_mixed: | 1066 | case Opt_shortname_mixed: |
1067 | opts->shortname = VFAT_SFN_DISPLAY_WINNT | 1067 | opts->shortname = VFAT_SFN_DISPLAY_WINNT |
1068 | | VFAT_SFN_CREATE_WIN95; | 1068 | | VFAT_SFN_CREATE_WIN95; |
1069 | break; | 1069 | break; |
1070 | case Opt_utf8_no: /* 0 or no or false */ | 1070 | case Opt_utf8_no: /* 0 or no or false */ |
1071 | opts->utf8 = 0; | 1071 | opts->utf8 = 0; |
1072 | break; | 1072 | break; |
1073 | case Opt_utf8_yes: /* empty or 1 or yes or true */ | 1073 | case Opt_utf8_yes: /* empty or 1 or yes or true */ |
1074 | opts->utf8 = 1; | 1074 | opts->utf8 = 1; |
1075 | break; | 1075 | break; |
1076 | case Opt_uni_xl_no: /* 0 or no or false */ | 1076 | case Opt_uni_xl_no: /* 0 or no or false */ |
1077 | opts->unicode_xlate = 0; | 1077 | opts->unicode_xlate = 0; |
1078 | break; | 1078 | break; |
1079 | case Opt_uni_xl_yes: /* empty or 1 or yes or true */ | 1079 | case Opt_uni_xl_yes: /* empty or 1 or yes or true */ |
1080 | opts->unicode_xlate = 1; | 1080 | opts->unicode_xlate = 1; |
1081 | break; | 1081 | break; |
1082 | case Opt_nonumtail_no: /* 0 or no or false */ | 1082 | case Opt_nonumtail_no: /* 0 or no or false */ |
1083 | opts->numtail = 1; /* negated option */ | 1083 | opts->numtail = 1; /* negated option */ |
1084 | break; | 1084 | break; |
1085 | case Opt_nonumtail_yes: /* empty or 1 or yes or true */ | 1085 | case Opt_nonumtail_yes: /* empty or 1 or yes or true */ |
1086 | opts->numtail = 0; /* negated option */ | 1086 | opts->numtail = 0; /* negated option */ |
1087 | break; | 1087 | break; |
1088 | 1088 | ||
1089 | /* obsolete mount options */ | 1089 | /* obsolete mount options */ |
1090 | case Opt_obsolate: | 1090 | case Opt_obsolate: |
1091 | printk(KERN_INFO "FAT: \"%s\" option is obsolete, " | 1091 | printk(KERN_INFO "FAT: \"%s\" option is obsolete, " |
1092 | "not supported now\n", p); | 1092 | "not supported now\n", p); |
1093 | break; | 1093 | break; |
1094 | /* unknown option */ | 1094 | /* unknown option */ |
1095 | default: | 1095 | default: |
1096 | if (!silent) { | 1096 | if (!silent) { |
1097 | printk(KERN_ERR | 1097 | printk(KERN_ERR |
1098 | "FAT: Unrecognized mount option \"%s\" " | 1098 | "FAT: Unrecognized mount option \"%s\" " |
1099 | "or missing value\n", p); | 1099 | "or missing value\n", p); |
1100 | } | 1100 | } |
1101 | return -EINVAL; | 1101 | return -EINVAL; |
1102 | } | 1102 | } |
1103 | } | 1103 | } |
1104 | /* UTF8 doesn't provide FAT semantics */ | 1104 | /* UTF-8 doesn't provide FAT semantics */ |
1105 | if (!strcmp(opts->iocharset, "utf8")) { | 1105 | if (!strcmp(opts->iocharset, "utf8")) { |
1106 | printk(KERN_ERR "FAT: utf8 is not a recommended IO charset" | 1106 | printk(KERN_ERR "FAT: utf8 is not a recommended IO charset" |
1107 | " for FAT filesystems, filesystem will be case sensitive!\n"); | 1107 | " for FAT filesystems, filesystem will be case sensitive!\n"); |
1108 | } | 1108 | } |
1109 | 1109 | ||
1110 | if (opts->unicode_xlate) | 1110 | if (opts->unicode_xlate) |
1111 | opts->utf8 = 0; | 1111 | opts->utf8 = 0; |
1112 | 1112 | ||
1113 | return 0; | 1113 | return 0; |
1114 | } | 1114 | } |
1115 | 1115 | ||
1116 | static int fat_read_root(struct inode *inode) | 1116 | static int fat_read_root(struct inode *inode) |
1117 | { | 1117 | { |
1118 | struct super_block *sb = inode->i_sb; | 1118 | struct super_block *sb = inode->i_sb; |
1119 | struct msdos_sb_info *sbi = MSDOS_SB(sb); | 1119 | struct msdos_sb_info *sbi = MSDOS_SB(sb); |
1120 | int error; | 1120 | int error; |
1121 | 1121 | ||
1122 | MSDOS_I(inode)->i_pos = 0; | 1122 | MSDOS_I(inode)->i_pos = 0; |
1123 | inode->i_uid = sbi->options.fs_uid; | 1123 | inode->i_uid = sbi->options.fs_uid; |
1124 | inode->i_gid = sbi->options.fs_gid; | 1124 | inode->i_gid = sbi->options.fs_gid; |
1125 | inode->i_version++; | 1125 | inode->i_version++; |
1126 | inode->i_generation = 0; | 1126 | inode->i_generation = 0; |
1127 | inode->i_mode = (S_IRWXUGO & ~sbi->options.fs_dmask) | S_IFDIR; | 1127 | inode->i_mode = (S_IRWXUGO & ~sbi->options.fs_dmask) | S_IFDIR; |
1128 | inode->i_op = sbi->dir_ops; | 1128 | inode->i_op = sbi->dir_ops; |
1129 | inode->i_fop = &fat_dir_operations; | 1129 | inode->i_fop = &fat_dir_operations; |
1130 | if (sbi->fat_bits == 32) { | 1130 | if (sbi->fat_bits == 32) { |
1131 | MSDOS_I(inode)->i_start = sbi->root_cluster; | 1131 | MSDOS_I(inode)->i_start = sbi->root_cluster; |
1132 | error = fat_calc_dir_size(inode); | 1132 | error = fat_calc_dir_size(inode); |
1133 | if (error < 0) | 1133 | if (error < 0) |
1134 | return error; | 1134 | return error; |
1135 | } else { | 1135 | } else { |
1136 | MSDOS_I(inode)->i_start = 0; | 1136 | MSDOS_I(inode)->i_start = 0; |
1137 | inode->i_size = sbi->dir_entries * sizeof(struct msdos_dir_entry); | 1137 | inode->i_size = sbi->dir_entries * sizeof(struct msdos_dir_entry); |
1138 | } | 1138 | } |
1139 | inode->i_blksize = sbi->cluster_size; | 1139 | inode->i_blksize = sbi->cluster_size; |
1140 | inode->i_blocks = ((inode->i_size + (sbi->cluster_size - 1)) | 1140 | inode->i_blocks = ((inode->i_size + (sbi->cluster_size - 1)) |
1141 | & ~((loff_t)sbi->cluster_size - 1)) >> 9; | 1141 | & ~((loff_t)sbi->cluster_size - 1)) >> 9; |
1142 | MSDOS_I(inode)->i_logstart = 0; | 1142 | MSDOS_I(inode)->i_logstart = 0; |
1143 | MSDOS_I(inode)->mmu_private = inode->i_size; | 1143 | MSDOS_I(inode)->mmu_private = inode->i_size; |
1144 | 1144 | ||
1145 | MSDOS_I(inode)->i_attrs = ATTR_NONE; | 1145 | MSDOS_I(inode)->i_attrs = ATTR_NONE; |
1146 | inode->i_mtime.tv_sec = inode->i_atime.tv_sec = inode->i_ctime.tv_sec = 0; | 1146 | inode->i_mtime.tv_sec = inode->i_atime.tv_sec = inode->i_ctime.tv_sec = 0; |
1147 | inode->i_mtime.tv_nsec = inode->i_atime.tv_nsec = inode->i_ctime.tv_nsec = 0; | 1147 | inode->i_mtime.tv_nsec = inode->i_atime.tv_nsec = inode->i_ctime.tv_nsec = 0; |
1148 | inode->i_nlink = fat_subdirs(inode)+2; | 1148 | inode->i_nlink = fat_subdirs(inode)+2; |
1149 | 1149 | ||
1150 | return 0; | 1150 | return 0; |
1151 | } | 1151 | } |
1152 | 1152 | ||
1153 | /* | 1153 | /* |
1154 | * Read the super block of an MS-DOS FS. | 1154 | * Read the super block of an MS-DOS FS. |
1155 | */ | 1155 | */ |
1156 | int fat_fill_super(struct super_block *sb, void *data, int silent, | 1156 | int fat_fill_super(struct super_block *sb, void *data, int silent, |
1157 | struct inode_operations *fs_dir_inode_ops, int isvfat) | 1157 | struct inode_operations *fs_dir_inode_ops, int isvfat) |
1158 | { | 1158 | { |
1159 | struct inode *root_inode = NULL; | 1159 | struct inode *root_inode = NULL; |
1160 | struct buffer_head *bh; | 1160 | struct buffer_head *bh; |
1161 | struct fat_boot_sector *b; | 1161 | struct fat_boot_sector *b; |
1162 | struct msdos_sb_info *sbi; | 1162 | struct msdos_sb_info *sbi; |
1163 | u16 logical_sector_size; | 1163 | u16 logical_sector_size; |
1164 | u32 total_sectors, total_clusters, fat_clusters, rootdir_sectors; | 1164 | u32 total_sectors, total_clusters, fat_clusters, rootdir_sectors; |
1165 | int debug; | 1165 | int debug; |
1166 | unsigned int media; | 1166 | unsigned int media; |
1167 | long error; | 1167 | long error; |
1168 | char buf[50]; | 1168 | char buf[50]; |
1169 | 1169 | ||
1170 | sbi = kmalloc(sizeof(struct msdos_sb_info), GFP_KERNEL); | 1170 | sbi = kmalloc(sizeof(struct msdos_sb_info), GFP_KERNEL); |
1171 | if (!sbi) | 1171 | if (!sbi) |
1172 | return -ENOMEM; | 1172 | return -ENOMEM; |
1173 | sb->s_fs_info = sbi; | 1173 | sb->s_fs_info = sbi; |
1174 | memset(sbi, 0, sizeof(struct msdos_sb_info)); | 1174 | memset(sbi, 0, sizeof(struct msdos_sb_info)); |
1175 | 1175 | ||
1176 | sb->s_flags |= MS_NODIRATIME; | 1176 | sb->s_flags |= MS_NODIRATIME; |
1177 | sb->s_magic = MSDOS_SUPER_MAGIC; | 1177 | sb->s_magic = MSDOS_SUPER_MAGIC; |
1178 | sb->s_op = &fat_sops; | 1178 | sb->s_op = &fat_sops; |
1179 | sb->s_export_op = &fat_export_ops; | 1179 | sb->s_export_op = &fat_export_ops; |
1180 | sbi->dir_ops = fs_dir_inode_ops; | 1180 | sbi->dir_ops = fs_dir_inode_ops; |
1181 | 1181 | ||
1182 | error = parse_options(data, isvfat, silent, &debug, &sbi->options); | 1182 | error = parse_options(data, isvfat, silent, &debug, &sbi->options); |
1183 | if (error) | 1183 | if (error) |
1184 | goto out_fail; | 1184 | goto out_fail; |
1185 | 1185 | ||
1186 | error = -EIO; | 1186 | error = -EIO; |
1187 | sb_min_blocksize(sb, 512); | 1187 | sb_min_blocksize(sb, 512); |
1188 | bh = sb_bread(sb, 0); | 1188 | bh = sb_bread(sb, 0); |
1189 | if (bh == NULL) { | 1189 | if (bh == NULL) { |
1190 | printk(KERN_ERR "FAT: unable to read boot sector\n"); | 1190 | printk(KERN_ERR "FAT: unable to read boot sector\n"); |
1191 | goto out_fail; | 1191 | goto out_fail; |
1192 | } | 1192 | } |
1193 | 1193 | ||
1194 | b = (struct fat_boot_sector *) bh->b_data; | 1194 | b = (struct fat_boot_sector *) bh->b_data; |
1195 | if (!b->reserved) { | 1195 | if (!b->reserved) { |
1196 | if (!silent) | 1196 | if (!silent) |
1197 | printk(KERN_ERR "FAT: bogus number of reserved sectors\n"); | 1197 | printk(KERN_ERR "FAT: bogus number of reserved sectors\n"); |
1198 | brelse(bh); | 1198 | brelse(bh); |
1199 | goto out_invalid; | 1199 | goto out_invalid; |
1200 | } | 1200 | } |
1201 | if (!b->fats) { | 1201 | if (!b->fats) { |
1202 | if (!silent) | 1202 | if (!silent) |
1203 | printk(KERN_ERR "FAT: bogus number of FAT structure\n"); | 1203 | printk(KERN_ERR "FAT: bogus number of FAT structure\n"); |
1204 | brelse(bh); | 1204 | brelse(bh); |
1205 | goto out_invalid; | 1205 | goto out_invalid; |
1206 | } | 1206 | } |
1207 | 1207 | ||
1208 | /* | 1208 | /* |
1209 | * Earlier we checked here that b->secs_track and b->head are nonzero, | 1209 | * Earlier we checked here that b->secs_track and b->head are nonzero, |
1210 | * but it turns out valid FAT filesystems can have zero there. | 1210 | * but it turns out valid FAT filesystems can have zero there. |
1211 | */ | 1211 | */ |
1212 | 1212 | ||
1213 | media = b->media; | 1213 | media = b->media; |
1214 | if (!FAT_VALID_MEDIA(media)) { | 1214 | if (!FAT_VALID_MEDIA(media)) { |
1215 | if (!silent) | 1215 | if (!silent) |
1216 | printk(KERN_ERR "FAT: invalid media value (0x%02x)\n", | 1216 | printk(KERN_ERR "FAT: invalid media value (0x%02x)\n", |
1217 | media); | 1217 | media); |
1218 | brelse(bh); | 1218 | brelse(bh); |
1219 | goto out_invalid; | 1219 | goto out_invalid; |
1220 | } | 1220 | } |
1221 | logical_sector_size = | 1221 | logical_sector_size = |
1222 | le16_to_cpu(get_unaligned((__le16 *)&b->sector_size)); | 1222 | le16_to_cpu(get_unaligned((__le16 *)&b->sector_size)); |
1223 | if (!logical_sector_size | 1223 | if (!logical_sector_size |
1224 | || (logical_sector_size & (logical_sector_size - 1)) | 1224 | || (logical_sector_size & (logical_sector_size - 1)) |
1225 | || (logical_sector_size < 512) | 1225 | || (logical_sector_size < 512) |
1226 | || (PAGE_CACHE_SIZE < logical_sector_size)) { | 1226 | || (PAGE_CACHE_SIZE < logical_sector_size)) { |
1227 | if (!silent) | 1227 | if (!silent) |
1228 | printk(KERN_ERR "FAT: bogus logical sector size %u\n", | 1228 | printk(KERN_ERR "FAT: bogus logical sector size %u\n", |
1229 | logical_sector_size); | 1229 | logical_sector_size); |
1230 | brelse(bh); | 1230 | brelse(bh); |
1231 | goto out_invalid; | 1231 | goto out_invalid; |
1232 | } | 1232 | } |
1233 | sbi->sec_per_clus = b->sec_per_clus; | 1233 | sbi->sec_per_clus = b->sec_per_clus; |
1234 | if (!sbi->sec_per_clus | 1234 | if (!sbi->sec_per_clus |
1235 | || (sbi->sec_per_clus & (sbi->sec_per_clus - 1))) { | 1235 | || (sbi->sec_per_clus & (sbi->sec_per_clus - 1))) { |
1236 | if (!silent) | 1236 | if (!silent) |
1237 | printk(KERN_ERR "FAT: bogus sectors per cluster %u\n", | 1237 | printk(KERN_ERR "FAT: bogus sectors per cluster %u\n", |
1238 | sbi->sec_per_clus); | 1238 | sbi->sec_per_clus); |
1239 | brelse(bh); | 1239 | brelse(bh); |
1240 | goto out_invalid; | 1240 | goto out_invalid; |
1241 | } | 1241 | } |
1242 | 1242 | ||
1243 | if (logical_sector_size < sb->s_blocksize) { | 1243 | if (logical_sector_size < sb->s_blocksize) { |
1244 | printk(KERN_ERR "FAT: logical sector size too small for device" | 1244 | printk(KERN_ERR "FAT: logical sector size too small for device" |
1245 | " (logical sector size = %u)\n", logical_sector_size); | 1245 | " (logical sector size = %u)\n", logical_sector_size); |
1246 | brelse(bh); | 1246 | brelse(bh); |
1247 | goto out_fail; | 1247 | goto out_fail; |
1248 | } | 1248 | } |
1249 | if (logical_sector_size > sb->s_blocksize) { | 1249 | if (logical_sector_size > sb->s_blocksize) { |
1250 | brelse(bh); | 1250 | brelse(bh); |
1251 | 1251 | ||
1252 | if (!sb_set_blocksize(sb, logical_sector_size)) { | 1252 | if (!sb_set_blocksize(sb, logical_sector_size)) { |
1253 | printk(KERN_ERR "FAT: unable to set blocksize %u\n", | 1253 | printk(KERN_ERR "FAT: unable to set blocksize %u\n", |
1254 | logical_sector_size); | 1254 | logical_sector_size); |
1255 | goto out_fail; | 1255 | goto out_fail; |
1256 | } | 1256 | } |
1257 | bh = sb_bread(sb, 0); | 1257 | bh = sb_bread(sb, 0); |
1258 | if (bh == NULL) { | 1258 | if (bh == NULL) { |
1259 | printk(KERN_ERR "FAT: unable to read boot sector" | 1259 | printk(KERN_ERR "FAT: unable to read boot sector" |
1260 | " (logical sector size = %lu)\n", | 1260 | " (logical sector size = %lu)\n", |
1261 | sb->s_blocksize); | 1261 | sb->s_blocksize); |
1262 | goto out_fail; | 1262 | goto out_fail; |
1263 | } | 1263 | } |
1264 | b = (struct fat_boot_sector *) bh->b_data; | 1264 | b = (struct fat_boot_sector *) bh->b_data; |
1265 | } | 1265 | } |
1266 | 1266 | ||
1267 | sbi->cluster_size = sb->s_blocksize * sbi->sec_per_clus; | 1267 | sbi->cluster_size = sb->s_blocksize * sbi->sec_per_clus; |
1268 | sbi->cluster_bits = ffs(sbi->cluster_size) - 1; | 1268 | sbi->cluster_bits = ffs(sbi->cluster_size) - 1; |
1269 | sbi->fats = b->fats; | 1269 | sbi->fats = b->fats; |
1270 | sbi->fat_bits = 0; /* Don't know yet */ | 1270 | sbi->fat_bits = 0; /* Don't know yet */ |
1271 | sbi->fat_start = le16_to_cpu(b->reserved); | 1271 | sbi->fat_start = le16_to_cpu(b->reserved); |
1272 | sbi->fat_length = le16_to_cpu(b->fat_length); | 1272 | sbi->fat_length = le16_to_cpu(b->fat_length); |
1273 | sbi->root_cluster = 0; | 1273 | sbi->root_cluster = 0; |
1274 | sbi->free_clusters = -1; /* Don't know yet */ | 1274 | sbi->free_clusters = -1; /* Don't know yet */ |
1275 | sbi->prev_free = FAT_START_ENT; | 1275 | sbi->prev_free = FAT_START_ENT; |
1276 | 1276 | ||
1277 | if (!sbi->fat_length && b->fat32_length) { | 1277 | if (!sbi->fat_length && b->fat32_length) { |
1278 | struct fat_boot_fsinfo *fsinfo; | 1278 | struct fat_boot_fsinfo *fsinfo; |
1279 | struct buffer_head *fsinfo_bh; | 1279 | struct buffer_head *fsinfo_bh; |
1280 | 1280 | ||
1281 | /* Must be FAT32 */ | 1281 | /* Must be FAT32 */ |
1282 | sbi->fat_bits = 32; | 1282 | sbi->fat_bits = 32; |
1283 | sbi->fat_length = le32_to_cpu(b->fat32_length); | 1283 | sbi->fat_length = le32_to_cpu(b->fat32_length); |
1284 | sbi->root_cluster = le32_to_cpu(b->root_cluster); | 1284 | sbi->root_cluster = le32_to_cpu(b->root_cluster); |
1285 | 1285 | ||
1286 | sb->s_maxbytes = 0xffffffff; | 1286 | sb->s_maxbytes = 0xffffffff; |
1287 | 1287 | ||
1288 | /* MC - if info_sector is 0, don't multiply by 0 */ | 1288 | /* MC - if info_sector is 0, don't multiply by 0 */ |
1289 | sbi->fsinfo_sector = le16_to_cpu(b->info_sector); | 1289 | sbi->fsinfo_sector = le16_to_cpu(b->info_sector); |
1290 | if (sbi->fsinfo_sector == 0) | 1290 | if (sbi->fsinfo_sector == 0) |
1291 | sbi->fsinfo_sector = 1; | 1291 | sbi->fsinfo_sector = 1; |
1292 | 1292 | ||
1293 | fsinfo_bh = sb_bread(sb, sbi->fsinfo_sector); | 1293 | fsinfo_bh = sb_bread(sb, sbi->fsinfo_sector); |
1294 | if (fsinfo_bh == NULL) { | 1294 | if (fsinfo_bh == NULL) { |
1295 | printk(KERN_ERR "FAT: bread failed, FSINFO block" | 1295 | printk(KERN_ERR "FAT: bread failed, FSINFO block" |
1296 | " (sector = %lu)\n", sbi->fsinfo_sector); | 1296 | " (sector = %lu)\n", sbi->fsinfo_sector); |
1297 | brelse(bh); | 1297 | brelse(bh); |
1298 | goto out_fail; | 1298 | goto out_fail; |
1299 | } | 1299 | } |
1300 | 1300 | ||
1301 | fsinfo = (struct fat_boot_fsinfo *)fsinfo_bh->b_data; | 1301 | fsinfo = (struct fat_boot_fsinfo *)fsinfo_bh->b_data; |
1302 | if (!IS_FSINFO(fsinfo)) { | 1302 | if (!IS_FSINFO(fsinfo)) { |
1303 | printk(KERN_WARNING | 1303 | printk(KERN_WARNING |
1304 | "FAT: Did not find valid FSINFO signature.\n" | 1304 | "FAT: Did not find valid FSINFO signature.\n" |
1305 | " Found signature1 0x%08x signature2 0x%08x" | 1305 | " Found signature1 0x%08x signature2 0x%08x" |
1306 | " (sector = %lu)\n", | 1306 | " (sector = %lu)\n", |
1307 | le32_to_cpu(fsinfo->signature1), | 1307 | le32_to_cpu(fsinfo->signature1), |
1308 | le32_to_cpu(fsinfo->signature2), | 1308 | le32_to_cpu(fsinfo->signature2), |
1309 | sbi->fsinfo_sector); | 1309 | sbi->fsinfo_sector); |
1310 | } else { | 1310 | } else { |
1311 | sbi->free_clusters = le32_to_cpu(fsinfo->free_clusters); | 1311 | sbi->free_clusters = le32_to_cpu(fsinfo->free_clusters); |
1312 | sbi->prev_free = le32_to_cpu(fsinfo->next_cluster); | 1312 | sbi->prev_free = le32_to_cpu(fsinfo->next_cluster); |
1313 | } | 1313 | } |
1314 | 1314 | ||
1315 | brelse(fsinfo_bh); | 1315 | brelse(fsinfo_bh); |
1316 | } | 1316 | } |
1317 | 1317 | ||
1318 | sbi->dir_per_block = sb->s_blocksize / sizeof(struct msdos_dir_entry); | 1318 | sbi->dir_per_block = sb->s_blocksize / sizeof(struct msdos_dir_entry); |
1319 | sbi->dir_per_block_bits = ffs(sbi->dir_per_block) - 1; | 1319 | sbi->dir_per_block_bits = ffs(sbi->dir_per_block) - 1; |
1320 | 1320 | ||
1321 | sbi->dir_start = sbi->fat_start + sbi->fats * sbi->fat_length; | 1321 | sbi->dir_start = sbi->fat_start + sbi->fats * sbi->fat_length; |
1322 | sbi->dir_entries = | 1322 | sbi->dir_entries = |
1323 | le16_to_cpu(get_unaligned((__le16 *)&b->dir_entries)); | 1323 | le16_to_cpu(get_unaligned((__le16 *)&b->dir_entries)); |
1324 | if (sbi->dir_entries & (sbi->dir_per_block - 1)) { | 1324 | if (sbi->dir_entries & (sbi->dir_per_block - 1)) { |
1325 | if (!silent) | 1325 | if (!silent) |
1326 | printk(KERN_ERR "FAT: bogus directroy-entries per block" | 1326 | printk(KERN_ERR "FAT: bogus directroy-entries per block" |
1327 | " (%u)\n", sbi->dir_entries); | 1327 | " (%u)\n", sbi->dir_entries); |
1328 | brelse(bh); | 1328 | brelse(bh); |
1329 | goto out_invalid; | 1329 | goto out_invalid; |
1330 | } | 1330 | } |
1331 | 1331 | ||
1332 | rootdir_sectors = sbi->dir_entries | 1332 | rootdir_sectors = sbi->dir_entries |
1333 | * sizeof(struct msdos_dir_entry) / sb->s_blocksize; | 1333 | * sizeof(struct msdos_dir_entry) / sb->s_blocksize; |
1334 | sbi->data_start = sbi->dir_start + rootdir_sectors; | 1334 | sbi->data_start = sbi->dir_start + rootdir_sectors; |
1335 | total_sectors = le16_to_cpu(get_unaligned((__le16 *)&b->sectors)); | 1335 | total_sectors = le16_to_cpu(get_unaligned((__le16 *)&b->sectors)); |
1336 | if (total_sectors == 0) | 1336 | if (total_sectors == 0) |
1337 | total_sectors = le32_to_cpu(b->total_sect); | 1337 | total_sectors = le32_to_cpu(b->total_sect); |
1338 | 1338 | ||
1339 | total_clusters = (total_sectors - sbi->data_start) / sbi->sec_per_clus; | 1339 | total_clusters = (total_sectors - sbi->data_start) / sbi->sec_per_clus; |
1340 | 1340 | ||
1341 | if (sbi->fat_bits != 32) | 1341 | if (sbi->fat_bits != 32) |
1342 | sbi->fat_bits = (total_clusters > MAX_FAT12) ? 16 : 12; | 1342 | sbi->fat_bits = (total_clusters > MAX_FAT12) ? 16 : 12; |
1343 | 1343 | ||
1344 | /* check that FAT table does not overflow */ | 1344 | /* check that FAT table does not overflow */ |
1345 | fat_clusters = sbi->fat_length * sb->s_blocksize * 8 / sbi->fat_bits; | 1345 | fat_clusters = sbi->fat_length * sb->s_blocksize * 8 / sbi->fat_bits; |
1346 | total_clusters = min(total_clusters, fat_clusters - FAT_START_ENT); | 1346 | total_clusters = min(total_clusters, fat_clusters - FAT_START_ENT); |
1347 | if (total_clusters > MAX_FAT(sb)) { | 1347 | if (total_clusters > MAX_FAT(sb)) { |
1348 | if (!silent) | 1348 | if (!silent) |
1349 | printk(KERN_ERR "FAT: count of clusters too big (%u)\n", | 1349 | printk(KERN_ERR "FAT: count of clusters too big (%u)\n", |
1350 | total_clusters); | 1350 | total_clusters); |
1351 | brelse(bh); | 1351 | brelse(bh); |
1352 | goto out_invalid; | 1352 | goto out_invalid; |
1353 | } | 1353 | } |
1354 | 1354 | ||
1355 | sbi->max_cluster = total_clusters + FAT_START_ENT; | 1355 | sbi->max_cluster = total_clusters + FAT_START_ENT; |
1356 | /* check the free_clusters, it's not necessarily correct */ | 1356 | /* check the free_clusters, it's not necessarily correct */ |
1357 | if (sbi->free_clusters != -1 && sbi->free_clusters > total_clusters) | 1357 | if (sbi->free_clusters != -1 && sbi->free_clusters > total_clusters) |
1358 | sbi->free_clusters = -1; | 1358 | sbi->free_clusters = -1; |
1359 | /* check the prev_free, it's not necessarily correct */ | 1359 | /* check the prev_free, it's not necessarily correct */ |
1360 | sbi->prev_free %= sbi->max_cluster; | 1360 | sbi->prev_free %= sbi->max_cluster; |
1361 | if (sbi->prev_free < FAT_START_ENT) | 1361 | if (sbi->prev_free < FAT_START_ENT) |
1362 | sbi->prev_free = FAT_START_ENT; | 1362 | sbi->prev_free = FAT_START_ENT; |
1363 | 1363 | ||
1364 | brelse(bh); | 1364 | brelse(bh); |
1365 | 1365 | ||
1366 | /* set up enough so that it can read an inode */ | 1366 | /* set up enough so that it can read an inode */ |
1367 | fat_hash_init(sb); | 1367 | fat_hash_init(sb); |
1368 | fat_ent_access_init(sb); | 1368 | fat_ent_access_init(sb); |
1369 | 1369 | ||
1370 | /* | 1370 | /* |
1371 | * The low byte of FAT's first entry must have same value with | 1371 | * The low byte of FAT's first entry must have same value with |
1372 | * media-field. But in real world, too many devices is | 1372 | * media-field. But in real world, too many devices is |
1373 | * writing wrong value. So, removed that validity check. | 1373 | * writing wrong value. So, removed that validity check. |
1374 | * | 1374 | * |
1375 | * if (FAT_FIRST_ENT(sb, media) != first) | 1375 | * if (FAT_FIRST_ENT(sb, media) != first) |
1376 | */ | 1376 | */ |
1377 | 1377 | ||
1378 | error = -EINVAL; | 1378 | error = -EINVAL; |
1379 | sprintf(buf, "cp%d", sbi->options.codepage); | 1379 | sprintf(buf, "cp%d", sbi->options.codepage); |
1380 | sbi->nls_disk = load_nls(buf); | 1380 | sbi->nls_disk = load_nls(buf); |
1381 | if (!sbi->nls_disk) { | 1381 | if (!sbi->nls_disk) { |
1382 | printk(KERN_ERR "FAT: codepage %s not found\n", buf); | 1382 | printk(KERN_ERR "FAT: codepage %s not found\n", buf); |
1383 | goto out_fail; | 1383 | goto out_fail; |
1384 | } | 1384 | } |
1385 | 1385 | ||
1386 | /* FIXME: utf8 is using iocharset for upper/lower conversion */ | 1386 | /* FIXME: utf8 is using iocharset for upper/lower conversion */ |
1387 | if (sbi->options.isvfat) { | 1387 | if (sbi->options.isvfat) { |
1388 | sbi->nls_io = load_nls(sbi->options.iocharset); | 1388 | sbi->nls_io = load_nls(sbi->options.iocharset); |
1389 | if (!sbi->nls_io) { | 1389 | if (!sbi->nls_io) { |
1390 | printk(KERN_ERR "FAT: IO charset %s not found\n", | 1390 | printk(KERN_ERR "FAT: IO charset %s not found\n", |
1391 | sbi->options.iocharset); | 1391 | sbi->options.iocharset); |
1392 | goto out_fail; | 1392 | goto out_fail; |
1393 | } | 1393 | } |
1394 | } | 1394 | } |
1395 | 1395 | ||
1396 | error = -ENOMEM; | 1396 | error = -ENOMEM; |
1397 | root_inode = new_inode(sb); | 1397 | root_inode = new_inode(sb); |
1398 | if (!root_inode) | 1398 | if (!root_inode) |
1399 | goto out_fail; | 1399 | goto out_fail; |
1400 | root_inode->i_ino = MSDOS_ROOT_INO; | 1400 | root_inode->i_ino = MSDOS_ROOT_INO; |
1401 | root_inode->i_version = 1; | 1401 | root_inode->i_version = 1; |
1402 | error = fat_read_root(root_inode); | 1402 | error = fat_read_root(root_inode); |
1403 | if (error < 0) | 1403 | if (error < 0) |
1404 | goto out_fail; | 1404 | goto out_fail; |
1405 | error = -ENOMEM; | 1405 | error = -ENOMEM; |
1406 | insert_inode_hash(root_inode); | 1406 | insert_inode_hash(root_inode); |
1407 | sb->s_root = d_alloc_root(root_inode); | 1407 | sb->s_root = d_alloc_root(root_inode); |
1408 | if (!sb->s_root) { | 1408 | if (!sb->s_root) { |
1409 | printk(KERN_ERR "FAT: get root inode failed\n"); | 1409 | printk(KERN_ERR "FAT: get root inode failed\n"); |
1410 | goto out_fail; | 1410 | goto out_fail; |
1411 | } | 1411 | } |
1412 | 1412 | ||
1413 | return 0; | 1413 | return 0; |
1414 | 1414 | ||
1415 | out_invalid: | 1415 | out_invalid: |
1416 | error = -EINVAL; | 1416 | error = -EINVAL; |
1417 | if (!silent) | 1417 | if (!silent) |
1418 | printk(KERN_INFO "VFS: Can't find a valid FAT filesystem" | 1418 | printk(KERN_INFO "VFS: Can't find a valid FAT filesystem" |
1419 | " on dev %s.\n", sb->s_id); | 1419 | " on dev %s.\n", sb->s_id); |
1420 | 1420 | ||
1421 | out_fail: | 1421 | out_fail: |
1422 | if (root_inode) | 1422 | if (root_inode) |
1423 | iput(root_inode); | 1423 | iput(root_inode); |
1424 | if (sbi->nls_io) | 1424 | if (sbi->nls_io) |
1425 | unload_nls(sbi->nls_io); | 1425 | unload_nls(sbi->nls_io); |
1426 | if (sbi->nls_disk) | 1426 | if (sbi->nls_disk) |
1427 | unload_nls(sbi->nls_disk); | 1427 | unload_nls(sbi->nls_disk); |
1428 | if (sbi->options.iocharset != fat_default_iocharset) | 1428 | if (sbi->options.iocharset != fat_default_iocharset) |
1429 | kfree(sbi->options.iocharset); | 1429 | kfree(sbi->options.iocharset); |
1430 | sb->s_fs_info = NULL; | 1430 | sb->s_fs_info = NULL; |
1431 | kfree(sbi); | 1431 | kfree(sbi); |
1432 | return error; | 1432 | return error; |
1433 | } | 1433 | } |
1434 | 1434 | ||
1435 | EXPORT_SYMBOL_GPL(fat_fill_super); | 1435 | EXPORT_SYMBOL_GPL(fat_fill_super); |
1436 | 1436 | ||
1437 | int __init fat_cache_init(void); | 1437 | int __init fat_cache_init(void); |
1438 | void fat_cache_destroy(void); | 1438 | void fat_cache_destroy(void); |
1439 | 1439 | ||
1440 | static int __init init_fat_fs(void) | 1440 | static int __init init_fat_fs(void) |
1441 | { | 1441 | { |
1442 | int err; | 1442 | int err; |
1443 | 1443 | ||
1444 | err = fat_cache_init(); | 1444 | err = fat_cache_init(); |
1445 | if (err) | 1445 | if (err) |
1446 | return err; | 1446 | return err; |
1447 | 1447 | ||
1448 | err = fat_init_inodecache(); | 1448 | err = fat_init_inodecache(); |
1449 | if (err) | 1449 | if (err) |
1450 | goto failed; | 1450 | goto failed; |
1451 | 1451 | ||
1452 | return 0; | 1452 | return 0; |
1453 | 1453 | ||
1454 | failed: | 1454 | failed: |
1455 | fat_cache_destroy(); | 1455 | fat_cache_destroy(); |
1456 | return err; | 1456 | return err; |
1457 | } | 1457 | } |
1458 | 1458 | ||
1459 | static void __exit exit_fat_fs(void) | 1459 | static void __exit exit_fat_fs(void) |
1460 | { | 1460 | { |
1461 | fat_cache_destroy(); | 1461 | fat_cache_destroy(); |
1462 | fat_destroy_inodecache(); | 1462 | fat_destroy_inodecache(); |
1463 | } | 1463 | } |
1464 | 1464 | ||
1465 | module_init(init_fat_fs) | 1465 | module_init(init_fat_fs) |
1466 | module_exit(exit_fat_fs) | 1466 | module_exit(exit_fat_fs) |
1467 | 1467 | ||
1468 | MODULE_LICENSE("GPL"); | 1468 | MODULE_LICENSE("GPL"); |
1469 | 1469 |
fs/isofs/joliet.c
1 | /* | 1 | /* |
2 | * linux/fs/isofs/joliet.c | 2 | * linux/fs/isofs/joliet.c |
3 | * | 3 | * |
4 | * (C) 1996 Gordon Chaffee | 4 | * (C) 1996 Gordon Chaffee |
5 | * | 5 | * |
6 | * Joliet: Microsoft's Unicode extensions to iso9660 | 6 | * Joliet: Microsoft's Unicode extensions to iso9660 |
7 | */ | 7 | */ |
8 | 8 | ||
9 | #include <linux/types.h> | 9 | #include <linux/types.h> |
10 | #include <linux/nls.h> | 10 | #include <linux/nls.h> |
11 | #include "isofs.h" | 11 | #include "isofs.h" |
12 | 12 | ||
13 | /* | 13 | /* |
14 | * Convert Unicode 16 to UTF8 or ASCII. | 14 | * Convert Unicode 16 to UTF-8 or ASCII. |
15 | */ | 15 | */ |
16 | static int | 16 | static int |
17 | uni16_to_x8(unsigned char *ascii, u16 *uni, int len, struct nls_table *nls) | 17 | uni16_to_x8(unsigned char *ascii, u16 *uni, int len, struct nls_table *nls) |
18 | { | 18 | { |
19 | wchar_t *ip, ch; | 19 | wchar_t *ip, ch; |
20 | unsigned char *op; | 20 | unsigned char *op; |
21 | 21 | ||
22 | ip = uni; | 22 | ip = uni; |
23 | op = ascii; | 23 | op = ascii; |
24 | 24 | ||
25 | while ((ch = get_unaligned(ip)) && len) { | 25 | while ((ch = get_unaligned(ip)) && len) { |
26 | int llen; | 26 | int llen; |
27 | ch = be16_to_cpu(ch); | 27 | ch = be16_to_cpu(ch); |
28 | if ((llen = nls->uni2char(ch, op, NLS_MAX_CHARSET_SIZE)) > 0) | 28 | if ((llen = nls->uni2char(ch, op, NLS_MAX_CHARSET_SIZE)) > 0) |
29 | op += llen; | 29 | op += llen; |
30 | else | 30 | else |
31 | *op++ = '?'; | 31 | *op++ = '?'; |
32 | ip++; | 32 | ip++; |
33 | 33 | ||
34 | len--; | 34 | len--; |
35 | } | 35 | } |
36 | *op = 0; | 36 | *op = 0; |
37 | return (op - ascii); | 37 | return (op - ascii); |
38 | } | 38 | } |
39 | 39 | ||
40 | /* Convert big endian wide character string to utf8 */ | 40 | /* Convert big endian wide character string to utf8 */ |
41 | static int | 41 | static int |
42 | wcsntombs_be(__u8 *s, const __u8 *pwcs, int inlen, int maxlen) | 42 | wcsntombs_be(__u8 *s, const __u8 *pwcs, int inlen, int maxlen) |
43 | { | 43 | { |
44 | const __u8 *ip; | 44 | const __u8 *ip; |
45 | __u8 *op; | 45 | __u8 *op; |
46 | int size; | 46 | int size; |
47 | __u16 c; | 47 | __u16 c; |
48 | 48 | ||
49 | op = s; | 49 | op = s; |
50 | ip = pwcs; | 50 | ip = pwcs; |
51 | while ((*ip || ip[1]) && (maxlen > 0) && (inlen > 0)) { | 51 | while ((*ip || ip[1]) && (maxlen > 0) && (inlen > 0)) { |
52 | c = (*ip << 8) | ip[1]; | 52 | c = (*ip << 8) | ip[1]; |
53 | if (c > 0x7f) { | 53 | if (c > 0x7f) { |
54 | size = utf8_wctomb(op, c, maxlen); | 54 | size = utf8_wctomb(op, c, maxlen); |
55 | if (size == -1) { | 55 | if (size == -1) { |
56 | /* Ignore character and move on */ | 56 | /* Ignore character and move on */ |
57 | maxlen--; | 57 | maxlen--; |
58 | } else { | 58 | } else { |
59 | op += size; | 59 | op += size; |
60 | maxlen -= size; | 60 | maxlen -= size; |
61 | } | 61 | } |
62 | } else { | 62 | } else { |
63 | *op++ = (__u8) c; | 63 | *op++ = (__u8) c; |
64 | } | 64 | } |
65 | ip += 2; | 65 | ip += 2; |
66 | inlen--; | 66 | inlen--; |
67 | } | 67 | } |
68 | return (op - s); | 68 | return (op - s); |
69 | } | 69 | } |
70 | 70 | ||
71 | int | 71 | int |
72 | get_joliet_filename(struct iso_directory_record * de, unsigned char *outname, struct inode * inode) | 72 | get_joliet_filename(struct iso_directory_record * de, unsigned char *outname, struct inode * inode) |
73 | { | 73 | { |
74 | unsigned char utf8; | 74 | unsigned char utf8; |
75 | struct nls_table *nls; | 75 | struct nls_table *nls; |
76 | unsigned char len = 0; | 76 | unsigned char len = 0; |
77 | 77 | ||
78 | utf8 = ISOFS_SB(inode->i_sb)->s_utf8; | 78 | utf8 = ISOFS_SB(inode->i_sb)->s_utf8; |
79 | nls = ISOFS_SB(inode->i_sb)->s_nls_iocharset; | 79 | nls = ISOFS_SB(inode->i_sb)->s_nls_iocharset; |
80 | 80 | ||
81 | if (utf8) { | 81 | if (utf8) { |
82 | len = wcsntombs_be(outname, de->name, | 82 | len = wcsntombs_be(outname, de->name, |
83 | de->name_len[0] >> 1, PAGE_SIZE); | 83 | de->name_len[0] >> 1, PAGE_SIZE); |
84 | } else { | 84 | } else { |
85 | len = uni16_to_x8(outname, (u16 *) de->name, | 85 | len = uni16_to_x8(outname, (u16 *) de->name, |
86 | de->name_len[0] >> 1, nls); | 86 | de->name_len[0] >> 1, nls); |
87 | } | 87 | } |
88 | if ((len > 2) && (outname[len-2] == ';') && (outname[len-1] == '1')) { | 88 | if ((len > 2) && (outname[len-2] == ';') && (outname[len-1] == '1')) { |
89 | len -= 2; | 89 | len -= 2; |
90 | } | 90 | } |
91 | 91 | ||
92 | /* | 92 | /* |
93 | * Windows doesn't like periods at the end of a name, | 93 | * Windows doesn't like periods at the end of a name, |
94 | * so neither do we | 94 | * so neither do we |
95 | */ | 95 | */ |
96 | while (len >= 2 && (outname[len-1] == '.')) { | 96 | while (len >= 2 && (outname[len-1] == '.')) { |
97 | len--; | 97 | len--; |
98 | } | 98 | } |
99 | 99 | ||
100 | return len; | 100 | return len; |
101 | } | 101 | } |
102 | 102 |
fs/nls/Kconfig
1 | # | 1 | # |
2 | # Native language support configuration | 2 | # Native language support configuration |
3 | # | 3 | # |
4 | 4 | ||
5 | menu "Native Language Support" | 5 | menu "Native Language Support" |
6 | 6 | ||
7 | config NLS | 7 | config NLS |
8 | tristate "Base native language support" | 8 | tristate "Base native language support" |
9 | ---help--- | 9 | ---help--- |
10 | The base Native Language Support. A number of filesystems | 10 | The base Native Language Support. A number of filesystems |
11 | depend on it (e.g. FAT, JOLIET, NT, BEOS filesystems), as well | 11 | depend on it (e.g. FAT, JOLIET, NT, BEOS filesystems), as well |
12 | as the ability of some filesystems to use native languages | 12 | as the ability of some filesystems to use native languages |
13 | (NCP, SMB). | 13 | (NCP, SMB). |
14 | 14 | ||
15 | If unsure, say Y. | 15 | If unsure, say Y. |
16 | 16 | ||
17 | To compile this code as a module, choose M here: the module | 17 | To compile this code as a module, choose M here: the module |
18 | will be called nls_base. | 18 | will be called nls_base. |
19 | 19 | ||
20 | config NLS_DEFAULT | 20 | config NLS_DEFAULT |
21 | string "Default NLS Option" | 21 | string "Default NLS Option" |
22 | depends on NLS | 22 | depends on NLS |
23 | default "iso8859-1" | 23 | default "iso8859-1" |
24 | ---help--- | 24 | ---help--- |
25 | The default NLS used when mounting file system. Note, that this is | 25 | The default NLS used when mounting file system. Note, that this is |
26 | the NLS used by your console, not the NLS used by a specific file | 26 | the NLS used by your console, not the NLS used by a specific file |
27 | system (if different) to store data (filenames) on a disk. | 27 | system (if different) to store data (filenames) on a disk. |
28 | Currently, the valid values are: | 28 | Currently, the valid values are: |
29 | big5, cp437, cp737, cp775, cp850, cp852, cp855, cp857, cp860, cp861, | 29 | big5, cp437, cp737, cp775, cp850, cp852, cp855, cp857, cp860, cp861, |
30 | cp862, cp863, cp864, cp865, cp866, cp869, cp874, cp932, cp936, | 30 | cp862, cp863, cp864, cp865, cp866, cp869, cp874, cp932, cp936, |
31 | cp949, cp950, cp1251, cp1255, euc-jp, euc-kr, gb2312, iso8859-1, | 31 | cp949, cp950, cp1251, cp1255, euc-jp, euc-kr, gb2312, iso8859-1, |
32 | iso8859-2, iso8859-3, iso8859-4, iso8859-5, iso8859-6, iso8859-7, | 32 | iso8859-2, iso8859-3, iso8859-4, iso8859-5, iso8859-6, iso8859-7, |
33 | iso8859-8, iso8859-9, iso8859-13, iso8859-14, iso8859-15, | 33 | iso8859-8, iso8859-9, iso8859-13, iso8859-14, iso8859-15, |
34 | koi8-r, koi8-ru, koi8-u, sjis, tis-620, utf8. | 34 | koi8-r, koi8-ru, koi8-u, sjis, tis-620, utf8. |
35 | If you specify a wrong value, it will use the built-in NLS; | 35 | If you specify a wrong value, it will use the built-in NLS; |
36 | compatible with iso8859-1. | 36 | compatible with iso8859-1. |
37 | 37 | ||
38 | If unsure, specify it as "iso8859-1". | 38 | If unsure, specify it as "iso8859-1". |
39 | 39 | ||
40 | config NLS_CODEPAGE_437 | 40 | config NLS_CODEPAGE_437 |
41 | tristate "Codepage 437 (United States, Canada)" | 41 | tristate "Codepage 437 (United States, Canada)" |
42 | depends on NLS | 42 | depends on NLS |
43 | help | 43 | help |
44 | The Microsoft FAT file system family can deal with filenames in | 44 | The Microsoft FAT file system family can deal with filenames in |
45 | native language character sets. These character sets are stored | 45 | native language character sets. These character sets are stored |
46 | in so-called DOS codepages. You need to include the appropriate | 46 | in so-called DOS codepages. You need to include the appropriate |
47 | codepage if you want to be able to read/write these filenames on | 47 | codepage if you want to be able to read/write these filenames on |
48 | DOS/Windows partitions correctly. This does apply to the filenames | 48 | DOS/Windows partitions correctly. This does apply to the filenames |
49 | only, not to the file contents. You can include several codepages; | 49 | only, not to the file contents. You can include several codepages; |
50 | say Y here if you want to include the DOS codepage that is used in | 50 | say Y here if you want to include the DOS codepage that is used in |
51 | the United States and parts of Canada. This is recommended. | 51 | the United States and parts of Canada. This is recommended. |
52 | 52 | ||
53 | config NLS_CODEPAGE_737 | 53 | config NLS_CODEPAGE_737 |
54 | tristate "Codepage 737 (Greek)" | 54 | tristate "Codepage 737 (Greek)" |
55 | depends on NLS | 55 | depends on NLS |
56 | help | 56 | help |
57 | The Microsoft FAT file system family can deal with filenames in | 57 | The Microsoft FAT file system family can deal with filenames in |
58 | native language character sets. These character sets are stored | 58 | native language character sets. These character sets are stored |
59 | in so-called DOS codepages. You need to include the appropriate | 59 | in so-called DOS codepages. You need to include the appropriate |
60 | codepage if you want to be able to read/write these filenames on | 60 | codepage if you want to be able to read/write these filenames on |
61 | DOS/Windows partitions correctly. This does apply to the filenames | 61 | DOS/Windows partitions correctly. This does apply to the filenames |
62 | only, not to the file contents. You can include several codepages; | 62 | only, not to the file contents. You can include several codepages; |
63 | say Y here if you want to include the DOS codepage that is used for | 63 | say Y here if you want to include the DOS codepage that is used for |
64 | Greek. If unsure, say N. | 64 | Greek. If unsure, say N. |
65 | 65 | ||
66 | config NLS_CODEPAGE_775 | 66 | config NLS_CODEPAGE_775 |
67 | tristate "Codepage 775 (Baltic Rim)" | 67 | tristate "Codepage 775 (Baltic Rim)" |
68 | depends on NLS | 68 | depends on NLS |
69 | help | 69 | help |
70 | The Microsoft FAT file system family can deal with filenames in | 70 | The Microsoft FAT file system family can deal with filenames in |
71 | native language character sets. These character sets are stored | 71 | native language character sets. These character sets are stored |
72 | in so-called DOS codepages. You need to include the appropriate | 72 | in so-called DOS codepages. You need to include the appropriate |
73 | codepage if you want to be able to read/write these filenames on | 73 | codepage if you want to be able to read/write these filenames on |
74 | DOS/Windows partitions correctly. This does apply to the filenames | 74 | DOS/Windows partitions correctly. This does apply to the filenames |
75 | only, not to the file contents. You can include several codepages; | 75 | only, not to the file contents. You can include several codepages; |
76 | say Y here if you want to include the DOS codepage that is used | 76 | say Y here if you want to include the DOS codepage that is used |
77 | for the Baltic Rim Languages (Latvian and Lithuanian). If unsure, | 77 | for the Baltic Rim Languages (Latvian and Lithuanian). If unsure, |
78 | say N. | 78 | say N. |
79 | 79 | ||
80 | config NLS_CODEPAGE_850 | 80 | config NLS_CODEPAGE_850 |
81 | tristate "Codepage 850 (Europe)" | 81 | tristate "Codepage 850 (Europe)" |
82 | depends on NLS | 82 | depends on NLS |
83 | ---help--- | 83 | ---help--- |
84 | The Microsoft FAT file system family can deal with filenames in | 84 | The Microsoft FAT file system family can deal with filenames in |
85 | native language character sets. These character sets are stored in | 85 | native language character sets. These character sets are stored in |
86 | so-called DOS codepages. You need to include the appropriate | 86 | so-called DOS codepages. You need to include the appropriate |
87 | codepage if you want to be able to read/write these filenames on | 87 | codepage if you want to be able to read/write these filenames on |
88 | DOS/Windows partitions correctly. This does apply to the filenames | 88 | DOS/Windows partitions correctly. This does apply to the filenames |
89 | only, not to the file contents. You can include several codepages; | 89 | only, not to the file contents. You can include several codepages; |
90 | say Y here if you want to include the DOS codepage that is used for | 90 | say Y here if you want to include the DOS codepage that is used for |
91 | much of Europe -- United Kingdom, Germany, Spain, Italy, and [add | 91 | much of Europe -- United Kingdom, Germany, Spain, Italy, and [add |
92 | more countries here]. It has some characters useful to many European | 92 | more countries here]. It has some characters useful to many European |
93 | languages that are not part of the US codepage 437. | 93 | languages that are not part of the US codepage 437. |
94 | 94 | ||
95 | If unsure, say Y. | 95 | If unsure, say Y. |
96 | 96 | ||
97 | config NLS_CODEPAGE_852 | 97 | config NLS_CODEPAGE_852 |
98 | tristate "Codepage 852 (Central/Eastern Europe)" | 98 | tristate "Codepage 852 (Central/Eastern Europe)" |
99 | depends on NLS | 99 | depends on NLS |
100 | ---help--- | 100 | ---help--- |
101 | The Microsoft FAT file system family can deal with filenames in | 101 | The Microsoft FAT file system family can deal with filenames in |
102 | native language character sets. These character sets are stored in | 102 | native language character sets. These character sets are stored in |
103 | so-called DOS codepages. You need to include the appropriate | 103 | so-called DOS codepages. You need to include the appropriate |
104 | codepage if you want to be able to read/write these filenames on | 104 | codepage if you want to be able to read/write these filenames on |
105 | DOS/Windows partitions correctly. This does apply to the filenames | 105 | DOS/Windows partitions correctly. This does apply to the filenames |
106 | only, not to the file contents. You can include several codepages; | 106 | only, not to the file contents. You can include several codepages; |
107 | say Y here if you want to include the Latin 2 codepage used by DOS | 107 | say Y here if you want to include the Latin 2 codepage used by DOS |
108 | for much of Central and Eastern Europe. It has all the required | 108 | for much of Central and Eastern Europe. It has all the required |
109 | characters for these languages: Albanian, Croatian, Czech, English, | 109 | characters for these languages: Albanian, Croatian, Czech, English, |
110 | Finnish, Hungarian, Irish, German, Polish, Romanian, Serbian (Latin | 110 | Finnish, Hungarian, Irish, German, Polish, Romanian, Serbian (Latin |
111 | transcription), Slovak, Slovenian, and Sorbian. | 111 | transcription), Slovak, Slovenian, and Sorbian. |
112 | 112 | ||
113 | config NLS_CODEPAGE_855 | 113 | config NLS_CODEPAGE_855 |
114 | tristate "Codepage 855 (Cyrillic)" | 114 | tristate "Codepage 855 (Cyrillic)" |
115 | depends on NLS | 115 | depends on NLS |
116 | help | 116 | help |
117 | The Microsoft FAT file system family can deal with filenames in | 117 | The Microsoft FAT file system family can deal with filenames in |
118 | native language character sets. These character sets are stored in | 118 | native language character sets. These character sets are stored in |
119 | so-called DOS codepages. You need to include the appropriate | 119 | so-called DOS codepages. You need to include the appropriate |
120 | codepage if you want to be able to read/write these filenames on | 120 | codepage if you want to be able to read/write these filenames on |
121 | DOS/Windows partitions correctly. This does apply to the filenames | 121 | DOS/Windows partitions correctly. This does apply to the filenames |
122 | only, not to the file contents. You can include several codepages; | 122 | only, not to the file contents. You can include several codepages; |
123 | say Y here if you want to include the DOS codepage for Cyrillic. | 123 | say Y here if you want to include the DOS codepage for Cyrillic. |
124 | 124 | ||
125 | config NLS_CODEPAGE_857 | 125 | config NLS_CODEPAGE_857 |
126 | tristate "Codepage 857 (Turkish)" | 126 | tristate "Codepage 857 (Turkish)" |
127 | depends on NLS | 127 | depends on NLS |
128 | help | 128 | help |
129 | The Microsoft FAT file system family can deal with filenames in | 129 | The Microsoft FAT file system family can deal with filenames in |
130 | native language character sets. These character sets are stored in | 130 | native language character sets. These character sets are stored in |
131 | so-called DOS codepages. You need to include the appropriate | 131 | so-called DOS codepages. You need to include the appropriate |
132 | codepage if you want to be able to read/write these filenames on | 132 | codepage if you want to be able to read/write these filenames on |
133 | DOS/Windows partitions correctly. This does apply to the filenames | 133 | DOS/Windows partitions correctly. This does apply to the filenames |
134 | only, not to the file contents. You can include several codepages; | 134 | only, not to the file contents. You can include several codepages; |
135 | say Y here if you want to include the DOS codepage for Turkish. | 135 | say Y here if you want to include the DOS codepage for Turkish. |
136 | 136 | ||
137 | config NLS_CODEPAGE_860 | 137 | config NLS_CODEPAGE_860 |
138 | tristate "Codepage 860 (Portuguese)" | 138 | tristate "Codepage 860 (Portuguese)" |
139 | depends on NLS | 139 | depends on NLS |
140 | help | 140 | help |
141 | The Microsoft FAT file system family can deal with filenames in | 141 | The Microsoft FAT file system family can deal with filenames in |
142 | native language character sets. These character sets are stored in | 142 | native language character sets. These character sets are stored in |
143 | so-called DOS codepages. You need to include the appropriate | 143 | so-called DOS codepages. You need to include the appropriate |
144 | codepage if you want to be able to read/write these filenames on | 144 | codepage if you want to be able to read/write these filenames on |
145 | DOS/Windows partitions correctly. This does apply to the filenames | 145 | DOS/Windows partitions correctly. This does apply to the filenames |
146 | only, not to the file contents. You can include several codepages; | 146 | only, not to the file contents. You can include several codepages; |
147 | say Y here if you want to include the DOS codepage for Portuguese. | 147 | say Y here if you want to include the DOS codepage for Portuguese. |
148 | 148 | ||
149 | config NLS_CODEPAGE_861 | 149 | config NLS_CODEPAGE_861 |
150 | tristate "Codepage 861 (Icelandic)" | 150 | tristate "Codepage 861 (Icelandic)" |
151 | depends on NLS | 151 | depends on NLS |
152 | help | 152 | help |
153 | The Microsoft FAT file system family can deal with filenames in | 153 | The Microsoft FAT file system family can deal with filenames in |
154 | native language character sets. These character sets are stored in | 154 | native language character sets. These character sets are stored in |
155 | so-called DOS codepages. You need to include the appropriate | 155 | so-called DOS codepages. You need to include the appropriate |
156 | codepage if you want to be able to read/write these filenames on | 156 | codepage if you want to be able to read/write these filenames on |
157 | DOS/Windows partitions correctly. This does apply to the filenames | 157 | DOS/Windows partitions correctly. This does apply to the filenames |
158 | only, not to the file contents. You can include several codepages; | 158 | only, not to the file contents. You can include several codepages; |
159 | say Y here if you want to include the DOS codepage for Icelandic. | 159 | say Y here if you want to include the DOS codepage for Icelandic. |
160 | 160 | ||
161 | config NLS_CODEPAGE_862 | 161 | config NLS_CODEPAGE_862 |
162 | tristate "Codepage 862 (Hebrew)" | 162 | tristate "Codepage 862 (Hebrew)" |
163 | depends on NLS | 163 | depends on NLS |
164 | help | 164 | help |
165 | The Microsoft FAT file system family can deal with filenames in | 165 | The Microsoft FAT file system family can deal with filenames in |
166 | native language character sets. These character sets are stored in | 166 | native language character sets. These character sets are stored in |
167 | so-called DOS codepages. You need to include the appropriate | 167 | so-called DOS codepages. You need to include the appropriate |
168 | codepage if you want to be able to read/write these filenames on | 168 | codepage if you want to be able to read/write these filenames on |
169 | DOS/Windows partitions correctly. This does apply to the filenames | 169 | DOS/Windows partitions correctly. This does apply to the filenames |
170 | only, not to the file contents. You can include several codepages; | 170 | only, not to the file contents. You can include several codepages; |
171 | say Y here if you want to include the DOS codepage for Hebrew. | 171 | say Y here if you want to include the DOS codepage for Hebrew. |
172 | 172 | ||
173 | config NLS_CODEPAGE_863 | 173 | config NLS_CODEPAGE_863 |
174 | tristate "Codepage 863 (Canadian French)" | 174 | tristate "Codepage 863 (Canadian French)" |
175 | depends on NLS | 175 | depends on NLS |
176 | help | 176 | help |
177 | The Microsoft FAT file system family can deal with filenames in | 177 | The Microsoft FAT file system family can deal with filenames in |
178 | native language character sets. These character sets are stored in | 178 | native language character sets. These character sets are stored in |
179 | so-called DOS codepages. You need to include the appropriate | 179 | so-called DOS codepages. You need to include the appropriate |
180 | codepage if you want to be able to read/write these filenames on | 180 | codepage if you want to be able to read/write these filenames on |
181 | DOS/Windows partitions correctly. This does apply to the filenames | 181 | DOS/Windows partitions correctly. This does apply to the filenames |
182 | only, not to the file contents. You can include several codepages; | 182 | only, not to the file contents. You can include several codepages; |
183 | say Y here if you want to include the DOS codepage for Canadian | 183 | say Y here if you want to include the DOS codepage for Canadian |
184 | French. | 184 | French. |
185 | 185 | ||
186 | config NLS_CODEPAGE_864 | 186 | config NLS_CODEPAGE_864 |
187 | tristate "Codepage 864 (Arabic)" | 187 | tristate "Codepage 864 (Arabic)" |
188 | depends on NLS | 188 | depends on NLS |
189 | help | 189 | help |
190 | The Microsoft FAT file system family can deal with filenames in | 190 | The Microsoft FAT file system family can deal with filenames in |
191 | native language character sets. These character sets are stored in | 191 | native language character sets. These character sets are stored in |
192 | so-called DOS codepages. You need to include the appropriate | 192 | so-called DOS codepages. You need to include the appropriate |
193 | codepage if you want to be able to read/write these filenames on | 193 | codepage if you want to be able to read/write these filenames on |
194 | DOS/Windows partitions correctly. This does apply to the filenames | 194 | DOS/Windows partitions correctly. This does apply to the filenames |
195 | only, not to the file contents. You can include several codepages; | 195 | only, not to the file contents. You can include several codepages; |
196 | say Y here if you want to include the DOS codepage for Arabic. | 196 | say Y here if you want to include the DOS codepage for Arabic. |
197 | 197 | ||
198 | config NLS_CODEPAGE_865 | 198 | config NLS_CODEPAGE_865 |
199 | tristate "Codepage 865 (Norwegian, Danish)" | 199 | tristate "Codepage 865 (Norwegian, Danish)" |
200 | depends on NLS | 200 | depends on NLS |
201 | help | 201 | help |
202 | The Microsoft FAT file system family can deal with filenames in | 202 | The Microsoft FAT file system family can deal with filenames in |
203 | native language character sets. These character sets are stored in | 203 | native language character sets. These character sets are stored in |
204 | so-called DOS codepages. You need to include the appropriate | 204 | so-called DOS codepages. You need to include the appropriate |
205 | codepage if you want to be able to read/write these filenames on | 205 | codepage if you want to be able to read/write these filenames on |
206 | DOS/Windows partitions correctly. This does apply to the filenames | 206 | DOS/Windows partitions correctly. This does apply to the filenames |
207 | only, not to the file contents. You can include several codepages; | 207 | only, not to the file contents. You can include several codepages; |
208 | say Y here if you want to include the DOS codepage for the Nordic | 208 | say Y here if you want to include the DOS codepage for the Nordic |
209 | European countries. | 209 | European countries. |
210 | 210 | ||
211 | config NLS_CODEPAGE_866 | 211 | config NLS_CODEPAGE_866 |
212 | tristate "Codepage 866 (Cyrillic/Russian)" | 212 | tristate "Codepage 866 (Cyrillic/Russian)" |
213 | depends on NLS | 213 | depends on NLS |
214 | help | 214 | help |
215 | The Microsoft FAT file system family can deal with filenames in | 215 | The Microsoft FAT file system family can deal with filenames in |
216 | native language character sets. These character sets are stored in | 216 | native language character sets. These character sets are stored in |
217 | so-called DOS codepages. You need to include the appropriate | 217 | so-called DOS codepages. You need to include the appropriate |
218 | codepage if you want to be able to read/write these filenames on | 218 | codepage if you want to be able to read/write these filenames on |
219 | DOS/Windows partitions correctly. This does apply to the filenames | 219 | DOS/Windows partitions correctly. This does apply to the filenames |
220 | only, not to the file contents. You can include several codepages; | 220 | only, not to the file contents. You can include several codepages; |
221 | say Y here if you want to include the DOS codepage for | 221 | say Y here if you want to include the DOS codepage for |
222 | Cyrillic/Russian. | 222 | Cyrillic/Russian. |
223 | 223 | ||
224 | config NLS_CODEPAGE_869 | 224 | config NLS_CODEPAGE_869 |
225 | tristate "Codepage 869 (Greek)" | 225 | tristate "Codepage 869 (Greek)" |
226 | depends on NLS | 226 | depends on NLS |
227 | help | 227 | help |
228 | The Microsoft FAT file system family can deal with filenames in | 228 | The Microsoft FAT file system family can deal with filenames in |
229 | native language character sets. These character sets are stored in | 229 | native language character sets. These character sets are stored in |
230 | so-called DOS codepages. You need to include the appropriate | 230 | so-called DOS codepages. You need to include the appropriate |
231 | codepage if you want to be able to read/write these filenames on | 231 | codepage if you want to be able to read/write these filenames on |
232 | DOS/Windows partitions correctly. This does apply to the filenames | 232 | DOS/Windows partitions correctly. This does apply to the filenames |
233 | only, not to the file contents. You can include several codepages; | 233 | only, not to the file contents. You can include several codepages; |
234 | say Y here if you want to include the DOS codepage for Greek. | 234 | say Y here if you want to include the DOS codepage for Greek. |
235 | 235 | ||
236 | config NLS_CODEPAGE_936 | 236 | config NLS_CODEPAGE_936 |
237 | tristate "Simplified Chinese charset (CP936, GB2312)" | 237 | tristate "Simplified Chinese charset (CP936, GB2312)" |
238 | depends on NLS | 238 | depends on NLS |
239 | help | 239 | help |
240 | The Microsoft FAT file system family can deal with filenames in | 240 | The Microsoft FAT file system family can deal with filenames in |
241 | native language character sets. These character sets are stored in | 241 | native language character sets. These character sets are stored in |
242 | so-called DOS codepages. You need to include the appropriate | 242 | so-called DOS codepages. You need to include the appropriate |
243 | codepage if you want to be able to read/write these filenames on | 243 | codepage if you want to be able to read/write these filenames on |
244 | DOS/Windows partitions correctly. This does apply to the filenames | 244 | DOS/Windows partitions correctly. This does apply to the filenames |
245 | only, not to the file contents. You can include several codepages; | 245 | only, not to the file contents. You can include several codepages; |
246 | say Y here if you want to include the DOS codepage for Simplified | 246 | say Y here if you want to include the DOS codepage for Simplified |
247 | Chinese(GBK). | 247 | Chinese(GBK). |
248 | 248 | ||
249 | config NLS_CODEPAGE_950 | 249 | config NLS_CODEPAGE_950 |
250 | tristate "Traditional Chinese charset (Big5)" | 250 | tristate "Traditional Chinese charset (Big5)" |
251 | depends on NLS | 251 | depends on NLS |
252 | help | 252 | help |
253 | The Microsoft FAT file system family can deal with filenames in | 253 | The Microsoft FAT file system family can deal with filenames in |
254 | native language character sets. These character sets are stored in | 254 | native language character sets. These character sets are stored in |
255 | so-called DOS codepages. You need to include the appropriate | 255 | so-called DOS codepages. You need to include the appropriate |
256 | codepage if you want to be able to read/write these filenames on | 256 | codepage if you want to be able to read/write these filenames on |
257 | DOS/Windows partitions correctly. This does apply to the filenames | 257 | DOS/Windows partitions correctly. This does apply to the filenames |
258 | only, not to the file contents. You can include several codepages; | 258 | only, not to the file contents. You can include several codepages; |
259 | say Y here if you want to include the DOS codepage for Traditional | 259 | say Y here if you want to include the DOS codepage for Traditional |
260 | Chinese(Big5). | 260 | Chinese(Big5). |
261 | 261 | ||
262 | config NLS_CODEPAGE_932 | 262 | config NLS_CODEPAGE_932 |
263 | tristate "Japanese charsets (Shift-JIS, EUC-JP)" | 263 | tristate "Japanese charsets (Shift-JIS, EUC-JP)" |
264 | depends on NLS | 264 | depends on NLS |
265 | help | 265 | help |
266 | The Microsoft FAT file system family can deal with filenames in | 266 | The Microsoft FAT file system family can deal with filenames in |
267 | native language character sets. These character sets are stored in | 267 | native language character sets. These character sets are stored in |
268 | so-called DOS codepages. You need to include the appropriate | 268 | so-called DOS codepages. You need to include the appropriate |
269 | codepage if you want to be able to read/write these filenames on | 269 | codepage if you want to be able to read/write these filenames on |
270 | DOS/Windows partitions correctly. This does apply to the filenames | 270 | DOS/Windows partitions correctly. This does apply to the filenames |
271 | only, not to the file contents. You can include several codepages; | 271 | only, not to the file contents. You can include several codepages; |
272 | say Y here if you want to include the DOS codepage for Shift-JIS | 272 | say Y here if you want to include the DOS codepage for Shift-JIS |
273 | or EUC-JP. To use EUC-JP, you can use 'euc-jp' as mount option or | 273 | or EUC-JP. To use EUC-JP, you can use 'euc-jp' as mount option or |
274 | NLS Default value during kernel configuration, instead of 'cp932'. | 274 | NLS Default value during kernel configuration, instead of 'cp932'. |
275 | 275 | ||
276 | config NLS_CODEPAGE_949 | 276 | config NLS_CODEPAGE_949 |
277 | tristate "Korean charset (CP949, EUC-KR)" | 277 | tristate "Korean charset (CP949, EUC-KR)" |
278 | depends on NLS | 278 | depends on NLS |
279 | help | 279 | help |
280 | The Microsoft FAT file system family can deal with filenames in | 280 | The Microsoft FAT file system family can deal with filenames in |
281 | native language character sets. These character sets are stored in | 281 | native language character sets. These character sets are stored in |
282 | so-called DOS codepages. You need to include the appropriate | 282 | so-called DOS codepages. You need to include the appropriate |
283 | codepage if you want to be able to read/write these filenames on | 283 | codepage if you want to be able to read/write these filenames on |
284 | DOS/Windows partitions correctly. This does apply to the filenames | 284 | DOS/Windows partitions correctly. This does apply to the filenames |
285 | only, not to the file contents. You can include several codepages; | 285 | only, not to the file contents. You can include several codepages; |
286 | say Y here if you want to include the DOS codepage for UHC. | 286 | say Y here if you want to include the DOS codepage for UHC. |
287 | 287 | ||
288 | config NLS_CODEPAGE_874 | 288 | config NLS_CODEPAGE_874 |
289 | tristate "Thai charset (CP874, TIS-620)" | 289 | tristate "Thai charset (CP874, TIS-620)" |
290 | depends on NLS | 290 | depends on NLS |
291 | help | 291 | help |
292 | The Microsoft FAT file system family can deal with filenames in | 292 | The Microsoft FAT file system family can deal with filenames in |
293 | native language character sets. These character sets are stored in | 293 | native language character sets. These character sets are stored in |
294 | so-called DOS codepages. You need to include the appropriate | 294 | so-called DOS codepages. You need to include the appropriate |
295 | codepage if you want to be able to read/write these filenames on | 295 | codepage if you want to be able to read/write these filenames on |
296 | DOS/Windows partitions correctly. This does apply to the filenames | 296 | DOS/Windows partitions correctly. This does apply to the filenames |
297 | only, not to the file contents. You can include several codepages; | 297 | only, not to the file contents. You can include several codepages; |
298 | say Y here if you want to include the DOS codepage for Thai. | 298 | say Y here if you want to include the DOS codepage for Thai. |
299 | 299 | ||
300 | config NLS_ISO8859_8 | 300 | config NLS_ISO8859_8 |
301 | tristate "Hebrew charsets (ISO-8859-8, CP1255)" | 301 | tristate "Hebrew charsets (ISO-8859-8, CP1255)" |
302 | depends on NLS | 302 | depends on NLS |
303 | help | 303 | help |
304 | If you want to display filenames with native language characters | 304 | If you want to display filenames with native language characters |
305 | from the Microsoft FAT file system family or from JOLIET CD-ROMs | 305 | from the Microsoft FAT file system family or from JOLIET CD-ROMs |
306 | correctly on the screen, you need to include the appropriate | 306 | correctly on the screen, you need to include the appropriate |
307 | input/output character sets. Say Y here for ISO8859-8, the Hebrew | 307 | input/output character sets. Say Y here for ISO8859-8, the Hebrew |
308 | character set. | 308 | character set. |
309 | 309 | ||
310 | config NLS_CODEPAGE_1250 | 310 | config NLS_CODEPAGE_1250 |
311 | tristate "Windows CP1250 (Slavic/Central European Languages)" | 311 | tristate "Windows CP1250 (Slavic/Central European Languages)" |
312 | depends on NLS | 312 | depends on NLS |
313 | help | 313 | help |
314 | If you want to display filenames with native language characters | 314 | If you want to display filenames with native language characters |
315 | from the Microsoft FAT file system family or from JOLIET CDROMs | 315 | from the Microsoft FAT file system family or from JOLIET CDROMs |
316 | correctly on the screen, you need to include the appropriate | 316 | correctly on the screen, you need to include the appropriate |
317 | input/output character sets. Say Y here for the Windows CP-1250 | 317 | input/output character sets. Say Y here for the Windows CP-1250 |
318 | character set, which works for most Latin-written Slavic and Central | 318 | character set, which works for most Latin-written Slavic and Central |
319 | European languages: Czech, German, Hungarian, Polish, Rumanian, Croatian, | 319 | European languages: Czech, German, Hungarian, Polish, Rumanian, Croatian, |
320 | Slovak, Slovene. | 320 | Slovak, Slovene. |
321 | 321 | ||
322 | config NLS_CODEPAGE_1251 | 322 | config NLS_CODEPAGE_1251 |
323 | tristate "Windows CP1251 (Bulgarian, Belarusian)" | 323 | tristate "Windows CP1251 (Bulgarian, Belarusian)" |
324 | depends on NLS | 324 | depends on NLS |
325 | help | 325 | help |
326 | The Microsoft FAT file system family can deal with filenames in | 326 | The Microsoft FAT file system family can deal with filenames in |
327 | native language character sets. These character sets are stored in | 327 | native language character sets. These character sets are stored in |
328 | so-called DOS codepages. You need to include the appropriate | 328 | so-called DOS codepages. You need to include the appropriate |
329 | codepage if you want to be able to read/write these filenames on | 329 | codepage if you want to be able to read/write these filenames on |
330 | DOS/Windows partitions correctly. This does apply to the filenames | 330 | DOS/Windows partitions correctly. This does apply to the filenames |
331 | only, not to the file contents. You can include several codepages; | 331 | only, not to the file contents. You can include several codepages; |
332 | say Y here if you want to include the DOS codepage for Russian and | 332 | say Y here if you want to include the DOS codepage for Russian and |
333 | Bulgarian and Belarusian. | 333 | Bulgarian and Belarusian. |
334 | 334 | ||
335 | config NLS_ASCII | 335 | config NLS_ASCII |
336 | tristate "ASCII (United States)" | 336 | tristate "ASCII (United States)" |
337 | depends on NLS | 337 | depends on NLS |
338 | help | 338 | help |
339 | An ASCII NLS module is needed if you want to override the | 339 | An ASCII NLS module is needed if you want to override the |
340 | DEFAULT NLS with this very basic charset and don't want any | 340 | DEFAULT NLS with this very basic charset and don't want any |
341 | non-ASCII characters to be translated. | 341 | non-ASCII characters to be translated. |
342 | 342 | ||
343 | config NLS_ISO8859_1 | 343 | config NLS_ISO8859_1 |
344 | tristate "NLS ISO 8859-1 (Latin 1; Western European Languages)" | 344 | tristate "NLS ISO 8859-1 (Latin 1; Western European Languages)" |
345 | depends on NLS | 345 | depends on NLS |
346 | help | 346 | help |
347 | If you want to display filenames with native language characters | 347 | If you want to display filenames with native language characters |
348 | from the Microsoft FAT file system family or from JOLIET CD-ROMs | 348 | from the Microsoft FAT file system family or from JOLIET CD-ROMs |
349 | correctly on the screen, you need to include the appropriate | 349 | correctly on the screen, you need to include the appropriate |
350 | input/output character sets. Say Y here for the Latin 1 character | 350 | input/output character sets. Say Y here for the Latin 1 character |
351 | set, which covers most West European languages such as Albanian, | 351 | set, which covers most West European languages such as Albanian, |
352 | Catalan, Danish, Dutch, English, Faeroese, Finnish, French, German, | 352 | Catalan, Danish, Dutch, English, Faeroese, Finnish, French, German, |
353 | Galician, Irish, Icelandic, Italian, Norwegian, Portuguese, Spanish, | 353 | Galician, Irish, Icelandic, Italian, Norwegian, Portuguese, Spanish, |
354 | and Swedish. It is also the default for the US. If unsure, say Y. | 354 | and Swedish. It is also the default for the US. If unsure, say Y. |
355 | 355 | ||
356 | config NLS_ISO8859_2 | 356 | config NLS_ISO8859_2 |
357 | tristate "NLS ISO 8859-2 (Latin 2; Slavic/Central European Languages)" | 357 | tristate "NLS ISO 8859-2 (Latin 2; Slavic/Central European Languages)" |
358 | depends on NLS | 358 | depends on NLS |
359 | help | 359 | help |
360 | If you want to display filenames with native language characters | 360 | If you want to display filenames with native language characters |
361 | from the Microsoft FAT file system family or from JOLIET CD-ROMs | 361 | from the Microsoft FAT file system family or from JOLIET CD-ROMs |
362 | correctly on the screen, you need to include the appropriate | 362 | correctly on the screen, you need to include the appropriate |
363 | input/output character sets. Say Y here for the Latin 2 character | 363 | input/output character sets. Say Y here for the Latin 2 character |
364 | set, which works for most Latin-written Slavic and Central European | 364 | set, which works for most Latin-written Slavic and Central European |
365 | languages: Czech, German, Hungarian, Polish, Rumanian, Croatian, | 365 | languages: Czech, German, Hungarian, Polish, Rumanian, Croatian, |
366 | Slovak, Slovene. | 366 | Slovak, Slovene. |
367 | 367 | ||
368 | config NLS_ISO8859_3 | 368 | config NLS_ISO8859_3 |
369 | tristate "NLS ISO 8859-3 (Latin 3; Esperanto, Galician, Maltese, Turkish)" | 369 | tristate "NLS ISO 8859-3 (Latin 3; Esperanto, Galician, Maltese, Turkish)" |
370 | depends on NLS | 370 | depends on NLS |
371 | help | 371 | help |
372 | If you want to display filenames with native language characters | 372 | If you want to display filenames with native language characters |
373 | from the Microsoft FAT file system family or from JOLIET CD-ROMs | 373 | from the Microsoft FAT file system family or from JOLIET CD-ROMs |
374 | correctly on the screen, you need to include the appropriate | 374 | correctly on the screen, you need to include the appropriate |
375 | input/output character sets. Say Y here for the Latin 3 character | 375 | input/output character sets. Say Y here for the Latin 3 character |
376 | set, which is popular with authors of Esperanto, Galician, Maltese, | 376 | set, which is popular with authors of Esperanto, Galician, Maltese, |
377 | and Turkish. | 377 | and Turkish. |
378 | 378 | ||
379 | config NLS_ISO8859_4 | 379 | config NLS_ISO8859_4 |
380 | tristate "NLS ISO 8859-4 (Latin 4; old Baltic charset)" | 380 | tristate "NLS ISO 8859-4 (Latin 4; old Baltic charset)" |
381 | depends on NLS | 381 | depends on NLS |
382 | help | 382 | help |
383 | If you want to display filenames with native language characters | 383 | If you want to display filenames with native language characters |
384 | from the Microsoft FAT file system family or from JOLIET CD-ROMs | 384 | from the Microsoft FAT file system family or from JOLIET CD-ROMs |
385 | correctly on the screen, you need to include the appropriate | 385 | correctly on the screen, you need to include the appropriate |
386 | input/output character sets. Say Y here for the Latin 4 character | 386 | input/output character sets. Say Y here for the Latin 4 character |
387 | set which introduces letters for Estonian, Latvian, and | 387 | set which introduces letters for Estonian, Latvian, and |
388 | Lithuanian. It is an incomplete predecessor of Latin 7. | 388 | Lithuanian. It is an incomplete predecessor of Latin 7. |
389 | 389 | ||
390 | config NLS_ISO8859_5 | 390 | config NLS_ISO8859_5 |
391 | tristate "NLS ISO 8859-5 (Cyrillic)" | 391 | tristate "NLS ISO 8859-5 (Cyrillic)" |
392 | depends on NLS | 392 | depends on NLS |
393 | help | 393 | help |
394 | If you want to display filenames with native language characters | 394 | If you want to display filenames with native language characters |
395 | from the Microsoft FAT file system family or from JOLIET CD-ROMs | 395 | from the Microsoft FAT file system family or from JOLIET CD-ROMs |
396 | correctly on the screen, you need to include the appropriate | 396 | correctly on the screen, you need to include the appropriate |
397 | input/output character sets. Say Y here for ISO8859-5, a Cyrillic | 397 | input/output character sets. Say Y here for ISO8859-5, a Cyrillic |
398 | character set with which you can type Bulgarian, Belarusian, | 398 | character set with which you can type Bulgarian, Belarusian, |
399 | Macedonian, Russian, Serbian, and Ukrainian. Note that the charset | 399 | Macedonian, Russian, Serbian, and Ukrainian. Note that the charset |
400 | KOI8-R is preferred in Russia. | 400 | KOI8-R is preferred in Russia. |
401 | 401 | ||
402 | config NLS_ISO8859_6 | 402 | config NLS_ISO8859_6 |
403 | tristate "NLS ISO 8859-6 (Arabic)" | 403 | tristate "NLS ISO 8859-6 (Arabic)" |
404 | depends on NLS | 404 | depends on NLS |
405 | help | 405 | help |
406 | If you want to display filenames with native language characters | 406 | If you want to display filenames with native language characters |
407 | from the Microsoft FAT file system family or from JOLIET CD-ROMs | 407 | from the Microsoft FAT file system family or from JOLIET CD-ROMs |
408 | correctly on the screen, you need to include the appropriate | 408 | correctly on the screen, you need to include the appropriate |
409 | input/output character sets. Say Y here for ISO8859-6, the Arabic | 409 | input/output character sets. Say Y here for ISO8859-6, the Arabic |
410 | character set. | 410 | character set. |
411 | 411 | ||
412 | config NLS_ISO8859_7 | 412 | config NLS_ISO8859_7 |
413 | tristate "NLS ISO 8859-7 (Modern Greek)" | 413 | tristate "NLS ISO 8859-7 (Modern Greek)" |
414 | depends on NLS | 414 | depends on NLS |
415 | help | 415 | help |
416 | If you want to display filenames with native language characters | 416 | If you want to display filenames with native language characters |
417 | from the Microsoft FAT file system family or from JOLIET CD-ROMs | 417 | from the Microsoft FAT file system family or from JOLIET CD-ROMs |
418 | correctly on the screen, you need to include the appropriate | 418 | correctly on the screen, you need to include the appropriate |
419 | input/output character sets. Say Y here for ISO8859-7, the Modern | 419 | input/output character sets. Say Y here for ISO8859-7, the Modern |
420 | Greek character set. | 420 | Greek character set. |
421 | 421 | ||
422 | config NLS_ISO8859_9 | 422 | config NLS_ISO8859_9 |
423 | tristate "NLS ISO 8859-9 (Latin 5; Turkish)" | 423 | tristate "NLS ISO 8859-9 (Latin 5; Turkish)" |
424 | depends on NLS | 424 | depends on NLS |
425 | help | 425 | help |
426 | If you want to display filenames with native language characters | 426 | If you want to display filenames with native language characters |
427 | from the Microsoft FAT file system family or from JOLIET CD-ROMs | 427 | from the Microsoft FAT file system family or from JOLIET CD-ROMs |
428 | correctly on the screen, you need to include the appropriate | 428 | correctly on the screen, you need to include the appropriate |
429 | input/output character sets. Say Y here for the Latin 5 character | 429 | input/output character sets. Say Y here for the Latin 5 character |
430 | set, and it replaces the rarely needed Icelandic letters in Latin 1 | 430 | set, and it replaces the rarely needed Icelandic letters in Latin 1 |
431 | with the Turkish ones. Useful in Turkey. | 431 | with the Turkish ones. Useful in Turkey. |
432 | 432 | ||
433 | config NLS_ISO8859_13 | 433 | config NLS_ISO8859_13 |
434 | tristate "NLS ISO 8859-13 (Latin 7; Baltic)" | 434 | tristate "NLS ISO 8859-13 (Latin 7; Baltic)" |
435 | depends on NLS | 435 | depends on NLS |
436 | help | 436 | help |
437 | If you want to display filenames with native language characters | 437 | If you want to display filenames with native language characters |
438 | from the Microsoft FAT file system family or from JOLIET CD-ROMs | 438 | from the Microsoft FAT file system family or from JOLIET CD-ROMs |
439 | correctly on the screen, you need to include the appropriate | 439 | correctly on the screen, you need to include the appropriate |
440 | input/output character sets. Say Y here for the Latin 7 character | 440 | input/output character sets. Say Y here for the Latin 7 character |
441 | set, which supports modern Baltic languages including Latvian | 441 | set, which supports modern Baltic languages including Latvian |
442 | and Lithuanian. | 442 | and Lithuanian. |
443 | 443 | ||
444 | config NLS_ISO8859_14 | 444 | config NLS_ISO8859_14 |
445 | tristate "NLS ISO 8859-14 (Latin 8; Celtic)" | 445 | tristate "NLS ISO 8859-14 (Latin 8; Celtic)" |
446 | depends on NLS | 446 | depends on NLS |
447 | help | 447 | help |
448 | If you want to display filenames with native language characters | 448 | If you want to display filenames with native language characters |
449 | from the Microsoft FAT file system family or from JOLIET CD-ROMs | 449 | from the Microsoft FAT file system family or from JOLIET CD-ROMs |
450 | correctly on the screen, you need to include the appropriate | 450 | correctly on the screen, you need to include the appropriate |
451 | input/output character sets. Say Y here for the Latin 8 character | 451 | input/output character sets. Say Y here for the Latin 8 character |
452 | set, which adds the last accented vowels for Welsh (aka Cymraeg) | 452 | set, which adds the last accented vowels for Welsh (aka Cymraeg) |
453 | (and Manx Gaelic) that were missing in Latin 1. | 453 | (and Manx Gaelic) that were missing in Latin 1. |
454 | <http://linux.speech.cymru.org/> has further information. | 454 | <http://linux.speech.cymru.org/> has further information. |
455 | 455 | ||
456 | config NLS_ISO8859_15 | 456 | config NLS_ISO8859_15 |
457 | tristate "NLS ISO 8859-15 (Latin 9; Western European Languages with Euro)" | 457 | tristate "NLS ISO 8859-15 (Latin 9; Western European Languages with Euro)" |
458 | depends on NLS | 458 | depends on NLS |
459 | ---help--- | 459 | ---help--- |
460 | If you want to display filenames with native language characters | 460 | If you want to display filenames with native language characters |
461 | from the Microsoft FAT file system family or from JOLIET CD-ROMs | 461 | from the Microsoft FAT file system family or from JOLIET CD-ROMs |
462 | correctly on the screen, you need to include the appropriate | 462 | correctly on the screen, you need to include the appropriate |
463 | input/output character sets. Say Y here for the Latin 9 character | 463 | input/output character sets. Say Y here for the Latin 9 character |
464 | set, which covers most West European languages such as Albanian, | 464 | set, which covers most West European languages such as Albanian, |
465 | Catalan, Danish, Dutch, English, Estonian, Faeroese, Finnish, | 465 | Catalan, Danish, Dutch, English, Estonian, Faeroese, Finnish, |
466 | French, German, Galician, Irish, Icelandic, Italian, Norwegian, | 466 | French, German, Galician, Irish, Icelandic, Italian, Norwegian, |
467 | Portuguese, Spanish, and Swedish. Latin 9 is an update to | 467 | Portuguese, Spanish, and Swedish. Latin 9 is an update to |
468 | Latin 1 (ISO 8859-1) that removes a handful of rarely used | 468 | Latin 1 (ISO 8859-1) that removes a handful of rarely used |
469 | characters and instead adds support for Estonian, corrects the | 469 | characters and instead adds support for Estonian, corrects the |
470 | support for French and Finnish, and adds the new Euro character. | 470 | support for French and Finnish, and adds the new Euro character. |
471 | If unsure, say Y. | 471 | If unsure, say Y. |
472 | 472 | ||
473 | config NLS_KOI8_R | 473 | config NLS_KOI8_R |
474 | tristate "NLS KOI8-R (Russian)" | 474 | tristate "NLS KOI8-R (Russian)" |
475 | depends on NLS | 475 | depends on NLS |
476 | help | 476 | help |
477 | If you want to display filenames with native language characters | 477 | If you want to display filenames with native language characters |
478 | from the Microsoft FAT file system family or from JOLIET CD-ROMs | 478 | from the Microsoft FAT file system family or from JOLIET CD-ROMs |
479 | correctly on the screen, you need to include the appropriate | 479 | correctly on the screen, you need to include the appropriate |
480 | input/output character sets. Say Y here for the preferred Russian | 480 | input/output character sets. Say Y here for the preferred Russian |
481 | character set. | 481 | character set. |
482 | 482 | ||
483 | config NLS_KOI8_U | 483 | config NLS_KOI8_U |
484 | tristate "NLS KOI8-U/RU (Ukrainian, Belarusian)" | 484 | tristate "NLS KOI8-U/RU (Ukrainian, Belarusian)" |
485 | depends on NLS | 485 | depends on NLS |
486 | help | 486 | help |
487 | If you want to display filenames with native language characters | 487 | If you want to display filenames with native language characters |
488 | from the Microsoft FAT file system family or from JOLIET CD-ROMs | 488 | from the Microsoft FAT file system family or from JOLIET CD-ROMs |
489 | correctly on the screen, you need to include the appropriate | 489 | correctly on the screen, you need to include the appropriate |
490 | input/output character sets. Say Y here for the preferred Ukrainian | 490 | input/output character sets. Say Y here for the preferred Ukrainian |
491 | (koi8-u) and Belarusian (koi8-ru) character sets. | 491 | (koi8-u) and Belarusian (koi8-ru) character sets. |
492 | 492 | ||
493 | config NLS_UTF8 | 493 | config NLS_UTF8 |
494 | tristate "NLS UTF8" | 494 | tristate "NLS UTF-8" |
495 | depends on NLS | 495 | depends on NLS |
496 | help | 496 | help |
497 | If you want to display filenames with native language characters | 497 | If you want to display filenames with native language characters |
498 | from the Microsoft FAT file system family or from JOLIET CD-ROMs | 498 | from the Microsoft FAT file system family or from JOLIET CD-ROMs |
499 | correctly on the screen, you need to include the appropriate | 499 | correctly on the screen, you need to include the appropriate |
500 | input/output character sets. Say Y here for the UTF-8 encoding of | 500 | input/output character sets. Say Y here for the UTF-8 encoding of |
501 | the Unicode/ISO9646 universal character set. | 501 | the Unicode/ISO9646 universal character set. |
502 | 502 | ||
503 | endmenu | 503 | endmenu |
504 | 504 | ||
505 | 505 |
include/asm-mips/termbits.h
1 | /* | 1 | /* |
2 | * This file is subject to the terms and conditions of the GNU General Public | 2 | * This file is subject to the terms and conditions of the GNU General Public |
3 | * License. See the file "COPYING" in the main directory of this archive | 3 | * License. See the file "COPYING" in the main directory of this archive |
4 | * for more details. | 4 | * for more details. |
5 | * | 5 | * |
6 | * Copyright (C) 1995, 1996, 1999, 2001 Ralf Baechle | 6 | * Copyright (C) 1995, 1996, 1999, 2001 Ralf Baechle |
7 | * Copyright (C) 1999 Silicon Graphics, Inc. | 7 | * Copyright (C) 1999 Silicon Graphics, Inc. |
8 | * Copyright (C) 2001 MIPS Technologies, Inc. | 8 | * Copyright (C) 2001 MIPS Technologies, Inc. |
9 | */ | 9 | */ |
10 | #ifndef _ASM_TERMBITS_H | 10 | #ifndef _ASM_TERMBITS_H |
11 | #define _ASM_TERMBITS_H | 11 | #define _ASM_TERMBITS_H |
12 | 12 | ||
13 | #include <linux/posix_types.h> | 13 | #include <linux/posix_types.h> |
14 | 14 | ||
15 | typedef unsigned char cc_t; | 15 | typedef unsigned char cc_t; |
16 | #if (_MIPS_SZLONG == 32) | 16 | #if (_MIPS_SZLONG == 32) |
17 | typedef unsigned long speed_t; | 17 | typedef unsigned long speed_t; |
18 | typedef unsigned long tcflag_t; | 18 | typedef unsigned long tcflag_t; |
19 | #endif | 19 | #endif |
20 | #if (_MIPS_SZLONG == 64) | 20 | #if (_MIPS_SZLONG == 64) |
21 | typedef __u32 speed_t; | 21 | typedef __u32 speed_t; |
22 | typedef __u32 tcflag_t; | 22 | typedef __u32 tcflag_t; |
23 | #endif | 23 | #endif |
24 | 24 | ||
25 | /* | 25 | /* |
26 | * The ABI says nothing about NCC but seems to use NCCS as | 26 | * The ABI says nothing about NCC but seems to use NCCS as |
27 | * replacement for it in struct termio | 27 | * replacement for it in struct termio |
28 | */ | 28 | */ |
29 | #define NCCS 23 | 29 | #define NCCS 23 |
30 | struct termios { | 30 | struct termios { |
31 | tcflag_t c_iflag; /* input mode flags */ | 31 | tcflag_t c_iflag; /* input mode flags */ |
32 | tcflag_t c_oflag; /* output mode flags */ | 32 | tcflag_t c_oflag; /* output mode flags */ |
33 | tcflag_t c_cflag; /* control mode flags */ | 33 | tcflag_t c_cflag; /* control mode flags */ |
34 | tcflag_t c_lflag; /* local mode flags */ | 34 | tcflag_t c_lflag; /* local mode flags */ |
35 | cc_t c_line; /* line discipline */ | 35 | cc_t c_line; /* line discipline */ |
36 | cc_t c_cc[NCCS]; /* control characters */ | 36 | cc_t c_cc[NCCS]; /* control characters */ |
37 | }; | 37 | }; |
38 | 38 | ||
39 | /* c_cc characters */ | 39 | /* c_cc characters */ |
40 | #define VINTR 0 /* Interrupt character [ISIG]. */ | 40 | #define VINTR 0 /* Interrupt character [ISIG]. */ |
41 | #define VQUIT 1 /* Quit character [ISIG]. */ | 41 | #define VQUIT 1 /* Quit character [ISIG]. */ |
42 | #define VERASE 2 /* Erase character [ICANON]. */ | 42 | #define VERASE 2 /* Erase character [ICANON]. */ |
43 | #define VKILL 3 /* Kill-line character [ICANON]. */ | 43 | #define VKILL 3 /* Kill-line character [ICANON]. */ |
44 | #define VMIN 4 /* Minimum number of bytes read at once [!ICANON]. */ | 44 | #define VMIN 4 /* Minimum number of bytes read at once [!ICANON]. */ |
45 | #define VTIME 5 /* Time-out value (tenths of a second) [!ICANON]. */ | 45 | #define VTIME 5 /* Time-out value (tenths of a second) [!ICANON]. */ |
46 | #define VEOL2 6 /* Second EOL character [ICANON]. */ | 46 | #define VEOL2 6 /* Second EOL character [ICANON]. */ |
47 | #define VSWTC 7 /* ??? */ | 47 | #define VSWTC 7 /* ??? */ |
48 | #define VSWTCH VSWTC | 48 | #define VSWTCH VSWTC |
49 | #define VSTART 8 /* Start (X-ON) character [IXON, IXOFF]. */ | 49 | #define VSTART 8 /* Start (X-ON) character [IXON, IXOFF]. */ |
50 | #define VSTOP 9 /* Stop (X-OFF) character [IXON, IXOFF]. */ | 50 | #define VSTOP 9 /* Stop (X-OFF) character [IXON, IXOFF]. */ |
51 | #define VSUSP 10 /* Suspend character [ISIG]. */ | 51 | #define VSUSP 10 /* Suspend character [ISIG]. */ |
52 | #if 0 | 52 | #if 0 |
53 | /* | 53 | /* |
54 | * VDSUSP is not supported | 54 | * VDSUSP is not supported |
55 | */ | 55 | */ |
56 | #define VDSUSP 11 /* Delayed suspend character [ISIG]. */ | 56 | #define VDSUSP 11 /* Delayed suspend character [ISIG]. */ |
57 | #endif | 57 | #endif |
58 | #define VREPRINT 12 /* Reprint-line character [ICANON]. */ | 58 | #define VREPRINT 12 /* Reprint-line character [ICANON]. */ |
59 | #define VDISCARD 13 /* Discard character [IEXTEN]. */ | 59 | #define VDISCARD 13 /* Discard character [IEXTEN]. */ |
60 | #define VWERASE 14 /* Word-erase character [ICANON]. */ | 60 | #define VWERASE 14 /* Word-erase character [ICANON]. */ |
61 | #define VLNEXT 15 /* Literal-next character [IEXTEN]. */ | 61 | #define VLNEXT 15 /* Literal-next character [IEXTEN]. */ |
62 | #define VEOF 16 /* End-of-file character [ICANON]. */ | 62 | #define VEOF 16 /* End-of-file character [ICANON]. */ |
63 | #define VEOL 17 /* End-of-line character [ICANON]. */ | 63 | #define VEOL 17 /* End-of-line character [ICANON]. */ |
64 | 64 | ||
65 | /* c_iflag bits */ | 65 | /* c_iflag bits */ |
66 | #define IGNBRK 0000001 /* Ignore break condition. */ | 66 | #define IGNBRK 0000001 /* Ignore break condition. */ |
67 | #define BRKINT 0000002 /* Signal interrupt on break. */ | 67 | #define BRKINT 0000002 /* Signal interrupt on break. */ |
68 | #define IGNPAR 0000004 /* Ignore characters with parity errors. */ | 68 | #define IGNPAR 0000004 /* Ignore characters with parity errors. */ |
69 | #define PARMRK 0000010 /* Mark parity and framing errors. */ | 69 | #define PARMRK 0000010 /* Mark parity and framing errors. */ |
70 | #define INPCK 0000020 /* Enable input parity check. */ | 70 | #define INPCK 0000020 /* Enable input parity check. */ |
71 | #define ISTRIP 0000040 /* Strip 8th bit off characters. */ | 71 | #define ISTRIP 0000040 /* Strip 8th bit off characters. */ |
72 | #define INLCR 0000100 /* Map NL to CR on input. */ | 72 | #define INLCR 0000100 /* Map NL to CR on input. */ |
73 | #define IGNCR 0000200 /* Ignore CR. */ | 73 | #define IGNCR 0000200 /* Ignore CR. */ |
74 | #define ICRNL 0000400 /* Map CR to NL on input. */ | 74 | #define ICRNL 0000400 /* Map CR to NL on input. */ |
75 | #define IUCLC 0001000 /* Map upper case to lower case on input. */ | 75 | #define IUCLC 0001000 /* Map upper case to lower case on input. */ |
76 | #define IXON 0002000 /* Enable start/stop output control. */ | 76 | #define IXON 0002000 /* Enable start/stop output control. */ |
77 | #define IXANY 0004000 /* Any character will restart after stop. */ | 77 | #define IXANY 0004000 /* Any character will restart after stop. */ |
78 | #define IXOFF 0010000 /* Enable start/stop input control. */ | 78 | #define IXOFF 0010000 /* Enable start/stop input control. */ |
79 | #define IMAXBEL 0020000 /* Ring bell when input queue is full. */ | 79 | #define IMAXBEL 0020000 /* Ring bell when input queue is full. */ |
80 | #define IUTF8 0040000 /* Input is UTF8 */ | 80 | #define IUTF8 0040000 /* Input is UTF-8 */ |
81 | 81 | ||
82 | /* c_oflag bits */ | 82 | /* c_oflag bits */ |
83 | #define OPOST 0000001 /* Perform output processing. */ | 83 | #define OPOST 0000001 /* Perform output processing. */ |
84 | #define OLCUC 0000002 /* Map lower case to upper case on output. */ | 84 | #define OLCUC 0000002 /* Map lower case to upper case on output. */ |
85 | #define ONLCR 0000004 /* Map NL to CR-NL on output. */ | 85 | #define ONLCR 0000004 /* Map NL to CR-NL on output. */ |
86 | #define OCRNL 0000010 | 86 | #define OCRNL 0000010 |
87 | #define ONOCR 0000020 | 87 | #define ONOCR 0000020 |
88 | #define ONLRET 0000040 | 88 | #define ONLRET 0000040 |
89 | #define OFILL 0000100 | 89 | #define OFILL 0000100 |
90 | #define OFDEL 0000200 | 90 | #define OFDEL 0000200 |
91 | #define NLDLY 0000400 | 91 | #define NLDLY 0000400 |
92 | #define NL0 0000000 | 92 | #define NL0 0000000 |
93 | #define NL1 0000400 | 93 | #define NL1 0000400 |
94 | #define CRDLY 0003000 | 94 | #define CRDLY 0003000 |
95 | #define CR0 0000000 | 95 | #define CR0 0000000 |
96 | #define CR1 0001000 | 96 | #define CR1 0001000 |
97 | #define CR2 0002000 | 97 | #define CR2 0002000 |
98 | #define CR3 0003000 | 98 | #define CR3 0003000 |
99 | #define TABDLY 0014000 | 99 | #define TABDLY 0014000 |
100 | #define TAB0 0000000 | 100 | #define TAB0 0000000 |
101 | #define TAB1 0004000 | 101 | #define TAB1 0004000 |
102 | #define TAB2 0010000 | 102 | #define TAB2 0010000 |
103 | #define TAB3 0014000 | 103 | #define TAB3 0014000 |
104 | #define XTABS 0014000 | 104 | #define XTABS 0014000 |
105 | #define BSDLY 0020000 | 105 | #define BSDLY 0020000 |
106 | #define BS0 0000000 | 106 | #define BS0 0000000 |
107 | #define BS1 0020000 | 107 | #define BS1 0020000 |
108 | #define VTDLY 0040000 | 108 | #define VTDLY 0040000 |
109 | #define VT0 0000000 | 109 | #define VT0 0000000 |
110 | #define VT1 0040000 | 110 | #define VT1 0040000 |
111 | #define FFDLY 0100000 | 111 | #define FFDLY 0100000 |
112 | #define FF0 0000000 | 112 | #define FF0 0000000 |
113 | #define FF1 0100000 | 113 | #define FF1 0100000 |
114 | /* | 114 | /* |
115 | #define PAGEOUT ??? | 115 | #define PAGEOUT ??? |
116 | #define WRAP ??? | 116 | #define WRAP ??? |
117 | */ | 117 | */ |
118 | 118 | ||
119 | /* c_cflag bit meaning */ | 119 | /* c_cflag bit meaning */ |
120 | #define CBAUD 0010017 | 120 | #define CBAUD 0010017 |
121 | #define B0 0000000 /* hang up */ | 121 | #define B0 0000000 /* hang up */ |
122 | #define B50 0000001 | 122 | #define B50 0000001 |
123 | #define B75 0000002 | 123 | #define B75 0000002 |
124 | #define B110 0000003 | 124 | #define B110 0000003 |
125 | #define B134 0000004 | 125 | #define B134 0000004 |
126 | #define B150 0000005 | 126 | #define B150 0000005 |
127 | #define B200 0000006 | 127 | #define B200 0000006 |
128 | #define B300 0000007 | 128 | #define B300 0000007 |
129 | #define B600 0000010 | 129 | #define B600 0000010 |
130 | #define B1200 0000011 | 130 | #define B1200 0000011 |
131 | #define B1800 0000012 | 131 | #define B1800 0000012 |
132 | #define B2400 0000013 | 132 | #define B2400 0000013 |
133 | #define B4800 0000014 | 133 | #define B4800 0000014 |
134 | #define B9600 0000015 | 134 | #define B9600 0000015 |
135 | #define B19200 0000016 | 135 | #define B19200 0000016 |
136 | #define B38400 0000017 | 136 | #define B38400 0000017 |
137 | #define EXTA B19200 | 137 | #define EXTA B19200 |
138 | #define EXTB B38400 | 138 | #define EXTB B38400 |
139 | #define CSIZE 0000060 /* Number of bits per byte (mask). */ | 139 | #define CSIZE 0000060 /* Number of bits per byte (mask). */ |
140 | #define CS5 0000000 /* 5 bits per byte. */ | 140 | #define CS5 0000000 /* 5 bits per byte. */ |
141 | #define CS6 0000020 /* 6 bits per byte. */ | 141 | #define CS6 0000020 /* 6 bits per byte. */ |
142 | #define CS7 0000040 /* 7 bits per byte. */ | 142 | #define CS7 0000040 /* 7 bits per byte. */ |
143 | #define CS8 0000060 /* 8 bits per byte. */ | 143 | #define CS8 0000060 /* 8 bits per byte. */ |
144 | #define CSTOPB 0000100 /* Two stop bits instead of one. */ | 144 | #define CSTOPB 0000100 /* Two stop bits instead of one. */ |
145 | #define CREAD 0000200 /* Enable receiver. */ | 145 | #define CREAD 0000200 /* Enable receiver. */ |
146 | #define PARENB 0000400 /* Parity enable. */ | 146 | #define PARENB 0000400 /* Parity enable. */ |
147 | #define PARODD 0001000 /* Odd parity instead of even. */ | 147 | #define PARODD 0001000 /* Odd parity instead of even. */ |
148 | #define HUPCL 0002000 /* Hang up on last close. */ | 148 | #define HUPCL 0002000 /* Hang up on last close. */ |
149 | #define CLOCAL 0004000 /* Ignore modem status lines. */ | 149 | #define CLOCAL 0004000 /* Ignore modem status lines. */ |
150 | #define CBAUDEX 0010000 | 150 | #define CBAUDEX 0010000 |
151 | #define B57600 0010001 | 151 | #define B57600 0010001 |
152 | #define B115200 0010002 | 152 | #define B115200 0010002 |
153 | #define B230400 0010003 | 153 | #define B230400 0010003 |
154 | #define B460800 0010004 | 154 | #define B460800 0010004 |
155 | #define B500000 0010005 | 155 | #define B500000 0010005 |
156 | #define B576000 0010006 | 156 | #define B576000 0010006 |
157 | #define B921600 0010007 | 157 | #define B921600 0010007 |
158 | #define B1000000 0010010 | 158 | #define B1000000 0010010 |
159 | #define B1152000 0010011 | 159 | #define B1152000 0010011 |
160 | #define B1500000 0010012 | 160 | #define B1500000 0010012 |
161 | #define B2000000 0010013 | 161 | #define B2000000 0010013 |
162 | #define B2500000 0010014 | 162 | #define B2500000 0010014 |
163 | #define B3000000 0010015 | 163 | #define B3000000 0010015 |
164 | #define B3500000 0010016 | 164 | #define B3500000 0010016 |
165 | #define B4000000 0010017 | 165 | #define B4000000 0010017 |
166 | #define CIBAUD 002003600000 /* input baud rate (not used) */ | 166 | #define CIBAUD 002003600000 /* input baud rate (not used) */ |
167 | #define CMSPAR 010000000000 /* mark or space (stick) parity */ | 167 | #define CMSPAR 010000000000 /* mark or space (stick) parity */ |
168 | #define CRTSCTS 020000000000 /* flow control */ | 168 | #define CRTSCTS 020000000000 /* flow control */ |
169 | 169 | ||
170 | /* c_lflag bits */ | 170 | /* c_lflag bits */ |
171 | #define ISIG 0000001 /* Enable signals. */ | 171 | #define ISIG 0000001 /* Enable signals. */ |
172 | #define ICANON 0000002 /* Do erase and kill processing. */ | 172 | #define ICANON 0000002 /* Do erase and kill processing. */ |
173 | #define XCASE 0000004 | 173 | #define XCASE 0000004 |
174 | #define ECHO 0000010 /* Enable echo. */ | 174 | #define ECHO 0000010 /* Enable echo. */ |
175 | #define ECHOE 0000020 /* Visual erase for ERASE. */ | 175 | #define ECHOE 0000020 /* Visual erase for ERASE. */ |
176 | #define ECHOK 0000040 /* Echo NL after KILL. */ | 176 | #define ECHOK 0000040 /* Echo NL after KILL. */ |
177 | #define ECHONL 0000100 /* Echo NL even if ECHO is off. */ | 177 | #define ECHONL 0000100 /* Echo NL even if ECHO is off. */ |
178 | #define NOFLSH 0000200 /* Disable flush after interrupt. */ | 178 | #define NOFLSH 0000200 /* Disable flush after interrupt. */ |
179 | #define IEXTEN 0000400 /* Enable DISCARD and LNEXT. */ | 179 | #define IEXTEN 0000400 /* Enable DISCARD and LNEXT. */ |
180 | #define ECHOCTL 0001000 /* Echo control characters as ^X. */ | 180 | #define ECHOCTL 0001000 /* Echo control characters as ^X. */ |
181 | #define ECHOPRT 0002000 /* Hardcopy visual erase. */ | 181 | #define ECHOPRT 0002000 /* Hardcopy visual erase. */ |
182 | #define ECHOKE 0004000 /* Visual erase for KILL. */ | 182 | #define ECHOKE 0004000 /* Visual erase for KILL. */ |
183 | #define FLUSHO 0020000 | 183 | #define FLUSHO 0020000 |
184 | #define PENDIN 0040000 /* Retype pending input (state). */ | 184 | #define PENDIN 0040000 /* Retype pending input (state). */ |
185 | #define TOSTOP 0100000 /* Send SIGTTOU for background output. */ | 185 | #define TOSTOP 0100000 /* Send SIGTTOU for background output. */ |
186 | #define ITOSTOP TOSTOP | 186 | #define ITOSTOP TOSTOP |
187 | 187 | ||
188 | /* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */ | 188 | /* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */ |
189 | #define TIOCSER_TEMT 0x01 /* Transmitter physically empty */ | 189 | #define TIOCSER_TEMT 0x01 /* Transmitter physically empty */ |
190 | 190 | ||
191 | /* tcflow() and TCXONC use these */ | 191 | /* tcflow() and TCXONC use these */ |
192 | #define TCOOFF 0 /* Suspend output. */ | 192 | #define TCOOFF 0 /* Suspend output. */ |
193 | #define TCOON 1 /* Restart suspended output. */ | 193 | #define TCOON 1 /* Restart suspended output. */ |
194 | #define TCIOFF 2 /* Send a STOP character. */ | 194 | #define TCIOFF 2 /* Send a STOP character. */ |
195 | #define TCION 3 /* Send a START character. */ | 195 | #define TCION 3 /* Send a START character. */ |
196 | 196 | ||
197 | /* tcflush() and TCFLSH use these */ | 197 | /* tcflush() and TCFLSH use these */ |
198 | #define TCIFLUSH 0 /* Discard data received but not yet read. */ | 198 | #define TCIFLUSH 0 /* Discard data received but not yet read. */ |
199 | #define TCOFLUSH 1 /* Discard data written but not yet sent. */ | 199 | #define TCOFLUSH 1 /* Discard data written but not yet sent. */ |
200 | #define TCIOFLUSH 2 /* Discard all pending data. */ | 200 | #define TCIOFLUSH 2 /* Discard all pending data. */ |
201 | 201 | ||
202 | /* tcsetattr uses these */ | 202 | /* tcsetattr uses these */ |
203 | #define TCSANOW TCSETS /* Change immediately. */ | 203 | #define TCSANOW TCSETS /* Change immediately. */ |
204 | #define TCSADRAIN TCSETSW /* Change when pending output is written. */ | 204 | #define TCSADRAIN TCSETSW /* Change when pending output is written. */ |
205 | #define TCSAFLUSH TCSETSF /* Flush pending input before changing. */ | 205 | #define TCSAFLUSH TCSETSF /* Flush pending input before changing. */ |
206 | 206 | ||
207 | #endif /* _ASM_TERMBITS_H */ | 207 | #endif /* _ASM_TERMBITS_H */ |
208 | 208 |
include/linux/msdos_fs.h
1 | #ifndef _LINUX_MSDOS_FS_H | 1 | #ifndef _LINUX_MSDOS_FS_H |
2 | #define _LINUX_MSDOS_FS_H | 2 | #define _LINUX_MSDOS_FS_H |
3 | 3 | ||
4 | /* | 4 | /* |
5 | * The MS-DOS filesystem constants/structures | 5 | * The MS-DOS filesystem constants/structures |
6 | */ | 6 | */ |
7 | #include <asm/byteorder.h> | 7 | #include <asm/byteorder.h> |
8 | 8 | ||
9 | #define SECTOR_SIZE 512 /* sector size (bytes) */ | 9 | #define SECTOR_SIZE 512 /* sector size (bytes) */ |
10 | #define SECTOR_BITS 9 /* log2(SECTOR_SIZE) */ | 10 | #define SECTOR_BITS 9 /* log2(SECTOR_SIZE) */ |
11 | #define MSDOS_DPB (MSDOS_DPS) /* dir entries per block */ | 11 | #define MSDOS_DPB (MSDOS_DPS) /* dir entries per block */ |
12 | #define MSDOS_DPB_BITS 4 /* log2(MSDOS_DPB) */ | 12 | #define MSDOS_DPB_BITS 4 /* log2(MSDOS_DPB) */ |
13 | #define MSDOS_DPS (SECTOR_SIZE / sizeof(struct msdos_dir_entry)) | 13 | #define MSDOS_DPS (SECTOR_SIZE / sizeof(struct msdos_dir_entry)) |
14 | #define MSDOS_DPS_BITS 4 /* log2(MSDOS_DPS) */ | 14 | #define MSDOS_DPS_BITS 4 /* log2(MSDOS_DPS) */ |
15 | #define CF_LE_W(v) le16_to_cpu(v) | 15 | #define CF_LE_W(v) le16_to_cpu(v) |
16 | #define CF_LE_L(v) le32_to_cpu(v) | 16 | #define CF_LE_L(v) le32_to_cpu(v) |
17 | #define CT_LE_W(v) cpu_to_le16(v) | 17 | #define CT_LE_W(v) cpu_to_le16(v) |
18 | #define CT_LE_L(v) cpu_to_le32(v) | 18 | #define CT_LE_L(v) cpu_to_le32(v) |
19 | 19 | ||
20 | 20 | ||
21 | #define MSDOS_SUPER_MAGIC 0x4d44 /* MD */ | 21 | #define MSDOS_SUPER_MAGIC 0x4d44 /* MD */ |
22 | 22 | ||
23 | #define MSDOS_ROOT_INO 1 /* == MINIX_ROOT_INO */ | 23 | #define MSDOS_ROOT_INO 1 /* == MINIX_ROOT_INO */ |
24 | #define MSDOS_DIR_BITS 5 /* log2(sizeof(struct msdos_dir_entry)) */ | 24 | #define MSDOS_DIR_BITS 5 /* log2(sizeof(struct msdos_dir_entry)) */ |
25 | 25 | ||
26 | /* directory limit */ | 26 | /* directory limit */ |
27 | #define FAT_MAX_DIR_ENTRIES (65536) | 27 | #define FAT_MAX_DIR_ENTRIES (65536) |
28 | #define FAT_MAX_DIR_SIZE (FAT_MAX_DIR_ENTRIES << MSDOS_DIR_BITS) | 28 | #define FAT_MAX_DIR_SIZE (FAT_MAX_DIR_ENTRIES << MSDOS_DIR_BITS) |
29 | 29 | ||
30 | #define ATTR_NONE 0 /* no attribute bits */ | 30 | #define ATTR_NONE 0 /* no attribute bits */ |
31 | #define ATTR_RO 1 /* read-only */ | 31 | #define ATTR_RO 1 /* read-only */ |
32 | #define ATTR_HIDDEN 2 /* hidden */ | 32 | #define ATTR_HIDDEN 2 /* hidden */ |
33 | #define ATTR_SYS 4 /* system */ | 33 | #define ATTR_SYS 4 /* system */ |
34 | #define ATTR_VOLUME 8 /* volume label */ | 34 | #define ATTR_VOLUME 8 /* volume label */ |
35 | #define ATTR_DIR 16 /* directory */ | 35 | #define ATTR_DIR 16 /* directory */ |
36 | #define ATTR_ARCH 32 /* archived */ | 36 | #define ATTR_ARCH 32 /* archived */ |
37 | 37 | ||
38 | /* attribute bits that are copied "as is" */ | 38 | /* attribute bits that are copied "as is" */ |
39 | #define ATTR_UNUSED (ATTR_VOLUME | ATTR_ARCH | ATTR_SYS | ATTR_HIDDEN) | 39 | #define ATTR_UNUSED (ATTR_VOLUME | ATTR_ARCH | ATTR_SYS | ATTR_HIDDEN) |
40 | /* bits that are used by the Windows 95/Windows NT extended FAT */ | 40 | /* bits that are used by the Windows 95/Windows NT extended FAT */ |
41 | #define ATTR_EXT (ATTR_RO | ATTR_HIDDEN | ATTR_SYS | ATTR_VOLUME) | 41 | #define ATTR_EXT (ATTR_RO | ATTR_HIDDEN | ATTR_SYS | ATTR_VOLUME) |
42 | 42 | ||
43 | #define CASE_LOWER_BASE 8 /* base is lower case */ | 43 | #define CASE_LOWER_BASE 8 /* base is lower case */ |
44 | #define CASE_LOWER_EXT 16 /* extension is lower case */ | 44 | #define CASE_LOWER_EXT 16 /* extension is lower case */ |
45 | 45 | ||
46 | #define DELETED_FLAG 0xe5 /* marks file as deleted when in name[0] */ | 46 | #define DELETED_FLAG 0xe5 /* marks file as deleted when in name[0] */ |
47 | #define IS_FREE(n) (!*(n) || *(n) == DELETED_FLAG) | 47 | #define IS_FREE(n) (!*(n) || *(n) == DELETED_FLAG) |
48 | 48 | ||
49 | /* valid file mode bits */ | 49 | /* valid file mode bits */ |
50 | #define MSDOS_VALID_MODE (S_IFREG | S_IFDIR | S_IRWXU | S_IRWXG | S_IRWXO) | 50 | #define MSDOS_VALID_MODE (S_IFREG | S_IFDIR | S_IRWXU | S_IRWXG | S_IRWXO) |
51 | /* Convert attribute bits and a mask to the UNIX mode. */ | 51 | /* Convert attribute bits and a mask to the UNIX mode. */ |
52 | #define MSDOS_MKMODE(a, m) (m & (a & ATTR_RO ? S_IRUGO|S_IXUGO : S_IRWXUGO)) | 52 | #define MSDOS_MKMODE(a, m) (m & (a & ATTR_RO ? S_IRUGO|S_IXUGO : S_IRWXUGO)) |
53 | 53 | ||
54 | #define MSDOS_NAME 11 /* maximum name length */ | 54 | #define MSDOS_NAME 11 /* maximum name length */ |
55 | #define MSDOS_LONGNAME 256 /* maximum name length */ | 55 | #define MSDOS_LONGNAME 256 /* maximum name length */ |
56 | #define MSDOS_SLOTS 21 /* max # of slots for short and long names */ | 56 | #define MSDOS_SLOTS 21 /* max # of slots for short and long names */ |
57 | #define MSDOS_DOT ". " /* ".", padded to MSDOS_NAME chars */ | 57 | #define MSDOS_DOT ". " /* ".", padded to MSDOS_NAME chars */ |
58 | #define MSDOS_DOTDOT ".. " /* "..", padded to MSDOS_NAME chars */ | 58 | #define MSDOS_DOTDOT ".. " /* "..", padded to MSDOS_NAME chars */ |
59 | 59 | ||
60 | /* media of boot sector */ | 60 | /* media of boot sector */ |
61 | #define FAT_VALID_MEDIA(x) ((0xF8 <= (x) && (x) <= 0xFF) || (x) == 0xF0) | 61 | #define FAT_VALID_MEDIA(x) ((0xF8 <= (x) && (x) <= 0xFF) || (x) == 0xF0) |
62 | #define FAT_FIRST_ENT(s, x) ((MSDOS_SB(s)->fat_bits == 32 ? 0x0FFFFF00 : \ | 62 | #define FAT_FIRST_ENT(s, x) ((MSDOS_SB(s)->fat_bits == 32 ? 0x0FFFFF00 : \ |
63 | MSDOS_SB(s)->fat_bits == 16 ? 0xFF00 : 0xF00) | (x)) | 63 | MSDOS_SB(s)->fat_bits == 16 ? 0xFF00 : 0xF00) | (x)) |
64 | 64 | ||
65 | /* start of data cluster's entry (number of reserved clusters) */ | 65 | /* start of data cluster's entry (number of reserved clusters) */ |
66 | #define FAT_START_ENT 2 | 66 | #define FAT_START_ENT 2 |
67 | 67 | ||
68 | /* maximum number of clusters */ | 68 | /* maximum number of clusters */ |
69 | #define MAX_FAT12 0xFF4 | 69 | #define MAX_FAT12 0xFF4 |
70 | #define MAX_FAT16 0xFFF4 | 70 | #define MAX_FAT16 0xFFF4 |
71 | #define MAX_FAT32 0x0FFFFFF6 | 71 | #define MAX_FAT32 0x0FFFFFF6 |
72 | #define MAX_FAT(s) (MSDOS_SB(s)->fat_bits == 32 ? MAX_FAT32 : \ | 72 | #define MAX_FAT(s) (MSDOS_SB(s)->fat_bits == 32 ? MAX_FAT32 : \ |
73 | MSDOS_SB(s)->fat_bits == 16 ? MAX_FAT16 : MAX_FAT12) | 73 | MSDOS_SB(s)->fat_bits == 16 ? MAX_FAT16 : MAX_FAT12) |
74 | 74 | ||
75 | /* bad cluster mark */ | 75 | /* bad cluster mark */ |
76 | #define BAD_FAT12 0xFF7 | 76 | #define BAD_FAT12 0xFF7 |
77 | #define BAD_FAT16 0xFFF7 | 77 | #define BAD_FAT16 0xFFF7 |
78 | #define BAD_FAT32 0x0FFFFFF7 | 78 | #define BAD_FAT32 0x0FFFFFF7 |
79 | 79 | ||
80 | /* standard EOF */ | 80 | /* standard EOF */ |
81 | #define EOF_FAT12 0xFFF | 81 | #define EOF_FAT12 0xFFF |
82 | #define EOF_FAT16 0xFFFF | 82 | #define EOF_FAT16 0xFFFF |
83 | #define EOF_FAT32 0x0FFFFFFF | 83 | #define EOF_FAT32 0x0FFFFFFF |
84 | 84 | ||
85 | #define FAT_ENT_FREE (0) | 85 | #define FAT_ENT_FREE (0) |
86 | #define FAT_ENT_BAD (BAD_FAT32) | 86 | #define FAT_ENT_BAD (BAD_FAT32) |
87 | #define FAT_ENT_EOF (EOF_FAT32) | 87 | #define FAT_ENT_EOF (EOF_FAT32) |
88 | 88 | ||
89 | #define FAT_FSINFO_SIG1 0x41615252 | 89 | #define FAT_FSINFO_SIG1 0x41615252 |
90 | #define FAT_FSINFO_SIG2 0x61417272 | 90 | #define FAT_FSINFO_SIG2 0x61417272 |
91 | #define IS_FSINFO(x) (le32_to_cpu((x)->signature1) == FAT_FSINFO_SIG1 \ | 91 | #define IS_FSINFO(x) (le32_to_cpu((x)->signature1) == FAT_FSINFO_SIG1 \ |
92 | && le32_to_cpu((x)->signature2) == FAT_FSINFO_SIG2) | 92 | && le32_to_cpu((x)->signature2) == FAT_FSINFO_SIG2) |
93 | 93 | ||
94 | /* | 94 | /* |
95 | * ioctl commands | 95 | * ioctl commands |
96 | */ | 96 | */ |
97 | #define VFAT_IOCTL_READDIR_BOTH _IOR('r', 1, struct dirent [2]) | 97 | #define VFAT_IOCTL_READDIR_BOTH _IOR('r', 1, struct dirent [2]) |
98 | #define VFAT_IOCTL_READDIR_SHORT _IOR('r', 2, struct dirent [2]) | 98 | #define VFAT_IOCTL_READDIR_SHORT _IOR('r', 2, struct dirent [2]) |
99 | /* <linux/videotext.h> has used 0x72 ('r') in collision, so skip a few */ | 99 | /* <linux/videotext.h> has used 0x72 ('r') in collision, so skip a few */ |
100 | #define FAT_IOCTL_GET_ATTRIBUTES _IOR('r', 0x10, __u32) | 100 | #define FAT_IOCTL_GET_ATTRIBUTES _IOR('r', 0x10, __u32) |
101 | #define FAT_IOCTL_SET_ATTRIBUTES _IOW('r', 0x11, __u32) | 101 | #define FAT_IOCTL_SET_ATTRIBUTES _IOW('r', 0x11, __u32) |
102 | 102 | ||
103 | /* | 103 | /* |
104 | * vfat shortname flags | 104 | * vfat shortname flags |
105 | */ | 105 | */ |
106 | #define VFAT_SFN_DISPLAY_LOWER 0x0001 /* convert to lowercase for display */ | 106 | #define VFAT_SFN_DISPLAY_LOWER 0x0001 /* convert to lowercase for display */ |
107 | #define VFAT_SFN_DISPLAY_WIN95 0x0002 /* emulate win95 rule for display */ | 107 | #define VFAT_SFN_DISPLAY_WIN95 0x0002 /* emulate win95 rule for display */ |
108 | #define VFAT_SFN_DISPLAY_WINNT 0x0004 /* emulate winnt rule for display */ | 108 | #define VFAT_SFN_DISPLAY_WINNT 0x0004 /* emulate winnt rule for display */ |
109 | #define VFAT_SFN_CREATE_WIN95 0x0100 /* emulate win95 rule for create */ | 109 | #define VFAT_SFN_CREATE_WIN95 0x0100 /* emulate win95 rule for create */ |
110 | #define VFAT_SFN_CREATE_WINNT 0x0200 /* emulate winnt rule for create */ | 110 | #define VFAT_SFN_CREATE_WINNT 0x0200 /* emulate winnt rule for create */ |
111 | 111 | ||
112 | struct fat_boot_sector { | 112 | struct fat_boot_sector { |
113 | __u8 ignored[3]; /* Boot strap short or near jump */ | 113 | __u8 ignored[3]; /* Boot strap short or near jump */ |
114 | __u8 system_id[8]; /* Name - can be used to special case | 114 | __u8 system_id[8]; /* Name - can be used to special case |
115 | partition manager volumes */ | 115 | partition manager volumes */ |
116 | __u8 sector_size[2]; /* bytes per logical sector */ | 116 | __u8 sector_size[2]; /* bytes per logical sector */ |
117 | __u8 sec_per_clus; /* sectors/cluster */ | 117 | __u8 sec_per_clus; /* sectors/cluster */ |
118 | __le16 reserved; /* reserved sectors */ | 118 | __le16 reserved; /* reserved sectors */ |
119 | __u8 fats; /* number of FATs */ | 119 | __u8 fats; /* number of FATs */ |
120 | __u8 dir_entries[2]; /* root directory entries */ | 120 | __u8 dir_entries[2]; /* root directory entries */ |
121 | __u8 sectors[2]; /* number of sectors */ | 121 | __u8 sectors[2]; /* number of sectors */ |
122 | __u8 media; /* media code */ | 122 | __u8 media; /* media code */ |
123 | __le16 fat_length; /* sectors/FAT */ | 123 | __le16 fat_length; /* sectors/FAT */ |
124 | __le16 secs_track; /* sectors per track */ | 124 | __le16 secs_track; /* sectors per track */ |
125 | __le16 heads; /* number of heads */ | 125 | __le16 heads; /* number of heads */ |
126 | __le32 hidden; /* hidden sectors (unused) */ | 126 | __le32 hidden; /* hidden sectors (unused) */ |
127 | __le32 total_sect; /* number of sectors (if sectors == 0) */ | 127 | __le32 total_sect; /* number of sectors (if sectors == 0) */ |
128 | 128 | ||
129 | /* The following fields are only used by FAT32 */ | 129 | /* The following fields are only used by FAT32 */ |
130 | __le32 fat32_length; /* sectors/FAT */ | 130 | __le32 fat32_length; /* sectors/FAT */ |
131 | __le16 flags; /* bit 8: fat mirroring, low 4: active fat */ | 131 | __le16 flags; /* bit 8: fat mirroring, low 4: active fat */ |
132 | __u8 version[2]; /* major, minor filesystem version */ | 132 | __u8 version[2]; /* major, minor filesystem version */ |
133 | __le32 root_cluster; /* first cluster in root directory */ | 133 | __le32 root_cluster; /* first cluster in root directory */ |
134 | __le16 info_sector; /* filesystem info sector */ | 134 | __le16 info_sector; /* filesystem info sector */ |
135 | __le16 backup_boot; /* backup boot sector */ | 135 | __le16 backup_boot; /* backup boot sector */ |
136 | __le16 reserved2[6]; /* Unused */ | 136 | __le16 reserved2[6]; /* Unused */ |
137 | }; | 137 | }; |
138 | 138 | ||
139 | struct fat_boot_fsinfo { | 139 | struct fat_boot_fsinfo { |
140 | __le32 signature1; /* 0x41615252L */ | 140 | __le32 signature1; /* 0x41615252L */ |
141 | __le32 reserved1[120]; /* Nothing as far as I can tell */ | 141 | __le32 reserved1[120]; /* Nothing as far as I can tell */ |
142 | __le32 signature2; /* 0x61417272L */ | 142 | __le32 signature2; /* 0x61417272L */ |
143 | __le32 free_clusters; /* Free cluster count. -1 if unknown */ | 143 | __le32 free_clusters; /* Free cluster count. -1 if unknown */ |
144 | __le32 next_cluster; /* Most recently allocated cluster */ | 144 | __le32 next_cluster; /* Most recently allocated cluster */ |
145 | __le32 reserved2[4]; | 145 | __le32 reserved2[4]; |
146 | }; | 146 | }; |
147 | 147 | ||
148 | struct msdos_dir_entry { | 148 | struct msdos_dir_entry { |
149 | __u8 name[8],ext[3]; /* name and extension */ | 149 | __u8 name[8],ext[3]; /* name and extension */ |
150 | __u8 attr; /* attribute bits */ | 150 | __u8 attr; /* attribute bits */ |
151 | __u8 lcase; /* Case for base and extension */ | 151 | __u8 lcase; /* Case for base and extension */ |
152 | __u8 ctime_cs; /* Creation time, centiseconds (0-199) */ | 152 | __u8 ctime_cs; /* Creation time, centiseconds (0-199) */ |
153 | __le16 ctime; /* Creation time */ | 153 | __le16 ctime; /* Creation time */ |
154 | __le16 cdate; /* Creation date */ | 154 | __le16 cdate; /* Creation date */ |
155 | __le16 adate; /* Last access date */ | 155 | __le16 adate; /* Last access date */ |
156 | __le16 starthi; /* High 16 bits of cluster in FAT32 */ | 156 | __le16 starthi; /* High 16 bits of cluster in FAT32 */ |
157 | __le16 time,date,start;/* time, date and first cluster */ | 157 | __le16 time,date,start;/* time, date and first cluster */ |
158 | __le32 size; /* file size (in bytes) */ | 158 | __le32 size; /* file size (in bytes) */ |
159 | }; | 159 | }; |
160 | 160 | ||
161 | /* Up to 13 characters of the name */ | 161 | /* Up to 13 characters of the name */ |
162 | struct msdos_dir_slot { | 162 | struct msdos_dir_slot { |
163 | __u8 id; /* sequence number for slot */ | 163 | __u8 id; /* sequence number for slot */ |
164 | __u8 name0_4[10]; /* first 5 characters in name */ | 164 | __u8 name0_4[10]; /* first 5 characters in name */ |
165 | __u8 attr; /* attribute byte */ | 165 | __u8 attr; /* attribute byte */ |
166 | __u8 reserved; /* always 0 */ | 166 | __u8 reserved; /* always 0 */ |
167 | __u8 alias_checksum; /* checksum for 8.3 alias */ | 167 | __u8 alias_checksum; /* checksum for 8.3 alias */ |
168 | __u8 name5_10[12]; /* 6 more characters in name */ | 168 | __u8 name5_10[12]; /* 6 more characters in name */ |
169 | __le16 start; /* starting cluster number, 0 in long slots */ | 169 | __le16 start; /* starting cluster number, 0 in long slots */ |
170 | __u8 name11_12[4]; /* last 2 characters in name */ | 170 | __u8 name11_12[4]; /* last 2 characters in name */ |
171 | }; | 171 | }; |
172 | 172 | ||
173 | struct fat_slot_info { | 173 | struct fat_slot_info { |
174 | loff_t i_pos; /* on-disk position of directory entry */ | 174 | loff_t i_pos; /* on-disk position of directory entry */ |
175 | loff_t slot_off; /* offset for slot or de start */ | 175 | loff_t slot_off; /* offset for slot or de start */ |
176 | int nr_slots; /* number of slots + 1(de) in filename */ | 176 | int nr_slots; /* number of slots + 1(de) in filename */ |
177 | struct msdos_dir_entry *de; | 177 | struct msdos_dir_entry *de; |
178 | struct buffer_head *bh; | 178 | struct buffer_head *bh; |
179 | }; | 179 | }; |
180 | 180 | ||
181 | #ifdef __KERNEL__ | 181 | #ifdef __KERNEL__ |
182 | 182 | ||
183 | #include <linux/buffer_head.h> | 183 | #include <linux/buffer_head.h> |
184 | #include <linux/string.h> | 184 | #include <linux/string.h> |
185 | #include <linux/nls.h> | 185 | #include <linux/nls.h> |
186 | #include <linux/fs.h> | 186 | #include <linux/fs.h> |
187 | 187 | ||
188 | struct fat_mount_options { | 188 | struct fat_mount_options { |
189 | uid_t fs_uid; | 189 | uid_t fs_uid; |
190 | gid_t fs_gid; | 190 | gid_t fs_gid; |
191 | unsigned short fs_fmask; | 191 | unsigned short fs_fmask; |
192 | unsigned short fs_dmask; | 192 | unsigned short fs_dmask; |
193 | unsigned short codepage; /* Codepage for shortname conversions */ | 193 | unsigned short codepage; /* Codepage for shortname conversions */ |
194 | char *iocharset; /* Charset used for filename input/display */ | 194 | char *iocharset; /* Charset used for filename input/display */ |
195 | unsigned short shortname; /* flags for shortname display/create rule */ | 195 | unsigned short shortname; /* flags for shortname display/create rule */ |
196 | unsigned char name_check; /* r = relaxed, n = normal, s = strict */ | 196 | unsigned char name_check; /* r = relaxed, n = normal, s = strict */ |
197 | unsigned quiet:1, /* set = fake successful chmods and chowns */ | 197 | unsigned quiet:1, /* set = fake successful chmods and chowns */ |
198 | showexec:1, /* set = only set x bit for com/exe/bat */ | 198 | showexec:1, /* set = only set x bit for com/exe/bat */ |
199 | sys_immutable:1, /* set = system files are immutable */ | 199 | sys_immutable:1, /* set = system files are immutable */ |
200 | dotsOK:1, /* set = hidden and system files are named '.filename' */ | 200 | dotsOK:1, /* set = hidden and system files are named '.filename' */ |
201 | isvfat:1, /* 0=no vfat long filename support, 1=vfat support */ | 201 | isvfat:1, /* 0=no vfat long filename support, 1=vfat support */ |
202 | utf8:1, /* Use of UTF8 character set (Default) */ | 202 | utf8:1, /* Use of UTF-8 character set (Default) */ |
203 | unicode_xlate:1, /* create escape sequences for unhandled Unicode */ | 203 | unicode_xlate:1, /* create escape sequences for unhandled Unicode */ |
204 | numtail:1, /* Does first alias have a numeric '~1' type tail? */ | 204 | numtail:1, /* Does first alias have a numeric '~1' type tail? */ |
205 | atari:1, /* Use Atari GEMDOS variation of MS-DOS fs */ | 205 | atari:1, /* Use Atari GEMDOS variation of MS-DOS fs */ |
206 | nocase:1; /* Does this need case conversion? 0=need case conversion*/ | 206 | nocase:1; /* Does this need case conversion? 0=need case conversion*/ |
207 | }; | 207 | }; |
208 | 208 | ||
209 | #define FAT_HASH_BITS 8 | 209 | #define FAT_HASH_BITS 8 |
210 | #define FAT_HASH_SIZE (1UL << FAT_HASH_BITS) | 210 | #define FAT_HASH_SIZE (1UL << FAT_HASH_BITS) |
211 | #define FAT_HASH_MASK (FAT_HASH_SIZE-1) | 211 | #define FAT_HASH_MASK (FAT_HASH_SIZE-1) |
212 | 212 | ||
213 | /* | 213 | /* |
214 | * MS-DOS file system in-core superblock data | 214 | * MS-DOS file system in-core superblock data |
215 | */ | 215 | */ |
216 | struct msdos_sb_info { | 216 | struct msdos_sb_info { |
217 | unsigned short sec_per_clus; /* sectors/cluster */ | 217 | unsigned short sec_per_clus; /* sectors/cluster */ |
218 | unsigned short cluster_bits; /* log2(cluster_size) */ | 218 | unsigned short cluster_bits; /* log2(cluster_size) */ |
219 | unsigned int cluster_size; /* cluster size */ | 219 | unsigned int cluster_size; /* cluster size */ |
220 | unsigned char fats,fat_bits; /* number of FATs, FAT bits (12 or 16) */ | 220 | unsigned char fats,fat_bits; /* number of FATs, FAT bits (12 or 16) */ |
221 | unsigned short fat_start; | 221 | unsigned short fat_start; |
222 | unsigned long fat_length; /* FAT start & length (sec.) */ | 222 | unsigned long fat_length; /* FAT start & length (sec.) */ |
223 | unsigned long dir_start; | 223 | unsigned long dir_start; |
224 | unsigned short dir_entries; /* root dir start & entries */ | 224 | unsigned short dir_entries; /* root dir start & entries */ |
225 | unsigned long data_start; /* first data sector */ | 225 | unsigned long data_start; /* first data sector */ |
226 | unsigned long max_cluster; /* maximum cluster number */ | 226 | unsigned long max_cluster; /* maximum cluster number */ |
227 | unsigned long root_cluster; /* first cluster of the root directory */ | 227 | unsigned long root_cluster; /* first cluster of the root directory */ |
228 | unsigned long fsinfo_sector; /* sector number of FAT32 fsinfo */ | 228 | unsigned long fsinfo_sector; /* sector number of FAT32 fsinfo */ |
229 | struct semaphore fat_lock; | 229 | struct semaphore fat_lock; |
230 | unsigned int prev_free; /* previously allocated cluster number */ | 230 | unsigned int prev_free; /* previously allocated cluster number */ |
231 | unsigned int free_clusters; /* -1 if undefined */ | 231 | unsigned int free_clusters; /* -1 if undefined */ |
232 | struct fat_mount_options options; | 232 | struct fat_mount_options options; |
233 | struct nls_table *nls_disk; /* Codepage used on disk */ | 233 | struct nls_table *nls_disk; /* Codepage used on disk */ |
234 | struct nls_table *nls_io; /* Charset used for input and display */ | 234 | struct nls_table *nls_io; /* Charset used for input and display */ |
235 | void *dir_ops; /* Opaque; default directory operations */ | 235 | void *dir_ops; /* Opaque; default directory operations */ |
236 | int dir_per_block; /* dir entries per block */ | 236 | int dir_per_block; /* dir entries per block */ |
237 | int dir_per_block_bits; /* log2(dir_per_block) */ | 237 | int dir_per_block_bits; /* log2(dir_per_block) */ |
238 | 238 | ||
239 | int fatent_shift; | 239 | int fatent_shift; |
240 | struct fatent_operations *fatent_ops; | 240 | struct fatent_operations *fatent_ops; |
241 | 241 | ||
242 | spinlock_t inode_hash_lock; | 242 | spinlock_t inode_hash_lock; |
243 | struct hlist_head inode_hashtable[FAT_HASH_SIZE]; | 243 | struct hlist_head inode_hashtable[FAT_HASH_SIZE]; |
244 | }; | 244 | }; |
245 | 245 | ||
246 | #define FAT_CACHE_VALID 0 /* special case for valid cache */ | 246 | #define FAT_CACHE_VALID 0 /* special case for valid cache */ |
247 | 247 | ||
248 | /* | 248 | /* |
249 | * MS-DOS file system inode data in memory | 249 | * MS-DOS file system inode data in memory |
250 | */ | 250 | */ |
251 | struct msdos_inode_info { | 251 | struct msdos_inode_info { |
252 | spinlock_t cache_lru_lock; | 252 | spinlock_t cache_lru_lock; |
253 | struct list_head cache_lru; | 253 | struct list_head cache_lru; |
254 | int nr_caches; | 254 | int nr_caches; |
255 | /* for avoiding the race between fat_free() and fat_get_cluster() */ | 255 | /* for avoiding the race between fat_free() and fat_get_cluster() */ |
256 | unsigned int cache_valid_id; | 256 | unsigned int cache_valid_id; |
257 | 257 | ||
258 | loff_t mmu_private; | 258 | loff_t mmu_private; |
259 | int i_start; /* first cluster or 0 */ | 259 | int i_start; /* first cluster or 0 */ |
260 | int i_logstart; /* logical first cluster */ | 260 | int i_logstart; /* logical first cluster */ |
261 | int i_attrs; /* unused attribute bits */ | 261 | int i_attrs; /* unused attribute bits */ |
262 | loff_t i_pos; /* on-disk position of directory entry or 0 */ | 262 | loff_t i_pos; /* on-disk position of directory entry or 0 */ |
263 | struct hlist_node i_fat_hash; /* hash by i_location */ | 263 | struct hlist_node i_fat_hash; /* hash by i_location */ |
264 | struct inode vfs_inode; | 264 | struct inode vfs_inode; |
265 | }; | 265 | }; |
266 | 266 | ||
267 | static inline struct msdos_sb_info *MSDOS_SB(struct super_block *sb) | 267 | static inline struct msdos_sb_info *MSDOS_SB(struct super_block *sb) |
268 | { | 268 | { |
269 | return sb->s_fs_info; | 269 | return sb->s_fs_info; |
270 | } | 270 | } |
271 | 271 | ||
272 | static inline struct msdos_inode_info *MSDOS_I(struct inode *inode) | 272 | static inline struct msdos_inode_info *MSDOS_I(struct inode *inode) |
273 | { | 273 | { |
274 | return container_of(inode, struct msdos_inode_info, vfs_inode); | 274 | return container_of(inode, struct msdos_inode_info, vfs_inode); |
275 | } | 275 | } |
276 | 276 | ||
277 | /* Return the FAT attribute byte for this inode */ | 277 | /* Return the FAT attribute byte for this inode */ |
278 | static inline u8 fat_attr(struct inode *inode) | 278 | static inline u8 fat_attr(struct inode *inode) |
279 | { | 279 | { |
280 | return ((inode->i_mode & S_IWUGO) ? ATTR_NONE : ATTR_RO) | | 280 | return ((inode->i_mode & S_IWUGO) ? ATTR_NONE : ATTR_RO) | |
281 | (S_ISDIR(inode->i_mode) ? ATTR_DIR : ATTR_NONE) | | 281 | (S_ISDIR(inode->i_mode) ? ATTR_DIR : ATTR_NONE) | |
282 | MSDOS_I(inode)->i_attrs; | 282 | MSDOS_I(inode)->i_attrs; |
283 | } | 283 | } |
284 | 284 | ||
285 | static inline unsigned char fat_checksum(const __u8 *name) | 285 | static inline unsigned char fat_checksum(const __u8 *name) |
286 | { | 286 | { |
287 | unsigned char s = name[0]; | 287 | unsigned char s = name[0]; |
288 | s = (s<<7) + (s>>1) + name[1]; s = (s<<7) + (s>>1) + name[2]; | 288 | s = (s<<7) + (s>>1) + name[1]; s = (s<<7) + (s>>1) + name[2]; |
289 | s = (s<<7) + (s>>1) + name[3]; s = (s<<7) + (s>>1) + name[4]; | 289 | s = (s<<7) + (s>>1) + name[3]; s = (s<<7) + (s>>1) + name[4]; |
290 | s = (s<<7) + (s>>1) + name[5]; s = (s<<7) + (s>>1) + name[6]; | 290 | s = (s<<7) + (s>>1) + name[5]; s = (s<<7) + (s>>1) + name[6]; |
291 | s = (s<<7) + (s>>1) + name[7]; s = (s<<7) + (s>>1) + name[8]; | 291 | s = (s<<7) + (s>>1) + name[7]; s = (s<<7) + (s>>1) + name[8]; |
292 | s = (s<<7) + (s>>1) + name[9]; s = (s<<7) + (s>>1) + name[10]; | 292 | s = (s<<7) + (s>>1) + name[9]; s = (s<<7) + (s>>1) + name[10]; |
293 | return s; | 293 | return s; |
294 | } | 294 | } |
295 | 295 | ||
296 | static inline sector_t fat_clus_to_blknr(struct msdos_sb_info *sbi, int clus) | 296 | static inline sector_t fat_clus_to_blknr(struct msdos_sb_info *sbi, int clus) |
297 | { | 297 | { |
298 | return ((sector_t)clus - FAT_START_ENT) * sbi->sec_per_clus | 298 | return ((sector_t)clus - FAT_START_ENT) * sbi->sec_per_clus |
299 | + sbi->data_start; | 299 | + sbi->data_start; |
300 | } | 300 | } |
301 | 301 | ||
302 | static inline void fat16_towchar(wchar_t *dst, const __u8 *src, size_t len) | 302 | static inline void fat16_towchar(wchar_t *dst, const __u8 *src, size_t len) |
303 | { | 303 | { |
304 | #ifdef __BIG_ENDIAN | 304 | #ifdef __BIG_ENDIAN |
305 | while (len--) { | 305 | while (len--) { |
306 | *dst++ = src[0] | (src[1] << 8); | 306 | *dst++ = src[0] | (src[1] << 8); |
307 | src += 2; | 307 | src += 2; |
308 | } | 308 | } |
309 | #else | 309 | #else |
310 | memcpy(dst, src, len * 2); | 310 | memcpy(dst, src, len * 2); |
311 | #endif | 311 | #endif |
312 | } | 312 | } |
313 | 313 | ||
314 | static inline void fatwchar_to16(__u8 *dst, const wchar_t *src, size_t len) | 314 | static inline void fatwchar_to16(__u8 *dst, const wchar_t *src, size_t len) |
315 | { | 315 | { |
316 | #ifdef __BIG_ENDIAN | 316 | #ifdef __BIG_ENDIAN |
317 | while (len--) { | 317 | while (len--) { |
318 | dst[0] = *src & 0x00FF; | 318 | dst[0] = *src & 0x00FF; |
319 | dst[1] = (*src & 0xFF00) >> 8; | 319 | dst[1] = (*src & 0xFF00) >> 8; |
320 | dst += 2; | 320 | dst += 2; |
321 | src++; | 321 | src++; |
322 | } | 322 | } |
323 | #else | 323 | #else |
324 | memcpy(dst, src, len * 2); | 324 | memcpy(dst, src, len * 2); |
325 | #endif | 325 | #endif |
326 | } | 326 | } |
327 | 327 | ||
328 | /* fat/cache.c */ | 328 | /* fat/cache.c */ |
329 | extern void fat_cache_inval_inode(struct inode *inode); | 329 | extern void fat_cache_inval_inode(struct inode *inode); |
330 | extern int fat_get_cluster(struct inode *inode, int cluster, | 330 | extern int fat_get_cluster(struct inode *inode, int cluster, |
331 | int *fclus, int *dclus); | 331 | int *fclus, int *dclus); |
332 | extern int fat_bmap(struct inode *inode, sector_t sector, sector_t *phys, | 332 | extern int fat_bmap(struct inode *inode, sector_t sector, sector_t *phys, |
333 | unsigned long *mapped_blocks); | 333 | unsigned long *mapped_blocks); |
334 | 334 | ||
335 | /* fat/dir.c */ | 335 | /* fat/dir.c */ |
336 | extern struct file_operations fat_dir_operations; | 336 | extern struct file_operations fat_dir_operations; |
337 | extern int fat_search_long(struct inode *inode, const unsigned char *name, | 337 | extern int fat_search_long(struct inode *inode, const unsigned char *name, |
338 | int name_len, struct fat_slot_info *sinfo); | 338 | int name_len, struct fat_slot_info *sinfo); |
339 | extern int fat_dir_empty(struct inode *dir); | 339 | extern int fat_dir_empty(struct inode *dir); |
340 | extern int fat_subdirs(struct inode *dir); | 340 | extern int fat_subdirs(struct inode *dir); |
341 | extern int fat_scan(struct inode *dir, const unsigned char *name, | 341 | extern int fat_scan(struct inode *dir, const unsigned char *name, |
342 | struct fat_slot_info *sinfo); | 342 | struct fat_slot_info *sinfo); |
343 | extern int fat_get_dotdot_entry(struct inode *dir, struct buffer_head **bh, | 343 | extern int fat_get_dotdot_entry(struct inode *dir, struct buffer_head **bh, |
344 | struct msdos_dir_entry **de, loff_t *i_pos); | 344 | struct msdos_dir_entry **de, loff_t *i_pos); |
345 | extern int fat_alloc_new_dir(struct inode *dir, struct timespec *ts); | 345 | extern int fat_alloc_new_dir(struct inode *dir, struct timespec *ts); |
346 | extern int fat_add_entries(struct inode *dir, void *slots, int nr_slots, | 346 | extern int fat_add_entries(struct inode *dir, void *slots, int nr_slots, |
347 | struct fat_slot_info *sinfo); | 347 | struct fat_slot_info *sinfo); |
348 | extern int fat_remove_entries(struct inode *dir, struct fat_slot_info *sinfo); | 348 | extern int fat_remove_entries(struct inode *dir, struct fat_slot_info *sinfo); |
349 | 349 | ||
350 | /* fat/fatent.c */ | 350 | /* fat/fatent.c */ |
351 | struct fat_entry { | 351 | struct fat_entry { |
352 | int entry; | 352 | int entry; |
353 | union { | 353 | union { |
354 | u8 *ent12_p[2]; | 354 | u8 *ent12_p[2]; |
355 | __le16 *ent16_p; | 355 | __le16 *ent16_p; |
356 | __le32 *ent32_p; | 356 | __le32 *ent32_p; |
357 | } u; | 357 | } u; |
358 | int nr_bhs; | 358 | int nr_bhs; |
359 | struct buffer_head *bhs[2]; | 359 | struct buffer_head *bhs[2]; |
360 | }; | 360 | }; |
361 | 361 | ||
362 | static inline void fatent_init(struct fat_entry *fatent) | 362 | static inline void fatent_init(struct fat_entry *fatent) |
363 | { | 363 | { |
364 | fatent->nr_bhs = 0; | 364 | fatent->nr_bhs = 0; |
365 | fatent->entry = 0; | 365 | fatent->entry = 0; |
366 | fatent->u.ent32_p = NULL; | 366 | fatent->u.ent32_p = NULL; |
367 | fatent->bhs[0] = fatent->bhs[1] = NULL; | 367 | fatent->bhs[0] = fatent->bhs[1] = NULL; |
368 | } | 368 | } |
369 | 369 | ||
370 | static inline void fatent_set_entry(struct fat_entry *fatent, int entry) | 370 | static inline void fatent_set_entry(struct fat_entry *fatent, int entry) |
371 | { | 371 | { |
372 | fatent->entry = entry; | 372 | fatent->entry = entry; |
373 | fatent->u.ent32_p = NULL; | 373 | fatent->u.ent32_p = NULL; |
374 | } | 374 | } |
375 | 375 | ||
376 | static inline void fatent_brelse(struct fat_entry *fatent) | 376 | static inline void fatent_brelse(struct fat_entry *fatent) |
377 | { | 377 | { |
378 | int i; | 378 | int i; |
379 | fatent->u.ent32_p = NULL; | 379 | fatent->u.ent32_p = NULL; |
380 | for (i = 0; i < fatent->nr_bhs; i++) | 380 | for (i = 0; i < fatent->nr_bhs; i++) |
381 | brelse(fatent->bhs[i]); | 381 | brelse(fatent->bhs[i]); |
382 | fatent->nr_bhs = 0; | 382 | fatent->nr_bhs = 0; |
383 | fatent->bhs[0] = fatent->bhs[1] = NULL; | 383 | fatent->bhs[0] = fatent->bhs[1] = NULL; |
384 | } | 384 | } |
385 | 385 | ||
386 | extern void fat_ent_access_init(struct super_block *sb); | 386 | extern void fat_ent_access_init(struct super_block *sb); |
387 | extern int fat_ent_read(struct inode *inode, struct fat_entry *fatent, | 387 | extern int fat_ent_read(struct inode *inode, struct fat_entry *fatent, |
388 | int entry); | 388 | int entry); |
389 | extern int fat_ent_write(struct inode *inode, struct fat_entry *fatent, | 389 | extern int fat_ent_write(struct inode *inode, struct fat_entry *fatent, |
390 | int new, int wait); | 390 | int new, int wait); |
391 | extern int fat_alloc_clusters(struct inode *inode, int *cluster, | 391 | extern int fat_alloc_clusters(struct inode *inode, int *cluster, |
392 | int nr_cluster); | 392 | int nr_cluster); |
393 | extern int fat_free_clusters(struct inode *inode, int cluster); | 393 | extern int fat_free_clusters(struct inode *inode, int cluster); |
394 | extern int fat_count_free_clusters(struct super_block *sb); | 394 | extern int fat_count_free_clusters(struct super_block *sb); |
395 | 395 | ||
396 | /* fat/file.c */ | 396 | /* fat/file.c */ |
397 | extern int fat_generic_ioctl(struct inode *inode, struct file *filp, | 397 | extern int fat_generic_ioctl(struct inode *inode, struct file *filp, |
398 | unsigned int cmd, unsigned long arg); | 398 | unsigned int cmd, unsigned long arg); |
399 | extern struct file_operations fat_file_operations; | 399 | extern struct file_operations fat_file_operations; |
400 | extern struct inode_operations fat_file_inode_operations; | 400 | extern struct inode_operations fat_file_inode_operations; |
401 | extern int fat_notify_change(struct dentry * dentry, struct iattr * attr); | 401 | extern int fat_notify_change(struct dentry * dentry, struct iattr * attr); |
402 | extern void fat_truncate(struct inode *inode); | 402 | extern void fat_truncate(struct inode *inode); |
403 | 403 | ||
404 | /* fat/inode.c */ | 404 | /* fat/inode.c */ |
405 | extern void fat_attach(struct inode *inode, loff_t i_pos); | 405 | extern void fat_attach(struct inode *inode, loff_t i_pos); |
406 | extern void fat_detach(struct inode *inode); | 406 | extern void fat_detach(struct inode *inode); |
407 | extern struct inode *fat_iget(struct super_block *sb, loff_t i_pos); | 407 | extern struct inode *fat_iget(struct super_block *sb, loff_t i_pos); |
408 | extern struct inode *fat_build_inode(struct super_block *sb, | 408 | extern struct inode *fat_build_inode(struct super_block *sb, |
409 | struct msdos_dir_entry *de, loff_t i_pos); | 409 | struct msdos_dir_entry *de, loff_t i_pos); |
410 | extern int fat_sync_inode(struct inode *inode); | 410 | extern int fat_sync_inode(struct inode *inode); |
411 | extern int fat_fill_super(struct super_block *sb, void *data, int silent, | 411 | extern int fat_fill_super(struct super_block *sb, void *data, int silent, |
412 | struct inode_operations *fs_dir_inode_ops, int isvfat); | 412 | struct inode_operations *fs_dir_inode_ops, int isvfat); |
413 | 413 | ||
414 | /* fat/misc.c */ | 414 | /* fat/misc.c */ |
415 | extern void fat_fs_panic(struct super_block *s, const char *fmt, ...); | 415 | extern void fat_fs_panic(struct super_block *s, const char *fmt, ...); |
416 | extern void fat_clusters_flush(struct super_block *sb); | 416 | extern void fat_clusters_flush(struct super_block *sb); |
417 | extern int fat_chain_add(struct inode *inode, int new_dclus, int nr_cluster); | 417 | extern int fat_chain_add(struct inode *inode, int new_dclus, int nr_cluster); |
418 | extern int date_dos2unix(unsigned short time, unsigned short date); | 418 | extern int date_dos2unix(unsigned short time, unsigned short date); |
419 | extern void fat_date_unix2dos(int unix_date, __le16 *time, __le16 *date); | 419 | extern void fat_date_unix2dos(int unix_date, __le16 *time, __le16 *date); |
420 | extern int fat_sync_bhs(struct buffer_head **bhs, int nr_bhs); | 420 | extern int fat_sync_bhs(struct buffer_head **bhs, int nr_bhs); |
421 | 421 | ||
422 | #endif /* __KERNEL__ */ | 422 | #endif /* __KERNEL__ */ |
423 | 423 | ||
424 | #endif | 424 | #endif |
425 | 425 |