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 
  17 static int nfs_readlink(struct inode *, char *, int);
  18 static int nfs_follow_link(struct inode *, struct inode *, int, int,
  19                            struct inode **);
  20 
  21 /*
  22  * symlinks can't do much...
  23  */
  24 struct inode_operations nfs_symlink_inode_operations = {
  25         NULL,                   /* no file-operations */
  26         NULL,                   /* create */
  27         NULL,                   /* lookup */
  28         NULL,                   /* link */
  29         NULL,                   /* unlink */
  30         NULL,                   /* symlink */
  31         NULL,                   /* mkdir */
  32         NULL,                   /* rmdir */
  33         NULL,                   /* mknod */
  34         NULL,                   /* rename */
  35         nfs_readlink,           /* readlink */
  36         nfs_follow_link,        /* follow_link */
  37         NULL,                   /* bmap */
  38         NULL,                   /* truncate */
  39         NULL                    /* permission */
  40 };
  41 
  42 static int nfs_follow_link(struct inode *dir, struct inode *inode,
     /* [previous][next][first][last][top][bottom][index][help] */
  43                            int flag, int mode, struct inode **res_inode)
  44 {
  45         int error;
  46         unsigned short fs;
  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         __asm__("mov %%fs,%0":"=r" (fs));
  78         __asm__("mov %0,%%fs"::"r" ((unsigned short) 0x10));
  79         current->link_count++;
  80         error = open_namei(res, flag, mode, res_inode, dir);
  81         current->link_count--;
  82         kfree_s(res, NFS_MAXPATHLEN + 1);
  83         __asm__("mov %0,%%fs"::"r" (fs));
  84         return error;
  85 }
  86 
  87 static int nfs_readlink(struct inode *inode, char *buffer, int buflen)
     /* [previous][next][first][last][top][bottom][index][help] */
  88 {
  89         int i;
  90         char c;
  91         int error;
  92         char *res;
  93 
  94         if (!S_ISLNK(inode->i_mode)) {
  95                 iput(inode);
  96                 return -EINVAL;
  97         }
  98         if (buflen > NFS_MAXPATHLEN)
  99                 buflen = NFS_MAXPATHLEN;
 100         res = (char *) kmalloc(buflen + 1, GFP_KERNEL);
 101         error = nfs_proc_readlink(NFS_SERVER(inode), NFS_FH(inode), res);
 102         iput(inode);
 103         if (error) {
 104                 kfree_s(res, buflen + 1);
 105                 return error;
 106         }
 107         for (i = 0; i < buflen && (c = res[i]); i++)
 108                 put_fs_byte(c,buffer++);
 109         kfree_s(res, buflen + 1);
 110         return i;
 111 }

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