Kern's ToDo List
- 03 August 2004
+ 05 August 2004
Major development:
Project Developer
1.35 Items to do for release:
- Knoppix CDROM
-- Add bscan to four-concurrent-jobs regression.
-- Doc new IPv6 syntax
-- Add IPv6 to regression
-- Do tape alerts -- see tapealert.txt
-- 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?".
-- When passwords do not match, print message that points the
- user to the doc.
- Make Verify jobs require exclusive use of Volume as Restore
jobs do.
- Perhaps add read/write programs and/or plugins to FileSets.
-- Look at adding Client run command that will use the
- port opened by the client.
-- Fix find_device in stored/dircmd.c:462
-- Add new DCR calling sequences everywhere in SD.
- This will permit simultaneous use of multiple
- devices by a single job.
-- bscan does not put first of two volumes back with all info in
- bscan-test.
+- Add new DCR calling sequences everywhere in SD. This will permit
+ simultaneous use of multiple devices by a single job.
- Fix restore ++++ that get intermingled with "Building directory tree"
- Solve the termcap.h problem on Solaris configure.
-- Fix ./configure to handle installed SQLite
-- Test Win32 errno handling.
-
+- Test Win32 errno handling.
+- Add bscan to four-concurrent-jobs regression.
+- Doc new IPv6 syntax
+- Add IPv6 to regression
+- Alternative to static linking "ldd prog" save all binaries listed,
+ restore them and point LD_LIBRARY_PATH to them.
+- 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?".
+- Test Tape Alerts
+- Doc update AllFromVol
+- Doc dbcheck eliminate orphaned clients.
+
Documentation to do: (any release a little bit at a time)
- Document query file format.
+- Add more documentation for bsr files.
- Document problems with Verify and pruning.
- Document how to use multiple databases.
- VXA drives have a "cleaning required"
- Document doing table repair
Testing to do: (painful)
-- Test drive polling!
-- blocksize recognition code.
-- Test if rewind at end of tape waits for tape to rewind.
-- Test cancel at EOM.
+
For 1.37 Testing/Documentation:
+- Fix find_device in stored/dircmd.c:462 (see code)
- Add db check test to regression. Test each function like delete,
purge, ...
- If you use restore replace=never, the directory attributes for
non-existent directories will not be restored properly.
Wish list:
+- Look at adding Client run command that will use the
+ port opened by the client.
+- bscan does not put first of two volumes back with all info in
+ bscan-test.
- Implement the FreeBSD nodump flag in chflags.
- Figure out how to make named console messages go only to that
console and to the non-restricted console (new console class?).
- Add better error codes to run_program (10000+)
- Revisit and revise Disaster Recovery (fix SCSI and RAID
disk detection)
+- When passwords do not match, print message that points the
+ user to the doc.
+- Do tape alerts -- see tapealert.txt
+
return 0;
}
+int db_update_media_defaults(JCR *jcr, B_DB *mdb, MEDIA_DBR *mr)
+{
+ return 1;
+}
+
#endif /* HAVE_BACULA_DB */
/* sql.c */
B_DB *db_init_database(JCR *jcr, const char *db_name, const char *db_user, const char *db_password,
- const char *db_address, int db_port, const char *db_socket);
+ const char *db_address, int db_port, const char *db_socket);
int db_open_database(JCR *jcr, B_DB *db);
void db_close_database(JCR *jcr, B_DB *db);
void db_escape_string(char *snew, char *old, int len);
int db_create_media_record(JCR *jcr, B_DB *db, MEDIA_DBR *media_dbr);
int db_create_client_record(JCR *jcr, B_DB *db, CLIENT_DBR *cr);
int db_create_fileset_record(JCR *jcr, B_DB *db, FILESET_DBR *fsr);
-int db_create_pool_record(JCR *jcr, B_DB *db, POOL_DBR *pool_dbr);
+int db_create_pool_record(JCR *jcr, B_DB *db, POOL_DBR *pool_dbr);
int db_create_jobmedia_record(JCR *jcr, B_DB *mdb, JOBMEDIA_DBR *jr);
int db_create_counter_record(JCR *jcr, B_DB *mdb, COUNTER_DBR *cr);
int db_update_client_record(JCR *jcr, B_DB *mdb, CLIENT_DBR *cr);
int db_update_pool_record(JCR *jcr, B_DB *db, POOL_DBR *pr);
int db_update_media_record(JCR *jcr, B_DB *db, MEDIA_DBR *mr);
+int db_update_media_defaults(JCR *jcr, B_DB *mdb, MEDIA_DBR *mr);
int db_update_counter_record(JCR *jcr, B_DB *mdb, COUNTER_DBR *cr);
int db_add_SIG_to_file_record(JCR *jcr, B_DB *mdb, FileId_t FileId, char *SIG, int type);
int db_mark_file_record(JCR *jcr, B_DB *mdb, FileId_t FileId, JobId_t JobId);
return stat;
}
+/*
+ * Update the Media Record Default values from Pool
+ *
+ * Returns: 0 on failure
+ * numrows on success
+ */
+int
+db_update_media_defaults(JCR *jcr, B_DB *mdb, MEDIA_DBR *mr)
+{
+ int stat;
+ char ed1[30], ed2[30], ed3[30];
+
+
+ db_lock(mdb);
+ if (mr->VolumeName[0]) {
+ Mmsg(&mdb->cmd, "UPDATE Media SET "
+ "Recycle=%d,VolRetention=%s,VolUseDuration=%s,"
+ "MaxVolJobs=%u,MaxVolFiles=%u,MaxVolBytes=%s"
+ " WHERE VolumeName='%s'",
+ mr->Recycle,edit_uint64(mr->VolRetention, ed1),
+ edit_uint64(mr->VolUseDuration, ed2),
+ mr->MaxVolJobs, mr->MaxVolFiles,
+ edit_uint64(mr->VolBytes, ed3),
+ mr->VolumeName);
+ } else {
+ Mmsg(&mdb->cmd, "UPDATE Media SET "
+ "Recycle=%d,VolRetention=%s,VolUseDuration=%s,"
+ "MaxVolJobs=%u,MaxVolFiles=%u,MaxVolBytes=%s"
+ " WHERE PoolId=%u",
+ mr->Recycle,edit_uint64(mr->VolRetention, ed1),
+ edit_uint64(mr->VolUseDuration, ed2),
+ mr->MaxVolJobs, mr->MaxVolFiles,
+ edit_uint64(mr->VolBytes, ed3),
+ mr->PoolId);
+ }
+
+ Dmsg1(400, "%s\n", mdb->cmd);
+
+ stat = UPDATE_DB(jcr, mdb, mdb->cmd);
+
+ db_unlock(mdb);
+ return stat;
+}
+
+
/*
* If we have a non-zero InChanger, ensure that no other Media
* record has InChanger set on the same Slot.
!cram_md5_auth(dir, password, ssl_need)) {
stop_bsock_timer(tid);
sendit( _("Director authorization problem.\n"
- "Most likely the passwords do not agree.\n"));
+ "Most likely the passwords do not agree.\n"
+ "Please see http://www.bacula.org/html-manual/faq.html#AuthorizationErrors for help.\n"));
return 0;
}
if (!cram_md5_get_auth(sd, jcr->store->password, ssl_need) ||
!cram_md5_auth(sd, jcr->store->password, ssl_need)) {
stop_bsock_timer(tid);
- Jmsg0(jcr, M_FATAL, 0, _("Director and Storage daemon passwords or names not the same.\n"));
+ Jmsg0(jcr, M_FATAL, 0, _("Director and Storage daemon passwords or names not the same.\n"
+ "Please see http://www.bacula.org/html-manual/faq.html#AuthorizationErrors for help.\n"));
return 0;
}
Dmsg1(116, ">stored: %s", sd->msg);
if (!cram_md5_get_auth(fd, jcr->client->password, ssl_need) ||
!cram_md5_auth(fd, jcr->client->password, ssl_need)) {
stop_bsock_timer(tid);
- Jmsg(jcr, M_FATAL, 0, _("Director and File daemon passwords or names not the same.\n"));
+ Jmsg(jcr, M_FATAL, 0, _("Director and File daemon passwords or names not the same.\n"
+ "Please see http://www.bacula.org/html-manual/faq.html#AuthorizationErrors for help.\n"));
return 0;
}
Dmsg1(116, ">filed: %s", fd->msg);
/* fd_cmds.c */
extern int connect_to_file_daemon(JCR *jcr, int retry_interval,
- int max_retry_time, int verbose);
+ int max_retry_time, int verbose);
extern int send_include_list(JCR *jcr);
extern int send_exclude_list(JCR *jcr);
extern int send_bootstrap_file(JCR *jcr);
extern int get_attributes_and_put_in_catalog(JCR *jcr);
extern int get_attributes_and_compare_to_catalog(JCR *jcr, JobId_t JobId);
extern int put_file_into_catalog(JCR *jcr, long file_index, char *fname,
- char *link, char *attr, int stream);
+ char *link, char *attr, int stream);
extern void get_level_since_time(JCR *jcr, char *since, int since_len);
extern int send_run_before_and_after_commands(JCR *jcr);
/* msgchan.c */
extern int connect_to_storage_daemon(JCR *jcr, int retry_interval,
- int max_retry_time, int verbose);
+ int max_retry_time, int verbose);
extern int start_storage_daemon_job(JCR *jcr);
extern int start_storage_daemon_message_thread(JCR *jcr);
extern int bget_dirmsg(BSOCK *bs);
void free_ua_context(UAContext *ua);
/* ua_select.c */
-STORE *select_storage_resource(UAContext *ua);
-JOB *select_job_resource(UAContext *ua);
-JOB *select_restore_job_resource(UAContext *ua);
-CLIENT *select_client_resource(UAContext *ua);
+STORE *select_storage_resource(UAContext *ua);
+JOB *select_job_resource(UAContext *ua);
+JOB *select_restore_job_resource(UAContext *ua);
+CLIENT *select_client_resource(UAContext *ua);
FILESET *select_fileset_resource(UAContext *ua);
-int select_pool_and_media_dbr(UAContext *ua, POOL_DBR *pr, MEDIA_DBR *mr);
-int select_media_dbr(UAContext *ua, MEDIA_DBR *mr);
-int select_pool_dbr(UAContext *ua, POOL_DBR *pr);
-int select_client_dbr(UAContext *ua, CLIENT_DBR *cr);
-
-void start_prompt(UAContext *ua, const char *msg);
-void add_prompt(UAContext *ua, const char *prompt);
-int do_prompt(UAContext *ua, const char *automsg, const char *msg, char *prompt, int max_prompt);
-CAT *get_catalog_resource(UAContext *ua);
+int select_pool_and_media_dbr(UAContext *ua, POOL_DBR *pr, MEDIA_DBR *mr);
+int select_media_dbr(UAContext *ua, MEDIA_DBR *mr);
+bool select_pool_dbr(UAContext *ua, POOL_DBR *pr);
+int select_client_dbr(UAContext *ua, CLIENT_DBR *cr);
+
+void start_prompt(UAContext *ua, const char *msg);
+void add_prompt(UAContext *ua, const char *prompt);
+int do_prompt(UAContext *ua, const char *automsg, const char *msg, char *prompt, int max_prompt);
+CAT *get_catalog_resource(UAContext *ua);
STORE *get_storage_resource(UAContext *ua, int use_default);
-int get_media_type(UAContext *ua, char *MediaType, int max_media);
-int get_pool_dbr(UAContext *ua, POOL_DBR *pr);
-int get_client_dbr(UAContext *ua, CLIENT_DBR *cr);
+int get_media_type(UAContext *ua, char *MediaType, int max_media);
+bool get_pool_dbr(UAContext *ua, POOL_DBR *pr);
+int get_client_dbr(UAContext *ua, CLIENT_DBR *cr);
POOL *get_pool_resource(UAContext *ua);
POOL *select_pool_resource(UAContext *ua);
CLIENT *get_client_resource(UAContext *ua);
-int get_job_dbr(UAContext *ua, JOB_DBR *jr);
+int get_job_dbr(UAContext *ua, JOB_DBR *jr);
int find_arg_keyword(UAContext *ua, const char **list);
int find_arg(UAContext *ua, const char *keyword);
static void update_volfrompool(UAContext *ua, MEDIA_DBR *mr)
{
POOL_DBR pr;
- char VolStatus[50];
memset(&pr, 0, sizeof(pr));
pr.PoolId = mr->PoolId;
if (!get_pool_dbr(ua, &pr)) {
return;
}
- bstrncpy(VolStatus, mr->VolStatus, sizeof(VolStatus));
set_pool_dbr_defaults_in_media_dbr(mr, &pr);
- bstrncpy(mr->VolStatus, VolStatus, sizeof(mr->VolStatus));
- if (!db_update_media_record(ua->jcr, ua->db, mr)) {
+ if (!db_update_media_defaults(ua->jcr, ua->db, mr)) {
bsendmsg(ua, _("Error updating Volume record: ERR=%s"), db_strerror(ua->db));
} else {
bsendmsg(ua, _("Volume defaults updated from Pool record.\n"));
}
}
+/*
+ * Refresh the Volume information from the Pool record
+ * for all Volumes
+ */
+static void update_all_vols_from_pool(UAContext *ua)
+{
+ POOL_DBR pr;
+ MEDIA_DBR mr;
+
+ memset(&pr, 0, sizeof(pr));
+ if (!get_pool_dbr(ua, &pr)) {
+ return;
+ }
+ memset(&mr, 0, sizeof(mr));
+ set_pool_dbr_defaults_in_media_dbr(&mr, &pr);
+ mr.PoolId = pr.PoolId;
+ if (!db_update_media_defaults(ua->jcr, ua->db, &mr)) {
+ bsendmsg(ua, _("Error updating Volume records: ERR=%s"), db_strerror(ua->db));
+ } else {
+ bsendmsg(ua, _("All Volume defaults updated from Pool record.\n"));
+ }
+}
+
+
/*
* Update a media record -- allows you to change the
* Volume status. E.g. if you want Bacula to stop
N_("Recycle"), /* 6 */
N_("Pool"), /* 7 */
N_("FromPool"), /* 8 */
+ N_("AllFromPool"), /* 9 */
NULL };
for (int i=0; kw[i]; i++) {
int j;
POOL_DBR pr;
if ((j=find_arg_with_value(ua, kw[i])) > 0) {
- if (!select_media_dbr(ua, &mr)) {
+ if (i != 9 && !select_media_dbr(ua, &mr)) {
return 0;
}
switch (i) {
case 8:
update_volfrompool(ua, &mr);
break;
+ case 9:
+ update_all_vols_from_pool(ua);
}
done = true;
}
}
memset(&mr, 0, sizeof(mr));
mr.InChanger = 1;
+ db_lock(ua->db);
for (int i=1; i<max_slots; i++) {
if (slot_list[i]) {
mr.Slot = i;
/* Set InChanger to zero for this Slot */
- db_lock(ua->db);
db_make_inchanger_unique(ua->jcr, ua->db, &mr);
- db_unlock(ua->db);
- bsendmsg(ua, _("No VolName for Slot=%d set InChanger to zero.\n"), i);
}
}
+ db_unlock(ua->db);
bail_out:
* if error or not found, put up a list of pool DBRs
* to choose from.
*
- * returns: 0 on error
- * 1 on success and fills in POOL_DBR
+ * returns: false on error
+ * true on success and fills in POOL_DBR
*/
-int get_pool_dbr(UAContext *ua, POOL_DBR *pr)
+bool get_pool_dbr(UAContext *ua, POOL_DBR *pr)
{
if (pr->Name[0]) { /* If name already supplied */
if (db_get_pool_record(ua->jcr, ua->db, pr) &&
acl_access_ok(ua, Pool_ACL, pr->Name)) {
- return pr->PoolId;
+ return true;
}
bsendmsg(ua, _("Could not find Pool \"%s\": ERR=%s"), pr->Name, db_strerror(ua->db));
}
if (!select_pool_dbr(ua, pr)) { /* try once more */
- return 0;
+ return false;
}
- return 1;
+ return true;
}
/*
* Select a Pool record from the catalog
*/
-int select_pool_dbr(UAContext *ua, POOL_DBR *pr)
+bool select_pool_dbr(UAContext *ua, POOL_DBR *pr)
{
POOL_DBR opr;
char name[MAX_NAME_LENGTH];
pr->PoolId = 0;
break;
}
- return 1;
+ return true;
}
}
}
if (num_pools <= 0) {
bsendmsg(ua, _("No pools defined. Use the \"create\" command to create one.\n"));
- return 0;
+ return false;
}
start_prompt(ua, _("Defined Pools:\n"));
}
free(ids);
if (do_prompt(ua, _("Pool"), _("Select the Pool"), name, sizeof(name)) < 0) {
- return 0;
+ return false;
}
memset(&opr, 0, sizeof(opr));
bstrncpy(opr.Name, name, sizeof(opr.Name));
if (!db_get_pool_record(ua->jcr, ua->db, &opr)) {
bsendmsg(ua, _("Could not find Pool \"%s\": ERR=%s"), name, db_strerror(ua->db));
- return 0;
+ return false;
}
memcpy(pr, &opr, sizeof(opr));
- return 1;
+ return true;
}
/*
}
UnlockRes();
if (!director) {
- Emsg2(M_FATAL, 0, _("Connection from unknown Director %s at %s rejected.\n"),
+ Emsg2(M_FATAL, 0, _("Connection from unknown Director %s at %s rejected.\n"
+ "Please see http://www.bacula.org/html-manual/faq.html#AuthorizationErrors for help.\n"),
dirname, bs->who);
free_pool_memory(dirname);
return 0;
btimer_t *tid = start_bsock_timer(bs, 60 * 5);
if (!cram_md5_auth(bs, director->password, ssl_need) ||
!cram_md5_get_auth(bs, director->password, ssl_need)) {
- Emsg1(M_FATAL, 0, _("Incorrect password given by Director at %s.\n"),
+ Emsg1(M_FATAL, 0, _("Incorrect password given by Director at %s.\n"
+ "Please see http://www.bacula.org/html-manual/faq.html#AuthorizationErrors for help.\n"),
bs->who);
director = NULL;
}
stop_bsock_timer(tid);
memset(jcr->sd_auth_key, 0, strlen(jcr->sd_auth_key));
if (!stat) {
- Jmsg(jcr, M_FATAL, 0, _("Authorization key rejected by Storage daemon.\n"));
+ Jmsg(jcr, M_FATAL, 0, _("Authorization key rejected by Storage daemon.\n"
+ "Please see http://www.bacula.org/html-manual/faq.html#AuthorizationErrors for help.\n"));
}
return stat;
}
if (bfd->fh == INVALID_HANDLE_VALUE) {
bfd->lerror = GetLastError();
bfd->berrno = b_errno_win32;
+ errno = b_errno_win32;
bfd->mode = BF_CLOSED;
}
bfd->errmsg = NULL;
1, /* Abort */
1, /* ProcessSecurity */
&bfd->lpContext)) { /* Read context */
+ errno = b_errno_win32;
stat = -1;
}
} else if (bfd->use_backup_api && bfd->mode == BF_WRITE) {
1, /* Abort */
1, /* ProcessSecurity */
&bfd->lpContext)) { /* Write context */
+ errno = b_errno_win32;
stat = -1;
}
}
if (!CloseHandle(bfd->fh)) {
stat = -1;
+ errno = b_errno_win32;
}
bfd->mode = BF_CLOSED;
bfd->lpContext = NULL;
/*
* Generate error message
*/
-char *berror(BFILE *bfd)
+/* DO NOT USE */
+char *xberror(BFILE *bfd)
{
LPTSTR msg;
&bfd->lpContext)) { /* Context */
bfd->lerror = GetLastError();
bfd->berrno = b_errno_win32;
+ errno = b_errno_win32;
return -1;
}
} else {
NULL)) {
bfd->lerror = GetLastError();
bfd->berrno = b_errno_win32;
+ errno = b_errno_win32;
return -1;
}
}
&bfd->lpContext)) { /* Context */
bfd->lerror = GetLastError();
bfd->berrno = b_errno_win32;
+ errno = b_errno_win32;
return -1;
}
} else {
NULL)) {
bfd->lerror = GetLastError();
bfd->berrno = b_errno_win32;
+ errno = b_errno_win32;
return -1;
}
}
off_t blseek(BFILE *bfd, off_t offset, int whence)
{
- /* ****FIXME**** this is needed if we want to read Win32 Archives */
+ /* ****FIXME**** this must be implemented if we want to read Win32 Archives */
return -1;
}
bfd->fid = open(fname, flags, mode);
bfd->berrno = errno;
Dmsg1(400, "Open file %d\n", bfd->fid);
+ errno = bfd->berrno;
return bfd->fid;
}
return pos;
}
-char *berror(BFILE *bfd)
+/* DO NOT USE */
+char *xberror(BFILE *bfd)
{
return strerror(bfd->berrno);
}
enum {
BF_CLOSED,
- BF_READ, /* BackupRead */
- BF_WRITE /* BackupWrite */
+ BF_READ, /* BackupRead */
+ BF_WRITE /* BackupWrite */
};
/* In bfile.c */
/* Basic low level I/O file packet */
struct BFILE {
- int use_backup_api; /* set if using BackupRead/Write */
- int mode; /* set if file is open */
- HANDLE fh; /* Win32 file handle */
- int fid; /* fd if doing Unix style */
- LPVOID lpContext; /* BackupRead/Write context */
- POOLMEM *errmsg; /* error message buffer */
- DWORD rw_bytes; /* Bytes read or written */
- DWORD lerror; /* Last error code */
- int berrno; /* errno */
-};
+ int use_backup_api; /* set if using BackupRead/Write */
+ int mode; /* set if file is open */
+ HANDLE fh; /* Win32 file handle */
+ int fid; /* fd if doing Unix style */
+ LPVOID lpContext; /* BackupRead/Write context */
+ POOLMEM *errmsg; /* error message buffer */
+ DWORD rw_bytes; /* Bytes read or written */
+ DWORD lerror; /* Last error code */
+ int berrno; /* errno */
+};
HANDLE bget_handle(BFILE *bfd);
-#else /* Linux/Unix systems */
+#else /* Linux/Unix systems */
/* =======================================================
*
/* Basic low level I/O file packet */
struct BFILE {
- int fid; /* file id on Unix */
+ int fid; /* file id on Unix */
int berrno;
-};
+};
#endif
-void binit(BFILE *bfd);
-int is_bopen(BFILE *bfd);
-int set_win32_backup(BFILE *bfd);
-int set_portable_backup(BFILE *bfd);
-int have_win32_api();
-int is_portable_backup(BFILE *bfd);
-int is_stream_supported(int stream);
-int is_win32_stream(int stream);
-char *berror(BFILE *bfd);
-int bopen(BFILE *bfd, const char *fname, int flags, mode_t mode);
-int bclose(BFILE *bfd);
+void binit(BFILE *bfd);
+int is_bopen(BFILE *bfd);
+int set_win32_backup(BFILE *bfd);
+int set_portable_backup(BFILE *bfd);
+int have_win32_api();
+int is_portable_backup(BFILE *bfd);
+int is_stream_supported(int stream);
+int is_win32_stream(int stream);
+char *xberror(BFILE *bfd); /* DO NOT USE -- use berrno class */
+int bopen(BFILE *bfd, const char *fname, int flags, mode_t mode);
+int bclose(BFILE *bfd);
ssize_t bread(BFILE *bfd, void *buf, size_t count);
ssize_t bwrite(BFILE *bfd, void *buf, size_t count);
-off_t blseek(BFILE *bfd, off_t offset, int whence);
+off_t blseek(BFILE *bfd, off_t offset, int whence);
const char *stream_to_ascii(int stream);
#endif /* __BFILE_H */
case FT_NOFOLLOW:
case FT_NOSTAT:
case FT_NOCHG:
- case FT_DIRNOCHG:
case FT_ISARCH:
case FT_NORECURSE:
case FT_NOFSCHG:
case FT_RAW:
case FT_FIFO:
case FT_SPEC:
+ case FT_DIRNOCHG:
if (accept_file(ff)) {
return ff->callback(ff, hpkt);
} else {
stop_bsock_timer(tid);
printf(_("%s: Director authorization problem.\n"), my_name);
set_text(_("Director authorization problem.\n"), -1);
+ set_text(_(
+ "Please see http://www.bacula.org/html-manual/faq.html#AuthorizationErrors for help.\n"),
+ -1);
return 0;
}
dev_name(dev), NPRT(jcr->VolumeName));
Jmsg2(jcr, M_ERROR, 0, _("num_writers=%d state=%x\n"), dev->num_writers, dev->state);
}
-// detach_jcr_from_device(dev, jcr);
+
+ /* Fire off Alert command and include any output */
+ if (jcr->device->alert_command) {
+ POOLMEM *alert;
+ int status;
+ BPIPE *bpipe;
+ char line[MAXSTRING];
+ alert = get_pool_memory(PM_FNAME);
+ alert = edit_device_codes(jcr, alert, jcr->device->alert_command, "");
+ bpipe = open_bpipe(alert, 0, "r");
+ free_pool_memory(alert);
+ while (fgets(line, sizeof(line), bpipe->rfd)) {
+ Jmsg(jcr, M_INFO, 0, _("Alert: %s"), line);
+ }
+ status = close_bpipe(bpipe);
+ if (status != 0) {
+ berrno be;
+ be.set_errno(status);
+ Jmsg(jcr, M_INFO, 0, _("3997 Bad alert command: %s: ERR=%s.\n"),
+ alert, be.strerror());
+ }
+
+ Dmsg1(400, "alert status=%d\n", status);
+
+ }
if (dev->prev && !dev_state(dev, ST_READ) && !dev->num_writers) {
P(mutex);
unlock_device(dev);
}
UnlockRes();
if (!director) {
- Emsg2(M_FATAL, 0, _("Connection from unknown Director %s at %s rejected.\n"),
+ Emsg2(M_FATAL, 0, _("Connection from unknown Director %s at %s rejected.\n"
+ "Please see http://www.bacula.org/html-manual/faq.html#AuthorizationErrors for help.\n"),
dirname, bs->who);
free_pool_memory(dirname);
return 0;
if (!cram_md5_auth(bs, director->password, ssl_need) ||
!cram_md5_get_auth(bs, director->password, ssl_need)) {
stop_bsock_timer(tid);
- Emsg0(M_FATAL, 0, _("Incorrect password given by Director.\n"));
+ Emsg0(M_FATAL, 0, _("Incorrect password given by Director.\n"
+ "Please see http://www.bacula.org/html-manual/faq.html#AuthorizationErrors for help.\n"));
free_pool_memory(dirname);
return 0;
}
}
stop_bsock_timer(tid);
if (!jcr->authenticated) {
- Jmsg(jcr, M_FATAL, 0, _("Incorrect authorization key from File daemon at %s rejected.\n"),
+ Jmsg(jcr, M_FATAL, 0, _("Incorrect authorization key from File daemon at %s rejected.\n"
+ "Please see http://www.bacula.org/html-manual/faq.html#AuthorizationErrors for help.\n"),
fd->who);
}
return jcr->authenticated;
case 'e': /* exclude list */
if ((fd = fopen(optarg, "r")) == NULL) {
+ berrno be;
Pmsg2(0, "Could not open exclude file: %s, ERR=%s\n",
- optarg, strerror(errno));
+ optarg, be.strerror());
exit(1);
}
while (fgets(line, sizeof(line), fd) != NULL) {
case 'i': /* include list */
if ((fd = fopen(optarg, "r")) == NULL) {
+ berrno be;
Pmsg2(0, "Could not open include file: %s, ERR=%s\n",
- optarg, strerror(errno));
+ optarg, be.strerror());
exit(1);
}
while (fgets(line, sizeof(line), fd) != NULL) {
/* Make sure where directory exists and that it is a directory */
if (stat(where, &statp) < 0) {
+ berrno be;
Emsg2(M_ERROR_TERM, 0, "Cannot stat %s. It must exist. ERR=%s\n",
- where, strerror(errno));
+ where, be.strerror());
}
if (!S_ISDIR(statp.st_mode)) {
Emsg1(M_ERROR_TERM, 0, "%s must be a directory.\n", where);
if (fileAddr != faddr) {
fileAddr = faddr;
if (blseek(&bfd, (off_t)fileAddr, SEEK_SET) < 0) {
+ berrno be;
Emsg2(M_ERROR_TERM, 0, _("Seek error on %s: %s\n"),
- attr->ofname, strerror(errno));
+ attr->ofname, be.strerror());
}
}
} else {
total += wsize;
Dmsg2(8, "Write %u bytes, total=%u\n", wsize, total);
if ((uint32_t)bwrite(&bfd, wbuf, wsize) != wsize) {
+ berrno be;
Emsg2(M_ERROR_TERM, 0, _("Write error on %s: %s\n"),
- attr->ofname, strerror(errno));
+ attr->ofname, be.strerror());
}
fileAddr += wsize;
}
if (fileAddr != faddr) {
fileAddr = faddr;
if (blseek(&bfd, (off_t)fileAddr, SEEK_SET) < 0) {
+ berrno be;
Emsg3(M_ERROR, 0, _("Seek to %s error on %s: ERR=%s\n"),
- edit_uint64(fileAddr, ec1), attr->ofname, berror(&bfd));
+ edit_uint64(fileAddr, ec1), attr->ofname, be.strerror());
extract = false;
return true;
}
Dmsg2(100, "Write uncompressed %d bytes, total before write=%d\n", compress_len, total);
if ((uLongf)bwrite(&bfd, compress_buf, (size_t)compress_len) != compress_len) {
+ berrno be;
Pmsg0(0, "===Write error===\n");
Emsg2(M_ERROR, 0, _("Write error on %s: %s\n"),
- attr->ofname, strerror(errno));
+ attr->ofname, be.strerror());
extract = false;
return true;
}
/* External subroutines */
extern void free_config_resources();
-extern char *edit_device_codes(JCR *jcr, char *omsg, const char *imsg, const char *cmd);
/* Exported variables */
int quit = 0;
static DEVICE *find_device(JCR *jcr, char *dname)
{
- DEVRES *device = NULL;
+ DEVRES *device;
bool found = false;
unbash_spaces(dname);
LockRes();
- while ((device=(DEVRES *)GetNextRes(R_DEVICE, (RES *)device))) {
+ foreach_res(device, R_DEVICE) {
/* Find resource, and make sure we were able to open it */
if (strcmp(device->hdr.name, dname) == 0 && device->dev) {
Dmsg1(20, "Found device %s\n", device->hdr.name);
int autoload_device(DCR *dcr, int writing, BSOCK *dir);
bool autochanger_list(DCR *dcr, BSOCK *dir);
void invalidate_slot_in_catalog(DCR *dcr);
+char *edit_device_codes(JCR *jcr, char *omsg, const char *imsg, const char *cmd);
/* From parse_bsr.c */
{"closeonpoll", store_yesno, ITEM(res_dev.cap_bits), CAP_CLOSEONPOLL, ITEM_DEFAULT, 0},
{"changerdevice", store_strname,ITEM(res_dev.changer_name), 0, 0, 0},
{"changercommand", store_strname,ITEM(res_dev.changer_command), 0, 0, 0},
+ {"alertcommand", store_strname,ITEM(res_dev.alert_command), 0, 0, 0},
{"maximumchangerwait", store_pint, ITEM(res_dev.max_changer_wait), 0, ITEM_DEFAULT, 5 * 60},
{"maximumopenwait", store_pint, ITEM(res_dev.max_open_wait), 0, ITEM_DEFAULT, 5 * 60},
{"maximumopenvolumes", store_pint, ITEM(res_dev.max_open_vols), 0, ITEM_DEFAULT, 1},
if (res->res_dev.changer_command) {
free(res->res_dev.changer_command);
}
+ if (res->res_dev.alert_command) {
+ free(res->res_dev.alert_command);
+ }
if (res->res_dev.spool_directory) {
free(res->res_dev.spool_directory);
}
char *device_name; /* Archive device name */
char *changer_name; /* Changer device name */
char *changer_command; /* Changer command -- external program */
+ char *alert_command; /* Alert command -- external program */
char *spool_directory; /* Spool file directory */
uint32_t drive_index; /* Autochanger drive index */
uint32_t cap_bits; /* Capabilities of this device */
static NAME_LIST name_list;
static char buf[2000];
-#define MAX_ID_LIST_LEN 1000000
+#define MAX_ID_LIST_LEN 10000000
/* Forward referenced functions */
static int make_id_list(const char *query, ID_LIST *id_list);
static void eliminate_orphaned_path_records();
static void eliminate_orphaned_filename_records();
static void eliminate_orphaned_fileset_records();
+static void eliminate_orphaned_client_records();
static void repair_bad_paths();
static void repair_bad_filenames();
static void do_interactive_mode();
eliminate_orphaned_path_records();
eliminate_orphaned_filename_records();
eliminate_orphaned_fileset_records();
+ eliminate_orphaned_client_records();
} else {
do_interactive_mode();
}
9) Eliminate orphaned Path records\n\
10) Eliminate orphaned Filename records\n\
11) Eliminate orphaned FileSet records\n\
- 12) All (3-11)\n\
- 13) Quit\n"));
+ 12) Eliminate orphaned Client records\n\
+ 13) All (3-12)\n\
+ 14) Quit\n"));
} else {
printf(_("\n\
1) Toggle modify database flag\n\
9) Check for orphaned Path records\n\
10) Check for orphaned Filename records\n\
11) Check for orphaned FileSet records\n\
- 12) All (3-11)\n\
- 13) Quit\n"));
+ 12) Check for orphaned FileSet records\n\
+ 13) All (3-12)\n\
+ 14) Quit\n"));
}
cmd = get_cmd(_("Select function number: "));
eliminate_orphaned_fileset_records();
break;
case 12:
+ eliminate_orphaned_client_records();
+ break;
+ case 13:
repair_bad_filenames();
repair_bad_paths();
eliminate_duplicate_filenames();
eliminate_orphaned_path_records();
eliminate_orphaned_filename_records();
eliminate_orphaned_fileset_records();
+ eliminate_orphaned_client_records();
break;
- case 13:
+ case 14:
quit = true;
break;
}
return 0;
}
+static int print_client_handler(void *ctx, int num_fields, char **row)
+{
+ printf(_("Orphaned ClientId=%s Name=\"%s\"\n"),
+ NPRT(row[0]), NPRT(row[1]));
+ return 0;
+}
+
+
/*
* Called here with each id to be added to the list
}
}
+static void eliminate_orphaned_client_records()
+{
+ const char *query;
+
+ printf("Checking for orphaned Client entries.\n");
+ /* In English:
+ * Wiffle through Client for every Client
+ * joining with the Job table including every Client even if
+ * there is not a match in Job (left outer join), then
+ * filter out only those where no Job points to a Client
+ * i.e. Job.Client is NULL
+ */
+ query = "SELECT Client.ClientId,Client.Name FROM Client "
+ "LEFT OUTER JOIN Job ON (Client.ClientId=Job.ClientId) "
+ "WHERE Job.ClientId IS NULL";
+ if (verbose > 1) {
+ printf("%s\n", query);
+ }
+ if (!make_id_list(query, &id_list)) {
+ exit(1);
+ }
+ printf("Found %d orphaned Client records.\n", id_list.num_ids);
+ if (id_list.num_ids && verbose && yes_no("Print them? (yes/no): ")) {
+ for (int i=0; i < id_list.num_ids; i++) {
+ sprintf(buf, "SELECT ClientId,Name FROM Client "
+ "WHERE ClientId=%u", id_list.Id[i]);
+ if (!db_sql_query(db, buf, print_client_handler, NULL)) {
+ printf("%s\n", db_strerror(db));
+ }
+ }
+ }
+
+ if (fix && id_list.num_ids > 0) {
+ printf("Deleting %d orphaned Client records.\n", id_list.num_ids);
+ delete_id_list("DELETE FROM Client WHERE ClientId=%u", &id_list);
+ }
+}
+
+
static void repair_bad_filenames()
{
const char *query;
/* */
#undef VERSION
#define VERSION "1.35.1"
-#define BDATE "30 July 2004"
-#define LSMDATE "30Jul04"
+#define BDATE "05 August 2004"
+#define LSMDATE "05Aug04"
/* Debug flags */
#undef DEBUG
!cram_md5_auth(dir, password, ssl_need)) {
stop_bsock_timer(tid);
csprint("Director authorization problem.\nMost likely the passwords do not agree.\n", CS_DATA);
+ csprint(
+ "Please see http://www.bacula.org/html-manual/faq.html#AuthorizationErrors for help.\n", CS_DATA);
return 0;
}