import of ftp.dlink.com/GPL/DSMG-600_reB/ppclinux.tar.gz
[linux-2.4.21-pre4.git] / 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         fat_mark_buffer_dirty(sb, bh);
112         fat_brelse(sb, bh);
113 }
114
115 /*
116  * fat_add_cluster tries to allocate a new cluster and adds it to the
117  * file represented by inode.
118  */
119 int fat_add_cluster(struct inode *inode)
120 {
121         struct super_block *sb = inode->i_sb;
122         int count, nr, limit, last, curr, file_cluster;
123         int cluster_size = MSDOS_SB(sb)->cluster_size;
124         int res = -ENOSPC;
125         
126         lock_fat(sb);
127         
128         if (MSDOS_SB(sb)->free_clusters == 0) {
129                 unlock_fat(sb);
130                 return res;
131         }
132         limit = MSDOS_SB(sb)->clusters;
133         nr = limit; /* to keep GCC happy */
134         for (count = 0; count < limit; count++) {
135                 nr = ((count + MSDOS_SB(sb)->prev_free) % limit) + 2;
136                 if (fat_access(sb, nr, -1) == 0)
137                         break;
138         }
139         if (count >= limit) {
140                 MSDOS_SB(sb)->free_clusters = 0;
141                 unlock_fat(sb);
142                 return res;
143         }
144         
145         MSDOS_SB(sb)->prev_free = (count + MSDOS_SB(sb)->prev_free + 1) % limit;
146         fat_access(sb, nr, EOF_FAT(sb));
147         if (MSDOS_SB(sb)->free_clusters != -1)
148                 MSDOS_SB(sb)->free_clusters--;
149         if (MSDOS_SB(sb)->fat_bits == 32)
150                 fat_clusters_flush(sb);
151         
152         unlock_fat(sb);
153         
154         /* We must locate the last cluster of the file to add this
155            new one (nr) to the end of the link list (the FAT).
156            
157            Here file_cluster will be the number of the last cluster of the
158            file (before we add nr).
159            
160            last is the corresponding cluster number on the disk. We will
161            use last to plug the nr cluster. We will use file_cluster to
162            update the cache.
163         */
164         last = file_cluster = 0;
165         if ((curr = MSDOS_I(inode)->i_start) != 0) {
166                 fat_cache_lookup(inode, INT_MAX, &last, &curr);
167                 file_cluster = last;
168                 while (curr && curr != -1){
169                         file_cluster++;
170                         if (!(curr = fat_access(sb, last = curr,-1))) {
171                                 fat_fs_panic(sb, "File without EOF");
172                                 return res;
173                         }
174                 }
175         }
176         if (last) {
177                 fat_access(sb, last, nr);
178                 fat_cache_add(inode, file_cluster, nr);
179         } else {
180                 MSDOS_I(inode)->i_start = nr;
181                 MSDOS_I(inode)->i_logstart = nr;
182                 mark_inode_dirty(inode);
183         }
184         if (file_cluster
185             != inode->i_blocks / cluster_size / (sb->s_blocksize / 512)) {
186                 printk ("file_cluster badly computed!!! %d <> %ld\n",
187                         file_cluster,
188                         inode->i_blocks / cluster_size / (sb->s_blocksize / 512));
189                 fat_cache_inval_inode(inode);
190         }
191         inode->i_blocks += (1 << MSDOS_SB(sb)->cluster_bits) / 512;
192
193         return nr;
194 }
195
196 struct buffer_head *fat_extend_dir(struct inode *inode)
197 {
198         struct super_block *sb = inode->i_sb;
199         int nr, sector, last_sector;
200         struct buffer_head *bh, *res = NULL;
201         int cluster_size = MSDOS_SB(sb)->cluster_size;
202
203         if (MSDOS_SB(sb)->fat_bits != 32) {
204                 if (inode->i_ino == MSDOS_ROOT_INO)
205                         return res;
206         }
207
208         nr = fat_add_cluster(inode);
209         if (nr < 0)
210                 return res;
211         
212         sector = MSDOS_SB(sb)->data_start + (nr - 2) * cluster_size;
213         last_sector = sector + cluster_size;
214         if (MSDOS_SB(sb)->cvf_format && MSDOS_SB(sb)->cvf_format->zero_out_cluster)
215                 MSDOS_SB(sb)->cvf_format->zero_out_cluster(inode, nr);
216         else {
217                 for ( ; sector < last_sector; sector++) {
218 #ifdef DEBUG
219                         printk("zeroing sector %d\n", sector);
220 #endif
221                         if (!(bh = fat_getblk(sb, sector)))
222                                 printk("getblk failed\n");
223                         else {
224                                 memset(bh->b_data, 0, sb->s_blocksize);
225                                 fat_set_uptodate(sb, bh, 1);
226                                 fat_mark_buffer_dirty(sb, bh);
227                                 if (!res)
228                                         res = bh;
229                                 else
230                                         fat_brelse(sb, bh);
231                         }
232                 }
233         }
234         if (inode->i_size & (sb->s_blocksize - 1)) {
235                 fat_fs_panic(sb, "Odd directory size");
236                 inode->i_size = (inode->i_size + sb->s_blocksize)
237                         & ~(sb->s_blocksize - 1);
238         }
239         inode->i_size += 1 << MSDOS_SB(sb)->cluster_bits;
240         MSDOS_I(inode)->mmu_private += 1 << MSDOS_SB(sb)->cluster_bits;
241         mark_inode_dirty(inode);
242
243         return res;
244 }
245
246 /* Linear day numbers of the respective 1sts in non-leap years. */
247
248 static int day_n[] = { 0,31,59,90,120,151,181,212,243,273,304,334,0,0,0,0 };
249                   /* JanFebMarApr May Jun Jul Aug Sep Oct Nov Dec */
250
251
252 extern struct timezone sys_tz;
253
254
255 /* Convert a MS-DOS time/date pair to a UNIX date (seconds since 1 1 70). */
256
257 int date_dos2unix(unsigned short time,unsigned short date)
258 {
259         int month,year,secs;
260
261         /* first subtract and mask after that... Otherwise, if
262            date == 0, bad things happen */
263         month = ((date >> 5) - 1) & 15;
264         year = date >> 9;
265         secs = (time & 31)*2+60*((time >> 5) & 63)+(time >> 11)*3600+86400*
266             ((date & 31)-1+day_n[month]+(year/4)+year*365-((year & 3) == 0 &&
267             month < 2 ? 1 : 0)+3653);
268                         /* days since 1.1.70 plus 80's leap day */
269         secs += sys_tz.tz_minuteswest*60;
270         return secs;
271 }
272
273
274 /* Convert linear UNIX date to a MS-DOS time/date pair. */
275
276 void fat_date_unix2dos(int unix_date,unsigned short *time,
277     unsigned short *date)
278 {
279         int day,year,nl_day,month;
280
281         unix_date -= sys_tz.tz_minuteswest*60;
282
283         /* Jan 1 GMT 00:00:00 1980. But what about another time zone? */
284         if (unix_date < 315532800)
285                 unix_date = 315532800;
286
287         *time = (unix_date % 60)/2+(((unix_date/60) % 60) << 5)+
288             (((unix_date/3600) % 24) << 11);
289         day = unix_date/86400-3652;
290         year = day/365;
291         if ((year+3)/4+365*year > day) year--;
292         day -= (year+3)/4+365*year;
293         if (day == 59 && !(year & 3)) {
294                 nl_day = day;
295                 month = 2;
296         }
297         else {
298                 nl_day = (year & 3) || day <= 59 ? day : day-1;
299                 for (month = 0; month < 12; month++)
300                         if (day_n[month] > nl_day) break;
301         }
302         *date = nl_day-day_n[month-1]+1+(month << 5)+(year << 9);
303 }
304
305
306 /* Returns the inode number of the directory entry at offset pos. If bh is
307    non-NULL, it is brelse'd before. Pos is incremented. The buffer header is
308    returned in bh.
309    AV. Most often we do it item-by-item. Makes sense to optimize.
310    AV. OK, there we go: if both bh and de are non-NULL we assume that we just
311    AV. want the next entry (took one explicit de=NULL in vfat/namei.c).
312    AV. It's done in fat_get_entry() (inlined), here the slow case lives.
313    AV. Additionally, when we return -1 (i.e. reached the end of directory)
314    AV. we make bh NULL. 
315  */
316
317 int fat__get_entry(struct inode *dir, loff_t *pos,struct buffer_head **bh,
318     struct msdos_dir_entry **de, int *ino)
319 {
320         struct super_block *sb = dir->i_sb;
321         struct msdos_sb_info *sbi = MSDOS_SB(sb);
322         int sector, offset;
323
324         while (1) {
325                 offset = *pos;
326                 PRINTK (("get_entry offset %d\n",offset));
327                 if (*bh)
328                         fat_brelse(sb, *bh);
329                 *bh = NULL;
330                 if ((sector = fat_bmap(dir,offset >> sb->s_blocksize_bits)) == -1)
331                         return -1;
332                 PRINTK (("get_entry sector %d %p\n",sector,*bh));
333                 PRINTK (("get_entry sector apres brelse\n"));
334                 if (!sector)
335                         return -1; /* beyond EOF */
336                 *pos += sizeof(struct msdos_dir_entry);
337                 if (!(*bh = fat_bread(sb, sector))) {
338                         printk("Directory sread (sector 0x%x) failed\n",sector);
339                         continue;
340                 }
341                 PRINTK (("get_entry apres sread\n"));
342
343                 offset &= sb->s_blocksize - 1;
344                 *de = (struct msdos_dir_entry *) ((*bh)->b_data + offset);
345                 *ino = (sector << sbi->dir_per_block_bits) + (offset >> MSDOS_DIR_BITS);
346
347                 return 0;
348         }
349 }
350
351
352 /*
353  * Now an ugly part: this set of directory scan routines works on clusters
354  * rather than on inodes and sectors. They are necessary to locate the '..'
355  * directory "inode". raw_scan_sector operates in four modes:
356  *
357  * name     number   ino      action
358  * -------- -------- -------- -------------------------------------------------
359  * non-NULL -        X        Find an entry with that name
360  * NULL     non-NULL non-NULL Find an entry whose data starts at *number
361  * NULL     non-NULL NULL     Count subdirectories in *number. (*)
362  * NULL     NULL     non-NULL Find an empty entry
363  *
364  * (*) The return code should be ignored. It DOES NOT indicate success or
365  *     failure. *number has to be initialized to zero.
366  *
367  * - = not used, X = a value is returned unless NULL
368  *
369  * If res_bh is non-NULL, the buffer is not deallocated but returned to the
370  * caller on success. res_de is set accordingly.
371  *
372  * If cont is non-zero, raw_found continues with the entry after the one
373  * res_bh/res_de point to.
374  */
375
376
377 #define RSS_NAME /* search for name */ \
378     done = !strncmp(data[entry].name,name,MSDOS_NAME) && \
379      !(data[entry].attr & ATTR_VOLUME);
380
381 #define RSS_START /* search for start cluster */ \
382     done = !IS_FREE(data[entry].name) \
383       && ( \
384            ( \
385              (MSDOS_SB(sb)->fat_bits != 32) ? 0 : (CF_LE_W(data[entry].starthi) << 16) \
386            ) \
387            | CF_LE_W(data[entry].start) \
388          ) == *number;
389
390 #define RSS_FREE /* search for free entry */ \
391     { \
392         done = IS_FREE(data[entry].name); \
393     }
394
395 #define RSS_COUNT /* count subdirectories */ \
396     { \
397         done = 0; \
398         if (!IS_FREE(data[entry].name) && (data[entry].attr & ATTR_DIR)) \
399             (*number)++; \
400     }
401
402 static int raw_scan_sector(struct super_block *sb,int sector,const char *name,
403     int *number,int *ino,struct buffer_head **res_bh,
404     struct msdos_dir_entry **res_de)
405 {
406         struct buffer_head *bh;
407         struct msdos_dir_entry *data;
408         int entry,start,done;
409
410         if (!(bh = fat_bread(sb,sector)))
411                 return -EIO;
412         data = (struct msdos_dir_entry *) bh->b_data;
413         for (entry = 0; entry < MSDOS_SB(sb)->dir_per_block; entry++) {
414 /* RSS_COUNT:  if (data[entry].name == name) done=true else done=false. */
415                 if (name) {
416                         RSS_NAME
417                 } else {
418                         if (!ino) RSS_COUNT
419                         else {
420                                 if (number) RSS_START
421                                 else RSS_FREE
422                         }
423                 }
424                 if (done) {
425                         if (ino)
426                                 *ino = sector * MSDOS_SB(sb)->dir_per_block + entry;
427                         start = CF_LE_W(data[entry].start);
428                         if (MSDOS_SB(sb)->fat_bits == 32) {
429                                 start |= (CF_LE_W(data[entry].starthi) << 16);
430                         }
431                         if (!res_bh)
432                                 fat_brelse(sb, bh);
433                         else {
434                                 *res_bh = bh;
435                                 *res_de = &data[entry];
436                         }
437                         return start;
438                 }
439         }
440         fat_brelse(sb, bh);
441         return -ENOENT;
442 }
443
444
445 /*
446  * raw_scan_root performs raw_scan_sector on the root directory until the
447  * requested entry is found or the end of the directory is reached.
448  */
449
450 static int raw_scan_root(struct super_block *sb,const char *name,int *number,int *ino,
451     struct buffer_head **res_bh,struct msdos_dir_entry **res_de)
452 {
453         int count,cluster;
454
455         for (count = 0;
456              count < MSDOS_SB(sb)->dir_entries / MSDOS_SB(sb)->dir_per_block;
457              count++) {
458                 if ((cluster = raw_scan_sector(sb,MSDOS_SB(sb)->dir_start+count,
459                                                name,number,ino,res_bh,res_de)) >= 0)
460                         return cluster;
461         }
462         return -ENOENT;
463 }
464
465
466 /*
467  * raw_scan_nonroot performs raw_scan_sector on a non-root directory until the
468  * requested entry is found or the end of the directory is reached.
469  */
470
471 static int raw_scan_nonroot(struct super_block *sb,int start,const char *name,
472     int *number,int *ino,struct buffer_head **res_bh,struct msdos_dir_entry
473     **res_de)
474 {
475         int count,cluster;
476
477 #ifdef DEBUG
478         printk("raw_scan_nonroot: start=%d\n",start);
479 #endif
480         do {
481                 for (count = 0; count < MSDOS_SB(sb)->cluster_size; count++) {
482                         if ((cluster = raw_scan_sector(sb,(start-2)*
483                             MSDOS_SB(sb)->cluster_size+MSDOS_SB(sb)->data_start+
484                             count,name,number,ino,res_bh,res_de)) >= 0)
485                                 return cluster;
486                 }
487                 if (!(start = fat_access(sb,start,-1))) {
488                         fat_fs_panic(sb,"FAT error");
489                         break;
490                 }
491 #ifdef DEBUG
492         printk("next start: %d\n",start);
493 #endif
494         }
495         while (start != -1);
496         return -ENOENT;
497 }
498
499
500 /*
501  * raw_scan performs raw_scan_sector on any sector.
502  *
503  * NOTE: raw_scan must not be used on a directory that is is the process of
504  *       being created.
505  */
506
507 static int raw_scan(struct super_block *sb, int start, const char *name,
508     int *number, int *ino, struct buffer_head **res_bh,
509     struct msdos_dir_entry **res_de)
510 {
511         if (start)
512                 return raw_scan_nonroot(sb,start,name,number,ino,res_bh,res_de);
513         else
514                 return raw_scan_root(sb,name,number,ino,res_bh,res_de);
515 }
516
517 /*
518  * fat_subdirs counts the number of sub-directories of dir. It can be run
519  * on directories being created.
520  */
521 int fat_subdirs(struct inode *dir)
522 {
523         int count;
524
525         count = 0;
526         if ((dir->i_ino == MSDOS_ROOT_INO) &&
527             (MSDOS_SB(dir->i_sb)->fat_bits != 32)) {
528                 (void) raw_scan_root(dir->i_sb,NULL,&count,NULL,NULL,NULL);
529         } else {
530                 if ((dir->i_ino != MSDOS_ROOT_INO) &&
531                     !MSDOS_I(dir)->i_start) return 0; /* in mkdir */
532                 else (void) raw_scan_nonroot(dir->i_sb,MSDOS_I(dir)->i_start,
533                     NULL,&count,NULL,NULL,NULL);
534         }
535         return count;
536 }
537
538
539 /*
540  * Scans a directory for a given file (name points to its formatted name) or
541  * for an empty directory slot (name is NULL). Returns an error code or zero.
542  */
543
544 int fat_scan(struct inode *dir,const char *name,struct buffer_head **res_bh,
545     struct msdos_dir_entry **res_de,int *ino)
546 {
547         int res;
548
549         res = raw_scan(dir->i_sb,MSDOS_I(dir)->i_start,
550                        name, NULL, ino, res_bh, res_de);
551         return res<0 ? res : 0;
552 }