From 9966f06b045f4dfa163830e19a7f8e9190f3ccac Mon Sep 17 00:00:00 2001 From: Kern Sibbald Date: Mon, 18 Jun 2012 14:28:55 +0200 Subject: [PATCH] Back port fixes from BEE to fix Windows bug #1892 --- bacula/src/filed/backup.c | 13 +- bacula/src/filed/job.c | 56 +-- bacula/src/jcr.h | 1 + bacula/src/win32/compat/compat.cpp | 15 + bacula/src/win32/compat/mingwconfig.h | 6 +- bacula/src/win32/compat/winconfig.h | 638 ------------------------- bacula/src/win32/filed/vss.cpp | 21 +- bacula/src/win32/filed/vss.h | 11 +- bacula/src/win32/filed/vss_generic.cpp | 495 +++++++++++-------- bacula/src/win32/winapi.h | 3 +- 10 files changed, 350 insertions(+), 909 deletions(-) delete mode 100644 bacula/src/win32/compat/winconfig.h diff --git a/bacula/src/filed/backup.c b/bacula/src/filed/backup.c index a17e8ceb3f..080e4cf2e9 100644 --- a/bacula/src/filed/backup.c +++ b/bacula/src/filed/backup.c @@ -535,7 +535,7 @@ int save_file(JCR *jcr, FF_PKT *ff_pkt, bool top_level) set_portable_backup(&ff_pkt->bfd); /* disable Win32 BackupRead() */ } - if (ff_pkt->cmd_plugin && !ff_pkt->no_read) { + if (ff_pkt->cmd_plugin) { do_plugin_set = true; /* option and cmd plugin are not compatible together */ @@ -602,7 +602,7 @@ int save_file(JCR *jcr, FF_PKT *ff_pkt, bool top_level) do_read = true; } - if (ff_pkt->cmd_plugin) { + if (ff_pkt->cmd_plugin && !ff_pkt->no_read) { do_read = true; } @@ -1098,12 +1098,16 @@ static int send_data(JCR *jcr, int stream, FF_PKT *ff_pkt, DIGEST *digest, #ifdef HAVE_LZO /** Do compression if turned on */ if (ff_pkt->flags & FO_COMPRESS && ff_pkt->Compress_algo == COMPRESS_LZO1X && jcr->LZO_compress_workset) { + lzo_uint len; /* TODO: See with the latest patch how to handle lzo_uint with 64bit */ + ser_declare; ser_begin(cbuf, sizeof(comp_stream_header)); Dmsg3(400, "cbuf=0x%x rbuf=0x%x len=%u\n", cbuf, rbuf, sd->msglen); - lzores = lzo1x_1_compress((const unsigned char*)rbuf, sd->msglen, cbuf2, &compress_len, jcr->LZO_compress_workset); + lzores = lzo1x_1_compress((const unsigned char*)rbuf, sd->msglen, cbuf2, + &len, jcr->LZO_compress_workset); + compress_len = len; if (lzores == LZO_E_OK && compress_len <= max_compress_len) { /* complete header */ @@ -1536,10 +1540,11 @@ static void close_vss_backup_session(JCR *jcr) Jmsg(jcr, msg_type, 0, _("VSS Writer (BackupComplete): %s\n"), g_pVSSClient->GetWriterInfo(i)); } } + /* Generate Job global writer metadata */ WCHAR *metadata = g_pVSSClient->GetMetadata(); if (metadata) { FF_PKT *ff_pkt = jcr->ff; - ff_pkt->fname = (char *)"job"; + ff_pkt->fname = (char *)"*all*"; /* for all plugins */ ff_pkt->type = FT_RESTORE_FIRST; ff_pkt->LinkFI = 0; ff_pkt->object_name = (char *)"job_metadata.xml"; diff --git a/bacula/src/filed/job.c b/bacula/src/filed/job.c index 4a6f8c36a4..d7a44543a6 100644 --- a/bacula/src/filed/job.c +++ b/bacula/src/filed/job.c @@ -84,7 +84,6 @@ static int session_cmd(JCR *jcr); static int response(JCR *jcr, BSOCK *sd, char *resp, const char *cmd); static void filed_free_jcr(JCR *jcr); static int open_sd_read_session(JCR *jcr); -static int send_bootstrap_file(JCR *jcr); static int runscript_cmd(JCR *jcr); static int runbefore_cmd(JCR *jcr); static int runafter_cmd(JCR *jcr); @@ -188,7 +187,6 @@ static char OK_close[] = "3000 OK close Status = %d\n"; static char OK_open[] = "3000 OK open ticket = %d\n"; static char OK_data[] = "3000 OK data\n"; static char OK_append[] = "3000 OK append data\n"; -static char OKSDbootstrap[]= "3000 OK bootstrap\n"; /* Commands sent to Storage Daemon */ @@ -765,9 +763,7 @@ static int restore_object_cmd(JCR *jcr) /* we still need to do this to detect a vss restore */ if (strcmp(rop.object_name, "job_metadata.xml") == 0) { Dmsg0(100, "got job metadata\n"); - //free_and_null_pool_memory(jcr->job_metadata); - jcr->job_metadata = rop.object; /* this is like a boolean in the restore case */ - // rop.object = NULL; /* but not this */ + jcr->got_metadata = true; } generate_plugin_event(jcr, bEventRestoreObject, (void *)&rop); @@ -2119,8 +2115,7 @@ static int restore_cmd(JCR *jcr) * No need to enable VSS for restore if we do not have plugin * data to restore */ - enable_vss = jcr->job_metadata != NULL; - jcr->job_metadata = NULL; + enable_vss = jcr->got_metadata; Dmsg2(50, "g_pVSSClient = %p, enable_vss = %d\n", g_pVSSClient, enable_vss); // capture state here, if client is backed up by multiple directors @@ -2271,7 +2266,6 @@ bail_out: dir->fsend(OKstoreend); ret = 1; /* we continue the loop, waiting for next part */ } else { - end_restore_cmd(jcr); ret = 0; /* we stop here */ } @@ -2279,6 +2273,9 @@ bail_out: ret = 0; /* we stop here */ } + if (ret == 0) { + end_restore_cmd(jcr); /* stopping so send bEventEndRestoreJob */ + } return ret; } @@ -2323,10 +2320,6 @@ static int open_sd_read_session(JCR *jcr) return 0; } - if (!send_bootstrap_file(jcr)) { - return 0; - } - /* * Start read of data with Storage daemon */ @@ -2395,42 +2388,3 @@ int response(JCR *jcr, BSOCK *sd, char *resp, const char *cmd) } return 0; } - -static int send_bootstrap_file(JCR *jcr) -{ - FILE *bs; - char buf[2000]; - BSOCK *sd = jcr->store_bsock; - const char *bootstrap = "bootstrap\n"; - int stat = 0; - - Dmsg1(400, "send_bootstrap_file: %s\n", jcr->RestoreBootstrap); - if (!jcr->RestoreBootstrap) { - return 1; - } - bs = fopen(jcr->RestoreBootstrap, "rb"); - if (!bs) { - berrno be; - Jmsg(jcr, M_FATAL, 0, _("Could not open bootstrap file %s: ERR=%s\n"), - jcr->RestoreBootstrap, be.bstrerror()); - jcr->setJobStatus(JS_ErrorTerminated); - goto bail_out; - } - sd->msglen = pm_strcpy(sd->msg, bootstrap); - sd->send(); - while (fgets(buf, sizeof(buf), bs)) { - sd->msglen = Mmsg(sd->msg, "%s", buf); - sd->send(); - } - sd->signal(BNET_EOD); - fclose(bs); - if (!response(jcr, sd, OKSDbootstrap, "Bootstrap")) { - jcr->setJobStatus(JS_ErrorTerminated); - goto bail_out; - } - stat = 1; - -bail_out: - free_bootstrap(jcr); - return stat; -} diff --git a/bacula/src/jcr.h b/bacula/src/jcr.h index 10a40c14dc..3aecc9e75f 100644 --- a/bacula/src/jcr.h +++ b/bacula/src/jcr.h @@ -410,6 +410,7 @@ public: CRYPTO_CTX crypto; /* Crypto ctx */ DIRRES* director; /* Director resource */ bool VSS; /* VSS used by FD */ + bool got_metadata; /* set when found job_metadata */ bool multi_restore; /* Dir can do multiple storage restore */ htable *file_list; /* Previous file list (accurate mode) */ uint64_t base_size; /* compute space saved with base job */ diff --git a/bacula/src/win32/compat/compat.cpp b/bacula/src/win32/compat/compat.cpp index 48446aac26..17e279b86b 100644 --- a/bacula/src/win32/compat/compat.cpp +++ b/bacula/src/win32/compat/compat.cpp @@ -2733,3 +2733,18 @@ void LogErrorMsg(const char *message) DeregisterEventSource(eventHandler); } } + +/* + * Don't allow OS to suspend while backup running + * Note, the OS automatically tracks these for each thread + */ +void prevent_os_suspensions() +{ + /* not in mingw */ +// SetThreadExecutionState(ES_CONTINUOUS | ES_SYSTEM_REQUIRED); +} + +void allow_os_suspensions() +{ +// SetThreadExecutionState(ES_CONTINUOUS); +} diff --git a/bacula/src/win32/compat/mingwconfig.h b/bacula/src/win32/compat/mingwconfig.h index 2d408bf012..2b29c6498b 100644 --- a/bacula/src/win32/compat/mingwconfig.h +++ b/bacula/src/win32/compat/mingwconfig.h @@ -49,13 +49,13 @@ /* #undef HAVE_SYS_BITYPES_H */ /* Define if you have zlib */ -/* #define HAVE_LIBZ 1 */ +#define HAVE_LIBZ 1 /* Define if you have lzo lib */ -/* #define HAVE_LZO 1 */ +/* #define HAVE_LZO 1 */ /* Define to 1 if you have the header file. */ -/* #define HAVE_LZO_LZOCONF_H 1 */ +/* #define HAVE_LZO_LZOCONF_H 1 */ /* File daemon specif libraries */ diff --git a/bacula/src/win32/compat/winconfig.h b/bacula/src/win32/compat/winconfig.h deleted file mode 100644 index 29f48a0f75..0000000000 --- a/bacula/src/win32/compat/winconfig.h +++ /dev/null @@ -1,638 +0,0 @@ -/* - * This file was originally generated by configure, but has been edited - * to provide the correct defines for the Native Win32 build under - * Visual Studio. - * - * Note!!! We normally do NOT build the Windows versions with this header - * file. We use the Mingw environment defined in mingwconfig.h. - */ -/* ------------------------------------------------------------------------- */ -/* -- CONFIGURE SPECIFIED FEATURES -- */ -/* ------------------------------------------------------------------------- */ - -#ifndef __WINCONFIG_H -#define __WINCONFIG_H - -#define HAVE_OPENSSL 1 -#define HAVE_CRYPTO 1 -#define HAVE_TLS 1 - -/* Define if you want to use MySQL as Catalog database */ -/* #undef USE_MYSQL_DB */ - -/* Define if you want SmartAlloc debug code enabled */ -#define SMARTALLOC 1 - -/* Define to `int' if doesn't define. */ -/* #undef daddr_t */ - -/* Define to `int' if doesn't define. */ -#define major_t int - -/* Define to `int' if doesn't define. */ -#define minor_t int - -/* Define to `int' if doesn't define. */ -/* #undef ssize_t */ - -/* Define if you want to use MySQL */ -/* #define HAVE_MYSQL 1 */ - -/* Define if you want to use embedded MySQL */ -/* #undef HAVE_EMBEDDED_MYSQL */ - -/* Define if you want to use SQLite3 */ -/* #undef HAVE_SQLITE3 */ - -/* Define if you want to use Berkeley DB */ -/* #undef HAVE_BERKELEY_DB */ - - -/* Define if you want to use PostgreSQL */ -/* #undef HAVE_PGSQL */ - -/* ------------------------------------------------------------------------- */ -/* -- CONFIGURE DETECTED FEATURES -- */ -/* ------------------------------------------------------------------------- */ - -/* Define if you need function prototypes */ -#define PROTOTYPES 1 - -/* Define if you have XPointer typedef */ -/* #undef HAVE_XPOINTER */ - -/* Define if you have _GNU_SOURCE getpt() */ -/* #undef HAVE_GETPT */ - -/* Define if you have GCC */ -/* #undef HAVE_GCC 1 */ - -/* Define if you have the Andrew File System. */ -/* #undef AFS */ - -/* Define If you want find -nouser and -nogroup to make tables of - used UIDs and GIDs at startup instead of using getpwuid or - getgrgid when needed. Speeds up -nouser and -nogroup unless you - are running NIS or Hesiod, which make password and group calls - very expensive. */ -/* #undef CACHE_IDS */ - -/* Define to use SVR4 statvfs to get filesystem type. */ -/* #undef FSTYPE_STATVFS */ - -/* Define to use SVR3.2 statfs to get filesystem type. */ -/* #undef FSTYPE_USG_STATFS */ - -/* Define to use AIX3 statfs to get filesystem type. */ -/* #undef FSTYPE_AIX_STATFS */ - -/* Define to use 4.3BSD getmntent to get filesystem type. */ -/* #undef FSTYPE_MNTENT 1 */ - -/* Define to use 4.4BSD and TRU64 statfs to get filesystem type. */ -/* #undef FSTYPE_STATFS */ - -/* Define to use Ultrix getmnt to get filesystem type. */ -/* #undef FSTYPE_GETMNT */ - -/* Define to `unsigned long' if doesn't define. */ -/* #undef dev_t */ - -/* Define to `unsigned long' if doesn't define. */ -/* #undef ino_t */ - -/* Define to 1 if utime.h exists and declares struct utimbuf. */ -#ifdef HAVE_MINGW -#define HAVE_UTIME_H 1 -#endif - -/* Data types */ -#define HAVE_U_INT 1 -#define HAVE_INTXX_T 1 -#define HAVE_U_INTXX_T 1 -/* #undef HAVE_UINTXX_T */ -#define HAVE_INT64_T 1 -#define HAVE_U_INT64_T 1 -#define HAVE_INTMAX_T 1 -/* #undef HAVE_U_INTMAX_T */ - -/* Define if you want TCP Wrappers support */ -/* #undef HAVE_LIBWRAP */ - -/* Define if you have sys/bitypes.h */ -/* #undef HAVE_SYS_BITYPES_H */ - -/* Directory for PID files */ -/* #define _PATH_BACULA_PIDDIR "/var/run" */ -#undef _PATH_BACULA_PIDDIR - -/* Define if you have zlib */ -#define HAVE_LIBZ 1 - -/* General libs */ -/* #undef LIBS */ - -/* File daemon specif libraries */ -#define FDLIBS 1 - -/* Path to Sendmail program */ -/* #undef SENDMAIL_PATH */ - -/* What kind of signals we have */ -/*#define HAVE_POSIX_SIGNALS 1 */ -/* #undef HAVE_BSD_SIGNALS */ -/* #undef HAVE_USG_SIGHOLD */ - -/* Operating systems */ -/* OSes */ -/* #undef HAVE_LINUX_OS */ -/* #undef HAVE_FREEBSD_OS */ -/* #undef HAVE_NETBSD_OS */ -/* #undef HAVE_OPENBSD_OS */ -/* #undef HAVE_BSDI_OS */ -/* #undef HAVE_HPUX_OS */ -/* #undef HAVE_SUN_OS */ -/* #undef HAVE_IRIX_OS */ -/* #undef HAVE_AIX_OS */ -/* #undef HAVE_SGI_OS */ -/* #define HAVE_CYGWIN 1 */ -/* #undef HAVE_OSF1_OS */ -/* #undef HAVE_DARWIN_OS */ - -/* Set to correct scanf value for long long int */ -#define lld "lld" -#define llu "llu" - -/*#define HAVE_READLINE 1 */ - -/* #undef HAVE_GMP */ - -/* #undef HAVE_CWEB */ - -/* #define HAVE_FCHDIR 1 */ - -/* #undef HAVE_GETOPT_LONG */ - -/* #undef HAVE_LIBSM */ - -/* Check for thread safe routines */ -/*#define HAVE_LOCALTIME_R 1 */ -/* #undef HAVE_READDIR_R */ -/*#define HAVE_STRERROR_R 1*/ -/* #undef HAVE_GETHOSTBYNAME_R */ - -#define HAVE_STRTOLL 1 -/* #undef HAVE_INET_PTON */ - -/*#define HAVE_SOCKLEN_T 1 */ - -/* #undef HAVE_OLD_SOCKOPT */ - -/* #undef HAVE_BIGENDIAN */ - -/* Define to 1 if the `closedir' function returns void instead of `int'. */ -/* #undef CLOSEDIR_VOID */ - -/* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP - systems. This function is required for `alloca.c' support on those systems. - */ -/* #undef CRAY_STACKSEG_END */ - -/* Define to 1 if using `alloca.c'. */ -/* #undef C_ALLOCA */ - -/* Define to 1 if you have `alloca', as a function or macro. */ -#define HAVE_ALLOCA 1 -#ifndef HAVE_MINGW -#define alloca _alloca -#endif -/* Define to 1 if you have and it should be used (not on Ultrix). - */ -#define HAVE_ALLOCA_H 1 - -/* Define to 1 if you have the header file. */ -/*#define HAVE_ARPA_NAMESER_H 1 */ - -/* Define to 1 if you have the header file. */ -#define HAVE_ASSERT_H 1 - -/* Define to 1 if you have the `chflags' function. */ -/* #undef HAVE_CHFLAGS */ - -/* Define to 1 if you have the header file, and it defines `DIR'. - */ -#define HAVE_DIRENT_H 1 - -/* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */ -/* #undef HAVE_DOPRNT */ - -/* Define to 1 if you have the `fchdir' function. */ -/*#define HAVE_FCHDIR 1 */ - -/* Define to 1 if you have the header file. */ -#define HAVE_FCNTL_H 1 - -/* Define to 1 if your system has a working POSIX `fnmatch' function. */ -/*#define HAVE_FNMATCH 1 */ - -/* Define to 1 if you have the `fork' function. */ -/*#define HAVE_FORK 1 */ - -/* Define to 1 if you have the `getcwd' function. */ -#define HAVE_GETCWD 1 - -/* Define to 1 if you have the `getdomainname' function. */ -/*#define HAVE_GETDOMAINNAME 1 */ - -/* Define to 1 if you have the `gethostbyname_r' function. */ -/* #undef HAVE_GETHOSTBYNAME_R */ - -/* Define to 1 if you have the `gethostid' function. */ -#define HAVE_GETHOSTID 1 - -/* Define to 1 if you have the `gethostname' function. */ -#define HAVE_GETHOSTNAME 1 - -/* Define to 1 if you have the `getmntent' function. */ -/*#define HAVE_GETMNTENT 1 */ - -/* Define to 1 if you have the `getpid' function. */ -#define HAVE_GETPID 1 -#define getpid _getpid - -/* Define to 1 if you have the `gettimeofday' function. */ -#define HAVE_GETTIMEOFDAY 1 - -/* Define to 1 if you have the header file. */ -/*#define HAVE_GRP_H 1*/ - -/* Define to 1 if you have the `inet_pton' function. */ -/* #undef HAVE_INET_PTON */ - -/* Define to 1 if you have the header file. */ -#define HAVE_INTTYPES_H 1 - -/* Define to 1 if you have the `lchown' function. */ -#define HAVE_LCHOWN 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_LIBC_H */ - -/* Define to 1 if you have the `inet' library (-linet). */ -/* #undef HAVE_LIBINET */ - -/* Define to 1 if you have the `nsl' library (-lnsl). */ -/* #undef HAVE_LIBNSL */ - -/* Define to 1 if you have the `resolv' library (-lresolv). */ -/* #undef HAVE_LIBRESOLV */ - -/* Define to 1 if you have the `socket' library (-lsocket). */ -/* #undef HAVE_LIBSOCKET */ - -/* Define to 1 if you have the `sun' library (-lsun). */ -/* #undef HAVE_LIBSUN */ - -/* Define to 1 if you have the `xnet' library (-lxnet). */ -/* #undef HAVE_LIBXNET */ - -/* Define to 1 if you have the header file. */ -#define HAVE_LIMITS_H 1 - -/* Define to 1 if you have the `localtime_r' function. */ -#define HAVE_LOCALTIME_R 1 - -/* Define to 1 if you have the `lstat' function. */ -#define HAVE_LSTAT 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_MEMORY_H 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_MTIO_H */ - -/* Define to 1 if you have the `nanosleep' function. */ -#define HAVE_NANOSLEEP 1 - -/* Define to 1 if you have the header file, and it defines `DIR'. */ -/* #undef HAVE_NDIR_H */ - -/* Define to 1 if you have the `putenv' function. */ -#define HAVE_PUTENV 1 - -/* Define to 1 if you have the header file. */ -/*#define HAVE_PWD_H 1*/ - -/* Define to 1 if you have the `readdir_r' function. */ -/* #undef HAVE_READDIR_R */ - -/* Define to 1 if you have the header file. */ -/*#define HAVE_RESOLV_H 1*/ - -/* Define to 1 if you have the `select' function. */ -#define HAVE_SELECT 1 - -/* Define to 1 if you have the `setenv' function. */ -#define HAVE_SETENV 1 - -/* Define to 1 if you have the `setlocale' function. */ -#undef HAVE_SETLOCALE - -/* Define to 1 if translation of program messages to the user's native - language is requested. */ -#if (defined _MSC_VER) && (_MSC_VER >= 1400) // VC8+ -/* Enable NLS only if we are using the new VC++. - * NLS should also work with VC++ 7.1, but the Makefiles are - * not adapted to support it (include, lib...). */ -//#define ENABLE_NLS 1 -#endif - -#undef LOCALEDIR -#define LOCALEDIR "." - -#undef HAVE_NL_LANGINFO - -/* Define to 1 if you have the `setpgid' function. */ -#define HAVE_SETPGID 1 - -/* Define to 1 if you have the `setpgrp' function. */ -#define HAVE_SETPGRP 1 - -/* Define to 1 if you have the `setsid' function. */ -#define HAVE_SETSID 1 - -/* Define to 1 if you have the `signal' function. */ -/*#define HAVE_SIGNAL 1 */ - -/* Define to 1 if you have the `snprintf' function. */ -#define HAVE_SNPRINTF 1 -#define HAVE_SNPRINTF_DECL 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_STDARG_H 1 - -/* Define to 1 if you have the header file. */ -/*#define HAVE_STDINT_H 1 */ - -/* Define to 1 if you have the header file. */ -#define HAVE_STDLIB_H 1 - -/* Define to 1 if you have the `strcasecmp' function. */ -/*#define HAVE_STRCASECMP 1*/ - -/* Define to 1 if you have the `strerror' function. */ -#define HAVE_STRERROR 1 - -/* Define to 1 if you have the `strerror_r' function. */ -#define HAVE_STRERROR_R 1 - -/* Define to 1 if you have the `strftime' function. */ -#define HAVE_STRFTIME 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_STRINGS_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_STRING_H 1 - -/* Define to 1 if you have the `strncmp' function. */ -#define HAVE_STRNCMP 1 - -/* Define to 1 if you have the `strncpy' function. */ -#define HAVE_STRNCPY 1 - -/* Define to 1 if you have the `strtoll' function. */ -#define HAVE_STRTOLL 1 - -/* Define to 1 if `st_blksize' is member of `struct stat'. */ -#define HAVE_STRUCT_STAT_ST_BLKSIZE 1 - -/* Define to 1 if `st_blocks' is member of `struct stat'. */ -#define HAVE_STRUCT_STAT_ST_BLOCKS 1 - -/* Define to 1 if `st_rdev' is member of `struct stat'. */ -#define HAVE_STRUCT_STAT_ST_RDEV 1 - -/* Define to 1 if `tm_zone' is member of `struct tm'. */ -/* #undef HAVE_STRUCT_TM_TM_ZONE */ - -/* Define to 1 if your `struct stat' has `st_blksize'. Deprecated, use - `HAVE_STRUCT_STAT_ST_BLKSIZE' instead. */ -#define HAVE_ST_BLKSIZE 1 - -/* Define to 1 if your `struct stat' has `st_blocks'. Deprecated, use - `HAVE_STRUCT_STAT_ST_BLOCKS' instead. */ -#define HAVE_ST_BLOCKS 1 - -/* Define to 1 if your `struct stat' has `st_rdev'. Deprecated, use - `HAVE_STRUCT_STAT_ST_RDEV' instead. */ -#define HAVE_ST_RDEV 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_SYS_BYTEORDER_H */ - -/* Define to 1 if you have the header file, and it defines `DIR'. - */ -/* #undef HAVE_SYS_DIR_H */ - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_IOCTL_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_MTIO_H 1 - -/* Define to 1 if you have the header file, and it defines `DIR'. - */ -/* #undef HAVE_SYS_NDIR_H */ - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_SELECT_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_SOCKET_H 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_SYS_SOCKIO_H */ - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_STAT_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_TIME_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_TYPES_H 1 - -/* Define to 1 if you have that is POSIX.1 compatible. */ -#define HAVE_SYS_WAIT_H 1 - -/* Define to 1 if you have the `tcgetattr' function. */ -#define HAVE_TCGETATTR 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_TERMIOS_H 1 - -/* Define to 1 if your `struct tm' has `tm_zone'. Deprecated, use - `HAVE_STRUCT_TM_TM_ZONE' instead. */ -/* #undef HAVE_TM_ZONE */ - -/* Define to 1 if you don't have `tm_zone' but do have the external array - `tzname'. */ -#define HAVE_TZNAME 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_UNISTD_H 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_VARARGS_H */ - -/* Define to 1 if you have the `vfprintf' function. */ -#define HAVE_VFPRINTF 1 - -/* Define to 1 if you have the `vprintf' function. */ -#define HAVE_VPRINTF 1 - -/* Define to 1 if you have the `vsnprintf' function. */ -#define HAVE_VSNPRINTF 1 -#define HAVE_VSNPRINTF_DECL 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_ZLIB_H 1 - -/* Define to 1 if `major', `minor', and `makedev' are declared in . - */ -/* #undef MAJOR_IN_MKDEV */ - -/* Define to 1 if `major', `minor', and `makedev' are declared in - . */ -/* #undef MAJOR_IN_SYSMACROS */ - -/* Define to 1 if your C compiler doesn't accept -c and -o together. */ -/* #undef NO_MINUS_C_MINUS_O */ - -/* Define to the address where bug reports for this package should be sent. */ -#define PACKAGE_BUGREPORT "" - -/* Define to the full name of this package. */ -#define PACKAGE_NAME "" - -/* Define to the full name and version of this package. */ -#define PACKAGE_STRING "" - -/* Define to the one symbol short name of this package. */ -#define PACKAGE_TARNAME "" - -/* Define to the version of this package. */ -#define PACKAGE_VERSION "" - -/* Define as the return type of signal handlers (`int' or `void'). */ -#define RETSIGTYPE void - -/* Define to 1 if the `setpgrp' function takes no argument. */ -#define SETPGRP_VOID 1 - -/* The size of a `char', as computed by sizeof. */ -#define SIZEOF_CHAR 1 - -/* The size of a `int', as computed by sizeof. */ -#define SIZEOF_INT 4 - -/* The size of a `int *', as computed by sizeof. */ -#define SIZEOF_INT_P 4 - -/* The size of a `long int', as computed by sizeof. */ -#define SIZEOF_LONG 4 - -/* The size of a `long int', as computed by sizeof. */ -#define SIZEOF_LONG_INT 4 - -/* The size of a `long long int', as computed by sizeof. */ -#define SIZEOF_LONG_LONG_INT 8 - -/* The size of a `short int', as computed by sizeof. */ -#define SIZEOF_SHORT_INT 2 - -/* The size of a `void *', as computed by sizeof. */ -#define SIZEOF_VOID_P 4 - -/* The size of a `size_t', as computed by sizeof. */ -#define SIZEOF_SIZE_T 4 - -/* If using the C implementation of alloca, define if you know the - direction of stack growth for your system; otherwise it will be - automatically deduced at run-time. - STACK_DIRECTION > 0 => grows toward higher addresses - STACK_DIRECTION < 0 => grows toward lower addresses - STACK_DIRECTION = 0 => direction of growth unknown */ -/* #undef STACK_DIRECTION */ - -/* Define to 1 if the `S_IS*' macros in do not work properly. */ -/* #undef STAT_MACROS_BROKEN */ - -/* Define to 1 if you have the ANSI C header files. */ -#define STDC_HEADERS 1 - -/* Define to 1 if you can safely include both and . */ -#define TIME_WITH_SYS_TIME 1 - -/* Define to 1 if your declares `struct tm'. */ -/* #undef TM_IN_SYS_TIME */ - -/* Define to 1 if the X Window System is missing or not being used. */ -/* #undef X_DISPLAY_MISSING */ - -/* Define to empty if `const' does not conform to ANSI C. */ -/* #undef const */ - -/* Define to `long' if does not define. */ -/* #undef daddr_t */ - -/* Define to `unsigned long' if does not define. */ -/* #undef dev_t */ - -/* Define to `int' if doesn't define. */ -/* #undef gid_t */ - -/* Define to `unsigned long' if does not define. */ -/* #undef ino_t */ - -/* Define to `int' if does not define. */ -#define major_t int - -/* Define to `int' if does not define. */ -#define minor_t int - -/* Define to `int' if does not define. */ -/* #undef mode_t */ - -/* Define to `long' if does not define. */ -/* #undef off_t */ - -/* Define to `int' if does not define. */ -/* #undef pid_t */ - -/* Define to `unsigned' if does not define. */ -/* #undef size_t */ - -/* Define to `int' if does not define. */ -/* #undef ssize_t */ - -/* Define to `int' if doesn't define. */ -/* #undef uid_t */ - -/* Use long unsigned int for ioctl request */ -#define HAVE_IOCTL_ULINT_REQUEST - -/* Little Endian */ -#define HAVE_LITTLE_ENDIAN 1 - -/* Number of bits in a file offset, on hosts where this is settable. */ -#define _FILE_OFFSET_BITS 64 - -/* Define to make fseeko etc. visible, on some hosts. */ -#define _LARGEFILE_SOURCE 1 - -/* Define for large files, on AIX-style hosts. */ -#define _LARGE_FILES 1 - -#endif /* __WINCONFIG_H */ diff --git a/bacula/src/win32/filed/vss.cpp b/bacula/src/win32/filed/vss.cpp index 376a8eb3f6..a923fb827f 100644 --- a/bacula/src/win32/filed/vss.cpp +++ b/bacula/src/win32/filed/vss.cpp @@ -50,7 +50,6 @@ VSSClient *g_pVSSClient; static const GUID VSS_SWPRV_ProviderID = { 0xb5946137, 0x7b9f, 0x4925, { 0xaf, 0x80, 0x51, 0xab, 0xd6, 0x0b, 0x20, 0xd5 } }; - void VSSCleanup() { @@ -102,17 +101,10 @@ VSSPathConvertW(const wchar_t *szFilePath, wchar_t *szShadowPath, int nBuflen) // Constructor VSSClient::VSSClient() { - m_bCoInitializeCalled = false; - m_bCoInitializeSecurityCalled = false; - m_dwContext = 0; // VSS_CTX_BACKUP; - m_bDuringRestore = false; - m_bBackupIsInitialized = false; - m_pVssObject = NULL; + memset(this, 0, sizeof(VSSClient)); m_pAlistWriterState = New(alist(10, not_owned_by_alist)); m_pAlistWriterInfoText = New(alist(10, owned_by_alist)); m_uidCurrentSnapshotSet = GUID_NULL; - memset(m_wszUniqueVolumeName, 0, sizeof(m_wszUniqueVolumeName)); - memset(m_szShadowCopyName, 0, sizeof(m_szShadowCopyName)); } // Destructor @@ -121,7 +113,7 @@ VSSClient::~VSSClient() // Release the IVssBackupComponents interface // WARNING: this must be done BEFORE calling CoUninitialize() if (m_pVssObject) { - m_pVssObject->Release(); +// m_pVssObject->Release(); m_pVssObject = NULL; } @@ -130,8 +122,9 @@ VSSClient::~VSSClient() delete m_pAlistWriterInfoText; // Call CoUninitialize if the CoInitialize was performed successfully - if (m_bCoInitializeCalled) + if (m_bCoInitializeCalled) { CoUninitialize(); + } } bool VSSClient::InitializeForBackup(JCR *jcr) @@ -142,11 +135,11 @@ bool VSSClient::InitializeForBackup(JCR *jcr) } -bool VSSClient::InitializeForRestore(JCR *jcr, bool (*VssInitCallback)(JCR *, int), WCHAR *job_metadata) +bool VSSClient::InitializeForRestore(JCR *jcr) { - m_metadata = job_metadata; + m_metadata = NULL; m_jcr = jcr; - return Initialize(0, true/*=>Restore*/, VssInitCallback); + return Initialize(0, true/*=>Restore*/); } bool VSSClient::GetShadowPath(const char *szFilePath, char *szShadowPath, int nBuflen) diff --git a/bacula/src/win32/filed/vss.h b/bacula/src/win32/filed/vss.h index 4268bf1a7c..64160863a7 100644 --- a/bacula/src/win32/filed/vss.h +++ b/bacula/src/win32/filed/vss.h @@ -60,7 +60,7 @@ public: // Backup Process bool InitializeForBackup(JCR *jcr); - bool InitializeForRestore(JCR *jcr, bool (*VssInitCallback)(JCR *, int) = NULL, WCHAR *job_metadata = NULL); + bool InitializeForRestore(JCR *jcr); virtual bool CreateSnapshots(char* szDriveLetters) = 0; virtual bool CloseBackup() = 0; virtual bool CloseRestore() = 0; @@ -79,7 +79,7 @@ public: IUnknown *GetVssObject() { return m_pVssObject; }; private: - virtual bool Initialize(DWORD dwContext, bool bDuringRestore = FALSE, bool (*VssInitCallback)(JCR *, int) = NULL) = 0; + virtual bool Initialize(DWORD dwContext, bool bDuringRestore = FALSE) = 0; virtual bool WaitAndCheckForAsyncOperation(IVssAsync* pAsync) = 0; virtual void QuerySnapshotSet(GUID snapshotSetID) = 0; @@ -103,6 +103,7 @@ protected: bool m_bCoInitializeSecurityCalled; bool m_bDuringRestore; /* true if we are doing a restore */ bool m_bBackupIsInitialized; + bool m_bWriterStatusCurrent; WCHAR *m_metadata; }; @@ -122,7 +123,7 @@ public: virtual const char* GetDriverName() { return "Win32 VSS"; }; #endif private: - virtual bool Initialize(DWORD dwContext, bool bDuringRestore, bool (*VssInitCallback)(JCR *, int) = NULL); + virtual bool Initialize(DWORD dwContext, bool bDuringRestore); virtual bool WaitAndCheckForAsyncOperation(IVssAsync* pAsync); virtual void QuerySnapshotSet(GUID snapshotSetID); bool CheckWriterStatus(); @@ -143,7 +144,7 @@ public: virtual const char* GetDriverName() { return "Win32 VSS"; }; #endif private: - virtual bool Initialize(DWORD dwContext, bool bDuringRestore, bool (*VssInitCallback)(JCR *, int) = NULL); + virtual bool Initialize(DWORD dwContext, bool bDuringRestore); virtual bool WaitAndCheckForAsyncOperation(IVssAsync* pAsync); virtual void QuerySnapshotSet(GUID snapshotSetID); bool CheckWriterStatus(); @@ -164,7 +165,7 @@ public: virtual const char* GetDriverName() { return "Win32 VSS"; }; #endif private: - virtual bool Initialize(DWORD dwContext, bool bDuringRestore, bool (*VssInitCallback)(JCR *, int) = NULL); + virtual bool Initialize(DWORD dwContext, bool bDuringRestore); virtual bool WaitAndCheckForAsyncOperation(IVssAsync* pAsync); virtual void QuerySnapshotSet(GUID snapshotSetID); bool CheckWriterStatus(); diff --git a/bacula/src/win32/filed/vss_generic.cpp b/bacula/src/win32/filed/vss_generic.cpp index 7b718e87b7..d3fca1f999 100644 --- a/bacula/src/win32/filed/vss_generic.cpp +++ b/bacula/src/win32/filed/vss_generic.cpp @@ -1,7 +1,7 @@ /* Bacula® - The Network Backup Solution - Copyright (C) 2005-2012 Free Software Foundation Europe e.V. + Copyright (C) 2005-2010 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. @@ -87,7 +87,6 @@ class IXMLDOMDocument; #ifdef B_VSS_XP #define VSSClientGeneric VSSClientXP - #include "inc/WinXP/vss.h" #include "inc/WinXP/vswriter.h" #include "inc/WinXP/vsbackup.h" @@ -96,7 +95,6 @@ class IXMLDOMDocument; #ifdef B_VSS_W2K3 #define VSSClientGeneric VSSClient2003 - #include "inc/Win2003/vss.h" #include "inc/Win2003/vswriter.h" #include "inc/Win2003/vsbackup.h" @@ -104,7 +102,6 @@ class IXMLDOMDocument; #ifdef B_VSS_VISTA #define VSSClientGeneric VSSClientVista - #include "inc/Win2003/vss.h" #include "inc/Win2003/vswriter.h" #include "inc/Win2003/vsbackup.h" @@ -117,9 +114,122 @@ typedef void (APIENTRY* t_VssFreeSnapshotProperties)(IN VSS_SNAPSHOT_PROP*); static t_CreateVssBackupComponents p_CreateVssBackupComponents = NULL; static t_VssFreeSnapshotProperties p_VssFreeSnapshotProperties = NULL; +#include "vss.h" + +static void JmsgVssApiStatus(JCR *jcr, int msg_status, HRESULT hr, const char *apiName) +{ + const char *errmsg; + if (hr == S_OK || hr == VSS_S_ASYNC_FINISHED) { + return; + } + switch (hr) { + case E_INVALIDARG: + errmsg = "One of the parameter values is not valid."; + break; + case E_OUTOFMEMORY: + errmsg = "The caller is out of memory or other system resources."; + break; + case E_ACCESSDENIED: + errmsg = "The caller does not have sufficient backup privileges or is not an administrator."; + break; + case VSS_E_INVALID_XML_DOCUMENT: + errmsg = "The XML document is not valid."; + break; + case VSS_E_OBJECT_NOT_FOUND: + errmsg = "The specified file does not exist."; + break; + case VSS_E_BAD_STATE: + errmsg = "Object is not initialized; called during restore or not called in correct sequence."; + break; + case VSS_E_WRITER_INFRASTRUCTURE: + errmsg = "The writer infrastructure is not operating properly. Check that the Event Service and VSS have been started, and check for errors associated with those services in the error log."; + break; + case VSS_S_ASYNC_CANCELLED: + errmsg = "The asynchronous operation was canceled by a previous call to IVssAsync::Cancel."; + break; + case VSS_S_ASYNC_PENDING: + errmsg = "The asynchronous operation is still running."; + break; + case RPC_E_CHANGED_MODE: + errmsg = "Previous call to CoInitializeEx specified the multithread apartment (MTA). This call indicates single-threaded apartment has occurred."; + break; + case S_FALSE: + errmsg = "No writer found for the current component."; + break; + default: + errmsg = "Unexpected error. The error code is logged in the error log file."; + break; + } + Jmsg(jcr, msg_status, 0, "VSS API failure calling \"%s\". ERR=%s\n", apiName, errmsg); +} + +#ifndef VSS_WS_FAILED_AT_BACKUPSHUTDOWN +#define VSS_WS_FAILED_AT_BACKUPSHUTDOWN (VSS_WRITER_STATE)15 +#endif -#include "vss.h" +static void JmsgVssWriterStatus(JCR *jcr, int msg_status, VSS_WRITER_STATE eWriterStatus, char *writer_name) +{ + const char *errmsg; + + /* The following are normal states */ + if (eWriterStatus == VSS_WS_STABLE || + eWriterStatus == VSS_WS_WAITING_FOR_BACKUP_COMPLETE) { + return; + } + + /* Potential errors */ + switch (eWriterStatus) { + default: + case VSS_WS_UNKNOWN: + errmsg = "The writer's state is not known. This is a writer error."; + break; + case VSS_WS_WAITING_FOR_FREEZE: + errmsg = "The writer is waiting for the freeze state."; + break; + case VSS_WS_WAITING_FOR_THAW: + errmsg = "The writer is waiting for the thaw state."; + break; + case VSS_WS_WAITING_FOR_POST_SNAPSHOT: + errmsg = "The writer is waiting for the PostSnapshot state."; + break; + case VSS_WS_WAITING_FOR_BACKUP_COMPLETE: + errmsg = "The writer is waiting for the requester to finish its backup operation."; + break; + case VSS_WS_FAILED_AT_IDENTIFY: + errmsg = "The writer vetoed the shadow copy creation process at the writer identification state."; + break; + case VSS_WS_FAILED_AT_PREPARE_BACKUP: + errmsg = "The writer vetoed the shadow copy creation process during the backup preparation state."; + break; + case VSS_WS_FAILED_AT_PREPARE_SNAPSHOT: + errmsg = "The writer vetoed the shadow copy creation process during the PrepareForSnapshot state."; + break; + case VSS_WS_FAILED_AT_FREEZE: + errmsg = "The writer vetoed the shadow copy creation process during the freeze state."; + break; + case VSS_WS_FAILED_AT_THAW: + errmsg = "The writer vetoed the shadow copy creation process during the thaw state."; + break; + case VSS_WS_FAILED_AT_POST_SNAPSHOT: + errmsg = "The writer vetoed the shadow copy creation process during the PostSnapshot state."; + break; + case VSS_WS_FAILED_AT_BACKUP_COMPLETE: + errmsg = "The shadow copy has been created and the writer failed during the BackupComplete state."; + break; + case VSS_WS_FAILED_AT_PRE_RESTORE: + errmsg = "The writer failed during the PreRestore state."; + break; + case VSS_WS_FAILED_AT_POST_RESTORE: + errmsg = "The writer failed during the PostRestore state."; + break; + case VSS_WS_FAILED_AT_BACKUPSHUTDOWN: + errmsg = "The writer failed during the shutdown of the backup application."; + + } + Jmsg(jcr, msg_status, 0, "VSS Writer \"%s\" has invalid state. ERR=%s\n", writer_name, errmsg); +} + /* * @@ -131,10 +241,12 @@ static t_VssFreeSnapshotProperties p_VssFreeSnapshotProperties = NULL; // Append a backslash to the current string inline wstring AppendBackslash(wstring str) { - if (str.length() == 0) + if (str.length() == 0) { return wstring(L"\\"); - if (str[str.length() - 1] == L'\\') + } + if (str[str.length() - 1] == L'\\') { return str; + } return str.append(L"\\"); } @@ -153,16 +265,19 @@ inline wstring GetUniqueVolumeNameForPath(wstring path) wchar_t volumeName[MAX_PATH]; wchar_t volumeUniqueName[MAX_PATH]; - if (!p_GetVolumePathNameW || !p_GetVolumePathNameW((LPCWSTR)path.c_str(), volumeRootPath, MAX_PATH)) - return L""; + if (!p_GetVolumePathNameW || !p_GetVolumePathNameW((LPCWSTR)path.c_str(), volumeRootPath, MAX_PATH)) { + return L""; + } // Get the volume name alias (might be different from the unique volume name in rare cases) - if (!p_GetVolumeNameForVolumeMountPointW || !p_GetVolumeNameForVolumeMountPointW(volumeRootPath, volumeName, MAX_PATH)) + if (!p_GetVolumeNameForVolumeMountPointW || !p_GetVolumeNameForVolumeMountPointW(volumeRootPath, volumeName, MAX_PATH)) { return L""; + } // Get the unique volume name - if (!p_GetVolumeNameForVolumeMountPointW(volumeName, volumeUniqueName, MAX_PATH)) + if (!p_GetVolumeNameForVolumeMountPointW(volumeName, volumeUniqueName, MAX_PATH)) { return L""; + } return volumeUniqueName; } @@ -194,7 +309,6 @@ inline const wchar_t* GetStringFromWriterStatus(VSS_WRITER_STATE eWriterStatus) CHECK_CASE_FOR_CONSTANT(VSS_WS_FAILED_AT_BACKUP_COMPLETE); CHECK_CASE_FOR_CONSTANT(VSS_WS_FAILED_AT_PRE_RESTORE); CHECK_CASE_FOR_CONSTANT(VSS_WS_FAILED_AT_POST_RESTORE); - default: return L"Error or Undefined"; } @@ -226,20 +340,21 @@ VSSClientGeneric::VSSClientGeneric() // Destructor VSSClientGeneric::~VSSClientGeneric() { - if (m_hLib) + if (m_hLib) { FreeLibrary(m_hLib); + } } // Initialize the COM infrastructure and the internal pointers -bool VSSClientGeneric::Initialize(DWORD dwContext, bool bDuringRestore, - bool (*VssInitCallback)(JCR *, int)) +bool VSSClientGeneric::Initialize(DWORD dwContext, bool bDuringRestore) { CComPtr pAsync1; VSS_BACKUP_TYPE backup_type; + IVssBackupComponents* pVssObj = (IVssBackupComponents*)m_pVssObject; if (!(p_CreateVssBackupComponents && p_VssFreeSnapshotProperties)) { - Dmsg2(0, "VSSClientGeneric::Initialize: p_CreateVssBackupComponents = 0x%08X, p_VssFreeSnapshotProperties = 0x%08X\n", p_CreateVssBackupComponents, p_VssFreeSnapshotProperties); - errno = ENOSYS; + Dmsg2(0, "VSSClientGeneric::Initialize: p_CreateVssBackupComponents=0x%08X, p_VssFreeSnapshotProperties=0x%08X\n", p_CreateVssBackupComponents, p_VssFreeSnapshotProperties); + Jmsg(m_jcr, M_FATAL, 0, "Entry point CreateVssBackupComponents or VssFreeSnapshotProperties missing.\n"); return false; } @@ -249,6 +364,7 @@ bool VSSClientGeneric::Initialize(DWORD dwContext, bool bDuringRestore, hr = CoInitialize(NULL); if (FAILED(hr)) { Dmsg1(0, "VSSClientGeneric::Initialize: CoInitialize returned 0x%08X\n", hr); + JmsgVssApiStatus(m_jcr, M_FATAL, hr, "CoInitialize"); errno = b_errno_win32; return false; } @@ -272,50 +388,58 @@ bool VSSClientGeneric::Initialize(DWORD dwContext, bool bDuringRestore, if (FAILED(hr)) { Dmsg1(0, "VSSClientGeneric::Initialize: CoInitializeSecurity returned 0x%08X\n", hr); + JmsgVssApiStatus(m_jcr, M_FATAL, hr, "CoInitializeSecurity"); errno = b_errno_win32; return false; } m_bCoInitializeSecurityCalled = true; } - // Release the IVssBackupComponents interface - if (m_pVssObject) { - m_pVssObject->Release(); + // Release the any old IVssBackupComponents interface + if (pVssObj) { + pVssObj->Release(); m_pVssObject = NULL; } - // Create the internal backup components object - hr = p_CreateVssBackupComponents((IVssBackupComponents**) &m_pVssObject); + // Create new internal backup components object + hr = p_CreateVssBackupComponents((IVssBackupComponents**)&m_pVssObject); if (FAILED(hr)) { - Dmsg1(0, "VSSClientGeneric::Initialize: CreateVssBackupComponents returned 0x%08X.\n", - hr); + berrno be; + Dmsg2(0, "VSSClientGeneric::Initialize: CreateVssBackupComponents returned 0x%08X. ERR=%s\n", + hr, be.bstrerror(b_errno_win32)); + JmsgVssApiStatus(m_jcr, M_FATAL, hr, "CreateVssBackupComponents"); errno = b_errno_win32; return false; } + /* Define shorthand VssObject with time */ + pVssObj = (IVssBackupComponents*)m_pVssObject; + + + if (!bDuringRestore) { #if defined(B_VSS_W2K3) || defined(B_VSS_VISTA) - if (dwContext != VSS_CTX_BACKUP) { - hr = ((IVssBackupComponents*) m_pVssObject)->SetContext(dwContext); - if (FAILED(hr)) { - Dmsg1(0, "VSSClientGeneric::Initialize: IVssBackupComponents->SetContext returned 0x%08X\n", hr); - errno = b_errno_win32; - return false; + if (dwContext != VSS_CTX_BACKUP) { + hr = pVssObj->SetContext(dwContext); + if (FAILED(hr)) { + Dmsg1(0, "VSSClientGeneric::Initialize: IVssBackupComponents->SetContext returned 0x%08X\n", hr); + JmsgVssApiStatus(m_jcr, M_FATAL, hr, "SetContext"); + errno = b_errno_win32; + return false; + } } - } #endif - if (!bDuringRestore) { // 1. InitializeForBackup - hr = ((IVssBackupComponents*) m_pVssObject)->InitializeForBackup(); + hr = pVssObj->InitializeForBackup(); if (FAILED(hr)) { Dmsg1(0, "VSSClientGeneric::Initialize: IVssBackupComponents->InitializeForBackup returned 0x%08X\n", hr); + JmsgVssApiStatus(m_jcr, M_FATAL, hr, "InitializeForBackup"); errno = b_errno_win32; return false; } // 2. SetBackupState - switch (m_jcr->getJobLevel()) - { + switch (m_jcr->getJobLevel()) { case L_FULL: backup_type = VSS_BT_FULL; break; @@ -330,60 +454,25 @@ bool VSSClientGeneric::Initialize(DWORD dwContext, bool bDuringRestore, backup_type = VSS_BT_FULL; break; } - hr = ((IVssBackupComponents*) m_pVssObject)->SetBackupState(true, true, backup_type, false); + hr = pVssObj->SetBackupState(true, true, backup_type, false); /* FIXME: need to support partial files - make last parameter true when done */ if (FAILED(hr)) { Dmsg1(0, "VSSClientGeneric::Initialize: IVssBackupComponents->SetBackupState returned 0x%08X\n", hr); + JmsgVssApiStatus(m_jcr, M_FATAL, hr, "SetBackupState"); errno = b_errno_win32; return false; } // 3. GatherWriterMetaData - hr = ((IVssBackupComponents*) m_pVssObject)->GatherWriterMetadata(&pAsync1.p); + hr = pVssObj->GatherWriterMetadata(&pAsync1.p); if (FAILED(hr)) { Dmsg1(0, "VSSClientGeneric::Initialize: IVssBackupComponents->GatherWriterMetadata returned 0x%08X\n", hr); + JmsgVssApiStatus(m_jcr, M_FATAL, hr, "GatherWriterMetadata"); errno = b_errno_win32; return false; } // Waits for the async operation to finish and checks the result - WaitAndCheckForAsyncOperation(pAsync1.p); - } else { - - /* - * Initialize for restore - */ - - HRESULT hr; - - // 1. InitializeForRestore - hr = ((IVssBackupComponents*) m_pVssObject)->InitializeForRestore(m_metadata); - if (FAILED(hr)) { - Dmsg1(0, "VSSClientGeneric::Initialize: IVssBackupComponents->InitializeForRestore returned 0x%08X\n", hr); - errno = b_errno_win32; - return false; - } - VssInitCallback(m_jcr, VSS_INIT_RESTORE_AFTER_INIT); - - // 2. GatherWriterMetaData - hr = ((IVssBackupComponents*) m_pVssObject)->GatherWriterMetadata(&pAsync1.p); - if (FAILED(hr)) { - Dmsg1(0, "VSSClientGeneric::Initialize: IVssBackupComponents->GatherWriterMetadata returned 0x%08X\n", hr); - errno = b_errno_win32; - return false; - } - WaitAndCheckForAsyncOperation(pAsync1.p); - VssInitCallback(m_jcr, VSS_INIT_RESTORE_AFTER_GATHER); - - // 3. PreRestore - hr = ((IVssBackupComponents*) m_pVssObject)->PreRestore(&pAsync1.p); - if (FAILED(hr)) { - Dmsg1(0, "VSSClientGeneric::Initialize: IVssBackupComponents->PreRestore returned 0x%08X\n", hr); - errno = b_errno_win32; - return false; - } - WaitAndCheckForAsyncOperation(pAsync1.p); - /* get latest info about writer status */ - if (!CheckWriterStatus()) { - Dmsg0(0, "VSSClientGeneric::InitializePostPlugin: Failed to CheckWriterstatus\n"); + if (!WaitAndCheckForAsyncOperation(pAsync1.p)) { + /* Error message already printed */ errno = b_errno_win32; return false; } @@ -414,59 +503,50 @@ bool VSSClientGeneric::WaitAndCheckForAsyncOperation(IVssAsync* pAsync) int queryErrors = 0; do { - if (hrReturned != S_OK) + if (hrReturned != S_OK) { Sleep(1000); - + } hrReturned = S_OK; hr = pAsync->QueryStatus(&hrReturned, NULL); - - if (FAILED(hr)) + if (FAILED(hr)) { queryErrors++; + } } while ((timeout-- > 0) && (hrReturned == VSS_S_ASYNC_PENDING)); - if (hrReturned == VSS_S_ASYNC_FINISHED) + if (hrReturned == VSS_S_ASYNC_FINISHED) { return true; - - -#ifdef xDEBUG - // Check if the async operation succeeded... - if(hrReturned != VSS_S_ASYNC_FINISHED) { - wchar_t *pwszBuffer = NULL; - /* I don't see the usefulness of the following -- KES */ - FormatMessageW( - FORMAT_MESSAGE_ALLOCATE_BUFFER - | FORMAT_MESSAGE_FROM_SYSTEM - | FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, hrReturned, - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), - (LPWSTR)&pwszBuffer, 0, NULL); - - LocalFree(pwszBuffer); - errno = b_errno_win32; } -#endif - + + JmsgVssApiStatus(m_jcr, M_FATAL, hr, "Query Async Status after 10 minute wait"); return false; } bool VSSClientGeneric::CreateSnapshots(char* szDriveLetters) { + IVssBackupComponents *pVssObj; + HRESULT hr; + /* szDriveLetters contains all drive letters in uppercase */ /* if a drive can not being added, it's converted to lowercase in szDriveLetters */ /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vss/base/ivssbackupcomponents_startsnapshotset.asp */ - if (!m_pVssObject || m_bBackupIsInitialized) { + Jmsg(m_jcr, M_FATAL, 0, "No pointer to VssObject or Backup is not Initialized\n"); errno = ENOSYS; return false; } m_uidCurrentSnapshotSet = GUID_NULL; - IVssBackupComponents *pVss = (IVssBackupComponents*)m_pVssObject; + pVssObj = (IVssBackupComponents*)m_pVssObject; /* startSnapshotSet */ - - pVss->StartSnapshotSet(&m_uidCurrentSnapshotSet); + hr = pVssObj->StartSnapshotSet(&m_uidCurrentSnapshotSet); + if (FAILED(hr)) { + JmsgVssApiStatus(m_jcr, M_FATAL, hr, "StartSnapshotSet"); + errno = ENOSYS; + return false; + } + /* AddToSnapshotSet */ @@ -484,37 +564,53 @@ bool VSSClientGeneric::CreateSnapshots(char* szDriveLetters) szDrive[0] = szDriveLetters[i]; volume = GetUniqueVolumeNameForPath(szDrive); // store uniquevolumname - if (SUCCEEDED(pVss->AddToSnapshotSet((LPWSTR)volume.c_str(), GUID_NULL, &pid))) { + if (SUCCEEDED(pVssObj->AddToSnapshotSet((LPWSTR)volume.c_str(), GUID_NULL, &pid))) { wcsncpy (m_wszUniqueVolumeName[szDriveLetters[i]-'A'], (LPWSTR) volume.c_str(), MAX_PATH); } else { - szDriveLetters[i] = tolower (szDriveLetters[i]); + szDriveLetters[i] = tolower(szDriveLetters[i]); } } /* PrepareForBackup */ - if (FAILED(pVss->PrepareForBackup(&pAsync1.p))) { + hr = pVssObj->PrepareForBackup(&pAsync1.p); + if (FAILED(hr)) { + JmsgVssApiStatus(m_jcr, M_FATAL, hr, "PrepareForBackup"); errno = b_errno_win32; return false; } // Waits for the async operation to finish and checks the result - WaitAndCheckForAsyncOperation(pAsync1.p); + if (!WaitAndCheckForAsyncOperation(pAsync1.p)) { + errno = b_errno_win32; + return false; + } /* get latest info about writer status */ if (!CheckWriterStatus()) { - errno = b_errno_win32; + errno = b_errno_win32; /* Error already printed */ return false; } /* DoSnapShotSet */ - if (FAILED(pVss->DoSnapshotSet(&pAsync2.p))) { + hr = pVssObj->DoSnapshotSet(&pAsync2.p); + if (FAILED(hr)) { + JmsgVssApiStatus(m_jcr, M_FATAL, hr, "DoSnapshotSet"); errno = b_errno_win32; return false; } // Waits for the async operation to finish and checks the result - WaitAndCheckForAsyncOperation(pAsync2.p); + if (!WaitAndCheckForAsyncOperation(pAsync2.p)) { + errno = b_errno_win32; + return false; + } + /* get latest info about writer status */ + if (!CheckWriterStatus()) { + errno = b_errno_win32; /* Error already printed */ + return false; + } + /* query snapshot info */ QuerySnapshotSet(m_uidCurrentSnapshotSet); @@ -530,64 +626,63 @@ bool VSSClientGeneric::CloseBackup() bool bRet = false; HRESULT hr; BSTR xml; + IVssBackupComponents* pVssObj = (IVssBackupComponents*)m_pVssObject; - if (!m_pVssObject) + if (!m_pVssObject) { + Jmsg(m_jcr, M_FATAL, 0, "VssOject is NULL.\n"); errno = ENOSYS; - else { - IVssBackupComponents* pVss = (IVssBackupComponents*) m_pVssObject; - CComPtr pAsync; + return bRet; + } + CComPtr pAsync; - SetVSSPathConvert(NULL, NULL); + SetVSSPathConvert(NULL, NULL); - m_bBackupIsInitialized = false; + m_bBackupIsInitialized = false; - hr = pVss->SaveAsXML(&xml); - if (hr == ERROR_SUCCESS) - m_metadata = xml; - else - m_metadata = NULL; -#if 0 -{ - HRESULT hr; - BSTR xml; - int fd; + hr = pVssObj->BackupComplete(&pAsync.p); + if (SUCCEEDED(hr)) { + // Waits for the async operation to finish and checks the result + WaitAndCheckForAsyncOperation(pAsync.p); + bRet = true; + } else { + JmsgVssApiStatus(m_jcr, M_ERROR, hr, "BackupComplete"); + errno = b_errno_win32; + pVssObj->AbortBackup(); + } - hr = pVss->SaveAsXML(&xml); - fd = open("C:\\james.xml", O_CREAT | O_WRONLY | O_TRUNC, 0777); - write(fd, xml, wcslen(xml) * sizeof(WCHAR)); - close(fd); -} -#endif - if (SUCCEEDED(pVss->BackupComplete(&pAsync.p))) { - // Waits for the async operation to finish and checks the result - WaitAndCheckForAsyncOperation(pAsync.p); - bRet = true; - } else { - errno = b_errno_win32; - pVss->AbortBackup(); - } + /* get latest info about writer status */ + CheckWriterStatus(); - /* get latest info about writer status */ - CheckWriterStatus(); + hr = pVssObj->SaveAsXML(&xml); + if (SUCCEEDED(hr)) { + m_metadata = xml; + } else { + m_metadata = NULL; + } - if (m_uidCurrentSnapshotSet != GUID_NULL) { - VSS_ID idNonDeletedSnapshotID = GUID_NULL; - LONG lSnapshots; + /* FIXME?: The docs http://msdn.microsoft.com/en-us/library/aa384582%28v=VS.85%29.aspx say this isn't required... */ + if (m_uidCurrentSnapshotSet != GUID_NULL) { + VSS_ID idNonDeletedSnapshotID = GUID_NULL; + LONG lSnapshots; - pVss->DeleteSnapshots( - m_uidCurrentSnapshotSet, - VSS_OBJECT_SNAPSHOT_SET, - false, - &lSnapshots, - &idNonDeletedSnapshotID); + pVssObj->DeleteSnapshots( + m_uidCurrentSnapshotSet, + VSS_OBJECT_SNAPSHOT_SET, + false, + &lSnapshots, + &idNonDeletedSnapshotID); - m_uidCurrentSnapshotSet = GUID_NULL; - } + m_uidCurrentSnapshotSet = GUID_NULL; + } - pVss->Release(); - m_pVssObject = NULL; + if (m_bWriterStatusCurrent) { + m_bWriterStatusCurrent = false; + pVssObj->FreeWriterStatus(); } + pVssObj->Release(); + m_pVssObject = NULL; + // Call CoUninitialize if the CoInitialize was performed sucesfully if (m_bCoInitializeCalled) { CoUninitialize(); @@ -604,16 +699,17 @@ WCHAR *VSSClientGeneric::GetMetadata() bool VSSClientGeneric::CloseRestore() { - HRESULT hr; - IVssBackupComponents* pVss = (IVssBackupComponents*) m_pVssObject; + //HRESULT hr; + IVssBackupComponents* pVssObj = (IVssBackupComponents*)m_pVssObject; CComPtr pAsync; - if (!pVss) - { + if (!pVssObj) { errno = ENOSYS; return false; } - if (SUCCEEDED(hr = pVss->PostRestore(&pAsync.p))) { +#if 0 +/* done by plugin now */ + if (SUCCEEDED(hr = pVssObj->PostRestore(&pAsync.p))) { // Waits for the async operation to finish and checks the result WaitAndCheckForAsyncOperation(pAsync.p); /* get latest info about writer status */ @@ -625,6 +721,7 @@ bool VSSClientGeneric::CloseRestore() errno = b_errno_win32; return false; } +#endif return true; } @@ -632,28 +729,31 @@ bool VSSClientGeneric::CloseRestore() void VSSClientGeneric::QuerySnapshotSet(GUID snapshotSetID) { if (!(p_CreateVssBackupComponents && p_VssFreeSnapshotProperties)) { + Jmsg(m_jcr, M_FATAL, 0, "CreateVssBackupComponents or VssFreeSnapshotProperties API is NULL.\n"); errno = ENOSYS; return; } - memset (m_szShadowCopyName,0,sizeof (m_szShadowCopyName)); + memset(m_szShadowCopyName,0,sizeof (m_szShadowCopyName)); if (snapshotSetID == GUID_NULL || m_pVssObject == NULL) { + Jmsg(m_jcr, M_FATAL, 0, "snapshotSetID == NULL or VssObject is NULL.\n"); errno = ENOSYS; return; } - IVssBackupComponents* pVss = (IVssBackupComponents*) m_pVssObject; + IVssBackupComponents* pVssObj = (IVssBackupComponents*) m_pVssObject; // Get list all shadow copies. CComPtr pIEnumSnapshots; - HRESULT hr = pVss->Query( GUID_NULL, + HRESULT hr = pVssObj->Query( GUID_NULL, VSS_OBJECT_NONE, VSS_OBJECT_SNAPSHOT, (IVssEnumObject**)(&pIEnumSnapshots) ); // If there are no shadow copies, just return if (FAILED(hr)) { + Jmsg(m_jcr, M_FATAL, 0, "No Volume Shadow copies made.\n"); errno = b_errno_win32; return; } @@ -691,31 +791,47 @@ bool VSSClientGeneric::CheckWriterStatus() /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vss/base/ivssbackupcomponents_startsnapshotset.asp */ - IVssBackupComponents* pVss = (IVssBackupComponents*) m_pVssObject; + IVssBackupComponents* pVssObj = (IVssBackupComponents*)m_pVssObject; + if (!pVssObj) { + Jmsg(m_jcr, M_FATAL, 0, "Cannot get IVssBackupComponents pointer.\n"); + errno = ENOSYS; + return false; + } DestroyWriterInfo(); + if (m_bWriterStatusCurrent) { + m_bWriterStatusCurrent = false; + pVssObj->FreeWriterStatus(); + } // Gather writer status to detect potential errors CComPtr pAsync; - HRESULT hr = pVss->GatherWriterStatus(&pAsync.p); + HRESULT hr = pVssObj->GatherWriterStatus(&pAsync.p); if (FAILED(hr)) { + JmsgVssApiStatus(m_jcr, M_FATAL, hr, "GatherWriterStatus"); errno = b_errno_win32; return false; - } + } // Waits for the async operation to finish and checks the result - WaitAndCheckForAsyncOperation(pAsync.p); + if (!WaitAndCheckForAsyncOperation(pAsync.p)) { + errno = b_errno_win32; + return false; + } + m_bWriterStatusCurrent = true; + unsigned cWriters = 0; - hr = pVss->GetWriterStatusCount(&cWriters); + hr = pVssObj->GetWriterStatusCount(&cWriters); if (FAILED(hr)) { + JmsgVssApiStatus(m_jcr, M_FATAL, hr, "GatherWriterStatusCount"); errno = b_errno_win32; return false; } - - int nState; + int nState; + POOLMEM *szBuf = get_pool_memory(PM_FNAME); // Enumerate each writer for (unsigned iWriter = 0; iWriter < cWriters; iWriter++) { VSS_ID idInstance = GUID_NULL; @@ -725,17 +841,17 @@ bool VSSClientGeneric::CheckWriterStatus() HRESULT hrWriterFailure = S_OK; // Get writer status - hr = pVss->GetWriterStatus(iWriter, + hr = pVssObj->GetWriterStatus(iWriter, &idInstance, &idWriter, &bstrWriterName, &eWriterStatus, &hrWriterFailure); if (FAILED(hr)) { - /* unknown */ - nState = 0; - } - else { + /* Api failed */ + JmsgVssApiStatus(m_jcr, M_WARNING, hr, "GetWriterStatus"); + nState = 0; /* Unknown writer state -- API failed */ + } else { switch(eWriterStatus) { case VSS_WS_FAILED_AT_IDENTIFY: case VSS_WS_FAILED_AT_PREPARE_BACKUP: @@ -749,39 +865,32 @@ bool VSSClientGeneric::CheckWriterStatus() #if defined(B_VSS_W2K3) || defined(B_VSS_VISTA) case VSS_WS_FAILED_AT_BACKUPSHUTDOWN: #endif - /* failed */ - nState = -1; + /* Writer status problem */ + wchar_2_UTF8(&szBuf, bstrWriterName.p); + JmsgVssWriterStatus(m_jcr, M_WARNING, eWriterStatus, szBuf); + nState = -1; /* bad writer state */ break; default: /* ok */ - nState = 1; + nState = 1; /* Writer state OK */ } } /* store text info */ char str[1000]; - char szBuf[200]; bstrncpy(str, "\"", sizeof(str)); - wchar_2_UTF8(szBuf, bstrWriterName.p, sizeof(szBuf)); + wchar_2_UTF8(&szBuf, bstrWriterName.p); bstrncat(str, szBuf, sizeof(str)); bstrncat(str, "\", State: 0x", sizeof(str)); - itoa(eWriterStatus, szBuf, sizeof(szBuf)); + itoa(eWriterStatus, szBuf, sizeof_pool_memory(szBuf)); bstrncat(str, szBuf, sizeof(str)); bstrncat(str, " (", sizeof(str)); - wchar_2_UTF8(szBuf, GetStringFromWriterStatus(eWriterStatus), sizeof(szBuf)); + wchar_2_UTF8(&szBuf, GetStringFromWriterStatus(eWriterStatus)); bstrncat(str, szBuf, sizeof(str)); bstrncat(str, ")", sizeof(str)); - - AppendWriterInfo(nState, (const char *)str); + AppendWriterInfo(nState, (const char *)str); } - - hr = pVss->FreeWriterStatus(); - - if (FAILED(hr)) { - errno = b_errno_win32; - return false; - } - + free_pool_memory(szBuf); errno = 0; return true; } diff --git a/bacula/src/win32/winapi.h b/bacula/src/win32/winapi.h index fcd6c5e699..b4027dc9a3 100644 --- a/bacula/src/win32/winapi.h +++ b/bacula/src/win32/winapi.h @@ -1,7 +1,7 @@ /* Bacula® - The Network Backup Solution - Copyright (C) 2003-2008 Free Software Foundation Europe e.V. + Copyright (C) 2003-2010 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. @@ -67,6 +67,7 @@ typedef char POOLMEM; // "\\?\" to the path. For more information, see Naming a File. #define MAX_PATH_W 32767 +int wchar_2_UTF8(POOLMEM **pszUTF, const wchar_t *pszUCS); 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); -- 2.39.2