Kern Sibbald
General:
+19Apr06
+- Apply patch from Christopher Hull
+ - Allow multiple connections to database with different
+ parameters.
+ - Invalidate the scheduler when doing a reload. Fixes seg
+ fault, but still 60 second window.
+ - Additional info in Reschedule message.
+ - Use set_jcr_job_status() everywhere to prevent loss of
+ cancel, error.
+ - Display peer IP in FD if error from connecting DIR.
+ - Don't increment file count for DIRBEGIN.
+ - Replace illegal characters in Win32 filename by _.
+ - Add SE_CREATE_PERMANENT_NAME privilege in Win32.
+ - Hash hard link filenames rather than linked list.
+ - Fix for security failure in chdir on Win32.
+ - Add CreateDirectoryA/W win32 API entry points.
+- Add /silent option to Win32 FD for Install/Remove service.
+- Always print Heap statistics in FD.
18Apr06
- Remove the -f option from the chown in Makefile.in for more
portability.
/* Look to see if DB already open */
if (!mult_db_connections) {
for (mdb=NULL; (mdb=(B_DB *)qnext(&db_list, &mdb->bq)); ) {
- if (strcmp(mdb->db_name, db_name) == 0) {
+ if (bstrcmp(mdb->db_name, db_name) &&
+ bstrcmp(mdb->db_address, db_address) &&
+ mdb->db_port == db_port) {
Dmsg2(100, "DB REopen %d %s\n", mdb->ref_count, db_name);
mdb->ref_count++;
V(mutex);
if (!mult_db_connections) {
/* Look to see if DB already open */
for (mdb=NULL; (mdb=(B_DB *)qnext(&db_list, &mdb->bq)); ) {
- if (strcmp(mdb->db_name, db_name) == 0) {
+ if (bstrcmp(mdb->db_name, db_name) &&
+ bstrcmp(mdb->db_address, db_address) &&
+ mdb->db_port == db_port) {
Dmsg2(100, "DB REopen %d %s\n", mdb->ref_count, db_name);
mdb->ref_count++;
V(mutex);
const char *query = "SELECT VersionId FROM Version";
bacula_db_version = 0;
- db_sql_query(mdb, query, int_handler, (void *)&bacula_db_version);
+ if (!db_sql_query(mdb, query, int_handler, (void *)&bacula_db_version)) {
+ Mmsg(mdb->errmsg, "Database not created or server not running.\n");
+ Jmsg(jcr, M_FATAL, 0, "%s", mdb->errmsg);
+ }
if (bacula_db_version != BDB_VERSION) {
Mmsg(mdb->errmsg, "Version error for database \"%s\". Wanted %d, got %d\n",
mdb->db_name, BDB_VERSION, bacula_db_version);
*
* Version $Id$
*/
-
/*
- Copyright (C) 2002-2005 Kern Sibbald
+ Copyright (C) 2002-2006 Kern Sibbald
This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License 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.
*/
+
/* The following is necessary so that we do not include
* the dummy external definition of DB.
*/
/* Look to see if DB already open */
if (!mult_db_connections) {
for (mdb=NULL; (mdb=(B_DB *)qnext(&db_list, &mdb->bq)); ) {
- if (strcmp(mdb->db_name, db_name) == 0) {
+ if (bstrcmp(mdb->db_name, db_name) &&
+ bstrcmp(mdb->db_address, db_address) &&
+ mdb->db_port == db_port) {
Dmsg2(300, "DB REopen %d %s\n", mdb->ref_count, db_name);
mdb->ref_count++;
V(mutex);
*
*/
/*
- Copyright (C) 2001-2005 Kern Sibbald
+ Copyright (C) 2001-2006 Kern Sibbald
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
static int check_resources();
/* Exported subroutines */
-
extern "C" void reload_config(int sig);
+extern void invalidate_schedules();
/* Imported subroutines */
RES **res_table;
};
-static const int max_reloads = 10;
+static const int max_reloads = 32;
static RELOAD_TABLE reload_table[max_reloads];
static void init_reload(void)
}
table = rtable; /* release new, bad, saved table below */
} else {
+ invalidate_schedules();
/*
* Hook all active jobs so that they release this table
*/
catalog->db_port, catalog->db_socket,
catalog->mult_db_connections);
if (!db || !db_open_database(NULL, db)) {
- Jmsg(NULL, M_FATAL, 0, _("Could not open database \"%s\".\n"),
- catalog->db_name);
+ Jmsg(NULL, M_FATAL, 0, _("Could not open Catalog \"%s\", database \"%s\".\n"),
+ catalog->hdr.name, catalog->db_name);
if (db) {
Jmsg(NULL, M_FATAL, 0, _("%s"), db_strerror(db));
}
jcr->job->RescheduleTimes > 0 &&
jcr->JobType == JT_BACKUP &&
jcr->reschedule_count < jcr->job->RescheduleTimes) {
- char dt[50];
+ char dt[50], dt2[50];
/*
* Reschedule this job by cleaning it up, but
* reuse the same JobId if possible.
*/
+ time_t now = time(NULL);
jcr->reschedule_count++;
- jcr->sched_time = time(NULL) + jcr->job->RescheduleInterval;
- Dmsg2(2300, "Rescheduled Job %s to re-run in %d seconds.\n", jcr->Job,
- (int)jcr->job->RescheduleInterval);
- bstrftime(dt, sizeof(dt), time(NULL));
- Jmsg(jcr, M_INFO, 0, _("Rescheduled Job %s at %s to re-run in %d seconds.\n"),
- jcr->Job, dt, (int)jcr->job->RescheduleInterval);
+ jcr->sched_time = now + jcr->job->RescheduleInterval;
+ bstrftime(dt, sizeof(dt), now);
+ bstrftime(dt2, sizeof(dt2), jcr->sched_time);
+ Dmsg4(2300, "Rescheduled Job %s to re-run in %d seconds.(now=%u,then=%u)\n", jcr->Job,
+ (int)jcr->job->RescheduleInterval, now, jcr->sched_time);
+ Jmsg(jcr, M_INFO, 0, _("Rescheduled Job %s at %s to re-run in %d seconds (%s).\n"),
+ jcr->Job, dt, (int)jcr->job->RescheduleInterval, dt2);
dird_free_jcr_pointers(jcr); /* partial cleanup old stuff */
- jcr->JobStatus = JS_WaitStartTime;
+ jcr->JobStatus = -1;
+ set_jcr_job_status(jcr, JS_WaitStartTime);
jcr->SDJobStatus = 0;
if (jcr->JobBytes == 0) {
Dmsg2(2300, "Requeue job=%d use=%d\n", jcr->JobId, jcr->use_count());
- jcr->JobStatus = JS_WaitStartTime;
+ set_jcr_job_status(jcr, JS_WaitStartTime);
V(jq->mutex);
jobq_add(jq, jcr); /* queue the job to run again */
P(jq->mutex);
set_jcr_defaults(njcr, jcr->job);
njcr->reschedule_count = jcr->reschedule_count;
njcr->JobLevel = jcr->JobLevel;
- njcr->JobStatus = jcr->JobStatus;
+ njcr->JobStatus = -1;
+ set_jcr_job_status(njcr, jcr->JobStatus);
copy_storage(njcr, jcr->storage);
njcr->messages = jcr->messages;
Dmsg0(2300, "Call to run new job\n");
JCR *prev_jcr;
if (jcr->previous_jr.JobId == 0) {
- jcr->JobStatus = JS_Terminated;
+ set_jcr_job_status(jcr, JS_Terminated);
migration_cleanup(jcr, jcr->JobStatus);
return true; /* no work */
}
/* Note, the SD stores in jcr->JobFiles/ReadBytes/JobBytes/Errors */
wait_for_storage_daemon_termination(jcr);
- jcr->JobStatus = jcr->SDJobStatus;
+ set_jcr_job_status(jcr, jcr->SDJobStatus);
if (jcr->JobStatus == JS_Terminated) {
migration_cleanup(jcr, jcr->JobStatus);
return true;
#include "bacula.h"
#include "dird.h"
-/* #define SCHED_DEBUG */
+#if 0
+#define SCHED_DEBUG
+#define DBGLVL 0
+#else
+#undef SCHED_DEBUG
+#define DBGLVL 200
+#endif
+const int dbglvl = DBGLVL;
/* Local variables */
struct job_item {
/* Imported variables */
+/**
+ * called by reload_config to tell us that the schedules
+ * we may have based our next jobs to run queues have been
+ * invalidated. In fact the schedules may not have changed
+ * but the run object that we have recorded the last_run time
+ * on are new and no longer have a valid last_run time which
+ * causes us to double run schedules that get put into the list
+ * because run_nh = 1.
+ */
+static bool schedules_invalidated = false;
+void invalidate_schedules(void) {
+ schedules_invalidated = true;
+}
/*********************************************************************
*
static bool first = true;
job_item *next_job = NULL;
- Dmsg0(200, "Enter wait_for_next_job\n");
+ Dmsg0(dbglvl, "Enter wait_for_next_job\n");
if (first) {
first = false;
/* Create scheduled jobs list */
/* Now wait for the time to run the job */
for (;;) {
time_t twait;
+ if (schedules_invalidated) { /** discard scheduled queue and rebuild with new schedule objects. **/
+ dump_job(next_job, "Invalidated job");
+ free(next_job);
+ while (!jobs_to_run->empty()) {
+ next_job = (job_item *)jobs_to_run->first();
+ jobs_to_run->remove(next_job);
+ dump_job(next_job, "Invalidated job");
+ free(next_job);
+ }
+ schedules_invalidated = false;
+ goto again;
+ }
now = time(NULL);
twait = next_job->runtime - now;
if (twait <= 0) { /* time to run it */
break;
}
- bmicrosleep(twait, 0);
+ bmicrosleep((NEXT_CHECK_SECS<twait)?NEXT_CHECK_SECS:twait, 0); /* recheck at least once per minute */
}
run = next_job->run; /* pick up needed values */
job = next_job->job;
if (run->write_part_after_job_set) {
jcr->write_part_after_job = run->write_part_after_job;
}
- Dmsg0(200, "Leave wait_for_next_job()\n");
+ Dmsg0(dbglvl, "Leave wait_for_next_job()\n");
return jcr;
}
/* Items corresponding to above at the next hour */
int nh_hour, nh_mday, nh_wday, nh_month, nh_wom, nh_woy, nh_year;
- Dmsg0(1200, "enter find_runs()\n");
+ Dmsg0(dbglvl, "enter find_runs()\n");
/* compute values for time now */
if (sched == NULL || !job->enabled) { /* scheduled? or enabled? */
continue; /* no, skip this job */
}
- Dmsg1(1200, "Got job: %s\n", job->hdr.name);
+ Dmsg1(dbglvl, "Got job: %s\n", job->hdr.name);
for (run=sched->run; run; run=run->next) {
bool run_now, run_nh;
/*
bit_is_set(nh_wom, run->wom) &&
bit_is_set(nh_woy, run->woy);
- Dmsg2(1200, "run_now=%d run_nh=%d\n", run_now, run_nh);
+ Dmsg3(dbglvl, "run@%p: run_now=%d run_nh=%d\n", run, run_now, run_nh);
/* find time (time_t) job is to be run */
localtime_r(&now, &tm); /* reset tm structure */
}
}
UnlockRes();
- Dmsg0(1200, "Leave find_runs()\n");
+ Dmsg0(dbglvl, "Leave find_runs()\n");
}
static void add_job(JOB *job, RUN *run, time_t now, time_t runtime)
bstrftime_nc(dt, sizeof(dt), runtime);
bstrftime_nc(dt1, sizeof(dt1), run->last_run);
bstrftime_nc(dt2, sizeof(dt2), now);
- Dmsg4(000, "Drop: Job=\"%s\" run=%s. last_run=%s. now=%s\n", job->hdr.name,
- dt, dt1, dt2);
+ Dmsg7(000, "Drop: Job=\"%s\" run=%s(%x). last_run=%s(%x). now=%s(%x)\n", job->hdr.name,
+ dt, runtime, dt1, run->last_run, dt2, now);
fflush(stdout);
#endif
return;
}
+#ifdef SCHED_DEBUG
+ Dmsg4(000, "Add: Job=\"%s\" run=%x last_run=%x now=%x\n", job->hdr.name,
+ runtime, run->last_run, now);
+#endif
/* accept to run this job */
job_item *je = (job_item *)malloc(sizeof(job_item));
je->run = run;
#ifdef SCHED_DEBUG
char dt[MAX_TIME_LENGTH];
int save_debug = debug_level;
- debug_level = 200;
- if (debug_level < 200) {
+ if (debug_level < dbglvl) {
return;
}
bstrftime_nc(dt, sizeof(dt), ji->runtime);
- Dmsg4(200, "%s: Job=%s priority=%d run %s\n", msg, ji->job->hdr.name,
+ Dmsg4(dbglvl, "%s: Job=%s priority=%d run %s\n", msg, ji->job->hdr.name,
ji->Priority, dt);
fflush(stdout);
debug_level = save_debug;
Dmsg1(800, "Calling run_job job=%x\n", jcr->job);
start_job:
JobId = run_job(jcr);
+#if 0
+ bsendmsg(ua, "<job director=\"console\" time=\"%u\" status=\"%c\" type=\"%c\" "
+ "jobid=\"%u\" job=\"%s\" level=\"%c\" finished=\"false\" priority=\"%u\"/>\n",
+ time(NULL), jcr->JobStatus, jcr->JobType, jcr->JobId,
+ jcr->Job, jcr->JobLevel, jcr->JobPriority);
+#endif
free_jcr(jcr); /* release jcr */
if (JobId == 0) {
bsendmsg(ua, _("Job failed.\n"));
jcr->sched_time = jcr->start_time;
jcr->JobType = job_type;
jcr->JobLevel = L_NONE;
- jcr->JobStatus = JS_Running;
+ set_jcr_job_status(jcr, JS_Running);
jcr->JobId = 0;
return jcr;
}
if (bs->msglen < 25 || bs->msglen > 200) {
Dmsg2(50, "Bad Hello command from Director at %s. Len=%d.\n",
bs->who, bs->msglen);
+ char addr[64];
+ char *who = bnet_get_peer(bs, addr, sizeof(addr)) ? bs->who : addr;
Emsg2(M_FATAL, 0, _("Bad Hello command from Director at %s. Len=%d.\n"),
- bs->who, bs->msglen);
+ who, bs->msglen);
return 0;
}
dirname = get_pool_memory(PM_MESSAGE);
dirname = check_pool_memory_size(dirname, bs->msglen);
if (sscanf(bs->msg, "Hello Director %s calling\n", dirname) != 1) {
+ char addr[64];
+ char *who = bnet_get_peer(bs, addr, sizeof(addr)) ? bs->who : addr;
free_pool_memory(dirname);
bs->msg[100] = 0;
Dmsg2(50, "Bad Hello command from Director at %s: %s\n",
bs->who, bs->msg);
Emsg2(M_FATAL, 0, _("Bad Hello command from Director at %s: %s\n"),
- bs->who, bs->msg);
+ who, bs->msg);
return 0;
}
unbash_spaces(dirname);
}
UnlockRes();
if (!director) {
- Dmsg2(50, "Connection from unknown Director %s at %s rejected.\n",
- dirname, bs->who);
- Emsg2(M_FATAL, 0, _("Connection from unknown Director %s at %s rejected.\n"
- "Please see http://www.bacula.org/rel-manual/faq.html#AuthorizationErrors for help.\n"),
- dirname, bs->who);
+ char addr[64];
+ char *who = bnet_get_peer(bs, addr, sizeof(addr)) ? bs->who : addr;
+ Emsg2(M_FATAL, 0, _("Connection from unknown Director %s at %s rejected.\n"),
+ dirname, who);
free_pool_memory(dirname);
return 0;
}
}
btimer_t *tid = start_bsock_timer(bs, AUTH_TIMEOUT);
- auth_success = cram_md5_auth(bs, director->password, tls_local_need);
+ auth_success = cram_md5_auth(bs, director->password, tls_local_need);
if (auth_success) {
auth_success = cram_md5_get_auth(bs, director->password, &tls_remote_need);
if (!auth_success) {
- Dmsg1(50, "cram_get_auth failed for %s\n", bs->who);
+ char addr[64];
+ char *who = bnet_get_peer(bs, addr, sizeof(addr)) ? bs->who : addr;
+ Dmsg1(50, "cram_get_auth failed for %s\n", who);
}
} else {
- Dmsg1(50, "cram_auth failed for %s\n", bs->who);
+ char addr[64];
+ char *who = bnet_get_peer(bs, addr, sizeof(addr)) ? bs->who : addr;
+ Dmsg1(50, "cram_auth failed for %s\n", who);
}
if (!auth_success) {
- Emsg1(M_FATAL, 0, _("Incorrect password given by Director at %s.\n"
- "Please see http://www.bacula.org/rel-manual/faq.html#AuthorizationErrors for help.\n"),
- bs->who);
- director = NULL;
- goto auth_fatal;
+ Emsg1(M_FATAL, 0, _("Incorrect password given by Director at %s.\n"),
+ bs->who);
+ director = NULL;
+ goto auth_fatal;
}
/* Verify that the remote host is willing to meet our TLS requirements */
*
*/
/*
- Copyright (C) 2000-2005 Kern Sibbald
+ Copyright (C) 2000-2006 Kern Sibbald
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
#else
crypto_digest_t signing_algorithm = CRYPTO_DIGEST_SHA1;
#endif
- BSOCK *sd;
JCR *jcr = (JCR *)vjcr;
+ BSOCK *sd = jcr->store_bsock;
if (job_canceled(jcr)) {
return 0;
}
- sd = jcr->store_bsock;
jcr->num_files_examined++; /* bump total file count */
switch (ff_pkt->type) {
Dmsg2(130, "FT_LNK saving: %s -> %s\n", ff_pkt->fname, ff_pkt->link);
break;
case FT_DIRBEGIN:
+ jcr->num_files_examined--; /* correct file count */
return 1; /* not used */
case FT_NORECURSE:
Jmsg(jcr, M_INFO, 1, _(" Recursion turned off. Will not descend into %s\n"),
{
int stat;
- jcr->JobStatus = JS_Running;
+ set_jcr_job_status(jcr, JS_Running);
set_find_options((FF_PKT *)jcr->ff, jcr->incremental, jcr->mtime);
stat = find_files(jcr, (FF_PKT *)jcr->ff, tally_file, (void *)jcr);
sendit(msg, len, arg);
}
#endif
- if (debug_level > 0) {
- len = Mmsg(msg, _(" Heap: bytes=%s max_bytes=%s bufs=%s max_bufs=%s\n"),
- edit_uint64_with_commas(sm_bytes, b1),
- edit_uint64_with_commas(sm_max_bytes, b2),
- edit_uint64_with_commas(sm_buffers, b3),
- edit_uint64_with_commas(sm_max_buffers, b4));
- sendit(msg, len, arg);
- len = Mmsg(msg, _(" Sizeof: off_t=%d size_t=%d debug=%d trace=%d\n"),
- sizeof(off_t), sizeof(size_t), debug_level, get_trace());
- sendit(msg, len, arg);
- }
+ len = Mmsg(msg, _(" Heap: bytes=%s max_bytes=%s bufs=%s max_bufs=%s\n"),
+ edit_uint64_with_commas(sm_bytes, b1),
+ edit_uint64_with_commas(sm_max_bytes, b2),
+ edit_uint64_with_commas(sm_buffers, b3),
+ edit_uint64_with_commas(sm_max_buffers, b4));
+ sendit(msg, len, arg);
+ len = Mmsg(msg, _(" Sizeof: off_t=%d size_t=%d debug=%d trace=%d\n"),
+ sizeof(off_t), sizeof(size_t), debug_level, get_trace());
+ sendit(msg, len, arg);
list_terminated_jobs(sendit, arg);
/*
- Copyright (C) 2000-2005 Kern Sibbald
+ Copyright (C) 2000-2006 Kern Sibbald
This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License 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.
This file is patterned after the VNC Win32 code by ATT
char *szCmdLine = CmdLine;
char *wordPtr, *tempPtr;
int i, quote;
+ bool silent = false;
/* Save the application instance and main thread id */
hAppInstance = hInstance;
/* Now check for command-line arguments */
- /* /service helper - probably only needed on win9x */
- if (strncmp(&szCmdLine[i], BaculaRunServiceHelper, strlen(BaculaRunServiceHelper)) == 0
- && g_platform_id == VER_PLATFORM_WIN32_NT) {
- /* exit with result "okay" */
- return 0;
+ /* /silent install quietly -- no prompts */
+ if (strncmp(&szCmdLine[i], "/silent", strlen("/silent")) == 0) {
+ silent = true;
+ i += strlen("/silent");
}
/* /service start service */
/* /install */
if (strncmp(&szCmdLine[i], BaculaInstallService, strlen(BaculaInstallService)) == 0) {
/* Install Bacula as a service */
- bacService::InstallService();
+ bacService::InstallService(silent);
i += strlen(BaculaInstallService);
continue;
}
/* /remove */
if (strncmp(&szCmdLine[i], BaculaRemoveService, strlen(BaculaRemoveService)) == 0) {
/* Remove the Bacula service */
- bacService::RemoveService();
+ bacService::RemoveService(silent);
i += strlen(BaculaRemoveService);
continue;
}
// by Kern E. Sibbald. Many thanks to ATT and James Weatherall,
// the original author, for providing an excellent template.
//
-// Copyright (2000-2003) Kern E. Sibbald
+// Copyright (C) 2000-2006 Kern E. Sibbald
//
// SERVICE INSTALL ROUTINE
int
-bacService::InstallService()
+bacService::InstallService(bool silent)
{
const int pathlength = 2048;
char path[pathlength];
RegCloseKey(runservices);
// We have successfully installed the service!
- MessageBox(NULL,
+ if (!silent) {
+ MessageBox(NULL,
_("The Bacula File service was successfully installed.\n"
"The service may be started by double clicking on the\n"
"Bacula \"Start\" icon and will be automatically\n"
"be run the next time this machine is rebooted. "),
szAppName,
MB_ICONINFORMATION | MB_OK);
+ }
break;
// Windows NT, Win2K, WinXP
CloseServiceHandle(hservice);
// Everything went fine
- MessageBox(NULL,
+ if (!silent) {
+ MessageBox(NULL,
_("The Bacula File service was successfully installed.\n"
"The service may be started from the Control Panel and will\n"
"automatically be run the next time this machine is rebooted."),
szAppName,
MB_ICONINFORMATION | MB_OK);
+ }
break;
default:
log_error_message("Unknown Windows System version");
// SERVICE REMOVE ROUTINE
int
-bacService::RemoveService()
+bacService::RemoveService(bool silent)
{
// How to remove the Bacula service depends upon the OS
switch (g_platform_id) {
}
// We have successfully removed the service!
- MessageBox(NULL, _("The Bacula service has been removed"), szAppName, MB_ICONINFORMATION | MB_OK);
+ if (!silent) {
+ MessageBox(NULL, _("The Bacula service has been removed"), szAppName, MB_ICONINFORMATION | MB_OK);
+ }
break;
// Windows NT, Win2K, WinXP
}
// Now remove the service from the SCM
- if(DeleteService(hservice)) {
- MessageBox(NULL, _("The Bacula service has been removed"), szAppName, MB_ICONINFORMATION | MB_OK);
+ if (DeleteService(hservice)) {
+ if (!silent) {
+ MessageBox(NULL, _("The Bacula service has been removed"), szAppName, MB_ICONINFORMATION | MB_OK);
+ }
} else {
MessageBox(NULL, _("The Bacula service could not be removed"), szAppName, MB_ICONEXCLAMATION | MB_OK);
}
// by Kern E. Sibbald. Many thanks to ATT and James Weatherall,
// the original author, for providing an excellent template.
//
-// Copyright (2000) Kern E. Sibbald
+// Copyright (C) 2000-2006 Kern E. Sibbald
//
class bacService
{
public:
- bacService();
+ bacService();
// SERVICE INSTALL & START FUNCTIONS
// Routine called by WinMain to cause Bacula to be installed
// as a service.
- static int BaculaServiceMain();
+ int BaculaServiceMain();
// Routine to install the Apcupsd service on the local machine
- static int InstallService();
+ int InstallService(bool silent);
// Routine to remove the Apcupsd service from the local machine
- static int RemoveService();
+ int RemoveService(bool silent);
// SERVICE SUPPORT FUNCTIONS
gid = attr->statp.st_gid;
uid = attr->statp.st_uid;
+#ifdef HAVE_WIN32
+ if (!bfd->use_backup_api) {
+ // eliminate invalid windows filename characters from foreign filenames
+ char *ch = (char *)attr->ofname;
+ if (ch[0] != 0 && ch[1] != 0) {
+ ch+=2;
+ while (*ch) {
+ switch (*ch) {
+ case ':':
+ case '<':
+ case '>':
+ case '*':
+ case '?':
+ case '|':
+ *ch = '_';
+ break;
+ }
+ ch++;
+ }
+ }
+ }
+#endif
+
Dmsg2(400, "Replace=%c %d\n", (char)replace, replace);
if (lstat(attr->ofname, &mstatp) == 0) {
exists = true;
/*=============================================================*/
-/* */
-/* * * * U n i x * * * * */
-/* */
+/* */
+/* * * * U n i x * * * * */
+/* */
/*=============================================================*/
#if !defined(HAVE_CYGWIN) && !defined(HAVE_WIN32)
/*=============================================================*/
-/* */
-/* * * * W i n 3 2 * * * * */
-/* */
+/* */
+/* * * * W i n 3 2 * * * * */
+/* */
/*=============================================================*/
#if defined(HAVE_CYGWIN) || defined(HAVE_WIN32)
DWORD lerror;
if (!(p_LookupPrivilegeValue && p_AdjustTokenPrivileges)) {
- return 0; /* not avail on this OS */
+ return 0; /* not avail on this OS */
}
// Get the LUID for the security privilege.
if (!p_LookupPrivilegeValue(NULL, name, &tkp.Privileges[0].Luid)) {
- if (!ignore_errors) {
- win_error(jcr, "LookupPrivilegeValue", GetLastError());
- }
+ win_error(jcr, "LookupPrivilegeValue", GetLastError());
+ return 0;
}
/* Set the security privilege for this process. */
lerror = GetLastError();
if (lerror != ERROR_SUCCESS) {
if (!ignore_errors) {
- char buf[200];
- strcpy(buf, _("AdjustTokenPrivileges set "));
- bstrncat(buf, name, sizeof(buf));
- win_error(jcr, buf, lerror);
+ char buf[200];
+ strcpy(buf, _("AdjustTokenPrivileges set "));
+ bstrncat(buf, name, sizeof(buf));
+ win_error(jcr, buf, lerror);
}
return 0;
}
int stat = 0;
if (!p_OpenProcessToken) {
- return 0; /* No avail on this OS */
+ return 0; /* No avail on this OS */
}
hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, GetCurrentProcessId());
// Get a token for this process.
if (!p_OpenProcessToken(hProcess,
- TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) {
+ TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) {
if (!ignore_errors) {
- win_error(jcr, "OpenProcessToken", GetLastError());
+ win_error(jcr, "OpenProcessToken", GetLastError());
}
/* Forge on anyway */
}
if (enable_priv(jcr, hToken, SE_TCB_NAME, ignore_errors)) {
stat |= 1<<8;
}
+ if (enable_priv(jcr, hToken, SE_CREATE_PERMANENT_NAME, ignore_errors)) {
+ stat |= 1<<10;
+ }
if (stat) {
stat |= 1<<9;
}
return stat;
}
-#endif /* HAVE_CYGWIN */
+#endif /* HAVE_CYGWIN */
alist fstypes; /* allowed file system types */
/* List of all hard linked files found */
- struct f_link *linklist; /* hard linked files */
+ struct f_link **linkhash; /* hard linked files */
/* Darwin specific things.
* To avoid clutter, we always include rsrc_bfd and volhas_attrlist */
char name[1]; /* The name */
};
+typedef struct f_link link_t;
+#define LINK_HASHTABLE_BITS 16
+#define LINK_HASHTABLE_SIZE (1<<LINK_HASHTABLE_BITS)
+#define LINK_HASHTABLE_MASK (LINK_HASHTABLE_SIZE-1)
+
+static inline int LINKHASH(const struct stat &info)
+{
+ int hash = info.st_dev;
+ unsigned long long i = info.st_ino;
+ hash ^= i;
+ i >>= 16;
+ hash ^= i;
+ i >>= 16;
+ hash ^= i;
+ i >>= 16;
+ hash ^= i;
+ return hash & LINK_HASHTABLE_MASK;
+}
+
static void free_dir_ff_pkt(FF_PKT *dir_ff_pkt)
{
free(dir_ff_pkt->fname);
|| S_ISSOCK(ff_pkt->statp.st_mode))) {
struct f_link *lp;
+ if (ff_pkt->linkhash == NULL) {
+ ff_pkt->linkhash = (link_t **)bmalloc(LINK_HASHTABLE_SIZE * sizeof(link_t *));
+ memset(ff_pkt->linkhash, 0, LINK_HASHTABLE_SIZE * sizeof(link_t *));
+ }
+ const int linkhash = LINKHASH(ff_pkt->statp);
/* Search link list of hard linked files */
- for (lp = ff_pkt->linklist; lp; lp = lp->next)
+ for (lp = ff_pkt->linkhash[linkhash]; lp; lp = lp->next)
if (lp->ino == (ino_t)ff_pkt->statp.st_ino &&
lp->dev == (dev_t)ff_pkt->statp.st_dev) {
/* If we have already backed up the hard linked file don't do it again */
lp->ino = ff_pkt->statp.st_ino;
lp->dev = ff_pkt->statp.st_dev;
bstrncpy(lp->name, fname, len);
- lp->next = ff_pkt->linklist;
- ff_pkt->linklist = lp;
+ lp->next = ff_pkt->linkhash[linkhash];
+ ff_pkt->linkhash[linkhash] = lp;
ff_pkt->linked = lp; /* mark saved link */
} else {
ff_pkt->linked = NULL;
dir_ff_pkt->included_files_list = NULL;
dir_ff_pkt->excluded_files_list = NULL;
dir_ff_pkt->excluded_paths_list = NULL;
- dir_ff_pkt->linklist = NULL;
+ dir_ff_pkt->linkhash = NULL;
/*
* Do not descend into subdirectories (recurse) if the
{
struct f_link *lp, *lc;
int count = 0;
+ int i;
+
+ if (ff->linkhash == NULL) return 0;
+
+ for (i =0 ; i < LINK_HASHTABLE_SIZE; i ++) {
/* Free up list of hard linked files */
- for (lp = ff->linklist; lp;) {
+ lp = ff->linkhash[i];
+ while (lp) {
lc = lp;
lp = lp->next;
if (lc) {
count++;
}
}
- ff->linklist = NULL;
+ ff->linkhash[i] = NULL;
+ }
+ free(ff->linkhash);
+ ff->linkhash = NULL;
return count;
}
/* Because of silly Win32 security, we allow everything */
tmp_mode = S_IRWXUGO;
re_protect = 0;
-#endif
+#endif
+#if defined(HAVE_WIN32)
+ // chdir can fail if permissions are sufficiently restricted since I don't think
+ // backup/restore security rights affect ChangeWorkingDirectory
+ cwd.do_chdir = 0;
+#else
/* If we can record the current working directory, we may be able
to do the chdir optimization. */
cwd.do_chdir = !save_cwd(&cwd);
-
+#endif
/* If we've saved the cwd and DIRPATH is an absolute pathname,
we must chdir to `/' in order to enable the chdir optimization.
So if chdir ("/") fails, turn off the optimization. */
return bnet_send(bs);
}
+int bnet_get_peer(BSOCK *bs, char *buf, socklen_t buflen) {
+#if !defined(HAVE_WIN32)
+ if (bs->peer_addr.sin_family == 0) {
+ socklen_t salen = sizeof(bs->peer_addr);
+ int rval = (getpeername)(bs->fd, (struct sockaddr *)&bs->peer_addr, &salen);
+ if (rval < 0) return rval;
+ }
+ if (!inet_ntop(bs->peer_addr.sin_family, &bs->peer_addr.sin_addr, buf, buflen))
+ return -1;
+
+ return 0;
+#else
+ return -1;
+#endif
+}
/*
* Set the network buffer size, suggested size is in size.
* Actual size obtained is returned in bs->msglen
bsock->who = bstrdup(who);
bsock->host = bstrdup(host);
bsock->port = port;
+ memset(&bsock->peer_addr, 0, sizeof(bsock->peer_addr));
memcpy(&bsock->client_addr, client_addr, sizeof(bsock->client_addr));
/*
* ****FIXME**** reduce this to a few hours once
FILE *spool_fd; /* spooling file */
JCR *jcr; /* jcr or NULL for error msgs */
struct sockaddr client_addr; /* client's IP address */
+ struct sockaddr_in peer_addr; /* peer's IP address */
};
/* Signal definitions for use in bnet_sig() */
* Version $Id$
*/
/*
- Copyright (C) 2000-2005 Kern Sibbald
+ Copyright (C) 2000-2006 Kern Sibbald
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
return dest;
}
+/*
+ * Allows one or both pointers to be NULL
+ */
+bool bstrcmp(const char *s1, const char *s2)
+{
+ if (s1 == s2) return true;
+ if (s1 == NULL || s2 == NULL) return false;
+ return strcmp(s1, s2) == 0;
+}
+
/*
* Get character length of UTF-8 string
*
jcr->daemon_free_jcr = daemon_free_jcr; /* plug daemon free routine */
jcr->init_mutex();
jcr->inc_use_count();
- jcr->JobStatus = JS_Created; /* ready to run */
+ set_jcr_job_status(jcr, JS_Created); /* ready to run */
jcr->VolumeName = get_pool_memory(PM_FNAME);
jcr->VolumeName[0] = 0;
jcr->errmsg = get_pool_memory(PM_MESSAGE);
char *bstrncpy (char *dest, POOL_MEM &src, int maxlen);
char *bstrncat (char *dest, const char *src, int maxlen);
char *bstrncat (char *dest, POOL_MEM &src, int maxlen);
+bool bstrcmp (const char *s1, const char *s2);
int cstrlen (const char *str);
void *b_malloc (const char *file, int line, size_t size);
#ifndef DEBUG
void bnet_close (BSOCK *bsock);
BSOCK * init_bsock (JCR *jcr, int sockfd, const char *who, const char *ip,
int port, struct sockaddr *client_addr);
+int bnet_get_peer (BSOCK *bs, char *buf, socklen_t buflen);
BSOCK * dup_bsock (BSOCK *bsock);
void term_bsock (BSOCK *bsock);
const char *bnet_strerror (BSOCK *bsock);
* Kern Sibbald MMIII
*/
/*
- Copyright (C) 2003-2005 Kern Sibbald
+ Copyright (C) 2003-2006 Kern Sibbald
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
t_CreateFileA p_CreateFileA = NULL;
t_CreateFileW p_CreateFileW = NULL;
+t_CreateDirectoryA p_CreateDirectoryA;
+t_CreateDirectoryW p_CreateDirectoryW;
t_wunlink p_wunlink = NULL;
t_wmkdir p_wmkdir = NULL;
p_CreateFileW = (t_CreateFileW)
GetProcAddress(hLib, "CreateFileW");
+ p_CreateDirectoryA = (t_CreateDirectoryA)
+ GetProcAddress(hLib, "CreateDirectoryA");
+ p_CreateDirectoryW = (t_CreateDirectoryW)
+ GetProcAddress(hLib, "CreateDirectoryW");
+
/* attribute calls */
p_GetFileAttributesA = (t_GetFileAttributesA)
GetProcAddress(hLib, "GetFileAttributesA");
* Kern Sibbald MMIII
*/
/*
- Copyright (C) 2000-2005 Kern Sibbald
+ Copyright (C) 2003-2006 Kern Sibbald
This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License 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.
*/
#endif
// unicode enabling of win 32 needs some defines and functions
-#define MAX_PATH_UTF8 MAX_PATH*3
+
+// using an average of 3 bytes per character is probably fine in
+// practice but I believe that Windows actually uses UTF-16 encoding
+// as opposed to UCS2 which means characters 0x10000-0x10ffff are
+// valid and result in 4 byte UTF-8 encodings.
+#define MAX_PATH_UTF8 MAX_PATH*4 // strict upper bound on UTF-16 to UTF-8 conversion
+// from
+// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/fileio/fs/getfileattributesex.asp
+// In the ANSI version of this function, the name is limited to
+// MAX_PATH characters. To extend this limit to 32,767 wide
+// characters, call the Unicode version of the function and prepend
+// "\\?\" to the path. For more information, see Naming a File.
+#define MAX_PATH_W 32767
int wchar_2_UTF8(char *pszUTF, const WCHAR *pszUCS, int cchChar = MAX_PATH_UTF8);
int UTF8_2_wchar(POOLMEM **pszUCS, const char *pszUTF);
-int make_win32_path_UTF8_2_wchar(POOLMEM **pszUCS, const char *pszUTF, BOOL* pBIsRawPath = NULL);
+
/* In ADVAPI32.DLL */
typedef HANDLE (WINAPI * t_CreateFileW) (LPCWSTR, DWORD ,DWORD, LPSECURITY_ATTRIBUTES,
DWORD , DWORD, HANDLE);
+typedef BOOL (WINAPI * t_CreateDirectoryA) (LPCSTR, LPSECURITY_ATTRIBUTES);
+typedef BOOL (WINAPI * t_CreateDirectoryW) (LPCWSTR, LPSECURITY_ATTRIBUTES);
+
typedef BOOL (WINAPI * t_SetProcessShutdownParameters)(DWORD, DWORD);
typedef BOOL (WINAPI * t_BackupRead)(HANDLE,LPBYTE,DWORD,LPDWORD,BOOL,BOOL,LPVOID*);
typedef BOOL (WINAPI * t_BackupWrite)(HANDLE,LPBYTE,DWORD,LPDWORD,BOOL,BOOL,LPVOID*);
extern t_CreateFileA p_CreateFileA;
extern t_CreateFileW p_CreateFileW;
+
+extern t_CreateDirectoryA p_CreateDirectoryA;
+extern t_CreateDirectoryW p_CreateDirectoryW;
+
extern t_SetProcessShutdownParameters p_SetProcessShutdownParameters;
extern t_BackupRead p_BackupRead;
extern t_BackupWrite p_BackupWrite;
}
}
- jcr->JobStatus = JS_WaitMedia;
+ set_jcr_job_status(jcr, JS_WaitMedia);
dir_send_job_status(jcr);
stat = wait_for_sysop(dcr);
dcr->VolumeName, dev->print_name(), jcr->Job);
}
- jcr->JobStatus = JS_WaitMount;
+ set_jcr_job_status(jcr, JS_WaitMount);
dir_send_job_status(jcr);
stat = wait_for_sysop(dcr); /* wait on device */
#undef VERSION
#define VERSION "1.39.9"
-#define BDATE "18 April 2006"
-#define LSMDATE "18Apr06"
+#define BDATE "19 April 2006"
+#define LSMDATE "19Apr06"
/* Debug flags */
#undef DEBUG