• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /***************************************************************************
2  *                                  _   _ ____  _
3  *  Project                     ___| | | |  _ \| |
4  *                             / __| | | | |_) | |
5  *                            | (__| |_| |  _ <| |___
6  *                             \___|\___/|_| \_\_____|
7  *
8  * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
9  *
10  * This software is licensed as described in the file COPYING, which
11  * you should have received as part of this distribution. The terms
12  * are also available at https://curl.se/docs/copyright.html.
13  *
14  * You may opt to use, copy, modify, merge, publish, distribute and/or sell
15  * copies of the Software, and permit persons to whom the Software is
16  * furnished to do so, under the terms of the COPYING file.
17  *
18  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19  * KIND, either express or implied.
20  *
21  * SPDX-License-Identifier: curl
22  *
23  ***************************************************************************/
24 #include "tool_setup.h"
25 
26 #include "tool_util.h"
27 
28 #include "curlx.h"
29 #include "memdebug.h" /* keep this as LAST include */
30 
31 #if defined(_WIN32)
32 
33 /* In case of bug fix this function has a counterpart in timeval.c */
tvnow(void)34 struct timeval tvnow(void)
35 {
36   struct timeval now;
37   if(tool_isVistaOrGreater) { /* QPC timer might have issues pre-Vista */
38     LARGE_INTEGER count;
39     QueryPerformanceCounter(&count);
40     now.tv_sec = (long)(count.QuadPart / tool_freq.QuadPart);
41     now.tv_usec = (long)((count.QuadPart % tool_freq.QuadPart) * 1000000 /
42                          tool_freq.QuadPart);
43   }
44   else {
45     /* Disable /analyze warning that GetTickCount64 is preferred  */
46 #if defined(_MSC_VER)
47 #pragma warning(push)
48 #pragma warning(disable:28159)
49 #endif
50     DWORD milliseconds = GetTickCount();
51 #if defined(_MSC_VER)
52 #pragma warning(pop)
53 #endif
54 
55     now.tv_sec = (long)(milliseconds / 1000);
56     now.tv_usec = (long)((milliseconds % 1000) * 1000);
57   }
58   return now;
59 }
60 
61 #elif defined(HAVE_CLOCK_GETTIME_MONOTONIC)
62 
tvnow(void)63 struct timeval tvnow(void)
64 {
65   /*
66   ** clock_gettime() is granted to be increased monotonically when the
67   ** monotonic clock is queried. Time starting point is unspecified, it
68   ** could be the system start-up time, the Epoch, or something else,
69   ** in any case the time starting point does not change once that the
70   ** system has started up.
71   */
72   struct timeval now;
73   struct timespec tsnow;
74   if(0 == clock_gettime(CLOCK_MONOTONIC, &tsnow)) {
75     now.tv_sec = tsnow.tv_sec;
76     now.tv_usec = (int)(tsnow.tv_nsec / 1000);
77   }
78   /*
79   ** Even when the configure process has truly detected monotonic clock
80   ** availability, it might happen that it is not actually available at
81   ** runtime. When this occurs simply fallback to other time source.
82   */
83 #ifdef HAVE_GETTIMEOFDAY
84   else
85     (void)gettimeofday(&now, NULL);
86 #else
87   else {
88     now.tv_sec = time(NULL);
89     now.tv_usec = 0;
90   }
91 #endif
92   return now;
93 }
94 
95 #elif defined(HAVE_GETTIMEOFDAY)
96 
tvnow(void)97 struct timeval tvnow(void)
98 {
99   /*
100   ** gettimeofday() is not granted to be increased monotonically, due to
101   ** clock drifting and external source time synchronization it can jump
102   ** forward or backward in time.
103   */
104   struct timeval now;
105   (void)gettimeofday(&now, NULL);
106   return now;
107 }
108 
109 #else
110 
tvnow(void)111 struct timeval tvnow(void)
112 {
113   /*
114   ** time() returns the value of time in seconds since the Epoch.
115   */
116   struct timeval now;
117   now.tv_sec = time(NULL);
118   now.tv_usec = 0;
119   return now;
120 }
121 
122 #endif
123 
124 #if defined(_WIN32)
125 
tvrealnow(void)126 struct timeval tvrealnow(void)
127 {
128   /* UNIX EPOCH (1970-01-01) in FILETIME (1601-01-01) as 64-bit value */
129   static const curl_uint64_t EPOCH = (curl_uint64_t)116444736000000000ULL;
130   SYSTEMTIME systime;
131   FILETIME ftime; /* 100ns since 1601-01-01, as double 32-bit value */
132   curl_uint64_t time; /* 100ns since 1601-01-01, as 64-bit value */
133   struct timeval now;
134 
135   GetSystemTime(&systime);
136   SystemTimeToFileTime(&systime, &ftime);
137   time = ((curl_uint64_t)ftime.dwLowDateTime);
138   time += ((curl_uint64_t)ftime.dwHighDateTime) << 32;
139 
140   now.tv_sec  = (long)((time - EPOCH) / 10000000L); /* unit is 100ns */
141   now.tv_usec = (long)(systime.wMilliseconds * 1000);
142   return now;
143 }
144 
145 #else
146 
tvrealnow(void)147 struct timeval tvrealnow(void)
148 {
149   struct timeval now;
150 #ifdef HAVE_GETTIMEOFDAY
151   (void)gettimeofday(&now, NULL);
152 #else
153   now.tv_sec = time(NULL);
154   now.tv_usec = 0;
155 #endif
156   return now;
157 }
158 
159 #endif
160 
161 /*
162  * Make sure that the first argument is the more recent time, as otherwise
163  * we will get a weird negative time-diff back...
164  *
165  * Returns: the time difference in number of milliseconds.
166  */
tvdiff(struct timeval newer,struct timeval older)167 long tvdiff(struct timeval newer, struct timeval older)
168 {
169   return (long)(newer.tv_sec-older.tv_sec)*1000+
170     (long)(newer.tv_usec-older.tv_usec)/1000;
171 }
172 
173 /* Case insensitive compare. Accept NULL pointers. */
struplocompare(const char * p1,const char * p2)174 int struplocompare(const char *p1, const char *p2)
175 {
176   if(!p1)
177     return p2 ? -1 : 0;
178   if(!p2)
179     return 1;
180   return CURL_STRICMP(p1, p2);
181 }
182 
183 /* Indirect version to use as qsort callback. */
struplocompare4sort(const void * p1,const void * p2)184 int struplocompare4sort(const void *p1, const void *p2)
185 {
186   return struplocompare(* (char * const *) p1, * (char * const *) p2);
187 }
188 
189 #ifdef USE_TOOL_FTRUNCATE
190 
191 #ifdef _WIN32_WCE
192 /* 64-bit lseek-like function unavailable */
193 #  undef _lseeki64
194 #  define _lseeki64(hnd,ofs,whence) lseek(hnd,ofs,whence)
195 #  undef _get_osfhandle
196 #  define _get_osfhandle(fd) (fd)
197 #endif
198 
199 /*
200  * Truncate a file handle at a 64-bit position 'where'.
201  */
202 
tool_ftruncate64(int fd,curl_off_t where)203 int tool_ftruncate64(int fd, curl_off_t where)
204 {
205   intptr_t handle = _get_osfhandle(fd);
206 
207   if(_lseeki64(fd, where, SEEK_SET) < 0)
208     return -1;
209 
210   if(!SetEndOfFile((HANDLE)handle))
211     return -1;
212 
213   return 0;
214 }
215 
216 #endif /* USE_TOOL_FTRUNCATE */
217 
218 #ifdef _WIN32
Curl_execpath(const char * filename,char ** pathp)219 FILE *Curl_execpath(const char *filename, char **pathp)
220 {
221   static char filebuffer[512];
222   unsigned long len;
223   /* Get the filename of our executable. GetModuleFileName is already declared
224    * via inclusions done in setup header file. We assume that we are using
225    * the ASCII version here.
226    */
227   len = GetModuleFileNameA(0, filebuffer, sizeof(filebuffer));
228   if(len > 0 && len < sizeof(filebuffer)) {
229     /* We got a valid filename - get the directory part */
230     char *lastdirchar = strrchr(filebuffer, DIR_CHAR[0]);
231     if(lastdirchar) {
232       size_t remaining;
233       *lastdirchar = 0;
234       /* If we have enough space, build the RC filename */
235       remaining = sizeof(filebuffer) - strlen(filebuffer);
236       if(strlen(filename) < remaining - 1) {
237         msnprintf(lastdirchar, remaining, "%s%s", DIR_CHAR, filename);
238         *pathp = filebuffer;
239         return fopen(filebuffer, FOPEN_READTEXT);
240       }
241     }
242   }
243 
244   return NULL;
245 }
246 #endif
247