From d4f2ae682e857739b82ba7a6b9dcf5e111cb73a4 Mon Sep 17 00:00:00 2001 From: Kern Sibbald Date: Wed, 12 Jan 2011 18:49:37 +0100 Subject: [PATCH] Ignore replace=xx for directories. Corrects (not total solution) ticket 2317 and bug #1444 --- bacula/src/findlib/create_file.c | 53 ++++++++++++++++++-------------- bacula/src/findlib/mkpath.c | 11 +++++-- 2 files changed, 39 insertions(+), 25 deletions(-) diff --git a/bacula/src/findlib/create_file.c b/bacula/src/findlib/create_file.c index e4f6920054..6a4fddd568 100644 --- a/bacula/src/findlib/create_file.c +++ b/bacula/src/findlib/create_file.c @@ -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. @@ -114,31 +114,38 @@ int create_file(JCR *jcr, ATTR *attr, BFILE *bfd, int replace) } } #endif - - Dmsg2(400, "Replace=%c %d\n", (char)replace, replace); + Dmsg3(200, "Create %s Replace=%c FT=%d\n", attr->ofname, (char)replace, attr->type); if (lstat(attr->ofname, &mstatp) == 0) { exists = true; - 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; + /* + * 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; + 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_NEVER: - Qmsg(jcr, M_SKIPPED, 0, _("File skipped. Already exists: %s\n"), attr->ofname); - return CF_SKIP; + case REPLACE_NEVER: + Qmsg(jcr, M_SKIPPED, 0, _("File skipped. Already exists: %s\n"), attr->ofname); + return CF_SKIP; - case REPLACE_ALWAYS: - break; + case REPLACE_ALWAYS: + break; + } } } switch (attr->type) { @@ -186,12 +193,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 */ @@ -226,7 +233,7 @@ int create_file(JCR *jcr, ATTR *attr, BFILE *bfd, int replace) } return CF_EXTRACT; -#ifndef HAVE_WIN32 // none of these exists on MS Windows +#ifndef HAVE_WIN32 // none of these exist in MS Windows case FT_RAW: /* Bacula raw device e.g. /dev/sda1 */ case FT_FIFO: /* Bacula fifo to save data */ case FT_SPEC: diff --git a/bacula/src/findlib/mkpath.c b/bacula/src/findlib/mkpath.c index 0c39a42b1b..4e4dfb57b3 100644 --- a/bacula/src/findlib/mkpath.c +++ b/bacula/src/findlib/mkpath.c @@ -1,7 +1,7 @@ /* Bacula® - The Network Backup Solution - Copyright (C) 2007-2008 Free Software Foundation Europe e.V. + Copyright (C) 2007-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. @@ -32,7 +32,12 @@ * This is tricky code, especially when writing from scratch. Fortunately, * a non-copyrighted version of mkdir was available to consult. * - * Version $Id$ + * ***FIXME*** the mkpath code could be significantly optimized by + * walking up the path chain from the bottom until it either gets + * to the top or finds an existing directory then walk back down + * creating the path components. Currently, it always starts at + * the top, which can be rather inefficient for long path names. + * */ #include "bacula.h" #include "jcr.h" @@ -169,6 +174,7 @@ 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; } @@ -181,6 +187,7 @@ 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; } -- 2.39.5