root/fs/ext2/namei.c

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

DEFINITIONS

This source file includes following definitions.
  1. ext2_match
  2. ext2_find_entry
  3. ext2_lookup
  4. ext2_add_entry
  5. ext2_delete_entry
  6. ext2_create
  7. ext2_mknod
  8. ext2_mkdir
  9. empty_dir
  10. ext2_rmdir
  11. ext2_unlink
  12. ext2_symlink
  13. ext2_link
  14. subdir
  15. do_ext2_rename
  16. ext2_rename

   1 /*
   2  *  linux/fs/ext2/namei.c
   3  *
   4  *  Copyright (C) 1992, 1993  Remy Card (card@masi.ibp.fr)
   5  *
   6  *  from
   7  *
   8  *  linux/fs/minix/namei.c
   9  *
  10  *  Copyright (C) 1991, 1992  Linus Torvalds
  11  */
  12 
  13 #include <linux/sched.h>
  14 #include <linux/ext2_fs.h>
  15 #include <linux/kernel.h>
  16 #include <linux/string.h>
  17 #include <linux/stat.h>
  18 #include <linux/fcntl.h>
  19 #include <linux/errno.h>
  20 
  21 #include <asm/segment.h>
  22 
  23 /*
  24  * comment out this line if you want names > EXT2_NAME_LEN chars to be
  25  * truncated. Else they will be disallowed.
  26  */
  27 /* #define NO_TRUNCATE */
  28         
  29 /*
  30  * ok, we cannot use strncmp, as the name is not in our data space.
  31  * Thus we'll have to use ext2_match. No big problem. ext2_match also makes
  32  * some sanity tests.
  33  *
  34  * NOTE! unlike strncmp, ext2_match returns 1 for success, 0 for failure.
  35  */
  36 static int ext2_match (int len, const char * const name,
     /* [previous][next][first][last][top][bottom][index][help] */
  37                        struct ext2_dir_entry * de)
  38 {
  39         unsigned char same;
  40 
  41         if (!de || !de->inode || len > EXT2_NAME_LEN)
  42                 return 0;
  43         /* "" means "." ---> so paths like "/usr/lib//libc.a" work */
  44         if (!len && de->name_len == 1 && (de->name[0] == '.') &&
  45            (de->name[1] == '\0'))
  46                 return 1;
  47         if (len != de->name_len)
  48                 return 0;
  49         __asm__("cld\n\t"
  50                 "repe ; cmpsb\n\t"
  51                 "setz %0"
  52                 :"=q" (same)
  53                 :"S" ((long) name), "D" ((long) de->name), "c" (len)
  54                 :"cx", "di", "si");
  55         return (int) same;
  56 }
  57 
  58 /*
  59  *      ext2_find_entry()
  60  *
  61  * finds an entry in the specified directory with the wanted name. It
  62  * returns the cache buffer in which the entry was found, and the entry
  63  * itself (as a parameter - res_dir). It does NOT read the inode of the
  64  * entry - you'll have to do that yourself if you want to.
  65  *
  66  * In the ext2 file system, this function also returns a pointer on the
  67  * previous directory entry because functions which remove directory
  68  * entries need it
  69  */
  70 static struct buffer_head * ext2_find_entry (struct inode * dir,
     /* [previous][next][first][last][top][bottom][index][help] */
  71                                              const char * const name, int namelen,
  72                                              struct ext2_dir_entry ** res_dir,
  73                                              struct ext2_dir_entry ** prev_dir)
  74 {
  75         long offset;
  76         struct buffer_head * bh;
  77         struct ext2_dir_entry * de;
  78         struct super_block * sb;
  79         int err;
  80 
  81         *res_dir = NULL;
  82         if (!dir)
  83                 return NULL;
  84         sb = dir->i_sb;
  85 #ifdef NO_TRUNCATE
  86         if (namelen > EXT2_NAME_LEN)
  87                 return NULL;
  88 #else
  89         if (namelen > EXT2_NAME_LEN)
  90                 namelen = EXT2_NAME_LEN;
  91 #endif
  92         bh = ext2_bread (dir, 0, 0, &err);
  93         if (!bh)
  94                 return NULL;
  95         if (prev_dir)
  96                 *prev_dir = NULL;
  97         offset = 0;
  98         de = (struct ext2_dir_entry *) bh->b_data;
  99         while (offset < dir->i_size) {
 100                 if (!bh || (char *)de >= sb->s_blocksize + bh->b_data) {
 101                         brelse (bh);
 102                         bh = ext2_bread (dir, offset >> EXT2_BLOCK_SIZE_BITS(sb), 0, &err);
 103                         if (!bh) {
 104                                 offset += sb->s_blocksize;
 105                                 continue;
 106                         }
 107                         de = (struct ext2_dir_entry *) bh->b_data;
 108                         if (prev_dir)
 109                                 *prev_dir = NULL;
 110                 }
 111                 if (! ext2_check_dir_entry ("ext2_find_entry", dir, de, bh,
 112                                             offset)) {
 113                         brelse (bh);
 114                         return NULL;
 115                 }
 116                 if (ext2_match (namelen, name, de)) {
 117                         *res_dir = de;
 118                         return bh;
 119                 }
 120                 offset += de->rec_len;
 121                 if (prev_dir)
 122                         *prev_dir = de;
 123                 de = (struct ext2_dir_entry *) ((char *) de + de->rec_len);
 124         }
 125         brelse (bh);
 126         return NULL;
 127 }
 128 
 129 int ext2_lookup (struct inode * dir, const char * name, int len,
     /* [previous][next][first][last][top][bottom][index][help] */
 130                  struct inode ** result)
 131 {
 132         int ino;
 133         struct ext2_dir_entry * de;
 134         struct buffer_head * bh;
 135 
 136         *result = NULL;
 137         if (!dir)
 138                 return -ENOENT;
 139         if (!S_ISDIR(dir->i_mode)) {
 140                 iput (dir);
 141                 return -ENOENT;
 142         }
 143 #ifndef DONT_USE_DCACHE
 144         if (!(ino = ext2_dcache_lookup (dir->i_dev, dir->i_ino, name, len))) {
 145 #endif
 146                 if (!(bh = ext2_find_entry (dir, name, len, &de, NULL))) {
 147                         iput (dir);
 148                         return -ENOENT;
 149                 }
 150                 ino = de->inode;
 151 #ifndef DONT_USE_DCACHE
 152                 ext2_dcache_add (dir->i_dev, dir->i_ino, de->name,
 153                                  de->name_len, ino);
 154 #endif
 155                 brelse (bh);
 156 #ifndef DONT_USE_DCACHE
 157         }
 158 #endif
 159         if (!(*result = iget (dir->i_sb, ino))) {
 160                 iput (dir);
 161                 return -EACCES;
 162         }
 163         iput (dir);
 164         return 0;
 165 }
 166 
 167 /*
 168  *      ext2_add_entry()
 169  *
 170  * adds a file entry to the specified directory, using the same
 171  * semantics as ext2_find_entry(). It returns NULL if it failed.
 172  *
 173  * NOTE!! The inode part of 'de' is left at 0 - which means you
 174  * may not sleep between calling this and putting something into
 175  * the entry, as someone else might have used it while you slept.
 176  */
 177 static struct buffer_head * ext2_add_entry (struct inode * dir,
     /* [previous][next][first][last][top][bottom][index][help] */
 178                                             const char * name, int namelen,
 179                                             struct ext2_dir_entry ** res_dir,
 180                                             int *err)
 181 {
 182         int i;
 183         long offset;
 184         unsigned short rec_len;
 185         struct buffer_head * bh;
 186         struct ext2_dir_entry * de, * de1;
 187         struct super_block * sb;
 188 
 189         *err = -EINVAL;
 190         *res_dir = NULL;
 191         if (!dir)
 192                 return NULL;
 193         sb = dir->i_sb;
 194 #ifdef NO_TRUNCATE
 195         if (namelen > EXT2_NAME_LEN)
 196                 return NULL;
 197 #else
 198         if (namelen > EXT2_NAME_LEN)
 199                 namelen = EXT2_NAME_LEN;
 200 #endif
 201         if (!namelen)
 202                 return NULL;
 203         bh = ext2_bread (dir, 0, 0, err);
 204         if (!bh)
 205                 return NULL;
 206         rec_len = EXT2_DIR_REC_LEN(namelen);
 207         offset = 0;
 208         de = (struct ext2_dir_entry *) bh->b_data;
 209         *err = -ENOSPC;
 210         while (1) {
 211                 if ((char *)de >= sb->s_blocksize + bh->b_data) {
 212                         brelse (bh);
 213                         bh = NULL;
 214                         bh = ext2_bread (dir, offset >> EXT2_BLOCK_SIZE_BITS(sb), 1, err);
 215                         if (!bh)
 216                                 return NULL;
 217                         if (dir->i_size <= offset) {
 218 #ifdef EXT2FS_DEBUG
 219                                 printk ("ext2_add_entry: creating next block\n");
 220 #endif
 221                                 de = (struct ext2_dir_entry *) bh->b_data;
 222                                 de->inode = 0;
 223                                 de->rec_len = sb->s_blocksize;
 224                                 dir->i_size = offset + sb->s_blocksize;
 225                                 dir->i_dirt = 1;
 226                                 dir->i_ctime = CURRENT_TIME;
 227                         } else {
 228 #ifdef EXT2FS_DEBUG
 229                                 printk ("ext2_add_entry: skipping to next block\n");
 230 #endif
 231                                 de = (struct ext2_dir_entry *) bh->b_data;
 232                         }
 233                 }
 234                 if (! ext2_check_dir_entry ("ext2_add_entry", dir, de, bh,
 235                                             offset)) {
 236                         *err = -ENOENT;
 237                         brelse (bh);
 238                         return NULL;
 239                 }
 240                 if (de->inode) {
 241                         if (ext2_match (namelen, name, de)) {
 242                                 *err = -EEXIST;
 243                                 brelse (bh);
 244                                 return NULL;
 245                         }
 246                 }
 247                 if ((!de->inode && de->rec_len >= rec_len) ||
 248                     (de->rec_len >= EXT2_DIR_REC_LEN(de->name_len) + rec_len)) {
 249                         offset += de->rec_len;
 250                         if (de->inode) {
 251                                 de1 = (struct ext2_dir_entry *) ((char *) de +
 252                                         EXT2_DIR_REC_LEN(de->name_len));
 253                                 de1->rec_len = de->rec_len -
 254                                         EXT2_DIR_REC_LEN(de->name_len);
 255                                 de->rec_len = EXT2_DIR_REC_LEN(de->name_len);
 256                                 de = de1;
 257                         }
 258                         de->inode = 0;
 259                         de->name_len = namelen;
 260                         for (i = 0; i < namelen ; i++)
 261                                 de->name[i] = name [i];
 262                         dir->i_mtime = dir->i_ctime = CURRENT_TIME;
 263                         bh->b_dirt = 1;
 264                         *res_dir = de;
 265                         return bh;
 266                 }
 267                 offset += de->rec_len;
 268                 de = (struct ext2_dir_entry *) ((char *) de + de->rec_len);
 269         }
 270         brelse (bh);
 271         return NULL;
 272 }
 273 
 274 /*
 275  * ext2_delete_entry deletes a directory entry by merging it with the
 276  * previous entry
 277  */
 278 static void ext2_delete_entry (struct ext2_dir_entry * dir,
     /* [previous][next][first][last][top][bottom][index][help] */
 279                                struct ext2_dir_entry * prev_dir)
 280 {
 281         if (prev_dir != NULL)
 282                 prev_dir->rec_len += dir->rec_len;
 283         else
 284                 dir->inode = 0;
 285 }
 286 
 287 int ext2_create (struct inode * dir,const char * name, int len, int mode,
     /* [previous][next][first][last][top][bottom][index][help] */
 288                  struct inode ** result)
 289 {
 290         struct inode * inode;
 291         struct buffer_head * bh;
 292         struct ext2_dir_entry * de;
 293         int err;
 294 
 295         *result = NULL;
 296         if (!dir)
 297                 return -ENOENT;
 298         inode = ext2_new_inode (dir, mode);
 299         if (!inode) {
 300                 iput (dir);
 301                 return -ENOSPC;
 302         }
 303         inode->i_op = &ext2_file_inode_operations;
 304         inode->i_mode = mode;
 305         inode->i_dirt = 1;
 306         bh = ext2_add_entry (dir, name, len, &de, &err);
 307         if (!bh) {
 308                 inode->i_nlink --;
 309                 inode->i_dirt = 1;
 310                 iput (inode);
 311                 iput (dir);
 312                 return err;
 313         }
 314         de->inode = inode->i_ino;
 315 #ifndef DONT_USE_DCACHE
 316         ext2_dcache_add (dir->i_dev, dir->i_ino, de->name, de->name_len,
 317                          de->inode);
 318 #endif
 319         bh->b_dirt = 1;
 320         brelse (bh);
 321         iput (dir);
 322         *result = inode;
 323         return 0;
 324 }
 325 
 326 int ext2_mknod (struct inode * dir, const char * name, int len, int mode,
     /* [previous][next][first][last][top][bottom][index][help] */
 327                 int rdev)
 328 {
 329         struct inode * inode;
 330         struct buffer_head * bh;
 331         struct ext2_dir_entry * de;
 332         int err;
 333 
 334         if (!dir)
 335                 return -ENOENT;
 336         bh = ext2_find_entry (dir, name, len, &de, NULL);
 337         if (bh) {
 338                 brelse (bh);
 339                 iput (dir);
 340                 return -EEXIST;
 341         }
 342         inode = ext2_new_inode (dir, mode);
 343         if (!inode) {
 344                 iput (dir);
 345                 return -ENOSPC;
 346         }
 347         inode->i_uid = current->euid;
 348         inode->i_mode = mode;
 349         inode->i_op = NULL;
 350         if (S_ISREG(inode->i_mode))
 351                 inode->i_op = &ext2_file_inode_operations;
 352         else if (S_ISDIR(inode->i_mode)) {
 353                 inode->i_op = &ext2_dir_inode_operations;
 354                 if (dir->i_mode & S_ISGID)
 355                         inode->i_mode |= S_ISGID;
 356         }
 357         else if (S_ISLNK(inode->i_mode))
 358                 inode->i_op = &ext2_symlink_inode_operations;
 359         else if (S_ISCHR(inode->i_mode))
 360                 inode->i_op = &chrdev_inode_operations;
 361         else if (S_ISBLK(inode->i_mode))
 362                 inode->i_op = &blkdev_inode_operations;
 363         else if (S_ISFIFO(inode->i_mode)) 
 364                 init_fifo(inode);
 365         if (S_ISBLK(mode) || S_ISCHR(mode))
 366                 inode->i_rdev = rdev;
 367         inode->i_mtime = inode->i_atime = CURRENT_TIME;
 368         inode->i_dirt = 1;
 369         bh = ext2_add_entry (dir, name, len, &de, &err);
 370         if (!bh) {
 371                 inode->i_nlink --;
 372                 inode->i_dirt = 1;
 373                 iput (inode);
 374                 iput (dir);
 375                 return err;
 376         }
 377         de->inode = inode->i_ino;
 378 #ifndef DONT_USE_DCACHE
 379         ext2_dcache_add (dir->i_dev, dir->i_ino, de->name, de->name_len,
 380                          de->inode);
 381 #endif
 382         bh->b_dirt = 1;
 383         brelse (bh);
 384         iput (dir);
 385         iput (inode);
 386         return 0;
 387 }
 388 
 389 int ext2_mkdir (struct inode * dir, const char * name, int len, int mode)
     /* [previous][next][first][last][top][bottom][index][help] */
 390 {
 391         struct inode * inode;
 392         struct buffer_head * bh, * dir_block;
 393         struct ext2_dir_entry * de;
 394         int err;
 395 
 396         if (!dir)
 397                 return -ENOENT;
 398         bh = ext2_find_entry (dir, name, len, &de, NULL);
 399         if (bh) {
 400                 brelse (bh);
 401                 iput (dir);
 402                 return -EEXIST;
 403         }
 404         if (dir->i_nlink >= EXT2_LINK_MAX) {
 405                 iput (dir);
 406                 return -EMLINK;
 407         }
 408         inode = ext2_new_inode (dir, S_IFDIR);
 409         if (!inode) {
 410                 iput (dir);
 411                 return -ENOSPC;
 412         }
 413         inode->i_op = &ext2_dir_inode_operations;
 414         inode->i_size = inode->i_sb->s_blocksize;
 415         inode->i_mtime = inode->i_atime = CURRENT_TIME;
 416         dir_block = ext2_bread (inode, 0, 1, &err);
 417         if (!dir_block) {
 418                 iput (dir);
 419                 inode->i_nlink --;
 420                 inode->i_dirt = 1;
 421                 iput (inode);
 422                 return err;
 423         }
 424         inode->i_blocks = inode->i_sb->s_blocksize / 512;
 425         de = (struct ext2_dir_entry *) dir_block->b_data;
 426         de->inode = inode->i_ino;
 427         de->name_len = 1;
 428         de->rec_len = EXT2_DIR_REC_LEN(de->name_len);
 429         strcpy (de->name, ".");
 430         de = (struct ext2_dir_entry *) ((char *) de + de->rec_len);
 431         de->inode = dir->i_ino;
 432         de->rec_len = inode->i_sb->s_blocksize - EXT2_DIR_REC_LEN(1);
 433         de->name_len = 2;
 434         strcpy (de->name, "..");
 435         inode->i_nlink = 2;
 436         dir_block->b_dirt = 1;
 437         brelse (dir_block);
 438         inode->i_mode = S_IFDIR | (mode & 0777 & ~current->umask);
 439         if (dir->i_mode & S_ISGID)
 440                 inode->i_mode |= S_ISGID;
 441         inode->i_dirt = 1;
 442         bh = ext2_add_entry (dir, name, len, &de, &err);
 443         if (!bh) {
 444                 iput (dir);
 445                 inode->i_nlink = 0;
 446                 iput (inode);
 447                 return err;
 448         }
 449         de->inode = inode->i_ino;
 450 #ifndef DONT_USE_DCACHE
 451         ext2_dcache_add (dir->i_dev, dir->i_ino, de->name, de->name_len,
 452                          de->inode);
 453 #endif
 454         bh->b_dirt = 1;
 455         dir->i_nlink ++;
 456         dir->i_dirt = 1;
 457         iput (dir);
 458         iput (inode);
 459         brelse (bh);
 460         return 0;
 461 }
 462 
 463 /*
 464  * routine to check that the specified directory is empty (for rmdir)
 465  */
 466 static int empty_dir (struct inode * inode)
     /* [previous][next][first][last][top][bottom][index][help] */
 467 {
 468         unsigned long offset;
 469         struct buffer_head * bh;
 470         struct ext2_dir_entry * de, * de1;
 471         struct super_block * sb;
 472         int err;
 473 
 474         sb = inode->i_sb;
 475         if (inode->i_size < EXT2_DIR_REC_LEN(1) + EXT2_DIR_REC_LEN(2) ||
 476             !(bh = ext2_bread (inode, 0, 0, &err))) {
 477                 printk ("warning - bad directory (dev %04x, dir %d)\n",
 478                         inode->i_dev, inode->i_ino);
 479                 return 1;
 480         }
 481         de = (struct ext2_dir_entry *) bh->b_data;
 482         de1 = (struct ext2_dir_entry *) ((char *) de + de->rec_len);
 483         if (de->inode != inode->i_ino || !de1->inode || 
 484             strcmp (".", de->name) || strcmp ("..", de1->name)) {
 485                 printk ("warning - bad directory (dev %04x, dir %d)\n",
 486                         inode->i_dev, inode->i_ino);
 487                 return 1;
 488         }
 489         offset = de->rec_len + de1->rec_len;
 490         de = (struct ext2_dir_entry *) ((char *) de1 + de1->rec_len);
 491         while (offset < inode->i_size ) {
 492                 if ((void *) de >= (void *) (bh->b_data + sb->s_blocksize)) {
 493                         brelse (bh);
 494                         bh = ext2_bread (inode, offset >> EXT2_BLOCK_SIZE_BITS(sb), 1, &err);
 495                         if (!bh) {
 496                                 offset += sb->s_blocksize;
 497                                 continue;
 498                         }
 499                         de = (struct ext2_dir_entry *) bh->b_data;
 500                 }
 501                 if (! ext2_check_dir_entry ("empty_dir", inode, de, bh,
 502                                             offset)) {
 503                         brelse (bh);
 504                         return 1;
 505                 }
 506                 if (de->inode) {
 507                         brelse (bh);
 508                         return 0;
 509                 }
 510                 offset += de->rec_len;
 511                 de = (struct ext2_dir_entry *) ((char *) de + de->rec_len);
 512         }
 513         brelse (bh);
 514         return 1;
 515 }
 516 
 517 int ext2_rmdir (struct inode * dir, const char * name, int len)
     /* [previous][next][first][last][top][bottom][index][help] */
 518 {
 519         int retval;
 520         struct inode * inode;
 521         struct buffer_head * bh;
 522         struct ext2_dir_entry * de, * pde;
 523 
 524         if (!dir)
 525                 return -ENOENT;
 526         inode = NULL;
 527         bh = ext2_find_entry (dir, name, len, &de, &pde);
 528         retval = -ENOENT;
 529         if (!bh)
 530                 goto end_rmdir;
 531         retval = -EPERM;
 532         if (!(inode = iget (dir->i_sb, de->inode)))
 533                 goto end_rmdir;
 534         if ((dir->i_mode & S_ISVTX) && current->euid &&
 535             inode->i_uid != current->euid)
 536                 goto end_rmdir;
 537         if (inode->i_dev != dir->i_dev)
 538                 goto end_rmdir;
 539         if (inode == dir)       /* we may not delete ".", but "../dir" is ok */
 540                 goto end_rmdir;
 541         if (!S_ISDIR(inode->i_mode)) {
 542                 retval = -ENOTDIR;
 543                 goto end_rmdir;
 544         }
 545         if (!empty_dir (inode)) {
 546                 retval = -ENOTEMPTY;
 547                 goto end_rmdir;
 548         }
 549         if (inode->i_count > 1) {
 550                 retval = -EBUSY;
 551                 goto end_rmdir;
 552         }
 553         if (inode->i_nlink != 2)
 554                 printk ("empty  directory has nlink!=2 (%d)\n", inode->i_nlink);
 555 #ifndef DONT_USE_DCACHE
 556         ext2_dcache_remove (dir->i_dev, dir->i_ino, de->name, de->name_len);
 557 #endif
 558         ext2_delete_entry (de, pde);
 559         bh->b_dirt = 1;
 560         inode->i_nlink = 0;
 561         inode->i_dirt = 1;
 562         dir->i_nlink --;
 563         dir->i_ctime = dir->i_mtime = CURRENT_TIME;
 564         dir->i_dirt = 1;
 565         retval = 0;
 566 end_rmdir:
 567         iput (dir);
 568         iput (inode);
 569         brelse (bh);
 570         return retval;
 571 }
 572 
 573 int ext2_unlink (struct inode * dir, const char * name, int len)
     /* [previous][next][first][last][top][bottom][index][help] */
 574 {
 575         int retval;
 576         struct inode * inode;
 577         struct buffer_head * bh;
 578         struct ext2_dir_entry * de, * pde;
 579 
 580         if (!dir)
 581                 return -ENOENT;
 582         retval = -ENOENT;
 583         inode = NULL;
 584         bh = ext2_find_entry (dir, name, len, &de, &pde);
 585         if (!bh)
 586                 goto end_unlink;
 587         if (!(inode = iget (dir->i_sb, de->inode)))
 588                 goto end_unlink;
 589         retval = -EPERM;
 590         if ((dir->i_mode & S_ISVTX) && !suser() &&
 591             current->euid != inode->i_uid &&
 592             current->euid != dir->i_uid)
 593                 goto end_unlink;
 594         if (S_ISDIR(inode->i_mode))
 595                 goto end_unlink;
 596         if (!inode->i_nlink) {
 597                 printk ("Deleting nonexistent file (%04x:%d), %d\n",
 598                         inode->i_dev, inode->i_ino, inode->i_nlink);
 599                 inode->i_nlink = 1;
 600         }
 601 #ifndef DONT_USE_DCACHE
 602         ext2_dcache_remove (dir->i_dev, dir->i_ino, de->name, de->name_len);
 603 #endif
 604         ext2_delete_entry (de, pde);
 605         bh->b_dirt = 1;
 606         dir->i_ctime = dir->i_mtime = CURRENT_TIME;
 607         dir->i_dirt = 1;
 608         inode->i_nlink --;
 609         inode->i_dirt = 1;
 610         inode->i_ctime = CURRENT_TIME;
 611         retval = 0;
 612 end_unlink:
 613         brelse (bh);
 614         iput (inode);
 615         iput (dir);
 616         return retval;
 617 }
 618 
 619 int ext2_symlink (struct inode * dir, const char * name, int len,
     /* [previous][next][first][last][top][bottom][index][help] */
 620                   const char * symname)
 621 {
 622         struct ext2_dir_entry * de;
 623         struct inode * inode = NULL;
 624         struct buffer_head * bh = NULL, * name_block = NULL;
 625         char * link;
 626         int i, err;
 627         int l;
 628         char c;
 629 
 630         if (!(inode = ext2_new_inode (dir, S_IFLNK))) {
 631                 iput (dir);
 632                 return -ENOSPC;
 633         }
 634         inode->i_mode = S_IFLNK | 0777;
 635         inode->i_op = &ext2_symlink_inode_operations;
 636         for (l = 0; l < inode->i_sb->s_blocksize - 1 &&
 637              symname [l]; l++)
 638                 ;
 639         if (l >= EXT2_N_BLOCKS * sizeof (unsigned long)) {
 640 #ifdef EXT2FS_DEBUG
 641                 printk ("ext2_symlink: l=%d, normal symlink\n", l);
 642 #endif
 643                 name_block = ext2_bread (inode, 0, 1, &err);
 644                 if (!name_block) {
 645                         iput (dir);
 646                         inode->i_nlink --;
 647                         inode->i_dirt = 1;
 648                         iput (inode);
 649                         return err;
 650                 }
 651                 link = name_block->b_data;
 652         } else {
 653                 link = (char *) inode->u.ext2_i.i_data;
 654 #ifdef EXT2FS_DEBUG
 655                 printk ("ext2_symlink: l=%d, fast symlink\n", l);
 656 #endif
 657         }
 658         i = 0;
 659         while (i < inode->i_sb->s_blocksize - 1 && (c = *(symname ++)))
 660                 link[i++] = c;
 661         link[i] = 0;
 662         if (name_block) {
 663                 name_block->b_dirt = 1;
 664                 brelse (name_block);
 665         }
 666         inode->i_size = i;
 667         inode->i_dirt = 1;
 668         bh = ext2_find_entry (dir, name, len, &de, NULL);
 669         if (bh) {
 670                 inode->i_nlink --;
 671                 inode->i_dirt = 1;
 672                 iput (inode);
 673                 brelse (bh);
 674                 iput (dir);
 675                 return -EEXIST;
 676         }
 677         bh = ext2_add_entry (dir, name, len, &de, &err);
 678         if (!bh) {
 679                 inode->i_nlink --;
 680                 inode->i_dirt = 1;
 681                 iput (inode);
 682                 iput (dir);
 683                 return err;
 684         }
 685         de->inode = inode->i_ino;
 686 #ifndef DONT_USE_DCACHE
 687         ext2_dcache_add (dir->i_dev, dir->i_ino, de->name, de->name_len,
 688                          de->inode);
 689 #endif
 690         bh->b_dirt = 1;
 691         brelse (bh);
 692         iput (dir);
 693         iput (inode);
 694         return 0;
 695 }
 696 
 697 int ext2_link (struct inode * oldinode, struct inode * dir,
     /* [previous][next][first][last][top][bottom][index][help] */
 698                const char * name, int len)
 699 {
 700         struct ext2_dir_entry * de;
 701         struct buffer_head * bh;
 702         int err;
 703 
 704         if (S_ISDIR(oldinode->i_mode)) {
 705                 iput (oldinode);
 706                 iput (dir);
 707                 return -EPERM;
 708         }
 709         if (oldinode->i_nlink > EXT2_LINK_MAX) {
 710                 iput (oldinode);
 711                 iput (dir);
 712                 return -EMLINK;
 713         }
 714         bh = ext2_find_entry (dir, name, len, &de, NULL);
 715         if (bh) {
 716                 brelse (bh);
 717                 iput (dir);
 718                 iput (oldinode);
 719                 return -EEXIST;
 720         }
 721         bh = ext2_add_entry (dir, name, len, &de, &err);
 722         if (!bh) {
 723                 iput (dir);
 724                 iput (oldinode);
 725                 return err;
 726         }
 727         de->inode = oldinode->i_ino;
 728 #ifndef DONT_USE_DCACHE
 729         ext2_dcache_add (dir->i_dev, dir->i_ino, de->name, de->name_len,
 730                          de->inode);
 731 #endif
 732         bh->b_dirt = 1;
 733         brelse (bh);
 734         iput (dir);
 735         oldinode->i_nlink ++;
 736         oldinode->i_ctime = CURRENT_TIME;
 737         oldinode->i_dirt = 1;
 738         iput (oldinode);
 739         return 0;
 740 }
 741 
 742 static int subdir (struct inode * new, struct inode * old)
     /* [previous][next][first][last][top][bottom][index][help] */
 743 {
 744         int ino;
 745         int result;
 746 
 747         new->i_count ++;
 748         result = 0;
 749         for (;;) {
 750                 if (new == old) {
 751                         result = 1;
 752                         break;
 753                 }
 754                 if (new->i_dev != old->i_dev)
 755                         break;
 756                 ino = new->i_ino;
 757                 if (ext2_lookup (new, "..", 2, &new))
 758                         break;
 759                 if (new->i_ino == ino)
 760                         break;
 761         }
 762         iput (new);
 763         return result;
 764 }
 765 
 766 #define PARENT_INO(buffer) \
 767         ((struct ext2_dir_entry *) ((char *) buffer + \
 768         ((struct ext2_dir_entry *) buffer)->rec_len))->inode
 769 
 770 #define PARENT_NAME(buffer) \
 771         ((struct ext2_dir_entry *) ((char *) buffer + \
 772         ((struct ext2_dir_entry *) buffer)->rec_len))->name
 773 
 774 /*
 775  * rename uses retrying to avoid race-conditions: at least they should be
 776  * minimal.
 777  * it tries to allocate all the blocks, then sanity-checks, and if the sanity-
 778  * checks fail, it tries to restart itself again. Very practical - no changes
 779  * are done until we know everything works ok.. and then all the changes can be
 780  * done in one fell swoop when we have claimed all the buffers needed.
 781  *
 782  * Anybody can rename anything with this: the permission checks are left to the
 783  * higher-level routines.
 784  */
 785 static int do_ext2_rename (struct inode * old_dir, const char * old_name,
     /* [previous][next][first][last][top][bottom][index][help] */
 786                            int old_len, struct inode * new_dir,
 787                            const char * new_name, int new_len)
 788 {
 789         struct inode * old_inode, * new_inode;
 790         struct buffer_head * old_bh, * new_bh, * dir_bh;
 791         struct ext2_dir_entry * old_de, * new_de, * pde;
 792         int retval;
 793 
 794         goto start_up;
 795 try_again:
 796         brelse (old_bh);
 797         brelse (new_bh);
 798         brelse (dir_bh);
 799         iput (old_inode);
 800         iput (new_inode);
 801         current->counter = 0;
 802         schedule ();
 803 start_up:
 804         old_inode = new_inode = NULL;
 805         old_bh = new_bh = dir_bh = NULL;
 806         old_bh = ext2_find_entry (old_dir, old_name, old_len, &old_de, &pde);
 807         retval = -ENOENT;
 808         if (!old_bh)
 809                 goto end_rename;
 810         old_inode = iget (old_dir->i_sb, old_de->inode);
 811         if (!old_inode)
 812                 goto end_rename;
 813         retval = -EPERM;
 814         if ((old_dir->i_mode & S_ISVTX) && 
 815             current->euid != old_inode->i_uid &&
 816             current->euid != old_dir->i_uid && !suser())
 817                 goto end_rename;
 818         new_bh = ext2_find_entry (new_dir, new_name, new_len, &new_de, NULL);
 819         if (new_bh) {
 820                 new_inode = iget (new_dir->i_sb, new_de->inode);
 821                 if (!new_inode) {
 822                         brelse (new_bh);
 823                         new_bh = NULL;
 824                 }
 825         }
 826         if (new_inode == old_inode) {
 827                 retval = 0;
 828                 goto end_rename;
 829         }
 830         if (new_inode && S_ISDIR(new_inode->i_mode)) {
 831                 retval = -EISDIR;
 832                 if (!S_ISDIR(old_inode->i_mode))
 833                         goto end_rename;
 834                 retval = -EINVAL;
 835                 if (subdir (new_dir, old_inode))
 836                         goto end_rename;
 837                 retval = -ENOTEMPTY;
 838                 if (!empty_dir (new_inode))
 839                         goto end_rename;
 840                 retval = -EBUSY;
 841                 if (new_inode->i_count > 1)
 842                         goto end_rename;
 843         }
 844         retval = -EPERM;
 845         if (new_inode && (new_dir->i_mode & S_ISVTX) &&
 846             current->euid != new_inode->i_uid &&
 847             current->euid != new_dir->i_uid && !suser())
 848                 goto end_rename;
 849         if (S_ISDIR(old_inode->i_mode)) {
 850                 retval = -ENOTDIR;
 851                 if (new_inode && !S_ISDIR(new_inode->i_mode))
 852                         goto end_rename;
 853                 retval = -EINVAL;
 854                 if (subdir (new_dir, old_inode))
 855                         goto end_rename;
 856                 dir_bh = ext2_bread (old_inode, 0, 0, &retval);
 857                 if (!dir_bh)
 858                         goto end_rename;
 859                 if (PARENT_INO(dir_bh->b_data) != old_dir->i_ino)
 860                         goto end_rename;
 861                 retval = -EMLINK;
 862                 if (!new_inode && new_dir->i_nlink >= EXT2_LINK_MAX)
 863                         goto end_rename;
 864         }
 865         if (!new_bh)
 866                 new_bh = ext2_add_entry (new_dir, new_name, new_len, &new_de,
 867                                          &retval);
 868         if (!new_bh)
 869                 goto end_rename;
 870 /* sanity checking before doing the rename - avoid races */
 871         if (new_inode && (new_de->inode != new_inode->i_ino))
 872                 goto try_again;
 873         if (new_de->inode && !new_inode)
 874                 goto try_again;
 875         if (old_de->inode != old_inode->i_ino)
 876                 goto try_again;
 877 /* ok, that's it */
 878         new_de->inode = old_inode->i_ino;
 879 #ifndef DONT_USE_DCACHE
 880         ext2_dcache_remove (old_dir->i_dev, old_dir->i_ino, old_de->name,
 881                             old_de->name_len);
 882         ext2_dcache_add (new_dir->i_dev, new_dir->i_ino, new_de->name,
 883                          new_de->name_len, new_de->inode);
 884 #endif
 885         if (old_bh->b_blocknr == new_bh->b_blocknr &&
 886             ((char *) new_de) + new_de->rec_len == (char *) old_de)
 887                 new_de->rec_len += old_de->rec_len;
 888         else
 889                 ext2_delete_entry (old_de, pde);
 890         if (new_inode) {
 891                 new_inode->i_nlink --;
 892                 new_inode->i_dirt = 1;
 893         }
 894         old_bh->b_dirt = 1;
 895         new_bh->b_dirt = 1;
 896         if (dir_bh) {
 897                 PARENT_INO(dir_bh->b_data) = new_dir->i_ino;
 898                 dir_bh->b_dirt = 1;
 899                 old_dir->i_nlink --;
 900                 new_dir->i_nlink ++;
 901                 old_dir->i_dirt = 1;
 902                 new_dir->i_dirt = 1;
 903         }
 904         retval = 0;
 905 end_rename:
 906         brelse (dir_bh);
 907         brelse (old_bh);
 908         brelse (new_bh);
 909         iput (old_inode);
 910         iput (new_inode);
 911         iput (old_dir);
 912         iput (new_dir);
 913         return retval;
 914 }
 915 
 916 /*
 917  * Ok, rename also locks out other renames, as they can change the parent of
 918  * a directory, and we don't want any races. Other races are checked for by
 919  * "do_rename()", which restarts if there are inconsistencies.
 920  *
 921  * Note that there is no race between different filesystems: it's only within
 922  * the same device that races occur: many renames can happen at once, as long
 923  * as they are on different partitions.
 924  *
 925  * In the second extended file system, we use a lock flag stored in the memory
 926  * super-block.  This way, we really lock other renames only if they occur
 927  * on the same file system
 928  */
 929 int ext2_rename (struct inode * old_dir, const char * old_name, int old_len,
     /* [previous][next][first][last][top][bottom][index][help] */
 930                  struct inode * new_dir, const char * new_name, int new_len)
 931 {
 932         int result;
 933 
 934         while (old_dir->i_sb->u.ext2_sb.s_rename_lock)
 935                 sleep_on (&old_dir->i_sb->u.ext2_sb.s_rename_wait);
 936         old_dir->i_sb->u.ext2_sb.s_rename_lock = 1;
 937         result = do_ext2_rename (old_dir, old_name, old_len, new_dir,
 938                                  new_name, new_len);
 939         old_dir->i_sb->u.ext2_sb.s_rename_lock = 0;
 940         wake_up (&old_dir->i_sb->u.ext2_sb.s_rename_wait);
 941         return result;
 942 }

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