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