From: Kern Sibbald Date: Sat, 3 Dec 2005 15:00:04 +0000 (+0000) Subject: 03Dec05 X-Git-Tag: Release-1.38.3~49 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=d788c7298ec0f7da8dc629de2338f0d72a8ad838;p=bacula%2Fbacula 03Dec05 - Fix font code in gnome2 console user patch. Fixes bug #501. - Fix malformatted bnet error message that caused seg fault fixes bug 502 - Applied user patch to improve README.vc8 in src/win32. 29Nov05 - Add Migrate, Copy, Archive Job types (some where there) - Correct some more editing of JobId's (for 64 bit compatibility). - Ensure that StorageId is stored in Media record when ever possible. - Add Migration Job to Job. - Add Migration Time, Migration High Bytes, Migration Low Bytes Next Pool to Pool resource. - Add more code to mac.c (migration archive copy). - Change Start Storage daemon job to require read and write storage pointers. - Pass read storage data to SD as well as write storage data. - Remove old code from winservice.cpp - Break on error in scan. - Fix typo in signal.c - Separate read/write DCR in SD. Add jcr->read_dcr. - Cleanup how find_device() works. - Add read output to Status in SD. git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@2636 91ce42f0-d328-0410-95d8-f526ca767f89 --- diff --git a/bacula/kernstodo b/bacula/kernstodo index 21af52086a..1093efbd17 100644 --- a/bacula/kernstodo +++ b/bacula/kernstodo @@ -1,5 +1,5 @@ Kern's ToDo List - 21 November 2005 + 30 November 2005 Major development: Project Developer @@ -16,8 +16,14 @@ Document: - Does WildFile match against full name? Doc. For 1.39: -- Make sure that all do_prompt() calls in Dir check for - -1 (error) and -2 (cancel) returns. +- Queue warning/error messages during restore so that they + are reported at the end of the report rather than being + hidden in the file listing ... +- A Volume taken from Scratch should take on the retention period + of the new pool. +- Correct doc for Maximum Changer Wait (and others) accepting only + integers. +- Fix Maximum Changer Wait (and others) to accept qualifiers. - Look at -D_FORTIFY_SOURCE=2 - Add Win32 FileSet definition somewhere - Look at fixing restore status stats in SD. @@ -1252,4 +1258,6 @@ Block Position: 0 ==== -=== Done -- see kernsdone +=== Done +- Make sure that all do_prompt() calls in Dir check for + -1 (error) and -2 (cancel) returns. diff --git a/bacula/kes-1.39 b/bacula/kes-1.39 index 9daab4d782..b1a58fc6dd 100644 --- a/bacula/kes-1.39 +++ b/bacula/kes-1.39 @@ -3,6 +3,29 @@ General: +Changes to 1.39.1: +03Dec05 +- Fix font code in gnome2 console user patch. Fixes bug #501. +- Fix malformatted bnet error message that caused seg fault + fixes bug 502 +- Applied user patch to improve README.vc8 in src/win32. +29Nov05 +- Add Migrate, Copy, Archive Job types (some where there) +- Correct some more editing of JobId's (for 64 bit compatibility). +- Ensure that StorageId is stored in Media record when ever possible. +- Add Migration Job to Job. +- Add Migration Time, Migration High Bytes, Migration Low Bytes + Next Pool to Pool resource. +- Add more code to mac.c (migration archive copy). +- Change Start Storage daemon job to require read and write storage + pointers. +- Pass read storage data to SD as well as write storage data. +- Remove old code from winservice.cpp +- Break on error in scan. +- Fix typo in signal.c +- Separate read/write DCR in SD. Add jcr->read_dcr. +- Cleanup how find_device() works. +- Add read output to Status in SD. Changes to 1.39.0: 23Nov05 - Add red-black btree routines diff --git a/bacula/projects b/bacula/projects index 32d851f7d6..6c3450ed37 100644 --- a/bacula/projects +++ b/bacula/projects @@ -4,7 +4,7 @@ Projects: 29 November 2005 Summary: -Item 1: Implement Migration that moves Jobs from one Pool to another. +Item 1: Implement Migration that moves Jobs from one Pool to another. Item 2: Implement extraction of Win32 BackupWrite data. Item 3: Implement a Bacula GUI/management tool using Python. Item 4: Implement a Python interface to the Bacula catalog. @@ -718,7 +718,18 @@ Item 25: Implement creation and maintenance of copy pools Notes: I would commit some of my developers' time if we can agree on the design and behavior. +=============================================== +Not in Dec 2005 Vote: +Item n: One line summary ... + Date: 29 November 2005 + Origin: Florian Schnabel + Status: + What: An easy option to skip a certain job on a certain date. + Why: You could then easily skip tape backups on holidays. Especially + if you got no autochanger and can only fit one backup on a tape + that would be really handy, other jobs could proceed normally + and you won't get errors that way. ============= Empty Feature Request form =========== Item n: One line summary ... diff --git a/bacula/src/dird/backup.c b/bacula/src/dird/backup.c index 0d2b181355..f10207a158 100644 --- a/bacula/src/dird/backup.c +++ b/bacula/src/dird/backup.c @@ -138,11 +138,12 @@ bool do_backup(JCR *jcr) int tls_need = BNET_TLS_NONE; BSOCK *fd; STORE *store; + char ed1[100]; /* Print Job Start message */ - Jmsg(jcr, M_INFO, 0, _("Start Backup JobId %u, Job=%s\n"), - jcr->JobId, jcr->Job); + Jmsg(jcr, M_INFO, 0, _("Start Backup JobId %s, Job=%s\n"), + edit_uint64(jcr->JobId, ed1), jcr->Job); set_jcr_job_status(jcr, JS_Running); Dmsg2(100, "JobId=%d JobLevel=%c\n", jcr->jr.JobId, jcr->jr.JobLevel); @@ -168,7 +169,7 @@ bool do_backup(JCR *jcr) /* * Now start a job with the Storage daemon */ - if (!start_storage_daemon_job(jcr, jcr->storage, SD_APPEND)) { + if (!start_storage_daemon_job(jcr, NULL, jcr->storage)) { return false; } /* diff --git a/bacula/src/dird/catreq.c b/bacula/src/dird/catreq.c index 2f6a34053a..41cebc6d29 100644 --- a/bacula/src/dird/catreq.c +++ b/bacula/src/dird/catreq.c @@ -258,19 +258,23 @@ void catalog_request(JCR *jcr, BSOCK *bs) mr.VolWriteTime = sdmr.VolWriteTime; mr.VolParts = sdmr.VolParts; bstrncpy(mr.VolStatus, sdmr.VolStatus, sizeof(mr.VolStatus)); + if (jcr->store->StorageId) { + mr.StorageId = jcr->store->StorageId; + } Dmsg2(400, "db_update_media_record. Stat=%s Vol=%s\n", mr.VolStatus, mr.VolumeName); /* - * Check if it has expired, and if not update the DB. Note, if - * Volume has expired, has_volume_expired() will update the DB. + * Update the database, then before sending the response to the + * SD, check if the Volume has expired. */ - if (has_volume_expired(jcr, &mr) || db_update_media_record(jcr, jcr->db, &mr)) { - send_volume_info_to_storage_daemon(jcr, bs, &mr); - } else { + if (!db_update_media_record(jcr, jcr->db, &mr)) { Jmsg(jcr, M_FATAL, 0, _("Catalog error updating Media record. %s"), db_strerror(jcr->db)); bnet_fsend(bs, _("1993 Update Media error\n")); Dmsg0(400, "send error\n"); + } else { + (void)has_volume_expired(jcr, &mr); + send_volume_info_to_storage_daemon(jcr, bs, &mr); } db_unlock(jcr->db); diff --git a/bacula/src/dird/dird_conf.c b/bacula/src/dird/dird_conf.c index 994f383fdf..6fd684c206 100644 --- a/bacula/src/dird/dird_conf.c +++ b/bacula/src/dird/dird_conf.c @@ -236,6 +236,7 @@ RES_ITEM job_items[] = { {"fileset", store_res, ITEM(res_job.fileset), R_FILESET, ITEM_REQUIRED, 0}, {"schedule", store_res, ITEM(res_job.schedule), R_SCHEDULE, 0, 0}, {"verifyjob", store_res, ITEM(res_job.verify_job), R_JOB, 0, 0}, + {"migrationjob", store_res, ITEM(res_job.migration_job), R_JOB, 0, 0}, {"jobdefs", store_res, ITEM(res_job.jobdefs), R_JOBDEFS, 0, 0}, {"run", store_alist_str, ITEM(res_job.run_cmds), 0, 0, 0}, {"where", store_dir, ITEM(res_job.RestoreWhere), 0, 0, 0}, @@ -321,6 +322,10 @@ static RES_ITEM pool_items[] = { {"catalogfiles", store_yesno, ITEM(res_pool.catalog_files), 1, ITEM_DEFAULT, 1}, {"volumeretention", store_time, ITEM(res_pool.VolRetention), 0, ITEM_DEFAULT, 60*60*24*365}, {"volumeuseduration", store_time, ITEM(res_pool.VolUseDuration), 0, 0, 0}, + {"migrationtime", store_time, ITEM(res_pool.MigrationTime), 0, 0, 0}, + {"migrationhighbytes", store_size, ITEM(res_pool.MigrationHighBytes), 0, 0, 0}, + {"migrationlowbytes", store_size, ITEM(res_pool.MigrationLowBytes), 0, 0, 0}, + {"nextpool", store_res, ITEM(res_pool.NextPool), R_POOL, 0, 0}, {"autoprune", store_yesno, ITEM(res_pool.AutoPrune), 1, ITEM_DEFAULT, 1}, {"recycle", store_yesno, ITEM(res_pool.Recycle), 1, ITEM_DEFAULT, 1}, {NULL, NULL, NULL, 0, 0, 0} @@ -400,6 +405,8 @@ struct s_jt jobtypes[] = { {"admin", JT_ADMIN}, {"verify", JT_VERIFY}, {"restore", JT_RESTORE}, + {"copy", JT_COPY}, + {"migrate", JT_MIGRATE}, {NULL, 0} }; @@ -434,7 +441,7 @@ void dump_resource(int type, RES *reshdr, void sendit(void *sock, const char *fm { URES *res = (URES *)reshdr; bool recurse = true; - char ed1[100], ed2[100]; + char ed1[100], ed2[100], ed3[100]; DEVICE *dev; if (res == NULL) { @@ -460,13 +467,8 @@ void dump_resource(int type, RES *reshdr, void sendit(void *sock, const char *fm } break; case R_CONSOLE: -#ifdef HAVE_TLS sendit(sock, _("Console: name=%s SSL=%d\n"), res->res_con.hdr.name, res->res_con.tls_enable); -#else - sendit(sock, _("Console: name=%s SSL=%d\n"), - res->res_con.hdr.name, BNET_TLS_NONE); -#endif break; case R_COUNTER: if (res->res_counter.WrapCounter) { @@ -771,6 +773,14 @@ next_run: res->res_pool.recycle_oldest_volume, res->res_pool.purge_oldest_volume, res->res_pool.MaxVolJobs, res->res_pool.MaxVolFiles); + sendit(sock, _(" MigTime=%s MigHiBytes=%s MigLoBytes=%s\n"), + edit_utime(res->res_pool.MigrationTime, ed1, sizeof(ed1)), + edit_uint64(res->res_pool.MigrationHighBytes, ed2), + edit_uint64(res->res_pool.MigrationLowBytes, ed3)); + if (res->res_pool.NextPool) { + sendit(sock, _(" --> ")); + dump_resource(-R_POOL, (RES *)res->res_pool.NextPool, sendit, sock); + } break; case R_MSGS: sendit(sock, _("Messages: name=%s\n"), res->res_msgs.hdr.name); @@ -1137,13 +1147,26 @@ void save_resource(int type, RES_ITEM *items, int pass) switch (type) { /* Resources not containing a resource */ case R_CATALOG: - case R_POOL: case R_MSGS: case R_FILESET: case R_DEVICE: break; - /* Resources containing another resource or alist */ + /* + * Resources containing another resource or alist. First + * look up the resource which contains another resource. It + * was written during pass 1. Then stuff in the pointers to + * the resources it contains, which were inserted this pass. + * Finally, it will all be stored back. + */ + case R_POOL: + /* Find resource saved in pass 1 */ + if ((res = (URES *)GetResWithName(R_POOL, res_all.res_con.hdr.name)) == NULL) { + Emsg1(M_ERROR_TERM, 0, _("Cannot find Pool resource %s\n"), res_all.res_con.hdr.name); + } + /* Update it with pointer to NextPool from this pass (res_all) */ + res->res_pool.NextPool = res_all.res_pool.NextPool; + break; case R_CONSOLE: if ((res = (URES *)GetResWithName(R_CONSOLE, res_all.res_con.hdr.name)) == NULL) { Emsg1(M_ERROR_TERM, 0, _("Cannot find Console resource %s\n"), res_all.res_con.hdr.name); diff --git a/bacula/src/dird/dird_conf.h b/bacula/src/dird/dird_conf.h index 5d2ef5befc..8e980d621f 100644 --- a/bacula/src/dird/dird_conf.h +++ b/bacula/src/dird/dird_conf.h @@ -316,7 +316,10 @@ public: POOL *full_pool; /* Pool for Full backups */ POOL *inc_pool; /* Pool for Incremental backups */ POOL *dif_pool; /* Pool for Differental backups */ - JOB *verify_job; /* Job name to verify */ + union { + JOB *verify_job; /* Job name to verify */ + JOB *migration_job; /* Job name to migrate */ + }; JOB *jobdefs; /* Job defaults */ alist *run_cmds; /* Run commands */ uint32_t NumConcurrentJobs; /* number of concurrent jobs running */ @@ -421,6 +424,10 @@ public: uint32_t MaxVolJobs; /* Maximum jobs on the Volume */ uint32_t MaxVolFiles; /* Maximum files on the Volume */ uint64_t MaxVolBytes; /* Maximum bytes on the Volume */ + utime_t MigrationTime; /* Time to migrate to next pool */ + uint32_t MigrationHighBytes; /* When migration starts */ + uint32_t MigrationLowBytes; /* When migration stops */ + POOL *NextPool; /* Next pool for migration */ int AutoPrune; /* default for pool auto prune */ int Recycle; /* default for media recycle yes/no */ }; diff --git a/bacula/src/dird/job.c b/bacula/src/dird/job.c index ecb0d7bf34..38bc8f9080 100644 --- a/bacula/src/dird/job.c +++ b/bacula/src/dird/job.c @@ -218,7 +218,7 @@ static void *job_thread(void *arg) admin_cleanup(jcr, JS_ErrorTerminated); } break; - case JT_MIGRATION: + case JT_MIGRATE: case JT_COPY: case JT_ARCHIVE: if (!do_mac_init(jcr)) { /* migration, archive, copy */ @@ -294,7 +294,7 @@ static void *job_thread(void *arg) admin_cleanup(jcr, JS_ErrorTerminated); } break; - case JT_MIGRATION: + case JT_MIGRATE: case JT_COPY: case JT_ARCHIVE: if (do_mac(jcr)) { /* migration, archive, copy */ diff --git a/bacula/src/dird/mac.c b/bacula/src/dird/mac.c index bd6c1d2dc5..ecbe8aa013 100644 --- a/bacula/src/dird/mac.c +++ b/bacula/src/dird/mac.c @@ -43,6 +43,24 @@ bool do_mac_init(JCR *jcr) JOB_DBR jr; JobId_t input_jobid; char *Name; + RESTORE_CTX rx; + UAContext *ua; + const char *Type; + + switch(jcr->JobType) { + case JT_MIGRATE: + Type = "Migration"; + break; + case JT_ARCHIVE: + Type = "Archive"; + break; + case JT_COPY: + Type = "Copy"; + break; + default: + Type = "Unknown"; + break; + } if (!get_or_create_fileset_record(jcr)) { return false; @@ -52,7 +70,7 @@ bool do_mac_init(JCR *jcr) * Find JobId of last job that ran. */ memcpy(&jr, &jcr->jr, sizeof(jr)); - Name = jcr->job->hdr.name; + Name = jcr->job->migration_job->hdr.name; Dmsg1(100, "find last jobid for: %s\n", NPRT(Name)); if (!db_find_last_jobid(jcr, jcr->db, Name, &jr)) { Jmsg(jcr, M_FATAL, 0, _( @@ -60,9 +78,23 @@ bool do_mac_init(JCR *jcr) return false; } input_jobid = jr.JobId; - jcr->JobLevel = jr.JobLevel; Dmsg1(100, "Last jobid=%d\n", input_jobid); + jcr->target_jr.JobId = input_jobid; + if (!db_get_job_record(jcr, jcr->db, &jcr->target_jr)) { + Jmsg(jcr, M_FATAL, 0, _("Could not get job record for previous Job. ERR=%s"), + db_strerror(jcr->db)); + return false; + } + if (jcr->target_jr.JobStatus != 'T') { + Jmsg(jcr, M_FATAL, 0, _("Last Job %d did not terminate normally. JobStatus=%c\n"), + input_jobid, jcr->target_jr.JobStatus); + return false; + } + Jmsg(jcr, M_INFO, 0, _("%s using JobId=%d Job=%s\n"), + Type, jcr->target_jr.JobId, jcr->target_jr.Job); + + /* * Get the Pool record -- first apply any level defined pools */ @@ -98,6 +130,32 @@ bool do_mac_init(JCR *jcr) } jcr->PoolId = pr.PoolId; /****FIXME**** this can go away */ jcr->jr.PoolId = pr.PoolId; + + memset(&rx, 0, sizeof(rx)); + rx.bsr = new_bsr(); + rx.JobIds = ""; + rx.bsr->JobId = jcr->target_jr.JobId; + ua = new_ua_context(jcr); + complete_bsr(ua, rx.bsr); + rx.bsr->fi = new_findex(); + rx.bsr->fi->findex = 1; + rx.bsr->fi->findex2 = jcr->target_jr.JobFiles; + jcr->ExpectedFiles = write_bsr_file(ua, rx); + if (jcr->ExpectedFiles == 0) { + free_ua_context(ua); + free_bsr(rx.bsr); + return false; + } + if (jcr->RestoreBootstrap) { + free(jcr->RestoreBootstrap); + } + POOLMEM *fname = get_pool_memory(PM_MESSAGE); + make_unique_restore_filename(ua, &fname); + jcr->RestoreBootstrap = bstrdup(fname); + free_ua_context(ua); + free_bsr(rx.bsr); + free_pool_memory(fname); + jcr->needs_sd = true; return true; } @@ -112,9 +170,10 @@ bool do_mac(JCR *jcr) { int stat; const char *Type; + char ed1[100]; switch(jcr->JobType) { - case JT_MIGRATION: + case JT_MIGRATE: Type = "Migration"; break; case JT_ARCHIVE: @@ -130,8 +189,8 @@ bool do_mac(JCR *jcr) /* Print Job Start message */ - Jmsg(jcr, M_INFO, 0, _("Start %s JobId %u, Job=%s\n"), - Type, jcr->JobId, jcr->Job); + Jmsg(jcr, M_INFO, 0, _("Start %s JobId %s, Job=%s\n"), + Type, edit_uint64(jcr->JobId, ed1), jcr->Job); set_jcr_job_status(jcr, JS_Running); Dmsg2(100, "JobId=%d JobLevel=%c\n", jcr->jr.JobId, jcr->jr.JobLevel); @@ -157,7 +216,7 @@ bool do_mac(JCR *jcr) /* * Now start a job with the Storage daemon */ - if (!start_storage_daemon_job(jcr, jcr->storage, SD_APPEND)) { + if (!start_storage_daemon_job(jcr, jcr->storage, jcr->storage)) { return false; } /* @@ -203,7 +262,7 @@ void mac_cleanup(JCR *jcr, int TermCode) const char *Type; switch(jcr->JobType) { - case JT_MIGRATION: + case JT_MIGRATE: Type = "Migration"; break; case JT_ARCHIVE: diff --git a/bacula/src/dird/msgchan.c b/bacula/src/dird/msgchan.c index fbe9d5e136..a0b2e0a1bf 100644 --- a/bacula/src/dird/msgchan.c +++ b/bacula/src/dird/msgchan.c @@ -119,14 +119,13 @@ bool update_device_res(JCR *jcr, DEVICE *dev) /* * Start a job with the Storage daemon */ -int start_storage_daemon_job(JCR *jcr, alist *store, int append) +bool start_storage_daemon_job(JCR *jcr, alist *rstore, alist *wstore) { - bool ok = false; + bool ok = true; STORE *storage; BSOCK *sd; char auth_key[100]; POOL_MEM store_name, device_name, pool_name, pool_type, media_type; - char PoolId[50]; int copy = 0; int stripe = 0; @@ -170,7 +169,6 @@ int start_storage_daemon_job(JCR *jcr, alist *store, int append) pm_strcpy(pool_name, jcr->pool->hdr.name); bash_spaces(pool_type); bash_spaces(pool_name); - edit_int64(jcr->PoolId, PoolId); /* * We have two loops here. The first comes from the @@ -181,36 +179,76 @@ int start_storage_daemon_job(JCR *jcr, alist *store, int append) * available one. * */ - foreach_alist(storage, store) { - pm_strcpy(store_name, storage->hdr.name); - bash_spaces(store_name); - pm_strcpy(media_type, storage->media_type); - bash_spaces(media_type); - bnet_fsend(sd, use_storage, store_name.c_str(), media_type.c_str(), - pool_name.c_str(), pool_type.c_str(), append, copy, stripe); - - DEVICE *dev; - /* Loop over alternative storage Devices until one is OK */ - foreach_alist(dev, storage->device) { - pm_strcpy(device_name, dev->hdr.name); - bash_spaces(device_name); - bnet_fsend(sd, use_device, device_name.c_str()); - Dmsg1(100, ">stored: %s", sd->msg); + /* Do read side of storage daemon */ + if (ok && rstore) { + foreach_alist(storage, rstore) { + pm_strcpy(store_name, storage->hdr.name); + bash_spaces(store_name); + pm_strcpy(media_type, storage->media_type); + bash_spaces(media_type); + bnet_fsend(sd, use_storage, store_name.c_str(), media_type.c_str(), + pool_name.c_str(), pool_type.c_str(), 0, copy, stripe); + + DEVICE *dev; + /* Loop over alternative storage Devices until one is OK */ + foreach_alist(dev, storage->device) { + pm_strcpy(device_name, dev->hdr.name); + bash_spaces(device_name); + bnet_fsend(sd, use_device, device_name.c_str()); + Dmsg1(100, ">stored: %s", sd->msg); + } + bnet_sig(sd, BNET_EOD); /* end of Devices */ + bnet_sig(sd, BNET_EOD); /* end of Storages */ + if (bget_dirmsg(sd) > 0) { + Dmsg1(100, "msg); + /* ****FIXME**** save actual device name */ + ok = sscanf(sd->msg, OK_device, device_name.c_str()) == 1; + } else { + POOL_MEM err_msg; + pm_strcpy(err_msg, sd->msg); /* save message */ + Jmsg(jcr, M_FATAL, 0, _("\n" + " Storage daemon didn't accept Device \"%s\" because:\n %s"), + device_name.c_str(), err_msg.c_str()/* sd->msg */); + ok = false; + } + break; } - bnet_sig(sd, BNET_EOD); /* end of Devices */ - bnet_sig(sd, BNET_EOD); /* end of Storages */ - if (bget_dirmsg(sd) > 0) { - Dmsg1(100, "msg); - /* ****FIXME**** save actual device name */ - ok = sscanf(sd->msg, OK_device, device_name.c_str()) == 1; - } else { - POOL_MEM err_msg; - pm_strcpy(err_msg, sd->msg); /* save message */ - Jmsg(jcr, M_FATAL, 0, _("\n" - " Storage daemon didn't accept Device \"%s\" because:\n %s"), - device_name.c_str(), err_msg.c_str()/* sd->msg */); + } + + /* Do write side of storage daemon */ + if (ok && wstore) { + foreach_alist(storage, wstore) { + pm_strcpy(store_name, storage->hdr.name); + bash_spaces(store_name); + pm_strcpy(media_type, storage->media_type); + bash_spaces(media_type); + bnet_fsend(sd, use_storage, store_name.c_str(), media_type.c_str(), + pool_name.c_str(), pool_type.c_str(), 1, copy, stripe); + + DEVICE *dev; + /* Loop over alternative storage Devices until one is OK */ + foreach_alist(dev, storage->device) { + pm_strcpy(device_name, dev->hdr.name); + bash_spaces(device_name); + bnet_fsend(sd, use_device, device_name.c_str()); + Dmsg1(100, ">stored: %s", sd->msg); + } + bnet_sig(sd, BNET_EOD); /* end of Devices */ + bnet_sig(sd, BNET_EOD); /* end of Storages */ + if (bget_dirmsg(sd) > 0) { + Dmsg1(100, "msg); + /* ****FIXME**** save actual device name */ + ok = sscanf(sd->msg, OK_device, device_name.c_str()) == 1; + } else { + POOL_MEM err_msg; + pm_strcpy(err_msg, sd->msg); /* save message */ + Jmsg(jcr, M_FATAL, 0, _("\n" + " Storage daemon didn't accept Device \"%s\" because:\n %s"), + device_name.c_str(), err_msg.c_str()/* sd->msg */); + ok = false; + } + break; } - break; } if (ok) { ok = bnet_fsend(sd, "run"); diff --git a/bacula/src/dird/next_vol.c b/bacula/src/dird/next_vol.c index 52086651a1..9a64bf3921 100644 --- a/bacula/src/dird/next_vol.c +++ b/bacula/src/dird/next_vol.c @@ -12,19 +12,14 @@ Copyright (C) 2001-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 amended with additional clauses defined in the + file LICENSE in the main source directory. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 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. */ diff --git a/bacula/src/dird/protos.h b/bacula/src/dird/protos.h index a7aabf4ec2..96b79e5294 100644 --- a/bacula/src/dird/protos.h +++ b/bacula/src/dird/protos.h @@ -111,7 +111,7 @@ extern void mount_request(JCR *jcr, BSOCK *bs, char *buf); /* msgchan.c */ extern bool connect_to_storage_daemon(JCR *jcr, int retry_interval, int max_retry_time, int verbose); -extern int start_storage_daemon_job(JCR *jcr, alist *store, int append); +extern bool start_storage_daemon_job(JCR *jcr, alist *rstore, alist *wstore); extern int start_storage_daemon_message_thread(JCR *jcr); extern int bget_dirmsg(BSOCK *bs); extern void wait_for_storage_daemon_termination(JCR *jcr); diff --git a/bacula/src/dird/query.sql b/bacula/src/dird/query.sql index 55101486c9..3b1aff3e0c 100644 --- a/bacula/src/dird/query.sql +++ b/bacula/src/dird/query.sql @@ -176,3 +176,17 @@ SELECT DISTINCT Job.JobId as JobId,Job.Name as Name,Job.StartTime as StartTime, AND Media.MediaId=JobMedia.MediaId AND JobMedia.JobId=Job.JobId ORDER by Job.StartTime; +# 16 +:List File record for given Job and File +*Enter JobId: +*Enter Full path (no filename) with trailing slash: +*Enter Filename: +SELECT File.JobId AS JobId,FileIndex FROM File,Path,Filename + WHERE File.JobId=%1 AND + Path.Path='%2' AND Filename.Name='%3' AND + File.PathId=Path.PathId AND File.FilenameId=Filename.FilenameId; +SELECT JobId,Name,VolSessionId,VolsessionTime,JobFiles FROM Job WHERE JobId=%1; +SELECT JobId,MediaId,FirstIndex,LastIndex,StartFile,EndFile,StartBlock,EndBlock, + VolIndex FROM JobMedia WHERE JobId=%1; +SELECT VolumeName FROM Media,JobMedia WHERE JobMedia.JobId=%1 AND + Media.MediaId=JobMedia.MediaId; diff --git a/bacula/src/dird/recycle.c b/bacula/src/dird/recycle.c index 633cb5d35a..61da3577f7 100644 --- a/bacula/src/dird/recycle.c +++ b/bacula/src/dird/recycle.c @@ -1,7 +1,7 @@ /* * * Bacula Director -- Automatic Recycling of Volumes - * Recycles Volumes that have been purged + * Recycles Volumes that have been purged * * Kern Sibbald, May MMII * @@ -9,22 +9,17 @@ */ /* - Copyright (C) 2002-20054 Kern Sibbald + Copyright (C) 2002-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 amended with additional clauses defined in the + file LICENSE in the main source directory. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 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. */ @@ -98,11 +93,11 @@ int recycle_oldest_purged_volume(JCR *jcr, bool InChanger, MEDIA_DBR *mr) if (oldest.MediaId != 0) { mr->MediaId = oldest.MediaId; if (db_get_media_record(jcr, jcr->db, mr)) { - if (recycle_volume(jcr, mr)) { + if (recycle_volume(jcr, mr)) { Jmsg(jcr, M_INFO, 0, _("Recycled volume \"%s\"\n"), mr->VolumeName); Dmsg1(100, "return 1 recycle_oldest_purged_volume Vol=%s\n", mr->VolumeName); - return 1; - } + return 1; + } } Jmsg(jcr, M_ERROR, 0, "%s", db_strerror(jcr->db)); } diff --git a/bacula/src/dird/restore.c b/bacula/src/dird/restore.c index 2e1d24fe4b..4c442816c8 100644 --- a/bacula/src/dird/restore.c +++ b/bacula/src/dird/restore.c @@ -94,7 +94,7 @@ bool do_restore(JCR *jcr) /* * Now start a job with the Storage daemon */ - if (!start_storage_daemon_job(jcr, jcr->storage, SD_READ)) { + if (!start_storage_daemon_job(jcr, jcr->storage, NULL)) { restore_cleanup(jcr, JS_ErrorTerminated); return false; } diff --git a/bacula/src/dird/ua_label.c b/bacula/src/dird/ua_label.c index 384315b694..a0bdd945ad 100644 --- a/bacula/src/dird/ua_label.c +++ b/bacula/src/dird/ua_label.c @@ -535,6 +535,7 @@ static void label_from_barcodes(UAContext *ua, int drive) mr.VolBytes = 1; bstrncpy(mr.VolStatus, "Cleaning", sizeof(mr.VolStatus)); mr.MediaType[0] = 0; + mr.StorageId = store->StorageId; if (!db_update_media_record(ua->jcr, ua->db, &mr)) { bsendmsg(ua, "%s", db_strerror(ua->db)); } @@ -659,6 +660,7 @@ static bool send_label_request(UAContext *ua, MEDIA_DBR *mr, MEDIA_DBR *omr, if (media_record_exists) { /* we update it */ mr->VolBytes = 1; mr->InChanger = 1; + mr->StorageId = ua->jcr->store->StorageId; if (!db_update_media_record(ua->jcr, ua->db, mr)) { bsendmsg(ua, "%s", db_strerror(ua->db)); ok = false; @@ -667,6 +669,7 @@ static bool send_label_request(UAContext *ua, MEDIA_DBR *mr, MEDIA_DBR *omr, set_pool_dbr_defaults_in_media_dbr(mr, pr); mr->VolBytes = 1; /* flag indicating Volume labeled */ mr->InChanger = 1; + mr->StorageId = ua->jcr->store->StorageId; if (db_create_media_record(ua->jcr, ua->db, mr)) { bsendmsg(ua, _("Catalog record for Volume \"%s\", Slot %d successfully created.\n"), mr->VolumeName, mr->Slot); diff --git a/bacula/src/dird/ua_select.c b/bacula/src/dird/ua_select.c index 1a5df789aa..41765194a5 100644 --- a/bacula/src/dird/ua_select.c +++ b/bacula/src/dird/ua_select.c @@ -837,7 +837,7 @@ STORE *get_storage_resource(UAContext *ua, bool use_default) store = NULL; } - if (!store && store_name) { + if (!store && store_name && store_name[0] != 0) { store = (STORE *)GetResWithName(R_STORAGE, store_name); if (!store) { bsendmsg(ua, _("Storage resource \"%s\": not found\n"), store_name); diff --git a/bacula/src/dird/verify.c b/bacula/src/dird/verify.c index 6edbf80cad..f15233465f 100644 --- a/bacula/src/dird/verify.c +++ b/bacula/src/dird/verify.c @@ -176,6 +176,7 @@ bool do_verify(JCR *jcr) const char *level; BSOCK *fd; int stat; + char ed1[100]; if (!db_update_job_start_record(jcr, jcr->db, &jcr->jr)) { Jmsg(jcr, M_FATAL, 0, "%s", db_strerror(jcr->db)); @@ -183,8 +184,8 @@ bool do_verify(JCR *jcr) } /* Print Job Start message */ - Jmsg(jcr, M_INFO, 0, _("Start Verify JobId=%d Level=%s Job=%s\n"), - jcr->JobId, level_to_str(jcr->JobLevel), jcr->Job); + Jmsg(jcr, M_INFO, 0, _("Start Verify JobId=%s Level=%s Job=%s\n"), + edit_uint64(jcr->JobId, ed1), level_to_str(jcr->JobLevel), jcr->Job); if (jcr->JobLevel == L_VERIFY_VOLUME_TO_CATALOG) { /* @@ -197,7 +198,7 @@ bool do_verify(JCR *jcr) /* * Now start a job with the Storage daemon */ - if (!start_storage_daemon_job(jcr, jcr->storage, SD_READ)) { + if (!start_storage_daemon_job(jcr, jcr->storage, NULL)) { return false; } /* diff --git a/bacula/src/filed/job.c b/bacula/src/filed/job.c index e30ed6720d..edbac446d9 100644 --- a/bacula/src/filed/job.c +++ b/bacula/src/filed/job.c @@ -1508,7 +1508,7 @@ static int open_sd_read_session(JCR *jcr) /* * Open Read Session with Storage daemon */ - bnet_fsend(sd, read_open, jcr->VolumeName, + bnet_fsend(sd, read_open, "DummyVolume", jcr->VolSessionId, jcr->VolSessionTime, jcr->StartFile, jcr->EndFile, jcr->StartBlock, jcr->EndBlock); Dmsg1(110, ">stored: %s", sd->msg); diff --git a/bacula/src/filed/win32/winservice.cpp b/bacula/src/filed/win32/winservice.cpp index e8dc2811ff..186d0a73ef 100755 --- a/bacula/src/filed/win32/winservice.cpp +++ b/bacula/src/filed/win32/winservice.cpp @@ -457,32 +457,6 @@ _("Provides file backup and restore services. Bacula -- the network backup solut CloseServiceHandle(hsrvmanager); CloseServiceHandle(hservice); -#ifdef xxx_needed - // Now install the servicehelper registry setting... - // Locate the RunService registry entry - HKEY runapps; - if (RegCreateKey(HKEY_LOCAL_MACHINE, - "Software\\Microsoft\\Windows\\CurrentVersion\\Run", - &runapps) != ERROR_SUCCESS) { - MessageBox(NULL, "WARNING: Unable to install the ServiceHelper hook\nGlobal user-specific registry settings will not be loaded", - szAppName, MB_ICONEXCLAMATION | MB_OK); - } else { - char servicehelpercmd[pathlength]; - - // Append the service-helper-start flag to the end of the path: - if ((int)strlen(path) + 4 + (int)strlen(BaculaRunServiceHelper) < pathlength) { - sprintf(servicehelpercmd, "\"%s\" %s", path, BaculaRunServiceHelper); - - // Add the Bacula Service Helper entry - if (RegSetValueEx(runapps, szAppName, 0, REG_SZ, - (unsigned char *)servicehelpercmd, strlen(servicehelpercmd)+1) != ERROR_SUCCESS) { - MessageBox(NULL, "WARNING:Unable to install the ServiceHelper hook\nGlobal user-specific registry settings will not be loaded", szAppName, MB_ICONEXCLAMATION | MB_OK); - } - RegCloseKey(runapps); - } - } -#endif - // Everything went fine MessageBox(NULL, _("The Bacula File service was successfully installed.\n" @@ -548,19 +522,6 @@ bacService::RemoveService() SC_HANDLE hservice; SC_HANDLE hsrvmanager; -#ifdef xxx_needed - // Attempt to remove the service-helper hook - HKEY runapps; - if (RegOpenKey(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows\\CurrentVersion\\Run", - &runapps) == ERROR_SUCCESS) { - // Attempt to delete the Bacula key - if (RegDeleteValue(runapps, szAppName) != ERROR_SUCCESS) { - MessageBox(NULL, "WARNING:The ServiceHelper hook entry could not be removed from the registry", szAppName, MB_ICONEXCLAMATION | MB_OK); - } - RegCloseKey(runapps); - } -#endif - // Open the SCM hsrvmanager = OpenSCManager( NULL, // machine (NULL == local) diff --git a/bacula/src/gnome2-console/console.c b/bacula/src/gnome2-console/console.c index 4116569ee8..38fc765ac9 100644 --- a/bacula/src/gnome2-console/console.c +++ b/bacula/src/gnome2-console/console.c @@ -48,8 +48,8 @@ GtkWidget *restore_file_selection; GtkWidget *dir_select; GtkWidget *about1; /* about box */ GtkWidget *label_dialog; -GdkFont *text_font = NULL; PangoFontDescription *font_desc; +PangoFontDescription *console_font_desc = NULL; pthread_mutex_t cmd_mutex = PTHREAD_MUTEX_INITIALIZER; pthread_cond_t cmd_wait; char cmd[1000]; @@ -292,12 +292,7 @@ int main(int argc, char *argv[]) gtk_widget_show(console); /* - * Thanks to Phil Stracchino for providing the font configuration code. - * original default: - text_font = gdk_font_load("-misc-fixed-medium-r-normal-*-*-130-*-*-c-*-koi8-r"); - * this works for me: - text_font = gdk_font_load("-Bigelow & Holmes-lucida console-medium-r-semi condensed-*-12-0-100-100-m-0-iso8859-1"); - * and, new automagic:font specification! + * Gtk2/pango have different font names. Gnome2 comes with "Monospace 10" */ LockRes(); @@ -306,8 +301,9 @@ int main(int argc, char *argv[]) Dmsg1(400, "No fontface for %s\n", con_font->hdr.name); continue; } - text_font = gdk_font_load(con_font->fontface); - if (text_font == NULL) { + Dmsg1(100, "Now loading: %s\n",con_font->fontface); + console_font_desc = pango_font_description_from_string(con_font->fontface); + if (console_font_desc == NULL) { Dmsg2(400, "Load of requested ConsoleFont \"%s\" (%s) failed!\n", con_font->hdr.name, con_font->fontface); } else { @@ -318,16 +314,16 @@ int main(int argc, char *argv[]) } UnlockRes(); - if (text_font == NULL) { - Dmsg1(400, "Attempting to load fallback font %s\n", - "-misc-fixed-medium-r-normal-*-*-130-*-*-c-*-iso8859-1"); - text_font = gdk_font_load("-misc-fixed-medium-r-normal-*-*-130-*-*-c-*-iso8859-1"); - } font_desc = pango_font_description_from_string("LucidaTypewriter 9"); gtk_widget_modify_font(console, font_desc); - gtk_widget_modify_font(text1, font_desc); gtk_widget_modify_font(entry1, font_desc); gtk_widget_modify_font(status1, font_desc); + if (console_font_desc) { + gtk_widget_modify_font(text1, console_font_desc); + pango_font_description_free(console_font_desc); + } else { + gtk_widget_modify_font(text1, font_desc); + } pango_font_description_free(font_desc); if (test_config) { diff --git a/bacula/src/gnome2-console/gnome-console.conf.in b/bacula/src/gnome2-console/gnome-console.conf.in index 8ca3533b3d..9c3731d433 100644 --- a/bacula/src/gnome2-console/gnome-console.conf.in +++ b/bacula/src/gnome2-console/gnome-console.conf.in @@ -11,5 +11,5 @@ Director { ConsoleFont { Name = Default - Font = "-misc-fixed-medium-r-normal-*-*-130-*-*-c-*-iso8859-1" + Font = "LucidaTypewriter 9" } diff --git a/bacula/src/jcr.h b/bacula/src/jcr.h index 8ee90ca56f..4bd623ea72 100644 --- a/bacula/src/jcr.h +++ b/bacula/src/jcr.h @@ -45,12 +45,12 @@ #define JT_BACKUP 'B' /* Backup Job */ #define JT_VERIFY 'V' /* Verify Job */ #define JT_RESTORE 'R' /* Restore Job */ -#define JT_CONSOLE 'C' /* console program */ +#define JT_CONSOLE 'c' /* console program */ #define JT_SYSTEM 'I' /* internal system "job" */ #define JT_ADMIN 'D' /* admin job */ #define JT_ARCHIVE 'A' /* Archive Job */ -#define JT_COPY 'Y' /* Copy Job */ -#define JT_MIGRATION 'M' /* Migration Job */ +#define JT_COPY 'C' /* Copy Job */ +#define JT_MIGRATE 'M' /* Migration Job */ #define JT_SCAN 'S' /* Scan Job */ /* Job Status. Some of these are stored in the DB */ @@ -239,6 +239,7 @@ public: JCR *prev_dev; /* previous JCR attached to device */ pthread_cond_t job_start_wait; /* Wait for FD to start Job */ int type; + DCR *read_dcr; /* device context for reading */ DCR *dcr; /* device context record */ alist *dcrs; /* list of dcrs open */ POOLMEM *job_name; /* base Job name (not unique) */ diff --git a/bacula/src/lib/bnet.c b/bacula/src/lib/bnet.c index 3f850d1d05..74e198220d 100644 --- a/bacula/src/lib/bnet.c +++ b/bacula/src/lib/bnet.c @@ -394,8 +394,9 @@ bool bnet_send(BSOCK * bsock) } } else { Qmsg5(bsock->jcr, M_ERROR, 0, - _("Wrote %d bytes to %s:%s:%d, but only %d accepted.\n"), bsock->who, - bsock->host, bsock->port, bsock->msglen, rc); + _("Wrote %d bytes to %s:%s:%d, but only %d accepted.\n"), + sizeof(int32_t), bsock->who, + bsock->host, bsock->port, rc); } return false; } diff --git a/bacula/src/lib/jcr.c b/bacula/src/lib/jcr.c index fbb1356ac8..747ebc7fc9 100755 --- a/bacula/src/lib/jcr.c +++ b/bacula/src/lib/jcr.c @@ -17,7 +17,7 @@ * in the list while traversing it rather than a single lock * at the beginning of a traversal and one at the end. This * incurs slightly more overhead, but effectively eliminates - * the possibilty of race conditions. In addition, with the + * the possibilty of race conditions. In addition, with the * exception of the global locking of the list during the * re-reading of the config file, no recursion is needed. * @@ -61,7 +61,7 @@ int num_jobs_run; dlist *last_jobs = NULL; const int max_last_jobs = 10; -static dlist *jcrs = NULL; /* JCR chain */ +static dlist *jcrs = NULL; /* JCR chain */ static pthread_mutex_t jcr_lock = PTHREAD_MUTEX_INITIALIZER; static pthread_mutex_t job_start_mutex = PTHREAD_MUTEX_INITIALIZER; @@ -92,9 +92,9 @@ void term_last_jobs_list() { if (last_jobs) { while (!last_jobs->empty()) { - void *je = last_jobs->first(); - last_jobs->remove(je); - free(je); + void *je = last_jobs->first(); + last_jobs->remove(je); + free(je); } delete last_jobs; last_jobs = NULL; @@ -124,20 +124,20 @@ void read_last_jobs_list(int fd, uint64_t addr) for ( ; num; num--) { if (read(fd, &job, sizeof(job)) != sizeof(job)) { Dmsg1(000, "Read job entry. ERR=%s\n", strerror(errno)); - return; + return; } if (job.JobId > 0) { - je = (struct s_last_job *)malloc(sizeof(struct s_last_job)); - memcpy((char *)je, (char *)&job, sizeof(job)); - if (!last_jobs) { - init_last_jobs_list(); - } - last_jobs->append(je); - if (last_jobs->size() > max_last_jobs) { - je = (struct s_last_job *)last_jobs->first(); - last_jobs->remove(je); - free(je); - } + je = (struct s_last_job *)malloc(sizeof(struct s_last_job)); + memcpy((char *)je, (char *)&job, sizeof(job)); + if (!last_jobs) { + init_last_jobs_list(); + } + last_jobs->append(je); + if (last_jobs->size() > max_last_jobs) { + je = (struct s_last_job *)last_jobs->first(); + last_jobs->remove(je); + free(je); + } } } } @@ -156,13 +156,13 @@ uint64_t write_last_jobs_list(int fd, uint64_t addr) num = last_jobs->size(); if (write(fd, &num, sizeof(num)) != sizeof(num)) { Dmsg1(000, "Error writing num_items: ERR=%s\n", strerror(errno)); - return 0; + return 0; } foreach_dlist(je, last_jobs) { - if (write(fd, je, sizeof(struct s_last_job)) != sizeof(struct s_last_job)) { + if (write(fd, je, sizeof(struct s_last_job)) != sizeof(struct s_last_job)) { Dmsg1(000, "Error writing job: ERR=%s\n", strerror(errno)); - return 0; - } + return 0; + } } } /* Return current address */ @@ -237,7 +237,7 @@ JCR *new_jcr(int size, JCR_free_HANDLER *daemon_free_jcr) /* Setup some dummy values */ bstrncpy(jcr->Job, "*System*", sizeof(jcr->Job)); jcr->JobId = 0; - jcr->JobType = JT_SYSTEM; /* internal job until defined */ + jcr->JobType = JT_SYSTEM; /* internal job until defined */ jcr->JobLevel = L_NONE; jcr->JobStatus = JS_Created; @@ -268,7 +268,7 @@ JCR *new_jcr(int size, JCR_free_HANDLER *daemon_free_jcr) /* * Remove a JCR from the chain * NOTE! The chain must be locked prior to calling - * this routine. + * this routine. */ static void remove_jcr(JCR *jcr) { @@ -293,6 +293,8 @@ static void free_common_jcr(JCR *jcr) case JT_BACKUP: case JT_VERIFY: case JT_RESTORE: + case JT_MIGRATE: + case JT_COPY: case JT_ADMIN: num_jobs_run++; last_job.Errors = jcr->Errors; @@ -309,17 +311,17 @@ static void free_common_jcr(JCR *jcr) last_job.end_time = time(NULL); /* Keep list of last jobs, but not Console where JobId==0 */ if (last_job.JobId > 0) { - je = (struct s_last_job *)malloc(sizeof(struct s_last_job)); - memcpy((char *)je, (char *)&last_job, sizeof(last_job)); - if (!last_jobs) { - init_last_jobs_list(); - } - last_jobs->append(je); - if (last_jobs->size() > max_last_jobs) { - je = (struct s_last_job *)last_jobs->first(); - last_jobs->remove(je); - free(je); - } + je = (struct s_last_job *)malloc(sizeof(struct s_last_job)); + memcpy((char *)je, (char *)&last_job, sizeof(last_job)); + if (!last_jobs) { + init_last_jobs_list(); + } + last_jobs->append(je); + if (last_jobs->size() > max_last_jobs) { + je = (struct s_last_job *)last_jobs->first(); + last_jobs->remove(je); + free(je); + } } break; default: @@ -328,7 +330,7 @@ static void free_common_jcr(JCR *jcr) pthread_mutex_destroy(&jcr->mutex); delete jcr->msg_queue; - close_msg(jcr); /* close messages for this job */ + close_msg(jcr); /* close messages for this job */ /* do this after closing messages */ if (jcr->client_name) { @@ -391,29 +393,29 @@ void free_jcr(JCR *jcr) dequeue_messages(jcr); lock_jcr_chain(); - jcr->dec_use_count(); /* decrement use count */ + jcr->dec_use_count(); /* decrement use count */ if (jcr->use_count < 0) { Emsg2(M_ERROR, 0, _("JCR use_count=%d JobId=%d\n"), - jcr->use_count, jcr->JobId); + jcr->use_count, jcr->JobId); } Dmsg3(3400, "Dec free_jcr 0x%x use_count=%d jobid=%d\n", jcr, jcr->use_count, jcr->JobId); - if (jcr->use_count > 0) { /* if in use */ + if (jcr->use_count > 0) { /* if in use */ unlock_jcr_chain(); Dmsg2(3400, "free_jcr 0x%x use_count=%d\n", jcr, jcr->use_count); return; } - remove_jcr(jcr); /* remove Jcr from chain */ + remove_jcr(jcr); /* remove Jcr from chain */ unlock_jcr_chain(); - job_end_pop(jcr); /* pop and call hooked routines */ + job_end_pop(jcr); /* pop and call hooked routines */ Dmsg1(3400, "End job=%d\n", jcr->JobId); if (jcr->daemon_free_jcr) { jcr->daemon_free_jcr(jcr); /* call daemon free routine */ } free_common_jcr(jcr); - close_msg(NULL); /* flush any daemon messages */ + close_msg(NULL); /* flush any daemon messages */ Dmsg0(3400, "Exit free_jcr\n"); } @@ -421,18 +423,18 @@ void free_jcr(JCR *jcr) /* * Given a JobId, find the JCR * Returns: jcr on success - * NULL on failure + * NULL on failure */ JCR *get_jcr_by_id(uint32_t JobId) { JCR *jcr; - lock_jcr_chain(); /* lock chain */ + lock_jcr_chain(); /* lock chain */ foreach_dlist(jcr, jcrs) { if (jcr->JobId == JobId) { - jcr->inc_use_count(); + jcr->inc_use_count(); Dmsg2(3400, "Inc get_jcr 0x%x use_count=%d\n", jcr, jcr->use_count); - break; + break; } } unlock_jcr_chain(); @@ -442,7 +444,7 @@ JCR *get_jcr_by_id(uint32_t JobId) /* * Given a SessionId and SessionTime, find the JCR * Returns: jcr on success - * NULL on failure + * NULL on failure */ JCR *get_jcr_by_session(uint32_t SessionId, uint32_t SessionTime) { @@ -451,10 +453,10 @@ JCR *get_jcr_by_session(uint32_t SessionId, uint32_t SessionTime) lock_jcr_chain(); foreach_dlist(jcr, jcrs) { if (jcr->VolSessionId == SessionId && - jcr->VolSessionTime == SessionTime) { - jcr->inc_use_count(); + jcr->VolSessionTime == SessionTime) { + jcr->inc_use_count(); Dmsg2(3400, "Inc get_jcr 0x%x use_count=%d\n", jcr, jcr->use_count); - break; + break; } } unlock_jcr_chain(); @@ -467,7 +469,7 @@ JCR *get_jcr_by_session(uint32_t SessionId, uint32_t SessionTime) * compares on the number of characters in Job * thus allowing partial matches. * Returns: jcr on success - * NULL on failure + * NULL on failure */ JCR *get_jcr_by_partial_name(char *Job) { @@ -481,9 +483,9 @@ JCR *get_jcr_by_partial_name(char *Job) len = strlen(Job); foreach_dlist(jcr, jcrs) { if (strncmp(Job, jcr->Job, len) == 0) { - jcr->inc_use_count(); + jcr->inc_use_count(); Dmsg2(3400, "Inc get_jcr 0x%x use_count=%d\n", jcr, jcr->use_count); - break; + break; } } unlock_jcr_chain(); @@ -495,7 +497,7 @@ JCR *get_jcr_by_partial_name(char *Job) * Given a Job, find the JCR * requires an exact match of names. * Returns: jcr on success - * NULL on failure + * NULL on failure */ JCR *get_jcr_by_full_name(char *Job) { @@ -507,9 +509,9 @@ JCR *get_jcr_by_full_name(char *Job) lock_jcr_chain(); foreach_dlist(jcr, jcrs) { if (strcmp(jcr->Job, Job) == 0) { - jcr->inc_use_count(); + jcr->inc_use_count(); Dmsg2(3400, "Inc get_jcr 0x%x use_count=%d\n", jcr, jcr->use_count); - break; + break; } } unlock_jcr_chain(); @@ -590,8 +592,8 @@ bool init_jcr_subsystem(void) watchdog_t *wd = new_watchdog(); wd->one_shot = false; - wd->interval = 30; /* FIXME: should be configurable somewhere, even - if only with a #define */ + wd->interval = 30; /* FIXME: should be configurable somewhere, even + if only with a #define */ wd->callback = jcr_timeout_check; register_watchdog(wd); @@ -612,44 +614,44 @@ static void jcr_timeout_check(watchdog_t *self) */ foreach_jcr(jcr) { if (jcr->JobId == 0) { - free_jcr(jcr); - continue; + free_jcr(jcr); + continue; } fd = jcr->store_bsock; if (fd) { - timer_start = fd->timer_start; - if (timer_start && (watchdog_time - timer_start) > fd->timeout) { - fd->timer_start = 0; /* turn off timer */ - fd->timed_out = TRUE; - Jmsg(jcr, M_ERROR, 0, _( + timer_start = fd->timer_start; + if (timer_start && (watchdog_time - timer_start) > fd->timeout) { + fd->timer_start = 0; /* turn off timer */ + fd->timed_out = TRUE; + Jmsg(jcr, M_ERROR, 0, _( "Watchdog sending kill after %d secs to thread stalled reading Storage daemon.\n"), - watchdog_time - timer_start); - pthread_kill(jcr->my_thread_id, TIMEOUT_SIGNAL); - } + watchdog_time - timer_start); + pthread_kill(jcr->my_thread_id, TIMEOUT_SIGNAL); + } } fd = jcr->file_bsock; if (fd) { - timer_start = fd->timer_start; - if (timer_start && (watchdog_time - timer_start) > fd->timeout) { - fd->timer_start = 0; /* turn off timer */ - fd->timed_out = TRUE; - Jmsg(jcr, M_ERROR, 0, _( + timer_start = fd->timer_start; + if (timer_start && (watchdog_time - timer_start) > fd->timeout) { + fd->timer_start = 0; /* turn off timer */ + fd->timed_out = TRUE; + Jmsg(jcr, M_ERROR, 0, _( "Watchdog sending kill after %d secs to thread stalled reading File daemon.\n"), - watchdog_time - timer_start); - pthread_kill(jcr->my_thread_id, TIMEOUT_SIGNAL); - } + watchdog_time - timer_start); + pthread_kill(jcr->my_thread_id, TIMEOUT_SIGNAL); + } } fd = jcr->dir_bsock; if (fd) { - timer_start = fd->timer_start; - if (timer_start && (watchdog_time - timer_start) > fd->timeout) { - fd->timer_start = 0; /* turn off timer */ - fd->timed_out = TRUE; - Jmsg(jcr, M_ERROR, 0, _( + timer_start = fd->timer_start; + if (timer_start && (watchdog_time - timer_start) > fd->timeout) { + fd->timer_start = 0; /* turn off timer */ + fd->timed_out = TRUE; + Jmsg(jcr, M_ERROR, 0, _( "Watchdog sending kill after %d secs to thread stalled reading Director.\n"), - watchdog_time - timer_start); - pthread_kill(jcr->my_thread_id, TIMEOUT_SIGNAL); - } + watchdog_time - timer_start); + pthread_kill(jcr->my_thread_id, TIMEOUT_SIGNAL); + } } free_jcr(jcr); } @@ -662,5 +664,5 @@ static void jcr_timeout_check(watchdog_t *self) */ extern "C" void timeout_handler(int sig) { - return; /* thus interrupting the function */ + return; /* thus interrupting the function */ } diff --git a/bacula/src/lib/scan.c b/bacula/src/lib/scan.c index 3bdc3526fb..cfb5751300 100644 --- a/bacula/src/lib/scan.c +++ b/bacula/src/lib/scan.c @@ -406,6 +406,7 @@ switch_top: } else if (*buf++ != *fmt++) { // Dmsg2(000, "Mismatch buf=%c fmt=%c\n", *--buf, *--fmt); error = true; + break; } } va_end(ap); diff --git a/bacula/src/lib/signal.c b/bacula/src/lib/signal.c index 3b06e2f08a..fd55deeeee 100644 --- a/bacula/src/lib/signal.c +++ b/bacula/src/lib/signal.c @@ -245,7 +245,7 @@ void init_signals(void terminate(int sig)) sig_names[SIGWAITING] = _("No runnable lwp"); #endif #ifdef SIGLWP - sig_names[SIGLWP] = _("SIGLWP special signal used by thread library"); + sig_names[SIGLWP] = _("SIGLWP special signal used by thread library"); #endif #ifdef SIGFREEZE sig_names[SIGFREEZE] = _("Checkpoint Freeze"); diff --git a/bacula/src/lib/util.c b/bacula/src/lib/util.c index 1d53dc2e22..35cbb4a7e3 100644 --- a/bacula/src/lib/util.c +++ b/bacula/src/lib/util.c @@ -5,24 +5,18 @@ * * Version $Id$ */ - /* - Copyright (C) 2000-2004 Kern Sibbald and John Walker + 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 amended with additional clauses defined in the + file LICENSE in the main source directory. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 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. */ @@ -50,7 +44,7 @@ int is_buf_zero(char *buf, int len) len64 = len / sizeof(uint64_t); for (i=0; i < len64; i++) { if (ip[i] != 0) { - return 0; + return 0; } } done = len64 * sizeof(uint64_t); /* bytes already checked */ @@ -58,7 +52,7 @@ int is_buf_zero(char *buf, int len) rem = len - done; for (i = 0; i < rem; i++) { if (p[i] != 0) { - return 0; + return 0; } } return 1; @@ -70,7 +64,7 @@ void lcase(char *str) { while (*str) { if (B_ISUPPER(*str)) - *str = tolower((int)(*str)); + *str = tolower((int)(*str)); str++; } } @@ -83,7 +77,7 @@ bash_spaces(char *str) { while (*str) { if (*str == ' ') - *str = 0x1; + *str = 0x1; str++; } } @@ -97,7 +91,7 @@ bash_spaces(POOL_MEM &pm) char *str = pm.c_str(); while (*str) { if (*str == ' ') - *str = 0x1; + *str = 0x1; str++; } } @@ -142,10 +136,10 @@ char *encode_time(time_t time, char *buf) #if HAVE_WIN32 && !HAVE_CONSOLE && !HAVE_WXCONSOLE /* * Gross kludge to avoid a seg fault in Microsoft's CRT localtime_r(), - * which incorrectly references a NULL returned from gmtime() if - * the time (adjusted for the current timezone) is invalid. - * This could happen if you have a bad date/time, or perhaps if you - * moved a file from one timezone to another? + * which incorrectly references a NULL returned from gmtime() if + * the time (adjusted for the current timezone) is invalid. + * This could happen if you have a bad date/time, or perhaps if you + * moved a file from one timezone to another? */ struct tm *gtm; time_t gtime; @@ -157,14 +151,14 @@ char *encode_time(time_t time, char *buf) if (_daylight && _isindst(gtm)) { gtime -= _dstbias; if (!gmtime(>ime)) { - return buf; + return buf; } } #endif if (localtime_r(&time, &tm)) { n = sprintf(buf, "%04d-%02d-%02d %02d:%02d:%02d", - tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, - tm.tm_hour, tm.tm_min, tm.tm_sec); + tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, + tm.tm_hour, tm.tm_min, tm.tm_sec); } return buf+n; } @@ -238,7 +232,7 @@ void jobstatus_to_ascii(int JobStatus, char *msg, int maxlen) default: if (JobStatus == 0) { - buf[0] = 0; + buf[0] = 0; } else { bsnprintf(buf, sizeof(buf), _("Unknown Job termination status=%d"), JobStatus); } @@ -300,6 +294,12 @@ const char *job_type_to_str(int type) case JT_ADMIN: str = _("Admin"); break; + case JT_MIGRATE: + str = _("Migrate"); + break; + case JT_COPY: + str = _("Copy"); + break; default: str = _("Unknown Type"); break; @@ -399,8 +399,8 @@ int do_shell_expansion(char *name, int name_len) len = strlen(meta); for (i = 0; i < len; i++) { if (strchr(name, meta[i])) { - found = true; - break; + found = true; + break; } } if (found) { @@ -415,27 +415,27 @@ int do_shell_expansion(char *name, int name_len) pm_strcat(&cmd, "\""); Dmsg1(400, "Send: %s\n", cmd); if ((bpipe = open_bpipe(cmd, 0, "r"))) { - *line = 0; - fgets(line, sizeof(line), bpipe->rfd); - strip_trailing_junk(line); - stat = close_bpipe(bpipe); + *line = 0; + fgets(line, sizeof(line), bpipe->rfd); + strip_trailing_junk(line); + stat = close_bpipe(bpipe); Dmsg2(400, "stat=%d got: %s\n", stat, line); } else { - stat = 1; /* error */ + stat = 1; /* error */ } free_pool_memory(cmd); if (stat == 0) { - bstrncpy(name, line, name_len); + bstrncpy(name, line, name_len); } } return 1; } -/* MAKESESSIONKEY -- Generate session key with optional start - key. If mode is TRUE, the key will be - translated to a string, otherwise it is - returned as 16 binary bytes. +/* MAKESESSIONKEY -- Generate session key with optional start + key. If mode is TRUE, the key will be + translated to a string, otherwise it is + returned as 16 binary bytes. from SpeakFreely by John Walker */ @@ -448,15 +448,15 @@ void make_session_key(char *key, char *seed, int mode) s[0] = 0; if (seed != NULL) { - bstrncat(s, seed, sizeof(s)); + bstrncat(s, seed, sizeof(s)); } /* The following creates a seed for the session key generator - based on a collection of volatile and environment-specific - information unlikely to be vulnerable (as a whole) to an + based on a collection of volatile and environment-specific + information unlikely to be vulnerable (as a whole) to an exhaustive search attack. If one of these items isn't - available on your machine, replace it with something - equivalent or, if you like, just delete it. */ + available on your machine, replace it with something + equivalent or, if you like, just delete it. */ sprintf(s + strlen(s), "%lu", (unsigned long)getpid()); sprintf(s + strlen(s), "%lu", (unsigned long)getppid()); @@ -481,22 +481,22 @@ void make_session_key(char *key, char *seed, int mode) MD5Final(md5key1, &md5c); #define nextrand (md5key[j] ^ md5key1[j]) if (mode) { - for (j = k = 0; j < 16; j++) { - unsigned char rb = nextrand; + for (j = k = 0; j < 16; j++) { + unsigned char rb = nextrand; #define Rad16(x) ((x) + 'A') - key[k++] = Rad16((rb >> 4) & 0xF); - key[k++] = Rad16(rb & 0xF); + key[k++] = Rad16((rb >> 4) & 0xF); + key[k++] = Rad16(rb & 0xF); #undef Rad16 - if (j & 1) { + if (j & 1) { key[k++] = '-'; - } - } - key[--k] = 0; + } + } + key[--k] = 0; } else { - for (j = 0; j < 16; j++) { - key[j] = nextrand; - } + for (j = 0; j < 16; j++) { + key[j] = nextrand; + } } } #undef nextrand @@ -535,102 +535,102 @@ POOLMEM *edit_job_codes(JCR *jcr, char *omsg, char *imsg, const char *to) Dmsg1(200, "edit_job_codes: %s\n", imsg); for (p=imsg; *p; p++) { if (*p == '%') { - switch (*++p) { + switch (*++p) { case '%': str = "%"; - break; + break; case 'c': - if (jcr) { - str = jcr->client_name; - } else { + if (jcr) { + str = jcr->client_name; + } else { str = _("*none*"); - } - break; + } + break; case 'd': str = my_name; /* Director's name */ - break; + break; case 'e': - if (jcr) { - str = job_status_to_str(jcr->JobStatus); - } else { + if (jcr) { + str = job_status_to_str(jcr->JobStatus); + } else { str = _("*none*"); - } - break; + } + break; case 'i': - if (jcr) { + if (jcr) { bsnprintf(add, sizeof(add), "%d", jcr->JobId); - str = add; - } else { + str = add; + } else { str = _("*none*"); - } - break; + } + break; case 'j': /* Job name */ - if (jcr) { - str = jcr->Job; - } else { + if (jcr) { + str = jcr->Job; + } else { str = _("*none*"); - } - break; + } + break; case 'l': - if (jcr) { - str = job_level_to_str(jcr->JobLevel); - } else { + if (jcr) { + str = job_level_to_str(jcr->JobLevel); + } else { str = _("*none*"); - } - break; + } + break; case 'n': - if (jcr) { - bstrncpy(name, jcr->Job, sizeof(name)); - /* There are three periods after the Job name */ - for (i=0; i<3; i++) { + if (jcr) { + bstrncpy(name, jcr->Job, sizeof(name)); + /* There are three periods after the Job name */ + for (i=0; i<3; i++) { if ((q=strrchr(name, '.')) != NULL) { - *q = 0; - } - } - str = name; - } else { + *q = 0; + } + } + str = name; + } else { str = _("*none*"); - } - break; + } + break; case 'r': - str = to; - break; + str = to; + break; case 's': /* since time */ - if (jcr && jcr->stime) { - str = jcr->stime; - } else { + if (jcr && jcr->stime) { + str = jcr->stime; + } else { str = _("*none*"); - } - break; + } + break; case 't': - if (jcr) { - str = job_type_to_str(jcr->JobType); - } else { + if (jcr) { + str = job_type_to_str(jcr->JobType); + } else { str = _("*none*"); - } - break; + } + break; case 'v': - if (jcr) { - if (jcr->VolumeName && jcr->VolumeName[0]) { - str = jcr->VolumeName; - } else { + if (jcr) { + if (jcr->VolumeName && jcr->VolumeName[0]) { + str = jcr->VolumeName; + } else { str = ""; - } - } else { + } + } else { str = _("*none*"); - } - break; - default: + } + break; + default: add[0] = '%'; - add[1] = *p; - add[2] = 0; - str = add; - break; - } + add[1] = *p; + add[2] = 0; + str = add; + break; + } } else { - add[0] = *p; - add[1] = 0; - str = add; + add[0] = *p; + add[1] = 0; + str = add; } Dmsg1(1200, "add_str %s\n", str); pm_strcat(&omsg, str); @@ -648,11 +648,11 @@ void set_working_directory(char *wd) } if (stat(wd, &stat_buf) != 0) { Emsg1(M_ERROR_TERM, 0, _("Working Directory: \"%s\" not found. Cannot continue.\n"), - wd); + wd); } if (!S_ISDIR(stat_buf.st_mode)) { Emsg1(M_ERROR_TERM, 0, _("Working Directory: \"%s\" is not a directory. Cannot continue.\n"), - wd); + wd); } - working_directory = wd; /* set global */ + working_directory = wd; /* set global */ } diff --git a/bacula/src/stored/acquire.c b/bacula/src/stored/acquire.c index 8c2d9e80cf..e0ce9c5be3 100644 --- a/bacula/src/stored/acquire.c +++ b/bacula/src/stored/acquire.c @@ -29,16 +29,10 @@ */ DCR *new_dcr(JCR *jcr, DEVICE *dev) { - if (jcr && jcr->dcr) { - return jcr->dcr; - } DCR *dcr = (DCR *)malloc(sizeof(DCR)); memset(dcr, 0, sizeof(DCR)); dcr->jcr = jcr; if (dev) { - if (jcr) { - jcr->dcr = dcr; - } dcr->dev = dev; dcr->device = dev->device; dcr->block = new_block(dev); @@ -275,7 +269,6 @@ default_path: get_out: dev->unblock(); if (!vol_ok) { - free_dcr(dcr); dcr = NULL; } return dcr; @@ -423,6 +416,7 @@ bool release_device(DCR *dcr) JCR *jcr = dcr->jcr; DEVICE *dev = dcr->dev; bool ok = true; + bool was_reading = false; lock_device(dev); Dmsg1(100, "release_device device is %s\n", dev->is_tape()?"tape":"disk"); @@ -436,6 +430,7 @@ bool release_device(DCR *dcr) if (dev->can_read()) { dev->clear_read(); /* clear read bit */ + was_reading = true; /******FIXME**** send read volume usage statistics to director */ @@ -510,7 +505,11 @@ bool release_device(DCR *dcr) } unlock_device(dev); free_dcr(dcr); - jcr->dcr = NULL; + if (was_reading) { + jcr->read_dcr = NULL; + } else { + jcr->dcr = NULL; + } pthread_cond_broadcast(&wait_device_release); return ok; } diff --git a/bacula/src/stored/askdir.c b/bacula/src/stored/askdir.c index b9f4340b6c..248a2116ab 100644 --- a/bacula/src/stored/askdir.c +++ b/bacula/src/stored/askdir.c @@ -503,7 +503,7 @@ bool dir_ask_sysop_to_create_appendable_volume(DCR *dcr) Jmsg(jcr, M_WARNING, 0, _("pthread error in mount_next_volume stat=%d ERR=%s\n"), stat, be.strerror(stat)); } - Dmsg1(000, "Someone woke me for device %s\n", dev->print_name()); + Dmsg1(100, "Someone woke me for device %s\n", dev->print_name()); /* If no VolumeName, and cannot get one, try again */ P(dev->mutex); @@ -531,7 +531,7 @@ bool dir_ask_sysop_to_create_appendable_volume(DCR *dcr) } set_jcr_job_status(jcr, JS_Running); dir_send_job_status(jcr); - Dmsg0(000, "leave dir_ask_sysop_to_mount_create_appendable_volume\n"); + Dmsg0(100, "leave dir_ask_sysop_to_mount_create_appendable_volume\n"); return true; } diff --git a/bacula/src/stored/autochanger.c b/bacula/src/stored/autochanger.c index 63c2feea35..805aa2e871 100644 --- a/bacula/src/stored/autochanger.c +++ b/bacula/src/stored/autochanger.c @@ -37,7 +37,6 @@ bool init_autochangers() /* Ensure that the media_type for each device is the same */ foreach_res(changer, R_AUTOCHANGER) { DEVRES *device; - char *media_type = NULL; foreach_alist(device, changer->device) { /* * If the device does not have a changer name or changer command @@ -62,6 +61,7 @@ bool init_autochangers() OK = false; } +#ifdef xxx_needed if (media_type == NULL) { media_type = device->media_type; /* get Media Type of first device */ continue; @@ -74,6 +74,7 @@ bool init_autochangers() OK = false; continue; } +#endif } } return OK; diff --git a/bacula/src/stored/bextract.c b/bacula/src/stored/bextract.c index 92fcbd7618..addb74bbdc 100644 --- a/bacula/src/stored/bextract.c +++ b/bacula/src/stored/bextract.c @@ -214,11 +214,11 @@ static void do_extract(char *devname) if (!jcr) { exit(1); } - dev = jcr->dcr->dev; + dev = jcr->read_dcr->dev; if (!dev) { exit(1); } - dcr = jcr->dcr; + dcr = jcr->read_dcr; /* Make sure where directory exists and that it is a directory */ if (stat(where, &statp) < 0) { diff --git a/bacula/src/stored/bscan.c b/bacula/src/stored/bscan.c index b46c66c273..bd9b310e92 100644 --- a/bacula/src/stored/bscan.c +++ b/bacula/src/stored/bscan.c @@ -259,7 +259,7 @@ int main (int argc, char *argv[]) if (!bjcr) { exit(1); } - dev = bjcr->dcr->dev; + dev = bjcr->read_dcr->dev; if (showProgress) { char ed1[50]; struct stat sb; @@ -356,7 +356,7 @@ static void do_scan() /* Detach bscan's jcr as we are not a real Job on the tape */ - read_records(bjcr->dcr, record_cb, bscan_mount_next_read_volume); + read_records(bjcr->read_dcr, record_cb, bscan_mount_next_read_volume); free_attr(attr); } @@ -499,7 +499,7 @@ static bool record_cb(DCR *dcr, DEV_RECORD *rec) /* process label, if Job record exists don't update db */ mjcr = create_job_record(db, &jr, &label, rec); - dcr = mjcr->dcr; + dcr = mjcr->read_dcr; update_db = save_update_db; jr.PoolId = pr.PoolId; @@ -571,7 +571,7 @@ static bool record_cb(DCR *dcr, DEV_RECORD *rec) /* Create JobMedia record */ create_jobmedia_record(db, mjcr); - dev->attached_dcrs->remove(mjcr->dcr); + dev->attached_dcrs->remove(mjcr->read_dcr); free_jcr(mjcr); break; @@ -603,7 +603,7 @@ static bool record_cb(DCR *dcr, DEV_RECORD *rec) if (!db_update_job_end_record(bjcr, db, &jr)) { Pmsg1(0, _("Could not update job record. ERR=%s\n"), db_strerror(db)); } - mjcr->dcr = NULL; + mjcr->read_dcr = NULL; free_jcr(mjcr); } } @@ -631,7 +631,7 @@ static bool record_cb(DCR *dcr, DEV_RECORD *rec) } return true; } - dcr = mjcr->dcr; + dcr = mjcr->read_dcr; if (dcr->VolFirstIndex == 0) { dcr->VolFirstIndex = block->FirstIndex; } @@ -760,6 +760,10 @@ static void bscan_free_jcr(JCR *jcr) free_dcr(jcr->dcr); jcr->dcr = NULL; } + if (jcr->read_dcr) { + free_dcr(jcr->read_dcr); + jcr->read_dcr = NULL; + } Dmsg0(200, "End bscan free_jcr\n"); } @@ -771,7 +775,7 @@ static int create_file_attributes_record(B_DB *db, JCR *mjcr, char *fname, char *lname, int type, char *ap, DEV_RECORD *rec) { - DCR *dcr = mjcr->dcr; + DCR *dcr = mjcr->read_dcr; ar.fname = fname; ar.link = lname; ar.ClientId = mjcr->ClientId; @@ -1103,7 +1107,7 @@ static int update_job_record(B_DB *db, JOB_DBR *jr, SESSION_LABEL *elabel, static int create_jobmedia_record(B_DB *db, JCR *mjcr) { JOBMEDIA_DBR jmr; - DCR *dcr = mjcr->dcr; + DCR *dcr = mjcr->read_dcr; if (dev->is_tape()) { dcr->EndBlock = dev->EndBlock; @@ -1198,7 +1202,8 @@ static JCR *create_jcr(JOB_DBR *jr, DEV_RECORD *rec, uint32_t JobId) jobjcr->VolSessionId = rec->VolSessionId; jobjcr->VolSessionTime = rec->VolSessionTime; jobjcr->ClientId = jr->ClientId; - new_dcr(jobjcr, dev); + jobjcr->read_dcr = new_dcr(jobjcr, dev); + return jobjcr; } diff --git a/bacula/src/stored/butil.c b/bacula/src/stored/butil.c index 92923e03e6..7a8da3571c 100644 --- a/bacula/src/stored/butil.c +++ b/bacula/src/stored/butil.c @@ -171,11 +171,13 @@ static DCR *setup_to_access_device(JCR *jcr, char *dev_name, if (!acquire_device_for_read(dcr)) { return NULL; } + jcr->read_dcr = dcr; } else { if (!first_open_device(dcr)) { Jmsg1(jcr, M_FATAL, 0, _("Cannot open %s\n"), dev->print_name()); return NULL; } + jcr->dcr = dcr; /* write dcr */ } return dcr; } diff --git a/bacula/src/stored/device.c b/bacula/src/stored/device.c index 17d1803c1d..d516a6d0e7 100644 --- a/bacula/src/stored/device.c +++ b/bacula/src/stored/device.c @@ -136,8 +136,7 @@ bool fixup_device_block_write_error(DCR *dcr) /* * Walk through all attached jcrs indicating the volume has changed */ - Dmsg1(100, "Walk attached jcrs. Volume=%s\n", dev->VolCatInfo.VolCatName); -// for (JCR *mjcr=NULL; (mjcr=next_attached_jcr(dev, mjcr)); ) { + Dmsg1(100, "Walk attached dcrs. Volume=%s\n", dev->VolCatInfo.VolCatName); DCR *mdcr; foreach_dlist(mdcr, dev->attached_dcrs) { JCR *mjcr = mdcr->jcr; diff --git a/bacula/src/stored/dircmd.c b/bacula/src/stored/dircmd.c index 5a06eeba48..71c9bb959c 100644 --- a/bacula/src/stored/dircmd.c +++ b/bacula/src/stored/dircmd.c @@ -73,9 +73,9 @@ static bool mount_cmd(JCR *jcr); static bool unmount_cmd(JCR *jcr); static bool changer_cmd(JCR *sjcr); static bool do_label(JCR *jcr, int relabel); -static DEVICE *find_device(JCR *jcr, POOL_MEM &dev_name, int drive); +static DCR *find_device(JCR *jcr, POOL_MEM &dev_name, int drive); static void read_volume_label(JCR *jcr, DEVICE *dev, int Slot); -static void label_volume_if_ok(JCR *jcr, DEVICE *dev, char *oldname, +static void label_volume_if_ok(DCR *dcr, char *oldname, char *newname, char *poolname, int Slot, int relabel); static bool try_autoload_device(JCR *jcr, int slot, const char *VolName); @@ -276,6 +276,10 @@ static bool cancel_cmd(JCR *cjcr) pthread_cond_signal(&jcr->dcr->dev->wait_next_vol); pthread_cond_broadcast(&wait_device_release); } + if (jcr->read_dcr && jcr->read_dcr->dev && jcr->read_dcr->dev->waiting_for_mount()) { + pthread_cond_signal(&jcr->read_dcr->dev->wait_next_vol); + pthread_cond_broadcast(&wait_device_release); + } bnet_fsend(dir, _("3000 Job %s marked to be canceled.\n"), jcr->Job); free_jcr(jcr); } @@ -305,6 +309,7 @@ static bool do_label(JCR *jcr, int relabel) POOLMEM *newname, *oldname, *poolname, *mtype; POOL_MEM dev_name; BSOCK *dir = jcr->dir_bsock; + DCR *dcr; DEVICE *dev; bool ok = false; int slot; @@ -334,24 +339,27 @@ static bool do_label(JCR *jcr, int relabel) unbash_spaces(oldname); unbash_spaces(poolname); unbash_spaces(mtype); - dev = find_device(jcr, dev_name, drive); - if (dev) { + dcr = find_device(jcr, dev_name, drive); + if (dcr) { + dev = dcr->dev; P(dev->mutex); /* Use P to avoid indefinite block */ if (!dev->is_open()) { Dmsg0(400, "Can relabel. Device is not open\n"); - label_volume_if_ok(jcr, dev, oldname, newname, poolname, slot, relabel); + label_volume_if_ok(dcr, oldname, newname, poolname, slot, relabel); force_close_device(dev); /* Under certain "safe" conditions, we can steal the lock */ } else if (dev->can_steal_lock()) { Dmsg0(400, "Can relabel. can_steal_lock\n"); - label_volume_if_ok(jcr, dev, oldname, newname, poolname, slot, relabel); + label_volume_if_ok(dcr, oldname, newname, poolname, slot, relabel); } else if (dev->is_busy() || dev->is_blocked()) { send_dir_busy_message(dir, dev); } else { /* device not being used */ Dmsg0(400, "Can relabel. device not used\n"); - label_volume_if_ok(jcr, dev, oldname, newname, poolname, slot, relabel); + label_volume_if_ok(dcr, oldname, newname, poolname, slot, relabel); } V(dev->mutex); + free_dcr(dcr); + jcr->dcr = NULL; } else { bnet_fsend(dir, _("3999 Device \"%s\" not found or could not be opened.\n"), dev_name.c_str()); } @@ -374,21 +382,20 @@ static bool do_label(JCR *jcr, int relabel) * * Enter with the mutex set */ -static void label_volume_if_ok(JCR *jcr, DEVICE *dev, char *oldname, +static void label_volume_if_ok(DCR *dcr, char *oldname, char *newname, char *poolname, int slot, int relabel) { - BSOCK *dir = jcr->dir_bsock; + BSOCK *dir = dcr->jcr->dir_bsock; bsteal_lock_t hold; - DCR *dcr = jcr->dcr; + DEVICE *dev = dcr->dev; int label_status; - dcr->dev = dev; steal_device_lock(dev, &hold, BST_WRITING_LABEL); Dmsg1(100, "Stole device %s lock, writing label.\n", dev->print_name()); /* Note, try_autoload_device() opens the device */ - if (!try_autoload_device(jcr, slot, newname)) { + if (!try_autoload_device(dcr->jcr, slot, newname)) { goto bail_out; /* error */ } @@ -479,11 +486,16 @@ static bool read_label(DCR *dcr) return ok; } -static DEVICE *find_device(JCR *jcr, POOL_MEM &devname, int drive) +/* + * Searches for device by name, and if found, creates a dcr and + * returns it. + */ +static DCR *find_device(JCR *jcr, POOL_MEM &devname, int drive) { DEVRES *device; AUTOCHANGER *changer; bool found = false; + DCR *dcr = NULL; unbash_spaces(devname); foreach_res(device, R_DEVICE) { @@ -537,11 +549,11 @@ static DEVICE *find_device(JCR *jcr, POOL_MEM &devname, int drive) if (found) { Dmsg1(100, "Found changer device %s\n", device->hdr.name); - jcr->dcr = new_dcr(jcr, device->dev); - jcr->dcr->device = device; - return jcr->dcr->dev; + dcr = new_dcr(jcr, device->dev); + dcr->device = device; + jcr->dcr = dcr; } - return NULL; + return dcr; } @@ -557,9 +569,9 @@ static bool mount_cmd(JCR *jcr) int drive; if (sscanf(dir->msg, "mount %127s drive=%d", devname.c_str(), &drive) == 2) { - dev = find_device(jcr, devname, drive); - dcr = jcr->dcr; - if (dev) { + dcr = find_device(jcr, devname, drive); + if (dcr) { + dev = dcr->dev; P(dev->mutex); /* Use P to avoid indefinite block */ switch (dev->dev_blocked) { /* device blocked? */ case BST_WAITING_FOR_SYSOP: @@ -667,6 +679,8 @@ static bool mount_cmd(JCR *jcr) break; } V(dev->mutex); + free_dcr(dcr); + jcr->dcr = NULL; } else { bnet_fsend(dir, _("3999 Device \"%s\" not found or could not be opened.\n"), devname.c_str()); } @@ -686,11 +700,13 @@ static bool unmount_cmd(JCR *jcr) POOL_MEM devname; BSOCK *dir = jcr->dir_bsock; DEVICE *dev; + DCR *dcr; int drive; if (sscanf(dir->msg, "unmount %127s drive=%d", devname.c_str(), &drive) == 2) { - dev = find_device(jcr, devname, drive); - if (dev) { + dcr = find_device(jcr, devname, drive); + if (dcr) { + dev = dcr->dev; P(dev->mutex); /* Use P to avoid indefinite block */ if (!dev->is_open()) { if (!dev->is_busy()) { @@ -739,6 +755,8 @@ static bool unmount_cmd(JCR *jcr) dev->print_name()); } V(dev->mutex); + free_dcr(dcr); + jcr->dcr = NULL; } else { bnet_fsend(dir, _("3999 Device \"%s\" not found or could not be opened.\n"), devname.c_str()); } @@ -763,11 +781,13 @@ static bool release_cmd(JCR *jcr) POOL_MEM devname; BSOCK *dir = jcr->dir_bsock; DEVICE *dev; + DCR *dcr; int drive; if (sscanf(dir->msg, "release %127s drive=%d", devname.c_str(), &drive) == 2) { - dev = find_device(jcr, devname, drive); - if (dev) { + dcr = find_device(jcr, devname, drive); + if (dcr) { + dev = dcr->dev; P(dev->mutex); /* Use P to avoid indefinite block */ if (!dev->is_open()) { Dmsg0(90, "Device already released\n"); @@ -798,6 +818,8 @@ static bool release_cmd(JCR *jcr) dev->print_name()); } V(dev->mutex); + free_dcr(dcr); + jcr->dcr = NULL; } else { bnet_fsend(dir, _("3999 Device \"%s\" not found or could not be opened.\n"), devname.c_str()); } @@ -835,9 +857,9 @@ static bool changer_cmd(JCR *jcr) ok = true; } if (ok) { - dev = find_device(jcr, devname, -1); - dcr = jcr->dcr; - if (dev) { + dcr = find_device(jcr, devname, -1); + if (dcr) { + dev = dcr->dev; P(dev->mutex); /* Use P to avoid indefinite block */ if (!dev->is_tape()) { bnet_fsend(dir, _("3995 Device %s is not an autochanger.\n"), @@ -851,6 +873,8 @@ static bool changer_cmd(JCR *jcr) autochanger_cmd(dcr, dir, cmd); } V(dev->mutex); + free_dcr(dcr); + jcr->dcr = NULL; } else { bnet_fsend(dir, _("3999 Device \"%s\" not found or could not be opened.\n"), devname.c_str()); } @@ -871,13 +895,15 @@ static bool readlabel_cmd(JCR *jcr) POOL_MEM devname; BSOCK *dir = jcr->dir_bsock; DEVICE *dev; + DCR *dcr; int Slot; int drive; if (sscanf(dir->msg, "readlabel %127s Slot=%d drive=%d", devname.c_str(), &Slot, &drive) == 3) { - dev = find_device(jcr, devname, drive); - if (dev) { + dcr = find_device(jcr, devname, drive); + if (dcr) { + dev = dcr->dev; P(dev->mutex); /* Use P to avoid indefinite block */ if (!dev->is_open()) { read_volume_label(jcr, dev, Slot); @@ -891,6 +917,8 @@ static bool readlabel_cmd(JCR *jcr) read_volume_label(jcr, dev, Slot); } V(dev->mutex); + free_dcr(dcr); + jcr->dcr = NULL; } else { bnet_fsend(dir, _("3999 Device \"%s\" not found or could not be opened.\n"), devname.c_str()); } diff --git a/bacula/src/stored/fd_cmds.c b/bacula/src/stored/fd_cmds.c index 330ee30b9a..fbb609e085 100644 --- a/bacula/src/stored/fd_cmds.c +++ b/bacula/src/stored/fd_cmds.c @@ -284,7 +284,7 @@ static bool read_open_session(JCR *jcr) return false; } - if (sscanf(fd->msg, read_open, jcr->dcr->VolumeName, &jcr->read_VolSessionId, + if (sscanf(fd->msg, read_open, jcr->read_dcr->VolumeName, &jcr->read_VolSessionId, &jcr->read_VolSessionTime, &jcr->read_StartFile, &jcr->read_EndFile, &jcr->read_StartBlock, &jcr->read_EndBlock) == 7) { if (jcr->session_opened) { @@ -292,7 +292,7 @@ static bool read_open_session(JCR *jcr) return false; } Dmsg4(100, "read_open_session got: JobId=%d Vol=%s VolSessId=%ld VolSessT=%ld\n", - jcr->JobId, jcr->dcr->VolumeName, jcr->read_VolSessionId, + jcr->JobId, jcr->read_dcr->VolumeName, jcr->read_VolSessionId, jcr->read_VolSessionTime); Dmsg4(100, " StartF=%ld EndF=%ld StartB=%ld EndB=%ld\n", jcr->read_StartFile, jcr->read_EndFile, jcr->read_StartBlock, diff --git a/bacula/src/stored/job.c b/bacula/src/stored/job.c index 9eb1d6780c..5faac87ba3 100644 --- a/bacula/src/stored/job.c +++ b/bacula/src/stored/job.c @@ -137,7 +137,7 @@ bool run_cmd(JCR *jcr) Dmsg1(100, "Run_cmd: %s\n", jcr->dir_bsock->msg); /* The following jobs don't need the FD */ switch (jcr->JobType) { - case JT_MIGRATION: + case JT_MIGRATE: case JT_COPY: case JT_ARCHIVE: jcr->authenticated = true; @@ -346,5 +346,9 @@ void stored_free_jcr(JCR *jcr) free_dcr(jcr->dcr); jcr->dcr = NULL; } + if (jcr->read_dcr) { + free_dcr(jcr->read_dcr); + jcr->read_dcr = NULL; + } return; } diff --git a/bacula/src/stored/read.c b/bacula/src/stored/read.c index 6becec3377..2eb3518665 100644 --- a/bacula/src/stored/read.c +++ b/bacula/src/stored/read.c @@ -41,7 +41,7 @@ bool do_read_data(JCR *jcr) { BSOCK *fd = jcr->file_bsock; bool ok = true; - DCR *dcr = jcr->dcr; + DCR *dcr = jcr->read_dcr; Dmsg0(20, "Start read data.\n"); diff --git a/bacula/src/stored/reserve.c b/bacula/src/stored/reserve.c index ccd8527da6..55a903a3f1 100644 --- a/bacula/src/stored/reserve.c +++ b/bacula/src/stored/reserve.c @@ -450,7 +450,6 @@ bool find_suitable_device_for_job(JCR *jcr, RCTX &rctx) { bool first = true; bool ok; - DCR *dcr = NULL; DIRSTORE *store; char *device_name; @@ -496,9 +495,6 @@ bool find_suitable_device_for_job(JCR *jcr, RCTX &rctx) } #endif } - if (dcr) { - free_dcr(dcr); - } return ok; } @@ -539,10 +535,7 @@ static int search_res_for_device(RCTX &rctx) foreach_alist(rctx.device, changer->device) { Dmsg1(100, "Try changer device %s\n", rctx.device->hdr.name); stat = reserve_device(rctx); - if (stat == -1) { /* hard error */ - return -1; - } - if (stat == 0) { /* must wait, try next one */ + if (stat != 1) { /* try another device */ continue; } POOL_MEM dev_name; @@ -599,7 +592,6 @@ static int reserve_device(RCTX &rctx) Dmsg1(100, ">dird: %s", dir->msg); return -1; } - rctx.jcr->dcr = dcr; bstrncpy(dcr->pool_name, rctx.store->pool_name, name_len); bstrncpy(dcr->pool_type, rctx.store->pool_type, name_len); bstrncpy(dcr->media_type, rctx.store->media_type, name_len); @@ -617,12 +609,18 @@ static int reserve_device(RCTX &rctx) } } ok = reserve_device_for_append(dcr, rctx); + if (ok) { + rctx.jcr->dcr = dcr; + } Dmsg3(200, "dev_name=%s mediatype=%s ok=%d\n", dcr->dev_name, dcr->media_type, ok); } else { ok = reserve_device_for_read(dcr); + if (ok) { + rctx.jcr->read_dcr = dcr; + } } if (!ok) { - free_dcr(rctx.jcr->dcr); + free_dcr(dcr); return 0; } return 1; diff --git a/bacula/src/stored/spool.c b/bacula/src/stored/spool.c index c4fd2641ba..cd73dea27b 100644 --- a/bacula/src/stored/spool.c +++ b/bacula/src/stored/spool.c @@ -196,7 +196,8 @@ static bool despool_data(DCR *dcr, bool commit) Dmsg0(100, "Despooling data\n"); if (commit) { - Jmsg(jcr, M_INFO, 0, _("Committing spooled data to Volume. Despooling %s bytes ...\n"), + Jmsg(jcr, M_INFO, 0, _("Committing spooled data to Volume \"%s\". Despooling %s bytes ...\n"), + jcr->dcr->VolumeName, edit_uint64_with_commas(jcr->dcr->job_spool_size, ec1)); } else { diff --git a/bacula/src/stored/status.c b/bacula/src/stored/status.c index de80fd34b0..6be4e9a6cd 100644 --- a/bacula/src/stored/status.c +++ b/bacula/src/stored/status.c @@ -264,7 +264,7 @@ static void list_running_jobs(BSOCK *user) bool found = false; int bps, sec; JCR *jcr; - DCR *dcr; + DCR *dcr, *rdcr; char JobName[MAX_NAME_LENGTH]; char b1[30], b2[30], b3[30]; @@ -275,7 +275,8 @@ static void list_running_jobs(BSOCK *user) job_type_to_str(jcr->JobType), jcr->Job); } dcr = jcr->dcr; - if (dcr && dcr->device) { + rdcr = jcr->read_dcr; + if ((dcr && dcr->device) || rdcr && rdcr->device) { bstrncpy(JobName, jcr->Job, sizeof(JobName)); /* There are three periods after the Job name */ char *p; @@ -284,7 +285,20 @@ static void list_running_jobs(BSOCK *user) *p = 0; } } - bnet_fsend(user, _("%s %s job %s JobId=%d Volume=\"%s\"\n" + if (rdcr && rdcr->device) { + bnet_fsend(user, _("Reading: %s %s job %s JobId=%d Volume=\"%s\"\n" + " pool=\"%s\" device=\"%s\"\n"), + job_level_to_str(jcr->JobLevel), + job_type_to_str(jcr->JobType), + JobName, + jcr->JobId, + rdcr->VolumeName, + rdcr->pool_name, + rdcr->dev?rdcr->dev->print_name(): + rdcr->device->device_name); + } + if (dcr && dcr->device) { + bnet_fsend(user, _("Writing: %s %s job %s JobId=%d Volume=\"%s\"\n" " pool=\"%s\" device=\"%s\"\n"), job_level_to_str(jcr->JobLevel), job_type_to_str(jcr->JobType), @@ -294,6 +308,7 @@ static void list_running_jobs(BSOCK *user) dcr->pool_name, dcr->dev?dcr->dev->print_name(): dcr->device->device_name); + } sec = time(NULL) - jcr->run_time; if (sec <= 0) { sec = 1; diff --git a/bacula/src/stored/stored.c b/bacula/src/stored/stored.c index 11f31b2209..9b0ab92f4f 100644 --- a/bacula/src/stored/stored.c +++ b/bacula/src/stored/stored.c @@ -468,6 +468,7 @@ void *device_initialization(void *arg) Jmsg1(NULL, M_ERROR, 0, _("Could not open device %s\n"), dev->print_name()); Dmsg1(20, "Could not open device %s\n", dev->print_name()); free_dcr(dcr); + jcr->dcr = NULL; continue; } } @@ -482,6 +483,7 @@ void *device_initialization(void *arg) } } free_dcr(dcr); + jcr->dcr = NULL; } free_jcr(jcr); init_done = true; @@ -526,6 +528,10 @@ void terminate_stored(int sig) pthread_cond_broadcast(&jcr->dcr->dev->wait_next_vol); pthread_cond_broadcast(&wait_device_release); } + if (jcr->read_dcr && jcr->read_dcr->dev && jcr->read_dcr->dev->dev_blocked) { + pthread_cond_broadcast(&jcr->read_dcr->dev->wait_next_vol); + pthread_cond_broadcast(&wait_device_release); + } bmicrosleep(0, 50000); } free_jcr(jcr); diff --git a/bacula/src/version.h b/bacula/src/version.h index c308c8273e..4058a040e2 100644 --- a/bacula/src/version.h +++ b/bacula/src/version.h @@ -3,9 +3,9 @@ */ #undef VERSION -#define VERSION "1.39.0" -#define BDATE "20 November 2005" -#define LSMDATE "20Nov05" +#define VERSION "1.39.1" +#define BDATE "29 November 2005" +#define LSMDATE "29Nov05" /* Debug flags */ #undef DEBUG diff --git a/bacula/src/win32/README.vc8 b/bacula/src/win32/README.vc8 index 9ed93221e9..b92a4ebcf2 100644 --- a/bacula/src/win32/README.vc8 +++ b/bacula/src/win32/README.vc8 @@ -76,6 +76,10 @@ Build instructions: #ifndef (line 145) and #endif (line 147) in file: /bacula/src/win32/compat/compat.h + Repeat the operation for the "Unicode Debug" configuration if needed. + + Open /bacula/src/win32/bacula.sln + + Launch Build->Configuration Manager, then select your configuration. + + Then run Build->Build Solution (this will build wx-console, bconsole + and bacula-fd). Deploy instructions - Bacula: @@ -84,12 +88,20 @@ Deploy instructions http://nsis.sourceforge.net/Download + Modify the default \bacula\src\win32\winbacula.nsi.in script to include your own customizations. - Also change all references to msvcr71.dll to msvcr80.dll to - reflect the DLL used by VC++ 2005 - + Open /bacula/src/win32/bacula.sln - + Launch Build->Configuration Manager, then select your configuration. - + Then run Build->Build Solution (this will build wx-console, bconsole and bacula-fd). - + Don't forget to copy pthreadVCE.dll from /deppkgs-win32/pthreads and - iconv.dll and intl.dll from /deppkgs-win32/gettext/bin to - the Release and Debug directories in src/win32/baculafd, src/win32/wx-console - and src/win32/console. + These are the required modifications: + + * Remove all references to msvcr71.dll, as this is a pre VC++ 2005 library. + * VC++ 2005 compiled binaries require a new way of deploying DLLs: WinSxS. + More info: http://blogs.msdn.com/nikolad/archive/2005/03/18/398720.aspx + Collect the following 4 files from c:\WINDOWS\WinSxS and copy them into the + directory where winbacula.nsi resides. Also add them to winbacula.nsi where + msvcr71.dll was previously. + + File msvcm80.dll + File msvcp80.dll + File msvcr80.dll + File Microsoft.VC80.CRT.manifest + + Modify Microsoft.VC80.CRT.manifest to match the version number mentioned in + bacula-fd.exe.intermediate.manifest that is in /bacula/src/win32/baculafd/Release. +