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