]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
s3: smbd: Change hardlink_internals() to use a real directory fsp for SMB_VFS_LINKAT().
authorJeremy Allison <jra@samba.org>
Tue, 19 Jan 2021 20:57:51 +0000 (12:57 -0800)
committerJeremy Allison <jra@samba.org>
Tue, 9 Feb 2021 00:10:29 +0000 (00:10 +0000)
New VFS change.

Signed-off-by: Jeremy Allison <jra@samba.org>
Reviewed-by: Ralph Böhme <slow@samba.org>
source3/smbd/trans2.c

index a869d034f9f153a2f572a23052196a5bafb767e3..92856163ac524834e417ed54ad77fb70881a480f 100644 (file)
@@ -6466,6 +6466,10 @@ NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
        NTSTATUS status = NT_STATUS_OK;
        int ret;
        bool ok;
+       struct smb_filename *parent_fname_old = NULL;
+       struct smb_filename *base_name_old = NULL;
+       struct smb_filename *parent_fname_new = NULL;
+       struct smb_filename *base_name_new = NULL;
 
        /* source must already exist. */
        if (!VALID_STAT(smb_fname_old->st)) {
@@ -6473,6 +6477,44 @@ NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
                goto out;
        }
 
+       /* No links from a directory. */
+       if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
+               status = NT_STATUS_FILE_IS_A_DIRECTORY;
+               goto out;
+       }
+
+       /* Setting a hardlink to/from a stream isn't currently supported. */
+       ok = is_ntfs_stream_smb_fname(smb_fname_old);
+       if (ok) {
+               DBG_DEBUG("Old name has streams\n");
+               status = NT_STATUS_INVALID_PARAMETER;
+               goto out;
+       }
+       ok = is_ntfs_stream_smb_fname(smb_fname_new);
+       if (ok) {
+               DBG_DEBUG("New name has streams\n");
+               status = NT_STATUS_INVALID_PARAMETER;
+               goto out;
+       }
+
+       status = parent_pathref(talloc_tos(),
+                               conn->cwd_fsp,
+                               smb_fname_old,
+                               &parent_fname_old,
+                               &base_name_old);
+       if (!NT_STATUS_IS_OK(status)) {
+               goto out;
+       }
+
+       status = parent_pathref(talloc_tos(),
+                               conn->cwd_fsp,
+                               smb_fname_new,
+                               &parent_fname_new,
+                               &base_name_new);
+       if (!NT_STATUS_IS_OK(status)) {
+               goto out;
+       }
+
        if (VALID_STAT(smb_fname_new->st)) {
                if (overwrite_if_exists) {
                        if (S_ISDIR(smb_fname_new->st.st_ex_mode)) {
@@ -6494,34 +6536,14 @@ NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
                }
        }
 
-       /* No links from a directory. */
-       if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
-               status = NT_STATUS_FILE_IS_A_DIRECTORY;
-               goto out;
-       }
-
-       /* Setting a hardlink to/from a stream isn't currently supported. */
-       ok = is_ntfs_stream_smb_fname(smb_fname_old);
-       if (ok) {
-               DBG_DEBUG("Old name has streams\n");
-               status = NT_STATUS_INVALID_PARAMETER;
-               goto out;
-       }
-       ok = is_ntfs_stream_smb_fname(smb_fname_new);
-       if (ok) {
-               DBG_DEBUG("New name has streams\n");
-               status = NT_STATUS_INVALID_PARAMETER;
-               goto out;
-       }
-
        DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
                  smb_fname_old->base_name, smb_fname_new->base_name));
 
        ret = SMB_VFS_LINKAT(conn,
-                       conn->cwd_fsp,
-                       smb_fname_old,
-                       conn->cwd_fsp,
-                       smb_fname_new,
+                       parent_fname_old->fsp,
+                       base_name_old,
+                       parent_fname_new->fsp,
+                       base_name_new,
                        0);
 
        if (ret != 0) {
@@ -6533,6 +6555,8 @@ NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
 
   out:
 
+       TALLOC_FREE(parent_fname_old);
+       TALLOC_FREE(parent_fname_new);
        return status;
 }