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