]> git.sur5r.net Git - bacula/bacula/blobdiff - bacula/src/lib/bsys.c
Work on state file. Add popup if Abort on Windows. Attempt cleaner shutdown
[bacula/bacula] / bacula / src / lib / bsys.c
index da3fd7c1761713ab4d8fa8ebe164b5d4ed4315a4..13a5f8295b71fe8f586a28424344e48bff9c4ed2 100644 (file)
@@ -66,7 +66,7 @@ void *bmalloc(size_t size)
 }
 #endif
 
-void *b_malloc(char *file, int line, size_t size)
+void *b_malloc(const char *file, int line, size_t size)
 {
   void *buf;
 
@@ -108,7 +108,7 @@ void *bcalloc (size_t size1, size_t size2)
 /*
  * Implement snprintf
  */
-int bsnprintf(char *str, size_t size, const  char  *fmt,  ...) 
+int bsnprintf(char *str, int32_t size, const char *fmt,  ...) 
 {
 #ifdef HAVE_VSNPRINTF
    va_list   arg_ptr;
@@ -143,7 +143,7 @@ int bsnprintf(char *str, size_t size, const  char  *fmt,  ...)
 /*
  * Implement vsnprintf()
  */
-int bvsnprintf(char *str, size_t size, const char  *format, va_list ap)
+int bvsnprintf(char *str, int32_t size, const char  *format, va_list ap)
 {
 #ifdef HAVE_VSNPRINTF
    int len;
@@ -190,7 +190,7 @@ struct tm *localtime_r(const time_t *timep, struct tm *tm)
 #endif /* HAVE_LOCALTIME_R */
 
 #ifndef HAVE_READDIR_R
-
+#ifndef HAVE_WIN32
 #include <dirent.h>
 
 int readdir_r(DIR *dirp, struct dirent *entry, struct dirent **result)
@@ -217,8 +217,9 @@ int readdir_r(DIR *dirp, struct dirent *entry, struct dirent **result)
     }
     V(mutex);
     return stat;
-}
 
+}
+#endif
 #endif /* HAVE_READDIR_R */
 
 #ifdef xxxxxxxxxx_STRERROR_R
@@ -282,16 +283,16 @@ void _v(char *file, int line, pthread_mutex_t *m)
 }
 #endif /* DEBUG_MUTEX */
 
-#ifndef HAVE_CYGWIN
+#if !defined(HAVE_CYGWIN) && !defined(HAVE_WIN32)
 static int del_pid_file_ok = FALSE;
 #endif
 
 /*
  * Create a standard "Unix" pid file.
  */
-void create_pid_file(char *dir, char *progname, int port)
+void create_pid_file(char *dir, const char *progname, int port)
 {
-#ifndef HAVE_CYGWIN
+#if !defined(HAVE_CYGWIN) && !defined(HAVE_WIN32)
    int pidfd, len;
    int oldpid;
    char  pidbuf[20];
@@ -328,12 +329,13 @@ void create_pid_file(char *dir, char *progname, int port)
 #endif
 }
 
+
 /*
  * Delete the pid file if we created it
  */
-int delete_pid_file(char *dir, char *progname, int port)
+int delete_pid_file(char *dir, const char *progname, int port)
 {
-#ifndef HAVE_CYGWIN
+#if !defined(HAVE_CYGWIN)  && !defined(HAVE_WIN32)
    POOLMEM *fname = get_pool_memory(PM_FNAME);
 
    if (!del_pid_file_ok) {
@@ -348,6 +350,84 @@ int delete_pid_file(char *dir, char *progname, int port)
    return 1;
 }
 
+struct s_state_hdr {
+   char id[14];
+   int32_t version;
+   uint64_t last_jobs_addr;
+   uint64_t reserved[20];
+};
+
+static struct s_state_hdr state_hdr = { 
+   "Bacula State\n",
+   3,
+   0
+};
+
+/*
+ * Open and read the state file for the daemon
+ */
+void read_state_file(char *dir, const char *progname, int port)
+{
+   int sfd;
+   POOLMEM *fname = get_pool_memory(PM_FNAME);
+   struct s_state_hdr hdr;
+
+   Mmsg(&fname, "%s/%s.%d.state", dir, progname, port);
+   /* If file exists, see what we have */
+   if ((sfd = open(mp_chr(fname), O_RDONLY, 0)) < 0 ||
+       read(sfd, &hdr, sizeof(hdr)) < 0 ||
+       hdr.version != state_hdr.version) {
+      Dmsg2(000, "Could not open or read state file. sfd=%d: ERR=%s\n", 
+                   sfd, strerror(errno));
+      goto bail_out;
+   }
+   hdr.id[13] = 0;
+   if (strcmp(hdr.id, state_hdr.id) != 0) {
+      Dmsg0(000, "State file header invalid.\n");
+      goto bail_out;
+   }
+   read_last_jobs_list(sfd, hdr.last_jobs_addr);
+bail_out:
+   if (sfd >= 0) {
+      close(sfd);
+   }
+   free_pool_memory(fname);
+}
+
+/*
+ * Write the state file
+ */
+void write_state_file(char *dir, const char *progname, int port)
+{
+   int sfd;
+   POOLMEM *fname = get_pool_memory(PM_FNAME);
+
+   Mmsg(&fname, "%s/%s.%d.state", dir, progname, port);
+   /* Create new state file */
+   if ((sfd = open(mp_chr(fname), O_CREAT | O_TRUNC | O_WRONLY, 0640)) < 0) {
+      Dmsg2(000, _("Could not create state file. %s ERR=%s\n"), fname, strerror(errno));
+      Emsg2(M_ERROR, 0, _("Could not create state file. %s ERR=%s\n"), fname, strerror(errno));
+      goto bail_out;
+   }
+   if (write(sfd, &state_hdr, sizeof(state_hdr)) < 0) {
+      Dmsg1(000, "Write error: ERR=%s\n", strerror(errno));
+      goto bail_out;
+   }
+   state_hdr.last_jobs_addr = sizeof(state_hdr);
+   state_hdr.reserved[0] = write_last_jobs_list(sfd, state_hdr.last_jobs_addr);   
+   if (lseek(sfd, 0, SEEK_SET) < 0) {
+      Dmsg1(000, "lseek error: ERR=%s\n", strerror(errno));
+      goto bail_out;
+   }  
+   write(sfd, &state_hdr, sizeof(state_hdr));
+bail_out:
+   if (sfd >= 0) {
+      close(sfd);
+   }
+   free_pool_memory(fname);
+}
+
+
 /*
  * Drop to privilege new userid and new gid if non-NULL
  */
@@ -389,12 +469,12 @@ static pthread_mutex_t timer_mutex = PTHREAD_MUTEX_INITIALIZER;
 static pthread_cond_t timer = PTHREAD_COND_INITIALIZER;
 
 /*
- * This routine will sleep (sec, msec).  Note, however, that if a 
+ * This routine will sleep (sec, microsec).  Note, however, that if a 
  *   signal occurs, it will return early.  It is up to the caller
  *   to recall this routine if he/she REALLY wants to sleep the
  *   requested time.
  */
-int bmicrosleep(time_t sec, long msec)
+int bmicrosleep(time_t sec, long usec)
 {
    struct timespec timeout;
    struct timeval tv;
@@ -402,7 +482,7 @@ int bmicrosleep(time_t sec, long msec)
    int stat;
 
    timeout.tv_sec = sec;
-   timeout.tv_nsec = msec * 1000;
+   timeout.tv_nsec = usec * 1000;
 
 #ifdef HAVE_NANOSLEEP
    stat = nanosleep(&timeout, NULL);