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