X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=fs%2Fmsdos%2Fnamei.c;h=cb452cf3905678814901d8e4b42d9fdee38488b4;hb=6a77f38946aaee1cd85eeec6cf4229b204c15071;hp=817f57aa90e62735d80e5375afddfe159e2ffd74;hpb=87fc8d1bb10cd459024a742c6a10961fefcef18f;p=linux-2.6.git diff --git a/fs/msdos/namei.c b/fs/msdos/namei.c index 817f57aa9..cb452cf39 100644 --- a/fs/msdos/namei.c +++ b/fs/msdos/namei.c @@ -12,25 +12,28 @@ #include #include - /* MS-DOS "device special files" */ static const unsigned char *reserved_names[] = { - "CON ","PRN ","NUL ","AUX ", - "LPT1 ","LPT2 ","LPT3 ","LPT4 ", - "COM1 ","COM2 ","COM3 ","COM4 ", + "CON ", "PRN ", "NUL ", "AUX ", + "LPT1 ", "LPT2 ", "LPT3 ", "LPT4 ", + "COM1 ", "COM2 ", "COM3 ", "COM4 ", NULL }; /* Characters that are undesirable in an MS-DOS file name */ static unsigned char bad_chars[] = "*?<>|\""; static unsigned char bad_if_strict_pc[] = "+=,; "; -static unsigned char bad_if_strict_atari[] = " "; /* GEMDOS is less restrictive */ -#define bad_if_strict(opts) ((opts)->atari ? bad_if_strict_atari : bad_if_strict_pc) +/* GEMDOS is less restrictive */ +static unsigned char bad_if_strict_atari[] = " "; + +#define bad_if_strict(opts) \ + ((opts)->atari ? bad_if_strict_atari : bad_if_strict_pc) /***** Formats an MS-DOS file name. Rejects invalid names. */ static int msdos_format_name(const unsigned char *name, int len, - unsigned char *res, struct fat_mount_options *opts) - /* name is the proposed name, len is its length, res is + unsigned char *res, struct fat_mount_options *opts) + /* + * name is the proposed name, len is its length, res is * the resulting name, opts->name_check is either (r)elaxed, * (n)ormal or (s)trict, opts->dotsOK allows dots at the * beginning of name (for hidden files) @@ -41,52 +44,66 @@ static int msdos_format_name(const unsigned char *name, int len, unsigned char c; int space; - if (name[0] == '.') { /* dotfile because . and .. already done */ + if (name[0] == '.') { /* dotfile because . and .. already done */ if (opts->dotsOK) { /* Get rid of dot - test for it elsewhere */ - name++; len--; - } - else if (!opts->atari) return -EINVAL; + name++; + len--; + } else if (!opts->atari) + return -EINVAL; } - /* disallow names that _really_ start with a dot for MS-DOS, GEMDOS does - * not care */ + /* + * disallow names that _really_ start with a dot for MS-DOS, + * GEMDOS does not care + */ space = !opts->atari; c = 0; - for (walk = res; len && walk-res < 8; walk++) { - c = *name++; + for (walk = res; len && walk - res < 8; walk++) { + c = *name++; len--; - if (opts->name_check != 'r' && strchr(bad_chars,c)) + if (opts->name_check != 'r' && strchr(bad_chars, c)) return -EINVAL; - if (opts->name_check == 's' && strchr(bad_if_strict(opts),c)) + if (opts->name_check == 's' && strchr(bad_if_strict(opts), c)) return -EINVAL; - if (c >= 'A' && c <= 'Z' && opts->name_check == 's') + if (c >= 'A' && c <= 'Z' && opts->name_check == 's') return -EINVAL; - if (c < ' ' || c == ':' || c == '\\') return -EINVAL; -/* 0xE5 is legal as a first character, but we must substitute 0x05 */ -/* because 0xE5 marks deleted files. Yes, DOS really does this. */ -/* It seems that Microsoft hacked DOS to support non-US characters */ -/* after the 0xE5 character was already in use to mark deleted files. */ - if((res==walk) && (c==0xE5)) c=0x05; - if (c == '.') break; + if (c < ' ' || c == ':' || c == '\\') + return -EINVAL; + /* + * 0xE5 is legal as a first character, but we must substitute + * 0x05 because 0xE5 marks deleted files. Yes, DOS really + * does this. + * It seems that Microsoft hacked DOS to support non-US + * characters after the 0xE5 character was already in use to + * mark deleted files. + */ + if ((res == walk) && (c == 0xE5)) + c = 0x05; + if (c == '.') + break; space = (c == ' '); - *walk = (!opts->nocase && c >= 'a' && c <= 'z') ? c-32 : c; + *walk = (!opts->nocase && c >= 'a' && c <= 'z') ? c - 32 : c; } - if (space) return -EINVAL; + if (space) + return -EINVAL; if (opts->name_check == 's' && len && c != '.') { c = *name++; len--; - if (c != '.') return -EINVAL; + if (c != '.') + return -EINVAL; } - while (c != '.' && len--) c = *name++; + while (c != '.' && len--) + c = *name++; if (c == '.') { - while (walk-res < 8) *walk++ = ' '; - while (len > 0 && walk-res < MSDOS_NAME) { + while (walk - res < 8) + *walk++ = ' '; + while (len > 0 && walk - res < MSDOS_NAME) { c = *name++; len--; - if (opts->name_check != 'r' && strchr(bad_chars,c)) + if (opts->name_check != 'r' && strchr(bad_chars, c)) return -EINVAL; if (opts->name_check == 's' && - strchr(bad_if_strict(opts),c)) + strchr(bad_if_strict(opts), c)) return -EINVAL; if (c < ' ' || c == ':' || c == '\\') return -EINVAL; @@ -98,16 +115,23 @@ static int msdos_format_name(const unsigned char *name, int len, if (c >= 'A' && c <= 'Z' && opts->name_check == 's') return -EINVAL; space = c == ' '; - *walk++ = (!opts->nocase && c >= 'a' && c <= 'z') ? c-32 : c; + if (!opts->nocase && c >= 'a' && c <= 'z') + *walk++ = c - 32; + else + *walk++ = c; } - if (space) return -EINVAL; - if (opts->name_check == 's' && len) return -EINVAL; + if (space) + return -EINVAL; + if (opts->name_check == 's' && len) + return -EINVAL; } - while (walk-res < MSDOS_NAME) *walk++ = ' '; + while (walk - res < MSDOS_NAME) + *walk++ = ' '; if (!opts->atari) /* GEMDOS is less stupid and has no reserved names */ for (reserved = reserved_names; *reserved; reserved++) - if (!strncmp(res,*reserved,8)) return -EINVAL; + if (!strncmp(res, *reserved, 8)) + return -EINVAL; return 0; } @@ -121,12 +145,13 @@ static int msdos_find(struct inode *dir, const unsigned char *name, int len, int res; dotsOK = MSDOS_SB(dir->i_sb)->options.dotsOK; - res = msdos_format_name(name,len, msdos_name,&MSDOS_SB(dir->i_sb)->options); + res = msdos_format_name(name, len, msdos_name, + &MSDOS_SB(dir->i_sb)->options); if (res < 0) return -ENOENT; res = fat_scan(dir, msdos_name, bh, de, i_pos); if (!res && dotsOK) { - if (name[0]=='.') { + if (name[0] == '.') { if (!((*de)->attr & ATTR_HIDDEN)) res = -ENOENT; } else { @@ -145,10 +170,10 @@ static int msdos_find(struct inode *dir, const unsigned char *name, int len, */ static int msdos_hash(struct dentry *dentry, struct qstr *qstr) { - struct fat_mount_options *options = & (MSDOS_SB(dentry->d_sb)->options); + struct fat_mount_options *options = &MSDOS_SB(dentry->d_sb)->options; unsigned char msdos_name[MSDOS_NAME]; int error; - + error = msdos_format_name(qstr->name, qstr->len, msdos_name, options); if (!error) qstr->hash = full_name_hash(msdos_name, MSDOS_NAME); @@ -161,7 +186,7 @@ static int msdos_hash(struct dentry *dentry, struct qstr *qstr) */ static int msdos_cmp(struct dentry *dentry, struct qstr *a, struct qstr *b) { - struct fat_mount_options *options = & (MSDOS_SB(dentry->d_sb)->options); + struct fat_mount_options *options = &MSDOS_SB(dentry->d_sb)->options; unsigned char a_msdos_name[MSDOS_NAME], b_msdos_name[MSDOS_NAME]; int error; @@ -182,7 +207,6 @@ old_compare: goto out; } - static struct dentry_operations msdos_dentry_operations = { .d_hash = msdos_hash, .d_compare = msdos_cmp, @@ -194,7 +218,7 @@ static struct dentry_operations msdos_dentry_operations = { /***** Get inode using directory and name */ static struct dentry *msdos_lookup(struct inode *dir, struct dentry *dentry, - struct nameidata *nd) + struct nameidata *nd) { struct super_block *sb = dir->i_sb; struct inode *inode = NULL; @@ -202,7 +226,7 @@ static struct dentry *msdos_lookup(struct inode *dir, struct dentry *dentry, struct buffer_head *bh = NULL; loff_t i_pos; int res; - + dentry->d_op = &msdos_dentry_operations; lock_kernel(); @@ -243,7 +267,7 @@ static int msdos_add_entry(struct inode *dir, const unsigned char *name, /* * XXX all times should be set by caller upon successful completion. */ - dir->i_ctime = dir->i_mtime = CURRENT_TIME; + dir->i_ctime = dir->i_mtime = CURRENT_TIME_SEC; mark_inode_dirty(dir); memcpy((*de)->name, name, MSDOS_NAME); @@ -260,7 +284,7 @@ static int msdos_add_entry(struct inode *dir, const unsigned char *name, /***** Create a file */ static int msdos_create(struct inode *dir, struct dentry *dentry, int mode, - struct nameidata *nd) + struct nameidata *nd) { struct super_block *sb = dir->i_sb; struct buffer_head *bh; @@ -271,19 +295,19 @@ static int msdos_create(struct inode *dir, struct dentry *dentry, int mode, unsigned char msdos_name[MSDOS_NAME]; lock_kernel(); - res = msdos_format_name(dentry->d_name.name,dentry->d_name.len, + res = msdos_format_name(dentry->d_name.name, dentry->d_name.len, msdos_name, &MSDOS_SB(sb)->options); if (res < 0) { unlock_kernel(); return res; } - is_hid = (dentry->d_name.name[0]=='.') && (msdos_name[0]!='.'); + is_hid = (dentry->d_name.name[0] == '.') && (msdos_name[0] != '.'); /* Have to do it due to foo vs. .foo conflicts */ if (fat_scan(dir, msdos_name, &bh, &de, &i_pos) >= 0) { brelse(bh); unlock_kernel(); return -EINVAL; - } + } inode = NULL; res = msdos_add_entry(dir, msdos_name, &bh, &de, &i_pos, 0, is_hid); if (res) { @@ -296,7 +320,7 @@ static int msdos_create(struct inode *dir, struct dentry *dentry, int mode, unlock_kernel(); return res; } - inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; + inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME_SEC; mark_inode_dirty(inode); d_instantiate(dentry, inode); unlock_kernel(); @@ -330,7 +354,7 @@ static int msdos_rmdir(struct inode *dir, struct dentry *dentry) mark_buffer_dirty(bh); fat_detach(inode); inode->i_nlink = 0; - inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME; + inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME_SEC; dir->i_nlink--; mark_inode_dirty(inode); mark_inode_dirty(dir); @@ -349,18 +373,18 @@ static int msdos_mkdir(struct inode *dir, struct dentry *dentry, int mode) struct buffer_head *bh; struct msdos_dir_entry *de; struct inode *inode; - int res,is_hid; + int res, is_hid; unsigned char msdos_name[MSDOS_NAME]; loff_t i_pos; lock_kernel(); - res = msdos_format_name(dentry->d_name.name,dentry->d_name.len, + res = msdos_format_name(dentry->d_name.name, dentry->d_name.len, msdos_name, &MSDOS_SB(sb)->options); if (res < 0) { unlock_kernel(); return res; } - is_hid = (dentry->d_name.name[0]=='.') && (msdos_name[0]!='.'); + is_hid = (dentry->d_name.name[0] == '.') && (msdos_name[0] != '.'); /* foo vs .foo situation */ if (fat_scan(dir, msdos_name, &bh, &de, &i_pos) >= 0) goto out_exist; @@ -376,7 +400,7 @@ static int msdos_mkdir(struct inode *dir, struct dentry *dentry, int mode) res = 0; dir->i_nlink++; - inode->i_nlink = 2; /* no need to mark them dirty */ + inode->i_nlink = 2; /* no need to mark them dirty */ res = fat_new_dir(inode, dir, 0); if (res) @@ -392,7 +416,7 @@ out_unlock: mkdir_error: inode->i_nlink = 0; - inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME; + inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME_SEC; dir->i_nlink--; mark_inode_dirty(inode); mark_inode_dirty(dir); @@ -430,7 +454,7 @@ static int msdos_unlink(struct inode *dir, struct dentry *dentry) fat_detach(inode); brelse(bh); inode->i_nlink = 0; - inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME; + inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME_SEC; mark_inode_dirty(inode); mark_inode_dirty(dir); res = 0; @@ -440,14 +464,16 @@ unlink_done: } static int do_msdos_rename(struct inode *old_dir, unsigned char *old_name, - struct dentry *old_dentry, - struct inode *new_dir, unsigned char *new_name, struct dentry *new_dentry, - struct buffer_head *old_bh, - struct msdos_dir_entry *old_de, loff_t old_i_pos, int is_hid) + struct dentry *old_dentry, + struct inode *new_dir, unsigned char *new_name, + struct dentry *new_dentry, + struct buffer_head *old_bh, + struct msdos_dir_entry *old_de, loff_t old_i_pos, + int is_hid) { - struct buffer_head *new_bh=NULL,*dotdot_bh=NULL; - struct msdos_dir_entry *new_de,*dotdot_de; - struct inode *old_inode,*new_inode; + struct buffer_head *new_bh = NULL, *dotdot_bh = NULL; + struct msdos_dir_entry *new_de, *dotdot_de; + struct inode *old_inode, *new_inode; loff_t new_i_pos, dotdot_i_pos; int error; int is_dir; @@ -456,8 +482,8 @@ static int do_msdos_rename(struct inode *old_dir, unsigned char *old_name, new_inode = new_dentry->d_inode; is_dir = S_ISDIR(old_inode->i_mode); - if (fat_scan(new_dir, new_name, &new_bh, &new_de, &new_i_pos) >= 0 - && !new_inode) + if (fat_scan(new_dir, new_name, &new_bh, &new_de, &new_i_pos) >= 0 && + !new_inode) goto degenerate_case; if (is_dir) { if (new_inode) { @@ -493,16 +519,17 @@ static int do_msdos_rename(struct inode *old_dir, unsigned char *old_name, MSDOS_I(old_inode)->i_attrs &= ~ATTR_HIDDEN; mark_inode_dirty(old_inode); old_dir->i_version++; - old_dir->i_ctime = old_dir->i_mtime = CURRENT_TIME; + old_dir->i_ctime = old_dir->i_mtime = CURRENT_TIME_SEC; mark_inode_dirty(old_dir); if (new_inode) { new_inode->i_nlink--; - new_inode->i_ctime = CURRENT_TIME; + new_inode->i_ctime = CURRENT_TIME_SEC; mark_inode_dirty(new_inode); } if (dotdot_bh) { - dotdot_de->start = CT_LE_W(MSDOS_I(new_dir)->i_logstart); - dotdot_de->starthi = CT_LE_W((MSDOS_I(new_dir)->i_logstart) >> 16); + dotdot_de->start = cpu_to_le16(MSDOS_I(new_dir)->i_logstart); + dotdot_de->starthi = + cpu_to_le16((MSDOS_I(new_dir)->i_logstart) >> 16); mark_buffer_dirty(dotdot_bh); old_dir->i_nlink--; mark_inode_dirty(old_dir); @@ -522,7 +549,7 @@ out: degenerate_case: error = -EINVAL; - if (new_de!=old_de) + if (new_de != old_de) goto out; if (is_hid) MSDOS_I(old_inode)->i_attrs |= ATTR_HIDDEN; @@ -530,14 +557,14 @@ degenerate_case: MSDOS_I(old_inode)->i_attrs &= ~ATTR_HIDDEN; mark_inode_dirty(old_inode); old_dir->i_version++; - old_dir->i_ctime = old_dir->i_mtime = CURRENT_TIME; + old_dir->i_ctime = old_dir->i_mtime = CURRENT_TIME_SEC; mark_inode_dirty(old_dir); return 0; } /***** Rename, a wrapper for rename_same_dir & rename_diff_dir */ static int msdos_rename(struct inode *old_dir, struct dentry *old_dentry, - struct inode *new_dir, struct dentry *new_dentry) + struct inode *new_dir, struct dentry *new_dentry) { struct buffer_head *old_bh; struct msdos_dir_entry *old_de; @@ -547,18 +574,21 @@ static int msdos_rename(struct inode *old_dir, struct dentry *old_dentry, lock_kernel(); error = msdos_format_name(old_dentry->d_name.name, - old_dentry->d_name.len,old_msdos_name, + old_dentry->d_name.len, old_msdos_name, &MSDOS_SB(old_dir->i_sb)->options); if (error < 0) goto rename_done; error = msdos_format_name(new_dentry->d_name.name, - new_dentry->d_name.len,new_msdos_name, + new_dentry->d_name.len, new_msdos_name, &MSDOS_SB(new_dir->i_sb)->options); if (error < 0) goto rename_done; - is_hid = (new_dentry->d_name.name[0]=='.') && (new_msdos_name[0]!='.'); - old_hid = (old_dentry->d_name.name[0]=='.') && (old_msdos_name[0]!='.'); + is_hid = + (new_dentry->d_name.name[0] == '.') && (new_msdos_name[0] != '.'); + old_hid = + (old_dentry->d_name.name[0] == '.') && (old_msdos_name[0] != '.'); + error = fat_scan(old_dir, old_msdos_name, &old_bh, &old_de, &old_i_pos); if (error < 0) goto rename_done; @@ -583,7 +613,7 @@ static struct inode_operations msdos_dir_inode_operations = { .setattr = fat_notify_change, }; -static int msdos_fill_super(struct super_block *sb,void *data, int silent) +static int msdos_fill_super(struct super_block *sb, void *data, int silent) { int res; @@ -596,7 +626,8 @@ static int msdos_fill_super(struct super_block *sb,void *data, int silent) } static struct super_block *msdos_get_sb(struct file_system_type *fs_type, - int flags, const char *dev_name, void *data) + int flags, const char *dev_name, + void *data) { return get_sb_bdev(fs_type, flags, dev_name, data, msdos_fill_super); }