@MCOMMON@
working_dir=@working_dir@
+dir_group=@dir_group@
+dir_user=@dir_user@
srcdir = @srcdir@
VPATH = @srcdir@
$(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:
- 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
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.
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.
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.
* 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
#include "bacula.h"
#include "dird.h"
#include "ua.h"
+#include <regex.h>
static char OKbootstrap[] = "3000 OK bootstrap\n";
static bool get_job_to_migrate(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));
return false;
}
-
/*
* Now start a Storage daemon message thread
*/
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"
" 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"
" Media.PoolId=Pool.PoolId AND Pool.Name='%s'";
-
/*
* Returns: false on error
* true if OK and jcr->previous_jr filled in
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;
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)) {
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);
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;
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,
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);
/* 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];
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);
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;
}
/*
NAME_LIST name_list;
};
-#define MAX_ID_LIST_LEN 1000000
+#define MAX_ID_LIST_LEN 2000000
#endif
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);
/* Forward referenced functions */
-#define MAX_DEL_LIST_LEN 1000000
+#define MAX_DEL_LIST_LEN 2000000
/* Imported variables */
extern char *select_job;
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;
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++;
}
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);
}
* 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
*
*
*/
/*
- 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
((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++;
}
((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++;
}
* 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))
{
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 */
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) {
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;
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;
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;
jcr->buf = bstrdup(buf);
jcr_chain->prepend(jcr);
if (i == 10) {
- save_jcr = jcr;
+ save_jcr = jcr;
}
}
jcr->buf = bstrdup(buf);
jcr_chain->append(jcr);
if (i == 10) {
- save_jcr = jcr;
+ save_jcr = jcr;
}
}
int count = 0;
for (int i=0; i<CNT; i++) {
for (int j=0; j<CNT; j++) {
- for (int k=0; k<CNT; k++) {
- count++;
- if ((count & 0x3FF) == 0) {
+ for (int k=0; k<CNT; k++) {
+ count++;
+ if ((count & 0x3FF) == 0) {
Dmsg1(000, "At %d\n", count);
- }
- jcr = (MYJCR *)malloc(sizeof(MYJCR));
- jcr->buf = 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]--;
* 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
/* 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);
*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)
{
*
*/
/*
- 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
*
*/
/*
- 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
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);
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);
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);
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
$(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
/*
- 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
time_t now = time(NULL);
struct tm tm;
- setlocale(LC_ALL, "");
+ setlocale(LC_ALL, "en_US");
bindtextdomain("bacula", LOCALEDIR);
textdomain("bacula");
* 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");
--- /dev/null
+/*
+ * 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 <regex.h>
+#endif
+
+
+static void usage()
+{
+ fprintf(stderr,
+"\n"
+"Usage: regex [-d debug_level] -f <data-file>\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
+}
#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