X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=bacula%2Fsrc%2Flib%2Futil.c;h=8a3e56453cb491e77b648bdc581bbe39db81ccfe;hb=4132c9f33642f579d89700f36caced609d374d51;hp=505851583fd4a2f094316627dd2372c211f45fdf;hpb=c7b579e609651df22be2eb6a9f2e8bcb3dfa204f;p=bacula%2Fbacula diff --git a/bacula/src/lib/util.c b/bacula/src/lib/util.c index 505851583f..8a3e56453c 100644 --- a/bacula/src/lib/util.c +++ b/bacula/src/lib/util.c @@ -1,3 +1,30 @@ +/* + Bacula® - The Network Backup Solution + + Copyright (C) 2000-2009 Free Software Foundation Europe e.V. + + The main author of Bacula is Kern Sibbald, with contributions from + many others, a complete list can be found in the file AUTHORS. + This program is Free Software; you can redistribute it and/or + modify it under the terms of version three of the GNU Affero General Public + License as published by the Free Software Foundation and included + in the file LICENSE. + + 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 Affero General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. + + Bacula® is a registered trademark of Kern Sibbald. + The licensor of Bacula is the Free Software Foundation Europe + (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich, + Switzerland, email:ftf@fsfeurope.org. +*/ /* * util.c miscellaneous utility subroutines for Bacula * @@ -5,20 +32,6 @@ * * Version $Id$ */ -/* - 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 - 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 - the file LICENSE for additional details. - - */ #include "bacula.h" #include "jcr.h" @@ -30,21 +43,21 @@ */ /* Return true of buffer has all zero bytes */ -int is_buf_zero(char *buf, int len) +bool is_buf_zero(char *buf, int len) { uint64_t *ip; char *p; int i, len64, done, rem; if (buf[0] != 0) { - return 0; + return false; } ip = (uint64_t *)buf; /* Optimize by checking uint64_t for zero */ len64 = len / sizeof(uint64_t); for (i=0; i < len64; i++) { if (ip[i] != 0) { - return 0; + return false; } } done = len64 * sizeof(uint64_t); /* bytes already checked */ @@ -52,10 +65,10 @@ int is_buf_zero(char *buf, int len) rem = len - done; for (i = 0; i < rem; i++) { if (p[i] != 0) { - return 0; + return false; } } - return 1; + return true; } @@ -63,8 +76,9 @@ int is_buf_zero(char *buf, int len) void lcase(char *str) { while (*str) { - if (B_ISUPPER(*str)) + if (B_ISUPPER(*str)) { *str = tolower((int)(*str)); + } str++; } } @@ -120,10 +134,11 @@ unbash_spaces(POOL_MEM &pm) } } -char *encode_time(time_t time, char *buf) +char *encode_time(utime_t utime, char *buf) { struct tm tm; int n = 0; + time_t time = utime; #if defined(HAVE_WIN32) /* @@ -180,6 +195,9 @@ void jobstatus_to_ascii(int JobStatus, char *msg, int maxlen) case JS_Error: jobstat = _("Non-fatal error"); break; + case JS_Warnings: + jobstat = _("OK -- with warnings"); + break; case JS_Canceled: jobstat = _("Canceled"); break; @@ -216,6 +234,18 @@ void jobstatus_to_ascii(int JobStatus, char *msg, int maxlen) case JS_WaitPriority: jobstat = _("Waiting on Priority"); break; + case JS_DataCommitting: + jobstat = _("SD committing Data"); + break; + case JS_DataDespooling: + jobstat = _("SD despooling Data"); + break; + case JS_AttrDespooling: + jobstat = _("SD despooling Attributes"); + break; + case JS_AttrInserting: + jobstat = _("Dir inserting Attributes"); + break; default: if (JobStatus == 0) { @@ -229,6 +259,56 @@ void jobstatus_to_ascii(int JobStatus, char *msg, int maxlen) bstrncpy(msg, jobstat, maxlen); } +/* + * Convert a JobStatus code into a human readable form - gui version + */ +void jobstatus_to_ascii_gui(int JobStatus, char *msg, int maxlen) +{ + const char *cnv = NULL; + switch (JobStatus) { + case JS_Terminated: + cnv = _("Completed successfully"); + break; + case JS_Warnings: + cnv = _("Completed with warnings"); + break; + case JS_ErrorTerminated: + cnv = _("Terminated with errors"); + break; + case JS_FatalError: + cnv = _("Fatal error"); + break; + case JS_Created: + cnv = _("Created, not yet running"); + break; + case JS_Canceled: + cnv = _("Canceled by user"); + break; + case JS_Differences: + cnv = _("Verify found differences"); + break; + case JS_WaitFD: + cnv = _("Waiting for File daemon"); + break; + case JS_WaitSD: + cnv = _("Waiting for Storage daemon"); + break; + case JS_WaitPriority: + cnv = _("Waiting for higher priority jobs"); + break; + case JS_AttrInserting: + cnv = _("Batch inserting file records"); + break; + }; + + if (cnv) { + bstrncpy(msg, cnv, maxlen); + } else { + jobstatus_to_ascii(JobStatus, msg, maxlen); + } +} + + /* * Convert Job Termination Status into a string */ @@ -240,6 +320,9 @@ const char *job_status_to_str(int stat) case JS_Terminated: str = _("OK"); break; + case JS_Warnings: + str = _("OK -- with warnings"); + break; case JS_ErrorTerminated: case JS_Error: str = _("Error"); @@ -266,34 +349,65 @@ const char *job_status_to_str(int stat) */ const char *job_type_to_str(int type) { - const char *str; + const char *str = NULL; switch (type) { case JT_BACKUP: str = _("Backup"); break; + case JT_MIGRATED_JOB: + str = _("Migrated Job"); + break; case JT_VERIFY: str = _("Verify"); break; case JT_RESTORE: str = _("Restore"); break; + case JT_CONSOLE: + str = _("Console"); + break; + case JT_SYSTEM: + str = _("System or Console"); + break; case JT_ADMIN: str = _("Admin"); break; - case JT_MIGRATE: - str = _("Migrate"); + case JT_ARCHIVE: + str = _("Archive"); + break; + case JT_JOB_COPY: + str = _("Job Copy"); break; case JT_COPY: str = _("Copy"); break; - default: - str = _("Unknown Type"); + case JT_MIGRATE: + str = _("Migrate"); + break; + case JT_SCAN: + str = _("Scan"); break; } + if (!str) { + str = _("Unknown Type"); + } return str; } +/* Convert ActionOnPurge to string (Truncate, Erase, Destroy) + */ +char *action_on_purge_to_string(int aop, POOL_MEM &ret) +{ + if (aop & ON_PURGE_TRUNCATE) { + pm_strcpy(ret, _("Truncate")); + } + if (!aop) { + pm_strcpy(ret, _("None")); + } + return ret.c_str(); +} + /* * Convert Job Level into a string */ @@ -331,6 +445,9 @@ const char *job_level_to_str(int level) case L_VERIFY_DATA: str = _("Verify Data"); break; + case L_VIRTUAL_FULL: + str = _("Virtual Full"); + break; case L_NONE: str = " "; break; @@ -341,6 +458,33 @@ const char *job_level_to_str(int level) return str; } +const char *volume_status_to_str(const char *status) +{ + int pos; + const char *vs[] = { + NT_("Append"), _("Append"), + NT_("Archive"), _("Archive"), + NT_("Disabled"), _("Disabled"), + NT_("Full"), _("Full"), + NT_("Used"), _("Used"), + NT_("Cleaning"), _("Cleaning"), + NT_("Purged"), _("Purged"), + NT_("Recycle"), _("Recycle"), + NT_("Read-Only"), _("Read-Only"), + NT_("Error"), _("Error"), + NULL, NULL}; + + if (status) { + for (pos = 0 ; vs[pos] ; pos += 2) { + if ( !strcmp(vs[pos],status) ) { + return vs[pos+1]; + } + } + } + + return _("Invalid volume status"); +} + /*********************************************************************** * Encode the mode bits into a 10 character string like LS does @@ -371,7 +515,18 @@ char *encode_mode(mode_t mode, char *buf) return cp; } +#if defined(HAVE_WIN32) +int do_shell_expansion(char *name, int name_len) +{ + char *src = bstrdup(name); + + ExpandEnvironmentStrings(src, name, name_len); + + free(src); + return 1; +} +#else int do_shell_expansion(char *name, int name_len) { static char meta[] = "~\\$[]*?`'<>\""; @@ -417,6 +572,7 @@ int do_shell_expansion(char *name, int name_len) } return 1; } +#endif /* MAKESESSIONKEY -- Generate session key with optional start @@ -428,66 +584,124 @@ int do_shell_expansion(char *name, int name_len) void make_session_key(char *key, char *seed, int mode) { - int j, k; - struct MD5Context md5c; - unsigned char md5key[16], md5key1[16]; - char s[1024]; - - s[0] = 0; - if (seed != NULL) { - bstrncat(s, seed, sizeof(s)); - } + int j, k; + struct MD5Context md5c; + unsigned char md5key[16], md5key1[16]; + char s[1024]; + +#define ss 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 - 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. */ - - sprintf(s + strlen(s), "%lu", (unsigned long)getpid()); - sprintf(s + strlen(s), "%lu", (unsigned long)getppid()); - (void)getcwd(s + strlen(s), 256); - sprintf(s + strlen(s), "%lu", (unsigned long)clock()); - sprintf(s + strlen(s), "%lu", (unsigned long)time(NULL)); + s[0] = 0; + if (seed != NULL) { + 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 + 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. */ + +#if defined(HAVE_WIN32) + { + LARGE_INTEGER li; + DWORD length; + FILETIME ft; + char *p; + + p = s; + bsnprintf(s + strlen(s), ss, "%lu", (uint32_t)GetCurrentProcessId()); + (void)getcwd(s + strlen(s), 256); + bsnprintf(s + strlen(s), ss, "%lu", (uint32_t)GetTickCount()); + QueryPerformanceCounter(&li); + bsnprintf(s + strlen(s), ss, "%lu", (uint32_t)li.LowPart); + GetSystemTimeAsFileTime(&ft); + bsnprintf(s + strlen(s), ss, "%lu", (uint32_t)ft.dwLowDateTime); + bsnprintf(s + strlen(s), ss, "%lu", (uint32_t)ft.dwHighDateTime); + length = 256; + GetComputerName(s + strlen(s), &length); + length = 256; + GetUserName(s + strlen(s), &length); + } +#else + bsnprintf(s + strlen(s), ss, "%lu", (uint32_t)getpid()); + bsnprintf(s + strlen(s), ss, "%lu", (uint32_t)getppid()); + (void)getcwd(s + strlen(s), 256); + bsnprintf(s + strlen(s), ss, "%lu", (uint32_t)clock()); + bsnprintf(s + strlen(s), ss, "%lu", (uint32_t)time(NULL)); #if defined(Solaris) - sysinfo(SI_HW_SERIAL,s + strlen(s), 12); + sysinfo(SI_HW_SERIAL,s + strlen(s), 12); #endif #if defined(HAVE_GETHOSTID) - sprintf(s + strlen(s), "%lu", (unsigned long) gethostid()); + bsnprintf(s + strlen(s), ss, "%lu", (uint32_t) gethostid()); +#endif + gethostname(s + strlen(s), 256); + bsnprintf(s + strlen(s), ss, "%lu", (uint32_t)getuid()); + bsnprintf(s + strlen(s), ss, "%lu", (uint32_t)getgid()); #endif - gethostname(s + strlen(s), 256); - sprintf(s + strlen(s), "%u", (unsigned)getuid()); - sprintf(s + strlen(s), "%u", (unsigned)getgid()); - MD5Init(&md5c); - MD5Update(&md5c, (unsigned char *)s, strlen(s)); - MD5Final(md5key, &md5c); - sprintf(s + strlen(s), "%lu", (unsigned long)((time(NULL) + 65121) ^ 0x375F)); - MD5Init(&md5c); - MD5Update(&md5c, (unsigned char *)s, strlen(s)); - MD5Final(md5key1, &md5c); + MD5Init(&md5c); + MD5Update(&md5c, (uint8_t *)s, strlen(s)); + MD5Final(md5key, &md5c); + bsnprintf(s + strlen(s), ss, "%lu", (uint32_t)((time(NULL) + 65121) ^ 0x375F)); + MD5Init(&md5c); + MD5Update(&md5c, (uint8_t *)s, strlen(s)); + MD5Final(md5key1, &md5c); #define nextrand (md5key[j] ^ md5key1[j]) - if (mode) { - for (j = k = 0; j < 16; j++) { - unsigned char rb = nextrand; + if (mode) { + 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) { - key[k++] = '-'; - } - } - key[--k] = 0; - } else { - for (j = 0; j < 16; j++) { - key[j] = nextrand; + if (j & 1) { + key[k++] = '-'; } } + key[--k] = 0; + } else { + for (j = 0; j < 16; j++) { + key[j] = nextrand; + } + } } #undef nextrand +void encode_session_key(char *encode, char *session, char *key, int maxlen) +{ + int i; + for (i=0; (i < maxlen-1) && session[i]; i++) { + if (session[i] == '-') { + encode[i] = '-'; + } else { + encode[i] = ((session[i] - 'A' + key[i]) & 0xF) + 'A'; + } + } + encode[i] = 0; + Dmsg3(000, "Session=%s key=%s encode=%s\n", session, key, encode); +} + +void decode_session_key(char *decode, char *session, char *key, int maxlen) +{ + int i, x; + + for (i=0; (i < maxlen-1) && session[i]; i++) { + if (session[i] == '-') { + decode[i] = '-'; + } else { + x = (session[i] - 'A' - key[i]) & 0xF; + if (x < 0) { + x += 16; + } + decode[i] = x + 'A'; + } + } + decode[i] = 0; + Dmsg3(000, "Session=%s key=%s decode=%s\n", session, key, decode); +} + /* @@ -504,17 +718,19 @@ void make_session_key(char *key, char *seed, int mode) * %t = Job type (Backup, ...) * %r = Recipients * %v = Volume name + * %b = Job Bytes + * %f = Job Files * * omsg = edited output message * imsg = input string containing edit codes (%x) * to = recepients list * */ -POOLMEM *edit_job_codes(JCR *jcr, char *omsg, char *imsg, const char *to) +POOLMEM *edit_job_codes(JCR *jcr, char *omsg, char *imsg, const char *to, job_code_callback_t callback) { char *p, *q; const char *str; - char add[20]; + char add[50]; char name[MAX_NAME_LENGTH]; int i; @@ -560,7 +776,7 @@ POOLMEM *edit_job_codes(JCR *jcr, char *omsg, char *imsg, const char *to) break; case 'l': if (jcr) { - str = job_level_to_str(jcr->JobLevel); + str = job_level_to_str(jcr->getJobLevel()); } else { str = _("*none*"); } @@ -589,9 +805,15 @@ POOLMEM *edit_job_codes(JCR *jcr, char *omsg, char *imsg, const char *to) str = _("*none*"); } break; + case 'f': /* Job Files */ + str = edit_uint64(jcr->JobFiles, add); + break; + case 'b': /* Job Bytes */ + str = edit_uint64(jcr->JobBytes, add); + break; case 't': if (jcr) { - str = job_type_to_str(jcr->JobType); + str = job_type_to_str(jcr->getJobType()); } else { str = _("*none*"); } @@ -608,10 +830,17 @@ POOLMEM *edit_job_codes(JCR *jcr, char *omsg, char *imsg, const char *to) } break; default: - add[0] = '%'; - add[1] = *p; - add[2] = 0; - str = add; + str = NULL; + if (callback != NULL) { + str = callback(jcr, p); + } + + if (!str) { + add[0] = '%'; + add[1] = *p; + add[2] = 0; + str = add; + } break; } } else { @@ -643,3 +872,15 @@ void set_working_directory(char *wd) } working_directory = wd; /* set global */ } + +const char *last_path_separator(const char *str) +{ + if (*str != '\0') { + for (const char *p = &str[strlen(str) - 1]; p >= str; p--) { + if (IsPathSeparator(*p)) { + return p; + } + } + } + return NULL; +}