]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/findlib/namedpipe.c
Restore win32 dir from Branch-5.2 and update it
[bacula/bacula] / bacula / src / findlib / namedpipe.c
1 /*
2    Bacula(R) - The Network Backup Solution
3
4    Copyright (C) 2000-2018 Kern Sibbald
5
6    The original author of Bacula is Kern Sibbald, with contributions
7    from many others, a complete list can be found in the file AUTHORS.
8
9    You may use this file and others of this release according to the
10    license defined in the LICENSE file, which includes the Affero General
11    Public License, v3.0 ("AGPLv3") and some additional permissions and
12    terms pursuant to its AGPLv3 Section 7.
13
14    This notice must be preserved when any source code is
15    conveyed and/or propagated.
16
17    Bacula(R) is a registered trademark of Kern Sibbald.
18 */
19
20 #ifdef HAVE_WIN32
21
22 # include <windows.h> 
23 # include <conio.h>
24 # include <stdbool.h>
25
26 #else  /* !HAVE_WIN32 */
27
28 # include <sys/stat.h>
29 # include <unistd.h>
30 # include <errno.h>
31 # include <stdlib.h>
32 # include <string.h>
33
34 #endif  /* HAVE_WIN32 */
35
36 /* Common include */
37 #include <stdio.h>
38 #include <sys/types.h>
39 #include <fcntl.h>
40
41 #include "namedpipe.h"
42
43 #ifdef TEST_PROGRAM
44 # define Dmsg(level, ...) printf(__VA_ARGS__ ) 
45 #endif
46
47 #ifdef HAVE_WIN32
48
49 void namedpipe_init(NamedPipe *self)
50 {
51    self->fd   = INVALID_HANDLE_VALUE;
52    self->ifd  = -1;
53 }
54
55 void namedpipe_free(NamedPipe *self)
56 {
57    if (self->fd != INVALID_HANDLE_VALUE) {
58       CloseHandle(self->fd);
59       self->fd = INVALID_HANDLE_VALUE;
60       self->ifd = -1;
61    }
62 }
63 #define BUFSIZE 8192
64 int namedpipe_create(NamedPipe *self, const char *path, mode_t mode)
65 {
66    /* On windows,  */
67    self->fd = CreateNamedPipeA( 
68       path,                     // pipe name 
69       PIPE_ACCESS_DUPLEX,       // read/write access 
70       PIPE_TYPE_MESSAGE |       // message type pipe 
71       PIPE_READMODE_MESSAGE |   // message-read mode 
72       PIPE_WAIT,                // blocking mode 
73       PIPE_UNLIMITED_INSTANCES, // max. instances  
74       BUFSIZE,                  // output buffer size 
75       BUFSIZE,                  // input buffer size 
76       0,                        // client time-out 
77       NULL);                    // default security attribute 
78    
79    if (self->fd == INVALID_HANDLE_VALUE) {
80       Dmsg(10, "CreateNamedPipe failed, ERR=%d.\n", (int)GetLastError()); 
81       return -1;
82    }
83    
84    return 0;
85 }
86
87 int namedpipe_open(NamedPipe *self, const char *path, mode_t mode)
88 {
89    bool fConnected=false;
90    int  retry = 30;
91
92    if (self->fd != INVALID_HANDLE_VALUE) { /* server mode */
93
94       fConnected = ConnectNamedPipe(self->fd, NULL) ? 
95          TRUE : (GetLastError() == ERROR_PIPE_CONNECTED); 
96
97    } else {                               /* client mode */
98
99       /* Need to wait for creation */
100       while (retry-- > 0)
101       { 
102          self->fd = CreateFileA( 
103             path,               // pipe name 
104             GENERIC_WRITE | GENERIC_READ,
105             0,              // no sharing 
106             NULL,           // default security attributes
107             OPEN_EXISTING,  // opens existing pipe 
108             0,              // default attributes 
109             NULL);          // no template file 
110          
111          // Break if the pipe handle is valid. 
112          if (self->fd != INVALID_HANDLE_VALUE) {
113             break; 
114          }
115
116          /* Wait a little bit for the other side to create the fifo */
117          if (GetLastError() == ERROR_FILE_NOT_FOUND) {
118             Dmsg(10, "File not found, ERR=%d.\n", (int)GetLastError()); 
119             Sleep(20000);
120             continue;
121          }
122
123          // Exit if an error other than ERROR_PIPE_BUSY occurs. 
124          if (GetLastError() != ERROR_PIPE_BUSY) {
125             Dmsg(10, "CreateFile failed, ERR=%d.\n", 
126                  (int)GetLastError()); 
127             return -1;
128          }
129  
130          // All pipe instances are busy, so wait for 20 seconds. 
131          if (!WaitNamedPipeA(path, 20000)) { 
132             Dmsg(10, "WaitNamedPipe failed, ERR=%d.\n", 
133                  (int)GetLastError()); 
134             return -1;
135          } 
136       } 
137    }
138
139    DWORD dwMode = PIPE_READMODE_MESSAGE; 
140    
141    fConnected = SetNamedPipeHandleState( 
142       self->fd, // pipe handle 
143       &dwMode,  // new pipe mode 
144       NULL,     // don't set maximum bytes 
145       NULL);    // don't set maximum time 
146
147    if (!fConnected) {
148       Dmsg(10, "SetNamedPipeHandleState failed, ERR=%d.\n", 
149            (int)GetLastError()); 
150    }
151
152    if (fConnected) {
153       int m = 0;
154       if (mode & O_WRONLY || mode & O_APPEND) {
155          m |= O_APPEND;
156          
157       } else if (mode & O_RDONLY) {
158          m |= O_RDONLY;
159       }
160       self->ifd = _open_osfhandle((intptr_t)self->fd, m);
161    }
162
163    return self->ifd;
164 }
165
166
167 #else  /* !HAVE_WIN32 */
168
169 void namedpipe_init(NamedPipe *self)
170 {
171    self->fd   = -1;
172    self->ifd  = -1;
173    self->name = NULL;
174 }
175
176 void namedpipe_free(NamedPipe *self)
177 {
178    if (self->fd != -1) {
179       close(self->fd);
180       self->fd  = -1;
181       self->ifd = -1;
182    }
183    if (self->name) {
184       unlink(self->name);
185       free(self->name);
186       self->name = NULL;
187    }
188 }
189
190 int namedpipe_create(NamedPipe *self, const char *path, mode_t mode)
191 {
192    self->name = (char *)malloc(strlen(path) + 1);
193    strcpy(self->name, path);
194
195    if (mkfifo(path, mode) < 0 && errno != EEXIST) {
196       return -1;
197    }
198
199    return 0;
200 }
201
202 int namedpipe_open(NamedPipe *self, const char *path, mode_t mode)
203 {
204    self->ifd = self->fd = open(path, mode);
205    return self->fd;
206 }
207
208 #endif  /* HAVE_WIN32 */
209
210 #ifdef TEST_PROGRAM
211
212 #include <string.h>
213 #include <stdlib.h>
214
215 #define BUF  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \
216              "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \
217              "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \
218              "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \
219              "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \
220              "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \
221              "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \
222              "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \
223              "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n"
224
225 int main(int argc, char **argv)
226 {
227    FILE *fp;
228    NamedPipe p;
229    char buf[65*1024], file[128];
230    int fd;
231    int mode;
232    int n, m, o;
233    if (argc < 4) {
234       printf("Usage: %s client|server pipe file\n", argv[0]);
235       exit(3);
236    }
237
238    namedpipe_init(&p);
239
240    if (strcmp(argv[1], "server") == 0) {
241       mode = O_WRONLY;
242       if (namedpipe_create(&p, argv[2], 0600) < 0) {
243          exit(2);
244       }
245
246    } else {
247       mode = O_RDONLY;
248    }
249
250    printf("Trying to open %s mode=%d\n", argv[2], mode);
251    fd = namedpipe_open(&p, argv[2], mode);
252
253    if (fd < 0) {
254       printf("Unable to open pipe\n");
255       exit(1);
256    }
257
258    if (strcmp(argv[1], "server") == 0) {
259       if (write(fd, BUF, strlen(BUF)+1) != strlen(BUF)+1) {
260          printf("Unable to write data\n");
261          exit(4);
262       }
263       
264       if (write(fd, BUF, strlen(BUF)+1) != strlen(BUF)+1) {
265          printf("Unable to write data\n");
266          exit(4);
267       }
268
269       fp = fopen(argv[3], "rb");
270       if (!fp) {
271          printf("Unable to open %s for reading\n", argv[3]);
272          exit(4);
273       }
274
275       fseek(fp, 0, SEEK_END);
276       m = ftell(fp);
277       fseek(fp, 0, SEEK_SET);
278
279       snprintf(buf, sizeof(buf), "%.10d\n", m);
280       write(fd, buf, strlen(buf)+1);
281
282       while (m > 0 && !feof(fp)) {
283          n = fread(buf, 1, sizeof(buf), fp);
284          Dmsg(000, "read %d from file\n", n);
285          if (write(fd, buf, n) != n) {
286             printf("Unable to write data from file\n");
287             exit(5);
288          }
289          m -= n;
290       }
291       Dmsg(000, "EOF found\n");
292       fclose(fp);
293
294    } else {
295       if ((n = read(fd, buf, sizeof(buf))) != strlen(BUF)+1) {
296          Dmsg(000, "read failed (%d != %d), ERR=%d.\n", n, 
297               (int)strlen(BUF)+1, errno); 
298          exit(4);
299       }
300       if (read(fd, buf, sizeof(buf)) != strlen(BUF)+1) {
301          Dmsg(000, "read failed, ERR=%d.\n", errno); 
302          exit(4);
303       }
304
305       printf("buf=[%s]\n", buf);
306
307       snprintf(file, sizeof(file), "%s.out", argv[3]);
308       fp = fopen(file, "wb");
309       if (!fp) {
310          printf("Unable to open %s for writing\n", buf);
311          exit(4);
312       }
313
314       if ((n = read(fd, buf, sizeof(buf))) != 12) {
315          Dmsg(000, "read failed (%d != %d), ERR=%d.\n", n, 12, errno); 
316          exit(4);
317       }
318
319       m = atoi(buf);
320       Dmsg(000, "will read %d from fifo\n", m);
321
322       while (m > 0) {
323          n = read(fd, buf, sizeof(buf));
324          Dmsg(000, "Got %d bytes\n", n);
325          if ((o = fwrite(buf, n, 1, fp)) != 1) {
326             Dmsg(000, "write to file failed (%d != %d) ERR=%d.\n", o, n, errno); 
327             exit(4);
328          }
329          m -= n;
330       }
331       fclose(fp);
332    }
333
334    namedpipe_free(&p);
335
336    exit(0);
337 }
338 #endif