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                 bh->b_dirt = 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     bh->b_dirt = 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     bh->b_dirt = 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     dir_block->b_dirt = 1;
 379     brelse(dir_block);
 380     inode->i_mode = S_IFDIR | (mode & S_IRWXUGO & ~current->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     bh->b_dirt = 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) && current->euid &&
 500             inode->i_uid != current->euid)
 501         goto end_rmdir;
 502     if (inode->i_dev != dir->i_dev)
 503         goto end_rmdir;
 504     if (inode == dir)   /* we may not delete ".", but "../dir" is ok */
 505         goto end_rmdir;
 506     if (!S_ISDIR(inode->i_mode)) {
 507         retval = -ENOTDIR;
 508         goto end_rmdir;
 509     }
 510     if (!empty_dir(inode)) {
 511         retval = -ENOTEMPTY;
 512         goto end_rmdir;
 513     }
 514     if (inode->i_count > 1) {
 515         retval = -EBUSY;
 516         goto end_rmdir;
 517     }
 518     if (inode->i_nlink != 2)
 519         printk("XIA-FS: empty directory has nlink!=2 (%s %d)\n", WHERE_ERR);
 520     xiafs_rm_entry(de, de_pre);
 521     bh->b_dirt = 1;
 522     inode->i_nlink=0;
 523     inode->i_dirt=1;
 524     dir->i_nlink--;
 525     inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
 526     dir->i_dirt=1;
 527     retval = 0;
 528 end_rmdir:
 529     iput(dir);
 530     iput(inode);
 531     brelse(bh);
 532     return retval;
 533 }
 534 
 535 int xiafs_unlink(struct inode * dir, const char * name, int len)
     /* [previous][next][first][last][top][bottom][index][help] */
 536 {
 537     int retval;
 538     struct inode * inode;
 539     struct buffer_head * bh;
 540     struct xiafs_direct * de, * de_pre;
 541 
 542 repeat:
 543     retval = -ENOENT;
 544     inode = NULL;
 545     bh = xiafs_find_entry(dir, name, len, &de, &de_pre);
 546     if (!bh)
 547         goto end_unlink;
 548     if (!(inode = iget(dir->i_sb, de->d_ino)))
 549         goto end_unlink;
 550     retval = -EPERM;
 551     if (S_ISDIR(inode->i_mode))
 552         goto end_unlink;
 553     if (de->d_ino != inode->i_ino) {
 554         iput(inode);
 555         brelse(bh);
 556         current->counter = 0;
 557         schedule();
 558         goto repeat;
 559     }
 560     if ((dir->i_mode & S_ISVTX) && !suser() &&
 561             current->euid != inode->i_uid &&
 562             current->euid != dir->i_uid)
 563         goto end_unlink;
 564     if (!inode->i_nlink) {
 565         printk("XIA-FS: Deleting nonexistent file (%s %d)\n", WHERE_ERR);
 566         inode->i_nlink=1;
 567     }
 568     xiafs_rm_entry(de, de_pre);
 569     bh->b_dirt = 1;
 570     inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
 571     dir->i_dirt = 1;
 572     inode->i_nlink--;
 573     inode->i_dirt = 1;
 574     retval = 0;
 575 end_unlink:
 576     brelse(bh);
 577     iput(inode);
 578     iput(dir);
 579     return retval;
 580 }
 581 
 582 int xiafs_symlink(struct inode * dir, const char * name, 
     /* [previous][next][first][last][top][bottom][index][help] */
 583                 int len, const char * symname)
 584 {
 585     struct xiafs_direct * de;
 586     struct inode * inode = NULL;
 587     struct buffer_head * bh = NULL, * name_block = NULL;
 588     int i;
 589     char c;
 590 
 591     bh = xiafs_find_entry(dir,name,len, &de, NULL);
 592     if (bh) {
 593         brelse(bh);
 594         iput(dir);
 595         return -EEXIST;
 596     }
 597     if (!(inode = xiafs_new_inode(dir))) {
 598         iput(dir);
 599         return -ENOSPC;
 600     }
 601     inode->i_mode = S_IFLNK | S_IRWXUGO;
 602     inode->i_op = &xiafs_symlink_inode_operations;
 603     name_block = xiafs_bread(inode,0,1);
 604     if (!name_block) {
 605         iput(dir);
 606         inode->i_nlink--;
 607         inode->i_dirt = 1;
 608         iput(inode);
 609         return -ENOSPC;
 610     }
 611     for (i = 0; i < BLOCK_SIZE-1 && (c=*symname++); i++)
 612         name_block->b_data[i] = c;
 613     name_block->b_data[i] = 0;
 614     name_block->b_dirt = 1;
 615     brelse(name_block);
 616     inode->i_size = i;
 617     inode->i_dirt = 1;
 618     bh = xiafs_add_entry(dir, name, len, &de, NULL);
 619     if (!bh) {
 620         inode->i_nlink--;
 621         inode->i_dirt = 1;
 622         iput(inode);
 623         iput(dir);
 624         return -ENOSPC;
 625     }
 626     de->d_ino = inode->i_ino;
 627     bh->b_dirt = 1;
 628     brelse(bh);
 629     iput(dir);
 630     iput(inode);
 631     return 0;
 632 }
 633 
 634 int xiafs_link(struct inode * oldinode, struct inode * dir, 
     /* [previous][next][first][last][top][bottom][index][help] */
 635              const char * name, int len)
 636 {
 637     struct xiafs_direct * de;
 638     struct buffer_head * bh;
 639 
 640     if (S_ISDIR(oldinode->i_mode)) {
 641         iput(oldinode);
 642         iput(dir);
 643         return -EPERM;
 644     }
 645     if (oldinode->i_nlink > 64000) {
 646         iput(oldinode);
 647         iput(dir);
 648         return -EMLINK;
 649     }
 650     bh = xiafs_find_entry(dir, name, len, &de, NULL);
 651     if (bh) {
 652         brelse(bh);
 653         iput(dir);
 654         iput(oldinode);
 655         return -EEXIST;
 656     }
 657     bh = xiafs_add_entry(dir, name, len, &de, NULL);
 658     if (!bh) {
 659         iput(dir);
 660         iput(oldinode);
 661         return -ENOSPC;
 662     }
 663     de->d_ino = oldinode->i_ino;
 664     bh->b_dirt = 1;
 665     brelse(bh);
 666     iput(dir);
 667     oldinode->i_nlink++;
 668     oldinode->i_ctime = CURRENT_TIME;
 669     oldinode->i_dirt = 1;
 670     iput(oldinode);
 671     return 0;
 672 }
 673 
 674 static int subdir(struct inode * new_inode, struct inode * old_inode)
     /* [previous][next][first][last][top][bottom][index][help] */
 675 {
 676     int ino;
 677     int result;
 678 
 679     new_inode->i_count++;
 680     result = 0;
 681     for (;;) {
 682         if (new_inode == old_inode) {
 683             result = 1;
 684             break;
 685         }
 686         if (new_inode->i_dev != old_inode->i_dev)
 687             break;
 688         ino = new_inode->i_ino;
 689         if (xiafs_lookup(new_inode,"..",2,&new_inode))
 690             break;
 691         if (new_inode->i_ino == ino)
 692             break;
 693     }
 694     iput(new_inode);
 695     return result;
 696 }
 697 
 698 #define PARENT_INO(buffer) \
 699     (((struct xiafs_direct *) ((u_char *)(buffer) + 12))->d_ino)
 700 
 701 /*
 702  * rename uses retry to avoid race-conditions: at least they should be minimal.
 703  * it tries to allocate all the blocks, then sanity-checks, and if the sanity-
 704  * checks fail, it tries to restart itself again. Very practical - no changes
 705  * are done until we know everything works ok.. and then all the changes can be
 706  * done in one fell swoop when we have claimed all the buffers needed.
 707  *
 708  * Anybody can rename anything with this: the permission checks are left to the
 709  * higher-level routines.
 710  */
 711 static int do_xiafs_rename(struct inode * old_dir, const char * old_name, 
     /* [previous][next][first][last][top][bottom][index][help] */
 712                          int old_len, struct inode * new_dir, 
 713                          const char * new_name, int new_len)
 714 {
 715     struct inode * old_inode, * new_inode;
 716     struct buffer_head * old_bh, * new_bh, * dir_bh;
 717     struct xiafs_direct * old_de, * old_de_pre, * new_de, * new_de_pre;
 718     int retval;
 719 
 720 try_again:
 721     old_inode = new_inode = NULL;
 722     old_bh = new_bh = dir_bh = NULL;
 723     old_bh = xiafs_find_entry(old_dir, old_name, old_len, &old_de, &old_de_pre);
 724     retval = -ENOENT;
 725     if (!old_bh)
 726         goto end_rename;
 727     old_inode = __iget(old_dir->i_sb, old_de->d_ino, 0); /* don't cross mnt-points */
 728     if (!old_inode)
 729         goto end_rename;
 730     retval = -EPERM;
 731     if ((old_dir->i_mode & S_ISVTX) && 
 732             current->euid != old_inode->i_uid &&
 733             current->euid != old_dir->i_uid && !suser())
 734         goto end_rename;
 735     new_bh = xiafs_find_entry(new_dir, new_name, new_len, &new_de, NULL);
 736     if (new_bh) {
 737         new_inode = __iget(new_dir->i_sb, new_de->d_ino, 0);
 738         if (!new_inode) {
 739             brelse(new_bh);
 740             new_bh = NULL;
 741         }
 742     }
 743     if (new_inode == old_inode) {
 744         retval = 0;
 745         goto end_rename;
 746     }
 747     if (new_inode && S_ISDIR(new_inode->i_mode)) {
 748         retval = -EEXIST;
 749         goto end_rename;
 750     }
 751     retval = -EPERM;
 752     if (new_inode && (new_dir->i_mode & S_ISVTX) && 
 753             current->euid != new_inode->i_uid &&
 754             current->euid != new_dir->i_uid && !suser())
 755         goto end_rename;
 756     if (S_ISDIR(old_inode->i_mode)) {
 757         retval = -EEXIST;
 758         if (new_bh)
 759             goto end_rename;
 760         retval = -EACCES;
 761         if (!permission(old_inode, MAY_WRITE))
 762             goto end_rename;
 763         retval = -EINVAL;
 764         if (subdir(new_dir, old_inode))
 765             goto end_rename;
 766         retval = -EIO;
 767         dir_bh = xiafs_bread(old_inode,0,0);
 768         if (!dir_bh)
 769             goto end_rename;
 770         if (PARENT_INO(dir_bh->b_data) != old_dir->i_ino)
 771             goto end_rename;
 772         retval = -EMLINK;
 773         if (new_dir->i_nlink > 64000)
 774             goto end_rename;
 775     }
 776     if (!new_bh)
 777         new_bh = xiafs_add_entry(new_dir, new_name, new_len, &new_de, &new_de_pre);
 778     retval = -ENOSPC;
 779     if (!new_bh) 
 780         goto end_rename;
 781     /* sanity checking */
 782     if ( (new_inode && (new_de->d_ino != new_inode->i_ino))
 783             || (new_de->d_ino && !new_inode)
 784             || (old_de->d_ino != old_inode->i_ino)) {
 785         xiafs_rm_entry(new_de, new_de_pre);
 786         brelse(old_bh);
 787         brelse(new_bh);
 788         brelse(dir_bh);
 789         iput(old_inode);
 790         iput(new_inode);
 791         current->counter=0;
 792         schedule();
 793         goto try_again;
 794     }
 795     xiafs_rm_entry(old_de, old_de_pre);
 796     new_de->d_ino = old_inode->i_ino;
 797     if (new_inode) {
 798         new_inode->i_nlink--;
 799         new_inode->i_dirt = 1;
 800     }
 801     old_bh->b_dirt = 1;
 802     new_bh->b_dirt = 1;
 803     if (dir_bh) {
 804         PARENT_INO(dir_bh->b_data) = new_dir->i_ino;
 805         dir_bh->b_dirt = 1;
 806         old_dir->i_nlink--;
 807         new_dir->i_nlink++;
 808         old_dir->i_dirt = 1;
 809         new_dir->i_dirt = 1;
 810     }
 811     retval = 0;
 812 end_rename:
 813     brelse(dir_bh);
 814     brelse(old_bh);
 815     brelse(new_bh);
 816     iput(old_inode);
 817     iput(new_inode);
 818     iput(old_dir);
 819     iput(new_dir);
 820     return retval;
 821 }
 822 
 823 /*
 824  * Ok, rename also locks out other renames, as they can change the parent of
 825  * a directory, and we don't want any races. Other races are checked for by
 826  * "do_rename()", which restarts if there are inconsistencies.
 827  *
 828  * Note that there is no race between different filesystems: it's only within
 829  * the same device that races occur: many renames can happen at once, as long
 830  * as they are on different partitions.
 831  */
 832 int xiafs_rename(struct inode * old_dir, const char * old_name, int old_len,
     /* [previous][next][first][last][top][bottom][index][help] */
 833         struct inode * new_dir, const char * new_name, int new_len)
 834 {
 835     static struct wait_queue * wait = NULL;
 836     static int lock = 0;
 837     int result;
 838 
 839     while (lock)
 840         sleep_on(&wait);
 841     lock = 1;
 842     result = do_xiafs_rename(old_dir, old_name, old_len,
 843                            new_dir, new_name, new_len);
 844     lock = 0;
 845     wake_up(&wait);
 846     return result;
 847 }

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