From bfc2223cafb2fb3b52e96d06961a35e71494e37e Mon Sep 17 00:00:00 2001 From: Kern Sibbald Date: Wed, 25 Jun 2003 19:56:41 +0000 Subject: [PATCH] Implement Win32 data detection code git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@612 91ce42f0-d328-0410-95d8-f526ca767f89 --- bacula/kernstodo | 55 +++++++++++------------ bacula/src/dird/dird_conf.h | 12 ++--- bacula/src/dird/inc_conf.c | 8 ++-- bacula/src/dird/verify.c | 2 +- bacula/src/filed/backup.c | 40 ++++++++--------- bacula/src/filed/restore.c | 17 ++++++-- bacula/src/filed/verify.c | 2 +- bacula/src/findlib/attribs.c | 80 +++++++++++++++++++++++++-------- bacula/src/findlib/bfile.c | 85 ++++++++++++++++++++++++++++++++---- bacula/src/findlib/bfile.h | 20 ++++----- bacula/src/findlib/find.h | 46 +++++++++---------- bacula/src/findlib/protos.h | 5 ++- bacula/src/lib/Makefile.in | 4 +- bacula/src/lib/bnet.c | 1 + bacula/src/lib/lib.h | 1 + bacula/src/stored/askdir.c | 1 + bacula/src/stored/bextract.c | 12 ++++- bacula/src/stored/block.c | 1 + bacula/src/stored/bls.c | 11 ++++- bacula/src/stored/device.c | 5 +++ bacula/src/stored/mount.c | 14 +++--- bacula/src/version.h | 4 +- 22 files changed, 287 insertions(+), 139 deletions(-) diff --git a/bacula/kernstodo b/bacula/kernstodo index 95e5cdd9c9..9b6222e385 100644 --- a/bacula/kernstodo +++ b/bacula/kernstodo @@ -1,5 +1,5 @@ Kern's ToDo List - 22 June 2003 + 25 June 2003 Documentation to do: (any release a little bit at a time) - Document running a test version. @@ -16,17 +16,15 @@ Documentation to do: (any release a little bit at a time) - Document FInclude ... - Document need to add "-u root" to most of MySQL script calls (./create_mys... ./make_my...). -- Document recycling algorithm. +- Document c:/working directory better than /working directory. Testing to do: (painful) - that ALL console command line options work and are always implemented - blocksize recognition code. -- multiple simultaneous Volumes - Test if rewind at end of tape waits for tape to rewind. - Test cancel at EOM. - Test not zeroing Autochanger slot when it is wrong. -- Test multiple simultaneous Volumes - Test of last block is correct in JobMedia when splitting file over two volumes. - Test recycling and purging (code changed in db_find_next_volume and @@ -34,16 +32,11 @@ Testing to do: (painful) - Figure out how to use ssh or stunnel to protect Bacula communications. For 1.31 release: +- Finish Windows implementation. - Remove multiple simultaneous devices code in SD. - Check that Block number in JobMedia are correct. -- Complain if record dropped in bnet_recv because too long. -- Suppress Job Name in Jmsg for console -- Check Jmsg in bnet, may not work, must dup bsock. -- Use SD returned values in report -- or add them. - Increment DB version prior to releasing. - Turn off FULL_DEBUG prior to releasing. -- Implement forward spacing block/file: position_device(bsr) -- - just before read_block_from_device(); - On Windows with very long path names, it may be impossible to create a file (and thus restore it) because the total length is too long. We must cd into the directory then create the file without the @@ -51,8 +44,6 @@ For 1.31 release: - Move JobFiles and JobBytes to SD rather than FD -- more correct. - Add client name to cram-md5 challenge so Director can immediately verify if it is the correct client. -- Use runbeforejob to unload, then reload a volume previously used, - then the next job run gets an error reading the drive. - lstat() is not going to work on Win32 for testing date. - Implement a Recycle command - Something is not right in last block of fill command. @@ -61,15 +52,30 @@ For 1.31 release: - Check if Incremental is working correctly when it looks for the previous Job (Phil's problem). - Add next Volume to be used to status output. -- Make bootstrap filename unique. - The bsr for Dan's job has file indexes covering the whole range rather than only the range contained on the volume. Constrain FileIndex to be within range for Volume. +- Pass prefix_links to FD. + + +For 1.32: +- Implement new alist in FileSet scanning. +- Add JobLevel in FD status (but make sure it is defined). +- Audit all UA commands to ensure that we always prompt where possible. +- Restrict characters permitted in a Resource name, and don't permit + duplicate names. +- Prohibit backing up archive device (findlib/find_one.c:128) +- Make | and < work on FD side. +- Check Jmsg in bnet, may not work, must dup bsock. +- Suppress Job Name in Jmsg for console +- Create Pools that are referenced in a Run statement at startup if possible. +- Use runbeforejob to unload, then reload a volume previously used, + then the next job run gets an error reading the drive. +- Make bootstrap filename unique. - Test a second language e.g. french. - Start working on Base jobs. - Make "make binary-release" work from any directory. -- Document c:/working directory better than /working directory. -- Unsaved Flag in Job record. +- Unsaved Flag in Job record (use JobMissingFiles). - Base Flag in Job record. - Implement UnsavedFiles DB record. - Implement argc/argv for daemon command line scanning using table driven @@ -77,9 +83,6 @@ For 1.31 release: - Implement table driven single argc/argv scanner to pickup all arguments. Much like xxx_conf.c scan table. keyword, handler(store_routine), store_address, code, flags, default. -- Make | and < work on FD side. -- Pass prefix_links to FD. -- Implement a M_SECURITY message class. - From Phil Stracchino: It would probably be a per-client option, and would be called something like, say, "Automatically purge obsoleted jobs". What it @@ -90,18 +93,12 @@ For 1.31 release: all Differential and Incremental jobs obsoleted by that Full backup. This would let people minimize the number of tapes they're keeping on hand without having to master the art of retention times. -- Prohibit backing up archive device (findlib/find_one.c:128) -- Make Restore report an error if FD or SD term codes are not OK. -- Add JobLevel in FD status (but make sure it is defined). -- Restrict characters permitted in a Resource name, and don't permit - duplicate names. - Implement new serialize subroutines send(socket, "string", &Vol, "uint32", &i, NULL) -- Audit all UA commands to ensure that we always prompt where possible. - Scratch Pool where the volumes can be re-assigned to any Pool. - - -After 1.31: +- Implement a M_SECURITY message class. +- Implement forward spacing block/file: position_device(bsr) -- + just before read_block_from_device(); - When doing a Backup send all attributes back to the Director, who would then figure out what files have been deleted. - Currently in mount.c:236 the SD simply creates a Volume. It should have @@ -1002,4 +999,8 @@ Done: (see kernsdone for more) being close()ed at the appropriate time. - Test long path names (>64 chars) in Windows -- crashes FD? - Implement fast block rejection: match_bsr_block(). +- Complain if record dropped in bnet_recv because too long. +- Test multiple simultaneous Volumes +- Document recycling algorithm. +- Make Restore report an error if FD or SD term codes are not OK. diff --git a/bacula/src/dird/dird_conf.h b/bacula/src/dird/dird_conf.h index 869343b245..817183b1b3 100644 --- a/bacula/src/dird/dird_conf.h +++ b/bacula/src/dird/dird_conf.h @@ -198,12 +198,12 @@ struct JOB { int RescheduleTimes; /* Number of times to reschedule job */ utime_t RescheduleInterval; /* Reschedule interval */ - MSGS *messages; /* How and where to send messages */ - SCHED *schedule; /* When -- Automatic schedule */ - CLIENT *client; /* Who to backup */ - FILESET *fileset; /* What to backup -- Fileset */ - STORE *storage; /* Where is device -- Storage daemon */ - POOL *pool; /* Where is media -- Media Pool */ + MSGS *messages; /* How and where to send messages */ + SCHED *schedule; /* When -- Automatic schedule */ + CLIENT *client; /* Who to backup */ + FILESET *fileset; /* What to backup -- Fileset */ + STORE *storage; /* Where is device -- Storage daemon */ + POOL *pool; /* Where is media -- Media Pool */ semlock_t sem; /* Job semaphore */ }; diff --git a/bacula/src/dird/inc_conf.c b/bacula/src/dird/inc_conf.c index 4dcfe3f156..6c5ea73eb9 100644 --- a/bacula/src/dird/inc_conf.c +++ b/bacula/src/dird/inc_conf.c @@ -250,7 +250,7 @@ void store_inc(LEX *lc, struct res_items *item, int index, int pass) res_all.res_fs.include_items = (INCEXE **)malloc(sizeof(INCEXE *)); } else { res_all.res_fs.include_items = (INCEXE **)realloc(res_all.res_fs.include_items, - sizeof(INCEXE *) * res_all.res_fs.num_includes + 1); + sizeof(INCEXE *) * (res_all.res_fs.num_includes + 1)); } res_all.res_fs.include_items[res_all.res_fs.num_includes++] = incexe; Dmsg1(200, "num_includes=%d\n", res_all.res_fs.num_includes); @@ -259,7 +259,7 @@ void store_inc(LEX *lc, struct res_items *item, int index, int pass) res_all.res_fs.exclude_items = (INCEXE **)malloc(sizeof(INCEXE *)); } else { res_all.res_fs.exclude_items = (INCEXE **)realloc(res_all.res_fs.exclude_items, - sizeof(INCEXE *) * res_all.res_fs.num_excludes + 1); + sizeof(INCEXE *) * (res_all.res_fs.num_excludes + 1)); } res_all.res_fs.exclude_items[res_all.res_fs.num_excludes++] = incexe; Dmsg1(200, "num_excludes=%d\n", res_all.res_fs.num_excludes); @@ -363,7 +363,7 @@ void store_finc(LEX *lc, struct res_items *item, int index, int pass) res_all.res_fs.include_items = (INCEXE **)malloc(sizeof(INCEXE *)); } else { res_all.res_fs.include_items = (INCEXE **)realloc(res_all.res_fs.include_items, - sizeof(INCEXE *) * res_all.res_fs.num_includes + 1); + sizeof(INCEXE *) * (res_all.res_fs.num_includes + 1)); } res_all.res_fs.include_items[res_all.res_fs.num_includes++] = incexe; Dmsg1(200, "num_includes=%d\n", res_all.res_fs.num_includes); @@ -372,7 +372,7 @@ void store_finc(LEX *lc, struct res_items *item, int index, int pass) res_all.res_fs.exclude_items = (INCEXE **)malloc(sizeof(INCEXE *)); } else { res_all.res_fs.exclude_items = (INCEXE **)realloc(res_all.res_fs.exclude_items, - sizeof(INCEXE *) * res_all.res_fs.num_excludes + 1); + sizeof(INCEXE *) * (res_all.res_fs.num_excludes + 1)); } res_all.res_fs.exclude_items[res_all.res_fs.num_excludes++] = incexe; Dmsg1(200, "num_excludes=%d\n", res_all.res_fs.num_excludes); diff --git a/bacula/src/dird/verify.c b/bacula/src/dird/verify.c index 0242b82aa8..b1b4f40b71 100644 --- a/bacula/src/dird/verify.c +++ b/bacula/src/dird/verify.c @@ -497,7 +497,7 @@ int get_attributes_and_compare_to_catalog(JCR *jcr, JobId_t JobId) decode_stat(attr, &statf, &LinkFIf); /* decode file stat packet */ do_SIG = NO_SIG; jcr->fn_printed = FALSE; - strcpy(jcr->fname, fname); /* move filename into JCR */ + pm_strcpy(&jcr->fname, fname); /* move filename into JCR */ Dmsg2(040, "dirdfname); Dmsg1(020, "dirdbfd); - /* Open any file with data that we intend to save */ + /* + * Open any file with data that we intend to save. + * Note, if is_win32_backup, we must open the Directory so that + * the BackupRead will save its permissions and ownership streams. + */ if (ff_pkt->type != FT_LNKSAVED && (S_ISREG(ff_pkt->statp.st_mode) && ff_pkt->statp.st_size > 0) || ff_pkt->type == FT_RAW || ff_pkt->type == FT_FIFO || @@ -217,8 +221,14 @@ static int save_file(FF_PKT *ff_pkt, void *vjcr) } Dmsg1(130, "bfiled: sending %s to stored\n", ff_pkt->fname); - encode_stat(attribs, &ff_pkt->statp, ff_pkt->LinkFI); - stream = encode_attribsEx(jcr, attribsEx, ff_pkt); + + /* Find what data stream we will use, then encode the attributes */ + data_stream = select_data_stream(ff_pkt); + encode_stat(attribs, ff_pkt, data_stream); + + /* Now possibly extend the attributes */ + attr_stream = encode_attribsEx(jcr, attribsEx, ff_pkt); + Dmsg3(200, "File %s\nattribs=%s\nattribsEx=%s\n", ff_pkt->fname, attribs, attribsEx); P(jcr->mutex); @@ -231,7 +241,7 @@ static int save_file(FF_PKT *ff_pkt, void *vjcr) * Send Attributes header to Storage daemon * */ - if (!bnet_fsend(sd, "%ld %d 0", jcr->JobFiles, stream)) { + if (!bnet_fsend(sd, "%ld %d 0", jcr->JobFiles, attr_stream)) { if (is_bopen(&ff_pkt->bfd)) { bclose(&ff_pkt->bfd); } @@ -289,31 +299,15 @@ static int save_file(FF_PKT *ff_pkt, void *vjcr) rbuf = sd->msg; /* read buffer */ wbuf = sd->msg; /* write buffer */ + Dmsg1(100, "Saving data, type=%d\n", ff_pkt->type); - /* Note, no sparse option for win32_data */ - if (is_win32_backup()) { - stream = STREAM_WIN32_DATA; - ff_pkt->flags &= ~FO_SPARSE; - } else if (ff_pkt->flags & FO_SPARSE) { - stream = STREAM_SPARSE_DATA; - } else { - stream = STREAM_FILE_DATA; - } #ifdef HAVE_LIBZ uLong compress_len, max_compress_len = 0; const Bytef *cbuf = NULL; if (ff_pkt->flags & FO_GZIP) { - if (stream == STREAM_WIN32_DATA) { - stream = STREAM_WIN32_GZIP_DATA; - } else if (stream == STREAM_FILE_DATA) { - stream = STREAM_GZIP_DATA; - } else { - stream = STREAM_SPARSE_GZIP_DATA; - } - if (ff_pkt->flags & FO_SPARSE) { cbuf = (Bytef *)jcr->compress_buf + SPARSE_FADDR_SIZE; max_compress_len = jcr->compress_buf_size - SPARSE_FADDR_SIZE; @@ -329,7 +323,7 @@ static int save_file(FF_PKT *ff_pkt, void *vjcr) * Send Data header to Storage daemon * */ - if (!bnet_fsend(sd, "%ld %d 0", jcr->JobFiles, stream)) { + if (!bnet_fsend(sd, "%ld %d 0", jcr->JobFiles, data_stream)) { bclose(&ff_pkt->bfd); set_jcr_job_status(jcr, JS_ErrorTerminated); return 0; diff --git a/bacula/src/filed/restore.c b/bacula/src/filed/restore.c index 8b4a7e0772..2070f6e9cf 100644 --- a/bacula/src/filed/restore.c +++ b/bacula/src/filed/restore.c @@ -118,6 +118,7 @@ void do_restore(JCR *jcr) case STREAM_UNIX_ATTRIBUTES: case STREAM_UNIX_ATTRIBUTES_EX: uint32_t LinkFI; + int data_stream; Dmsg1(30, "Stream=Unix Attributes. extract=%d\n", extract); /* If extracting, it was from previous stream, so @@ -145,7 +146,15 @@ void do_restore(JCR *jcr) Dmsg3(200, "File %s\nattrib=%s\nattribsEx=%s\n", attr->fname, attr->attr, attr->attrEx); - decode_stat(attr->attr, &attr->statp, &LinkFI); + data_stream = decode_stat(attr->attr, &attr->statp, &LinkFI); + + if (!is_stream_supported(data_stream)) { + if (!non_support_data++) { + Jmsg(jcr, M_ERROR, 0, _("%s stream not supported on this Client.\n"), + stream_to_ascii(data_stream)); + } + continue; + } build_attr_output_fnames(jcr, attr); @@ -185,7 +194,8 @@ void do_restore(JCR *jcr) case STREAM_WIN32_DATA: if (!is_win32_backup()) { if (!non_support_data) { - Jmsg(jcr, M_ERROR, 0, _("Win32 backup data not supported on this Client.\n")); + Jmsg(jcr, M_ERROR, 0, _("%s stream not supported on this Client.\n"), + stream_to_ascii(stream)); } extract = FALSE; non_support_data++; @@ -239,7 +249,8 @@ extract_data: case STREAM_WIN32_GZIP_DATA: if (!is_win32_backup()) { if (!non_support_attr) { - Jmsg(jcr, M_ERROR, 0, _("Win32 GZIP backup data not supported on this Client.\n")); + Jmsg(jcr, M_ERROR, 0, _("%s stream not supported on this Client.\n"), + stream_to_ascii(stream)); } extract = FALSE; non_support_attr++; diff --git a/bacula/src/filed/verify.c b/bacula/src/filed/verify.c index 2919ad3fb2..bd5ac212e0 100644 --- a/bacula/src/filed/verify.c +++ b/bacula/src/filed/verify.c @@ -154,7 +154,7 @@ static int verify_file(FF_PKT *ff_pkt, void *pkt) } } - encode_stat(attribs, &ff_pkt->statp, ff_pkt->LinkFI); + encode_stat(attribs, ff_pkt, 0); P(jcr->mutex); jcr->JobFiles++; /* increment number of files sent */ diff --git a/bacula/src/findlib/attribs.c b/bacula/src/findlib/attribs.c index 591900b963..70e44bf358 100755 --- a/bacula/src/findlib/attribs.c +++ b/bacula/src/findlib/attribs.c @@ -52,6 +52,36 @@ HANDLE bget_handle(BFILE *bfd); /* */ /*=============================================================*/ +/* + * Return the data stream that will be used + */ +int select_data_stream(FF_PKT *ff_pkt) +{ + int stream; + + /* Note, no sparse option for win32_data */ + if (is_win32_backup()) { + stream = STREAM_WIN32_DATA; + ff_pkt->flags &= ~FO_SPARSE; + } else if (ff_pkt->flags & FO_SPARSE) { + stream = STREAM_SPARSE_DATA; + } else { + stream = STREAM_FILE_DATA; + } +#ifdef HAVE_LIBZ + if (ff_pkt->flags & FO_GZIP) { + if (stream == STREAM_WIN32_DATA) { + stream = STREAM_WIN32_GZIP_DATA; + } else if (stream == STREAM_FILE_DATA) { + stream = STREAM_GZIP_DATA; + } else { + stream = STREAM_SPARSE_GZIP_DATA; + } + } +#endif + return stream; +} + /* * Encode a stat structure into a base64 character string @@ -64,15 +94,13 @@ HANDLE bget_handle(BFILE *bfd); * them in the encode_attribsEx() subroutine, but this is * not recommended. */ -void encode_stat(char *buf, struct stat *statp, uint32_t LinkFI) +void encode_stat(char *buf, FF_PKT *ff_pkt, int data_stream) { char *p = buf; + struct stat *statp = &ff_pkt->statp; /* - * NOTE: we should use rdev as major and minor device if - * it is a block or char device (S_ISCHR(statp->st_mode) - * or S_ISBLK(statp->st_mode)). In all other cases, - * it is not used. - * + * Encode a stat packet. I should have done this more intelligently + * with a length so that it could be easily expanded. */ p += to_base64((int64_t)statp->st_dev, p); *p++ = ' '; /* separate fields with a space */ @@ -100,13 +128,17 @@ void encode_stat(char *buf, struct stat *statp, uint32_t LinkFI) *p++ = ' '; p += to_base64((int64_t)statp->st_ctime, p); *p++ = ' '; - p += to_base64((int64_t)LinkFI, p); + p += to_base64((int64_t)ff_pkt->LinkFI, p); + *p++ = ' '; -/* FreeBSD function */ #ifdef HAVE_CHFLAGS - *p++ = ' '; - p += to_base64((int64_t)statp->st_flags, p); + /* FreeBSD function */ + p += to_base64((int64_t)statp->st_flags, p); /* output st_flags */ +#else + p += to_base64((int64_t)0, p); /* output place holder */ #endif + *p++ = ' '; + p += to_base64((int64_t)data_stream, p); *p = 0; return; } @@ -114,8 +146,7 @@ void encode_stat(char *buf, struct stat *statp, uint32_t LinkFI) /* Decode a stat packet from base64 characters */ -void -decode_stat(char *buf, struct stat *statp, uint32_t *LinkFI) +int decode_stat(char *buf, struct stat *statp, uint32_t *LinkFI) { char *p = buf; int64_t val; @@ -158,25 +189,36 @@ decode_stat(char *buf, struct stat *statp, uint32_t *LinkFI) p++; p += from_base64(&val, p); statp->st_ctime = val; + /* Optional FileIndex of hard linked file data */ if (*p == ' ' || (*p != 0 && *(p+1) == ' ')) { p++; p += from_base64(&val, p); *LinkFI = (uint32_t)val; - } else { + } else { *LinkFI = 0; - } + return 0; + } -/* FreeBSD user flags */ -#ifdef HAVE_CHFLAGS + /* FreeBSD user flags */ if (*p == ' ' || (*p != 0 && *(p+1) == ' ')) { p++; p += from_base64(&val, p); +#ifdef HAVE_CHFLAGS statp->st_flags = (uint32_t)val; - } else { + } else { statp->st_flags = 0; - } #endif + } + + /* Look for data stream id */ + if (*p == ' ' || (*p != 0 && *(p+1) == ' ')) { + p++; + p += from_base64(&val, p); + } else { + val = 0; + } + return (int)val; } /* @@ -311,7 +353,7 @@ int encode_attribsEx(JCR *jcr, char *attribsEx, FF_PKT *ff_pkt) if (!p_GetFileAttributesEx(ff_pkt->sys_fname, GetFileExInfoStandard, (LPVOID)&atts)) { win_error(jcr, "GetFileAttributesEx:", ff_pkt->sys_fname); - return STREAM_UNIX_ATTRIBUTES_EX; + return STREAM_UNIX_ATTRIBUTES; } p += to_base64((uint64_t)atts.dwFileAttributes, p); diff --git a/bacula/src/findlib/bfile.c b/bacula/src/findlib/bfile.c index a42eb03006..84b2908c0a 100644 --- a/bacula/src/findlib/bfile.c +++ b/bacula/src/findlib/bfile.c @@ -31,6 +31,58 @@ #include "bacula.h" #include "find.h" +/* =============================================================== + * + * U N I X AND W I N D O W S + * + * =============================================================== + */ +char *stream_to_ascii(int stream) +{ + static char buf[20]; + + switch (stream) { + case STREAM_GZIP_DATA: + return "GZIP data"; + case STREAM_SPARSE_GZIP_DATA: + return "GZIP sparse data"; + case STREAM_WIN32_ATTRIBUTES: + return "Win32 attributes"; + case STREAM_WIN32_DATA: + return "Win32 data"; + case STREAM_WIN32_GZIP_DATA: + return "Win32 GZIP data"; + case STREAM_UNIX_ATTRIBUTES: + return "File attributes"; + case STREAM_FILE_DATA: + return "File data"; + case STREAM_MD5_SIGNATURE: + return "MD5 signature"; + case STREAM_UNIX_ATTRIBUTES_EX: + return "Extended attributes"; + case STREAM_SPARSE_DATA: + return "Sparse data"; + case STREAM_PROGRAM_NAMES: + return "Program names"; + case STREAM_PROGRAM_DATA: + return "Program data"; + case STREAM_SHA1_SIGNATURE: + return "SHA1 signature"; + default: + sprintf(buf, "%d", stream); + return buf; + } +} + + + +/* =============================================================== + * + * W I N D O W S + * + * =============================================================== + */ + #ifdef HAVE_CYGWIN void unix_name_to_win32(POOLMEM **win32_name, char *name); @@ -72,31 +124,39 @@ int is_win32_backup(void) return p_BackupRead && p_BackupWrite; } +/* + * Return 1 if we support the stream + * 0 if we do not support the stream + */ int is_stream_supported(int stream) { - if (is_win32_backup()) { - return 1; - } /* No Win32 backup on this machine */ switch (stream) { +#ifndef HAVE_LIBZ + case STREAM_GZIP_DATA: + case STREAM_SPARSE_GZIP_DATA: + return 0; +#endif case STREAM_WIN32_ATTRIBUTES: case STREAM_WIN32_DATA: case STREAM_WIN32_GZIP_DATA: - return 0; + return is_win32_backup(); /* check if we support BackupRead/Write data */ /* Known streams */ +#ifdef HAVE_LIBZ + case STREAM_GZIP_DATA: + case STREAM_SPARSE_GZIP_DATA: +#endif case STREAM_UNIX_ATTRIBUTES: case STREAM_FILE_DATA: case STREAM_MD5_SIGNATURE: - case STREAM_GZIP_DATA: case STREAM_UNIX_ATTRIBUTES_EX: case STREAM_SPARSE_DATA: - case STREAM_SPARSE_GZIP_DATA: case STREAM_PROGRAM_NAMES: case STREAM_PROGRAM_DATA: case STREAM_SHA1_SIGNATURE: + case 0: /* compatibility with old tapes */ return 1; - } return 0; } @@ -345,22 +405,29 @@ int is_stream_supported(int stream) { /* No Win32 backup on this machine */ switch (stream) { +#ifndef HAVE_LIBZ + case STREAM_GZIP_DATA: + case STREAM_SPARSE_GZIP_DATA: +#endif case STREAM_WIN32_ATTRIBUTES: case STREAM_WIN32_DATA: case STREAM_WIN32_GZIP_DATA: return 0; /* Known streams */ +#ifdef HAVE_LIBZ + case STREAM_GZIP_DATA: + case STREAM_SPARSE_GZIP_DATA: +#endif case STREAM_UNIX_ATTRIBUTES: case STREAM_FILE_DATA: case STREAM_MD5_SIGNATURE: - case STREAM_GZIP_DATA: case STREAM_UNIX_ATTRIBUTES_EX: case STREAM_SPARSE_DATA: - case STREAM_SPARSE_GZIP_DATA: case STREAM_PROGRAM_NAMES: case STREAM_PROGRAM_DATA: case STREAM_SHA1_SIGNATURE: + case 0: /* compatibility with old tapes */ return 1; } diff --git a/bacula/src/findlib/bfile.h b/bacula/src/findlib/bfile.h index 5250847eb9..6ed03470e4 100644 --- a/bacula/src/findlib/bfile.h +++ b/bacula/src/findlib/bfile.h @@ -33,17 +33,16 @@ #include #include "winapi.h" -#define BF_CLOSED 0 -#define BF_READ 1 /* BackupRead */ -#define BF_WRITE 2 /* BackupWrite */ +enum { + BF_CLOSED, + BF_READ, /* BackupRead */ + BF_WRITE /* BackupWrite */ +}; /* In bfile.c */ /* Basic low level I/O file packet */ -typedef struct s_bfile { -#ifdef xxx - int use_win_api; /* set if using WinAPI */ -#endif +struct BFILE { int use_backup_api; /* set if using BackupRead/Write */ int mode; /* set if file is open */ HANDLE fh; /* Win32 file handle */ @@ -52,17 +51,17 @@ typedef struct s_bfile { POOLMEM *errmsg; /* error message buffer */ DWORD rw_bytes; /* Bytes read or written */ DWORD lerror; /* Last error code */ -} BFILE; +}; HANDLE bget_handle(BFILE *bfd); #else /* Linux/Unix systems */ /* Basic low level I/O file packet */ -typedef struct s_bfile { +struct BFILE { int fid; /* file id on Unix */ int berrno; -} BFILE; +}; #endif @@ -77,5 +76,6 @@ int bclose(BFILE *bfd); ssize_t bread(BFILE *bfd, void *buf, size_t count); ssize_t bwrite(BFILE *bfd, void *buf, size_t count); off_t blseek(BFILE *bfd, off_t offset, int whence); +char *stream_to_ascii(int stream); #endif /* __BFILE_H */ diff --git a/bacula/src/findlib/find.h b/bacula/src/findlib/find.h index 22c272ccd9..c25fafa692 100755 --- a/bacula/src/findlib/find.h +++ b/bacula/src/findlib/find.h @@ -62,22 +62,24 @@ int readdir_r(DIR *dirp, struct dirent *entry, struct dirent **result); /* * Status codes returned by create_file() */ -#define CF_SKIP 1 /* skip file (not newer or something) */ -#define CF_ERROR 2 /* error creating file */ -#define CF_EXTRACT 3 /* file created, data to extract */ -#define CF_CREATED 4 /* file created, no data to extract */ +enum { + CF_SKIP = 1, /* skip file (not newer or something) */ + CF_ERROR, /* error creating file */ + CF_EXTRACT, /* file created, data to extract */ + CF_CREATED /* file created, no data to extract */ +}; /* Options saved in "flag" of ff packet */ -#define FO_MD5 0x001 /* Do MD5 checksum */ -#define FO_GZIP 0x002 /* Do Zlib compression */ -#define FO_NO_RECURSION 0x004 /* no recursion in directories */ -#define FO_MULTIFS 0x008 /* multiple file systems */ -#define FO_SPARSE 0x010 /* do sparse file checking */ -#define FO_IF_NEWER 0x020 /* replace if newer */ -#define FO_NOREPLACE 0x040 /* never replace */ -#define FO_READFIFO 0x080 /* read data from fifo */ -#define FO_SHA1 0x100 /* Do SHA1 checksum */ +#define FO_MD5 (1<<1) /* Do MD5 checksum */ +#define FO_GZIP (1<<2) /* Do Zlib compression */ +#define FO_NO_RECURSION (1<<3) /* no recursion in directories */ +#define FO_MULTIFS (1<<4) /* multiple file systems */ +#define FO_SPARSE (1<<5) /* do sparse file checking */ +#define FO_IF_NEWER (1<<6) /* replace if newer */ +#define FO_NOREPLACE (1<<7) /* never replace */ +#define FO_READFIFO (1<<8) /* read data from fifo */ +#define FO_SHA1 (1<<9) /* Do SHA1 checksum */ /* * Options saved in "options" of include list @@ -86,15 +88,15 @@ int readdir_r(DIR *dirp, struct dirent *entry, struct dirent **result); * * ***FIXME*** replace all OPT_xxx with FO_xxx or vise-versa */ -#define OPT_compute_MD5 0x01 /* compute MD5 of file's data */ -#define OPT_GZIP_compression 0x02 /* use GZIP compression */ -#define OPT_no_recursion 0x04 /* no recursion in directories */ -#define OPT_multifs 0x08 /* multiple file systems */ -#define OPT_sparse 0x10 /* do sparse file checking */ -#define OPT_replace_if_newer 0x20 /* replace file if newer */ -#define OPT_never_replace 0x40 /* never replace */ -#define OPT_read_fifo 0x80 /* read data from fifo (named pipe) */ -#define OPT_compute_SHA1 0x100 /* compute SHA1 of file's data */ +#define OPT_compute_MD5 FO_MD5 /* compute MD5 of file's data */ +#define OPT_GZIP_compression FO_GZIP /* use GZIP compression */ +#define OPT_no_recursion FO_NO_RECURSION /* no recursion in directories */ +#define OPT_multifs FO_MULTIFS /* multiple file systems */ +#define OPT_sparse FO_SPARSE /* do sparse file checking */ +#define OPT_replace_if_newer FO_IF_NEWER /* replace file if newer */ +#define OPT_never_replace FO_NOREPLACE /* never replace */ +#define OPT_read_fifo FO_READFIFO /* read data from fifo (named pipe) */ +#define OPT_compute_SHA1 FO_SHA1 /* compute SHA1 of file's data */ struct s_included_file { diff --git a/bacula/src/findlib/protos.h b/bacula/src/findlib/protos.h index f1f5a188e8..8fe5c0c39b 100644 --- a/bacula/src/findlib/protos.h +++ b/bacula/src/findlib/protos.h @@ -24,10 +24,11 @@ */ /* from attribs.c */ -void encode_stat (char *buf, struct stat *statp, uint32_t LinkFI); -void decode_stat (char *buf, struct stat *statp, uint32_t *LinkFI); +void encode_stat (char *buf, FF_PKT *ff_pkt, int data_stream); +int decode_stat (char *buf, struct stat *statp, uint32_t *LinkFI); int encode_attribsEx (JCR *jcr, char *attribsEx, FF_PKT *ff_pkt); int set_attributes (JCR *jcr, ATTR *attr, BFILE *ofd); +int select_data_stream(FF_PKT *ff_pkt); /* from create_file.c */ int create_file (JCR *jcr, ATTR *attr, BFILE *ofd, int replace); diff --git a/bacula/src/lib/Makefile.in b/bacula/src/lib/Makefile.in index 5eda0b8eca..5ef2096bec 100644 --- a/bacula/src/lib/Makefile.in +++ b/bacula/src/lib/Makefile.in @@ -35,7 +35,7 @@ LIBSRCS = alloc.c attr.c base64.c bsys.c bget_msg.c \ bnet.c bnet_server.c \ bpipe.c bshm.c btime.c \ cram-md5.c crc32.c daemon.c edit.c fnmatch.c \ - hmac.c idcache.c jcr.c lex.c \ + hmac.c idcache.c jcr.c lex.c list.c \ md5.c message.c mem_pool.c parse_conf.c \ queue.c rwlock.c scan.c serial.c sha1.c \ semlock.c signal.c smartall.c tree.c \ @@ -46,7 +46,7 @@ LIBOBJS = alloc.o attr.o base64.o bsys.o bget_msg.o \ bnet.o bnet_server.o \ bpipe.o bshm.o btime.o \ cram-md5.o crc32.o daemon.o edit.o fnmatch.o \ - hmac.o idcache.o jcr.o lex.o \ + hmac.o idcache.o jcr.o lex.o list.o \ md5.o message.o mem_pool.o parse_conf.o \ queue.o rwlock.o scan.o serial.o sha1.o \ semlock.o signal.o smartall.o tree.o \ diff --git a/bacula/src/lib/bnet.c b/bacula/src/lib/bnet.c index 4e62c4aa9e..3d31b67aae 100644 --- a/bacula/src/lib/bnet.c +++ b/bacula/src/lib/bnet.c @@ -188,6 +188,7 @@ int32_t bnet_recv(BSOCK *bsock) /* If signal or packet size too big */ if (pktsiz < 0 || pktsiz > 1000000) { if (pktsiz > 0) { /* if packet too big */ + Jmsg0(bsock->jcr, M_FATAL, 0, _("Received packet too big. Terminating.\n")); pktsiz = BNET_TERMINATE; /* hang up */ } if (pktsiz == BNET_TERMINATE) { diff --git a/bacula/src/lib/lib.h b/bacula/src/lib/lib.h index 0a4b7715b3..a9afae76db 100644 --- a/bacula/src/lib/lib.h +++ b/bacula/src/lib/lib.h @@ -28,6 +28,7 @@ */ +#include "list.h" #include "bits.h" #include "btime.h" #include "smartall.h" diff --git a/bacula/src/stored/askdir.c b/bacula/src/stored/askdir.c index ac8f928441..a48dc5de7c 100644 --- a/bacula/src/stored/askdir.c +++ b/bacula/src/stored/askdir.c @@ -193,6 +193,7 @@ int dir_create_jobmedia_record(JCR *jcr) return 1; /* nothing written to tape */ } + jcr->WroteVol = false; bnet_fsend(dir, Create_job_media, jcr->Job, jcr->VolFirstIndex, jcr->VolLastIndex, jcr->StartFile, jcr->EndFile, diff --git a/bacula/src/stored/bextract.c b/bacula/src/stored/bextract.c index 7734432b43..710d5fb126 100644 --- a/bacula/src/stored/bextract.c +++ b/bacula/src/stored/bextract.c @@ -272,8 +272,18 @@ static void record_cb(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec) if (file_is_included(ff, attr->fname) && !file_is_excluded(ff, attr->fname)) { uint32_t LinkFI; + int data_stream; + + data_stream = decode_stat(attr->attr, &attr->statp, &LinkFI); + if (!is_stream_supported(data_stream)) { + if (!non_support_data++) { + Jmsg(jcr, M_ERROR, 0, _("%s stream not supported on this Client.\n"), + stream_to_ascii(data_stream)); + } + return; + } + - decode_stat(attr->attr, &attr->statp, &LinkFI); build_attr_output_fnames(jcr, attr); extract = FALSE; diff --git a/bacula/src/stored/block.c b/bacula/src/stored/block.c index 4f49ded7e0..acbb5d5e60 100644 --- a/bacula/src/stored/block.c +++ b/bacula/src/stored/block.c @@ -287,6 +287,7 @@ int write_block_to_device(JCR *jcr, DEVICE *dev, DEV_BLOCK *block) if (!dir_create_jobmedia_record(jcr)) { Jmsg(jcr, M_ERROR, 0, _("Could not create JobMedia record for Volume=\"%s\" Job=%s\n"), jcr->VolCatInfo.VolCatName, jcr->Job); + set_new_volume_parameters(jcr, dev); unlock_device(dev); return 0; } diff --git a/bacula/src/stored/bls.c b/bacula/src/stored/bls.c index f16723cfe9..ac8f516067 100644 --- a/bacula/src/stored/bls.c +++ b/bacula/src/stored/bls.c @@ -52,6 +52,7 @@ static JCR *jcr; static SESSION_LABEL sessrec; static uint32_t num_files = 0; static ATTR *attr; +static int non_support_data = 0; #define CONFIG_FILE "bacula-sd.conf" char *configfile; @@ -342,6 +343,7 @@ static void record_cb(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec) if (rec->Stream == STREAM_UNIX_ATTRIBUTES || rec->Stream == STREAM_UNIX_ATTRIBUTES_EX) { uint32_t LinkFI; + int data_stream; if (!unpack_attributes_record(jcr, rec->Stream, rec->data, attr)) { Emsg0(M_ERROR_TERM, 0, _("Cannot continue.\n")); @@ -352,7 +354,14 @@ static void record_cb(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec) rec->FileIndex, attr->file_index); } - decode_stat(attr->attr, &attr->statp, &LinkFI); + data_stream = decode_stat(attr->attr, &attr->statp, &LinkFI); + if (!is_stream_supported(data_stream)) { + if (!non_support_data++) { + Jmsg(jcr, M_ERROR, 0, _("%s stream not supported on this Client.\n"), + stream_to_ascii(data_stream)); + } + return; + } build_attr_output_fnames(jcr, attr); if (file_is_included(&ff, attr->fname) && !file_is_excluded(&ff, attr->fname)) { diff --git a/bacula/src/stored/device.c b/bacula/src/stored/device.c index c927ee6921..5e047de557 100644 --- a/bacula/src/stored/device.c +++ b/bacula/src/stored/device.c @@ -190,6 +190,11 @@ int fixup_device_block_write_error(JCR *jcr, DEVICE *dev, DEV_BLOCK *block) return 1; /* device locked */ } +/* + * We have a new Volume mounted, so reset the Volume parameters + * concerning this job. The global changes were made earlier + * in the dev structure. + */ void set_new_volume_parameters(JCR *jcr, DEVICE *dev) { if (jcr->NewVol && !dir_get_volume_info(jcr, GET_VOL_INFO_FOR_WRITE)) { diff --git a/bacula/src/stored/mount.c b/bacula/src/stored/mount.c index 4efe9b3641..c747ef5fc5 100644 --- a/bacula/src/stored/mount.c +++ b/bacula/src/stored/mount.c @@ -63,7 +63,6 @@ mount_next_vol: recycle = ask = autochanger = 0; if (release) { Dmsg0(100, "mount_next_volume release=1\n"); - release_volume(jcr, dev); ask = 1; /* ask operator to mount tape */ } @@ -361,16 +360,19 @@ int mount_next_read_volume(JCR *jcr, DEVICE *dev, DEV_BLOCK *block) return 0; } +/* + * Either because we are going to hang a new volume, or because + * of explicit user request, we release the current volume. + */ void release_volume(JCR *jcr, DEVICE *dev) { - /********FIXME******* if WroteVol, must write JobMedia record */ - /* - * First erase all memory of the current volume - */ if (jcr->WroteVol) { - Jmsg0(jcr, M_ERROR, 0, "Hey!!!!! WriteVol non-zero !!!!!\n"); + Jmsg0(jcr, M_ERROR, 0, "Hey!!!!! WroteVol non-zero !!!!!\n"); } + /* + * First erase all memory of the current volume + */ dev->block_num = dev->file = 0; dev->EndBlock = dev->EndFile = 0; memset(&dev->VolCatInfo, 0, sizeof(dev->VolCatInfo)); diff --git a/bacula/src/version.h b/bacula/src/version.h index d11ad29c99..2694345dae 100644 --- a/bacula/src/version.h +++ b/bacula/src/version.h @@ -1,8 +1,8 @@ /* */ #define VERSION "1.31" #define VSTRING "1" -#define BDATE "22 Jun 2003" -#define LSMDATE "22Jun03" +#define BDATE "25 Jun 2003" +#define LSMDATE "25Jun03" /* Debug flags */ #define DEBUG 1 -- 2.39.5