root/fs/xiafs/symlink.c

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

DEFINITIONS

This source file includes following definitions.
  1. xiafs_readlink
  2. xiafs_follow_link

   1 /*
   2  *  linux/fs/xiafs/symlink.c
   3  *
   4  *  Copyright (C) Q. Frank Xia, 1993.
   5  *  
   6  *  Based on Linus' minix/symlink.c
   7  *  Copyright (C) Linus Torvalds, 1991, 1992.
   8  *
   9  *  This software may be redistributed per Linux Copyright.
  10  */
  11 
  12 #ifdef MODULE
  13 #include <linux/module.h>
  14 #endif
  15 
  16 #include <asm/segment.h>
  17 
  18 #include <linux/errno.h>
  19 #include <linux/sched.h>
  20 #include <linux/fs.h>
  21 #include <linux/xia_fs.h>
  22 #include <linux/stat.h>
  23 
  24 static int 
  25 xiafs_readlink(struct inode *, char *, int);
  26 
  27 static int 
  28 xiafs_follow_link(struct inode *, struct inode *, int, int, struct inode **);
  29 
  30 /*
  31  * symlinks can't do much...
  32  */
  33 struct inode_operations xiafs_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         xiafs_readlink,         /* readlink */
  45         xiafs_follow_link,      /* follow_link */
  46         NULL,                   /* bmap */
  47         NULL,                   /* truncate */
  48         NULL                    /* permission */
  49 };
  50 
  51 static int xiafs_readlink(struct inode * inode, char * buffer, int buflen)
     /* [previous][next][first][last][top][bottom][index][help] */
  52 {
  53     struct buffer_head * bh;
  54     int i;
  55     char c;
  56 
  57     if (!S_ISLNK(inode->i_mode)) {
  58         iput(inode);
  59         return -EINVAL;
  60     }
  61     if (buflen > BLOCK_SIZE)
  62         buflen = BLOCK_SIZE;
  63     bh = xiafs_bread(inode, 0, 0);
  64     if (!IS_RDONLY (inode)) {
  65         inode->i_atime=CURRENT_TIME;
  66         inode->i_dirt=1;
  67     }
  68     iput(inode);
  69     if (!bh)
  70         return 0;
  71     for (i=0; i < buflen && (c=bh->b_data[i]); i++)
  72       put_user(c, buffer++);
  73     if (i < buflen-1)
  74       put_user('\0', buffer);
  75     brelse(bh);
  76     return i;
  77 }
  78 
  79 static int xiafs_follow_link(struct inode * dir, struct inode * inode,
     /* [previous][next][first][last][top][bottom][index][help] */
  80         int flag, int mode, struct inode ** res_inode)
  81 {
  82     int error;
  83     struct buffer_head * bh;
  84 
  85     *res_inode = NULL;
  86     if (!dir) {
  87         dir = current->fs->root;
  88         dir->i_count++;
  89     }
  90     if (!inode) {
  91         iput(dir);
  92         return -ENOENT;
  93     }
  94     if (!S_ISLNK(inode->i_mode)) {
  95         iput(dir);
  96         *res_inode = inode;
  97         return 0;
  98     }
  99     if (!IS_RDONLY (inode)) {
 100         inode->i_atime=CURRENT_TIME;
 101         inode->i_dirt=1;
 102     }
 103     if (current->link_count > 5) {
 104         iput(inode);
 105         iput(dir);
 106         return -ELOOP;
 107     }
 108     if (!(bh = xiafs_bread(inode, 0, 0))) {
 109         iput(inode);
 110         iput(dir);
 111         return -EIO;
 112     }
 113     iput(inode);
 114     current->link_count++;
 115     error = open_namei(bh->b_data,flag,mode,res_inode,dir);
 116     current->link_count--;
 117     brelse(bh);
 118     return error;
 119 }
 120 
 121 
 122 

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