|
|
1.1 ! root 1: /* ! 2: * linux/fs/ext/symlink.c ! 3: * ! 4: * (C) 1992 Remy Card ([email protected]) ! 5: * ! 6: * from ! 7: * ! 8: * linux/fs/minix/symlink.c ! 9: * ! 10: * (C) 1991 Linus Torvalds ! 11: * ! 12: * ext symlink handling code ! 13: */ ! 14: ! 15: #include <errno.h> ! 16: ! 17: #include <asm/segment.h> ! 18: ! 19: #include <linux/sched.h> ! 20: #include <linux/fs.h> ! 21: #include <linux/ext_fs.h> ! 22: #include <linux/stat.h> ! 23: ! 24: static int ext_readlink(struct inode *, char *, int); ! 25: static struct inode * ext_follow_link(struct inode *, struct inode *); ! 26: ! 27: /* ! 28: * symlinks can't do much... ! 29: */ ! 30: struct inode_operations ext_symlink_inode_operations = { ! 31: NULL, /* no file-operations */ ! 32: NULL, /* create */ ! 33: NULL, /* lookup */ ! 34: NULL, /* link */ ! 35: NULL, /* unlink */ ! 36: NULL, /* symlink */ ! 37: NULL, /* mkdir */ ! 38: NULL, /* rmdir */ ! 39: NULL, /* mknod */ ! 40: NULL, /* rename */ ! 41: ext_readlink, /* readlink */ ! 42: ext_follow_link, /* follow_link */ ! 43: NULL, /* bmap */ ! 44: NULL /* truncate */ ! 45: }; ! 46: ! 47: static struct inode * ext_follow_link(struct inode * dir, struct inode * inode) ! 48: { ! 49: unsigned short fs; ! 50: struct buffer_head * bh; ! 51: ! 52: if (!dir) { ! 53: dir = current->root; ! 54: dir->i_count++; ! 55: } ! 56: if (!inode) { ! 57: iput(dir); ! 58: return NULL; ! 59: } ! 60: if (!S_ISLNK(inode->i_mode)) { ! 61: iput(dir); ! 62: return inode; ! 63: } ! 64: __asm__("mov %%fs,%0":"=r" (fs)); ! 65: if ((current->link_count > 5) || !inode->i_data[0] || ! 66: !(bh = bread(inode->i_dev, inode->i_data[0]))) { ! 67: iput(dir); ! 68: iput(inode); ! 69: return NULL; ! 70: } ! 71: iput(inode); ! 72: __asm__("mov %0,%%fs"::"r" ((unsigned short) 0x10)); ! 73: current->link_count++; ! 74: inode = _namei(bh->b_data,dir,1); ! 75: current->link_count--; ! 76: __asm__("mov %0,%%fs"::"r" (fs)); ! 77: brelse(bh); ! 78: return inode; ! 79: } ! 80: ! 81: static int ext_readlink(struct inode * inode, char * buffer, int buflen) ! 82: { ! 83: struct buffer_head * bh; ! 84: int i; ! 85: char c; ! 86: ! 87: if (!S_ISLNK(inode->i_mode)) { ! 88: iput(inode); ! 89: return -EINVAL; ! 90: } ! 91: if (buflen > 1023) ! 92: buflen = 1023; ! 93: if (inode->i_data[0]) ! 94: bh = bread(inode->i_dev, inode->i_data[0]); ! 95: else ! 96: bh = NULL; ! 97: iput(inode); ! 98: if (!bh) ! 99: return 0; ! 100: i = 0; ! 101: while (i<buflen && (c = bh->b_data[i])) { ! 102: i++; ! 103: put_fs_byte(c,buffer++); ! 104: } ! 105: brelse(bh); ! 106: return i; ! 107: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.