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