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

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