The branch, master has been updated
       via  572e5de... Implement missing info level SMB_FILE_LINK_INFORMATION.
      from  c798207... Keep track of credits we're giving out. Set initial 
credits to 1 (MS-SMB2 spec required).

http://gitweb.samba.org/?p=samba.git;a=shortlog;h=master


- Log -----------------------------------------------------------------
commit 572e5dec1bbd4af3ccc4b8bfe56a72ded4c9aa6e
Author: Jeremy Allison <j...@samba.org>
Date:   Tue May 18 18:34:54 2010 -0700

    Implement missing info level SMB_FILE_LINK_INFORMATION.
    
    Fix bug #7435 - SMB2 hardlink fails (invalid level).
    Found at the Microsoft plugsharing plugfest.
    
    Jeremy.

-----------------------------------------------------------------------

Summary of changes:
 source3/include/proto.h |    4 +-
 source3/smbd/nttrans.c  |    2 +
 source3/smbd/trans2.c   |  104 ++++++++++++++++++++++++++++++++++++++++++++--
 3 files changed, 104 insertions(+), 6 deletions(-)


Changeset truncated at 500 lines:

diff --git a/source3/include/proto.h b/source3/include/proto.h
index 154efeb..3deeb9f 100644
--- a/source3/include/proto.h
+++ b/source3/include/proto.h
@@ -6368,8 +6368,10 @@ void send_trans2_replies(connection_struct *conn,
 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char 
objid[16]);
 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
                connection_struct *conn,
+               struct smb_request *req,
+               bool overwrite_if_exists,
                const struct smb_filename *smb_fname_old,
-               const struct smb_filename *smb_fname_new);
+               struct smb_filename *smb_fname_new);
 NTSTATUS smb_set_file_time(connection_struct *conn,
                           files_struct *fsp,
                           const struct smb_filename *smb_fname,
diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c
index b42d665..9b4d38a 100644
--- a/source3/smbd/nttrans.c
+++ b/source3/smbd/nttrans.c
@@ -1550,6 +1550,8 @@ void reply_ntrename(struct smb_request *req)
                                status = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
                        } else {
                                status = hardlink_internals(ctx, conn,
+                                                           req,
+                                                           false,
                                                            smb_fname_old,
                                                            smb_fname_new);
                        }
diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c
index 56d22b3..dec9d7f 100644
--- a/source3/smbd/trans2.c
+++ b/source3/smbd/trans2.c
@@ -5348,8 +5348,10 @@ total_data=%u (should be %u)\n", (unsigned 
int)total_data, (unsigned int)IVAL(pd
 
 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
                connection_struct *conn,
+               struct smb_request *req,
+               bool overwrite_if_exists,
                const struct smb_filename *smb_fname_old,
-               const struct smb_filename *smb_fname_new)
+               struct smb_filename *smb_fname_new)
 {
        NTSTATUS status = NT_STATUS_OK;
 
@@ -5358,9 +5360,23 @@ NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
                return NT_STATUS_OBJECT_NAME_NOT_FOUND;
        }
 
-       /* Disallow if newname already exists. */
        if (VALID_STAT(smb_fname_new->st)) {
-               return NT_STATUS_OBJECT_NAME_COLLISION;
+               if (overwrite_if_exists) {
+                       if (S_ISDIR(smb_fname_new->st.st_ex_mode)) {
+                               return NT_STATUS_FILE_IS_A_DIRECTORY;
+                       }
+                       status = unlink_internals(conn,
+                                               req,
+                                               FILE_ATTRIBUTE_NORMAL,
+                                               smb_fname_new,
+                                               false);
+                       if (!NT_STATUS_IS_OK(status)) {
+                               return status;
+                       }
+               } else {
+                       /* Disallow if newname already exists. */
+                       return NT_STATUS_OBJECT_NAME_COLLISION;
+               }
        }
 
        /* No links from a directory. */
@@ -5870,7 +5886,7 @@ static NTSTATUS smb_set_file_unix_link(connection_struct 
*conn,
 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
                                        struct smb_request *req,
                                        const char *pdata, int total_data,
-                                       const struct smb_filename 
*smb_fname_new)
+                                       struct smb_filename *smb_fname_new)
 {
        char *oldname = NULL;
        struct smb_filename *smb_fname_old = NULL;
@@ -5902,7 +5918,8 @@ static NTSTATUS smb_set_file_unix_hlink(connection_struct 
*conn,
                return status;
        }
 
-       return hardlink_internals(ctx, conn, smb_fname_old, smb_fname_new);
+       return hardlink_internals(ctx, conn, req, false,
+                       smb_fname_old, smb_fname_new);
 }
 
 /****************************************************************************
@@ -6006,6 +6023,75 @@ static NTSTATUS 
smb2_file_rename_information(connection_struct *conn,
        return status;
 }
 
+static NTSTATUS smb_file_link_information(connection_struct *conn,
+                                           struct smb_request *req,
+                                           const char *pdata,
+                                           int total_data,
+                                           files_struct *fsp,
+                                           struct smb_filename *smb_fname_src)
+{
+       bool overwrite;
+       uint32_t len;
+       char *newname = NULL;
+       struct smb_filename *smb_fname_dst = NULL;
+       NTSTATUS status = NT_STATUS_OK;
+       TALLOC_CTX *ctx = talloc_tos();
+
+       if (!fsp) {
+               return NT_STATUS_INVALID_HANDLE;
+       }
+
+       if (total_data < 20) {
+               return NT_STATUS_INVALID_PARAMETER;
+       }
+
+       overwrite = (CVAL(pdata,0) ? true : false);
+       len = IVAL(pdata,16);
+
+       if (len > (total_data - 20) || (len == 0)) {
+               return NT_STATUS_INVALID_PARAMETER;
+       }
+
+       srvstr_get_path(ctx, pdata, req->flags2, &newname,
+                               &pdata[20], len, STR_TERMINATE,
+                               &status);
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
+       }
+
+       DEBUG(10,("smb_file_link_information: got name |%s|\n",
+                               newname));
+
+       status = filename_convert(ctx,
+                               conn,
+                               req->flags2 & FLAGS2_DFS_PATHNAMES,
+                               newname,
+                               0,
+                               NULL,
+                               &smb_fname_dst);
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
+       }
+
+       if (fsp->base_fsp) {
+               /* No stream names. */
+               return NT_STATUS_NOT_SUPPORTED;
+       }
+
+       DEBUG(10,("smb_file_link_information: "
+                 "SMB_FILE_LINK_INFORMATION (fnum %d) %s -> %s\n",
+                 fsp->fnum, fsp_str_dbg(fsp),
+                 smb_fname_str_dbg(smb_fname_dst)));
+       status = hardlink_internals(ctx,
+                               conn,
+                               req,
+                               overwrite,
+                               fsp->fsp_name,
+                               smb_fname_dst);
+
+       TALLOC_FREE(smb_fname_dst);
+       return status;
+}
 
 /****************************************************************************
  Deal with SMB_FILE_RENAME_INFORMATION.
@@ -7609,6 +7695,14 @@ NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
                        break;
                }
 
+               case SMB_FILE_LINK_INFORMATION:
+               {
+                       status = smb_file_link_information(conn, req,
+                                                       pdata, total_data,
+                                                       fsp, smb_fname);
+                       break;
+               }
+
 #if defined(HAVE_POSIX_ACLS)
                case SMB_SET_POSIX_ACL:
                {


-- 
Samba Shared Repository

Reply via email to