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

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