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

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