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