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