char FileSet[MAX_NAME_LENGTH]; /* FileSet name */
char MD5[50]; /* MD5 signature of include/exclude */
time_t CreateTime; /* date created */
+ char Content[MAX_PLUGIN_LENGTH]; /* List of plugins in a fileset record */
/*
* This is where we return CreateTime
*/
FileSet TINYBLOB NOT NULL,
MD5 TINYBLOB,
CreateTime DATETIME,
+ Content BLOB DEFAULT '',
PRIMARY KEY(FileSetId)
);
fileset text not null,
md5 text not null,
createtime timestamp without time zone not null,
+ content text default '',
primary key (filesetid)
);
FileSet VARCHAR(128) NOT NULL,
MD5 VARCHAR(25) NOT NULL,
CreateTime DATETIME DEFAULT 0,
+ Content TEXT DEFAULT '',
PRIMARY KEY(FileSetId)
);
struct tm tm;
char esc_fs[MAX_ESCAPE_NAME_LENGTH];
char esc_md5[MAX_ESCAPE_NAME_LENGTH];
+ char esc_content[MAX_ESCAPE_PLUGIN_LENGTH];
/* TODO: Escape FileSet and MD5 */
bdb_lock();
fsr->created = false;
bdb_escape_string(jcr, esc_fs, fsr->FileSet, strlen(fsr->FileSet));
bdb_escape_string(jcr, esc_md5, fsr->MD5, strlen(fsr->MD5));
- Mmsg(cmd, "SELECT FileSetId,CreateTime FROM FileSet WHERE "
+ bdb_escape_string(jcr, esc_content, fsr->Content, strlen(fsr->Content));
+ Mmsg(cmd, "SELECT FileSetId,CreateTime,Content FROM FileSet WHERE "
"FileSet='%s' AND MD5='%s'", esc_fs, esc_md5);
fsr->FileSetId = 0;
} else {
bstrncpy(fsr->cCreateTime, row[1], sizeof(fsr->cCreateTime));
}
+ if ((row[2] == NULL || strcmp(row[2], "") == 0) && esc_content[0]) {
+ Mmsg(cmd, "UPDATE FileSet SET Content='%s' WHERE FileSetId=%ld",
+ esc_content, fsr->FileSetId);
+ if (!UpdateDB(jcr, cmd, false /* should match*/)) {
+ /* If we cannot update, this is not the end of the world, but we
+ * can display a message
+ */
+ Dmsg2(50, "Unable to update FileSet content field for %ld ERR=%s\n",
+ fsr->FileSetId, sql_strerror());
+ }
+ }
sql_free_result();
bdb_unlock();
return true;
strftime(fsr->cCreateTime, sizeof(fsr->cCreateTime), "%Y-%m-%d %H:%M:%S", &tm);
/* Must create it */
- Mmsg(cmd, "INSERT INTO FileSet (FileSet,MD5,CreateTime) "
-"VALUES ('%s','%s','%s')", esc_fs, esc_md5, fsr->cCreateTime);
+ Mmsg(cmd, "INSERT INTO FileSet (FileSet,MD5,CreateTime,Content) "
+ "VALUES ('%s','%s','%s','%s')", esc_fs, esc_md5, fsr->cCreateTime, esc_content);
if ((fsr->FileSetId = sql_insert_autokey_record(cmd, NT_("FileSet"))) == 0) {
Mmsg2(&errmsg, _("Create DB FileSet record %s failed. ERR=%s\n"),
bdb_lock();
if (fsr->FileSetId != 0) { /* find by id */
Mmsg(cmd,
- "SELECT FileSetId,FileSet,MD5,CreateTime FROM FileSet "
+ "SELECT FileSetId,FileSet,MD5,CreateTime,Content FROM FileSet "
"WHERE FileSetId=%s",
edit_int64(fsr->FileSetId, ed1));
} else { /* find by name */
bdb_escape_string(jcr, esc, fsr->FileSet, strlen(fsr->FileSet));
Mmsg(cmd,
- "SELECT FileSetId,FileSet,MD5,CreateTime FROM FileSet "
+ "SELECT FileSetId,FileSet,MD5,CreateTime,Content FROM FileSet "
"WHERE FileSet='%s' ORDER BY CreateTime DESC LIMIT 1", esc);
}
bstrncpy(fsr->FileSet, row[1]!=NULL?row[1]:"", sizeof(fsr->FileSet));
bstrncpy(fsr->MD5, row[2]!=NULL?row[2]:"", sizeof(fsr->MD5));
bstrncpy(fsr->cCreateTime, row[3]!=NULL?row[3]:"", sizeof(fsr->cCreateTime));
+ bstrncpy(fsr->Content, row[4]!=NULL?row[4]:"", sizeof(fsr->Content));
stat = fsr->FileSetId;
}
sql_free_result();
MODIFY COLUMN ObjectCategory BLOB;
MODIFY COLUMN ObjectUUID BLOB;
+ALTER TABLE FileSet
+ ADD COLUMN Content BLOB DEFAULT '';
+
ALTER TABLE Job
ADD COLUMN RealStartTime DATETIME,
ADD COLUMN isVirtualFull TINYINT default 0,
ALTER TABLE Media ADD COLUMN UseProtect smallint default 0;
ALTER TABLE Media ADD COLUMN VolEncrypted smallint default 0;
+ALTER TABLE FileSet ADD COLUMN Content text default '';
+
INSERT INTO Events (EventsCode, EventsType, EventsTime, EventsDaemon, EventsSource, EventsRef, EventsText) VALUES
('DU0001', 'catalog_update', NOW(), '*SHELL*', 'update_bacula_tables', 'pid$$', 'Catalog schema was updated to 1026');
UPDATE Version SET VersionId=1026;
counter->CurrentValue = counter->MinValue; /* default value */
}
}
+ /* Loop over all fileset, defining/updating them in each database */
+ FILESET *fs;
+ foreach_res(fs, R_FILESET) {
+ FILESET_DBR fsr;
+
+ bmemset(&fsr, 0, sizeof(FILESET_DBR));
+ bstrncpy(fsr.FileSet, fs->hdr.name, sizeof(fsr.FileSet));
+ if (fs->have_MD5) {
+ struct MD5Context md5c;
+ unsigned char digest[MD5HashSize];
+ memcpy(&md5c, &fs->md5c, sizeof(md5c));
+ MD5Final(digest, &md5c);
+ /*
+ * Keep the flag (last arg) set to false otherwise old FileSets will
+ * get new MD5 sums and the user will get Full backups on everything
+ */
+ bin_to_base64(fsr.MD5, sizeof(fsr.MD5), (char *)digest, MD5HashSize, false);
+ bstrncpy(fs->MD5, fsr.MD5, sizeof(fs->MD5));
+ }
+ /* Previously, the content of the fileset was not generated, so, if
+ * we have a fileset like that, we can update the record
+ */
+ if (!db_get_fileset_record(NULL, db, &fsr) || fsr.Content[0] == 0) {
+ fileset_get_content(&fsr, fs);
+ if (!db_create_fileset_record(NULL, db, &fsr)) {
+ Jmsg(NULL, M_FATAL, 0,
+ _("Could not create FileSet \"%s\" record. ERR=%s\n"),
+ fs->hdr.name, configfile);
+ }
+ }
+ }
/* cleanup old job records */
if (mode == UPDATE_AND_FIX) {
alist events(100, not_owned_by_alist);
return true;
}
+struct name_item
+{
+ rblink link;
+ char val[1];
+};
+
+static int my_strcmp(void *a, void *b)
+{
+ struct name_item *a1 = (struct name_item*)a;
+ struct name_item *b1 = (struct name_item*)b;
+ return strcmp(a1->val, b1->val);
+}
+
+/* Get the content overview of a FileSet */
+void fileset_get_content(FILESET_DBR *fdbr, FILESET *fileset)
+{
+ POOL_MEM tmp;
+ struct name_item *el = NULL;
+ bool files = false, first=true;
+ rblist c(el, &el->link);
+ regex_t r1;
+ regmatch_t pmatch[6];
+ /* We are looking for the plugin name, so basically Plugin = "mysql: options"
+ * Some plugins like Exchange have the interesting part inside the second part
+ */
+ regcomp(&r1, "^ *([a-zA-Z0-9-]+) *(: */@([A-Za-z]+))?", REG_EXTENDED);
+ for (int i=0; i<fileset->num_includes; i++) {
+ INCEXE *ie = fileset->include_items[i];
+
+ if (ie->name_list.size() > 0) {
+ files = true;
+ }
+ for (int j=0; j < ie->plugin_list.size(); j++) {
+ char *item = (char *)ie->plugin_list.get(j);
+ if (regexec(&r1, item, 5, pmatch, 0) == 0 &&
+ pmatch[1].rm_so >= 0 &&
+ pmatch[1].rm_eo > 0)
+ {
+ int l = pmatch[1].rm_eo - pmatch[1].rm_so + 1;
+ tmp.check_size(l+1);
+ bstrncpy(tmp.c_str(),
+ item + pmatch[1].rm_so,
+ l);
+
+ /* Special case for VSS plugins, the exact module is found in the
+ * second part
+ */
+ if (strcasecmp(tmp.c_str(), "vss") == 0 &&
+ pmatch[3].rm_so >= 0 &&
+ pmatch[3].rm_eo > 0)
+ {
+ // vss - SYSTEMSTATE \0
+ l = l + 1 + pmatch[3].rm_eo - pmatch[3].rm_so;
+ tmp.check_size(l+1);
+ bstrncat(tmp.c_str(), "-", l);
+ bstrncat(tmp.c_str(), item + pmatch[3].rm_so, l);
+ }
+
+ struct name_item *el2;
+ el = (struct name_item *) malloc(sizeof(struct name_item) + l + 1);
+ bstrncpy(el->val, tmp.c_str(), l);
+ el2 = (struct name_item *)c.insert(el, my_strcmp);
+ if (el2 != el) {
+ free(el); // not inserted
+ }
+ }
+ }
+ }
+ pm_strcpy(tmp, "");
+ if (files) {
+ pm_strcpy(tmp, "files");
+ first=false;
+ }
+ foreach_rblist(el, &c) {
+ if (!first) {
+ pm_strcat(tmp, ",");
+ }
+ pm_strcat(tmp, el->val);
+ first = false;
+ }
+ bstrncpy(fdbr->Content, tmp.c_str(), sizeof(fdbr->Content));
+ regfree(&r1);
+}
+
/*
* Get or Create FileSet record
*/
bool get_or_create_fileset_record(JCR *jcr)
{
FILESET_DBR fsr;
-
bmemset(&fsr, 0, sizeof(FILESET_DBR));
bstrncpy(fsr.FileSet, jcr->fileset->hdr.name, sizeof(fsr.FileSet));
if (jcr->fileset->have_MD5) {
Jmsg(jcr, M_WARNING, 0, _("FileSet MD5 digest not found.\n"));
}
if (!jcr->fileset->ignore_fs_changes ||
- !db_get_fileset_record(jcr, jcr->db, &fsr)) {
+ !db_get_fileset_record(jcr, jcr->db, &fsr))
+ {
+ /* Now we create the fileset at reload/startup, it should not happen */
+ fileset_get_content(&fsr, jcr->fileset);
if (!db_create_fileset_record(jcr, jcr->db, &fsr)) {
Jmsg(jcr, M_ERROR, 0, _("Could not create FileSet \"%s\" record. ERR=%s\n"),
fsr.FileSet, db_strerror(jcr->db));
extern void create_unique_job_name(JCR *jcr, const char *base_name);
extern void update_job_end_record(JCR *jcr);
extern bool get_or_create_client_record(JCR *jcr);
+extern void fileset_get_content(FILESET_DBR *fdbr, FILESET *fileset);
extern bool get_or_create_fileset_record(JCR *jcr);
extern DBId_t get_or_create_pool_record(JCR *jcr, char *pool_name);
extern void apply_pool_overrides(JCR *jcr);
MODIFY COLUMN ObjectCategory BLOB;
MODIFY COLUMN ObjectUUID BLOB;
+ALTER TABLE FileSet
+ ADD COLUMN Content BLOB DEFAULT '';
+
ALTER TABLE Job
ADD COLUMN RealStartTime DATETIME,
ADD COLUMN isVirtualFull TINYINT default 0,
ALTER TABLE Media ADD COLUMN UseProtect smallint default 0;
ALTER TABLE Media ADD COLUMN VolEncrypted smallint default 0;
+ALTER TABLE FileSet ADD COLUMN Content text default '';
+
INSERT INTO Events (EventsCode, EventsType, EventsTime, EventsDaemon, EventsSource, EventsRef, EventsText) VALUES
('DU0001', 'catalog_update', NOW(), '*SHELL*', 'update_bacula_tables', 'pid$$', 'Catalog schema was updated to 1026');
UPDATE Version SET VersionId=1026;