]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/lib/bsys.c
Remove SQLite2 scripts
[bacula/bacula] / bacula / src / lib / bsys.c
1 /*
2    Bacula® - The Network Backup Solution
3
4    Copyright (C) 2000-2008 Free Software Foundation Europe e.V.
5
6    The main author of Bacula is Kern Sibbald, with contributions from
7    many others, a complete list can be found in the file AUTHORS.
8    This program is Free Software; you can redistribute it and/or
9    modify it under the terms of version two of the GNU General Public
10    License as published by the Free Software Foundation and included
11    in the file LICENSE.
12
13    This program is distributed in the hope that it will be useful, but
14    WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16    General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21    02110-1301, USA.
22
23    Bacula® is a registered trademark of Kern Sibbald.
24    The licensor of Bacula is the Free Software Foundation Europe
25    (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
26    Switzerland, email:ftf@fsfeurope.org.
27 */
28 /*
29  * Miscellaneous Bacula memory and thread safe routines
30  *   Generally, these are interfaces to system or standard
31  *   library routines.
32  *
33  *  Bacula utility functions are in util.c
34  *
35  *   Version $Id$
36  */
37
38 #include "bacula.h"
39
40
41 static pthread_mutex_t timer_mutex = PTHREAD_MUTEX_INITIALIZER;
42 static pthread_cond_t timer = PTHREAD_COND_INITIALIZER;
43
44 /*
45  * This routine will sleep (sec, microsec).  Note, however, that if a
46  *   signal occurs, it will return early.  It is up to the caller
47  *   to recall this routine if he/she REALLY wants to sleep the
48  *   requested time.
49  */
50 int bmicrosleep(int32_t sec, int32_t usec)
51 {
52    struct timespec timeout;
53    struct timeval tv;
54    struct timezone tz;
55    int stat;
56
57    timeout.tv_sec = sec;
58    timeout.tv_nsec = usec * 1000;
59
60 #ifdef HAVE_NANOSLEEP
61    stat = nanosleep(&timeout, NULL);
62    if (!(stat < 0 && errno == ENOSYS)) {
63       return stat;
64    }
65    /* If we reach here it is because nanosleep is not supported by the OS */
66 #endif
67
68    /* Do it the old way */
69    gettimeofday(&tv, &tz);
70    timeout.tv_nsec += tv.tv_usec * 1000;
71    timeout.tv_sec += tv.tv_sec;
72    while (timeout.tv_nsec >= 1000000000) {
73       timeout.tv_nsec -= 1000000000;
74       timeout.tv_sec++;
75    }
76
77    Dmsg2(200, "pthread_cond_timedwait sec=%lld usec=%d\n", sec, usec);
78    /* Note, this unlocks mutex during the sleep */
79    P(timer_mutex);
80    stat = pthread_cond_timedwait(&timer, &timer_mutex, &timeout);
81    if (stat != 0) {
82       berrno be;
83       Dmsg2(200, "pthread_cond_timedwait stat=%d ERR=%s\n", stat,
84          be.bstrerror(stat));
85    }
86    V(timer_mutex);
87    return stat;
88 }
89
90 /*
91  * Guarantee that the string is properly terminated */
92 char *bstrncpy(char *dest, const char *src, int maxlen)
93 {
94    strncpy(dest, src, maxlen-1);
95    dest[maxlen-1] = 0;
96    return dest;
97 }
98
99 /*
100  * Guarantee that the string is properly terminated */
101 char *bstrncpy(char *dest, POOL_MEM &src, int maxlen)
102 {
103    strncpy(dest, src.c_str(), maxlen-1);
104    dest[maxlen-1] = 0;
105    return dest;
106 }
107
108
109 char *bstrncat(char *dest, const char *src, int maxlen)
110 {
111    strncat(dest, src, maxlen-1);
112    dest[maxlen-1] = 0;
113    return dest;
114 }
115
116 char *bstrncat(char *dest, POOL_MEM &src, int maxlen)
117 {
118    strncat(dest, src.c_str(), maxlen-1);
119    dest[maxlen-1] = 0;
120    return dest;
121 }
122
123 /*
124  * Allows one or both pointers to be NULL
125  */
126 bool bstrcmp(const char *s1, const char *s2)
127 {
128    if (s1 == s2) return true;
129    if (s1 == NULL || s2 == NULL) return false;
130    return strcmp(s1, s2) == 0;
131 }
132
133 /*
134  * Get character length of UTF-8 string
135  *
136  * Valid UTF-8 codes
137  * U-00000000 - U-0000007F: 0xxxxxxx 
138  * U-00000080 - U-000007FF: 110xxxxx 10xxxxxx 
139  * U-00000800 - U-0000FFFF: 1110xxxx 10xxxxxx 10xxxxxx 
140  * U-00010000 - U-001FFFFF: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx 
141  * U-00200000 - U-03FFFFFF: 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 
142  * U-04000000 - U-7FFFFFFF: 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
143  */
144 int cstrlen(const char *str)
145 {
146    uint8_t *p = (uint8_t *)str;
147    int len = 0;
148    while (*p) {
149       if ((*p & 0xC0) != 0xC0) {
150          p++;
151          len++;
152          continue;
153       }
154       if ((*p & 0xD0) == 0xC0) {
155          p += 2;
156          len++;
157          continue;
158       }
159       if ((*p & 0xF0) == 0xD0) {
160          p += 3;
161          len++;
162          continue;
163       }
164       if ((*p & 0xF8) == 0xF0) {
165          p += 4;
166          len++;
167          continue;
168       }
169       if ((*p & 0xFC) == 0xF8) {
170          p += 5;
171          len++;
172          continue;
173       }
174       if ((*p & 0xFE) == 0xFC) {
175          p += 6;
176          len++;
177          continue;
178       }
179       p++;                      /* Shouln't get here but must advance */
180    }
181    return len;
182 }
183
184
185
186 #ifndef bmalloc
187 void *bmalloc(size_t size)
188 {
189   void *buf;
190
191 #ifdef SMARTALLOC
192   buf = sm_malloc(file, line, size);
193 #else
194   buf = malloc(size);
195 #endif
196   if (buf == NULL) {
197      berrno be;
198      Emsg1(M_ABORT, 0, _("Out of memory: ERR=%s\n"), be.bstrerror());
199   }
200   return buf;
201 }
202 #endif
203
204 void *b_malloc(const char *file, int line, size_t size)
205 {
206   void *buf;
207
208 #ifdef SMARTALLOC
209   buf = sm_malloc(file, line, size);
210 #else
211   buf = malloc(size);
212 #endif
213   if (buf == NULL) {
214      berrno be;
215      e_msg(file, line, M_ABORT, 0, _("Out of memory: ERR=%s\n"), be.bstrerror());
216   }
217   return buf;
218 }
219
220
221 void bfree(void *buf)
222 {
223 #ifdef SMARTALLOC
224   sm_free(__FILE__, __LINE__, buf);
225 #else
226   free(buf);
227 #endif
228 }
229
230 void *brealloc (void *buf, size_t size)
231 {
232 #ifdef SMARTALOC
233    buf = sm_realloc(__FILE__, __LINE__, buf, size);
234 #else
235    buf = realloc(buf, size);
236 #endif
237    if (buf == NULL) {
238       berrno be;
239       Emsg1(M_ABORT, 0, _("Out of memory: ERR=%s\n"), be.bstrerror());
240    }
241    return buf;
242 }
243
244
245 void *bcalloc(size_t size1, size_t size2)
246 {
247   void *buf;
248
249    buf = calloc(size1, size2);
250    if (buf == NULL) {
251       berrno be;
252       Emsg1(M_ABORT, 0, _("Out of memory: ERR=%s\n"), be.bstrerror());
253    }
254    return buf;
255 }
256
257 /* Code now in src/lib/bsnprintf.c */
258 #ifndef USE_BSNPRINTF
259
260 #define BIG_BUF 5000
261 /*
262  * Implement snprintf
263  */
264 int bsnprintf(char *str, int32_t size, const char *fmt,  ...)
265 {
266    va_list   arg_ptr;
267    int len;
268
269    va_start(arg_ptr, fmt);
270    len = bvsnprintf(str, size, fmt, arg_ptr);
271    va_end(arg_ptr);
272    return len;
273 }
274
275 /*
276  * Implement vsnprintf()
277  */
278 int bvsnprintf(char *str, int32_t size, const char  *format, va_list ap)
279 {
280 #ifdef HAVE_VSNPRINTF
281    int len;
282    len = vsnprintf(str, size, format, ap);
283    str[size-1] = 0;
284    return len;
285
286 #else
287
288    int len, buflen;
289    char *buf;
290    buflen = size > BIG_BUF ? size : BIG_BUF;
291    buf = get_memory(buflen);
292    len = vsprintf(buf, format, ap);
293    if (len >= buflen) {
294       Emsg0(M_ABORT, 0, _("Buffer overflow.\n"));
295    }
296    memcpy(str, buf, len);
297    str[len] = 0;                /* len excludes the null */
298    free_memory(buf);
299    return len;
300 #endif
301 }
302 #endif /* USE_BSNPRINTF */
303
304 #ifndef HAVE_LOCALTIME_R
305
306 struct tm *localtime_r(const time_t *timep, struct tm *tm)
307 {
308     static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
309     struct tm *ltm,
310
311     P(mutex);
312     ltm = localtime(timep);
313     if (ltm) {
314        memcpy(tm, ltm, sizeof(struct tm));
315     }
316     V(mutex);
317     return ltm ? tm : NULL;
318 }
319 #endif /* HAVE_LOCALTIME_R */
320
321 #ifndef HAVE_READDIR_R
322 #ifndef HAVE_WIN32
323 #include <dirent.h>
324
325 int readdir_r(DIR *dirp, struct dirent *entry, struct dirent **result)
326 {
327     static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
328     struct dirent *ndir;
329     int stat;
330
331     P(mutex);
332     errno = 0;
333     ndir = readdir(dirp);
334     stat = errno;
335     if (ndir) {
336        memcpy(entry, ndir, sizeof(struct dirent));
337        strcpy(entry->d_name, ndir->d_name);
338        *result = entry;
339     } else {
340        *result = NULL;
341     }
342     V(mutex);
343     return stat;
344
345 }
346 #endif
347 #endif /* HAVE_READDIR_R */
348
349
350 int b_strerror(int errnum, char *buf, size_t bufsiz)
351 {
352     static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
353     int stat = 0;
354     const char *msg;
355
356     P(mutex);
357
358     msg = strerror(errnum);
359     if (!msg) {
360        msg = _("Bad errno");
361        stat = -1;
362     }
363     bstrncpy(buf, msg, bufsiz);
364     V(mutex);
365     return stat;
366 }
367
368 #ifdef DEBUG_MEMSET
369 /* These routines are not normally turned on */
370 #undef memset
371 void b_memset(const char *file, int line, void *mem, int val, size_t num)
372 {
373    /* Testing for 2000 byte zero at beginning of Volume block */
374    if (num > 1900 && num < 3000) {
375       Pmsg3(000, _("Memset for %d bytes at %s:%d\n"), (int)num, file, line);
376    }
377    memset(mem, val, num);
378 }
379 #endif
380
381 #if !defined(HAVE_WIN32)
382 static int del_pid_file_ok = FALSE;
383 #endif
384
385 /*
386  * Create a standard "Unix" pid file.
387  */
388 void create_pid_file(char *dir, const char *progname, int port)
389 {
390 #if !defined(HAVE_WIN32)
391    int pidfd, len;
392    int oldpid;
393    char  pidbuf[20];
394    POOLMEM *fname = get_pool_memory(PM_FNAME);
395    struct stat statp;
396
397    Mmsg(&fname, "%s/%s.%d.pid", dir, progname, port);
398    if (stat(fname, &statp) == 0) {
399       /* File exists, see what we have */
400       *pidbuf = 0;
401       if ((pidfd = open(fname, O_RDONLY|O_BINARY, 0)) < 0 ||
402            read(pidfd, &pidbuf, sizeof(pidbuf)) < 0 ||
403            sscanf(pidbuf, "%d", &oldpid) != 1) {
404          berrno be;
405          Emsg2(M_ERROR_TERM, 0, _("Cannot open pid file. %s ERR=%s\n"), fname, 
406                be.bstrerror());
407       }
408       /* Some OSes (IRIX) don't bother to clean out the old pid files after a crash, and
409        * since they use a deterministic algorithm for assigning PIDs, we can have
410        * pid conflicts with the old PID file after a reboot.
411        * The intent the following code is to check if the oldpid read from the pid
412        * file is the same as the currently executing process's pid,
413        * and if oldpid == getpid(), skip the attempt to
414        * kill(oldpid,0), since the attempt is guaranteed to succeed,
415        * but the success won't actually mean that there is an
416        * another Bacula process already running.
417        * For more details see bug #797.
418        */
419        if ((oldpid != (int)getpid()) && (kill(oldpid, 0) != -1 || errno != ESRCH)) {
420          Emsg3(M_ERROR_TERM, 0, _("%s is already running. pid=%d\nCheck file %s\n"),
421                progname, oldpid, fname);
422       }
423       /* He is not alive, so take over file ownership */
424       unlink(fname);                  /* remove stale pid file */
425    }
426    /* Create new pid file */
427    if ((pidfd = open(fname, O_CREAT|O_TRUNC|O_WRONLY|O_BINARY, 0640)) >= 0) {
428       len = sprintf(pidbuf, "%d\n", (int)getpid());
429       write(pidfd, pidbuf, len);
430       close(pidfd);
431       del_pid_file_ok = TRUE;         /* we created it so we can delete it */
432    } else {
433       berrno be;
434       Emsg2(M_ERROR_TERM, 0, _("Could not open pid file. %s ERR=%s\n"), fname, 
435             be.bstrerror());
436    }
437    free_pool_memory(fname);
438 #endif
439 }
440
441
442 /*
443  * Delete the pid file if we created it
444  */
445 int delete_pid_file(char *dir, const char *progname, int port)
446 {
447 #if !defined(HAVE_WIN32)
448    POOLMEM *fname = get_pool_memory(PM_FNAME);
449
450    if (!del_pid_file_ok) {
451       free_pool_memory(fname);
452       return 0;
453    }
454    del_pid_file_ok = FALSE;
455    Mmsg(&fname, "%s/%s.%d.pid", dir, progname, port);
456    unlink(fname);
457    free_pool_memory(fname);
458 #endif
459    return 1;
460 }
461
462 struct s_state_hdr {
463    char id[14];
464    int32_t version;
465    uint64_t last_jobs_addr;
466    uint64_t reserved[20];
467 };
468
469 static struct s_state_hdr state_hdr = {
470    "Bacula State\n",
471    4,
472    0
473 };
474
475 /*
476  * Open and read the state file for the daemon
477  */
478 void read_state_file(char *dir, const char *progname, int port)
479 {
480    int sfd;
481    ssize_t stat;
482    bool ok = false;
483    POOLMEM *fname = get_pool_memory(PM_FNAME);
484    struct s_state_hdr hdr;
485    int hdr_size = sizeof(hdr);
486
487    Mmsg(&fname, "%s/%s.%d.state", dir, progname, port);
488    /* If file exists, see what we have */
489 // Dmsg1(10, "O_BINARY=%d\n", O_BINARY);
490    if ((sfd = open(fname, O_RDONLY|O_BINARY)) < 0) {
491       berrno be;
492       Dmsg3(010, "Could not open state file. sfd=%d size=%d: ERR=%s\n",
493                     sfd, sizeof(hdr), be.bstrerror());
494       goto bail_out;
495    }
496    if ((stat=read(sfd, &hdr, hdr_size)) != hdr_size) {
497       berrno be;
498       Dmsg4(010, "Could not read state file. sfd=%d stat=%d size=%d: ERR=%s\n",
499                     sfd, (int)stat, hdr_size, be.bstrerror());
500       goto bail_out;
501    }
502    if (hdr.version != state_hdr.version) {
503       Dmsg2(010, "Bad hdr version. Wanted %d got %d\n",
504          state_hdr.version, hdr.version);
505       goto bail_out;
506    }
507    hdr.id[13] = 0;
508    if (strcmp(hdr.id, state_hdr.id) != 0) {
509       Dmsg0(000, "State file header id invalid.\n");
510       goto bail_out;
511    }
512 // Dmsg1(010, "Read header of %d bytes.\n", sizeof(hdr));
513    if (!read_last_jobs_list(sfd, hdr.last_jobs_addr)) {
514       goto bail_out;
515    }
516    ok = true;
517 bail_out:
518    if (sfd >= 0) {
519       close(sfd);
520    }
521    if (!ok) {
522       unlink(fname);
523     }
524    free_pool_memory(fname);
525 }
526
527 /*
528  * Write the state file
529  */
530 void write_state_file(char *dir, const char *progname, int port)
531 {
532    int sfd;
533    bool ok = false;
534    POOLMEM *fname = get_pool_memory(PM_FNAME);
535
536    Mmsg(&fname, "%s/%s.%d.state", dir, progname, port);
537    /* Create new state file */
538    unlink(fname);
539    if ((sfd = open(fname, O_CREAT|O_WRONLY|O_BINARY, 0640)) < 0) {
540       berrno be;
541       Dmsg2(000, "Could not create state file. %s ERR=%s\n", fname, be.bstrerror());
542       Emsg2(M_ERROR, 0, _("Could not create state file. %s ERR=%s\n"), fname, be.bstrerror());
543       goto bail_out;
544    }
545    if (write(sfd, &state_hdr, sizeof(state_hdr)) != sizeof(state_hdr)) {
546       berrno be;
547       Dmsg1(000, "Write hdr error: ERR=%s\n", be.bstrerror());
548       goto bail_out;
549    }
550 // Dmsg1(010, "Wrote header of %d bytes\n", sizeof(state_hdr));
551    state_hdr.last_jobs_addr = sizeof(state_hdr);
552    state_hdr.reserved[0] = write_last_jobs_list(sfd, state_hdr.last_jobs_addr);
553 // Dmsg1(010, "write last job end = %d\n", (int)state_hdr.reserved[0]);
554    if (lseek(sfd, 0, SEEK_SET) < 0) {
555       berrno be;
556       Dmsg1(000, "lseek error: ERR=%s\n", be.bstrerror());
557       goto bail_out;
558    }
559    if (write(sfd, &state_hdr, sizeof(state_hdr)) != sizeof(state_hdr)) {
560       berrno be;
561       Pmsg1(000, _("Write final hdr error: ERR=%s\n"), be.bstrerror());
562       goto bail_out;
563    }
564    ok = true;
565 // Dmsg1(010, "rewrote header = %d\n", sizeof(state_hdr));
566 bail_out:
567    if (sfd >= 0) {
568       close(sfd);
569    }
570    if (!ok) {
571       unlink(fname);
572    }
573    free_pool_memory(fname);
574 }
575
576
577 /* BSDI does not have this.  This is a *poor* simulation */
578 #ifndef HAVE_STRTOLL
579 long long int
580 strtoll(const char *ptr, char **endptr, int base)
581 {
582    return (long long int)strtod(ptr, endptr);
583 }
584 #endif
585
586 /*
587  * Bacula's implementation of fgets(). The difference is that it handles
588  *   being interrupted by a signal (e.g. a SIGCHLD).
589  */
590 #undef fgetc
591 char *bfgets(char *s, int size, FILE *fd)
592 {
593    char *p = s;
594    int ch;
595    *p = 0;
596    for (int i=0; i < size-1; i++) {
597       do {
598          errno = 0;
599          ch = fgetc(fd);
600       } while (ch == EOF && ferror(fd) && (errno == EINTR || errno == EAGAIN));
601       if (ch == EOF) {
602          if (i == 0) {
603             return NULL;
604          } else {
605             return s;
606          }
607       }
608       *p++ = ch;
609       *p = 0;
610       if (ch == '\r') { /* Support for Mac/Windows file format */
611          ch = fgetc(fd);
612          if (ch != '\n') { /* Mac (\r only) */
613             (void)ungetc(ch, fd); /* Push next character back to fd */
614          }
615          p[-1] = '\n';
616          break;
617       }
618       if (ch == '\n') {
619          break;
620       }
621    }
622    return s;
623 }
624
625 /*
626  * Make a "unique" filename.  It is important that if
627  *   called again with the same "what" that the result
628  *   will be identical. This allows us to use the file
629  *   without saving its name, and re-generate the name
630  *   so that it can be deleted.
631  */
632 void make_unique_filename(POOLMEM **name, int Id, char *what)
633 {
634    Mmsg(name, "%s/%s.%s.%d.tmp", working_directory, my_name, what, Id);
635 }
636
637 char *escape_filename(const char *file_path)
638 {
639    if (file_path == NULL || strpbrk(file_path, "\"\\") == NULL) {
640       return NULL;
641    }
642
643    char *escaped_path = (char *)bmalloc(2 * (strlen(file_path) + 1));
644    char *cur_char = escaped_path;
645
646    while (*file_path) {
647       if (*file_path == '\\' || *file_path == '"') {
648          *cur_char++ = '\\';
649       }
650
651       *cur_char++ = *file_path++;
652    }
653
654    *cur_char = '\0';
655
656    return escaped_path;
657 }