]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/win32/compat/compat.cpp
18d1ec6ec4cd0a3852d759e4fb8ec82e08f46811
[bacula/bacula] / bacula / src / win32 / compat / compat.cpp
1 //                              -*- Mode: C++ -*-
2 // compat.cpp -- compatibilty layer to make bacula-fd run
3 //               natively under windows
4 //
5 // Copyright transferred from Raider Solutions, Inc to
6 //   Kern Sibbald and John Walker by express permission.
7 //
8 // Copyright (C) 2004-2005 Kern Sibbald
9 //
10 //   This program is free software; you can redistribute it and/or
11 //   modify it under the terms of the GNU General Public License as
12 //   published by the Free Software Foundation; either version 2 of
13 //   the License, or (at your option) any later version.
14 //
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 GNU
18 //   General Public License for more details.
19 //
20 //   You should have received a copy of the GNU General Public
21 //   License along with this program; if not, write to the Free
22 //   Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
23 //   MA 02111-1307, USA.
24 //
25 // Author          : Christopher S. Hull
26 // Created On      : Sat Jan 31 15:55:00 2004
27 // $Id$
28
29 #include "bacula.h"
30
31 #ifdef WIN32_VSS
32 #include "vss.h"
33 #endif 
34
35 #include "../../lib/winapi.h"
36
37
38 /* to allow the usage of the original version in this file here */
39 #undef fputs
40
41 #define b_errno_win32 (1<<29)
42
43 #define USE_WIN32_COMPAT_IO 1
44
45 extern void d_msg(const char *file, int line, int level, const char *fmt,...);
46 extern DWORD   g_platform_id;
47
48 // from MicroSoft SDK (KES) is the diff between Jan 1 1601 and Jan 1 1970
49 #ifdef HAVE_MINGW
50 #define WIN32_FILETIME_ADJUST 0x19DB1DED53E8000UL //Not sure it works
51 #else
52 #define WIN32_FILETIME_ADJUST 0x19DB1DED53E8000I64
53 #endif
54
55 #define WIN32_FILETIME_SCALE  10000000             // 100ns/second
56
57 extern "C" void
58 cygwin_conv_to_win32_path(const char *name, char *win32_name, DWORD dwSize)
59 {
60     const char *fname = name;
61     char *tname = win32_name;
62     while (*name) {
63         /* Check for Unix separator and convert to Win32 */
64         if (*name == '/') {
65             *win32_name++ = '\\';     /* convert char */
66         /* If Win32 separated that is "quoted", remove quote */
67         } else if (*name == '\\' && name[1] == '\\') {
68             *win32_name++ = '\\';
69             name++;                   /* skip first \ */
70         } else {
71             *win32_name++ = *name;    /* copy character */
72         }
73         name++;
74     }
75     /* Strip any trailing slash, if we stored something */
76     if (*fname != 0 && win32_name[-1] == '\\') {
77         win32_name[-1] = 0;
78     } else {
79         *win32_name = 0;
80     }
81
82 #ifdef WIN32_VSS
83     /* here we convert to VSS specific file name which
84        can get longer because VSS will make something like
85        \\\\?\\GLOBALROOT\\Device\\HarddiskVolumeShadowCopy1\\bacula\\uninstall.exe
86        from c:\bacula\uninstall.exe
87     */ 
88     if (g_pVSSClient) {
89       POOLMEM* pszBuf = get_pool_memory (PM_FNAME);
90       pszBuf = check_pool_memory_size(pszBuf, dwSize);
91       bstrncpy (pszBuf, tname, strlen(tname)+1);
92       g_pVSSClient->GetShadowPath(pszBuf,tname,dwSize);
93       free_pool_memory(pszBuf);
94     }
95 #endif
96 }
97
98 int 
99 wchar_2_UTF8(char *pszUTF, const WCHAR *pszUCS, int cchChar)
100 {
101    /* the return value is the number of bytes written to the buffer. 
102       The number includes the byte for the null terminator. */
103
104    if (p_WideCharToMultiByte) {
105          int nRet = p_WideCharToMultiByte(CP_UTF8,0,pszUCS,-1,pszUTF,cchChar,NULL,NULL);
106          ASSERT (nRet > 0);
107          return nRet;
108       }
109    else
110       return NULL;
111 }
112
113 int 
114 UTF8_2_wchar(POOLMEM **ppszUCS, const char *pszUTF)
115 {
116    /* the return value is the number of wide characters written to the buffer. */
117    /* convert null terminated string from utf-8 to ucs2, enlarge buffer if necessary */
118
119    if (p_MultiByteToWideChar) {
120       /* strlen of UTF8 +1 is enough */ 
121       DWORD cchSize = (strlen(pszUTF)+1);
122       *ppszUCS = check_pool_memory_size(*ppszUCS, cchSize*sizeof (WCHAR));
123       
124       int nRet = p_MultiByteToWideChar(CP_UTF8, 0, pszUTF, -1, (LPWSTR) *ppszUCS,cchSize);
125       ASSERT (nRet > 0);
126       return nRet;
127    }
128    else
129       return NULL;
130 }
131
132
133 void
134 wchar_win32_path(const char *name, WCHAR *win32_name)
135 {
136     const char *fname = name;
137     while (*name) {
138         /* Check for Unix separator and convert to Win32 */
139         if (*name == '/') {
140             *win32_name++ = '\\';     /* convert char */
141         /* If Win32 separated that is "quoted", remove quote */
142         } else if (*name == '\\' && name[1] == '\\') {
143             *win32_name++ = '\\';
144             name++;                   /* skip first \ */
145         } else {
146             *win32_name++ = *name;    /* copy character */
147         }
148         name++;
149     }
150     /* Strip any trailing slash, if we stored something */
151     if (*fname != 0 && win32_name[-1] == '\\') {
152         win32_name[-1] = 0;
153     } else {
154         *win32_name = 0;
155     }
156 }
157
158 int umask(int)
159 {
160    return 0;
161 }
162
163 int chmod(const char *, mode_t)
164 {
165    return 0;
166 }
167
168 int chown(const char *k, uid_t, gid_t)
169 {
170    return 0;
171 }
172
173 int lchown(const char *k, uid_t, gid_t)
174 {
175    return 0;
176 }
177
178 #ifdef needed
179 bool fstype(const char *fname, char *fs, int fslen)
180 {
181    return true;                       /* accept anything */
182 }
183 #endif
184
185
186 long int
187 random(void)
188 {
189     return rand();
190 }
191
192 void
193 srandom(unsigned int seed)
194 {
195    srand(seed);
196 }
197 // /////////////////////////////////////////////////////////////////
198 // convert from Windows concept of time to Unix concept of time
199 // /////////////////////////////////////////////////////////////////
200 void
201 cvt_utime_to_ftime(const time_t  &time, FILETIME &wintime)
202 {
203     uint64_t mstime = time;
204     mstime *= WIN32_FILETIME_SCALE;
205     mstime += WIN32_FILETIME_ADJUST;
206
207     #ifdef HAVE_MINGW
208     wintime.dwLowDateTime = (DWORD)(mstime & 0xffffffffUL);
209     #else
210     wintime.dwLowDateTime = (DWORD)(mstime & 0xffffffffI64);
211     #endif
212     wintime.dwHighDateTime = (DWORD) ((mstime>>32)& 0xffffffffUL);
213 }
214
215 time_t
216 cvt_ftime_to_utime(const FILETIME &time)
217 {
218     uint64_t mstime = time.dwHighDateTime;
219     mstime <<= 32;
220     mstime |= time.dwLowDateTime;
221
222     mstime -= WIN32_FILETIME_ADJUST;
223     mstime /= WIN32_FILETIME_SCALE; // convert to seconds.
224
225     return (time_t) (mstime & 0xffffffff);
226 }
227
228 static const char *
229 errorString(void)
230 {
231    LPVOID lpMsgBuf;
232
233    FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
234                  FORMAT_MESSAGE_FROM_SYSTEM |
235                  FORMAT_MESSAGE_IGNORE_INSERTS,
236                  NULL,
237                  GetLastError(),
238                  MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default lang
239                  (LPTSTR) &lpMsgBuf,
240                  0,
241                  NULL);
242
243    return (const char *) lpMsgBuf;
244 }
245
246 #ifndef HAVE_MINGW
247
248 static int
249 statDir(const char *file, struct stat *sb)
250 {
251    WIN32_FIND_DATAW info_w;       // window's file info
252    WIN32_FIND_DATAA info_a;       // window's file info
253
254    // cache some common vars to make code more transparent
255    DWORD* pdwFileAttributes;
256    DWORD* pnFileSizeHigh;
257    DWORD* pnFileSizeLow;
258    FILETIME* pftLastAccessTime;
259    FILETIME* pftLastWriteTime;
260    FILETIME* pftCreationTime;
261
262    if (file[1] == ':' && file[2] == 0) {
263         d_msg(__FILE__, __LINE__, 99, "faking ROOT attrs(%s).\n", file);
264         sb->st_mode = S_IFDIR;
265         sb->st_mode |= S_IREAD|S_IEXEC|S_IWRITE;
266         time(&sb->st_ctime);
267         time(&sb->st_mtime);
268         time(&sb->st_atime);
269         return 0;
270     }
271
272    HANDLE h = INVALID_HANDLE_VALUE;
273
274    // use unicode or ascii
275    if (p_FindFirstFileW) {
276       POOLMEM* pwszBuf = get_pool_memory (PM_FNAME);         
277       UTF8_2_wchar(&pwszBuf, file);
278       
279       h = p_FindFirstFileW((LPCWSTR) pwszBuf, &info_w);
280       free_pool_memory(pwszBuf);
281
282       pdwFileAttributes = &info_w.dwFileAttributes;
283       pnFileSizeHigh    = &info_w.nFileSizeHigh;
284       pnFileSizeLow     = &info_w.nFileSizeLow;
285       pftLastAccessTime = &info_w.ftLastAccessTime;
286       pftLastWriteTime  = &info_w.ftLastWriteTime;
287       pftCreationTime   = &info_w.ftCreationTime;
288    }
289    else if (p_FindFirstFileA) {
290       h = p_FindFirstFileA(file, &info_a);
291
292       pdwFileAttributes = &info_a.dwFileAttributes;
293       pnFileSizeHigh    = &info_a.nFileSizeHigh;
294       pnFileSizeLow     = &info_a.nFileSizeLow;
295       pftLastAccessTime = &info_a.ftLastAccessTime;
296       pftLastWriteTime  = &info_a.ftLastWriteTime;
297       pftCreationTime   = &info_a.ftCreationTime;
298    }
299
300     if (h == INVALID_HANDLE_VALUE) {
301         const char *err = errorString();
302         d_msg(__FILE__, __LINE__, 99, "FindFirstFile(%s):%s\n", file, err);
303         LocalFree((void *)err);
304         errno = b_errno_win32;
305         return -1;
306     }
307
308     sb->st_mode = 0777;               /* start with everything */
309     if (*pdwFileAttributes & FILE_ATTRIBUTE_READONLY)
310         sb->st_mode &= ~(S_IRUSR|S_IRGRP|S_IROTH);
311     if (*pdwFileAttributes & FILE_ATTRIBUTE_SYSTEM)
312         sb->st_mode &= ~S_IRWXO; /* remove everything for other */
313     if (*pdwFileAttributes & FILE_ATTRIBUTE_HIDDEN)
314         sb->st_mode |= S_ISVTX; /* use sticky bit -> hidden */
315     sb->st_mode |= S_IFDIR;
316
317     sb->st_size = *pnFileSizeHigh;
318     sb->st_size <<= 32;
319     sb->st_size |= *pnFileSizeLow;
320     sb->st_blksize = 4096;
321     sb->st_blocks = (uint32_t)(sb->st_size + 4095)/4096;
322
323     sb->st_atime = cvt_ftime_to_utime(*pftLastAccessTime);
324     sb->st_mtime = cvt_ftime_to_utime(*pftLastWriteTime);
325     sb->st_ctime = cvt_ftime_to_utime(*pftCreationTime);
326     FindClose(h);
327
328     return 0;
329 }
330
331 static int
332 stat2(const char *file, struct stat *sb)
333 {
334     BY_HANDLE_FILE_INFORMATION info;
335     HANDLE h;
336     int rval = 0;
337     char tmpbuf[1024];
338     cygwin_conv_to_win32_path(file, tmpbuf, 1024);
339
340     DWORD attr = -1;
341
342     if (p_GetFileAttributesW) {
343       POOLMEM* pwszBuf = get_pool_memory(PM_FNAME);
344       UTF8_2_wchar(&pwszBuf, tmpbuf);
345       
346       attr = p_GetFileAttributesW((LPCWSTR) pwszBuf);
347       free_pool_memory(pwszBuf);
348     }
349     else if (p_GetFileAttributesA) {
350        attr = p_GetFileAttributesA(tmpbuf);
351     }
352
353     if (attr == -1) {
354         const char *err = errorString();
355         d_msg(__FILE__, __LINE__, 99,
356               "GetFileAttrubtes(%s): %s\n", tmpbuf, err);
357         LocalFree((void *)err);
358         errno = b_errno_win32;
359         return -1;
360     }
361
362     if (attr & FILE_ATTRIBUTE_DIRECTORY)
363         return statDir(tmpbuf, sb);
364
365     h = CreateFileA(tmpbuf, GENERIC_READ,
366                    FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
367
368     if (h == INVALID_HANDLE_VALUE) {
369         const char *err = errorString();
370         d_msg(__FILE__, __LINE__, 99,
371               "Cannot open file for stat (%s):%s\n", tmpbuf, err);
372         LocalFree((void *)err);
373         rval = -1;
374         errno = b_errno_win32;
375         goto error;
376     }
377
378     if (!GetFileInformationByHandle(h, &info)) {
379         const char *err = errorString();
380         d_msg(__FILE__, __LINE__, 99,
381               "GetfileInformationByHandle(%s): %s\n", tmpbuf, err);
382         LocalFree((void *)err);
383         rval = -1;
384         errno = b_errno_win32;
385         goto error;
386     }
387
388     sb->st_dev = info.dwVolumeSerialNumber;
389     sb->st_ino = info.nFileIndexHigh;
390     sb->st_ino <<= 32;
391     sb->st_ino |= info.nFileIndexLow;
392     sb->st_nlink = (short)info.nNumberOfLinks;
393     if (sb->st_nlink > 1) {
394        d_msg(__FILE__, __LINE__, 99,  "st_nlink=%d\n", sb->st_nlink);
395     }
396
397     sb->st_mode = 0777;               /* start with everything */
398     if (info.dwFileAttributes & FILE_ATTRIBUTE_READONLY)
399         sb->st_mode &= ~(S_IRUSR|S_IRGRP|S_IROTH);
400     if (info.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM)
401         sb->st_mode &= ~S_IRWXO; /* remove everything for other */
402     if (info.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN)
403         sb->st_mode |= S_ISVTX; /* use sticky bit -> hidden */
404     sb->st_mode |= S_IFREG;
405
406     sb->st_size = info.nFileSizeHigh;
407     sb->st_size <<= 32;
408     sb->st_size |= info.nFileSizeLow;
409     sb->st_blksize = 4096;
410     sb->st_blocks = (uint32_t)(sb->st_size + 4095)/4096;
411     sb->st_atime = cvt_ftime_to_utime(info.ftLastAccessTime);
412     sb->st_mtime = cvt_ftime_to_utime(info.ftLastWriteTime);
413     sb->st_ctime = cvt_ftime_to_utime(info.ftCreationTime);
414
415 error:
416     CloseHandle(h);
417     return rval;
418 }
419
420 int
421 stat(const char *file, struct stat *sb)
422 {
423     WIN32_FILE_ATTRIBUTE_DATA data;
424     errno = 0;
425
426
427     memset(sb, 0, sizeof(*sb));
428
429     if (g_platform_id == VER_PLATFORM_WIN32_WINDOWS)
430         return stat2(file, sb);
431
432     // otherwise we're on NT
433 #if 0
434     WCHAR buf[32767];
435     buf[0] = '\\';
436     buf[1] = '\\';
437     buf[2] = '?';
438     buf[3] = '\\';
439
440     wchar_win32_path(file, buf+4);
441
442     if (!GetFileAttributesExW((WCHAR *)buf, GetFileExInfoStandard, &data))
443         return stat2(file, sb);
444 #else
445
446     if (p_GetFileAttributesExW) {
447       /* dynamically allocate enough space for UCS2 filename */
448       POOLMEM* pwszBuf = get_pool_memory (PM_FNAME);          
449       UTF8_2_wchar(&pwszBuf, file);
450
451       BOOL b = p_GetFileAttributesExW((LPCWSTR) pwszBuf, GetFileExInfoStandard, &data);
452       free_pool_memory(pwszBuf);
453                         
454       if (!b) 
455          return stat2(file, sb);
456       
457     } else if (p_GetFileAttributesExA) {
458          if (!p_GetFileAttributesExA(file, GetFileExInfoStandard, &data))
459             return stat2(file, sb);
460     }
461     else
462        return stat2(file, sb);
463
464 #endif
465
466     sb->st_mode = 0777;               /* start with everything */
467     if (data.dwFileAttributes & FILE_ATTRIBUTE_READONLY)
468         sb->st_mode &= ~(S_IRUSR|S_IRGRP|S_IROTH);
469     if (data.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM)
470         sb->st_mode &= ~S_IRWXO; /* remove everything for other */
471     if (data.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN)
472         sb->st_mode |= S_ISVTX; /* use sticky bit -> hidden */
473
474     if (data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
475         sb->st_mode |= S_IFDIR;
476     else
477         sb->st_mode |= S_IFREG;
478
479     sb->st_nlink = 1;
480     sb->st_size = data.nFileSizeHigh;
481     sb->st_size <<= 32;
482     sb->st_size |= data.nFileSizeLow;
483     sb->st_blksize = 4096;
484     sb->st_blocks = (uint32_t)(sb->st_size + 4095)/4096;
485     sb->st_atime = cvt_ftime_to_utime(data.ftLastAccessTime);
486     sb->st_mtime = cvt_ftime_to_utime(data.ftLastWriteTime);
487     sb->st_ctime = cvt_ftime_to_utime(data.ftCreationTime);
488     return 0;
489 }
490
491 #endif //HAVE_MINGW
492
493 int
494 lstat(const char *file, struct stat *sb)
495 {
496     return stat(file, sb);
497 }
498
499 void
500 sleep(int sec)
501 {
502     Sleep(sec * 1000);
503 }
504
505 int
506 geteuid(void)
507 {
508     return 0;
509 }
510
511 int
512 execvp(const char *, char *[]) {
513     errno = ENOSYS;
514     return -1;
515 }
516
517
518 int
519 fork(void)
520 {
521     errno = ENOSYS;
522     return -1;
523 }
524
525 int
526 pipe(int[])
527 {
528     errno = ENOSYS;
529     return -1;
530 }
531
532 int
533 waitpid(int, int*, int)
534 {
535     errno = ENOSYS;
536     return -1;
537 }
538
539 int
540 readlink(const char *, char *, int)
541 {
542     errno = ENOSYS;
543     return -1;
544 }
545
546
547 #ifndef HAVE_MINGW
548 int
549 strcasecmp(const char *s1, const char *s2)
550 {
551     register int ch1, ch2;
552
553     if (s1==s2)
554         return 0;       /* strings are equal if same object. */
555     else if (!s1)
556         return -1;
557     else if (!s2)
558         return 1;
559     do
560     {
561         ch1 = *s1;
562         ch2 = *s2;
563         s1++;
564         s2++;
565     } while (ch1 != 0 && tolower(ch1) == tolower(ch2));
566
567   return(ch1 - ch2);
568 }
569 #endif //HAVE_MINGW
570
571 int
572 strncasecmp(const char *s1, const char *s2, int len)
573 {
574     register int ch1, ch2;
575
576     if (s1==s2)
577         return 0;       /* strings are equal if same object. */
578     else if (!s1)
579         return -1;
580     else if (!s2)
581         return 1;
582     while (len--)
583     {
584         ch1 = *s1;
585         ch2 = *s2;
586         s1++;
587         s2++;
588         if (ch1 == 0 || tolower(ch1) != tolower(ch2)) break;
589     } 
590
591     return (ch1 - ch2);
592 }
593
594 int
595 gettimeofday(struct timeval *tv, struct timezone *)
596 {
597     SYSTEMTIME now;
598     FILETIME tmp;
599     GetSystemTime(&now);
600
601     if (tv == NULL) {
602        errno = EINVAL;
603        return -1;
604     }
605     if (!SystemTimeToFileTime(&now, &tmp)) {
606        errno = b_errno_win32;
607        return -1;
608     }
609
610     int64_t _100nsec = tmp.dwHighDateTime;
611     _100nsec <<= 32;
612     _100nsec |= tmp.dwLowDateTime;
613     _100nsec -= WIN32_FILETIME_ADJUST;
614
615     tv->tv_sec =(long) (_100nsec / 10000000);
616     tv->tv_usec = (long) ((_100nsec % 10000000)/10);
617     return 0;
618
619 }
620
621 int
622 syslog(int type, const char *fmt, const char *msg)
623 {
624 /*#ifndef HAVE_CONSOLE
625     MessageBox(NULL, msg, "Bacula", MB_OK);
626 #endif*/
627     return 0;
628 }
629
630 struct passwd *
631 getpwuid(uid_t)
632 {
633     return NULL;
634 }
635
636 struct group *
637 getgrgid(uid_t)
638 {
639     return NULL;
640 }
641
642 // implement opendir/readdir/closedir on top of window's API
643
644 typedef struct _dir
645 {
646     WIN32_FIND_DATAA data_a;    // window's file info (ansii version)
647     WIN32_FIND_DATAW data_w;    // window's file info (wchar version)
648     const char *spec;           // the directory we're traversing
649     HANDLE      dirh;           // the search handle
650     BOOL        valid_a;        // the info in data_a field is valid
651     BOOL        valid_w;        // the info in data_w field is valid
652     UINT32      offset;         // pseudo offset for d_off
653 } _dir;
654
655 DIR *
656 opendir(const char *path)
657 {
658     /* enough space for VSS !*/
659     int max_len = strlen(path) + MAX_PATH;
660     _dir *rval = NULL;
661     if (path == NULL) {
662        errno = ENOENT;
663        return NULL;
664     }
665
666     rval = (_dir *)malloc(sizeof(_dir));
667     memset (rval, 0, sizeof (_dir));
668     if (rval == NULL) return NULL;
669     char *tspec = (char *)malloc(max_len);
670     if (tspec == NULL) return NULL;
671
672     if (g_platform_id != VER_PLATFORM_WIN32_WINDOWS) {
673 #ifdef WIN32_VSS
674        /* will append \\?\ at front itself */
675        cygwin_conv_to_win32_path(path, tspec, max_len-4);
676 #else
677        /* allow path to be 32767 bytes */
678        tspec[0] = '\\';
679        tspec[1] = '\\';
680        tspec[2] = '?';
681        tspec[3] = '\\';
682        tspec[4] = 0;
683        cygwin_conv_to_win32_path(path, tspec+4, max_len-4);
684 #endif
685     } else {
686        cygwin_conv_to_win32_path(path, tspec, max_len);
687     }
688
689     strncat(tspec, "\\*", max_len);
690     rval->spec = tspec;
691
692     // convert to WCHAR
693     if (p_FindFirstFileW) {
694       POOLMEM* pwcBuf = get_pool_memory(PM_FNAME);;
695       UTF8_2_wchar(&pwcBuf,rval->spec);
696       rval->dirh = p_FindFirstFileW((LPCWSTR)pwcBuf, &rval->data_w);   
697
698       free_pool_memory(pwcBuf);
699
700       if (rval->dirh != INVALID_HANDLE_VALUE)
701         rval->valid_w = 1;
702     } else if (p_FindFirstFileA) {
703       rval->dirh = p_FindFirstFileA(rval->spec, &rval->data_a);
704       
705       if (rval->dirh != INVALID_HANDLE_VALUE)
706         rval->valid_a = 1;
707     } else goto err;
708
709
710     d_msg(__FILE__, __LINE__,
711           99, "opendir(%s)\n\tspec=%s,\n\tFindFirstFile returns %d\n",
712           path, rval->spec, rval->dirh);
713
714     rval->offset = 0;
715     if (rval->dirh == INVALID_HANDLE_VALUE)
716         goto err;
717
718     if (rval->valid_w)
719       d_msg(__FILE__, __LINE__,
720             99, "\tFirstFile=%s\n", rval->data_w.cFileName);
721
722     if (rval->valid_a)
723       d_msg(__FILE__, __LINE__,
724             99, "\tFirstFile=%s\n", rval->data_a.cFileName);
725
726     return (DIR *)rval;
727
728 err:
729     free((void *)rval->spec);
730     free(rval);
731     errno = b_errno_win32;
732     return NULL;
733 }
734
735 int
736 closedir(DIR *dirp)
737 {
738     _dir *dp = (_dir *)dirp;
739     FindClose(dp->dirh);
740     free((void *)dp->spec);
741     free((void *)dp);
742     return 0;
743 }
744
745 /*
746   typedef struct _WIN32_FIND_DATA {
747     DWORD dwFileAttributes;
748     FILETIME ftCreationTime;
749     FILETIME ftLastAccessTime;
750     FILETIME ftLastWriteTime;
751     DWORD nFileSizeHigh;
752     DWORD nFileSizeLow;
753     DWORD dwReserved0;
754     DWORD dwReserved1;
755     TCHAR cFileName[MAX_PATH];
756     TCHAR cAlternateFileName[14];
757 } WIN32_FIND_DATA, *PWIN32_FIND_DATA;
758 */
759
760 static int
761 copyin(struct dirent &dp, const char *fname)
762 {
763     dp.d_ino = 0;
764     dp.d_reclen = 0;
765     char *cp = dp.d_name;
766     while (*fname) {
767         *cp++ = *fname++;
768         dp.d_reclen++;
769     }
770         *cp = 0;
771     return dp.d_reclen;
772 }
773
774 int
775 readdir_r(DIR *dirp, struct dirent *entry, struct dirent **result)
776 {
777     _dir *dp = (_dir *)dirp;
778     if (dp->valid_w || dp->valid_a) {
779       entry->d_off = dp->offset;
780                 
781       // copy unicode
782       if (dp->valid_w) {
783          char szBuf[MAX_PATH_UTF8];
784          wchar_2_UTF8(szBuf,dp->data_w.cFileName);
785          dp->offset += copyin(*entry, szBuf);
786       } else if (dp->valid_a) { // copy ansi (only 1 will be valid)
787          dp->offset += copyin(*entry, dp->data_a.cFileName);
788       }
789                 
790       *result = entry;              /* return entry address */
791       d_msg(__FILE__, __LINE__,
792             99, "readdir_r(%p, { d_name=\"%s\", d_reclen=%d, d_off=%d\n",
793             dirp, entry->d_name, entry->d_reclen, entry->d_off);
794     } else {
795 //      d_msg(__FILE__, __LINE__, 99, "readdir_r !valid\n");
796         errno = b_errno_win32;
797         return -1;
798     }
799
800     // get next file, try unicode first
801     if (p_FindNextFileW) 
802        dp->valid_w = p_FindNextFileW(dp->dirh, &dp->data_w);
803     else if (p_FindNextFileA)
804        dp->valid_a = p_FindNextFileA(dp->dirh, &dp->data_a);
805     else {
806        dp->valid_a = FALSE;
807        dp->valid_w = FALSE;
808     }
809
810     return 0;
811 }
812
813 /*
814  * Dotted IP address to network address
815  *
816  * Returns 1 if  OK
817  *         0 on error
818  */
819 int
820 inet_aton(const char *a, struct in_addr *inp)
821 {
822    const char *cp = a;
823    uint32_t acc = 0, tmp = 0;
824    int dotc = 0;
825
826    if (!isdigit(*cp)) {         /* first char must be digit */
827       return 0;                 /* error */
828    }
829    do {
830       if (isdigit(*cp)) {
831          tmp = (tmp * 10) + (*cp -'0');
832       } else if (*cp == '.' || *cp == 0) {
833          if (tmp > 255) {
834             return 0;           /* error */
835          }
836          acc = (acc << 8) + tmp;
837          dotc++;
838          tmp = 0;
839       } else {
840          return 0;              /* error */
841       }
842    } while (*cp++ != 0);
843    if (dotc != 4) {              /* want 3 .'s plus EOS */
844       return 0;                  /* error */
845    }
846    inp->s_addr = htonl(acc);     /* store addr in network format */
847    return 1;
848 }
849
850 int
851 nanosleep(const struct timespec *req, struct timespec *rem)
852 {
853     if (rem)
854         rem->tv_sec = rem->tv_nsec = 0;
855     Sleep((req->tv_sec * 1000) + (req->tv_nsec/100000));
856     return 0;
857 }
858
859 void
860 init_signals(void terminate(int sig))
861 {
862
863 }
864
865 void
866 init_stack_dump(void)
867 {
868
869 }
870
871
872 long
873 pathconf(const char *path, int name)
874 {
875     switch(name) {
876     case _PC_PATH_MAX :
877         if (strncmp(path, "\\\\?\\", 4) == 0)
878             return 32767;
879     case _PC_NAME_MAX :
880         return 255;
881     }
882     errno = ENOSYS;                                                         
883     return -1;
884 }
885
886 int
887 WSA_Init(void)
888 {
889     WORD wVersionRequested = MAKEWORD( 1, 1);
890     WSADATA wsaData;
891
892     int err = WSAStartup(wVersionRequested, &wsaData);
893
894
895     if (err != 0) {
896         printf("Can not start Windows Sockets\n");
897         errno = ENOSYS;
898         return -1;
899     }
900
901     return 0;
902 }
903
904
905 int
906 win32_chdir(const char *dir)
907 {
908    if (p_SetCurrentDirectoryW) {
909       POOLMEM* pwszBuf = get_pool_memory(PM_FNAME);
910       UTF8_2_wchar(&pwszBuf, dir);
911
912       BOOL b=p_SetCurrentDirectoryW((LPCWSTR)pwszBuf);
913       free_pool_memory(pwszBuf);
914
915       if (!b) {
916          errno = b_errno_win32;
917          return -1;
918       }
919    }
920    else if (p_SetCurrentDirectoryA) {
921       if (0 == p_SetCurrentDirectoryA(dir)) {
922          errno = b_errno_win32;
923          return -1;
924       }
925    }
926    else return -1;
927    
928    return 0;
929 }
930
931 int
932 win32_mkdir(const char *dir)
933 {
934    if (p_wmkdir){
935       POOLMEM* pwszBuf = get_pool_memory(PM_FNAME);
936       UTF8_2_wchar(&pwszBuf, dir);
937
938       int n=p_wmkdir((LPCWSTR)pwszBuf);
939       free_pool_memory(pwszBuf);      
940       return n;
941    }
942
943    return _mkdir(dir);        
944 }
945
946
947 char *
948 win32_getcwd(char *buf, int maxlen)
949 {
950    int n=0;
951
952    if (p_GetCurrentDirectoryW) {
953       POOLMEM* pwszBuf = get_pool_memory(PM_FNAME);
954       pwszBuf = check_pool_memory_size (pwszBuf, maxlen*sizeof(WCHAR));
955
956       n = p_GetCurrentDirectoryW(maxlen, (LPWSTR) pwszBuf);
957       n = wchar_2_UTF8 (buf, (WCHAR*)pwszBuf, maxlen)-1;
958       free_pool_memory(pwszBuf);
959
960    } else if (p_GetCurrentDirectoryA)
961       n = p_GetCurrentDirectoryA(maxlen, buf);
962
963    if (n == 0 || n > maxlen) return NULL;
964
965    if (n+1 > maxlen) return NULL;
966    if (n != 3) {
967        buf[n] = '\\';
968        buf[n+1] = 0;
969    }
970    return buf;
971 }
972
973 int 
974 win32_fputs(const char *string, FILE *stream)
975 {
976    /* we use WriteConsoleA / WriteConsoleA
977       so we can be sure that unicode support works on win32.
978       with fallback if something fails
979    */   
980
981    HANDLE hOut = GetStdHandle (STD_OUTPUT_HANDLE);
982    if (hOut && (hOut != INVALID_HANDLE_VALUE) && p_WideCharToMultiByte && 
983        p_MultiByteToWideChar && (stream == stdout)) {
984       
985       POOLMEM* pwszBuf = get_pool_memory(PM_MESSAGE);
986       
987       DWORD dwCharsWritten;
988       DWORD dwChars;
989          
990       dwChars = UTF8_2_wchar(&pwszBuf, string);
991
992       /* try WriteConsoleW */
993       if (WriteConsoleW (hOut, pwszBuf, dwChars-1, &dwCharsWritten, NULL)) {
994          free_pool_memory(pwszBuf);
995          return dwCharsWritten;   
996       }
997       
998       /* convert to local codepage and try WriteConsoleA */      
999       POOLMEM* pszBuf = get_pool_memory(PM_MESSAGE);         
1000       pszBuf = check_pool_memory_size(pszBuf, dwChars+1);
1001
1002       dwChars = p_WideCharToMultiByte(GetConsoleOutputCP(),0,(LPCWSTR) pwszBuf,-1,pszBuf,dwChars,NULL,NULL);      
1003       free_pool_memory(pwszBuf);
1004
1005       if (WriteConsoleA (hOut, pszBuf, dwChars-1, &dwCharsWritten, NULL)) {
1006          free_pool_memory(pszBuf);
1007          return dwCharsWritten;   
1008       }
1009    }
1010
1011    return fputs(string, stream);
1012 }
1013
1014 char*
1015 win32_cgets (char* buffer, int len)
1016 {
1017    /* we use console ReadConsoleA / ReadConsoleW to be able to read unicode
1018       from the win32 console and fallback if seomething fails */
1019
1020    HANDLE hIn = GetStdHandle (STD_INPUT_HANDLE);
1021    if (hIn && (hIn != INVALID_HANDLE_VALUE) && p_WideCharToMultiByte && p_MultiByteToWideChar) {            
1022       DWORD dwRead;
1023       WCHAR wszBuf[1024];
1024       char  szBuf[1024];    
1025
1026       /* nt and unicode conversion */
1027       if (ReadConsoleW (hIn, wszBuf, 1024, &dwRead, NULL)) {
1028
1029          /* null terminate at end */                
1030          if (wszBuf[dwRead-1] == L'\n') {
1031             wszBuf[dwRead-1] = L'\0';
1032             dwRead --;
1033          }
1034
1035          if (wszBuf[dwRead-1] == L'\r') {
1036             wszBuf[dwRead-1] = L'\0';
1037             dwRead --;
1038          }
1039          
1040          wchar_2_UTF8(buffer, wszBuf, len);
1041          return buffer;
1042       }    
1043       
1044       /* win 9x and unicode conversion */
1045       if (ReadConsoleA (hIn, szBuf, 1024, &dwRead, NULL)) {
1046
1047          /* null terminate at end */                
1048          if (szBuf[dwRead-1] == L'\n') {
1049             szBuf[dwRead-1] = L'\0';
1050             dwRead --;
1051          }
1052
1053          if (szBuf[dwRead-1] == L'\r') {
1054             szBuf[dwRead-1] = L'\0';
1055             dwRead --;
1056          }
1057
1058          /* convert from ansii to WCHAR */
1059          p_MultiByteToWideChar(GetConsoleCP(), 0, szBuf, -1, wszBuf,1024);
1060          /* convert from WCHAR to UTF-8 */
1061          if (wchar_2_UTF8(buffer, wszBuf, len))
1062             return buffer;         
1063       }
1064    }
1065
1066    /* fallback */
1067    if (fgets(buffer, len, stdin)) 
1068       return buffer;   
1069    else
1070       return NULL;
1071 }
1072
1073 int
1074 win32_unlink(const char *filename)
1075 {
1076    int nRetCode;
1077    if (p_wunlink) {
1078       POOLMEM* pwszBuf = get_pool_memory(PM_FNAME);      
1079       UTF8_2_wchar(&pwszBuf, filename);
1080       nRetCode = _wunlink((LPCWSTR) pwszBuf);
1081       free_pool_memory(pwszBuf);
1082    } else {
1083       nRetCode = _unlink(filename);
1084    }
1085    return nRetCode;
1086 }
1087
1088
1089 #include "mswinver.h"
1090
1091 char WIN_VERSION_LONG[64];
1092 char WIN_VERSION[32];
1093
1094 class winver {
1095 public:
1096     winver(void);
1097 };
1098
1099 static winver INIT;                     // cause constructor to be called before main()
1100
1101 #include "bacula.h"
1102 #include "jcr.h"
1103
1104 winver::winver(void)
1105 {
1106     const char *version = "";
1107     const char *platform = "";
1108     OSVERSIONINFO osvinfo;
1109     osvinfo.dwOSVersionInfoSize = sizeof(osvinfo);
1110
1111     // Get the current OS version
1112     if (!GetVersionEx(&osvinfo)) {
1113         version = "Unknown";
1114         platform = "Unknown";
1115     }
1116     else
1117         switch (_mkversion(osvinfo.dwPlatformId, osvinfo.dwMajorVersion, osvinfo.dwMinorVersion))
1118         {
1119         case MS_WINDOWS_95: (version =  "Windows 95"); break;
1120         case MS_WINDOWS_98: (version =  "Windows 98"); break;
1121         case MS_WINDOWS_ME: (version =  "Windows ME"); break;
1122         case MS_WINDOWS_NT4:(version =  "Windows NT 4.0"); platform = "NT"; break;
1123         case MS_WINDOWS_2K: (version =  "Windows 2000");platform = "NT"; break;
1124         case MS_WINDOWS_XP: (version =  "Windows XP");platform = "NT"; break;
1125         case MS_WINDOWS_S2003: (version =  "Windows Server 2003");platform = "NT"; break;
1126         default: version = "Windows ??"; break;
1127         }
1128
1129     bstrncpy(WIN_VERSION_LONG, version, sizeof(WIN_VERSION_LONG));
1130     snprintf(WIN_VERSION, sizeof(WIN_VERSION), "%s %d.%d.%d",
1131              platform, osvinfo.dwMajorVersion, osvinfo.dwMinorVersion, osvinfo.dwBuildNumber);
1132
1133 #if 0
1134     HANDLE h = CreateFile("G:\\foobar", GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
1135     CloseHandle(h);
1136 #endif
1137 #if 0
1138     BPIPE *b = open_bpipe("ls -l", 10, "r");
1139     char buf[1024];
1140     while (!feof(b->rfd)) {
1141         fgets(buf, sizeof(buf), b->rfd);
1142     }
1143     close_bpipe(b);
1144 #endif
1145 }
1146
1147 BOOL CreateChildProcess(VOID);
1148 VOID WriteToPipe(VOID);
1149 VOID ReadFromPipe(VOID);
1150 VOID ErrorExit(LPCSTR);
1151 VOID ErrMsg(LPTSTR, BOOL);
1152
1153 /**
1154  * Check for a quoted path,  if an absolute path name is given and it contains
1155  * spaces it will need to be quoted.  i.e.  "c:/Program Files/foo/bar.exe"
1156  * CreateProcess() says the best way to ensure proper results with executables
1157  * with spaces in path or filename is to quote the string.
1158  */
1159 const char *
1160 getArgv0(const char *cmdline)
1161 {
1162
1163     int inquote = 0;
1164     for (const char *cp = cmdline; *cp; cp++)
1165     {
1166         if (*cp == '"') {
1167             inquote = !inquote;
1168         }
1169         if (!inquote && isspace(*cp))
1170             break;
1171     }
1172
1173         
1174     int len = cp - cmdline;
1175     char *rval = (char *)malloc(len+1);
1176
1177     cp = cmdline;
1178     char *rp = rval;
1179     
1180     while (len--)
1181         *rp++ = *cp++;
1182
1183     *rp = 0;
1184     return rval;
1185 }
1186
1187
1188 /**
1189  * OK, so it would seem CreateProcess only handles true executables:
1190  *  .com or .exe files.
1191  * So test to see whether we're getting a .bat file and if so grab
1192  * $COMSPEC value and pass batch file to it.
1193  */
1194 HANDLE
1195 CreateChildProcess(const char *cmdline, HANDLE in, HANDLE out, HANDLE err)
1196 {
1197     PROCESS_INFORMATION piProcInfo;
1198     STARTUPINFOA siStartInfo;
1199     BOOL bFuncRetn = FALSE;
1200
1201     // Set up members of the PROCESS_INFORMATION structure.
1202
1203     ZeroMemory( &piProcInfo, sizeof(PROCESS_INFORMATION) );
1204
1205     // Set up members of the STARTUPINFO structure.
1206
1207     ZeroMemory( &siStartInfo, sizeof(STARTUPINFO) );
1208     siStartInfo.cb = sizeof(STARTUPINFO);
1209     // setup new process to use supplied handles for stdin,stdout,stderr
1210     // if supplied handles are not used the send a copy of our STD_HANDLE
1211     // as appropriate
1212     siStartInfo.dwFlags = STARTF_USESTDHANDLES;
1213
1214     if (in != INVALID_HANDLE_VALUE)
1215         siStartInfo.hStdInput = in;
1216     else
1217         siStartInfo.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
1218
1219     if (out != INVALID_HANDLE_VALUE)
1220         siStartInfo.hStdOutput = out;
1221     else
1222         siStartInfo.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
1223     if (err != INVALID_HANDLE_VALUE)
1224         siStartInfo.hStdError = err;
1225     else
1226         siStartInfo.hStdError = GetStdHandle(STD_ERROR_HANDLE);
1227     // Create the child process.
1228
1229     char exeFile[256];
1230
1231     const char *comspec = getenv("COMSPEC");
1232     
1233     if (comspec == NULL) // should never happen
1234         return INVALID_HANDLE_VALUE;
1235
1236     char *cmdLine = (char *)alloca(strlen(cmdline) + strlen(comspec) + 16);
1237     
1238     strcpy(exeFile, comspec);
1239     strcpy(cmdLine, comspec);
1240     strcat(cmdLine, " /c ");
1241     strcat(cmdLine, cmdline);
1242
1243     // try to execute program
1244     bFuncRetn = CreateProcessA(exeFile,
1245                               cmdLine, // command line
1246                               NULL, // process security attributes
1247                               NULL, // primary thread security attributes
1248                               TRUE, // handles are inherited
1249                               0, // creation flags
1250                               NULL, // use parent's environment
1251                               NULL, // use parent's current directory
1252                               &siStartInfo, // STARTUPINFO pointer
1253                               &piProcInfo); // receives PROCESS_INFORMATION
1254
1255     if (bFuncRetn == 0) {
1256         ErrorExit("CreateProcess failed\n");
1257         const char *err = errorString();
1258         d_msg(__FILE__, __LINE__, 99,
1259               "CreateProcess(%s, %s, ...)=%s\n", exeFile, cmdLine, err);
1260         LocalFree((void *)err);
1261         return INVALID_HANDLE_VALUE;
1262     }
1263     // we don't need a handle on the process primary thread so we close
1264     // this now.
1265     CloseHandle(piProcInfo.hThread);
1266
1267     return piProcInfo.hProcess;
1268 }
1269
1270
1271 void
1272 ErrorExit (LPCSTR lpszMessage)
1273 {
1274     d_msg(__FILE__, __LINE__, 0, "%s", lpszMessage);
1275 }
1276
1277
1278 /*
1279 typedef struct s_bpipe {
1280    pid_t worker_pid;
1281    time_t worker_stime;
1282    int wait;
1283    btimer_t *timer_id;
1284    FILE *rfd;
1285    FILE *wfd;
1286 } BPIPE;
1287 */
1288
1289 static void
1290 CloseIfValid(HANDLE handle)
1291 {
1292     if (handle != INVALID_HANDLE_VALUE)
1293         CloseHandle(handle);
1294 }
1295
1296 #ifndef HAVE_MINGW
1297 BPIPE *
1298 open_bpipe(char *prog, int wait, const char *mode)
1299 {
1300     HANDLE hChildStdinRd, hChildStdinWr, hChildStdinWrDup,
1301         hChildStdoutRd, hChildStdoutWr, hChildStdoutRdDup,
1302         hInputFile;
1303
1304     SECURITY_ATTRIBUTES saAttr;
1305
1306     BOOL fSuccess;
1307
1308     hChildStdinRd = hChildStdinWr = hChildStdinWrDup =
1309         hChildStdoutRd = hChildStdoutWr = hChildStdoutRdDup =
1310         hInputFile = INVALID_HANDLE_VALUE;
1311
1312     BPIPE *bpipe = (BPIPE *)malloc(sizeof(BPIPE));
1313     memset((void *)bpipe, 0, sizeof(BPIPE));
1314
1315     int mode_read = (mode[0] == 'r');
1316     int mode_write = (mode[0] == 'w' || mode[1] == 'w');
1317
1318
1319     // Set the bInheritHandle flag so pipe handles are inherited.
1320
1321     saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
1322     saAttr.bInheritHandle = TRUE;
1323     saAttr.lpSecurityDescriptor = NULL;
1324
1325     if (mode_read) {
1326
1327         // Create a pipe for the child process's STDOUT.
1328         if (! CreatePipe(&hChildStdoutRd, &hChildStdoutWr, &saAttr, 0)) {
1329             ErrorExit("Stdout pipe creation failed\n");
1330             goto cleanup;
1331         }
1332         // Create noninheritable read handle and close the inheritable read
1333         // handle.
1334
1335         fSuccess = DuplicateHandle(GetCurrentProcess(), hChildStdoutRd,
1336                                    GetCurrentProcess(), &hChildStdoutRdDup , 0,
1337                                    FALSE,
1338                                    DUPLICATE_SAME_ACCESS);
1339         if ( !fSuccess ) {
1340             ErrorExit("DuplicateHandle failed");
1341             goto cleanup;
1342         }
1343
1344         CloseHandle(hChildStdoutRd);
1345         hChildStdoutRd = INVALID_HANDLE_VALUE;
1346     }
1347
1348     if (mode_write) {
1349
1350         // Create a pipe for the child process's STDIN.
1351
1352         if (!CreatePipe(&hChildStdinRd, &hChildStdinWr, &saAttr, 0)) {
1353             ErrorExit("Stdin pipe creation failed\n");
1354             goto cleanup;
1355         }
1356
1357         // Duplicate the write handle to the pipe so it is not inherited.
1358         fSuccess = DuplicateHandle(GetCurrentProcess(), hChildStdinWr,
1359                                    GetCurrentProcess(), &hChildStdinWrDup,
1360                                    0,
1361                                    FALSE,                  // not inherited
1362                                    DUPLICATE_SAME_ACCESS);
1363         if (!fSuccess) {
1364             ErrorExit("DuplicateHandle failed");
1365             goto cleanup;
1366         }
1367
1368         CloseHandle(hChildStdinWr);
1369         hChildStdinWr = INVALID_HANDLE_VALUE;
1370     }
1371     // spawn program with redirected handles as appropriate
1372     bpipe->worker_pid = (pid_t)
1373         CreateChildProcess(prog,             // commandline
1374                            hChildStdinRd,    // stdin HANDLE
1375                            hChildStdoutWr,   // stdout HANDLE
1376                            hChildStdoutWr);  // stderr HANDLE
1377
1378     if ((HANDLE) bpipe->worker_pid == INVALID_HANDLE_VALUE)
1379         goto cleanup;
1380
1381     bpipe->wait = wait;
1382     bpipe->worker_stime = time(NULL);
1383
1384     if (mode_read) {
1385         CloseHandle(hChildStdoutWr); // close our write side so when
1386                                      // process terminates we can
1387                                      // detect eof.
1388         // ugly but convert WIN32 HANDLE to FILE*
1389         int rfd = _open_osfhandle((long)hChildStdoutRdDup, O_RDONLY);
1390         if (rfd >= 0) {
1391            bpipe->rfd = _fdopen(rfd, "r");
1392         }
1393     }
1394     if (mode_write) {
1395         CloseHandle(hChildStdinRd); // close our read side so as not
1396                                     // to interfre with child's copy
1397         // ugly but convert WIN32 HANDLE to FILE*
1398         int wfd = _open_osfhandle((long)hChildStdinWrDup, O_WRONLY);
1399         if (wfd >= 0) {
1400            bpipe->wfd = _fdopen(wfd, "w");
1401         }
1402     }
1403
1404     if (wait > 0) {
1405         bpipe->timer_id = start_child_timer(bpipe->worker_pid, wait);
1406     }
1407
1408     return bpipe;
1409
1410 cleanup:
1411
1412     CloseIfValid(hChildStdoutRd);
1413     CloseIfValid(hChildStdoutRdDup);
1414     CloseIfValid(hChildStdinWr);
1415     CloseIfValid(hChildStdinWrDup);
1416
1417     free((void *) bpipe);
1418     errno = b_errno_win32;            /* do GetLastError() for error code */
1419     return NULL;
1420 }
1421
1422 #endif //HAVE_MINGW
1423
1424 int
1425 kill(int pid, int signal)
1426 {
1427    int rval = 0;
1428    if (!TerminateProcess((HANDLE)pid, (UINT) signal)) {
1429       rval = -1;
1430       errno = b_errno_win32;
1431    }
1432    CloseHandle((HANDLE)pid);
1433    return rval;
1434 }
1435
1436 #ifndef HAVE_MINGW
1437
1438 int
1439 close_bpipe(BPIPE *bpipe)
1440 {
1441    int rval = 0;
1442    int32_t remaining_wait = bpipe->wait;
1443
1444    if (remaining_wait == 0) {         /* wait indefinitely */
1445       remaining_wait = INT32_MAX;
1446    }
1447    for ( ;; ) {
1448       DWORD exitCode;
1449       if (!GetExitCodeProcess((HANDLE)bpipe->worker_pid, &exitCode)) {
1450          const char *err = errorString();
1451          rval = b_errno_win32;
1452          d_msg(__FILE__, __LINE__, 0,
1453                "GetExitCode error %s\n", err);
1454          LocalFree((void *)err);
1455          break;
1456       }
1457       if (exitCode == STILL_ACTIVE) {
1458          if (remaining_wait <= 0) {
1459             rval = ETIME;             /* timed out */
1460             break;
1461          }
1462          bmicrosleep(1, 0);           /* wait one second */
1463          remaining_wait--;
1464       } else if (exitCode != 0) {
1465          /* Truncate exit code as it doesn't seem to be correct */
1466          rval = (exitCode & 0xFF) | b_errno_exit;
1467          break;
1468       } else {
1469          break;                       /* Shouldn't get here */
1470       }
1471    }
1472
1473    if (bpipe->timer_id) {
1474        stop_child_timer(bpipe->timer_id);
1475    }
1476    if (bpipe->rfd) fclose(bpipe->rfd);
1477    if (bpipe->wfd) fclose(bpipe->wfd);
1478    free((void *)bpipe);
1479    return rval;
1480 }
1481
1482 int
1483 close_wpipe(BPIPE *bpipe)
1484 {
1485     int stat = 1;
1486
1487     if (bpipe->wfd) {
1488         fflush(bpipe->wfd);
1489         if (fclose(bpipe->wfd) != 0) {
1490             stat = 0;
1491         }
1492         bpipe->wfd = NULL;
1493     }
1494     return stat;
1495 }
1496
1497 #include "findlib/find.h"
1498
1499 int
1500 utime(const char *fname, struct utimbuf *times)
1501 {
1502     FILETIME acc, mod;
1503     char tmpbuf[1024];
1504
1505     cygwin_conv_to_win32_path(fname, tmpbuf, 1024);
1506
1507     cvt_utime_to_ftime(times->actime, acc);
1508     cvt_utime_to_ftime(times->modtime, mod);
1509
1510     HANDLE h = INVALID_HANDLE_VALUE;
1511
1512     if (p_CreateFileW) {
1513       POOLMEM* pwszBuf = get_pool_memory(PM_FNAME);
1514       UTF8_2_wchar(&pwszBuf, tmpbuf);
1515
1516       h = p_CreateFileW((LPCWSTR) pwszBuf,
1517                         FILE_WRITE_ATTRIBUTES,
1518                         FILE_SHARE_WRITE,
1519                         NULL,
1520                         OPEN_EXISTING,
1521                         0,
1522                         NULL);
1523      
1524       free_pool_memory(pwszBuf);
1525     } else if (p_CreateFileA) {
1526       h = p_CreateFileA(tmpbuf,
1527                         FILE_WRITE_ATTRIBUTES,
1528                         FILE_SHARE_WRITE,
1529                         NULL,
1530                         OPEN_EXISTING,
1531                         0,
1532                         NULL);
1533     }
1534
1535     if (h == INVALID_HANDLE_VALUE) {
1536         const char *err = errorString();
1537         d_msg(__FILE__, __LINE__, 99,
1538               "Cannot open file \"%s\" for utime(): ERR=%s", tmpbuf, err);
1539         LocalFree((void *)err);
1540         errno = b_errno_win32;
1541         return -1;
1542     }
1543
1544     int rval = SetFileTime(h, NULL, &acc, &mod) ? 0 : -1;
1545     CloseHandle(h);
1546     if (rval == -1) {
1547        errno = b_errno_win32;
1548     }
1549     return rval;
1550 }
1551
1552 #if USE_WIN32_COMPAT_IO
1553
1554 int
1555 open(const char *file, int flags, int mode)
1556 {
1557    if (p_wopen) {
1558       POOLMEM* pwszBuf = get_pool_memory(PM_FNAME);      
1559       UTF8_2_wchar(&pwszBuf, file);
1560
1561       int nRet = p_wopen((LPCWSTR) pwszBuf, flags|_O_BINARY, mode);
1562       free_pool_memory(pwszBuf);
1563
1564       return nRet;
1565    }
1566
1567    return _open(file, flags|_O_BINARY, mode);
1568 }
1569
1570 /*
1571  * Note, this works only for a file. If you want
1572  *   to close a socket, use closesocket(). 
1573  *   Bacula has been modified in src/lib/bnet.c
1574  *   to use closesocket().
1575  */
1576 int
1577 close(int fd)
1578 {
1579     return _close(fd);
1580 }
1581
1582 #ifndef HAVE_WXCONSOLE
1583 ssize_t
1584 read(int fd, void *buf, ssize_t len)
1585 {
1586     return _read(fd, buf, (size_t)len);
1587 }
1588
1589 ssize_t
1590 write(int fd, const void *buf, ssize_t len)
1591 {
1592     return _write(fd, buf, (size_t)len);
1593 }
1594 #endif
1595
1596
1597 off_t
1598 lseek(int fd, off_t offset, int whence)
1599 {
1600     return _lseeki64(fd, offset, whence);
1601 }
1602
1603 int
1604 dup2(int fd1, int fd2)
1605 {
1606     return _dup2(fd1, fd2);
1607 }
1608 #else
1609 int
1610 open(const char *file, int flags, int mode)
1611 {
1612     DWORD access = 0;
1613     DWORD shareMode = 0;
1614     DWORD create = 0;
1615     DWORD msflags = 0;
1616     HANDLE foo = INVALID_HANDLE_VALUE;
1617     const char *remap = file;
1618
1619     if (flags & O_WRONLY) access = GENERIC_WRITE;
1620     else if (flags & O_RDWR) access = GENERIC_READ|GENERIC_WRITE;
1621     else access = GENERIC_READ;
1622
1623     if (flags & O_CREAT) create = CREATE_NEW;
1624     else create = OPEN_EXISTING;
1625
1626     if (flags & O_TRUNC) create = TRUNCATE_EXISTING;
1627
1628     if (!(flags & O_EXCL))
1629         shareMode = FILE_SHARE_DELETE|FILE_SHARE_READ|FILE_SHARE_WRITE;
1630
1631     if (flags & O_APPEND) {
1632         printf("open...APPEND not implemented yet.");
1633         exit(-1);
1634     }
1635
1636     if (p_CreateFileW) {
1637        POOLMEM* pwszBuf = get_pool_memory(PM_FNAME);       
1638        UTF8_2_wchar(pwszBuf, file);
1639
1640        foo = p_CreateFileW((LPCWSTR) pwszBuf, access, shareMode, NULL, create, msflags, NULL);
1641        free_pool_memory(pwszBuf);
1642     }
1643     else if (p_CreateFileA)
1644        foo = CreateFile(file, access, shareMode, NULL, create, msflags, NULL);
1645
1646     if (INVALID_HANDLE_VALUE == foo) {
1647         errno = b_errno_win32;
1648         return(int) -1;
1649     }
1650     return (int)foo;
1651
1652 }
1653
1654
1655 int
1656 close(int fd)
1657 {
1658     if (!CloseHandle((HANDLE)fd)) {
1659         errno = b_errno_win32;
1660         return -1;
1661     }
1662
1663     return 0;
1664 }
1665
1666 ssize_t
1667 write(int fd, const void *data, ssize_t len)
1668 {
1669     BOOL status;
1670     DWORD bwrite;
1671     status = WriteFile((HANDLE)fd, data, len, &bwrite, NULL);
1672     if (status) return bwrite;
1673     errno = b_errno_win32;
1674     return -1;
1675 }
1676
1677
1678 ssize_t
1679 read(int fd, void *data, ssize_t len)
1680 {
1681     BOOL status;
1682     DWORD bread;
1683
1684     status = ReadFile((HANDLE)fd, data, len, &bread, NULL);
1685     if (status) return bread;
1686     errno = b_errno_win32;
1687     return -1;
1688 }
1689
1690 off_t
1691 lseek(int fd, off_t offset, int whence)
1692 {
1693     DWORD method = 0;
1694     DWORD val;
1695     switch (whence) {
1696     case SEEK_SET :
1697         method = FILE_BEGIN;
1698         break;
1699     case SEEK_CUR:
1700         method = FILE_CURRENT;
1701         break;
1702     case SEEK_END:
1703         method = FILE_END;
1704         break;
1705     default:
1706         errno = EINVAL;
1707         return -1;
1708     }
1709
1710     if ((val=SetFilePointer((HANDLE)fd, (DWORD)offset, NULL, method)) == INVALID_SET_FILE_POINTER) {
1711        errno = b_errno_win32;
1712        return -1;
1713     }
1714     /* ***FIXME*** I doubt this works right */
1715     return val;
1716 }
1717
1718 int
1719 dup2(int, int)
1720 {
1721     errno = ENOSYS;
1722     return -1;
1723 }
1724
1725
1726 #endif
1727
1728 #endif //HAVE_MINGW
1729
1730 #ifdef HAVE_MINGW
1731 /* syslog function, added by Nicolas Boichat */
1732 void closelog() {}
1733 #endif //HAVE_MINGW