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