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                 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         init_fifo(inode);
 311     if (S_ISBLK(mode) || S_ISCHR(mode))
 312         inode->i_rdev = rdev;
 313     inode->i_atime = inode->i_ctime = inode->i_atime = CURRENT_TIME;
 314     inode->i_dirt = 1;
 315     bh = xiafs_add_entry(dir, name, len, &de, NULL);
 316     if (!bh) {
 317         inode->i_nlink--;
 318         inode->i_dirt = 1;
 319         iput(inode);
 320         iput(dir);
 321         return -ENOSPC;
 322     }
 323     de->d_ino = inode->i_ino;
 324     bh->b_dirt = 1;
 325     brelse(bh);
 326     iput(dir);
 327     iput(inode);
 328     return 0;
 329 }
 330 
 331 int xiafs_mkdir(struct inode * dir, const char * name, int len, int mode)
     /* [previous][next][first][last][top][bottom][index][help] */
 332 {
 333     struct inode * inode;
 334     struct buffer_head * bh, *dir_block;
 335     struct xiafs_direct * de;
 336         
 337     bh = xiafs_find_entry(dir,name,len,&de, NULL);
 338     if (bh) {
 339         brelse(bh);
 340         iput(dir);
 341         return -EEXIST;
 342     }
 343     if (dir->i_nlink > 64000) {
 344         iput(dir);
 345         return -EMLINK;
 346     }
 347     inode = xiafs_new_inode(dir);
 348     if (!inode) {
 349         iput(dir);
 350         return -ENOSPC;
 351     }
 352     inode->i_op = &xiafs_dir_inode_operations;
 353     inode->i_size = XIAFS_ZSIZE(dir->i_sb);
 354     inode->i_atime = inode->i_ctime = inode->i_mtime = CURRENT_TIME;
 355     dir_block = xiafs_bread(inode,0,1);
 356     if (!dir_block) {
 357         iput(dir);
 358         inode->i_nlink--;
 359         inode->i_dirt = 1;
 360         iput(inode);
 361         return -ENOSPC;
 362     }
 363     de = (struct xiafs_direct *) dir_block->b_data;
 364     de->d_ino=inode->i_ino;
 365     strcpy(de->d_name,".");
 366     de->d_name_len=1;
 367     de->d_rec_len=12;
 368     de =(struct xiafs_direct *)(12 + dir_block->b_data);
 369     de->d_ino = dir->i_ino;
 370     strcpy(de->d_name,"..");
 371     de->d_name_len=2;
 372     de->d_rec_len=XIAFS_ZSIZE(dir->i_sb)-12;
 373     inode->i_nlink = 2;
 374     dir_block->b_dirt = 1;
 375     brelse(dir_block);
 376     inode->i_mode = S_IFDIR | (mode & 0777 & ~current->umask);
 377     if (dir->i_mode & S_ISGID)
 378         inode->i_mode |= S_ISGID;
 379     inode->i_dirt = 1;
 380     bh = xiafs_add_entry(dir, name, len, &de, NULL);
 381     if (!bh) {
 382         iput(dir);
 383         inode->i_nlink=0;
 384         iput(inode);
 385         return -ENOSPC;
 386     }
 387     de->d_ino = inode->i_ino;
 388     bh->b_dirt = 1;
 389     dir->i_nlink++;
 390     dir->i_dirt = 1;
 391     iput(dir);
 392     iput(inode);
 393     brelse(bh);
 394     return 0;
 395 }
 396 
 397 /*
 398  * routine to check that the specified directory is empty (for rmdir)
 399  */
 400 static int empty_dir(struct inode * inode)
     /* [previous][next][first][last][top][bottom][index][help] */
 401 {
 402     int i, zones, offset;
 403     struct buffer_head * bh;
 404     struct xiafs_direct * de;
 405 
 406     if (inode->i_size & (XIAFS_ZSIZE(inode->i_sb)-1) ) {
 407         printk("XIA-FS: bad directory (%s %d)\n", WHERE_ERR);
 408         return 1;
 409     }
 410 
 411     zones=inode->i_size >> XIAFS_ZSIZE_BITS(inode->i_sb);
 412     for (i=0; i < zones; i++) {
 413         bh =  xiafs_bread(inode, i, 0);
 414         if (!i) {
 415             if (!bh) {
 416                 printk("XIA-FS: bad directory (%s %d)\n", WHERE_ERR);
 417                 return 1;
 418             }
 419             de=(struct xiafs_direct *)bh->b_data;
 420             if (de->d_ino != inode->i_ino || strcmp(".", de->d_name) ||
 421                     de->d_rec_len != 12 ) {
 422                 printk("XIA-FS: bad directory (%s %d)\n", WHERE_ERR);
 423                 brelse(bh);
 424                 return 1;        
 425             }
 426             de=(struct xiafs_direct *)(12 + bh->b_data);
 427             if (!de->d_ino || strcmp("..", de->d_name)) {
 428                 printk("XIA-FS: bad directory (%s %d)\n", WHERE_ERR);
 429                 brelse(bh);
 430                 return 1;
 431             }
 432             offset=de->d_rec_len+12;
 433         }
 434         else
 435             offset = 0;
 436         if (!bh)
 437             continue;
 438         while (offset < XIAFS_ZSIZE(inode->i_sb)) {
 439             de=(struct xiafs_direct *)(bh->b_data+offset);
 440             if (de->d_ino > inode->i_sb->u.xiafs_sb.s_ninodes ||
 441                 de->d_rec_len < 12 || 
 442                 (char *)de+de->d_rec_len > bh->b_data+XIAFS_ZSIZE(inode->i_sb) ||
 443                 de->d_name_len + 8 > de->d_rec_len ||
 444                 de->d_name[de->d_name_len]) {
 445                 printk("XIA-FS: bad directory (%s %d)\n", WHERE_ERR);
 446                 brelse(bh);
 447                 return 1;
 448             }
 449             if (de->d_ino) {
 450                 brelse(bh);
 451                 return 0;
 452             }
 453             offset+=de->d_rec_len;
 454         }
 455         brelse(bh);
 456     }
 457     return 1;
 458 }
 459 
 460 static void xiafs_rm_entry(struct xiafs_direct *de, struct xiafs_direct * de_pre)
     /* [previous][next][first][last][top][bottom][index][help] */
 461 {
 462     if (de==de_pre) {
 463         de->d_ino=0;
 464         return;
 465     }
 466     while (de_pre->d_rec_len+(u_char *)de_pre < (u_char *)de) {
 467         if (de_pre->d_rec_len < 12) {
 468             printk("XIA-FS: bad directory entry (%s %d)\n", WHERE_ERR);
 469             return;
 470         }
 471         de_pre=(struct xiafs_direct *)(de_pre->d_rec_len+(u_char *)de_pre);
 472     }
 473     if (de_pre->d_rec_len+(u_char *)de_pre > (u_char *)de) {
 474         printk("XIA-FS: bad directory entry (%s %d)\n", WHERE_ERR);
 475         return;
 476     }
 477     de_pre->d_rec_len+=de->d_rec_len;
 478 }
 479 
 480 int xiafs_rmdir(struct inode * dir, const char * name, int len)
     /* [previous][next][first][last][top][bottom][index][help] */
 481 {
 482     int retval;
 483     struct inode * inode;
 484     struct buffer_head * bh;
 485     struct xiafs_direct * de, * de_pre;
 486 
 487     inode = NULL;
 488     bh = xiafs_find_entry(dir, name, len, &de, &de_pre);
 489     retval = -ENOENT;
 490     if (!bh)
 491         goto end_rmdir;
 492     retval = -EPERM;
 493     if (!(inode = iget(dir->i_sb, de->d_ino)))
 494         goto end_rmdir;
 495     if ((dir->i_mode & S_ISVTX) && current->euid &&
 496             inode->i_uid != current->euid)
 497         goto end_rmdir;
 498     if (inode->i_dev != dir->i_dev)
 499         goto end_rmdir;
 500     if (inode == dir)   /* we may not delete ".", but "../dir" is ok */
 501         goto end_rmdir;
 502     if (!S_ISDIR(inode->i_mode)) {
 503         retval = -ENOTDIR;
 504         goto end_rmdir;
 505     }
 506     if (!empty_dir(inode)) {
 507         retval = -ENOTEMPTY;
 508         goto end_rmdir;
 509     }
 510     if (inode->i_count > 1) {
 511         retval = -EBUSY;
 512         goto end_rmdir;
 513     }
 514     if (inode->i_nlink != 2)
 515         printk("XIA-FS: empty directory has nlink!=2 (%s %d)\n", WHERE_ERR);
 516     xiafs_rm_entry(de, de_pre);
 517     bh->b_dirt = 1;
 518     inode->i_nlink=0;
 519     inode->i_dirt=1;
 520     dir->i_nlink--;
 521     dir->i_atime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
 522     dir->i_dirt=1;
 523     retval = 0;
 524 end_rmdir:
 525     iput(dir);
 526     iput(inode);
 527     brelse(bh);
 528     return retval;
 529 }
 530 
 531 int xiafs_unlink(struct inode * dir, const char * name, int len)
     /* [previous][next][first][last][top][bottom][index][help] */
 532 {
 533     int retval;
 534     struct inode * inode;
 535     struct buffer_head * bh;
 536     struct xiafs_direct * de, * de_pre;
 537 
 538 repeat:
 539     retval = -ENOENT;
 540     inode = NULL;
 541     bh = xiafs_find_entry(dir, name, len, &de, &de_pre);
 542     if (!bh)
 543         goto end_unlink;
 544     if (!(inode = iget(dir->i_sb, de->d_ino)))
 545         goto end_unlink;
 546     if (de->d_ino != inode->i_ino) {
 547         iput(inode);
 548         brelse(bh);
 549         current->counter = 0;
 550         schedule();
 551         goto repeat;
 552     }
 553     retval = -EPERM;
 554     if ((dir->i_mode & S_ISVTX) && !suser() &&
 555             current->euid != inode->i_uid &&
 556             current->euid != dir->i_uid)
 557         goto end_unlink;
 558     if (S_ISDIR(inode->i_mode))
 559         goto end_unlink;
 560     if (!inode->i_nlink) {
 561         printk("XIA-FS: Deleting nonexistent file (%s %d)\n", WHERE_ERR);
 562         inode->i_nlink=1;
 563     }
 564     xiafs_rm_entry(de, de_pre);
 565     bh->b_dirt = 1;
 566     dir->i_atime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
 567     dir->i_dirt = 1;
 568     inode->i_nlink--;
 569     inode->i_dirt = 1;
 570     retval = 0;
 571 end_unlink:
 572     brelse(bh);
 573     iput(inode);
 574     iput(dir);
 575     return retval;
 576 }
 577 
 578 int xiafs_symlink(struct inode * dir, const char * name, 
     /* [previous][next][first][last][top][bottom][index][help] */
 579                 int len, const char * symname)
 580 {
 581     struct xiafs_direct * de;
 582     struct inode * inode = NULL;
 583     struct buffer_head * bh = NULL, * name_block = NULL;
 584     int i;
 585     char c;
 586 
 587     bh = xiafs_find_entry(dir,name,len, &de, NULL);
 588     if (bh) {
 589         brelse(bh);
 590         iput(dir);
 591         return -EEXIST;
 592     }
 593     if (!(inode = xiafs_new_inode(dir))) {
 594         iput(dir);
 595         return -ENOSPC;
 596     }
 597     inode->i_mode = S_IFLNK | 0777;
 598     inode->i_op = &xiafs_symlink_inode_operations;
 599     name_block = xiafs_bread(inode,0,1);
 600     if (!name_block) {
 601         iput(dir);
 602         inode->i_nlink--;
 603         inode->i_dirt = 1;
 604         iput(inode);
 605         return -ENOSPC;
 606     }
 607     for (i = 0; i < BLOCK_SIZE-1 && (c=*symname++); i++)
 608         name_block->b_data[i] = c;
 609     name_block->b_data[i] = 0;
 610     name_block->b_dirt = 1;
 611     brelse(name_block);
 612     inode->i_size = i;
 613     inode->i_dirt = 1;
 614     bh = xiafs_add_entry(dir, name, len, &de, NULL);
 615     if (!bh) {
 616         inode->i_nlink--;
 617         inode->i_dirt = 1;
 618         iput(inode);
 619         iput(dir);
 620         return -ENOSPC;
 621     }
 622     de->d_ino = inode->i_ino;
 623     bh->b_dirt = 1;
 624     brelse(bh);
 625     iput(dir);
 626     iput(inode);
 627     return 0;
 628 }
 629 
 630 int xiafs_link(struct inode * oldinode, struct inode * dir, 
     /* [previous][next][first][last][top][bottom][index][help] */
 631              const char * name, int len)
 632 {
 633     struct xiafs_direct * de;
 634     struct buffer_head * bh;
 635 
 636     if (S_ISDIR(oldinode->i_mode)) {
 637         iput(oldinode);
 638         iput(dir);
 639         return -EPERM;
 640     }
 641     if (oldinode->i_nlink > 64000) {
 642         iput(oldinode);
 643         iput(dir);
 644         return -EMLINK;
 645     }
 646     bh = xiafs_find_entry(dir, name, len, &de, NULL);
 647     if (bh) {
 648         brelse(bh);
 649         iput(dir);
 650         iput(oldinode);
 651         return -EEXIST;
 652     }
 653     bh = xiafs_add_entry(dir, name, len, &de, NULL);
 654     if (!bh) {
 655         iput(dir);
 656         iput(oldinode);
 657         return -ENOSPC;
 658     }
 659     de->d_ino = oldinode->i_ino;
 660     bh->b_dirt = 1;
 661     brelse(bh);
 662     iput(dir);
 663     oldinode->i_nlink++;
 664     oldinode->i_atime = oldinode->i_ctime = CURRENT_TIME;
 665     oldinode->i_dirt = 1;
 666     iput(oldinode);
 667     return 0;
 668 }
 669 
 670 static int subdir(struct inode * new, struct inode * old)
     /* [previous][next][first][last][top][bottom][index][help] */
 671 {
 672     int ino;
 673     int result;
 674 
 675     new->i_count++;
 676     result = 0;
 677     for (;;) {
 678         if (new == old) {
 679             result = 1;
 680             break;
 681         }
 682         if (new->i_dev != old->i_dev)
 683             break;
 684         ino = new->i_ino;
 685         if (xiafs_lookup(new,"..",2,&new))
 686             break;
 687         if (new->i_ino == ino)
 688             break;
 689     }
 690     iput(new);
 691     return result;
 692 }
 693 
 694 #define PARENT_INO(buffer) \
 695     (((struct xiafs_direct *) ((u_char *)(buffer) + 12))->d_ino)
 696 
 697 /*
 698  * rename uses retry to avoid race-conditions: at least they should be minimal.
 699  * it tries to allocate all the blocks, then sanity-checks, and if the sanity-
 700  * checks fail, it tries to restart itself again. Very practical - no changes
 701  * are done until we know everything works ok.. and then all the changes can be
 702  * done in one fell swoop when we have claimed all the buffers needed.
 703  *
 704  * Anybody can rename anything with this: the permission checks are left to the
 705  * higher-level routines.
 706  */
 707 static int do_xiafs_rename(struct inode * old_dir, const char * old_name, 
     /* [previous][next][first][last][top][bottom][index][help] */
 708                          int old_len, struct inode * new_dir, 
 709                          const char * new_name, int new_len)
 710 {
 711     struct inode * old_inode, * new_inode;
 712     struct buffer_head * old_bh, * new_bh, * dir_bh;
 713     struct xiafs_direct * old_de, * old_de_pre, * new_de, * new_de_pre;
 714     int retval;
 715 
 716 try_again:
 717     old_inode = new_inode = NULL;
 718     old_bh = new_bh = dir_bh = NULL;
 719     old_bh = xiafs_find_entry(old_dir, old_name, old_len, &old_de, &old_de_pre);
 720     retval = -ENOENT;
 721     if (!old_bh)
 722         goto end_rename;
 723     old_inode = iget(old_dir->i_sb, old_de->d_ino);
 724     if (!old_inode)
 725         goto end_rename;
 726     retval = -EPERM;
 727     if ((old_dir->i_mode & S_ISVTX) && 
 728             current->euid != old_inode->i_uid &&
 729             current->euid != old_dir->i_uid && !suser())
 730         goto end_rename;
 731     new_bh = xiafs_find_entry(new_dir, new_name, new_len, &new_de, NULL);
 732     if (new_bh) {
 733         new_inode = iget(new_dir->i_sb, new_de->d_ino);
 734         if (!new_inode) {
 735             brelse(new_bh);
 736             new_bh = NULL;
 737         }
 738     }
 739     if (new_inode == old_inode) {
 740         retval = 0;
 741         goto end_rename;
 742     }
 743     if (new_inode && S_ISDIR(new_inode->i_mode)) {
 744         retval = -EEXIST;
 745         goto end_rename;
 746     }
 747     retval = -EPERM;
 748     if (new_inode && (new_dir->i_mode & S_ISVTX) && 
 749             current->euid != new_inode->i_uid &&
 750             current->euid != new_dir->i_uid && !suser())
 751         goto end_rename;
 752     if (S_ISDIR(old_inode->i_mode)) {
 753         retval = -EEXIST;
 754         if (new_bh)
 755             goto end_rename;
 756         retval = -EACCES;
 757         if (!permission(old_inode, MAY_WRITE))
 758             goto end_rename;
 759         retval = -EINVAL;
 760         if (subdir(new_dir, old_inode))
 761             goto end_rename;
 762         retval = -EIO;
 763         dir_bh = xiafs_bread(old_inode,0,0);
 764         if (!dir_bh)
 765             goto end_rename;
 766         if (PARENT_INO(dir_bh->b_data) != old_dir->i_ino)
 767             goto end_rename;
 768         retval = -EMLINK;
 769         if (new_dir->i_nlink > 64000)
 770             goto end_rename;
 771     }
 772     if (!new_bh)
 773         new_bh = xiafs_add_entry(new_dir, new_name, new_len, &new_de, &new_de_pre);
 774     retval = -ENOSPC;
 775     if (!new_bh) 
 776         goto end_rename;
 777     /* sanity checking */
 778     if ( (new_inode && (new_de->d_ino != new_inode->i_ino))
 779             || (new_de->d_ino && !new_inode)
 780             || (old_de->d_ino != old_inode->i_ino)) {
 781         xiafs_rm_entry(new_de, new_de_pre);
 782         brelse(old_bh);
 783         brelse(new_bh);
 784         brelse(dir_bh);
 785         iput(old_inode);
 786         iput(new_inode);
 787         current->counter=0;
 788         schedule();
 789         goto try_again;
 790     }
 791     xiafs_rm_entry(old_de, old_de_pre);
 792     new_de->d_ino = old_inode->i_ino;
 793     if (new_inode) {
 794         new_inode->i_nlink--;
 795         new_inode->i_dirt = 1;
 796     }
 797     old_bh->b_dirt = 1;
 798     new_bh->b_dirt = 1;
 799     if (dir_bh) {
 800         PARENT_INO(dir_bh->b_data) = new_dir->i_ino;
 801         dir_bh->b_dirt = 1;
 802         old_dir->i_nlink--;
 803         new_dir->i_nlink++;
 804         old_dir->i_dirt = 1;
 805         new_dir->i_dirt = 1;
 806     }
 807     retval = 0;
 808 end_rename:
 809     brelse(dir_bh);
 810     brelse(old_bh);
 811     brelse(new_bh);
 812     iput(old_inode);
 813     iput(new_inode);
 814     iput(old_dir);
 815     iput(new_dir);
 816     return retval;
 817 }
 818 
 819 /*
 820  * Ok, rename also locks out other renames, as they can change the parent of
 821  * a directory, and we don't want any races. Other races are checked for by
 822  * "do_rename()", which restarts if there are inconsistencies.
 823  *
 824  * Note that there is no race between different filesystems: it's only within
 825  * the same device that races occur: many renames can happen at once, as long
 826  * as they are on different partitions.
 827  */
 828 int xiafs_rename(struct inode * old_dir, const char * old_name, int old_len,
     /* [previous][next][first][last][top][bottom][index][help] */
 829         struct inode * new_dir, const char * new_name, int new_len)
 830 {
 831     static struct wait_queue * wait = NULL;
 832     static int lock = 0;
 833     int result;
 834 
 835     while (lock)
 836         sleep_on(&wait);
 837     lock = 1;
 838     result = do_xiafs_rename(old_dir, old_name, old_len,
 839                            new_dir, new_name, new_len);
 840     lock = 0;
 841     wake_up(&wait);
 842     return result;
 843 }
 844 
 845 
 846 
 847 
 848 

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