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 < _XIAFS_NAME_LEN && dep->d_name[len])
  41         return 0;
  42     for (i=0; i < len; i++)
  43         if (*name++ != dep->d_name[i])
  44             break;
  45     return (i==len) ? 1 : 0;
  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                 dir->i_atime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
 216                 dir->i_dirt = 1;
 217                 memcpy(de->d_name, name, namelen);
 218                 de->d_name[namelen]=0;
 219                 de->d_name_len=namelen;
 220                 bh->b_dirt = 1;
 221                 *res_dir = de;
 222                 if (res_pre)
 223                     *res_pre = de_pre;
 224                 return bh;
 225             }
 226             offset+=de->d_rec_len;
 227             de_pre=de;
 228             de=(struct xiafs_direct *)(bh->b_data+offset);
 229         }
 230         brelse(bh);
 231         if (offset > XIAFS_ZSIZE(dir->i_sb)) {
 232             printk("XIA-FS: bad directory (%s %d)\n", WHERE_ERR);
 233             return NULL;
 234         }
 235         pos+=XIAFS_ZSIZE(dir->i_sb);
 236     }
 237     return NULL;
 238 }
 239 
 240 int xiafs_create(struct inode * dir, const char * name, int len, int mode,
     /* [previous][next][first][last][top][bottom][index][help] */
 241         struct inode ** result)
 242 {
 243     struct inode * inode;
 244     struct buffer_head * bh;
 245     struct xiafs_direct * de;
 246 
 247     *result = NULL;
 248     if (!dir)
 249         return -ENOENT;
 250     inode = xiafs_new_inode(dir);
 251     if (!inode) {
 252         iput(dir);
 253         return -ENOSPC;
 254     }
 255     inode->i_op = &xiafs_file_inode_operations;
 256     inode->i_mode = mode;
 257     inode->i_dirt = 1;
 258     bh = xiafs_add_entry(dir, name, len, &de, NULL);
 259     if (!bh) {
 260         inode->i_nlink--;
 261         inode->i_dirt = 1;
 262         iput(inode);
 263         iput(dir);
 264         return -ENOSPC;
 265     }
 266     de->d_ino = inode->i_ino;
 267     bh->b_dirt = 1;
 268     brelse(bh);
 269     iput(dir);
 270     *result = inode;
 271     return 0;
 272 }
 273 
 274 int xiafs_mknod(struct inode *dir, const char *name, int len, int mode, int rdev)
     /* [previous][next][first][last][top][bottom][index][help] */
 275 {
 276     struct inode * inode;
 277     struct buffer_head * bh;
 278     struct xiafs_direct * de;
 279 
 280     if (!dir)
 281         return -ENOENT;
 282     bh = xiafs_find_entry(dir,name,len,&de, NULL);
 283     if (bh) {
 284         brelse(bh);
 285         iput(dir);
 286         return -EEXIST;
 287     }
 288     inode = xiafs_new_inode(dir);
 289     if (!inode) {
 290         iput(dir);
 291         return -ENOSPC;
 292     }
 293     inode->i_uid = current->euid;
 294     inode->i_mode = mode;
 295     inode->i_op = NULL;
 296     if (S_ISREG(inode->i_mode))
 297         inode->i_op = &xiafs_file_inode_operations;
 298     else if (S_ISDIR(inode->i_mode)) {
 299         inode->i_op = &xiafs_dir_inode_operations;
 300         if (dir->i_mode & S_ISGID)
 301             inode->i_mode |= S_ISGID;
 302     }
 303     else if (S_ISLNK(inode->i_mode))
 304         inode->i_op = &xiafs_symlink_inode_operations;
 305     else if (S_ISCHR(inode->i_mode))
 306         inode->i_op = &chrdev_inode_operations;
 307     else if (S_ISBLK(inode->i_mode))
 308         inode->i_op = &blkdev_inode_operations;
 309     else if (S_ISFIFO(inode->i_mode)) {
 310         inode->i_op = &fifo_inode_operations;
 311         inode->i_pipe = 1;
 312         PIPE_BASE(*inode) = NULL;
 313         PIPE_HEAD(*inode) = PIPE_TAIL(*inode) = 0;
 314         PIPE_READ_WAIT(*inode) = PIPE_WRITE_WAIT(*inode) = NULL;
 315         PIPE_READERS(*inode) = PIPE_WRITERS(*inode) = 0;
 316     }
 317     if (S_ISBLK(mode) || S_ISCHR(mode))
 318         inode->i_rdev = rdev;
 319     inode->i_atime = inode->i_ctime = inode->i_atime = CURRENT_TIME;
 320     inode->i_dirt = 1;
 321     bh = xiafs_add_entry(dir, name, len, &de, NULL);
 322     if (!bh) {
 323         inode->i_nlink--;
 324         inode->i_dirt = 1;
 325         iput(inode);
 326         iput(dir);
 327         return -ENOSPC;
 328     }
 329     de->d_ino = inode->i_ino;
 330     bh->b_dirt = 1;
 331     brelse(bh);
 332     iput(dir);
 333     iput(inode);
 334     return 0;
 335 }
 336 
 337 int xiafs_mkdir(struct inode * dir, const char * name, int len, int mode)
     /* [previous][next][first][last][top][bottom][index][help] */
 338 {
 339     struct inode * inode;
 340     struct buffer_head * bh, *dir_block;
 341     struct xiafs_direct * de;
 342         
 343     bh = xiafs_find_entry(dir,name,len,&de, NULL);
 344     if (bh) {
 345         brelse(bh);
 346         iput(dir);
 347         return -EEXIST;
 348     }
 349     if (dir->i_nlink > 64000) {
 350         iput(dir);
 351         return -EMLINK;
 352     }
 353     inode = xiafs_new_inode(dir);
 354     if (!inode) {
 355         iput(dir);
 356         return -ENOSPC;
 357     }
 358     inode->i_op = &xiafs_dir_inode_operations;
 359     inode->i_size = XIAFS_ZSIZE(dir->i_sb);
 360     inode->i_atime = inode->i_ctime = inode->i_mtime = CURRENT_TIME;
 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     dir_block->b_dirt = 1;
 381     brelse(dir_block);
 382     inode->i_mode = S_IFDIR | (mode & 0777 & ~current->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     bh->b_dirt = 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) && current->euid &&
 502             inode->i_uid != current->euid)
 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     bh->b_dirt = 1;
 524     inode->i_nlink=0;
 525     inode->i_dirt=1;
 526     dir->i_nlink--;
 527     dir->i_atime = 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     if (de->d_ino != inode->i_ino) {
 553         iput(inode);
 554         brelse(bh);
 555         current->counter = 0;
 556         schedule();
 557         goto repeat;
 558     }
 559     retval = -EPERM;
 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 (S_ISDIR(inode->i_mode))
 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     bh->b_dirt = 1;
 572     dir->i_atime = 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 | 0777;
 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     name_block->b_dirt = 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     bh->b_dirt = 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     bh->b_dirt = 1;
 667     brelse(bh);
 668     iput(dir);
 669     oldinode->i_nlink++;
 670     oldinode->i_atime = 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, struct inode * old)
     /* [previous][next][first][last][top][bottom][index][help] */
 677 {
 678     int ino;
 679     int result;
 680 
 681     new->i_count++;
 682     result = 0;
 683     for (;;) {
 684         if (new == old) {
 685             result = 1;
 686             break;
 687         }
 688         if (new->i_dev != old->i_dev)
 689             break;
 690         ino = new->i_ino;
 691         if (xiafs_lookup(new,"..",2,&new))
 692             break;
 693         if (new->i_ino == ino)
 694             break;
 695     }
 696     iput(new);
 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);
 730     if (!old_inode)
 731         goto end_rename;
 732     retval = -EPERM;
 733     if ((old_dir->i_mode & S_ISVTX) && 
 734             current->euid != old_inode->i_uid &&
 735             current->euid != old_dir->i_uid && !suser())
 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);
 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->euid != new_inode->i_uid &&
 756             current->euid != new_dir->i_uid && !suser())
 757         goto end_rename;
 758     if (S_ISDIR(old_inode->i_mode)) {
 759         retval = -EEXIST;
 760         if (new_bh)
 761             goto end_rename;
 762         retval = -EACCES;
 763         if (!permission(old_inode, MAY_WRITE))
 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     old_bh->b_dirt = 1;
 804     new_bh->b_dirt = 1;
 805     if (dir_bh) {
 806         PARENT_INO(dir_bh->b_data) = new_dir->i_ino;
 807         dir_bh->b_dirt = 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 }
 850 
 851 
 852 
 853 
 854 

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