1 /* u_misc.c
2 *
3 * Copyright (c) 1996-2005 Mike Gleason, NcFTP Software.
4 * All rights reserved.
5 *
6 */
7
8 #include "syshdrs.h"
9 #ifdef PRAGMA_HDRSTOP
10 # pragma hdrstop
11 #endif
12
13 static int wsaInit = 0;
14 #if defined(WIN32) || defined(_WINDOWS)
15 WSADATA wsaData;
16 #endif
17
18
19
20 void
InitWinsock(void)21 InitWinsock(void)
22 {
23 #if (defined(WIN32) || defined(_WINDOWS)) && !defined(__CYGWIN__)
24 if (WSAStartup(MAKEWORD(2, 0), &wsaData) != 0) {
25 # ifdef _CONSOLE
26 fprintf(stderr, "could not initialize winsock\n");
27 # endif
28 exit(1);
29 }
30 #endif
31 wsaInit++;
32 } /* InitWinsock */
33
34
35
36 void
DisposeWinsock(void)37 DisposeWinsock(void)
38 {
39 #if (defined(WIN32) || defined(_WINDOWS)) && !defined(__CYGWIN__)
40 if (wsaInit > 0) { WSACleanup(); wsaInit--; }
41 #else
42 wsaInit--;
43 #endif
44 } /* DisposeWinsock */
45
46
47
48
49 #if (defined(WIN32) || defined(_WINDOWS)) && !defined(__CYGWIN__)
50
51
gettimeofday(struct timeval * const tp,void * junk)52 int gettimeofday(struct timeval *const tp, void *junk)
53 {
54 #if (_WIN32_WINNT < 0x0500)
55 /* Older systems don't have all the necessary time functions. */
56
57 SYSTEMTIME systemTime;
58
59 if (tp == NULL)
60 return (-1);
61
62 GetSystemTime(&systemTime);
63
64 /* Create an arbitrary second counter;
65 * Note that this particular one creates
66 * a problem at the end of the month.
67 */
68 tp->tv_sec =
69 systemTime.wSecond +
70 systemTime.wMinute * 60 +
71 systemTime.wHour * 3600 +
72 systemTime.wDay * 86400;
73
74 tp->tv_usec = systemTime.wMilliseconds * 1000;
75
76 return 0;
77 #else /* Windows 2000 or better */
78 FILETIME systemTime, unixEpochFileTime;
79 ULARGE_INTEGER sysTimeAsFileTime;
80 SYSTEMTIME unixEpochSysTime;
81 static int initialized = 0;
82 static unsigned __int64 unixEpochQuad = 0;
83 unsigned __int64 now_time64_t;
84 time_t now_time_t;
85
86 if (tp == NULL)
87 return (-1);
88
89 tp->tv_sec = 0;
90 tp->tv_usec = 0;
91
92 GetSystemTimeAsFileTime(&systemTime);
93 sysTimeAsFileTime.QuadPart = 0;
94 sysTimeAsFileTime.LowPart = systemTime.dwLowDateTime;
95 sysTimeAsFileTime.HighPart = systemTime.dwHighDateTime;
96
97 if (initialized == 0) {
98 memset(&unixEpochSysTime, 0, sizeof(unixEpochSysTime));
99 memset(&unixEpochFileTime, 0, sizeof(unixEpochFileTime));
100 unixEpochSysTime.wYear = 1970;
101 unixEpochSysTime.wMonth = 1;
102 unixEpochSysTime.wDay = 1;
103 if (! SystemTimeToFileTime(&unixEpochSysTime, &unixEpochFileTime))
104 return (-1);
105 unixEpochQuad = (unsigned __int64) unixEpochFileTime.dwLowDateTime + ((unsigned __int64) unixEpochFileTime.dwHighDateTime << 32);
106 if (sysTimeAsFileTime.QuadPart < unixEpochQuad)
107 return (-1);
108 initialized = 1;
109 }
110
111 /* Compute number of 100-ns (0.1 us) intervals since Jan 1, 1970. */
112 now_time64_t = sysTimeAsFileTime.QuadPart - unixEpochQuad;
113 tp->tv_usec = (unsigned long) ((now_time64_t / (unsigned __int64) 10) % (unsigned __int64) 1000000);
114 now_time64_t /= 10000000;
115 now_time_t = (time_t) (now_time64_t & 0xFFFFFFFF);
116 tp->tv_sec = (long) now_time_t;
117
118 return 0;
119 #endif
120 } /* gettimeofday */
121
122
123
124
WinSleep(unsigned int seconds)125 void WinSleep(unsigned int seconds)
126 {
127 DWORD now, deadline;
128 DWORD milliseconds = seconds * 1000;
129
130 if (milliseconds > 0) {
131 now = GetTickCount();
132 deadline = now + milliseconds;
133 if (now < deadline) {
134 /* Typical case */
135 do {
136 milliseconds = deadline - now;
137 Sleep(milliseconds);
138 now = GetTickCount();
139 } while (now < deadline);
140 } else {
141 /* Overflow case */
142 deadline = now - 1;
143 milliseconds -= (0xFFFFFFFF - now);
144 do {
145 Sleep(0xFFFFFFFF - now);
146 now = GetTickCount();
147 } while (now > deadline);
148 /* Counter has now wrapped around */
149 deadline = now + milliseconds;
150 do {
151 milliseconds = deadline - now;
152 Sleep(milliseconds);
153 now = GetTickCount();
154 } while (now < deadline);
155 }
156 }
157 } /* WinSleep */
158 #endif
159
160
161
162 #if defined(WIN32) || defined(_WINDOWS) || defined(__CYGWIN__)
163 char *
StrFindLocalPathDelim(const char * src)164 StrFindLocalPathDelim(const char *src) /* TODO: optimize */
165 {
166 const char *first;
167 int c;
168
169 first = NULL;
170 for (;;) {
171 c = *src++;
172 if (c == '\0')
173 break;
174 if (IsLocalPathDelim(c)) {
175 first = src - 1;
176 break;
177 }
178 }
179
180 return ((char *) first);
181 } /* StrFindLocalPathDelim */
182
183
184
185 char *
StrRFindLocalPathDelim(const char * src)186 StrRFindLocalPathDelim(const char *src) /* TODO: optimize */
187 {
188 const char *last;
189 int c;
190
191 last = NULL;
192 for (;;) {
193 c = *src++;
194 if (c == '\0')
195 break;
196 if (IsLocalPathDelim(c))
197 last = src - 1;
198 }
199
200 return ((char *) last);
201 } /* StrRFindLocalPathDelim */
202
203
204
205
206 void
StrRemoveTrailingLocalPathDelim(char * dst)207 StrRemoveTrailingLocalPathDelim(char *dst)
208 {
209 char *cp;
210
211 cp = StrRFindLocalPathDelim(dst);
212 if ((cp == NULL) || (cp[1] != '\0'))
213 return;
214
215 /* Note: Do not destroy a path of "/" */
216 while ((cp > dst) && (IsLocalPathDelim(*cp)))
217 *cp-- = '\0';
218 } /* StrRemoveTrailingLocalPathDelim */
219
220
221
222 void
TVFSPathToLocalPath(char * dst)223 TVFSPathToLocalPath(char *dst)
224 {
225 int c;
226
227 /* Note: Technically we don't need to do this,
228 * since Win32 accepts a / as equivalent to a \
229 * in a pathname.
230 */
231 if (dst != NULL) {
232 for (;;) {
233 c = *dst++;
234 if (c == '\0')
235 break;
236 if (c == '/')
237 dst[-1] = LOCAL_PATH_DELIM;
238 }
239 }
240 } /* TVFSPathToLocalPath */
241
242
243
244 void
LocalPathToTVFSPath(char * dst)245 LocalPathToTVFSPath(char *dst)
246 {
247 int c;
248
249 if (dst != NULL) {
250 for (;;) {
251 c = *dst++;
252 if (c == '\0')
253 break;
254 if (c == LOCAL_PATH_DELIM)
255 dst[-1] = '/';
256 }
257 }
258 } /* LocalPathToTVFSPath */
259 #endif
260
261
262
263
264 int
PathBuild(char * const dst,const size_t dsize,size_t * const dResultingLength,int dirSep,const char * const parentDir,const char * const fileName)265 PathBuild(char *const dst, const size_t dsize, size_t *const dResultingLength, int dirSep, const char *const parentDir, const char *const fileName)
266 {
267 char *dEnd = NULL;
268 char dirSepStr[4];
269 size_t nUsed;
270
271 #ifdef EINVAL
272 errno = 0;
273 #endif
274
275 if (dsize < 4) {
276 #ifdef EINVAL
277 errno = EINVAL;
278 #endif
279 return (-3);
280 }
281 if (dResultingLength != NULL)
282 *dResultingLength = 0;
283 memset(dst, 0, dsize);
284
285 if ((parentDir == NULL) || (parentDir[0] == '\0') || ((parentDir[0] == '.') && (parentDir[1] == '\0'))) {
286 dEnd = Strnpcpy(dst, ((fileName == NULL) || (fileName[0] == '\0')) ? "." : fileName, dsize);
287 } else if ((fileName == NULL) || (fileName[0] == '\0')) {
288 dEnd = Strnpcpy(dst, parentDir, dsize);
289 } else {
290 dirSepStr[0] = (char) dirSep;
291 dirSepStr[1] = '\0';
292 dEnd = Strnpcpy(dst, parentDir, dsize);
293 nUsed = (size_t) (dEnd - dst);
294 if (nUsed >= (dsize - 3)) {
295 #ifdef ENAMETOOLONG
296 errno = ENAMETOOLONG;
297 #elif defined(ERANGE)
298 errno = ERANGE;
299 #endif
300 return (-1);
301 }
302 if (strcmp(dst, dirSepStr) != 0) {
303 /* Append the separator, unless the file is in the root directory. */
304 if (dEnd != NULL) dEnd = Strnpcpy(dEnd, dirSepStr, dsize - nUsed);
305 }
306 if (nUsed >= (dsize - 2)) {
307 #ifdef ENAMETOOLONG
308 errno = ENAMETOOLONG;
309 #elif defined(ERANGE)
310 errno = ERANGE;
311 #endif
312 return (-1);
313 }
314 if (dEnd != NULL) dEnd = Strnpcpy(dEnd, fileName, dsize - nUsed);
315 }
316
317 if (dEnd == NULL) {
318 #ifdef EINVAL
319 errno = EINVAL;
320 #endif
321 return (-2);
322 }
323
324 if (dResultingLength != NULL)
325 *dResultingLength = (size_t) (dEnd - dst);
326
327 if (dst[dsize - 2] != '\0') {
328 #ifdef ENAMETOOLONG
329 errno = ENAMETOOLONG;
330 #elif defined(ERANGE)
331 errno = ERANGE;
332 #endif
333 return (-1); /* Truncation likely occurred */
334 }
335 return ((int) (dEnd - dst));
336 } /* PathBuild */
337
338
339
340
341 #if (defined(WIN32) || defined(_WINDOWS)) && !defined(__CYGWIN__)
342 int
WinFStat64(const int h0,struct WinStat64 * const stp)343 WinFStat64(const int h0, struct WinStat64 *const stp)
344 {
345 HANDLE h;
346 __int64 fSize;
347 DWORD fSize1, fSize2;
348 struct _stat st32;
349 DWORD winErr;
350
351 h = (HANDLE) _get_osfhandle(h0);
352 if (h == INVALID_HANDLE_VALUE)
353 return (-1);
354
355 memset(stp, 0, sizeof(struct WinStat64));
356 if (_fstat(h0, &st32) < 0)
357 return (-1);
358 stp->st_atime = st32.st_atime;
359 stp->st_ctime = st32.st_ctime;
360 stp->st_dev = st32.st_dev;
361 stp->st_gid = st32.st_gid;
362 stp->st_ino = st32.st_ino;
363 stp->st_mode = st32.st_mode;
364 stp->st_mtime = st32.st_mtime;
365 stp->st_nlink = st32.st_nlink;
366 stp->st_rdev = st32.st_rdev;
367 stp->st_uid = st32.st_uid;
368
369 if (S_ISREG(stp->st_mode)) {
370 fSize = (__int64)0;
371 fSize1 = GetFileSize(h, &fSize2);
372 if ((fSize1 == 0xFFFFFFFF) && ((winErr = GetLastError()) != NO_ERROR))
373 goto return_err;
374
375 fSize = ((__int64) fSize2 << 32) | (__int64) fSize1;
376 stp->st_size = fSize;
377 }
378 return (0);
379
380 return_err:
381 stp->st_size = (__int32) st32.st_size;
382 if ((winErr = GetLastError()) == ERROR_SHARING_VIOLATION) {
383 errno = EBUSY;
384 } else if ((winErr == ERROR_PATH_NOT_FOUND) || (winErr == ERROR_FILE_NOT_FOUND)) {
385 errno = ENOENT;
386 } else if (winErr == ERROR_INVALID_PARAMETER) {
387 errno = EINVAL;
388 } else {
389 errno = 100000 + winErr;
390 }
391 return (-1);
392 } /* WinFStat64 */
393
394
395
396
397 int
WinStat64(const char * const path,struct WinStat64 * const stp)398 WinStat64(const char *const path, struct WinStat64 *const stp)
399 {
400 HANDLE h;
401 __int64 fSize;
402 DWORD fSize1, fSize2;
403 struct _stat st32;
404 DWORD winErr;
405
406 memset(stp, 0, sizeof(struct WinStat64));
407 if (_stat(path, &st32) < 0)
408 return (-1);
409 stp->st_atime = st32.st_atime;
410 stp->st_ctime = st32.st_ctime;
411 stp->st_dev = st32.st_dev;
412 stp->st_gid = st32.st_gid;
413 stp->st_ino = st32.st_ino;
414 stp->st_mode = st32.st_mode;
415 stp->st_mtime = st32.st_mtime;
416 stp->st_nlink = st32.st_nlink;
417 stp->st_rdev = st32.st_rdev;
418 stp->st_uid = st32.st_uid;
419
420 if (S_ISREG(stp->st_mode)) {
421 h = CreateFile(path,
422 0, /* Not GENERIC_READ; use 0 for "query attributes only" mode */
423 0,
424 NULL,
425 OPEN_EXISTING, /* fails if it doesn't exist */
426 0,
427 NULL
428 );
429
430 if (h == INVALID_HANDLE_VALUE)
431 goto return_err;
432
433 fSize = (__int64)0;
434 fSize1 = GetFileSize(h, &fSize2);
435 if ((fSize1 == 0xFFFFFFFF) && ((winErr = GetLastError()) != NO_ERROR))
436 goto return_err;
437
438 fSize = ((__int64) fSize2 << 32) | (__int64) fSize1;
439 stp->st_size = fSize;
440 CloseHandle(h);
441 }
442 return (0);
443
444 return_err:
445 stp->st_size = (__int32) st32.st_size;
446 if ((winErr = GetLastError()) == ERROR_SHARING_VIOLATION) {
447 errno = EBUSY;
448 } else if ((winErr == ERROR_PATH_NOT_FOUND) || (winErr == ERROR_FILE_NOT_FOUND)) {
449 errno = ENOENT;
450 } else if (winErr == ERROR_INVALID_PARAMETER) {
451 errno = EINVAL;
452 } else {
453 errno = 100000 + winErr;
454 }
455
456 if (h != INVALID_HANDLE_VALUE)
457 CloseHandle(h);
458 return (-1);
459 } /* WinStat64 */
460
461 #endif
462