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

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