This source file includes following definitions.
- fat_dir_read
- fat_dir_ioctl
- fat_readdir
1
2
3
4
5
6
7
8
9
10
11
12
13 #include <linux/fs.h>
14 #include <linux/msdos_fs.h>
15 #include <linux/kernel.h>
16 #include <linux/errno.h>
17 #include <linux/stat.h>
18 #include <linux/string.h>
19 #include <linux/ioctl.h>
20
21 #include <asm/segment.h>
22
23 #include "msbuffer.h"
24 #include "tables.h"
25
26
27 #define PRINTK(X)
28
29 static int fat_dir_read(struct inode * inode,struct file * filp, char * buf,int count)
30 {
31 return -EISDIR;
32 }
33
34 struct file_operations fat_dir_operations = {
35 NULL,
36 fat_dir_read,
37 NULL,
38 fat_readdir,
39 NULL,
40 fat_dir_ioctl,
41 NULL,
42 NULL,
43 NULL,
44 file_fsync
45 };
46
47
48 int fat_dir_ioctl(struct inode * inode, struct file * filp,
49 unsigned int cmd, unsigned long arg)
50 {
51 switch (cmd) {
52 #if 0
53
54
55
56
57
58
59 case VFAT_LONGNAME_TO_SHORT:
60 #endif
61 default:
62 return -EINVAL;
63 }
64 }
65
66 int fat_readdir(
67 struct inode *inode,
68 struct file *filp,
69 void *dirent,
70 filldir_t filldir)
71 {
72 struct super_block *sb = inode->i_sb;
73 int ino,i,i2,last;
74 char c;
75 struct buffer_head *bh;
76 struct msdos_dir_entry *de;
77 unsigned long oldpos = filp->f_pos;
78 int is_long;
79 char longname[256];
80 unsigned char long_len = 0;
81 unsigned char alias_checksum = 0;
82
83
84 if (!inode || !S_ISDIR(inode->i_mode))
85 return -EBADF;
86
87 if (inode->i_ino == MSDOS_ROOT_INO) {
88 while (oldpos < 2) {
89 if (filldir(dirent, "..", oldpos+1, oldpos, MSDOS_ROOT_INO) < 0)
90 return 0;
91 oldpos++;
92 filp->f_pos++;
93 }
94 if (oldpos == 2)
95 filp->f_pos = 0;
96 }
97 if (filp->f_pos & (sizeof(struct msdos_dir_entry)-1))
98 return -ENOENT;
99
100 bh = NULL;
101 longname[0] = '\0';
102 is_long = 0;
103 ino = fat_get_entry(inode,&filp->f_pos,&bh,&de);
104 while (ino > -1) {
105
106
107
108
109 if (!MSDOS_SB(sb)->vfat &&
110 !MSDOS_SB(sb)->umsdos &&
111 !IS_RDONLY(inode) &&
112 (de->attr == ATTR_EXT) &&
113 !MSDOS_SB(sb)->quiet) {
114 printk("MSDOS-fs warning: vfat directory entry found on fs mounted non-vfat (device %s)\n",
115 kdevname(sb->s_dev));
116 }
117
118
119 if (MSDOS_SB(sb)->vfat && (de->name[0] == (__s8) DELETED_FLAG)) {
120 is_long = 0;
121 oldpos = filp->f_pos;
122 } else if (MSDOS_SB(sb)->vfat && de->attr == ATTR_EXT) {
123 int get_new_entry;
124 struct msdos_dir_slot *ds;
125 unsigned char page, pg_off, ascii;
126 unsigned char *uni_page;
127 unsigned char offset;
128 unsigned char id;
129 unsigned char slot;
130 unsigned char slots = 0;
131 int i;
132
133 offset = 0;
134 ds = (struct msdos_dir_slot *) de;
135 id = ds->id;
136 if (id & 0x40) {
137 slots = id & ~0x40;
138 is_long = 1;
139 alias_checksum = ds->alias_checksum;
140 }
141
142 get_new_entry = 1;
143 slot = slots;
144 while (slot > 0) {
145 PRINTK(("1. get_new_entry: %d\n", get_new_entry));
146 if (ds->attr != ATTR_EXT) {
147 is_long = 0;
148 get_new_entry = 0;
149 break;
150 }
151 if ((ds->id & ~0x40) != slot) {
152 is_long = 0;
153 break;
154 }
155 if (ds->alias_checksum != alias_checksum) {
156 is_long = 0;
157 break;
158 }
159 slot--;
160 offset = slot * 13;
161 PRINTK(("2. get_new_entry: %d\n", get_new_entry));
162 for (i = 0; i < 10; i += 2) {
163 pg_off = ds->name0_4[i];
164 page = ds->name0_4[i+1];
165 if (pg_off == 0 && page == 0) {
166 goto found_end;
167 }
168 uni_page = fat_uni2asc_pg[page];
169 ascii = uni_page[pg_off];
170 longname[offset++] = ascii ? ascii : '?';
171 }
172 for (i = 0; i < 12; i += 2) {
173 pg_off = ds->name5_10[i];
174 page = ds->name5_10[i+1];
175 if (pg_off == 0 && page == 0) {
176 goto found_end;
177 }
178 uni_page = fat_uni2asc_pg[page];
179 ascii = uni_page[pg_off];
180 longname[offset++] = ascii ? ascii : '?';
181 }
182 for (i = 0; i < 4; i += 2) {
183 pg_off = ds->name11_12[i];
184 page = ds->name11_12[i+1];
185 if (pg_off == 0 && page == 0) {
186 goto found_end;
187 }
188 uni_page = fat_uni2asc_pg[page];
189 ascii = uni_page[pg_off];
190 longname[offset++] = ascii ? ascii : '?';
191 }
192 found_end:
193 PRINTK(("3. get_new_entry: %d\n", get_new_entry));
194 if (ds->id & 0x40) {
195 longname[offset] = '\0';
196 long_len = offset;
197 }
198 if (slot > 0) {
199 ino = fat_get_entry(inode,&filp->f_pos,&bh,&de);
200 PRINTK(("4. get_new_entry: %d\n", get_new_entry));
201 if (ino == -1) {
202 is_long = 0;
203 get_new_entry = 0;
204 break;
205 }
206 ds = (struct msdos_dir_slot *) de;
207 }
208 PRINTK(("5. get_new_entry: %d\n", get_new_entry));
209 }
210 PRINTK(("Long filename: %s, get_new_entry: %d\n", longname, get_new_entry));
211 } else if (!IS_FREE(de->name) && !(de->attr & ATTR_VOLUME)) {
212 char bufname[13];
213 char *ptname = bufname;
214 int dotoffset = 0;
215
216 if (is_long) {
217 unsigned char sum;
218
219 for (sum = i = 0; i < 11; i++) {
220 sum = (((sum&1)<<7)|((sum&0xfe)>>1)) + de->name[i];
221 }
222
223 if (sum != alias_checksum) {
224 PRINTK(("Checksums don't match %d != %d\n", sum, alias_checksum));
225 is_long = 0;
226 }
227 }
228
229 if ((de->attr & ATTR_HIDDEN) && MSDOS_SB(sb)->dotsOK) {
230 bufname[0] = '.';
231 dotoffset = 1;
232 ptname = bufname+1;
233 }
234 for (i = last = 0; i < 8; i++) {
235 if (!(c = de->name[i])) break;
236 if (c >= 'A' && c <= 'Z') c += 32;
237
238 if (c == 0x05) c = 0xE5;
239 if (c != ' ')
240 last = i+1;
241 ptname[i] = c;
242 }
243 i = last;
244 ptname[i] = '.';
245 i++;
246 for (i2 = 0; i2 < 3; i2++) {
247 if (!(c = de->ext[i2])) break;
248 if (c >= 'A' && c <= 'Z') c += 32;
249 if (c != ' ')
250 last = i+1;
251 ptname[i] = c;
252 i++;
253 }
254 if ((i = last) != 0) {
255 if (!strcmp(de->name,MSDOS_DOT))
256 ino = inode->i_ino;
257 else if (!strcmp(de->name,MSDOS_DOTDOT))
258 ino = fat_parent_ino(inode,0);
259
260 if (!is_long) {
261 if (filldir(dirent, bufname, i+dotoffset, oldpos, ino) < 0) {
262 filp->f_pos = oldpos;
263 break;
264 }
265 } else {
266 if (filldir(dirent, longname, long_len, oldpos, ino) < 0) {
267 filp->f_pos = oldpos;
268 break;
269 }
270 }
271 oldpos = filp->f_pos;
272 }
273 is_long = 0;
274 } else {
275 is_long = 0;
276 oldpos = filp->f_pos;
277 }
278 ino = fat_get_entry(inode,&filp->f_pos,&bh,&de);
279 }
280 if (bh) brelse(bh);
281 return 0;
282 }