- Figure out how to use ssh or stunnel to protect Bacula communications.
For 1.31 release:
+- Implement non-blocking writes and bsock->terminate in heartbeat thread,
+ or set it in status.c cancel.
+- Add restore to specific date.
- 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 this below from Phil.
+ This was SD reported data rather than FD data!
> When the job was done, Bacula reported 11084 files restored:
>
> JobId: 527
#define DEV_BSIZE 512
#endif
-/* Maximum number of bytes that you can push into a
+/*
+ * Maximum number of bytes that you can push into a
* socket.
*/
#define MAX_NETWORK_BUFFER_SIZE (32 * 1024)
-/* Stream definitions. Once defined these must NEVER
+/*
+ * Stream definitions. Once defined these must NEVER
* change as they go on the storage media.
+ * Note, the following streams are passed from the SD to the DIR
+ * so that they may be put into the catalog (actually only the
+ * stat packet part of the attr record is put in the catalog.
+ *
+ * STREAM_UNIX_ATTRIBUTES
+ * STREAM_UNIX_ATTRIBUTES_EX
+ * STREAM_MD5_SIGNATURE
+ * STREAM_SHA1_SIGNATURE
*/
#define STREAM_UNIX_ATTRIBUTES 1 /* Generic Unix attributes */
#define STREAM_FILE_DATA 2 /* Standard uncompressed data */
#define STREAM_MD5_SIGNATURE 3 /* MD5 signature for the file */
#define STREAM_GZIP_DATA 4 /* GZip compressed file data */
-#define STREAM_UNIX_ATTRIBUTES_EX 5 /* Extended Unix attr. Win32Ex/FreeBSD */
+/* Extended Unix attributes with Win32 Extended data. Deprecated. */
+#define STREAM_UNIX_ATTRIBUTES_EX 5 /* Extended Unix attr for Win32 EX */
#define STREAM_SPARSE_DATA 6 /* Sparse data stream */
#define STREAM_SPARSE_GZIP_DATA 7
#define STREAM_PROGRAM_NAMES 8 /* program names for program data */
#define STREAM_SHA1_SIGNATURE 10 /* SHA1 signature for the file */
#define STREAM_WIN32_DATA 11 /* Win32 BackupRead data */
#define STREAM_WIN32_GZIP_DATA 12 /* Gzipped Win32 BackupRead data */
+#define STREAM_WIN32_ATTRIBUTES 13 /* Unix attribs, but WIN32_DATA follows */
+
+/*
+ * File type (Bacula defined).
+ * NOTE!!! These are saved in the Attributes record on the tape, so
+ * do not change them. If need be, add to them.
+ *
+ * This is stored as 32 bits on tape, but only FT_MASK bits are
+ * used for the file type. The upper bits are used to indicate
+ * additional optional fields in the attribute record.
+ */
+#define FT_MASK 0xFFFF /* Bits used by FT (type) */
+#define FT_LNKSAVED 1 /* hard link to file already saved */
+#define FT_REGE 2 /* Regular file but empty */
+#define FT_REG 3 /* Regular file */
+#define FT_LNK 4 /* Soft Link */
+#define FT_DIR 5 /* Directory */
+#define FT_SPEC 6 /* Special file -- chr, blk, fifo, sock */
+#define FT_NOACCESS 7 /* Not able to access */
+#define FT_NOFOLLOW 8 /* Could not follow link */
+#define FT_NOSTAT 9 /* Could not stat file */
+#define FT_NOCHG 10 /* Incremental option, file not changed */
+#define FT_DIRNOCHG 11 /* Incremental option, directory not changed */
+#define FT_ISARCH 12 /* Trying to save archive file */
+#define FT_NORECURSE 13 /* No recursion into directory */
+#define FT_NOFSCHG 14 /* Different file system, prohibited */
+#define FT_NOOPEN 15 /* Could not open directory */
+#define FT_RAW 16 /* Raw block device */
+#define FT_FIFO 17 /* Raw fifo device */
+
+/* Definitions for upper part of type word (see above). */
+#define AR_DATA_STREAM (1<<16) /* Data stream id present */
/*
* Internal code for Signature types
/* Must create it */
Mmsg(&mdb->cmd,
-"INSERT INTO File (FileIndex, JobId, PathId, FilenameId, \
-LStat, MD5) VALUES (%u, %u, %u, %u, '%s', '0')",
+"INSERT INTO File (FileIndex,JobId,PathId,FilenameId,"
+"LStat,MD5) VALUES (%u,%u,%u,%u,'%s','0')",
ar->FileIndex, ar->JobId, ar->PathId, ar->FilenameId,
ar->attr);
sql_free_result(mdb);
}
- Mmsg(&mdb->cmd, "INSERT INTO Path (Path) VALUES ('%s')", mdb->esc_name);
+ Mmsg(&mdb->cmd, "INSERT INTO Path (Path) VALUES ('%s')", mdb->esc_name);
if (!INSERT_DB(jcr, mdb, mdb->cmd)) {
Mmsg2(&mdb->errmsg, _("Create db Path record %s failed. ERR=%s\n"),
jcr->jr.JobId = 0;
if (!db_find_job_start_time(jcr, jcr->db, &jcr->jr, &jcr->stime)) {
Jmsg(jcr, M_INFO, 0, "%s", db_strerror(jcr->db));
- Jmsg(jcr, M_INFO, 0, _("No prior or suitable FULL backup found. Doing FULL backup.\n"));
+ Jmsg(jcr, M_INFO, 0, _("No prior or suitable Full backup found. Doing FULL backup.\n"));
bsnprintf(since, sizeof(since), " (upgraded from %s)",
level_to_str(jcr->jr.Level));
jcr->JobLevel = jcr->jr.Level = L_FULL;
/*
* Update File Attributes in the catalog with data
- * sent by the Storage daemon.
+ * sent by the Storage daemon. Note, we receive the whole
+ * attribute record, but we select out only the stat packet,
+ * VolSessionId, VolSessionTime, FileIndex, and file name
+ * to store in the catalog.
*/
void catalog_update(JCR *jcr, BSOCK *bs, char *msg)
{
Dmsg0(200, "Close DB\n");
db_close_database(jcr, jcr->db);
}
- if (jcr->RestoreWhere) {
- free(jcr->RestoreWhere);
- }
if (jcr->RestoreBootstrap) {
free(jcr->RestoreBootstrap);
}
} else {
replace = REPLACE_ALWAYS; /* always replace */
}
- if (jcr->RestoreWhere) {
- where = jcr->RestoreWhere; /* override */
+ if (jcr->where) {
+ where = jcr->where; /* override */
} else if (jcr->job->RestoreWhere) {
where = jcr->job->RestoreWhere; /* no override take from job */
} else {
jcr->fileset = fileset;
jcr->pool = pool;
if (where) {
- if (jcr->RestoreWhere) {
- free(jcr->RestoreWhere);
+ if (jcr->where) {
+ free(jcr->where);
}
- jcr->RestoreWhere = bstrdup(where);
+ jcr->where = bstrdup(where);
}
if (when) {
When: %s\n"),
job->hdr.name,
NPRT(jcr->RestoreBootstrap),
- jcr->RestoreWhere?jcr->RestoreWhere:NPRT(job->RestoreWhere),
+ jcr->where?jcr->where:NPRT(job->RestoreWhere),
replace,
jcr->fileset->hdr.name,
jcr->client->hdr.name,
When: %s\n"),
job->hdr.name,
NPRT(jcr->RestoreBootstrap),
- jcr->RestoreWhere?jcr->RestoreWhere:NPRT(job->RestoreWhere),
+ jcr->where?jcr->where:NPRT(job->RestoreWhere),
replace,
jcr->fileset->hdr.name,
jcr->client->hdr.name,
if (!get_cmd(ua, _("Please enter path prefix for restore (/ for none): "))) {
break;
}
- if (jcr->RestoreWhere) {
- free(jcr->RestoreWhere);
- jcr->RestoreWhere = NULL;
+ if (jcr->where) {
+ free(jcr->where);
+ jcr->where = NULL;
}
if (ua->cmd[0] == '/' && ua->cmd[1] == 0) {
ua->cmd[0] = 0;
}
- jcr->RestoreWhere = bstrdup(ua->cmd);
+ jcr->where = bstrdup(ua->cmd);
goto try_again;
case 8:
/* Replace */
jcr->compress_buf = get_memory(jcr->compress_buf_size);
Dmsg1(100, "set_find_options ff=%p\n", jcr->ff);
- set_find_options((FF_PKT *)jcr->ff, jcr->incremental, jcr->mtime);
+ set_find_options((FF_PKT *)jcr->ff, jcr->incremental, jcr->mtime, jcr->mtime_only);
Dmsg0(110, "start find files\n");
start_heartbeat_monitor(jcr);
jcr->JobStatus = JS_Running;
- set_find_options((FF_PKT *)jcr->ff, jcr->incremental, jcr->mtime);
+ set_find_options((FF_PKT *)jcr->ff, jcr->incremental, jcr->mtime, jcr->mtime_only);
stat = find_files(jcr, (FF_PKT *)jcr->ff, tally_file, (void *)jcr);
Dmsg2(150, "Got replace %c, where=%s\n", replace, where);
unbash_spaces(where);
- jcr->where = where;
+ jcr->where = bstrdup(where);
+ free_pool_memory(where);
jcr->replace = replace;
bnet_fsend(dir, OKrestore);
if (jcr->store_bsock) {
bnet_close(jcr->store_bsock);
}
- if (jcr->where) {
- free_pool_memory(jcr->where);
- }
if (jcr->RestoreBootstrap) {
unlink(jcr->RestoreBootstrap);
free_pool_memory(jcr->RestoreBootstrap);
static char rec_header[] = "rechdr %ld %ld %ld %ld %ld";
/* Forward referenced functions */
-static void print_ls_output(JCR *jcr, char *fname, char *lname, int type, struct stat *statp);
#define RETRY 10 /* retry wait time */
{
int wherelen;
BSOCK *sd;
- POOLMEM *fname; /* original file name */
- POOLMEM *ofile; /* output name with possible prefix */
- POOLMEM *lname; /* link name with possible prefix */
- POOLMEM *attribsEx; /* Extended attributes (Win32) */
int32_t stream;
uint32_t size;
- uint32_t VolSessionId, VolSessionTime, file_index;
- uint32_t record_file_index;
- struct stat statp;
+ uint32_t VolSessionId, VolSessionTime;
+ int32_t file_index;
int extract = FALSE;
BFILE bfd;
- int type, stat;
+ int stat;
uint32_t total = 0; /* Job total but only 32 bits for debug */
char *wbuf; /* write buffer */
uint32_t wsize; /* write size */
uint64_t fileAddr = 0; /* file write address */
+ int non_support_data = 0;
+ int non_support_attr = 0;
+ int prog_name_msg = 0;
+ ATTR *attr;
wherelen = strlen(jcr->where);
}
jcr->buf_size = sd->msglen;
- fname = get_pool_memory(PM_FNAME);
- ofile = get_pool_memory(PM_FNAME);
- lname = get_pool_memory(PM_FNAME);
- attribsEx = get_pool_memory(PM_FNAME);
+ attr = new_attr();
#ifdef HAVE_LIBZ
uint32_t compress_buf_size = jcr->buf_size + 12 + ((jcr->buf_size+999) / 1000) + 100;
Dmsg1(30, "Got stream data, len=%d\n", sd->msglen);
/* File Attributes stream */
- if (stream == STREAM_UNIX_ATTRIBUTES || stream == STREAM_WIN32_ATTRIBUTES) {
- char *ap, *lp, *fp, *apex;
+ switch (stream) {
+ case STREAM_UNIX_ATTRIBUTES:
+ case STREAM_UNIX_ATTRIBUTES_EX:
uint32_t LinkFI;
Dmsg1(30, "Stream=Unix Attributes. extract=%d\n", extract);
if (!is_bopen(&bfd)) {
Jmsg0(jcr, M_ERROR, 0, _("Logic error output file should be open\n"));
}
- set_attributes(jcr, fname, ofile, lname, type, stream,
- &statp, attribsEx, &bfd);
+ set_attributes(jcr, attr, &bfd);
extract = FALSE;
Dmsg0(30, "Stop extracting.\n");
}
- if ((int)sizeof_pool_memory(fname) < sd->msglen) {
- fname = realloc_pool_memory(fname, sd->msglen + 1);
- }
- if ((int)sizeof_pool_memory(ofile) < sd->msglen + wherelen + 1) {
- ofile = realloc_pool_memory(ofile, sd->msglen + wherelen + 1);
- }
- if ((int)sizeof_pool_memory(lname) < sd->msglen + wherelen + 1) {
- lname = realloc_pool_memory(lname, sd->msglen + wherelen + 1);
- }
- *fname = 0;
- *lname = 0;
-
- /*
- * An Attributes record consists of:
- * File_index
- * Type (FT_types)
- * Filename
- * Attributes
- * Link name (if file linked i.e. FT_LNK)
- * Extended attributes (Win32)
- *
- */
- Dmsg1(100, "Attr: %s\n", sd->msg);
- if (sscanf(sd->msg, "%d %d", &record_file_index, &type) != 2) {
- Jmsg(jcr, M_FATAL, 0, _("Error scanning attributes: %s\n"), sd->msg);
- Dmsg1(100, "\nError scanning attributes. %s\n", sd->msg);
+ if (!unpack_attributes_record(jcr, stream, sd->msg, attr)) {
goto bail_out;
}
- Dmsg2(100, "Got Attr: FilInx=%d type=%d\n", record_file_index, type);
- if (record_file_index != file_index) {
+ if (file_index != attr->file_index) {
Jmsg(jcr, M_FATAL, 0, _("Record header file index %ld not equal record index %ld\n"),
- file_index, record_file_index);
+ file_index, attr->file_index);
Dmsg0(100, "File index error\n");
goto bail_out;
}
- ap = sd->msg;
- while (*ap++ != ' ') /* skip record file index */
- ;
- while (*ap++ != ' ') /* skip type */
- ;
- /* Save filename and position to attributes */
- fp = fname;
- while (*ap != 0) {
- *fp++ = *ap++; /* copy filename to fname */
- }
- *fp = *ap++; /* terminate filename & point to attribs */
+
+ Dmsg3(200, "File %s\nattrib=%s\nattribsEx=%s\n", attr->fname,
+ attr->attr, attr->attrEx);
- /* Skip to Link name */
- if (type == FT_LNK || type == FT_LNKSAVED) {
- lp = ap;
- while (*lp++ != 0) {
- ;
- }
- } else {
- lp = "";
- }
+ decode_stat(attr->attr, &attr->statp, &LinkFI);
- if (stream == STREAM_WIN32_ATTRIBUTES) {
- apex = ap; /* start at attributes */
- while (*apex++ != 0) { /* skip attributes */
- ;
- }
- while (*apex++ != 0) { /* skip link name */
- ;
- }
- pm_strcpy(&attribsEx, apex); /* make a copy */
- } else {
- *attribsEx = 0; /* no extended attributes */
- }
-
- Dmsg3(200, "File %s\nattrib=%s\nattribsEx=%s\n", fname, ap, attribsEx);
-
- decode_stat(ap, &statp, &LinkFI);
- /*
- * Prepend the where directory so that the
- * files are put where the user wants.
- *
- * We do a little jig here to handle Win32 files with
- * a drive letter -- we simply strip the drive: from
- * every filename if a prefix is supplied.
- *
- */
- if (jcr->where[0] == 0) {
- strcpy(ofile, fname);
- strcpy(lname, lp);
- } else {
- char *fn;
- strcpy(ofile, jcr->where); /* copy prefix */
- if (win32_client && fname[1] == ':') {
- fn = fname+2; /* skip over drive: */
- } else {
- fn = fname; /* take whole name */
- }
- /* Ensure where is terminated with a slash */
- if (jcr->where[wherelen-1] != '/' && fn[0] != '/') {
- strcat(ofile, "/");
- }
- strcat(ofile, fn); /* copy rest of name */
- /*
- * Fixup link name -- if it is an absolute path
- */
- if (type == FT_LNKSAVED || type == FT_LNK) {
- int add_link;
- /* Always add prefix to hard links (FT_LNKSAVED) and
- * on user request to soft links
- */
- if (lp[0] == '/' &&
- (type == FT_LNKSAVED || jcr->prefix_links)) {
- strcpy(lname, jcr->where);
- add_link = 1;
- } else {
- lname[0] = 0;
- add_link = 0;
- }
- if (win32_client && lp[1] == ':') {
- fn = lp+2; /* skip over drive: */
- } else {
- fn = lp; /* take whole name */
- }
- /* Ensure where is terminated with a slash */
- if (add_link && jcr->where[wherelen-1] != '/' && fn[0] != '/') {
- strcat(lname, "/");
- }
- strcat(lname, fn); /* copy rest of link */
- }
- }
+ build_attr_output_fnames(jcr, attr);
- P(jcr->mutex);
- pm_strcpy(&jcr->last_fname, fname);
- V(jcr->mutex);
jcr->num_files_examined++;
- Dmsg1(30, "Outfile=%s\n", ofile);
+ Dmsg1(30, "Outfile=%s\n", attr->ofname);
extract = FALSE;
- stat = create_file(jcr, fname, ofile, lname, type,
- stream, &statp, attribsEx, &bfd,
- jcr->replace);
+ stat = create_file(jcr, attr, &bfd, jcr->replace);
switch (stat) {
case CF_ERROR:
case CF_SKIP:
case CF_EXTRACT:
extract = TRUE;
P(jcr->mutex);
- pm_strcpy(&jcr->last_fname, ofile);
+ pm_strcpy(&jcr->last_fname, attr->ofname);
V(jcr->mutex);
jcr->JobFiles++;
fileAddr = 0;
- print_ls_output(jcr, ofile, lname, type, &statp);
+ print_ls_output(jcr, attr);
/* Set attributes after file extracted */
break;
case CF_CREATED:
+ P(jcr->mutex);
+ pm_strcpy(&jcr->last_fname, attr->ofname);
+ V(jcr->mutex);
jcr->JobFiles++;
fileAddr = 0;
- print_ls_output(jcr, ofile, lname, type, &statp);
+ print_ls_output(jcr, attr);
/* set attributes now because file will not be extracted */
- set_attributes(jcr, fname, ofile, lname, type, stream,
- &statp, attribsEx, &bfd);
+ set_attributes(jcr, attr, &bfd);
break;
}
+ break;
-
- /* Data stream */
- } else if (stream == STREAM_FILE_DATA || stream == STREAM_SPARSE_DATA ||
- stream == STREAM_WIN32_DATA) {
- if (stream == STREAM_WIN32_DATA && !is_win32_backup()) {
- Jmsg(jcr, M_ERROR, 0, _("Win32 backup data not supported on this Client.\n"));
+ /* Windows Backup data stream */
+ 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"));
+ }
extract = FALSE;
+ non_support_data++;
continue;
}
+ goto extract_data;
+
+ /* Data stream */
+ case STREAM_FILE_DATA:
+ case STREAM_SPARSE_DATA:
+
+extract_data:
if (extract) {
if (stream == STREAM_SPARSE_DATA) {
ser_declare;
fileAddr = faddr;
if (blseek(&bfd, (off_t)fileAddr, SEEK_SET) < 0) {
Jmsg3(jcr, M_ERROR, 0, _("Seek to %s error on %s: ERR=%s\n"),
- edit_uint64(fileAddr, ec1), ofile, berror(&bfd));
+ edit_uint64(fileAddr, ec1), attr->ofname, berror(&bfd));
extract = FALSE;
continue;
}
Dmsg2(30, "Write %u bytes, total before write=%u\n", wsize, total);
if ((uint32_t)bwrite(&bfd, wbuf, wsize) != wsize) {
Dmsg0(0, "===Write error===\n");
- Jmsg2(jcr, M_ERROR, 0, _("Write error on %s: ERR=%s\n"), ofile, berror(&bfd));
+ Jmsg2(jcr, M_ERROR, 0, _("Write error on %s: ERR=%s\n"), attr->ofname, berror(&bfd));
extract = FALSE;
continue;
}
jcr->ReadBytes += wsize;
fileAddr += wsize;
}
-
- /* GZIP data stream */
- } else if (stream == STREAM_GZIP_DATA || stream == STREAM_SPARSE_GZIP_DATA ||
- stream == STREAM_WIN32_GZIP_DATA) {
- if (stream == STREAM_WIN32_GZIP_DATA && !is_win32_backup()) {
- Jmsg(jcr, M_ERROR, 0, _("Win32 GZIP backup data not supported on this Client.\n"));
+ break;
+
+ /* Windows Backup GZIP data stream */
+ 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"));
+ }
extract = FALSE;
+ non_support_attr++;
continue;
}
+ /* Fall through desired */
+
+ /* GZIP data stream */
+ case STREAM_GZIP_DATA:
+ case STREAM_SPARSE_GZIP_DATA:
#ifdef HAVE_LIBZ
if (extract) {
ser_declare;
fileAddr = faddr;
if (blseek(&bfd, (off_t)fileAddr, SEEK_SET) < 0) {
Jmsg3(jcr, M_ERROR, 0, _("Seek to %s error on %s: ERR=%s\n"),
- edit_uint64(fileAddr, ec1), ofile, berror(&bfd));
+ edit_uint64(fileAddr, ec1), attr->ofname, berror(&bfd));
extract = FALSE;
continue;
}
Dmsg2(100, "Write uncompressed %d bytes, total before write=%d\n", compress_len, total);
if ((uLong)bwrite(&bfd, jcr->compress_buf, compress_len) != compress_len) {
Dmsg0(0, "===Write error===\n");
- Jmsg2(jcr, M_ERROR, 0, _("Write error on %s: %s\n"), ofile, berror(&bfd));
+ Jmsg2(jcr, M_ERROR, 0, _("Write error on %s: %s\n"), attr->ofname, berror(&bfd));
extract = FALSE;
continue;
}
continue;
}
#endif
- /* If extracting, wierd stream (not 1 or 2), close output file anyway */
- } else if (extract) {
- Dmsg1(30, "Found wierd stream %d\n", stream);
- if (!is_bopen(&bfd)) {
- Jmsg0(jcr, M_ERROR, 0, _("Logic error output file should be open but is not.\n"));
+ break;
+
+ case STREAM_MD5_SIGNATURE:
+ case STREAM_SHA1_SIGNATURE:
+ break;
+
+ case STREAM_PROGRAM_NAMES:
+ case STREAM_PROGRAM_DATA:
+ if (!prog_name_msg) {
+ Pmsg0(000, "Got Program Name or Data Stream. Ignored.\n");
+ prog_name_msg++;
}
- set_attributes(jcr, fname, ofile, lname, type, stream,
- &statp, attribsEx, &bfd);
- extract = FALSE;
- } else if (!(stream == STREAM_MD5_SIGNATURE || stream == STREAM_SHA1_SIGNATURE)) {
+ break;
+
+ default:
+ /* If extracting, wierd stream (not 1 or 2), close output file anyway */
+ if (extract) {
+ Dmsg1(30, "Found wierd stream %d\n", stream);
+ if (!is_bopen(&bfd)) {
+ Jmsg0(jcr, M_ERROR, 0, _("Logic error output file should be open but is not.\n"));
+ }
+ set_attributes(jcr, attr, &bfd);
+ extract = FALSE;
+ }
+ Jmsg(jcr, M_ERROR, 0, _("Unknown stream=%d ignored. This shouldn't happen!\n"), stream);
Dmsg2(0, "None of above!!! stream=%d data=%s\n", stream,sd->msg);
- }
- }
+ break;
+ } /* end switch(stream) */
+
+ } /* end while get_msg() */
/* If output file is still open, it was the last one in the
* archive since we just hit an end of file, so close the file.
*/
if (is_bopen(&bfd)) {
- set_attributes(jcr, fname, ofile, lname, type, stream,
- &statp, attribsEx, &bfd);
+ set_attributes(jcr, attr, &bfd);
}
set_jcr_job_status(jcr, JS_Terminated);
goto ok_out;
free(jcr->compress_buf);
jcr->compress_buf = NULL;
}
- free_pool_memory(fname);
- free_pool_memory(ofile);
- free_pool_memory(lname);
- free_pool_memory(attribsEx);
+ free_attr(attr);
Dmsg2(10, "End Do Restore. Files=%d Bytes=%" lld "\n", jcr->JobFiles,
jcr->JobBytes);
-}
-
-extern char *getuser(uid_t uid);
-extern char *getgroup(gid_t gid);
-
-/*
- * Print an ls style message, also send INFO
- */
-static void print_ls_output(JCR *jcr, char *fname, char *lname, int type, struct stat *statp)
-{
- char buf[5000];
- char ec1[30];
- char *p, *f;
- int n;
-
- p = encode_mode(statp->st_mode, buf);
- n = sprintf(p, " %2d ", (uint32_t)statp->st_nlink);
- p += n;
- n = sprintf(p, "%-8.8s %-8.8s", getuser(statp->st_uid), getgroup(statp->st_gid));
- p += n;
- n = sprintf(p, "%8.8s ", edit_uint64(statp->st_size, ec1));
- p += n;
- p = encode_time(statp->st_ctime, p);
- *p++ = ' ';
- *p++ = ' ';
- for (f=fname; *f && (p-buf) < (int)sizeof(buf)-10; ) {
- *p++ = *f++;
+ if (non_support_data > 1 || non_support_attr > 1) {
+ Jmsg(jcr, M_ERROR, 0, _("%d non-supported data streams and %d non-supported attrib streams ignored.\n"),
+ non_support_data, non_support_attr);
}
- if (type == FT_LNK) {
- *p++ = ' ';
- *p++ = '-';
- *p++ = '>';
- *p++ = ' ';
- /* Copy link name */
- for (f=lname; *f && (p-buf) < (int)sizeof(buf)-10; ) {
- *p++ = *f++;
- }
- }
- *p++ = '\n';
- *p = 0;
- Dmsg1(20, "%s", buf);
- Jmsg(jcr, M_RESTORED, 0, "%s", buf);
-}
+}
if ((jcr->big_buf = (char *) malloc(jcr->buf_size)) == NULL) {
Jmsg1(jcr, M_ABORT, 0, _("Cannot malloc %d network read buffer\n"), MAX_NETWORK_BUFFER_SIZE);
}
- set_find_options((FF_PKT *)jcr->ff, jcr->incremental, jcr->mtime);
+ set_find_options((FF_PKT *)jcr->ff, jcr->incremental, jcr->mtime, jcr->mtime_only);
Dmsg0(10, "Start find files\n");
/* Subroutine verify_file() is called for each file */
find_files(jcr, (FF_PKT *)jcr->ff, verify_file, (void *)jcr);
static char rec_header[] = "rechdr %ld %ld %ld %ld %ld";
/* Forward referenced functions */
-#ifdef needed
-static void print_ls_output(JCR *jcr, char *fname, char *lname, int type, struct stat *statp);
-#endif
/*
/* File Attributes stream */
switch (stream) {
case STREAM_UNIX_ATTRIBUTES:
- case STREAM_WIN32_ATTRIBUTES:
+ case STREAM_UNIX_ATTRIBUTES_EX:
char *ap, *lp, *fp;
Dmsg0(400, "Stream=Unix Attributes.\n");
Dmsg2(050, "End Verify-Vol. Files=%d Bytes=%" lld "\n", jcr->JobFiles,
jcr->JobBytes);
}
-
-extern char *getuser(uid_t uid);
-extern char *getgroup(gid_t gid);
-
-/*
- * Print an ls style message, also send INFO
- */
-#ifdef needed
-static void print_ls_output(JCR *jcr, char *fname, char *lname, int type, struct stat *statp)
-{
- char buf[2000];
- char ec1[30];
- char *p, *f;
- int n;
-
- p = encode_mode(statp->st_mode, buf);
- n = sprintf(p, " %2d ", (uint32_t)statp->st_nlink);
- p += n;
- n = sprintf(p, "%-8.8s %-8.8s", getuser(statp->st_uid), getgroup(statp->st_gid));
- p += n;
- n = sprintf(p, "%8.8s ", edit_uint64(statp->st_size, ec1));
- p += n;
- p = encode_time(statp->st_ctime, p);
- *p++ = ' ';
- *p++ = ' ';
- for (f=fname; *f && (p-buf) < (int)sizeof(buf)-10; )
- *p++ = *f++;
- if (type == FT_LNK) {
- *p++ = ' ';
- *p++ = '-';
- *p++ = '>';
- *p++ = ' ';
- /* Copy link name */
- for (f=lname; *f && (p-buf) < (int)sizeof(buf)-10; )
- *p++ = *f++;
- }
- *p++ = '\n';
- *p = 0;
- Dmsg0(20, buf);
- Jmsg(jcr, M_INFO, 0, "%s", buf);
-}
-#endif
/* Forward referenced subroutines */
static
-int set_win32_attributes(JCR *jcr, char *fname, char *ofile, char *lname,
- int type, int stream, struct stat *statp,
- char *attribsEx, BFILE *ofd);
+int set_win32_attributes(JCR *jcr, ATTR *attr, BFILE *ofd);
void unix_name_to_win32(POOLMEM **win32_name, char *name);
void win_error(JCR *jcr, char *prefix, POOLMEM *ofile);
HANDLE bget_handle(BFILE *bfd);
/*=============================================================*/
-/* Encode a stat structure into a base64 character string */
+/*
+ * Encode a stat structure into a base64 character string
+ * All systems must create such a structure.
+ * In addition, we tack on the LinkFI, which is non-zero in
+ * the case of a hard linked file that has no data. This
+ * is a File Index pointing to the link that does have the
+ * data (always the first one encountered in a save).
+ * You may piggyback attributes on this packet by encoding
+ * them in the encode_attribsEx() subroutine, but this is
+ * not recommended.
+ */
void encode_stat(char *buf, struct stat *statp, uint32_t LinkFI)
{
char *p = buf;
* Returns: 1 on success
* 0 on failure
*/
-int set_attributes(JCR *jcr, char *fname, char *ofile, char *lname,
- int type, int stream, struct stat *statp,
- char *attribsEx, BFILE *ofd)
+int set_attributes(JCR *jcr, ATTR *attr, BFILE *ofd)
{
struct utimbuf ut;
mode_t old_mask;
int stat = 1;
#ifdef HAVE_CYGWIN
- if (set_win32_attributes(jcr, fname, ofile, lname, type, stream,
- statp, attribsEx, ofd)) {
+ if (stream == STREAM_UNIX_ATTRIBUTES_EX &&
+ set_win32_attributes(jcr, attr, ofd)) {
return 1;
}
/*
bclose(ofd); /* first close file */
}
- ut.actime = statp->st_atime;
- ut.modtime = statp->st_mtime;
+ ut.actime = attr->statp.st_atime;
+ ut.modtime = attr->statp.st_mtime;
/* ***FIXME**** optimize -- don't do if already correct */
/*
* For link, change owner of link using lchown, but don't
* try to do a chmod as that will update the file behind it.
*/
- if (type == FT_LNK) {
+ if (attr->type == FT_LNK) {
/* Change owner of link, not of real file */
- if (lchown(ofile, statp->st_uid, statp->st_gid) < 0) {
+ if (lchown(attr->ofname, attr->statp.st_uid, attr->statp.st_gid) < 0) {
Jmsg2(jcr, M_WARNING, 0, _("Unable to set file owner %s: ERR=%s\n"),
- ofile, strerror(errno));
+ attr->ofname, strerror(errno));
stat = 0;
}
} else {
- if (chown(ofile, statp->st_uid, statp->st_gid) < 0) {
+ if (chown(attr->ofname, attr->statp.st_uid, attr->statp.st_gid) < 0) {
Jmsg2(jcr, M_WARNING, 0, _("Unable to set file owner %s: ERR=%s\n"),
- ofile, strerror(errno));
+ attr->ofname, strerror(errno));
stat = 0;
}
- if (chmod(ofile, statp->st_mode) < 0) {
+ if (chmod(attr->ofname, attr->statp.st_mode) < 0) {
Jmsg2(jcr, M_WARNING, 0, _("Unable to set file modes %s: ERR=%s\n"),
- ofile, strerror(errno));
+ attr->ofname, strerror(errno));
stat = 0;
}
/* FreeBSD user flags */
#ifdef HAVE_CHFLAGS
- if (chflags(ofile, statp->st_flags) < 0) {
+ if (chflags(attr->ofname, attr->statp.st_flags) < 0) {
Jmsg2(jcr, M_WARNING, 0, _("Unable to set file flags %s: ERR=%s\n"),
- ofile, strerror(errno));
+ attr->ofname, strerror(errno));
stat = 0;
}
#endif
/*
* Reset file times.
*/
- if (utime(ofile, &ut) < 0) {
+ if (utime(attr->ofname, &ut) < 0) {
Jmsg2(jcr, M_ERROR, 0, _("Unable to set file times %s: ERR=%s\n"),
- ofile, strerror(errno));
+ attr->ofname, strerror(errno));
stat = 0;
}
}
#ifndef HAVE_CYGWIN
/*
- * If you have a Unix system with extended attributes (e.g.
- * ACLs for Solaris, do it here.
+ * It is possible to piggyback additional data e.g. ACLs on
+ * the encode_stat() data by returning the extended attributes
+ * here. They must be "self-contained" (i.e. you keep track
+ * of your own length), and they must be in ASCII string
+ * format. Using this feature is not recommended.
+ * The code below shows how to return nothing. See the Win32
+ * code below for returning something in the attributes.
*/
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_WIN32_ATTRIBUTES;
+ return STREAM_UNIX_ATTRIBUTES_EX;
}
p += to_base64((uint64_t)atts.dwFileAttributes, p);
*p++ = ' ';
p += to_base64((uint64_t)atts.nFileSizeLow, p);
*p = 0;
- return STREAM_WIN32_ATTRIBUTES;
+ return STREAM_UNIX_ATTRIBUTES_EX;
}
/* Define attributes that are legal to set with SetFileAttributes() */
* 0 on failure
*/
static
-int set_win32_attributes(JCR *jcr, char *fname, char *ofile, char *lname,
- int type, int stream, struct stat *statp,
- char *attribsEx, BFILE *ofd)
+int set_win32_attributes(JCR *jcr, ATTR *attr, BFILE *ofd)
{
- char *p = attribsEx;
+ char *p = attr->attrEx;
int64_t val;
WIN32_FILE_ATTRIBUTE_DATA atts;
ULARGE_INTEGER li;
POOLMEM *win32_ofile;
if (!p || !*p) { /* we should have attributes */
- Dmsg2(100, "Attributes missing. of=%s ofd=%d\n", ofile, ofd->fid);
+ Dmsg2(100, "Attributes missing. of=%s ofd=%d\n", attr->ofname, ofd->fid);
if (is_bopen(ofd)) {
bclose(ofd);
}
return 0;
} else {
- Dmsg2(100, "Attribs %s = %s\n", ofile, attribsEx);
+ Dmsg2(100, "Attribs %s = %s\n", attr->ofname, attr->attrEx);
}
p += from_base64(&val, p);
/* Convert to Windows path format */
win32_ofile = get_pool_memory(PM_FNAME);
- unix_name_to_win32(&win32_ofile, ofile);
+ unix_name_to_win32(&win32_ofile, attr->ofname);
if (!is_bopen(ofd)) {
- Dmsg1(100, "File not open: %s\n", ofile);
- bopen(ofd, ofile, O_WRONLY|O_BINARY, 0); /* attempt to open the file */
+ Dmsg1(100, "File not open: %s\n", attr->ofname);
+ bopen(ofd, attr->ofname, O_WRONLY|O_BINARY, 0); /* attempt to open the file */
}
if (is_bopen(ofd)) {
- Dmsg1(100, "SetFileTime %s\n", ofile);
+ Dmsg1(100, "SetFileTime %s\n", attr->ofname);
if (!SetFileTime(bget_handle(ofd),
&atts.ftCreationTime,
&atts.ftLastAccessTime,
bclose(ofd);
}
- Dmsg1(100, "SetFileAtts %s\n", ofile);
+ Dmsg1(100, "SetFileAtts %s\n", attr->ofname);
if (!(atts.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
if (!SetFileAttributes(win32_ofile, atts.dwFileAttributes & SET_ATTRS)) {
win_error(jcr, "SetFileAttributes:", win32_ofile);
return bfd->use_backup_api;
}
+/*
+ * Return 1 if we can do Win32 backup
+ * return 0 if not
+ */
int is_win32_backup(void)
{
return p_BackupRead && p_BackupWrite;
}
+int is_stream_supported(int stream)
+{
+ if (is_win32_backup()) {
+ return 1;
+ }
+ /* No Win32 backup on this machine */
+ switch (stream) {
+ case STREAM_WIN32_ATTRIBUTES:
+ case STREAM_WIN32_DATA:
+ case STREAM_WIN32_GZIP_DATA:
+ return 0;
+
+ /* Known streams */
+ 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:
+ return 1;
+
+ }
+ return 0;
+}
+
HANDLE bget_handle(BFILE *bfd)
{
return bfd->fh;
return 0;
}
+int is_stream_supported(int stream)
+{
+ /* No Win32 backup on this machine */
+ switch (stream) {
+ case STREAM_WIN32_ATTRIBUTES:
+ case STREAM_WIN32_DATA:
+ case STREAM_WIN32_GZIP_DATA:
+ return 0;
+
+ /* Known streams */
+ 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:
+ return 1;
+
+ }
+ return 0;
+}
int bopen(BFILE *bfd, const char *fname, int flags, mode_t mode)
{
#include "winapi.h"
#define BF_CLOSED 0
-#define BF_READ 1 /* BackupRead */
-#define BF_WRITE 2 /* BackupWrite */
+#define BF_READ 1 /* BackupRead */
+#define BF_WRITE 2 /* 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 */
+ int use_win_api; /* set if using WinAPI */
#endif
- int use_backup_api; /* set if using BackupRead/Write */
- int mode; /* set if file is open */
- HANDLE fh; /* Win32 file handle */
- int fid; /* fd if doing Unix style */
- LPVOID lpContext; /* BackupRead/Write context */
- POOLMEM *errmsg; /* error message buffer */
- DWORD rw_bytes; /* Bytes read or written */
- DWORD lerror; /* Last error code */
+ int use_backup_api; /* set if using BackupRead/Write */
+ int mode; /* set if file is open */
+ HANDLE fh; /* Win32 file handle */
+ int fid; /* fd if doing Unix style */
+ LPVOID lpContext; /* BackupRead/Write context */
+ 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 */
+#else /* Linux/Unix systems */
/* Basic low level I/O file packet */
typedef struct s_bfile {
- int fid; /* file id on Unix */
+ int fid; /* file id on Unix */
int berrno;
} BFILE;
#endif
-void binit(BFILE *bfd);
-int is_bopen(BFILE *bfd);
-int set_win32_backup(BFILE *bfd, int enable);
-int is_win32_backup();
-char *berror(BFILE *bfd);
-int bopen(BFILE *bfd, const char *fname, int flags, mode_t mode);
-int bclose(BFILE *bfd);
+void binit(BFILE *bfd);
+int is_bopen(BFILE *bfd);
+int set_win32_backup(BFILE *bfd, int enable);
+int is_win32_backup();
+int is_stream_supported(int stream);
+char *berror(BFILE *bfd);
+int bopen(BFILE *bfd, const char *fname, int flags, mode_t mode);
+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);
+off_t blseek(BFILE *bfd, off_t offset, int whence);
#endif /* __BFILE_H */
* files.
*
*/
-int create_file(JCR *jcr, char *fname, char *ofile, char *lname,
- int type, int stream, struct stat *statp,
- char *attribsEx, BFILE *ofd, int replace)
+int create_file(JCR *jcr, ATTR *attr, BFILE *ofd, int replace)
{
int new_mode, parent_mode, mode;
uid_t uid;
int pnl;
binit(ofd);
- new_mode = statp->st_mode;
- Dmsg2(300, "newmode=%x file=%s\n", new_mode, ofile);
+ new_mode = attr->statp.st_mode;
+ Dmsg2(300, "newmode=%x file=%s\n", new_mode, attr->ofname);
parent_mode = S_IWUSR | S_IXUSR | new_mode;
- gid = statp->st_gid;
- uid = statp->st_uid;
+ gid = attr->statp.st_gid;
+ uid = attr->statp.st_uid;
Dmsg2(400, "Replace=%c %d\n", (char)replace, replace);
/* If not always replacing, do a stat and decide */
if (replace != REPLACE_ALWAYS) {
struct stat mstatp;
- if (lstat(ofile, &mstatp) == 0) {
+ if (lstat(attr->ofname, &mstatp) == 0) {
switch (replace) {
case REPLACE_IFNEWER:
- if (statp->st_mtime <= mstatp.st_mtime) {
- Jmsg(jcr, M_SKIPPED, 0, _("File skipped. Not newer: %s\n"), ofile);
+ if (attr->statp.st_mtime <= mstatp.st_mtime) {
+ Jmsg(jcr, M_SKIPPED, 0, _("File skipped. Not newer: %s\n"), attr->ofname);
return CF_SKIP;
}
break;
case REPLACE_IFOLDER:
- if (statp->st_mtime >= mstatp.st_mtime) {
- Jmsg(jcr, M_SKIPPED, 0, _("File skipped. Not older: %s\n"), ofile);
+ if (attr->statp.st_mtime >= mstatp.st_mtime) {
+ Jmsg(jcr, M_SKIPPED, 0, _("File skipped. Not older: %s\n"), attr->ofname);
return CF_SKIP;
}
break;
case REPLACE_NEVER:
- Jmsg(jcr, M_SKIPPED, 0, _("File skipped. Already exists: %s\n"), ofile);
+ Jmsg(jcr, M_SKIPPED, 0, _("File skipped. Already exists: %s\n"), attr->ofname);
return CF_SKIP;
}
}
}
- switch (type) {
+ switch (attr->type) {
case FT_LNKSAVED: /* Hard linked, file already saved */
case FT_LNK:
case FT_RAW:
* not already exist. Below, we will split to
* do the file type specific work
*/
- pnl = separate_path_and_file(jcr, fname, ofile);
+ pnl = separate_path_and_file(jcr, attr->fname, attr->ofname);
if (pnl < 0) {
return CF_ERROR;
}
*/
if (pnl > 0) {
char savechr;
- savechr = ofile[pnl];
- ofile[pnl] = 0; /* terminate path */
+ savechr = attr->ofname[pnl];
+ attr->ofname[pnl] = 0; /* terminate path */
- if (!path_already_seen(ofile, pnl)) {
- Dmsg1(50, "Make path %s\n", ofile);
+ if (!path_already_seen(attr->ofname, pnl)) {
+ Dmsg1(50, "Make path %s\n", attr->ofname);
/*
* If we need to make the directory, ensure that it is with
* execute bit set (i.e. parent_mode), and preserve what already
* exists. Normally, this should do nothing.
*/
- if (make_path(jcr, ofile, parent_mode, parent_mode, uid, gid, 1, NULL) != 0) {
- Dmsg1(0, "Could not make path. %s\n", ofile);
+ if (make_path(jcr, attr->ofname, parent_mode, parent_mode, uid, gid, 1, NULL) != 0) {
+ Dmsg1(0, "Could not make path. %s\n", attr->ofname);
return CF_ERROR;
}
}
- ofile[pnl] = savechr; /* restore full name */
+ attr->ofname[pnl] = savechr; /* restore full name */
}
/* Now we do the specific work for each file type */
- switch(type) {
+ switch(attr->type) {
case FT_REGE:
case FT_REG:
- Dmsg1(100, "Create file %s\n", ofile);
+ Dmsg1(100, "Create file %s\n", attr->ofname);
mode = O_WRONLY | O_CREAT | O_TRUNC | O_BINARY; /* O_NOFOLLOW; */
- if (IS_CTG(statp->st_mode)) {
+ if (IS_CTG(attr->statp.st_mode)) {
mode |= O_CTG; /* set contiguous bit if needed */
}
- Dmsg1(50, "Create file: %s\n", ofile);
- if ((bopen(ofd, ofile, mode, S_IRUSR | S_IWUSR)) < 0) {
+ Dmsg1(50, "Create file: %s\n", attr->ofname);
+ if ((bopen(ofd, attr->ofname, mode, S_IRUSR | S_IWUSR)) < 0) {
Jmsg2(jcr, M_ERROR, 0, _("Could not create %s: ERR=%s\n"),
- ofile, berror(ofd));
+ attr->ofname, berror(ofd));
return CF_ERROR;
}
return CF_EXTRACT;
case FT_RAW: /* Bacula raw device e.g. /dev/sda1 */
case FT_FIFO: /* Bacula fifo to save data */
case FT_SPEC:
- if (S_ISFIFO(statp->st_mode)) {
- Dmsg1(200, "Restore fifo: %s\n", ofile);
- if (mkfifo(ofile, statp->st_mode) != 0 && errno != EEXIST) {
+ if (S_ISFIFO(attr->statp.st_mode)) {
+ Dmsg1(200, "Restore fifo: %s\n", attr->ofname);
+ if (mkfifo(attr->ofname, attr->statp.st_mode) != 0 && errno != EEXIST) {
Jmsg2(jcr, M_ERROR, 0, _("Cannot make fifo %s: ERR=%s\n"),
- ofile, strerror(errno));
+ attr->ofname, strerror(errno));
return CF_ERROR;
}
} else {
- Dmsg1(200, "Restore node: %s\n", ofile);
- if (mknod(ofile, statp->st_mode, statp->st_rdev) != 0 && errno != EEXIST) {
+ Dmsg1(200, "Restore node: %s\n", attr->ofname);
+ if (mknod(attr->ofname, attr->statp.st_mode, attr->statp.st_rdev) != 0 && errno != EEXIST) {
Jmsg2(jcr, M_ERROR, 0, _("Cannot make node %s: ERR=%s\n"),
- ofile, strerror(errno));
+ attr->ofname, strerror(errno));
return CF_ERROR;
}
}
- if (type == FT_RAW || type == FT_FIFO) {
+ if (attr->type == FT_RAW || attr->type == FT_FIFO) {
btimer_id tid;
- Dmsg1(200, "FT_RAW|FT_FIFO %s\n", ofile);
+ Dmsg1(200, "FT_RAW|FT_FIFO %s\n", attr->ofname);
mode = O_WRONLY | O_BINARY;
/* Timeout open() in 60 seconds */
- if (type == FT_FIFO) {
+ if (attr->type == FT_FIFO) {
tid = start_thread_timer(pthread_self(), 60);
} else {
tid = NULL;
}
- if ((bopen(ofd, ofile, mode, 0)) < 0) {
+ if ((bopen(ofd, attr->ofname, mode, 0)) < 0) {
Jmsg2(jcr, M_ERROR, 0, _("Could not open %s: ERR=%s\n"),
- ofile, berror(ofd));
+ attr->ofname, berror(ofd));
stop_thread_timer(tid);
return CF_ERROR;
}
stop_thread_timer(tid);
return CF_EXTRACT;
}
- Dmsg1(200, "FT_SPEC %s\n", ofile);
+ Dmsg1(200, "FT_SPEC %s\n", attr->ofname);
return CF_CREATED;
case FT_LNK:
- Dmsg2(130, "FT_LNK should restore: %s -> %s\n", ofile, lname);
- if (symlink(lname, ofile) != 0 && errno != EEXIST) {
+ Dmsg2(130, "FT_LNK should restore: %s -> %s\n", attr->ofname, attr->olname);
+ if (symlink(attr->olname, attr->ofname) != 0 && errno != EEXIST) {
Jmsg3(jcr, M_ERROR, 0, _("Could not symlink %s -> %s: ERR=%s\n"),
- ofile, lname, strerror(errno));
+ attr->ofname, attr->olname, strerror(errno));
return CF_ERROR;
}
return CF_CREATED;
case FT_LNKSAVED: /* Hard linked, file already saved */
- Dmsg2(130, "Hard link %s => %s\n", ofile, lname);
- if (link(lname, ofile) != 0) {
+ Dmsg2(130, "Hard link %s => %s\n", attr->ofname, attr->olname);
+ if (link(attr->olname, attr->ofname) != 0) {
Jmsg3(jcr, M_ERROR, 0, _("Could not hard link %s -> %s: ERR=%s\n"),
- ofile, lname, strerror(errno));
+ attr->ofname, attr->olname, strerror(errno));
return CF_ERROR;
}
return CF_CREATED;
} /* End inner switch */
case FT_DIR:
- Dmsg2(300, "Make dir mode=%o dir=%s\n", new_mode, ofile);
- if (make_path(jcr, ofile, new_mode, parent_mode, uid, gid, 0, NULL) != 0) {
+ Dmsg2(300, "Make dir mode=%o dir=%s\n", new_mode, attr->ofname);
+ if (make_path(jcr, attr->ofname, new_mode, parent_mode, uid, gid, 0, NULL) != 0) {
return CF_ERROR;
}
/*
* and saved.
*/
if (is_win32_backup()) {
- if ((bopen(ofd, ofile, O_WRONLY|O_BINARY, 0)) < 0) {
+ if ((bopen(ofd, attr->ofname, O_WRONLY|O_BINARY, 0)) < 0) {
Jmsg2(jcr, M_ERROR, 0, _("Could not open %s: ERR=%s\n"),
- ofile, berror(ofd));
+ attr->ofname, berror(ofd));
return CF_ERROR;
}
return CF_EXTRACT;
case FT_NORECURSE:
case FT_NOFSCHG:
case FT_NOOPEN:
- Jmsg2(jcr, M_ERROR, 0, _("Original file %s not saved: type=%d\n"), fname, type);
+ Jmsg2(jcr, M_ERROR, 0, _("Original file %s not saved: type=%d\n"), attr->fname, attr->type);
+ break;
default:
- Jmsg2(jcr, M_ERROR, 0, _("Unknown file type %d; not restored: %s\n"), type, fname);
+ Jmsg2(jcr, M_ERROR, 0, _("Unknown file type %d; not restored: %s\n"), attr->type, attr->fname);
+ break;
}
return CF_ERROR;
}
* of save_time. For additional options, see above
*/
void
-set_find_options(FF_PKT *ff, int incremental, time_t save_time)
+set_find_options(FF_PKT *ff, int incremental, time_t save_time, int mtime_only)
{
Dmsg0(100, "Enter set_find_options()\n");
ff->incremental = incremental;
ff->save_time = save_time;
+ ff->mtime_only = mtime_only;
Dmsg0(100, "Leave set_find_options()\n");
}
#define CF_EXTRACT 3 /* file created, data to extract */
#define CF_CREATED 4 /* file created, no data to extract */
-/*
- * NOTE!!! These go on the tape, so don't change them. If
- * need be, add to them.
- */
-#define FT_LNKSAVED 1 /* hard link to file already saved */
-#define FT_REGE 2 /* Regular file but empty */
-#define FT_REG 3 /* Regular file */
-#define FT_LNK 4 /* Soft Link */
-#define FT_DIR 5 /* Directory */
-#define FT_SPEC 6 /* Special file -- chr, blk, fifo, sock */
-#define FT_NOACCESS 7 /* Not able to access */
-#define FT_NOFOLLOW 8 /* Could not follow link */
-#define FT_NOSTAT 9 /* Could not stat file */
-#define FT_NOCHG 10 /* Incremental option, file not changed */
-#define FT_DIRNOCHG 11 /* Incremental option, directory not changed */
-#define FT_ISARCH 12 /* Trying to save archive file */
-#define FT_NORECURSE 13 /* No recursion into directory */
-#define FT_NOFSCHG 14 /* Different file system, prohibited */
-#define FT_NOOPEN 15 /* Could not open directory */
-#define FT_RAW 16 /* Raw block device */
-#define FT_FIFO 17 /* Raw fifo device */
/* Options saved in "flag" of ff packet */
#define FO_MD5 0x001 /* Do MD5 checksum */
*/
/* 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);
-int encode_attribsEx (JCR *jcr, char *attribsEx, FF_PKT *ff_pkt);
-int set_attributes(JCR *jcr, char *fname, char *ofile, char *lname,
- int type, int stream, struct stat *statp,
- char *attribsEx, BFILE *ofd);
+void encode_stat (char *buf, struct stat *statp, uint32_t LinkFI);
+void 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);
/* from create_file.c */
-int create_file(JCR *jcr, char *fname, char *ofile, char *lname,
- int type, int stream, struct stat *statp,
- char *attribsEx, BFILE *ofd, int replace);
+int create_file (JCR *jcr, ATTR *attr, BFILE *ofd, int replace);
/* From find.c */
FF_PKT *init_find_files();
-void set_find_options(FF_PKT *ff, int incremental, time_t mtime);
-int find_files(JCR *jcr, FF_PKT *ff, int sub(FF_PKT *ff_pkt, void *hpkt), void *pkt);
-int term_find_files(FF_PKT *ff);
+void set_find_options(FF_PKT *ff, int incremental, time_t mtime, int mtime_only);
+int find_files(JCR *jcr, FF_PKT *ff, int sub(FF_PKT *ff_pkt, void *hpkt), void *pkt);
+int term_find_files(FF_PKT *ff);
/* From match.c */
-void init_include_exclude_files(FF_PKT *ff);
-void term_include_exclude_files(FF_PKT *ff);
-void add_fname_to_include_list(FF_PKT *ff, int prefixed, char *fname);
-void add_fname_to_exclude_list(FF_PKT *ff, char *fname);
-int file_is_excluded(FF_PKT *ff, char *file);
-int file_is_included(FF_PKT *ff, char *file);
+void init_include_exclude_files(FF_PKT *ff);
+void term_include_exclude_files(FF_PKT *ff);
+void add_fname_to_include_list(FF_PKT *ff, int prefixed, char *fname);
+void add_fname_to_exclude_list(FF_PKT *ff, char *fname);
+int file_is_excluded(FF_PKT *ff, char *file);
+int file_is_included(FF_PKT *ff, char *file);
struct s_included_file *get_next_included_file(FF_PKT *ff,
struct s_included_file *inc);
/* From find_one.c */
-int find_one_file(JCR *jcr, FF_PKT *ff, int handle_file(FF_PKT *ff_pkt, void *hpkt),
+int find_one_file(JCR *jcr, FF_PKT *ff, int handle_file(FF_PKT *ff_pkt, void *hpkt),
void *pkt, char *p, dev_t parent_device, int top_level);
-int term_find_one(FF_PKT *ff);
+int term_find_one(FF_PKT *ff);
/* From get_priv.c */
-int get_backup_privileges(JCR *jcr, int ignore_errors);
+int enable_backup_privileges(JCR *jcr, int ignore_errors);
/* from makepath.c */
char *sd_auth_key; /* SD auth key */
MSGS *jcr_msgs; /* Copy of message resource -- actually used */
uint32_t ClientId; /* Client associated with Job */
+ char *where; /* prefix to restore files to */
+ int prefix_links; /* Prefix links with Where path */
/* Daemon specific part of JCR */
/* This should be empty in the library */
POOLMEM *stime; /* start time for incremental/differential */
JOB_DBR jr; /* Job record in Database */
uint32_t RestoreJobId; /* Id specified by UA */
- char *RestoreWhere; /* Where to restore the files */
POOLMEM *client_uname; /* client uname */
int replace; /* Replace option */
int acquired_resource_locks; /* set if resource locks acquired */
char *big_buf; /* I/O buffer */
POOLMEM *compress_buf; /* Compression buffer */
int32_t compress_buf_size; /* Length of compression buffer */
- POOLMEM *where; /* Root where to restore */
int replace; /* Replace options */
- int prefix_links; /* Prefix links with Where path */
int buf_size; /* length of buffer */
void *ff; /* Find Files packet */
char stored_addr[MAX_NAME_LENGTH]; /* storage daemon address */
first_rule: all
dummy:
-LIBSRCS = alloc.c base64.c bsys.c bget_msg.c \
+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 \
util.c watchdog.c workq.c
-LIBOBJS = alloc.o base64.o bsys.o bget_msg.o \
+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 \
--- /dev/null
+/*
+ * attr.c Unpack an Attribute record returned from the tape
+ *
+ * Kern Sibbald, June MMIII (code pulled from filed/restore.c and updated)
+ *
+ * Version $Id$
+ */
+
+/*
+ Copyright (C) 2000, 2001, 2002 Kern Sibbald and John Walker
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of
+ the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public
+ License along with this program; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ MA 02111-1307, USA.
+
+ */
+
+#include "bacula.h"
+#include "jcr.h"
+
+extern int win32_client;
+
+ATTR *new_attr()
+{
+ ATTR *attr = (ATTR *)malloc(sizeof(ATTR));
+ memset(attr, 0, sizeof(ATTR));
+ attr->ofname = get_pool_memory(PM_FNAME);
+ attr->olname = get_pool_memory(PM_FNAME);
+ return attr;
+}
+
+void free_attr(ATTR *attr)
+{
+ free_pool_memory(attr->olname);
+ free_pool_memory(attr->ofname);
+ free(attr);
+}
+
+int unpack_attributes_record(JCR *jcr, int32_t stream, char *rec, ATTR *attr)
+{
+ char *p;
+ /*
+ * An Attributes record consists of:
+ * File_index
+ * Type (FT_types)
+ * Filename
+ * Attributes
+ * Link name (if file linked i.e. FT_LNK)
+ * Extended attributes (Win32)
+ * plus optional values determined by AR_ flags in upper bits of Type
+ * Data_stream
+ *
+ */
+ attr->stream = stream;
+ Dmsg1(100, "Attr: %s\n", rec);
+ if (sscanf(rec, "%d %d", &attr->file_index, &attr->type) != 2) {
+ Jmsg(jcr, M_FATAL, 0, _("Error scanning attributes: %s\n"), rec);
+ Dmsg1(100, "\nError scanning attributes. %s\n", rec);
+ return 0;
+ }
+ Dmsg2(100, "Got Attr: FilInx=%d type=%d\n", attr->file_index, attr->type);
+ if (attr->type & AR_DATA_STREAM) {
+ attr->data_stream = 1;
+ } else {
+ attr->data_stream = 0;
+ }
+ attr->type &= FT_MASK; /* keep only type bits */
+ p = rec;
+ while (*p++ != ' ') /* skip record file index */
+ { }
+ while (*p++ != ' ') /* skip type */
+ { }
+
+ attr->fname = p; /* set filname position */
+ while (*p++ != 0) /* skip filename */
+ { }
+ attr->attr = p; /* set attributes position */
+ while (*p++ != 0) /* skip attributes */
+ { }
+ attr->lname = p; /* set link position */
+ while (*p++ != 0) /* skip link */
+ { }
+ attr->attrEx = p; /* set extended attributes position */
+
+ if (attr->data_stream) {
+ int64_t val;
+ while (*p++ != 0) /* skip extended attributes */
+ { }
+ from_base64(&val, p);
+ attr->data_stream = (int32_t)val;
+ }
+ Dmsg7(200, "unpack_attr FI=%d Type=%d fname=%s attr=%s lname=%s attrEx=%s ds=%d\n",
+ attr->file_index, attr->type, attr->fname, attr->attr, attr->lname,
+ attr->attrEx, attr->data_stream);
+ *attr->ofname = 0;
+ *attr->olname = 0;
+ return 1;
+}
+
+/*
+ * Build attr->ofname from attr->fname and
+ * attr->olname from attr->olname
+ */
+void build_attr_output_fnames(JCR *jcr, ATTR *attr)
+{
+ /*
+ * Prepend the where directory so that the
+ * files are put where the user wants.
+ *
+ * We do a little jig here to handle Win32 files with
+ * a drive letter -- we simply strip the drive: from
+ * every filename if a prefix is supplied.
+ *
+ */
+ if (jcr->where[0] == 0) {
+ pm_strcpy(&attr->ofname, attr->fname);
+ pm_strcpy(&attr->olname, attr->lname);
+ } else {
+ char *fn;
+ int wherelen = strlen(jcr->where);
+ pm_strcpy(&attr->ofname, jcr->where); /* copy prefix */
+ if (win32_client && attr->fname[1] == ':') {
+ fn = attr->fname+2; /* skip over drive: */
+ } else {
+ fn = attr->fname; /* take whole name */
+ }
+ /* Ensure where is terminated with a slash */
+ if (jcr->where[wherelen-1] != '/' && fn[0] != '/') {
+ pm_strcat(&attr->ofname, "/");
+ }
+ pm_strcat(&attr->ofname, fn); /* copy rest of name */
+ /*
+ * Fixup link name -- if it is an absolute path
+ */
+ if (attr->type == FT_LNKSAVED || attr->type == FT_LNK) {
+ bool add_link;
+ /* Always add prefix to hard links (FT_LNKSAVED) and
+ * on user request to soft links
+ */
+ if (attr->lname[0] == '/' &&
+ (attr->type == FT_LNKSAVED || jcr->prefix_links)) {
+ pm_strcpy(&attr->olname, jcr->where);
+ add_link = true;
+ } else {
+ attr->olname[0] = 0;
+ add_link = false;
+ }
+ if (win32_client && attr->lname[1] == ':') {
+ fn = attr->lname+2; /* skip over drive: */
+ } else {
+ fn = attr->lname; /* take whole name */
+ }
+ /* Ensure where is terminated with a slash */
+ if (add_link && jcr->where[wherelen-1] != '/' && fn[0] != '/') {
+ pm_strcat(&attr->olname, "/");
+ }
+ pm_strcat(&attr->olname, fn); /* copy rest of link */
+ }
+ }
+}
+
+extern char *getuser(uid_t uid);
+extern char *getgroup(gid_t gid);
+
+/*
+ * Print an ls style message, also send M_RESTORED
+ */
+void print_ls_output(JCR *jcr, ATTR *attr)
+{
+ char buf[5000];
+ char ec1[30];
+ char *p, *f;
+ int n;
+
+ p = encode_mode(attr->statp.st_mode, buf);
+ n = sprintf(p, " %2d ", (uint32_t)attr->statp.st_nlink);
+ p += n;
+ n = sprintf(p, "%-8.8s %-8.8s", getuser(attr->statp.st_uid), getgroup(attr->statp.st_gid));
+ p += n;
+ n = sprintf(p, "%8.8s ", edit_uint64(attr->statp.st_size, ec1));
+ p += n;
+ p = encode_time(attr->statp.st_ctime, p);
+ *p++ = ' ';
+ *p++ = ' ';
+ for (f=attr->ofname; *f && (p-buf) < (int)sizeof(buf)-10; ) {
+ *p++ = *f++;
+ }
+ if (attr->type == FT_LNK) {
+ *p++ = ' ';
+ *p++ = '-';
+ *p++ = '>';
+ *p++ = ' ';
+ /* Copy link name */
+ for (f=attr->olname; *f && (p-buf) < (int)sizeof(buf)-10; ) {
+ *p++ = *f++;
+ }
+ }
+ *p++ = '\n';
+ *p = 0;
+ Dmsg1(20, "%s", buf);
+ Jmsg(jcr, M_RESTORED, 0, "%s", buf);
+}
--- /dev/null
+/*
+ * attr.h Definition of attributes packet for unpacking from tape
+ *
+ * Kern Sibbald, June MMIII
+ *
+ * Version $Id$
+ */
+
+/*
+ Copyright (C) 2000, 2001, 2002 Kern Sibbald and John Walker
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of
+ the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public
+ License along with this program; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ MA 02111-1307, USA.
+
+ */
+
+struct ATTR {
+ int32_t stream; /* attribute stream id */
+ int32_t data_stream; /* id of data stream to follow */
+ int32_t type; /* file type FT */
+ int32_t file_index; /* file index */
+ struct stat statp; /* decoded stat packet */
+ char *attr; /* attributes position */
+ char *attrEx; /* extended attributes if any */
+ char *fname; /* filename */
+ char *lname; /* link name if any */
+ POOLMEM *ofname; /* output filename */
+ POOLMEM *olname; /* output link name */
+};
do {
errno = 0;
nread = read(bsock->fd, ptr, nleft);
- } while (!bsock->timed_out && nread == -1 && (errno == EINTR || errno == EAGAIN));
+ if (bsock->timed_out || bsock->terminated) {
+ return nread;
+ }
+ } while (nread == -1 && (errno == EINTR || errno == EAGAIN));
if (nread <= 0) {
return nread; /* error, or EOF */
}
do {
errno = 0;
nwritten = write(bsock->fd, ptr, nleft);
- } while (!bsock->timed_out && nwritten == -1 && (errno == EINTR || errno == EAGAIN));
+ if (bsock->timed_out || bsock->terminated) {
+ return nwritten;
+ }
+ } while (nwritten == -1 && errno == EINTR);
+ /*
+ * If connection is non-blocking, we will get eagain, so
+ * sleep long enough to keep from consuming all the CPU
+ * and try again.
+ */
+ if (nwritten == -1 && errno == EAGAIN) {
+ bmicrosleep(0, 50); /* sleep 50 ms */
+ continue;
+ }
if (nwritten <= 0) {
return nwritten; /* error */
}
free_pool_memory(jcr->errmsg);
jcr->errmsg = NULL;
}
+ if (jcr->where) {
+ free(jcr->where);
+ jcr->where = NULL;
+ }
free(jcr);
}
#include "tree.h"
#include "watchdog.h"
#include "bpipe.h"
+#include "attr.h"
#include "protos.h"
char catalog_db[] = "SQLite";
#endif
#ifdef HAVE_BACULA_DB
-char catlog_db[] = "Internal";
+char catalog_db[] = "Internal";
#endif
extern char my_name[];
extern char *working_directory;
extern time_t daemon_start_time;
+extern char catalog_db[];
struct JCR;
+/* attr.c */
+ATTR *new_attr();
+void free_attr(ATTR *attr);
+int unpack_attributes_record(JCR *jcr, int32_t stream, char *rec, ATTR *attr);
+void build_attr_output_fnames(JCR *jcr, ATTR *attr);
+void print_ls_output(JCR *jcr, ATTR *attr);
+
/* base64.c */
-void base64_init (void);
-int to_base64 (intmax_t value, char *where);
-int from_base64 (intmax_t *value, char *where);
-int bin_to_base64 (char *buf, char *bin, int len);
+void base64_init (void);
+int to_base64 (intmax_t value, char *where);
+int from_base64 (intmax_t *value, char *where);
+int bin_to_base64 (char *buf, char *bin, int len);
/* bsys.c */
-char *bstrncpy (char *dest, const char *src, int maxlen);
-char *bstrncat (char *dest, const char *src, int maxlen);
-void *b_malloc (char *file, int line, size_t size);
+char *bstrncpy (char *dest, const char *src, int maxlen);
+char *bstrncat (char *dest, const char *src, int maxlen);
+void *b_malloc (char *file, int line, size_t size);
#ifndef DEBUG
-void *bmalloc (size_t size);
+void *bmalloc (size_t size);
#endif
-void *brealloc (void *buf, size_t size);
-void *bcalloc (size_t size1, size_t size2);
-int bsnprintf (char *str, size_t size, const char *format, ...);
-int bvsnprintf (char *str, size_t size, const char *format, va_list ap);
-int pool_sprintf (char *pool_buf, char *fmt, ...);
-void create_pid_file (char *dir, char *progname, int port);
-int delete_pid_file (char *dir, char *progname, int port);
-void drop (char *uid, char *gid);
-int bmicrosleep (time_t sec, long msec);
+void *brealloc (void *buf, size_t size);
+void *bcalloc (size_t size1, size_t size2);
+int bsnprintf (char *str, size_t size, const char *format, ...);
+int bvsnprintf (char *str, size_t size, const char *format, va_list ap);
+int pool_sprintf (char *pool_buf, char *fmt, ...);
+void create_pid_file (char *dir, char *progname, int port);
+int delete_pid_file (char *dir, char *progname, int port);
+void drop (char *uid, char *gid);
+int bmicrosleep (time_t sec, long msec);
#ifndef HAVE_STRTOLL
long long int strtoll(const char *ptr, char **endptr, int base);
#endif
/* bnet.c */
-int32_t bnet_recv (BSOCK *bsock);
-int bnet_send (BSOCK *bsock);
-int bnet_fsend (BSOCK *bs, char *fmt, ...);
-int bnet_set_buffer_size (BSOCK *bs, uint32_t size, int rw);
-int bnet_sig (BSOCK *bs, int sig);
-int bnet_ssl_server (BSOCK *bsock, char *password, int ssl_need, int ssl_has);
-int bnet_ssl_client (BSOCK *bsock, char *password, int ssl_need);
-BSOCK * bnet_connect (JCR *jcr, int retry_interval,
- int max_retry_time, char *name, char *host, char *service,
- int port, int verbose);
-void bnet_close (BSOCK *bsock);
-BSOCK * init_bsock (JCR *jcr, int sockfd, char *who, char *ip, int port);
-BSOCK * dup_bsock (BSOCK *bsock);
-void term_bsock (BSOCK *bsock);
-char * bnet_strerror (BSOCK *bsock);
-char * bnet_sig_to_ascii (BSOCK *bsock);
-int bnet_wait_data (BSOCK *bsock, int sec);
-int bnet_wait_data_intr (BSOCK *bsock, int sec);
-int bnet_despool (BSOCK *bsock);
-int is_bnet_stop (BSOCK *bsock);
-int is_bnet_error (BSOCK *bsock);
-void bnet_suppress_error_messages(BSOCK *bsock, int flag);
+int32_t bnet_recv (BSOCK *bsock);
+int bnet_send (BSOCK *bsock);
+int bnet_fsend (BSOCK *bs, char *fmt, ...);
+int bnet_set_buffer_size (BSOCK *bs, uint32_t size, int rw);
+int bnet_sig (BSOCK *bs, int sig);
+int bnet_ssl_server (BSOCK *bsock, char *password, int ssl_need, int ssl_has);
+int bnet_ssl_client (BSOCK *bsock, char *password, int ssl_need);
+BSOCK * bnet_connect (JCR *jcr, int retry_interval,
+ int max_retry_time, char *name, char *host, char *service,
+ int port, int verbose);
+void bnet_close (BSOCK *bsock);
+BSOCK * init_bsock (JCR *jcr, int sockfd, char *who, char *ip, int port);
+BSOCK * dup_bsock (BSOCK *bsock);
+void term_bsock (BSOCK *bsock);
+char * bnet_strerror (BSOCK *bsock);
+char * bnet_sig_to_ascii (BSOCK *bsock);
+int bnet_wait_data (BSOCK *bsock, int sec);
+int bnet_wait_data_intr (BSOCK *bsock, int sec);
+int bnet_despool (BSOCK *bsock);
+int is_bnet_stop (BSOCK *bsock);
+int is_bnet_error (BSOCK *bsock);
+void bnet_suppress_error_messages(BSOCK *bsock, int flag);
/* bget_msg.c */
-int bget_msg(BSOCK *sock);
+int bget_msg(BSOCK *sock);
/* bpipe.c */
-BPIPE * open_bpipe(char *prog, int wait, char *mode);
-int close_wpipe(BPIPE *bpipe);
-int close_bpipe(BPIPE *bpipe);
+BPIPE * open_bpipe(char *prog, int wait, char *mode);
+int close_wpipe(BPIPE *bpipe);
+int close_bpipe(BPIPE *bpipe);
/* cram-md5.c */
int cram_md5_get_auth(BSOCK *bs, char *password, int ssl_need);
int cram_md5_auth(BSOCK *bs, char *password, int ssl_need);
void hmac_md5(uint8_t* text, int text_len, uint8_t* key,
- int key_len, uint8_t *hmac);
+ int key_len, uint8_t *hmac);
/* crc32.c */
uint32_t bcrc32(uint8_t *buf, int len);
/* daemon.c */
-void daemon_start ();
+void daemon_start ();
/* edit.c */
-uint64_t str_to_uint64(char *str);
-int64_t str_to_int64(char *str);
-char * edit_uint64_with_commas (uint64_t val, char *buf);
-char * add_commas (char *val, char *buf);
-char * edit_uint64 (uint64_t val, char *buf);
-int duration_to_utime (char *str, utime_t *value);
-int size_to_uint64(char *str, int str_len, uint64_t *rtn_value);
-char *edit_utime (utime_t val, char *buf);
-int is_a_number (const char *num);
-int is_an_integer (const char *n);
+uint64_t str_to_uint64(char *str);
+int64_t str_to_int64(char *str);
+char * edit_uint64_with_commas (uint64_t val, char *buf);
+char * add_commas (char *val, char *buf);
+char * edit_uint64 (uint64_t val, char *buf);
+int duration_to_utime (char *str, utime_t *value);
+int size_to_uint64(char *str, int str_len, uint64_t *rtn_value);
+char *edit_utime (utime_t val, char *buf);
+int is_a_number (const char *num);
+int is_an_integer (const char *n);
/* lex.c */
-LEX * lex_close_file (LEX *lf);
-LEX * lex_open_file (LEX *lf, char *fname, LEX_ERROR_HANDLER *scan_error);
-int lex_get_char (LEX *lf);
-void lex_unget_char (LEX *lf);
-char * lex_tok_to_str (int token);
-int lex_get_token (LEX *lf, int expect);
+LEX * lex_close_file (LEX *lf);
+LEX * lex_open_file (LEX *lf, char *fname, LEX_ERROR_HANDLER *scan_error);
+int lex_get_char (LEX *lf);
+void lex_unget_char (LEX *lf);
+char * lex_tok_to_str (int token);
+int lex_get_token (LEX *lf, int expect);
/* message.c */
-void my_name_is (int argc, char *argv[], char *name);
-void init_msg (JCR *jcr, MSGS *msg);
-void term_msg (void);
-void close_msg (JCR *jcr);
-void add_msg_dest (MSGS *msg, int dest, int type, char *where, char *dest_code);
-void rem_msg_dest (MSGS *msg, int dest, int type, char *where);
-void Jmsg (JCR *jcr, int type, int level, char *fmt, ...);
-void dispatch_message (JCR *jcr, int type, int level, char *buf);
-void init_console_msg (char *wd);
-void free_msgs_res (MSGS *msgs);
-int open_spool_file (JCR *jcr, BSOCK *bs);
-int close_spool_file (JCR *jcr, BSOCK *bs);
+void my_name_is (int argc, char *argv[], char *name);
+void init_msg (JCR *jcr, MSGS *msg);
+void term_msg (void);
+void close_msg (JCR *jcr);
+void add_msg_dest (MSGS *msg, int dest, int type, char *where, char *dest_code);
+void rem_msg_dest (MSGS *msg, int dest, int type, char *where);
+void Jmsg (JCR *jcr, int type, int level, char *fmt, ...);
+void dispatch_message (JCR *jcr, int type, int level, char *buf);
+void init_console_msg (char *wd);
+void free_msgs_res (MSGS *msgs);
+int open_spool_file (JCR *jcr, BSOCK *bs);
+int close_spool_file (JCR *jcr, BSOCK *bs);
/* bnet_server.c */
-void bnet_thread_server(char *bind_addr, int port, int max_clients, workq_t *client_wq,
- void *handle_client_request(void *bsock));
-void bnet_server (int port, void handle_client_request(BSOCK *bsock));
-int net_connect (int port);
-BSOCK * bnet_bind (int port);
-BSOCK * bnet_accept (BSOCK *bsock, char *who);
+void bnet_thread_server(char *bind_addr, int port, int max_clients, workq_t *client_wq,
+ void *handle_client_request(void *bsock));
+void bnet_server (int port, void handle_client_request(BSOCK *bsock));
+int net_connect (int port);
+BSOCK * bnet_bind (int port);
+BSOCK * bnet_accept (BSOCK *bsock, char *who);
/* signal.c */
-void init_signals (void terminate(int sig));
-void init_stack_dump (void);
+void init_signals (void terminate(int sig));
+void init_stack_dump (void);
/* scan.c */
-void strip_trailing_junk (char *str);
-void strip_trailing_slashes (char *dir);
-int skip_spaces (char **msg);
-int skip_nonspaces (char **msg);
-int fstrsch (char *a, char *b);
-int parse_args(POOLMEM *cmd, POOLMEM *args, int *argc,
- char **argk, char **argv, int max_args);
-char *next_arg(char **s);
+void strip_trailing_junk (char *str);
+void strip_trailing_slashes (char *dir);
+int skip_spaces (char **msg);
+int skip_nonspaces (char **msg);
+int fstrsch (char *a, char *b);
+int parse_args(POOLMEM *cmd, POOLMEM *args, int *argc,
+ char **argk, char **argv, int max_args);
+char *next_arg(char **s);
/* util.c */
-int is_buf_zero (char *buf, int len);
-void lcase (char *str);
-void bash_spaces (char *str);
-void unbash_spaces (char *str);
-char * encode_time (time_t time, char *buf);
-char * encode_mode (mode_t mode, char *buf);
-int do_shell_expansion (char *name, int name_len);
-void jobstatus_to_ascii (int JobStatus, char *msg, int maxlen);
-void pm_strcat (POOLMEM **pm, char *str);
-void pm_strcpy (POOLMEM **pm, char *str);
-int run_program (char *prog, int wait, POOLMEM *results);
-char * job_type_to_str (int type);
-char * job_status_to_str (int stat);
-char * job_level_to_str (int level);
-void make_session_key (char *key, char *seed, int mode);
-POOLMEM *edit_job_codes(JCR *jcr, char *omsg, char *imsg, char *to);
-void set_working_directory(char *wd);
+int is_buf_zero (char *buf, int len);
+void lcase (char *str);
+void bash_spaces (char *str);
+void unbash_spaces (char *str);
+char * encode_time (time_t time, char *buf);
+char * encode_mode (mode_t mode, char *buf);
+int do_shell_expansion (char *name, int name_len);
+void jobstatus_to_ascii (int JobStatus, char *msg, int maxlen);
+void pm_strcat (POOLMEM **pm, char *str);
+void pm_strcpy (POOLMEM **pm, char *str);
+int run_program (char *prog, int wait, POOLMEM *results);
+char * job_type_to_str (int type);
+char * job_status_to_str (int stat);
+char * job_level_to_str (int level);
+void make_session_key (char *key, char *seed, int mode);
+POOLMEM *edit_job_codes(JCR *jcr, char *omsg, char *imsg, char *to);
+void set_working_directory(char *wd);
/* watchdog.c */
if ((shellcmd = getenv("SHELL")) == NULL) {
shellcmd = "/bin/sh";
}
-#ifdef xxx
- close(1); dup(pfd[1]); /* attach pipes to stdout and stderr */
- close(2); dup(pfd[1]);
- for (i = 3; i < 32; i++) /* close everything else */
- close(i);
-#endif
close(pfd[0]); /* close stdin */
dup2(pfd[1], 1); /* attach to stdout */
dup2(pfd[1], 2); /* and stderr */
restore.bsr
startit
stopit
+changer.out
+mtx-changer
/* Read Stream header from the File daemon.
* The stream header consists of the following:
- * file_index (sequential Bacula file index)
- * stream (arbitrary Bacula number to distinguish parts of data)
+ * file_index (sequential Bacula file index, base 1)
+ * stream (Bacula number to distinguish parts of data)
* info (Info for Storage daemon -- compressed, encryped, ...)
* info is not currently used, so is read, but ignored!
*/
stream_to_ascii(rec.Stream, rec.FileIndex), rec.data_len);
/* Send attributes and MD5 to Director for Catalog */
- if (stream == STREAM_UNIX_ATTRIBUTES || stream == STREAM_MD5_SIGNATURE ||
- stream == STREAM_WIN32_ATTRIBUTES || stream == STREAM_SHA1_SIGNATURE) {
+ if (stream == STREAM_UNIX_ATTRIBUTES || stream == STREAM_MD5_SIGNATURE ||
+ stream == STREAM_UNIX_ATTRIBUTES_EX || stream == STREAM_SHA1_SIGNATURE) {
if (!jcr->no_attributes) {
if (jcr->spool_attributes && jcr->dir_bsock->spool_fd) {
jcr->dir_bsock->spool = 1;
static FF_PKT *ff = &my_ff;
static BSR *bsr = NULL;
static int extract = FALSE;
-static long record_file_index;
+static int non_support_data = 0;
+static int non_support_attr = 0;
static long total = 0;
-static POOLMEM *fname; /* original file name */
-static POOLMEM *ofile; /* output name with prefix */
-static POOLMEM *lname; /* link name */
-static POOLMEM *attribsEx; /* extended attributes (Win32) */
+static ATTR *attr;
static char *where;
-static int wherelen; /* prefix length */
static uint32_t num_files = 0;
-static struct stat statp;
static uint32_t compress_buf_size = 70000;
static POOLMEM *compress_buf;
-static int type;
-static int stream;
static int prog_name_msg = 0;
static int win32_data_msg = 0;
static char *VolumeName = NULL;
while ((ch = getopt(argc, argv, "b:c:d:e:i:?")) != -1) {
switch (ch) {
- case 'b': /* bootstrap file */
- bsr = parse_bsr(NULL, optarg);
-// dump_bsr(bsr);
- break;
-
- case 'c': /* specify config file */
- if (configfile != NULL) {
- free(configfile);
- }
- configfile = bstrdup(optarg);
- break;
-
- case 'd': /* debug level */
- debug_level = atoi(optarg);
- if (debug_level <= 0)
- debug_level = 1;
- break;
-
- case 'e': /* exclude list */
- if ((fd = fopen(optarg, "r")) == NULL) {
- Pmsg2(0, "Could not open exclude file: %s, ERR=%s\n",
- optarg, strerror(errno));
- exit(1);
- }
- while (fgets(line, sizeof(line), fd) != NULL) {
- strip_trailing_junk(line);
- Dmsg1(900, "add_exclude %s\n", line);
- add_fname_to_exclude_list(ff, line);
- }
- fclose(fd);
- break;
-
- case 'i': /* include list */
- if ((fd = fopen(optarg, "r")) == NULL) {
- Pmsg2(0, "Could not open include file: %s, ERR=%s\n",
- optarg, strerror(errno));
- exit(1);
- }
- while (fgets(line, sizeof(line), fd) != NULL) {
- strip_trailing_junk(line);
- Dmsg1(900, "add_include %s\n", line);
- add_fname_to_include_list(ff, 0, line);
- }
- fclose(fd);
- got_inc = TRUE;
- break;
+ case 'b': /* bootstrap file */
+ bsr = parse_bsr(NULL, optarg);
+// dump_bsr(bsr);
+ break;
+
+ case 'c': /* specify config file */
+ if (configfile != NULL) {
+ free(configfile);
+ }
+ configfile = bstrdup(optarg);
+ break;
+
+ case 'd': /* debug level */
+ debug_level = atoi(optarg);
+ if (debug_level <= 0)
+ debug_level = 1;
+ break;
+
+ case 'e': /* exclude list */
+ if ((fd = fopen(optarg, "r")) == NULL) {
+ Pmsg2(0, "Could not open exclude file: %s, ERR=%s\n",
+ optarg, strerror(errno));
+ exit(1);
+ }
+ while (fgets(line, sizeof(line), fd) != NULL) {
+ strip_trailing_junk(line);
+ Dmsg1(900, "add_exclude %s\n", line);
+ add_fname_to_exclude_list(ff, line);
+ }
+ fclose(fd);
+ break;
+
+ case 'i': /* include list */
+ if ((fd = fopen(optarg, "r")) == NULL) {
+ Pmsg2(0, "Could not open include file: %s, ERR=%s\n",
+ optarg, strerror(errno));
+ exit(1);
+ }
+ while (fgets(line, sizeof(line), fd) != NULL) {
+ strip_trailing_junk(line);
+ Dmsg1(900, "add_include %s\n", line);
+ add_fname_to_include_list(ff, 0, line);
+ }
+ fclose(fd);
+ got_inc = TRUE;
+ break;
- case 'V': /* Volume name */
- VolumeName = optarg;
- break;
+ case 'V': /* Volume name */
+ VolumeName = optarg;
+ break;
- case '?':
- default:
- usage();
+ case '?':
+ default:
+ usage();
- }
- }
+ } /* end switch */
+ } /* end while */
argc -= optind;
argv += optind;
static void do_extract(char *devname)
{
-
+ struct stat statp;
jcr = setup_jcr("bextract", devname, bsr, VolumeName);
dev = setup_to_access_device(jcr, 1); /* acquire for read */
if (!dev) {
Emsg1(M_ERROR_TERM, 0, "%s must be a directory.\n", where);
}
- wherelen = strlen(where);
- fname = get_pool_memory(PM_FNAME);
- ofile = get_pool_memory(PM_FNAME);
- lname = get_pool_memory(PM_FNAME);
- attribsEx = get_pool_memory(PM_FNAME);
+ free(jcr->where);
+ jcr->where = bstrdup(where);
+ attr = new_attr();
compress_buf = get_memory(compress_buf_size);
* archive since we just hit an end of file, so close the file.
*/
if (is_bopen(&bfd)) {
- set_attributes(jcr, fname, ofile, lname, type, stream, &statp,
- attribsEx, &bfd);
+ set_attributes(jcr, attr, &bfd);
}
release_device(jcr, dev);
- free_pool_memory(fname);
- free_pool_memory(ofile);
- free_pool_memory(lname);
- free_pool_memory(compress_buf);
+ free_attr(attr);
term_dev(dev);
free_jcr(jcr);
printf("%u files restored.\n", num_files);
}
/* File Attributes stream */
- if (rec->Stream == STREAM_UNIX_ATTRIBUTES || rec->Stream == STREAM_WIN32_ATTRIBUTES) {
- char *ap, *lp, *fp, *apex;
- stream = rec->Stream;
+ switch (rec->Stream) {
+ case STREAM_UNIX_ATTRIBUTES:
+ case STREAM_UNIX_ATTRIBUTES_EX:
/* If extracting, it was from previous stream, so
* close the output file.
*/
if (extract) {
if (!is_bopen(&bfd)) {
- Emsg0(M_ERROR, 0, "Logic error output file should be open but is not.\n");
+ Emsg0(M_ERROR, 0, _("Logic error output file should be open but is not.\n"));
}
extract = FALSE;
- set_attributes(jcr, fname, ofile, lname, type, stream, &statp,
- attribsEx, &bfd);
+ set_attributes(jcr, attr, &bfd);
}
- if (sizeof_pool_memory(fname) < rec->data_len) {
- fname = realloc_pool_memory(fname, rec->data_len + 1);
- }
- if (sizeof_pool_memory(ofile) < rec->data_len + wherelen + 1) {
- ofile = realloc_pool_memory(ofile, rec->data_len + wherelen + 1);
+ if (!unpack_attributes_record(jcr, rec->Stream, rec->data, attr)) {
+ Emsg0(M_ERROR_TERM, 0, _("Cannot continue.\n"));
}
- if (sizeof_pool_memory(lname) < rec->data_len) {
- lname = realloc_pool_memory(lname, rec->data_len + wherelen + 1);
- }
- *fname = 0;
- *lname = 0;
-
- /*
- * An Attributes record consists of:
- * File_index
- * Type (FT_types)
- * Filename
- * Attributes
- * Link name (if file linked i.e. FT_LNK)
- * Extended Attributes (Win32)
- *
- */
- sscanf(rec->data, "%ld %d", &record_file_index, &type);
- if (record_file_index != rec->FileIndex)
- Emsg2(M_ERROR_TERM, 0, "Record header file index %ld not equal record index %ld\n",
- rec->FileIndex, record_file_index);
- ap = rec->data;
- while (*ap++ != ' ') /* skip record file index */
- ;
- while (*ap++ != ' ') /* skip type */
- ;
- /* Save filename and position to attributes */
- fp = fname;
- while (*ap != 0) {
- *fp++ = *ap++;
- }
- *fp = *ap++; /* terminate filename & point to attribs */
- /* Skip to Link name */
- if (type == FT_LNK || type == FT_LNKSAVED) {
- lp = ap;
- while (*lp++ != 0) {
- ;
- }
- } else {
- lp = "";
+ if (attr->file_index != rec->FileIndex) {
+ Emsg2(M_ERROR_TERM, 0, _("Record header file index %ld not equal record index %ld\n"),
+ rec->FileIndex, attr->file_index);
}
-
- if (rec->Stream == STREAM_WIN32_ATTRIBUTES) {
- apex = ap; /* start at attributes */
- while (*apex++ != 0) { /* skip attributes */
- ;
- }
- while (*apex++ != 0) { /* skip link name */
- ;
- }
- pm_strcpy(&attribsEx, apex); /* make a copy of Extended attributes */
- } else {
- *attribsEx = 0; /* no extended attributes */
- }
-
- if (file_is_included(ff, fname) && !file_is_excluded(ff, fname)) {
+ if (file_is_included(ff, attr->fname) && !file_is_excluded(ff, attr->fname)) {
uint32_t LinkFI;
- decode_stat(ap, &statp, &LinkFI);
- /*
- * Prepend the where directory so that the
- * files are put where the user wants.
- *
- * We do a little jig here to handle Win32 files with
- * a drive letter -- we simply strip the drive: from
- * every filename if a prefix is supplied.
- */
- if (where[0] == 0) {
- strcpy(ofile, fname);
- strcpy(lname, lp);
- } else {
- char *fn;
- strcpy(ofile, where);
- if (win32_client && fname[1] == ':') {
- fn = fname+2; /* skip over drive: */
- } else {
- fn = fname; /* take whole name */
- }
- /* Ensure where is terminated with a slash */
- if (where[wherelen-1] != '/' && fn[0] != '/') {
- strcat(ofile, "/");
- }
- strcat(ofile, fn); /* copy rest of name */
- /* Fixup link name for hard links, but not for
- * soft links
- */
- if (type == FT_LNKSAVED) {
- if (lp[0] == '/') { /* if absolute path */
- strcpy(lname, where);
- }
- if (win32_client && lp[1] == ':') {
- strcat(lname, lp+2); /* copy rest of name */
- } else {
- strcat(lname, lp); /* On Unix systems we take everything */
- }
- }
- }
+ decode_stat(attr->attr, &attr->statp, &LinkFI);
- /* Pmsg1(000, "Restoring: %s\n", ofile); */
+ build_attr_output_fnames(jcr, attr);
extract = FALSE;
- stat = create_file(jcr, fname, ofile, lname, type, stream,
- &statp, attribsEx, &bfd, REPLACE_ALWAYS);
+ stat = create_file(jcr, attr, &bfd, REPLACE_ALWAYS);
switch (stat) {
case CF_ERROR:
case CF_SKIP:
break;
case CF_EXTRACT:
extract = TRUE;
- print_ls_output(ofile, lname, type, &statp);
+ print_ls_output(jcr, attr);
num_files++;
fileAddr = 0;
break;
case CF_CREATED:
- set_attributes(jcr, fname, ofile, lname, type, stream, &statp,
- attribsEx, &bfd);
- print_ls_output(ofile, lname, type, &statp);
+ set_attributes(jcr, attr, &bfd);
+ print_ls_output(jcr, attr);
num_files++;
fileAddr = 0;
break;
}
}
+ /* Windows Backup data stream */
+ 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"));
+ }
+ extract = FALSE;
+ non_support_data++;
+ return;
+ }
+ goto extract_data;
+
+
/* Data stream and extracting */
- } else if (rec->Stream == STREAM_FILE_DATA || rec->Stream == STREAM_SPARSE_DATA) {
+ case STREAM_FILE_DATA:
+ case STREAM_SPARSE_DATA:
+
+extract_data:
if (extract) {
if (rec->Stream == STREAM_SPARSE_DATA) {
ser_declare;
if (fileAddr != faddr) {
fileAddr = faddr;
if (blseek(&bfd, (off_t)fileAddr, SEEK_SET) < 0) {
- Emsg2(M_ERROR_TERM, 0, _("Seek error on %s: %s\n"), ofile, strerror(errno));
+ Emsg2(M_ERROR_TERM, 0, _("Seek error on %s: %s\n"),
+ attr->ofname, strerror(errno));
}
}
} else {
total += wsize;
Dmsg2(8, "Write %u bytes, total=%u\n", wsize, total);
if ((uint32_t)bwrite(&bfd, wbuf, wsize) != wsize) {
- Emsg2(M_ERROR_TERM, 0, _("Write error on %s: %s\n"), ofile, strerror(errno));
+ Emsg2(M_ERROR_TERM, 0, _("Write error on %s: %s\n"),
+ attr->ofname, strerror(errno));
}
fileAddr += wsize;
}
- } else if (rec->Stream == STREAM_GZIP_DATA || rec->Stream == STREAM_SPARSE_GZIP_DATA) {
+ /* Windows Backup GZIP data stream */
+ 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"));
+ }
+ extract = FALSE;
+ non_support_attr++;
+ return;
+ }
+ /* Fall through desired */
+
+ /* GZIP data stream */
+ case STREAM_GZIP_DATA:
+ case STREAM_SPARSE_GZIP_DATA:
#ifdef HAVE_LIBZ
if (extract) {
uLongf compress_len;
if (fileAddr != faddr) {
fileAddr = faddr;
if (blseek(&bfd, (off_t)fileAddr, SEEK_SET) < 0) {
- Emsg2(M_ERROR, 0, _("Seek error on %s: %s\n"), ofile, strerror(errno));
+ Emsg2(M_ERROR, 0, _("Seek error on %s: %s\n"),
+ attr->ofname, strerror(errno));
}
}
} else {
Dmsg2(100, "Write uncompressed %d bytes, total before write=%d\n", compress_len, total);
if ((uLongf)bwrite(&bfd, compress_buf, (size_t)compress_len) != compress_len) {
Pmsg0(0, "===Write error===\n");
- Emsg2(M_ERROR_TERM, 0, _("Write error on %s: %s\n"), ofile, strerror(errno));
+ Emsg2(M_ERROR_TERM, 0, _("Write error on %s: %s\n"),
+ attr->ofname, strerror(errno));
}
total += compress_len;
fileAddr += compress_len;
#else
if (extract) {
Emsg0(M_ERROR, 0, "GZIP data stream found, but GZIP not configured!\n");
+ extract = FALSE;
+ return;
}
#endif
+ case STREAM_MD5_SIGNATURE:
+ case STREAM_SHA1_SIGNATURE:
+ break;
- /* If extracting, wierd stream (not 1 or 2), close output file anyway */
- } else if (extract) {
- if (!is_bopen(&bfd)) {
- Emsg0(M_ERROR, 0, "Logic error output file should be open but is not.\n");
- }
- extract = FALSE;
- set_attributes(jcr, fname, ofile, lname, type, stream, &statp,
- attribsEx, &bfd);
- } else if (rec->Stream == STREAM_PROGRAM_NAMES || rec->Stream == STREAM_PROGRAM_DATA) {
+ case STREAM_PROGRAM_NAMES:
+ case STREAM_PROGRAM_DATA:
if (!prog_name_msg) {
Pmsg0(000, "Got Program Name or Data Stream. Ignored.\n");
prog_name_msg++;
}
- } else if (rec->Stream == STREAM_WIN32_DATA || rec->Stream == STREAM_WIN32_GZIP_DATA) {
- if (!win32_data_msg) {
- Pmsg0(000, "Got Win32 data or Win32 gzip data stream. Ignored.\n");
- win32_data_msg++;
+ break;
+
+ default:
+ /* If extracting, wierd stream (not 1 or 2), close output file anyway */
+ if (extract) {
+ if (!is_bopen(&bfd)) {
+ Emsg0(M_ERROR, 0, "Logic error output file should be open but is not.\n");
+ }
+ extract = FALSE;
+ set_attributes(jcr, attr, &bfd);
}
- } else if (!(rec->Stream == STREAM_MD5_SIGNATURE ||
- rec->Stream == STREAM_SHA1_SIGNATURE)) {
- Pmsg2(0, "None of above!!! stream=%d data=%s\n", rec->Stream, rec->data);
- }
+ Jmsg(jcr, M_ERROR, 0, _("Unknown stream=%d ignored. This shouldn't happen!\n"),
+ rec->Stream);
+ break;
+
+ } /* end switch */
}
#include "stored.h"
#include "findlib/find.h"
+#ifdef HAVE_CYGWIN
+int win32_client = 1;
+#else
+int win32_client = 0;
+#endif
+
+
static void do_blocks(char *infname);
static void do_jobs(char *infname);
static void do_ls(char *fname);
static JCR *jcr;
static SESSION_LABEL sessrec;
static uint32_t num_files = 0;
-static long record_file_index;
+static ATTR *attr;
#define CONFIG_FILE "bacula-sd.conf"
char *configfile;
while ((ch = getopt(argc, argv, "b:c:d:e:i:jkLtvV:?")) != -1) {
switch (ch) {
- case 'b':
- bsrName = optarg;
- break;
+ case 'b':
+ bsrName = optarg;
+ break;
- case 'c': /* specify config file */
- if (configfile != NULL) {
- free(configfile);
- }
- configfile = bstrdup(optarg);
- break;
+ case 'c': /* specify config file */
+ if (configfile != NULL) {
+ free(configfile);
+ }
+ configfile = bstrdup(optarg);
+ break;
- case 'd': /* debug level */
- debug_level = atoi(optarg);
- if (debug_level <= 0)
- debug_level = 1;
- break;
+ case 'd': /* debug level */
+ debug_level = atoi(optarg);
+ if (debug_level <= 0)
+ debug_level = 1;
+ break;
- case 'e': /* exclude list */
- if ((fd = fopen(optarg, "r")) == NULL) {
- Pmsg2(0, _("Could not open exclude file: %s, ERR=%s\n"),
- optarg, strerror(errno));
- exit(1);
- }
- while (fgets(line, sizeof(line), fd) != NULL) {
- strip_trailing_junk(line);
- Dmsg1(100, "add_exclude %s\n", line);
- add_fname_to_exclude_list(&ff, line);
- }
- fclose(fd);
- break;
+ case 'e': /* exclude list */
+ if ((fd = fopen(optarg, "r")) == NULL) {
+ Pmsg2(0, _("Could not open exclude file: %s, ERR=%s\n"),
+ optarg, strerror(errno));
+ exit(1);
+ }
+ while (fgets(line, sizeof(line), fd) != NULL) {
+ strip_trailing_junk(line);
+ Dmsg1(100, "add_exclude %s\n", line);
+ add_fname_to_exclude_list(&ff, line);
+ }
+ fclose(fd);
+ break;
- case 'i': /* include list */
- if ((fd = fopen(optarg, "r")) == NULL) {
- Pmsg2(0, "Could not open include file: %s, ERR=%s\n",
- optarg, strerror(errno));
- exit(1);
- }
- while (fgets(line, sizeof(line), fd) != NULL) {
- strip_trailing_junk(line);
- Dmsg1(100, "add_include %s\n", line);
- add_fname_to_include_list(&ff, 0, line);
- }
- fclose(fd);
- break;
+ case 'i': /* include list */
+ if ((fd = fopen(optarg, "r")) == NULL) {
+ Pmsg2(0, "Could not open include file: %s, ERR=%s\n",
+ optarg, strerror(errno));
+ exit(1);
+ }
+ while (fgets(line, sizeof(line), fd) != NULL) {
+ strip_trailing_junk(line);
+ Dmsg1(100, "add_include %s\n", line);
+ add_fname_to_include_list(&ff, 0, line);
+ }
+ fclose(fd);
+ break;
- case 'j':
- list_jobs = TRUE;
- break;
+ case 'j':
+ list_jobs = TRUE;
+ break;
- case 'k':
- list_blocks = TRUE;
- break;
+ case 'k':
+ list_blocks = TRUE;
+ break;
- case 'L':
- dump_label = TRUE;
- break;
+ case 'L':
+ dump_label = TRUE;
+ break;
- case 'v':
- verbose++;
- break;
+ case 'v':
+ verbose++;
+ break;
- case 'V': /* Volume name */
- VolumeName = optarg;
- break;
+ case 'V': /* Volume name */
+ VolumeName = optarg;
+ break;
- case '?':
- default:
- usage();
+ case '?':
+ default:
+ usage();
- }
- }
+ } /* end switch */
+ } /* end while */
argc -= optind;
argv += optind;
}
rec = new_record();
block = new_block(dev);
+ attr = new_attr();
/*
* Assume that we have already read the volume label.
* If on second or subsequent volume, adjust buffer pointer
static void do_close(JCR *jcr)
{
release_device(jcr, dev);
+ free_attr(attr);
term_dev(dev);
free_record(rec);
free_block(block);
*/
static void record_cb(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec)
{
- char fname[2000];
- struct stat statp;
- int type;
-
if (rec->FileIndex < 0) {
get_session_record(dev, rec, &sessrec);
return;
}
/* File Attributes stream */
- if (rec->Stream == STREAM_UNIX_ATTRIBUTES || rec->Stream == STREAM_WIN32_ATTRIBUTES) {
- char *ap, *fp;
+ if (rec->Stream == STREAM_UNIX_ATTRIBUTES ||
+ rec->Stream == STREAM_UNIX_ATTRIBUTES_EX) {
uint32_t LinkFI;
- sscanf(rec->data, "%ld %d", &record_file_index, &type);
- if (record_file_index != rec->FileIndex) {
- Emsg2(M_ERROR_TERM, 0, "Record header file index %ld not equal record index %ld\n",
- rec->FileIndex, record_file_index);
+ if (!unpack_attributes_record(jcr, rec->Stream, rec->data, attr)) {
+ Emsg0(M_ERROR_TERM, 0, _("Cannot continue.\n"));
}
- ap = rec->data;
-
- while (*ap++ != ' ') /* skip record file index */
- ;
- while (*ap++ != ' ') /* skip type */
- ;
- /* Save filename and position to attributes */
- fp = fname;
- while (*ap != 0) {
- *fp++ = *ap++;
+
+ if (attr->file_index != rec->FileIndex) {
+ Emsg2(M_ERROR_TERM, 0, _("Record header file index %ld not equal record index %ld\n"),
+ rec->FileIndex, attr->file_index);
}
- *fp = *ap++; /* terminate filename & point to attribs */
-
- decode_stat(ap, &statp, &LinkFI);
- /* Skip to link name */
- while (*ap++ != 0)
- ;
- if (file_is_included(&ff, fname) && !file_is_excluded(&ff, fname)) {
- print_ls_output(fname, ap, type, &statp);
+
+ decode_stat(attr->attr, &attr->statp, &LinkFI);
+
+ if (file_is_included(&ff, attr->fname) && !file_is_excluded(&ff, attr->fname)) {
+ print_ls_output(jcr, attr);
num_files++;
}
}
/* Global variables */
STORES *me;
+#ifdef HAVE_CYGWIN
+int win32_client = 1;
+#else
+int win32_client = 0;
+#endif
+
/* Local variables */
static DEVICE *dev = NULL;
static B_DB *db;
static JCR *bjcr; /* jcr for bscan */
static BSR *bsr = NULL;
-static struct stat statp;
-static int type;
-static long record_file_index;
-static POOLMEM *fname; /* original file name */
-static POOLMEM *ofile; /* output name with prefix */
-static POOLMEM *lname; /* link name */
static MEDIA_DBR mr;
static POOL_DBR pr;
static JOB_DBR jr;
static FILE_DBR fr;
static SESSION_LABEL label;
static SESSION_LABEL elabel;
+static ATTR *attr;
static time_t lasttime = 0;
while ((ch = getopt(argc, argv, "b:c:d:mn:p:rsu:vw:?")) != -1) {
switch (ch) {
- case 'b':
- bsr = parse_bsr(NULL, optarg);
- break;
+ case 'b':
+ bsr = parse_bsr(NULL, optarg);
+ break;
- case 'c': /* specify config file */
- if (configfile != NULL) {
- free(configfile);
- }
- configfile = bstrdup(optarg);
- break;
+ case 'c': /* specify config file */
+ if (configfile != NULL) {
+ free(configfile);
+ }
+ configfile = bstrdup(optarg);
+ break;
- case 'd': /* debug level */
- debug_level = atoi(optarg);
- if (debug_level <= 0)
- debug_level = 1;
- break;
+ case 'd': /* debug level */
+ debug_level = atoi(optarg);
+ if (debug_level <= 0)
+ debug_level = 1;
+ break;
- case 'm':
- update_vol_info = 1;
- break;
+ case 'm':
+ update_vol_info = 1;
+ break;
- case 'n':
- db_name = optarg;
- break;
+ case 'n':
+ db_name = optarg;
+ break;
- case 'u':
- db_user = optarg;
- break;
+ case 'u':
+ db_user = optarg;
+ break;
- case 'p':
- db_password = optarg;
- break;
+ case 'p':
+ db_password = optarg;
+ break;
- case 'r':
- list_records = 1;
- break;
+ case 'r':
+ list_records = 1;
+ break;
- case 's':
- update_db = 1;
- break;
+ case 's':
+ update_db = 1;
+ break;
- case 'v':
- verbose++;
- break;
+ case 'v':
+ verbose++;
+ break;
- case 'V': /* Volume name */
- VolumeName = optarg;
- break;
+ case 'V': /* Volume name */
+ VolumeName = optarg;
+ break;
- case 'w':
- wd = optarg;
- break;
+ case 'w':
+ wd = optarg;
+ break;
- case '?':
- default:
- usage();
+ case '?':
+ default:
+ usage();
}
}
static void do_scan()
{
- fname = get_pool_memory(PM_FNAME);
- ofile = get_pool_memory(PM_FNAME);
- lname = get_pool_memory(PM_FNAME);
+ attr = new_attr();
memset(&ar, 0, sizeof(ar));
memset(&pr, 0, sizeof(pr));
read_records(bjcr, dev, record_cb, mount_next_read_volume);
release_device(bjcr, dev);
- free_pool_memory(fname);
- free_pool_memory(ofile);
- free_pool_memory(lname);
+ free_attr(attr);
term_dev(dev);
}
dump_label_record(dev, rec, 1);
}
switch (rec->FileIndex) {
- case PRE_LABEL:
- Pmsg0(000, _("Volume is prelabeled. This tape cannot be scanned.\n"));
- return;
- break;
- case VOL_LABEL:
- unser_volume_label(dev, rec);
- /* Check Pool info */
- strcpy(pr.Name, dev->VolHdr.PoolName);
- strcpy(pr.PoolType, dev->VolHdr.PoolType);
- if (db_get_pool_record(bjcr, db, &pr)) {
- if (verbose) {
- Pmsg1(000, _("Pool record for %s found in DB.\n"), pr.Name);
- }
- } else {
- if (!update_db) {
- Pmsg1(000, _("VOL_LABEL: Pool record not found for Pool: %s\n"),
- pr.Name);
- }
- create_pool_record(db, &pr);
+ case PRE_LABEL:
+ Pmsg0(000, _("Volume is prelabeled. This tape cannot be scanned.\n"));
+ return;
+ break;
+ case VOL_LABEL:
+ unser_volume_label(dev, rec);
+ /* Check Pool info */
+ strcpy(pr.Name, dev->VolHdr.PoolName);
+ strcpy(pr.PoolType, dev->VolHdr.PoolType);
+ if (db_get_pool_record(bjcr, db, &pr)) {
+ if (verbose) {
+ Pmsg1(000, _("Pool record for %s found in DB.\n"), pr.Name);
}
- if (strcmp(pr.PoolType, dev->VolHdr.PoolType) != 0) {
- Pmsg2(000, _("VOL_LABEL: PoolType mismatch. DB=%s Vol=%s\n"),
- pr.PoolType, dev->VolHdr.PoolType);
- return;
- } else if (verbose) {
- Pmsg1(000, _("Pool type \"%s\" is OK.\n"), pr.PoolType);
+ } else {
+ if (!update_db) {
+ Pmsg1(000, _("VOL_LABEL: Pool record not found for Pool: %s\n"),
+ pr.Name);
}
+ create_pool_record(db, &pr);
+ }
+ if (strcmp(pr.PoolType, dev->VolHdr.PoolType) != 0) {
+ Pmsg2(000, _("VOL_LABEL: PoolType mismatch. DB=%s Vol=%s\n"),
+ pr.PoolType, dev->VolHdr.PoolType);
+ return;
+ } else if (verbose) {
+ Pmsg1(000, _("Pool type \"%s\" is OK.\n"), pr.PoolType);
+ }
- /* Check Media Info */
- memset(&mr, 0, sizeof(mr));
- strcpy(mr.VolumeName, dev->VolHdr.VolName);
- mr.PoolId = pr.PoolId;
- if (db_get_media_record(bjcr, db, &mr)) {
- if (verbose) {
- Pmsg1(000, _("Media record for %s found in DB.\n"), mr.VolumeName);
- }
- /* Clear out some volume statistics that will be updated */
- mr.VolJobs = mr.VolFiles = mr.VolBlocks = 0;
- mr.VolBytes = rec->data_len + 20;
- } else {
- if (!update_db) {
- Pmsg1(000, _("VOL_LABEL: Media record not found for Volume: %s\n"),
- mr.VolumeName);
- }
- strcpy(mr.MediaType, dev->VolHdr.MediaType);
- create_media_record(db, &mr, &dev->VolHdr);
- }
- if (strcmp(mr.MediaType, dev->VolHdr.MediaType) != 0) {
- Pmsg2(000, _("VOL_LABEL: MediaType mismatch. DB=%s Vol=%s\n"),
- mr.MediaType, dev->VolHdr.MediaType);
- return;
- } else if (verbose) {
- Pmsg1(000, _("Media type \"%s\" is OK.\n"), mr.MediaType);
+ /* Check Media Info */
+ memset(&mr, 0, sizeof(mr));
+ strcpy(mr.VolumeName, dev->VolHdr.VolName);
+ mr.PoolId = pr.PoolId;
+ if (db_get_media_record(bjcr, db, &mr)) {
+ if (verbose) {
+ Pmsg1(000, _("Media record for %s found in DB.\n"), mr.VolumeName);
}
- /* Reset some JCR variables */
- for (mjcr=NULL; (mjcr=next_attached_jcr(dev, mjcr)); ) {
- mjcr->VolFirstIndex = mjcr->FileIndex = 0;
- mjcr->StartBlock = mjcr->EndBlock = 0;
- mjcr->StartFile = mjcr->EndFile = 0;
+ /* Clear out some volume statistics that will be updated */
+ mr.VolJobs = mr.VolFiles = mr.VolBlocks = 0;
+ mr.VolBytes = rec->data_len + 20;
+ } else {
+ if (!update_db) {
+ Pmsg1(000, _("VOL_LABEL: Media record not found for Volume: %s\n"),
+ mr.VolumeName);
}
+ strcpy(mr.MediaType, dev->VolHdr.MediaType);
+ create_media_record(db, &mr, &dev->VolHdr);
+ }
+ if (strcmp(mr.MediaType, dev->VolHdr.MediaType) != 0) {
+ Pmsg2(000, _("VOL_LABEL: MediaType mismatch. DB=%s Vol=%s\n"),
+ mr.MediaType, dev->VolHdr.MediaType);
+ return;
+ } else if (verbose) {
+ Pmsg1(000, _("Media type \"%s\" is OK.\n"), mr.MediaType);
+ }
+ /* Reset some JCR variables */
+ for (mjcr=NULL; (mjcr=next_attached_jcr(dev, mjcr)); ) {
+ mjcr->VolFirstIndex = mjcr->FileIndex = 0;
+ mjcr->StartBlock = mjcr->EndBlock = 0;
+ mjcr->StartFile = mjcr->EndFile = 0;
+ }
- Pmsg1(000, _("VOL_LABEL: OK for Volume: %s\n"), mr.VolumeName);
- break;
- case SOS_LABEL:
- mr.VolJobs++;
- if (ignored_msgs > 0) {
- Pmsg1(000, _("%d \"errors\" ignored before first Start of Session record.\n"),
- ignored_msgs);
- ignored_msgs = 0;
- }
- unser_session_label(&label, rec);
- memset(&jr, 0, sizeof(jr));
- jr.JobId = label.JobId;
- if (db_get_job_record(bjcr, db, &jr)) {
- /* Job record already exists in DB */
- update_db = 0; /* don't change db in create_job_record */
- if (verbose) {
- Pmsg1(000, _("SOS_LABEL: Found Job record for JobId: %d\n"), jr.JobId);
- }
- } else {
- /* Must create a Job record in DB */
- if (!update_db) {
- Pmsg1(000, _("SOS_LABEL: Job record not found for JobId: %d\n"),
- jr.JobId);
- }
- }
- /* Create Client record if not already there */
- strcpy(cr.Name, label.ClientName);
- create_client_record(db, &cr);
- jr.ClientId = cr.ClientId;
-
- /* process label, if Job record exists don't update db */
- mjcr = create_job_record(db, &jr, &label, rec);
- update_db = save_update_db;
-
- jr.PoolId = pr.PoolId;
- /* Set start positions into JCR */
- if (dev->state & ST_TAPE) {
- mjcr->StartBlock = dev->block_num;
- mjcr->StartFile = dev->file;
- } else {
- mjcr->StartBlock = (uint32_t)dev->file_addr;
- mjcr->StartFile = (uint32_t)(dev->file_addr >> 32);
- }
- mjcr->start_time = jr.StartTime;
- mjcr->JobLevel = jr.Level;
-
- mjcr->client_name = get_pool_memory(PM_FNAME);
- pm_strcpy(&mjcr->client_name, label.ClientName);
- mjcr->pool_type = get_pool_memory(PM_FNAME);
- pm_strcpy(&mjcr->pool_type, label.PoolType);
- mjcr->fileset_name = get_pool_memory(PM_FNAME);
- pm_strcpy(&mjcr->fileset_name, label.FileSetName);
- mjcr->pool_name = get_pool_memory(PM_FNAME);
- pm_strcpy(&mjcr->pool_name, label.PoolName);
-
- if (rec->VolSessionId != jr.VolSessionId) {
- Pmsg3(000, _("SOS_LABEL: VolSessId mismatch for JobId=%u. DB=%d Vol=%d\n"),
- jr.JobId,
- jr.VolSessionId, rec->VolSessionId);
- return;
- }
- if (rec->VolSessionTime != jr.VolSessionTime) {
- Pmsg3(000, _("SOS_LABEL: VolSessTime mismatch for JobId=%u. DB=%d Vol=%d\n"),
- jr.JobId,
- jr.VolSessionTime, rec->VolSessionTime);
- return;
+ Pmsg1(000, _("VOL_LABEL: OK for Volume: %s\n"), mr.VolumeName);
+ break;
+ case SOS_LABEL:
+ mr.VolJobs++;
+ if (ignored_msgs > 0) {
+ Pmsg1(000, _("%d \"errors\" ignored before first Start of Session record.\n"),
+ ignored_msgs);
+ ignored_msgs = 0;
+ }
+ unser_session_label(&label, rec);
+ memset(&jr, 0, sizeof(jr));
+ jr.JobId = label.JobId;
+ if (db_get_job_record(bjcr, db, &jr)) {
+ /* Job record already exists in DB */
+ update_db = 0; /* don't change db in create_job_record */
+ if (verbose) {
+ Pmsg1(000, _("SOS_LABEL: Found Job record for JobId: %d\n"), jr.JobId);
}
- if (jr.PoolId != pr.PoolId) {
- Pmsg3(000, _("SOS_LABEL: PoolId mismatch for JobId=%u. DB=%d Vol=%d\n"),
- jr.JobId,
- jr.PoolId, pr.PoolId);
- return;
+ } else {
+ /* Must create a Job record in DB */
+ if (!update_db) {
+ Pmsg1(000, _("SOS_LABEL: Job record not found for JobId: %d\n"),
+ jr.JobId);
}
+ }
+ /* Create Client record if not already there */
+ strcpy(cr.Name, label.ClientName);
+ create_client_record(db, &cr);
+ jr.ClientId = cr.ClientId;
+
+ /* process label, if Job record exists don't update db */
+ mjcr = create_job_record(db, &jr, &label, rec);
+ update_db = save_update_db;
+
+ jr.PoolId = pr.PoolId;
+ /* Set start positions into JCR */
+ if (dev->state & ST_TAPE) {
+ mjcr->StartBlock = dev->block_num;
+ mjcr->StartFile = dev->file;
+ } else {
+ mjcr->StartBlock = (uint32_t)dev->file_addr;
+ mjcr->StartFile = (uint32_t)(dev->file_addr >> 32);
+ }
+ mjcr->start_time = jr.StartTime;
+ mjcr->JobLevel = jr.Level;
+
+ mjcr->client_name = get_pool_memory(PM_FNAME);
+ pm_strcpy(&mjcr->client_name, label.ClientName);
+ mjcr->pool_type = get_pool_memory(PM_FNAME);
+ pm_strcpy(&mjcr->pool_type, label.PoolType);
+ mjcr->fileset_name = get_pool_memory(PM_FNAME);
+ pm_strcpy(&mjcr->fileset_name, label.FileSetName);
+ mjcr->pool_name = get_pool_memory(PM_FNAME);
+ pm_strcpy(&mjcr->pool_name, label.PoolName);
+
+ if (rec->VolSessionId != jr.VolSessionId) {
+ Pmsg3(000, _("SOS_LABEL: VolSessId mismatch for JobId=%u. DB=%d Vol=%d\n"),
+ jr.JobId,
+ jr.VolSessionId, rec->VolSessionId);
+ return;
+ }
+ if (rec->VolSessionTime != jr.VolSessionTime) {
+ Pmsg3(000, _("SOS_LABEL: VolSessTime mismatch for JobId=%u. DB=%d Vol=%d\n"),
+ jr.JobId,
+ jr.VolSessionTime, rec->VolSessionTime);
+ return;
+ }
+ if (jr.PoolId != pr.PoolId) {
+ Pmsg3(000, _("SOS_LABEL: PoolId mismatch for JobId=%u. DB=%d Vol=%d\n"),
+ jr.JobId,
+ jr.PoolId, pr.PoolId);
+ return;
+ }
+ break;
+ case EOS_LABEL:
+ unser_session_label(&elabel, rec);
+
+ /* Create FileSet record */
+ strcpy(fsr.FileSet, label.FileSetName);
+ strcpy(fsr.MD5, label.FileSetMD5);
+ create_fileset_record(db, &fsr);
+ jr.FileSetId = fsr.FileSetId;
+
+ mjcr = get_jcr_by_session(rec->VolSessionId, rec->VolSessionTime);
+ if (!mjcr) {
+ Pmsg2(000, _("Could not find SessId=%d SessTime=%d for EOS record.\n"),
+ rec->VolSessionId, rec->VolSessionTime);
break;
- case EOS_LABEL:
- unser_session_label(&elabel, rec);
-
- /* Create FileSet record */
- strcpy(fsr.FileSet, label.FileSetName);
- strcpy(fsr.MD5, label.FileSetMD5);
- create_fileset_record(db, &fsr);
- jr.FileSetId = fsr.FileSetId;
-
- mjcr = get_jcr_by_session(rec->VolSessionId, rec->VolSessionTime);
- if (!mjcr) {
- Pmsg2(000, _("Could not find SessId=%d SessTime=%d for EOS record.\n"),
- rec->VolSessionId, rec->VolSessionTime);
- break;
- }
+ }
- /* Do the final update to the Job record */
- update_job_record(db, &jr, &elabel, rec);
+ /* Do the final update to the Job record */
+ update_job_record(db, &jr, &elabel, rec);
- mjcr->end_time = jr.EndTime;
- mjcr->JobStatus = JS_Terminated;
+ mjcr->end_time = jr.EndTime;
+ mjcr->JobStatus = JS_Terminated;
- /* Create JobMedia record */
- create_jobmedia_record(db, mjcr);
- detach_jcr_from_device(dev, mjcr);
- free_jcr(mjcr);
+ /* Create JobMedia record */
+ create_jobmedia_record(db, mjcr);
+ detach_jcr_from_device(dev, mjcr);
+ free_jcr(mjcr);
- break;
- case EOM_LABEL:
- break;
- case EOT_LABEL: /* end of all tapes */
- /*
- * Wiffle through all jobs still open and close
- * them.
- */
- if (update_db) {
- for (mjcr=NULL; (mjcr=next_attached_jcr(dev, mjcr)); ) {
- jr.JobId = mjcr->JobId;
- jr.JobStatus = JS_ErrorTerminated;
- jr.JobFiles = mjcr->JobFiles;
- jr.JobBytes = mjcr->JobBytes;
- jr.VolSessionId = mjcr->VolSessionId;
- jr.VolSessionTime = mjcr->VolSessionTime;
- jr.JobTDate = (utime_t)mjcr->start_time;
- jr.ClientId = mjcr->ClientId;
- free_jcr(mjcr);
- if (!db_update_job_end_record(bjcr, db, &jr)) {
- Pmsg1(0, _("Could not update job record. ERR=%s\n"), db_strerror(db));
- }
+ break;
+ case EOM_LABEL:
+ break;
+ case EOT_LABEL: /* end of all tapes */
+ /*
+ * Wiffle through all jobs still open and close
+ * them.
+ */
+ if (update_db) {
+ for (mjcr=NULL; (mjcr=next_attached_jcr(dev, mjcr)); ) {
+ jr.JobId = mjcr->JobId;
+ jr.JobStatus = JS_ErrorTerminated;
+ jr.JobFiles = mjcr->JobFiles;
+ jr.JobBytes = mjcr->JobBytes;
+ jr.VolSessionId = mjcr->VolSessionId;
+ jr.VolSessionTime = mjcr->VolSessionTime;
+ jr.JobTDate = (utime_t)mjcr->start_time;
+ jr.ClientId = mjcr->ClientId;
+ free_jcr(mjcr);
+ if (!db_update_job_end_record(bjcr, db, &jr)) {
+ Pmsg1(0, _("Could not update job record. ERR=%s\n"), db_strerror(db));
}
}
- mr.VolFiles = rec->File;
- mr.VolBlocks = rec->Block;
- mr.VolBytes += mr.VolBlocks * WRITE_BLKHDR_LENGTH; /* approx. */
- mr.VolMounts++;
- update_media_record(db, &mr);
- Pmsg3(0, _("End of Volume. VolFiles=%u VolBlocks=%u VolBytes=%s\n"), mr.VolFiles,
- mr.VolBlocks, edit_uint64_with_commas(mr.VolBytes, ec1));
- break;
- default:
- break;
- }
+ }
+ mr.VolFiles = rec->File;
+ mr.VolBlocks = rec->Block;
+ mr.VolBytes += mr.VolBlocks * WRITE_BLKHDR_LENGTH; /* approx. */
+ mr.VolMounts++;
+ update_media_record(db, &mr);
+ Pmsg3(0, _("End of Volume. VolFiles=%u VolBlocks=%u VolBytes=%s\n"), mr.VolFiles,
+ mr.VolBlocks, edit_uint64_with_commas(mr.VolBytes, ec1));
+ break;
+ default:
+ break;
+ } /* end switch */
return;
}
/* File Attributes stream */
- if (rec->Stream == STREAM_UNIX_ATTRIBUTES || rec->Stream == STREAM_WIN32_ATTRIBUTES) {
- char *ap, *lp, *fp;
+ switch (rec->Stream) {
+ case STREAM_UNIX_ATTRIBUTES:
+ case STREAM_UNIX_ATTRIBUTES_EX:
- if (sizeof_pool_memory(fname) < rec->data_len) {
- fname = realloc_pool_memory(fname, rec->data_len + 1);
+ if (!unpack_attributes_record(bjcr, rec->Stream, rec->data, attr)) {
+ Emsg0(M_ERROR_TERM, 0, _("Cannot continue.\n"));
}
- if (sizeof_pool_memory(lname) < rec->data_len) {
- lname = realloc_pool_memory(lname, rec->data_len + 1);
- }
- *fname = 0;
- *lname = 0;
-
- /*
- * An Attributes record consists of:
- * File_index
- * Type (FT_types)
- * Filename
- * Attributes
- * Link name (if file linked i.e. FT_LNK)
- *
- */
- sscanf(rec->data, "%ld %d", &record_file_index, &type);
- if (record_file_index != rec->FileIndex)
- Emsg2(M_ERROR_TERM, 0, "Record header file index %ld not equal record index %ld\n",
- rec->FileIndex, record_file_index);
- ap = rec->data;
- while (*ap++ != ' ') /* skip record file index */
- ;
- while (*ap++ != ' ') /* skip type */
- ;
- /* Save filename and position to attributes */
- fp = fname;
- while (*ap != 0) {
- *fp++ = *ap++;
- }
- *fp = *ap++; /* terminate filename & point to attribs */
- /* Skip through attributes to link name */
- lp = ap;
- while (*lp++ != 0) {
- ;
+ if (attr->file_index != rec->FileIndex) {
+ Emsg2(M_ERROR_TERM, 0, _("Record header file index %ld not equal record index %ld\n"),
+ rec->FileIndex, attr->file_index);
}
- strcat(lname, lp); /* "save" link name */
+
if (verbose > 1) {
uint32_t LinkFI;
- decode_stat(ap, &statp, &LinkFI);
- print_ls_output(fname, lname, type, &statp);
+ decode_stat(attr->attr, &attr->statp, &LinkFI);
+ print_ls_output(bjcr, attr);
}
mjcr = get_jcr_by_session(rec->VolSessionId, rec->VolSessionTime);
if (!mjcr) {
}
fr.JobId = mjcr->JobId;
fr.FileId = 0;
- if (db_get_file_attributes_record(bjcr, db, fname, &fr)) {
+ if (db_get_file_attributes_record(bjcr, db, attr->fname, &fr)) {
if (verbose > 1) {
- Pmsg1(000, _("File record already exists for: %s\n"), fname);
+ Pmsg1(000, _("File record already exists for: %s\n"), attr->fname);
}
} else {
- create_file_attributes_record(db, mjcr, fname, lname, type, ap, rec);
+ create_file_attributes_record(db, mjcr, attr->fname, attr->lname,
+ attr->type, attr->attr, rec);
}
free_jcr(mjcr);
+ break;
/* Data stream */
- } else if (rec->Stream == STREAM_FILE_DATA) {
+ case STREAM_WIN32_DATA:
+ case STREAM_FILE_DATA:
+ case STREAM_SPARSE_DATA:
mjcr = get_jcr_by_session(rec->VolSessionId, rec->VolSessionTime);
if (!mjcr) {
if (mr.VolJobs > 0) {
return;
}
mjcr->JobBytes += rec->data_len;
- free_jcr(mjcr); /* done using JCR */
-
- } else if (rec->Stream == STREAM_SPARSE_DATA) {
- mjcr = get_jcr_by_session(rec->VolSessionId, rec->VolSessionTime);
- if (!mjcr) {
- if (mr.VolJobs > 0) {
- Pmsg2(000, _("Could not find Job SessId=%d SessTime=%d for Sparse Data record.\n"),
- rec->VolSessionId, rec->VolSessionTime);
- } else {
- ignored_msgs++;
- }
- return;
+ if (rec->Stream == STREAM_SPARSE_DATA) {
+ mjcr->JobBytes -= sizeof(uint64_t);
}
- mjcr->JobBytes += rec->data_len - sizeof(uint64_t);
+
free_jcr(mjcr); /* done using JCR */
+ break;
- } else if (rec->Stream == STREAM_GZIP_DATA) {
+ case STREAM_GZIP_DATA:
mjcr = get_jcr_by_session(rec->VolSessionId, rec->VolSessionTime);
if (!mjcr) {
if (mr.VolJobs > 0) {
}
mjcr->JobBytes += rec->data_len; /* No correct, we should expand it */
free_jcr(mjcr); /* done using JCR */
+ break;
- } else if (rec->Stream == STREAM_SPARSE_GZIP_DATA) {
+ case STREAM_SPARSE_GZIP_DATA:
mjcr = get_jcr_by_session(rec->VolSessionId, rec->VolSessionTime);
if (!mjcr) {
if (mr.VolJobs > 0) {
}
mjcr->JobBytes += rec->data_len - sizeof(uint64_t); /* No correct, we should expand it */
free_jcr(mjcr); /* done using JCR */
-
- /* Win32 Data stream */
- } else if (rec->Stream == STREAM_WIN32_DATA) {
- mjcr = get_jcr_by_session(rec->VolSessionId, rec->VolSessionTime);
- if (!mjcr) {
- if (mr.VolJobs > 0) {
- Pmsg2(000, _("Could not find Job SessId=%d SessTime=%d for Win32 Data record.\n"),
- rec->VolSessionId, rec->VolSessionTime);
- } else {
- ignored_msgs++;
- }
- return;
- }
- mjcr->JobBytes += rec->data_len;
- free_jcr(mjcr); /* done using JCR */
+ break;
/* Win32 GZIP stream */
- } else if (rec->Stream == STREAM_WIN32_GZIP_DATA) {
+ case STREAM_WIN32_GZIP_DATA:
mjcr = get_jcr_by_session(rec->VolSessionId, rec->VolSessionTime);
if (!mjcr) {
if (mr.VolJobs > 0) {
}
mjcr->JobBytes += rec->data_len;
free_jcr(mjcr); /* done using JCR */
+ break;
- } else if (rec->Stream == STREAM_MD5_SIGNATURE) {
+ case STREAM_MD5_SIGNATURE:
char MD5buf[50];
bin_to_base64(MD5buf, (char *)rec->data, 16); /* encode 16 bytes */
if (verbose > 1) {
Pmsg1(000, _("Got MD5 record: %s\n"), MD5buf);
}
update_SIG_record(db, MD5buf, rec, MD5_SIG);
+ break;
- } else if (rec->Stream == STREAM_SHA1_SIGNATURE) {
+ case STREAM_SHA1_SIGNATURE:
char SIGbuf[50];
bin_to_base64(SIGbuf, (char *)rec->data, 20); /* encode 20 bytes */
if (verbose > 1) {
Pmsg1(000, _("Got SHA1 record: %s\n"), SIGbuf);
}
update_SIG_record(db, SIGbuf, rec, SHA1_SIG);
+ break;
- } else if (rec->Stream == STREAM_PROGRAM_NAMES) {
+ case STREAM_PROGRAM_NAMES:
if (verbose) {
Pmsg1(000, _("Got Prog Names Stream: %s\n"), rec->data);
}
- } else if (rec->Stream == STREAM_PROGRAM_DATA) {
+ break;
+
+ case STREAM_PROGRAM_DATA:
if (verbose > 1) {
Pmsg0(000, _("Got Prog Data Stream record.\n"));
}
- } else {
+ break;
+ default:
Pmsg2(0, _("Unknown stream type!!! stream=%d data=%s\n"), rec->Stream, rec->data);
+ break;
}
return;
}
if (!bsr && VolumeName) {
pm_strcpy(&jcr->VolumeName, VolumeName);
}
+ jcr->where = bstrdup("");
return jcr;
}
else
Jmsg(jcr, M_ERROR, 0, _("Read error on Record Header %s: %s\n"), dev_name(dev), strerror(errno));
}
-
-
-extern char *getuser(uid_t uid);
-extern char *getgroup(gid_t gid);
-
-void print_ls_output(char *fname, char *link, int type, struct stat *statp)
-{
- char buf[1000];
- char ec1[30];
- char *p, *f;
- int n;
-
- p = encode_mode(statp->st_mode, buf);
- n = sprintf(p, " %2d ", (uint32_t)statp->st_nlink);
- p += n;
- n = sprintf(p, "%-8.8s %-8.8s", getuser(statp->st_uid), getgroup(statp->st_gid));
- p += n;
- n = sprintf(p, "%8.8s ", edit_uint64(statp->st_size, ec1));
- p += n;
- p = encode_time(statp->st_ctime, p);
- *p++ = ' ';
- *p++ = ' ';
- /* Copy file name */
- for (f=fname; *f && (p-buf) < (int)sizeof(buf); )
- *p++ = *f++;
- if (type == FT_LNK) {
- *p++ = ' ';
- *p++ = '-';
- *p++ = '>';
- *p++ = ' ';
- /* Copy link name */
- for (f=link; *f && (p-buf) < (int)sizeof(buf); )
- *p++ = *f++;
- }
- *p++ = '\n';
- *p = 0;
- fputs(buf, stdout);
-}
return "SHA1";
case STREAM_GZIP_DATA:
return "GZIP";
- case STREAM_WIN32_ATTRIBUTES:
- return "WIN32-ATTR";
+ case STREAM_UNIX_ATTRIBUTES_EX:
+ return "UNIX-ATTR-EX";
case STREAM_SPARSE_DATA:
return "SPARSE-DATA";
case STREAM_SPARSE_GZIP_DATA:
return "contSHA1";
case -STREAM_GZIP_DATA:
return "contGZIP";
- case -STREAM_WIN32_ATTRIBUTES:
- return "contWIN32-ATTR";
+ case -STREAM_UNIX_ATTRIBUTES_EX:
+ return "contUNIX-ATTR-EX";
case -STREAM_SPARSE_DATA:
return "contSPARSE-DATA";
case -STREAM_SPARSE_GZIP_DATA:
#include "jcr.h"
#include "protos.h"
#ifdef HAVE_LIBZ
-#include <zlib.h> /* compression headers */
+#include <zlib.h> /* compression headers */
#else
#define uLongf uint32_t
#endif
-#include "findlib/find.h"
-
-extern char errmsg[]; /* general error message */
+extern char errmsg[]; /* general error message */
extern STORES *me; /* "Global" daemon resource */