2 // compat.cpp -- compatibilty layer to make bacula-fd run
3 // natively under windows
5 // Copyright transferred from Raider Solutions, Inc to
6 // Kern Sibbald and John Walker by express permission.
8 // Copyright (C) 2004-2005 Kern Sibbald
10 // This program is free software; you can redistribute it and/or
11 // modify it under the terms of the GNU General Public License
12 // version 2 as amended with additional clauses defined in the
13 // file LICENSE in the main source directory.
15 // This program is distributed in the hope that it will be useful,
16 // but WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 // the file LICENSE for additional details.
20 // Author : Christopher S. Hull
21 // Created On : Sat Jan 31 15:55:00 2004
25 #define b_errno_win32 (1<<29)
29 #include "../../lib/winapi.h"
32 /* to allow the usage of the original version in this file here */
36 #define USE_WIN32_COMPAT_IO 1
37 #define USE_WIN32_32KPATHCONVERSION 1
39 extern void d_msg(const char *file, int line, int level, const char *fmt,...);
40 extern DWORD g_platform_id;
41 extern int enable_vss;
43 // from MicroSoft SDK (KES) is the diff between Jan 1 1601 and Jan 1 1970
45 #define WIN32_FILETIME_ADJUST 0x19DB1DED53E8000ULL //Not sure it works
47 #define WIN32_FILETIME_ADJUST 0x19DB1DED53E8000I64
50 #define WIN32_FILETIME_SCALE 10000000 // 100ns/second
52 void conv_unix_to_win32_path(const char *name, char *win32_name, DWORD dwSize)
54 const char *fname = name;
55 char *tname = win32_name;
57 /* Check for Unix separator and convert to Win32 */
58 if (name[0] == '/' && name[1] == '/') { /* double slash? */
59 name++; /* yes, skip first one */
62 *win32_name++ = '\\'; /* convert char */
63 /* If Win32 separated that is "quoted", remove quote */
64 } else if (*name == '\\' && name[1] == '\\') {
66 name++; /* skip first \ */
68 *win32_name++ = *name; /* copy character */
72 /* Strip any trailing slash, if we stored something */
73 /* but leave "c:\" with backslash (root directory case */
74 if (*fname != 0 && win32_name[-1] == '\\' && strlen (fname) != 3) {
81 /* here we convert to VSS specific file name which
82 can get longer because VSS will make something like
83 \\\\?\\GLOBALROOT\\Device\\HarddiskVolumeShadowCopy1\\bacula\\uninstall.exe
84 from c:\bacula\uninstall.exe
86 if (g_pVSSClient && enable_vss && g_pVSSClient->IsInitialized()) {
87 POOLMEM *pszBuf = get_pool_memory (PM_FNAME);
88 pszBuf = check_pool_memory_size(pszBuf, dwSize);
89 bstrncpy(pszBuf, tname, strlen(tname)+1);
90 g_pVSSClient->GetShadowPath(pszBuf, tname, dwSize);
91 free_pool_memory(pszBuf);
97 make_wchar_win32_path(POOLMEM* pszUCSPath, BOOL* pBIsRawPath /*= NULL*/)
99 /* created 02/27/2006 Thorsten Engel
101 This function expects an UCS-encoded standard WCHAR in pszUCSPath and
102 will complete the input path to an absolue path of the form \\?\c:\path\file
104 With this trick, it is possible to have 32K characters long paths.
106 Optionally one can use pBIsRawPath to determine id pszUCSPath contains a path
107 to a raw windows partition */
110 *pBIsRawPath = FALSE;
112 if (!p_GetCurrentDirectoryW)
115 WCHAR* name = (WCHAR*) pszUCSPath;
117 /* if it has already the desired form, exit without changes */
118 if (wcslen(name) > 3 && wcsncmp (name, L"\\\\?\\", 4) == 0)
121 POOLMEM* pwszBuf = get_pool_memory (PM_FNAME);
122 POOLMEM* pwszCurDirBuf = get_pool_memory (PM_FNAME);
123 DWORD dwCurDirPathSize = 0;
125 /* get buffer with enough size (name+max 6. wchars+1 null terminator */
126 DWORD dwBufCharsNeeded = (wcslen(name)+7);
127 pwszBuf = check_pool_memory_size(pwszBuf, dwBufCharsNeeded*sizeof(WCHAR));
129 /* add \\?\ to support 32K long filepaths
130 it is important to make absolute paths, so we add drive and
131 current path if necessary */
133 BOOL bAddDrive = TRUE;
134 BOOL bAddCurrentPath = TRUE;
135 BOOL bAddPrefix = TRUE;
137 /* does path begin with drive? if yes, it is absolute */
138 if (wcslen(name) >= 3 && (iswalpha (*name) && *(name+1) == ':'
139 && (*(name+2) == '\\' || *(name+2) == '/'))) {
141 bAddCurrentPath = FALSE;
144 /* is path absolute? */
145 if (*name == '/' || *name == '\\')
146 bAddCurrentPath = FALSE;
148 /* is path relative to itself?, if yes, skip ./ */
149 if (wcslen(name) > 2 && ((wcsncmp (name, L"./", 2) == 0) || (wcsncmp (name, L".\\", 2) == 0))) {
153 /* is path of form '//./'? */
154 if (wcslen(name) > 3 && ((wcsncmp (name, L"//./", 4) == 0) || (wcsncmp (name, L"\\\\.\\", 4) == 0))) {
156 bAddCurrentPath = FALSE;
162 int nParseOffset = 0;
164 /* add 4 bytes header */
167 wcscpy ((WCHAR*) pwszBuf,L"\\\\?\\");
170 /* get current path if needed */
171 if (bAddDrive || bAddCurrentPath) {
172 dwCurDirPathSize = p_GetCurrentDirectoryW(0, NULL);
173 if (dwCurDirPathSize > 0) {
174 /* get directory into own buffer as it may either return c:\... or \\?\C:\.... */
175 pwszCurDirBuf = check_pool_memory_size(pwszCurDirBuf, (dwCurDirPathSize+1)*sizeof(WCHAR));
176 p_GetCurrentDirectoryW(dwCurDirPathSize,(WCHAR*)pwszCurDirBuf);
180 /* we have no info for doing so */
182 bAddCurrentPath = FALSE;
187 /* add drive if needed */
188 if (bAddDrive && !bAddCurrentPath) {
191 if (dwCurDirPathSize > 3 && wcsncmp ((LPCWSTR)pwszCurDirBuf, L"\\\\?\\", 4) == 0)
192 /* copy drive character */
193 wcsncpy ((WCHAR*) szDrive, (LPCWSTR)pwszCurDirBuf+4,2);
195 /* copy drive character */
196 wcsncpy ((WCHAR*) szDrive, (LPCWSTR)pwszCurDirBuf,2);
200 wcscat ((WCHAR*) pwszBuf, szDrive);
204 /* add path if needed */
205 if (bAddCurrentPath) {
206 /* the 1 add. character is for the eventually added backslash */
207 dwBufCharsNeeded += dwCurDirPathSize+1;
208 pwszBuf = check_pool_memory_size(pwszBuf, dwBufCharsNeeded*sizeof(WCHAR));
209 /* get directory into own buffer as it may either return c:\... or \\?\C:\.... */
211 if (dwCurDirPathSize > 3 && wcsncmp ((LPCWSTR)pwszCurDirBuf, L"\\\\?\\", 4) == 0)
212 /* copy complete string */
213 wcscpy ((WCHAR*) pwszBuf, (LPCWSTR)pwszCurDirBuf);
216 wcscat ((WCHAR*) pwszBuf, (LPCWSTR)pwszCurDirBuf);
218 nParseOffset = wcslen ((LPCWSTR) pwszBuf);
220 /* check if path ends with backslash, if not, add one */
221 if (*((WCHAR*) pwszBuf+nParseOffset-1) != L'\\') {
222 wcscat ((WCHAR*) pwszBuf, L"\\");
228 WCHAR* win32_name = (WCHAR*) pwszBuf+nParseOffset;
231 /* Check for Unix separator and convert to Win32 */
233 *win32_name++ = '\\'; /* convert char */
234 /* If Win32 separated that is "quoted", remove quote */
235 /* HELPME (Thorsten Engel): I don't understand the following part
236 and it removes a backslash from e.g. "\\.\c:" which I need for
237 RAW device access. So I took it out */
238 /* } else if (*name == '\\' && name[1] == '\\') {
239 *win32_name++ = '\\';
240 name++; */ /* skip first \ */
242 *win32_name++ = *name; /* copy character */
247 /* null terminate string */
251 /* here we convert to VSS specific file name which
252 can get longer because VSS will make something like
253 \\\\?\\GLOBALROOT\\Device\\HarddiskVolumeShadowCopy1\\bacula\\uninstall.exe
254 from c:\bacula\uninstall.exe
256 if (g_pVSSClient && enable_vss && g_pVSSClient->IsInitialized()) {
257 /* is output buffer large enough? */
258 pwszBuf = check_pool_memory_size(pwszBuf, (dwBufCharsNeeded+MAX_PATH)*sizeof(WCHAR));
259 /* create temp. buffer */
260 POOLMEM* pszBuf = get_pool_memory (PM_FNAME);
261 pszBuf = check_pool_memory_size(pszBuf, (dwBufCharsNeeded+MAX_PATH)*sizeof(WCHAR));
266 wcsncpy ((WCHAR*) pszBuf, (WCHAR*) pwszBuf+nParseOffset, wcslen((WCHAR*)pwszBuf)+1-nParseOffset);
267 g_pVSSClient->GetShadowPathW((WCHAR*)pszBuf,(WCHAR*)pwszBuf,dwBufCharsNeeded+MAX_PATH);
268 free_pool_memory(pszBuf);
272 free_pool_memory (pszUCSPath);
273 free_pool_memory (pwszCurDirBuf);
279 wchar_2_UTF8(char *pszUTF, const WCHAR *pszUCS, int cchChar)
281 /* the return value is the number of bytes written to the buffer.
282 The number includes the byte for the null terminator. */
284 if (p_WideCharToMultiByte) {
285 int nRet = p_WideCharToMultiByte(CP_UTF8,0,pszUCS,-1,pszUTF,cchChar,NULL,NULL);
294 UTF8_2_wchar(POOLMEM **ppszUCS, const char *pszUTF)
296 /* the return value is the number of wide characters written to the buffer. */
297 /* convert null terminated string from utf-8 to ucs2, enlarge buffer if necessary */
299 if (p_MultiByteToWideChar) {
300 /* strlen of UTF8 +1 is enough */
301 DWORD cchSize = (strlen(pszUTF)+1);
302 *ppszUCS = check_pool_memory_size(*ppszUCS, cchSize*sizeof (WCHAR));
304 int nRet = p_MultiByteToWideChar(CP_UTF8, 0, pszUTF, -1, (LPWSTR) *ppszUCS,cchSize);
314 wchar_win32_path(const char *name, WCHAR *win32_name)
316 const char *fname = name;
318 /* Check for Unix separator and convert to Win32 */
320 *win32_name++ = '\\'; /* convert char */
321 /* If Win32 separated that is "quoted", remove quote */
322 } else if (*name == '\\' && name[1] == '\\') {
323 *win32_name++ = '\\';
324 name++; /* skip first \ */
326 *win32_name++ = *name; /* copy character */
330 /* Strip any trailing slash, if we stored something */
331 if (*fname != 0 && win32_name[-1] == '\\') {
339 make_win32_path_UTF8_2_wchar(POOLMEM **pszUCS, const char *pszUTF, BOOL* pBIsRawPath /*= NULL*/)
341 /* helper to convert from utf-8 to UCS-2 and to complete a path for 32K path syntax */
342 int nRet = UTF8_2_wchar(pszUCS, pszUTF);
344 #ifdef USE_WIN32_32KPATHCONVERSION
345 /* add \\?\ to support 32K long filepaths */
346 *pszUCS = make_wchar_win32_path(*pszUCS, pBIsRawPath);
349 *pBIsRawPath = FALSE;
362 int chmod(const char *, mode_t)
367 int chown(const char *k, uid_t, gid_t)
372 int lchown(const char *k, uid_t, gid_t)
378 bool fstype(const char *fname, char *fs, int fslen)
380 return true; /* accept anything */
392 srandom(unsigned int seed)
396 // /////////////////////////////////////////////////////////////////
397 // convert from Windows concept of time to Unix concept of time
398 // /////////////////////////////////////////////////////////////////
400 cvt_utime_to_ftime(const time_t &time, FILETIME &wintime)
402 uint64_t mstime = time;
403 mstime *= WIN32_FILETIME_SCALE;
404 mstime += WIN32_FILETIME_ADJUST;
407 wintime.dwLowDateTime = (DWORD)(mstime & 0xffffffffUL);
409 wintime.dwLowDateTime = (DWORD)(mstime & 0xffffffffI64);
411 wintime.dwHighDateTime = (DWORD) ((mstime>>32)& 0xffffffffUL);
415 cvt_ftime_to_utime(const FILETIME &time)
417 uint64_t mstime = time.dwHighDateTime;
419 mstime |= time.dwLowDateTime;
421 mstime -= WIN32_FILETIME_ADJUST;
422 mstime /= WIN32_FILETIME_SCALE; // convert to seconds.
424 return (time_t) (mstime & 0xffffffff);
432 FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
433 FORMAT_MESSAGE_FROM_SYSTEM |
434 FORMAT_MESSAGE_IGNORE_INSERTS,
437 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default lang
442 return (const char *) lpMsgBuf;
448 statDir(const char *file, struct stat *sb)
450 WIN32_FIND_DATAW info_w; // window's file info
451 WIN32_FIND_DATAA info_a; // window's file info
453 // cache some common vars to make code more transparent
454 DWORD* pdwFileAttributes;
455 DWORD* pnFileSizeHigh;
456 DWORD* pnFileSizeLow;
457 FILETIME* pftLastAccessTime;
458 FILETIME* pftLastWriteTime;
459 FILETIME* pftCreationTime;
461 if (file[1] == ':' && file[2] == 0) {
462 d_msg(__FILE__, __LINE__, 99, "faking ROOT attrs(%s).\n", file);
463 sb->st_mode = S_IFDIR;
464 sb->st_mode |= S_IREAD|S_IEXEC|S_IWRITE;
471 HANDLE h = INVALID_HANDLE_VALUE;
473 // use unicode or ascii
474 if (p_FindFirstFileW) {
475 POOLMEM* pwszBuf = get_pool_memory (PM_FNAME);
476 make_win32_path_UTF8_2_wchar(&pwszBuf, file);
478 h = p_FindFirstFileW((LPCWSTR) pwszBuf, &info_w);
479 free_pool_memory(pwszBuf);
481 pdwFileAttributes = &info_w.dwFileAttributes;
482 pnFileSizeHigh = &info_w.nFileSizeHigh;
483 pnFileSizeLow = &info_w.nFileSizeLow;
484 pftLastAccessTime = &info_w.ftLastAccessTime;
485 pftLastWriteTime = &info_w.ftLastWriteTime;
486 pftCreationTime = &info_w.ftCreationTime;
488 else if (p_FindFirstFileA) {
489 h = p_FindFirstFileA(file, &info_a);
491 pdwFileAttributes = &info_a.dwFileAttributes;
492 pnFileSizeHigh = &info_a.nFileSizeHigh;
493 pnFileSizeLow = &info_a.nFileSizeLow;
494 pftLastAccessTime = &info_a.ftLastAccessTime;
495 pftLastWriteTime = &info_a.ftLastWriteTime;
496 pftCreationTime = &info_a.ftCreationTime;
499 if (h == INVALID_HANDLE_VALUE) {
500 const char *err = errorString();
501 d_msg(__FILE__, __LINE__, 99, "FindFirstFile(%s):%s\n", file, err);
502 LocalFree((void *)err);
503 errno = b_errno_win32;
507 sb->st_mode = 0777; /* start with everything */
508 if (*pdwFileAttributes & FILE_ATTRIBUTE_READONLY)
509 sb->st_mode &= ~(S_IRUSR|S_IRGRP|S_IROTH);
510 if (*pdwFileAttributes & FILE_ATTRIBUTE_SYSTEM)
511 sb->st_mode &= ~S_IRWXO; /* remove everything for other */
512 if (*pdwFileAttributes & FILE_ATTRIBUTE_HIDDEN)
513 sb->st_mode |= S_ISVTX; /* use sticky bit -> hidden */
514 sb->st_mode |= S_IFDIR;
516 sb->st_size = *pnFileSizeHigh;
518 sb->st_size |= *pnFileSizeLow;
519 sb->st_blksize = 4096;
520 sb->st_blocks = (uint32_t)(sb->st_size + 4095)/4096;
522 sb->st_atime = cvt_ftime_to_utime(*pftLastAccessTime);
523 sb->st_mtime = cvt_ftime_to_utime(*pftLastWriteTime);
524 sb->st_ctime = cvt_ftime_to_utime(*pftCreationTime);
531 stat2(const char *file, struct stat *sb)
533 BY_HANDLE_FILE_INFORMATION info;
537 conv_unix_to_win32_path(file, tmpbuf, 1024);
541 if (p_GetFileAttributesW) {
542 POOLMEM* pwszBuf = get_pool_memory(PM_FNAME);
543 make_win32_path_UTF8_2_wchar(&pwszBuf, tmpbuf);
545 attr = p_GetFileAttributesW((LPCWSTR) pwszBuf);
546 free_pool_memory(pwszBuf);
547 } else if (p_GetFileAttributesA) {
548 attr = p_GetFileAttributesA(tmpbuf);
552 const char *err = errorString();
553 d_msg(__FILE__, __LINE__, 99,
554 "GetFileAttributes(%s): %s\n", tmpbuf, err);
555 LocalFree((void *)err);
556 errno = b_errno_win32;
560 if (attr & FILE_ATTRIBUTE_DIRECTORY)
561 return statDir(tmpbuf, sb);
563 h = CreateFileA(tmpbuf, GENERIC_READ,
564 FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
566 if (h == INVALID_HANDLE_VALUE) {
567 const char *err = errorString();
568 d_msg(__FILE__, __LINE__, 99,
569 "Cannot open file for stat (%s):%s\n", tmpbuf, err);
570 LocalFree((void *)err);
572 errno = b_errno_win32;
576 if (!GetFileInformationByHandle(h, &info)) {
577 const char *err = errorString();
578 d_msg(__FILE__, __LINE__, 99,
579 "GetfileInformationByHandle(%s): %s\n", tmpbuf, err);
580 LocalFree((void *)err);
582 errno = b_errno_win32;
586 sb->st_dev = info.dwVolumeSerialNumber;
587 sb->st_ino = info.nFileIndexHigh;
589 sb->st_ino |= info.nFileIndexLow;
590 sb->st_nlink = (short)info.nNumberOfLinks;
591 if (sb->st_nlink > 1) {
592 d_msg(__FILE__, __LINE__, 99, "st_nlink=%d\n", sb->st_nlink);
595 sb->st_mode = 0777; /* start with everything */
596 if (info.dwFileAttributes & FILE_ATTRIBUTE_READONLY)
597 sb->st_mode &= ~(S_IRUSR|S_IRGRP|S_IROTH);
598 if (info.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM)
599 sb->st_mode &= ~S_IRWXO; /* remove everything for other */
600 if (info.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN)
601 sb->st_mode |= S_ISVTX; /* use sticky bit -> hidden */
602 sb->st_mode |= S_IFREG;
604 sb->st_size = info.nFileSizeHigh;
606 sb->st_size |= info.nFileSizeLow;
607 sb->st_blksize = 4096;
608 sb->st_blocks = (uint32_t)(sb->st_size + 4095)/4096;
609 sb->st_atime = cvt_ftime_to_utime(info.ftLastAccessTime);
610 sb->st_mtime = cvt_ftime_to_utime(info.ftLastWriteTime);
611 sb->st_ctime = cvt_ftime_to_utime(info.ftCreationTime);
619 stat(const char *file, struct stat *sb)
621 WIN32_FILE_ATTRIBUTE_DATA data;
625 memset(sb, 0, sizeof(*sb));
627 /* why not allow win 95 to use p_GetFileAttributesExA ?
628 * this function allows _some_ open files to be stat'ed
629 * if (g_platform_id == VER_PLATFORM_WIN32_WINDOWS) {
630 * return stat2(file, sb);
634 if (p_GetFileAttributesExW) {
635 /* dynamically allocate enough space for UCS2 filename */
636 POOLMEM* pwszBuf = get_pool_memory (PM_FNAME);
637 make_win32_path_UTF8_2_wchar(&pwszBuf, file);
639 BOOL b = p_GetFileAttributesExW((LPCWSTR) pwszBuf, GetFileExInfoStandard, &data);
640 free_pool_memory(pwszBuf);
643 return stat2(file, sb);
645 } else if (p_GetFileAttributesExA) {
646 if (!p_GetFileAttributesExA(file, GetFileExInfoStandard, &data)) {
647 return stat2(file, sb);
650 return stat2(file, sb);
653 sb->st_mode = 0777; /* start with everything */
654 if (data.dwFileAttributes & FILE_ATTRIBUTE_READONLY) {
655 sb->st_mode &= ~(S_IRUSR|S_IRGRP|S_IROTH);
657 if (data.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM) {
658 sb->st_mode &= ~S_IRWXO; /* remove everything for other */
660 if (data.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) {
661 sb->st_mode |= S_ISVTX; /* use sticky bit -> hidden */
663 if (data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
664 sb->st_mode |= S_IFDIR;
666 sb->st_mode |= S_IFREG;
670 sb->st_size = data.nFileSizeHigh;
672 sb->st_size |= data.nFileSizeLow;
673 sb->st_blksize = 4096;
674 sb->st_blocks = (uint32_t)(sb->st_size + 4095)/4096;
675 sb->st_atime = cvt_ftime_to_utime(data.ftLastAccessTime);
676 sb->st_mtime = cvt_ftime_to_utime(data.ftLastWriteTime);
677 sb->st_ctime = cvt_ftime_to_utime(data.ftCreationTime);
684 lstat(const char *file, struct stat *sb)
686 return stat(file, sb);
702 execvp(const char *, char *[]) {
723 waitpid(int, int*, int)
730 readlink(const char *, char *, int)
739 strcasecmp(const char *s1, const char *s2)
741 register int ch1, ch2;
744 return 0; /* strings are equal if same object. */
754 } while (ch1 != 0 && tolower(ch1) == tolower(ch2));
761 strncasecmp(const char *s1, const char *s2, int len)
763 register int ch1, ch2;
766 return 0; /* strings are equal if same object. */
776 if (ch1 == 0 || tolower(ch1) != tolower(ch2)) break;
783 gettimeofday(struct timeval *tv, struct timezone *)
793 if (!SystemTimeToFileTime(&now, &tmp)) {
794 errno = b_errno_win32;
798 int64_t _100nsec = tmp.dwHighDateTime;
800 _100nsec |= tmp.dwLowDateTime;
801 _100nsec -= WIN32_FILETIME_ADJUST;
803 tv->tv_sec =(long) (_100nsec / 10000000);
804 tv->tv_usec = (long) ((_100nsec % 10000000)/10);
810 syslog(int type, const char *fmt, const char *msg)
812 /*#ifndef HAVE_CONSOLE
813 MessageBox(NULL, msg, "Bacula", MB_OK);
830 // implement opendir/readdir/closedir on top of window's API
834 WIN32_FIND_DATAA data_a; // window's file info (ansii version)
835 WIN32_FIND_DATAW data_w; // window's file info (wchar version)
836 const char *spec; // the directory we're traversing
837 HANDLE dirh; // the search handle
838 BOOL valid_a; // the info in data_a field is valid
839 BOOL valid_w; // the info in data_w field is valid
840 UINT32 offset; // pseudo offset for d_off
844 opendir(const char *path)
846 /* enough space for VSS !*/
847 int max_len = strlen(path) + MAX_PATH;
854 rval = (_dir *)malloc(sizeof(_dir));
855 memset (rval, 0, sizeof (_dir));
856 if (rval == NULL) return NULL;
857 char *tspec = (char *)malloc(max_len);
858 if (tspec == NULL) return NULL;
860 if (g_platform_id != VER_PLATFORM_WIN32_WINDOWS) {
862 /* will append \\?\ at front itself */
863 conv_unix_to_win32_path(path, tspec, max_len-4);
865 /* allow path to be 32767 bytes */
871 conv_unix_to_win32_path(path, tspec+4, max_len-4);
874 conv_unix_to_win32_path(path, tspec, max_len);
877 // add backslash only if there is none yet (think of c:\)
878 if (tspec[strlen(tspec)-1] != '\\')
879 bstrncat(tspec, "\\*", max_len);
881 bstrncat(tspec, "*", max_len);
886 if (p_FindFirstFileW) {
887 POOLMEM* pwcBuf = get_pool_memory(PM_FNAME);;
888 make_win32_path_UTF8_2_wchar(&pwcBuf,rval->spec);
890 rval->dirh = p_FindFirstFileW((LPCWSTR)pwcBuf, &rval->data_w);
892 free_pool_memory(pwcBuf);
894 if (rval->dirh != INVALID_HANDLE_VALUE)
896 } else if (p_FindFirstFileA) {
897 rval->dirh = p_FindFirstFileA(rval->spec, &rval->data_a);
899 if (rval->dirh != INVALID_HANDLE_VALUE)
904 d_msg(__FILE__, __LINE__,
905 99, "opendir(%s)\n\tspec=%s,\n\tFindFirstFile returns %d\n",
906 path, rval->spec, rval->dirh);
909 if (rval->dirh == INVALID_HANDLE_VALUE)
913 d_msg(__FILE__, __LINE__,
914 99, "\tFirstFile=%s\n", rval->data_w.cFileName);
917 d_msg(__FILE__, __LINE__,
918 99, "\tFirstFile=%s\n", rval->data_a.cFileName);
923 free((void *)rval->spec);
925 errno = b_errno_win32;
932 _dir *dp = (_dir *)dirp;
934 free((void *)dp->spec);
940 typedef struct _WIN32_FIND_DATA {
941 DWORD dwFileAttributes;
942 FILETIME ftCreationTime;
943 FILETIME ftLastAccessTime;
944 FILETIME ftLastWriteTime;
949 TCHAR cFileName[MAX_PATH];
950 TCHAR cAlternateFileName[14];
951 } WIN32_FIND_DATA, *PWIN32_FIND_DATA;
955 copyin(struct dirent &dp, const char *fname)
959 char *cp = dp.d_name;
969 readdir_r(DIR *dirp, struct dirent *entry, struct dirent **result)
971 _dir *dp = (_dir *)dirp;
972 if (dp->valid_w || dp->valid_a) {
973 entry->d_off = dp->offset;
977 char szBuf[MAX_PATH_UTF8];
978 wchar_2_UTF8(szBuf,dp->data_w.cFileName);
979 dp->offset += copyin(*entry, szBuf);
980 } else if (dp->valid_a) { // copy ansi (only 1 will be valid)
981 dp->offset += copyin(*entry, dp->data_a.cFileName);
984 *result = entry; /* return entry address */
985 d_msg(__FILE__, __LINE__,
986 99, "readdir_r(%p, { d_name=\"%s\", d_reclen=%d, d_off=%d\n",
987 dirp, entry->d_name, entry->d_reclen, entry->d_off);
989 // d_msg(__FILE__, __LINE__, 99, "readdir_r !valid\n");
990 errno = b_errno_win32;
994 // get next file, try unicode first
996 dp->valid_w = p_FindNextFileW(dp->dirh, &dp->data_w);
997 else if (p_FindNextFileA)
998 dp->valid_a = p_FindNextFileA(dp->dirh, &dp->data_a);
1000 dp->valid_a = FALSE;
1001 dp->valid_w = FALSE;
1008 * Dotted IP address to network address
1014 inet_aton(const char *a, struct in_addr *inp)
1017 uint32_t acc = 0, tmp = 0;
1020 if (!isdigit(*cp)) { /* first char must be digit */
1021 return 0; /* error */
1025 tmp = (tmp * 10) + (*cp -'0');
1026 } else if (*cp == '.' || *cp == 0) {
1028 return 0; /* error */
1030 acc = (acc << 8) + tmp;
1034 return 0; /* error */
1036 } while (*cp++ != 0);
1037 if (dotc != 4) { /* want 3 .'s plus EOS */
1038 return 0; /* error */
1040 inp->s_addr = htonl(acc); /* store addr in network format */
1045 nanosleep(const struct timespec *req, struct timespec *rem)
1048 rem->tv_sec = rem->tv_nsec = 0;
1049 Sleep((req->tv_sec * 1000) + (req->tv_nsec/100000));
1054 init_signals(void terminate(int sig))
1060 init_stack_dump(void)
1067 pathconf(const char *path, int name)
1071 if (strncmp(path, "\\\\?\\", 4) == 0)
1083 WORD wVersionRequested = MAKEWORD( 1, 1);
1086 int err = WSAStartup(wVersionRequested, &wsaData);
1090 printf("Can not start Windows Sockets\n");
1100 win32_chdir(const char *dir)
1102 if (p_SetCurrentDirectoryW) {
1103 POOLMEM* pwszBuf = get_pool_memory(PM_FNAME);
1104 make_win32_path_UTF8_2_wchar(&pwszBuf, dir);
1106 BOOL b=p_SetCurrentDirectoryW((LPCWSTR)pwszBuf);
1108 free_pool_memory(pwszBuf);
1111 errno = b_errno_win32;
1115 else if (p_SetCurrentDirectoryA) {
1116 if (0 == p_SetCurrentDirectoryA(dir)) {
1117 errno = b_errno_win32;
1127 win32_mkdir(const char *dir)
1130 POOLMEM* pwszBuf = get_pool_memory(PM_FNAME);
1131 make_win32_path_UTF8_2_wchar(&pwszBuf, dir);
1133 int n=p_wmkdir((LPCWSTR)pwszBuf);
1134 free_pool_memory(pwszBuf);
1143 win32_getcwd(char *buf, int maxlen)
1147 if (p_GetCurrentDirectoryW) {
1148 POOLMEM* pwszBuf = get_pool_memory(PM_FNAME);
1149 pwszBuf = check_pool_memory_size (pwszBuf, maxlen*sizeof(WCHAR));
1151 n = p_GetCurrentDirectoryW(maxlen, (LPWSTR) pwszBuf);
1153 n = wchar_2_UTF8 (buf, (WCHAR*)pwszBuf, maxlen)-1;
1154 free_pool_memory(pwszBuf);
1156 } else if (p_GetCurrentDirectoryA)
1157 n = p_GetCurrentDirectoryA(maxlen, buf);
1159 if (n == 0 || n > maxlen) return NULL;
1161 if (n+1 > maxlen) return NULL;
1170 win32_fputs(const char *string, FILE *stream)
1172 /* we use WriteConsoleA / WriteConsoleA
1173 so we can be sure that unicode support works on win32.
1174 with fallback if something fails
1177 HANDLE hOut = GetStdHandle (STD_OUTPUT_HANDLE);
1178 if (hOut && (hOut != INVALID_HANDLE_VALUE) && p_WideCharToMultiByte &&
1179 p_MultiByteToWideChar && (stream == stdout)) {
1181 POOLMEM* pwszBuf = get_pool_memory(PM_MESSAGE);
1183 DWORD dwCharsWritten;
1186 dwChars = UTF8_2_wchar(&pwszBuf, string);
1188 /* try WriteConsoleW */
1189 if (WriteConsoleW (hOut, pwszBuf, dwChars-1, &dwCharsWritten, NULL)) {
1190 free_pool_memory(pwszBuf);
1191 return dwCharsWritten;
1194 /* convert to local codepage and try WriteConsoleA */
1195 POOLMEM* pszBuf = get_pool_memory(PM_MESSAGE);
1196 pszBuf = check_pool_memory_size(pszBuf, dwChars+1);
1198 dwChars = p_WideCharToMultiByte(GetConsoleOutputCP(),0,(LPCWSTR) pwszBuf,-1,pszBuf,dwChars,NULL,NULL);
1199 free_pool_memory(pwszBuf);
1201 if (WriteConsoleA (hOut, pszBuf, dwChars-1, &dwCharsWritten, NULL)) {
1202 free_pool_memory(pszBuf);
1203 return dwCharsWritten;
1207 return fputs(string, stream);
1211 win32_cgets (char* buffer, int len)
1213 /* we use console ReadConsoleA / ReadConsoleW to be able to read unicode
1214 from the win32 console and fallback if seomething fails */
1216 HANDLE hIn = GetStdHandle (STD_INPUT_HANDLE);
1217 if (hIn && (hIn != INVALID_HANDLE_VALUE) && p_WideCharToMultiByte && p_MultiByteToWideChar) {
1222 /* nt and unicode conversion */
1223 if (ReadConsoleW (hIn, wszBuf, 1024, &dwRead, NULL)) {
1225 /* null terminate at end */
1226 if (wszBuf[dwRead-1] == L'\n') {
1227 wszBuf[dwRead-1] = L'\0';
1231 if (wszBuf[dwRead-1] == L'\r') {
1232 wszBuf[dwRead-1] = L'\0';
1236 wchar_2_UTF8(buffer, wszBuf, len);
1240 /* win 9x and unicode conversion */
1241 if (ReadConsoleA (hIn, szBuf, 1024, &dwRead, NULL)) {
1243 /* null terminate at end */
1244 if (szBuf[dwRead-1] == L'\n') {
1245 szBuf[dwRead-1] = L'\0';
1249 if (szBuf[dwRead-1] == L'\r') {
1250 szBuf[dwRead-1] = L'\0';
1254 /* convert from ansii to WCHAR */
1255 p_MultiByteToWideChar(GetConsoleCP(), 0, szBuf, -1, wszBuf,1024);
1256 /* convert from WCHAR to UTF-8 */
1257 if (wchar_2_UTF8(buffer, wszBuf, len))
1263 if (fgets(buffer, len, stdin))
1270 win32_unlink(const char *filename)
1274 POOLMEM* pwszBuf = get_pool_memory(PM_FNAME);
1275 make_win32_path_UTF8_2_wchar(&pwszBuf, filename);
1277 nRetCode = _wunlink((LPCWSTR) pwszBuf);
1279 /* special case if file is readonly,
1280 we retry but unset attribute before */
1281 if (nRetCode == -1 && errno == EACCES && p_SetFileAttributesW && p_GetFileAttributesW) {
1282 DWORD dwAttr = p_GetFileAttributesW((LPCWSTR)pwszBuf);
1283 if (dwAttr != INVALID_FILE_ATTRIBUTES) {
1284 if (p_SetFileAttributesW((LPCWSTR)pwszBuf, dwAttr & ~FILE_ATTRIBUTE_READONLY)) {
1285 nRetCode = _wunlink((LPCWSTR) pwszBuf);
1286 /* reset to original if it didn't help */
1288 p_SetFileAttributesW((LPCWSTR)pwszBuf, dwAttr);
1292 free_pool_memory(pwszBuf);
1294 nRetCode = _unlink(filename);
1296 /* special case if file is readonly,
1297 we retry but unset attribute before */
1298 if (nRetCode == -1 && errno == EACCES && p_SetFileAttributesA && p_GetFileAttributesA) {
1299 DWORD dwAttr = p_GetFileAttributesA(filename);
1300 if (dwAttr != INVALID_FILE_ATTRIBUTES) {
1301 if (p_SetFileAttributesA(filename, dwAttr & ~FILE_ATTRIBUTE_READONLY)) {
1302 nRetCode = _unlink(filename);
1303 /* reset to original if it didn't help */
1305 p_SetFileAttributesA(filename, dwAttr);
1314 #include "mswinver.h"
1316 char WIN_VERSION_LONG[64];
1317 char WIN_VERSION[32];
1324 static winver INIT; // cause constructor to be called before main()
1329 winver::winver(void)
1331 const char *version = "";
1332 const char *platform = "";
1333 OSVERSIONINFO osvinfo;
1334 osvinfo.dwOSVersionInfoSize = sizeof(osvinfo);
1336 // Get the current OS version
1337 if (!GetVersionEx(&osvinfo)) {
1338 version = "Unknown";
1339 platform = "Unknown";
1342 switch (_mkversion(osvinfo.dwPlatformId, osvinfo.dwMajorVersion, osvinfo.dwMinorVersion))
1344 case MS_WINDOWS_95: (version = "Windows 95"); break;
1345 case MS_WINDOWS_98: (version = "Windows 98"); break;
1346 case MS_WINDOWS_ME: (version = "Windows ME"); break;
1347 case MS_WINDOWS_NT4:(version = "Windows NT 4.0"); platform = "NT"; break;
1348 case MS_WINDOWS_2K: (version = "Windows 2000");platform = "NT"; break;
1349 case MS_WINDOWS_XP: (version = "Windows XP");platform = "NT"; break;
1350 case MS_WINDOWS_S2003: (version = "Windows Server 2003");platform = "NT"; break;
1351 default: version = "Windows ??"; break;
1354 bstrncpy(WIN_VERSION_LONG, version, sizeof(WIN_VERSION_LONG));
1355 snprintf(WIN_VERSION, sizeof(WIN_VERSION), "%s %d.%d.%d",
1356 platform, osvinfo.dwMajorVersion, osvinfo.dwMinorVersion, osvinfo.dwBuildNumber);
1359 HANDLE h = CreateFile("G:\\foobar", GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
1363 BPIPE *b = open_bpipe("ls -l", 10, "r");
1365 while (!feof(b->rfd)) {
1366 fgets(buf, sizeof(buf), b->rfd);
1372 BOOL CreateChildProcess(VOID);
1373 VOID WriteToPipe(VOID);
1374 VOID ReadFromPipe(VOID);
1375 VOID ErrorExit(LPCSTR);
1376 VOID ErrMsg(LPTSTR, BOOL);
1379 * Check for a quoted path, if an absolute path name is given and it contains
1380 * spaces it will need to be quoted. i.e. "c:/Program Files/foo/bar.exe"
1381 * CreateProcess() says the best way to ensure proper results with executables
1382 * with spaces in path or filename is to quote the string.
1385 getArgv0(const char *cmdline)
1390 for (cp = cmdline; *cp; cp++)
1395 if (!inquote && isspace(*cp))
1400 int len = cp - cmdline;
1401 char *rval = (char *)malloc(len+1);
1415 * OK, so it would seem CreateProcess only handles true executables:
1416 * .com or .exe files.
1417 * So test to see whether we're getting a .bat file and if so grab
1418 * $COMSPEC value and pass batch file to it.
1421 CreateChildProcess(const char *cmdline, HANDLE in, HANDLE out, HANDLE err)
1423 PROCESS_INFORMATION piProcInfo;
1424 STARTUPINFOA siStartInfo;
1425 BOOL bFuncRetn = FALSE;
1427 // Set up members of the PROCESS_INFORMATION structure.
1429 ZeroMemory( &piProcInfo, sizeof(PROCESS_INFORMATION) );
1431 // Set up members of the STARTUPINFO structure.
1433 ZeroMemory( &siStartInfo, sizeof(STARTUPINFO) );
1434 siStartInfo.cb = sizeof(STARTUPINFO);
1435 // setup new process to use supplied handles for stdin,stdout,stderr
1436 // if supplied handles are not used the send a copy of our STD_HANDLE
1438 siStartInfo.dwFlags = STARTF_USESTDHANDLES;
1440 if (in != INVALID_HANDLE_VALUE)
1441 siStartInfo.hStdInput = in;
1443 siStartInfo.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
1445 if (out != INVALID_HANDLE_VALUE)
1446 siStartInfo.hStdOutput = out;
1448 siStartInfo.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
1449 if (err != INVALID_HANDLE_VALUE)
1450 siStartInfo.hStdError = err;
1452 siStartInfo.hStdError = GetStdHandle(STD_ERROR_HANDLE);
1453 // Create the child process.
1457 const char *comspec = getenv("COMSPEC");
1459 if (comspec == NULL) // should never happen
1460 return INVALID_HANDLE_VALUE;
1462 char *cmdLine = (char *)alloca(strlen(cmdline) + strlen(comspec) + 16);
1464 strcpy(exeFile, comspec);
1465 strcpy(cmdLine, comspec);
1466 strcat(cmdLine, " /c ");
1467 strcat(cmdLine, cmdline);
1469 // try to execute program
1470 bFuncRetn = CreateProcessA(exeFile,
1471 cmdLine, // command line
1472 NULL, // process security attributes
1473 NULL, // primary thread security attributes
1474 TRUE, // handles are inherited
1475 0, // creation flags
1476 NULL, // use parent's environment
1477 NULL, // use parent's current directory
1478 &siStartInfo, // STARTUPINFO pointer
1479 &piProcInfo); // receives PROCESS_INFORMATION
1481 if (bFuncRetn == 0) {
1482 ErrorExit("CreateProcess failed\n");
1483 const char *err = errorString();
1484 d_msg(__FILE__, __LINE__, 99,
1485 "CreateProcess(%s, %s, ...)=%s\n", exeFile, cmdLine, err);
1486 LocalFree((void *)err);
1487 return INVALID_HANDLE_VALUE;
1489 // we don't need a handle on the process primary thread so we close
1491 CloseHandle(piProcInfo.hThread);
1493 return piProcInfo.hProcess;
1498 ErrorExit (LPCSTR lpszMessage)
1500 d_msg(__FILE__, __LINE__, 0, "%s", lpszMessage);
1505 typedef struct s_bpipe {
1507 time_t worker_stime;
1516 CloseIfValid(HANDLE handle)
1518 if (handle != INVALID_HANDLE_VALUE)
1519 CloseHandle(handle);
1524 open_bpipe(char *prog, int wait, const char *mode)
1526 HANDLE hChildStdinRd, hChildStdinWr, hChildStdinWrDup,
1527 hChildStdoutRd, hChildStdoutWr, hChildStdoutRdDup,
1530 SECURITY_ATTRIBUTES saAttr;
1534 hChildStdinRd = hChildStdinWr = hChildStdinWrDup =
1535 hChildStdoutRd = hChildStdoutWr = hChildStdoutRdDup =
1536 hInputFile = INVALID_HANDLE_VALUE;
1538 BPIPE *bpipe = (BPIPE *)malloc(sizeof(BPIPE));
1539 memset((void *)bpipe, 0, sizeof(BPIPE));
1541 int mode_read = (mode[0] == 'r');
1542 int mode_write = (mode[0] == 'w' || mode[1] == 'w');
1545 // Set the bInheritHandle flag so pipe handles are inherited.
1547 saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
1548 saAttr.bInheritHandle = TRUE;
1549 saAttr.lpSecurityDescriptor = NULL;
1553 // Create a pipe for the child process's STDOUT.
1554 if (! CreatePipe(&hChildStdoutRd, &hChildStdoutWr, &saAttr, 0)) {
1555 ErrorExit("Stdout pipe creation failed\n");
1558 // Create noninheritable read handle and close the inheritable read
1561 fSuccess = DuplicateHandle(GetCurrentProcess(), hChildStdoutRd,
1562 GetCurrentProcess(), &hChildStdoutRdDup , 0,
1564 DUPLICATE_SAME_ACCESS);
1566 ErrorExit("DuplicateHandle failed");
1570 CloseHandle(hChildStdoutRd);
1571 hChildStdoutRd = INVALID_HANDLE_VALUE;
1576 // Create a pipe for the child process's STDIN.
1578 if (!CreatePipe(&hChildStdinRd, &hChildStdinWr, &saAttr, 0)) {
1579 ErrorExit("Stdin pipe creation failed\n");
1583 // Duplicate the write handle to the pipe so it is not inherited.
1584 fSuccess = DuplicateHandle(GetCurrentProcess(), hChildStdinWr,
1585 GetCurrentProcess(), &hChildStdinWrDup,
1587 FALSE, // not inherited
1588 DUPLICATE_SAME_ACCESS);
1590 ErrorExit("DuplicateHandle failed");
1594 CloseHandle(hChildStdinWr);
1595 hChildStdinWr = INVALID_HANDLE_VALUE;
1597 // spawn program with redirected handles as appropriate
1598 bpipe->worker_pid = (pid_t)
1599 CreateChildProcess(prog, // commandline
1600 hChildStdinRd, // stdin HANDLE
1601 hChildStdoutWr, // stdout HANDLE
1602 hChildStdoutWr); // stderr HANDLE
1604 if ((HANDLE) bpipe->worker_pid == INVALID_HANDLE_VALUE)
1608 bpipe->worker_stime = time(NULL);
1611 CloseHandle(hChildStdoutWr); // close our write side so when
1612 // process terminates we can
1614 // ugly but convert WIN32 HANDLE to FILE*
1615 int rfd = _open_osfhandle((long)hChildStdoutRdDup, O_RDONLY);
1617 bpipe->rfd = _fdopen(rfd, "r");
1621 CloseHandle(hChildStdinRd); // close our read side so as not
1622 // to interfre with child's copy
1623 // ugly but convert WIN32 HANDLE to FILE*
1624 int wfd = _open_osfhandle((long)hChildStdinWrDup, O_WRONLY);
1626 bpipe->wfd = _fdopen(wfd, "w");
1631 bpipe->timer_id = start_child_timer(bpipe->worker_pid, wait);
1638 CloseIfValid(hChildStdoutRd);
1639 CloseIfValid(hChildStdoutRdDup);
1640 CloseIfValid(hChildStdinWr);
1641 CloseIfValid(hChildStdinWrDup);
1643 free((void *) bpipe);
1644 errno = b_errno_win32; /* do GetLastError() for error code */
1651 kill(int pid, int signal)
1654 if (!TerminateProcess((HANDLE)pid, (UINT) signal)) {
1656 errno = b_errno_win32;
1658 CloseHandle((HANDLE)pid);
1665 close_bpipe(BPIPE *bpipe)
1668 int32_t remaining_wait = bpipe->wait;
1670 if (remaining_wait == 0) { /* wait indefinitely */
1671 remaining_wait = INT32_MAX;
1675 if (!GetExitCodeProcess((HANDLE)bpipe->worker_pid, &exitCode)) {
1676 const char *err = errorString();
1677 rval = b_errno_win32;
1678 d_msg(__FILE__, __LINE__, 0,
1679 "GetExitCode error %s\n", err);
1680 LocalFree((void *)err);
1683 if (exitCode == STILL_ACTIVE) {
1684 if (remaining_wait <= 0) {
1685 rval = ETIME; /* timed out */
1688 bmicrosleep(1, 0); /* wait one second */
1690 } else if (exitCode != 0) {
1691 /* Truncate exit code as it doesn't seem to be correct */
1692 rval = (exitCode & 0xFF) | b_errno_exit;
1695 break; /* Shouldn't get here */
1699 if (bpipe->timer_id) {
1700 stop_child_timer(bpipe->timer_id);
1702 if (bpipe->rfd) fclose(bpipe->rfd);
1703 if (bpipe->wfd) fclose(bpipe->wfd);
1704 free((void *)bpipe);
1709 close_wpipe(BPIPE *bpipe)
1715 if (fclose(bpipe->wfd) != 0) {
1723 #include "findlib/find.h"
1726 utime(const char *fname, struct utimbuf *times)
1731 conv_unix_to_win32_path(fname, tmpbuf, 1024);
1733 cvt_utime_to_ftime(times->actime, acc);
1734 cvt_utime_to_ftime(times->modtime, mod);
1736 HANDLE h = INVALID_HANDLE_VALUE;
1738 if (p_CreateFileW) {
1739 POOLMEM* pwszBuf = get_pool_memory(PM_FNAME);
1740 make_win32_path_UTF8_2_wchar(&pwszBuf, tmpbuf);
1742 h = p_CreateFileW((LPCWSTR) pwszBuf,
1743 FILE_WRITE_ATTRIBUTES,
1750 free_pool_memory(pwszBuf);
1751 } else if (p_CreateFileA) {
1752 h = p_CreateFileA(tmpbuf,
1753 FILE_WRITE_ATTRIBUTES,
1761 if (h == INVALID_HANDLE_VALUE) {
1762 const char *err = errorString();
1763 d_msg(__FILE__, __LINE__, 99,
1764 "Cannot open file \"%s\" for utime(): ERR=%s", tmpbuf, err);
1765 LocalFree((void *)err);
1766 errno = b_errno_win32;
1770 int rval = SetFileTime(h, NULL, &acc, &mod) ? 0 : -1;
1773 errno = b_errno_win32;
1778 #if USE_WIN32_COMPAT_IO
1781 open(const char *file, int flags, int mode)
1784 POOLMEM* pwszBuf = get_pool_memory(PM_FNAME);
1785 make_win32_path_UTF8_2_wchar(&pwszBuf, file);
1787 int nRet = p_wopen((LPCWSTR) pwszBuf, flags|_O_BINARY, mode);
1788 free_pool_memory(pwszBuf);
1793 return _open(file, flags|_O_BINARY, mode);
1797 * Note, this works only for a file. If you want
1798 * to close a socket, use closesocket().
1799 * Bacula has been modified in src/lib/bnet.c
1800 * to use closesocket().
1809 #ifndef HAVE_WXCONSOLE
1811 read(int fd, void *buf, ssize_t len)
1813 return _read(fd, buf, (size_t)len);
1817 write(int fd, const void *buf, ssize_t len)
1819 return _write(fd, buf, (size_t)len);
1825 lseek(int fd, off_t offset, int whence)
1827 return (off_t)_lseeki64(fd, offset, whence);
1831 dup2(int fd1, int fd2)
1833 return _dup2(fd1, fd2);
1838 open(const char *file, int flags, int mode)
1841 DWORD shareMode = 0;
1844 HANDLE foo = INVALID_HANDLE_VALUE;
1845 const char *remap = file;
1847 if (flags & O_WRONLY) access = GENERIC_WRITE;
1848 else if (flags & O_RDWR) access = GENERIC_READ|GENERIC_WRITE;
1849 else access = GENERIC_READ;
1851 if (flags & O_CREAT) create = CREATE_NEW;
1852 else create = OPEN_EXISTING;
1854 if (flags & O_TRUNC) create = TRUNCATE_EXISTING;
1856 if (!(flags & O_EXCL))
1857 shareMode = FILE_SHARE_DELETE|FILE_SHARE_READ|FILE_SHARE_WRITE;
1859 if (flags & O_APPEND) {
1860 printf("open...APPEND not implemented yet.");
1864 if (p_CreateFileW) {
1865 POOLMEM* pwszBuf = get_pool_memory(PM_FNAME);
1866 make_win32_path_UTF8_2_wchar(pwszBuf, file);
1868 foo = p_CreateFileW((LPCWSTR) pwszBuf, access, shareMode, NULL, create, msflags, NULL);
1869 free_pool_memory(pwszBuf);
1871 else if (p_CreateFileA)
1872 foo = CreateFile(file, access, shareMode, NULL, create, msflags, NULL);
1874 if (INVALID_HANDLE_VALUE == foo) {
1875 errno = b_errno_win32;
1886 if (!CloseHandle((HANDLE)fd)) {
1887 errno = b_errno_win32;
1895 write(int fd, const void *data, ssize_t len)
1899 status = WriteFile((HANDLE)fd, data, len, &bwrite, NULL);
1900 if (status) return bwrite;
1901 errno = b_errno_win32;
1907 read(int fd, void *data, ssize_t len)
1912 status = ReadFile((HANDLE)fd, data, len, &bread, NULL);
1913 if (status) return bread;
1914 errno = b_errno_win32;
1919 lseek(int fd, off_t offset, int whence)
1925 method = FILE_BEGIN;
1928 method = FILE_CURRENT;
1938 if ((val=SetFilePointer((HANDLE)fd, (DWORD)offset, NULL, method)) == INVALID_SET_FILE_POINTER) {
1939 errno = b_errno_win32;
1942 /* ***FIXME*** I doubt this works right */
1959 /* syslog function, added by Nicolas Boichat */