#define STREAM_ENCRYPTED_MACOS_FORK_DATA 25 /* Encrypted, uncompressed Mac resource fork */
#define STREAM_PLUGIN_NAME 26 /* Plugin "file" string */
#define STREAM_PLUGIN_DATA 27 /* Plugin specific data */
+#define STREAM_RESTORE_OBJECT 28 /* Plugin restore object */
/**
* Additional Stream definitions. Once defined these must NEVER
struct ROBJECT_DBR {
char *object_name;
char *object;
+ char *plugin_name;
uint32_t object_len;
- uint32_t ObjectIndex;
+ uint32_t object_index;
+ int32_t object_compression;
uint32_t FileIndex;
uint32_t Stream;
uint32_t FileType;
-- ***FIXME*** this needs to be corrected and turned on
--CREATE TABLE RestoreObject (
-- RestoreObjectId INTEGER NOT NULL DEFAULT RestoreObject_seq.nextval,
--- Fname TEXT NOT NULL,
--- Path TEXT NOT NULL,
+-- ObjectName TEXT NOT NULL,
-- RestoreObject TEXT NOT NULL,
-- PluginName TEXT NOT NULL,
-- ObjectIndex INTEGER DEFAULT 0,
-- ObjectType INTEGER DEFAULT 0,
-- FileIndex INTEGER UNSIGNED DEFAULT 0,
-- JobId INTEGER UNSIGNED,
+-- ObjectCompression INTEGER DEFAULT 0,
-- PRIMARY KEY(RestoreObjectId),
-- );
--CREATE INDEX restore_jobid_idx on file(JobId);
CREATE TABLE RestoreObject (
RestoreObjectId INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,
- Fname BLOB NOT NULL,
- Path BLOB NOT NULL,
- RestoreObject BLOB NOT NULL,
+ ObjectName BLOB NOT NULL,
+ RestoreObject LONGBLOB NOT NULL,
PluginName TINYBLOB NOT NULL,
ObjectLength INTEGER DEFAULT 0,
ObjectIndex INTEGER DEFAULT 0,
ObjectType INTEGER DEFAULT 0,
FileIndex INTEGER UNSIGNED DEFAULT 0,
JobId INTEGER UNSIGNED NOT NULL REFERENCES Job,
+ ObjectCompression INTEGER DEFAULT 0,
PRIMARY KEY(RestoreObjectId),
INDEX (JobId)
);
CREATE TABLE RestoreObject (
RestoreObjectId SERIAL NOT NULL,
- Fname TEXT NOT NULL,
- Path TEXT NOT NULL,
+ ObjectName TEXT NOT NULL,
RestoreObject TEXT NOT NULL,
PluginName TEXT NOT NULL,
ObjectLength INTEGER DEFAULT 0,
ObjectType INTEGER DEFAULT 0,
FileIndex INTEGER UNSIGNED DEFAULT 0,
JobId INTEGER UNSIGNED,
+ ObjectCompression INTEGER DEFAULT 0,
PRIMARY KEY(RestoreObjectId),
);
CREATE INDEX restore_jobid_idx on file(JobId);
CREATE TABLE RestoreObject (
RestoreObjectId INTEGER,
- Fname TEXT DEFAULT '',
- Path TEXT DEFAULT '',
+ ObjectName TEXT DEFAULT '',
RestoreObject TEXT DEFAULT '',
PluginName TEXT DEFAULT '',
ObjectLength INTEGER DEFAULT 0,
ObjectIndex INTEGER DEFAULT 0,
ObjectType INTEGER DEFAULT 0,
FileIndex INTEGER UNSIGNED DEFAULT 0,
+ ObejctCompression INTEGER DEFAULT 0,
JobId INTEGER UNSIGNED REFERENCES Job NOT NULL,
PRIMARY KEY(RestoreObjectId)
);
db_escape_string(jcr, mdb, esc_obj, ro->object, ro->object_len);
Mmsg(mdb->cmd,
- "INSERT INTO RestoreObject (Fname,RestoreObject,"
- "ObjectLength,ObjectIndex,ObjectType,FileIndex,JobId) VALUES"
- "('%s','%s',%d,%d,%d,%d,%u)",
- mdb->esc_name, esc_obj, ro->object_len,
- ro->ObjectIndex, FT_RESTORE_FIRST, ro->FileIndex, ro->JobId);
+ "INSERT INTO RestoreObject (ObjectName,RestoreObject,"
+ "ObjectLength,ObjectIndex,ObjectType,ObjectCompression,FileIndex,JobId) "
+ "VALUES ('%s','%s',%d,%d,%d,%d,%d,%u)",
+ mdb->esc_name, esc_obj, ro->object_len, ro->object_index,
+ FT_RESTORE_FIRST, ro->object_compression, ro->FileIndex, ro->JobId);
ro->RestoreObjectId = sql_insert_autokey_record(mdb, mdb->cmd, NT_("RestoreObject"));
if (ro->RestoreObjectId == 0) {
skip_spaces(&p);
skip_nonspaces(&p); /* Job=nnn */
skip_spaces(&p);
- skip_nonspaces(&p); /* FileAttributes */
+ skip_nonspaces(&p); /* "FileAttributes" */
p += 1;
+ /* The following "SD header" fields are serialized */
unser_begin(p, 0);
unser_uint32(VolSessionId); /* VolSessionId */
unser_uint32(VolSessionTime); /* VolSessionTime */
unser_uint32(reclen); /* Record length */
p += unser_length(p); /* Raw record follows */
- /*
+ /**
* At this point p points to the raw record, which varies according
- * to what kind of a record (Stream) was sent
+ * to what kind of a record (Stream) was sent. Note, the integer
+ * fields at the beginning of these "raw" records are in ASCII with
+ * spaces between them so one can use scanf or manual scanning to
+ * extract the fields.
+ *
+ * File Attributes
+ * File_index
+ * File type
+ * Filename (full path)
+ * Encoded attributes
+ * Link name (if type==FT_LNK or FT_LNKSAVED)
+ * Encoded extended-attributes (for Win32)
+ *
+ * Restore Object
+ * File_index
+ * File_type
+ * Object_index
+ * Object_len
+ * Object_compression
+ * Plugin_name
+ * Object_name
+ * Binary Object data
*/
Dmsg1(400, "UpdCat msg=%s\n", msg);
p = jcr->attr - msg + p; /* point p into jcr->attr */
skip_nonspaces(&p); /* skip FileIndex */
skip_spaces(&p);
- ar->FileType = str_to_int32(p); /* TODO: choose between unserialize and str_to_int32 */
+ ar->FileType = str_to_int32(p);
skip_nonspaces(&p); /* skip FileType */
skip_spaces(&p);
fname = p;
} else {
ar->JobId = jcr->JobId;
}
- /*
- * Restore object */
- if (ar->FileType == FT_RESTORE_FIRST) {
- ROBJECT_DBR ro;
- POOLMEM *attrEx = get_pool_memory(PM_MESSAGE);
- char *p;
- memset(&ro, 0, sizeof(ro));
- ro.object_name = fname;
- ro.Stream = Stream;
- ro.FileType = ar->FileType;
- ro.FileIndex = FileIndex;
- ro.JobId = ar->JobId;
- p = ar->attr; /* point to attributes */
- while (*p++ != 0) /* skip attributes */
- { }
- while (*p++ != 0) /* skip link */
- { }
- /* We have an object, so do a binary copy */
- ro.object_len = msglen + jcr->attr - p;
- attrEx = check_pool_memory_size(attrEx, ro.object_len + 1);
- memcpy(attrEx, p, ro.object_len);
- ro.object = attrEx;
- /* Add a EOS for those who attempt to print the object */
- p = attrEx + ro.object_len;
- *p = 0;
- Dmsg7(000, "oname=%s stream=%d FT=%d FI=%d JobId=%d, obj_len=%d\nobj=\"%s\"\n",
- ro.object_name, ro.Stream, ro.FileType, ro.FileIndex, ro.JobId,
- ro.object_len, attrEx);
- /* Send it */
- if (!db_create_restore_object_record(jcr, jcr->db, &ro)) {
- Jmsg1(jcr, M_FATAL, 0, _("Restore object create error. %s"), db_strerror(jcr->db));
- }
- free_pool_memory(attrEx);
- } else {
- ar->Digest = NULL;
- ar->DigestType = CRYPTO_DIGEST_NONE;
- jcr->cached_attribute = true;
- }
+ ar->Digest = NULL;
+ ar->DigestType = CRYPTO_DIGEST_NONE;
+ jcr->cached_attribute = true;
Dmsg2(400, "dird<filed: stream=%d %s\n", Stream, fname);
Dmsg1(400, "dird<filed: attr=%s\n", attr);
+ } else if (Stream == STREAM_RESTORE_OBJECT) {
+ ROBJECT_DBR ro;
+
+ memset(&ro, 0, sizeof(ro));
+ ro.Stream = Stream;
+ ro.FileIndex = FileIndex;
+ if (jcr->mig_jcr) {
+ ro.JobId = jcr->mig_jcr->JobId;
+ } else {
+ ro.JobId = jcr->JobId;
+ }
+
+ Dmsg1(100, "Robj=%s\n", p);
+
+ skip_nonspaces(&p); /* skip FileIndex */
+ skip_spaces(&p);
+ ro.FileType = str_to_int32(p);
+ skip_nonspaces(&p); /* move past FileType */
+ skip_spaces(&p);
+ ro.object_index = str_to_int32(p);
+ skip_nonspaces(&p); /* move past object_index */
+ ro.object_len = str_to_int32(p);
+ skip_nonspaces(&p); /* move past object_length */
+ ro.object_compression = str_to_int32(p);
+ skip_nonspaces(&p); /* move past object_compression */
+
+ ro.plugin_name = p; /* point to plugin name */
+ len = strlen(ro.plugin_name);
+ ro.object_name = &ro.plugin_name[len+1]; /* point to object name */
+ len = strlen(ro.object_name);
+ ro.object = &ro.object_name[len+1]; /* point to object */
+ ro.object[ro.object_len] = 0; /* add zero for those who attempt printing */
+ Dmsg7(100, "oname=%s stream=%d FT=%d FI=%d JobId=%d, obj_len=%d\nobj=\"%s\"\n",
+ ro.object_name, ro.Stream, ro.FileType, ro.FileIndex, ro.JobId,
+ ro.object_len, ro.object);
+ /* Send it */
+ if (!db_create_restore_object_record(jcr, jcr->db, &ro)) {
+ Jmsg1(jcr, M_FATAL, 0, _("Restore object create error. %s"), db_strerror(jcr->db));
+ }
+
} else if (crypto_digest_stream_type(Stream) != CRYPTO_DIGEST_NONE) {
fname = p;
if (ar->FileIndex != FileIndex) {
* attributes.
*/
attribsEx = ff_pkt->object;
- attr_stream = STREAM_UNIX_ATTRIBUTES_EX;
+ attr_stream = STREAM_RESTORE_OBJECT;
} else {
attribsEx = attribsExBuf;
attr_stream = encode_attribsEx(jcr, attribsEx, ff_pkt);
* Link name (if type==FT_LNK or FT_LNKSAVED)
* Encoded extended-attributes (for Win32)
*
+ * or send Restore Object to Storage daemon
+ * File_index
+ * File_type
+ * Object_index
+ * Object_len
+ * Object_compression
+ * Plugin_name
+ * Object_name
+ * Binary Object data
+ *
* For a directory, link is the same as fname, but with trailing
* slash. For a linked file, link is the link.
*/
ff_pkt->type, ff_pkt->link, 0, attribs, 0, 0, attribsEx, 0);
break;
case FT_RESTORE_FIRST:
- /**
- * Note, we edit everything as we do for the default case, but the
- * object is tacked on to the end in place of the extended attributes,
- * but we do a memcpy so that the object can be a binary object.
- */
- Dmsg6(100, "Type=%d DataStream=%d attrStream=%d File=%s\nattribs=%s\nattribsEx=%s",
- ff_pkt->type, data_stream, STREAM_UNIX_ATTRIBUTES_EX,
- ff_pkt->fname, attribs, ff_pkt->object);
- sd->msglen = Mmsg(sd->msg, "%ld %d %s%c%s%c%c",
- jcr->JobFiles, ff_pkt->type, ff_pkt->fname, 0, attribs, 0, 0);
- sd->msg = check_pool_memory_size(sd->msg, sd->msglen + ff_pkt->object_len + 1);
+ sd->msglen = Mmsg(sd->msg, "%d %d %d %d %d %s%c%s%c",
+ jcr->JobFiles, ff_pkt->type, ff_pkt->object_index,
+ ff_pkt->object_len, ff_pkt->object_compression,
+ ff_pkt->fname, 0, ff_pkt->object_name, 0);
+ sd->msg = check_pool_memory_size(sd->msg, sd->msglen + ff_pkt->object_len + 2);
memcpy(sd->msg + sd->msglen, ff_pkt->object, ff_pkt->object_len);
- sd->msglen += ff_pkt->object_len;
+ /* Note we send one extra byte so Dir can store zero after object */
+ sd->msglen += ff_pkt->object_len + 1;
stat = sd->send();
break;
default:
cmd);
goto bail_out;
}
- pm_strcpy(fname, sp.object_name);
- ff_pkt->fname = fname.c_str();
- ff_pkt->LinkFI = sp.index; /* restore object index */
+ ff_pkt->fname = cmd; /* full plugin string */
+ ff_pkt->object_name = sp.object_name;
+ ff_pkt->object_index = sp.index; /* restore object index */
+ ff_pkt->object_compression = 0; /* no compression for now */
ff_pkt->object = sp.object;
ff_pkt->object_len = sp.object_len;
} else {
/*
Bacula® - The Network Backup Solution
- Copyright (C) 2000-2009 Free Software Foundation Europe e.V.
+ Copyright (C) 2000-2010 Free Software Foundation Europe e.V.
The main author of Bacula is Kern Sibbald, with contributions from
many others, a complete list can be found in the file AUTHORS.
*
* Kern Sibbald, October MM
*
- * Version $Id$
- *
*/
#include "bacula.h"
-/*
- * Bacula File Daemon verify-vol.c Verify files on a Volume
- * versus attributes in Catalog
- *
- * Kern Sibbald, July MMII
- *
- * Version $Id$
- *
- */
/*
Bacula® - The Network Backup Solution
- Copyright (C) 2002-2006 Free Software Foundation Europe e.V.
+ Copyright (C) 2002-2010 Free Software Foundation Europe e.V.
The main author of Bacula is Kern Sibbald, with contributions from
many others, a complete list can be found in the file AUTHORS.
(FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
Switzerland, email:ftf@fsfeurope.org.
*/
+/*
+ * Bacula File Daemon verify-vol.c Verify files on a Volume
+ * versus attributes in Catalog
+ *
+ * Kern Sibbald, July MMII
+ *
+ */
#include "bacula.h"
#include "filed.h"
/* File Attributes stream */
switch (stream) {
- case STREAM_UNIX_ATTRIBUTES:
case STREAM_UNIX_ATTRIBUTES_EX:
char *ap, *lp, *fp;
char *top_fname; /* full filename before descending */
char *fname; /* full filename */
char *link; /* link if file linked */
+ char *object_name; /* Object name */
char *object; /* restore object */
POOLMEM *sys_fname; /* system filename */
POOLMEM *fname_save; /* save when stripping path */
struct stat statp; /* stat packet */
int32_t FileIndex; /* FileIndex of this file */
int32_t LinkFI; /* FileIndex of main hard linked file */
+ int32_t object_index; /* Object index */
int32_t object_len; /* Object length */
+ int32_t object_compression; /* Type of compression for object */
struct f_link *linked; /* Set if this file is hard linked */
int type; /* FT_ type from above */
int ff_errno; /* errno */
FI_to_ascii(buf1, rec.FileIndex), rec.VolSessionId,
stream_to_ascii(buf2, rec.Stream, rec.FileIndex), rec.data_len);
- /* Send attributes and digest to Director for Catalog */
- if (stream == STREAM_UNIX_ATTRIBUTES ||
- stream == STREAM_UNIX_ATTRIBUTES_EX ||
- crypto_digest_stream_type(stream) != CRYPTO_DIGEST_NONE) {
- if (!jcr->no_attributes) {
- BSOCK *dir = jcr->dir_bsock;
- if (are_attributes_spooled(jcr)) {
- dir->set_spooling();
- }
- Dmsg0(850, "Send attributes to dir.\n");
- if (!dir_update_file_attributes(dcr, &rec)) {
- dir->clear_spooling();
- Jmsg(jcr, M_FATAL, 0, _("Error updating file attributes. ERR=%s\n"),
- dir->bstrerror());
- ok = false;
- break;
- }
- dir->clear_spooling();
- }
- }
+ send_attrs_to_dir(jcr, &rec);
Dmsg0(650, "Enter bnet_get\n");
}
Dmsg1(650, "End read loop with FD. Stat=%d\n", n);
Dmsg1(100, "return from do_append_data() ok=%d\n", ok);
return ok;
}
+
+
+/* Send attributes and digest to Director for Catalog */
+bool send_attrs_to_dir(JCR *jcr, DEV_RECORD *rec)
+{
+ int stream = rec->Stream;
+
+ if (stream == STREAM_UNIX_ATTRIBUTES ||
+ stream == STREAM_UNIX_ATTRIBUTES_EX ||
+ stream == STREAM_RESTORE_OBJECT ||
+ crypto_digest_stream_type(stream) != CRYPTO_DIGEST_NONE) {
+ if (!jcr->no_attributes) {
+ BSOCK *dir = jcr->dir_bsock;
+ if (are_attributes_spooled(jcr)) {
+ dir->set_spooling();
+ }
+ Dmsg0(850, "Send attributes to dir.\n");
+ if (!dir_update_file_attributes(jcr->dcr, rec)) {
+ Jmsg(jcr, M_FATAL, 0, _("Error updating file attributes. ERR=%s\n"),
+ dir->bstrerror());
+ dir->clear_spooling();
+ return false;
+ }
+ dir->clear_spooling();
+ }
+ }
+ return true;
+}
"changer_name=%s media_type=%s volume_name=%s\n";
-/* Send update information about a device to Director */
+/** Send update information about a device to Director */
bool dir_update_device(JCR *jcr, DEVICE *dev)
{
BSOCK *dir = jcr->dir_bsock;
#endif
-/*
+/**
* Send current JobStatus to Director
*/
bool dir_send_job_status(JCR *jcr)
return jcr->dir_bsock->fsend(Job_status, jcr->Job, jcr->JobStatus);
}
-/*
+/**
* Common routine for:
* dir_get_volume_info()
* and
}
-/*
+/**
* Get Volume info for a specific volume from the Director's Database
*
* Returns: true on success (Director guarantees that Pool and MediaType
-/*
+/**
* Get info on the next appendable volume in the Director's database
*
* Returns: true on success dcr->VolumeName is volume
}
-/*
+/**
* After writing a Volume, send the updated statistics
* back to the director. The information comes from the
* dev record.
return ok;
}
-/*
+/**
* After writing a Volume, create the JobMedia record.
*/
bool dir_create_jobmedia_record(DCR *dcr, bool zero)
}
-/*
+/**
* Update File Attribute data
+ * We do the following:
+ * 1. expand the bsock buffer to be large enough
+ * 2. Write a "header" into the buffer with serialized data
+ * VolSessionId
+ * VolSeesionTime
+ * FileIndex
+ * Stream
+ * data length that follows
+ * start of raw byte data from the Device record.
+ * Note, this is primarily for Attribute data, but can
+ * also handle any device record. The Director must know
+ * the raw byte data format that is defined for each Stream.
+ * Now Restore Objects pass through here STREAM_RESTORE_OBJECT
*/
bool dir_update_file_attributes(DCR *dcr, DEV_RECORD *rec)
{
}
-/*
+/**
* Request the sysop to create an appendable volume
*
* Entered with device blocked.
return true;
}
-/*
+/**
* Request to mount specific Volume
*
* Entered with device blocked and dcr->VolumeName is desired
}
break;
+ case STREAM_RESTORE_OBJECT:
+ /* nothing to do */
+ break;
+
/* Data stream and extracting */
case STREAM_FILE_DATA:
case STREAM_SPARSE_DATA:
/* File Attributes stream */
if (rec->Stream == STREAM_UNIX_ATTRIBUTES ||
rec->Stream == STREAM_UNIX_ATTRIBUTES_EX) {
-
if (!unpack_attributes_record(jcr, rec->Stream, rec->data, rec->data_len, attr)) {
if (!forge_on) {
Emsg0(M_ERROR_TERM, 0, _("Cannot continue.\n"));
if (strncmp("0 0", rec->data, 3) != 0) {
Pmsg1(000, "Plugin data: %s\n", rec->data);
}
+ } else if (rec->Stream == STREAM_RESTORE_OBJECT) {
+ Pmsg0(000, "Restore Object record\n");
}
return true;
free_jcr(mjcr);
break;
+ case STREAM_RESTORE_OBJECT:
+ /* ****FIXME*****/
+ /* Implement putting into catalog */
+ break;
+
/* Data stream */
case STREAM_WIN32_DATA:
case STREAM_FILE_DATA:
JCR *jcr = dcr->jcr;
DEVICE *dev = jcr->dcr->dev;
char buf1[100], buf2[100];
- int32_t stream;
#ifdef xxx
Dmsg5(000, "on entry JobId=%d FI=%s SessId=%d Strm=%s len=%d\n",
FI_to_ascii(buf1, rec->FileIndex), rec->VolSessionId,
stream_to_ascii(buf2, rec->Stream, rec->FileIndex), rec->data_len);
- /* Send attributes and digest to Director for Catalog */
- stream = rec->Stream;
- if (stream == STREAM_UNIX_ATTRIBUTES ||
- stream == STREAM_UNIX_ATTRIBUTES_EX ||
- crypto_digest_stream_type(stream) != CRYPTO_DIGEST_NONE) {
- if (!jcr->no_attributes) {
- BSOCK *dir = jcr->dir_bsock;
- if (are_attributes_spooled(jcr)) {
- dir->set_spooling();
- }
- Dmsg0(850, "Send attributes to dir.\n");
- if (!dir_update_file_attributes(jcr->dcr, rec)) {
- dir->clear_spooling();
- Jmsg(jcr, M_FATAL, 0, _("Error updating file attributes. ERR=%s\n"),
- dir->bstrerror());
- return false;
- }
- dir->clear_spooling();
- }
- }
+ send_attrs_to_dir(jcr, rec);
return true;
}
/*
Bacula® - The Network Backup Solution
- Copyright (C) 2000-2008 Free Software Foundation Europe e.V.
+ Copyright (C) 2000-2010 Free Software Foundation Europe e.V.
The main author of Bacula is Kern Sibbald, with contributions from
many others, a complete list can be found in the file AUTHORS.
/*
* Protypes for stored -- Kern Sibbald MM
*
- * Version $Id$
*/
/* From stored.c */
DCR *new_dcr(JCR *jcr, DCR *dcr, DEVICE *dev);
void free_dcr(DCR *dcr);
+/* From append.c */
+bool send_attrs_to_dir(JCR *jcr, DEV_RECORD *rec);
+
/* From askdir.c */
enum get_vol_info_rw {
GET_VOL_INFO_FOR_WRITE,
return "GZIP";
case STREAM_UNIX_ATTRIBUTES_EX:
return "UNIX-ATTR-EX";
+ case STREAM_RESTORE_OBJECT:
+ return "RESTORE-OBJECT";
case STREAM_SPARSE_DATA:
return "SPARSE-DATA";
case STREAM_SPARSE_GZIP_DATA:
return "contGZIP";
case -STREAM_UNIX_ATTRIBUTES_EX:
return "contUNIX-ATTR-EX";
+ case -STREAM_RESTORE_OBJECT:
+ return "contRESTORE-OBJECT";
case -STREAM_SPARSE_DATA:
return "contSPARSE-DATA";
case -STREAM_SPARSE_GZIP_DATA: