From c005bc1086f2c27ecd56a90186d86d08951e22fa Mon Sep 17 00:00:00 2001 From: Eric Bollengier Date: Wed, 4 Jan 2012 14:13:47 +0100 Subject: [PATCH] Set directory attributes when using Replace=Never when Bacula creates them --- bacula/src/findlib/create_file.c | 49 ++++++++--------- bacula/src/findlib/find.c | 2 + bacula/src/findlib/find.h | 3 ++ bacula/src/findlib/mkpath.c | 92 +++++++++++++++++++++++++++++++- bacula/src/findlib/protos.h | 7 ++- 5 files changed, 123 insertions(+), 30 deletions(-) diff --git a/bacula/src/findlib/create_file.c b/bacula/src/findlib/create_file.c index ab8afd2ff5..b283af3cbf 100644 --- a/bacula/src/findlib/create_file.c +++ b/bacula/src/findlib/create_file.c @@ -114,38 +114,35 @@ int create_file(JCR *jcr, ATTR *attr, BFILE *bfd, int replace) } } #endif - Dmsg3(200, "Create %s Replace=%c FT=%d\n", attr->ofname, (char)replace, attr->type); + + Dmsg2(400, "Replace=%c %d\n", (char)replace, replace); if (lstat(attr->ofname, &mstatp) == 0) { exists = true; - /* - * For directories we do not apply the replace options, because - * we must always create directories that do not exist, and thus - * when the directory end record comes, the directory exists. So - * we always apply the FT_DIREND record for directories. - */ - if (attr->type != FT_DIREND) { - switch (replace) { - case REPLACE_IFNEWER: - if (attr->statp.st_mtime <= mstatp.st_mtime) { - Qmsg(jcr, M_SKIPPED, 0, _("File skipped. Not newer: %s\n"), attr->ofname); - return CF_SKIP; - } - break; - - case REPLACE_IFOLDER: - if (attr->statp.st_mtime >= mstatp.st_mtime) { - Qmsg(jcr, M_SKIPPED, 0, _("File skipped. Not older: %s\n"), attr->ofname); - return CF_SKIP; - } - break; + switch (replace) { + case REPLACE_IFNEWER: + if (attr->statp.st_mtime <= mstatp.st_mtime) { + Qmsg(jcr, M_SKIPPED, 0, _("File skipped. Not newer: %s\n"), attr->ofname); + return CF_SKIP; + } + break; - case REPLACE_NEVER: - Qmsg(jcr, M_SKIPPED, 0, _("File skipped. Already exists: %s\n"), attr->ofname); + case REPLACE_IFOLDER: + if (attr->statp.st_mtime >= mstatp.st_mtime) { + Qmsg(jcr, M_SKIPPED, 0, _("File skipped. Not older: %s\n"), attr->ofname); return CF_SKIP; + } + break; - case REPLACE_ALWAYS: + case REPLACE_NEVER: + /* Set attributes if we created this directory */ + if (attr->type == FT_DIREND && path_list_lookup(jcr, attr->ofname)) { break; } + Qmsg(jcr, M_SKIPPED, 0, _("File skipped. Already exists: %s\n"), attr->ofname); + return CF_SKIP; + + case REPLACE_ALWAYS: + break; } } switch (attr->type) { @@ -193,12 +190,12 @@ int create_file(JCR *jcr, ATTR *attr, BFILE *bfd, int replace) attr->ofname[pnl] = 0; /* terminate path */ if (!path_already_seen(jcr, attr->ofname, pnl)) { + Dmsg1(400, "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. */ - Dmsg1(400, "makepath %s\n", attr->ofname); if (!makepath(attr, attr->ofname, parent_mode, parent_mode, uid, gid, 1)) { Dmsg1(10, "Could not make path. %s\n", attr->ofname); attr->ofname[pnl] = savechr; /* restore full name */ diff --git a/bacula/src/findlib/find.c b/bacula/src/findlib/find.c index 3098f615c1..cf707265f6 100644 --- a/bacula/src/findlib/find.c +++ b/bacula/src/findlib/find.c @@ -197,6 +197,8 @@ find_files(JCR *jcr, FF_PKT *ff, int file_save(JCR *jcr, FF_PKT *ff_pkt, bool to ff->strip_path = fo->strip_path; ff->fstypes = fo->fstype; ff->drivetypes = fo->drivetype; + ff->plugin = fo->plugin; /* TODO: generate a plugin event ? */ + ff->opt_plugin = (ff->plugin != NULL)? true : false; bstrncat(ff->VerifyOpts, fo->VerifyOpts, sizeof(ff->VerifyOpts)); if (fo->AccurateOpts[0]) { bstrncpy(ff->AccurateOpts, fo->AccurateOpts, sizeof(ff->AccurateOpts)); diff --git a/bacula/src/findlib/find.h b/bacula/src/findlib/find.h index cda9e9b016..fddd0fc832 100644 --- a/bacula/src/findlib/find.h +++ b/bacula/src/findlib/find.h @@ -115,6 +115,7 @@ struct findFOPTS { char VerifyOpts[MAX_FOPTS]; /* verify options */ char AccurateOpts[MAX_FOPTS]; /* accurate mode options */ char BaseJobOpts[MAX_FOPTS]; /* basejob mode options */ + char *plugin; /* Plugin that handle this section */ alist regex; /* regex string(s) */ alist regexdir; /* regex string(s) for directories */ alist regexfile; /* regex string(s) for files */ @@ -164,6 +165,7 @@ struct FF_PKT { char *link; /* link if file linked */ char *object_name; /* Object name */ char *object; /* restore object */ + char *plugin; /* Current Options{Plugin=} name */ POOLMEM *sys_fname; /* system filename */ POOLMEM *fname_save; /* save when stripping path */ POOLMEM *link_save; /* save when stripping path */ @@ -202,6 +204,7 @@ struct FF_PKT { int Compress_level; /* compression level */ int strip_path; /* strip path count */ bool cmd_plugin; /* set if we have a command plugin */ + bool opt_plugin; /* set if we have an option plugin */ alist fstypes; /* allowed file system types */ alist drivetypes; /* allowed drive types */ diff --git a/bacula/src/findlib/mkpath.c b/bacula/src/findlib/mkpath.c index 4e4dfb57b3..884ba10083 100644 --- a/bacula/src/findlib/mkpath.c +++ b/bacula/src/findlib/mkpath.c @@ -42,6 +42,90 @@ #include "bacula.h" #include "jcr.h" +#define dbglvl 50 + +typedef struct PrivateCurDir { + hlink link; + char fname[1]; +} CurDir; + +/* Initialize the path hash table */ +static bool path_list_init(JCR *jcr) +{ + CurDir *elt = NULL; + jcr->path_list = (htable *)malloc(sizeof(htable)); + + /* Hard to know in advance how many directories will + * be stored in this hash + */ + jcr->path_list->init(elt, &elt->link, 10000); + return true; +} + +/* Add a path to the hash when we create a directory + * with the replace=NEVER option + */ +bool path_list_add(JCR *jcr, uint32_t len, char *fname) +{ + bool ret = true; + CurDir *item; + + if (!jcr->path_list) { + path_list_init(jcr); + } + + /* we store CurDir, fname in the same chunk */ + item = (CurDir *)jcr->path_list->hash_malloc(sizeof(CurDir)+len+1); + + memset(item, 0, sizeof(CurDir)); + memcpy(item->fname, fname, len+1); + + jcr->path_list->insert(item->fname, item); + + Dmsg1(dbglvl, "add fname=<%s>\n", fname); + return ret; +} + +void free_path_list(JCR *jcr) +{ + if (jcr->path_list) { + jcr->path_list->destroy(); + free(jcr->path_list); + jcr->path_list = NULL; + } +} + +bool path_list_lookup(JCR *jcr, char *fname) +{ + bool found=false; + char bkp; + + if (!jcr->path_list) { + return false; + } + + /* Strip trailing / */ + int len = strlen(fname); + if (len == 0) { + return false; + } + len--; + bkp = fname[len]; + if (fname[len] == '/') { /* strip any trailing slash */ + fname[len] = 0; + } + + CurDir *temp = (CurDir *)jcr->path_list->lookup(fname); + if (temp) { + found=true; + } + + Dmsg2(dbglvl, "lookup <%s> %s\n", fname, found?"ok":"not ok"); + + fname[len] = bkp; /* restore last / */ + return found; +} + static bool makedir(JCR *jcr, char *path, mode_t mode, int *created) { struct stat statp; @@ -59,6 +143,12 @@ static bool makedir(JCR *jcr, char *path, mode_t mode, int *created) } return true; /* directory exists */ } + + if (jcr->keep_path_list) { + /* When replace=NEVER, we keep track of all directories newly created */ + path_list_add(jcr, strlen(path), path); + } + *created = true; return true; } @@ -174,7 +264,6 @@ bool makepath(ATTR *attr, const char *apath, mode_t mode, mode_t parent_mode, if (!makedir(jcr, path, tmode, &created)) { goto bail_out; } - Dmsg2(400, "makedir: created=%d %s\n", created, path); if (ndir < max_dirs) { new_dir[ndir++] = created; } @@ -187,7 +276,6 @@ bool makepath(ATTR *attr, const char *apath, mode_t mode, mode_t parent_mode, if (!makedir(jcr, path, tmode, &created)) { goto bail_out; } - Dmsg2(400, "makedir: created=%d %s\n", created, path); if (ndir < max_dirs) { new_dir[ndir++] = created; } diff --git a/bacula/src/findlib/protos.h b/bacula/src/findlib/protos.h index fc6fccbdbf..b39d25d3a1 100644 --- a/bacula/src/findlib/protos.h +++ b/bacula/src/findlib/protos.h @@ -1,7 +1,7 @@ /* Bacula® - The Network Backup Solution - Copyright (C) 2000-2008 Free Software Foundation Europe e.V. + Copyright (C) 2000-2011 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. @@ -28,7 +28,6 @@ /* * Prototypes for finlib directory of Bacula * - * Version $Id$ */ /* from attribs.c */ @@ -81,6 +80,10 @@ int enable_backup_privileges(JCR *jcr, int ignore_errors); bool makepath(ATTR *attr, const char *path, mode_t mode, mode_t parent_mode, uid_t owner, gid_t group, int keep_dir_modes); +void free_path_list(JCR *jcr); +bool path_list_lookup(JCR *jcr, char *fname); +bool path_list_add(JCR *jcr, uint32_t len, char *fname); + /* from fstype.c */ bool fstype(const char *fname, char *fs, int fslen); -- 2.39.5