This source file includes following definitions.
- fat_fs_panic
- is_binary
- fat_lock_creation
- fat_unlock_creation
- lock_fat
- unlock_fat
- fat_add_cluster
- date_dos2unix
- fat_date_unix2dos
- fat_get_entry
- raw_scan_sector
- raw_scan_root
- raw_scan_nonroot
- raw_scan
- fat_parent_ino
- fat_subdirs
- fat_scan
1
2
3
4
5
6
7 #include <linux/fs.h>
8 #include <linux/msdos_fs.h>
9 #include <linux/sched.h>
10 #include <linux/kernel.h>
11 #include <linux/errno.h>
12 #include <linux/string.h>
13 #include <linux/stat.h>
14
15 #include "msbuffer.h"
16
17 #define PRINTK(x)
18 #define Printk(x) printk x
19
20
21
22 static char bin_extensions[] =
23 "EXE" "COM" "BIN" "APP" "SYS" "DRV" "OVL" "OVR" "OBJ" "LIB" "DLL" "PIF"
24 "ARC" "ZIP" "LHA" "LZH" "ZOO" "TAR" "Z " "ARJ"
25 "TZ " "TAZ" "TZP" "TPZ"
26 "GZ " "TGZ" "DEB"
27 "GIF" "BMP" "TIF" "GL " "JPG" "PCX"
28 "TFM" "VF " "GF " "PK " "PXL" "DVI";
29
30
31
32
33
34
35
36 void fat_fs_panic(struct super_block *s,const char *msg)
37 {
38 int not_ro;
39
40 not_ro = !(s->s_flags & MS_RDONLY);
41 if (not_ro) s->s_flags |= MS_RDONLY;
42 printk("Filesystem panic (dev %s, ", kdevname(s->s_dev));
43 printk("mounted on %s:%ld)\n %s\n",
44 kdevname(s->s_covered->i_dev), s->s_covered->i_ino, msg);
45 if (not_ro)
46 printk(" File system has been set read-only\n");
47 }
48
49
50
51
52
53
54
55 int is_binary(char conversion,char *extension)
56 {
57 char *walk;
58
59 switch (conversion) {
60 case 'b':
61 return 1;
62 case 't':
63 return 0;
64 case 'a':
65 for (walk = bin_extensions; *walk; walk += 3)
66 if (!strncmp(extension,walk,3)) return 1;
67 return 0;
68 default:
69 printk("Invalid conversion mode - defaulting to "
70 "binary.\n");
71 return 1;
72 }
73 }
74
75
76
77
78
79 static struct wait_queue *creation_wait = NULL;
80 static creation_lock = 0;
81
82
83 void fat_lock_creation(void)
84 {
85 while (creation_lock) sleep_on(&creation_wait);
86 creation_lock = 1;
87 }
88
89
90 void fat_unlock_creation(void)
91 {
92 creation_lock = 0;
93 wake_up(&creation_wait);
94 }
95
96
97 void lock_fat(struct super_block *sb)
98 {
99 while (MSDOS_SB(sb)->fat_lock) sleep_on(&MSDOS_SB(sb)->fat_wait);
100 MSDOS_SB(sb)->fat_lock = 1;
101 }
102
103
104 void unlock_fat(struct super_block *sb)
105 {
106 MSDOS_SB(sb)->fat_lock = 0;
107 wake_up(&MSDOS_SB(sb)->fat_wait);
108 }
109
110
111
112
113
114
115
116 int fat_add_cluster(struct inode *inode)
117 {
118 struct super_block *sb = inode->i_sb;
119 int count,nr,limit,last,curr,sector,last_sector,file_cluster;
120 struct buffer_head *bh;
121 int cluster_size = MSDOS_SB(inode->i_sb)->cluster_size;
122
123 if (inode->i_ino == MSDOS_ROOT_INO) return -ENOSPC;
124 if (!MSDOS_SB(inode->i_sb)->free_clusters) return -ENOSPC;
125 lock_fat(inode->i_sb);
126 limit = MSDOS_SB(inode->i_sb)->clusters;
127 nr = limit;
128 for (count = 0; count < limit; count++) {
129 nr = ((count+MSDOS_SB(inode->i_sb)->prev_free) % limit)+2;
130 if (fat_access(inode->i_sb,nr,-1) == 0) break;
131 }
132 PRINTK (("cnt = %d --",count));
133 #ifdef DEBUG
134 printk("free cluster: %d\n",nr);
135 #endif
136 MSDOS_SB(inode->i_sb)->prev_free = (count+MSDOS_SB(inode->i_sb)->
137 prev_free+1) % limit;
138 if (count >= limit) {
139 MSDOS_SB(inode->i_sb)->free_clusters = 0;
140 unlock_fat(inode->i_sb);
141 return -ENOSPC;
142 }
143 fat_access(inode->i_sb,nr,MSDOS_SB(inode->i_sb)->fat_bits == 12 ?
144 0xff8 : 0xfff8);
145 if (MSDOS_SB(inode->i_sb)->free_clusters != -1)
146 MSDOS_SB(inode->i_sb)->free_clusters--;
147 unlock_fat(inode->i_sb);
148 #ifdef DEBUG
149 printk("set to %x\n",fat_access(inode->i_sb,nr,-1));
150 #endif
151 last = 0;
152
153
154
155
156
157
158
159
160
161
162 file_cluster = 0;
163 if ((curr = MSDOS_I(inode)->i_start) != 0) {
164 cache_lookup(inode,INT_MAX,&last,&curr);
165 file_cluster = last;
166 while (curr && curr != -1){
167 PRINTK (("."));
168 file_cluster++;
169 if (!(curr = fat_access(inode->i_sb,
170 last = curr,-1))) {
171 fat_fs_panic(inode->i_sb,"File without EOF");
172 return -ENOSPC;
173 }
174 }
175 PRINTK ((" -- "));
176 }
177 #ifdef DEBUG
178 printk("last = %d\n",last);
179 #endif
180 if (last) fat_access(inode->i_sb,last,nr);
181 else {
182 MSDOS_I(inode)->i_start = nr;
183 inode->i_dirt = 1;
184 }
185 #ifdef DEBUG
186 if (last) printk("next set to %d\n",fat_access(inode->i_sb,last,-1));
187 #endif
188 sector = MSDOS_SB(inode->i_sb)->data_start+(nr-2)*cluster_size;
189 last_sector = sector + cluster_size;
190 for ( ; sector < last_sector; sector++) {
191 #ifdef DEBUG
192 printk("zeroing sector %d\n",sector);
193 #endif
194 if (!(bh = getblk(inode->i_dev,sector,SECTOR_SIZE)))
195 printk("getblk failed\n");
196 else {
197 memset(bh->b_data,0,SECTOR_SIZE);
198 fat_set_uptodate(sb,bh,1);
199 mark_buffer_dirty(bh, 1);
200 brelse(bh);
201 }
202 }
203 if (file_cluster != inode->i_blocks/cluster_size){
204 printk ("file_cluster badly computed!!! %d <> %ld\n"
205 ,file_cluster,inode->i_blocks/cluster_size);
206 }else{
207 cache_add(inode,file_cluster,nr);
208 }
209 inode->i_blocks += cluster_size;
210 if (S_ISDIR(inode->i_mode)) {
211 if (inode->i_size & (SECTOR_SIZE-1)) {
212 fat_fs_panic(inode->i_sb,"Odd directory size");
213 inode->i_size = (inode->i_size+SECTOR_SIZE) &
214 ~(SECTOR_SIZE-1);
215 }
216 inode->i_size += SECTOR_SIZE*cluster_size;
217 #ifdef DEBUG
218 printk("size is %d now (%x)\n",inode->i_size,inode);
219 #endif
220 inode->i_dirt = 1;
221 }
222 return 0;
223 }
224
225
226
227
228 static int day_n[] = { 0,31,59,90,120,151,181,212,243,273,304,334,0,0,0,0 };
229
230
231
232 extern struct timezone sys_tz;
233
234
235
236
237 int date_dos2unix(unsigned short time,unsigned short date)
238 {
239 int month,year,secs;
240
241 month = ((date >> 5) & 15)-1;
242 year = date >> 9;
243 secs = (time & 31)*2+60*((time >> 5) & 63)+(time >> 11)*3600+86400*
244 ((date & 31)-1+day_n[month]+(year/4)+year*365-((year & 3) == 0 &&
245 month < 2 ? 1 : 0)+3653);
246
247 secs += sys_tz.tz_minuteswest*60;
248 return secs;
249 }
250
251
252
253
254 void fat_date_unix2dos(int unix_date,unsigned short *time,
255 unsigned short *date)
256 {
257 int day,year,nl_day,month;
258
259 unix_date -= sys_tz.tz_minuteswest*60;
260 *time = (unix_date % 60)/2+(((unix_date/60) % 60) << 5)+
261 (((unix_date/3600) % 24) << 11);
262 day = unix_date/86400-3652;
263 year = day/365;
264 if ((year+3)/4+365*year > day) year--;
265 day -= (year+3)/4+365*year;
266 if (day == 59 && !(year & 3)) {
267 nl_day = day;
268 month = 2;
269 }
270 else {
271 nl_day = (year & 3) || day <= 59 ? day : day-1;
272 for (month = 0; month < 12; month++)
273 if (day_n[month] > nl_day) break;
274 }
275 *date = nl_day-day_n[month-1]+1+(month << 5)+(year << 9);
276 }
277
278
279
280
281
282
283 int fat_get_entry(struct inode *dir, loff_t *pos,struct buffer_head **bh,
284 struct msdos_dir_entry **de)
285 {
286 struct super_block *sb = dir->i_sb;
287 int sector,offset;
288
289 while (1) {
290 offset = *pos;
291 PRINTK (("get_entry offset %d\n",offset));
292 if ((sector = fat_smap(dir,offset >> SECTOR_BITS)) == -1)
293 return -1;
294 PRINTK (("get_entry sector %d %p\n",sector,*bh));
295 if (!sector)
296 return -1;
297 *pos += sizeof(struct msdos_dir_entry);
298 if (*bh)
299 brelse(*bh);
300 PRINTK (("get_entry sector apres brelse\n"));
301 if (!(*bh = bread(dir->i_dev,sector,SECTOR_SIZE))) {
302 printk("Directory sread (sector %d) failed\n",sector);
303 continue;
304 }
305 PRINTK (("get_entry apres sread\n"));
306 *de = (struct msdos_dir_entry *) ((*bh)->b_data+(offset &
307 (SECTOR_SIZE-1)));
308 return (sector << MSDOS_DPS_BITS)+((offset & (SECTOR_SIZE-1)) >>
309 MSDOS_DIR_BITS);
310 }
311 }
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339 #define RSS_NAME \
340 done = !strncmp(data[entry].name,name,MSDOS_NAME) && \
341 !(data[entry].attr & ATTR_VOLUME);
342
343 #define RSS_START \
344 done = !IS_FREE(data[entry].name) && CF_LE_W(data[entry].start) == *number;
345
346 #define RSS_FREE \
347 { \
348 done = IS_FREE(data[entry].name); \
349 if (done) { \
350 inode = iget(sb,sector*MSDOS_DPS+entry); \
351 if (inode) { \
352 \
353 done = !MSDOS_I(inode)->i_busy; \
354 iput(inode); \
355 } \
356 } \
357 }
358
359 #define RSS_COUNT \
360 { \
361 done = 0; \
362 if (!IS_FREE(data[entry].name) && (data[entry].attr & ATTR_DIR)) \
363 (*number)++; \
364 }
365
366 static int raw_scan_sector(struct super_block *sb,int sector,const char *name,
367 int *number,int *ino,struct buffer_head **res_bh,
368 struct msdos_dir_entry **res_de,char scantype)
369 {
370 struct buffer_head *bh;
371 struct msdos_dir_entry *data;
372 struct inode *inode;
373 int entry,start,done;
374
375 if (!(bh = bread(sb->s_dev,sector,SECTOR_SIZE))) return -EIO;
376 data = (struct msdos_dir_entry *) bh->b_data;
377 for (entry = 0; entry < MSDOS_DPS; entry++) {
378
379 if (name) {
380 RSS_NAME
381 if (done && scantype) {
382 done = (data[entry].attr & ATTR_HIDDEN)
383 ? (scantype==SCAN_HID)
384 : (scantype==SCAN_NOTHID);
385 }
386 } else {
387 if (!ino) RSS_COUNT
388 else {
389 if (number) RSS_START
390 else RSS_FREE
391 }
392 }
393 if (done) {
394 if (ino) *ino = sector*MSDOS_DPS+entry;
395 start = CF_LE_W(data[entry].start);
396 if (!res_bh) brelse(bh);
397 else {
398 *res_bh = bh;
399 *res_de = &data[entry];
400 }
401 return start;
402 }
403 }
404 brelse(bh);
405 return -ENOENT;
406 }
407
408
409
410
411
412
413
414 static int raw_scan_root(struct super_block *sb,const char *name,int *number,int *ino,
415 struct buffer_head **res_bh,struct msdos_dir_entry **res_de,char scantype)
416 {
417 int count,cluster;
418
419 for (count = 0; count < MSDOS_SB(sb)->dir_entries/MSDOS_DPS; count++) {
420 if ((cluster = raw_scan_sector(sb,MSDOS_SB(sb)->dir_start+count,
421 name,number,ino,res_bh,res_de,scantype)) >= 0) return cluster;
422 }
423 return -ENOENT;
424 }
425
426
427
428
429
430
431
432 static int raw_scan_nonroot(struct super_block *sb,int start,const char *name,
433 int *number,int *ino,struct buffer_head **res_bh,struct msdos_dir_entry
434 **res_de,char scantype)
435 {
436 int count,cluster;
437
438 #ifdef DEBUG
439 printk("raw_scan_nonroot: start=%d\n",start);
440 #endif
441 do {
442 for (count = 0; count < MSDOS_SB(sb)->cluster_size; count++) {
443 if ((cluster = raw_scan_sector(sb,(start-2)*
444 MSDOS_SB(sb)->cluster_size+MSDOS_SB(sb)->data_start+
445 count,name,number,ino,res_bh,res_de,scantype)) >= 0)
446 return cluster;
447 }
448 if (!(start = fat_access(sb,start,-1))) {
449 fat_fs_panic(sb,"FAT error");
450 break;
451 }
452 #ifdef DEBUG
453 printk("next start: %d\n",start);
454 #endif
455 }
456 while (start != -1);
457 return -ENOENT;
458 }
459
460
461
462
463
464
465
466
467
468 static int raw_scan(struct super_block *sb, int start, const char *name,
469 int *number, int *ino, struct buffer_head **res_bh,
470 struct msdos_dir_entry **res_de, char scantype)
471 {
472 if (start) return raw_scan_nonroot
473 (sb,start,name,number,ino,res_bh,res_de,scantype);
474 else return raw_scan_root
475 (sb,name,number,ino,res_bh,res_de,scantype);
476 }
477
478
479
480
481
482
483
484
485 int fat_parent_ino(struct inode *dir,int locked)
486 {
487 static int zero = 0;
488 int error,curr,prev,nr;
489
490 if (!S_ISDIR(dir->i_mode)) panic("Non-directory fed to m_p_i");
491 if (dir->i_ino == MSDOS_ROOT_INO) return dir->i_ino;
492 if (!locked) fat_lock_creation();
493 if ((curr = raw_scan(dir->i_sb,MSDOS_I(dir)->i_start,MSDOS_DOTDOT,
494 &zero,NULL,NULL,NULL,SCAN_ANY)) < 0) {
495 if (!locked) fat_unlock_creation();
496 return curr;
497 }
498 if (!curr) nr = MSDOS_ROOT_INO;
499 else {
500 if ((prev = raw_scan(dir->i_sb,curr,MSDOS_DOTDOT,&zero,NULL,
501 NULL,NULL,SCAN_ANY)) < 0) {
502 if (!locked) fat_unlock_creation();
503 return prev;
504 }
505 if ((error = raw_scan(dir->i_sb,prev,NULL,&curr,&nr,NULL,
506 NULL,SCAN_ANY)) < 0) {
507 if (!locked) fat_unlock_creation();
508 return error;
509 }
510 }
511 if (!locked) fat_unlock_creation();
512 return nr;
513 }
514
515
516
517
518
519
520
521 int fat_subdirs(struct inode *dir)
522 {
523 int count;
524
525 count = 0;
526 if (dir->i_ino == MSDOS_ROOT_INO)
527 (void) raw_scan_root(dir->i_sb,NULL,&count,NULL,NULL,NULL,SCAN_ANY);
528 else {
529 if (!MSDOS_I(dir)->i_start) return 0;
530 else (void) raw_scan_nonroot(dir->i_sb,MSDOS_I(dir)->i_start,
531 NULL,&count,NULL,NULL,NULL,SCAN_ANY);
532 }
533 return count;
534 }
535
536
537
538
539
540
541
542 int fat_scan(struct inode *dir,const char *name,struct buffer_head **res_bh,
543 struct msdos_dir_entry **res_de,int *ino, char scantype)
544 {
545 int res;
546
547 res = (name)
548 ? raw_scan(dir->i_sb,MSDOS_I(dir)->i_start,
549 name, NULL, ino, res_bh, res_de, scantype)
550 : raw_scan(dir->i_sb,MSDOS_I(dir)->i_start,
551 NULL, NULL, ino, res_bh, res_de, scantype);
552 return res<0 ? res : 0;
553 }