udf: Make stat on symlink report symlink length as st_size
[sfrench/cifs-2.6.git] / fs / udf / symlink.c
index 8d619773056b5ef0b0a3f2d7dd27b74a6eb76434..f7dfef53f7396805c93d06c2c814423af6519b8c 100644 (file)
@@ -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,
+};