1
0
mirror of https://github.com/samba-team/samba.git synced 2025-01-08 21:18:16 +03:00

smbd: remove itime and file_id logic and code

This bases File-Ids on the inode numbers again. The whole stuff was
added because at that time Apple clients

1. would be upset by inode number reusage and

2. had a client side bug in their fallback implemetentation that
assigns File-Ids on the client side in case the server provides
File-Ids of 0.

After discussion with folks at Apple it should be safe these days to
rely on the Mac to generate its own File-Ids and let Samba return 0
File-Ids.

Signed-off-by: Ralph Boehme <slow@samba.org>
Reviewed-by: Jeremy Allison <jra@samba.org>
This commit is contained in:
Ralph Boehme 2022-03-28 11:48:37 +02:00 committed by Jeremy Allison
parent 8ad0febd13
commit 643da37fd1
21 changed files with 48 additions and 415 deletions

View File

@ -94,12 +94,19 @@ interface xattr
NTTIME create_time;
} xattr_DosInfo4;
typedef struct {
xattr_DosInfoValidFlags valid_flags;
uint32 attrib;
NTTIME create_time;
} xattr_DosInfo5;
typedef [public,switch_type(uint16)] union {
[case(0xFFFF)] xattr_DosInfoFFFFCompat compatinfoFFFF;
[case(1)] xattr_DosInfo1 info1;
[case(2)] xattr_DosInfo2Old oldinfo2;
[case(3)] xattr_DosInfo3 info3;
[case(4)] xattr_DosInfo4 info4;
[case(5)] xattr_DosInfo5 info5;
} xattr_DosInfo;
typedef [public] struct {

View File

@ -183,8 +183,6 @@ typedef sig_atomic_t volatile SIG_ATOMIC_T;
/* Is birthtime real, or was it calculated ? */
#define ST_EX_IFLAG_CALCULATED_BTIME (1 << 0)
#define ST_EX_IFLAG_CALCULATED_ITIME (1 << 1)
#define ST_EX_IFLAG_CALCULATED_FILE_ID (1 << 2)
/*
* Type for stat structure.
@ -193,7 +191,6 @@ typedef sig_atomic_t volatile SIG_ATOMIC_T;
struct stat_ex {
dev_t st_ex_dev;
ino_t st_ex_ino;
uint64_t st_ex_file_id;
mode_t st_ex_mode;
nlink_t st_ex_nlink;
uid_t st_ex_uid;
@ -204,11 +201,6 @@ struct stat_ex {
struct timespec st_ex_mtime;
struct timespec st_ex_ctime;
struct timespec st_ex_btime; /* birthtime */
/*
* Immutable original birth time aka invented time. Set when a file
* is created, never changes thereafter. May not be set by the client.
*/
struct timespec st_ex_itime; /* invented time */
blksize_t st_ex_blksize;
blkcnt_t st_ex_blocks;

View File

@ -170,12 +170,10 @@ int sys_fcntl_ptr(int fd, int cmd, void *arg);
int sys_fcntl_long(int fd, int cmd, long arg);
int sys_fcntl_int(int fd, int cmd, int arg);
void update_stat_ex_mtime(struct stat_ex *dst, struct timespec write_ts);
void update_stat_ex_itime(struct stat_ex *dst, struct timespec itime);
void update_stat_ex_create_time(struct stat_ex *dst, struct timespec create_time);
void update_stat_ex_file_id(struct stat_ex *dst, uint64_t file_id);
void update_stat_ex_from_saved_stat(struct stat_ex *dst,
const struct stat_ex *src);
void create_clock_itime(struct stat_ex *dst);
int sys_stat(const char *fname, SMB_STRUCT_STAT *sbuf,
bool fake_dir_create_times);
int sys_fstat(int fd, SMB_STRUCT_STAT *sbuf,

View File

@ -366,6 +366,7 @@
* Change to Version 47 - will ship with 4.17
* Version 47 - Add SMB_VFS_FSTATAT
* Version 47 - Change SMB_VFS_GET_REAL_FILENAME to return NTSTATUS
* Version 47 - remove st_ex_itime from struct stat_ex
*/
#define SMB_VFS_INTERFACE_VERSION 47

View File

@ -80,39 +80,3 @@ void pull_file_id_24(const char *buf, struct file_id *id)
id->extid = IVAL(buf, 16);
id->extid |= ((uint64_t)IVAL(buf,20))<<32;
}
uint64_t make_file_id_from_itime(const struct stat_ex *st)
{
struct timespec itime = st->st_ex_itime;
ino_t ino = st->st_ex_ino;
uint64_t file_id_low;
uint64_t file_id;
if (st->st_ex_iflags & ST_EX_IFLAG_CALCULATED_ITIME) {
return ino;
}
round_timespec_to_nttime(&itime);
file_id_low = itime.tv_nsec;
if (file_id_low == 0) {
/*
* This could be by coincidence, but more likely the filesystem
* is only giving us seconds granularity. We need more fine
* grained granularity for the File-ID, so combine with the
* inode number.
*/
file_id_low = ino & ((1 << 30) - 1);
}
/*
* Set the high bit so ideally File-IDs based on inode numbers and
* File-IDs based on Birth Time use disjoint ranges, given inodes never
* have the high bit set.
*/
file_id = ((uint64_t)1) << 63;
file_id |= (uint64_t)itime.tv_sec << 30;
file_id |= file_id_low;
return file_id;
}

View File

@ -41,10 +41,4 @@ void push_file_id_16(char *buf, const struct file_id *id);
void push_file_id_24(char *buf, const struct file_id *id);
void pull_file_id_24(const char *buf, struct file_id *id);
/*
* Make a SMB File-ID from itime
*/
struct stat_ex;
uint64_t make_file_id_from_itime(const struct stat_ex *st);
#endif

View File

@ -210,9 +210,6 @@ static void make_create_timespec(const struct stat *pst, struct stat_ex *dst,
dst->st_ex_btime = calc_create_time_stat(pst);
dst->st_ex_iflags |= ST_EX_IFLAG_CALCULATED_BTIME;
}
dst->st_ex_itime = dst->st_ex_btime;
dst->st_ex_iflags |= ST_EX_IFLAG_CALCULATED_ITIME;
}
/****************************************************************************
@ -239,19 +236,6 @@ void update_stat_ex_create_time(struct stat_ex *dst,
dst->st_ex_iflags &= ~ST_EX_IFLAG_CALCULATED_BTIME;
}
void update_stat_ex_itime(struct stat_ex *dst,
struct timespec itime)
{
dst->st_ex_itime = itime;
dst->st_ex_iflags &= ~ST_EX_IFLAG_CALCULATED_ITIME;
}
void update_stat_ex_file_id(struct stat_ex *dst, uint64_t file_id)
{
dst->st_ex_file_id = file_id;
dst->st_ex_iflags &= ~ST_EX_IFLAG_CALCULATED_FILE_ID;
}
void update_stat_ex_from_saved_stat(struct stat_ex *dst,
const struct stat_ex *src)
{
@ -262,14 +246,6 @@ void update_stat_ex_from_saved_stat(struct stat_ex *dst,
if (!(src->st_ex_iflags & ST_EX_IFLAG_CALCULATED_BTIME)) {
update_stat_ex_create_time(dst, src->st_ex_btime);
}
if (!(src->st_ex_iflags & ST_EX_IFLAG_CALCULATED_ITIME)) {
update_stat_ex_itime(dst, src->st_ex_itime);
}
if (!(src->st_ex_iflags & ST_EX_IFLAG_CALCULATED_FILE_ID)) {
update_stat_ex_file_id(dst, src->st_ex_file_id);
}
}
void init_stat_ex_from_stat (struct stat_ex *dst,
@ -306,60 +282,6 @@ void init_stat_ex_from_stat (struct stat_ex *dst,
#else
dst->st_ex_flags = 0;
#endif
dst->st_ex_file_id = dst->st_ex_ino;
dst->st_ex_iflags |= ST_EX_IFLAG_CALCULATED_FILE_ID;
}
/*******************************************************************
Create a clock-derived itime (invented) time. Used to generate
the fileid.
********************************************************************/
void create_clock_itime(struct stat_ex *dst)
{
NTTIME tval;
struct timespec itime;
uint64_t mixin;
uint8_t rval;
/* Start with the system clock. */
itime = timespec_current();
/* Convert to NTTIME. */
tval = unix_timespec_to_nt_time(itime);
/*
* In case the system clock is poor granularity
* (happens on VM or docker images) then mix in
* 8 bits of randomness.
*/
generate_random_buffer((unsigned char *)&rval, 1);
mixin = rval;
/*
* Shift up by 55 bits. This gives us approx 114 years
* of headroom.
*/
mixin <<= 55;
/* And OR into the nttime. */
tval |= mixin;
/*
* Convert to a unix timespec, ignoring any
* constraints on seconds being higher than
* TIME_T_MAX or lower than TIME_T_MIN. These
* are only needed to allow unix display time functions
* to work correctly, and this is being used to
* generate a fileid. All we care about is the
* NTTIME being valid across all NTTIME ranges
* (which we carefully ensured above).
*/
itime = nt_time_to_unix_timespec_raw(tval);
/* And set as a generated itime. */
update_stat_ex_itime(dst, itime);
}
/*******************************************************************

View File

@ -84,59 +84,6 @@ static void test_dosmode_to_gpfs_winattrs(void **state)
GPFS_WINATTR_SYSTEM);
}
static void test_gpfs_get_file_id(void **state)
{
struct gpfs_iattr64 iattr;
uint64_t fileid1, fileid2;
NTSTATUS status;
/*
* Ensure that the generated fileid only depends on the
* ia_inode, ia_gen and ia_modsnapid fields in struct
* gpfs_iattr64 and any changes to these fields result in a
* different file id.
*/
memset(&iattr, 1, sizeof(iattr));
iattr.ia_inode = 0x11;
iattr.ia_gen = 0x22;
iattr.ia_modsnapid = 0x33;
status = vfs_gpfs_get_file_id(&iattr, &fileid1);
assert_true(NT_STATUS_IS_OK(status));
memset(&iattr, 2, sizeof(iattr));
iattr.ia_inode = 0x11;
iattr.ia_gen = 0x22;
iattr.ia_modsnapid = 0x33;
status = vfs_gpfs_get_file_id(&iattr, &fileid2);
assert_true(NT_STATUS_IS_OK(status));
assert_int_equal(fileid1, fileid2);
iattr.ia_inode = 0x44;
iattr.ia_gen = 0x22;
iattr.ia_modsnapid = 0x33;
status = vfs_gpfs_get_file_id(&iattr, &fileid2);
assert_true(NT_STATUS_IS_OK(status));
assert_true(NT_STATUS_IS_OK(status));
assert_int_not_equal(fileid1, fileid2);
iattr.ia_inode = 0x11;
iattr.ia_gen = 0x44;
iattr.ia_modsnapid = 0x33;
status = vfs_gpfs_get_file_id(&iattr, &fileid2);
assert_true(NT_STATUS_IS_OK(status));
assert_true(NT_STATUS_IS_OK(status));
assert_int_not_equal(fileid1, fileid2);
iattr.ia_inode = 0x11;
iattr.ia_gen = 0x22;
iattr.ia_modsnapid = 0x44;
status = vfs_gpfs_get_file_id(&iattr, &fileid2);
assert_true(NT_STATUS_IS_OK(status));
assert_true(NT_STATUS_IS_OK(status));
assert_int_not_equal(fileid1, fileid2);
}
int main(int argc, char **argv)
{
const struct CMUnitTest tests[] = {
@ -146,7 +93,6 @@ int main(int argc, char **argv)
#endif /* #ifdef HAVE_KERNEL_OPLOCKS_LINUX */
cmocka_unit_test(test_gpfs_winattrs_to_dosmode),
cmocka_unit_test(test_dosmode_to_gpfs_winattrs),
cmocka_unit_test(test_gpfs_get_file_id),
};
cmocka_set_message_output(CM_OUTPUT_SUBUNIT);

View File

@ -749,12 +749,8 @@ static void init_stat_ex_from_ceph_statx(struct stat_ex *dst, const struct ceph_
dst->st_ex_btime = stx->stx_btime;
dst->st_ex_ctime = stx->stx_ctime;
dst->st_ex_mtime = stx->stx_mtime;
dst->st_ex_itime = dst->st_ex_btime;
dst->st_ex_iflags = ST_EX_IFLAG_CALCULATED_ITIME;
dst->st_ex_blksize = stx->stx_blksize;
dst->st_ex_blocks = stx->stx_blocks;
dst->st_ex_file_id = dst->st_ex_ino;
dst->st_ex_iflags |= ST_EX_IFLAG_CALCULATED_FILE_ID;
}
static int cephwrap_stat(struct vfs_handle_struct *handle,

View File

@ -3294,10 +3294,6 @@ static uint64_t vfswrap_fs_file_id(struct vfs_handle_struct *handle,
{
uint64_t file_id;
if (!(psbuf->st_ex_iflags & ST_EX_IFLAG_CALCULATED_FILE_ID)) {
return psbuf->st_ex_file_id;
}
if (handle->conn->base_share_dev == psbuf->st_ex_dev) {
return (uint64_t)psbuf->st_ex_ino;
}

View File

@ -71,16 +71,12 @@ static void smb_stat_ex_from_stat(struct stat_ex *dst, const struct stat *src)
dst->st_ex_btime.tv_sec = src->st_mtime;
dst->st_ex_blksize = src->st_blksize;
dst->st_ex_blocks = src->st_blocks;
dst->st_ex_file_id = dst->st_ex_ino;
dst->st_ex_iflags |= ST_EX_IFLAG_CALCULATED_FILE_ID;
#ifdef STAT_HAVE_NSEC
dst->st_ex_atime.tv_nsec = src->st_atime_nsec;
dst->st_ex_mtime.tv_nsec = src->st_mtime_nsec;
dst->st_ex_ctime.tv_nsec = src->st_ctime_nsec;
dst->st_ex_btime.tv_nsec = src->st_mtime_nsec;
#endif
dst->st_ex_itime = dst->st_ex_btime;
dst->st_ex_iflags |= ST_EX_IFLAG_CALCULATED_ITIME;
}
/* pre-opened glfs_t */

View File

@ -1434,40 +1434,6 @@ static unsigned int vfs_gpfs_dosmode_to_winattrs(uint32_t dosmode)
return winattrs;
}
static NTSTATUS vfs_gpfs_get_file_id(struct gpfs_iattr64 *iattr,
uint64_t *fileid)
{
uint8_t input[sizeof(gpfs_ino64_t) +
sizeof(gpfs_gen64_t) +
sizeof(gpfs_snapid64_t)];
uint8_t digest[gnutls_hash_get_len(GNUTLS_DIG_SHA1)];
int rc;
DBG_DEBUG("ia_inode 0x%llx, ia_gen 0x%llx, ia_modsnapid 0x%llx\n",
iattr->ia_inode, iattr->ia_gen, iattr->ia_modsnapid);
SBVAL(input,
0, iattr->ia_inode);
SBVAL(input,
sizeof(gpfs_ino64_t), iattr->ia_gen);
SBVAL(input,
sizeof(gpfs_ino64_t) + sizeof(gpfs_gen64_t), iattr->ia_modsnapid);
GNUTLS_FIPS140_SET_LAX_MODE();
rc = gnutls_hash_fast(GNUTLS_DIG_SHA1, input, sizeof(input), &digest);
GNUTLS_FIPS140_SET_STRICT_MODE();
if (rc != 0) {
return gnutls_error_to_ntstatus(rc,
NT_STATUS_HASH_NOT_SUPPORTED);
}
memcpy(fileid, &digest, sizeof(*fileid));
DBG_DEBUG("file_id 0x%" PRIx64 "\n", *fileid);
return NT_STATUS_OK;
}
static struct timespec gpfs_timestruc64_to_timespec(struct gpfs_timestruc64 g)
{
return (struct timespec) { .tv_sec = g.tv_sec, .tv_nsec = g.tv_nsec };
@ -1484,8 +1450,6 @@ static NTSTATUS vfs_gpfs_fget_dos_attributes(struct vfs_handle_struct *handle,
struct gpfs_iattr64 iattr = { };
unsigned int litemask = 0;
struct timespec ts;
uint64_t file_id;
NTSTATUS status;
int ret;
SMB_VFS_HANDLE_GET_DATA(handle, config,
@ -1556,17 +1520,10 @@ static NTSTATUS vfs_gpfs_fget_dos_attributes(struct vfs_handle_struct *handle,
return map_nt_error_from_unix(errno);
}
ZERO_STRUCT(file_id);
status = vfs_gpfs_get_file_id(&iattr, &file_id);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
ts = gpfs_timestruc64_to_timespec(iattr.ia_createtime);
*dosmode |= vfs_gpfs_winattrs_to_dosmode(iattr.ia_winflags);
update_stat_ex_create_time(&fsp->fsp_name->st, ts);
update_stat_ex_file_id(&fsp->fsp_name->st, file_id);
return NT_STATUS_OK;
}

View File

@ -517,7 +517,6 @@ bool mds_add_result(struct sl_query *slq, const char *path)
{
struct smb_filename *smb_fname = NULL;
struct stat_ex sb;
uint32_t attr;
uint64_t ino64;
int result;
NTSTATUS status;
@ -560,33 +559,21 @@ bool mds_add_result(struct sl_query *slq, const char *path)
return true;
}
sb = smb_fname->st;
status = smbd_check_access_rights_fsp(slq->mds_ctx->conn->cwd_fsp,
smb_fname->fsp,
false,
FILE_READ_DATA);
unbecome_authenticated_pipe_user();
if (!NT_STATUS_IS_OK(status)) {
unbecome_authenticated_pipe_user();
TALLOC_FREE(smb_fname);
return true;
}
/* This is needed to fetch the itime from the DOS attribute blob */
status = SMB_VFS_FGET_DOS_ATTRIBUTES(slq->mds_ctx->conn,
smb_fname->fsp,
&attr);
if (!NT_STATUS_IS_OK(status)) {
/* Ignore the error, likely no DOS attr xattr */
DBG_DEBUG("SMB_VFS_FGET_DOS_ATTRIBUTES [%s]: %s\n",
smb_fname_str_dbg(smb_fname),
nt_errstr(status));
}
unbecome_authenticated_pipe_user();
smb_fname->st = smb_fname->fsp->fsp_name->st;
sb = smb_fname->st;
/* Done with smb_fname now. */
TALLOC_FREE(smb_fname);
ino64 = SMB_VFS_FS_FILE_ID(slq->mds_ctx->conn, &sb);
if (slq->cnids) {

View File

@ -1,39 +0,0 @@
#!/bin/sh
# this tests immutable birthtime
if [ $# != 6 ]; then
cat <<EOF
Usage: $0 SERVER USERNAME PASSWORD LOCAL_PATH SMBCLIENT SHARE
EOF
exit 1
fi
SERVER="$1"
USERNAME="$2"
PASSWORD="$3"
LOCAL_PATH="$4"
SMBCLIENT="$5"
SHARE="$6"
SAMBATOOL="$BINDIR/samba-tool"
incdir=`dirname $0`/../../../testprogs/blackbox
. $incdir/subunit.sh
# Show that setting DOS attributes on a locally created file, therefore lacking
# a DOS xattr and an itime, doesn't set an itime
no_itime_on_local_file() {
fname="tmp.$$"
local_fname="$LOCAL_PATH/$fname"
touch $local_fname || return 1
$SMBCLIENT //$SERVER/$SHARE -U $USERNAME%$PASSWORD -c "setmode $fname +h" || return 1
dosinfo=$($SAMBATOOL ntacl getdosinfo $local_fname) || return 1
echo $dosinfo | grep -q "xattr_DosInfo4" || return 1
echo $dosinfo | grep -q "1: XATTR_DOSINFO_ATTRIB" || return 1
echo $dosinfo | grep -q "1: XATTR_DOSINFO_CREATE_TIME" || return 1
echo $dosinfo | grep -q "0: XATTR_DOSINFO_ITIME" || return 1
}
testit "no_itime_on_local_file" no_itime_on_local_file

View File

@ -1396,8 +1396,6 @@ for env in ["ad_member_idmap_rid:local", "maptoguest:local"]:
[os.path.join(samba3srcdir, "script/tests/test_guest_auth.sh"),
'$SERVER', smbclient3, smbcontrol, net, configuration])
plantestsuite("samba3.blackbox.itime", "ad_dc", [os.path.join(samba3srcdir, "script/tests/test_itime.sh"), '$SERVER', '$USERNAME', '$PASSWORD', '$LOCAL_PATH', smbclient3, 'xattr'])
plantestsuite("samba3.blackbox.smbclient-mget",
"fileserver",
[os.path.join(samba3srcdir, "script/tests/test_smbclient_mget.sh"),

View File

@ -302,47 +302,34 @@ NTSTATUS parse_dos_attribute_blob(struct smb_filename *smb_fname,
}
break;
case 4:
case 5:
{
struct xattr_DosInfo4 *info = &dosattrib.info.info4;
uint32_t info_valid_flags;
NTTIME info_create_time;
dosattr = info->attrib;
if (dosattrib.version == 4) {
info_valid_flags = dosattrib.info.info4.valid_flags;
info_create_time = dosattrib.info.info4.create_time;
dosattr = dosattrib.info.info4.attrib;
} else {
info_valid_flags = dosattrib.info.info5.valid_flags;
info_create_time = dosattrib.info.info5.create_time;
dosattr = dosattrib.info.info5.attrib;
}
if ((info->valid_flags & XATTR_DOSINFO_CREATE_TIME) &&
!null_nttime(info->create_time))
if ((info_valid_flags & XATTR_DOSINFO_CREATE_TIME) &&
!null_nttime(info_create_time))
{
struct timespec creat_time;
creat_time = nt_time_to_full_timespec(info->create_time);
creat_time = nt_time_to_full_timespec(info_create_time);
update_stat_ex_create_time(&smb_fname->st, creat_time);
DBG_DEBUG("file [%s] creation time [%s]\n",
smb_fname_str_dbg(smb_fname),
nt_time_string(talloc_tos(), info->create_time));
nt_time_string(talloc_tos(), info_create_time));
}
if (info->valid_flags & XATTR_DOSINFO_ITIME) {
struct timespec itime;
uint64_t file_id;
itime = nt_time_to_unix_timespec(info->itime);
if (smb_fname->st.st_ex_iflags &
ST_EX_IFLAG_CALCULATED_ITIME)
{
update_stat_ex_itime(&smb_fname->st, itime);
}
file_id = make_file_id_from_itime(&smb_fname->st);
if (smb_fname->st.st_ex_iflags &
ST_EX_IFLAG_CALCULATED_FILE_ID)
{
update_stat_ex_file_id(&smb_fname->st, file_id);
}
DBG_DEBUG("file [%s] itime [%s] fileid [%"PRIx64"]\n",
smb_fname_str_dbg(smb_fname),
nt_time_string(talloc_tos(), info->itime),
file_id);
}
break;
}
default:
@ -445,19 +432,13 @@ NTSTATUS set_ea_dos_attribute(connection_struct *conn,
ZERO_STRUCT(dosattrib);
ZERO_STRUCT(blob);
dosattrib.version = 4;
dosattrib.info.info4.valid_flags = XATTR_DOSINFO_ATTRIB |
dosattrib.version = 5;
dosattrib.info.info5.valid_flags = XATTR_DOSINFO_ATTRIB |
XATTR_DOSINFO_CREATE_TIME;
dosattrib.info.info4.attrib = dosmode;
dosattrib.info.info4.create_time = full_timespec_to_nt_time(
dosattrib.info.info5.attrib = dosmode;
dosattrib.info.info5.create_time = full_timespec_to_nt_time(
&smb_fname->st.st_ex_btime);
if (!(smb_fname->st.st_ex_iflags & ST_EX_IFLAG_CALCULATED_ITIME)) {
dosattrib.info.info4.valid_flags |= XATTR_DOSINFO_ITIME;
dosattrib.info.info4.itime = full_timespec_to_nt_time(
&smb_fname->st.st_ex_itime);
}
DEBUG(10,("set_ea_dos_attributes: set attribute 0x%x, btime = %s on file %s\n",
(unsigned int)dosmode,
time_to_asc(convert_timespec_to_time_t(smb_fname->st.st_ex_btime)),

View File

@ -4172,28 +4172,6 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn,
fsp->fsp_flags.initial_delete_on_close = true;
}
/*
* If we created a file and it's not a stream, this is the point where
* we set the itime (aka invented time) that get's stored in the DOS
* attribute xattr. The value is going to be either what the filesystem
* provided or a generated itime value.
*
* Either way, we turn the itime into a File-ID, unless the filesystem
* provided one (unlikely).
*/
if (info == FILE_WAS_CREATED && !is_named_stream(smb_fname)) {
create_clock_itime(&smb_fname->st);
if (lp_store_dos_attributes(SNUM(conn)) &&
smb_fname->st.st_ex_iflags & ST_EX_IFLAG_CALCULATED_FILE_ID)
{
uint64_t file_id;
file_id = make_file_id_from_itime(&smb_fname->st);
update_stat_ex_file_id(&smb_fname->st, file_id);
}
}
if (info != FILE_WAS_OPENED) {
/* Overwritten files should be initially set as archive */
if ((info == FILE_WAS_OVERWRITTEN && lp_map_archive(SNUM(conn))) ||
@ -4365,17 +4343,7 @@ static NTSTATUS mkdir_internal(connection_struct *conn,
return NT_STATUS_NOT_A_DIRECTORY;
}
create_clock_itime(&smb_dname->st);
if (lp_store_dos_attributes(SNUM(conn))) {
if (smb_dname->st.st_ex_iflags & ST_EX_IFLAG_CALCULATED_FILE_ID)
{
uint64_t file_id;
file_id = make_file_id_from_itime(&smb_dname->st);
update_stat_ex_file_id(&smb_dname->st, file_id);
}
if (!posix_open) {
file_set_dosmode(conn, smb_dname,
file_attributes | FILE_ATTRIBUTE_DIRECTORY,

View File

@ -1511,9 +1511,11 @@ static void smbd_smb2_create_after_exec(struct tevent_req *req)
if (state->qfid != NULL) {
uint8_t p[32];
SMB_STRUCT_STAT *base_sp = state->result->base_fsp ?
&state->result->base_fsp->fsp_name->st :
&state->result->fsp_name->st;
uint64_t file_id = SMB_VFS_FS_FILE_ID(
state->result->conn,
&state->result->fsp_name->st);
state->result->conn, base_sp);
DATA_BLOB blob = data_blob_const(p, sizeof(p));
ZERO_STRUCT(p);
@ -1523,7 +1525,7 @@ static void smbd_smb2_create_after_exec(struct tevent_req *req)
== inode, the second 8 bytes are the "volume id",
== dev. This will be updated in the SMB2 doc. */
SBVAL(p, 0, file_id);
SIVAL(p, 8, state->result->fsp_name->st.st_ex_dev);/* FileIndexHigh */
SIVAL(p, 8, base_sp->st_ex_dev);/* FileIndexHigh */
status = smb2_create_blob_add(state->out_context_blobs,
state->out_context_blobs,

View File

@ -1000,11 +1000,8 @@ static void fetch_dos_mode_done(struct tevent_req *subreq)
uint32_t dfs_dosmode;
uint32_t dosmode;
struct timespec btime_ts = {0};
bool need_file_id = false;
uint64_t file_id;
off_t dosmode_off;
off_t btime_off;
off_t file_id_off;
NTSTATUS status;
status = dos_mode_at_recv(subreq, &dosmode);
@ -1056,30 +1053,6 @@ static void fetch_dos_mode_done(struct tevent_req *subreq)
(char *)state->entry_marshall_buf + btime_off,
&btime_ts);
switch (state->info_level) {
case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
file_id_off = 96;
need_file_id = true;
break;
case SMB_FIND_ID_FULL_DIRECTORY_INFO:
file_id_off = 72;
need_file_id = true;
break;
default:
break;
}
if (need_file_id) {
/*
* File-ID might have been updated from calculated (based on
* inode) to storage based, fetch via DOS attributes in
* vfs_default.
*/
file_id = SMB_VFS_FS_FILE_ID(state->dir_fsp->conn,
&state->smb_fname->st);
SBVAL(state->entry_marshall_buf, file_id_off, file_id);
}
tevent_req_done(req);
return;
}

View File

@ -5146,6 +5146,7 @@ NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
time_t create_time, mtime, atime, c_time;
SMB_STRUCT_STAT *psbuf = NULL;
SMB_STRUCT_STAT *base_sp = NULL;
char *p;
char *base_name;
char *dos_fname;
@ -5183,6 +5184,14 @@ NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
mode = fdos_mode(fsp);
psbuf = &smb_fname->st;
if (fsp != NULL) {
base_sp = fsp->base_fsp ?
&fsp->base_fsp->fsp_name->st :
&fsp->fsp_name->st;
} else {
base_sp = &smb_fname->st;
}
nlink = psbuf->st_ex_nlink;
if (nlink && (mode&FILE_ATTRIBUTE_DIRECTORY)) {
@ -5292,7 +5301,7 @@ NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
I think this causes us to fail the IFSKIT
BasicFileInformationTest. -tpot */
file_id = SMB_VFS_FS_FILE_ID(conn, psbuf);
file_id = SMB_VFS_FS_FILE_ID(conn, base_sp);
*fixed_portion = 0;

View File

@ -3000,23 +3000,8 @@ static bool test_fileid_unique_object(
goto done;
}
smb2_util_close(tree, h1);
/*
* Samba created files on a "normal" share
* using itime should have the top bit of the fileid set.
*/
fileid_array[i] = finfo.all_info2.out.file_id;
if ((fileid_array[i] & 0x8000000000000000) == 0) {
torture_fail(tctx,
talloc_asprintf(tctx,
"test file %s fileid 0x%lx top "
"bit not set\n",
fname,
fileid_array[i]));
TALLOC_FREE(fname);
ret = false;
goto done;
}
fileid_array[i] = finfo.all_info2.out.file_id;
TALLOC_FREE(fname);
}