root/fs/msdos/namei.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. msdos_format_name
  2. msdos_find
  3. msdos_lookup
  4. msdos_create_entry
  5. msdos_create
  6. dump_fat
  7. msdos_mkdir
  8. msdos_empty
  9. msdos_rmdir
  10. msdos_unlinkx
  11. msdos_unlink
  12. msdos_unlink_umsdos
  13. rename_same_dir
  14. rename_diff_dir
  15. msdos_rename

   1 /*
   2  *  linux/fs/msdos/namei.c
   3  *
   4  *  Written 1992,1993 by Werner Almesberger
   5  */
   6 
   7 #include <asm/segment.h>
   8 
   9 #include <linux/sched.h>
  10 #include <linux/msdos_fs.h>
  11 #include <linux/kernel.h>
  12 #include <linux/errno.h>
  13 #include <linux/string.h>
  14 #include <linux/stat.h>
  15 
  16 #include "msbuffer.h"
  17 
  18 #define PRINTK(x)
  19 
  20 /* MS-DOS "device special files" */
  21 
  22 static char *reserved_names[] = {
  23     "CON     ","PRN     ","NUL     ","AUX     ",
  24     "LPT1    ","LPT2    ","LPT3    ","LPT4    ",
  25     "COM1    ","COM2    ","COM3    ","COM4    ",
  26     NULL };
  27 
  28 
  29 /* Characters that are undesirable in an MS-DOS file name */
  30   
  31 static char bad_chars[] = "*?<>|\"";
  32 static char bad_if_strict[] = "+=,; ";
  33 
  34 
  35 /* Formats an MS-DOS file name. Rejects invalid names. */
  36 
  37 static int msdos_format_name(char conv,const char *name,int len,char *res,
     /* [previous][next][first][last][top][bottom][index][help] */
  38   int dot_dirs)
  39 {
  40         char *walk,**reserved;
  41         unsigned char c;
  42         int space;
  43 
  44         if (IS_FREE(name)) return -EINVAL;
  45         if (name[0] == '.' && (len == 1 || (len == 2 && name[1] == '.'))) {
  46                 if (!dot_dirs) return -EEXIST;
  47                 memset(res+1,' ',10);
  48                 while (len--) *res++ = '.';
  49                 return 0;
  50         }
  51         space = 1; /* disallow names starting with a dot */
  52         c = 0;
  53         for (walk = res; len && walk-res < 8; walk++) {
  54                 c = *name++;
  55                 len--;
  56                 if (conv != 'r' && strchr(bad_chars,c)) return -EINVAL;
  57                 if (conv == 's' && strchr(bad_if_strict,c)) return -EINVAL;
  58                 if (c >= 'A' && c <= 'Z' && conv == 's') return -EINVAL;
  59                 if (c < ' ' || c == ':' || c == '\\') return -EINVAL;
  60                 if (c == '.') break;
  61                 space = c == ' ';
  62                 *walk = c >= 'a' && c <= 'z' ? c-32 : c;
  63         }
  64         if (space) return -EINVAL;
  65         if (conv == 's' && len && c != '.') {
  66                 c = *name++;
  67                 len--;
  68                 if (c != '.') return -EINVAL;
  69         }
  70         while (c != '.' && len--) c = *name++;
  71         if (c == '.') {
  72                 while (walk-res < 8) *walk++ = ' ';
  73                 while (len > 0 && walk-res < MSDOS_NAME) {
  74                         c = *name++;
  75                         len--;
  76                         if (conv != 'r' && strchr(bad_chars,c)) return -EINVAL;
  77                         if (conv == 's' && strchr(bad_if_strict,c))
  78                                 return -EINVAL;
  79                         if (c < ' ' || c == ':' || c == '\\' || c == '.')
  80                                 return -EINVAL;
  81                         if (c >= 'A' && c <= 'Z' && conv == 's') return -EINVAL;
  82                         space = c == ' ';
  83                         *walk++ = c >= 'a' && c <= 'z' ? c-32 : c;
  84                 }
  85                 if (space) return -EINVAL;
  86                 if (conv == 's' && len) return -EINVAL;
  87         }
  88         while (walk-res < MSDOS_NAME) *walk++ = ' ';
  89         for (reserved = reserved_names; *reserved; reserved++)
  90                 if (!strncmp(res,*reserved,8)) return -EINVAL;
  91         return 0;
  92 }
  93 
  94 
  95 /* Locates a directory entry. */
  96 
  97 static int msdos_find(struct inode *dir,const char *name,int len,
     /* [previous][next][first][last][top][bottom][index][help] */
  98     struct buffer_head **bh,struct msdos_dir_entry **de,int *ino)
  99 {
 100         char msdos_name[MSDOS_NAME];
 101         int res;
 102 
 103         if ((res = msdos_format_name(MSDOS_SB(dir->i_sb)->name_check,name,len,
 104             msdos_name,1)) < 0) return res;
 105         return msdos_scan(dir,msdos_name,bh,de,ino);
 106 }
 107 
 108 
 109 int msdos_lookup(struct inode *dir,const char *name,int len,
     /* [previous][next][first][last][top][bottom][index][help] */
 110     struct inode **result)
 111 {
 112         struct super_block *sb = dir->i_sb;
 113         int ino,res;
 114         struct msdos_dir_entry *de;
 115         struct buffer_head *bh;
 116         struct inode *next;
 117         
 118         PRINTK (("msdos_lookup\n"));
 119 
 120         *result = NULL;
 121         if (!dir) return -ENOENT;
 122         if (!S_ISDIR(dir->i_mode)) {
 123                 iput(dir);
 124                 return -ENOENT;
 125         }
 126         PRINTK (("msdos_lookup 2\n"));
 127         if (len == 1 && name[0] == '.') {
 128                 *result = dir;
 129                 return 0;
 130         }
 131         if (len == 2 && name[0] == '.' && name[1] == '.') {
 132                 ino = msdos_parent_ino(dir,0);
 133                 iput(dir);
 134                 if (ino < 0) return ino;
 135                 if (!(*result = iget(dir->i_sb,ino))) return -EACCES;
 136                 return 0;
 137         }
 138         PRINTK (("msdos_lookup 3\n"));
 139         if ((res = msdos_find(dir,name,len,&bh,&de,&ino)) < 0) {
 140                 iput(dir);
 141                 return res;
 142         }
 143         PRINTK (("msdos_lookup 4\n"));
 144         if (bh) brelse(bh);
 145         PRINTK (("msdos_lookup 4.5\n"));
 146 /* printk("lookup: ino=%d\n",ino); */
 147         if (!(*result = iget(dir->i_sb,ino))) {
 148                 iput(dir);
 149                 return -EACCES;
 150         }
 151         PRINTK (("msdos_lookup 5\n"));
 152         if (MSDOS_I(*result)->i_busy) { /* mkdir in progress */
 153                 iput(*result);
 154                 iput(dir);
 155                 return -ENOENT;
 156         }
 157         PRINTK (("msdos_lookup 6\n"));
 158         while (MSDOS_I(*result)->i_old) {
 159                 next = MSDOS_I(*result)->i_old;
 160                 iput(*result);
 161                 if (!(*result = iget(next->i_sb,next->i_ino))) {
 162                         fs_panic(dir->i_sb,"msdos_lookup: Can't happen");
 163                         iput(dir);
 164                         return -ENOENT;
 165                 }
 166         }
 167         PRINTK (("msdos_lookup 7\n"));
 168         iput(dir);
 169         PRINTK (("msdos_lookup 8\n"));
 170         return 0;
 171 }
 172 
 173 
 174 /* Creates a directory entry (name is already formatted). */
 175 
 176 static int msdos_create_entry(struct inode *dir,char *name,int is_dir,
     /* [previous][next][first][last][top][bottom][index][help] */
 177     struct inode **result)
 178 {
 179         struct super_block *sb = dir->i_sb;
 180         struct buffer_head *bh;
 181         struct msdos_dir_entry *de;
 182         int res,ino;
 183 
 184         if ((res = msdos_scan(dir,NULL,&bh,&de,&ino)) < 0) {
 185                 if (res != -ENOENT) return res;
 186                 if (dir->i_ino == MSDOS_ROOT_INO) return -ENOSPC;
 187                 if ((res = msdos_add_cluster(dir)) < 0) return res;
 188                 if ((res = msdos_scan(dir,NULL,&bh,&de,&ino)) < 0) return res;
 189         }
 190         /*
 191          * XXX all times should be set by caller upon successful completion.
 192          */
 193         dir->i_ctime = dir->i_mtime = CURRENT_TIME;
 194         dir->i_dirt = 1;
 195         memcpy(de->name,name,MSDOS_NAME);
 196         memset(de->unused, 0, sizeof(de->unused));
 197         de->attr = is_dir ? ATTR_DIR : ATTR_ARCH;
 198         de->start = 0;
 199         date_unix2dos(dir->i_mtime,&de->time,&de->date);
 200         de->size = 0;
 201         mark_buffer_dirty(bh, 1);
 202         if ((*result = iget(dir->i_sb,ino)) != NULL)
 203                 msdos_read_inode(*result);
 204         brelse(bh);
 205         if (!*result) return -EIO;
 206         (*result)->i_mtime = (*result)->i_atime = (*result)->i_ctime =
 207             CURRENT_TIME;
 208         (*result)->i_dirt = 1;
 209         return 0;
 210 }
 211 
 212 
 213 int msdos_create(struct inode *dir,const char *name,int len,int mode,
     /* [previous][next][first][last][top][bottom][index][help] */
 214         struct inode **result)
 215 {
 216         struct super_block *sb = dir->i_sb;
 217         struct buffer_head *bh;
 218         struct msdos_dir_entry *de;
 219         char msdos_name[MSDOS_NAME];
 220         int ino,res;
 221 
 222         if (!dir) return -ENOENT;
 223         if ((res = msdos_format_name(MSDOS_SB(dir->i_sb)->name_check,name,len,
 224             msdos_name,0)) < 0) {
 225                 iput(dir);
 226                 return res;
 227         }
 228         lock_creation();
 229         if (msdos_scan(dir,msdos_name,&bh,&de,&ino) >= 0) {
 230                 unlock_creation();
 231                 brelse(bh);
 232                 iput(dir);
 233                 return -EEXIST;
 234         }
 235         res = msdos_create_entry(dir,msdos_name,S_ISDIR(mode),result);
 236         unlock_creation();
 237         iput(dir);
 238         return res;
 239 }
 240 
 241 
 242 #ifdef DEBUG
 243 
 244 static void dump_fat(struct super_block *sb,int start)
     /* [previous][next][first][last][top][bottom][index][help] */
 245 {
 246         printk("[");
 247         while (start) {
 248                 printk("%d ",start);
 249                 start = fat_access(sb,start,-1);
 250                 if (!start) {
 251                         printk("ERROR");
 252                         break;
 253                 }
 254                 if (start == -1) break;
 255         }
 256         printk("]\n");
 257 }
 258 
 259 #endif
 260 
 261 
 262 int msdos_mkdir(struct inode *dir,const char *name,int len,int mode)
     /* [previous][next][first][last][top][bottom][index][help] */
 263 {
 264         struct super_block *sb = dir->i_sb;
 265         struct buffer_head *bh;
 266         struct msdos_dir_entry *de;
 267         struct inode *inode,*dot;
 268         char msdos_name[MSDOS_NAME];
 269         int ino,res;
 270 
 271         if ((res = msdos_format_name(MSDOS_SB(dir->i_sb)->name_check,name,len,
 272             msdos_name,0)) < 0) {
 273                 iput(dir);
 274                 return res;
 275         }
 276         lock_creation();
 277         if (msdos_scan(dir,msdos_name,&bh,&de,&ino) >= 0) {
 278                 unlock_creation();
 279                 brelse(bh);
 280                 iput(dir);
 281                 return -EEXIST;
 282         }
 283         if ((res = msdos_create_entry(dir,msdos_name,1,&inode)) < 0) {
 284                 unlock_creation();
 285                 iput(dir);
 286                 return res;
 287         }
 288         dir->i_nlink++;
 289         inode->i_nlink = 2; /* no need to mark them dirty */
 290         MSDOS_I(inode)->i_busy = 1; /* prevent lookups */
 291         if ((res = msdos_add_cluster(inode)) < 0) goto mkdir_error;
 292         if ((res = msdos_create_entry(inode,MSDOS_DOT,1,&dot)) < 0)
 293                 goto mkdir_error;
 294         dot->i_size = inode->i_size; /* doesn't grow in the 2nd create_entry */
 295         MSDOS_I(dot)->i_start = MSDOS_I(inode)->i_start;
 296         dot->i_nlink = inode->i_nlink;
 297         dot->i_dirt = 1;
 298         iput(dot);
 299         if ((res = msdos_create_entry(inode,MSDOS_DOTDOT,1,&dot)) < 0)
 300                 goto mkdir_error;
 301         unlock_creation();
 302         dot->i_size = dir->i_size;
 303         MSDOS_I(dot)->i_start = MSDOS_I(dir)->i_start;
 304         dot->i_nlink = dir->i_nlink;
 305         dot->i_dirt = 1;
 306         MSDOS_I(inode)->i_busy = 0;
 307         iput(dot);
 308         iput(inode);
 309         iput(dir);
 310         return 0;
 311 mkdir_error:
 312         iput(inode);
 313         if (msdos_rmdir(dir,name,len) < 0)
 314                 fs_panic(dir->i_sb,"rmdir in mkdir failed");
 315         unlock_creation();
 316         return res;
 317 }
 318 
 319 
 320 static int msdos_empty(struct inode *dir)
     /* [previous][next][first][last][top][bottom][index][help] */
 321 {
 322         struct super_block *sb = dir->i_sb;
 323         loff_t pos;
 324         struct buffer_head *bh;
 325         struct msdos_dir_entry *de;
 326 
 327         if (dir->i_count > 1)
 328                 return -EBUSY;
 329         if (MSDOS_I(dir)->i_start) { /* may be zero in mkdir */
 330                 pos = 0;
 331                 bh = NULL;
 332                 while (msdos_get_entry(dir,&pos,&bh,&de) > -1)
 333                         if (!IS_FREE(de->name) && strncmp(de->name,MSDOS_DOT,
 334                             MSDOS_NAME) && strncmp(de->name,MSDOS_DOTDOT,
 335                             MSDOS_NAME)) {
 336                                 brelse(bh);
 337                                 return -ENOTEMPTY;
 338                         }
 339                 if (bh)
 340                         brelse(bh);
 341         }
 342         return 0;
 343 }
 344 
 345 
 346 int msdos_rmdir(struct inode *dir,const char *name,int len)
     /* [previous][next][first][last][top][bottom][index][help] */
 347 {
 348         struct super_block *sb = dir->i_sb;
 349         int res,ino;
 350         struct buffer_head *bh;
 351         struct msdos_dir_entry *de;
 352         struct inode *inode;
 353 
 354         bh = NULL;
 355         inode = NULL;
 356         res = -EPERM;
 357         if (name[0] == '.' && (len == 1 || (len == 2 && name[1] == '.')))
 358                 goto rmdir_done;
 359         if ((res = msdos_find(dir,name,len,&bh,&de,&ino)) < 0) goto rmdir_done;
 360         res = -ENOENT;
 361         if (!(inode = iget(dir->i_sb,ino))) goto rmdir_done;
 362         res = -ENOTDIR;
 363         if (!S_ISDIR(inode->i_mode)) goto rmdir_done;
 364         res = -EBUSY;
 365         if (dir->i_dev != inode->i_dev || dir == inode) goto rmdir_done;
 366         res = msdos_empty(inode);
 367         if (res)
 368                 goto rmdir_done;
 369         inode->i_nlink = 0;
 370         inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
 371         dir->i_nlink--;
 372         inode->i_dirt = dir->i_dirt = 1;
 373         de->name[0] = DELETED_FLAG;
 374         mark_buffer_dirty(bh, 1);
 375         res = 0;
 376 rmdir_done:
 377         brelse(bh);
 378         iput(dir);
 379         iput(inode);
 380         return res;
 381 }
 382 
 383 
 384 static int msdos_unlinkx(
     /* [previous][next][first][last][top][bottom][index][help] */
 385         struct inode *dir,
 386         const char *name,
 387         int len,
 388         int nospc)      /* Flag special file ? */
 389 {
 390         struct super_block *sb = dir->i_sb;
 391         int res,ino;
 392         struct buffer_head *bh;
 393         struct msdos_dir_entry *de;
 394         struct inode *inode;
 395 
 396         bh = NULL;
 397         inode = NULL;
 398         if ((res = msdos_find(dir,name,len,&bh,&de,&ino)) < 0)
 399                 goto unlink_done;
 400         if (!(inode = iget(dir->i_sb,ino))) {
 401                 res = -ENOENT;
 402                 goto unlink_done;
 403         }
 404         if (!S_ISREG(inode->i_mode) && nospc){
 405                 res = -EPERM;
 406                 goto unlink_done;
 407         }
 408         inode->i_nlink = 0;
 409         inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
 410         MSDOS_I(inode)->i_busy = 1;
 411         inode->i_dirt = dir->i_dirt = 1;
 412         de->name[0] = DELETED_FLAG;
 413         mark_buffer_dirty(bh, 1);
 414 unlink_done:
 415         brelse(bh);
 416         iput(inode);
 417         iput(dir);
 418         return res;
 419 }
 420 
 421 int msdos_unlink(struct inode *dir,const char *name,int len)
     /* [previous][next][first][last][top][bottom][index][help] */
 422 {
 423         return msdos_unlinkx (dir,name,len,1);
 424 }
 425 /*
 426         Special entry for umsdos
 427 */
 428 int msdos_unlink_umsdos(struct inode *dir,const char *name,int len)
     /* [previous][next][first][last][top][bottom][index][help] */
 429 {
 430         return msdos_unlinkx (dir,name,len,0);
 431 }
 432 
 433 static int rename_same_dir(struct inode *old_dir,char *old_name,
     /* [previous][next][first][last][top][bottom][index][help] */
 434     struct inode *new_dir,char *new_name,struct buffer_head *old_bh,
 435     struct msdos_dir_entry *old_de,int old_ino)
 436 {
 437         struct super_block *sb = old_dir->i_sb;
 438         struct buffer_head *new_bh;
 439         struct msdos_dir_entry *new_de;
 440         struct inode *new_inode,*old_inode;
 441         int new_ino,exists,error;
 442 
 443         if (!strncmp(old_name,new_name,MSDOS_NAME)) return 0;
 444         exists = msdos_scan(new_dir,new_name,&new_bh,&new_de,&new_ino) >= 0;
 445         if (*(unsigned char *) old_de->name == DELETED_FLAG) {
 446                 if (exists) brelse(new_bh);
 447                 return -ENOENT;
 448         }
 449         if (exists) {
 450                 if (!(new_inode = iget(new_dir->i_sb,new_ino))) {
 451                         brelse(new_bh);
 452                         return -EIO;
 453                 }
 454                 error = S_ISDIR(new_inode->i_mode) ? (old_de->attr & ATTR_DIR) ?
 455                     msdos_empty(new_inode) : -EPERM : (old_de->attr & ATTR_DIR)
 456                     ? -EPERM : 0;
 457                 if (error) {
 458                         iput(new_inode);
 459                         brelse(new_bh);
 460                         return error;
 461                 }
 462                 if (S_ISDIR(new_inode->i_mode)) {
 463                         new_dir->i_nlink--;
 464                         new_dir->i_dirt = 1;
 465                 }
 466                 new_inode->i_nlink = 0;
 467                 MSDOS_I(new_inode)->i_busy = 1;
 468                 new_inode->i_dirt = 1;
 469                 new_de->name[0] = DELETED_FLAG;
 470                 mark_buffer_dirty(new_bh, 1);
 471                 iput(new_inode);
 472                 brelse(new_bh);
 473         }
 474         memcpy(old_de->name,new_name,MSDOS_NAME);
 475         mark_buffer_dirty(old_bh, 1);
 476         if (MSDOS_SB(old_dir->i_sb)->conversion == 'a') /* update binary info */
 477                 if ((old_inode = iget(old_dir->i_sb,old_ino)) != NULL) {
 478                         msdos_read_inode(old_inode);
 479                         iput(old_inode);
 480                 }
 481         return 0;
 482 }
 483 
 484 
 485 static int rename_diff_dir(struct inode *old_dir,char *old_name,
     /* [previous][next][first][last][top][bottom][index][help] */
 486     struct inode *new_dir,char *new_name,struct buffer_head *old_bh,
 487     struct msdos_dir_entry *old_de,int old_ino)
 488 {
 489         struct super_block *sb = old_dir->i_sb;
 490         struct buffer_head *new_bh,*free_bh,*dotdot_bh;
 491         struct msdos_dir_entry *new_de,*free_de,*dotdot_de;
 492         struct inode *old_inode,*new_inode,*free_inode,*dotdot_inode,*walk;
 493         int new_ino,free_ino,dotdot_ino;
 494         int error,exists,ino;
 495 
 496         if (old_dir->i_dev != new_dir->i_dev) return -EINVAL;
 497         if (old_ino == new_dir->i_ino) return -EINVAL;
 498         if (!(walk = iget(new_dir->i_sb,new_dir->i_ino))) return -EIO;
 499         while (walk->i_ino != MSDOS_ROOT_INO) {
 500                 ino = msdos_parent_ino(walk,1);
 501                 iput(walk);
 502                 if (ino < 0) return ino;
 503                 if (ino == old_ino) return -EINVAL;
 504                 if (!(walk = iget(new_dir->i_sb,ino))) return -EIO;
 505         }
 506         iput(walk);
 507         while ((error = msdos_scan(new_dir,NULL,&free_bh,&free_de,&free_ino)) <
 508              0) {
 509                 if (error != -ENOENT) return error;
 510                 error = msdos_add_cluster(new_dir);
 511                 if (error) return error;
 512         }
 513         exists = msdos_scan(new_dir,new_name,&new_bh,&new_de,&new_ino) >= 0;
 514         if (!(old_inode = iget(old_dir->i_sb,old_ino))) {
 515                 brelse(free_bh);
 516                 if (exists) brelse(new_bh);
 517                 return -EIO;
 518         }
 519         if (*(unsigned char *) old_de->name == DELETED_FLAG) {
 520                 iput(old_inode);
 521                 brelse(free_bh);
 522                 if (exists) brelse(new_bh);
 523                 return -ENOENT;
 524         }
 525         new_inode = NULL; /* to make GCC happy */
 526         if (exists) {
 527                 if (!(new_inode = iget(new_dir->i_sb,new_ino))) {
 528                         iput(old_inode);
 529                         brelse(new_bh);
 530                         return -EIO;
 531                 }
 532                 error = S_ISDIR(new_inode->i_mode) ? (old_de->attr & ATTR_DIR) ?
 533                     msdos_empty(new_inode) : -EPERM : (old_de->attr & ATTR_DIR)
 534                     ? -EPERM : 0;
 535                 if (error) {
 536                         iput(new_inode);
 537                         iput(old_inode);
 538                         brelse(new_bh);
 539                         return error;
 540                 }
 541                 new_inode->i_nlink = 0;
 542                 MSDOS_I(new_inode)->i_busy = 1;
 543                 new_inode->i_dirt = 1;
 544                 new_de->name[0] = DELETED_FLAG;
 545                 mark_buffer_dirty(new_bh, 1);
 546         }
 547         memcpy(free_de,old_de,sizeof(struct msdos_dir_entry));
 548         memcpy(free_de->name,new_name,MSDOS_NAME);
 549         if (!(free_inode = iget(new_dir->i_sb,free_ino))) {
 550                 free_de->name[0] = DELETED_FLAG;
 551 /*  Don't mark free_bh as dirty. Both states are supposed to be equivalent. */
 552                 brelse(free_bh);
 553                 if (exists) {
 554                         iput(new_inode);
 555                         brelse(new_bh);
 556                 }
 557                 return -EIO;
 558         }
 559         if (exists && S_ISDIR(new_inode->i_mode)) {
 560                 new_dir->i_nlink--;
 561                 new_dir->i_dirt = 1;
 562         }
 563         msdos_read_inode(free_inode);
 564         MSDOS_I(old_inode)->i_busy = 1;
 565         cache_inval_inode(old_inode);
 566         old_inode->i_dirt = 1;
 567         old_de->name[0] = DELETED_FLAG;
 568         mark_buffer_dirty(old_bh, 1);
 569         mark_buffer_dirty(free_bh, 1);
 570         if (!exists) iput(free_inode);
 571         else {
 572                 MSDOS_I(new_inode)->i_depend = free_inode;
 573                 MSDOS_I(free_inode)->i_old = new_inode;
 574                 /* free_inode is put when putting new_inode */
 575                 iput(new_inode);
 576                 brelse(new_bh);
 577         }
 578         if (S_ISDIR(old_inode->i_mode)) {
 579                 if ((error = msdos_scan(old_inode,MSDOS_DOTDOT,&dotdot_bh,
 580                     &dotdot_de,&dotdot_ino)) < 0) goto rename_done;
 581                 if (!(dotdot_inode = iget(old_inode->i_sb,dotdot_ino))) {
 582                         brelse(dotdot_bh);
 583                         error = -EIO;
 584                         goto rename_done;
 585                 }
 586                 dotdot_de->start = MSDOS_I(dotdot_inode)->i_start =
 587                     MSDOS_I(new_dir)->i_start;
 588                 dotdot_inode->i_dirt = 1;
 589                 mark_buffer_dirty(dotdot_bh, 1);
 590                 old_dir->i_nlink--;
 591                 new_dir->i_nlink++;
 592                 /* no need to mark them dirty */
 593                 dotdot_inode->i_nlink = new_dir->i_nlink;
 594                 iput(dotdot_inode);
 595                 brelse(dotdot_bh);
 596         }
 597         error = 0;
 598 rename_done:
 599         brelse(free_bh);
 600         iput(old_inode);
 601         return error;
 602 }
 603 
 604 
 605 int msdos_rename(struct inode *old_dir,const char *old_name,int old_len,
     /* [previous][next][first][last][top][bottom][index][help] */
 606         struct inode *new_dir,const char *new_name,int new_len)
 607 {
 608         struct super_block *sb = old_dir->i_sb;
 609         char old_msdos_name[MSDOS_NAME],new_msdos_name[MSDOS_NAME];
 610         struct buffer_head *old_bh;
 611         struct msdos_dir_entry *old_de;
 612         int old_ino,error;
 613 
 614         if ((error = msdos_format_name(MSDOS_SB(old_dir->i_sb)->name_check,
 615             old_name,old_len,old_msdos_name,1)) < 0) goto rename_done;
 616         if ((error = msdos_format_name(MSDOS_SB(new_dir->i_sb)->name_check,
 617             new_name,new_len,new_msdos_name,0)) < 0) goto rename_done;
 618         if ((error = msdos_scan(old_dir,old_msdos_name,&old_bh,&old_de,
 619             &old_ino)) < 0) goto rename_done;
 620         lock_creation();
 621         if (old_dir == new_dir)
 622                 error = rename_same_dir(old_dir,old_msdos_name,new_dir,
 623                     new_msdos_name,old_bh,old_de,old_ino);
 624         else error = rename_diff_dir(old_dir,old_msdos_name,new_dir,
 625                     new_msdos_name,old_bh,old_de,old_ino);
 626         unlock_creation();
 627         brelse(old_bh);
 628 rename_done:
 629         iput(old_dir);
 630         iput(new_dir);
 631         return error;
 632 }

/* [previous][next][first][last][top][bottom][index][help] */