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