From: Kern Sibbald Date: Wed, 13 Oct 2004 16:10:10 +0000 (+0000) Subject: - Add a kludge to detect bad date/times, which cause a seg fault in X-Git-Tag: Release-7.0.0~9138 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=a5e467e33f0a6dcb7a33d43118868bbb596604b5;p=bacula%2Fbacula - Add a kludge to detect bad date/times, which cause a seg fault in Microsoft's version of localtime_r(). So, now we know that Microsoft programmers do not check return codes! - Minor update to web site (new projects page). - Remove bigint for filenameid from postgresql table -- as demonstrated by Martin, it has negative performance repercussions. - Rework getuser() and getgroup() to avoid any possible race condition by returning the value in a buffer rather than from the cached table. - Add a bit more debug code to the FD status output. git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@1644 91ce42f0-d328-0410-95d8-f526ca767f89 --- diff --git a/bacula/ReleaseNotes b/bacula/ReleaseNotes index 835d2f5241..2ccbf273f5 100644 --- a/bacula/ReleaseNotes +++ b/bacula/ReleaseNotes @@ -24,7 +24,9 @@ Major Changes: to files written to an alternate directory (i.e. using a where=). - Certain open files (Word for example) can now be saved on Win32 systems. -- Default for Wild-cards on Win32 systems is to fold case. +- Default for Wild-cards on Win32 systems is to fold case this + should correct most of the problems users are having with + exclusion on Win32. New Directives: - Added "Rerun Failed levels = yes/no" in the Job resource diff --git a/bacula/kernstodo b/bacula/kernstodo index ffaa7b0612..0a9e2dc01d 100644 --- a/bacula/kernstodo +++ b/bacula/kernstodo @@ -11,6 +11,12 @@ Version 1.35 Kern (see below) ======================================================== 1.35 Items to do for release: +- Remove documentation for readline. +- Add File indexes as suggested by Martin -- modify update + scripts to add them. +- Modify postgresql update script to remove bigint FilenameId + reference. + Maybe for 1.35: - Add Pool/Storage override regression test. @@ -1370,4 +1376,3 @@ Block Position: 0 - Document a get out of jail procedure if everything breaks if you lost/broke the Catalog -- do the same for "I know my file is there how do I get it back?". - diff --git a/bacula/src/cats/make_postgresql_tables.in b/bacula/src/cats/make_postgresql_tables.in index f055fd7267..324a14f782 100644 --- a/bacula/src/cats/make_postgresql_tables.in +++ b/bacula/src/cats/make_postgresql_tables.in @@ -202,7 +202,7 @@ create table file default 0, jobid integer not null, pathid integer not null, - filenameid bigint not null, + filenameid integer not null, markid integer not null default 0, lstat text not null, diff --git a/bacula/src/dird/ua_tree.c b/bacula/src/dird/ua_tree.c index 769a069b08..517ccf767d 100644 --- a/bacula/src/dird/ua_tree.c +++ b/bacula/src/dird/ua_tree.c @@ -451,8 +451,8 @@ static int lsmarkcmd(UAContext *ua, TREE_CTX *tree) -extern char *getuser(uid_t uid); -extern char *getgroup(gid_t gid); +extern char *getuser(uid_t uid, char *name, int len); +extern char *getgroup(gid_t gid, char *name, int len); /* * This is actually the long form used for "dir" @@ -462,12 +462,14 @@ static void ls_output(char *buf, const char *fname, const char *tag, struct stat char *p; const char *f; char ec1[30]; + char en1[30], en2[30]; int n; p = encode_mode(statp->st_mode, buf); n = sprintf(p, " %2d ", (uint32_t)statp->st_nlink); p += n; - n = sprintf(p, "%-8.8s %-8.8s", getuser(statp->st_uid), getgroup(statp->st_gid)); + n = sprintf(p, "%-8.8s %-8.8s", getuser(statp->st_uid, en1, sizeof(en1)), + getgroup(statp->st_gid, en2, sizeof(en2))); p += n; n = sprintf(p, "%8.8s ", edit_uint64(statp->st_size, ec1)); p += n; diff --git a/bacula/src/filed/job.c b/bacula/src/filed/job.c index 0f590305a3..465ab44c42 100644 --- a/bacula/src/filed/job.c +++ b/bacula/src/filed/job.c @@ -177,7 +177,7 @@ void *handle_client_request(void *dirp) jcr->last_fname = get_pool_memory(PM_FNAME); jcr->last_fname[0] = 0; jcr->client_name = get_memory(strlen(my_name) + 1); - pm_strcpy(&jcr->client_name, my_name); + pm_strcpy(jcr->client_name, my_name); dir->jcr = jcr; enable_backup_privileges(NULL, 1 /* ignore_errors */); @@ -348,7 +348,7 @@ static int setdebug_cmd(JCR *jcr) Dmsg1(110, "setdebug_cmd: %s", dir->msg); if (sscanf(dir->msg, "setdebug=%d trace=%d", &level, &trace_flag) != 2 || level < 0) { - pm_strcpy(&jcr->errmsg, dir->msg); + pm_strcpy(jcr->errmsg, dir->msg); bnet_fsend(dir, "2991 Bad setdebug command: %s\n", jcr->errmsg); return 0; } @@ -364,7 +364,7 @@ static int estimate_cmd(JCR *jcr) char ed2[50]; if (sscanf(dir->msg, estimatecmd, &jcr->listing) != 1) { - pm_strcpy(&jcr->errmsg, dir->msg); + pm_strcpy(jcr->errmsg, dir->msg); Jmsg(jcr, M_FATAL, 0, _("Bad estimate command: %s"), jcr->errmsg); bnet_fsend(dir, "2992 Bad estimate command.\n"); return 0; @@ -388,7 +388,7 @@ static int job_cmd(JCR *jcr) if (sscanf(dir->msg, jobcmd, &jcr->JobId, jcr->Job, &jcr->VolSessionId, &jcr->VolSessionTime, sd_auth_key) != 5) { - pm_strcpy(&jcr->errmsg, dir->msg); + pm_strcpy(jcr->errmsg, dir->msg); Jmsg(jcr, M_FATAL, 0, _("Bad Job Command: %s"), jcr->errmsg); bnet_fsend(dir, BADjob); free_pool_memory(sd_auth_key); @@ -408,7 +408,7 @@ static int runbefore_cmd(JCR *jcr) Dmsg1(100, "runbefore_cmd: %s", dir->msg); if (sscanf(dir->msg, runbefore, cmd) != 1) { - pm_strcpy(&jcr->errmsg, dir->msg); + pm_strcpy(jcr->errmsg, dir->msg); Jmsg1(jcr, M_FATAL, 0, _("Bad RunBeforeJob command: %s\n"), jcr->errmsg); bnet_fsend(dir, "2905 Bad RunBeforeJob command.\n"); free_memory(cmd); @@ -435,7 +435,7 @@ static int runafter_cmd(JCR *jcr) Dmsg1(100, "runafter_cmd: %s", dir->msg); if (sscanf(dir->msg, runafter, msg) != 1) { - pm_strcpy(&jcr->errmsg, dir->msg); + pm_strcpy(jcr->errmsg, dir->msg); Jmsg1(jcr, M_FATAL, 0, _("Bad RunAfter command: %s\n"), jcr->errmsg); bnet_fsend(dir, "2905 Bad RunAfterJob command.\n"); free_memory(msg); @@ -446,7 +446,7 @@ static int runafter_cmd(JCR *jcr) free_pool_memory(jcr->RunAfterJob); } jcr->RunAfterJob = get_pool_memory(PM_FNAME); - pm_strcpy(&jcr->RunAfterJob, msg); + pm_strcpy(jcr->RunAfterJob, msg); free_pool_memory(msg); return bnet_fsend(dir, OKRunAfter); } @@ -1098,7 +1098,7 @@ static int level_cmd(JCR *jcr) return bnet_fsend(dir, OKlevel); bail_out: - pm_strcpy(&jcr->errmsg, dir->msg); + pm_strcpy(jcr->errmsg, dir->msg); Jmsg1(jcr, M_FATAL, 0, _("Bad level command: %s\n"), jcr->errmsg); free_memory(level); if (buf) { @@ -1119,7 +1119,7 @@ static int session_cmd(JCR *jcr) &jcr->VolSessionId, &jcr->VolSessionTime, &jcr->StartFile, &jcr->EndFile, &jcr->StartBlock, &jcr->EndBlock) != 7) { - pm_strcpy(&jcr->errmsg, dir->msg); + pm_strcpy(jcr->errmsg, dir->msg); Jmsg(jcr, M_FATAL, 0, "Bad session command: %s", jcr->errmsg); return 0; } @@ -1140,7 +1140,7 @@ static int storage_cmd(JCR *jcr) Dmsg1(100, "StorageCmd: %s", dir->msg); if (sscanf(dir->msg, storaddr, &jcr->stored_addr, &stored_port, &enable_ssl) != 3) { - pm_strcpy(&jcr->errmsg, dir->msg); + pm_strcpy(jcr->errmsg, dir->msg); Jmsg(jcr, M_FATAL, 0, _("Bad storage command: %s"), jcr->errmsg); return 0; } @@ -1391,7 +1391,7 @@ static int restore_cmd(JCR *jcr) if (sscanf(dir->msg, restorecmd, &replace, &prefix_links, where) != 3) { if (sscanf(dir->msg, restorecmd1, &replace, &prefix_links) != 2) { - pm_strcpy(&jcr->errmsg, dir->msg); + pm_strcpy(jcr->errmsg, dir->msg); Jmsg(jcr, M_FATAL, 0, _("Bad replace command. CMD=%s\n"), jcr->errmsg); return 0; } @@ -1591,8 +1591,7 @@ static int send_bootstrap_file(JCR *jcr) set_jcr_job_status(jcr, JS_ErrorTerminated); goto bail_out; } - pm_strcpy(&sd->msg, bootstrap); - sd->msglen = strlen(sd->msg); + sd->msglen = pm_strcpy(sd->msg, bootstrap); bnet_send(sd); while (fgets(buf, sizeof(buf), bs)) { sd->msglen = Mmsg(sd->msg, "%s", buf); diff --git a/bacula/src/filed/status.c b/bacula/src/filed/status.c index 0d28b9c43a..3ca00fe8bc 100755 --- a/bacula/src/filed/status.c +++ b/bacula/src/filed/status.c @@ -32,6 +32,7 @@ extern char my_name[]; extern int num_jobs_run; extern time_t daemon_start_time; +extern bool get_trace(void); /* Forward referenced functions */ static void list_terminated_jobs(void sendit(const char *msg, int len, void *sarg), void *arg); @@ -91,11 +92,9 @@ static void do_status(void sendit(const char *msg, int len, void *sarg), void *a edit_uint64_with_commas(sm_max_bytes, b2), edit_uint64_with_commas(sm_buffers, b3), edit_uint64_with_commas(sm_max_buffers, b4)); - sendit(msg, len, arg); - } - if (debug_level > 0) { - len = Mmsg(msg, _(" Sizeof: off_t=%d size_t=%d\n"), sizeof(off_t), - sizeof(size_t)); + sendit(msg, len, arg); + len = Mmsg(msg, _(" Sizeof: off_t=%d size_t=%d debug=%d trace=%d\n"), + sizeof(off_t), sizeof(size_t), debug_level, get_trace()); sendit(msg, len, arg); } @@ -298,18 +297,18 @@ int qstatus_cmd(JCR *jcr) bnet_fsend(dir, OKqstatus, time); lock_jcr_chain(); foreach_jcr(njcr) { - if (njcr->JobId != 0) { - bnet_fsend(dir, DotStatusJob, njcr->JobId, njcr->JobStatus, njcr->JobErrors); - } - free_locked_jcr(njcr); + if (njcr->JobId != 0) { + bnet_fsend(dir, DotStatusJob, njcr->JobId, njcr->JobStatus, njcr->JobErrors); + } + free_locked_jcr(njcr); } unlock_jcr_chain(); } else if (strcmp(time, "last") == 0) { bnet_fsend(dir, OKqstatus, time); if ((last_jobs) && (last_jobs->size() > 0)) { - job = (s_last_job*)last_jobs->last(); - bnet_fsend(dir, DotStatusJob, job->JobId, job->JobStatus, job->Errors); + job = (s_last_job*)last_jobs->last(); + bnet_fsend(dir, DotStatusJob, job->JobId, job->JobStatus, job->Errors); } } else { diff --git a/bacula/src/lib/attr.c b/bacula/src/lib/attr.c index 43d590d86f..bd9746c64f 100644 --- a/bacula/src/lib/attr.c +++ b/bacula/src/lib/attr.c @@ -171,8 +171,8 @@ void build_attr_output_fnames(JCR *jcr, ATTR *attr) } } -extern char *getuser(uid_t uid); -extern char *getgroup(gid_t gid); +extern char *getuser(uid_t uid, char *name, int len); +extern char *getgroup(gid_t gid, char *name, int len); /* * Print an ls style message, also send M_RESTORED @@ -181,11 +181,13 @@ void print_ls_output(JCR *jcr, ATTR *attr) { char buf[5000]; char ec1[30]; + char en1[30], en2[30]; char *p, *f; p = encode_mode(attr->statp.st_mode, buf); p += sprintf(p, " %2d ", (uint32_t)attr->statp.st_nlink); - p += sprintf(p, "%-8.8s %-8.8s", getuser(attr->statp.st_uid), getgroup(attr->statp.st_gid)); + p += sprintf(p, "%-8.8s %-8.8s", getuser(attr->statp.st_uid, en1, sizeof(en1)), + getgroup(attr->statp.st_gid, en2, sizeof(en2))); p += sprintf(p, "%8.8s ", edit_uint64(attr->statp.st_size, ec1)); p = encode_time(attr->statp.st_ctime, p); *p++ = ' '; diff --git a/bacula/src/lib/bnet.c b/bacula/src/lib/bnet.c index 181574b543..eedb327266 100644 --- a/bacula/src/lib/bnet.c +++ b/bacula/src/lib/bnet.c @@ -334,8 +334,8 @@ int bnet_despool_to_bsock(BSOCK * bsock, void update_attr_spool_size(ssize_t siz * two network packets. The first is sends a 32 bit integer containing * the length of the data packet which follows. * - * Returns: 0 on failure - * 1 on success + * Returns: false on failure + * true on success */ bool bnet_send(BSOCK * bsock) { diff --git a/bacula/src/lib/bsys.c b/bacula/src/lib/bsys.c index a4105affa6..b0d6cb240c 100644 --- a/bacula/src/lib/bsys.c +++ b/bacula/src/lib/bsys.c @@ -169,14 +169,16 @@ int bvsnprintf(char *str, int32_t size, const char *format, va_list ap) struct tm *localtime_r(const time_t *timep, struct tm *tm) { static pthread_mutex_t mutex; - static int first = 1; - struct tm *ltm; + static bool first = true; + struct tm *ltm, if (first) { pthread_mutex_init(&mutex, NULL); - first = 0; + first = false; } + P(mutex); + ltm = localtime(timep); if (ltm) { memcpy(tm, ltm, sizeof(struct tm)); diff --git a/bacula/src/lib/idcache.c b/bacula/src/lib/idcache.c index 1c16780afc..99c7362b05 100644 --- a/bacula/src/lib/idcache.c +++ b/bacula/src/lib/idcache.c @@ -35,7 +35,7 @@ static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; /* Translate UID to a login name or a stringified number, with cache. */ -char *getuser(uid_t uid) +char *getuser(uid_t uid, char *name, int len) { register struct userid *tail; struct passwd *pwent; @@ -44,8 +44,7 @@ char *getuser(uid_t uid) P(mutex); for (tail = user_alist; tail; tail = tail->next) { if (tail->id.u == uid) { - V(mutex); - return tail->name; + goto uid_done; } } @@ -53,7 +52,7 @@ char *getuser(uid_t uid) tail = (struct userid *)malloc(sizeof (struct userid)); tail->id.u = uid; #ifndef HAVE_WIN32 - if (pwent == 0 || strcmp(pwent->pw_name, "????????") == 0) { + if (pwent == NULL || strcmp(pwent->pw_name, "????????") == 0) { sprintf(usernum_string, "%u", (uint32_t)uid); tail->name = bstrdup(usernum_string); } else { @@ -67,8 +66,11 @@ char *getuser(uid_t uid) /* Add to the head of the list, so most recently used is first. */ tail->next = user_alist; user_alist = tail; + +uid_done: + bstrncpy(name, tail->name, len); V(mutex); - return tail->name; + return name; } void free_getuser_cache() @@ -90,7 +92,7 @@ void free_getuser_cache() /* Translate GID to a group name or a stringified number, with cache. */ -char *getgroup(gid_t gid) +char *getgroup(gid_t gid, char *name, int len) { register struct userid *tail; struct group *grent; @@ -99,8 +101,7 @@ char *getgroup(gid_t gid) P(mutex); for (tail = group_alist; tail; tail = tail->next) { if (tail->id.g == gid) { - V(mutex); - return tail->name; + goto gid_done; } } @@ -108,7 +109,7 @@ char *getgroup(gid_t gid) tail = (struct userid *)malloc(sizeof (struct userid)); tail->id.g = gid; #ifndef HAVE_WIN32 - if (grent == 0 || strcmp(grent->gr_name, "????????") == 0) { + if (grent == NULL || strcmp(grent->gr_name, "????????") == 0) { sprintf (groupnum_string, "%u", (uint32_t)gid); tail->name = bstrdup(groupnum_string); } else { @@ -121,8 +122,11 @@ char *getgroup(gid_t gid) /* Add to the head of the list, so most recently used is first. */ tail->next = group_alist; group_alist = tail; + +gid_done: + bstrncpy(name, tail->name, len); V(mutex); - return tail->name; + return name; } void free_getgroup_cache() diff --git a/bacula/src/lib/message.c b/bacula/src/lib/message.c index af87bed48f..0165e9f0cc 100755 --- a/bacula/src/lib/message.c +++ b/bacula/src/lib/message.c @@ -816,6 +816,11 @@ void set_trace(int trace_flag) } } +bool get_trace(void) +{ + return trace; +} + /********************************************************************* * * This subroutine prints a message regardless of the debug level diff --git a/bacula/src/lib/util.c b/bacula/src/lib/util.c index d8c0a72458..7ac8df6863 100644 --- a/bacula/src/lib/util.c +++ b/bacula/src/lib/util.c @@ -126,12 +126,41 @@ unbash_spaces(POOL_MEM &pm) } } +#ifdef WIN32 +extern long _timezone; +extern int _daylight; +extern long _dstbias; +extern "C" void __tzset(void); +extern "C" int _isindst(struct tm *); +#endif char *encode_time(time_t time, char *buf) { struct tm tm; int n = 0; +#ifdef WIN32 + /* + * Gross kludge to avoid a seg fault in Microsoft's CRT localtime_r(), + * which incorrectly references a NULL returned from gmtime() if + * the time (adjusted for the current timezone) is invalid. + * This could happen if you have a bad date/time, or perhaps if you + * moved a file from one timezone to another? + */ + struct tm *gtm; + time_t gtime; + __tzset(); + gtime = time - _timezone; + if (!(gtm = gmtime(>ime))) { + return buf; + } + if (_daylight && _isindst(gtm)) { + gtime -= _dstbias; + if (!gmtime(>ime)) { + return buf; + } + } +#endif if (localtime_r(&time, &tm)) { n = sprintf(buf, "%04d-%02d-%02d %02d:%02d:%02d", tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, diff --git a/bacula/src/version.h b/bacula/src/version.h index 406ebaafaa..397282dd65 100644 --- a/bacula/src/version.h +++ b/bacula/src/version.h @@ -1,8 +1,8 @@ /* */ #undef VERSION -#define VERSION "1.35.8" -#define BDATE "08 October 2004" -#define LSMDATE "08Oct04" +#define VERSION "1.35.9" +#define BDATE "12 October 2004" +#define LSMDATE "12Oct04" /* Debug flags */ #undef DEBUG