From: Kern Sibbald Date: Sun, 3 Jul 2005 13:54:30 +0000 (+0000) Subject: - Tweak dvd-writepart script to prevent door from opening/closing X-Git-Tag: Release-7.0.0~8660 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=24b9e858ee8080fee1e5cc3926c433d2059cf0ca;p=bacula%2Fbacula - Tweak dvd-writepart script to prevent door from opening/closing so much. - Remove GROUP BY in several PostgreSQL commands to prevent error. Resolves bug report. - Ensure that < as first character of filename list is not treated as a directory for restore. - Add debug to heartbeat in FD as it seems to go into an infinite loop from time to time during SD failure in DVD writing. - Add more debug code to dvd writing. - Attempt not to destroy existing fs on DVD. git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@2171 91ce42f0-d328-0410-95d8-f526ca767f89 --- diff --git a/bacula/kernstodo b/bacula/kernstodo index 2571adee1d..6387dc40ac 100644 --- a/bacula/kernstodo +++ b/bacula/kernstodo @@ -22,6 +22,30 @@ Autochangers: - Make "update slots" when pointing to Autochanger, remove all Volumes from other drives. "update slots all-drives"? +For 1.37: +- Finish TLS implementation. +- Fix PostgreSQL GROUP BY problems in restore. +- Fix PostgreSQL sql problems in bugs. +- Refuse to prune last valid Full backup. Same goes for Catalog. +- --without-openssl breaks at least on Solaris. +- Python: + - Make a callback when Rerun failed levels is called. + - Give Python program access to Scheduled jobs. + - Add setting Volume State via Python. + - Python script to save with Python, not save, save with Bacula. + - Python script to do backup. + - What events? + - Change the Priority, Client, Storage, JobStatus (error) + at the start of a job. +- Why is SpoolDirectory = /home/bacula/spool; not reported + as an error when writing a DVD? +- Make bootstrap file handle multiple MediaTypes (SD) +- Remove all old Device resource code in Dir and code to pass it + back in SD -- better, rework it to pass back device statistics. +- Check locking of resources -- be sure to lock devices where previously + resources were locked. +- The last part is left in the spool dir. + Document: - Port limiting -m in iptables to prevent DoS attacks could cause broken pipes on Bacula. @@ -50,31 +74,6 @@ Document: - Document Heartbeat Interval in the dealing with firewalls section. - Document the multiple-drive-changer.txt script. -For 1.37: -- Cleaning tapes should have Status "Cleaning" rather than append. -- Refuse to prune last valid Full backup. Same goes for Catalog. -- Why is SpoolDirectory = /home/bacula/spool; not reported - as an error when writing a DVD? -- Add setting Volume State via Python. -- Make bootstrap file handle multiple MediaTypes (SD) -- --without-openssl breaks at least on Solaris. -- Python: - - Make a callback when Rerun failed levels is called. - - Give Python program access to Scheduled jobs. - - Python script to save with Python, not save, save with Bacula. - - Python script to do backup. - - What events? - - Change the Priority, Client, Storage, JobStatus (error) - at the start of a job. - - Make sure that Python has access to Client address/port so that - it can check if Clients are alive. - -- Remove all old Device resource code in Dir and code to pass it - back in SD -- better, rework it to pass back device statistics. -- Check locking of resources -- be sure to lock devices where previously - resources were locked. -- Add global lock on all devices when creating a device structure. - Maybe in 1.37: - In restore don't compare byte count on a raw device -- directory entry does not contain bytes. @@ -1294,3 +1293,8 @@ Block Position: 0 - Implement "PreferMountedVolumes = yes|no" in Job resource. ## Integrate web-bacula into a new Bacula project with bimagemgr. +- Cleaning tapes should have Status "Cleaning" rather than append. +- Make sure that Python has access to Client address/port so that + it can check if Clients are alive. +- Review all items in "restore". + diff --git a/bacula/kes-1.37 b/bacula/kes-1.37 index 9bdca22393..dc904e44f8 100644 --- a/bacula/kes-1.37 +++ b/bacula/kes-1.37 @@ -4,6 +4,17 @@ General: Changes to 1.37.28: +02Jul05 +- Tweak dvd-writepart script to prevent door from opening/closing + so much. +- Remove GROUP BY in several PostgreSQL commands to prevent error. + Resolves bug report. +- Ensure that < as first character of filename list is not treated + as a directory for restore. +- Add debug to heartbeat in FD as it seems to go into an + infinite loop from time to time during SD failure in DVD writing. +- Add more debug code to dvd writing. +- Attempt not to destroy existing fs on DVD. 30Jun05 - Detect device mounted for DVD and suppress be sure to mount message after label. diff --git a/bacula/scripts/dvd-writepart.in b/bacula/scripts/dvd-writepart.in index 5de917c8e4..515daa8583 100644 --- a/bacula/scripts/dvd-writepart.in +++ b/bacula/scripts/dvd-writepart.in @@ -9,8 +9,8 @@ # Write Part Command = "path-to-this-script/dvd-writepart %n %a %v" # you will have the following input to this script: # -# dvd-writepart "part_number" "device" "part_filename" -# $1 $2 $3 +# dvd-writepart "part_number" "device" "part_filename" +# $1 $2 $3 # # for example: # @@ -19,11 +19,12 @@ MKISOFS=@MKISOFS@ GROWISOFS=@GROWISOFS@ -GROWARGS="-use-the-force-luke=tty -quiet" +# GROWARGS="-use-the-force-luke=tty -quiet" +GROWARGS="-quiet" # Uncomment the following line if you do not want the tray to be reloaded # when writing ends. -#GROWARGS="${GROWARGS} -use-the-force-luke=notray" +GROWARGS="${GROWARGS} -use-the-force-luke=notray" # Uncomment the following line if you have a Linux kernel >=2.6.8, and # if you want to allow a session to start beyond the 4gb boundary. diff --git a/bacula/src/cats/sql_list.c b/bacula/src/cats/sql_list.c index cb229b72c2..7b2659e15d 100644 --- a/bacula/src/cats/sql_list.c +++ b/bacula/src/cats/sql_list.c @@ -5,31 +5,25 @@ * * Version $Id$ */ - /* Copyright (C) 2000-2005 Kern Sibbald This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of - the License, or (at your option) any later version. + modify it under the terms of the GNU General Public License + version 2 as ammended 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 GNU - General Public License for more details. - - You should have received a copy of the GNU General Public - License along with this program; if not, write to the Free - Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - MA 02111-1307, USA. + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + the file LICENSE for additional details. */ /* The following is necessary so that we do not include * the dummy external definition of DB. */ -#define __SQL_C /* indicate that this is sql.c */ +#define __SQL_C /* indicate that this is sql.c */ #include "bacula.h" #include "cats.h" @@ -52,13 +46,13 @@ extern int QueryDB(const char *file, int line, JCR *jcr, B_DB *db, char *select_ * Submit general SQL query */ int db_list_sql_query(JCR *jcr, B_DB *mdb, char *query, DB_LIST_HANDLER *sendit, - void *ctx, int verbose, e_list_type type) + void *ctx, int verbose, e_list_type type) { db_lock(mdb); if (sql_query(mdb, query) != 0) { Mmsg(mdb->errmsg, _("Query failed: %s\n"), sql_strerror(mdb)); if (verbose) { - sendit(ctx, mdb->errmsg); + sendit(ctx, mdb->errmsg); } db_unlock(mdb); return 0; @@ -131,7 +125,7 @@ db_list_client_records(JCR *jcr, B_DB *mdb, DB_LIST_HANDLER *sendit, void *ctx, */ void db_list_media_records(JCR *jcr, B_DB *mdb, MEDIA_DBR *mdbr, - DB_LIST_HANDLER *sendit, void *ctx, e_list_type type) + DB_LIST_HANDLER *sendit, void *ctx, e_list_type type) { char ed1[50]; db_lock(mdb); @@ -152,7 +146,7 @@ db_list_media_records(JCR *jcr, B_DB *mdb, MEDIA_DBR *mdbr, "VolUseDuration,MaxVolJobs,MaxVolFiles,MaxVolBytes,InChanger," "EndFile,EndBlock,VolParts,LabelType,StorageId" " FROM Media WHERE Media.PoolId=%s ORDER BY MediaId", - edit_int64(mdbr->PoolId, ed1)); + edit_int64(mdbr->PoolId, ed1)); } } else { if (mdbr->VolumeName[0] != 0) { @@ -163,7 +157,7 @@ db_list_media_records(JCR *jcr, B_DB *mdb, MEDIA_DBR *mdbr, Mmsg(mdb->cmd, "SELECT MediaId,VolumeName,VolStatus," "VolBytes,VolFiles,VolRetention,Recycle,Slot,InChanger,MediaType,LastWritten " "FROM Media WHERE Media.PoolId=%s ORDER BY MediaId", - edit_int64(mdbr->PoolId, ed1)); + edit_int64(mdbr->PoolId, ed1)); } } @@ -179,12 +173,12 @@ db_list_media_records(JCR *jcr, B_DB *mdb, MEDIA_DBR *mdbr, } void db_list_jobmedia_records(JCR *jcr, B_DB *mdb, uint32_t JobId, - DB_LIST_HANDLER *sendit, void *ctx, e_list_type type) + DB_LIST_HANDLER *sendit, void *ctx, e_list_type type) { char ed1[50]; db_lock(mdb); if (type == VERT_LIST) { - if (JobId > 0) { /* do by JobId */ + if (JobId > 0) { /* do by JobId */ Mmsg(mdb->cmd, "SELECT JobMediaId,JobId,Media.MediaId,Media.VolumeName," "FirstIndex,LastIndex,StartFile,JobMedia.EndFile,StartBlock," "JobMedia.EndBlock,Copy,Stripe " @@ -198,7 +192,7 @@ void db_list_jobmedia_records(JCR *jcr, B_DB *mdb, uint32_t JobId, } } else { - if (JobId > 0) { /* do by JobId */ + if (JobId > 0) { /* do by JobId */ Mmsg(mdb->cmd, "SELECT JobId,Media.VolumeName,FirstIndex,LastIndex " "FROM JobMedia,Media WHERE Media.MediaId=JobMedia.MediaId " "AND JobMedia.JobId=%s", edit_int64(JobId, ed1)); @@ -228,7 +222,7 @@ void db_list_jobmedia_records(JCR *jcr, B_DB *mdb, uint32_t JobId, */ void db_list_job_records(JCR *jcr, B_DB *mdb, JOB_DBR *jr, DB_LIST_HANDLER *sendit, - void *ctx, e_list_type type) + void *ctx, e_list_type type) { char ed1[50]; char limit[100]; @@ -240,7 +234,7 @@ db_list_job_records(JCR *jcr, B_DB *mdb, JOB_DBR *jr, DB_LIST_HANDLER *sendit, } if (type == VERT_LIST) { if (jr->JobId == 0 && jr->Job[0] == 0) { - Mmsg(mdb->cmd, + Mmsg(mdb->cmd, "SELECT JobId,Job,Job.Name,PurgedFiles,Type,Level," "Job.ClientId,Client.Name,JobStatus,SchedTime," "StartTime,EndTime,JobTDate," @@ -249,8 +243,8 @@ db_list_job_records(JCR *jcr, B_DB *mdb, JOB_DBR *jr, DB_LIST_HANDLER *sendit, "FROM Job,Client,Pool,FileSet WHERE " "Client.ClientId=Job.ClientId AND Pool.PoolId=Job.PoolId " "AND FileSet.FileSetId=Job.FileSetId ORDER BY StartTime%s", limit); - } else { /* single record */ - Mmsg(mdb->cmd, + } else { /* single record */ + Mmsg(mdb->cmd, "SELECT JobId,Job,Job.Name,PurgedFiles,Type,Level," "Job.ClientId,Client.Name,JobStatus,SchedTime," "StartTime,EndTime,JobTDate," @@ -259,17 +253,17 @@ db_list_job_records(JCR *jcr, B_DB *mdb, JOB_DBR *jr, DB_LIST_HANDLER *sendit, "FROM Job,Client,Pool,FileSet WHERE Job.JobId=%s AND " "Client.ClientId=Job.ClientId AND Pool.PoolId=Job.PoolId " "AND FileSet.FileSetId=Job.FileSetId", - edit_int64(jr->JobId, ed1)); + edit_int64(jr->JobId, ed1)); } } else { if (jr->JobId == 0 && jr->Job[0] == 0) { - Mmsg(mdb->cmd, + Mmsg(mdb->cmd, "SELECT JobId,Name,StartTime,Type,Level,JobFiles,JobBytes,JobStatus " "FROM Job ORDER BY StartTime%s", limit); - } else { /* single record */ + } else { /* single record */ Mmsg(mdb->cmd, "SELECT JobId,Name,StartTime,Type,Level," "JobFiles,JobBytes,JobStatus FROM Job WHERE JobId=%s", - edit_int64(jr->JobId, ed1)); + edit_int64(jr->JobId, ed1)); } } if (!QUERY_DB(jcr, mdb, mdb->cmd)) { @@ -306,7 +300,7 @@ db_list_job_totals(JCR *jcr, B_DB *mdb, JOB_DBR *jr, DB_LIST_HANDLER *sendit, vo /* Do Grand Total */ Mmsg(mdb->cmd, "SELECT count(*) AS Jobs,sum(JobFiles) " -"AS Files,sum(JobBytes) As Bytes FROM Job"); + "AS Files,sum(JobBytes) As Bytes FROM Job"); if (!QUERY_DB(jcr, mdb, mdb->cmd)) { db_unlock(mdb); diff --git a/bacula/src/dird/sql_cmds.c b/bacula/src/dird/sql_cmds.c index 9a2a5aa3f4..f0fa6bb0a0 100644 --- a/bacula/src/dird/sql_cmds.c +++ b/bacula/src/dird/sql_cmds.c @@ -304,10 +304,20 @@ const char *uar_inc = "AND FileSet.FileSet='%s' " "%s"; +#ifdef HAVE_POSTGRESQL +/* Note, the PostgreSQL will have a much uglier looking + * list since it cannot do GROUP BY of different values. + */ +const char *uar_list_temp = + "SELECT JobId,Level,JobFiles,JobBytes,StartTime,VolumeName,StartFile" + " FROM temp" + " ORDER BY StartTime,StartFile ASC"; +#else const char *uar_list_temp = "SELECT JobId,Level,JobFiles,JobBytes,StartTime,VolumeName,StartFile" " FROM temp" " GROUP BY JobId ORDER BY StartTime,StartFile ASC"; +#endif const char *uar_sel_jobid_temp = "SELECT JobId FROM temp ORDER BY StartTime ASC"; @@ -359,7 +369,24 @@ const char *uar_jobids_fileindex = "AND Filename.FilenameId=File.FilenameId " "ORDER BY Job.StartTime DESC LIMIT 1"; -/* Query to get all files in a directory -- no recursing */ +/* Query to get all files in a directory -- no recursing + * Note, for PostgreSQL since it respects the "Single Value + * rule", the results of the SELECT will be unoptimized. + * I.e. the same file will be restored multiple times, once + * for each time it was backed up. + */ + +#ifdef HAVE_POSTGRESQL +const char *uar_jobid_fileindex_from_dir = + "SELECT Job.JobId,File.FileIndex FROM Job,File,Path,Filename,Client " + "WHERE Job.JobId IN (%s) " + "AND Job.JobId=File.JobId " + "AND Path.Path='%s' " + "AND Client.Name='%s' " + "AND Job.ClientId=Client.ClientId " + "AND Path.PathId=File.Pathid " + "AND Filename.FilenameId=File.FilenameId"; +#else const char *uar_jobid_fileindex_from_dir = "SELECT Job.JobId,File.FileIndex FROM Job,File,Path,Filename,Client " "WHERE Job.JobId IN (%s) " @@ -370,4 +397,5 @@ const char *uar_jobid_fileindex_from_dir = "AND Path.PathId=File.Pathid " "AND Filename.FilenameId=File.FilenameId " "GROUP BY File.FileIndex "; +#endif diff --git a/bacula/src/dird/ua_restore.c b/bacula/src/dird/ua_restore.c index 23a02883cf..5bff2b886d 100644 --- a/bacula/src/dird/ua_restore.c +++ b/bacula/src/dird/ua_restore.c @@ -1,12 +1,12 @@ /* * * Bacula Director -- User Agent Database restore Command - * Creates a bootstrap file for restoring files and - * starts the restore job. + * Creates a bootstrap file for restoring files and + * starts the restore job. * - * Tree handling routines split into ua_tree.c July MMIII. - * BSR (bootstrap record) handling routines split into - * bsr.c July MMIII + * Tree handling routines split into ua_tree.c July MMIII. + * BSR (bootstrap record) handling routines split into + * bsr.c July MMIII * * Kern Sibbald, July MMII * @@ -36,22 +36,22 @@ extern void print_bsr(UAContext *ua, RBSR *bsr); /* Imported variables */ -extern char *uar_list_jobs, *uar_file, *uar_sel_files; -extern char *uar_del_temp, *uar_del_temp1, *uar_create_temp; -extern char *uar_create_temp1, *uar_last_full, *uar_full; -extern char *uar_inc, *uar_list_temp, *uar_sel_jobid_temp; +extern char *uar_list_jobs, *uar_file, *uar_sel_files; +extern char *uar_del_temp, *uar_del_temp1, *uar_create_temp; +extern char *uar_create_temp1, *uar_last_full, *uar_full; +extern char *uar_inc, *uar_list_temp, *uar_sel_jobid_temp; extern char *uar_sel_all_temp1, *uar_sel_fileset, *uar_mediatype; -extern char *uar_jobid_fileindex, *uar_dif, *uar_sel_all_temp; -extern char *uar_count_files, *uar_jobids_fileindex; +extern char *uar_jobid_fileindex, *uar_dif, *uar_sel_all_temp; +extern char *uar_count_files, *uar_jobids_fileindex; extern char *uar_jobid_fileindex_from_dir; struct NAME_LIST { - char **name; /* list of names */ - int num_ids; /* ids stored */ - int max_ids; /* size of array */ - int num_del; /* number deleted */ - int tot_ids; /* total to process */ + char **name; /* list of names */ + int num_ids; /* ids stored */ + int max_ids; /* size of array */ + int num_del; /* number deleted */ + int tot_ids; /* total to process */ }; @@ -62,7 +62,7 @@ struct RESTORE_CTX { uint32_t JobId; char ClientName[MAX_NAME_LENGTH]; char last_jobid[20]; - POOLMEM *JobIds; /* User entered string of JobIds */ + POOLMEM *JobIds; /* User entered string of JobIds */ STORE *store; JOB *restore_job; POOL *pool; @@ -70,13 +70,13 @@ struct RESTORE_CTX { uint32_t selected_files; char *where; RBSR *bsr; - POOLMEM *fname; /* filename only */ - POOLMEM *path; /* path only */ + POOLMEM *fname; /* filename only */ + POOLMEM *path; /* path only */ POOLMEM *query; - int fnl; /* filename length */ - int pnl; /* path length */ + int fnl; /* filename length */ + int pnl; /* path length */ bool found; - bool all; /* mark all as default */ + bool all; /* mark all as default */ NAME_LIST name_list; }; @@ -100,9 +100,9 @@ static void free_rx(RESTORE_CTX *rx); static void split_path_and_filename(RESTORE_CTX *rx, char *fname); static int jobid_fileindex_handler(void *ctx, int num_fields, char **row); static bool insert_file_into_findex_list(UAContext *ua, RESTORE_CTX *rx, char *file, - char *date); + char *date); static bool insert_dir_into_findex_list(UAContext *ua, RESTORE_CTX *rx, char *dir, - char *date); + char *date); static void insert_one_file_or_dir(UAContext *ua, RESTORE_CTX *rx, char *date, bool dir); static int get_client_name(UAContext *ua, RESTORE_CTX *rx); static int get_date(UAContext *ua, char *date, int date_len); @@ -114,7 +114,7 @@ static int count_handler(void *ctx, int num_fields, char **row); */ int restore_cmd(UAContext *ua, const char *cmd) { - RESTORE_CTX rx; /* restore context */ + RESTORE_CTX rx; /* restore context */ JOB *job; int i; POOLMEM *fname; @@ -139,10 +139,10 @@ int restore_cmd(UAContext *ua, const char *cmd) LockRes(); foreach_res(job, R_JOB) { if (job->JobType == JT_RESTORE) { - if (!rx.restore_job) { - rx.restore_job = job; - } - rx.restore_jobs++; + if (!rx.restore_job) { + rx.restore_job = job; + } + rx.restore_jobs++; } } UnlockRes(); @@ -160,26 +160,26 @@ int restore_cmd(UAContext *ua, const char *cmd) * add_findex() */ switch (user_select_jobids_or_files(ua, &rx)) { - case 0: /* error */ + case 0: /* error */ goto bail_out; - case 1: /* selected by jobid */ + case 1: /* selected by jobid */ if (!build_directory_tree(ua, &rx)) { bsendmsg(ua, _("Restore not done.\n")); - goto bail_out; + goto bail_out; } break; - case 2: /* selected by filename, no tree needed */ + case 2: /* selected by filename, no tree needed */ break; } if (rx.bsr->JobId) { - if (!complete_bsr(ua, rx.bsr)) { /* find Vol, SessId, SessTime from JobIds */ + if (!complete_bsr(ua, rx.bsr)) { /* find Vol, SessId, SessTime from JobIds */ bsendmsg(ua, _("Unable to construct a valid BSR. Cannot continue.\n")); - goto bail_out; + goto bail_out; } if (!(rx.selected_files = write_bsr_file(ua, rx.bsr))) { bsendmsg(ua, _("No files selected to be restored.\n")); - goto bail_out; + goto bail_out; } bsendmsg(ua, _("\n%u file%s selected to be restored.\n\n"), rx.selected_files, rx.selected_files==1?"":"s"); @@ -211,13 +211,13 @@ int restore_cmd(UAContext *ua, const char *cmd) "run job=\"%s\" client=\"%s\" storage=\"%s\" bootstrap=\"%s\"" " where=\"%s\" files=%d catalog=\"%s\"", job->hdr.name, rx.ClientName, rx.store?rx.store->hdr.name:"", - fname, rx.where, rx.selected_files, ua->catalog->hdr.name); + fname, rx.where, rx.selected_files, ua->catalog->hdr.name); } else { Mmsg(ua->cmd, "run job=\"%s\" client=\"%s\" storage=\"%s\" bootstrap=\"%s\"" " files=%d catalog=\"%s\"", job->hdr.name, rx.ClientName, rx.store?rx.store->hdr.name:"", - fname, rx.selected_files, ua->catalog->hdr.name); + fname, rx.selected_files, ua->catalog->hdr.name); } free_pool_memory(fname); if (find_arg(ua, _("yes")) > 0) { @@ -266,12 +266,12 @@ static int get_client_name(UAContext *ua, RESTORE_CTX *rx) /* try command line argument */ int i = find_arg_with_value(ua, _("client")); if (i >= 0) { - bstrncpy(rx->ClientName, ua->argv[i], sizeof(rx->ClientName)); - return 1; + bstrncpy(rx->ClientName, ua->argv[i], sizeof(rx->ClientName)); + return 1; } memset(&cr, 0, sizeof(cr)); if (!get_client_dbr(ua, &cr)) { - return 0; + return 0; } bstrncpy(rx->ClientName, cr.Name, sizeof(rx->ClientName)); } @@ -284,8 +284,8 @@ static int get_client_name(UAContext *ua, RESTORE_CTX *rx) * select which files are to be restored. * * Returns: 2 if filename list made - * 1 if jobid list made - * 0 on error + * 1 if jobid list made + * 0 on error */ static int user_select_jobids_or_files(UAContext *ua, RESTORE_CTX *rx) { @@ -307,7 +307,7 @@ static int user_select_jobids_or_files(UAContext *ua, RESTORE_CTX *rx) "Enter a list of files to restore before a specified time", "Find the JobIds of the most recent backup for a client", "Find the JobIds for a backup for a client before a specified time", - "Enter a list of directories to restore for given JobIds", + "Enter a list of directories to restore for found JobIds", "Cancel", NULL }; @@ -337,86 +337,86 @@ static int user_select_jobids_or_files(UAContext *ua, RESTORE_CTX *rx) for (i=1; iargc; i++) { /* loop through arguments */ bool found_kw = false; - for (j=0; kw[j]; j++) { /* loop through keywords */ - if (strcasecmp(kw[j], ua->argk[i]) == 0) { - found_kw = true; - break; - } + for (j=0; kw[j]; j++) { /* loop through keywords */ + if (strcasecmp(kw[j], ua->argk[i]) == 0) { + found_kw = true; + break; + } } if (!found_kw) { bsendmsg(ua, _("Unknown keyword: %s\n"), ua->argk[i]); - return 0; + return 0; } /* Found keyword in kw[] list, process it */ switch (j) { - case 0: /* jobid */ - if (*rx->JobIds != 0) { + case 0: /* jobid */ + if (*rx->JobIds != 0) { pm_strcat(rx->JobIds, ","); - } - pm_strcat(rx->JobIds, ua->argv[i]); - done = true; - break; - case 1: /* current */ - bstrutime(date, sizeof(date), time(NULL)); - have_date = true; - break; - case 2: /* before */ - if (str_to_utime(ua->argv[i]) == 0) { + } + pm_strcat(rx->JobIds, ua->argv[i]); + done = true; + break; + case 1: /* current */ + bstrutime(date, sizeof(date), time(NULL)); + have_date = true; + break; + case 2: /* before */ + if (str_to_utime(ua->argv[i]) == 0) { bsendmsg(ua, _("Improper date format: %s\n"), ua->argv[i]); - return 0; - } - bstrncpy(date, ua->argv[i], sizeof(date)); - have_date = true; - break; - case 3: /* file */ - case 4: /* dir */ - if (!have_date) { - bstrutime(date, sizeof(date), time(NULL)); - } - if (!get_client_name(ua, rx)) { - return 0; - } - pm_strcpy(ua->cmd, ua->argv[i]); - insert_one_file_or_dir(ua, rx, date, j==4); - if (rx->name_list.num_ids) { - /* Check MediaType and select storage that corresponds */ - get_storage_from_mediatype(ua, &rx->name_list, rx); - done = true; - } - break; - case 5: /* select */ - if (!have_date) { - bstrutime(date, sizeof(date), time(NULL)); - } - if (!select_backups_before_date(ua, rx, date)) { - return 0; - } - done = true; - break; - case 6: /* pool specified */ - rx->pool = (POOL *)GetResWithName(R_POOL, ua->argv[i]); - if (!rx->pool) { + return 0; + } + bstrncpy(date, ua->argv[i], sizeof(date)); + have_date = true; + break; + case 3: /* file */ + case 4: /* dir */ + if (!have_date) { + bstrutime(date, sizeof(date), time(NULL)); + } + if (!get_client_name(ua, rx)) { + return 0; + } + pm_strcpy(ua->cmd, ua->argv[i]); + insert_one_file_or_dir(ua, rx, date, j==4); + if (rx->name_list.num_ids) { + /* Check MediaType and select storage that corresponds */ + get_storage_from_mediatype(ua, &rx->name_list, rx); + done = true; + } + break; + case 5: /* select */ + if (!have_date) { + bstrutime(date, sizeof(date), time(NULL)); + } + if (!select_backups_before_date(ua, rx, date)) { + return 0; + } + done = true; + break; + case 6: /* pool specified */ + rx->pool = (POOL *)GetResWithName(R_POOL, ua->argv[i]); + if (!rx->pool) { bsendmsg(ua, _("Error: Pool resource \"%s\" does not exist.\n"), ua->argv[i]); - return 0; - } - if (!acl_access_ok(ua, Pool_ACL, ua->argv[i])) { - rx->pool = NULL; + return 0; + } + if (!acl_access_ok(ua, Pool_ACL, ua->argv[i])) { + rx->pool = NULL; bsendmsg(ua, _("Error: Pool resource \"%s\" access not allowed.\n"), ua->argv[i]); - return 0; - } - break; - case 7: /* all specified */ - rx->all = true; - break; + return 0; + } + break; + case 7: /* all specified */ + rx->all = true; + break; /* * All keywords 7 or greater are ignored or handled by a select prompt */ default: - break; + break; } } if (rx->name_list.num_ids) { - return 2; /* filename list made */ + return 2; /* filename list made */ } if (!done) { @@ -434,175 +434,176 @@ static int user_select_jobids_or_files(UAContext *ua, RESTORE_CTX *rx) start_prompt(ua, _("To select the JobIds, you have the following choices:\n")); for (int i=0; list[i]; i++) { - add_prompt(ua, list[i]); + add_prompt(ua, list[i]); } done = true; switch (do_prompt(ua, "", _("Select item: "), NULL, 0)) { - case -1: /* error */ - return 0; - case 0: /* list last 20 Jobs run */ - gui_save = ua->jcr->gui; - ua->jcr->gui = true; - db_list_sql_query(ua->jcr, ua->db, uar_list_jobs, prtit, ua, 1, HORZ_LIST); - ua->jcr->gui = gui_save; - done = false; - break; - case 1: /* list where a file is saved */ - if (!get_client_name(ua, rx)) { - return 0; - } + case -1: /* error */ + return 0; + case 0: /* list last 20 Jobs run */ + gui_save = ua->jcr->gui; + ua->jcr->gui = true; + db_list_sql_query(ua->jcr, ua->db, uar_list_jobs, prtit, ua, 1, HORZ_LIST); + ua->jcr->gui = gui_save; + done = false; + break; + case 1: /* list where a file is saved */ + if (!get_client_name(ua, rx)) { + return 0; + } if (!get_cmd(ua, _("Enter Filename (no path):"))) { - return 0; - } - len = strlen(ua->cmd); - fname = (char *)malloc(len * 2 + 1); - db_escape_string(fname, ua->cmd, len); - Mmsg(rx->query, uar_file, rx->ClientName, fname); - free(fname); - gui_save = ua->jcr->gui; - ua->jcr->gui = true; - db_list_sql_query(ua->jcr, ua->db, rx->query, prtit, ua, 1, HORZ_LIST); - ua->jcr->gui = gui_save; - done = false; - break; - case 2: /* enter a list of JobIds */ + return 0; + } + len = strlen(ua->cmd); + fname = (char *)malloc(len * 2 + 1); + db_escape_string(fname, ua->cmd, len); + Mmsg(rx->query, uar_file, rx->ClientName, fname); + free(fname); + gui_save = ua->jcr->gui; + ua->jcr->gui = true; + db_list_sql_query(ua->jcr, ua->db, rx->query, prtit, ua, 1, HORZ_LIST); + ua->jcr->gui = gui_save; + done = false; + break; + case 2: /* enter a list of JobIds */ if (!get_cmd(ua, _("Enter JobId(s), comma separated, to restore: "))) { - return 0; - } - pm_strcpy(rx->JobIds, ua->cmd); - break; - case 3: /* Enter an SQL list command */ + return 0; + } + pm_strcpy(rx->JobIds, ua->cmd); + break; + case 3: /* Enter an SQL list command */ if (!get_cmd(ua, _("Enter SQL list command: "))) { - return 0; - } - gui_save = ua->jcr->gui; - ua->jcr->gui = true; - db_list_sql_query(ua->jcr, ua->db, ua->cmd, prtit, ua, 1, HORZ_LIST); - ua->jcr->gui = gui_save; - done = false; - break; - case 4: /* Select the most recent backups */ - bstrutime(date, sizeof(date), time(NULL)); - if (!select_backups_before_date(ua, rx, date)) { - return 0; - } - break; - case 5: /* select backup at specified time */ - if (!get_date(ua, date, sizeof(date))) { - return 0; - } - if (!select_backups_before_date(ua, rx, date)) { - return 0; - } - break; - case 6: /* Enter files */ - bstrutime(date, sizeof(date), time(NULL)); - if (!get_client_name(ua, rx)) { - return 0; - } + return 0; + } + gui_save = ua->jcr->gui; + ua->jcr->gui = true; + db_list_sql_query(ua->jcr, ua->db, ua->cmd, prtit, ua, 1, HORZ_LIST); + ua->jcr->gui = gui_save; + done = false; + break; + case 4: /* Select the most recent backups */ + bstrutime(date, sizeof(date), time(NULL)); + if (!select_backups_before_date(ua, rx, date)) { + return 0; + } + break; + case 5: /* select backup at specified time */ + if (!get_date(ua, date, sizeof(date))) { + return 0; + } + if (!select_backups_before_date(ua, rx, date)) { + return 0; + } + break; + case 6: /* Enter files */ + bstrutime(date, sizeof(date), time(NULL)); + if (!get_client_name(ua, rx)) { + return 0; + } bsendmsg(ua, _("Enter file names with paths, or < to enter a filename\n" "containg a list of file names with paths, and terminate\n" "them with a blank line.\n")); - for ( ;; ) { + for ( ;; ) { if (!get_cmd(ua, _("Enter full filename: "))) { - return 0; - } - len = strlen(ua->cmd); - if (len == 0) { - break; - } - insert_one_file_or_dir(ua, rx, date, false); - } - /* Check MediaType and select storage that corresponds */ - if (rx->name_list.num_ids) { - get_storage_from_mediatype(ua, &rx->name_list, rx); - } - return 2; - case 7: /* enter files backed up before specified time */ - if (!get_date(ua, date, sizeof(date))) { - return 0; - } - if (!get_client_name(ua, rx)) { - return 0; - } + return 0; + } + len = strlen(ua->cmd); + if (len == 0) { + break; + } + insert_one_file_or_dir(ua, rx, date, false); + } + /* Check MediaType and select storage that corresponds */ + if (rx->name_list.num_ids) { + get_storage_from_mediatype(ua, &rx->name_list, rx); + } + return 2; + case 7: /* enter files backed up before specified time */ + if (!get_date(ua, date, sizeof(date))) { + return 0; + } + if (!get_client_name(ua, rx)) { + return 0; + } bsendmsg(ua, _("Enter file names with paths, or < to enter a filename\n" "containg a list of file names with paths, and terminate\n" "them with a blank line.\n")); - for ( ;; ) { + for ( ;; ) { if (!get_cmd(ua, _("Enter full filename: "))) { - return 0; - } - len = strlen(ua->cmd); - if (len == 0) { - break; - } - insert_one_file_or_dir(ua, rx, date, false); - } - /* Check MediaType and select storage that corresponds */ - if (rx->name_list.num_ids) { - get_storage_from_mediatype(ua, &rx->name_list, rx); - } - return 2; - - case 8: /* Find JobIds for current backup */ - bstrutime(date, sizeof(date), time(NULL)); - if (!select_backups_before_date(ua, rx, date)) { - return 0; - } - done = false; - break; - - case 9: /* Find JobIds for give date */ - if (!get_date(ua, date, sizeof(date))) { - return 0; - } - if (!select_backups_before_date(ua, rx, date)) { - return 0; - } - done = false; - break; - - case 10: /* Enter directories */ - if (*rx->JobIds != 0) { + return 0; + } + len = strlen(ua->cmd); + if (len == 0) { + break; + } + insert_one_file_or_dir(ua, rx, date, false); + } + /* Check MediaType and select storage that corresponds */ + if (rx->name_list.num_ids) { + get_storage_from_mediatype(ua, &rx->name_list, rx); + } + return 2; + + case 8: /* Find JobIds for current backup */ + bstrutime(date, sizeof(date), time(NULL)); + if (!select_backups_before_date(ua, rx, date)) { + return 0; + } + done = false; + break; + + case 9: /* Find JobIds for give date */ + if (!get_date(ua, date, sizeof(date))) { + return 0; + } + if (!select_backups_before_date(ua, rx, date)) { + return 0; + } + done = false; + break; + + case 10: /* Enter directories */ + if (*rx->JobIds != 0) { bsendmsg(ua, _("You have already seleted the following JobIds: %s\n"), - rx->JobIds); + rx->JobIds); } else if (get_cmd(ua, _("Enter JobId(s), comma separated, to restore: "))) { - if (*rx->JobIds != 0 && *ua->cmd) { + if (*rx->JobIds != 0 && *ua->cmd) { pm_strcat(rx->JobIds, ","); - } - pm_strcat(rx->JobIds, ua->cmd); - } + } + pm_strcat(rx->JobIds, ua->cmd); + } if (*rx->JobIds == 0 || *rx->JobIds == '.') { - return 0; /* nothing entered, return */ - } - bstrutime(date, sizeof(date), time(NULL)); - if (!get_client_name(ua, rx)) { - return 0; - } - bsendmsg(ua, _("Enter directory names with a trailing /, or < to enter a filename\n" - "containg a list of directories and terminate\n" - "them with a blank line.\n")); - for ( ;; ) { + return 0; /* nothing entered, return */ + } + bstrutime(date, sizeof(date), time(NULL)); + if (!get_client_name(ua, rx)) { + return 0; + } + bsendmsg(ua, _("Enter full directory names or start the name\n" + "with a < to indicate it is a filename containg a list\n" + "of directories and terminate them with a blank line.\n")); + for ( ;; ) { if (!get_cmd(ua, _("Enter directory name: "))) { - return 0; - } - len = strlen(ua->cmd); - if (len == 0) { - break; - } - if (ua->cmd[len-1] != '/') { + return 0; + } + len = strlen(ua->cmd); + if (len == 0) { + break; + } + /* Add trailing slash to end of directory names */ + if (ua->cmd[0] != '<' && ua->cmd[len-1] != '/') { strcat(ua->cmd, "/"); - } - insert_one_file_or_dir(ua, rx, date, true); - } - /* Check MediaType and select storage that corresponds */ - if (rx->name_list.num_ids) { - get_storage_from_mediatype(ua, &rx->name_list, rx); - } - return 2; - - case 11: /* Cancel or quit */ - return 0; + } + insert_one_file_or_dir(ua, rx, date, true); + } + /* Check MediaType and select storage that corresponds */ + if (rx->name_list.num_ids) { + get_storage_from_mediatype(ua, &rx->name_list, rx); + } + return 2; + + case 11: /* Cancel or quit */ + return 0; } } @@ -620,25 +621,25 @@ static int user_select_jobids_or_files(UAContext *ua, RESTORE_CTX *rx) int stat = get_next_jobid_from_list(&p, &JobId); if (stat < 0) { bsendmsg(ua, _("Invalid JobId in list.\n")); - return 0; + return 0; } if (stat == 0) { - break; + break; } if (jr.JobId == JobId) { - continue; /* duplicate of last JobId */ + continue; /* duplicate of last JobId */ } jr.JobId = JobId; if (!db_get_job_record(ua->jcr, ua->db, &jr)) { - char ed1[50]; + char ed1[50]; bsendmsg(ua, _("Unable to get Job record for JobId=%s: ERR=%s\n"), - edit_int64(JobId, ed1), db_strerror(ua->db)); - return 0; + edit_int64(JobId, ed1), db_strerror(ua->db)); + return 0; } if (!acl_access_ok(ua, Job_ACL, jr.Name)) { bsendmsg(ua, _("No authorization. Job \"%s\" not selected.\n"), - jr.Name); - continue; + jr.Name); + continue; } rx->TotalFiles += jr.JobFiles; } @@ -654,10 +655,10 @@ static int get_date(UAContext *ua, char *date, int date_len) "BEFORE the date you specify below.\n\n")); for ( ;; ) { if (!get_cmd(ua, _("Enter date as YYYY-MM-DD HH:MM:SS :"))) { - return 0; + return 0; } if (str_to_utime(ua->cmd) != 0) { - break; + break; } bsendmsg(ua, _("Improper date format.\n")); } @@ -679,30 +680,30 @@ static void insert_one_file_or_dir(UAContext *ua, RESTORE_CTX *rx, char *date, b case '<': p++; if ((ffd = fopen(p, "r")) == NULL) { - berrno be; + berrno be; bsendmsg(ua, _("Cannot open file %s: ERR=%s\n"), - p, be.strerror()); - break; + p, be.strerror()); + break; } while (fgets(file, sizeof(file), ffd)) { - line++; - if (dir) { - if (!insert_dir_into_findex_list(ua, rx, file, date)) { + line++; + if (dir) { + if (!insert_dir_into_findex_list(ua, rx, file, date)) { bsendmsg(ua, _("Error occurred on line %d of %s\n"), line, p); - } - } else { - if (!insert_file_into_findex_list(ua, rx, file, date)) { + } + } else { + if (!insert_file_into_findex_list(ua, rx, file, date)) { bsendmsg(ua, _("Error occurred on line %d of %s\n"), line, p); - } - } + } + } } fclose(ffd); break; default: if (dir) { - insert_dir_into_findex_list(ua, rx, ua->cmd, date); + insert_dir_into_findex_list(ua, rx, ua->cmd, date); } else { - insert_file_into_findex_list(ua, rx, ua->cmd, date); + insert_file_into_findex_list(ua, rx, ua->cmd, date); } break; } @@ -714,7 +715,7 @@ static void insert_one_file_or_dir(UAContext *ua, RESTORE_CTX *rx, char *date, b * and FileIndex, then insert them into the findex list. */ static bool insert_file_into_findex_list(UAContext *ua, RESTORE_CTX *rx, char *file, - char *date) + char *date) { char ed1[50]; @@ -722,16 +723,16 @@ static bool insert_file_into_findex_list(UAContext *ua, RESTORE_CTX *rx, char *f split_path_and_filename(rx, file); if (*rx->JobIds == 0) { Mmsg(rx->query, uar_jobid_fileindex, date, rx->path, rx->fname, - rx->ClientName); + rx->ClientName); } else { Mmsg(rx->query, uar_jobids_fileindex, rx->JobIds, date, - rx->path, rx->fname, rx->ClientName); + rx->path, rx->fname, rx->ClientName); } rx->found = false; /* Find and insert jobid and File Index */ if (!db_sql_query(ua->db, rx->query, jobid_fileindex_handler, (void *)rx)) { bsendmsg(ua, _("Query failed: %s. ERR=%s\n"), - rx->query, db_strerror(ua->db)); + rx->query, db_strerror(ua->db)); } if (!rx->found) { bsendmsg(ua, _("No database record found for: %s\n"), file); @@ -753,7 +754,7 @@ static bool insert_file_into_findex_list(UAContext *ua, RESTORE_CTX *rx, char *f * to get the JobId and FileIndexes of all files in that directory. */ static bool insert_dir_into_findex_list(UAContext *ua, RESTORE_CTX *rx, char *dir, - char *date) + char *date) { char ed1[50]; @@ -763,13 +764,13 @@ static bool insert_dir_into_findex_list(UAContext *ua, RESTORE_CTX *rx, char *di return false; } else { Mmsg(rx->query, uar_jobid_fileindex_from_dir, rx->JobIds, - dir, rx->ClientName); + dir, rx->ClientName); } rx->found = false; /* Find and insert jobid and File Index */ if (!db_sql_query(ua->db, rx->query, jobid_fileindex_handler, (void *)rx)) { bsendmsg(ua, _("Query failed: %s. ERR=%s\n"), - rx->query, db_strerror(ua->db)); + rx->query, db_strerror(ua->db)); } if (!rx->found) { bsendmsg(ua, _("No database record found for: %s\n"), dir); @@ -799,12 +800,12 @@ static void split_path_and_filename(RESTORE_CTX *rx, char *name) */ for (p=f=name; *p; p++) { if (*p == '/') { - f = p; /* set pos of last slash */ + f = p; /* set pos of last slash */ } } if (*f == '/') { /* did we find a slash? */ - f++; /* yes, point to filename */ - } else { /* no, whole thing must be path name */ + f++; /* yes, point to filename */ + } else { /* no, whole thing must be path name */ f = p; } @@ -816,7 +817,7 @@ static void split_path_and_filename(RESTORE_CTX *rx, char *name) rx->fnl = p - f; if (rx->fnl > 0) { rx->fname = check_pool_memory_size(rx->fname, rx->fnl+1); - memcpy(rx->fname, f, rx->fnl); /* copy filename */ + memcpy(rx->fname, f, rx->fnl); /* copy filename */ rx->fname[rx->fnl] = 0; } else { rx->fname[0] = 0; @@ -866,20 +867,20 @@ static bool build_directory_tree(UAContext *ua, RESTORE_CTX *rx) bsendmsg(ua, "%s\n", db_strerror(ua->db)); } if (rx->found) { - /* Add about 25% more than this job for over estimate */ - tree.FileEstimate = rx->JobId + (rx->JobId >> 2); - tree.DeltaCount = rx->JobId/50; /* print 50 ticks */ + /* Add about 25% more than this job for over estimate */ + tree.FileEstimate = rx->JobId + (rx->JobId >> 2); + tree.DeltaCount = rx->JobId/50; /* print 50 ticks */ } } for (p=rx->JobIds; get_next_jobid_from_list(&p, &JobId) > 0; ) { char ed1[50]; if (JobId == last_JobId) { - continue; /* eliminate duplicate JobIds */ + continue; /* eliminate duplicate JobIds */ } last_JobId = JobId; bsendmsg(ua, _("\nBuilding directory tree for JobId %s ... "), - edit_int64(JobId, ed1)); + edit_int64(JobId, ed1)); items++; /* * Find files for this JobId and insert them in the tree @@ -900,16 +901,16 @@ static bool build_directory_tree(UAContext *ua, RESTORE_CTX *rx) bsendmsg(ua, "\nThere were no files inserted into the tree, so file selection\n" "is not possible.Most likely your retention policy pruned the files\n"); if (!get_yesno(ua, _("\nDo you want to restore all the files? (yes|no): "))) { - OK = false; + OK = false; } else { - last_JobId = 0; - for (p=rx->JobIds; get_next_jobid_from_list(&p, &JobId) > 0; ) { - if (JobId == last_JobId) { - continue; /* eliminate duplicate JobIds */ - } - add_findex_all(rx->bsr, JobId); - } - OK = true; + last_JobId = 0; + for (p=rx->JobIds; get_next_jobid_from_list(&p, &JobId) > 0; ) { + if (JobId == last_JobId) { + continue; /* eliminate duplicate JobIds */ + } + add_findex_all(rx->bsr, JobId); + } + OK = true; } } else { char ec1[50]; @@ -921,8 +922,8 @@ static bool build_directory_tree(UAContext *ua, RESTORE_CTX *rx) get_storage_from_mediatype(ua, &rx->name_list, rx); if (find_arg(ua, _("done")) < 0) { - /* Let the user interact in selecting which files to restore */ - OK = user_select_files_from_tree(&tree); + /* Let the user interact in selecting which files to restore */ + OK = user_select_files_from_tree(&tree); } /* @@ -930,20 +931,20 @@ static bool build_directory_tree(UAContext *ua, RESTORE_CTX *rx) * extracted making a bootstrap file. */ if (OK) { - for (TREE_NODE *node=first_tree_node(tree.root); node; node=next_tree_node(node)) { + for (TREE_NODE *node=first_tree_node(tree.root); node; node=next_tree_node(node)) { Dmsg2(400, "FI=%d node=0x%x\n", node->FileIndex, node); - if (node->extract || node->extract_dir) { + if (node->extract || node->extract_dir) { Dmsg2(400, "type=%d FI=%d\n", node->type, node->FileIndex); - add_findex(rx->bsr, node->JobId, node->FileIndex); - if (node->extract && node->type != TN_NEWDIR) { - rx->selected_files++; /* count only saved files */ - } - } - } + add_findex(rx->bsr, node->JobId, node->FileIndex); + if (node->extract && node->type != TN_NEWDIR) { + rx->selected_files++; /* count only saved files */ + } + } + } } } - free_tree(tree.root); /* free the directory tree */ + free_tree(tree.root); /* free the directory tree */ return OK; } @@ -990,11 +991,11 @@ static bool select_backups_before_date(UAContext *ua, RESTORE_CTX *rx, char *dat bstrncpy(fsr.FileSet, ua->argv[i], sizeof(fsr.FileSet)); if (!db_get_fileset_record(ua->jcr, ua->db, &fsr)) { bsendmsg(ua, _("Error getting FileSet \"%s\": ERR=%s\n"), fsr.FileSet, - db_strerror(ua->db)); - i = -1; + db_strerror(ua->db)); + i = -1; } } - if (i < 0) { /* fileset not found */ + if (i < 0) { /* fileset not found */ edit_int64(cr.ClientId, ed1); Mmsg(rx->query, uar_sel_fileset, ed1, ed1); start_prompt(ua, _("The defined FileSet resources are:\n")); @@ -1002,8 +1003,8 @@ static bool select_backups_before_date(UAContext *ua, RESTORE_CTX *rx, char *dat bsendmsg(ua, "%s\n", db_strerror(ua->db)); } if (do_prompt(ua, _("FileSet"), _("Select FileSet resource"), - fileset_name, sizeof(fileset_name)) < 0) { - goto bail_out; + fileset_name, sizeof(fileset_name)) < 0) { + goto bail_out; } bstrncpy(fsr.FileSet, fileset_name, sizeof(fsr.FileSet)); @@ -1022,7 +1023,7 @@ static bool select_backups_before_date(UAContext *ua, RESTORE_CTX *rx, char *dat bstrncpy(pr.Name, rx->pool->hdr.name, sizeof(pr.Name)); if (db_get_pool_record(ua->jcr, ua->db, &pr)) { bsnprintf(pool_select, sizeof(pool_select), "AND Media.PoolId=%s ", - edit_int64(pr.PoolId, ed1)); + edit_int64(pr.PoolId, ed1)); } else { bsendmsg(ua, _("Pool \"%s\" not found, using any pool.\n"), pr.Name); } @@ -1031,7 +1032,7 @@ static bool select_backups_before_date(UAContext *ua, RESTORE_CTX *rx, char *dat /* Find JobId of last Full backup for this client, fileset */ edit_int64(cr.ClientId, ed1); Mmsg(rx->query, uar_last_full, ed1, ed1, date, fsr.FileSet, - pool_select); + pool_select); if (!db_sql_query(ua->db, rx->query, NULL, NULL)) { bsendmsg(ua, "%s\n", db_strerror(ua->db)); goto bail_out; @@ -1056,7 +1057,7 @@ static bool select_backups_before_date(UAContext *ua, RESTORE_CTX *rx, char *dat /* Now find most recent Differental Job after Full save, if any */ Mmsg(rx->query, uar_dif, edit_uint64(rx->JobTDate, ed1), date, - edit_int64(cr.ClientId, ed2), fsr.FileSet, pool_select); + edit_int64(cr.ClientId, ed2), fsr.FileSet, pool_select); if (!db_sql_query(ua->db, rx->query, NULL, NULL)) { bsendmsg(ua, "%s\n", db_strerror(ua->db)); } @@ -1072,7 +1073,7 @@ static bool select_backups_before_date(UAContext *ua, RESTORE_CTX *rx, char *dat /* Now find all Incremental Jobs after Full/dif save */ Mmsg(rx->query, uar_inc, edit_uint64(rx->JobTDate, ed1), date, - edit_int64(cr.ClientId, ed2), fsr.FileSet, pool_select); + edit_int64(cr.ClientId, ed2), fsr.FileSet, pool_select); if (!db_sql_query(ua->db, rx->query, NULL, NULL)) { bsendmsg(ua, "%s\n", db_strerror(ua->db)); } @@ -1108,10 +1109,10 @@ static int get_next_jobid_from_list(char **p, uint32_t *JobId) jobid[0] = 0; for (int i=0; i<(int)sizeof(jobid); i++) { if (*q == 0) { - break; + break; } else if (*q == ',') { - q++; - break; + q++; + break; } jobid[i] = *q++; jobid[i+1] = 0; @@ -1119,7 +1120,7 @@ static int get_next_jobid_from_list(char **p, uint32_t *JobId) if (jobid[0] == 0) { return 0; } else if (!is_a_number(jobid)) { - return -1; /* error */ + return -1; /* error */ } *p = q; *JobId = str_to_int64(jobid); @@ -1156,7 +1157,7 @@ static int jobid_handler(void *ctx, int num_fields, char **row) RESTORE_CTX *rx = (RESTORE_CTX *)ctx; if (strcmp(rx->last_jobid, row[0]) == 0) { - return 0; /* duplicate id */ + return 0; /* duplicate id */ } bstrncpy(rx->last_jobid, row[0], sizeof(rx->last_jobid)); if (rx->JobIds[0] != 0) { @@ -1205,16 +1206,16 @@ static int unique_name_list_handler(void *ctx, int num_fields, char **row) } if (name->num_ids == name->max_ids) { if (name->max_ids == 0) { - name->max_ids = 1000; - name->name = (char **)bmalloc(sizeof(char *) * name->max_ids); + name->max_ids = 1000; + name->name = (char **)bmalloc(sizeof(char *) * name->max_ids); } else { - name->max_ids = (name->max_ids * 3) / 2; - name->name = (char **)brealloc(name->name, sizeof(char *) * name->max_ids); + name->max_ids = (name->max_ids * 3) / 2; + name->name = (char **)brealloc(name->name, sizeof(char *) * name->max_ids); } } for (int i=0; inum_ids; i++) { if (strcmp(name->name[i], row[0]) == 0) { - return 0; /* already in list, return */ + return 0; /* already in list, return */ } } /* Add new name to list */ @@ -1276,10 +1277,10 @@ static void get_storage_from_mediatype(UAContext *ua, NAME_LIST *name_list, REST LockRes(); foreach_res(store, R_STORAGE) { if (strcmp(name_list->name[0], store->media_type) == 0) { - if (acl_access_ok(ua, Storage_ACL, store->hdr.name)) { - rx->store = store; - } - break; + if (acl_access_ok(ua, Storage_ACL, store->hdr.name)) { + rx->store = store; + } + break; } } UnlockRes(); @@ -1289,15 +1290,15 @@ static void get_storage_from_mediatype(UAContext *ua, NAME_LIST *name_list, REST store = NULL; int i = find_arg_with_value(ua, "storage"); if (i > 0) { - store = (STORE *)GetResWithName(R_STORAGE, ua->argv[i]); - if (store && !acl_access_ok(ua, Storage_ACL, store->hdr.name)) { - store = NULL; - } + store = (STORE *)GetResWithName(R_STORAGE, ua->argv[i]); + if (store && !acl_access_ok(ua, Storage_ACL, store->hdr.name)) { + store = NULL; + } } if (store && (store != rx->store)) { bsendmsg(ua, _("Warning default storage overridden by %s on command line.\n"), - store->hdr.name); - rx->store = store; + store->hdr.name); + rx->store = store; } return; } @@ -1309,6 +1310,6 @@ static void get_storage_from_mediatype(UAContext *ua, NAME_LIST *name_list, REST bsendmsg(ua, _("\nWarning. Unable to find Storage resource for\n" "MediaType \"%s\", needed by the Jobs you selected.\n" "You will be allowed to select a Storage device later.\n"), - name_list->name[0]); + name_list->name[0]); } } diff --git a/bacula/src/filed/heartbeat.c b/bacula/src/filed/heartbeat.c index 93e2bc4543..cb80c769ea 100644 --- a/bacula/src/filed/heartbeat.c +++ b/bacula/src/filed/heartbeat.c @@ -61,30 +61,31 @@ extern "C" void *sd_heartbeat_thread(void *arg) jcr->hb_dir_bsock = dir; /* Hang reading the socket to the SD, and every time we get - * a heartbeat or we get a wait timeout (1 minute), we - * check to see if we need to send a heartbeat to the - * Director. + * a heartbeat or we get a wait timeout (1 minute), we + * check to see if we need to send a heartbeat to the + * Director. */ for ( ; !is_bnet_stop(sd); ) { n = bnet_wait_data_intr(sd, WAIT_INTERVAL); if (me->heartbeat_interval) { - now = time(NULL); - if (now-last_heartbeat >= me->heartbeat_interval) { - bnet_sig(dir, BNET_HEARTBEAT); - last_heartbeat = now; - } + now = time(NULL); + if (now-last_heartbeat >= me->heartbeat_interval) { + bnet_sig(dir, BNET_HEARTBEAT); + last_heartbeat = now; + } } if (is_bnet_stop(sd)) { - break; + break; } - if (n == 1) { /* input waiting */ - bnet_recv(sd); /* read it -- probably heartbeat from sd */ - if (sd->msglen <= 0) { + if (n == 1) { /* input waiting */ + bnet_recv(sd); /* read it -- probably heartbeat from sd */ + if (sd->msglen <= 0) { Dmsg1(100, "Got BNET_SIG %d from SD\n", sd->msglen); - } else { + } else { Dmsg2(100, "Got %d bytes from SD. MSG=%s\n", sd->msglen, sd->msg); - } + } } + Dmsg2(000, "wait_intr=%d stop=%d\n", n, is_bnet_stop(sd)); } bnet_close(sd); bnet_close(dir); @@ -117,7 +118,7 @@ void stop_heartbeat_monitor(JCR *jcr) } /* Wait max 10 secs for heartbeat thread to start */ while (jcr->hb_bsock == NULL && cnt++ < 200) { - bmicrosleep(0, 50000); /* wait for start */ + bmicrosleep(0, 50000); /* wait for start */ } if (!jcr->hb_bsock) { } @@ -135,7 +136,7 @@ void stop_heartbeat_monitor(JCR *jcr) cnt = 0; /* Wait max 100 secs for heartbeat thread to stop */ while (jcr->hb_bsock && cnt++ < 200) { - pthread_kill(jcr->heartbeat_id, TIMEOUT_SIGNAL); /* make heartbeat thread go away */ + pthread_kill(jcr->heartbeat_id, TIMEOUT_SIGNAL); /* make heartbeat thread go away */ bmicrosleep(0, 500000); } if (jcr->hb_bsock) { @@ -166,8 +167,8 @@ extern "C" void *dir_heartbeat_thread(void *arg) now = time(NULL); next = now - last_heartbeat; if (next >= me->heartbeat_interval) { - bnet_sig(dir, BNET_HEARTBEAT); - last_heartbeat = now; + bnet_sig(dir, BNET_HEARTBEAT); + last_heartbeat = now; } bmicrosleep(next, 0); } diff --git a/bacula/src/stored/dev.c b/bacula/src/stored/dev.c index 1958574770..b495f9f70b 100644 --- a/bacula/src/stored/dev.c +++ b/bacula/src/stored/dev.c @@ -89,6 +89,7 @@ static bool dev_get_os_pos(DEVICE *dev, struct mtget *mt_stat); static void open_tape_device(DCR *dcr, int mode); static void open_file_device(DCR *dcr, int mode); static void open_dvd_device(DCR *dcr, int mode); +static char *mode_to_str(int mode); /* * Allocate and initialize the DEVICE structure @@ -275,17 +276,17 @@ DEVICE::open(DCR *dcr, int mode) } bstrncpy(VolCatInfo.VolCatName, dcr->VolumeName, sizeof(VolCatInfo.VolCatName)); - Dmsg4(29, "open dev: tape=%d dev_name=%s vol=%s mode=%d\n", is_tape(), - dev_name, VolCatInfo.VolCatName, mode); + Dmsg4(29, "open dev: tape=%d dev_name=%s vol=%s mode=%s\n", is_tape(), + dev_name, VolCatInfo.VolCatName, mode_to_str(mode)); state &= ~(ST_LABEL|ST_APPEND|ST_READ|ST_EOT|ST_WEOT|ST_EOF); label_type = B_BACULA_LABEL; if (is_tape() || is_fifo()) { open_tape_device(dcr, mode); } else if (is_dvd()) { - Dmsg1(100, "call open_dvd_device mode=%d\n", mode); + Dmsg1(100, "call open_dvd_device mode=%s\n", mode_to_str(mode)); open_dvd_device(dcr, mode); } else { - Dmsg1(100, "call open_file_device mode=%d\n", mode); + Dmsg1(100, "call open_file_device mode=%d\n", mode_to_str(mode)); open_file_device(dcr, mode); } return fd; @@ -404,8 +405,8 @@ static void open_file_device(DCR *dcr, int mode) /* * Handle opening of File Archive (not a tape) */ - Dmsg3(29, "Enter: open_file_dev: %s dev=%s mode=%d\n", dev->is_dvd()?"DVD":"disk", - archive_name.c_str(), mode); + Dmsg3(29, "Enter: open_file_dev: %s dev=%s mode=%s\n", dev->is_dvd()?"DVD":"disk", + archive_name.c_str(), mode_to_str(mode)); if (dev->VolCatInfo.VolCatName[0] == 0) { Mmsg(dev->errmsg, _("Could not open file device %s. No Volume name given.\n"), @@ -420,13 +421,14 @@ static void open_file_device(DCR *dcr, int mode) } pm_strcat(archive_name, dev->VolCatInfo.VolCatName); - Dmsg3(29, "open dev: %s dev=%s mode=%d\n", dev->is_dvd()?"DVD":"disk", - archive_name.c_str(), mode); + Dmsg3(29, "open dev: %s dev=%s mode=%s\n", dev->is_dvd()?"DVD":"disk", + archive_name.c_str(), mode_to_str(mode)); dev->openmode = mode; dev->set_mode(mode); /* If creating file, give 0640 permissions */ - Dmsg3(29, "mode=%d open(%s, 0x%x, 0640)\n", mode, archive_name.c_str(), dev->mode); + Dmsg3(29, "mode=%s open(%s, 0x%x, 0640)\n", mode, archive_name.c_str(), + mode_to_str(dev->mode)); if ((dev->fd = open(archive_name.c_str(), dev->mode, 0640)) < 0) { berrno be; dev->dev_errno = errno; @@ -459,8 +461,8 @@ static void open_dvd_device(DCR *dcr, int mode) /* * Handle opening of DVD Volume */ - Dmsg3(29, "Enter: open_file_dev: %s dev=%s mode=%d\n", dev->is_dvd()?"DVD":"disk", - archive_name.c_str(), mode); + Dmsg3(29, "Enter: open_dvd_dev: %s dev=%s mode=%s\n", dev->is_dvd()?"DVD":"disk", + archive_name.c_str(), mode_to_str(mode)); if (dev->VolCatInfo.VolCatName[0] == 0) { Mmsg(dev->errmsg, _("Could not open file device %s. No Volume name given.\n"), @@ -483,8 +485,8 @@ static void open_dvd_device(DCR *dcr, int mode) return; } - Dmsg3(29, "open dev: %s dev=%s mode=%d\n", dev->is_dvd()?"DVD":"disk", - archive_name.c_str(), mode); + Dmsg3(29, "open dev: %s dev=%s mode=%s\n", dev->is_dvd()?"DVD":"disk", + archive_name.c_str(), mode_to_str(mode)); dev->openmode = mode; /* @@ -496,7 +498,6 @@ static void open_dvd_device(DCR *dcr, int mode) } dev->set_mode(mode); - Dmsg1(100, "Call make_dvd_filename. Vol=%s\n", dev->VolCatInfo.VolCatName); /* * If we are opening it read-only, it is *probably* on the * DVD, so try the DVD first, otherwise look in the spool dir. @@ -508,7 +509,8 @@ static void open_dvd_device(DCR *dcr, int mode) } /* If creating file, give 0640 permissions */ - Dmsg3(29, "mode=%d open(%s, 0x%x, 0640)\n", mode, archive_name.c_str(), dev->mode); + Dmsg3(29, "mode=%s open(%s, 0x%x, 0640)\n", mode_to_str(mode), + archive_name.c_str(), dev->mode); if ((dev->fd = open(archive_name.c_str(), dev->mode, 0640)) < 0) { berrno be; dev->dev_errno = errno; @@ -1877,3 +1879,16 @@ static bool dev_get_os_pos(DEVICE *dev, struct mtget *mt_stat) ioctl(dev->fd, MTIOCGET, (char *)mt_stat) == 0 && mt_stat->mt_fileno >= 0; } + +static char *modes[] = { + "CREATE_READ_WRITE", + "OPEN_READ_WRITE", + "OPEN_READ_ONLY", + "OPEN_WRITE_ONLY" +}; + + +static char *mode_to_str(int mode) +{ + return modes[mode-1]; +} diff --git a/bacula/src/stored/dvd.c b/bacula/src/stored/dvd.c index c60cb5f878..7cda72f7d5 100644 --- a/bacula/src/stored/dvd.c +++ b/bacula/src/stored/dvd.c @@ -28,7 +28,6 @@ /* Forward referenced functions */ static char *edit_device_codes_dev(DEVICE *dev, char *omsg, const char *imsg); static bool do_mount_dev(DEVICE* dev, int mount, int dotimeout); -static bool dvd_write_part(DEVICE *dev); static void add_file_and_part_name(DEVICE *dev, POOL_MEM &archive_name); /* @@ -131,6 +130,7 @@ static bool do_mount_dev(DEVICE* dev, int mount, int dotimeout) /* If busy retry each second */ while ((status = run_program_full_output(ocmd.c_str(), dev->max_open_wait/2, results)) != 0) { + Dmsg1(100, "results len=%d\n", strlen(results)); if (fnmatch("*is already mounted on", results, 0) == 0) { break; } @@ -147,6 +147,45 @@ static bool do_mount_dev(DEVICE* dev, int mount, int dotimeout) Dmsg2(40, "Device %s cannot be mounted. ERR=%s\n", dev->print_name(), results); Mmsg(dev->errmsg, "Device %s cannot be mounted. ERR=%s\n", dev->print_name(), results); +#ifdef xxx + /* + * Now, just to be sure it is not mounted, try to read the + * filesystem. + */ + DIR* dp; + struct dirent *entry, *result; + int name_max; + int count = 0; + + name_max = pathconf(".", _PC_NAME_MAX); + if (name_max < 1024) { + name_max = 1024; + } + + if (!(dp = opendir(dev->device->mount_point))) { + berrno be; + dev->dev_errno = errno; + Dmsg3(29, "open_mounted_dev: failed to open dir %s (dev=%s), ERR=%s\n", dev->device->mount_point, dev->dev_name, be.strerror()); + goto get_out; + } + + entry = (struct dirent *)malloc(sizeof(struct dirent) + name_max + 1000); + while (1) { + if ((readdir_r(dp, entry, &result) != 0) || (result == NULL)) { + dev->dev_errno = ENOENT; + Dmsg2(29, "open_mounted_dev: failed to find suitable file in dir %s (dev=%s)\n", dev->device->mount_point, dev->dev_name); + break; + } + count++; + } + free(entry); + closedir(dp); + if (count > 2) { + mount = 1; /* If we got more than . and .. */ + break; /* there must be something mounted */ + } +get_out: +#endif free_pool_memory(results); return false; } @@ -188,6 +227,7 @@ void update_free_space_dev(DEVICE* dev) while (1) { if (run_program_full_output(ocmd.c_str(), dev->max_open_wait/2, results) == 0) { + Dmsg1(100, "results len=%d\n", strlen(results)); Dmsg1(100, "Free space program run : %s\n", results); free = str_to_int64(results); if (free >= 0) { @@ -225,9 +265,13 @@ void update_free_space_dev(DEVICE* dev) return; } -static bool dvd_write_part(DEVICE *dev) +/* + * Write a part (Vol, Vol.1, ...) from the spool to the DVD + */ +static bool dvd_write_part(DCR *dcr) { - Dmsg1(29, "dvd_write_part: device is %s\n", dev->dev_name); + DEVICE *dev = dcr->dev; + Dmsg1(29, "dvd_write_part: device is %s\n", dev->print_name()); if (unmount_dev(dev, 1) < 0) { Dmsg0(29, "dvd_write_part: unable to unmount the device\n"); @@ -238,12 +282,25 @@ static bool dvd_write_part(DEVICE *dev) char* icmd; int status; int timeout; + int part; + char ed1[50]; results = get_pool_memory(PM_MESSAGE); results[0] = 0; icmd = dev->device->write_part_command; + /* + * Note! part is used to control whether or not we create a + * new filesystem. If the device could be mounted, it is because + * it already has a filesystem, so we artificially set part=1 + * to avoid zapping an existing filesystem. + */ + part = dev->part; + if (dev->is_mounted() && dev->part == 0) { + dev->part = 1; /* do not wipe out existing filesystem */ + } edit_device_codes_dev(dev, ocmd.c_str(), icmd); + dev->part = part; /* Wait at most the time a maximum size part is written in DVD 0.5x speed * FIXME: Minimum speed should be in device configuration @@ -253,6 +310,7 @@ static bool dvd_write_part(DEVICE *dev) Dmsg2(29, "dvd_write_part: cmd=%s timeout=%d\n", ocmd.c_str(), timeout); status = run_program_full_output(ocmd.c_str(), timeout, results); + Dmsg1(100, "results len=%d\n", strlen(results)); if (status != 0) { Mmsg1(dev->errmsg, "Error while writing current part to the DVD: %s", results); @@ -266,7 +324,11 @@ static bool dvd_write_part(DEVICE *dev) /* Delete spool file */ make_spooled_dvd_filename(dev, archive_name); unlink(archive_name.c_str()); + Dmsg1(29, "unlink(%s)\n", archive_name.c_str()); free_pool_memory(results); + update_free_space_dev(dev); + Jmsg(dcr->jcr, M_INFO, 0, _("Remaining free space %s on %s\n"), + edit_uint64_with_commas(dev->free_space, ed1), dev->print_name()); return true; } @@ -301,7 +363,7 @@ int open_next_part(DCR *dcr) * DVD before opening the next part. */ if (dev->is_dvd() && (dev->part == dev->num_parts) && dev->can_append()) { - if (!dvd_write_part(dev)) { + if (!dvd_write_part(dcr)) { return -1; } } @@ -356,6 +418,9 @@ int open_next_part(DCR *dcr) /* Open the first part file. * - Close the fd * - Reopen the device + * + * I don't see why this is necessary unless the current + * part is not zero. */ int open_first_part(DCR *dcr, int mode) { @@ -500,14 +565,16 @@ bool dvd_close_job(DCR *dcr) ok = false; } - if (ok && (open_next_part(dcr) < 0)) { - Jmsg2(jcr, M_FATAL, 0, _("Unable to open device next part %s: ERR=%s\n"), + /* This should be !dvd_write_part(dcr) */ + if (ok && open_next_part(dcr) < 0) { +// if (ok && !dvd_write_part(dcr)) { + Jmsg2(jcr, M_FATAL, 0, _("Unable to write part %s: ERR=%s\n"), dev->print_name(), strerror_dev(dev)); dev->dev_errno = EIO; ok = false; } - dev->VolCatInfo.VolCatParts = dev->num_parts; } + dev->VolCatInfo.VolCatParts = dev->num_parts; return ok; } diff --git a/bacula/src/version.h b/bacula/src/version.h index c1659c1084..0aee6f7f73 100644 --- a/bacula/src/version.h +++ b/bacula/src/version.h @@ -1,8 +1,8 @@ /* */ #undef VERSION #define VERSION "1.37.28" -#define BDATE "30 June 2005" -#define LSMDATE "30Jun05" +#define BDATE "02 July 2005" +#define LSMDATE "02Jul05" /* Debug flags */ #undef DEBUG