Import 2.1.81
[davej-history.git] / fs / fat / misc.c
blobb398a0bbd1e8ac92866caaabb92cc4642d4c9f0f
1 /*
2 * linux/fs/fat/misc.c
4 * Written 1992,1993 by Werner Almesberger
5 */
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>
15 #include "msbuffer.h"
17 #if 0
18 # define PRINTK(x) printk x
19 #else
20 # define PRINTK(x)
21 #endif
22 #define Printk(x) printk x
24 /* Well-known binary file extensions - of course there are many more */
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 */
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.
41 void fat_fs_panic(struct super_block *s,const char *msg)
43 int not_ro;
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");
54 * is_binary selects optional text conversion based on the conversion mode and
55 * the extension part of the file name.
58 int is_binary(char conversion,char *extension)
60 char *walk;
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;
79 /* File creation lock. This is system-wide to avoid deadlocks in rename. */
80 /* (rename might deadlock before detecting cross-FS moves.) */
82 static struct wait_queue *creation_wait = NULL;
83 static int creation_lock = 0;
86 void fat_lock_creation(void)
88 while (creation_lock) sleep_on(&creation_wait);
89 creation_lock = 1;
93 void fat_unlock_creation(void)
95 creation_lock = 0;
96 wake_up(&creation_wait);
100 void lock_fat(struct super_block *sb)
102 while (MSDOS_SB(sb)->fat_lock) sleep_on(&MSDOS_SB(sb)->fat_wait);
103 MSDOS_SB(sb)->fat_lock = 1;
107 void unlock_fat(struct super_block *sb)
109 MSDOS_SB(sb)->fat_lock = 0;
110 wake_up(&MSDOS_SB(sb)->fat_wait);
113 /* Flushes the number of free clusters on FAT32 */
114 /* XXX: Need to write one per FSINFO block. Currently only writes 1 */
115 void fat_clusters_flush(struct super_block *sb)
117 int offset;
118 struct buffer_head *bh;
119 struct fat_boot_fsinfo *fsinfo;
121 /* The fat32 boot fs info is at offset 0x3e0 by observation */
122 offset = MSDOS_SB(sb)->fsinfo_offset;
123 bh = fat_bread(sb, (offset >> SECTOR_BITS));
124 if (bh == NULL) {
125 printk("FAT bread failed in fat_clusters_flush\n");
126 return;
128 fsinfo = (struct fat_boot_fsinfo *)
129 &bh->b_data[offset & (SECTOR_SIZE-1)];
131 /* Sanity check */
132 if (CF_LE_L(fsinfo->signature) != 0x61417272) {
133 printk("fat_clusters_flush: Did not find valid FSINFO signature. Found 0x%x. offset=0x%x\n", CF_LE_L(fsinfo->signature), offset);
134 fat_brelse(sb, bh);
135 return;
137 fsinfo->free_clusters = CF_LE_L(MSDOS_SB(sb)->free_clusters);
138 fat_mark_buffer_dirty(sb, bh, 1);
139 fat_brelse(sb, bh);
143 * fat_add_cluster tries to allocate a new cluster and adds it to the file
144 * represented by inode. The cluster is zero-initialized.
147 int fat_add_cluster(struct inode *inode)
149 struct super_block *sb = inode->i_sb;
150 int count,nr,limit,last,curr,sector,last_sector,file_cluster;
151 struct buffer_head *bh;
152 int cluster_size = MSDOS_SB(sb)->cluster_size;
154 if (MSDOS_SB(sb)->fat_bits != 32) {
155 if (inode->i_ino == MSDOS_ROOT_INO) return -ENOSPC;
157 if (!MSDOS_SB(sb)->free_clusters) return -ENOSPC;
158 lock_fat(sb);
159 limit = MSDOS_SB(sb)->clusters;
160 nr = limit; /* to keep GCC happy */
161 for (count = 0; count < limit; count++) {
162 nr = ((count+MSDOS_SB(sb)->prev_free) % limit)+2;
163 if (fat_access(sb,nr,-1) == 0) break;
165 PRINTK (("cnt = %d --",count));
166 #ifdef DEBUG
167 printk("free cluster: %d\n",nr);
168 #endif
169 MSDOS_SB(sb)->prev_free = (count+MSDOS_SB(sb)->prev_free+1) % limit;
170 if (count >= limit) {
171 MSDOS_SB(sb)->free_clusters = 0;
172 unlock_fat(sb);
173 return -ENOSPC;
175 fat_access(sb,nr,EOF_FAT(sb));
176 if (MSDOS_SB(sb)->free_clusters != -1)
177 MSDOS_SB(sb)->free_clusters--;
178 if (MSDOS_SB(sb)->fat_bits == 32)
179 fat_clusters_flush(sb);
180 unlock_fat(sb);
181 #ifdef DEBUG
182 printk("set to %x\n",fat_access(sb,nr,-1));
183 #endif
184 last = 0;
185 /* We must locate the last cluster of the file to add this
186 new one (nr) to the end of the link list (the FAT).
188 Here file_cluster will be the number of the last cluster of the
189 file (before we add nr).
191 last is the corresponding cluster number on the disk. We will
192 use last to plug the nr cluster. We will use file_cluster to
193 update the cache.
195 file_cluster = 0;
196 if ((curr = MSDOS_I(inode)->i_start) != 0) {
197 fat_cache_lookup(inode,INT_MAX,&last,&curr);
198 file_cluster = last;
199 while (curr && curr != -1){
200 PRINTK (("."));
201 file_cluster++;
202 if (!(curr = fat_access(sb,
203 last = curr,-1))) {
204 fat_fs_panic(sb,"File without EOF");
205 return -ENOSPC;
208 PRINTK ((" -- "));
210 #ifdef DEBUG
211 printk("last = %d\n",last);
212 #endif
213 if (last) fat_access(sb,last,nr);
214 else {
215 MSDOS_I(inode)->i_start = nr;
216 MSDOS_I(inode)->i_logstart = nr;
217 mark_inode_dirty(inode);
219 #ifdef DEBUG
220 if (last) printk("next set to %d\n",fat_access(sb,last,-1));
221 #endif
222 sector = MSDOS_SB(sb)->data_start+(nr-2)*cluster_size;
223 last_sector = sector + cluster_size;
224 if (MSDOS_SB(sb)->cvf_format &&
225 MSDOS_SB(sb)->cvf_format->zero_out_cluster)
226 MSDOS_SB(sb)->cvf_format->zero_out_cluster(inode,nr);
227 else
228 for ( ; sector < last_sector; sector++) {
229 #ifdef DEBUG
230 printk("zeroing sector %d\n",sector);
231 #endif
232 if (!(bh = fat_getblk(sb, sector)))
233 printk("getblk failed\n");
234 else {
235 memset(bh->b_data,0,SECTOR_SIZE);
236 fat_set_uptodate(sb, bh, 1);
237 fat_mark_buffer_dirty(sb, bh, 1);
238 fat_brelse(sb, bh);
241 if (file_cluster != inode->i_blocks/cluster_size){
242 printk ("file_cluster badly computed!!! %d <> %ld\n"
243 ,file_cluster,inode->i_blocks/cluster_size);
244 }else{
245 fat_cache_add(inode,file_cluster,nr);
247 inode->i_blocks += cluster_size;
248 if (S_ISDIR(inode->i_mode)) {
249 if (inode->i_size & (SECTOR_SIZE-1)) {
250 fat_fs_panic(sb,"Odd directory size");
251 inode->i_size = (inode->i_size+SECTOR_SIZE) &
252 ~(SECTOR_SIZE-1);
254 inode->i_size += SECTOR_SIZE*cluster_size;
255 #ifdef DEBUG
256 printk("size is %d now (%x)\n",inode->i_size,inode);
257 #endif
258 mark_inode_dirty(inode);
260 return 0;
264 /* Linear day numbers of the respective 1sts in non-leap years. */
266 static int day_n[] = { 0,31,59,90,120,151,181,212,243,273,304,334,0,0,0,0 };
267 /* JanFebMarApr May Jun Jul Aug Sep Oct Nov Dec */
270 extern struct timezone sys_tz;
273 /* Convert a MS-DOS time/date pair to a UNIX date (seconds since 1 1 70). */
275 int date_dos2unix(unsigned short time,unsigned short date)
277 int month,year,secs;
279 month = ((date >> 5) & 15)-1;
280 year = date >> 9;
281 secs = (time & 31)*2+60*((time >> 5) & 63)+(time >> 11)*3600+86400*
282 ((date & 31)-1+day_n[month]+(year/4)+year*365-((year & 3) == 0 &&
283 month < 2 ? 1 : 0)+3653);
284 /* days since 1.1.70 plus 80's leap day */
285 secs += sys_tz.tz_minuteswest*60;
286 if (sys_tz.tz_dsttime) secs -= 3600;
287 return secs;
291 /* Convert linear UNIX date to a MS-DOS time/date pair. */
293 void fat_date_unix2dos(int unix_date,unsigned short *time,
294 unsigned short *date)
296 int day,year,nl_day,month;
298 unix_date -= sys_tz.tz_minuteswest*60;
299 if (sys_tz.tz_dsttime) unix_date += 3600;
301 *time = (unix_date % 60)/2+(((unix_date/60) % 60) << 5)+
302 (((unix_date/3600) % 24) << 11);
303 day = unix_date/86400-3652;
304 year = day/365;
305 if ((year+3)/4+365*year > day) year--;
306 day -= (year+3)/4+365*year;
307 if (day == 59 && !(year & 3)) {
308 nl_day = day;
309 month = 2;
311 else {
312 nl_day = (year & 3) || day <= 59 ? day : day-1;
313 for (month = 0; month < 12; month++)
314 if (day_n[month] > nl_day) break;
316 *date = nl_day-day_n[month-1]+1+(month << 5)+(year << 9);
320 /* Returns the inode number of the directory entry at offset pos. If bh is
321 non-NULL, it is brelse'd before. Pos is incremented. The buffer header is
322 returned in bh. */
324 int fat_get_entry(struct inode *dir, loff_t *pos,struct buffer_head **bh,
325 struct msdos_dir_entry **de)
327 struct super_block *sb = dir->i_sb;
328 int sector, offset;
330 while (1) {
331 offset = *pos;
332 PRINTK (("get_entry offset %d\n",offset));
333 if ((sector = fat_smap(dir,offset >> SECTOR_BITS)) == -1)
334 return -1;
335 PRINTK (("get_entry sector %d %p\n",sector,*bh));
336 if (!sector)
337 return -1; /* beyond EOF */
338 *pos += sizeof(struct msdos_dir_entry);
339 if (*bh)
340 fat_brelse(sb, *bh);
341 PRINTK (("get_entry sector apres brelse\n"));
342 if (!(*bh = fat_bread(sb, sector))) {
343 printk("Directory sread (sector 0x%x) failed\n",sector);
344 continue;
346 PRINTK (("get_entry apres sread\n"));
347 *de = (struct msdos_dir_entry *) ((*bh)->b_data+(offset &
348 (SECTOR_SIZE-1)));
349 return (sector << MSDOS_DPS_BITS)+((offset & (SECTOR_SIZE-1)) >>
350 MSDOS_DIR_BITS);
356 * Now an ugly part: this set of directory scan routines works on clusters
357 * rather than on inodes and sectors. They are necessary to locate the '..'
358 * directory "inode". raw_scan_sector operates in four modes:
360 * name number ino action
361 * -------- -------- -------- -------------------------------------------------
362 * non-NULL - X Find an entry with that name
363 * NULL non-NULL non-NULL Find an entry whose data starts at *number
364 * NULL non-NULL NULL Count subdirectories in *number. (*)
365 * NULL NULL non-NULL Find an empty entry
367 * (*) The return code should be ignored. It DOES NOT indicate success or
368 * failure. *number has to be initialized to zero.
370 * - = not used, X = a value is returned unless NULL
372 * If res_bh is non-NULL, the buffer is not deallocated but returned to the
373 * caller on success. res_de is set accordingly.
375 * If cont is non-zero, raw_found continues with the entry after the one
376 * res_bh/res_de point to.
380 #define RSS_NAME /* search for name */ \
381 done = !strncmp(data[entry].name,name,MSDOS_NAME) && \
382 !(data[entry].attr & ATTR_VOLUME);
384 #define RSS_START /* search for start cluster */ \
385 done = !IS_FREE(data[entry].name) \
386 && ( \
388 (MSDOS_SB(sb)->fat_bits != 32) ? 0 : (CF_LE_W(data[entry].starthi) << 16) \
390 | CF_LE_W(data[entry].start) \
391 ) == *number;
393 #define RSS_FREE /* search for free entry */ \
395 done = IS_FREE(data[entry].name); \
396 if (done) { \
397 inode = iget(sb,sector*MSDOS_DPS+entry); \
398 if (inode) { \
399 /* Directory slots of busy deleted files aren't available yet. */ \
400 done = !MSDOS_I(inode)->i_busy; \
401 iput(inode); \
406 #define RSS_COUNT /* count subdirectories */ \
408 done = 0; \
409 if (!IS_FREE(data[entry].name) && (data[entry].attr & ATTR_DIR)) \
410 (*number)++; \
413 static int raw_scan_sector(struct super_block *sb,int sector,const char *name,
414 int *number,int *ino,struct buffer_head **res_bh,
415 struct msdos_dir_entry **res_de,char scantype)
417 struct buffer_head *bh;
418 struct msdos_dir_entry *data;
419 struct inode *inode;
420 int entry,start,done;
422 if (!(bh = fat_bread(sb,sector)))
423 return -EIO;
424 data = (struct msdos_dir_entry *) bh->b_data;
425 for (entry = 0; entry < MSDOS_DPS; entry++) {
426 /* RSS_COUNT: if (data[entry].name == name) done=true else done=false. */
427 if (name) {
428 RSS_NAME
429 if (done && scantype) { /* scantype != SCAN_ANY */
430 done = (data[entry].attr & ATTR_HIDDEN)
431 ? (scantype==SCAN_HID)
432 : (scantype==SCAN_NOTHID);
434 } else {
435 if (!ino) RSS_COUNT
436 else {
437 if (number) RSS_START
438 else RSS_FREE
441 if (done) {
442 if (ino) *ino = sector*MSDOS_DPS+entry;
443 start = CF_LE_W(data[entry].start);
444 if (MSDOS_SB(sb)->fat_bits == 32) {
445 start |= (CF_LE_W(data[entry].starthi) << 16);
447 if (!res_bh)
448 fat_brelse(sb, bh);
449 else {
450 *res_bh = bh;
451 *res_de = &data[entry];
453 return start;
456 fat_brelse(sb, bh);
457 return -ENOENT;
462 * raw_scan_root performs raw_scan_sector on the root directory until the
463 * requested entry is found or the end of the directory is reached.
466 static int raw_scan_root(struct super_block *sb,const char *name,int *number,int *ino,
467 struct buffer_head **res_bh,struct msdos_dir_entry **res_de,char scantype)
469 int count,cluster;
471 for (count = 0; count < MSDOS_SB(sb)->dir_entries/MSDOS_DPS; count++) {
472 if ((cluster = raw_scan_sector(sb,MSDOS_SB(sb)->dir_start+count,
473 name,number,ino,res_bh,res_de,scantype)) >= 0) return cluster;
475 return -ENOENT;
480 * raw_scan_nonroot performs raw_scan_sector on a non-root directory until the
481 * requested entry is found or the end of the directory is reached.
484 static int raw_scan_nonroot(struct super_block *sb,int start,const char *name,
485 int *number,int *ino,struct buffer_head **res_bh,struct msdos_dir_entry
486 **res_de,char scantype)
488 int count,cluster;
490 #ifdef DEBUG
491 printk("raw_scan_nonroot: start=%d\n",start);
492 #endif
493 do {
494 for (count = 0; count < MSDOS_SB(sb)->cluster_size; count++) {
495 if ((cluster = raw_scan_sector(sb,(start-2)*
496 MSDOS_SB(sb)->cluster_size+MSDOS_SB(sb)->data_start+
497 count,name,number,ino,res_bh,res_de,scantype)) >= 0)
498 return cluster;
500 if (!(start = fat_access(sb,start,-1))) {
501 fat_fs_panic(sb,"FAT error");
502 break;
504 #ifdef DEBUG
505 printk("next start: %d\n",start);
506 #endif
508 while (start != -1);
509 return -ENOENT;
514 * raw_scan performs raw_scan_sector on any sector.
516 * NOTE: raw_scan must not be used on a directory that is is the process of
517 * being created.
520 static int raw_scan(struct super_block *sb, int start, const char *name,
521 int *number, int *ino, struct buffer_head **res_bh,
522 struct msdos_dir_entry **res_de, char scantype)
524 if (start) return raw_scan_nonroot
525 (sb,start,name,number,ino,res_bh,res_de,scantype);
526 else return raw_scan_root
527 (sb,name,number,ino,res_bh,res_de,scantype);
532 * fat_parent_ino returns the inode number of the parent directory of dir.
533 * File creation has to be deferred while fat_parent_ino is running to
534 * prevent renames.
537 int fat_parent_ino(struct inode *dir,int locked)
539 static int zero = 0;
540 int error,curr,prev,nr;
542 PRINTK(("fat_parent_ino: Debug 0\n"));
543 if (!S_ISDIR(dir->i_mode)) panic("Non-directory fed to m_p_i");
544 if (dir->i_ino == MSDOS_ROOT_INO) return dir->i_ino;
545 if (!locked) fat_lock_creation(); /* prevent renames */
546 if ((curr = raw_scan(dir->i_sb,MSDOS_I(dir)->i_start,MSDOS_DOTDOT,
547 &zero,NULL,NULL,NULL,SCAN_ANY)) < 0) {
548 if (!locked) fat_unlock_creation();
549 return curr;
551 PRINTK(("fat_parent_ino: Debug 1 curr=%d\n", curr));
552 if (!curr) nr = MSDOS_ROOT_INO;
553 else {
554 PRINTK(("fat_parent_ino: Debug 2\n"));
555 if ((prev = raw_scan(dir->i_sb,curr,MSDOS_DOTDOT,&zero,NULL,
556 NULL,NULL,SCAN_ANY)) < 0) {
557 PRINTK(("fat_parent_ino: Debug 3 prev=%d\n", prev));
558 if (!locked) fat_unlock_creation();
559 return prev;
561 PRINTK(("fat_parent_ino: Debug 4 prev=%d\n", prev));
562 if (prev == 0 && MSDOS_SB(dir->i_sb)->fat_bits == 32) {
563 prev = MSDOS_SB(dir->i_sb)->root_cluster;
565 if ((error = raw_scan(dir->i_sb,prev,NULL,&curr,&nr,NULL,
566 NULL,SCAN_ANY)) < 0) {
567 PRINTK(("fat_parent_ino: Debug 5 error=%d\n", error));
568 if (!locked) fat_unlock_creation();
569 return error;
571 PRINTK(("fat_parent_ino: Debug 6 nr=%d\n", nr));
573 if (!locked) fat_unlock_creation();
574 return nr;
579 * fat_subdirs counts the number of sub-directories of dir. It can be run
580 * on directories being created.
583 int fat_subdirs(struct inode *dir)
585 int count;
587 count = 0;
588 if ((dir->i_ino == MSDOS_ROOT_INO) &&
589 (MSDOS_SB(dir->i_sb)->fat_bits != 32)) {
590 (void) raw_scan_root(dir->i_sb,NULL,&count,NULL,NULL,NULL,SCAN_ANY);
591 } else {
592 if ((dir->i_ino != MSDOS_ROOT_INO) &&
593 !MSDOS_I(dir)->i_start) return 0; /* in mkdir */
594 else (void) raw_scan_nonroot(dir->i_sb,MSDOS_I(dir)->i_start,
595 NULL,&count,NULL,NULL,NULL,SCAN_ANY);
597 return count;
602 * Scans a directory for a given file (name points to its formatted name) or
603 * for an empty directory slot (name is NULL). Returns an error code or zero.
606 int fat_scan(struct inode *dir,const char *name,struct buffer_head **res_bh,
607 struct msdos_dir_entry **res_de,int *ino, char scantype)
609 int res;
611 res = raw_scan(dir->i_sb,MSDOS_I(dir)->i_start,
612 name, NULL, ino, res_bh, res_de, scantype);
613 return res<0 ? res : 0;