From: Kern Sibbald Date: Fri, 17 Mar 2006 17:42:42 +0000 (+0000) Subject: 17Mar06 X-Git-Tag: Release-7.0.0~8113 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=3d52afb93a3d89ac9d5aebf2052fc625a3274b75;p=bacula%2Fbacula 17Mar06 - Implement regex test program in tools directory. - Attempt to fix time problem with bsmtp with foreign langs. - Add strip_trailing_newline() submitted by user. - Implement regex matching in migrate.c 16Mar06 - Fix bug #537 to allow arbitrary time to mount a volume for restore, if polling is turned on. - If dir_user or dir-group is specified in ./configure apply it to the working-dir. Fixes bug #533. - If rescheduling a job cancel the previous incarnation with the SD. Fixes bugs #566 and 557. - Fix bug #567 do_message() definition type conflict. git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@2836 91ce42f0-d328-0410-95d8-f526ca767f89 --- diff --git a/bacula/Makefile.in b/bacula/Makefile.in index 64042e8390..f6cd26a08a 100755 --- a/bacula/Makefile.in +++ b/bacula/Makefile.in @@ -4,6 +4,8 @@ @MCOMMON@ working_dir=@working_dir@ +dir_group=@dir_group@ +dir_user=@dir_user@ srcdir = @srcdir@ VPATH = @srcdir@ @@ -88,6 +90,10 @@ installdirs: $(MKDIR) $(DESTDIR)$(sysconfdir) $(MKDIR) $(DESTDIR)$(scriptdir) $(MKDIR) $(DESTDIR)$(working_dir) + if test "x$(dir_user)" != "x" ; then \ + chown -f $(dir_user) $(DESTDIR)$(working_dir); fi + if test "x$(dir_group)" != "x" ; then \ + chown -f :$(dir_group) $(DESTDIR)$(working_dir); fi # $(MKDIR) $(DESTDIR)$(mandir) gnomedirs: diff --git a/bacula/ReleaseNotes b/bacula/ReleaseNotes index 53f9bbb104..1b9402964e 100644 --- a/bacula/ReleaseNotes +++ b/bacula/ReleaseNotes @@ -1,5 +1,5 @@ - Release Notes for Bacula 1.38.6-beta5 + Release Notes for Bacula 1.38.6-beta6 Bacula code: Total files = 419 Total lines = 137,078 (*.h *.c *.in) 20,440 additional lines of code since version 1.36.3 @@ -49,6 +49,18 @@ Major bug fixes: Minor bug fixes: - See below: +Release 1.38.6 beta6 16Mar06 +- Fix bug #537 to allow arbitrary time to mount a volume for + restore, if polling is turned on. +- Disallow multiple storage specifications for a job. Should fix Arno's + problem. +- Add back a missing store of poolid in jr.poolid. +- If dir_user or dir-group is specified in ./configure apply it to + the working-dir. Fixes bug #533. +- If rescheduling a job cancel the previous incarnation with the SD. + Fixes bugs #566 and 557. +- Fix bug #567 do_message() definition type conflict. + Release 1.38.6 beta5 14Mar06 - Add more jcr methods and make mutex and use_count private. - Create lock/unlock methods for jcr. diff --git a/bacula/kes-1.38 b/bacula/kes-1.38 index 4f2221c8f5..548e218a38 100644 --- a/bacula/kes-1.38 +++ b/bacula/kes-1.38 @@ -2,6 +2,19 @@ Kern Sibbald General: +16Mar06 +- Fix bug #537 to allow arbitrary time to mount a volume for + restore, if polling is turned on. +- Disallow multiple storage specifications for a job. Should fix Arno's + problem. +- Add back a missing store of poolid in jr.poolid. +- If dir_user or dir-group is specified in ./configure apply it to + the working-dir. Fixes bug #533. +- If rescheduling a job cancel the previous incarnation with the SD. + Fixes bugs #566 and 557. +- Fix bug #567 do_message() definition type conflict. + + 14Mar06 - Add more jcr methods and make mutex and use_count private. - Create lock/unlock methods for jcr. diff --git a/bacula/kes-1.39 b/bacula/kes-1.39 index 8ba0f81523..ee005f41c6 100644 --- a/bacula/kes-1.39 +++ b/bacula/kes-1.39 @@ -2,6 +2,20 @@ Kern Sibbald General: +17Mar06 +- Implement regex test program in tools directory. +- Attempt to fix time problem with bsmtp with foreign langs. +- Add strip_trailing_newline() submitted by user. +- Implement regex matching in migrate.c +16Mar06 +- Fix bug #537 to allow arbitrary time to mount a volume for + restore, if polling is turned on. +- If dir_user or dir-group is specified in ./configure apply it to + the working-dir. Fixes bug #533. +- If rescheduling a job cancel the previous incarnation with the SD. + Fixes bugs #566 and 557. +- Fix bug #567 do_message() definition type conflict. + 14Mar06 - Add more jcr methods and make mutex and use_count private. - Create lock/unlock methods for jcr. diff --git a/bacula/src/dird/inc_conf.c b/bacula/src/dird/inc_conf.c index 67ebde2ac8..38adb0b838 100644 --- a/bacula/src/dird/inc_conf.c +++ b/bacula/src/dird/inc_conf.c @@ -7,7 +7,7 @@ * Version $Id$ */ /* - Copyright (C) 2003-2005 Kern Sibbald + Copyright (C) 2003-2006 Kern Sibbald This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License diff --git a/bacula/src/dird/migrate.c b/bacula/src/dird/migrate.c index 4f94b3bb64..1efd244164 100644 --- a/bacula/src/dird/migrate.c +++ b/bacula/src/dird/migrate.c @@ -32,6 +32,7 @@ #include "bacula.h" #include "dird.h" #include "ua.h" +#include static char OKbootstrap[] = "3000 OK bootstrap\n"; static bool get_job_to_migrate(JCR *jcr); @@ -217,7 +218,7 @@ bool do_migration(JCR *jcr) edit_uint64(jcr->JobId, ed1), jcr->Job); set_jcr_job_status(jcr, JS_Running); - set_jcr_job_status(jcr, JS_Running); + set_jcr_job_status(tjcr, JS_Running); Dmsg2(100, "JobId=%d JobLevel=%c\n", jcr->jr.JobId, jcr->jr.JobLevel); if (!db_update_job_start_record(jcr, jcr->db, &jcr->jr)) { Jmsg(jcr, M_FATAL, 0, "%s", db_strerror(jcr->db)); @@ -262,7 +263,6 @@ bool do_migration(JCR *jcr) return false; } - /* * Now start a Storage daemon message thread */ @@ -303,6 +303,38 @@ static int jobid_handler(void *ctx, int num_fields, char **row) return 0; } + +struct uitem { + dlink link; + char *item; +}; + +static int item_compare(void *item1, void *item2) +{ + uitem *i1 = (uitem *)item1; + uitem *i2 = (uitem *)item2; + return strcmp(i1->item, i2->item); +} + +static int unique_name_handler(void *ctx, int num_fields, char **row) +{ + dlist *list = (dlist *)ctx; + + uitem *new_item = (uitem *)malloc(sizeof(uitem)); + uitem *item; + + memset(new_item, 0, sizeof(uitem)); + new_item->item = bstrdup(row[0]); + + item = (uitem *)list->binary_insert((void *)new_item, item_compare); + if (item != new_item) { /* already in list */ + free(new_item->item); + free((char *)new_item); + return 0; + } + return 0; +} + const char *sql_smallest_vol = "SELECT MediaId FROM Media,Pool WHERE" " VolStatus in ('Full','Used','Error') AND" @@ -338,16 +370,14 @@ const char *sql_client = " Job.PoolId=Media.PoolId"; const char *sql_job = - "SELECT DISTINCT Job.Name from Client,Pool,Media,Job,JobMedia " + "SELECT DISTINCT Job.Name from Pool,Media,Job,JobMedia " " WHERE Media.PoolId=Pool.PoolId AND Pool.Name='%s' AND" - " JobMedia.JobId=Job.JobId AND Job.ClientId=Client.ClientId AND" - " Job.PoolId=Media.PoolId"; + " JobMedia.JobId=Job.JobId AND Job.PoolId=Media.PoolId"; const char *sql_ujobid = "SELECT DISTINCT Job.Job from Client,Pool,Media,Job,JobMedia " " WHERE Media.PoolId=Pool.PoolId AND Pool.Name='%s' AND" - " JobMedia.JobId=Job.JobId AND Job.ClientId=Client.ClientId AND" - " Job.PoolId=Media.PoolId"; + " JobMedia.JobId=Job.JobId AND Job.PoolId=Media.PoolId"; const char *sql_vol = "SELECT DISTINCT VolumeName FROM Media,Pool WHERE" @@ -355,7 +385,6 @@ const char *sql_vol = " Media.PoolId=Pool.PoolId AND Pool.Name='%s'"; - /* * Returns: false on error * true if OK and jcr->previous_jr filled in @@ -366,8 +395,12 @@ static bool get_job_to_migrate(JCR *jcr) POOL_MEM query(PM_MESSAGE); POOLMEM *JobIds = get_pool_memory(PM_MESSAGE); JobId_t JobId; - int stat; + int stat, rc; char *p; + dlist *item_chain; + uitem *item; + char prbuf[500]; + regex_t preg; if (jcr->MigrateJobId != 0) { jcr->previous_jr.JobId = jcr->MigrateJobId; @@ -386,6 +419,7 @@ static bool get_job_to_migrate(JCR *jcr) Jmsg(jcr, M_INFO, 0, _("No Volumes found to migrate.\n")); goto ok_out; } + /* ***FIXME*** must loop over JobIds */ Mmsg(query, sql_jobids_from_mediaid, JobIds); JobIds[0] = 0; if (!db_sql_query(jcr->db, query.c_str(), jobid_handler, (void *)JobIds)) { @@ -405,7 +439,7 @@ static bool get_job_to_migrate(JCR *jcr) goto bail_out; } if (JobIds[0] == 0) { - Jmsg(jcr, M_INFO, 0, _("No jobs found to migrate.\n")); + Jmsg(jcr, M_INFO, 0, _("No Volume found to migrate.\n")); goto ok_out; } Mmsg(query, sql_jobids_from_mediaid, JobIds); @@ -434,10 +468,103 @@ static bool get_job_to_migrate(JCR *jcr) case MT_POOL_TIME: break; case MT_CLIENT: + if (!jcr->job->selection_pattern) { + Jmsg(jcr, M_FATAL, 0, _("No selection pattern specified.\n")); + goto bail_out; + } + rc = regcomp(&preg, jcr->job->selection_pattern, REG_EXTENDED); + if (rc != 0) { + regerror(rc, &preg, prbuf, sizeof(prbuf)); + Jmsg(jcr, M_FATAL, 0, _("Could not compile regex pattern \"%s\" ERR=%s\n"), + jcr->job->selection_pattern, prbuf); + } + item_chain = New(dlist(item, &item->link)); + Mmsg(query, sql_client, jcr->pool->hdr.name); + Dmsg1(100, "query=%s\n", query.c_str()); + if (!db_sql_query(jcr->db, query.c_str(), unique_name_handler, + (void *)item_chain)) { + Jmsg(jcr, M_FATAL, 0, + _("SQL to get Client failed. ERR=%s\n"), db_strerror(jcr->db)); + goto bail_out; + } + /* Now apply the regex and create the jobs */ + foreach_dlist(item, item_chain) { + const int nmatch = 30; + regmatch_t pmatch[nmatch]; + rc = regexec(&preg, item->item, nmatch, pmatch, 0); + if (rc == 0) { + Dmsg1(000, "Do Client=%s\n", item->item); + } + free(item->item); + } + regfree(&preg); + delete item_chain; break; case MT_VOLUME: + if (!jcr->job->selection_pattern) { + Jmsg(jcr, M_FATAL, 0, _("No selection pattern specified.\n")); + goto bail_out; + } + rc = regcomp(&preg, jcr->job->selection_pattern, REG_EXTENDED); + if (rc != 0) { + regerror(rc, &preg, prbuf, sizeof(prbuf)); + Jmsg(jcr, M_FATAL, 0, _("Could not compile regex pattern \"%s\" ERR=%s\n"), + jcr->job->selection_pattern, prbuf); + } + item_chain = New(dlist(item, &item->link)); + Mmsg(query, sql_vol, jcr->pool->hdr.name); + Dmsg1(100, "query=%s\n", query.c_str()); + if (!db_sql_query(jcr->db, query.c_str(), unique_name_handler, + (void *)item_chain)) { + Jmsg(jcr, M_FATAL, 0, + _("SQL to get Job failed. ERR=%s\n"), db_strerror(jcr->db)); + goto bail_out; + } + /* Now apply the regex and create the jobs */ + foreach_dlist(item, item_chain) { + const int nmatch = 30; + regmatch_t pmatch[nmatch]; + rc = regexec(&preg, item->item, nmatch, pmatch, 0); + if (rc == 0) { + Dmsg1(000, "Do Vol=%s\n", item->item); + } + free(item->item); + } + regfree(&preg); + delete item_chain; break; case MT_JOB: + if (!jcr->job->selection_pattern) { + Jmsg(jcr, M_FATAL, 0, _("No selection pattern specified.\n")); + goto bail_out; + } + rc = regcomp(&preg, jcr->job->selection_pattern, REG_EXTENDED); + if (rc != 0) { + regerror(rc, &preg, prbuf, sizeof(prbuf)); + Jmsg(jcr, M_FATAL, 0, _("Could not compile regex pattern \"%s\" ERR=%s\n"), + jcr->job->selection_pattern, prbuf); + } + item_chain = New(dlist(item, &item->link)); + Mmsg(query, sql_job, jcr->pool->hdr.name); + Dmsg1(100, "query=%s\n", query.c_str()); + if (!db_sql_query(jcr->db, query.c_str(), unique_name_handler, + (void *)item_chain)) { + Jmsg(jcr, M_FATAL, 0, + _("SQL to get Job failed. ERR=%s\n"), db_strerror(jcr->db)); + goto bail_out; + } + /* Now apply the regex and create the jobs */ + foreach_dlist(item, item_chain) { + const int nmatch = 30; + regmatch_t pmatch[nmatch]; + rc = regexec(&preg, item->item, nmatch, pmatch, 0); + if (rc == 0) { + Dmsg1(000, "Do Job=%s\n", item->item); + } + free(item->item); + } + regfree(&preg); + delete item_chain; break; case MT_SQLQUERY: JobIds[0] = 0; diff --git a/bacula/src/dird/msgchan.c b/bacula/src/dird/msgchan.c index 42dd9446e5..524c2e520b 100644 --- a/bacula/src/dird/msgchan.c +++ b/bacula/src/dird/msgchan.c @@ -141,6 +141,16 @@ bool start_storage_daemon_job(JCR *jcr, alist *rstore, alist *wstore) if (jcr->fileset->MD5[0] == 0) { bstrncpy(jcr->fileset->MD5, "**Dummy**", sizeof(jcr->fileset->MD5)); } + /* If rescheduling, cancel the previous incarnation of this job + * with the SD, which might be waiting on the FD connection. + * If we do not cancel it the SD will not accept a new connection + * for the same jobid. + */ + if (jcr->reschedule_count) { + bnet_fsend(sd, "cancel Job=%s\n", jcr->Job); + while (bnet_recv(sd) >= 0) + { } + } bnet_fsend(sd, jobcmd, jcr->JobId, jcr->Job, jcr->job->hdr.name, jcr->client->hdr.name, jcr->JobType, jcr->JobLevel, jcr->fileset->hdr.name, !jcr->pool->catalog_files, diff --git a/bacula/src/dird/protos.h b/bacula/src/dird/protos.h index db1d32f6d2..03b4e4d45f 100644 --- a/bacula/src/dird/protos.h +++ b/bacula/src/dird/protos.h @@ -34,9 +34,9 @@ extern int do_autoprune(JCR *jcr); extern int prune_volumes(JCR *jcr); /* autorecycle.c */ -extern int recycle_oldest_purged_volume(JCR *jcr, bool InChanger, MEDIA_DBR *mr); +extern bool recycle_oldest_purged_volume(JCR *jcr, bool InChanger, MEDIA_DBR *mr); extern int recycle_volume(JCR *jcr, MEDIA_DBR *mr); -extern int find_recycled_volume(JCR *jcr, bool InChanger, MEDIA_DBR *mr); +extern bool find_recycled_volume(JCR *jcr, bool InChanger, MEDIA_DBR *mr); /* backup.c */ extern int wait_for_job_termination(JCR *jcr); diff --git a/bacula/src/dird/recycle.c b/bacula/src/dird/recycle.c index f034fae717..b8d0fc9d56 100644 --- a/bacula/src/dird/recycle.c +++ b/bacula/src/dird/recycle.c @@ -46,23 +46,23 @@ static int oldest_handler(void *ctx, int num_fields, char **row) /* Forward referenced functions */ -int find_recycled_volume(JCR *jcr, bool InChanger, MEDIA_DBR *mr) +bool find_recycled_volume(JCR *jcr, bool InChanger, MEDIA_DBR *mr) { bstrncpy(mr->VolStatus, "Recycle", sizeof(mr->VolStatus)); if (db_find_next_volume(jcr, jcr->db, 1, InChanger, mr)) { jcr->MediaId = mr->MediaId; Dmsg1(20, "Find_next_vol MediaId=%u\n", jcr->MediaId); pm_strcpy(jcr->VolumeName, mr->VolumeName); - return 1; + return true; } - return 0; + return false; } /* * Look for oldest Purged volume */ -int recycle_oldest_purged_volume(JCR *jcr, bool InChanger, MEDIA_DBR *mr) +bool recycle_oldest_purged_volume(JCR *jcr, bool InChanger, MEDIA_DBR *mr) { struct s_oldest_ctx oldest; char ed1[50]; @@ -88,7 +88,7 @@ int recycle_oldest_purged_volume(JCR *jcr, bool InChanger, MEDIA_DBR *mr) Jmsg(jcr, M_ERROR, 0, "%s", db_strerror(jcr->db)); Dmsg0(100, "return 0 recycle_oldest_purged_volume query\n"); free_pool_memory(query); - return 0; + return false; } free_pool_memory(query); Dmsg1(100, "Oldest mediaid=%d\n", oldest.MediaId); @@ -98,13 +98,13 @@ int recycle_oldest_purged_volume(JCR *jcr, bool InChanger, MEDIA_DBR *mr) if (recycle_volume(jcr, mr)) { Jmsg(jcr, M_INFO, 0, _("Recycled volume \"%s\"\n"), mr->VolumeName); Dmsg1(100, "return 1 recycle_oldest_purged_volume Vol=%s\n", mr->VolumeName); - return 1; + return true; } } Jmsg(jcr, M_ERROR, 0, "%s", db_strerror(jcr->db)); } Dmsg0(100, "return 0 recycle_oldest_purged_volume end\n"); - return 0; + return false; } /* diff --git a/bacula/src/dird/ua.h b/bacula/src/dird/ua.h index e88143095a..b06f62c7cb 100644 --- a/bacula/src/dird/ua.h +++ b/bacula/src/dird/ua.h @@ -98,7 +98,7 @@ struct RESTORE_CTX { NAME_LIST name_list; }; -#define MAX_ID_LIST_LEN 1000000 +#define MAX_ID_LIST_LEN 2000000 #endif diff --git a/bacula/src/dird/ua_dotcmds.c b/bacula/src/dird/ua_dotcmds.c index 688ceb8764..60f9c62e09 100644 --- a/bacula/src/dird/ua_dotcmds.c +++ b/bacula/src/dird/ua_dotcmds.c @@ -37,7 +37,7 @@ extern const char *client_backups; extern int console_msg_pending; /* Imported functions */ -extern int do_messages(UAContext *ua, const char *cmd); +extern void do_messages(UAContext *ua, const char *cmd); extern int quit_cmd(UAContext *ua, const char *cmd); extern int qhelp_cmd(UAContext *ua, const char *cmd); extern int qstatus_cmd(UAContext *ua, const char *cmd); diff --git a/bacula/src/dird/ua_prune.c b/bacula/src/dird/ua_prune.c index 7fdd575407..c6e8dd0d13 100644 --- a/bacula/src/dird/ua_prune.c +++ b/bacula/src/dird/ua_prune.c @@ -30,7 +30,7 @@ /* Forward referenced functions */ -#define MAX_DEL_LIST_LEN 1000000 +#define MAX_DEL_LIST_LEN 2000000 /* Imported variables */ extern char *select_job; @@ -46,6 +46,7 @@ extern char *del_File; extern char *upd_Purged; extern char *cnt_DelCand; extern char *del_Job; +extern char *del_MAC; extern char *del_JobMedia; extern char *cnt_JobMedia; extern char *sel_JobMedia; @@ -556,6 +557,8 @@ int prune_volume(UAContext *ua, MEDIA_DBR *mr) db_sql_query(ua->db, query, NULL, (void *)NULL); Mmsg(query, del_JobMedia, ed1); db_sql_query(ua->db, query, NULL, (void *)NULL); + Mmsg(query, del_MAC, ed1); + db_sql_query(ua->db, query, NULL, (void *)NULL); Dmsg1(050, "Del sql=%s\n", query); del.num_del++; } @@ -567,8 +570,18 @@ int prune_volume(UAContext *ua, MEDIA_DBR *mr) del.num_del == 1 ? "Job" : "Jobs", mr->VolumeName); } - /* If purged, mark it so */ - if (del.num_ids == del.num_del) { + /* + * Find out how many Jobs remain on this Volume by + * counting the JobMedia records. + */ + cnt.count = 0; + Mmsg(query, cnt_JobMedia, edit_int64(mr->MediaId, ed1)); + if (!db_sql_query(ua->db, query, count_handler, (void *)&cnt)) { + bsendmsg(ua, "%s", db_strerror(ua->db)); + Dmsg0(050, "Count failed\n"); + goto bail_out; + } + if (cnt.count == 0) { Dmsg0(200, "Volume is purged.\n"); stat = mark_media_purged(ua, mr); } diff --git a/bacula/src/lib/dlist.c b/bacula/src/lib/dlist.c index 9fff70c173..f3d59b1ce6 100644 --- a/bacula/src/lib/dlist.c +++ b/bacula/src/lib/dlist.c @@ -2,7 +2,7 @@ * Bacula doubly linked list routines. * * dlist is a doubly linked list with the links being in the - * list data item. + * list data item. * * Kern Sibbald, July MMIII * @@ -10,7 +10,7 @@ * */ /* - Copyright (C) 2003-2005 Kern Sibbald + Copyright (C) 2003-2006 Kern Sibbald This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -41,8 +41,8 @@ void dlist::append(void *item) ((dlink *)(((char *)tail)+loffset))->next = item; } tail = item; - if (head == NULL) { /* if empty list, */ - head = item; /* item is head as well */ + if (head == NULL) { /* if empty list, */ + head = item; /* item is head as well */ } num_items++; } @@ -58,8 +58,8 @@ void dlist::prepend(void *item) ((dlink *)(((char *)head)+loffset))->prev = item; } head = item; - if (tail == NULL) { /* if empty list, */ - tail = item; /* item is tail too */ + if (tail == NULL) { /* if empty list, */ + tail = item; /* item is tail too */ } num_items++; } @@ -102,8 +102,8 @@ void dlist::insert_after(void *item, void *where) * Insert an item in the list, but only if it is unique * otherwise, the item is returned non inserted * - * Returns: item if item inserted - * other_item if same value already exists (item not inserted) + * Returns: item if item inserted + * other_item if same value already exists (item not inserted) */ void *dlist::binary_insert(void *item, int compare(void *item1, void *item2)) { @@ -119,16 +119,16 @@ void *dlist::binary_insert(void *item, int compare(void *item1, void *item2)) if (num_items == 1) { comp = compare(item, first()); if (comp < 0) { - prepend(item); + prepend(item); //Dmsg0(000, "Insert before first.\n"); - return item; + return item; } else if (comp > 0) { - insert_after(item, first()); + insert_after(item, first()); //Dmsg0(000, "Insert after first.\n"); - return item; + return item; } else { //Dmsg0(000, "Same as first.\n"); - return first(); + return first(); } } /* Check against last item */ @@ -164,25 +164,25 @@ void *dlist::binary_insert(void *item, int compare(void *item1, void *item2)) int nxt; nxt = (low + high) / 2; while (nxt > cur) { - cur_item = next(cur_item); - cur++; + cur_item = next(cur_item); + cur++; } while (nxt < cur) { - cur_item = prev(cur_item); - cur--; + cur_item = prev(cur_item); + cur--; } //Dmsg1(000, "Compare item to %d\n", cur); comp = compare(item, cur_item); //Dmsg2(000, "Compare item to %d = %d\n", cur, comp); if (comp < 0) { - high = cur; + high = cur; //Dmsg2(000, "set high; low=%d high=%d\n", low, high); } else if (comp > 0) { - low = cur + 1; + low = cur + 1; //Dmsg2(000, "set low; low=%d high=%d\n", low, high); } else { //Dmsg1(000, "Same as item %d\n", cur); - return cur_item; + return cur_item; } } if (high == cur) { @@ -225,9 +225,9 @@ void *dlist::binary_search(void *item, int compare(void *item1, void *item2)) if (num_items == 1) { comp = compare(item, cur_item); if (comp == 0) { - return cur_item; + return cur_item; } else { - return NULL; + return NULL; } } low = 1; @@ -239,35 +239,35 @@ void *dlist::binary_search(void *item, int compare(void *item1, void *item2)) nxt = (low + high) / 2; /* Now get cur pointing to nxt */ while (nxt > cur) { - cur_item = next(cur_item); - cur++; + cur_item = next(cur_item); + cur++; } while (nxt < cur) { - cur_item = prev(cur_item); - cur--; + cur_item = prev(cur_item); + cur--; } comp = compare(item, cur_item); //Dmsg2(000, "Compare item to %d = %d\n", cur, comp); if (comp < 0) { - high = cur; + high = cur; //Dmsg2(000, "set high; low=%d high=%d\n", low, high); } else if (comp > 0) { - low = cur + 1; + low = cur + 1; //Dmsg2(000, "set low; low=%d high=%d\n", low, high); } else { - return cur_item; + return cur_item; } } /* * low == high can only happen if low just - * got incremented from cur, and we have - * not yet tested cur+1 + * got incremented from cur, and we have + * not yet tested cur+1 */ if (low == high) { cur_item = next(cur_item); comp = compare(item, cur_item); if (comp == 0) { - return cur_item; + return cur_item; } } return NULL; @@ -281,15 +281,15 @@ void dlist::remove(void *item) if (item == head) { head = ilink->next; if (head) { - ((dlink *)(((char *)head)+loffset))->prev = NULL; + ((dlink *)(((char *)head)+loffset))->prev = NULL; } if (item == tail) { - tail = ilink->prev; + tail = ilink->prev; } } else if (item == tail) { tail = ilink->prev; if (tail) { - ((dlink *)(((char *)tail)+loffset))->next = NULL; + ((dlink *)(((char *)tail)+loffset))->next = NULL; } } else { xitem = ilink->next; @@ -371,7 +371,7 @@ int main() jcr->buf = bstrdup(buf); jcr_chain->prepend(jcr); if (i == 10) { - save_jcr = jcr; + save_jcr = jcr; } } @@ -401,7 +401,7 @@ int main() jcr->buf = bstrdup(buf); jcr_chain->append(jcr); if (i == 10) { - save_jcr = jcr; + save_jcr = jcr; } } @@ -432,21 +432,21 @@ int main() int count = 0; for (int i=0; ibuf = bstrdup(buf); - jcr1 = (MYJCR *)jcr_chain->binary_insert(jcr, my_compare); - if (jcr != jcr1) { + } + jcr = (MYJCR *)malloc(sizeof(MYJCR)); + jcr->buf = bstrdup(buf); + jcr1 = (MYJCR *)jcr_chain->binary_insert(jcr, my_compare); + if (jcr != jcr1) { Dmsg2(000, "Insert of %s vs %s failed.\n", jcr->buf, jcr1->buf); - } - buf[1]--; - } + } + buf[1]--; + } buf[1] = 'Z'; - buf[2]--; + buf[2]--; } buf[2] = 'Z'; buf[0]--; diff --git a/bacula/src/lib/dlist.h b/bacula/src/lib/dlist.h index ce975f4865..40c54f0133 100644 --- a/bacula/src/lib/dlist.h +++ b/bacula/src/lib/dlist.h @@ -2,7 +2,7 @@ * Version $Id$ */ /* - Copyright (C) 2004-2005 Kern Sibbald + Copyright (C) 2004-2006 Kern Sibbald This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License diff --git a/bacula/src/lib/protos.h b/bacula/src/lib/protos.h index eedbc018cb..e24292a7c3 100644 --- a/bacula/src/lib/protos.h +++ b/bacula/src/lib/protos.h @@ -235,6 +235,8 @@ void init_stack_dump (void); /* scan.c */ void strip_leading_space (char *str); void strip_trailing_junk (char *str); +void strip_trailing_newline (char *str); + void strip_trailing_slashes (char *dir); bool skip_spaces (char **msg); bool skip_nonspaces (char **msg); diff --git a/bacula/src/lib/scan.c b/bacula/src/lib/scan.c index cfb5751300..53c4024210 100644 --- a/bacula/src/lib/scan.c +++ b/bacula/src/lib/scan.c @@ -49,6 +49,16 @@ void strip_trailing_junk(char *cmd) *p-- = 0; } +/* Strip any trailing newline characters from the string */ +void strip_trailing_newline(char *cmd) +{ + char *p; + p = cmd + strlen(cmd) - 1; + + while ((p >= cmd) && (*p == '\n' || *p == '\r')) + *p-- = 0; +} + /* Strip any trailing slashes from a directory path */ void strip_trailing_slashes(char *dir) { diff --git a/bacula/src/lib/tree.c b/bacula/src/lib/tree.c index 6035e72f38..b223ef8a94 100755 --- a/bacula/src/lib/tree.c +++ b/bacula/src/lib/tree.c @@ -5,7 +5,7 @@ * */ /* - Copyright (C) 2002-2005 Kern Sibbald + Copyright (C) 2002-2006 Kern Sibbald This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License diff --git a/bacula/src/lib/tree.h b/bacula/src/lib/tree.h index 3a696e235d..c5faa14945 100644 --- a/bacula/src/lib/tree.h +++ b/bacula/src/lib/tree.h @@ -5,7 +5,7 @@ * */ /* - Copyright (C) 2002-2005 Kern Sibbald + Copyright (C) 2002-2006 Kern Sibbald This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License diff --git a/bacula/src/stored/acquire.c b/bacula/src/stored/acquire.c index 9528f786c5..34b2860986 100644 --- a/bacula/src/stored/acquire.c +++ b/bacula/src/stored/acquire.c @@ -47,6 +47,7 @@ bool acquire_device_for_read(DCR *dcr) bool try_autochanger = true; int i; int vol_label_status; + int retry = 0; Dmsg1(50, "jcr->dcr=%p\n", jcr->dcr); dev->block(BST_DOING_ACQUIRE); @@ -156,7 +157,11 @@ bool acquire_device_for_read(DCR *dcr) Jmsg1(jcr, M_WARNING, 0, "%s", jcr->errmsg); } - for (i=0; i<5; i++) { + for ( ;; ) { + /* If not polling limit retries */ + if (!dev->poll && retry++ > 10) { + break; + } dev->clear_labeled(); /* force reread of label */ if (job_canceled(jcr)) { Mmsg1(dev->errmsg, _("Job %d canceled.\n"), jcr->JobId); @@ -205,6 +210,12 @@ bool acquire_device_for_read(DCR *dcr) tape_initially_mounted = false; goto default_path; } + /* If polling and got a previous bad name, ignore it */ + if (dev->poll && strcmp(dev->BadVolName, dev->VolHdr.VolumeName) == 0) { + goto default_path; + } else { + bstrncpy(dev->BadVolName, dev->VolHdr.VolumeName, sizeof(dev->BadVolName)); + } /* Fall through */ default: Jmsg1(jcr, M_WARNING, 0, "%s", jcr->errmsg); diff --git a/bacula/src/tools/Makefile.in b/bacula/src/tools/Makefile.in index 2debf389cb..d961440392 100644 --- a/bacula/src/tools/Makefile.in +++ b/bacula/src/tools/Makefile.in @@ -38,7 +38,7 @@ EXTRAOBJS = @OBJLIST@ DIRCONFOBJS = ../dird/dird_conf.o ../dird/run_conf.o ../dird/inc_conf.o NODIRTOOLS = bsmtp -DIRTOOLS = bsmtp dbcheck fstype testfind testls +DIRTOOLS = bsmtp dbcheck fstype testfind testls regex TOOLS = $(@DIR_TOOLS@) INSNODIRTOOLS = bsmtp @@ -75,6 +75,11 @@ testls: ../findlib/libfind.a ../lib/libbac.a testls.o $(CXX) -g $(LDFLAGS) -L. -L../lib -L../findlib -o $@ testls.o \ $(DLIB) -lfind -lbac -lm $(LIBS) $(GETTEXT_LIBS) $(OPENSSL_LIBS) +regex: ../findlib/libfind.a ../lib/libbac.a regex.o + $(CXX) -g $(LDFLAGS) -L. -L../lib -o $@ regex.o \ + $(DLIB) -lbac -lm $(LIBS) $(GETTEXT_LIBS) $(OPENSSL_LIBS) + + Makefile: $(srcdir)/Makefile.in $(topdir)/config.status cd $(topdir) \ && CONFIG_FILES=$(thisdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status diff --git a/bacula/src/tools/bsmtp.c b/bacula/src/tools/bsmtp.c index ab6883db73..cb994bdf20 100644 --- a/bacula/src/tools/bsmtp.c +++ b/bacula/src/tools/bsmtp.c @@ -1,5 +1,5 @@ /* - Copyright (C) 2001-2005 Kern Sibbald + Copyright (C) 2001-2006 Kern Sibbald This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -147,7 +147,7 @@ int main (int argc, char *argv[]) time_t now = time(NULL); struct tm tm; - setlocale(LC_ALL, ""); + setlocale(LC_ALL, "en_US"); bindtextdomain("bacula", LOCALEDIR); textdomain("bacula"); @@ -313,35 +313,46 @@ hp: * Send message header */ fprintf(sfp, "From: %s\r\n", from_addr); + Dmsg1(10, "From: %s\r\n", from_addr); if (subject) { fprintf(sfp, "Subject: %s\r\n", subject); + Dmsg1(10, "Subject: %s\r\n", subject); } if (reply_addr) { fprintf(sfp, "Reply-To: %s\r\n", reply_addr); + Dmsg1(10, "Reply-To: %s\r\n", reply_addr); } if (err_addr) { fprintf(sfp, "Errors-To: %s\r\n", err_addr); + Dmsg1(10, "Errors-To: %s\r\n", err_addr); } if ((pwd = getpwuid(getuid())) == 0) { fprintf(sfp, "Sender: userid-%d@%s\r\n", (int)getuid(), my_hostname); + Dmsg2(10, "Sender: userid-%d@%s\r\n", (int)getuid(), my_hostname); } else { fprintf(sfp, "Sender: %s@%s\r\n", pwd->pw_name, my_hostname); + Dmsg2(10, "Sender: %s@%s\r\n", pwd->pw_name, my_hostname); } fprintf(sfp, "To: %s", argv[0]); + Dmsg1(10, "To: %s", argv[0]); for (i = 1; i < argc; i++) { fprintf(sfp, ",%s", argv[i]); + Dmsg1(10, ",%s", argv[i]); } fprintf(sfp, "\r\n"); + Dmsg0(10, "\r\n"); if (cc_addr) { fprintf(sfp, "Cc: %s\r\n", cc_addr); + Dmsg1(10, "Cc: %s\r\n", cc_addr); } /* Add RFC822 date */ localtime_r(&now, &tm); strftime(buf, sizeof(buf), "%a, %d %b %Y %H:%M:%S %z", &tm); fprintf(sfp, "Date: %s\r\n", buf); + Dmsg1(10, "Date: %s\r\n", buf); fprintf(sfp, "\r\n"); diff --git a/bacula/src/tools/regex.c b/bacula/src/tools/regex.c new file mode 100644 index 0000000000..c2dcd58f9c --- /dev/null +++ b/bacula/src/tools/regex.c @@ -0,0 +1,137 @@ +/* + * Test program for testing regular expressions. + */ +/* + Copyright (C) 2006 Kern Sibbald + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + version 2 as amended with additional clauses defined in the + file LICENSE in the main source directory. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + the file LICENSE for additional details. + + */ + +#include "bacula.h" +#ifdef HAVE_REGEX_H +#include +#endif + + +static void usage() +{ + fprintf(stderr, +"\n" +"Usage: regex [-d debug_level] -f \n" +" -f specify file of data to be matched\n" +" -l suppress line numbers\n" +" -n print lines that do not match\n" +" -? print this message.\n" +"\n\n"); + + exit(1); +} + + +int main(int argc, char *const *argv) +{ +#ifndef HAVE_REGEX_H + printf("The regex libraries don't seem to be available.\n"); + exit(1); +#else + regex_t preg; + char prbuf[500]; + char *fname = NULL; + int rc, ch; + char data[1000]; + char pat[500]; + FILE *fd; + bool match_only = true; + int lineno; + bool no_linenos = false; + + + setlocale(LC_ALL, ""); + bindtextdomain("bacula", LOCALEDIR); + textdomain("bacula"); + + while ((ch = getopt(argc, argv, "d:f:n?")) != -1) { + switch (ch) { + case 'd': /* set debug level */ + debug_level = atoi(optarg); + if (debug_level <= 0) { + debug_level = 1; + } + break; + + case 'f': /* data */ + fname = optarg; + break; + + case 'l': + no_linenos = true; + break; + + case 'n': + match_only = false; + break; + + case '?': + default: + usage(); + + } + } + argc -= optind; + argv += optind; + + if (!fname) { + printf("A data file must be specified.\n"); + usage(); + } + + for ( ;; ) { + printf("Enter regex pattern: "); + if (fgets(pat, sizeof(pat)-1, stdin) == NULL) { + break; + } + strip_trailing_newline(pat); + if (pat[0] == 0) { + exit(0); + } + rc = regcomp(&preg, pat, REG_EXTENDED); + if (rc != 0) { + regerror(rc, &preg, prbuf, sizeof(prbuf)); + printf("Regex compile error: %s\n", prbuf); + continue; + } + fd = fopen(fname, "r"); + if (!fd) { + printf(_("Could not open data file: %s\n"), fname); + exit(1); + } + lineno = 0; + while (fgets(data, sizeof(data)-1, fd)) { + const int nmatch = 30; + regmatch_t pmatch[nmatch]; + strip_trailing_newline(data); + lineno++; + rc = regexec(&preg, data, nmatch, pmatch, 0); + if ((match_only && rc == 0) || (!match_only && rc != 0)) { + if (no_linenos) { + printf("%s\n", data); + } else { + printf("%5d: %s\n", lineno, data); + } + } + } + fclose(fd); + regfree(&preg); + } + exit(0); +#endif +} diff --git a/bacula/src/version.h b/bacula/src/version.h index e65726357c..5756349191 100644 --- a/bacula/src/version.h +++ b/bacula/src/version.h @@ -4,8 +4,8 @@ #undef VERSION #define VERSION "1.39.6" -#define BDATE "14 March 2006" -#define LSMDATE "14Mar06" +#define BDATE "17 March 2006" +#define LSMDATE "17Mar06" /* Debug flags */ #undef DEBUG