root/fs/ext2/symlink.c

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

DEFINITIONS

This source file includes following definitions.
  1. ext2_follow_link
  2. ext2_readlink

   1 /*
   2  *  linux/fs/ext2/symlink.c
   3  *
   4  *  Copyright (C) 1992, 1993, 1994  Remy Card (card@masi.ibp.fr)
   5  *                                  Laboratoire MASI - Institut Blaise Pascal
   6  *                                  Universite Pierre et Marie Curie (Paris VI)
   7  *
   8  *  from
   9  *
  10  *  linux/fs/minix/symlink.c
  11  *
  12  *  Copyright (C) 1991, 1992  Linus Torvalds
  13  *
  14  *  ext2 symlink handling code
  15  */
  16 
  17 #include <asm/segment.h>
  18 
  19 #include <linux/errno.h>
  20 #include <linux/fs.h>
  21 #include <linux/ext2_fs.h>
  22 #include <linux/sched.h>
  23 #include <linux/stat.h>
  24 
  25 static int ext2_readlink (struct inode *, char *, int);
  26 static int ext2_follow_link (struct inode *, struct inode *, int, int,
  27                                struct inode **);
  28 
  29 /*
  30  * symlinks can't do much...
  31  */
  32 struct inode_operations ext2_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         ext2_readlink,          /* readlink */
  44         ext2_follow_link,       /* follow_link */
  45         NULL,                   /* bmap */
  46         NULL,                   /* truncate */
  47         NULL,                   /* permission */
  48         NULL                    /* smap */
  49 };
  50 
  51 static int ext2_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 = NULL;
  56         char * link;
  57 
  58         *res_inode = NULL;
  59         if (!dir) {
  60                 dir = current->fs->root;
  61                 dir->i_count++;
  62         }
  63         if (!inode) {
  64                 iput (dir);
  65                 return -ENOENT;
  66         }
  67         if (!S_ISLNK(inode->i_mode)) {
  68                 iput (dir);
  69                 *res_inode = inode;
  70                 return 0;
  71         }
  72         if (current->link_count > 5) {
  73                 iput (dir);
  74                 iput (inode);
  75                 return -ELOOP;
  76         }
  77         if (inode->i_blocks) {
  78                 if (!(bh = ext2_bread (inode, 0, 0, &error))) {
  79                         iput (dir);
  80                         iput (inode);
  81                         return -EIO;
  82                 }
  83                 link = bh->b_data;
  84         } else
  85                 link = (char *) inode->u.ext2_i.i_data;
  86         current->link_count++;
  87         error = open_namei (link, flag, mode, res_inode, dir);
  88         current->link_count--;
  89         iput (inode);
  90         if (bh)
  91                 brelse (bh);
  92         return error;
  93 }
  94 
  95 static int ext2_readlink (struct inode * inode, char * buffer, int buflen)
     /* [previous][next][first][last][top][bottom][index][help] */
  96 {
  97         struct buffer_head * bh = NULL;
  98         char * link;
  99         int i, err;
 100         char c;
 101 
 102         if (!S_ISLNK(inode->i_mode)) {
 103                 iput (inode);
 104                 return -EINVAL;
 105         }
 106         if (buflen > inode->i_sb->s_blocksize - 1)
 107                 buflen = inode->i_sb->s_blocksize - 1;
 108         if (inode->i_blocks) {
 109                 bh = ext2_bread (inode, 0, 0, &err);
 110                 if (!bh) {
 111                         iput (inode);
 112                         return 0;
 113                 }
 114                 link = bh->b_data;
 115         }
 116         else
 117                 link = (char *) inode->u.ext2_i.i_data;
 118         i = 0;
 119         while (i < buflen && (c = link[i])) {
 120                 i++;
 121                 put_fs_byte (c, buffer++);
 122         }
 123         iput (inode);
 124         if (bh)
 125                 brelse (bh);
 126         return i;
 127 }

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