root/fs/ext/symlink.c

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

DEFINITIONS

This source file includes following definitions.
  1. ext_follow_link
  2. ext_readlink

   1 /*
   2  *  linux/fs/ext/symlink.c
   3  *
   4  *  Copyright (C) 1992 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  *  ext 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/ext_fs.h>
  21 #include <linux/stat.h>
  22 
  23 static int ext_readlink(struct inode *, char *, int);
  24 static struct inode * ext_follow_link(struct inode *, struct inode *);
  25 
  26 /*
  27  * symlinks can't do much...
  28  */
  29 struct inode_operations ext_symlink_inode_operations = {
  30         NULL,                   /* no file-operations */
  31         NULL,                   /* create */
  32         NULL,                   /* lookup */
  33         NULL,                   /* link */
  34         NULL,                   /* unlink */
  35         NULL,                   /* symlink */
  36         NULL,                   /* mkdir */
  37         NULL,                   /* rmdir */
  38         NULL,                   /* mknod */
  39         NULL,                   /* rename */
  40         ext_readlink,           /* readlink */
  41         ext_follow_link,        /* follow_link */
  42         NULL,                   /* bmap */
  43         NULL                    /* truncate */
  44 };
  45 
  46 static struct inode * ext_follow_link(struct inode * dir, struct inode * inode)
     /* [previous][next][first][last][top][bottom][index][help] */
  47 {
  48         unsigned short fs;
  49         struct buffer_head * bh;
  50 
  51         if (!dir) {
  52                 dir = current->root;
  53                 dir->i_count++;
  54         }
  55         if (!inode) {
  56                 iput(dir);
  57                 return NULL;
  58         }
  59         if (!S_ISLNK(inode->i_mode)) {
  60                 iput(dir);
  61                 return inode;
  62         }
  63         __asm__("mov %%fs,%0":"=r" (fs));
  64         if ((current->link_count > 5) || !inode->i_data[0] ||
  65            !(bh = bread(inode->i_dev, inode->i_data[0], BLOCK_SIZE))) {
  66                 iput(dir);
  67                 iput(inode);
  68                 return NULL;
  69         }
  70         iput(inode);
  71         __asm__("mov %0,%%fs"::"r" ((unsigned short) 0x10));
  72         current->link_count++;
  73         inode = _namei(bh->b_data,dir,1);
  74         current->link_count--;
  75         __asm__("mov %0,%%fs"::"r" (fs));
  76         brelse(bh);
  77         return inode;
  78 }
  79 
  80 static int ext_readlink(struct inode * inode, char * buffer, int buflen)
     /* [previous][next][first][last][top][bottom][index][help] */
  81 {
  82         struct buffer_head * bh;
  83         int i;
  84         char c;
  85 
  86         if (!S_ISLNK(inode->i_mode)) {
  87                 iput(inode);
  88                 return -EINVAL;
  89         }
  90         if (buflen > 1023)
  91                 buflen = 1023;
  92         if (inode->i_data[0])
  93                 bh = bread(inode->i_dev, inode->i_data[0], BLOCK_SIZE);
  94         else
  95                 bh = NULL;
  96         iput(inode);
  97         if (!bh)
  98                 return 0;
  99         i = 0;
 100         while (i<buflen && (c = bh->b_data[i])) {
 101                 i++;
 102                 put_fs_byte(c,buffer++);
 103         }
 104         brelse(bh);
 105         return i;
 106 }

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