s3: smbd: Add dirfsp parameter to unlink_internals().
[samba.git] / source3 / smbd / smb2_trans2.c
index 65d8532468d7e37c36623c8781b091f2421b3bc4..118eb480911ed473b4e405bae34230435087c0dd 100644 (file)
@@ -59,6 +59,10 @@ static char *store_file_unix_basic_info2(connection_struct *conn,
                                files_struct *fsp,
                                const SMB_STRUCT_STAT *psbuf);
 
+static uint32_t generate_volume_serial_number(
+                               const struct loadparm_substitution *lp_sub,
+                               int snum);
+
 /****************************************************************************
  Check if an open file handle is a symlink.
 ****************************************************************************/
@@ -148,6 +152,7 @@ static NTSTATUS get_posix_fsp(connection_struct *conn,
        status = SMB_VFS_CREATE_FILE(
                conn,           /* conn */
                req,            /* req */
+               NULL,           /* dirfsp */
                smb_fname,      /* fname */
                access_mask,    /* access_mask */
                share_access,   /* share_access */
@@ -2120,6 +2125,7 @@ NTSTATUS smbd_do_qfsinfo(struct smbXsrv_connection *xconn,
        SMB_STRUCT_STAT st;
        NTSTATUS status = NT_STATUS_OK;
        uint64_t df_ret;
+       uint32_t serial;
 
        if (fname == NULL || fname->base_name == NULL) {
                filename = ".";
@@ -2218,7 +2224,8 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (u
                         * Add volume serial number - hash of a combination of
                         * the called hostname and the service name.
                         */
-                       SIVAL(pdata,0,str_checksum(lp_servicename(talloc_tos(), lp_sub, snum)) ^ (str_checksum(get_local_machine_name())<<16) );
+                       serial = generate_volume_serial_number(lp_sub, snum);
+                       SIVAL(pdata,0,serial);
                        /*
                         * Win2k3 and previous mess this up by sending a name length
                         * one byte short. I believe only older clients (OS/2 Win9x) use
@@ -2235,9 +2242,10 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (u
                        }
                        SCVAL(pdata,l2_vol_cch,len);
                        data_len = l2_vol_szVolLabel + len;
-                       DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %u, name = %s\n",
+                       DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %u, "
+                                "name = %s serial = 0x%04"PRIx32"\n",
                                 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
-                                (unsigned)len, vname));
+                                (unsigned)len, vname, serial));
                        break;
 
                case SMB_QUERY_FS_ATTRIBUTE_INFO:
@@ -2295,13 +2303,14 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (u
 
                case SMB_QUERY_FS_VOLUME_INFO:      
                case SMB_FS_VOLUME_INFORMATION:
-
+                       put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER,
+                                                   pdata, &st.st_ex_btime);
                        /* 
                         * Add volume serial number - hash of a combination of
                         * the called hostname and the service name.
                         */
-                       SIVAL(pdata,8,str_checksum(lp_servicename(talloc_tos(), lp_sub, snum)) ^
-                               (str_checksum(get_local_machine_name())<<16));
+                       serial = generate_volume_serial_number(lp_sub, snum);
+                       SIVAL(pdata,8,serial);
 
                        /* Max label len is 32 characters. */
                        status = srvstr_push(pdata, flags2, pdata+18, vname,
@@ -2313,9 +2322,12 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (u
                        SIVAL(pdata,12,len);
                        data_len = 18+len;
 
-                       DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
-                               (int)strlen(vname),vname,
-                               lp_servicename(talloc_tos(), lp_sub, snum)));
+                       DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO "
+                                "namelen = %d, vol=%s serv=%s "
+                                "serial=0x%04"PRIx32"\n",
+                                (int)strlen(vname),vname,
+                                lp_servicename(talloc_tos(), lp_sub, snum),
+                                serial));
                        if (max_data_bytes >= 24 && data_len > max_data_bytes) {
                                /* the client only requested a portion of the
                                   volume label */
@@ -2587,7 +2599,7 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned
                case SMB_QUERY_POSIX_FS_INFO:
                {
                        int rc;
-                       vfs_statvfs_struct svfs;
+                       struct vfs_statvfs_struct svfs;
 
                        if (!lp_smb1_unix_extensions()) {
                                return NT_STATUS_INVALID_LEVEL;
@@ -4293,6 +4305,7 @@ NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
                        status = unlink_internals(conn,
                                                req,
                                                FILE_ATTRIBUTE_NORMAL,
+                                               NULL, /* new_dirfsp */
                                                smb_fname_new);
                        if (!NT_STATUS_IS_OK(status)) {
                                goto out;
@@ -4537,6 +4550,7 @@ static NTSTATUS smb_set_file_size(connection_struct *conn,
         status = SMB_VFS_CREATE_FILE(
                conn,                                   /* conn */
                req,                                    /* req */
+               NULL,                                   /* dirfsp */
                smb_fname,                              /* fname */
                FILE_WRITE_DATA,                        /* access_mask */
                (FILE_SHARE_READ | FILE_SHARE_WRITE |   /* share_access */
@@ -4970,22 +4984,7 @@ static NTSTATUS smb2_file_rename_information(connection_struct *conn,
        DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
                                newname));
 
-       status = filename_convert(ctx,
-                               conn,
-                               newname,
-                               ucf_flags,
-                               0,
-                               &smb_fname_dst);
-       if (!NT_STATUS_IS_OK(status)) {
-               return status;
-       }
-
-       if (fsp->base_fsp) {
-               /* newname must be a stream name. */
-               if (newname[0] != ':') {
-                       return NT_STATUS_NOT_SUPPORTED;
-               }
-
+       if (newname[0] == ':') {
                /* Create an smb_fname to call rename_internals_fsp() with. */
                smb_fname_dst = synthetic_smb_fname(talloc_tos(),
                                        fsp->base_fsp->fsp_name->base_name,
@@ -4997,6 +4996,16 @@ static NTSTATUS smb2_file_rename_information(connection_struct *conn,
                        status = NT_STATUS_NO_MEMORY;
                        goto out;
                }
+       } else {
+               status = filename_convert(ctx,
+                                       conn,
+                                       newname,
+                                       ucf_flags,
+                                       0,
+                                       &smb_fname_dst);
+               if (!NT_STATUS_IS_OK(status)) {
+                       goto out;
+               }
        }
 
        /*
@@ -5140,7 +5149,7 @@ static NTSTATUS smb_file_rename_information(connection_struct *conn,
                return NT_STATUS_INVALID_PARAMETER;
        }
 
-       overwrite = (CVAL(pdata,0) ? True : False);
+       overwrite = (CVAL(pdata,0) != 0);
        root_fid = IVAL(pdata,4);
        len = IVAL(pdata,8);
 
@@ -5288,7 +5297,9 @@ static NTSTATUS smb_file_rename_information(connection_struct *conn,
                status = rename_internals(ctx,
                                        conn,
                                        req,
+                                       NULL, /* src_dirfsp */
                                        smb_fname_src,
+                                       NULL, /* dst_dirfsp */
                                        smb_fname_dst,
                                        dst_original_lcomp,
                                        0,
@@ -5640,6 +5651,7 @@ static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
        status = SMB_VFS_CREATE_FILE(
                conn,                                   /* conn */
                req,                                    /* req */
+               NULL,                                   /* dirfsp */
                smb_fname,                              /* fname */
                FILE_WRITE_DATA,                        /* access_mask */
                (FILE_SHARE_READ | FILE_SHARE_WRITE |   /* share_access */
@@ -6162,6 +6174,7 @@ static NTSTATUS smb_posix_mkdir(connection_struct *conn,
         status = SMB_VFS_CREATE_FILE(
                conn,                                   /* conn */
                req,                                    /* req */
+               NULL,                                   /* dirfsp */
                smb_fname,                              /* fname */
                FILE_READ_ATTRIBUTES,                   /* access_mask */
                FILE_SHARE_NONE,                        /* share_access */
@@ -6403,6 +6416,7 @@ static NTSTATUS smb_posix_open(connection_struct *conn,
         status = SMB_VFS_CREATE_FILE(
                conn,                                   /* conn */
                req,                                    /* req */
+               NULL,                                   /* dirfsp */
                smb_fname,                              /* fname */
                access_mask,                            /* access_mask */
                (FILE_SHARE_READ | FILE_SHARE_WRITE |   /* share_access */
@@ -6545,6 +6559,7 @@ static NTSTATUS smb_posix_unlink(connection_struct *conn,
         status = SMB_VFS_CREATE_FILE(
                conn,                                   /* conn */
                req,                                    /* req */
+               NULL,                                   /* dirfsp */
                smb_fname,                              /* fname */
                DELETE_ACCESS,                          /* access_mask */
                (FILE_SHARE_READ | FILE_SHARE_WRITE |   /* share_access */
@@ -6950,3 +6965,13 @@ NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
        *ret_data_size = data_return_size;
        return NT_STATUS_OK;
 }
+
+static uint32_t generate_volume_serial_number(
+                       const struct loadparm_substitution *lp_sub,
+                       int snum)
+{
+       int serial = lp_volume_serial_number(snum);
+       return serial != -1 ? serial:
+               str_checksum(lp_servicename(talloc_tos(), lp_sub, snum)) ^
+               (str_checksum(get_local_machine_name())<<16);
+}