root/fs/xiafs/namei.c

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

DEFINITIONS

This source file includes following definitions.
  1. xiafs_match
  2. xiafs_find_entry
  3. xiafs_lookup
  4. xiafs_add_entry
  5. xiafs_create
  6. xiafs_mknod
  7. xiafs_mkdir
  8. empty_dir
  9. xiafs_rm_entry
  10. xiafs_rmdir
  11. xiafs_unlink
  12. xiafs_symlink
  13. xiafs_link
  14. subdir
  15. do_xiafs_rename
  16. xiafs_rename

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

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