^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /* SPDX-License-Identifier: GPL-2.0-or-later */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * time.h - NTFS time conversion functions. Part of the Linux-NTFS project.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (c) 2001-2005 Anton Altaparmakov
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #ifndef _LINUX_NTFS_TIME_H
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #define _LINUX_NTFS_TIME_H
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/time.h> /* For current_kernel_time(). */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <asm/div64.h> /* For do_div(). */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include "endian.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #define NTFS_TIME_OFFSET ((s64)(369 * 365 + 89) * 24 * 3600 * 10000000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) * utc2ntfs - convert Linux UTC time to NTFS time
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) * @ts: Linux UTC time to convert to NTFS time
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) * Convert the Linux UTC time @ts to its corresponding NTFS time and return
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) * that in little endian format.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) * Linux stores time in a struct timespec64 consisting of a time64_t tv_sec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) * and a long tv_nsec where tv_sec is the number of 1-second intervals since
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) * 1st January 1970, 00:00:00 UTC and tv_nsec is the number of 1-nano-second
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) * intervals since the value of tv_sec.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) * NTFS uses Microsoft's standard time format which is stored in a s64 and is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) * measured as the number of 100-nano-second intervals since 1st January 1601,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) * 00:00:00 UTC.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) static inline sle64 utc2ntfs(const struct timespec64 ts)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) * Convert the seconds to 100ns intervals, add the nano-seconds
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) * converted to 100ns intervals, and then add the NTFS time offset.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) return cpu_to_sle64((s64)ts.tv_sec * 10000000 + ts.tv_nsec / 100 +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) NTFS_TIME_OFFSET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) * get_current_ntfs_time - get the current time in little endian NTFS format
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) * Get the current time from the Linux kernel, convert it to its corresponding
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) * NTFS time and return that in little endian format.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) static inline sle64 get_current_ntfs_time(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) struct timespec64 ts;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) ktime_get_coarse_real_ts64(&ts);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) return utc2ntfs(ts);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) * ntfs2utc - convert NTFS time to Linux time
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) * @time: NTFS time (little endian) to convert to Linux UTC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) * Convert the little endian NTFS time @time to its corresponding Linux UTC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) * time and return that in cpu format.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) * Linux stores time in a struct timespec64 consisting of a time64_t tv_sec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) * and a long tv_nsec where tv_sec is the number of 1-second intervals since
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) * 1st January 1970, 00:00:00 UTC and tv_nsec is the number of 1-nano-second
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) * intervals since the value of tv_sec.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) * NTFS uses Microsoft's standard time format which is stored in a s64 and is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) * measured as the number of 100 nano-second intervals since 1st January 1601,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) * 00:00:00 UTC.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) static inline struct timespec64 ntfs2utc(const sle64 time)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) struct timespec64 ts;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) /* Subtract the NTFS time offset. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) u64 t = (u64)(sle64_to_cpu(time) - NTFS_TIME_OFFSET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) * Convert the time to 1-second intervals and the remainder to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) * 1-nano-second intervals.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) ts.tv_nsec = do_div(t, 10000000) * 100;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) ts.tv_sec = t;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) return ts;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) #endif /* _LINUX_NTFS_TIME_H */