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

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