summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeremy Allison <jra@samba.org>2010-05-20 11:36:47 -0700
committerJeremy Allison <jra@samba.org>2010-05-20 11:36:47 -0700
commita8a4fe0605e6149efb5f9051181d794572edbf27 (patch)
tree15bcb3771d87fefcd91ae26fbf713c790cbf763e
parenta7cab4ea36eb21d7b72efa80a77c702bb92bec62 (diff)
downloadsamba-a8a4fe0605e6149efb5f9051181d794572edbf27.tar.gz
Fix bug #7410 - samba sends "raw" inode number as uniqueid with unix extensions.
Move to a consistent get_FileIndex() function for all inode returns, that checks if st_dev on the file is identical to the top directory dev_t of the exported share, and if so uses the raw 64-bit inode number. If it isn't (we've traversed a mount point) - return what we used to do for Windows which is the concatination of the bottom 32-bits of the inode with the 32-bit device number. We can get more creative with this over time (hashing?) if we want as now all inode returns go through this single function. Jeremy.
-rw-r--r--source3/include/proto.h1
-rw-r--r--source3/include/smb.h3
-rw-r--r--source3/smbd/service.c1
-rw-r--r--source3/smbd/smb2_create.c11
-rw-r--r--source3/smbd/trans2.c33
5 files changed, 39 insertions, 10 deletions
diff --git a/source3/include/proto.h b/source3/include/proto.h
index bd188b1bf18..1586592290d 100644
--- a/source3/include/proto.h
+++ b/source3/include/proto.h
@@ -6351,6 +6351,7 @@ int sys_statvfs(const char *path, vfs_statvfs_struct *statbuf);
/* The following definitions come from smbd/trans2.c */
uint64_t smb_roundup(connection_struct *conn, uint64_t val);
+uint64_t get_FileIndex(connection_struct *conn, const SMB_STRUCT_STAT *psbuf);
NTSTATUS get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn,
files_struct *fsp, const char *fname,
const char *ea_name, struct ea_struct *pea);
diff --git a/source3/include/smb.h b/source3/include/smb.h
index e1ec21f22c9..e2721700e52 100644
--- a/source3/include/smb.h
+++ b/source3/include/smb.h
@@ -588,6 +588,9 @@ typedef struct connection_struct {
/* Semantics provided by the underlying filesystem. */
int fs_capabilities;
+ /* Device number of the directory of the share mount.
+ Used to ensure unique FileIndex returns. */
+ SMB_DEV_T base_share_dev;
name_compare_entry *hide_list; /* Per-share list of files to return as hidden. */
name_compare_entry *veto_list; /* Per-share list of files to veto (never show). */
diff --git a/source3/smbd/service.c b/source3/smbd/service.c
index 36184af75c6..8ba32652cd1 100644
--- a/source3/smbd/service.c
+++ b/source3/smbd/service.c
@@ -1033,6 +1033,7 @@ connection_struct *make_connection_snum(struct smbd_server_connection *sconn,
*pstatus = NT_STATUS_BAD_NETWORK_NAME;
goto err_root_exit;
}
+ conn->base_share_dev = smb_fname_cpath->st.st_ex_dev;
string_set(&conn->origpath,conn->connectpath);
diff --git a/source3/smbd/smb2_create.c b/source3/smbd/smb2_create.c
index 09bd827802d..cc65df235ca 100644
--- a/source3/smbd/smb2_create.c
+++ b/source3/smbd/smb2_create.c
@@ -741,13 +741,18 @@ static struct tevent_req *smbd_smb2_create_send(TALLOC_CTX *mem_ctx,
if (qfid) {
uint8_t p[32];
+ uint64_t file_index = get_FileIndex(result->conn,
+ &result->fsp_name->st);
DATA_BLOB blob = data_blob_const(p, sizeof(p));
ZERO_STRUCT(p);
- /* TODO: maybe use result->file_id */
- SIVAL(p, 0, result->fsp_name->st.st_ex_ino);/* FileIndexLow */
- SIVAL(p, 4, result->fsp_name->st.st_ex_dev);/* FileIndexHigh */
+ /* From conversations with Microsoft engineers at
+ the MS plugfest. The first 8 bytes are the "volume index"
+ == inode, the second 8 bytes are the "volume id",
+ == dev. This will be updated in the SMB2 doc. */
+ SBVAL(p, 0, file_index);
+ SIVAL(p, 8, result->fsp_name->st.st_ex_dev);/* FileIndexHigh */
status = smb2_create_blob_add(state, &out_context_blobs,
SMB2_CREATE_TAG_QFID,
diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c
index 6e1defaac2c..8535d46afa4 100644
--- a/source3/smbd/trans2.c
+++ b/source3/smbd/trans2.c
@@ -58,6 +58,23 @@ uint64_t smb_roundup(connection_struct *conn, uint64_t val)
return val;
}
+/********************************************************************
+ Create a 64 bit FileIndex. If the file is on the same device as
+ the root of the share, just return the 64-bit inode. If it isn't,
+ mangle as we used to do.
+********************************************************************/
+
+uint64_t get_FileIndex(connection_struct *conn, const SMB_STRUCT_STAT *psbuf)
+{
+ uint64_t file_index;
+ if (conn->base_share_dev == psbuf->st_ex_dev) {
+ return (uint64_t)psbuf->st_ex_ino;
+ }
+ file_index = ((psbuf->st_ex_ino) & UINT32_MAX); /* FileIndexLow */
+ file_index |= ((uint64_t)((psbuf->st_ex_dev) & UINT32_MAX)) << 32; /* FileIndexHigh */
+ return file_index;
+}
+
/****************************************************************************
Utility functions for dealing with extended attributes.
****************************************************************************/
@@ -1478,6 +1495,7 @@ static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx,
uint32_t reskey=0;
uint64_t file_size = 0;
uint64_t allocation_size = 0;
+ uint64_t file_index = 0;
uint32_t len;
struct timespec mdate_ts, adate_ts, cdate_ts, create_date_ts;
time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
@@ -1500,6 +1518,8 @@ static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx,
}
allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
+ file_index = get_FileIndex(conn, &smb_fname->st);
+
mdate_ts = smb_fname->st.st_ex_mtime;
adate_ts = smb_fname->st.st_ex_atime;
create_date_ts = get_create_timespec(conn, NULL, smb_fname);
@@ -1886,8 +1906,7 @@ static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx,
p +=4;
}
SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
- SIVAL(p,0,smb_fname->st.st_ex_ino); p += 4; /* FileIndexLow */
- SIVAL(p,0,smb_fname->st.st_ex_dev); p += 4; /* FileIndexHigh */
+ SBVAL(p,0,file_index); p += 8;
len = srvstr_push(base_data, flags2, p,
fname, PTR_DIFF(end_data, p),
STR_TERMINATE_ASCII);
@@ -1957,8 +1976,7 @@ static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx,
}
p += 26;
SSVAL(p,0,0); p += 2; /* Reserved ? */
- SIVAL(p,0,smb_fname->st.st_ex_ino); p += 4; /* FileIndexLow */
- SIVAL(p,0,smb_fname->st.st_ex_dev); p += 4; /* FileIndexHigh */
+ SBVAL(p,0,file_index); p += 8;
len = srvstr_push(base_data, flags2, p,
fname, PTR_DIFF(end_data, p),
STR_TERMINATE_ASCII);
@@ -3890,6 +3908,8 @@ static char *store_file_unix_basic(connection_struct *conn,
files_struct *fsp,
const SMB_STRUCT_STAT *psbuf)
{
+ uint64_t file_index = get_FileIndex(conn, psbuf);
+
DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
@@ -3923,7 +3943,7 @@ static char *store_file_unix_basic(connection_struct *conn,
SIVAL(pdata,4,0);
pdata += 8;
- SINO_T_VAL(pdata,0,(SMB_INO_T)psbuf->st_ex_ino); /* inode number */
+ SINO_T_VAL(pdata,0,(SMB_INO_T)file_index); /* inode number */
pdata += 8;
SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
@@ -4319,8 +4339,7 @@ NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
I think this causes us to fail the IFSKIT
BasicFileInformationTest. -tpot */
- file_index = ((psbuf->st_ex_ino) & UINT32_MAX); /* FileIndexLow */
- file_index |= ((uint64_t)((psbuf->st_ex_dev) & UINT32_MAX)) << 32; /* FileIndexHigh */
+ file_index = get_FileIndex(conn, psbuf);
switch (info_level) {
case SMB_INFO_STANDARD: