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

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