diff options
author | Ralf Baechle <ralf@linux-mips.org> | 2000-02-04 07:40:19 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2000-02-04 07:40:19 +0000 |
commit | 33263fc5f9ac8e8cb2b22d06af3ce5ac1dd815e4 (patch) | |
tree | 2d1b86a40bef0958a68cf1a2eafbeb0667a70543 /fs/affs/symlink.c | |
parent | 216f5f51aa02f8b113aa620ebc14a9631a217a00 (diff) |
Merge with Linux 2.3.32.
Diffstat (limited to 'fs/affs/symlink.c')
-rw-r--r-- | fs/affs/symlink.c | 143 |
1 files changed, 31 insertions, 112 deletions
diff --git a/fs/affs/symlink.c b/fs/affs/symlink.c index 18c03730f..6aad1c222 100644 --- a/fs/affs/symlink.c +++ b/fs/affs/symlink.c @@ -9,103 +9,19 @@ */ #include <linux/errno.h> -#include <linux/sched.h> -#include <linux/malloc.h> #include <linux/fs.h> #include <linux/stat.h> #include <linux/affs_fs.h> #include <linux/amigaffs.h> -#include <asm/uaccess.h> +#include <linux/pagemap.h> -#define MIN(a,b) (((a) < (b)) ? (a) : (b)) - -static int affs_readlink(struct dentry *, char *, int); -static struct dentry *affs_follow_link(struct dentry *dentry, struct dentry *base, unsigned int); - -struct inode_operations affs_symlink_inode_operations = { - NULL, /* no file-operations */ - NULL, /* create */ - NULL, /* lookup */ - NULL, /* link */ - NULL, /* unlink */ - NULL, /* symlink */ - NULL, /* mkdir */ - NULL, /* rmdir */ - NULL, /* mknod */ - NULL, /* rename */ - affs_readlink, /* readlink */ - affs_follow_link, /* follow_link */ - NULL, /* get_block */ - NULL, /* readpage */ - NULL, /* writepage */ - NULL, /* flushpage */ - NULL, /* truncate */ - NULL, /* permission */ - NULL, /* smap */ - NULL /* revalidate */ -}; - -static int -affs_readlink(struct dentry *dentry, char *buffer, int buflen) +static int affs_symlink_readpage(struct dentry *dentry, struct page *page) { + struct buffer_head *bh; struct inode *inode = dentry->d_inode; - struct buffer_head *bh; - struct slink_front *lf; - int i, j; - char c; - char lc; - char *pf; - - pr_debug("AFFS: readlink(ino=%lu,buflen=%d)\n",inode->i_ino,buflen); - - bh = affs_bread(inode->i_dev,inode->i_ino,AFFS_I2BSIZE(inode)); - if (!bh) { - affs_warning(inode->i_sb,"follow_link","Unable to read i-node block %lu\n", - inode->i_ino); - return -EIO; - } - lf = (struct slink_front *)bh->b_data; - lc = 0; - i = 0; - j = 0; - pf = inode->i_sb->u.affs_sb.s_prefix ? inode->i_sb->u.affs_sb.s_prefix : "/"; - - if (strchr(lf->symname,':')) { /* Handle assign or volume name */ - while (i < buflen && (c = pf[i])) { - put_user(c,buffer++); - i++; - } - while (i < buflen && (c = lf->symname[j]) != ':') { - put_user(c,buffer++); - i++, j++; - } - if (i < buflen) { - put_user('/',buffer++); - i++, j++; - } - lc = '/'; - } - while (i < buflen && (c = lf->symname[j])) { - if (c == '/' && lc == '/' && (i + 3 < buflen)) { /* parent dir */ - put_user('.',buffer++); - put_user('.',buffer++); - i += 2; - } - put_user(c,buffer++); - lc = c; - i++, j++; - } - affs_brelse(bh); - return i; -} - -static struct dentry * -affs_follow_link(struct dentry *dentry, struct dentry *base, unsigned int follow) -{ - struct inode *inode = dentry->d_inode; - struct buffer_head *bh; - struct slink_front *lf; - char *buffer; + char *link = (char*)kmap(page); + struct slink_front *lf; + int err; int i, j; char c; char lc; @@ -113,47 +29,50 @@ affs_follow_link(struct dentry *dentry, struct dentry *base, unsigned int follow pr_debug("AFFS: follow_link(ino=%lu)\n",inode->i_ino); - if (!(buffer = kmalloc(1024,GFP_KERNEL))) { - dput(base); - return ERR_PTR(-ENOSPC); - } + err = -EIO; bh = affs_bread(inode->i_dev,inode->i_ino,AFFS_I2BSIZE(inode)); - if (!bh) { - affs_warning(inode->i_sb,"follow_link","Unable to read i-node block %lu\n", - inode->i_ino); - kfree(buffer); - dput(base); - return ERR_PTR(-EIO); - } + if (!bh) + goto fail; i = 0; j = 0; lf = (struct slink_front *)bh->b_data; lc = 0; pf = inode->i_sb->u.affs_sb.s_prefix ? inode->i_sb->u.affs_sb.s_prefix : "/"; - if (strchr(lf->symname,':')) { /* Handle assign or volume name */ + if (strchr(lf->symname,':')) { /* Handle assign or volume name */ while (i < 1023 && (c = pf[i])) - buffer[i++] = c; + link[i++] = c; while (i < 1023 && lf->symname[j] != ':') - buffer[i++] = lf->symname[j++]; + link[i++] = lf->symname[j++]; if (i < 1023) - buffer[i++] = '/'; + link[i++] = '/'; j++; lc = '/'; } while (i < 1023 && (c = lf->symname[j])) { if (c == '/' && lc == '/' && i < 1020) { /* parent dir */ - buffer[i++] = '.'; - buffer[i++] = '.'; + link[i++] = '.'; + link[i++] = '.'; } - buffer[i++] = c; + link[i++] = c; lc = c; j++; } - buffer[i] = '\0'; + link[i] = '\0'; affs_brelse(bh); - base = lookup_dentry(buffer,base,follow); - kfree(buffer); - return base; + SetPageUptodate(page); + kunmap(page); + UnlockPage(page); + return 0; +fail: + SetPageError(page); + kunmap(page); + UnlockPage(page); + return err; } +struct inode_operations affs_symlink_inode_operations = { + readlink: page_readlink, + follow_link: page_follow_link, + readpage: affs_symlink_readpage, +}; |