summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeremy Allison <jra@samba.org>2010-05-20 11:36:47 -0700
committerKarolin Seeger <kseeger@samba.org>2010-06-18 08:33:26 +0200
commita160aeddea2d9dedaa9e66ac30b4bf713c68192f (patch)
treeb69cb34a98192bc6a173854a77fbf40148ed39aa
parent7bc852f91dcb977aa70c6ce63c2631881be18b6a (diff)
downloadsamba-a160aeddea2d9dedaa9e66ac30b4bf713c68192f.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. (cherry picked from commit 920ffe49290cacd30d9bc582c1c3fee38308c260)
-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 f30939a8857..04065b0c5a2 100644
--- a/source3/include/proto.h
+++ b/source3/include/proto.h
@@ -7050,6 +7050,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 bc7a90d5492..202f9d77db6 100644
--- a/source3/include/smb.h
+++ b/source3/include/smb.h
@@ -607,6 +607,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 25e0eb10f8e..bc2cdaf2d85 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 3cf8b185b08..3e0d180bf34 100644
--- a/source3/smbd/smb2_create.c
+++ b/source3/smbd/smb2_create.c
@@ -651,13 +651,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 963103c85b8..fb4d46b76bf 100644
--- a/source3/smbd/trans2.c
+++ b/source3/smbd/trans2.c
@@ -57,6 +57,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.
****************************************************************************/
@@ -1474,6 +1491,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;
@@ -1496,6 +1514,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);
@@ -1864,8 +1884,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);
@@ -1935,8 +1954,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);
@@ -3850,6 +3868,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));
@@ -3883,7 +3903,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 */
@@ -4285,8 +4305,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: