]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/win32/compat/compat.cpp
3150a93841ef5a0377e078bc995a7696af2d55c9
[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 Kern Sibbald and John Walker
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
34 #define USE_WIN32_COMPAT_IO 1
35
36 extern void d_msg(const char *file, int line, int level, const char *fmt,...);
37 extern DWORD   g_platform_id;
38
39 // from CYGWIN (should be diff between Jan 1 1601 and Jan 1 1970
40 #ifdef HAVE_MINGW
41 #define WIN32_FILETIME_ADJUST 0x19DB1DED53E8000UL //Not sure it works
42 #else
43 #define WIN32_FILETIME_ADJUST 0x19DB1DED53E8000I64
44 #endif
45
46 #define WIN32_FILETIME_SCALE  10000000             // 100ns/second
47
48 extern "C" void
49 cygwin_conv_to_win32_path(const char *name, char *win32_name)
50 {
51     const char *fname = name;
52     while (*name) {
53         /* Check for Unix separator and convert to Win32 */
54         if (*name == '/') {
55             *win32_name++ = '\\';     /* convert char */
56         /* If Win32 separated that is "quoted", remove quote */
57         } else if (*name == '\\' && name[1] == '\\') {
58             *win32_name++ = '\\';
59             name++;                   /* skip first \ */
60         } else {
61             *win32_name++ = *name;    /* copy character */
62         }
63         name++;
64     }
65     /* Strip any trailing slash, if we stored something */
66     if (*fname != 0 && win32_name[-1] == '\\') {
67         win32_name[-1] = 0;
68     } else {
69         *win32_name = 0;
70     }
71 }
72
73
74 void
75 wchar_win32_path(const char *name, WCHAR *win32_name)
76 {
77     const char *fname = name;
78     while (*name) {
79         /* Check for Unix separator and convert to Win32 */
80         if (*name == '/') {
81             *win32_name++ = '\\';     /* convert char */
82         /* If Win32 separated that is "quoted", remove quote */
83         } else if (*name == '\\' && name[1] == '\\') {
84             *win32_name++ = '\\';
85             name++;                   /* skip first \ */
86         } else {
87             *win32_name++ = *name;    /* copy character */
88         }
89         name++;
90     }
91     /* Strip any trailing slash, if we stored something */
92     if (*fname != 0 && win32_name[-1] == '\\') {
93         win32_name[-1] = 0;
94     } else {
95         *win32_name = 0;
96     }
97 }
98
99 int
100 umask(int)
101 {
102     return 0;
103 }
104
105 int
106 chmod(const char *, mode_t)
107 {
108     return 0;
109 }
110
111 int
112 chown(const char *k, uid_t, gid_t)
113 {
114     return 0;
115 }
116
117 int
118 lchown(const char *k, uid_t, gid_t)
119 {
120     return 0;
121 }
122
123
124
125 long int
126 random(void)
127 {
128     return rand();
129 }
130
131 void
132 srandom(unsigned int seed)
133 {
134     srand(seed);
135 }
136 // /////////////////////////////////////////////////////////////////
137 // convert from Windows concept of time to Unix concept of time
138 // /////////////////////////////////////////////////////////////////
139 void
140 cvt_utime_to_ftime(const time_t  &time, FILETIME &wintime)
141 {
142     uint64_t mstime = time;
143     mstime *= WIN32_FILETIME_SCALE;
144     mstime += WIN32_FILETIME_ADJUST;
145
146     #ifdef HAVE_MINGW
147     wintime.dwLowDateTime = (DWORD)(mstime & 0xffffffffUL);
148     #else
149     wintime.dwLowDateTime = (DWORD)(mstime & 0xffffffffI64);
150     #endif
151     wintime.dwHighDateTime = (DWORD) ((mstime>>32)& 0xffffffffUL);
152 }
153
154 time_t
155 cvt_ftime_to_utime(const FILETIME &time)
156 {
157     uint64_t mstime = time.dwHighDateTime;
158     mstime <<= 32;
159     mstime |= time.dwLowDateTime;
160
161     mstime -= WIN32_FILETIME_ADJUST;
162     mstime /= WIN32_FILETIME_SCALE; // convert to seconds.
163
164     return (time_t) (mstime & 0xffffffff);
165 }
166
167 static const char *
168 errorString(void)
169 {
170     LPVOID lpMsgBuf;
171
172     FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
173                   FORMAT_MESSAGE_FROM_SYSTEM |
174                   FORMAT_MESSAGE_IGNORE_INSERTS,
175                   NULL,
176                   GetLastError(),
177                   MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default lang
178                   (LPTSTR) &lpMsgBuf,
179                   0,
180                   NULL);
181
182     return (const char *) lpMsgBuf;
183 }
184
185 #ifndef HAVE_MINGW
186
187 static int
188 statDir(const char *file, struct stat *sb)
189 {
190     WIN32_FIND_DATA info;       // window's file info
191
192     if (file[1] == ':' && file[2] == 0) {
193         d_msg(__FILE__, __LINE__, 99, "faking ROOT attrs(%s).\n", file);
194         sb->st_mode = S_IFDIR;
195         sb->st_mode |= S_IREAD|S_IEXEC|S_IWRITE;
196         time(&sb->st_ctime);
197         time(&sb->st_mtime);
198         time(&sb->st_atime);
199         return 0;
200     }
201     HANDLE h = FindFirstFile(file, &info);
202
203     if (h == INVALID_HANDLE_VALUE) {
204         const char *err = errorString();
205         d_msg(__FILE__, __LINE__, 99, "FindFirstFile(%s):%s\n", file, err);
206         LocalFree((void *)err);
207         errno = GetLastError();
208         return -1;
209     }
210
211     sb->st_mode = 0777;               /* start with everything */
212     if (info.dwFileAttributes & FILE_ATTRIBUTE_READONLY)
213         sb->st_mode &= ~(S_IRUSR|S_IRGRP|S_IROTH);
214     if (info.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM)
215         sb->st_mode &= ~S_IRWXO; /* remove everything for other */
216     if (info.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN)
217         sb->st_mode |= S_ISVTX; /* use sticky bit -> hidden */
218     sb->st_mode |= S_IFDIR;
219
220     sb->st_size = info.nFileSizeHigh;
221     sb->st_size <<= 32;
222     sb->st_size |= info.nFileSizeLow;
223     sb->st_blksize = 4096;
224     sb->st_blocks = (uint32_t)(sb->st_size + 4095)/4096;
225
226     sb->st_atime = cvt_ftime_to_utime(info.ftLastAccessTime);
227     sb->st_mtime = cvt_ftime_to_utime(info.ftLastWriteTime);
228     sb->st_ctime = cvt_ftime_to_utime(info.ftLastWriteTime);
229     FindClose(h);
230
231     return 0;
232 }
233
234 static int
235 stat2(const char *file, struct stat *sb)
236 {
237     BY_HANDLE_FILE_INFORMATION info;
238     HANDLE h;
239     int rval = 0;
240     char tmpbuf[1024];
241     cygwin_conv_to_win32_path(file, tmpbuf);
242
243     DWORD attr = GetFileAttributes(tmpbuf);
244
245     if (attr == -1) {
246         const char *err = errorString();
247         d_msg(__FILE__, __LINE__, 99,
248               "GetFileAttrubtes(%s): %s\n", tmpbuf, err);
249         LocalFree((void *)err);
250         errno = GetLastError();
251         return -1;
252     }
253
254     if (attr & FILE_ATTRIBUTE_DIRECTORY)
255         return statDir(tmpbuf, sb);
256
257     h = CreateFile(tmpbuf, GENERIC_READ,
258                    FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
259
260     if (h == INVALID_HANDLE_VALUE) {
261         const char *err = errorString();
262         d_msg(__FILE__, __LINE__, 99,
263               "Cannot open file for stat (%s):%s\n", tmpbuf, err);
264         LocalFree((void *)err);
265         rval = -1;
266         errno = GetLastError();
267         goto error;
268     }
269
270     if (!GetFileInformationByHandle(h, &info)) {
271         const char *err = errorString();
272         d_msg(__FILE__, __LINE__, 99,
273               "GetfileInformationByHandle(%s): %s\n", tmpbuf, err);
274         LocalFree((void *)err);
275         rval = -1;
276         errno = GetLastError();
277         goto error;
278     }
279
280     sb->st_dev = info.dwVolumeSerialNumber;
281     sb->st_ino = info.nFileIndexHigh;
282     sb->st_ino <<= 32;
283     sb->st_ino |= info.nFileIndexLow;
284     sb->st_nlink = (short)info.nNumberOfLinks;
285
286     sb->st_mode = 0777;               /* start with everything */
287     if (info.dwFileAttributes & FILE_ATTRIBUTE_READONLY)
288         sb->st_mode &= ~(S_IRUSR|S_IRGRP|S_IROTH);
289     if (info.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM)
290         sb->st_mode &= ~S_IRWXO; /* remove everything for other */
291     if (info.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN)
292         sb->st_mode |= S_ISVTX; /* use sticky bit -> hidden */
293     sb->st_mode |= S_IFREG;
294
295     sb->st_size = info.nFileSizeHigh;
296     sb->st_size <<= 32;
297     sb->st_size |= info.nFileSizeLow;
298     sb->st_blksize = 4096;
299     sb->st_blocks = (uint32_t)(sb->st_size + 4095)/4096;
300     sb->st_atime = cvt_ftime_to_utime(info.ftLastAccessTime);
301     sb->st_mtime = cvt_ftime_to_utime(info.ftLastWriteTime);
302     sb->st_ctime = cvt_ftime_to_utime(info.ftLastWriteTime);
303
304 error:
305     CloseHandle(h);
306     return rval;
307 }
308
309 int
310 stat(const char *file, struct stat *sb)
311 {
312     WIN32_FILE_ATTRIBUTE_DATA data;
313     errno = 0;
314
315
316     memset(sb, 0, sizeof(*sb));
317
318     if (g_platform_id == VER_PLATFORM_WIN32_WINDOWS)
319         return stat2(file, sb);
320
321     // otherwise we're on NT
322 #if 0
323     WCHAR buf[32767];
324     buf[0] = '\\';
325     buf[1] = '\\';
326     buf[2] = '?';
327     buf[3] = '\\';
328
329     wchar_win32_path(file, buf+4);
330
331     if (!GetFileAttributesExW((WCHAR *)buf, GetFileExInfoStandard, &data))
332         return stat2(file, sb);
333 #else
334     if (!GetFileAttributesEx(file, GetFileExInfoStandard, &data))
335         return stat2(file, sb);
336 #endif
337
338     sb->st_mode = 0777;               /* start with everything */
339     if (data.dwFileAttributes & FILE_ATTRIBUTE_READONLY)
340         sb->st_mode &= ~(S_IRUSR|S_IRGRP|S_IROTH);
341     if (data.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM)
342         sb->st_mode &= ~S_IRWXO; /* remove everything for other */
343     if (data.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN)
344         sb->st_mode |= S_ISVTX; /* use sticky bit -> hidden */
345
346     if (data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
347         sb->st_mode |= S_IFDIR;
348     else
349         sb->st_mode |= S_IFREG;
350
351     sb->st_nlink = 1;
352     sb->st_size = data.nFileSizeHigh;
353     sb->st_size <<= 32;
354     sb->st_size |= data.nFileSizeLow;
355     sb->st_blksize = 4096;
356     sb->st_blocks = (uint32_t)(sb->st_size + 4095)/4096;
357     sb->st_atime = cvt_ftime_to_utime(data.ftLastAccessTime);
358     sb->st_mtime = cvt_ftime_to_utime(data.ftLastWriteTime);
359     sb->st_ctime = cvt_ftime_to_utime(data.ftLastWriteTime);
360     return 0;
361 }
362
363 #endif //HAVE_MINGW
364
365 int
366 lstat(const char *file, struct stat *sb)
367 {
368     return stat(file, sb);
369 }
370
371 void
372 sleep(int sec)
373 {
374     Sleep(sec * 1000);
375 }
376
377 int
378 geteuid(void)
379 {
380     return 0;
381 }
382
383 int
384 execvp(const char *, char *[]) {
385     return -1;
386 }
387
388
389 int
390 fork(void)
391 {
392     return -1;
393 }
394
395 int
396 pipe(int[])
397 {
398     return -1;
399 }
400
401 int
402 waitpid(int, int*, int)
403 {
404     return -1;
405 }
406
407 int
408 readlink(const char *, char *, int)
409 {
410     return -1;
411 }
412
413
414 #ifndef HAVE_MINGW
415 int
416 strcasecmp(const char *s1, const char *s2)
417 {
418     register int ch1, ch2;
419
420     if (s1==s2)
421         return 0;       /* strings are equal if same object. */
422     else if (!s1)
423         return -1;
424     else if (!s2)
425         return 1;
426     do
427     {
428         ch1 = *s1;
429         ch2 = *s2;
430         s1++;
431         s2++;
432     } while (ch1 != 0 && tolower(ch1) == tolower(ch2));
433
434   return(ch1 - ch2);
435 }
436 #endif //HAVE_MINGW
437
438 int
439 strncasecmp(const char *s1, const char *s2, int len)
440 {
441     register int ch1, ch2;
442
443     if (s1==s2)
444         return 0;       /* strings are equal if same object. */
445     else if (!s1)
446         return -1;
447     else if (!s2)
448         return 1;
449     do
450     {
451         ch1 = *s1;
452         ch2 = *s2;
453         s1++;
454         s2++;
455     } while (len-- && ch1 != 0 && tolower(ch1) == tolower(ch2));
456
457     return(ch1 - ch2);
458 }
459
460 int
461 gettimeofday(struct timeval *tv, struct timezone *)
462 {
463     SYSTEMTIME now;
464     FILETIME tmp;
465     GetSystemTime(&now);
466
467     if (tv == NULL) return -1;
468     if (!SystemTimeToFileTime(&now, &tmp)) return -1;
469
470     int64_t _100nsec = tmp.dwHighDateTime;
471     _100nsec <<= 32;
472     _100nsec |= tmp.dwLowDateTime;
473     _100nsec -= WIN32_FILETIME_ADJUST;
474
475     tv->tv_sec =(long) (_100nsec / 10000000);
476     tv->tv_usec = (long) ((_100nsec % 10000000)/10);
477     return 0;
478
479 }
480
481 int
482 syslog(int type, const char *fmt, const char *msg)
483 {
484 /*#ifndef HAVE_CONSOLE
485     MessageBox(NULL, msg, "Bacula", MB_OK);
486 #endif*/
487     return 0;
488 }
489
490 struct passwd *
491 getpwuid(uid_t)
492 {
493     return NULL;
494 }
495
496 struct group *
497 getgrgid(uid_t)
498 {
499     return NULL;
500 }
501
502 // implement opendir/readdir/closedir on top of window's API
503 typedef struct _dir
504 {
505     WIN32_FIND_DATA data;       // window's file info
506     const char *spec;           // the directory we're traversing
507     HANDLE      dirh;           // the search handle
508     BOOL        valid;          // the info in data field is valid
509     UINT32      offset;         // pseudo offset for d_off
510 } _dir;
511
512 DIR *
513 opendir(const char *path)
514 {
515     int max_len = strlen(path) + 16;
516     _dir *rval = NULL;
517     if (path == NULL) return NULL;
518
519     rval = (_dir *)malloc(sizeof(_dir));
520     if (rval == NULL) return NULL;
521     char *tspec = (char *)malloc(max_len);
522     if (tspec == NULL) goto err1;
523
524     if (g_platform_id != VER_PLATFORM_WIN32_WINDOWS) {
525         // allow path to be 32767 bytes
526         tspec[0] = '\\';
527         tspec[1] = '\\';
528         tspec[2] = '?';
529         tspec[3] = '\\';
530         tspec[4] = 0;
531         cygwin_conv_to_win32_path(path, tspec+4);
532     } else {
533         cygwin_conv_to_win32_path(path, tspec);
534     }
535
536     strncat(tspec, "\\*", max_len);
537     rval->spec = tspec;
538
539     rval->dirh = FindFirstFile(rval->spec, &rval->data);
540     d_msg(__FILE__, __LINE__,
541           99, "opendir(%s)\n\tspec=%s,\n\tFindFirstFile returns %d\n",
542           path, rval->spec, rval->dirh);
543
544     rval->offset = 0;
545     if (rval->dirh == INVALID_HANDLE_VALUE)
546         goto err;
547     rval->valid = 1;
548     d_msg(__FILE__, __LINE__,
549           99, "\tFirstFile=%s\n", rval->data.cFileName);
550     return (DIR *)rval;
551 err:
552     free((void *)rval->spec);
553 err1:
554     free(rval);
555     return NULL;
556 }
557
558 int
559 closedir(DIR *dirp)
560 {
561     _dir *dp = (_dir *)dirp;
562     FindClose(dp->dirh);
563     free((void *)dp->spec);
564     free((void *)dp);
565     return 0;
566 }
567
568 /*
569   typedef struct _WIN32_FIND_DATA {
570     DWORD dwFileAttributes;
571     FILETIME ftCreationTime;
572     FILETIME ftLastAccessTime;
573     FILETIME ftLastWriteTime;
574     DWORD nFileSizeHigh;
575     DWORD nFileSizeLow;
576     DWORD dwReserved0;
577     DWORD dwReserved1;
578     TCHAR cFileName[MAX_PATH];
579     TCHAR cAlternateFileName[14];
580 } WIN32_FIND_DATA, *PWIN32_FIND_DATA;
581 */
582
583 static int
584 copyin(struct dirent &dp, const char *fname)
585 {
586     dp.d_ino = 0;
587     dp.d_reclen = 0;
588     char *cp = dp.d_name;
589     while (*fname) {
590         *cp++ = *fname++;
591         dp.d_reclen++;
592     }
593         *cp = 0;
594     return dp.d_reclen;
595 }
596
597 int
598 readdir_r(DIR *dirp, struct dirent *entry, struct dirent **result)
599 {
600
601     _dir *dp = (_dir *)dirp;
602     if (dp->valid) {
603         entry->d_off = dp->offset;
604         dp->offset += copyin(*entry, dp->data.cFileName);
605         *result = entry;              /* return entry address */
606         d_msg(__FILE__, __LINE__,
607               99, "readdir_r(%p, { d_name=\"%s\", d_reclen=%d, d_off=%d\n",
608               dirp, entry->d_name, entry->d_reclen, entry->d_off);
609     } else {
610 //      d_msg(__FILE__, __LINE__, 99, "readdir_r !valid\n");
611         return -1;
612     }
613     dp->valid = FindNextFile(dp->dirh, &dp->data);
614     return 0;
615 }
616
617 int
618 inet_aton(const char *a, struct in_addr *inp)
619 {
620
621     const char *cp = a;
622     uint32_t acc = 0, tmp = 0;
623     int dotc = 0;
624     if (!isdigit(*a)) return 0;
625     while (*cp) {
626         if (isdigit(*cp))
627             tmp = (tmp * 10) + (*cp -'0');
628         else if (*cp == '.') {
629             if (tmp > 255) return 0;
630             acc = (acc << 8) + tmp;
631             dotc++;
632         }
633         else return 0;
634     }
635
636     if (dotc != 3) return 0;
637     inp->s_addr = acc;
638     return 1;
639 }
640
641 int
642 nanosleep(const struct timespec *req, struct timespec *rem)
643 {
644     if (rem)
645         rem->tv_sec = rem->tv_nsec = 0;
646     Sleep((req->tv_sec * 1000) + (req->tv_nsec/100000));
647     return 0;
648 }
649
650 void
651 init_signals(void terminate(int sig))
652 {
653
654 }
655
656 void
657 init_stack_dump(void)
658 {
659
660 }
661
662
663 long
664 pathconf(const char *path, int name)
665 {
666     switch(name) {
667     case _PC_PATH_MAX :
668         if (strncmp(path, "\\\\?\\", 4) == 0)
669             return 32767;
670     case _PC_NAME_MAX :
671         return 255;
672     }
673
674     return -1;
675 }
676
677 int
678 WSA_Init(void)
679 {
680     WORD wVersionRequested = MAKEWORD( 1, 1);
681     WSADATA wsaData;
682
683     int err = WSAStartup(wVersionRequested, &wsaData);
684
685
686     if (err != 0)
687     {
688         printf("Can not start Windows Sockets\n");
689         return -1;
690     }
691
692     return 0;
693 }
694
695
696 int
697 win32_chdir(const char *dir)
698 {
699     if (0 == SetCurrentDirectory(dir)) return -1;
700     return 0;
701 }
702
703 char *
704 win32_getcwd(char *buf, int maxlen)
705 {
706    int n =  GetCurrentDirectory(maxlen, buf);
707
708    if (n == 0 || n > maxlen) return NULL;
709
710    if (n+1 > maxlen) return NULL;
711    if (n != 3) {
712        buf[n] = '\\';
713        buf[n+1] = 0;
714    }
715
716    return buf;
717 }
718
719 #include "mswinver.h"
720
721 char WIN_VERSION_LONG[64];
722 char WIN_VERSION[32];
723
724 class winver {
725 public:
726     winver(void);
727 };
728
729 static winver INIT;                     // cause constructor to be called before main()
730
731 #include "bacula.h"
732 #include "jcr.h"
733
734 winver::winver(void)
735 {
736     const char *version = "";
737     const char *platform = "";
738     OSVERSIONINFO osvinfo;
739     osvinfo.dwOSVersionInfoSize = sizeof(osvinfo);
740
741     // Get the current OS version
742     if (!GetVersionEx(&osvinfo)) {
743         version = "Unknown";
744         platform = "Unknown";
745     }
746     else
747         switch (_mkversion(osvinfo.dwPlatformId, osvinfo.dwMajorVersion, osvinfo.dwMinorVersion))
748         {
749         case MS_WINDOWS_95: (version =  "Windows 95"); break;
750         case MS_WINDOWS_98: (version =  "Windows 98"); break;
751         case MS_WINDOWS_ME: (version =  "Windows ME"); break;
752         case MS_WINDOWS_NT4:(version =  "Windows NT 4.0"); platform = "NT"; break;
753         case MS_WINDOWS_2K: (version =  "Windows 2000");platform = "NT"; break;
754         case MS_WINDOWS_XP: (version =  "Windows XP");platform = "NT"; break;
755         case MS_WINDOWS_S2003: (version =  "Windows Server 2003");platform = "NT"; break;
756         default: version = "Windows ??"; break;
757         }
758
759     bstrncpy(WIN_VERSION_LONG, version, sizeof(WIN_VERSION_LONG));
760     snprintf(WIN_VERSION, sizeof(WIN_VERSION), "%s %d.%d.%d",
761              platform, osvinfo.dwMajorVersion, osvinfo.dwMinorVersion, osvinfo.dwBuildNumber);
762
763 #if 0
764     HANDLE h = CreateFile("G:\\foobar", GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
765     CloseHandle(h);
766 #endif
767 #if 0
768     BPIPE *b = open_bpipe("ls -l", 10, "r");
769     char buf[1024];
770     while (!feof(b->rfd)) {
771         fgets(buf, sizeof(buf), b->rfd);
772     }
773     close_bpipe(b);
774 #endif
775 }
776
777 BOOL CreateChildProcess(VOID);
778 VOID WriteToPipe(VOID);
779 VOID ReadFromPipe(VOID);
780 VOID ErrorExit(LPTSTR);
781 VOID ErrMsg(LPTSTR, BOOL);
782
783
784 const char *
785 getArgv0(const char *cmdline)
786 {
787     const char *cp = cmdline;
788
789     while (*cp && !isspace(*cp)) cp++;
790
791     int len = cp - cmdline;
792     char *rval = (char *)malloc(len+1);
793
794     cp = cmdline;
795     char *rp = rval;
796     while (len--)
797         *rp++ = *cp++;
798
799     *rp = 0;
800     return rval;
801 }
802
803 HANDLE
804 CreateChildProcess(const char *cmdline, HANDLE in, HANDLE out, HANDLE err)
805 {
806     PROCESS_INFORMATION piProcInfo;
807     STARTUPINFO siStartInfo;
808     BOOL bFuncRetn = FALSE;
809
810     // Set up members of the PROCESS_INFORMATION structure.
811
812     ZeroMemory( &piProcInfo, sizeof(PROCESS_INFORMATION) );
813
814     // Set up members of the STARTUPINFO structure.
815
816     ZeroMemory( &siStartInfo, sizeof(STARTUPINFO) );
817     siStartInfo.cb = sizeof(STARTUPINFO);
818     // setup new process to use supplied handles for stdin,stdout,stderr
819     // if supplied handles are not used the send a copy of our STD_HANDLE
820     // as appropriate
821     siStartInfo.dwFlags = STARTF_USESTDHANDLES;
822
823     if (in != INVALID_HANDLE_VALUE)
824         siStartInfo.hStdInput = in;
825     else
826         siStartInfo.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
827
828     if (out != INVALID_HANDLE_VALUE)
829         siStartInfo.hStdOutput = out;
830     else
831         siStartInfo.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
832     if (err != INVALID_HANDLE_VALUE)
833         siStartInfo.hStdError = err;
834     else
835         siStartInfo.hStdError = GetStdHandle(STD_ERROR_HANDLE);
836     // Create the child process.
837
838     char cmdLine[1024];
839     char exeFile[1024];
840     // retrive the first compont of the command line which should be the
841     // executable
842     const char *exeName = getArgv0(cmdline);
843     // check to see if absolute path was passed to us already?
844     if (exeName[1] != ':'
845         || (strchr(cmdline, '/') == NULL
846             && strchr(cmdline, '\\') == NULL))
847     {
848         // only command name so perform search of PATH to find
849         char *file;
850         DWORD rval = SearchPath(NULL,
851                                 exeName,
852                                 ".exe",
853                                 sizeof(exeFile),
854                                 exeFile,
855                                 &file);
856         if (rval == 0)
857             return INVALID_HANDLE_VALUE;
858         if (rval > sizeof(exeFile))
859             return INVALID_HANDLE_VALUE;
860
861     }
862     else
863         strcpy(exeFile, exeName);
864
865     // exeFile now has absolute path to program to execute.
866     free((void *)exeName);
867     // copy original command line to pass to create process
868     strcpy(cmdLine, cmdline);
869     // try to execute program
870     bFuncRetn = CreateProcess(exeFile,
871                               cmdLine, // command line
872                               NULL, // process security attributes
873                               NULL, // primary thread security attributes
874                               TRUE, // handles are inherited
875                               0, // creation flags
876                               NULL, // use parent's environment
877                               NULL, // use parent's current directory
878                               &siStartInfo, // STARTUPINFO pointer
879                               &piProcInfo); // receives PROCESS_INFORMATION
880
881     if (bFuncRetn == 0) {
882         ErrorExit("CreateProcess failed\n");
883         return INVALID_HANDLE_VALUE;
884     }
885     // we don't need a handle on the process primary thread so we close
886     // this now.
887     CloseHandle(piProcInfo.hThread);
888
889     return piProcInfo.hProcess;
890 }
891
892
893 void
894 ErrorExit (LPTSTR lpszMessage)
895 {
896     d_msg(__FILE__, __LINE__, 0, "%s", lpszMessage);
897 }
898
899
900 /*
901 typedef struct s_bpipe {
902    pid_t worker_pid;
903    time_t worker_stime;
904    int wait;
905    btimer_t *timer_id;
906    FILE *rfd;
907    FILE *wfd;
908 } BPIPE;
909 */
910
911 static void
912 CloseIfValid(HANDLE handle)
913 {
914     if (handle != INVALID_HANDLE_VALUE)
915         CloseHandle(handle);
916 }
917
918 #ifndef HAVE_MINGW
919 BPIPE *
920 open_bpipe(char *prog, int wait, const char *mode)
921 {
922     HANDLE hChildStdinRd, hChildStdinWr, hChildStdinWrDup,
923         hChildStdoutRd, hChildStdoutWr, hChildStdoutRdDup,
924         hInputFile;
925
926     SECURITY_ATTRIBUTES saAttr;
927
928     BOOL fSuccess;
929
930     hChildStdinRd = hChildStdinWr = hChildStdinWrDup =
931         hChildStdoutRd = hChildStdoutWr = hChildStdoutRdDup =
932         hInputFile = INVALID_HANDLE_VALUE;
933
934     BPIPE *bpipe = (BPIPE *)malloc(sizeof(BPIPE));
935     memset((void *)bpipe, 0, sizeof(BPIPE));
936
937     int mode_read = (mode[0] == 'r');
938     int mode_write = (mode[0] == 'w' || mode[1] == 'w');
939
940
941     // Set the bInheritHandle flag so pipe handles are inherited.
942
943     saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
944     saAttr.bInheritHandle = TRUE;
945     saAttr.lpSecurityDescriptor = NULL;
946
947     if (mode_read) {
948
949         // Create a pipe for the child process's STDOUT.
950         if (! CreatePipe(&hChildStdoutRd, &hChildStdoutWr, &saAttr, 0)) {
951             ErrorExit("Stdout pipe creation failed\n");
952             goto cleanup;
953         }
954         // Create noninheritable read handle and close the inheritable read
955         // handle.
956
957         fSuccess = DuplicateHandle(GetCurrentProcess(), hChildStdoutRd,
958                                    GetCurrentProcess(), &hChildStdoutRdDup , 0,
959                                    FALSE,
960                                    DUPLICATE_SAME_ACCESS);
961         if ( !fSuccess ) {
962             ErrorExit("DuplicateHandle failed");
963             goto cleanup;
964         }
965
966         CloseHandle(hChildStdoutRd);
967     }
968
969     if (mode_write) {
970
971         // Create a pipe for the child process's STDIN.
972
973         if (!CreatePipe(&hChildStdinRd, &hChildStdinWr, &saAttr, 0)) {
974             ErrorExit("Stdin pipe creation failed\n");
975             goto cleanup;
976         }
977
978         // Duplicate the write handle to the pipe so it is not inherited.
979         fSuccess = DuplicateHandle(GetCurrentProcess(), hChildStdinWr,
980                                    GetCurrentProcess(), &hChildStdinWrDup,
981                                    0,
982                                    FALSE,                  // not inherited
983                                    DUPLICATE_SAME_ACCESS);
984         if (!fSuccess) {
985             ErrorExit("DuplicateHandle failed");
986             goto cleanup;
987         }
988
989         CloseHandle(hChildStdinWr);
990     }
991     // spawn program with redirected handles as appropriate
992     bpipe->worker_pid = (pid_t)
993         CreateChildProcess(prog,             // commandline
994                            hChildStdinRd,    // stdin HANDLE
995                            hChildStdoutWr,   // stdout HANDLE
996                            hChildStdoutWr);  // stderr HANDLE
997
998     if ((HANDLE) bpipe->worker_pid == INVALID_HANDLE_VALUE)
999         goto cleanup;
1000
1001     bpipe->wait = wait;
1002     bpipe->worker_stime = time(NULL);
1003
1004     if (mode_read) {
1005         CloseHandle(hChildStdoutWr); // close our write side so when
1006                                      // process terminates we can
1007                                      // detect eof.
1008         // ugly but convert WIN32 HANDLE to FILE*
1009         int rfd = _open_osfhandle((long)hChildStdoutRdDup, O_RDONLY);
1010         if (rfd >= 0) {
1011            bpipe->rfd = _fdopen(rfd, "r");
1012         }
1013     }
1014     if (mode_write) {
1015         CloseHandle(hChildStdinRd); // close our read side so as not
1016                                     // to interfre with child's copy
1017         // ugly but convert WIN32 HANDLE to FILE*
1018         int wfd = _open_osfhandle((long)hChildStdinWrDup, O_WRONLY);
1019         if (wfd >= 0) {
1020            bpipe->wfd = _fdopen(wfd, "w");
1021         }
1022     }
1023
1024     if (wait > 0) {
1025         bpipe->timer_id = start_child_timer(bpipe->worker_pid, wait);
1026     }
1027
1028     return bpipe;
1029
1030 cleanup:
1031
1032     CloseIfValid(hChildStdoutRd);
1033     CloseIfValid(hChildStdoutRdDup);
1034     CloseIfValid(hChildStdinWr);
1035     CloseIfValid(hChildStdinWrDup);
1036
1037     free((void *) bpipe);
1038
1039     return NULL;
1040 }
1041
1042 #endif //HAVE_MINGW
1043
1044 int
1045 kill(int pid, int signal)
1046 {
1047     int rval = 0;
1048     if (!TerminateProcess((HANDLE)pid, (UINT) signal))
1049         rval = -1;
1050     CloseHandle((HANDLE)pid);
1051     return rval;
1052 }
1053
1054 #ifndef HAVE_MINGW
1055
1056 int
1057 close_bpipe(BPIPE *bpipe)
1058 {
1059     int rval = 0;
1060     if (bpipe->rfd) fclose(bpipe->rfd);
1061     if (bpipe->wfd) fclose(bpipe->wfd);
1062
1063     if (bpipe->wait) {
1064         int remaining_wait = bpipe->wait;
1065         do {
1066             DWORD exitCode;
1067             if (!GetExitCodeProcess((HANDLE)bpipe->worker_pid, &exitCode)) {
1068                 const char *err = errorString();
1069                 rval = GetLastError();
1070                 d_msg(__FILE__, __LINE__, 0,
1071                       "GetExitCode error %s\n", err);
1072                 LocalFree((void *)err);
1073                 break;
1074             }
1075
1076             if (exitCode == STILL_ACTIVE) {
1077                 bmicrosleep(1, 0);             /* wait one second */
1078                 remaining_wait--;
1079             }
1080             else break;
1081         } while(remaining_wait);
1082     }
1083
1084     if (bpipe->timer_id) {
1085         stop_child_timer(bpipe->timer_id);
1086     }
1087     free((void *)bpipe);
1088     return rval;
1089 }
1090
1091 int
1092 close_wpipe(BPIPE *bpipe)
1093 {
1094     int stat = 1;
1095
1096     if (bpipe->wfd) {
1097         fflush(bpipe->wfd);
1098         if (fclose(bpipe->wfd) != 0) {
1099             stat = 0;
1100       }
1101         bpipe->wfd = NULL;
1102     }
1103     return stat;
1104 }
1105
1106 #include "findlib/find.h"
1107
1108 int
1109 utime(const char *fname, struct utimbuf *times)
1110 {
1111     FILETIME acc, mod;
1112     char tmpbuf[1024];
1113
1114     cygwin_conv_to_win32_path(fname, tmpbuf);
1115
1116     cvt_utime_to_ftime(times->actime, acc);
1117     cvt_utime_to_ftime(times->modtime, mod);
1118
1119     HANDLE h = CreateFile(tmpbuf,
1120                           FILE_WRITE_ATTRIBUTES,
1121                           FILE_SHARE_WRITE,
1122                           NULL,
1123                           OPEN_EXISTING,
1124                           0,
1125                           NULL);
1126
1127     if (h == INVALID_HANDLE_VALUE) {
1128         const char *err = errorString();
1129         d_msg(__FILE__, __LINE__, 99,
1130               "Cannot open file for utime(%s,...):%s\n", tmpbuf, err);
1131         LocalFree((void *)err);
1132         return -1;
1133     }
1134
1135     int rval = SetFileTime(h, NULL, &acc, &mod) ? 0 : -1;
1136
1137     CloseHandle(h);
1138
1139     return rval;
1140 }
1141
1142 #if USE_WIN32_COMPAT_IO
1143
1144 int
1145 open(const char *file, int flags, int mode)
1146 {
1147     return _open(file, flags|_O_BINARY, mode);
1148
1149 }
1150
1151 int
1152 close(int fd)
1153 {
1154     return _close(fd);
1155 }
1156
1157 #ifndef HAVE_WXCONSOLE
1158 ssize_t
1159 read(int fd, void *buf, size_t len)
1160 {
1161     return _read(fd, buf, len);
1162 }
1163
1164 ssize_t
1165 write(int fd, const void *buf, size_t len)
1166 {
1167     return _write(fd, buf, len);
1168 }
1169 #endif
1170
1171 off_t
1172 lseek(int fd, off_t offset, int whence)
1173 {
1174     return (off_t)_lseeki64(fd, offset, whence);
1175 }
1176
1177 int
1178 dup2(int fd1, int fd2)
1179 {
1180     return _dup2(fd1, fd2);
1181 }
1182 #else
1183 int
1184 open(const char *file, int flags, int mode)
1185 {
1186     DWORD access = 0;
1187     DWORD shareMode = 0;
1188     DWORD create = 0;
1189     DWORD msflags = 0;
1190     HANDLE foo;
1191     const char *remap = file;
1192
1193     if (flags & O_WRONLY) access = GENERIC_WRITE;
1194     else if (flags & O_RDWR) access = GENERIC_READ|GENERIC_WRITE;
1195     else access = GENERIC_READ;
1196
1197     if (flags & O_CREAT) create = CREATE_NEW;
1198     else create = OPEN_EXISTING;
1199
1200     if (flags & O_TRUNC) create = TRUNCATE_EXISTING;
1201
1202     if (!(flags & O_EXCL))
1203         shareMode = FILE_SHARE_DELETE|FILE_SHARE_READ|FILE_SHARE_WRITE;
1204
1205     if (flags & O_APPEND)
1206     {
1207         printf("open...APPEND not implemented yet.");
1208         exit(-1);
1209     }
1210
1211     foo = CreateFile(file, access, shareMode, NULL, create, msflags, NULL);
1212     if (INVALID_HANDLE_VALUE == foo)
1213         return(int) -1;
1214
1215     return (int)foo;
1216
1217 }
1218
1219
1220 int
1221 close(int fd)
1222 {
1223     if (!CloseHandle((HANDLE)fd))
1224         return -1;
1225
1226     return 0;
1227 }
1228
1229 ssize_t
1230 write(int fd, const void *data, size_t len)
1231 {
1232     BOOL status;
1233     DWORD bwrite;
1234     status = WriteFile((HANDLE)fd, data, len, &bwrite, NULL);
1235     if (status) return bwrite;
1236     return -1;
1237 }
1238
1239
1240 ssize_t
1241 read(int fd, void *data, size_t len)
1242 {
1243     BOOL status;
1244     DWORD bread;
1245
1246     status = ReadFile((HANDLE)fd, data, len, &bread, NULL);
1247     if (status) return bread;
1248     return -1;
1249 }
1250
1251 off_t
1252 lseek(int fd, off_t offset, int whence)
1253 {
1254     DWORD method = 0;
1255     switch (whence) {
1256     case SEEK_SET :
1257         method = FILE_BEGIN;
1258         break;
1259     case SEEK_CUR:
1260         method = FILE_CURRENT;
1261         break;
1262     case SEEK_END:
1263         method = FILE_END;
1264         break;
1265     default:
1266         return -1;
1267     }
1268
1269     return SetFilePointer((HANDLE)fd, (DWORD)offset, NULL, method);
1270 }
1271
1272 int
1273 dup2(int, int)
1274 {
1275     return -1;
1276 }
1277
1278
1279 #endif
1280
1281 #endif //HAVE_MINGW
1282
1283 #ifdef HAVE_MINGW
1284 /* syslog function, added by Nicolas Boichat */
1285 void closelog() {}
1286 #endif //HAVE_MINGW