]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/lib/bsys.c
3f6afaa3caf67c14a43d4c1b642da7be5469c67e
[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 #ifdef HAVE_WIN32
486 #undef open
487 #undef read
488 #undef write
489 #undef lseek
490 #undef close
491 #undef O_BINARY 
492 #define open _open
493 #define read _read
494 #define write _write
495 #define lseek _lseeki64
496 #define close _close
497 #define O_BINARY _O_BINARY
498 #endif
499
500 /*
501  * Open and read the state file for the daemon
502  */
503 void read_state_file(char *dir, const char *progname, int port)
504 {
505    int sfd;
506    ssize_t stat;
507    bool ok = false;
508    POOLMEM *fname = get_pool_memory(PM_FNAME);
509    struct s_state_hdr hdr;
510    int hdr_size = sizeof(hdr);
511
512    Mmsg(&fname, "%s/%s.%d.state", dir, progname, port);
513    /* If file exists, see what we have */
514 // Dmsg1(10, "O_BINARY=%d\n", O_BINARY);
515    if ((sfd = open(fname, O_RDONLY|O_BINARY)) < 0) {
516       Dmsg3(010, "Could not open state file. sfd=%d size=%d: ERR=%s\n",
517                     sfd, sizeof(hdr), strerror(errno));
518       goto bail_out;
519    }
520    if ((stat=read(sfd, &hdr, hdr_size)) != hdr_size) {
521       Dmsg4(010, "Could not read state file. sfd=%d stat=%d size=%d: ERR=%s\n",
522                     sfd, (int)stat, hdr_size, strerror(errno));
523       goto bail_out;
524    }
525    if (hdr.version != state_hdr.version) {
526       Dmsg2(010, "Bad hdr version. Wanted %d got %d\n",
527          state_hdr.version, hdr.version);
528       goto bail_out;
529    }
530    hdr.id[13] = 0;
531    if (strcmp(hdr.id, state_hdr.id) != 0) {
532       Dmsg0(000, "State file header id invalid.\n");
533       goto bail_out;
534    }
535 // Dmsg1(010, "Read header of %d bytes.\n", sizeof(hdr));
536    if (!read_last_jobs_list(sfd, hdr.last_jobs_addr)) {
537       goto bail_out;
538    }
539    ok = true;
540 bail_out:
541    if (sfd >= 0) {
542       close(sfd);
543    }
544    if (!ok) {
545       unlink(fname);
546     }
547    free_pool_memory(fname);
548 }
549
550 /*
551  * Write the state file
552  */
553 void write_state_file(char *dir, const char *progname, int port)
554 {
555    int sfd;
556    bool ok = false;
557    POOLMEM *fname = get_pool_memory(PM_FNAME);
558
559    Mmsg(&fname, "%s/%s.%d.state", dir, progname, port);
560    /* Create new state file */
561    unlink(fname);
562    if ((sfd = open(fname, O_CREAT|O_WRONLY|O_BINARY, 0640)) < 0) {
563       berrno be;
564       Dmsg2(000, "Could not create state file. %s ERR=%s\n", fname, be.strerror());
565       Emsg2(M_ERROR, 0, _("Could not create state file. %s ERR=%s\n"), fname, be.strerror());
566       goto bail_out;
567    }
568    if (write(sfd, &state_hdr, sizeof(state_hdr)) != sizeof(state_hdr)) {
569       berrno be;
570       Dmsg1(000, "Write hdr error: ERR=%s\n", be.strerror());
571       goto bail_out;
572    }
573 // Dmsg1(010, "Wrote header of %d bytes\n", sizeof(state_hdr));
574    state_hdr.last_jobs_addr = sizeof(state_hdr);
575    state_hdr.reserved[0] = write_last_jobs_list(sfd, state_hdr.last_jobs_addr);
576 // Dmsg1(010, "write last job end = %d\n", (int)state_hdr.reserved[0]);
577    if (lseek(sfd, 0, SEEK_SET) < 0) {
578       berrno be;
579       Dmsg1(000, "lseek error: ERR=%s\n", be.strerror());
580       goto bail_out;
581    }
582    if (write(sfd, &state_hdr, sizeof(state_hdr)) != sizeof(state_hdr)) {
583       berrno be;
584       Pmsg1(000, _("Write final hdr error: ERR=%s\n"), be.strerror());
585       goto bail_out;
586    }
587    ok = true;
588 // Dmsg1(010, "rewrote header = %d\n", sizeof(state_hdr));
589 bail_out:
590    if (sfd >= 0) {
591       close(sfd);
592    }
593    if (!ok) {
594       unlink(fname);
595    }
596    free_pool_memory(fname);
597 }
598
599
600 /*
601  * Drop to privilege new userid and new gid if non-NULL
602  */
603 void drop(char *uid, char *gid)
604 {
605 #ifdef HAVE_GRP_H
606    if (gid) {
607       struct group *group;
608       gid_t gr_list[1];
609
610       if ((group = getgrnam(gid)) == NULL) {
611          Emsg1(M_ERROR_TERM, 0, _("Could not find specified group: %s\n"), gid);
612       }
613       if (setgid(group->gr_gid)) {
614          Emsg1(M_ERROR_TERM, 0, _("Could not set specified group: %s\n"), gid);
615       }
616       gr_list[0] = group->gr_gid;
617       if (setgroups(1, gr_list)) {
618          Emsg1(M_ERROR_TERM, 0, _("Could not set specified group: %s\n"), gid);
619       }
620    }
621 #endif
622
623 #ifdef HAVE_PWD_H
624    if (uid) {
625       struct passwd *passw;
626       if ((passw = getpwnam(uid)) == NULL) {
627          Emsg1(M_ERROR_TERM, 0, _("Could not find specified userid: %s\n"), uid);
628       }
629       if (setuid(passw->pw_uid)) {
630          Emsg1(M_ERROR_TERM, 0, _("Could not set specified userid: %s\n"), uid);
631       }
632    }
633 #endif
634
635 }
636
637
638 /* BSDI does not have this.  This is a *poor* simulation */
639 #ifndef HAVE_STRTOLL
640 long long int
641 strtoll(const char *ptr, char **endptr, int base)
642 {
643    return (long long int)strtod(ptr, endptr);
644 }
645 #endif
646
647 /*
648  * Bacula's implementation of fgets(). The difference is that it handles
649  *   being interrupted by a signal (e.g. a SIGCHLD).
650  */
651 #undef fgetc
652 char *bfgets(char *s, int size, FILE *fd)
653 {
654    char *p = s;
655    int ch;
656    *p = 0;
657    for (int i=0; i < size-1; i++) {
658       do {
659          errno = 0;
660          ch = fgetc(fd);
661       } while (ch == -1 && (errno == EINTR || errno == EAGAIN));
662       if (ch == -1) {
663          if (i == 0) {
664             return NULL;
665          } else {
666             return s;
667          }
668       }
669       *p++ = ch;
670       *p = 0;
671       if (ch == '\r') { /* Support for Mac/Windows file format */
672          ch = fgetc(fd);
673          if (ch == '\n') { /* Windows (\r\n) */
674             *p++ = ch;
675             *p = 0;
676          }
677          else { /* Mac (\r only) */
678             (void)ungetc(ch, fd); /* Push next character back to fd */
679          }
680          break;
681       }
682       if (ch == '\n') {
683          break;
684       }
685    }
686    return s;
687 }
688
689 /*
690  * Make a "unique" filename.  It is important that if
691  *   called again with the same "what" that the result
692  *   will be identical. This allows us to use the file
693  *   without saving its name, and re-generate the name
694  *   so that it can be deleted.
695  */
696 void make_unique_filename(POOLMEM **name, int Id, char *what)
697 {
698    Mmsg(name, "%s/%s.%s.%d.tmp", working_directory, my_name, what, Id);
699 }