From: Kern Sibbald Date: Thu, 5 Aug 2004 11:51:54 +0000 (+0000) Subject: Fix new FileSet exclusion X-Git-Tag: Release-1.35.1~29 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=7c3f089bd92ffae85e068f3b7e9d16c701d98133;p=bacula%2Fbacula Fix new FileSet exclusion Implement update all Volumes from pool File update volume from pool Implement Alert command in SD Add eliminate orphaned Client records to dbcheck git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@1508 91ce42f0-d328-0410-95d8-f526ca767f89 --- diff --git a/bacula/kernstodo b/bacula/kernstodo index fedae668e3..ade42c86c4 100644 --- a/bacula/kernstodo +++ b/bacula/kernstodo @@ -1,5 +1,5 @@ Kern's ToDo List - 03 August 2004 + 05 August 2004 Major development: Project Developer @@ -12,35 +12,31 @@ Version 1.35 Kern (see below) 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" @@ -64,18 +60,20 @@ Documentation to do: (any release a little bit at a time) - 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?). @@ -1165,3 +1163,7 @@ Block Position: 0 - 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 + diff --git a/bacula/src/cats/bdb_update.c b/bacula/src/cats/bdb_update.c index 4d60965d64..d3e594558d 100755 --- a/bacula/src/cats/bdb_update.c +++ b/bacula/src/cats/bdb_update.c @@ -217,5 +217,10 @@ int db_update_counter_record(JCR *jcr, B_DB *mdb, COUNTER_DBR *cr) return 0; } +int db_update_media_defaults(JCR *jcr, B_DB *mdb, MEDIA_DBR *mr) +{ + return 1; +} + #endif /* HAVE_BACULA_DB */ diff --git a/bacula/src/cats/protos.h b/bacula/src/cats/protos.h index ef5d6ade11..c5c41879eb 100644 --- a/bacula/src/cats/protos.h +++ b/bacula/src/cats/protos.h @@ -34,7 +34,7 @@ /* 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); @@ -51,7 +51,7 @@ int db_create_job_record(JCR *jcr, B_DB *db, JOB_DBR *jr); 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); @@ -102,6 +102,7 @@ int db_update_job_end_record(JCR *jcr, B_DB *db, JOB_DBR *jr); 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); diff --git a/bacula/src/cats/sql_update.c b/bacula/src/cats/sql_update.c index c0af9184cc..fed8d82c20 100644 --- a/bacula/src/cats/sql_update.c +++ b/bacula/src/cats/sql_update.c @@ -333,6 +333,51 @@ db_update_media_record(JCR *jcr, B_DB *mdb, MEDIA_DBR *mr) 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. diff --git a/bacula/src/console/authenticate.c b/bacula/src/console/authenticate.c index 23fb727b67..fe242c256b 100644 --- a/bacula/src/console/authenticate.c +++ b/bacula/src/console/authenticate.c @@ -74,7 +74,8 @@ int authenticate_director(JCR *jcr, DIRRES *director, CONRES *cons) !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; } diff --git a/bacula/src/dird/authenticate.c b/bacula/src/dird/authenticate.c index c2522be1fa..00c793f3d3 100644 --- a/bacula/src/dird/authenticate.c +++ b/bacula/src/dird/authenticate.c @@ -73,7 +73,8 @@ int authenticate_storage_daemon(JCR *jcr) 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); @@ -116,7 +117,8 @@ int authenticate_file_daemon(JCR *jcr) 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); diff --git a/bacula/src/dird/protos.h b/bacula/src/dird/protos.h index ac61ca9935..45101b08e3 100644 --- a/bacula/src/dird/protos.h +++ b/bacula/src/dird/protos.h @@ -62,7 +62,7 @@ int variable_expansion(JCR *jcr, char *inp, POOLMEM **exp); /* 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); @@ -70,7 +70,7 @@ extern int send_level_command(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); @@ -96,7 +96,7 @@ extern void mount_request(JCR *jcr, BSOCK *bs, char *buf); /* 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); @@ -148,28 +148,28 @@ JCR *new_control_jcr(const char *base_name, int job_type); 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); diff --git a/bacula/src/dird/ua_cmds.c b/bacula/src/dird/ua_cmds.c index 8aa7ecccc1..173ba60490 100644 --- a/bacula/src/dird/ua_cmds.c +++ b/bacula/src/dird/ua_cmds.c @@ -847,23 +847,44 @@ static void update_vol_pool(UAContext *ua, char *val, MEDIA_DBR *mr, POOL_DBR *o 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 @@ -887,13 +908,14 @@ static int update_volume(UAContext *ua) 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) { @@ -930,6 +952,8 @@ static int update_volume(UAContext *ua) case 8: update_volfrompool(ua, &mr); break; + case 9: + update_all_vols_from_pool(ua); } done = true; } diff --git a/bacula/src/dird/ua_label.c b/bacula/src/dird/ua_label.c index 2b3c95cdd5..16d2e28cbc 100644 --- a/bacula/src/dird/ua_label.c +++ b/bacula/src/dird/ua_label.c @@ -248,16 +248,15 @@ int update_slots(UAContext *ua) } memset(&mr, 0, sizeof(mr)); mr.InChanger = 1; + db_lock(ua->db); for (int i=1; idb); 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: diff --git a/bacula/src/dird/ua_select.c b/bacula/src/dird/ua_select.c index f0d3b2588c..2330de5784 100644 --- a/bacula/src/dird/ua_select.c +++ b/bacula/src/dird/ua_select.c @@ -405,28 +405,28 @@ int select_client_dbr(UAContext *ua, CLIENT_DBR *cr) * 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]; @@ -443,7 +443,7 @@ int select_pool_dbr(UAContext *ua, POOL_DBR *pr) pr->PoolId = 0; break; } - return 1; + return true; } } @@ -454,7 +454,7 @@ int select_pool_dbr(UAContext *ua, POOL_DBR *pr) } 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")); @@ -468,17 +468,17 @@ int select_pool_dbr(UAContext *ua, POOL_DBR *pr) } 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; } /* diff --git a/bacula/src/filed/authenticate.c b/bacula/src/filed/authenticate.c index e01870b121..ec3acb05e8 100644 --- a/bacula/src/filed/authenticate.c +++ b/bacula/src/filed/authenticate.c @@ -69,7 +69,8 @@ static int authenticate(int rcode, BSOCK *bs) } 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; @@ -77,7 +78,8 @@ static int authenticate(int rcode, BSOCK *bs) 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; } @@ -123,7 +125,8 @@ int authenticate_storagedaemon(JCR *jcr) 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; } diff --git a/bacula/src/findlib/bfile.c b/bacula/src/findlib/bfile.c index f2ff68dbaa..0197bd3c40 100644 --- a/bacula/src/findlib/bfile.c +++ b/bacula/src/findlib/bfile.c @@ -255,6 +255,7 @@ int bopen(BFILE *bfd, const char *fname, int flags, mode_t mode) 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; @@ -287,6 +288,7 @@ int bclose(BFILE *bfd) 1, /* Abort */ 1, /* ProcessSecurity */ &bfd->lpContext)) { /* Read context */ + errno = b_errno_win32; stat = -1; } } else if (bfd->use_backup_api && bfd->mode == BF_WRITE) { @@ -298,11 +300,13 @@ int bclose(BFILE *bfd) 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; @@ -312,7 +316,8 @@ int bclose(BFILE *bfd) /* * Generate error message */ -char *berror(BFILE *bfd) +/* DO NOT USE */ +char *xberror(BFILE *bfd) { LPTSTR msg; @@ -351,6 +356,7 @@ ssize_t bread(BFILE *bfd, void *buf, size_t count) &bfd->lpContext)) { /* Context */ bfd->lerror = GetLastError(); bfd->berrno = b_errno_win32; + errno = b_errno_win32; return -1; } } else { @@ -361,6 +367,7 @@ ssize_t bread(BFILE *bfd, void *buf, size_t count) NULL)) { bfd->lerror = GetLastError(); bfd->berrno = b_errno_win32; + errno = b_errno_win32; return -1; } } @@ -382,6 +389,7 @@ ssize_t bwrite(BFILE *bfd, void *buf, size_t count) &bfd->lpContext)) { /* Context */ bfd->lerror = GetLastError(); bfd->berrno = b_errno_win32; + errno = b_errno_win32; return -1; } } else { @@ -392,6 +400,7 @@ ssize_t bwrite(BFILE *bfd, void *buf, size_t count) NULL)) { bfd->lerror = GetLastError(); bfd->berrno = b_errno_win32; + errno = b_errno_win32; return -1; } } @@ -405,7 +414,7 @@ int is_bopen(BFILE *bfd) 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; } @@ -490,6 +499,7 @@ int bopen(BFILE *bfd, const char *fname, int flags, mode_t mode) bfd->fid = open(fname, flags, mode); bfd->berrno = errno; Dmsg1(400, "Open file %d\n", bfd->fid); + errno = bfd->berrno; return bfd->fid; } @@ -536,7 +546,8 @@ off_t blseek(BFILE *bfd, off_t offset, int whence) return pos; } -char *berror(BFILE *bfd) +/* DO NOT USE */ +char *xberror(BFILE *bfd) { return strerror(bfd->berrno); } diff --git a/bacula/src/findlib/bfile.h b/bacula/src/findlib/bfile.h index 2282010e81..d65e5867b5 100644 --- a/bacula/src/findlib/bfile.h +++ b/bacula/src/findlib/bfile.h @@ -41,28 +41,28 @@ 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 */ /* ======================================================= * @@ -73,26 +73,26 @@ HANDLE bget_handle(BFILE *bfd); /* 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 */ diff --git a/bacula/src/findlib/find.c b/bacula/src/findlib/find.c index 0550e73786..5efc669655 100644 --- a/bacula/src/findlib/find.c +++ b/bacula/src/findlib/find.c @@ -218,7 +218,6 @@ static int our_callback(FF_PKT *ff, void *hpkt) case FT_NOFOLLOW: case FT_NOSTAT: case FT_NOCHG: - case FT_DIRNOCHG: case FT_ISARCH: case FT_NORECURSE: case FT_NOFSCHG: @@ -235,6 +234,7 @@ static int our_callback(FF_PKT *ff, void *hpkt) case FT_RAW: case FT_FIFO: case FT_SPEC: + case FT_DIRNOCHG: if (accept_file(ff)) { return ff->callback(ff, hpkt); } else { diff --git a/bacula/src/gnome2-console/authenticate.c b/bacula/src/gnome2-console/authenticate.c index f1c6febd74..8cebb7aca4 100644 --- a/bacula/src/gnome2-console/authenticate.c +++ b/bacula/src/gnome2-console/authenticate.c @@ -72,6 +72,9 @@ int authenticate_director(JCR *jcr, DIRRES *director, CONRES *cons) 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; } diff --git a/bacula/src/stored/acquire.c b/bacula/src/stored/acquire.c index 0a492a61f5..29b91e849e 100644 --- a/bacula/src/stored/acquire.c +++ b/bacula/src/stored/acquire.c @@ -412,7 +412,31 @@ bool release_device(JCR *jcr) 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); diff --git a/bacula/src/stored/authenticate.c b/bacula/src/stored/authenticate.c index 24c1383125..2cd2110c5b 100644 --- a/bacula/src/stored/authenticate.c +++ b/bacula/src/stored/authenticate.c @@ -70,7 +70,8 @@ static int authenticate(int rcode, BSOCK *bs) } 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; @@ -81,7 +82,8 @@ static int authenticate(int rcode, BSOCK *bs) 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; } @@ -128,7 +130,8 @@ int authenticate_filed(JCR *jcr) } 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; diff --git a/bacula/src/stored/bextract.c b/bacula/src/stored/bextract.c index daf491715c..72439b49a3 100644 --- a/bacula/src/stored/bextract.c +++ b/bacula/src/stored/bextract.c @@ -122,8 +122,9 @@ int main (int argc, char *argv[]) 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) { @@ -136,8 +137,9 @@ int main (int argc, char *argv[]) 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) { @@ -210,8 +212,9 @@ static void do_extract(char *devname) /* 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); @@ -329,8 +332,9 @@ static bool record_cb(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec) 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 { @@ -340,8 +344,9 @@ static bool record_cb(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec) 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; } @@ -367,8 +372,9 @@ static bool record_cb(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec) 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; } @@ -387,9 +393,10 @@ static bool record_cb(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec) 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; } diff --git a/bacula/src/stored/btape.c b/bacula/src/stored/btape.c index e9a1dc548b..d588a400af 100644 --- a/bacula/src/stored/btape.c +++ b/bacula/src/stored/btape.c @@ -39,7 +39,6 @@ /* 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; diff --git a/bacula/src/stored/dircmd.c b/bacula/src/stored/dircmd.c index a68fa8cb7a..045add3b5a 100644 --- a/bacula/src/stored/dircmd.c +++ b/bacula/src/stored/dircmd.c @@ -463,12 +463,12 @@ static int read_label(JCR *jcr, DEVICE *dev) 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); diff --git a/bacula/src/stored/protos.h b/bacula/src/stored/protos.h index 83471c1b83..f003e87493 100644 --- a/bacula/src/stored/protos.h +++ b/bacula/src/stored/protos.h @@ -176,6 +176,7 @@ void mark_volume_in_error(JCR *jcr, DEVICE *dev); 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 */ diff --git a/bacula/src/stored/stored_conf.c b/bacula/src/stored/stored_conf.c index 9f2a4911ef..0e557ebcc3 100644 --- a/bacula/src/stored/stored_conf.c +++ b/bacula/src/stored/stored_conf.c @@ -103,6 +103,7 @@ static RES_ITEM dev_items[] = { {"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}, @@ -311,6 +312,9 @@ void free_resource(RES *sres, int type) 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); } diff --git a/bacula/src/stored/stored_conf.h b/bacula/src/stored/stored_conf.h index 17c7e6630f..d2bef94658 100644 --- a/bacula/src/stored/stored_conf.h +++ b/bacula/src/stored/stored_conf.h @@ -75,6 +75,7 @@ struct DEVRES { 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 */ diff --git a/bacula/src/tools/dbcheck.c b/bacula/src/tools/dbcheck.c index 54114787fe..a692853dd9 100644 --- a/bacula/src/tools/dbcheck.c +++ b/bacula/src/tools/dbcheck.c @@ -58,7 +58,7 @@ static ID_LIST id_list; 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); @@ -74,6 +74,7 @@ static void eliminate_orphaned_file_records(); 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(); @@ -240,6 +241,7 @@ int main (int argc, char *argv[]) eliminate_orphaned_path_records(); eliminate_orphaned_filename_records(); eliminate_orphaned_fileset_records(); + eliminate_orphaned_client_records(); } else { do_interactive_mode(); } @@ -274,8 +276,9 @@ Please select the fuction you want to perform.\n", 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\ @@ -289,8 +292,9 @@ Please select the fuction you want to perform.\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: ")); @@ -333,6 +337,9 @@ Please select the fuction you want to perform.\n", eliminate_orphaned_fileset_records(); break; case 12: + eliminate_orphaned_client_records(); + break; + case 13: repair_bad_filenames(); repair_bad_paths(); eliminate_duplicate_filenames(); @@ -342,8 +349,9 @@ Please select the fuction you want to perform.\n", eliminate_orphaned_path_records(); eliminate_orphaned_filename_records(); eliminate_orphaned_fileset_records(); + eliminate_orphaned_client_records(); break; - case 13: + case 14: quit = true; break; } @@ -390,6 +398,14 @@ static int print_fileset_handler(void *ctx, int num_fields, char **row) 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 @@ -762,6 +778,45 @@ static void eliminate_orphaned_fileset_records() } } +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; diff --git a/bacula/src/version.h b/bacula/src/version.h index 67c7cfb2b5..d0fd264694 100644 --- a/bacula/src/version.h +++ b/bacula/src/version.h @@ -1,8 +1,8 @@ /* */ #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 diff --git a/bacula/src/wx-console/authenticate.c b/bacula/src/wx-console/authenticate.c index 94dc6a9031..1be70e7c75 100644 --- a/bacula/src/wx-console/authenticate.c +++ b/bacula/src/wx-console/authenticate.c @@ -74,6 +74,8 @@ int authenticate_director(JCR *jcr, DIRRES *director, CONRES *cons) !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; }