Version:  2.0.40 2.2.26 2.4.37 3.5 3.6 3.7 3.8 3.9 3.10 3.11 3.12 3.13 3.14 3.15 3.16 3.17 3.18 3.19 4.0 4.1

Linux/fs/fat/namei_msdos.c

  1 /*
  2  *  linux/fs/msdos/namei.c
  3  *
  4  *  Written 1992,1993 by Werner Almesberger
  5  *  Hidden files 1995 by Albert Cahalan <albert@ccs.neu.edu> <adc@coe.neu.edu>
  6  *  Rewritten for constant inumbers 1999 by Al Viro
  7  */
  8 
  9 #include <linux/module.h>
 10 #include "fat.h"
 11 
 12 /* Characters that are undesirable in an MS-DOS file name */
 13 static unsigned char bad_chars[] = "*?<>|\"";
 14 static unsigned char bad_if_strict[] = "+=,; ";
 15 
 16 /***** Formats an MS-DOS file name. Rejects invalid names. */
 17 static int msdos_format_name(const unsigned char *name, int len,
 18                              unsigned char *res, struct fat_mount_options *opts)
 19         /*
 20          * name is the proposed name, len is its length, res is
 21          * the resulting name, opts->name_check is either (r)elaxed,
 22          * (n)ormal or (s)trict, opts->dotsOK allows dots at the
 23          * beginning of name (for hidden files)
 24          */
 25 {
 26         unsigned char *walk;
 27         unsigned char c;
 28         int space;
 29 
 30         if (name[0] == '.') {   /* dotfile because . and .. already done */
 31                 if (opts->dotsOK) {
 32                         /* Get rid of dot - test for it elsewhere */
 33                         name++;
 34                         len--;
 35                 } else
 36                         return -EINVAL;
 37         }
 38         /*
 39          * disallow names that _really_ start with a dot
 40          */
 41         space = 1;
 42         c = 0;
 43         for (walk = res; len && walk - res < 8; walk++) {
 44                 c = *name++;
 45                 len--;
 46                 if (opts->name_check != 'r' && strchr(bad_chars, c))
 47                         return -EINVAL;
 48                 if (opts->name_check == 's' && strchr(bad_if_strict, c))
 49                         return -EINVAL;
 50                 if (c >= 'A' && c <= 'Z' && opts->name_check == 's')
 51                         return -EINVAL;
 52                 if (c < ' ' || c == ':' || c == '\\')
 53                         return -EINVAL;
 54         /*
 55          * 0xE5 is legal as a first character, but we must substitute
 56          * 0x05 because 0xE5 marks deleted files.  Yes, DOS really
 57          * does this.
 58          * It seems that Microsoft hacked DOS to support non-US
 59          * characters after the 0xE5 character was already in use to
 60          * mark deleted files.
 61          */
 62                 if ((res == walk) && (c == 0xE5))
 63                         c = 0x05;
 64                 if (c == '.')
 65                         break;
 66                 space = (c == ' ');
 67                 *walk = (!opts->nocase && c >= 'a' && c <= 'z') ? c - 32 : c;
 68         }
 69         if (space)
 70                 return -EINVAL;
 71         if (opts->name_check == 's' && len && c != '.') {
 72                 c = *name++;
 73                 len--;
 74                 if (c != '.')
 75                         return -EINVAL;
 76         }
 77         while (c != '.' && len--)
 78                 c = *name++;
 79         if (c == '.') {
 80                 while (walk - res < 8)
 81                         *walk++ = ' ';
 82                 while (len > 0 && walk - res < MSDOS_NAME) {
 83                         c = *name++;
 84                         len--;
 85                         if (opts->name_check != 'r' && strchr(bad_chars, c))
 86                                 return -EINVAL;
 87                         if (opts->name_check == 's' &&
 88                             strchr(bad_if_strict, c))
 89                                 return -EINVAL;
 90                         if (c < ' ' || c == ':' || c == '\\')
 91                                 return -EINVAL;
 92                         if (c == '.') {
 93                                 if (opts->name_check == 's')
 94                                         return -EINVAL;
 95                                 break;
 96                         }
 97                         if (c >= 'A' && c <= 'Z' && opts->name_check == 's')
 98                                 return -EINVAL;
 99                         space = c == ' ';
100                         if (!opts->nocase && c >= 'a' && c <= 'z')
101                                 *walk++ = c - 32;
102                         else
103                                 *walk++ = c;
104                 }
105                 if (space)
106                         return -EINVAL;
107                 if (opts->name_check == 's' && len)
108                         return -EINVAL;
109         }
110         while (walk - res < MSDOS_NAME)
111                 *walk++ = ' ';
112 
113         return 0;
114 }
115 
116 /***** Locates a directory entry.  Uses unformatted name. */
117 static int msdos_find(struct inode *dir, const unsigned char *name, int len,
118                       struct fat_slot_info *sinfo)
119 {
120         struct msdos_sb_info *sbi = MSDOS_SB(dir->i_sb);
121         unsigned char msdos_name[MSDOS_NAME];
122         int err;
123 
124         err = msdos_format_name(name, len, msdos_name, &sbi->options);
125         if (err)
126                 return -ENOENT;
127 
128         err = fat_scan(dir, msdos_name, sinfo);
129         if (!err && sbi->options.dotsOK) {
130                 if (name[0] == '.') {
131                         if (!(sinfo->de->attr & ATTR_HIDDEN))
132                                 err = -ENOENT;
133                 } else {
134                         if (sinfo->de->attr & ATTR_HIDDEN)
135                                 err = -ENOENT;
136                 }
137                 if (err)
138                         brelse(sinfo->bh);
139         }
140         return err;
141 }
142 
143 /*
144  * Compute the hash for the msdos name corresponding to the dentry.
145  * Note: if the name is invalid, we leave the hash code unchanged so
146  * that the existing dentry can be used. The msdos fs routines will
147  * return ENOENT or EINVAL as appropriate.
148  */
149 static int msdos_hash(const struct dentry *dentry, struct qstr *qstr)
150 {
151         struct fat_mount_options *options = &MSDOS_SB(dentry->d_sb)->options;
152         unsigned char msdos_name[MSDOS_NAME];
153         int error;
154 
155         error = msdos_format_name(qstr->name, qstr->len, msdos_name, options);
156         if (!error)
157                 qstr->hash = full_name_hash(msdos_name, MSDOS_NAME);
158         return 0;
159 }
160 
161 /*
162  * Compare two msdos names. If either of the names are invalid,
163  * we fall back to doing the standard name comparison.
164  */
165 static int msdos_cmp(const struct dentry *parent, const struct dentry *dentry,
166                 unsigned int len, const char *str, const struct qstr *name)
167 {
168         struct fat_mount_options *options = &MSDOS_SB(parent->d_sb)->options;
169         unsigned char a_msdos_name[MSDOS_NAME], b_msdos_name[MSDOS_NAME];
170         int error;
171 
172         error = msdos_format_name(name->name, name->len, a_msdos_name, options);
173         if (error)
174                 goto old_compare;
175         error = msdos_format_name(str, len, b_msdos_name, options);
176         if (error)
177                 goto old_compare;
178         error = memcmp(a_msdos_name, b_msdos_name, MSDOS_NAME);
179 out:
180         return error;
181 
182 old_compare:
183         error = 1;
184         if (name->len == len)
185                 error = memcmp(name->name, str, len);
186         goto out;
187 }
188 
189 static const struct dentry_operations msdos_dentry_operations = {
190         .d_hash         = msdos_hash,
191         .d_compare      = msdos_cmp,
192 };
193 
194 /*
195  * AV. Wrappers for FAT sb operations. Is it wise?
196  */
197 
198 /***** Get inode using directory and name */
199 static struct dentry *msdos_lookup(struct inode *dir, struct dentry *dentry,
200                                    unsigned int flags)
201 {
202         struct super_block *sb = dir->i_sb;
203         struct fat_slot_info sinfo;
204         struct inode *inode;
205         int err;
206 
207         mutex_lock(&MSDOS_SB(sb)->s_lock);
208         err = msdos_find(dir, dentry->d_name.name, dentry->d_name.len, &sinfo);
209         switch (err) {
210         case -ENOENT:
211                 inode = NULL;
212                 break;
213         case 0:
214                 inode = fat_build_inode(sb, sinfo.de, sinfo.i_pos);
215                 brelse(sinfo.bh);
216                 break;
217         default:
218                 inode = ERR_PTR(err);
219         }
220         mutex_unlock(&MSDOS_SB(sb)->s_lock);
221         return d_splice_alias(inode, dentry);
222 }
223 
224 /***** Creates a directory entry (name is already formatted). */
225 static int msdos_add_entry(struct inode *dir, const unsigned char *name,
226                            int is_dir, int is_hid, int cluster,
227                            struct timespec *ts, struct fat_slot_info *sinfo)
228 {
229         struct msdos_sb_info *sbi = MSDOS_SB(dir->i_sb);
230         struct msdos_dir_entry de;
231         __le16 time, date;
232         int err;
233 
234         memcpy(de.name, name, MSDOS_NAME);
235         de.attr = is_dir ? ATTR_DIR : ATTR_ARCH;
236         if (is_hid)
237                 de.attr |= ATTR_HIDDEN;
238         de.lcase = 0;
239         fat_time_unix2fat(sbi, ts, &time, &date, NULL);
240         de.cdate = de.adate = 0;
241         de.ctime = 0;
242         de.ctime_cs = 0;
243         de.time = time;
244         de.date = date;
245         fat_set_start(&de, cluster);
246         de.size = 0;
247 
248         err = fat_add_entries(dir, &de, 1, sinfo);
249         if (err)
250                 return err;
251 
252         dir->i_ctime = dir->i_mtime = *ts;
253         if (IS_DIRSYNC(dir))
254                 (void)fat_sync_inode(dir);
255         else
256                 mark_inode_dirty(dir);
257 
258         return 0;
259 }
260 
261 /***** Create a file */
262 static int msdos_create(struct inode *dir, struct dentry *dentry, umode_t mode,
263                         bool excl)
264 {
265         struct super_block *sb = dir->i_sb;
266         struct inode *inode = NULL;
267         struct fat_slot_info sinfo;
268         struct timespec ts;
269         unsigned char msdos_name[MSDOS_NAME];
270         int err, is_hid;
271 
272         mutex_lock(&MSDOS_SB(sb)->s_lock);
273 
274         err = msdos_format_name(dentry->d_name.name, dentry->d_name.len,
275                                 msdos_name, &MSDOS_SB(sb)->options);
276         if (err)
277                 goto out;
278         is_hid = (dentry->d_name.name[0] == '.') && (msdos_name[0] != '.');
279         /* Have to do it due to foo vs. .foo conflicts */
280         if (!fat_scan(dir, msdos_name, &sinfo)) {
281                 brelse(sinfo.bh);
282                 err = -EINVAL;
283                 goto out;
284         }
285 
286         ts = CURRENT_TIME_SEC;
287         err = msdos_add_entry(dir, msdos_name, 0, is_hid, 0, &ts, &sinfo);
288         if (err)
289                 goto out;
290         inode = fat_build_inode(sb, sinfo.de, sinfo.i_pos);
291         brelse(sinfo.bh);
292         if (IS_ERR(inode)) {
293                 err = PTR_ERR(inode);
294                 goto out;
295         }
296         inode->i_mtime = inode->i_atime = inode->i_ctime = ts;
297         /* timestamp is already written, so mark_inode_dirty() is unneeded. */
298 
299         d_instantiate(dentry, inode);
300 out:
301         mutex_unlock(&MSDOS_SB(sb)->s_lock);
302         if (!err)
303                 err = fat_flush_inodes(sb, dir, inode);
304         return err;
305 }
306 
307 /***** Remove a directory */
308 static int msdos_rmdir(struct inode *dir, struct dentry *dentry)
309 {
310         struct super_block *sb = dir->i_sb;
311         struct inode *inode = d_inode(dentry);
312         struct fat_slot_info sinfo;
313         int err;
314 
315         mutex_lock(&MSDOS_SB(sb)->s_lock);
316         /*
317          * Check whether the directory is not in use, then check
318          * whether it is empty.
319          */
320         err = fat_dir_empty(inode);
321         if (err)
322                 goto out;
323         err = msdos_find(dir, dentry->d_name.name, dentry->d_name.len, &sinfo);
324         if (err)
325                 goto out;
326 
327         err = fat_remove_entries(dir, &sinfo);  /* and releases bh */
328         if (err)
329                 goto out;
330         drop_nlink(dir);
331 
332         clear_nlink(inode);
333         inode->i_ctime = CURRENT_TIME_SEC;
334         fat_detach(inode);
335 out:
336         mutex_unlock(&MSDOS_SB(sb)->s_lock);
337         if (!err)
338                 err = fat_flush_inodes(sb, dir, inode);
339 
340         return err;
341 }
342 
343 /***** Make a directory */
344 static int msdos_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
345 {
346         struct super_block *sb = dir->i_sb;
347         struct fat_slot_info sinfo;
348         struct inode *inode;
349         unsigned char msdos_name[MSDOS_NAME];
350         struct timespec ts;
351         int err, is_hid, cluster;
352 
353         mutex_lock(&MSDOS_SB(sb)->s_lock);
354 
355         err = msdos_format_name(dentry->d_name.name, dentry->d_name.len,
356                                 msdos_name, &MSDOS_SB(sb)->options);
357         if (err)
358                 goto out;
359         is_hid = (dentry->d_name.name[0] == '.') && (msdos_name[0] != '.');
360         /* foo vs .foo situation */
361         if (!fat_scan(dir, msdos_name, &sinfo)) {
362                 brelse(sinfo.bh);
363                 err = -EINVAL;
364                 goto out;
365         }
366 
367         ts = CURRENT_TIME_SEC;
368         cluster = fat_alloc_new_dir(dir, &ts);
369         if (cluster < 0) {
370                 err = cluster;
371                 goto out;
372         }
373         err = msdos_add_entry(dir, msdos_name, 1, is_hid, cluster, &ts, &sinfo);
374         if (err)
375                 goto out_free;
376         inc_nlink(dir);
377 
378         inode = fat_build_inode(sb, sinfo.de, sinfo.i_pos);
379         brelse(sinfo.bh);
380         if (IS_ERR(inode)) {
381                 err = PTR_ERR(inode);
382                 /* the directory was completed, just return a error */
383                 goto out;
384         }
385         set_nlink(inode, 2);
386         inode->i_mtime = inode->i_atime = inode->i_ctime = ts;
387         /* timestamp is already written, so mark_inode_dirty() is unneeded. */
388 
389         d_instantiate(dentry, inode);
390 
391         mutex_unlock(&MSDOS_SB(sb)->s_lock);
392         fat_flush_inodes(sb, dir, inode);
393         return 0;
394 
395 out_free:
396         fat_free_clusters(dir, cluster);
397 out:
398         mutex_unlock(&MSDOS_SB(sb)->s_lock);
399         return err;
400 }
401 
402 /***** Unlink a file */
403 static int msdos_unlink(struct inode *dir, struct dentry *dentry)
404 {
405         struct inode *inode = d_inode(dentry);
406         struct super_block *sb = inode->i_sb;
407         struct fat_slot_info sinfo;
408         int err;
409 
410         mutex_lock(&MSDOS_SB(sb)->s_lock);
411         err = msdos_find(dir, dentry->d_name.name, dentry->d_name.len, &sinfo);
412         if (err)
413                 goto out;
414 
415         err = fat_remove_entries(dir, &sinfo);  /* and releases bh */
416         if (err)
417                 goto out;
418         clear_nlink(inode);
419         inode->i_ctime = CURRENT_TIME_SEC;
420         fat_detach(inode);
421 out:
422         mutex_unlock(&MSDOS_SB(sb)->s_lock);
423         if (!err)
424                 err = fat_flush_inodes(sb, dir, inode);
425 
426         return err;
427 }
428 
429 static int do_msdos_rename(struct inode *old_dir, unsigned char *old_name,
430                            struct dentry *old_dentry,
431                            struct inode *new_dir, unsigned char *new_name,
432                            struct dentry *new_dentry, int is_hid)
433 {
434         struct buffer_head *dotdot_bh;
435         struct msdos_dir_entry *dotdot_de;
436         struct inode *old_inode, *new_inode;
437         struct fat_slot_info old_sinfo, sinfo;
438         struct timespec ts;
439         loff_t new_i_pos;
440         int err, old_attrs, is_dir, update_dotdot, corrupt = 0;
441 
442         old_sinfo.bh = sinfo.bh = dotdot_bh = NULL;
443         old_inode = d_inode(old_dentry);
444         new_inode = d_inode(new_dentry);
445 
446         err = fat_scan(old_dir, old_name, &old_sinfo);
447         if (err) {
448                 err = -EIO;
449                 goto out;
450         }
451 
452         is_dir = S_ISDIR(old_inode->i_mode);
453         update_dotdot = (is_dir && old_dir != new_dir);
454         if (update_dotdot) {
455                 if (fat_get_dotdot_entry(old_inode, &dotdot_bh, &dotdot_de)) {
456                         err = -EIO;
457                         goto out;
458                 }
459         }
460 
461         old_attrs = MSDOS_I(old_inode)->i_attrs;
462         err = fat_scan(new_dir, new_name, &sinfo);
463         if (!err) {
464                 if (!new_inode) {
465                         /* "foo" -> ".foo" case. just change the ATTR_HIDDEN */
466                         if (sinfo.de != old_sinfo.de) {
467                                 err = -EINVAL;
468                                 goto out;
469                         }
470                         if (is_hid)
471                                 MSDOS_I(old_inode)->i_attrs |= ATTR_HIDDEN;
472                         else
473                                 MSDOS_I(old_inode)->i_attrs &= ~ATTR_HIDDEN;
474                         if (IS_DIRSYNC(old_dir)) {
475                                 err = fat_sync_inode(old_inode);
476                                 if (err) {
477                                         MSDOS_I(old_inode)->i_attrs = old_attrs;
478                                         goto out;
479                                 }
480                         } else
481                                 mark_inode_dirty(old_inode);
482 
483                         old_dir->i_version++;
484                         old_dir->i_ctime = old_dir->i_mtime = CURRENT_TIME_SEC;
485                         if (IS_DIRSYNC(old_dir))
486                                 (void)fat_sync_inode(old_dir);
487                         else
488                                 mark_inode_dirty(old_dir);
489                         goto out;
490                 }
491         }
492 
493         ts = CURRENT_TIME_SEC;
494         if (new_inode) {
495                 if (err)
496                         goto out;
497                 if (is_dir) {
498                         err = fat_dir_empty(new_inode);
499                         if (err)
500                                 goto out;
501                 }
502                 new_i_pos = MSDOS_I(new_inode)->i_pos;
503                 fat_detach(new_inode);
504         } else {
505                 err = msdos_add_entry(new_dir, new_name, is_dir, is_hid, 0,
506                                       &ts, &sinfo);
507                 if (err)
508                         goto out;
509                 new_i_pos = sinfo.i_pos;
510         }
511         new_dir->i_version++;
512 
513         fat_detach(old_inode);
514         fat_attach(old_inode, new_i_pos);
515         if (is_hid)
516                 MSDOS_I(old_inode)->i_attrs |= ATTR_HIDDEN;
517         else
518                 MSDOS_I(old_inode)->i_attrs &= ~ATTR_HIDDEN;
519         if (IS_DIRSYNC(new_dir)) {
520                 err = fat_sync_inode(old_inode);
521                 if (err)
522                         goto error_inode;
523         } else
524                 mark_inode_dirty(old_inode);
525 
526         if (update_dotdot) {
527                 fat_set_start(dotdot_de, MSDOS_I(new_dir)->i_logstart);
528                 mark_buffer_dirty_inode(dotdot_bh, old_inode);
529                 if (IS_DIRSYNC(new_dir)) {
530                         err = sync_dirty_buffer(dotdot_bh);
531                         if (err)
532                                 goto error_dotdot;
533                 }
534                 drop_nlink(old_dir);
535                 if (!new_inode)
536                         inc_nlink(new_dir);
537         }
538 
539         err = fat_remove_entries(old_dir, &old_sinfo);  /* and releases bh */
540         old_sinfo.bh = NULL;
541         if (err)
542                 goto error_dotdot;
543         old_dir->i_version++;
544         old_dir->i_ctime = old_dir->i_mtime = ts;
545         if (IS_DIRSYNC(old_dir))
546                 (void)fat_sync_inode(old_dir);
547         else
548                 mark_inode_dirty(old_dir);
549 
550         if (new_inode) {
551                 drop_nlink(new_inode);
552                 if (is_dir)
553                         drop_nlink(new_inode);
554                 new_inode->i_ctime = ts;
555         }
556 out:
557         brelse(sinfo.bh);
558         brelse(dotdot_bh);
559         brelse(old_sinfo.bh);
560         return err;
561 
562 error_dotdot:
563         /* data cluster is shared, serious corruption */
564         corrupt = 1;
565 
566         if (update_dotdot) {
567                 fat_set_start(dotdot_de, MSDOS_I(old_dir)->i_logstart);
568                 mark_buffer_dirty_inode(dotdot_bh, old_inode);
569                 corrupt |= sync_dirty_buffer(dotdot_bh);
570         }
571 error_inode:
572         fat_detach(old_inode);
573         fat_attach(old_inode, old_sinfo.i_pos);
574         MSDOS_I(old_inode)->i_attrs = old_attrs;
575         if (new_inode) {
576                 fat_attach(new_inode, new_i_pos);
577                 if (corrupt)
578                         corrupt |= fat_sync_inode(new_inode);
579         } else {
580                 /*
581                  * If new entry was not sharing the data cluster, it
582                  * shouldn't be serious corruption.
583                  */
584                 int err2 = fat_remove_entries(new_dir, &sinfo);
585                 if (corrupt)
586                         corrupt |= err2;
587                 sinfo.bh = NULL;
588         }
589         if (corrupt < 0) {
590                 fat_fs_error(new_dir->i_sb,
591                              "%s: Filesystem corrupted (i_pos %lld)",
592                              __func__, sinfo.i_pos);
593         }
594         goto out;
595 }
596 
597 /***** Rename, a wrapper for rename_same_dir & rename_diff_dir */
598 static int msdos_rename(struct inode *old_dir, struct dentry *old_dentry,
599                         struct inode *new_dir, struct dentry *new_dentry)
600 {
601         struct super_block *sb = old_dir->i_sb;
602         unsigned char old_msdos_name[MSDOS_NAME], new_msdos_name[MSDOS_NAME];
603         int err, is_hid;
604 
605         mutex_lock(&MSDOS_SB(sb)->s_lock);
606 
607         err = msdos_format_name(old_dentry->d_name.name,
608                                 old_dentry->d_name.len, old_msdos_name,
609                                 &MSDOS_SB(old_dir->i_sb)->options);
610         if (err)
611                 goto out;
612         err = msdos_format_name(new_dentry->d_name.name,
613                                 new_dentry->d_name.len, new_msdos_name,
614                                 &MSDOS_SB(new_dir->i_sb)->options);
615         if (err)
616                 goto out;
617 
618         is_hid =
619              (new_dentry->d_name.name[0] == '.') && (new_msdos_name[0] != '.');
620 
621         err = do_msdos_rename(old_dir, old_msdos_name, old_dentry,
622                               new_dir, new_msdos_name, new_dentry, is_hid);
623 out:
624         mutex_unlock(&MSDOS_SB(sb)->s_lock);
625         if (!err)
626                 err = fat_flush_inodes(sb, old_dir, new_dir);
627         return err;
628 }
629 
630 static const struct inode_operations msdos_dir_inode_operations = {
631         .create         = msdos_create,
632         .lookup         = msdos_lookup,
633         .unlink         = msdos_unlink,
634         .mkdir          = msdos_mkdir,
635         .rmdir          = msdos_rmdir,
636         .rename         = msdos_rename,
637         .setattr        = fat_setattr,
638         .getattr        = fat_getattr,
639 };
640 
641 static void setup(struct super_block *sb)
642 {
643         MSDOS_SB(sb)->dir_ops = &msdos_dir_inode_operations;
644         sb->s_d_op = &msdos_dentry_operations;
645         sb->s_flags |= MS_NOATIME;
646 }
647 
648 static int msdos_fill_super(struct super_block *sb, void *data, int silent)
649 {
650         return fat_fill_super(sb, data, silent, 0, setup);
651 }
652 
653 static struct dentry *msdos_mount(struct file_system_type *fs_type,
654                         int flags, const char *dev_name,
655                         void *data)
656 {
657         return mount_bdev(fs_type, flags, dev_name, data, msdos_fill_super);
658 }
659 
660 static struct file_system_type msdos_fs_type = {
661         .owner          = THIS_MODULE,
662         .name           = "msdos",
663         .mount          = msdos_mount,
664         .kill_sb        = kill_block_super,
665         .fs_flags       = FS_REQUIRES_DEV,
666 };
667 MODULE_ALIAS_FS("msdos");
668 
669 static int __init init_msdos_fs(void)
670 {
671         return register_filesystem(&msdos_fs_type);
672 }
673 
674 static void __exit exit_msdos_fs(void)
675 {
676         unregister_filesystem(&msdos_fs_type);
677 }
678 
679 MODULE_LICENSE("GPL");
680 MODULE_AUTHOR("Werner Almesberger");
681 MODULE_DESCRIPTION("MS-DOS filesystem support");
682 
683 module_init(init_msdos_fs)
684 module_exit(exit_msdos_fs)
685 

This page was automatically generated by LXR 0.3.1 (source).  •  Linux is a registered trademark of Linus Torvalds  •  Contact us