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