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 / minix / namei.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-12-01  |  18.5 KB  |  829 lines

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