home *** CD-ROM | disk | FTP | other *** search
/ Il CD di internet / CD.iso / SOURCE / KERNEL-S / V1.2 / LINUX-1.2 / LINUX-1 / linux / fs / sysv / symlink.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-01-23  |  2.2 KB  |  115 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. #ifdef MODULE
  17. #include <linux/module.h>
  18. #endif
  19.  
  20. #include <asm/segment.h>
  21.  
  22. #include <linux/errno.h>
  23. #include <linux/sched.h>
  24. #include <linux/sysv_fs.h>
  25. #include <linux/stat.h>
  26.  
  27. static int sysv_readlink(struct inode *, char *, int);
  28. static int sysv_follow_link(struct inode *, struct inode *, int, int, struct inode **);
  29.  
  30. /*
  31.  * symlinks can't do much...
  32.  */
  33. struct inode_operations sysv_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.     sysv_readlink,        /* readlink */
  45.     sysv_follow_link,    /* follow_link */
  46.     NULL,            /* bmap */
  47.     NULL,            /* truncate */
  48.     NULL            /* permission */
  49. };
  50.  
  51. static int sysv_follow_link(struct inode * dir, struct inode * inode,
  52.     int flag, int mode, struct inode ** res_inode)
  53. {
  54.     int error;
  55.     struct buffer_head * bh;
  56.  
  57.     *res_inode = NULL;
  58.     if (!dir) {
  59.         dir = current->fs->root;
  60.         dir->i_count++;
  61.     }
  62.     if (!inode) {
  63.         iput(dir);
  64.         return -ENOENT;
  65.     }
  66.     if (!S_ISLNK(inode->i_mode)) {
  67.         iput(dir);
  68.         *res_inode = inode;
  69.         return 0;
  70.     }
  71.     if (current->link_count > 5) {
  72.         iput(inode);
  73.         iput(dir);
  74.         return -ELOOP;
  75.     }
  76.     if (!(bh = sysv_file_bread(inode, 0, 0))) { /* is reading 1 block enough ?? */
  77.         iput(inode);
  78.         iput(dir);
  79.         return -EIO;
  80.     }
  81.     iput(inode);
  82.     current->link_count++;
  83.     error = open_namei(bh->b_data,flag,mode,res_inode,dir);
  84.     current->link_count--;
  85.     brelse(bh);
  86.     return error;
  87. }
  88.  
  89. static int sysv_readlink(struct inode * inode, char * buffer, int buflen)
  90. {
  91.     struct buffer_head * bh;
  92.     char * bh_data;
  93.     int i;
  94.     char c;
  95.  
  96.     if (!S_ISLNK(inode->i_mode)) {
  97.         iput(inode);
  98.         return -EINVAL;
  99.     }
  100.     if (buflen > inode->i_sb->sv_block_size_1)
  101.         buflen = inode->i_sb->sv_block_size_1;
  102.     bh = sysv_file_bread(inode, 0, 0);
  103.     iput(inode);
  104.     if (!bh)
  105.         return 0;
  106.     bh_data = bh->b_data;
  107.     i = 0;
  108.     while (i<buflen && (c = bh_data[i])) {
  109.         i++;
  110.         put_fs_byte(c,buffer++);
  111.     }
  112.     brelse(bh);
  113.     return i;
  114. }
  115.