]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/lib/bsys.c
Integrate most of the MinGW changes -- more to do.
[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    if ((errstat=pthread_mutex_trylock(m)) == 0) {
371       berrno be;
372       e_msg(file, line, M_ERROR, 0, _("Mutex unlock not locked. ERR=%s\n"),
373            be.strerror(errstat));
374     }
375     if ((errstat=pthread_mutex_unlock(m))) {
376        berrno be;
377        e_msg(file, line, M_ABORT, 0, _("Mutex unlock failure. ERR=%s\n"),
378               be.strerror(errstat));
379     }
380 }
381
382 #else
383
384 void _p(pthread_mutex_t *m)
385 {
386    int errstat;
387    if ((errstat=pthread_mutex_lock(m))) {
388       berrno be;
389       e_msg(__FILE__, __LINE__, M_ABORT, 0, _("Mutex lock failure. ERR=%s\n"),
390             be.strerror(errstat));
391    }
392 }
393
394 void _v(pthread_mutex_t *m)
395 {
396    int errstat;
397    if ((errstat=pthread_mutex_unlock(m))) {
398       berrno be;
399       e_msg(__FILE__, __LINE__, M_ABORT, 0, _("Mutex unlock failure. ERR=%s\n"),
400             be.strerror(errstat));
401    }
402 }
403
404 #endif /* DEBUG_MUTEX */
405
406 #ifdef DEBUG_MEMSET
407 /* These routines are not normally turned on */
408 #undef memset
409 void b_memset(const char *file, int line, void *mem, int val, size_t num)
410 {
411    /* Testing for 2000 byte zero at beginning of Volume block */
412    if (num > 1900 && num < 3000) {
413       Pmsg3(000, _("Memset for %d bytes at %s:%d\n"), (int)num, file, line);
414    }
415    memset(mem, val, num);
416 }
417 #endif
418
419 #if !defined(HAVE_CYGWIN) && !defined(HAVE_WIN32)
420 static int del_pid_file_ok = FALSE;
421 #endif
422
423 /*
424  * Create a standard "Unix" pid file.
425  */
426 void create_pid_file(char *dir, const char *progname, int port)
427 {
428 #if !defined(HAVE_CYGWIN) && !defined(HAVE_WIN32)
429    int pidfd, len;
430    int oldpid;
431    char  pidbuf[20];
432    POOLMEM *fname = get_pool_memory(PM_FNAME);
433    struct stat statp;
434
435    Mmsg(&fname, "%s/%s.%d.pid", dir, progname, port);
436    if (stat(fname, &statp) == 0) {
437       /* File exists, see what we have */
438       *pidbuf = 0;
439       if ((pidfd = open(fname, O_RDONLY|O_BINARY, 0)) < 0 ||
440            read(pidfd, &pidbuf, sizeof(pidbuf)) < 0 ||
441            sscanf(pidbuf, "%d", &oldpid) != 1) {
442          Emsg2(M_ERROR_TERM, 0, _("Cannot open pid file. %s ERR=%s\n"), fname, strerror(errno));
443       }
444       /* See if other Bacula is still alive */
445       if (kill(oldpid, 0) != -1 || errno != ESRCH) {
446          Emsg3(M_ERROR_TERM, 0, _("%s is already running. pid=%d\nCheck file %s\n"),
447                progname, oldpid, fname);
448       }
449       /* He is not alive, so take over file ownership */
450       unlink(fname);                  /* remove stale pid file */
451    }
452    /* Create new pid file */
453    if ((pidfd = open(fname, O_CREAT|O_TRUNC|O_WRONLY|O_BINARY, 0640)) >= 0) {
454       len = sprintf(pidbuf, "%d\n", (int)getpid());
455       write(pidfd, pidbuf, len);
456       close(pidfd);
457       del_pid_file_ok = TRUE;         /* we created it so we can delete it */
458    } else {
459       Emsg2(M_ERROR_TERM, 0, _("Could not open pid file. %s ERR=%s\n"), fname, strerror(errno));
460    }
461    free_pool_memory(fname);
462 #endif
463 }
464
465
466 /*
467  * Delete the pid file if we created it
468  */
469 int delete_pid_file(char *dir, const char *progname, int port)
470 {
471 #if !defined(HAVE_CYGWIN)  && !defined(HAVE_WIN32)
472    POOLMEM *fname = get_pool_memory(PM_FNAME);
473
474    if (!del_pid_file_ok) {
475       free_pool_memory(fname);
476       return 0;
477    }
478    del_pid_file_ok = FALSE;
479    Mmsg(&fname, "%s/%s.%d.pid", dir, progname, port);
480    unlink(fname);
481    free_pool_memory(fname);
482 #endif
483    return 1;
484 }
485
486 struct s_state_hdr {
487    char id[14];
488    int32_t version;
489    uint64_t last_jobs_addr;
490    uint64_t reserved[20];
491 };
492
493 static struct s_state_hdr state_hdr = {
494    "Bacula State\n",
495    3,
496    0
497 };
498
499 #ifdef HAVE_WIN32
500 #undef open
501 #undef read
502 #undef write
503 #undef lseek
504 #undef close
505 #undef O_BINARY 
506 #define open _open
507 #define read _read
508 #define write _write
509 #define lseek _lseeki64
510 #define close _close
511 #define O_BINARY _O_BINARY
512 #endif
513
514 /*
515  * Open and read the state file for the daemon
516  */
517 void read_state_file(char *dir, const char *progname, int port)
518 {
519    int sfd;
520    ssize_t stat;
521    bool ok = false;
522    POOLMEM *fname = get_pool_memory(PM_FNAME);
523    struct s_state_hdr hdr;
524    int hdr_size = sizeof(hdr);
525
526    Mmsg(&fname, "%s/%s.%d.state", dir, progname, port);
527    /* If file exists, see what we have */
528 // Dmsg1(10, "O_BINARY=%d\n", O_BINARY);
529    if ((sfd = open(fname, O_RDONLY|O_BINARY)) < 0) {
530       Dmsg3(010, "Could not open state file. sfd=%d size=%d: ERR=%s\n",
531                     sfd, sizeof(hdr), strerror(errno));
532       goto bail_out;
533    }
534    if ((stat=read(sfd, &hdr, hdr_size)) != hdr_size) {
535       Dmsg4(010, "Could not read state file. sfd=%d stat=%d size=%d: ERR=%s\n",
536                     sfd, (int)stat, hdr_size, strerror(errno));
537       goto bail_out;
538    }
539    if (hdr.version != state_hdr.version) {
540       Dmsg2(010, "Bad hdr version. Wanted %d got %d\n",
541          state_hdr.version, hdr.version);
542       goto bail_out;
543    }
544    hdr.id[13] = 0;
545    if (strcmp(hdr.id, state_hdr.id) != 0) {
546       Dmsg0(000, "State file header id invalid.\n");
547       goto bail_out;
548    }
549 // Dmsg1(010, "Read header of %d bytes.\n", sizeof(hdr));
550    if (!read_last_jobs_list(sfd, hdr.last_jobs_addr)) {
551       goto bail_out;
552    }
553    ok = true;
554 bail_out:
555    if (sfd >= 0) {
556       close(sfd);
557    }
558    if (!ok) {
559       unlink(fname);
560     }
561    free_pool_memory(fname);
562 }
563
564 /*
565  * Write the state file
566  */
567 void write_state_file(char *dir, const char *progname, int port)
568 {
569    int sfd;
570    bool ok = false;
571    POOLMEM *fname = get_pool_memory(PM_FNAME);
572
573    Mmsg(&fname, "%s/%s.%d.state", dir, progname, port);
574    /* Create new state file */
575    unlink(fname);
576    if ((sfd = open(fname, O_CREAT|O_WRONLY|O_BINARY, 0640)) < 0) {
577       berrno be;
578       Dmsg2(000, "Could not create state file. %s ERR=%s\n", fname, be.strerror());
579       Emsg2(M_ERROR, 0, _("Could not create state file. %s ERR=%s\n"), fname, be.strerror());
580       goto bail_out;
581    }
582    if (write(sfd, &state_hdr, sizeof(state_hdr)) != sizeof(state_hdr)) {
583       berrno be;
584       Dmsg1(000, "Write hdr error: ERR=%s\n", be.strerror());
585       goto bail_out;
586    }
587 // Dmsg1(010, "Wrote header of %d bytes\n", sizeof(state_hdr));
588    state_hdr.last_jobs_addr = sizeof(state_hdr);
589    state_hdr.reserved[0] = write_last_jobs_list(sfd, state_hdr.last_jobs_addr);
590 // Dmsg1(010, "write last job end = %d\n", (int)state_hdr.reserved[0]);
591    if (lseek(sfd, 0, SEEK_SET) < 0) {
592       berrno be;
593       Dmsg1(000, "lseek error: ERR=%s\n", be.strerror());
594       goto bail_out;
595    }
596    if (write(sfd, &state_hdr, sizeof(state_hdr)) != sizeof(state_hdr)) {
597       berrno be;
598       Pmsg1(000, _("Write final hdr error: ERR=%s\n"), be.strerror());
599       goto bail_out;
600    }
601    ok = true;
602 // Dmsg1(010, "rewrote header = %d\n", sizeof(state_hdr));
603 bail_out:
604    if (sfd >= 0) {
605       close(sfd);
606    }
607    if (!ok) {
608       unlink(fname);
609    }
610    free_pool_memory(fname);
611 }
612
613
614 /*
615  * Drop to privilege new userid and new gid if non-NULL
616  */
617 void drop(char *uid, char *gid)
618 {
619 #ifdef HAVE_GRP_H
620    if (gid) {
621       struct group *group;
622       gid_t gr_list[1];
623
624       if ((group = getgrnam(gid)) == NULL) {
625          Emsg1(M_ERROR_TERM, 0, _("Could not find specified group: %s\n"), gid);
626       }
627       if (setgid(group->gr_gid)) {
628          Emsg1(M_ERROR_TERM, 0, _("Could not set specified group: %s\n"), gid);
629       }
630       gr_list[0] = group->gr_gid;
631       if (setgroups(1, gr_list)) {
632          Emsg1(M_ERROR_TERM, 0, _("Could not set specified group: %s\n"), gid);
633       }
634    }
635 #endif
636
637 #ifdef HAVE_PWD_H
638    if (uid) {
639       struct passwd *passw;
640       if ((passw = getpwnam(uid)) == NULL) {
641          Emsg1(M_ERROR_TERM, 0, _("Could not find specified userid: %s\n"), uid);
642       }
643       if (setuid(passw->pw_uid)) {
644          Emsg1(M_ERROR_TERM, 0, _("Could not set specified userid: %s\n"), uid);
645       }
646    }
647 #endif
648
649 }
650
651
652 /* BSDI does not have this.  This is a *poor* simulation */
653 #ifndef HAVE_STRTOLL
654 long long int
655 strtoll(const char *ptr, char **endptr, int base)
656 {
657    return (long long int)strtod(ptr, endptr);
658 }
659 #endif
660
661 /*
662  * Bacula's implementation of fgets(). The difference is that it handles
663  *   being interrupted by a signal (e.g. a SIGCHLD).
664  */
665 #undef fgetc
666 char *bfgets(char *s, int size, FILE *fd)
667 {
668    char *p = s;
669    int ch;
670    *p = 0;
671    for (int i=0; i < size-1; i++) {
672       do {
673          errno = 0;
674          ch = fgetc(fd);
675       } while (ch == -1 && (errno == EINTR || errno == EAGAIN));
676       if (ch == -1) {
677          if (i == 0) {
678             return NULL;
679          } else {
680             return s;
681          }
682       }
683       *p++ = ch;
684       *p = 0;
685       if (ch == '\r') { /* Support for Mac/Windows file format */
686          ch = fgetc(fd);
687          if (ch == '\n') { /* Windows (\r\n) */
688             *p++ = ch;
689             *p = 0;
690          }
691          else { /* Mac (\r only) */
692             (void)ungetc(ch, fd); /* Push next character back to fd */
693          }
694          break;
695       }
696       if (ch == '\n') {
697          break;
698       }
699    }
700    return s;
701 }
702
703 /*
704  * Make a "unique" filename.  It is important that if
705  *   called again with the same "what" that the result
706  *   will be identical. This allows us to use the file
707  *   without saving its name, and re-generate the name
708  *   so that it can be deleted.
709  */
710 void make_unique_filename(POOLMEM **name, int Id, char *what)
711 {
712    Mmsg(name, "%s/%s.%s.%d.tmp", working_directory, my_name, what, Id);
713 }