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

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