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->fsuid;
 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     inode->i_dirt = 1;
 360     dir_block = xiafs_bread(inode,0,1);
 361     if (!dir_block) {
 362         iput(dir);
 363         inode->i_nlink--;
 364         inode->i_dirt = 1;
 365         iput(inode);
 366         return -ENOSPC;
 367     }
 368     de = (struct xiafs_direct *) dir_block->b_data;
 369     de->d_ino=inode->i_ino;
 370     strcpy(de->d_name,".");
 371     de->d_name_len=1;
 372     de->d_rec_len=12;
 373     de =(struct xiafs_direct *)(12 + dir_block->b_data);
 374     de->d_ino = dir->i_ino;
 375     strcpy(de->d_name,"..");
 376     de->d_name_len=2;
 377     de->d_rec_len=XIAFS_ZSIZE(dir->i_sb)-12;
 378     inode->i_nlink = 2;
 379     mark_buffer_dirty(dir_block, 1);
 380     brelse(dir_block);
 381     inode->i_mode = S_IFDIR | (mode & S_IRWXUGO & ~current->fs->umask);
 382     if (dir->i_mode & S_ISGID)
 383         inode->i_mode |= S_ISGID;
 384     inode->i_dirt = 1;
 385     bh = xiafs_add_entry(dir, name, len, &de, NULL);
 386     if (!bh) {
 387         iput(dir);
 388         inode->i_nlink=0;
 389         iput(inode);
 390         return -ENOSPC;
 391     }
 392     de->d_ino = inode->i_ino;
 393     mark_buffer_dirty(bh, 1);
 394     dir->i_nlink++;
 395     dir->i_dirt = 1;
 396     iput(dir);
 397     iput(inode);
 398     brelse(bh);
 399     return 0;
 400 }
 401 
 402 /*
 403  * routine to check that the specified directory is empty (for rmdir)
 404  */
 405 static int empty_dir(struct inode * inode)
     /* [previous][next][first][last][top][bottom][index][help] */
 406 {
 407     int i, zones, offset;
 408     struct buffer_head * bh;
 409     struct xiafs_direct * de;
 410 
 411     if (inode->i_size & (XIAFS_ZSIZE(inode->i_sb)-1) ) {
 412         printk("XIA-FS: bad directory (%s %d)\n", WHERE_ERR);
 413         return 1;
 414     }
 415 
 416     zones=inode->i_size >> XIAFS_ZSIZE_BITS(inode->i_sb);
 417     for (i=0; i < zones; i++) {
 418         bh =  xiafs_bread(inode, i, 0);
 419         if (!i) {
 420             if (!bh) {
 421                 printk("XIA-FS: bad directory (%s %d)\n", WHERE_ERR);
 422                 return 1;
 423             }
 424             de=(struct xiafs_direct *)bh->b_data;
 425             if (de->d_ino != inode->i_ino || strcmp(".", de->d_name) ||
 426                     de->d_rec_len != 12 ) {
 427                 printk("XIA-FS: bad directory (%s %d)\n", WHERE_ERR);
 428                 brelse(bh);
 429                 return 1;        
 430             }
 431             de=(struct xiafs_direct *)(12 + bh->b_data);
 432             if (!de->d_ino || strcmp("..", de->d_name)) {
 433                 printk("XIA-FS: bad directory (%s %d)\n", WHERE_ERR);
 434                 brelse(bh);
 435                 return 1;
 436             }
 437             offset=de->d_rec_len+12;
 438         }
 439         else
 440             offset = 0;
 441         if (!bh)
 442             continue;
 443         while (offset < XIAFS_ZSIZE(inode->i_sb)) {
 444             de=(struct xiafs_direct *)(bh->b_data+offset);
 445             if (de->d_ino > inode->i_sb->u.xiafs_sb.s_ninodes ||
 446                 de->d_rec_len < 12 || 
 447                 (char *)de+de->d_rec_len > bh->b_data+XIAFS_ZSIZE(inode->i_sb) ||
 448                 de->d_name_len + 8 > de->d_rec_len ||
 449                 de->d_name[de->d_name_len]) {
 450                 printk("XIA-FS: bad directory (%s %d)\n", WHERE_ERR);
 451                 brelse(bh);
 452                 return 1;
 453             }
 454             if (de->d_ino) {
 455                 brelse(bh);
 456                 return 0;
 457             }
 458             offset+=de->d_rec_len;
 459         }
 460         brelse(bh);
 461     }
 462     return 1;
 463 }
 464 
 465 static void xiafs_rm_entry(struct xiafs_direct *de, struct xiafs_direct * de_pre)
     /* [previous][next][first][last][top][bottom][index][help] */
 466 {
 467     if (de==de_pre) {
 468         de->d_ino=0;
 469         return;
 470     }
 471     while (de_pre->d_rec_len+(u_char *)de_pre < (u_char *)de) {
 472         if (de_pre->d_rec_len < 12) {
 473             printk("XIA-FS: bad directory entry (%s %d)\n", WHERE_ERR);
 474             return;
 475         }
 476         de_pre=(struct xiafs_direct *)(de_pre->d_rec_len+(u_char *)de_pre);
 477     }
 478     if (de_pre->d_rec_len+(u_char *)de_pre > (u_char *)de) {
 479         printk("XIA-FS: bad directory entry (%s %d)\n", WHERE_ERR);
 480         return;
 481     }
 482     de_pre->d_rec_len+=de->d_rec_len;
 483 }
 484 
 485 int xiafs_rmdir(struct inode * dir, const char * name, int len)
     /* [previous][next][first][last][top][bottom][index][help] */
 486 {
 487     int retval;
 488     struct inode * inode;
 489     struct buffer_head * bh;
 490     struct xiafs_direct * de, * de_pre;
 491 
 492     inode = NULL;
 493     bh = xiafs_find_entry(dir, name, len, &de, &de_pre);
 494     retval = -ENOENT;
 495     if (!bh)
 496         goto end_rmdir;
 497     retval = -EPERM;
 498     if (!(inode = iget(dir->i_sb, de->d_ino)))
 499         goto end_rmdir;
 500     if ((dir->i_mode & S_ISVTX) && !fsuser() &&
 501             current->fsuid != inode->i_uid &&
 502             current->fsuid != dir->i_uid)
 503         goto end_rmdir;
 504     if (inode->i_dev != dir->i_dev)
 505         goto end_rmdir;
 506     if (inode == dir)   /* we may not delete ".", but "../dir" is ok */
 507         goto end_rmdir;
 508     if (!S_ISDIR(inode->i_mode)) {
 509         retval = -ENOTDIR;
 510         goto end_rmdir;
 511     }
 512     if (!empty_dir(inode)) {
 513         retval = -ENOTEMPTY;
 514         goto end_rmdir;
 515     }
 516     if (inode->i_count > 1) {
 517         retval = -EBUSY;
 518         goto end_rmdir;
 519     }
 520     if (inode->i_nlink != 2)
 521         printk("XIA-FS: empty directory has nlink!=2 (%s %d)\n", WHERE_ERR);
 522     xiafs_rm_entry(de, de_pre);
 523     mark_buffer_dirty(bh, 1);
 524     inode->i_nlink=0;
 525     inode->i_dirt=1;
 526     dir->i_nlink--;
 527     inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
 528     dir->i_dirt=1;
 529     retval = 0;
 530 end_rmdir:
 531     iput(dir);
 532     iput(inode);
 533     brelse(bh);
 534     return retval;
 535 }
 536 
 537 int xiafs_unlink(struct inode * dir, const char * name, int len)
     /* [previous][next][first][last][top][bottom][index][help] */
 538 {
 539     int retval;
 540     struct inode * inode;
 541     struct buffer_head * bh;
 542     struct xiafs_direct * de, * de_pre;
 543 
 544 repeat:
 545     retval = -ENOENT;
 546     inode = NULL;
 547     bh = xiafs_find_entry(dir, name, len, &de, &de_pre);
 548     if (!bh)
 549         goto end_unlink;
 550     if (!(inode = iget(dir->i_sb, de->d_ino)))
 551         goto end_unlink;
 552     retval = -EPERM;
 553     if (S_ISDIR(inode->i_mode))
 554         goto end_unlink;
 555     if (de->d_ino != inode->i_ino) {
 556         iput(inode);
 557         brelse(bh);
 558         current->counter = 0;
 559         schedule();
 560         goto repeat;
 561     }
 562     if ((dir->i_mode & S_ISVTX) && !fsuser() &&
 563             current->fsuid != inode->i_uid &&
 564             current->fsuid != dir->i_uid)
 565         goto end_unlink;
 566     if (!inode->i_nlink) {
 567         printk("XIA-FS: Deleting nonexistent file (%s %d)\n", WHERE_ERR);
 568         inode->i_nlink=1;
 569     }
 570     xiafs_rm_entry(de, de_pre);
 571     mark_buffer_dirty(bh, 1);
 572     inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
 573     dir->i_dirt = 1;
 574     inode->i_nlink--;
 575     inode->i_dirt = 1;
 576     retval = 0;
 577 end_unlink:
 578     brelse(bh);
 579     iput(inode);
 580     iput(dir);
 581     return retval;
 582 }
 583 
 584 int xiafs_symlink(struct inode * dir, const char * name, 
     /* [previous][next][first][last][top][bottom][index][help] */
 585                 int len, const char * symname)
 586 {
 587     struct xiafs_direct * de;
 588     struct inode * inode = NULL;
 589     struct buffer_head * bh = NULL, * name_block = NULL;
 590     int i;
 591     char c;
 592 
 593     bh = xiafs_find_entry(dir,name,len, &de, NULL);
 594     if (bh) {
 595         brelse(bh);
 596         iput(dir);
 597         return -EEXIST;
 598     }
 599     if (!(inode = xiafs_new_inode(dir))) {
 600         iput(dir);
 601         return -ENOSPC;
 602     }
 603     inode->i_mode = S_IFLNK | S_IRWXUGO;
 604     inode->i_op = &xiafs_symlink_inode_operations;
 605     name_block = xiafs_bread(inode,0,1);
 606     if (!name_block) {
 607         iput(dir);
 608         inode->i_nlink--;
 609         inode->i_dirt = 1;
 610         iput(inode);
 611         return -ENOSPC;
 612     }
 613     for (i = 0; i < BLOCK_SIZE-1 && (c=*symname++); i++)
 614         name_block->b_data[i] = c;
 615     name_block->b_data[i] = 0;
 616     mark_buffer_dirty(name_block, 1);
 617     brelse(name_block);
 618     inode->i_size = i;
 619     inode->i_dirt = 1;
 620     bh = xiafs_add_entry(dir, name, len, &de, NULL);
 621     if (!bh) {
 622         inode->i_nlink--;
 623         inode->i_dirt = 1;
 624         iput(inode);
 625         iput(dir);
 626         return -ENOSPC;
 627     }
 628     de->d_ino = inode->i_ino;
 629     mark_buffer_dirty(bh, 1);
 630     brelse(bh);
 631     iput(dir);
 632     iput(inode);
 633     return 0;
 634 }
 635 
 636 int xiafs_link(struct inode * oldinode, struct inode * dir, 
     /* [previous][next][first][last][top][bottom][index][help] */
 637              const char * name, int len)
 638 {
 639     struct xiafs_direct * de;
 640     struct buffer_head * bh;
 641 
 642     if (S_ISDIR(oldinode->i_mode)) {
 643         iput(oldinode);
 644         iput(dir);
 645         return -EPERM;
 646     }
 647     if (oldinode->i_nlink > 64000) {
 648         iput(oldinode);
 649         iput(dir);
 650         return -EMLINK;
 651     }
 652     bh = xiafs_find_entry(dir, name, len, &de, NULL);
 653     if (bh) {
 654         brelse(bh);
 655         iput(dir);
 656         iput(oldinode);
 657         return -EEXIST;
 658     }
 659     bh = xiafs_add_entry(dir, name, len, &de, NULL);
 660     if (!bh) {
 661         iput(dir);
 662         iput(oldinode);
 663         return -ENOSPC;
 664     }
 665     de->d_ino = oldinode->i_ino;
 666     mark_buffer_dirty(bh, 1);
 667     brelse(bh);
 668     iput(dir);
 669     oldinode->i_nlink++;
 670     oldinode->i_ctime = CURRENT_TIME;
 671     oldinode->i_dirt = 1;
 672     iput(oldinode);
 673     return 0;
 674 }
 675 
 676 static int subdir(struct inode * new_inode, struct inode * old_inode)
     /* [previous][next][first][last][top][bottom][index][help] */
 677 {
 678     int ino;
 679     int result;
 680 
 681     new_inode->i_count++;
 682     result = 0;
 683     for (;;) {
 684         if (new_inode == old_inode) {
 685             result = 1;
 686             break;
 687         }
 688         if (new_inode->i_dev != old_inode->i_dev)
 689             break;
 690         ino = new_inode->i_ino;
 691         if (xiafs_lookup(new_inode,"..",2,&new_inode))
 692             break;
 693         if (new_inode->i_ino == ino)
 694             break;
 695     }
 696     iput(new_inode);
 697     return result;
 698 }
 699 
 700 #define PARENT_INO(buffer) \
 701     (((struct xiafs_direct *) ((u_char *)(buffer) + 12))->d_ino)
 702 
 703 /*
 704  * rename uses retry to avoid race-conditions: at least they should be minimal.
 705  * it tries to allocate all the blocks, then sanity-checks, and if the sanity-
 706  * checks fail, it tries to restart itself again. Very practical - no changes
 707  * are done until we know everything works ok.. and then all the changes can be
 708  * done in one fell swoop when we have claimed all the buffers needed.
 709  *
 710  * Anybody can rename anything with this: the permission checks are left to the
 711  * higher-level routines.
 712  */
 713 static int do_xiafs_rename(struct inode * old_dir, const char * old_name, 
     /* [previous][next][first][last][top][bottom][index][help] */
 714                          int old_len, struct inode * new_dir, 
 715                          const char * new_name, int new_len)
 716 {
 717     struct inode * old_inode, * new_inode;
 718     struct buffer_head * old_bh, * new_bh, * dir_bh;
 719     struct xiafs_direct * old_de, * old_de_pre, * new_de, * new_de_pre;
 720     int retval;
 721 
 722 try_again:
 723     old_inode = new_inode = NULL;
 724     old_bh = new_bh = dir_bh = NULL;
 725     old_bh = xiafs_find_entry(old_dir, old_name, old_len, &old_de, &old_de_pre);
 726     retval = -ENOENT;
 727     if (!old_bh)
 728         goto end_rename;
 729     old_inode = __iget(old_dir->i_sb, old_de->d_ino, 0); /* don't cross mnt-points */
 730     if (!old_inode)
 731         goto end_rename;
 732     retval = -EPERM;
 733     if ((old_dir->i_mode & S_ISVTX) && 
 734             current->fsuid != old_inode->i_uid &&
 735             current->fsuid != old_dir->i_uid && !fsuser())
 736         goto end_rename;
 737     new_bh = xiafs_find_entry(new_dir, new_name, new_len, &new_de, NULL);
 738     if (new_bh) {
 739         new_inode = __iget(new_dir->i_sb, new_de->d_ino, 0);
 740         if (!new_inode) {
 741             brelse(new_bh);
 742             new_bh = NULL;
 743         }
 744     }
 745     if (new_inode == old_inode) {
 746         retval = 0;
 747         goto end_rename;
 748     }
 749     if (new_inode && S_ISDIR(new_inode->i_mode)) {
 750         retval = -EEXIST;
 751         goto end_rename;
 752     }
 753     retval = -EPERM;
 754     if (new_inode && (new_dir->i_mode & S_ISVTX) && 
 755             current->fsuid != new_inode->i_uid &&
 756             current->fsuid != new_dir->i_uid && !fsuser())
 757         goto end_rename;
 758     if (S_ISDIR(old_inode->i_mode)) {
 759         retval = -EEXIST;
 760         if (new_bh)
 761             goto end_rename;
 762         if ((retval = permission(old_inode, MAY_WRITE)) != 0)
 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] */