FreeBSD/Linux Kernel Cross Reference
sys/fs/fat/misc.c
1 /*
2 * linux/fs/fat/misc.c
3 *
4 * Written 1992,1993 by Werner Almesberger
5 * 22/11/2000 - Fixed fat_date_unix2dos for dates earlier than 01/01/1980
6 * and date_dos2unix for date==0 by Igor Zhbanov(bsg@uniyar.ac.ru)
7 */
8
9 #include <linux/fs.h>
10 #include <linux/msdos_fs.h>
11 #include <linux/sched.h>
12 #include <linux/kernel.h>
13 #include <linux/errno.h>
14 #include <linux/string.h>
15 #include <linux/stat.h>
16
17 #if 0
18 # define PRINTK(x) printk x
19 #else
20 # define PRINTK(x)
21 #endif
22 #define Printk(x) printk x
23
24 /* Well-known binary file extensions - of course there are many more */
25
26 static char ascii_extensions[] =
27 "TXT" "ME " "HTM" "1ST" "LOG" " " /* text files */
28 "C " "H " "CPP" "LIS" "PAS" "FOR" /* programming languages */
29 "F " "MAK" "INC" "BAS" /* programming languages */
30 "BAT" "SH " /* program code :) */
31 "INI" /* config files */
32 "PBM" "PGM" "DXF" /* graphics */
33 "TEX"; /* TeX */
34
35
36 /*
37 * fat_fs_panic reports a severe file system problem and sets the file system
38 * read-only. The file system can be made writable again by remounting it.
39 */
40
41 void fat_fs_panic(struct super_block *s,const char *msg)
42 {
43 int not_ro;
44
45 not_ro = !(s->s_flags & MS_RDONLY);
46 if (not_ro) s->s_flags |= MS_RDONLY;
47 printk("Filesystem panic (dev %s).\n %s\n", kdevname(s->s_dev), msg);
48 if (not_ro)
49 printk(" File system has been set read-only\n");
50 }
51
52
53 /*
54 * fat_is_binary selects optional text conversion based on the conversion mode
55 * and the extension part of the file name.
56 */
57
58 int fat_is_binary(char conversion,char *extension)
59 {
60 char *walk;
61
62 switch (conversion) {
63 case 'b':
64 return 1;
65 case 't':
66 return 0;
67 case 'a':
68 for (walk = ascii_extensions; *walk; walk += 3)
69 if (!strncmp(extension,walk,3)) return 0;
70 return 1; /* default binary conversion */
71 default:
72 printk("Invalid conversion mode - defaulting to "
73 "binary.\n");
74 return 1;
75 }
76 }
77
78 void lock_fat(struct super_block *sb)
79 {
80 down(&(MSDOS_SB(sb)->fat_lock));
81 }
82
83 void unlock_fat(struct super_block *sb)
84 {
85 up(&(MSDOS_SB(sb)->fat_lock));
86 }
87
88 /* Flushes the number of free clusters on FAT32 */
89 /* XXX: Need to write one per FSINFO block. Currently only writes 1 */
90 void fat_clusters_flush(struct super_block *sb)
91 {
92 struct buffer_head *bh;
93 struct fat_boot_fsinfo *fsinfo;
94
95 bh = fat_bread(sb, MSDOS_SB(sb)->fsinfo_sector);
96 if (bh == NULL) {
97 printk("FAT bread failed in fat_clusters_flush\n");
98 return;
99 }
100
101 fsinfo = (struct fat_boot_fsinfo *)bh->b_data;
102 /* Sanity check */
103 if (!IS_FSINFO(fsinfo)) {
104 printk("FAT: Did not find valid FSINFO signature.\n"
105 "Found signature1 0x%x signature2 0x%x sector=%ld.\n",
106 CF_LE_L(fsinfo->signature1), CF_LE_L(fsinfo->signature2),
107 MSDOS_SB(sb)->fsinfo_sector);
108 return;
109 }
110 fsinfo->free_clusters = CF_LE_L(MSDOS_SB(sb)->free_clusters);
111 fsinfo->next_cluster = CF_LE_L(MSDOS_SB(sb)->prev_free);
112 fat_mark_buffer_dirty(sb, bh);
113 fat_brelse(sb, bh);
114 }
115
116 /*
117 * fat_add_cluster tries to allocate a new cluster and adds it to the
118 * file represented by inode.
119 */
120 int fat_add_cluster(struct inode *inode)
121 {
122 struct super_block *sb = inode->i_sb;
123 int count, nr, limit, last, curr, file_cluster;
124 int cluster_size = MSDOS_SB(sb)->cluster_size;
125 int res = -ENOSPC;
126
127 lock_fat(sb);
128
129 if (MSDOS_SB(sb)->free_clusters == 0) {
130 unlock_fat(sb);
131 return res;
132 }
133 limit = MSDOS_SB(sb)->clusters;
134 nr = limit; /* to keep GCC happy */
135 for (count = 0; count < limit; count++) {
136 nr = ((count + MSDOS_SB(sb)->prev_free) % limit) + 2;
137 if (fat_access(sb, nr, -1) == 0)
138 break;
139 }
140 if (count >= limit) {
141 MSDOS_SB(sb)->free_clusters = 0;
142 unlock_fat(sb);
143 return res;
144 }
145
146 MSDOS_SB(sb)->prev_free = (count + MSDOS_SB(sb)->prev_free + 1) % limit;
147 fat_access(sb, nr, EOF_FAT(sb));
148 if (MSDOS_SB(sb)->free_clusters != -1)
149 MSDOS_SB(sb)->free_clusters--;
150 if (MSDOS_SB(sb)->fat_bits == 32)
151 fat_clusters_flush(sb);
152
153 unlock_fat(sb);
154
155 /* We must locate the last cluster of the file to add this
156 new one (nr) to the end of the link list (the FAT).
157
158 Here file_cluster will be the number of the last cluster of the
159 file (before we add nr).
160
161 last is the corresponding cluster number on the disk. We will
162 use last to plug the nr cluster. We will use file_cluster to
163 update the cache.
164 */
165 last = file_cluster = 0;
166 if ((curr = MSDOS_I(inode)->i_start) != 0) {
167 fat_cache_lookup(inode, INT_MAX, &last, &curr);
168 file_cluster = last;
169 while (curr && curr != -1){
170 file_cluster++;
171 if (!(curr = fat_access(sb, last = curr,-1))) {
172 fat_fs_panic(sb, "File without EOF");
173 return res;
174 }
175 }
176 }
177 if (last) {
178 fat_access(sb, last, nr);
179 fat_cache_add(inode, file_cluster, nr);
180 } else {
181 MSDOS_I(inode)->i_start = nr;
182 MSDOS_I(inode)->i_logstart = nr;
183 mark_inode_dirty(inode);
184 }
185 if (file_cluster
186 != inode->i_blocks / cluster_size / (sb->s_blocksize / 512)) {
187 printk ("file_cluster badly computed!!! %d <> %ld\n",
188 file_cluster,
189 inode->i_blocks / cluster_size / (sb->s_blocksize / 512));
190 fat_cache_inval_inode(inode);
191 }
192 inode->i_blocks += (1 << MSDOS_SB(sb)->cluster_bits) / 512;
193
194 return nr;
195 }
196
197 struct buffer_head *fat_extend_dir(struct inode *inode)
198 {
199 struct super_block *sb = inode->i_sb;
200 int nr, sector, last_sector;
201 struct buffer_head *bh, *res = NULL;
202 int cluster_size = MSDOS_SB(sb)->cluster_size;
203
204 if (MSDOS_SB(sb)->fat_bits != 32) {
205 if (inode->i_ino == MSDOS_ROOT_INO)
206 return res;
207 }
208
209 nr = fat_add_cluster(inode);
210 if (nr < 0)
211 return res;
212
213 sector = MSDOS_SB(sb)->data_start + (nr - 2) * cluster_size;
214 last_sector = sector + cluster_size;
215 if (MSDOS_SB(sb)->cvf_format && MSDOS_SB(sb)->cvf_format->zero_out_cluster)
216 MSDOS_SB(sb)->cvf_format->zero_out_cluster(inode, nr);
217 else {
218 for ( ; sector < last_sector; sector++) {
219 #ifdef DEBUG
220 printk("zeroing sector %d\n", sector);
221 #endif
222 if (!(bh = fat_getblk(sb, sector)))
223 printk("getblk failed\n");
224 else {
225 memset(bh->b_data, 0, sb->s_blocksize);
226 fat_set_uptodate(sb, bh, 1);
227 fat_mark_buffer_dirty(sb, bh);
228 if (!res)
229 res = bh;
230 else
231 fat_brelse(sb, bh);
232 }
233 }
234 }
235 if (inode->i_size & (sb->s_blocksize - 1)) {
236 fat_fs_panic(sb, "Odd directory size");
237 inode->i_size = (inode->i_size + sb->s_blocksize)
238 & ~(sb->s_blocksize - 1);
239 }
240 inode->i_size += 1 << MSDOS_SB(sb)->cluster_bits;
241 MSDOS_I(inode)->mmu_private += 1 << MSDOS_SB(sb)->cluster_bits;
242 mark_inode_dirty(inode);
243
244 return res;
245 }
246
247 /* Linear day numbers of the respective 1sts in non-leap years. */
248
249 static int day_n[] = { 0,31,59,90,120,151,181,212,243,273,304,334,0,0,0,0 };
250 /* JanFebMarApr May Jun Jul Aug Sep Oct Nov Dec */
251
252
253 extern struct timezone sys_tz;
254
255
256 /* Convert a MS-DOS time/date pair to a UNIX date (seconds since 1 1 70). */
257
258 int date_dos2unix(unsigned short time,unsigned short date)
259 {
260 int month,year,secs;
261
262 /* first subtract and mask after that... Otherwise, if
263 date == 0, bad things happen */
264 month = ((date >> 5) - 1) & 15;
265 year = date >> 9;
266 secs = (time & 31)*2+60*((time >> 5) & 63)+(time >> 11)*3600+86400*
267 ((date & 31)-1+day_n[month]+(year/4)+year*365-((year & 3) == 0 &&
268 month < 2 ? 1 : 0)+3653);
269 /* days since 1.1.70 plus 80's leap day */
270 secs += sys_tz.tz_minuteswest*60;
271 return secs;
272 }
273
274
275 /* Convert linear UNIX date to a MS-DOS time/date pair. */
276
277 void fat_date_unix2dos(int unix_date,unsigned short *time,
278 unsigned short *date)
279 {
280 int day,year,nl_day,month;
281
282 unix_date -= sys_tz.tz_minuteswest*60;
283
284 /* Jan 1 GMT 00:00:00 1980. But what about another time zone? */
285 if (unix_date < 315532800)
286 unix_date = 315532800;
287
288 *time = (unix_date % 60)/2+(((unix_date/60) % 60) << 5)+
289 (((unix_date/3600) % 24) << 11);
290 day = unix_date/86400-3652;
291 year = day/365;
292 if ((year+3)/4+365*year > day) year--;
293 day -= (year+3)/4+365*year;
294 if (day == 59 && !(year & 3)) {
295 nl_day = day;
296 month = 2;
297 }
298 else {
299 nl_day = (year & 3) || day <= 59 ? day : day-1;
300 for (month = 0; month < 12; month++)
301 if (day_n[month] > nl_day) break;
302 }
303 *date = nl_day-day_n[month-1]+1+(month << 5)+(year << 9);
304 }
305
306
307 /* Returns the inode number of the directory entry at offset pos. If bh is
308 non-NULL, it is brelse'd before. Pos is incremented. The buffer header is
309 returned in bh.
310 AV. Most often we do it item-by-item. Makes sense to optimize.
311 AV. OK, there we go: if both bh and de are non-NULL we assume that we just
312 AV. want the next entry (took one explicit de=NULL in vfat/namei.c).
313 AV. It's done in fat_get_entry() (inlined), here the slow case lives.
314 AV. Additionally, when we return -1 (i.e. reached the end of directory)
315 AV. we make bh NULL.
316 */
317
318 int fat__get_entry(struct inode *dir, loff_t *pos,struct buffer_head **bh,
319 struct msdos_dir_entry **de, int *ino)
320 {
321 struct super_block *sb = dir->i_sb;
322 struct msdos_sb_info *sbi = MSDOS_SB(sb);
323 int sector, offset;
324
325 while (1) {
326 offset = *pos;
327 PRINTK (("get_entry offset %d\n",offset));
328 if (*bh)
329 fat_brelse(sb, *bh);
330 *bh = NULL;
331 if ((sector = fat_bmap(dir,offset >> sb->s_blocksize_bits)) == -1)
332 return -1;
333 PRINTK (("get_entry sector %d %p\n",sector,*bh));
334 PRINTK (("get_entry sector apres brelse\n"));
335 if (!sector)
336 return -1; /* beyond EOF */
337 *pos += sizeof(struct msdos_dir_entry);
338 if (!(*bh = fat_bread(sb, sector))) {
339 printk("Directory sread (sector 0x%x) failed\n",sector);
340 continue;
341 }
342 PRINTK (("get_entry apres sread\n"));
343
344 offset &= sb->s_blocksize - 1;
345 *de = (struct msdos_dir_entry *) ((*bh)->b_data + offset);
346 *ino = (sector << sbi->dir_per_block_bits) + (offset >> MSDOS_DIR_BITS);
347
348 return 0;
349 }
350 }
351
352
353 /*
354 * Now an ugly part: this set of directory scan routines works on clusters
355 * rather than on inodes and sectors. They are necessary to locate the '..'
356 * directory "inode". raw_scan_sector operates in four modes:
357 *
358 * name number ino action
359 * -------- -------- -------- -------------------------------------------------
360 * non-NULL - X Find an entry with that name
361 * NULL non-NULL non-NULL Find an entry whose data starts at *number
362 * NULL non-NULL NULL Count subdirectories in *number. (*)
363 * NULL NULL non-NULL Find an empty entry
364 *
365 * (*) The return code should be ignored. It DOES NOT indicate success or
366 * failure. *number has to be initialized to zero.
367 *
368 * - = not used, X = a value is returned unless NULL
369 *
370 * If res_bh is non-NULL, the buffer is not deallocated but returned to the
371 * caller on success. res_de is set accordingly.
372 *
373 * If cont is non-zero, raw_found continues with the entry after the one
374 * res_bh/res_de point to.
375 */
376
377
378 #define RSS_NAME /* search for name */ \
379 done = !strncmp(data[entry].name,name,MSDOS_NAME) && \
380 !(data[entry].attr & ATTR_VOLUME);
381
382 #define RSS_START /* search for start cluster */ \
383 done = !IS_FREE(data[entry].name) \
384 && ( \
385 ( \
386 (MSDOS_SB(sb)->fat_bits != 32) ? 0 : (CF_LE_W(data[entry].starthi) << 16) \
387 ) \
388 | CF_LE_W(data[entry].start) \
389 ) == *number;
390
391 #define RSS_FREE /* search for free entry */ \
392 { \
393 done = IS_FREE(data[entry].name); \
394 }
395
396 #define RSS_COUNT /* count subdirectories */ \
397 { \
398 done = 0; \
399 if (!IS_FREE(data[entry].name) && (data[entry].attr & ATTR_DIR)) \
400 (*number)++; \
401 }
402
403 static int raw_scan_sector(struct super_block *sb,int sector,const char *name,
404 int *number,int *ino,struct buffer_head **res_bh,
405 struct msdos_dir_entry **res_de)
406 {
407 struct buffer_head *bh;
408 struct msdos_dir_entry *data;
409 int entry,start,done;
410
411 if (!(bh = fat_bread(sb,sector)))
412 return -EIO;
413 data = (struct msdos_dir_entry *) bh->b_data;
414 for (entry = 0; entry < MSDOS_SB(sb)->dir_per_block; entry++) {
415 /* RSS_COUNT: if (data[entry].name == name) done=true else done=false. */
416 if (name) {
417 RSS_NAME
418 } else {
419 if (!ino) RSS_COUNT
420 else {
421 if (number) RSS_START
422 else RSS_FREE
423 }
424 }
425 if (done) {
426 if (ino)
427 *ino = sector * MSDOS_SB(sb)->dir_per_block + entry;
428 start = CF_LE_W(data[entry].start);
429 if (MSDOS_SB(sb)->fat_bits == 32) {
430 start |= (CF_LE_W(data[entry].starthi) << 16);
431 }
432 if (!res_bh)
433 fat_brelse(sb, bh);
434 else {
435 *res_bh = bh;
436 *res_de = &data[entry];
437 }
438 return start;
439 }
440 }
441 fat_brelse(sb, bh);
442 return -ENOENT;
443 }
444
445
446 /*
447 * raw_scan_root performs raw_scan_sector on the root directory until the
448 * requested entry is found or the end of the directory is reached.
449 */
450
451 static int raw_scan_root(struct super_block *sb,const char *name,int *number,int *ino,
452 struct buffer_head **res_bh,struct msdos_dir_entry **res_de)
453 {
454 int count,cluster;
455
456 for (count = 0;
457 count < MSDOS_SB(sb)->dir_entries / MSDOS_SB(sb)->dir_per_block;
458 count++) {
459 if ((cluster = raw_scan_sector(sb,MSDOS_SB(sb)->dir_start+count,
460 name,number,ino,res_bh,res_de)) >= 0)
461 return cluster;
462 }
463 return -ENOENT;
464 }
465
466
467 /*
468 * raw_scan_nonroot performs raw_scan_sector on a non-root directory until the
469 * requested entry is found or the end of the directory is reached.
470 */
471
472 static int raw_scan_nonroot(struct super_block *sb,int start,const char *name,
473 int *number,int *ino,struct buffer_head **res_bh,struct msdos_dir_entry
474 **res_de)
475 {
476 int count,cluster;
477
478 #ifdef DEBUG
479 printk("raw_scan_nonroot: start=%d\n",start);
480 #endif
481 do {
482 for (count = 0; count < MSDOS_SB(sb)->cluster_size; count++) {
483 if ((cluster = raw_scan_sector(sb,(start-2)*
484 MSDOS_SB(sb)->cluster_size+MSDOS_SB(sb)->data_start+
485 count,name,number,ino,res_bh,res_de)) >= 0)
486 return cluster;
487 }
488 if (!(start = fat_access(sb,start,-1))) {
489 fat_fs_panic(sb,"FAT error");
490 break;
491 }
492 #ifdef DEBUG
493 printk("next start: %d\n",start);
494 #endif
495 }
496 while (start != -1);
497 return -ENOENT;
498 }
499
500
501 /*
502 * raw_scan performs raw_scan_sector on any sector.
503 *
504 * NOTE: raw_scan must not be used on a directory that is is the process of
505 * being created.
506 */
507
508 static int raw_scan(struct super_block *sb, int start, const char *name,
509 int *number, int *ino, struct buffer_head **res_bh,
510 struct msdos_dir_entry **res_de)
511 {
512 if (start)
513 return raw_scan_nonroot(sb,start,name,number,ino,res_bh,res_de);
514 else
515 return raw_scan_root(sb,name,number,ino,res_bh,res_de);
516 }
517
518 /*
519 * fat_subdirs counts the number of sub-directories of dir. It can be run
520 * on directories being created.
521 */
522 int fat_subdirs(struct inode *dir)
523 {
524 int count;
525
526 count = 0;
527 if ((dir->i_ino == MSDOS_ROOT_INO) &&
528 (MSDOS_SB(dir->i_sb)->fat_bits != 32)) {
529 (void) raw_scan_root(dir->i_sb,NULL,&count,NULL,NULL,NULL);
530 } else {
531 if ((dir->i_ino != MSDOS_ROOT_INO) &&
532 !MSDOS_I(dir)->i_start) return 0; /* in mkdir */
533 else (void) raw_scan_nonroot(dir->i_sb,MSDOS_I(dir)->i_start,
534 NULL,&count,NULL,NULL,NULL);
535 }
536 return count;
537 }
538
539
540 /*
541 * Scans a directory for a given file (name points to its formatted name) or
542 * for an empty directory slot (name is NULL). Returns an error code or zero.
543 */
544
545 int fat_scan(struct inode *dir,const char *name,struct buffer_head **res_bh,
546 struct msdos_dir_entry **res_de,int *ino)
547 {
548 int res;
549
550 res = raw_scan(dir->i_sb,MSDOS_I(dir)->i_start,
551 name, NULL, ino, res_bh, res_de);
552 return res<0 ? res : 0;
553 }
Cache object: 25b5dfd15bfa5cfcea124745ca9e81ac
|