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