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