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