summaryrefslogtreecommitdiff
path: root/fs/udf/symlink.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/udf/symlink.c')
-rw-r--r--fs/udf/symlink.c30
1 files changed, 30 insertions, 0 deletions
diff --git a/fs/udf/symlink.c b/fs/udf/symlink.c
index 8d619773056b..f7dfef53f739 100644
--- a/fs/udf/symlink.c
+++ b/fs/udf/symlink.c
@@ -152,9 +152,39 @@ out_unmap:
return err;
}
+static int udf_symlink_getattr(struct vfsmount *mnt, struct dentry *dentry,
+ struct kstat *stat)
+{
+ struct inode *inode = d_backing_inode(dentry);
+ struct page *page;
+
+ generic_fillattr(inode, stat);
+ page = read_mapping_page(inode->i_mapping, 0, NULL);
+ if (IS_ERR(page))
+ return PTR_ERR(page);
+ /*
+ * UDF uses non-trivial encoding of symlinks so i_size does not match
+ * number of characters reported by readlink(2) which apparently some
+ * applications expect. Also POSIX says that "The value returned in the
+ * st_size field shall be the length of the contents of the symbolic
+ * link, and shall not count a trailing null if one is present." So
+ * let's report the length of string returned by readlink(2) for
+ * st_size.
+ */
+ stat->size = strlen(page_address(page));
+ put_page(page);
+
+ return 0;
+}
+
/*
* symlinks can't do much...
*/
const struct address_space_operations udf_symlink_aops = {
.readpage = udf_symlink_filler,
};
+
+const struct inode_operations udf_symlink_inode_operations = {
+ .get_link = page_get_link,
+ .getattr = udf_symlink_getattr,
+};