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 / nfs / symlink.c < prev   
Encoding:
C/C++ Source or Header  |  1995-01-23  |  2.4 KB  |  121 lines

  1. /*
  2.  *  linux/fs/nfs/symlink.c
  3.  *
  4.  *  Copyright (C) 1992  Rick Sladkey
  5.  *
  6.  *  Optimization changes Copyright (C) 1994 Florian La Roche
  7.  *
  8.  *  nfs symlink handling code
  9.  */
  10.  
  11. #ifdef MODULE
  12. #include <linux/module.h>
  13. #endif
  14.  
  15. #include <asm/segment.h>
  16.  
  17. #include <linux/sched.h>
  18. #include <linux/errno.h>
  19. #include <linux/nfs_fs.h>
  20. #include <linux/stat.h>
  21. #include <linux/mm.h>
  22. #include <linux/malloc.h>
  23. #include <linux/string.h>
  24.  
  25. static int nfs_readlink(struct inode *, char *, int);
  26. static int nfs_follow_link(struct inode *, struct inode *, int, int,
  27.                struct inode **);
  28.  
  29. /*
  30.  * symlinks can't do much...
  31.  */
  32. struct inode_operations nfs_symlink_inode_operations = {
  33.     NULL,            /* no file-operations */
  34.     NULL,            /* create */
  35.     NULL,            /* lookup */
  36.     NULL,            /* link */
  37.     NULL,            /* unlink */
  38.     NULL,            /* symlink */
  39.     NULL,            /* mkdir */
  40.     NULL,            /* rmdir */
  41.     NULL,            /* mknod */
  42.     NULL,            /* rename */
  43.     nfs_readlink,        /* readlink */
  44.     nfs_follow_link,    /* follow_link */
  45.     NULL,            /* bmap */
  46.     NULL,            /* truncate */
  47.     NULL            /* permission */
  48. };
  49.  
  50. static int nfs_follow_link(struct inode *dir, struct inode *inode,
  51.                int flag, int mode, struct inode **res_inode)
  52. {
  53.     int error, *mem;
  54.     unsigned int len;
  55.     char *res, *res2;
  56.  
  57.     *res_inode = NULL;
  58.     if (!dir) {
  59.         dir = current->fs->root;
  60.         dir->i_count++;
  61.     }
  62.     if (!inode) {
  63.         iput(dir);
  64.         return -ENOENT;
  65.     }
  66.     if (!S_ISLNK(inode->i_mode)) {
  67.         iput(dir);
  68.         *res_inode = inode;
  69.         return 0;
  70.     }
  71.     if (current->link_count > 5) {
  72.         iput(inode);
  73.         iput(dir);
  74.         return -ELOOP;
  75.     }
  76.     error = nfs_proc_readlink(NFS_SERVER(inode), NFS_FH(inode), &mem,
  77.         &res, &len, NFS_MAXPATHLEN);
  78.     if (error) {
  79.         iput(inode);
  80.         iput(dir);
  81.         kfree(mem);
  82.         return error;
  83.     }
  84.     while ((res2 = (char *) kmalloc(NFS_MAXPATHLEN + 1, GFP_NFS)) == NULL) {
  85.         schedule();
  86.     }
  87.     memcpy(res2, res, len);
  88.     res2[len] = '\0';
  89.     kfree(mem);
  90.     iput(inode);
  91.     current->link_count++;
  92.     error = open_namei(res2, flag, mode, res_inode, dir);
  93.     current->link_count--;
  94.     kfree_s(res2, NFS_MAXPATHLEN + 1);
  95.     return error;
  96. }
  97.  
  98. static int nfs_readlink(struct inode *inode, char *buffer, int buflen)
  99. {
  100.     int error, *mem;
  101.     unsigned int len;
  102.     char *res;
  103.  
  104.     if (!S_ISLNK(inode->i_mode)) {
  105.         iput(inode);
  106.         return -EINVAL;
  107.     }
  108.     if (buflen > NFS_MAXPATHLEN)
  109.         buflen = NFS_MAXPATHLEN;
  110.     error = nfs_proc_readlink(NFS_SERVER(inode), NFS_FH(inode), &mem,
  111.         &res, &len, buflen);
  112.     iput(inode);
  113.     if (! error) {
  114.         memcpy_tofs(buffer, res, len);
  115.         put_fs_byte('\0', buffer + len);
  116.         error = len;
  117.     }
  118.     kfree(mem);
  119.     return error;
  120. }
  121.