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