xref: /curl/src/tool_util.c (revision 9fc4b2c7)
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 #if defined(HAVE_STRCASECMP) && defined(HAVE_STRINGS_H)
27 #include <strings.h>
28 #endif
29 
30 #include "tool_util.h"
31 
32 #include "memdebug.h" /* keep this as LAST include */
33 
34 #if defined(_WIN32)
35 
36 /* In case of bug fix this function has a counterpart in timeval.c */
tvnow(void)37 struct timeval tvnow(void)
38 {
39   struct timeval now;
40   if(tool_isVistaOrGreater) { /* QPC timer might have issues pre-Vista */
41     LARGE_INTEGER count;
42     QueryPerformanceCounter(&count);
43     now.tv_sec = (long)(count.QuadPart / tool_freq.QuadPart);
44     now.tv_usec = (long)((count.QuadPart % tool_freq.QuadPart) * 1000000 /
45                          tool_freq.QuadPart);
46   }
47   else {
48     /* Disable /analyze warning that GetTickCount64 is preferred  */
49 #if defined(_MSC_VER)
50 #pragma warning(push)
51 #pragma warning(disable:28159)
52 #endif
53     DWORD milliseconds = GetTickCount();
54 #if defined(_MSC_VER)
55 #pragma warning(pop)
56 #endif
57 
58     now.tv_sec = (long)(milliseconds / 1000);
59     now.tv_usec = (long)((milliseconds % 1000) * 1000);
60   }
61   return now;
62 }
63 
64 #elif defined(HAVE_CLOCK_GETTIME_MONOTONIC)
65 
tvnow(void)66 struct timeval tvnow(void)
67 {
68   /*
69   ** clock_gettime() is granted to be increased monotonically when the
70   ** monotonic clock is queried. Time starting point is unspecified, it
71   ** could be the system start-up time, the Epoch, or something else,
72   ** in any case the time starting point does not change once that the
73   ** system has started up.
74   */
75   struct timeval now;
76   struct timespec tsnow;
77   if(0 == clock_gettime(CLOCK_MONOTONIC, &tsnow)) {
78     now.tv_sec = tsnow.tv_sec;
79     now.tv_usec = (int)(tsnow.tv_nsec / 1000);
80   }
81   /*
82   ** Even when the configure process has truly detected monotonic clock
83   ** availability, it might happen that it is not actually available at
84   ** run-time. When this occurs simply fallback to other time source.
85   */
86 #ifdef HAVE_GETTIMEOFDAY
87   else
88     (void)gettimeofday(&now, NULL);
89 #else
90   else {
91     now.tv_sec = time(NULL);
92     now.tv_usec = 0;
93   }
94 #endif
95   return now;
96 }
97 
98 #elif defined(HAVE_GETTIMEOFDAY)
99 
tvnow(void)100 struct timeval tvnow(void)
101 {
102   /*
103   ** gettimeofday() is not granted to be increased monotonically, due to
104   ** clock drifting and external source time synchronization it can jump
105   ** forward or backward in time.
106   */
107   struct timeval now;
108   (void)gettimeofday(&now, NULL);
109   return now;
110 }
111 
112 #else
113 
tvnow(void)114 struct timeval tvnow(void)
115 {
116   /*
117   ** time() returns the value of time in seconds since the Epoch.
118   */
119   struct timeval now;
120   now.tv_sec = time(NULL);
121   now.tv_usec = 0;
122   return now;
123 }
124 
125 #endif
126 
127 /*
128  * Make sure that the first argument is the more recent time, as otherwise
129  * we'll get a weird negative time-diff back...
130  *
131  * Returns: the time difference in number of milliseconds.
132  */
tvdiff(struct timeval newer,struct timeval older)133 long tvdiff(struct timeval newer, struct timeval older)
134 {
135   return (long)(newer.tv_sec-older.tv_sec)*1000+
136     (long)(newer.tv_usec-older.tv_usec)/1000;
137 }
138 
139 /* Case insensitive compare. Accept NULL pointers. */
struplocompare(const char * p1,const char * p2)140 int struplocompare(const char *p1, const char *p2)
141 {
142   if(!p1)
143     return p2? -1: 0;
144   if(!p2)
145     return 1;
146 #ifdef HAVE_STRCASECMP
147   return strcasecmp(p1, p2);
148 #elif defined(HAVE_STRCMPI)
149   return strcmpi(p1, p2);
150 #elif defined(HAVE_STRICMP)
151   return stricmp(p1, p2);
152 #else
153   return strcmp(p1, p2);
154 #endif
155 }
156 
157 /* Indirect version to use as qsort callback. */
struplocompare4sort(const void * p1,const void * p2)158 int struplocompare4sort(const void *p1, const void *p2)
159 {
160   return struplocompare(* (char * const *) p1, * (char * const *) p2);
161 }
162 
163 #ifdef USE_TOOL_FTRUNCATE
164 
165 #ifdef _WIN32_WCE
166 /* 64-bit lseek-like function unavailable */
167 #  undef _lseeki64
168 #  define _lseeki64(hnd,ofs,whence) lseek(hnd,ofs,whence)
169 #  undef _get_osfhandle
170 #  define _get_osfhandle(fd) (fd)
171 #endif
172 
173 /*
174  * Truncate a file handle at a 64-bit position 'where'.
175  */
176 
tool_ftruncate64(int fd,curl_off_t where)177 int tool_ftruncate64(int fd, curl_off_t where)
178 {
179   intptr_t handle = _get_osfhandle(fd);
180 
181   if(_lseeki64(fd, where, SEEK_SET) < 0)
182     return -1;
183 
184   if(!SetEndOfFile((HANDLE)handle))
185     return -1;
186 
187   return 0;
188 }
189 
190 #endif /* USE_TOOL_FTRUNCATE */
191