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.1 1996/04/21 14:41:23 davem Exp $
  10  *
  11  */
  12 
  13 #include <linux/fs.h>
  14 #include <linux/sched.h>
  15 
  16 #include <asm/segment.h>
  17 
  18 static int
  19 ufs_readlink(struct inode * inode, char * buffer, int buflen)
     /* [previous][next][first][last][top][bottom][index][help] */
  20 {
  21         unsigned long int block;
  22         struct buffer_head * bh = NULL;
  23         char * link;
  24         int i, err;
  25         char c;
  26 
  27         if (inode->i_sb->u.ufs_sb.s_flags & (UFS_DEBUG|UFS_DEBUG_LINKS)) {
  28                 printk("ufs_readlink: called on ino %lu dev %u/%u\n",
  29                        inode->i_ino, MAJOR(inode->i_dev), MINOR(inode->i_dev));
  30         }
  31 
  32         if (!S_ISLNK(inode->i_mode)) {
  33                 iput (inode);
  34                 return -EINVAL;
  35         }
  36         if (buflen > inode->i_sb->s_blocksize - 1)
  37                 buflen = inode->i_sb->s_blocksize - 1;
  38         if (inode->i_blocks) {
  39                 /* XXX - error checking */
  40                 block = ufs_bmap(inode, 0);
  41                 if (inode->i_sb->u.ufs_sb.s_flags &(UFS_DEBUG|UFS_DEBUG_LINKS)) {
  42                         printk("ufs_readlink: bmap got %lu for ino %lu\n",
  43                                block, inode->i_ino);
  44                 } 
  45                 bh = bread(inode->i_dev, block, BLOCK_SIZE);
  46                 if (!bh) {
  47                         iput (inode);
  48                         printk("ufs_readlink: can't read block 0 for ino %lu on dev %u/%u\n",
  49                                inode->i_ino, MAJOR(inode->i_dev),
  50                                MINOR(inode->i_dev));
  51                         return 0;
  52                 }
  53                 link = bh->b_data;
  54         }
  55         else {
  56                 link = (char *)&(inode->u.ufs_i.ui_db[0]);
  57         }
  58         i = 0;
  59         while (i < buflen && (c = link[i])) {
  60                 i++;
  61                 put_user (c, buffer++);
  62         }
  63         iput (inode);
  64         if (bh)
  65                 brelse (bh);
  66         return i;
  67 
  68         return(0);
  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] */