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.
- 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
- 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
- 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.
- 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
- 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
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
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.
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 */
};
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);
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);
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);
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);
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, "dird<filed: stream=%d %s\n", stream, jcr->fname);
Dmsg1(020, "dird<filed: attr=%s\n", attr);
{
char attribs[MAXSTRING];
char attribsEx[MAXSTRING];
- int stat, stream;
+ int stat, attr_stream, data_stream;
struct MD5Context md5c;
struct SHA1Context sha1c;
int gotMD5 = 0;
binit(&ff_pkt->bfd);
- /* 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 ||
}
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);
* Send Attributes header to Storage daemon
* <file-index> <stream> <info>
*/
- 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);
}
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;
* Send Data header to Storage daemon
* <file-index> <stream> <info>
*/
- 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;
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
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);
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++;
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++;
}
}
- 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 */
/* */
/*=============================================================*/
+/*
+ * 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
* 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 */
*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;
}
/* 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;
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;
}
/*
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);
#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);
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;
}
{
/* 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;
}
#include <windows.h>
#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 */
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
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 */
/*
* 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
*
* ***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 {
*/
/* 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);
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 \
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 \
/* 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) {
*/
+#include "list.h"
#include "bits.h"
#include "btime.h"
#include "smartall.h"
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,
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;
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;
}
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;
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"));
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)) {
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)) {
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 */
}
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));
/* */
#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