NTFS-3G used several different conventions for setting st_size of
symlinks.  Make it use the standard POSIX convention of setting st_size
to the length of the link target without a terminating null.

Signed-off-by: Eric Biggers <ebigge...@gmail.com>
---
 src/lowntfs-3g.c | 35 +++++++++++++++++++++++++++--------
 src/ntfs-3g.c    | 35 +++++++++++++++++++++++++++--------
 2 files changed, 54 insertions(+), 16 deletions(-)

diff --git a/src/lowntfs-3g.c b/src/lowntfs-3g.c
index a91d123..bc9770a 100644
--- a/src/lowntfs-3g.c
+++ b/src/lowntfs-3g.c
@@ -645,11 +645,10 @@ static int junction_getstat(ntfs_inode *ni,
                 * we still display as a symlink
                 */
        if (target || (errno == EOPNOTSUPP)) {
-                       /* returning attribute size */
                if (target)
-                       stbuf->st_size = attr_size;
+                       stbuf->st_size = strlen(target);
                else
-                       stbuf->st_size = sizeof(ntfs_bad_reparse);
+                       stbuf->st_size = sizeof(ntfs_bad_reparse) - 1;
                stbuf->st_blocks = (ni->allocated_size + 511) >> 9;
                stbuf->st_mode = S_IFLNK;
                free(target);
@@ -705,7 +704,7 @@ static int ntfs_fuse_getstat(struct SECURITY_CONTEXT *scx,
                                apply_umask(stbuf);
                        } else {
                                stbuf->st_size =
-                                       sizeof(ntfs_bad_reparse);
+                                       sizeof(ntfs_bad_reparse) - 1;
                                stbuf->st_blocks =
                                        (ni->allocated_size + 511) >> 9;
                                stbuf->st_mode = S_IFLNK;
@@ -725,12 +724,11 @@ static int ntfs_fuse_getstat(struct SECURITY_CONTEXT *scx,
                                 * we still display as a symlink
                                 */
                        if (target || (errno == EOPNOTSUPP)) {
-                                       /* returning attribute size */
                                if (target)
-                                       stbuf->st_size = attr_size;
+                                       stbuf->st_size = strlen(target);
                                else
                                        stbuf->st_size = 
-                                               sizeof(ntfs_bad_reparse);
+                                               sizeof(ntfs_bad_reparse) - 1;
                                stbuf->st_blocks =
                                        (ni->allocated_size + 511) >> 9;
                                stbuf->st_nlink =
@@ -837,8 +835,29 @@ static int ntfs_fuse_getstat(struct SECURITY_CONTEXT *scx,
                                                        le64_to_cpu(
                                                        intx_file->minor));
                                }
-                               if (intx_file->magic == INTX_SYMBOLIC_LINK)
+                               if (intx_file->magic == INTX_SYMBOLIC_LINK) {
+                                       char *target = NULL;
+                                       int len;
+
+                                       /* st_size should be set to length of
+                                        * symlink target as multibyte string */
+                                       len = ntfs_ucstombs(
+                                                       intx_file->target,
+                                                       (na->data_size -
+                                                           offsetof(INTX_FILE,
+                                                                    target)) /
+                                                              sizeof(ntfschar),
+                                                            &target, 0);
+                                       if (len < 0) {
+                                               res = -errno;
+                                               free(intx_file);
+                                               ntfs_attr_close(na);
+                                               goto exit;
+                                       }
+                                       free(target);
                                        stbuf->st_mode = S_IFLNK;
+                                       stbuf->st_size = len;
+                               }
                                free(intx_file);
                        }
                        ntfs_attr_close(na);
diff --git a/src/ntfs-3g.c b/src/ntfs-3g.c
index 702d676..f4af89b 100644
--- a/src/ntfs-3g.c
+++ b/src/ntfs-3g.c
@@ -709,11 +709,10 @@ static int junction_getattr(ntfs_inode *ni,
                 * we still display as a symlink
                 */
        if (target || (errno == EOPNOTSUPP)) {
-                       /* returning attribute size */
                if (target)
-                       stbuf->st_size = attr_size;
+                       stbuf->st_size = strlen(target);
                else
-                       stbuf->st_size = sizeof(ntfs_bad_reparse);
+                       stbuf->st_size = sizeof(ntfs_bad_reparse) - 1;
                stbuf->st_blocks = (ni->allocated_size + 511) >> 9;
                stbuf->st_mode = S_IFLNK;
                free(target);
@@ -796,7 +795,7 @@ static int ntfs_fuse_getattr(const char *org_path, struct 
stat *stbuf)
                                goto ok;
                        } else {
                                stbuf->st_size =
-                                       sizeof(ntfs_bad_reparse);
+                                       sizeof(ntfs_bad_reparse) - 1;
                                stbuf->st_blocks =
                                        (ni->allocated_size + 511) >> 9;
                                stbuf->st_mode = S_IFLNK;
@@ -816,11 +815,10 @@ static int ntfs_fuse_getattr(const char *org_path, struct 
stat *stbuf)
                                 * we still display as a symlink
                                 */
                        if (target || (errno == EOPNOTSUPP)) {
-                                       /* returning attribute size */
                                if (target)
-                                       stbuf->st_size = attr_size;
+                                       stbuf->st_size = strlen(target);
                                else
-                                       stbuf->st_size = 
sizeof(ntfs_bad_reparse);
+                                       stbuf->st_size = 
sizeof(ntfs_bad_reparse) - 1;
                                stbuf->st_blocks = (ni->allocated_size + 511) 
>> 9;
                                stbuf->st_nlink = 
le16_to_cpu(ni->mrec->link_count);
                                stbuf->st_mode = S_IFLNK;
@@ -942,8 +940,29 @@ static int ntfs_fuse_getattr(const char *org_path, struct 
stat *stbuf)
                                                        le64_to_cpu(
                                                        intx_file->minor));
                                }
-                               if (intx_file->magic == INTX_SYMBOLIC_LINK)
+                               if (intx_file->magic == INTX_SYMBOLIC_LINK) {
+                                       char *target = NULL;
+                                       int len;
+
+                                       /* st_size should be set to length of
+                                        * symlink target as multibyte string */
+                                       len = ntfs_ucstombs(
+                                                       intx_file->target,
+                                                       (na->data_size -
+                                                           offsetof(INTX_FILE,
+                                                                    target)) /
+                                                              sizeof(ntfschar),
+                                                            &target, 0);
+                                       if (len < 0) {
+                                               res = -errno;
+                                               free(intx_file);
+                                               ntfs_attr_close(na);
+                                               goto exit;
+                                       }
+                                       free(target);
                                        stbuf->st_mode = S_IFLNK;
+                                       stbuf->st_size = len;
+                               }
                                free(intx_file);
                        }
                        ntfs_attr_close(na);
-- 
2.9.3


------------------------------------------------------------------------------
_______________________________________________
ntfs-3g-devel mailing list
ntfs-3g-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/ntfs-3g-devel

Reply via email to