]> git.sur5r.net Git - bacula/bacula/blobdiff - bacula/src/findlib/namedpipe.c
Restore win32 dir from Branch-5.2 and update it
[bacula/bacula] / bacula / src / findlib / namedpipe.c
diff --git a/bacula/src/findlib/namedpipe.c b/bacula/src/findlib/namedpipe.c
new file mode 100644 (file)
index 0000000..92b2558
--- /dev/null
@@ -0,0 +1,338 @@
+/*
+   Bacula(R) - The Network Backup Solution
+
+   Copyright (C) 2000-2018 Kern Sibbald
+
+   The original author of Bacula is Kern Sibbald, with contributions
+   from many others, a complete list can be found in the file AUTHORS.
+
+   You may use this file and others of this release according to the
+   license defined in the LICENSE file, which includes the Affero General
+   Public License, v3.0 ("AGPLv3") and some additional permissions and
+   terms pursuant to its AGPLv3 Section 7.
+
+   This notice must be preserved when any source code is
+   conveyed and/or propagated.
+
+   Bacula(R) is a registered trademark of Kern Sibbald.
+*/
+
+#ifdef HAVE_WIN32
+
+# include <windows.h> 
+# include <conio.h>
+# include <stdbool.h>
+
+#else  /* !HAVE_WIN32 */
+
+# include <sys/stat.h>
+# include <unistd.h>
+# include <errno.h>
+# include <stdlib.h>
+# include <string.h>
+
+#endif  /* HAVE_WIN32 */
+
+/* Common include */
+#include <stdio.h>
+#include <sys/types.h>
+#include <fcntl.h>
+
+#include "namedpipe.h"
+
+#ifdef TEST_PROGRAM
+# define Dmsg(level, ...) printf(__VA_ARGS__ ) 
+#endif
+
+#ifdef HAVE_WIN32
+
+void namedpipe_init(NamedPipe *self)
+{
+   self->fd   = INVALID_HANDLE_VALUE;
+   self->ifd  = -1;
+}
+
+void namedpipe_free(NamedPipe *self)
+{
+   if (self->fd != INVALID_HANDLE_VALUE) {
+      CloseHandle(self->fd);
+      self->fd = INVALID_HANDLE_VALUE;
+      self->ifd = -1;
+   }
+}
+#define BUFSIZE 8192
+int namedpipe_create(NamedPipe *self, const char *path, mode_t mode)
+{
+   /* On windows,  */
+   self->fd = CreateNamedPipeA( 
+      path,                     // pipe name 
+      PIPE_ACCESS_DUPLEX,       // read/write access 
+      PIPE_TYPE_MESSAGE |       // message type pipe 
+      PIPE_READMODE_MESSAGE |   // message-read mode 
+      PIPE_WAIT,                // blocking mode 
+      PIPE_UNLIMITED_INSTANCES, // max. instances  
+      BUFSIZE,                  // output buffer size 
+      BUFSIZE,                  // input buffer size 
+      0,                        // client time-out 
+      NULL);                    // default security attribute 
+   
+   if (self->fd == INVALID_HANDLE_VALUE) {
+      Dmsg(10, "CreateNamedPipe failed, ERR=%d.\n", (int)GetLastError()); 
+      return -1;
+   }
+   
+   return 0;
+}
+
+int namedpipe_open(NamedPipe *self, const char *path, mode_t mode)
+{
+   bool fConnected=false;
+   int  retry = 30;
+
+   if (self->fd != INVALID_HANDLE_VALUE) { /* server mode */
+
+      fConnected = ConnectNamedPipe(self->fd, NULL) ? 
+         TRUE : (GetLastError() == ERROR_PIPE_CONNECTED); 
+
+   } else {                               /* client mode */
+
+      /* Need to wait for creation */
+      while (retry-- > 0)
+      { 
+         self->fd = CreateFileA( 
+            path,               // pipe name 
+            GENERIC_WRITE | GENERIC_READ,
+            0,              // no sharing 
+            NULL,           // default security attributes
+            OPEN_EXISTING,  // opens existing pipe 
+            0,              // default attributes 
+            NULL);          // no template file 
+         
+         // Break if the pipe handle is valid. 
+         if (self->fd != INVALID_HANDLE_VALUE) {
+            break; 
+         }
+
+         /* Wait a little bit for the other side to create the fifo */
+         if (GetLastError() == ERROR_FILE_NOT_FOUND) {
+            Dmsg(10, "File not found, ERR=%d.\n", (int)GetLastError()); 
+            Sleep(20000);
+            continue;
+         }
+
+         // Exit if an error other than ERROR_PIPE_BUSY occurs. 
+         if (GetLastError() != ERROR_PIPE_BUSY) {
+            Dmsg(10, "CreateFile failed, ERR=%d.\n", 
+                 (int)GetLastError()); 
+            return -1;
+         }
+         // All pipe instances are busy, so wait for 20 seconds. 
+         if (!WaitNamedPipeA(path, 20000)) { 
+            Dmsg(10, "WaitNamedPipe failed, ERR=%d.\n", 
+                 (int)GetLastError()); 
+            return -1;
+         } 
+      } 
+   }
+
+   DWORD dwMode = PIPE_READMODE_MESSAGE; 
+   
+   fConnected = SetNamedPipeHandleState( 
+      self->fd, // pipe handle 
+      &dwMode,  // new pipe mode 
+      NULL,     // don't set maximum bytes 
+      NULL);    // don't set maximum time 
+
+   if (!fConnected) {
+      Dmsg(10, "SetNamedPipeHandleState failed, ERR=%d.\n", 
+           (int)GetLastError()); 
+   }
+
+   if (fConnected) {
+      int m = 0;
+      if (mode & O_WRONLY || mode & O_APPEND) {
+         m |= O_APPEND;
+         
+      } else if (mode & O_RDONLY) {
+         m |= O_RDONLY;
+      }
+      self->ifd = _open_osfhandle((intptr_t)self->fd, m);
+   }
+
+   return self->ifd;
+}
+
+
+#else  /* !HAVE_WIN32 */
+
+void namedpipe_init(NamedPipe *self)
+{
+   self->fd   = -1;
+   self->ifd  = -1;
+   self->name = NULL;
+}
+
+void namedpipe_free(NamedPipe *self)
+{
+   if (self->fd != -1) {
+      close(self->fd);
+      self->fd  = -1;
+      self->ifd = -1;
+   }
+   if (self->name) {
+      unlink(self->name);
+      free(self->name);
+      self->name = NULL;
+   }
+}
+
+int namedpipe_create(NamedPipe *self, const char *path, mode_t mode)
+{
+   self->name = (char *)malloc(strlen(path) + 1);
+   strcpy(self->name, path);
+
+   if (mkfifo(path, mode) < 0 && errno != EEXIST) {
+      return -1;
+   }
+
+   return 0;
+}
+
+int namedpipe_open(NamedPipe *self, const char *path, mode_t mode)
+{
+   self->ifd = self->fd = open(path, mode);
+   return self->fd;
+}
+
+#endif  /* HAVE_WIN32 */
+
+#ifdef TEST_PROGRAM
+
+#include <string.h>
+#include <stdlib.h>
+
+#define BUF  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \
+             "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \
+             "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \
+             "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \
+             "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \
+             "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \
+             "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \
+             "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \
+             "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n"
+
+int main(int argc, char **argv)
+{
+   FILE *fp;
+   NamedPipe p;
+   char buf[65*1024], file[128];
+   int fd;
+   int mode;
+   int n, m, o;
+   if (argc < 4) {
+      printf("Usage: %s client|server pipe file\n", argv[0]);
+      exit(3);
+   }
+
+   namedpipe_init(&p);
+
+   if (strcmp(argv[1], "server") == 0) {
+      mode = O_WRONLY;
+      if (namedpipe_create(&p, argv[2], 0600) < 0) {
+         exit(2);
+      }
+
+   } else {
+      mode = O_RDONLY;
+   }
+
+   printf("Trying to open %s mode=%d\n", argv[2], mode);
+   fd = namedpipe_open(&p, argv[2], mode);
+
+   if (fd < 0) {
+      printf("Unable to open pipe\n");
+      exit(1);
+   }
+
+   if (strcmp(argv[1], "server") == 0) {
+      if (write(fd, BUF, strlen(BUF)+1) != strlen(BUF)+1) {
+         printf("Unable to write data\n");
+         exit(4);
+      }
+      
+      if (write(fd, BUF, strlen(BUF)+1) != strlen(BUF)+1) {
+         printf("Unable to write data\n");
+         exit(4);
+      }
+
+      fp = fopen(argv[3], "rb");
+      if (!fp) {
+         printf("Unable to open %s for reading\n", argv[3]);
+         exit(4);
+      }
+
+      fseek(fp, 0, SEEK_END);
+      m = ftell(fp);
+      fseek(fp, 0, SEEK_SET);
+
+      snprintf(buf, sizeof(buf), "%.10d\n", m);
+      write(fd, buf, strlen(buf)+1);
+
+      while (m > 0 && !feof(fp)) {
+         n = fread(buf, 1, sizeof(buf), fp);
+         Dmsg(000, "read %d from file\n", n);
+         if (write(fd, buf, n) != n) {
+            printf("Unable to write data from file\n");
+            exit(5);
+         }
+         m -= n;
+      }
+      Dmsg(000, "EOF found\n");
+      fclose(fp);
+
+   } else {
+      if ((n = read(fd, buf, sizeof(buf))) != strlen(BUF)+1) {
+         Dmsg(000, "read failed (%d != %d), ERR=%d.\n", n, 
+              (int)strlen(BUF)+1, errno); 
+         exit(4);
+      }
+      if (read(fd, buf, sizeof(buf)) != strlen(BUF)+1) {
+         Dmsg(000, "read failed, ERR=%d.\n", errno); 
+         exit(4);
+      }
+
+      printf("buf=[%s]\n", buf);
+
+      snprintf(file, sizeof(file), "%s.out", argv[3]);
+      fp = fopen(file, "wb");
+      if (!fp) {
+         printf("Unable to open %s for writing\n", buf);
+         exit(4);
+      }
+
+      if ((n = read(fd, buf, sizeof(buf))) != 12) {
+         Dmsg(000, "read failed (%d != %d), ERR=%d.\n", n, 12, errno); 
+         exit(4);
+      }
+
+      m = atoi(buf);
+      Dmsg(000, "will read %d from fifo\n", m);
+
+      while (m > 0) {
+         n = read(fd, buf, sizeof(buf));
+         Dmsg(000, "Got %d bytes\n", n);
+         if ((o = fwrite(buf, n, 1, fp)) != 1) {
+            Dmsg(000, "write to file failed (%d != %d) ERR=%d.\n", o, n, errno); 
+            exit(4);
+         }
+         m -= n;
+      }
+      fclose(fp);
+   }
+
+   namedpipe_free(&p);
+
+   exit(0);
+}
+#endif