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 {
/* 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.
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;
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;
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,
* 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
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;
-}
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
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;
}
/****************************************************************************
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)
{
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,
#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);
}
/*******************************************************************
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[] = {
#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);
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,
{
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;
}
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 */
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 };
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,
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;
}
{
struct smb_filename *smb_fname = NULL;
struct stat_ex sb;
- uint32_t attr;
uint64_t ino64;
int result;
NTSTATUS status;
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) {
+++ /dev/null
-#!/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
[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"),
}
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:
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)),
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))) ||
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,
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);
== 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,
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);
(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;
}
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;
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)) {
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;
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);
}