]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/win32/compat/compat.cpp
447971cad5ef1a2a1d877168749aa57d3f7f9448
[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 (C)2004 Raider Solutions, Inc
6 // 
7 //   This program is free software; you can redistribute it and/or
8 //   modify it under the terms of the GNU General Public License as
9 //   published by the Free Software Foundation; either version 2 of
10 //   the License, or (at your option) any later version.
11 //
12 //   This program is distributed in the hope that it will be useful,
13 //   but WITHOUT ANY WARRANTY; without even the implied warranty of
14 //   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 //   General Public License for more details.
16 //
17 //   You should have received a copy of the GNU General Public
18 //   License along with this program; if not, write to the Free
19 //   Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
20 //   MA 02111-1307, USA.
21 //
22 // Author          : Christopher S. Hull
23 // Created On      : Sat Jan 31 15:55:00 2004
24 // Last Modified By: Christopher S. Hull
25 // Last Modified On: Mon Feb  9 12:18:04 2004
26 // Update Count    : 474
27 // $Id$
28
29 #include <stdio.h>
30
31 #include "compat.h"
32 #include "pthread.h"
33
34 extern void d_msg(char *file, int line, int level, char *fmt,...);
35 extern DWORD   g_platform_id;
36
37
38 extern "C" void
39 cygwin_conv_to_win32_path(const char *name, char *win32_name)
40 {
41     while (*name) {
42         if (*name == '/')
43             *win32_name++ = '\\';
44         else
45             *win32_name++ = *name;
46         name++;
47     }
48     if (win32_name[-1] == '\\')
49         win32_name[-1] = 0;
50     else
51         *win32_name = 0;
52 }
53
54
55 int
56 open(const char *file, int flags, int mode)
57 {
58     DWORD access = 0;
59     DWORD shareMode = 0;
60     DWORD create = 0;
61     DWORD msflags = 0;
62     HANDLE foo;
63     const char *remap = file;
64
65     if (flags & O_WRONLY) access = GENERIC_WRITE;
66     else if (flags & O_RDWR) access = GENERIC_READ|GENERIC_WRITE;
67     else access = GENERIC_READ;
68     
69     if (flags & O_CREAT) create = CREATE_NEW;
70     else create = OPEN_EXISTING;
71     
72     if (flags & O_TRUNC) create = TRUNCATE_EXISTING;
73     
74     if (!(flags & O_EXCL))
75         shareMode = FILE_SHARE_DELETE|FILE_SHARE_READ|FILE_SHARE_WRITE;
76     
77     if (flags & O_APPEND)
78     {
79         printf("open...APPEND not implemented yet.");
80         exit(-1);
81     }
82     
83     foo = CreateFile(file, access, shareMode, NULL, create, msflags, NULL);
84     if (INVALID_HANDLE_VALUE == foo)
85         return(int) -1;
86
87     return (int)foo;
88
89 }
90
91
92 int
93 close(int fd)
94 {
95     if (!CloseHandle((HANDLE)fd))
96         return -1;
97
98     return 0;
99 }
100
101 int
102 write(int fd, const void *data, int32_t len)
103 {
104     BOOL status;
105     DWORD bwrite;
106     status = WriteFile((HANDLE)fd, data, len, &bwrite, NULL);
107     if (status) return bwrite;
108     return -1;
109 }
110
111
112 int
113 read(int fd, void *data, int32_t len)
114 {
115     BOOL status;
116     DWORD bread;
117
118     status = ReadFile((HANDLE)fd, data, len, &bread, NULL);
119     if (status) return bread;
120
121     return -1;
122 }
123
124 int
125 umask(int)
126 {
127     return 0;
128 }
129
130 int
131 chmod(const char *, mode_t)
132 {
133     return 0;
134 }
135
136 int
137 chown(const char *k, uid_t, gid_t)
138 {
139     return 0;
140 }
141
142 int
143 lchown(const char *k, uid_t, gid_t)
144 {
145     return 0;
146 }
147
148 int
149 utime(const char *, struct utimbuf *)
150 {
151     return -1;
152 }
153
154
155 long int
156 random(void)
157 {
158     return rand();
159 }
160
161 void
162 srandom(unsigned int seed)
163 {
164     srand(seed);
165 }
166 // /////////////////////////////////////////////////////////////////
167 // convert from Windows concept of time to Unix concept of time
168 // /////////////////////////////////////////////////////////////////
169 time_t
170 cvt(const FILETIME &time)
171 {
172     uint64_t mstime = time.dwHighDateTime;
173     mstime <<= 32;
174     mstime |= time.dwLowDateTime;
175
176     mstime /= 10000000;         // convert to seconds.
177     mstime -= 3234336I64*3600I64;               // difference between jan 1, 1601 and jan, 1 1970
178
179     return (time_t) (mstime & 0xffffffff);
180 }
181
182 static const char *
183 errorString(void)
184 {
185     LPVOID lpMsgBuf;
186
187     FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
188                   FORMAT_MESSAGE_FROM_SYSTEM |
189                   FORMAT_MESSAGE_IGNORE_INSERTS,
190                   NULL,
191                   GetLastError(),
192                   MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default lang
193                   (LPTSTR) &lpMsgBuf,
194                   0,
195                   NULL);
196
197     return (const char *) lpMsgBuf;
198 }
199
200 static int
201 statDir(const char *file, struct stat *sb)
202 {
203     WIN32_FIND_DATA info;       // window's file info
204     sb->st_mode |= S_IFDIR;
205
206     if (file[1] == ':' && file[2] == 0)
207     {
208         d_msg(__FILE__, __LINE__, 99, "faking ROOT attrs(%s).\n", file);
209         sb->st_mode |= S_IREAD|S_IEXEC|S_IWRITE;
210         time(&sb->st_ctime);
211         time(&sb->st_mtime);
212         time(&sb->st_atime);
213         return 0;
214     }
215     HANDLE h = FindFirstFile(file, &info);
216
217     if (h == INVALID_HANDLE_VALUE) {
218         const char *err = errorString();
219         d_msg(__FILE__, __LINE__, 99, "FindFirstFile(%s):%s\n", file, err);
220         LocalFree((void *)err);
221         errno = GetLastError();
222         return -1;
223     }
224
225     sb->st_mode |= (S_IREAD | S_IEXEC);
226     if (!(info.dwFileAttributes & FILE_ATTRIBUTE_READONLY))
227         sb->st_mode |= S_IWRITE;
228     
229     if (info.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM)
230         sb->st_mode |= S_IRGRP;
231     if (info.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN)
232         sb->st_mode |= S_IROTH;
233     sb->st_size = info.nFileSizeHigh;
234     sb->st_size <<= 32;
235     sb->st_size |= info.nFileSizeLow;
236     sb->st_blksize = 4096;
237     sb->st_blocks = (uint32_t)(sb->st_size + 4095)/4096;
238     sb->st_atime = cvt(info.ftLastAccessTime);
239     sb->st_mtime = cvt(info.ftLastWriteTime);
240     sb->st_ctime = cvt(info.ftCreationTime);
241
242     return 0;
243 }
244
245 static int
246 stat2(const char *file, struct stat *sb)
247 {
248     BY_HANDLE_FILE_INFORMATION info;
249     HANDLE h;
250     int rval = 0;
251     char tmpbuf[1024];
252     cygwin_conv_to_win32_path(file, tmpbuf);
253
254     DWORD attr = GetFileAttributes(tmpbuf);
255
256     if (attr == -1) {
257         const char *err = errorString();
258         d_msg(__FILE__, __LINE__, 99, "GetFileAttrubtes(%s): %s\n", tmpbuf, err);
259         LocalFree((void *)err);
260         errno = GetLastError();
261         return -1;
262     }
263     
264     if (attr & FILE_ATTRIBUTE_DIRECTORY) 
265         return statDir(tmpbuf, sb);
266
267     sb->st_mode |= S_IFREG;
268     
269     h = CreateFile(tmpbuf, GENERIC_READ,
270                    FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
271
272     if (h == INVALID_HANDLE_VALUE) {
273         const char *err = errorString();
274         d_msg(__FILE__, __LINE__, 99, "Cannot open file for stat (%s):%s\n", tmpbuf, err);
275         LocalFree((void *)err);
276         rval = -1;
277         errno = GetLastError();
278         goto error;
279     }
280     
281     if (!GetFileInformationByHandle(h, &info)) {
282         const char *err = errorString();
283         d_msg(__FILE__, __LINE__, 99, "GetfileInformationByHandle(%s): %s\n", tmpbuf, err);
284         LocalFree((void *)err);
285         rval = -1;
286         errno = GetLastError();
287         goto error;
288     }
289     
290     sb->st_dev = info.dwVolumeSerialNumber;
291     sb->st_ino = info.nFileIndexHigh;
292     sb->st_ino <<= 32;
293     sb->st_ino |= info.nFileIndexLow;
294     sb->st_nlink = (short)info.nNumberOfLinks;
295     sb->st_mode |= (S_IREAD | S_IEXEC);
296     if (!(info.dwFileAttributes & FILE_ATTRIBUTE_READONLY))
297         sb->st_mode |= S_IWRITE;
298
299     if (info.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM)
300         sb->st_mode |= S_IRGRP;
301     if (info.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN)
302         sb->st_mode |= S_IROTH;
303     sb->st_size = info.nFileSizeHigh;
304     sb->st_size <<= 32;
305     sb->st_size |= info.nFileSizeLow;
306     sb->st_blksize = 4096;
307     sb->st_blocks = (uint32_t)(sb->st_size + 4095)/4096;
308     sb->st_atime = cvt(info.ftLastAccessTime);
309     sb->st_mtime = cvt(info.ftLastWriteTime);
310     sb->st_ctime = cvt(info.ftCreationTime);
311
312 error:
313     CloseHandle(h);
314     return rval;
315 }
316 int
317 stat(const char *file, struct stat *sb)
318 {
319     WIN32_FILE_ATTRIBUTE_DATA data;
320     errno = 0;
321
322     memset(sb, 0, sizeof(*sb));
323
324     if (g_platform_id == VER_PLATFORM_WIN32_WINDOWS)
325         return stat2(file, sb);
326
327     if (!GetFileAttributesEx(file, GetFileExInfoStandard, &data))
328         return stat2(file, sb);
329
330     if (data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
331         sb->st_mode |= S_IFDIR;
332     else
333         sb->st_mode |= S_IFREG;
334
335     sb->st_nlink = 1;
336     sb->st_mode |= (S_IREAD | S_IEXEC);
337     if (!(data.dwFileAttributes & FILE_ATTRIBUTE_READONLY))
338         sb->st_mode |= S_IWRITE;
339
340     if (data.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM)
341         sb->st_mode |= S_IRGRP;
342     if (data.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN)
343         sb->st_mode |= S_IROTH;
344     sb->st_size = data.nFileSizeHigh;
345     sb->st_size <<= 32;
346     sb->st_size |= data.nFileSizeLow;
347     sb->st_blksize = 4096;
348     sb->st_blocks = (uint32_t)(sb->st_size + 4095)/4096;
349     sb->st_atime = cvt(data.ftLastAccessTime);
350     sb->st_mtime = cvt(data.ftLastWriteTime);
351     sb->st_ctime = cvt(data.ftCreationTime);
352     return 0;
353 }
354
355 int
356 lstat(const char *file, struct stat *sb)
357 {
358     return stat(file, sb);
359 }
360 void
361 sleep(int sec)
362 {
363     Sleep(sec * 1000);
364 }    
365
366 int
367 geteuid(void)
368 {
369     return 0;
370 }
371
372 int
373 execvp(const char *, char *[]) {
374     return -1;
375 }
376
377 int
378 dup2(int, int)
379 {
380     return -1;
381 }
382
383 int
384 fork(void)
385 {
386     return -1;
387 }
388
389 int
390 pipe(int[])
391 {
392     return -1;
393 }
394
395 int
396 waitpid(int, int*, int)
397 {
398     return -1;
399 }
400
401 int
402 readlink(const char *, char *, int)
403 {
404     return -1;
405 }
406
407 int
408 lseek(int fd, int offset, int whence)
409 {
410     DWORD method = 0;
411     switch (whence) {
412     case SEEK_SET :
413         method = FILE_BEGIN;
414         break;
415     case SEEK_CUR:
416         method = FILE_CURRENT;
417         break;
418     case SEEK_END:
419         method = FILE_END;
420         break;
421     default:
422         return -1;
423     }
424     
425     return SetFilePointer((HANDLE)fd, (DWORD)offset, NULL, method);
426 }
427
428 int
429 strcasecmp(const char *s1, const char *s2)
430 {
431     register int ch1, ch2;
432     
433     if (s1==s2)
434         return 0;       /* strings are equal if same object. */
435     else if (!s1)
436         return -1;
437     else if (!s2)
438         return 1;
439     do
440     {
441         ch1 = *s1;
442         ch2 = *s2;
443         s1++;
444         s2++;
445     } while (ch1 != 0 && tolower(ch1) == tolower(ch2));
446     
447   return(ch1 - ch2);
448 }
449
450 int
451 strncasecmp(const char *s1, const char *s2, int len)
452 {
453     register int ch1, ch2;
454     
455     if (s1==s2)
456         return 0;       /* strings are equal if same object. */
457     else if (!s1)
458         return -1;
459     else if (!s2)
460         return 1;
461     do
462     {
463         ch1 = *s1;
464         ch2 = *s2;
465         s1++;
466         s2++;
467     } while (len-- && ch1 != 0 && tolower(ch1) == tolower(ch2));
468     
469     return(ch1 - ch2);
470 }
471
472 int
473 gettimeofday(struct timeval *tv, struct timezone *)
474 {
475     SYSTEMTIME now;
476     FILETIME tmp;
477     GetSystemTime(&now);
478
479     if (tv == NULL) return -1;
480     if (!SystemTimeToFileTime(&now, &tmp)) return -1;
481
482     int64_t _100nsec = tmp.dwHighDateTime;
483     _100nsec <<= 32;
484     _100nsec |= tmp.dwLowDateTime;
485     _100nsec -= (3234336I64*3600I64 * 10000000I64);
486     tv->tv_sec =(long) (_100nsec / 10000000);
487     tv->tv_usec = (long) ((_100nsec % 10000000)/10);
488     return 0;
489     
490 }
491
492 int
493 syslog(int, const char *, const char *)
494 {
495     return 0;
496 }
497
498 struct passwd *
499 getpwuid(uid_t)
500 {
501     return NULL;
502 }
503 struct group *
504 getgrgid(uid_t)
505 {
506     return NULL;
507 }
508
509
510 // implement opendir/readdir/closedir on top of window's API
511 typedef struct _dir
512 {
513     WIN32_FIND_DATA data;       // window's file info
514     const char *spec;           // the directory we're traversing
515     HANDLE      dirh;           // the search handle
516     BOOL        valid;          // the info in data field is valid
517     UINT32      offset;         // pseudo offset for d_off
518 } _dir;
519
520 DIR *
521 opendir(const char *path)
522 {
523     _dir *rval = NULL;
524     if (path == NULL) return NULL;
525     
526     rval = (_dir *)malloc(sizeof(_dir));
527     if (rval == NULL) return NULL;
528     char *tspec = (char *)malloc(strlen(path)+16);
529     if (tspec == NULL) goto err1;
530     
531     if (g_platform_id != VER_PLATFORM_WIN32_WINDOWS) {
532         // allow path to be 32767 bytes
533         tspec[0] = '\\';
534         tspec[1] = '\\';
535         tspec[2] = '?';
536         tspec[3] = '\\';
537         tspec[4] = 0;
538         cygwin_conv_to_win32_path(path, tspec+4); 
539    }
540     else {
541         cygwin_conv_to_win32_path(path, tspec);
542     }
543     strcat(tspec, "\\*");
544     rval->spec = tspec;
545
546     rval->dirh = FindFirstFile(rval->spec, &rval->data);
547     d_msg(__FILE__, __LINE__,
548           99, "opendir(%s)\n\tspec=%s,\n\tFindFirstFile returns %d\n",
549           path, rval->spec, rval->dirh);
550
551     rval->offset = 0;
552     if (rval->dirh == INVALID_HANDLE_VALUE)
553         goto err;
554     rval->valid = 1;
555     d_msg(__FILE__, __LINE__,
556           99, "\tFirstFile=%s\n", rval->data.cFileName);
557     return (DIR *)rval;
558 err:
559     free((void *)rval->spec);
560 err1:
561     free(rval);
562     return NULL;
563 }
564     
565 int
566 closedir(DIR *dirp)
567 {
568     _dir *dp = (_dir *)dirp;
569     FindClose(dp->dirh);
570     free((void *)dp->spec);
571     free((void *)dp);
572     return 0;
573 }
574
575 /*
576   typedef struct _WIN32_FIND_DATA {
577     DWORD dwFileAttributes;
578     FILETIME ftCreationTime;
579     FILETIME ftLastAccessTime;
580     FILETIME ftLastWriteTime;
581     DWORD nFileSizeHigh;
582     DWORD nFileSizeLow;
583     DWORD dwReserved0;
584     DWORD dwReserved1;
585     TCHAR cFileName[MAX_PATH];
586     TCHAR cAlternateFileName[14];
587 } WIN32_FIND_DATA, *PWIN32_FIND_DATA;
588 */
589
590 static int
591 copyin(struct dirent &dp, const char *fname)
592 {
593     dp.d_ino = 0;
594     dp.d_reclen = 0;
595     char *cp = dp.d_name;
596     while (*fname) {
597         *cp++ = *fname++;
598         dp.d_reclen++;
599     }
600         *cp = 0;
601     return dp.d_reclen;
602 }
603 int
604 readdir_r(DIR *dirp, struct dirent *entry, struct dirent **result)
605 {
606
607     _dir *dp = (_dir *)dirp;
608     if (dp->valid) {
609         entry->d_off = dp->offset;
610         dp->offset += copyin(*entry, dp->data.cFileName);
611         d_msg(__FILE__, __LINE__,
612               99, "readdir_r(%p, { d_name=\"%s\", d_reclen=%d, d_off=%d\n",
613               dirp, entry->d_name, entry->d_reclen, entry->d_off);
614     }
615     else
616         return -1;
617     dp->valid = FindNextFile(dp->dirh, &dp->data);
618     return 0;
619 }
620
621
622 int
623 inet_aton(const char *a, struct in_addr *inp)
624 {
625
626     const char *cp = a;
627     uint32_t acc = 0, tmp = 0;
628     int dotc = 0;
629     if (!isdigit(*a)) return 0;
630     while (*cp) {
631         if (isdigit(*cp))
632             tmp = (tmp * 10) + (*cp -'0');
633         else if (*cp == '.') {
634             if (tmp > 255) return 0;
635             acc = (acc << 8) + tmp;
636             dotc++;
637         }
638         else return 0;
639     }
640
641     if (dotc != 3) return 0;
642     inp->s_addr = acc;
643     return 1;
644 }
645
646 int
647 nanosleep(const struct timespec *req, struct timespec *rem)
648 {
649     if (rem)
650         rem->tv_sec = rem->tv_nsec = 0;
651     Sleep((req->tv_sec * 1000) + (req->tv_nsec/100000));
652     return 0;
653 }
654
655 void
656 init_signals(void terminate(int sig))
657 {
658
659 }
660
661 void
662 init_stack_dump(void)
663 {
664
665 }
666
667
668 long
669 pathconf(const char *path, int name)
670 {
671     switch(name) {
672     case _PC_PATH_MAX :
673         if (strncmp(path, "\\\\?\\", 4) == 0)
674             return 32767;
675     case _PC_NAME_MAX :
676         return 255;
677     }
678
679     return -1;
680 }
681
682 int
683 WSA_Init(void)
684 {
685     WORD wVersionRequested = MAKEWORD( 1, 1);
686     WSADATA wsaData;
687     
688     int err = WSAStartup(wVersionRequested, &wsaData);
689     
690     
691     if (err != 0)
692     {
693         printf("Can not start Windows Sockets\n");
694         return -1;
695     }
696
697     return 0;
698 }
699
700
701 int
702 win32_chdir(const char *dir)
703 {
704     if (0 == SetCurrentDirectory(dir)) return -1;
705     return 0;
706 }
707
708 char *
709 win32_getcwd(char *buf, int maxlen)
710 {
711    int n =  GetCurrentDirectory(maxlen, buf);
712
713    if (n == 0 || n > maxlen) return NULL;
714
715    if (n+1 > maxlen) return NULL;
716    if (n != 3) {
717        buf[n] = '\\';
718        buf[n+1] = 0;
719    }
720    
721    return buf;
722 }
723
724 #include "mswinver.h"
725
726 char WIN_VERSION_LONG[64];
727 char WIN_VERSION[32];
728
729 class winver {
730 public:
731     winver(void);
732 };
733
734 static winver INIT;                     // cause constructor to be called before main()
735
736 winver::winver(void)
737 {
738     const char *version = "";
739     const char *platform = "";
740     OSVERSIONINFO osvinfo;
741     osvinfo.dwOSVersionInfoSize = sizeof(osvinfo);
742
743     // Get the current OS version
744     if (!GetVersionEx(&osvinfo)) {
745         version = "Unknown";
746         platform = "Unknown";
747     }
748     else
749         switch (_mkversion(osvinfo.dwPlatformId, osvinfo.dwMajorVersion, osvinfo.dwMinorVersion))
750         {
751         case MS_WINDOWS_95: (version =  "Windows 95"); break;
752         case MS_WINDOWS_98: (version =  "Windows 98"); break;
753         case MS_WINDOWS_ME: (version =  "Windows ME"); break;
754         case MS_WINDOWS_NT4:(version =  "Windows NT 4.0"); platform = "NT"; break;
755         case MS_WINDOWS_2K: (version =  "Windows 2000");platform = "NT"; break;
756         case MS_WINDOWS_XP: (version =  "Windows XP");platform = "NT"; break;
757         case MS_WINDOWS_S2003: (version =  "Windows Server 2003");platform = "NT"; break;
758         }
759
760     strcpy(WIN_VERSION_LONG, version);
761     snprintf(WIN_VERSION, sizeof(WIN_VERSION), "%s %d.%d.%d",
762              platform, osvinfo.dwMajorVersion, osvinfo.dwMinorVersion, osvinfo.dwBuildNumber);
763     
764 }
765
766
767
768
769
770 #define BUFSIZE 4096 
771  
772 HANDLE hChildStdinRd, hChildStdinWr, hChildStdinWrDup, 
773    hChildStdoutRd, hChildStdoutWr, hChildStdoutRdDup, 
774    hInputFile, hSaveStdin, hSaveStdout; 
775  
776 BOOL CreateChildProcess(VOID); 
777 VOID WriteToPipe(VOID); 
778 VOID ReadFromPipe(VOID); 
779 VOID ErrorExit(LPTSTR); 
780 VOID ErrMsg(LPTSTR, BOOL); 
781  
782
783 const char *getArgv0(const char *cmdline)
784 {
785     const char *cp = cmdline;
786
787     while (*cp && !isspace(*cp)) cp++;
788
789     int len = cp - cmdline;
790     char *rval = (char *)malloc(len+1);
791
792     cp = cmdline;
793     while (len--)
794         *rval++ = *cp++;
795
796     *rval = 0;
797     return rval;
798 }
799
800 HANDLE
801 CreateChildProcess(const char *cmdline) 
802
803    PROCESS_INFORMATION piProcInfo; 
804    STARTUPINFO siStartInfo;
805    BOOL bFuncRetn = FALSE; 
806  
807 // Set up members of the PROCESS_INFORMATION structure. 
808  
809    ZeroMemory( &piProcInfo, sizeof(PROCESS_INFORMATION) );
810  
811 // Set up members of the STARTUPINFO structure. 
812  
813    ZeroMemory( &siStartInfo, sizeof(STARTUPINFO) );
814    siStartInfo.cb = sizeof(STARTUPINFO); 
815  
816 // Create the child process. 
817
818    const char *exeName = getArgv0(cmdline);
819    if (exeName[1] != ':'
820        || (strchr(cmdline, '/') == NULL
821            && strchr(cmdline, '\\') == NULL))
822    {
823        char buf[1024];
824        char *file;
825        DWORD rval = SearchPath(NULL,
826                                exeName,
827                                ".exe",
828                                sizeof(buf),
829                                buf,
830                                &file);
831        if (rval == 0)
832            return INVALID_HANDLE_VALUE;
833        if (rval > sizeof(buf))
834            return INVALID_HANDLE_VALUE;
835        free((void *)exeName);
836        exeName = strdup(buf);
837    }
838
839    char *cmdLine = strdup(cmdline);
840    
841    bFuncRetn = CreateProcess(exeName, 
842                              cmdLine,       // command line 
843                              NULL,          // process security attributes 
844                              NULL,          // primary thread security attributes 
845                              TRUE,          // handles are inherited 
846                              0,             // creation flags 
847                              NULL,          // use parent's environment 
848                              NULL,          // use parent's current directory 
849                              &siStartInfo,  // STARTUPINFO pointer 
850                              &piProcInfo);  // receives PROCESS_INFORMATION
851    free((void *)exeName);
852    free((void *)cmdLine);
853    
854    if (bFuncRetn == 0) {
855        ErrorExit("CreateProcess failed\n");
856        return INVALID_HANDLE_VALUE;
857    }
858
859    CloseHandle(piProcInfo.hThread);
860    return piProcInfo.hProcess;
861 }
862  
863  
864 void
865 ErrorExit (LPTSTR lpszMessage) 
866
867     d_msg(__FILE__, __LINE__, 0, "%s", lpszMessage);
868
869  
870
871 /*
872 typedef struct s_bpipe {
873    pid_t worker_pid;
874    time_t worker_stime;
875    int wait;
876    btimer_t *timer_id;
877    FILE *rfd;
878    FILE *wfd;
879 } BPIPE;
880 */
881
882 #include "bacula.h"
883 #include "jcr.h"
884 extern "C" {
885 int __cdecl _open_osfhandle(long, int);
886 }
887 BPIPE *
888 open_bpipe(char *prog, int wait, char *mode)
889 {
890     HANDLE hChildStdinRd, hChildStdinWr, hChildStdinWrDup, 
891         hChildStdoutRd, hChildStdoutWr, hChildStdoutRdDup, 
892         hInputFile, hSaveStdin, hSaveStdout; 
893
894
895     SECURITY_ATTRIBUTES saAttr; 
896     BOOL fSuccess; 
897
898     hChildStdinRd = hChildStdinWr = hChildStdinWrDup = 
899         hChildStdoutRd = hChildStdoutWr = hChildStdoutRdDup = 
900         hInputFile = hSaveStdin = hSaveStdout = INVALID_HANDLE_VALUE;
901     
902     BPIPE *bpipe = (BPIPE *)malloc(sizeof(BPIPE));
903     memset((void *)bpipe, 0, sizeof(BPIPE));
904
905     int mode_read = (mode[0] == 'r');
906     int mode_write = (mode[0] == 'w' || mode[1] == 'w');
907
908    
909     // Set the bInheritHandle flag so pipe handles are inherited. 
910    
911    saAttr.nLength = sizeof(SECURITY_ATTRIBUTES); 
912    saAttr.bInheritHandle = TRUE; 
913    saAttr.lpSecurityDescriptor = NULL; 
914
915    // Save the handle to the current STDOUT. 
916    hSaveStdout = GetStdHandle(STD_OUTPUT_HANDLE); 
917    
918
919    if (mode_read) {
920        // Create a pipe for the child process's STDOUT. 
921        if (! CreatePipe(&hChildStdoutRd, &hChildStdoutWr, &saAttr, 0)) {
922            ErrorExit("Stdout pipe creation failed\n");
923            goto cleanup;
924        }
925        
926        // Set a write handle to the pipe to be STDOUT. 
927        if (! SetStdHandle(STD_OUTPUT_HANDLE, hChildStdoutWr))
928        {
929            ErrorExit("Redirecting STDOUT failed");
930            goto cleanup;
931        }
932        // Create noninheritable read handle and close the inheritable read 
933        // handle. 
934        
935        fSuccess = DuplicateHandle(GetCurrentProcess(), hChildStdoutRd,
936                                   GetCurrentProcess(), &hChildStdoutRdDup , 0,
937                                   FALSE,
938                                   DUPLICATE_SAME_ACCESS);
939        if( !fSuccess ) {
940            ErrorExit("DuplicateHandle failed");
941            goto cleanup;
942        }
943
944        CloseHandle(hChildStdoutRd);
945    }
946
947    if (mode_write) {
948 // Save the handle to the current STDIN. 
949        
950        hSaveStdin = GetStdHandle(STD_INPUT_HANDLE); 
951        
952 // Create a pipe for the child process's STDIN. 
953        
954        if (! CreatePipe(&hChildStdinRd, &hChildStdinWr, &saAttr, 0)) {
955            ErrorExit("Stdin pipe creation failed\n");
956            goto cleanup;
957        }
958        
959 // Set a read handle to the pipe to be STDIN. 
960        
961        if (! SetStdHandle(STD_INPUT_HANDLE, hChildStdinRd)) {
962            ErrorExit("Redirecting Stdin failed");
963            goto cleanup;
964        }
965        
966 // Duplicate the write handle to the pipe so it is not inherited. 
967        
968        fSuccess = DuplicateHandle(GetCurrentProcess(), hChildStdinWr, 
969                                   GetCurrentProcess(), &hChildStdinWrDup, 0, 
970                                   FALSE,                  // not inherited 
971                                   DUPLICATE_SAME_ACCESS); 
972        if (!fSuccess) {
973            ErrorExit("DuplicateHandle failed");
974            goto cleanup;
975        }
976        
977        CloseHandle(hChildStdinWr); 
978    }
979
980    bpipe->worker_pid = (pid_t)CreateChildProcess(prog);
981
982    bpipe->wait = wait;
983    bpipe->worker_stime = time(NULL);
984
985    if (mode_read) {
986        SetStdHandle(STD_OUTPUT_HANDLE, hSaveStdout);
987        int rfd = _open_osfhandle((long)hChildStdoutRdDup, O_RDONLY);
988        bpipe->rfd = fdopen(rfd, "r");
989    }
990    if (mode_write) {
991        SetStdHandle(STD_INPUT_HANDLE, hSaveStdin);
992        int wfd = _open_osfhandle((long)hChildStdinWrDup, O_WRONLY);
993        bpipe->wfd = fdopen(wfd, "w");
994    }
995
996    if (wait > 0) {
997        bpipe->timer_id = start_child_timer(bpipe->worker_pid, wait);
998    }
999
1000
1001    return bpipe;
1002
1003 cleanup: 
1004    free((void *) bpipe);
1005    return NULL;
1006 }
1007
1008 int kill(int pid, int signal)
1009 {
1010     int rval = 0;
1011     if (!TerminateProcess((HANDLE)pid, (UINT) signal))
1012         rval = -1;
1013
1014     CloseHandle((HANDLE)pid);
1015     return rval;
1016 }
1017
1018 int close_bpipe(BPIPE *bpipe)
1019 {
1020
1021     return 0;
1022 }
1023
1024 int close_wpipe(BPIPE *bpipe)
1025 {
1026
1027     return 0;
1028 }