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:
parent
8ad0febd13
commit
643da37fd1
@ -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 {
|
||||
|
@ -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;
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
/*******************************************************************
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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 */
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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
|
@ -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"),
|
||||
|
@ -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)),
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user