root/fs/ufs/ufs_symlink.c

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

DEFINITIONS

This source file includes following definitions.
  1. ufs_readlink
  2. ufs_follow_link

   1 /*
   2  *  linux/fs/ufs/ufs_symlink.c
   3  *
   4  * Copyright (C) 1996
   5  * Adrian Rodriguez (adrian@franklins-tower.rutgers.edu)
   6  * Laboratory for Computer Science Research Computing Facility
   7  * Rutgers, The State University of New Jersey
   8  *
   9  * $Id: ufs_symlink.c,v 1.3 1996/04/25 09:12:11 davem Exp $
  10  *
  11  */
  12 
  13 #include <linux/fs.h>
  14 #include <linux/sched.h>
  15 
  16 #include <asm/segment.h>
  17 
  18 extern int ufs_bmap (struct inode *, int);
  19 
  20 static int
  21 ufs_readlink(struct inode * inode, char * buffer, int buflen)
     /* [previous][next][first][last][top][bottom][index][help] */
  22 {
  23         unsigned long int block;
  24         struct buffer_head * bh = NULL;
  25         char * link;
  26         int i;
  27         char c;
  28 
  29         if (inode->i_sb->u.ufs_sb.s_flags & (UFS_DEBUG|UFS_DEBUG_LINKS)) {
  30                 printk("ufs_readlink: called on ino %lu dev %u/%u\n",
  31                        inode->i_ino, MAJOR(inode->i_dev), MINOR(inode->i_dev));
  32         }
  33 
  34         if (!S_ISLNK(inode->i_mode)) {
  35                 iput (inode);
  36                 return -EINVAL;
  37         }
  38         if (buflen > inode->i_sb->s_blocksize - 1)
  39                 buflen = inode->i_sb->s_blocksize - 1;
  40         if (inode->i_blocks) {
  41                 /* XXX - error checking */
  42                 block = ufs_bmap(inode, 0);
  43                 if (inode->i_sb->u.ufs_sb.s_flags &(UFS_DEBUG|UFS_DEBUG_LINKS)) {
  44                         printk("ufs_readlink: bmap got %lu for ino %lu\n",
  45                                block, inode->i_ino);
  46                 } 
  47                 bh = bread(inode->i_dev, block, BLOCK_SIZE);
  48                 if (!bh) {
  49                         iput (inode);
  50                         printk("ufs_readlink: can't read block 0 for ino %lu on dev %u/%u\n",
  51                                inode->i_ino, MAJOR(inode->i_dev),
  52                                MINOR(inode->i_dev));
  53                         return 0;
  54                 }
  55                 link = bh->b_data;
  56         }
  57         else {
  58                 link = (char *)&(inode->u.ufs_i.ui_db[0]);
  59         }
  60         i = 0;
  61         while (i < buflen && (c = link[i])) {
  62                 i++;
  63                 put_user (c, buffer++);
  64         }
  65         iput (inode);
  66         if (bh)
  67                 brelse (bh);
  68         return i;
  69 }
  70 
  71 /*
  72  * XXX - blatantly stolen from ext2fs
  73  */
  74 static int
  75 ufs_follow_link(struct inode * dir, struct inode * inode,
     /* [previous][next][first][last][top][bottom][index][help] */
  76                 int flag, int mode, struct inode ** res_inode)
  77 {
  78         unsigned long int block;
  79         int error;
  80         struct buffer_head * bh;
  81         char * link;
  82 
  83         bh = NULL;
  84 
  85         if (inode->i_sb->u.ufs_sb.s_flags & (UFS_DEBUG|UFS_DEBUG_LINKS)) {
  86                 printk("ufs_follow_link: called on ino %lu dev %u/%u\n",
  87                        dir->i_ino, MAJOR(dir->i_dev), MINOR(dir->i_dev));
  88         }
  89 
  90         *res_inode = NULL;
  91         if (!dir) {
  92                 dir = current->fs->root;
  93                 dir->i_count++;
  94         }
  95         if (!inode) {
  96                 iput (dir);
  97                 return -ENOENT;
  98         }
  99         if (!S_ISLNK(inode->i_mode)) {
 100                 iput (dir);
 101                 *res_inode = inode;
 102                 return 0;
 103         }
 104         if (current->link_count > 5) {
 105                 iput (dir);
 106                 iput (inode);
 107                 return -ELOOP;
 108         }
 109         if (inode->i_blocks) {
 110                 /* read the link from disk */
 111                 /* XXX - error checking */
 112                 block = ufs_bmap(inode, 0);
 113                 bh = bread(inode->i_dev, block, BLOCK_SIZE);
 114                 if (bh == NULL) {
 115                         printk("ufs_follow_link: can't read block 0 for ino %lu on dev %u/%u\n",
 116                                inode->i_ino, MAJOR(inode->i_dev),
 117                                MINOR(inode->i_dev));
 118                         iput(dir);
 119                         iput(inode);
 120                         return(-EIO);
 121                 }
 122                 link = bh->b_data;
 123         } else {
 124                 /* fast symlink */
 125                 link = (char *)&(inode->u.ufs_i.ui_db[0]);
 126         }
 127         current->link_count++;
 128         error = open_namei (link, flag, mode, res_inode, dir);
 129         current->link_count--;
 130         iput (inode);
 131         if (bh) {
 132                 brelse (bh);
 133         }
 134         return(error);
 135 }
 136 
 137 
 138 static struct file_operations ufs_symlink_operations = {
 139         NULL,                   /* lseek */
 140         NULL,                   /* read */
 141         NULL,                   /* write */
 142         NULL,                   /* readdir */
 143         NULL,                   /* select */
 144         NULL,                   /* ioctl */
 145         NULL,                   /* mmap */
 146         NULL,                   /* open */
 147         NULL,                   /* release */
 148         NULL,                   /* fsync */  /* XXX - is this ok? */
 149         NULL,                   /* fasync */
 150         NULL,                   /* check_media_change */
 151         NULL,                   /* revalidate */
 152 };
 153 
 154 struct inode_operations ufs_symlink_inode_operations = {
 155         &ufs_symlink_operations,        /* default directory file operations */
 156         NULL,                   /* create */
 157         NULL,                   /* lookup */
 158         NULL,                   /* link */
 159         NULL,                   /* unlink */
 160         NULL,                   /* symlink */
 161         NULL,                   /* mkdir */
 162         NULL,                   /* rmdir */
 163         NULL,                   /* mknod */
 164         NULL,                   /* rename */
 165         &ufs_readlink,          /* readlink */
 166         &ufs_follow_link,       /* follow_link */
 167         NULL,                   /* readpage */
 168         NULL,                   /* writepage */
 169         NULL,                   /* bmap */
 170         NULL,                   /* truncate */
 171         NULL,                   /* permission */
 172         NULL,                   /* smap */
 173 };
 174 
 175 /*
 176  * Local Variables: ***
 177  * c-indent-level: 8 ***
 178  * c-continued-statement-offset: 8 ***
 179  * c-brace-offset: -8 ***
 180  * c-argdecl-indent: 0 ***
 181  * c-label-offset: -8 ***
 182  * End: ***
 183  */

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