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