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