root/fs/sysv/symlink.c

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

DEFINITIONS

This source file includes following definitions.
  1. sysv_follow_link
  2. sysv_readlink

   1 /*
   2  *  linux/fs/sysv/symlink.c
   3  *
   4  *  minix/symlink.c
   5  *  Copyright (C) 1991, 1992  Linus Torvalds
   6  *
   7  *  coh/symlink.c
   8  *  Copyright (C) 1993  Pascal Haible, Bruno Haible
   9  *
  10  *  sysv/symlink.c
  11  *  Copyright (C) 1993  Bruno Haible
  12  *
  13  *  SystemV/Coherent symlink handling code
  14  */
  15 
  16 #ifdef MODULE
  17 #include <linux/module.h>
  18 #endif
  19 
  20 #include <asm/segment.h>
  21 
  22 #include <linux/errno.h>
  23 #include <linux/sched.h>
  24 #include <linux/sysv_fs.h>
  25 #include <linux/stat.h>
  26 
  27 static int sysv_readlink(struct inode *, char *, int);
  28 static int sysv_follow_link(struct inode *, struct inode *, int, int, struct inode **);
  29 
  30 /*
  31  * symlinks can't do much...
  32  */
  33 struct inode_operations sysv_symlink_inode_operations = {
  34         NULL,                   /* no file-operations */
  35         NULL,                   /* create */
  36         NULL,                   /* lookup */
  37         NULL,                   /* link */
  38         NULL,                   /* unlink */
  39         NULL,                   /* symlink */
  40         NULL,                   /* mkdir */
  41         NULL,                   /* rmdir */
  42         NULL,                   /* mknod */
  43         NULL,                   /* rename */
  44         sysv_readlink,          /* readlink */
  45         sysv_follow_link,       /* follow_link */
  46         NULL,                   /* bmap */
  47         NULL,                   /* truncate */
  48         NULL                    /* permission */
  49 };
  50 
  51 static int sysv_follow_link(struct inode * dir, struct inode * inode,
     /* [previous][next][first][last][top][bottom][index][help] */
  52         int flag, int mode, struct inode ** res_inode)
  53 {
  54         int error;
  55         struct buffer_head * bh;
  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         if (!(bh = sysv_file_bread(inode, 0, 0))) { /* is reading 1 block enough ?? */
  77                 iput(inode);
  78                 iput(dir);
  79                 return -EIO;
  80         }
  81         iput(inode);
  82         current->link_count++;
  83         error = open_namei(bh->b_data,flag,mode,res_inode,dir);
  84         current->link_count--;
  85         brelse(bh);
  86         return error;
  87 }
  88 
  89 static int sysv_readlink(struct inode * inode, char * buffer, int buflen)
     /* [previous][next][first][last][top][bottom][index][help] */
  90 {
  91         struct buffer_head * bh;
  92         char * bh_data;
  93         int i;
  94         char c;
  95 
  96         if (!S_ISLNK(inode->i_mode)) {
  97                 iput(inode);
  98                 return -EINVAL;
  99         }
 100         if (buflen > inode->i_sb->sv_block_size_1)
 101                 buflen = inode->i_sb->sv_block_size_1;
 102         bh = sysv_file_bread(inode, 0, 0);
 103         iput(inode);
 104         if (!bh)
 105                 return 0;
 106         bh_data = bh->b_data;
 107         i = 0;
 108         while (i<buflen && (c = bh_data[i])) {
 109                 i++;
 110                 put_user(c,buffer++);
 111         }
 112         brelse(bh);
 113         return i;
 114 }

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