home *** CD-ROM | disk | FTP | other *** search
/ Il CD di internet / CD.iso / SOURCE / KERNEL-S / V1.0 / LINUX-1.0 / LINUX-1 / linux / fs / sysv / symlink.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-07-03  |  2.2 KB  |  111 lines

  1. /*
  2.  *  linux/fs/sysv/symlink.c
  3.  *
  4.  *  minix/symlink.c
  5.  *  Copyright (C) 1991, 1992  Linus Torvalds
  6.  *
  7.  *  coh/symlink.c
  8.  *  Copyright (C) 1993  Pascal Haible, Bruno Haible
  9.  *
  10.  *  sysv/symlink.c
  11.  *  Copyright (C) 1993  Bruno Haible
  12.  *
  13.  *  SystemV/Coherent symlink handling code
  14.  */
  15.  
  16. #include <asm/segment.h>
  17.  
  18. #include <linux/errno.h>
  19. #include <linux/sched.h>
  20. #include <linux/sysv_fs.h>
  21. #include <linux/stat.h>
  22.  
  23. static int sysv_readlink(struct inode *, char *, int);
  24. static int sysv_follow_link(struct inode *, struct inode *, int, int, struct inode **);
  25.  
  26. /*
  27.  * symlinks can't do much...
  28.  */
  29. struct inode_operations sysv_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.     sysv_readlink,        /* readlink */
  41.     sysv_follow_link,    /* follow_link */
  42.     NULL,            /* bmap */
  43.     NULL,            /* truncate */
  44.     NULL            /* permission */
  45. };
  46.  
  47. static int sysv_follow_link(struct inode * dir, struct inode * inode,
  48.     int flag, int mode, struct inode ** res_inode)
  49. {
  50.     int error;
  51.     struct buffer_head * bh;
  52.     char * bh_data;
  53.  
  54.     *res_inode = NULL;
  55.     if (!dir) {
  56.         dir = current->root;
  57.         dir->i_count++;
  58.     }
  59.     if (!inode) {
  60.         iput(dir);
  61.         return -ENOENT;
  62.     }
  63.     if (!S_ISLNK(inode->i_mode)) {
  64.         iput(dir);
  65.         *res_inode = inode;
  66.         return 0;
  67.     }
  68.     if (current->link_count > 5) {
  69.         iput(inode);
  70.         iput(dir);
  71.         return -ELOOP;
  72.     }
  73.     if (!(bh = sysv_file_bread(inode, 0, 0, &bh_data))) { /* is reading 1 block enough ?? */
  74.         iput(inode);
  75.         iput(dir);
  76.         return -EIO;
  77.     }
  78.     iput(inode);
  79.     current->link_count++;
  80.     error = open_namei(bh_data,flag,mode,res_inode,dir);
  81.     current->link_count--;
  82.     brelse(bh);
  83.     return error;
  84. }
  85.  
  86. static int sysv_readlink(struct inode * inode, char * buffer, int buflen)
  87. {
  88.     struct buffer_head * bh;
  89.     char * bh_data;
  90.     int i;
  91.     char c;
  92.  
  93.     if (!S_ISLNK(inode->i_mode)) {
  94.         iput(inode);
  95.         return -EINVAL;
  96.     }
  97.     if (buflen > inode->i_sb->sv_block_size_1)
  98.         buflen = inode->i_sb->sv_block_size_1;
  99.     bh = sysv_file_bread(inode, 0, 0, &bh_data);
  100.     iput(inode);
  101.     if (!bh)
  102.         return 0;
  103.     i = 0;
  104.     while (i<buflen && (c = bh_data[i])) {
  105.         i++;
  106.         put_fs_byte(c,buffer++);
  107.     }
  108.     brelse(bh);
  109.     return i;
  110. }
  111.