162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-or-later */ 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * time.h - NTFS time conversion functions. Part of the Linux-NTFS project. 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (c) 2001-2005 Anton Altaparmakov 662306a36Sopenharmony_ci */ 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci#ifndef _LINUX_NTFS_TIME_H 962306a36Sopenharmony_ci#define _LINUX_NTFS_TIME_H 1062306a36Sopenharmony_ci 1162306a36Sopenharmony_ci#include <linux/time.h> /* For current_kernel_time(). */ 1262306a36Sopenharmony_ci#include <asm/div64.h> /* For do_div(). */ 1362306a36Sopenharmony_ci 1462306a36Sopenharmony_ci#include "endian.h" 1562306a36Sopenharmony_ci 1662306a36Sopenharmony_ci#define NTFS_TIME_OFFSET ((s64)(369 * 365 + 89) * 24 * 3600 * 10000000) 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_ci/** 1962306a36Sopenharmony_ci * utc2ntfs - convert Linux UTC time to NTFS time 2062306a36Sopenharmony_ci * @ts: Linux UTC time to convert to NTFS time 2162306a36Sopenharmony_ci * 2262306a36Sopenharmony_ci * Convert the Linux UTC time @ts to its corresponding NTFS time and return 2362306a36Sopenharmony_ci * that in little endian format. 2462306a36Sopenharmony_ci * 2562306a36Sopenharmony_ci * Linux stores time in a struct timespec64 consisting of a time64_t tv_sec 2662306a36Sopenharmony_ci * and a long tv_nsec where tv_sec is the number of 1-second intervals since 2762306a36Sopenharmony_ci * 1st January 1970, 00:00:00 UTC and tv_nsec is the number of 1-nano-second 2862306a36Sopenharmony_ci * intervals since the value of tv_sec. 2962306a36Sopenharmony_ci * 3062306a36Sopenharmony_ci * NTFS uses Microsoft's standard time format which is stored in a s64 and is 3162306a36Sopenharmony_ci * measured as the number of 100-nano-second intervals since 1st January 1601, 3262306a36Sopenharmony_ci * 00:00:00 UTC. 3362306a36Sopenharmony_ci */ 3462306a36Sopenharmony_cistatic inline sle64 utc2ntfs(const struct timespec64 ts) 3562306a36Sopenharmony_ci{ 3662306a36Sopenharmony_ci /* 3762306a36Sopenharmony_ci * Convert the seconds to 100ns intervals, add the nano-seconds 3862306a36Sopenharmony_ci * converted to 100ns intervals, and then add the NTFS time offset. 3962306a36Sopenharmony_ci */ 4062306a36Sopenharmony_ci return cpu_to_sle64((s64)ts.tv_sec * 10000000 + ts.tv_nsec / 100 + 4162306a36Sopenharmony_ci NTFS_TIME_OFFSET); 4262306a36Sopenharmony_ci} 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_ci/** 4562306a36Sopenharmony_ci * get_current_ntfs_time - get the current time in little endian NTFS format 4662306a36Sopenharmony_ci * 4762306a36Sopenharmony_ci * Get the current time from the Linux kernel, convert it to its corresponding 4862306a36Sopenharmony_ci * NTFS time and return that in little endian format. 4962306a36Sopenharmony_ci */ 5062306a36Sopenharmony_cistatic inline sle64 get_current_ntfs_time(void) 5162306a36Sopenharmony_ci{ 5262306a36Sopenharmony_ci struct timespec64 ts; 5362306a36Sopenharmony_ci 5462306a36Sopenharmony_ci ktime_get_coarse_real_ts64(&ts); 5562306a36Sopenharmony_ci return utc2ntfs(ts); 5662306a36Sopenharmony_ci} 5762306a36Sopenharmony_ci 5862306a36Sopenharmony_ci/** 5962306a36Sopenharmony_ci * ntfs2utc - convert NTFS time to Linux time 6062306a36Sopenharmony_ci * @time: NTFS time (little endian) to convert to Linux UTC 6162306a36Sopenharmony_ci * 6262306a36Sopenharmony_ci * Convert the little endian NTFS time @time to its corresponding Linux UTC 6362306a36Sopenharmony_ci * time and return that in cpu format. 6462306a36Sopenharmony_ci * 6562306a36Sopenharmony_ci * Linux stores time in a struct timespec64 consisting of a time64_t tv_sec 6662306a36Sopenharmony_ci * and a long tv_nsec where tv_sec is the number of 1-second intervals since 6762306a36Sopenharmony_ci * 1st January 1970, 00:00:00 UTC and tv_nsec is the number of 1-nano-second 6862306a36Sopenharmony_ci * intervals since the value of tv_sec. 6962306a36Sopenharmony_ci * 7062306a36Sopenharmony_ci * NTFS uses Microsoft's standard time format which is stored in a s64 and is 7162306a36Sopenharmony_ci * measured as the number of 100 nano-second intervals since 1st January 1601, 7262306a36Sopenharmony_ci * 00:00:00 UTC. 7362306a36Sopenharmony_ci */ 7462306a36Sopenharmony_cistatic inline struct timespec64 ntfs2utc(const sle64 time) 7562306a36Sopenharmony_ci{ 7662306a36Sopenharmony_ci struct timespec64 ts; 7762306a36Sopenharmony_ci 7862306a36Sopenharmony_ci /* Subtract the NTFS time offset. */ 7962306a36Sopenharmony_ci u64 t = (u64)(sle64_to_cpu(time) - NTFS_TIME_OFFSET); 8062306a36Sopenharmony_ci /* 8162306a36Sopenharmony_ci * Convert the time to 1-second intervals and the remainder to 8262306a36Sopenharmony_ci * 1-nano-second intervals. 8362306a36Sopenharmony_ci */ 8462306a36Sopenharmony_ci ts.tv_nsec = do_div(t, 10000000) * 100; 8562306a36Sopenharmony_ci ts.tv_sec = t; 8662306a36Sopenharmony_ci return ts; 8762306a36Sopenharmony_ci} 8862306a36Sopenharmony_ci 8962306a36Sopenharmony_ci#endif /* _LINUX_NTFS_TIME_H */ 90