summaryrefslogtreecommitdiff
path: root/source3
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 /source3
parenta7cab4ea36eb21d7b72efa80a77c702bb92bec62 (diff)
downloadsamba-a8a4fe0605e6149efb5f9051181d794572edbf27.tar.gz
samba-a8a4fe0605e6149efb5f9051181d794572edbf27.tar.bz2
samba-a8a4fe0605e6149efb5f9051181d794572edbf27.zip
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.
Diffstat (limited to 'source3')
-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 bd188b1bf1..1586592290 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 e1ec21f22c..e2721700e5 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 36184af75c..8ba32652cd 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 09bd827802..cc65df235c 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 6e1defaac2..8535d46afa 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: