]> git.sur5r.net Git - bacula/bacula/commitdiff
Set directory attributes when using Replace=Never when Bacula creates them
authorEric Bollengier <eric@baculasystems.com>
Wed, 4 Jan 2012 13:13:47 +0000 (14:13 +0100)
committerKern Sibbald <kern@sibbald.com>
Sat, 20 Apr 2013 12:50:22 +0000 (14:50 +0200)
bacula/src/findlib/create_file.c
bacula/src/findlib/find.c
bacula/src/findlib/find.h
bacula/src/findlib/mkpath.c
bacula/src/findlib/protos.h

index ab8afd2ff55cf6570ae60683b76add4e18c9cd2f..b283af3cbfcb7334caa5a62a60a700a4cb1bcae6 100644 (file)
@@ -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 */
index 3098f615c1e0a8a7bd793c9c357bef0398267921..cf707265f6f9657d2b6abf7047345c613edf6860 100644 (file)
@@ -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));
index cda9e9b016ab58be990e8ede36e69047b637aa62..fddd0fc83272a29e80da3bbbbd98ebd91780deb3 100644 (file)
@@ -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 */
 
index 4e4dfb57b357101a256cfbe35f382a27aa6f89f0..884ba10083590a583456cd2151299715f08a8332 100644 (file)
 #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;
    }
index fc6fccbdbf8b67ee3972b4f296395be5c80ddaff..b39d25d3a1eb93ae30cdc21f29960d54ee417b5d 100644 (file)
@@ -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);