1/*
2 * ntfs_time.h - NTFS time conversion functions for the NTFS kernel driver.
3 *
4 * Copyright (c) 2006-2008 Anton Altaparmakov.  All Rights Reserved.
5 * Portions Copyright (c) 2006-2008 Apple Inc.  All Rights Reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are met:
9 *
10 * 1. Redistributions of source code must retain the above copyright notice,
11 *    this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright notice,
13 *    this list of conditions and the following disclaimer in the documentation
14 *    and/or other materials provided with the distribution.
15 * 3. Neither the name of Apple Inc. ("Apple") nor the names of its
16 *    contributors may be used to endorse or promote products derived from this
17 *    software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
20 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
23 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
26 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 *
30 * ALTERNATIVELY, provided that this notice and licensing terms are retained in
31 * full, this file may be redistributed and/or modified under the terms of the
32 * GNU General Public License (GPL) Version 2, in which case the provisions of
33 * that version of the GPL will apply to you instead of the license terms
34 * above.  You can obtain a copy of the GPL Version 2 at
35 * http://developer.apple.com/opensource/licenses/gpl-2.txt.
36 */
37
38#ifndef _OSX_NTFS_TIME_H
39#define _OSX_NTFS_TIME_H
40
41#include <sys/time.h>
42
43#include "ntfs_endian.h"
44#include "ntfs_types.h"
45
46#define NTFS_TIME_OFFSET ((s64)(369 * 365 + 89) * 24 * 3600 * 10000000)
47
48/**
49 * utc2ntfs - convert OS X time to NTFS time
50 * @ts:		OS X UTC time to convert to NTFS (little endian) time
51 *
52 * Convert the OS X UTC time @ts to its corresponding NTFS time and return that
53 * in little endian format.
54 *
55 * OS X stores time in a struct timespec consisting of a time_t (long at
56 * present) tv_sec and a long tv_nsec where tv_sec is the number of 1-second
57 * intervals since 1st January 1970, 00:00:00 UTC and tv_nsec is the number of
58 * 1-nano-second intervals since the value of tv_sec.
59 *
60 * NTFS uses Microsoft's standard time format which is stored in a s64 and is
61 * measured as the number of 100-nano-second intervals since 1st January 1601,
62 * 00:00:00 UTC.
63 */
64static inline sle64 utc2ntfs(const struct timespec ts)
65{
66	/*
67	 * Convert the seconds to 100ns intervals, add the nano-seconds
68	 * converted to 100ns intervals, and then add the NTFS time offset.
69	 */
70	return cpu_to_sle64((s64)ts.tv_sec * 10000000 + ts.tv_nsec / 100 +
71			NTFS_TIME_OFFSET);
72}
73
74/**
75 * ntfs_utc_current_time - get the current time in OS X time
76 *
77 * Get the current time from the OS X kernel, round it down to the nearest
78 * 100-nano-second interval and return that in cpu format.
79 */
80static inline struct timespec ntfs_utc_current_time(void)
81{
82	struct timespec ts;
83
84	nanotime(&ts);
85	/* Round down to nearest 100-nano-second interval. */
86	ts.tv_nsec -= ts.tv_nsec % 100;
87	return ts;
88}
89
90/**
91 * ntfs_current_time - get the current time in little endian NTFS format
92 *
93 * Get the current time from the OS X kernel, convert it to its corresponding
94 * NTFS time and return that in little endian format.
95 */
96static inline sle64 ntfs_current_time(void)
97{
98	struct timespec ts;
99
100	nanotime(&ts);
101	return utc2ntfs(ts);
102}
103
104/**
105 * ntfs2utc - convert NTFS time to OS X time
106 * @time:	NTFS time (little endian) to convert to OS X UTC
107 *
108 * Convert the little endian NTFS time @time to its corresponding OS X UTC time
109 * and return that in cpu format.
110 *
111 * OS X stores time in a struct timespec consisting of a time_t (long at
112 * present) tv_sec and a long tv_nsec where tv_sec is the number of 1-second
113 * intervals since 1st January 1970, 00:00:00 UTC without including leap
114 * seconds and tv_nsec is the number of 1-nano-second intervals since the value
115 * of tv_sec.
116 *
117 * NTFS uses Microsoft's standard time format which is stored in a s64 and is
118 * measured as the number of 100 nano-second intervals since 1st January 1601,
119 * 00:00:00 UTC.
120 *
121 * FIXME: There does not appear to be an asm optimized function in xnu to do
122 * the division and return the remainder in one single step.  If there is or
123 * one gets added at some point the below division and remainder determination
124 * should be combined into a single step using it.
125 */
126static inline struct timespec ntfs2utc(const sle64 time)
127{
128	u64 t;
129	struct timespec ts;
130
131	/* Subtract the NTFS time offset. */
132	t = (u64)(sle64_to_cpu(time) - NTFS_TIME_OFFSET);
133	/*
134	 * Convert the time to 1-second intervals and the remainder to
135	 * 1-nano-second intervals.
136	 */
137	ts.tv_sec = t / 10000000;
138	ts.tv_nsec = (t % 10000000) * 100;
139	return ts;
140}
141
142#endif /* _OSX_NTFS_TIME_H */
143