From 0db554d32dfb11a1a9c1fed9b51467009bd45c16 Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Tue, 6 Jul 2021 09:04:26 +0200 Subject: [PATCH 1/8] smbd: canonicalize SMB_VFS_FSTAT() stat buffer This helps code inside any module implementing fstat() looking at fsp->fsp_name->st instead of the passed in stat buf. I only ran afoul of this in a DEBUG message I added while debugging some inode related problem. No change in behaviour. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14756 Signed-off-by: Ralph Boehme Reviewed-by: Jeremy Allison (cherry picked from commit 18a30d939e6f7d49300f235385953412f9e971b9) --- source3/smbd/open.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source3/smbd/open.c b/source3/smbd/open.c index b9f5472b765..2a370fc71b1 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -796,12 +796,12 @@ static NTSTATUS non_widelink_open(const struct files_struct *dirfsp, fsp_set_fd(fsp, fd); if (fd != -1) { - ret = SMB_VFS_FSTAT(fsp, &orig_fsp_name->st); + ret = SMB_VFS_FSTAT(fsp, &fsp->fsp_name->st); if (ret != 0) { status = map_nt_error_from_unix(errno); goto out; } - fsp->fsp_name->st = orig_fsp_name->st; + orig_fsp_name->st = fsp->fsp_name->st; } if (!is_ntfs_stream_smb_fname(fsp->fsp_name) && -- 2.31.1 From bb39dfcca8fa1b11f03d287cf72fee79acd48efb Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Wed, 7 Jul 2021 12:40:05 +0200 Subject: [PATCH 2/8] smbd: update smb_fname statinfo from fsp fd_openat() has done an FSTAT on the handle so update the smb_fname stat info with "truth". from the handle. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14756 Signed-off-by: Ralph Boehme Reviewed-by: Jeremy Allison (cherry picked from commit b32e56d6eb29bfb5f368602edbc10d4b8bc9b4f0) --- source3/smbd/files.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/source3/smbd/files.c b/source3/smbd/files.c index b70ce9f70e6..78629eb1d94 100644 --- a/source3/smbd/files.c +++ b/source3/smbd/files.c @@ -542,6 +542,13 @@ NTSTATUS openat_pathref_fsp(const struct files_struct *dirfsp, goto fail; } + /* + * fd_openat() has done an FSTAT on the handle + * so update the smb_fname stat info with "truth". + * from the handle. + */ + smb_fname->st = fsp->fsp_name->st; + fsp->file_id = vfs_file_id_from_sbuf(conn, &fsp->fsp_name->st); status = fsp_smb_fname_link(fsp, -- 2.31.1 From 7d7dde5f8854294343c9e2d0b63c717cae163a4b Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Tue, 6 Jul 2021 07:19:36 +0200 Subject: [PATCH 3/8] selftest: pass smbclient arg to samba3.blackbox.shadow_copy_torture test BUG: https://bugzilla.samba.org/show_bug.cgi?id=14756 Signed-off-by: Ralph Boehme Reviewed-by: Jeremy Allison (cherry picked from commit 745ded9afe12fda6d45638097a32b01122748649) --- source3/script/tests/test_shadow_copy_torture.sh | 3 ++- source3/selftest/tests.py | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/source3/script/tests/test_shadow_copy_torture.sh b/source3/script/tests/test_shadow_copy_torture.sh index 240a0083506..c9224892400 100755 --- a/source3/script/tests/test_shadow_copy_torture.sh +++ b/source3/script/tests/test_shadow_copy_torture.sh @@ -5,7 +5,7 @@ if [ $# -lt 7 ]; then cat < Date: Tue, 6 Jul 2021 07:20:15 +0200 Subject: [PATCH 4/8] selftest: enable "shadow:fixinodes" in "shadow_write" share The existing tests don't care and this will be used in a subsequent commit to demonstrate that this option is currently broken. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14756 Signed-off-by: Ralph Boehme Reviewed-by: Jeremy Allison (cherry picked from commit 0a0b438b8ab534eeb552a58ad72a714988e84d89) --- selftest/target/Samba3.pm | 1 + 1 file changed, 1 insertion(+) diff --git a/selftest/target/Samba3.pm b/selftest/target/Samba3.pm index b0910433940..4afcc47b82b 100755 --- a/selftest/target/Samba3.pm +++ b/selftest/target/Samba3.pm @@ -2810,6 +2810,7 @@ sub provision($$) aio write size = 0 error_inject:pwrite = EBADF shadow:mountpoint = $shadow_tstdir + shadow:fixinodes = yes [dfq] path = $shrdir/dfree -- 2.31.1 From 32831d1db50796b43b45eeef7b05bdc9b158fe27 Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Tue, 6 Jul 2021 07:22:40 +0200 Subject: [PATCH 5/8] selftest: simplify snapshot directory creation in test_shadow_copy_torture.sh BUG: https://bugzilla.samba.org/show_bug.cgi?id=14756 Signed-off-by: Ralph Boehme Reviewed-by: Jeremy Allison (cherry picked from commit 3aabc9825ca108641c2becf322fa0bd90ea18424) --- source3/script/tests/test_shadow_copy_torture.sh | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/source3/script/tests/test_shadow_copy_torture.sh b/source3/script/tests/test_shadow_copy_torture.sh index c9224892400..bfb698dd9c9 100755 --- a/source3/script/tests/test_shadow_copy_torture.sh +++ b/source3/script/tests/test_shadow_copy_torture.sh @@ -43,8 +43,7 @@ build_snapshots() snapdir=$WORKDIR/.snapshots - mkdir -p $snapdir - mkdir $snapdir/$SNAPSHOT + mkdir -p $snapdir/$SNAPSHOT build_files $snapdir/$SNAPSHOT } -- 2.31.1 From 441a35e061a7024f6b7f35de5f19c92eac051609 Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Tue, 6 Jul 2021 07:24:00 +0200 Subject: [PATCH 6/8] selftest: add a test for shadow:fixinodes This will fail with Failed to open file \@GMT-2015.10.31-19.40.30\subdir\hardlink. NT_STATUS_ACCESS_DENIED The open is failing in openat_pathref_fsp(): [2021/07/06 04:58:17.677104, 10, pid=95070, effective(1000, 1000), real(1000, 0)] ../../source3/smbd/files.c:541(openat_pathref_fsp) openat_pathref_fsp: file [subdir/hardlink {@GMT-2015.10.31-19.40.30}] - dev/ino mismatch. Old (dev=64770, ino=3826943444). New (dev=64770, ino=1746568660). [2021/07/06 04:58:17.677114, 10, pid=95070, effective(1000, 1000), real(1000, 0)] ../../source3/smbd/files.c:568(openat_pathref_fsp) openat_pathref_fsp: Opening pathref for [subdir/hardlink {@GMT-2015.10.31-19.40.30}] failed: NT_STATUS_ACCESS_DENIED The reason is subtle: shadow_copy2 calculates inode numbers of snapshot files based on the path of the file. The result of that when doing a path based stat() from filename_convert() was [2021/07/06 04:58:17.676159, 10, pid=95070, effective(1000, 1000), real(1000, 0)] ../../source3/smbd/filename.c:1945(filename_convert_internal) filename_convert_internal: XXX smb_fname [subdir/hardlink {@GMT-2015.10.31-19.40.30}] (dev=64770, ino=3826943444). which is the "Old" inode shown above. Later in the open code called from openat_pathref_fsp() -> fd_openat() -> non_widelink_open() since 4.14 we call SMB_VFS_FSTAT() where fsp->fsp_name will be set to the new relative *basename* of the file: [2021/07/06 04:58:17.676917, 10, pid=95070, effective(1000, 1000), real(1000, 0), class=vfs] ../../source3/modules/vfs_default.c:1302(vfswrap_fstat) vfswrap_fstat: XXX fsp [hardlink {@GMT-2015.10.31-19.40.30}] (dev=64770, ino=3826943444) So for stat() the hash function in called with the full path relative to the share root: subdir/hardlink while for fstat() the hash function will used hardlink BUG: https://bugzilla.samba.org/show_bug.cgi?id=14756 Signed-off-by: Ralph Boehme Reviewed-by: Jeremy Allison (cherry picked from commit 4a7e483c516cf2b9767919a764f05c43f4620cd7) --- .../samba3.blackbox.shadow_copy_torture | 1 + .../script/tests/test_shadow_copy_torture.sh | 26 +++++++++++++++++++ 2 files changed, 27 insertions(+) create mode 100644 selftest/knownfail.d/samba3.blackbox.shadow_copy_torture diff --git a/selftest/knownfail.d/samba3.blackbox.shadow_copy_torture b/selftest/knownfail.d/samba3.blackbox.shadow_copy_torture new file mode 100644 index 00000000000..aa68c3f3bbe --- /dev/null +++ b/selftest/knownfail.d/samba3.blackbox.shadow_copy_torture @@ -0,0 +1 @@ +^samba3.blackbox.shadow_copy_torture.fix inodes with hardlink\(fileserver\) diff --git a/source3/script/tests/test_shadow_copy_torture.sh b/source3/script/tests/test_shadow_copy_torture.sh index bfb698dd9c9..1185ad5da11 100755 --- a/source3/script/tests/test_shadow_copy_torture.sh +++ b/source3/script/tests/test_shadow_copy_torture.sh @@ -34,6 +34,9 @@ build_files() destdir=$1 echo "$content" > $destdir/foo + + mkdir -p $WORKDIR/subdir/ + touch $WORKDIR/subdir/hardlink } # build a snapshots directory @@ -46,6 +49,9 @@ build_snapshots() mkdir -p $snapdir/$SNAPSHOT build_files $snapdir/$SNAPSHOT + + mkdir -p $snapdir/$SNAPSHOT/subdir + ln "$WORKDIR"/subdir/hardlink "$snapdir"/$SNAPSHOT/subdir/hardlink } build_stream_on_snapshot() @@ -124,6 +130,24 @@ test_shadow_copy_openroot() failed=`expr $failed + 1` } +test_shadow_copy_fix_inodes() +{ + local msg + + msg=$1 + + #delete snapshots from previous tests + find $WORKDIR -name ".snapshots" -exec rm -rf {} \; 1>/dev/null 2>&1 + build_snapshots + + out=$($SMBCLIENT \ + -U $USERNAME%$PASSWORD \ + "//$SERVER/shadow_write" \ + -c "open $SNAPSHOT/subdir/hardlink") || failed=`expr $failed + 1` + echo $out + echo $out | grep "hardlink: for read/write fnum 1" || return 1 +} + build_files $WORKDIR # test open for writing and write behaviour of snapshoted files @@ -133,4 +157,6 @@ test_shadow_copy_stream "reading stream of snapshotted file" test_shadow_copy_openroot "opening root of shadow copy share" +testit "fix inodes with hardlink" test_shadow_copy_fix_inodes || failed=`expr $failed + 1` + exit $failed -- 2.31.1 From 8ad69a110862e864f70ff1def6dc24aa0a3dc785 Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Wed, 28 Jul 2021 17:16:27 +0200 Subject: [PATCH 7/8] vfs_streams_xattr: ensure fstat calls NEXT fstat This ensures fstat behaves the same as stat by calling the NEXT VFS stat function. This is required for matching path and handle based inode numbers. This bug is currently only exposed in a special case: a VSS snapshot of a stream. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14756 Signed-off-by: Ralph Boehme --- source3/modules/vfs_streams_xattr.c | 27 +++++++-------------------- 1 file changed, 7 insertions(+), 20 deletions(-) diff --git a/source3/modules/vfs_streams_xattr.c b/source3/modules/vfs_streams_xattr.c index 72032824b93..743cbd2e8b6 100644 --- a/source3/modules/vfs_streams_xattr.c +++ b/source3/modules/vfs_streams_xattr.c @@ -199,7 +199,6 @@ static int streams_xattr_stat_base(vfs_handle_struct *handle, static int streams_xattr_fstat(vfs_handle_struct *handle, files_struct *fsp, SMB_STRUCT_STAT *sbuf) { - struct smb_filename *smb_fname_base = NULL; int ret = -1; struct stream_io *io = (struct stream_io *) VFS_FETCH_FSP_EXTENSION(handle, fsp); @@ -214,30 +213,19 @@ static int streams_xattr_fstat(vfs_handle_struct *handle, files_struct *fsp, return -1; } - /* Create an smb_filename with stream_name == NULL. */ - smb_fname_base = synthetic_smb_fname(talloc_tos(), - io->base, - NULL, - NULL, - fsp->fsp_name->twrp, - fsp->fsp_name->flags); - if (smb_fname_base == NULL) { - errno = ENOMEM; - return -1; - } - - ret = vfs_stat(handle->conn, smb_fname_base); - *sbuf = smb_fname_base->st; - + ret = streams_xattr_stat_base( + handle, + fsp->fsp_name, + fsp->fsp_name->flags & SMB_FILENAME_POSIX_PATH); if (ret == -1) { - TALLOC_FREE(smb_fname_base); return -1; } + *sbuf = fsp->fsp_name->st; + sbuf->st_ex_size = get_xattr_size(handle->conn, - smb_fname_base, io->xattr_name); + fsp->fsp_name, io->xattr_name); if (sbuf->st_ex_size == -1) { - TALLOC_FREE(smb_fname_base); SET_STAT_INVALID(*sbuf); return -1; } @@ -250,7 +238,6 @@ static int streams_xattr_fstat(vfs_handle_struct *handle, files_struct *fsp, sbuf->st_ex_mode |= S_IFREG; sbuf->st_ex_blocks = sbuf->st_ex_size / STAT_ST_BLOCKSIZE + 1; - TALLOC_FREE(smb_fname_base); return 0; } -- 2.31.1 From f8de42655e2bae7d1c2b7e505cac5429e92650fe Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Sat, 3 Jul 2021 15:46:11 +0200 Subject: [PATCH 8/8] vfs_shadow_copy2: ensure we call convert_sbuf() in shadow_copy2_*stat() on already converted paths with absolute path shadow_copy2_strip_snapshot() will happily return without modifying the passed timestamp=0 if the path is already converted and refers to an object in a snapshot, eg (first debug line from extra debugging patch [1]): [10 2021/07/02 08:19:28.811424 pid=738290 ../../source3/modules/vfs_shadow_copy2.c:1303 shadow_copy2_fstat] shadow_copy2_fstat: fsp [test.txt {@GMT-2000.01.02-03.04.05}] [10 2021/07/02 08:19:28.811449 pid=738290 ../../source3/modules/vfs_shadow_copy2.c:607 _shadow_copy2_strip_snapshot_internal] _shadow_copy2_strip_snapshot_internal: [from shadow_copy2_fstat()] Path 'test.txt {@GMT-2000.01.02-03.04.05}' [10 2021/07/02 08:19:28.811474 pid=738290 ../../source3/modules/vfs_shadow_copy2.c:619 _shadow_copy2_strip_snapshot_internal] _shadow_copy2_strip_snapshot_internal: abs path '/gpfs0/smb_snapshots2/filesetone/.snapshots/@GMT-2000.01.02-03.04.05/test.txt' [10 2021/07/02 08:19:28.811496 pid=738290 ../../source3/modules/vfs_shadow_copy2.c:1924 shadow_copy2_snapshot_to_gmt] shadow_copy2_snapshot_to_gmt: match @GMT-%Y.%m.%d-%H.%M.%S: @GMT-2000.01.02-03.04.05 [10 2021/07/02 08:19:28.811536 pid=738290 ../../source3/modules/vfs_shadow_copy2.c:566 check_for_converted_path] check_for_converted_path: path |/gpfs0/smb_snapshots2/filesetone/.snapshots/@GMT-2000.01.02-03.04.05/test.txt| is already converted. connect path = |/gpfs0/smb_snapshots2/filesetone/.snapshots/@GMT-2000.01.02-03.04.05| As check_for_converted_path() detects an "already converted path", _shadow_copy2_strip_snapshot_internal() just returns without modifying the value of the timestamp. By using shadow_copy2_strip_snapshot_converted() instead of shadow_copy2_strip_snapshot() we can check if the path is in fact referring to a VSS object by checking the "converted" bool. An alternative way would have been directly checking fsp->fsp_name->twrp != 0, but that would be a new semantic in the module, I'll leave this excersize for the future when we clean up the usage of shadow_copy2_strip_snapshot() in the whole module. This change also switches to using the absolute paths in both place where convert_sbuf() is called. [1] @@ -1309,8 +1348,16 @@ static int shadow_copy2_fstat(vfs_handle_struct *handle, files_struct *fsp, saved_errno = errno; } + DBG_DEBUG("fsp [%s]\n", fsp_str_dbg(fsp)); RN: vfs_shadow_copy2 fixinodes not correctly updating inode numbers BUG: https://bugzilla.samba.org/show_bug.cgi?id=14756 Signed-off-by: Ralph Boehme Reviewed-by: Jeremy Allison (cherry picked from commit c7d6745858f2efdd24ed6fd353ec5ece898033fa) --- .../samba3.blackbox.shadow_copy_torture | 1 - source3/modules/vfs_shadow_copy2.c | 180 ++++++++++++++---- 2 files changed, 138 insertions(+), 43 deletions(-) delete mode 100644 selftest/knownfail.d/samba3.blackbox.shadow_copy_torture diff --git a/selftest/knownfail.d/samba3.blackbox.shadow_copy_torture b/selftest/knownfail.d/samba3.blackbox.shadow_copy_torture deleted file mode 100644 index aa68c3f3bbe..00000000000 --- a/selftest/knownfail.d/samba3.blackbox.shadow_copy_torture +++ /dev/null @@ -1 +0,0 @@ -^samba3.blackbox.shadow_copy_torture.fix inodes with hardlink\(fileserver\) diff --git a/source3/modules/vfs_shadow_copy2.c b/source3/modules/vfs_shadow_copy2.c index 227ac148260..e340382ff3c 100644 --- a/source3/modules/vfs_shadow_copy2.c +++ b/source3/modules/vfs_shadow_copy2.c @@ -1168,19 +1168,45 @@ static int shadow_copy2_linkat(vfs_handle_struct *handle, static int shadow_copy2_stat(vfs_handle_struct *handle, struct smb_filename *smb_fname) { + struct shadow_copy2_private *priv = NULL; time_t timestamp = 0; char *stripped = NULL; + bool converted = false; + char *abspath = NULL; char *tmp; - int saved_errno = 0; - int ret; + int ret = 0; - if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, - smb_fname, - ×tamp, &stripped)) { + SMB_VFS_HANDLE_GET_DATA(handle, priv, struct shadow_copy2_private, + return -1); + + if (!shadow_copy2_strip_snapshot_converted(talloc_tos(), + handle, + smb_fname, + ×tamp, + &stripped, + &converted)) { return -1; } if (timestamp == 0) { - return SMB_VFS_NEXT_STAT(handle, smb_fname); + TALLOC_FREE(stripped); + ret = SMB_VFS_NEXT_STAT(handle, smb_fname); + if (ret != 0) { + return ret; + } + if (!converted) { + return 0; + } + + abspath = make_path_absolute(talloc_tos(), + priv, + smb_fname->base_name); + if (abspath == NULL) { + return -1; + } + + convert_sbuf(handle, abspath, &smb_fname->st); + TALLOC_FREE(abspath); + return 0; } tmp = smb_fname->base_name; @@ -1194,38 +1220,70 @@ static int shadow_copy2_stat(vfs_handle_struct *handle, } ret = SMB_VFS_NEXT_STAT(handle, smb_fname); - if (ret == -1) { - saved_errno = errno; + if (ret != 0) { + goto out; } + abspath = make_path_absolute(talloc_tos(), + priv, + smb_fname->base_name); + if (abspath == NULL) { + ret = -1; + goto out; + } + + convert_sbuf(handle, abspath, &smb_fname->st); + TALLOC_FREE(abspath); + +out: TALLOC_FREE(smb_fname->base_name); smb_fname->base_name = tmp; - if (ret == 0) { - convert_sbuf(handle, smb_fname->base_name, &smb_fname->st); - } - if (saved_errno != 0) { - errno = saved_errno; - } return ret; } static int shadow_copy2_lstat(vfs_handle_struct *handle, struct smb_filename *smb_fname) { + struct shadow_copy2_private *priv = NULL; time_t timestamp = 0; char *stripped = NULL; + bool converted = false; + char *abspath = NULL; char *tmp; - int saved_errno = 0; - int ret; + int ret = 0; - if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, - smb_fname, - ×tamp, &stripped)) { + SMB_VFS_HANDLE_GET_DATA(handle, priv, struct shadow_copy2_private, + return -1); + + if (!shadow_copy2_strip_snapshot_converted(talloc_tos(), + handle, + smb_fname, + ×tamp, + &stripped, + &converted)) { return -1; } if (timestamp == 0) { - return SMB_VFS_NEXT_LSTAT(handle, smb_fname); + TALLOC_FREE(stripped); + ret = SMB_VFS_NEXT_LSTAT(handle, smb_fname); + if (ret != 0) { + return ret; + } + if (!converted) { + return 0; + } + + abspath = make_path_absolute(talloc_tos(), + priv, + smb_fname->base_name); + if (abspath == NULL) { + return -1; + } + + convert_sbuf(handle, abspath, &smb_fname->st); + TALLOC_FREE(abspath); + return 0; } tmp = smb_fname->base_name; @@ -1239,45 +1297,76 @@ static int shadow_copy2_lstat(vfs_handle_struct *handle, } ret = SMB_VFS_NEXT_LSTAT(handle, smb_fname); - if (ret == -1) { - saved_errno = errno; + if (ret != 0) { + goto out; + } + + abspath = make_path_absolute(talloc_tos(), + priv, + smb_fname->base_name); + if (abspath == NULL) { + ret = -1; + goto out; } + convert_sbuf(handle, abspath, &smb_fname->st); + TALLOC_FREE(abspath); + +out: TALLOC_FREE(smb_fname->base_name); smb_fname->base_name = tmp; - if (ret == 0) { - convert_sbuf(handle, smb_fname->base_name, &smb_fname->st); - } - if (saved_errno != 0) { - errno = saved_errno; - } return ret; } static int shadow_copy2_fstat(vfs_handle_struct *handle, files_struct *fsp, SMB_STRUCT_STAT *sbuf) { + struct shadow_copy2_private *priv = NULL; time_t timestamp = 0; struct smb_filename *orig_smb_fname = NULL; struct smb_filename vss_smb_fname; struct smb_filename *orig_base_smb_fname = NULL; struct smb_filename vss_base_smb_fname; char *stripped = NULL; - int saved_errno = 0; + char *abspath = NULL; + bool converted = false; bool ok; int ret; - ok = shadow_copy2_strip_snapshot(talloc_tos(), handle, - fsp->fsp_name, - ×tamp, &stripped); + SMB_VFS_HANDLE_GET_DATA(handle, priv, struct shadow_copy2_private, + return -1); + + ok = shadow_copy2_strip_snapshot_converted(talloc_tos(), + handle, + fsp->fsp_name, + ×tamp, + &stripped, + &converted); if (!ok) { return -1; } if (timestamp == 0) { TALLOC_FREE(stripped); - return SMB_VFS_NEXT_FSTAT(handle, fsp, sbuf); + ret = SMB_VFS_NEXT_FSTAT(handle, fsp, sbuf); + if (ret != 0) { + return ret; + } + if (!converted) { + return 0; + } + + abspath = make_path_absolute(talloc_tos(), + priv, + fsp->fsp_name->base_name); + if (abspath == NULL) { + return -1; + } + + convert_sbuf(handle, abspath, sbuf); + TALLOC_FREE(abspath); + return 0; } vss_smb_fname = *fsp->fsp_name; @@ -1301,20 +1390,27 @@ static int shadow_copy2_fstat(vfs_handle_struct *handle, files_struct *fsp, } ret = SMB_VFS_NEXT_FSTAT(handle, fsp, sbuf); + if (ret != 0) { + goto out; + } + + abspath = make_path_absolute(talloc_tos(), + priv, + fsp->fsp_name->base_name); + if (abspath == NULL) { + ret = -1; + goto out; + } + + convert_sbuf(handle, abspath, sbuf); + TALLOC_FREE(abspath); + +out: fsp->fsp_name = orig_smb_fname; if (fsp->base_fsp != NULL) { fsp->base_fsp->fsp_name = orig_base_smb_fname; } - if (ret == -1) { - saved_errno = errno; - } - if (ret == 0) { - convert_sbuf(handle, fsp->fsp_name->base_name, sbuf); - } - if (saved_errno != 0) { - errno = saved_errno; - } return ret; } -- 2.31.1