home *** CD-ROM | disk | FTP | other *** search
/ Il CD di internet / CD.iso / SOURCE / KERNEL-S / V1.0 / LINUX-1.0 / LINUX-1 / linux / fs / ext / namei.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-12-01  |  21.7 KB  |  901 lines

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