In ceph_snap_gmt_openat() we hand in the incoming smb_fname as it is
to ceph_snap_gmt_strip_snapshot() which is then passed on to derive
the actual snapshot path using ceph_snap_gmt_convert(). But this can
go wrong in ceph_snap_gmt_convert_dir() while opening the snapdir.
Unless we constitute the full path from dirfsp at the first place we
always end up opening the snapdir from the parent directory with
OpenDir().
For example with dirfsp("foobar") and smb_fname("shift.txt"), we open
snapdir from share root because parent is calculated as empty string
via ceph_snap_get_parent_path(). Instead we could construct the full
path from dirfsp using full_path_from_dirfsp_atname() to ensure we
don't open the wrong snapdir.
Since we have access to the twrp token at VFS layer it doesn't make
much sense to make use of ceph_snap_gmt_strip_snapshot() in openat.
We could instead directly act based on already available twrp token
avoiding an extra copy of incoming smb_filename.
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15819
Signed-off-by: Anoop C S <anoopcs@samba.org>
Reviewed-by: David Disseldorp ddiss@samba.org
(cherry picked from commit
ad8b2dbb67d87db22f2fa2df814dd91cbe071e60)
{
time_t timestamp = 0;
struct smb_filename *smb_fname = NULL;
- char stripped[PATH_MAX + 1];
char conv[PATH_MAX + 1];
int ret;
int saved_errno = 0;
- ret = ceph_snap_gmt_strip_snapshot(handle,
- smb_fname_in,
- ×tamp,
- stripped,
- sizeof(stripped));
- if (ret < 0) {
- errno = -ret;
- return -1;
- }
- if (timestamp == 0) {
+ if (smb_fname_in->twrp == 0) {
return SMB_VFS_NEXT_OPENAT(handle,
dirfsp,
smb_fname_in,
how);
}
+ timestamp = nt_time_to_unix(smb_fname_in->twrp);
+
+ smb_fname = full_path_from_dirfsp_atname(talloc_tos(),
+ dirfsp,
+ smb_fname_in);
+ if (smb_fname == NULL) {
+ errno = ENOMEM;
+ return -1;
+ }
+
ret = ceph_snap_gmt_convert(handle,
- stripped,
+ smb_fname->base_name,
timestamp,
conv,
sizeof(conv));
errno = -ret;
return -1;
}
- smb_fname = cp_smb_filename(talloc_tos(), smb_fname_in);
- if (smb_fname == NULL) {
- return -1;
- }
+
smb_fname->base_name = conv;
ret = SMB_VFS_NEXT_OPENAT(handle,