root/fs/nfs/symlink.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. nfs_follow_link
  2. nfs_readlink

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

/* [previous][next][first][last][top][bottom][index][help] */