]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/lib/bsys.c
kes Closed bug #1207 -- 2.4.4-b1 strange volume/device handling
[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 #ifdef HAVE_PWD_H
40 #include <pwd.h>
41 #endif
42 #ifdef HAVE_GRP_H
43 #include <grp.h>
44 #endif
45
46 #ifdef HAVE_AIX_OS
47 extern "C" int initgroups(const char *,int);
48 #endif
49
50
51 static pthread_mutex_t timer_mutex = PTHREAD_MUTEX_INITIALIZER;
52 static pthread_cond_t timer = PTHREAD_COND_INITIALIZER;
53
54 /*
55  * This routine will sleep (sec, microsec).  Note, however, that if a
56  *   signal occurs, it will return early.  It is up to the caller
57  *   to recall this routine if he/she REALLY wants to sleep the
58  *   requested time.
59  */
60 int bmicrosleep(int32_t sec, int32_t usec)
61 {
62    struct timespec timeout;
63    struct timeval tv;
64    struct timezone tz;
65    int stat;
66
67    timeout.tv_sec = sec;
68    timeout.tv_nsec = usec * 1000;
69
70 #ifdef HAVE_NANOSLEEP
71    stat = nanosleep(&timeout, NULL);
72    if (!(stat < 0 && errno == ENOSYS)) {
73       return stat;
74    }
75    /* If we reach here it is because nanosleep is not supported by the OS */
76 #endif
77
78    /* Do it the old way */
79    gettimeofday(&tv, &tz);
80    timeout.tv_nsec += tv.tv_usec * 1000;
81    timeout.tv_sec += tv.tv_sec;
82    while (timeout.tv_nsec >= 1000000000) {
83       timeout.tv_nsec -= 1000000000;
84       timeout.tv_sec++;
85    }
86
87    Dmsg2(200, "pthread_cond_timedwait sec=%lld usec=%d\n", sec, usec);
88    /* Note, this unlocks mutex during the sleep */
89    P(timer_mutex);
90    stat = pthread_cond_timedwait(&timer, &timer_mutex, &timeout);
91    if (stat != 0) {
92       berrno be;
93       Dmsg2(200, "pthread_cond_timedwait stat=%d ERR=%s\n", stat,
94          be.bstrerror(stat));
95    }
96    V(timer_mutex);
97    return stat;
98 }
99
100 /*
101  * Guarantee that the string is properly terminated */
102 char *bstrncpy(char *dest, const char *src, int maxlen)
103 {
104    strncpy(dest, src, maxlen-1);
105    dest[maxlen-1] = 0;
106    return dest;
107 }
108
109 /*
110  * Guarantee that the string is properly terminated */
111 char *bstrncpy(char *dest, POOL_MEM &src, int maxlen)
112 {
113    strncpy(dest, src.c_str(), maxlen-1);
114    dest[maxlen-1] = 0;
115    return dest;
116 }
117
118
119 char *bstrncat(char *dest, const char *src, int maxlen)
120 {
121    strncat(dest, src, maxlen-1);
122    dest[maxlen-1] = 0;
123    return dest;
124 }
125
126 char *bstrncat(char *dest, POOL_MEM &src, int maxlen)
127 {
128    strncat(dest, src.c_str(), maxlen-1);
129    dest[maxlen-1] = 0;
130    return dest;
131 }
132
133 /*
134  * Allows one or both pointers to be NULL
135  */
136 bool bstrcmp(const char *s1, const char *s2)
137 {
138    if (s1 == s2) return true;
139    if (s1 == NULL || s2 == NULL) return false;
140    return strcmp(s1, s2) == 0;
141 }
142
143 /*
144  * Get character length of UTF-8 string
145  *
146  * Valid UTF-8 codes
147  * U-00000000 - U-0000007F: 0xxxxxxx 
148  * U-00000080 - U-000007FF: 110xxxxx 10xxxxxx 
149  * U-00000800 - U-0000FFFF: 1110xxxx 10xxxxxx 10xxxxxx 
150  * U-00010000 - U-001FFFFF: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx 
151  * U-00200000 - U-03FFFFFF: 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 
152  * U-04000000 - U-7FFFFFFF: 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
153  */
154 int cstrlen(const char *str)
155 {
156    uint8_t *p = (uint8_t *)str;
157    int len = 0;
158    while (*p) {
159       if ((*p & 0xC0) != 0xC0) {
160          p++;
161          len++;
162          continue;
163       }
164       if ((*p & 0xD0) == 0xC0) {
165          p += 2;
166          len++;
167          continue;
168       }
169       if ((*p & 0xF0) == 0xD0) {
170          p += 3;
171          len++;
172          continue;
173       }
174       if ((*p & 0xF8) == 0xF0) {
175          p += 4;
176          len++;
177          continue;
178       }
179       if ((*p & 0xFC) == 0xF8) {
180          p += 5;
181          len++;
182          continue;
183       }
184       if ((*p & 0xFE) == 0xFC) {
185          p += 6;
186          len++;
187          continue;
188       }
189       p++;                      /* Shouln't get here but must advance */
190    }
191    return len;
192 }
193
194
195
196 #ifndef bmalloc
197 void *bmalloc(size_t size)
198 {
199   void *buf;
200
201 #ifdef SMARTALLOC
202   buf = sm_malloc(file, line, size);
203 #else
204   buf = malloc(size);
205 #endif
206   if (buf == NULL) {
207      berrno be;
208      Emsg1(M_ABORT, 0, _("Out of memory: ERR=%s\n"), be.bstrerror());
209   }
210   return buf;
211 }
212 #endif
213
214 void *b_malloc(const char *file, int line, size_t size)
215 {
216   void *buf;
217
218 #ifdef SMARTALLOC
219   buf = sm_malloc(file, line, size);
220 #else
221   buf = malloc(size);
222 #endif
223   if (buf == NULL) {
224      berrno be;
225      e_msg(file, line, M_ABORT, 0, _("Out of memory: ERR=%s\n"), be.bstrerror());
226   }
227   return buf;
228 }
229
230
231 void bfree(void *buf)
232 {
233 #ifdef SMARTALLOC
234   sm_free(__FILE__, __LINE__, buf);
235 #else
236   free(buf);
237 #endif
238 }
239
240 void *brealloc (void *buf, size_t size)
241 {
242 #ifdef SMARTALOC
243    buf = sm_realloc(__FILE__, __LINE__, buf, size);
244 #else
245    buf = realloc(buf, size);
246 #endif
247    if (buf == NULL) {
248       berrno be;
249       Emsg1(M_ABORT, 0, _("Out of memory: ERR=%s\n"), be.bstrerror());
250    }
251    return buf;
252 }
253
254
255 void *bcalloc(size_t size1, size_t size2)
256 {
257   void *buf;
258
259    buf = calloc(size1, size2);
260    if (buf == NULL) {
261       berrno be;
262       Emsg1(M_ABORT, 0, _("Out of memory: ERR=%s\n"), be.bstrerror());
263    }
264    return buf;
265 }
266
267 /* Code now in src/lib/bsnprintf.c */
268 #ifndef USE_BSNPRINTF
269
270 #define BIG_BUF 5000
271 /*
272  * Implement snprintf
273  */
274 int bsnprintf(char *str, int32_t size, const char *fmt,  ...)
275 {
276    va_list   arg_ptr;
277    int len;
278
279    va_start(arg_ptr, fmt);
280    len = bvsnprintf(str, size, fmt, arg_ptr);
281    va_end(arg_ptr);
282    return len;
283 }
284
285 /*
286  * Implement vsnprintf()
287  */
288 int bvsnprintf(char *str, int32_t size, const char  *format, va_list ap)
289 {
290 #ifdef HAVE_VSNPRINTF
291    int len;
292    len = vsnprintf(str, size, format, ap);
293    str[size-1] = 0;
294    return len;
295
296 #else
297
298    int len, buflen;
299    char *buf;
300    buflen = size > BIG_BUF ? size : BIG_BUF;
301    buf = get_memory(buflen);
302    len = vsprintf(buf, format, ap);
303    if (len >= buflen) {
304       Emsg0(M_ABORT, 0, _("Buffer overflow.\n"));
305    }
306    memcpy(str, buf, len);
307    str[len] = 0;                /* len excludes the null */
308    free_memory(buf);
309    return len;
310 #endif
311 }
312 #endif /* USE_BSNPRINTF */
313
314 #ifndef HAVE_LOCALTIME_R
315
316 struct tm *localtime_r(const time_t *timep, struct tm *tm)
317 {
318     static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
319     struct tm *ltm,
320
321     P(mutex);
322     ltm = localtime(timep);
323     if (ltm) {
324        memcpy(tm, ltm, sizeof(struct tm));
325     }
326     V(mutex);
327     return ltm ? tm : NULL;
328 }
329 #endif /* HAVE_LOCALTIME_R */
330
331 #ifndef HAVE_READDIR_R
332 #ifndef HAVE_WIN32
333 #include <dirent.h>
334
335 int readdir_r(DIR *dirp, struct dirent *entry, struct dirent **result)
336 {
337     static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
338     struct dirent *ndir;
339     int stat;
340
341     P(mutex);
342     errno = 0;
343     ndir = readdir(dirp);
344     stat = errno;
345     if (ndir) {
346        memcpy(entry, ndir, sizeof(struct dirent));
347        strcpy(entry->d_name, ndir->d_name);
348        *result = entry;
349     } else {
350        *result = NULL;
351     }
352     V(mutex);
353     return stat;
354
355 }
356 #endif
357 #endif /* HAVE_READDIR_R */
358
359
360 int b_strerror(int errnum, char *buf, size_t bufsiz)
361 {
362     static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
363     int stat = 0;
364     const char *msg;
365
366     P(mutex);
367
368     msg = strerror(errnum);
369     if (!msg) {
370        msg = _("Bad errno");
371        stat = -1;
372     }
373     bstrncpy(buf, msg, bufsiz);
374     V(mutex);
375     return stat;
376 }
377
378 #ifdef DEBUG_MEMSET
379 /* These routines are not normally turned on */
380 #undef memset
381 void b_memset(const char *file, int line, void *mem, int val, size_t num)
382 {
383    /* Testing for 2000 byte zero at beginning of Volume block */
384    if (num > 1900 && num < 3000) {
385       Pmsg3(000, _("Memset for %d bytes at %s:%d\n"), (int)num, file, line);
386    }
387    memset(mem, val, num);
388 }
389 #endif
390
391 #if !defined(HAVE_WIN32)
392 static int del_pid_file_ok = FALSE;
393 #endif
394
395 /*
396  * Create a standard "Unix" pid file.
397  */
398 void create_pid_file(char *dir, const char *progname, int port)
399 {
400 #if !defined(HAVE_WIN32)
401    int pidfd, len;
402    int oldpid;
403    char  pidbuf[20];
404    POOLMEM *fname = get_pool_memory(PM_FNAME);
405    struct stat statp;
406
407    Mmsg(&fname, "%s/%s.%d.pid", dir, progname, port);
408    if (stat(fname, &statp) == 0) {
409       /* File exists, see what we have */
410       *pidbuf = 0;
411       if ((pidfd = open(fname, O_RDONLY|O_BINARY, 0)) < 0 ||
412            read(pidfd, &pidbuf, sizeof(pidbuf)) < 0 ||
413            sscanf(pidbuf, "%d", &oldpid) != 1) {
414          berrno be;
415          Emsg2(M_ERROR_TERM, 0, _("Cannot open pid file. %s ERR=%s\n"), fname, 
416                be.bstrerror());
417       }
418       /* Some OSes (IRIX) don't bother to clean out the old pid files after a crash, and
419        * since they use a deterministic algorithm for assigning PIDs, we can have
420        * pid conflicts with the old PID file after a reboot.
421        * The intent the following code is to check if the oldpid read from the pid
422        * file is the same as the currently executing process's pid,
423        * and if oldpid == getpid(), skip the attempt to
424        * kill(oldpid,0), since the attempt is guaranteed to succeed,
425        * but the success won't actually mean that there is an
426        * another Bacula process already running.
427        * For more details see bug #797.
428        */
429        if ((oldpid != (int)getpid()) && (kill(oldpid, 0) != -1 || errno != ESRCH)) {
430          Emsg3(M_ERROR_TERM, 0, _("%s is already running. pid=%d\nCheck file %s\n"),
431                progname, oldpid, fname);
432       }
433       /* He is not alive, so take over file ownership */
434       unlink(fname);                  /* remove stale pid file */
435    }
436    /* Create new pid file */
437    if ((pidfd = open(fname, O_CREAT|O_TRUNC|O_WRONLY|O_BINARY, 0640)) >= 0) {
438       len = sprintf(pidbuf, "%d\n", (int)getpid());
439       write(pidfd, pidbuf, len);
440       close(pidfd);
441       del_pid_file_ok = TRUE;         /* we created it so we can delete it */
442    } else {
443       berrno be;
444       Emsg2(M_ERROR_TERM, 0, _("Could not open pid file. %s ERR=%s\n"), fname, 
445             be.bstrerror());
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_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    4,
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) {
501       berrno be;
502       Dmsg3(010, "Could not open state file. sfd=%d size=%d: ERR=%s\n",
503                     sfd, sizeof(hdr), be.bstrerror());
504       goto bail_out;
505    }
506    if ((stat=read(sfd, &hdr, hdr_size)) != hdr_size) {
507       berrno be;
508       Dmsg4(010, "Could not read state file. sfd=%d stat=%d size=%d: ERR=%s\n",
509                     sfd, (int)stat, hdr_size, be.bstrerror());
510       goto bail_out;
511    }
512    if (hdr.version != state_hdr.version) {
513       Dmsg2(010, "Bad hdr version. Wanted %d got %d\n",
514          state_hdr.version, hdr.version);
515       goto bail_out;
516    }
517    hdr.id[13] = 0;
518    if (strcmp(hdr.id, state_hdr.id) != 0) {
519       Dmsg0(000, "State file header id invalid.\n");
520       goto bail_out;
521    }
522 // Dmsg1(010, "Read header of %d bytes.\n", sizeof(hdr));
523    if (!read_last_jobs_list(sfd, hdr.last_jobs_addr)) {
524       goto bail_out;
525    }
526    ok = true;
527 bail_out:
528    if (sfd >= 0) {
529       close(sfd);
530    }
531    if (!ok) {
532       unlink(fname);
533     }
534    free_pool_memory(fname);
535 }
536
537 /*
538  * Write the state file
539  */
540 void write_state_file(char *dir, const char *progname, int port)
541 {
542    int sfd;
543    bool ok = false;
544    POOLMEM *fname = get_pool_memory(PM_FNAME);
545
546    Mmsg(&fname, "%s/%s.%d.state", dir, progname, port);
547    /* Create new state file */
548    unlink(fname);
549    if ((sfd = open(fname, O_CREAT|O_WRONLY|O_BINARY, 0640)) < 0) {
550       berrno be;
551       Dmsg2(000, "Could not create state file. %s ERR=%s\n", fname, be.bstrerror());
552       Emsg2(M_ERROR, 0, _("Could not create state file. %s ERR=%s\n"), fname, be.bstrerror());
553       goto bail_out;
554    }
555    if (write(sfd, &state_hdr, sizeof(state_hdr)) != sizeof(state_hdr)) {
556       berrno be;
557       Dmsg1(000, "Write hdr error: ERR=%s\n", be.bstrerror());
558       goto bail_out;
559    }
560 // Dmsg1(010, "Wrote header of %d bytes\n", sizeof(state_hdr));
561    state_hdr.last_jobs_addr = sizeof(state_hdr);
562    state_hdr.reserved[0] = write_last_jobs_list(sfd, state_hdr.last_jobs_addr);
563 // Dmsg1(010, "write last job end = %d\n", (int)state_hdr.reserved[0]);
564    if (lseek(sfd, 0, SEEK_SET) < 0) {
565       berrno be;
566       Dmsg1(000, "lseek error: ERR=%s\n", be.bstrerror());
567       goto bail_out;
568    }
569    if (write(sfd, &state_hdr, sizeof(state_hdr)) != sizeof(state_hdr)) {
570       berrno be;
571       Pmsg1(000, _("Write final hdr error: ERR=%s\n"), be.bstrerror());
572       goto bail_out;
573    }
574    ok = true;
575 // Dmsg1(010, "rewrote header = %d\n", sizeof(state_hdr));
576 bail_out:
577    if (sfd >= 0) {
578       close(sfd);
579    }
580    if (!ok) {
581       unlink(fname);
582    }
583    free_pool_memory(fname);
584 }
585
586
587 /*
588  * Drop to privilege new userid and new gid if non-NULL
589  */
590 void drop(char *uname, char *gname)
591 {
592 #if   defined(HAVE_PWD_H) && defined(HAVE_GRP_H)
593    struct passwd *passw = NULL;
594    struct group *group = NULL;
595    gid_t gid;
596    uid_t uid;
597    char username[1000];         
598
599    Dmsg2(900, "uname=%s gname=%s\n", uname?uname:"NONE", gname?gname:"NONE");
600    if (!uname && !gname) {
601       return;                            /* Nothing to do */
602    }
603
604    if (uname) {
605       if ((passw = getpwnam(uname)) == NULL) {
606          berrno be;
607          Emsg2(M_ERROR_TERM, 0, _("Could not find userid=%s: ERR=%s\n"), uname,
608             be.bstrerror());
609       }
610    } else {
611       if ((passw = getpwuid(getuid())) == NULL) {
612          berrno be;
613          Emsg1(M_ERROR_TERM, 0, _("Could not find password entry. ERR=%s\n"),
614             be.bstrerror());
615       } else {
616          uname = passw->pw_name;
617       }
618    }
619    /* Any OS uname pointer may get overwritten, so save name, uid, and gid */
620    bstrncpy(username, uname, sizeof(username));
621    uid = passw->pw_uid;
622    gid = passw->pw_gid;
623    if (gname) {
624       if ((group = getgrnam(gname)) == NULL) {
625          berrno be;
626          Emsg2(M_ERROR_TERM, 0, _("Could not find group=%s: ERR=%s\n"), gname,
627             be.bstrerror());
628       }
629       gid = group->gr_gid;
630    }
631    if (initgroups(username, gid)) {
632       berrno be;
633       if (gname) {
634          Emsg3(M_ERROR_TERM, 0, _("Could not initgroups for group=%s, userid=%s: ERR=%s\n"),         
635             gname, username, be.bstrerror());
636       } else {
637          Emsg2(M_ERROR_TERM, 0, _("Could not initgroups for userid=%s: ERR=%s\n"),         
638             username, be.bstrerror());
639       }
640    }
641    if (gname) {
642       if (setgid(gid)) {
643          berrno be;
644          Emsg2(M_ERROR_TERM, 0, _("Could not set group=%s: ERR=%s\n"), gname,
645             be.bstrerror());
646       }
647    }
648    if (setuid(uid)) {
649       berrno be;
650       Emsg1(M_ERROR_TERM, 0, _("Could not set specified userid: %s\n"), username);
651    }
652 #endif
653 }
654
655
656 /* BSDI does not have this.  This is a *poor* simulation */
657 #ifndef HAVE_STRTOLL
658 long long int
659 strtoll(const char *ptr, char **endptr, int base)
660 {
661    return (long long int)strtod(ptr, endptr);
662 }
663 #endif
664
665 /*
666  * Bacula's implementation of fgets(). The difference is that it handles
667  *   being interrupted by a signal (e.g. a SIGCHLD).
668  */
669 #undef fgetc
670 char *bfgets(char *s, int size, FILE *fd)
671 {
672    char *p = s;
673    int ch;
674    *p = 0;
675    for (int i=0; i < size-1; i++) {
676       do {
677          errno = 0;
678          ch = fgetc(fd);
679       } while (ch == EOF && ferror(fd) && (errno == EINTR || errno == EAGAIN));
680       if (ch == EOF) {
681          if (i == 0) {
682             return NULL;
683          } else {
684             return s;
685          }
686       }
687       *p++ = ch;
688       *p = 0;
689       if (ch == '\r') { /* Support for Mac/Windows file format */
690          ch = fgetc(fd);
691          if (ch != '\n') { /* Mac (\r only) */
692             (void)ungetc(ch, fd); /* Push next character back to fd */
693          }
694          p[-1] = '\n';
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 }
715
716 char *escape_filename(const char *file_path)
717 {
718    if (file_path == NULL || strpbrk(file_path, "\"\\") == NULL) {
719       return NULL;
720    }
721
722    char *escaped_path = (char *)bmalloc(2 * (strlen(file_path) + 1));
723    char *cur_char = escaped_path;
724
725    while (*file_path) {
726       if (*file_path == '\\' || *file_path == '"') {
727          *cur_char++ = '\\';
728       }
729
730       *cur_char++ = *file_path++;
731    }
732
733    *cur_char = '\0';
734
735    return escaped_path;
736 }