vserver 1.9.5.x5
[linux-2.6.git] / fs / msdos / namei.c
index 817f57a..cb452cf 100644 (file)
 #include <linux/msdos_fs.h>
 #include <linux/smp_lock.h>
 
-
 /* 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);
 }