patch-2.1.71 linux/fs/affs/symlink.c
Next file: linux/fs/coda/sysctl.c
Previous file: linux/fs/affs/super.c
Back to the patch index
Back to the overall index
- Lines: 122
- Date:
Tue Dec 2 22:25:07 1997
- Orig file:
v2.1.70/linux/fs/affs/symlink.c
- Orig date:
Mon Jun 16 16:35:56 1997
diff -u --recursive --new-file v2.1.70/linux/fs/affs/symlink.c linux/fs/affs/symlink.c
@@ -19,7 +19,8 @@
#define MIN(a,b) (((a) < (b)) ? (a) : (b))
-static int affs_readlink(struct inode *, char *, int);
+static int affs_readlink(struct inode *, char *, int);
+static struct dentry *affs_follow_link(struct inode *inode, struct dentry *base);
struct inode_operations affs_symlink_inode_operations = {
NULL, /* no file-operations */
@@ -33,9 +34,13 @@
NULL, /* mknod */
NULL, /* rename */
affs_readlink, /* readlink */
+ affs_follow_link, /* follow_link */
+ NULL, /* readpage */
+ NULL, /* writepage */
NULL, /* bmap */
NULL, /* truncate */
- NULL /* permission */
+ NULL, /* permission */
+ NULL /* smap */
};
static int
@@ -46,21 +51,24 @@
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));
- i = 0;
- j = 0;
if (!bh) {
- affs_error(inode->i_sb,"readlink","Cannot read block %lu\n",inode->i_ino);
- goto symlink_end;
+ 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 = inode->i_sb->u.affs_sb.s_prefix[i])) {
+ while (i < buflen && (c = pf[i])) {
put_user(c,buffer++);
i++;
}
@@ -84,8 +92,64 @@
lc = c;
i++, j++;
}
-symlink_end:
- iput(inode);
affs_brelse(bh);
return i;
}
+
+static struct dentry *
+affs_follow_link(struct inode *inode, struct dentry *base)
+{
+ struct buffer_head *bh;
+ struct slink_front *lf;
+ char *buffer;
+ int i, j;
+ char c;
+ char lc;
+ char *pf;
+
+ pr_debug("AFFS: follow_link(ino=%lu)\n",inode->i_ino);
+
+ if (!(buffer = kmalloc(1024,GFP_KERNEL))) {
+ dput(base);
+ return ERR_PTR(-ENOSPC);
+ }
+ 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);
+ }
+ 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 */
+ while (i < 1023 && (c = pf[i]))
+ buffer[i++] = c;
+ while (i < 1023 && lf->symname[j] != ':')
+ buffer[i++] = lf->symname[j++];
+ if (i < 1023)
+ buffer[i++] = '/';
+ j++;
+ lc = '/';
+ }
+ while (i < 1023 && (c = lf->symname[j])) {
+ if (c == '/' && lc == '/' && i < 1020) { /* parent dir */
+ buffer[i++] = '.';
+ buffer[i++] = '.';
+ }
+ buffer[i++] = c;
+ lc = c;
+ j++;
+ }
+ buffer[i] = '\0';
+ affs_brelse(bh);
+ base = lookup_dentry(buffer,base,1);
+ kfree(buffer);
+ return base;
+}
+
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov