Fork me on GitHub

root/fs/ext2/symlink.c

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

DEFINITIONS

This source file includes following definitions.
  1. ext2_readlink
  2. ext2_followlink

   1 /*
   2  * fiwix/fs/ext2/symlink.c
   3  *
   4  * Copyright 2018-2022, Jordi Sanfeliu. All rights reserved.
   5  * Distributed under the terms of the Fiwix License.
   6  */
   7 
   8 #include <fiwix/types.h>
   9 #include <fiwix/errno.h>
  10 #include <fiwix/buffer.h>
  11 #include <fiwix/fs.h>
  12 #include <fiwix/filesystems.h>
  13 #include <fiwix/stat.h>
  14 #include <fiwix/mm.h>
  15 #include <fiwix/stdio.h>
  16 #include <fiwix/string.h>
  17 
  18 struct fs_operations ext2_symlink_fsop = {
  19         0,
  20         0,
  21 
  22         NULL,                   /* open */
  23         NULL,                   /* close */
  24         NULL,                   /* read */
  25         NULL,                   /* write */
  26         NULL,                   /* ioctl */
  27         NULL,                   /* lseek */
  28         NULL,                   /* readdir */
  29         NULL,                   /* mmap */
  30         NULL,                   /* select */
  31 
  32         ext2_readlink,
  33         ext2_followlink,
  34         NULL,                   /* bmap */
  35         NULL,                   /* lookup */
  36         NULL,                   /* rmdir */
  37         NULL,                   /* link */
  38         NULL,                   /* unlink */
  39         NULL,                   /* symlink */
  40         NULL,                   /* mkdir */
  41         NULL,                   /* mknod */
  42         NULL,                   /* truncate */
  43         NULL,                   /* create */
  44         NULL,                   /* rename */
  45 
  46         NULL,                   /* read_block */
  47         NULL,                   /* write_block */
  48 
  49         NULL,                   /* read_inode */
  50         NULL,                   /* write_inode */
  51         NULL,                   /* ialloc */
  52         NULL,                   /* ifree */
  53         NULL,                   /* statfs */
  54         NULL,                   /* read_superblock */
  55         NULL,                   /* remount_fs */
  56         NULL,                   /* write_superblock */
  57         NULL                    /* release_superblock */
  58 };
  59 
  60 int ext2_readlink(struct inode *i, char *buffer, __size_t count)
  61 {
  62         __u32 blksize;
  63         struct buffer *buf;
  64 
  65         if(!S_ISLNK(i->i_mode)) {
  66                 printk("%s(): Oops, inode '%d' is not a symlink (!?).\n", __FUNCTION__, i->inode);
  67                 return 0;
  68         }
  69 
  70         inode_lock(i);
  71         blksize = i->sb->s_blocksize;
  72         count = MIN(count, i->i_size);
  73         if(!count) {
  74                 inode_unlock(i);
  75                 return 0;
  76         }
  77         count = MIN(count, blksize);
  78         if(i->i_blocks) {       /* slow symlink */
  79                 if(!(buf = bread(i->dev, i->u.ext2.i_data[0], blksize))) {
  80                         inode_unlock(i);
  81                         return -EIO;
  82                 }
  83                 memcpy_b(buffer, buf->data, count);
  84                 brelse(buf);
  85         } else {        /* fast symlink */
  86                 memcpy_b(buffer, (char *)i->u.ext2.i_data, count);
  87         }
  88         buffer[count] = 0;
  89         inode_unlock(i);
  90         return count;
  91 }
  92 
  93 int ext2_followlink(struct inode *dir, struct inode *i, struct inode **i_res)
  94 {
  95         struct buffer *buf;
  96         char *name;
  97         __ino_t errno;
  98 
  99         if(!i) {
 100                 return -ENOENT;
 101         }
 102 
 103         if(!S_ISLNK(i->i_mode)) {
 104                 printk("%s(): Oops, inode '%d' is not a symlink (!?).\n", __FUNCTION__, i->inode);
 105                 return 0;
 106         }
 107 
 108         if(current->loopcnt > MAX_SYMLINKS) {
 109                 printk("%s(): too many nested symbolic links!\n", __FUNCTION__);
 110                 return -ELOOP;
 111         }
 112 
 113         inode_lock(i);
 114         if(i->i_blocks) {       /* slow symlink */
 115                 if(!(buf = bread(i->dev, i->u.ext2.i_data[0], i->sb->s_blocksize))) {
 116                         inode_unlock(i);
 117                         return -EIO;
 118                 }
 119                 name = buf->data;
 120         } else {        /* fast symlink */
 121                 buf = NULL;
 122                 name = (char *)i->u.ext2.i_data;
 123         }
 124         inode_unlock(i);
 125 
 126         current->loopcnt++;
 127         iput(i);
 128         if(buf) {
 129                 brelse(buf);
 130         }
 131         errno = parse_namei(name, dir, i_res, NULL, FOLLOW_LINKS);
 132         current->loopcnt--;
 133         return errno;
 134 }

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