root/fs/namei.c

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

DEFINITIONS

This source file includes following definitions.
  1. permission
  2. match
  3. find_entry
  4. add_entry
  5. get_dir
  6. dir_namei
  7. namei
  8. open_namei
  9. sys_mknod
  10. sys_mkdir
  11. empty_dir
  12. sys_rmdir
  13. sys_unlink
  14. sys_link

   1 /*
   2  *  linux/fs/namei.c
   3  *
   4  *  (C) 1991  Linus Torvalds
   5  */
   6 
   7 #include <linux/sched.h>
   8 #include <linux/kernel.h>
   9 #include <asm/segment.h>
  10 
  11 #include <string.h>
  12 #include <fcntl.h>
  13 #include <errno.h>
  14 #include <const.h>
  15 #include <sys/stat.h>
  16 
  17 #define ACC_MODE(x) ("\004\002\006\377"[(x)&O_ACCMODE])
  18 
  19 /*
  20  * comment out this line if you want names > NAME_LEN chars to be
  21  * truncated. Else they will be disallowed.
  22  */
  23 /* #define NO_TRUNCATE */
  24 
  25 #define MAY_EXEC 1
  26 #define MAY_WRITE 2
  27 #define MAY_READ 4
  28 
  29 /*
  30  *      permission()
  31  *
  32  * is used to check for read/write/execute permissions on a file.
  33  * I don't know if we should look at just the euid or both euid and
  34  * uid, but that should be easily changed.
  35  */
  36 static int permission(struct m_inode * inode,int mask)
     /* [previous][next][first][last][top][bottom][index][help] */
  37 {
  38         int mode = inode->i_mode;
  39 
  40 /* special case: not even root can read/write a deleted file */
  41         if (inode->i_dev && !inode->i_nlinks)
  42                 return 0;
  43         else if (current->euid==inode->i_uid)
  44                 mode >>= 6;
  45         else if (current->egid==inode->i_gid)
  46                 mode >>= 3;
  47         if (((mode & mask & 0007) == mask) || suser())
  48                 return 1;
  49         return 0;
  50 }
  51 
  52 /*
  53  * ok, we cannot use strncmp, as the name is not in our data space.
  54  * Thus we'll have to use match. No big problem. Match also makes
  55  * some sanity tests.
  56  *
  57  * NOTE! unlike strncmp, match returns 1 for success, 0 for failure.
  58  */
  59 static int match(int len,const char * name,struct dir_entry * de)
     /* [previous][next][first][last][top][bottom][index][help] */
  60 {
  61         register int same __asm__("ax");
  62 
  63         if (!de || !de->inode || len > NAME_LEN)
  64                 return 0;
  65         if (len < NAME_LEN && de->name[len])
  66                 return 0;
  67         __asm__("cld\n\t"
  68                 "fs ; repe ; cmpsb\n\t"
  69                 "setz %%al"
  70                 :"=a" (same)
  71                 :"0" (0),"S" ((long) name),"D" ((long) de->name),"c" (len)
  72                 :"cx","di","si");
  73         return same;
  74 }
  75 
  76 /*
  77  *      find_entry()
  78  *
  79  * finds and entry in the specified directory with the wanted name. It
  80  * returns the cache buffer in which the entry was found, and the entry
  81  * itself (as a parameter - res_dir). It does NOT read the inode of the
  82  * entry - you'll have to do that yourself if you want to.
  83  *
  84  * This also takes care of the few special cases due to '..'-traversal
  85  * over a pseudo-root and a mount point.
  86  */
  87 static struct buffer_head * find_entry(struct m_inode ** dir,
     /* [previous][next][first][last][top][bottom][index][help] */
  88         const char * name, int namelen, struct dir_entry ** res_dir)
  89 {
  90         int entries;
  91         int block,i;
  92         struct buffer_head * bh;
  93         struct dir_entry * de;
  94         struct super_block * sb;
  95 
  96 #ifdef NO_TRUNCATE
  97         if (namelen > NAME_LEN)
  98                 return NULL;
  99 #else
 100         if (namelen > NAME_LEN)
 101                 namelen = NAME_LEN;
 102 #endif
 103         entries = (*dir)->i_size / (sizeof (struct dir_entry));
 104         *res_dir = NULL;
 105         if (!namelen)
 106                 return NULL;
 107 /* check for '..', as we might have to do some "magic" for it */
 108         if (namelen==2 && get_fs_byte(name)=='.' && get_fs_byte(name+1)=='.') {
 109 /* '..' in a pseudo-root results in a faked '.' (just change namelen) */
 110                 if ((*dir) == current->root)
 111                         namelen=1;
 112                 else if ((*dir)->i_num == ROOT_INO) {
 113 /* '..' over a mount-point results in 'dir' being exchanged for the mounted
 114    directory-inode. NOTE! We set mounted, so that we can iput the new dir */
 115                         sb=get_super((*dir)->i_dev);
 116                         if (sb->s_imount) {
 117                                 iput(*dir);
 118                                 (*dir)=sb->s_imount;
 119                                 (*dir)->i_count++;
 120                         }
 121                 }
 122         }
 123         if (!(block = (*dir)->i_zone[0]))
 124                 return NULL;
 125         if (!(bh = bread((*dir)->i_dev,block)))
 126                 return NULL;
 127         i = 0;
 128         de = (struct dir_entry *) bh->b_data;
 129         while (i < entries) {
 130                 if ((char *)de >= BLOCK_SIZE+bh->b_data) {
 131                         brelse(bh);
 132                         bh = NULL;
 133                         if (!(block = bmap(*dir,i/DIR_ENTRIES_PER_BLOCK)) ||
 134                             !(bh = bread((*dir)->i_dev,block))) {
 135                                 i += DIR_ENTRIES_PER_BLOCK;
 136                                 continue;
 137                         }
 138                         de = (struct dir_entry *) bh->b_data;
 139                 }
 140                 if (match(namelen,name,de)) {
 141                         *res_dir = de;
 142                         return bh;
 143                 }
 144                 de++;
 145                 i++;
 146         }
 147         brelse(bh);
 148         return NULL;
 149 }
 150 
 151 /*
 152  *      add_entry()
 153  *
 154  * adds a file entry to the specified directory, using the same
 155  * semantics as find_entry(). It returns NULL if it failed.
 156  *
 157  * NOTE!! The inode part of 'de' is left at 0 - which means you
 158  * may not sleep between calling this and putting something into
 159  * the entry, as someone else might have used it while you slept.
 160  */
 161 static struct buffer_head * add_entry(struct m_inode * dir,
     /* [previous][next][first][last][top][bottom][index][help] */
 162         const char * name, int namelen, struct dir_entry ** res_dir)
 163 {
 164         int block,i;
 165         struct buffer_head * bh;
 166         struct dir_entry * de;
 167 
 168         *res_dir = NULL;
 169 #ifdef NO_TRUNCATE
 170         if (namelen > NAME_LEN)
 171                 return NULL;
 172 #else
 173         if (namelen > NAME_LEN)
 174                 namelen = NAME_LEN;
 175 #endif
 176         if (!namelen)
 177                 return NULL;
 178         if (!(block = dir->i_zone[0]))
 179                 return NULL;
 180         if (!(bh = bread(dir->i_dev,block)))
 181                 return NULL;
 182         i = 0;
 183         de = (struct dir_entry *) bh->b_data;
 184         while (1) {
 185                 if ((char *)de >= BLOCK_SIZE+bh->b_data) {
 186                         brelse(bh);
 187                         bh = NULL;
 188                         block = create_block(dir,i/DIR_ENTRIES_PER_BLOCK);
 189                         if (!block)
 190                                 return NULL;
 191                         if (!(bh = bread(dir->i_dev,block))) {
 192                                 i += DIR_ENTRIES_PER_BLOCK;
 193                                 continue;
 194                         }
 195                         de = (struct dir_entry *) bh->b_data;
 196                 }
 197                 if (i*sizeof(struct dir_entry) >= dir->i_size) {
 198                         de->inode=0;
 199                         dir->i_size = (i+1)*sizeof(struct dir_entry);
 200                         dir->i_dirt = 1;
 201                         dir->i_ctime = CURRENT_TIME;
 202                 }
 203                 if (!de->inode) {
 204                         dir->i_mtime = CURRENT_TIME;
 205                         for (i=0; i < NAME_LEN ; i++)
 206                                 de->name[i]=(i<namelen)?get_fs_byte(name+i):0;
 207                         bh->b_dirt = 1;
 208                         *res_dir = de;
 209                         return bh;
 210                 }
 211                 de++;
 212                 i++;
 213         }
 214         brelse(bh);
 215         return NULL;
 216 }
 217 
 218 /*
 219  *      get_dir()
 220  *
 221  * Getdir traverses the pathname until it hits the topmost directory.
 222  * It returns NULL on failure.
 223  */
 224 static struct m_inode * get_dir(const char * pathname)
     /* [previous][next][first][last][top][bottom][index][help] */
 225 {
 226         char c;
 227         const char * thisname;
 228         struct m_inode * inode;
 229         struct buffer_head * bh;
 230         int namelen,inr,idev;
 231         struct dir_entry * de;
 232 
 233         if (!current->root || !current->root->i_count)
 234                 panic("No root inode");
 235         if (!current->pwd || !current->pwd->i_count)
 236                 panic("No cwd inode");
 237         if ((c=get_fs_byte(pathname))=='/') {
 238                 inode = current->root;
 239                 pathname++;
 240         } else if (c)
 241                 inode = current->pwd;
 242         else
 243                 return NULL;    /* empty name is bad */
 244         inode->i_count++;
 245         while (1) {
 246                 thisname = pathname;
 247                 if (!S_ISDIR(inode->i_mode) || !permission(inode,MAY_EXEC)) {
 248                         iput(inode);
 249                         return NULL;
 250                 }
 251                 for(namelen=0;(c=get_fs_byte(pathname++))&&(c!='/');namelen++)
 252                         /* nothing */ ;
 253                 if (!c)
 254                         return inode;
 255                 if (!(bh = find_entry(&inode,thisname,namelen,&de))) {
 256                         iput(inode);
 257                         return NULL;
 258                 }
 259                 inr = de->inode;
 260                 idev = inode->i_dev;
 261                 brelse(bh);
 262                 iput(inode);
 263                 if (!(inode = iget(idev,inr)))
 264                         return NULL;
 265         }
 266 }
 267 
 268 /*
 269  *      dir_namei()
 270  *
 271  * dir_namei() returns the inode of the directory of the
 272  * specified name, and the name within that directory.
 273  */
 274 static struct m_inode * dir_namei(const char * pathname,
     /* [previous][next][first][last][top][bottom][index][help] */
 275         int * namelen, const char ** name)
 276 {
 277         char c;
 278         const char * basename;
 279         struct m_inode * dir;
 280 
 281         if (!(dir = get_dir(pathname)))
 282                 return NULL;
 283         basename = pathname;
 284         while (c=get_fs_byte(pathname++))
 285                 if (c=='/')
 286                         basename=pathname;
 287         *namelen = pathname-basename-1;
 288         *name = basename;
 289         return dir;
 290 }
 291 
 292 /*
 293  *      namei()
 294  *
 295  * is used by most simple commands to get the inode of a specified name.
 296  * Open, link etc use their own routines, but this is enough for things
 297  * like 'chmod' etc.
 298  */
 299 struct m_inode * namei(const char * pathname)
     /* [previous][next][first][last][top][bottom][index][help] */
 300 {
 301         const char * basename;
 302         int inr,dev,namelen;
 303         struct m_inode * dir;
 304         struct buffer_head * bh;
 305         struct dir_entry * de;
 306 
 307         if (!(dir = dir_namei(pathname,&namelen,&basename)))
 308                 return NULL;
 309         if (!namelen)                   /* special case: '/usr/' etc */
 310                 return dir;
 311         bh = find_entry(&dir,basename,namelen,&de);
 312         if (!bh) {
 313                 iput(dir);
 314                 return NULL;
 315         }
 316         inr = de->inode;
 317         dev = dir->i_dev;
 318         brelse(bh);
 319         iput(dir);
 320         dir=iget(dev,inr);
 321         if (dir) {
 322                 dir->i_atime=CURRENT_TIME;
 323                 dir->i_dirt=1;
 324         }
 325         return dir;
 326 }
 327 
 328 /*
 329  *      open_namei()
 330  *
 331  * namei for open - this is in fact almost the whole open-routine.
 332  */
 333 int open_namei(const char * pathname, int flag, int mode,
     /* [previous][next][first][last][top][bottom][index][help] */
 334         struct m_inode ** res_inode)
 335 {
 336         const char * basename;
 337         int inr,dev,namelen;
 338         struct m_inode * dir, *inode;
 339         struct buffer_head * bh;
 340         struct dir_entry * de;
 341 
 342         if ((flag & O_TRUNC) && !(flag & O_ACCMODE))
 343                 flag |= O_WRONLY;
 344         mode &= 0777 & ~current->umask;
 345         mode |= I_REGULAR;
 346         if (!(dir = dir_namei(pathname,&namelen,&basename)))
 347                 return -ENOENT;
 348         if (!namelen) {                 /* special case: '/usr/' etc */
 349                 if (!(flag & (O_ACCMODE|O_CREAT|O_TRUNC))) {
 350                         *res_inode=dir;
 351                         return 0;
 352                 }
 353                 iput(dir);
 354                 return -EISDIR;
 355         }
 356         bh = find_entry(&dir,basename,namelen,&de);
 357         if (!bh) {
 358                 if (!(flag & O_CREAT)) {
 359                         iput(dir);
 360                         return -ENOENT;
 361                 }
 362                 if (!permission(dir,MAY_WRITE)) {
 363                         iput(dir);
 364                         return -EACCES;
 365                 }
 366                 inode = new_inode(dir->i_dev);
 367                 if (!inode) {
 368                         iput(dir);
 369                         return -ENOSPC;
 370                 }
 371                 inode->i_uid = current->euid;
 372                 inode->i_mode = mode;
 373                 inode->i_dirt = 1;
 374                 bh = add_entry(dir,basename,namelen,&de);
 375                 if (!bh) {
 376                         inode->i_nlinks--;
 377                         iput(inode);
 378                         iput(dir);
 379                         return -ENOSPC;
 380                 }
 381                 de->inode = inode->i_num;
 382                 bh->b_dirt = 1;
 383                 brelse(bh);
 384                 iput(dir);
 385                 *res_inode = inode;
 386                 return 0;
 387         }
 388         inr = de->inode;
 389         dev = dir->i_dev;
 390         brelse(bh);
 391         iput(dir);
 392         if (flag & O_EXCL)
 393                 return -EEXIST;
 394         if (!(inode=iget(dev,inr)))
 395                 return -EACCES;
 396         if ((S_ISDIR(inode->i_mode) && (flag & O_ACCMODE)) ||
 397             !permission(inode,ACC_MODE(flag))) {
 398                 iput(inode);
 399                 return -EPERM;
 400         }
 401         inode->i_atime = CURRENT_TIME;
 402         if (flag & O_TRUNC)
 403                 truncate(inode);
 404         *res_inode = inode;
 405         return 0;
 406 }
 407 
 408 int sys_mknod(const char * filename, int mode, int dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 409 {
 410         const char * basename;
 411         int namelen;
 412         struct m_inode * dir, * inode;
 413         struct buffer_head * bh;
 414         struct dir_entry * de;
 415         
 416         if (!suser())
 417                 return -EPERM;
 418         if (!(dir = dir_namei(filename,&namelen,&basename)))
 419                 return -ENOENT;
 420         if (!namelen) {
 421                 iput(dir);
 422                 return -ENOENT;
 423         }
 424         if (!permission(dir,MAY_WRITE)) {
 425                 iput(dir);
 426                 return -EPERM;
 427         }
 428         bh = find_entry(&dir,basename,namelen,&de);
 429         if (bh) {
 430                 brelse(bh);
 431                 iput(dir);
 432                 return -EEXIST;
 433         }
 434         inode = new_inode(dir->i_dev);
 435         if (!inode) {
 436                 iput(dir);
 437                 return -ENOSPC;
 438         }
 439         inode->i_mode = mode;
 440         if (S_ISBLK(mode) || S_ISCHR(mode))
 441                 inode->i_zone[0] = dev;
 442         inode->i_mtime = inode->i_atime = CURRENT_TIME;
 443         inode->i_dirt = 1;
 444         bh = add_entry(dir,basename,namelen,&de);
 445         if (!bh) {
 446                 iput(dir);
 447                 inode->i_nlinks=0;
 448                 iput(inode);
 449                 return -ENOSPC;
 450         }
 451         de->inode = inode->i_num;
 452         bh->b_dirt = 1;
 453         iput(dir);
 454         iput(inode);
 455         brelse(bh);
 456         return 0;
 457 }
 458 
 459 int sys_mkdir(const char * pathname, int mode)
     /* [previous][next][first][last][top][bottom][index][help] */
 460 {
 461         const char * basename;
 462         int namelen;
 463         struct m_inode * dir, * inode;
 464         struct buffer_head * bh, *dir_block;
 465         struct dir_entry * de;
 466 
 467         if (!suser())
 468                 return -EPERM;
 469         if (!(dir = dir_namei(pathname,&namelen,&basename)))
 470                 return -ENOENT;
 471         if (!namelen) {
 472                 iput(dir);
 473                 return -ENOENT;
 474         }
 475         if (!permission(dir,MAY_WRITE)) {
 476                 iput(dir);
 477                 return -EPERM;
 478         }
 479         bh = find_entry(&dir,basename,namelen,&de);
 480         if (bh) {
 481                 brelse(bh);
 482                 iput(dir);
 483                 return -EEXIST;
 484         }
 485         inode = new_inode(dir->i_dev);
 486         if (!inode) {
 487                 iput(dir);
 488                 return -ENOSPC;
 489         }
 490         inode->i_size = 32;
 491         inode->i_dirt = 1;
 492         inode->i_mtime = inode->i_atime = CURRENT_TIME;
 493         if (!(inode->i_zone[0]=new_block(inode->i_dev))) {
 494                 iput(dir);
 495                 inode->i_nlinks--;
 496                 iput(inode);
 497                 return -ENOSPC;
 498         }
 499         inode->i_dirt = 1;
 500         if (!(dir_block=bread(inode->i_dev,inode->i_zone[0]))) {
 501                 iput(dir);
 502                 free_block(inode->i_dev,inode->i_zone[0]);
 503                 inode->i_nlinks--;
 504                 iput(inode);
 505                 return -ERROR;
 506         }
 507         de = (struct dir_entry *) dir_block->b_data;
 508         de->inode=inode->i_num;
 509         strcpy(de->name,".");
 510         de++;
 511         de->inode = dir->i_num;
 512         strcpy(de->name,"..");
 513         inode->i_nlinks = 2;
 514         dir_block->b_dirt = 1;
 515         brelse(dir_block);
 516         inode->i_mode = I_DIRECTORY | (mode & 0777 & ~current->umask);
 517         inode->i_dirt = 1;
 518         bh = add_entry(dir,basename,namelen,&de);
 519         if (!bh) {
 520                 iput(dir);
 521                 free_block(inode->i_dev,inode->i_zone[0]);
 522                 inode->i_nlinks=0;
 523                 iput(inode);
 524                 return -ENOSPC;
 525         }
 526         de->inode = inode->i_num;
 527         bh->b_dirt = 1;
 528         dir->i_nlinks++;
 529         dir->i_dirt = 1;
 530         iput(dir);
 531         iput(inode);
 532         brelse(bh);
 533         return 0;
 534 }
 535 
 536 /*
 537  * routine to check that the specified directory is empty (for rmdir)
 538  */
 539 static int empty_dir(struct m_inode * inode)
     /* [previous][next][first][last][top][bottom][index][help] */
 540 {
 541         int nr,block;
 542         int len;
 543         struct buffer_head * bh;
 544         struct dir_entry * de;
 545 
 546         len = inode->i_size / sizeof (struct dir_entry);
 547         if (len<2 || !inode->i_zone[0] ||
 548             !(bh=bread(inode->i_dev,inode->i_zone[0]))) {
 549                 printk("warning - bad directory on dev %04x\n",inode->i_dev);
 550                 return 0;
 551         }
 552         de = (struct dir_entry *) bh->b_data;
 553         if (de[0].inode != inode->i_num || !de[1].inode || 
 554             strcmp(".",de[0].name) || strcmp("..",de[1].name)) {
 555                 printk("warning - bad directory on dev %04x\n",inode->i_dev);
 556                 return 0;
 557         }
 558         nr = 2;
 559         de += 2;
 560         while (nr<len) {
 561                 if ((void *) de >= (void *) (bh->b_data+BLOCK_SIZE)) {
 562                         brelse(bh);
 563                         block=bmap(inode,nr/DIR_ENTRIES_PER_BLOCK);
 564                         if (!block) {
 565                                 nr += DIR_ENTRIES_PER_BLOCK;
 566                                 continue;
 567                         }
 568                         if (!(bh=bread(inode->i_dev,block)))
 569                                 return 0;
 570                         de = (struct dir_entry *) bh->b_data;
 571                 }
 572                 if (de->inode) {
 573                         brelse(bh);
 574                         return 0;
 575                 }
 576                 de++;
 577                 nr++;
 578         }
 579         brelse(bh);
 580         return 1;
 581 }
 582 
 583 int sys_rmdir(const char * name)
     /* [previous][next][first][last][top][bottom][index][help] */
 584 {
 585         const char * basename;
 586         int namelen;
 587         struct m_inode * dir, * inode;
 588         struct buffer_head * bh;
 589         struct dir_entry * de;
 590 
 591         if (!suser())
 592                 return -EPERM;
 593         if (!(dir = dir_namei(name,&namelen,&basename)))
 594                 return -ENOENT;
 595         if (!namelen) {
 596                 iput(dir);
 597                 return -ENOENT;
 598         }
 599         bh = find_entry(&dir,basename,namelen,&de);
 600         if (!bh) {
 601                 iput(dir);
 602                 return -ENOENT;
 603         }
 604         if (!permission(dir,MAY_WRITE)) {
 605                 iput(dir);
 606                 brelse(bh);
 607                 return -EPERM;
 608         }
 609         if (!(inode = iget(dir->i_dev, de->inode))) {
 610                 iput(dir);
 611                 brelse(bh);
 612                 return -EPERM;
 613         }
 614         if (inode == dir) {     /* we may not delete ".", but "../dir" is ok */
 615                 iput(inode);
 616                 iput(dir);
 617                 brelse(bh);
 618                 return -EPERM;
 619         }
 620         if (!S_ISDIR(inode->i_mode)) {
 621                 iput(inode);
 622                 iput(dir);
 623                 brelse(bh);
 624                 return -ENOTDIR;
 625         }
 626         if (!empty_dir(inode)) {
 627                 iput(inode);
 628                 iput(dir);
 629                 brelse(bh);
 630                 return -ENOTEMPTY;
 631         }
 632         if (inode->i_nlinks != 2)
 633                 printk("empty directory has nlink!=2 (%d)",inode->i_nlinks);
 634         de->inode = 0;
 635         bh->b_dirt = 1;
 636         brelse(bh);
 637         inode->i_nlinks=0;
 638         inode->i_dirt=1;
 639         dir->i_nlinks--;
 640         dir->i_ctime = dir->i_mtime = CURRENT_TIME;
 641         dir->i_dirt=1;
 642         iput(dir);
 643         iput(inode);
 644         return 0;
 645 }
 646 
 647 int sys_unlink(const char * name)
     /* [previous][next][first][last][top][bottom][index][help] */
 648 {
 649         const char * basename;
 650         int namelen;
 651         struct m_inode * dir, * inode;
 652         struct buffer_head * bh;
 653         struct dir_entry * de;
 654 
 655         if (!(dir = dir_namei(name,&namelen,&basename)))
 656                 return -ENOENT;
 657         if (!namelen) {
 658                 iput(dir);
 659                 return -ENOENT;
 660         }
 661         if (!permission(dir,MAY_WRITE)) {
 662                 iput(dir);
 663                 return -EPERM;
 664         }
 665         bh = find_entry(&dir,basename,namelen,&de);
 666         if (!bh) {
 667                 iput(dir);
 668                 return -ENOENT;
 669         }
 670         inode = iget(dir->i_dev, de->inode);
 671         if (!inode) {
 672                 printk("iget failed in delete (%04x:%d)",dir->i_dev,de->inode);
 673                 iput(dir);
 674                 brelse(bh);
 675                 return -ENOENT;
 676         }
 677         if (S_ISDIR(inode->i_mode)) {
 678                 iput(inode);
 679                 iput(dir);
 680                 brelse(bh);
 681                 return -EPERM;
 682         }
 683         /*
 684          * If the directory has the sticky bit, the user must either
 685          * own the file or own the directory or be the superuser to 
 686          * delete a file in that directory.  This is typically used 
 687          * for /tmp and /usr/tmp.
 688          */
 689         if ((dir->i_mode & S_ISVTX) && (current->euid != inode->i_uid) &&
 690             (current->euid != dir->i_uid) && !suser()) {
 691                 iput(inode);
 692                 iput(dir);
 693                 brelse(bh);
 694                 return -EPERM;
 695         }               
 696         if (!inode->i_nlinks) {
 697                 printk("Deleting nonexistent file (%04x:%d), %d\n",
 698                         inode->i_dev,inode->i_num,inode->i_nlinks);
 699                 inode->i_nlinks=1;
 700         }
 701         de->inode = 0;
 702         bh->b_dirt = 1;
 703         brelse(bh);
 704         inode->i_nlinks--;
 705         inode->i_dirt = 1;
 706         inode->i_ctime = CURRENT_TIME;
 707         iput(inode);
 708         iput(dir);
 709         return 0;
 710 }
 711 
 712 int sys_link(const char * oldname, const char * newname)
     /* [previous][next][first][last][top][bottom][index][help] */
 713 {
 714         struct dir_entry * de;
 715         struct m_inode * oldinode, * dir;
 716         struct buffer_head * bh;
 717         const char * basename;
 718         int namelen;
 719 
 720         oldinode=namei(oldname);
 721         if (!oldinode)
 722                 return -ENOENT;
 723         if (S_ISDIR(oldinode->i_mode)) {
 724                 iput(oldinode);
 725                 return -EPERM;
 726         }
 727         dir = dir_namei(newname,&namelen,&basename);
 728         if (!dir) {
 729                 iput(oldinode);
 730                 return -EACCES;
 731         }
 732         if (!namelen) {
 733                 iput(oldinode);
 734                 iput(dir);
 735                 return -EPERM;
 736         }
 737         if (dir->i_dev != oldinode->i_dev) {
 738                 iput(dir);
 739                 iput(oldinode);
 740                 return -EXDEV;
 741         }
 742         if (!permission(dir,MAY_WRITE)) {
 743                 iput(dir);
 744                 iput(oldinode);
 745                 return -EACCES;
 746         }
 747         bh = find_entry(&dir,basename,namelen,&de);
 748         if (bh) {
 749                 brelse(bh);
 750                 iput(dir);
 751                 iput(oldinode);
 752                 return -EEXIST;
 753         }
 754         bh = add_entry(dir,basename,namelen,&de);
 755         if (!bh) {
 756                 iput(dir);
 757                 iput(oldinode);
 758                 return -ENOSPC;
 759         }
 760         de->inode = oldinode->i_num;
 761         bh->b_dirt = 1;
 762         brelse(bh);
 763         iput(dir);
 764         oldinode->i_nlinks++;
 765         oldinode->i_ctime = CURRENT_TIME;
 766         oldinode->i_dirt = 1;
 767         iput(oldinode);
 768         return 0;
 769 }

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