From 233b32b771188a6b9ee730a2a202023370e80746 Mon Sep 17 00:00:00 2001 From: Ira Cooper Date: Wed, 6 Feb 2013 13:35:25 +0000 Subject: 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 Autobuild-User(master): Jeremy Allison Autobuild-Date(master): Fri Feb 8 21:44:37 CET 2013 on sn-devel-104 --- 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 4a86697d48..6ead9626a5 100644 --- a/source3/smbd/globals.h +++ b/source3/smbd/globals.h @@ -155,6 +155,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 33cee9910c..5616c849ad 100644 --- a/source3/smbd/smb2_getinfo.c +++ b/source3/smbd/smb2_getinfo.c @@ -413,6 +413,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 92d047ae5d..8cffc15dec 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -3021,6 +3021,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) { @@ -3029,10 +3030,17 @@ NTSTATUS smbd_do_qfsinfo(connection_struct *conn, const char *vname = volume_label(talloc_tos(), SNUM(conn)); int snum = SNUM(conn); char *fstype = lp_fstype(talloc_tos(), SNUM(conn)); + 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 " @@ -3044,15 +3052,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); @@ -3069,7 +3077,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); } @@ -3193,7 +3201,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); @@ -3225,7 +3233,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); @@ -3418,7 +3426,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; @@ -3598,6 +3606,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); -- cgit