1 // Copyright 2020 The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include <io.h>
16 
17 #include "aemu/base/msvc.h"
18 
19 #include <stdarg.h>
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <sysinfoapi.h>
24 
25 #define FILETIME_1970 116444736000000000ull
26 #define HECTONANOSEC_PER_SEC 10000000ull
27 
28 
mkstemp(char * t)29 int mkstemp(char* t) {
30     // TODO(joshuaduong): Support unicode (b/117322783)
31     int len = strlen(t) + 1;
32     errno_t err = _mktemp_s(t, len);
33 
34     if (err != 0) {
35         return -1;
36     }
37 
38     return _sopen(t, _O_RDWR | _O_CREAT | _O_EXCL | _O_BINARY, _SH_DENYRW,
39                   _S_IREAD | _S_IWRITE);
40 }
41 
42 // From https://msdn.microsoft.com/en-us/library/28d5ce15.aspx
asprintf(char ** buf,const char * format,...)43 int asprintf(char** buf, const char* format, ...) {
44     va_list args;
45     int len;
46 
47     if (buf == NULL) {
48         return -1;
49     }
50 
51     // retrieve the variable arguments
52     va_start(args, format);
53 
54     len = _vscprintf(format, args)  // _vscprintf doesn't count
55           + 1;                      // terminating '\0'
56 
57     if (len <= 0) {
58         return len;
59     }
60 
61     *buf = (char*)malloc(len * sizeof(char));
62 
63     vsprintf(*buf, format, args);  // C4996
64     // Note: vsprintf is deprecated; consider using vsprintf_s instead
65     return len;
66 }
67 
68 // From https://msdn.microsoft.com/en-us/library/28d5ce15.aspx
vasprintf(char ** buf,const char * format,va_list args)69 static int vasprintf(char** buf, const char* format, va_list args) {
70     int len;
71 
72     if (buf == NULL) {
73         return -1;
74     }
75 
76     len = _vscprintf(format, args)  // _vscprintf doesn't count
77           + 1;                      // terminating '\0'
78 
79     if (len <= 0) {
80         return len;
81     }
82 
83     *buf = (char*)malloc(len * sizeof(char));
84 
85     vsprintf(*buf, format, args);  // C4996
86     // Note: vsprintf is deprecated; consider using vsprintf_s instead
87     return len;
88 }
89 
90 // This is a poor resolution timer, but at least it
91 // is available on Win7 and older. System.cpp will install
92 // a better one.
93 static SystemTime getSystemTime = (SystemTime)GetSystemTimeAsFileTime;
94 
95 int getntptimeofday(struct timespec*, struct timezone*);
96 
getntptimeofday(struct timespec * tp,struct timezone * z)97 int getntptimeofday(struct timespec* tp, struct timezone* z) {
98     int res = 0;
99     union {
100         unsigned long long ns100; /*time since 1 Jan 1601 in 100ns units */
101         FILETIME ft;
102     } _now;
103     TIME_ZONE_INFORMATION TimeZoneInformation;
104     DWORD tzi;
105 
106     if (z != NULL) {
107         if ((tzi = GetTimeZoneInformation(&TimeZoneInformation)) !=
108             TIME_ZONE_ID_INVALID) {
109             z->tz_minuteswest = TimeZoneInformation.Bias;
110             if (tzi == TIME_ZONE_ID_DAYLIGHT)
111                 z->tz_dsttime = 1;
112             else
113                 z->tz_dsttime = 0;
114         } else {
115             z->tz_minuteswest = 0;
116             z->tz_dsttime = 0;
117         }
118     }
119 
120     if (tp != NULL) {
121         getSystemTime((FileTime*)&_now.ft); /* 100-nanoseconds since 1-1-1601 */
122         /* The actual accuracy on XP seems to be 125,000 nanoseconds = 125
123          * microseconds = 0.125 milliseconds */
124         _now.ns100 -= FILETIME_1970; /* 100 nano-seconds since 1-1-1970 */
125         tp->tv_sec =
126                 _now.ns100 / HECTONANOSEC_PER_SEC; /* seconds since 1-1-1970 */
127         tp->tv_nsec = (long)(_now.ns100 % HECTONANOSEC_PER_SEC) *
128                       100; /* nanoseconds */
129     }
130     return res;
131 }
132 
gettimeofday(struct timeval * p,struct timezone * z)133 int gettimeofday(struct timeval* p, struct timezone* z) {
134     struct timespec tp;
135 
136     if (getntptimeofday(&tp, z))
137         return -1;
138     p->tv_sec = tp.tv_sec;
139     p->tv_usec = (tp.tv_nsec / 1000);
140     return 0;
141 }
142