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,
dst->st_ex_iflags |= ST_EX_IFLAG_CALCULATED_FILE_ID;
}
+/*******************************************************************
+ Create a clock-derived itime (imaginary) 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. */
+ clock_gettime_mono(&itime);
+
+ /* 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);
+}
+
/*******************************************************************
A stat() wrapper.
********************************************************************/
* 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 copy of the creation date.
+ * 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)) {
- smb_fname->st.st_ex_iflags &= ~ST_EX_IFLAG_CALCULATED_ITIME;
+ 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)
return NT_STATUS_NOT_A_DIRECTORY;
}
- smb_dname->st.st_ex_iflags &= ~ST_EX_IFLAG_CALCULATED_ITIME;
+ 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)