From 2ad5400d89c2e469cf1c4fa410d162bc3fecf312 Mon Sep 17 00:00:00 2001 From: Ira Cooper Date: Fri, 8 Feb 2013 14:47:57 -0800 Subject: [PATCH] s3: Make SMB2_GETINFO multi-volume aware. Not all shares are a single volume. Some actually expose multiple volumes under a single share. In these cases showing the amount of space free as the space free at the base of the directory heirarchy is wrong. Reviewed-by: Jeremy Allison --- source3/smbd/globals.h | 1 + source3/smbd/smb2_getinfo.c | 1 + source3/smbd/trans2.c | 27 ++++++++++++++++++--------- 3 files changed, 20 insertions(+), 9 deletions(-) diff --git a/source3/smbd/globals.h b/source3/smbd/globals.h index 24dcd3d..e227295 100644 --- a/source3/smbd/globals.h +++ b/source3/smbd/globals.h @@ -179,6 +179,7 @@ NTSTATUS smbd_do_qfsinfo(connection_struct *conn, uint16_t info_level, uint16_t flags2, unsigned int max_data_bytes, + struct smb_filename *smb_fname, char **ppdata, int *ret_data_len); diff --git a/source3/smbd/smb2_getinfo.c b/source3/smbd/smb2_getinfo.c index b109de4..55071e8 100644 --- a/source3/smbd/smb2_getinfo.c +++ b/source3/smbd/smb2_getinfo.c @@ -404,6 +404,7 @@ static struct tevent_req *smbd_smb2_getinfo_send(TALLOC_CTX *mem_ctx, file_info_level, STR_UNICODE, in_output_buffer_length, + fsp->fsp_name, &data, &data_size); if (!NT_STATUS_IS_OK(status)) { diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index c786dd1..5f5ae35 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -2921,6 +2921,7 @@ NTSTATUS smbd_do_qfsinfo(connection_struct *conn, uint16_t info_level, uint16_t flags2, unsigned int max_data_bytes, + struct smb_filename *fname, char **ppdata, int *ret_data_len) { @@ -2929,10 +2930,17 @@ NTSTATUS smbd_do_qfsinfo(connection_struct *conn, const char *vname = volume_label(SNUM(conn)); int snum = SNUM(conn); char *fstype = lp_fstype(SNUM(conn)); + const char *filename = NULL; uint32 additional_flags = 0; - struct smb_filename smb_fname_dot; + struct smb_filename smb_fname; SMB_STRUCT_STAT st; + if (fname == NULL || fname->base_name == NULL) { + filename = "."; + } else { + filename = fname->base_name; + } + if (IS_IPC(conn)) { if (info_level != SMB_QUERY_CIFS_UNIX_INFO) { DEBUG(0,("smbd_do_qfsinfo: not an allowed " @@ -2944,15 +2952,15 @@ NTSTATUS smbd_do_qfsinfo(connection_struct *conn, DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level)); - ZERO_STRUCT(smb_fname_dot); - smb_fname_dot.base_name = discard_const_p(char, "."); + ZERO_STRUCT(smb_fname); + smb_fname.base_name = discard_const_p(char, filename); - if(SMB_VFS_STAT(conn, &smb_fname_dot) != 0) { + if(SMB_VFS_STAT(conn, &smb_fname) != 0) { DEBUG(2,("stat of . failed (%s)\n", strerror(errno))); return map_nt_error_from_unix(errno); } - st = smb_fname_dot.st; + st = smb_fname.st; *ppdata = (char *)SMB_REALLOC( *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN); @@ -2969,7 +2977,7 @@ NTSTATUS smbd_do_qfsinfo(connection_struct *conn, { uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector; data_len = 18; - if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) { + if (get_dfree_info(conn,filename,False,&bsize,&dfree,&dsize) == (uint64_t)-1) { return map_nt_error_from_unix(errno); } @@ -3092,7 +3100,7 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (u { uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector; data_len = 24; - if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) { + if (get_dfree_info(conn,filename,False,&bsize,&dfree,&dsize) == (uint64_t)-1) { return map_nt_error_from_unix(errno); } block_size = lp_block_size(snum); @@ -3124,7 +3132,7 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned { uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector; data_len = 32; - if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) { + if (get_dfree_info(conn,filename,False,&bsize,&dfree,&dsize) == (uint64_t)-1) { return map_nt_error_from_unix(errno); } block_size = lp_block_size(snum); @@ -3317,7 +3325,7 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned return NT_STATUS_INVALID_LEVEL; } - rc = SMB_VFS_STATVFS(conn, ".", &svfs); + rc = SMB_VFS_STATVFS(conn, filename, &svfs); if (!rc) { data_len = 56; @@ -3510,6 +3518,7 @@ static void call_trans2qfsinfo(connection_struct *conn, info_level, req->flags2, max_data_bytes, + NULL, ppdata, &data_len); if (!NT_STATUS_IS_OK(status)) { reply_nterror(req, status); -- 1.8.1