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