/*
- Bacula® - The Network Backup Solution
-
- 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.
- This program is Free Software; you can redistribute it and/or
- modify it under the terms of version three of the GNU Affero General Public
- License as published by the Free Software Foundation and included
- in the file LICENSE.
-
- This program is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- 02110-1301, USA.
-
- Bacula® is a registered trademark of Kern Sibbald.
- The licensor of Bacula is the Free Software Foundation Europe
- (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
- Switzerland, email:ftf@fsfeurope.org.
+ Bacula(R) - The Network Backup Solution
+
+ Copyright (C) 2000-2015 Kern Sibbald
+
+ The original author of Bacula is Kern Sibbald, with contributions
+ from many others, a complete list can be found in the file AUTHORS.
+
+ You may use this file and others of this release according to the
+ license defined in the LICENSE file, which includes the Affero General
+ Public License, v3.0 ("AGPLv3") and some additional permissions and
+ terms pursuant to its AGPLv3 Section 7.
+
+ This notice must be preserved when any source code is
+ conveyed and/or propagated.
+
+ Bacula(R) is a registered trademark of Kern Sibbald.
*/
/*
* Kern Sibbald, September MMVII
- *
+ *
* This is tricky code, especially when writing from scratch. Fortunately,
* a non-copyrighted version of mkdir was available to consult.
*
#define dbglvl 50
+/*
+ * For old systems that don't have lchown() or lchmod()
+ */
+#ifndef HAVE_LCHOWN
+#define lchown chown
+#endif
+#ifndef HAVE_LCHMOD
+#define lchmod chmod
+#endif
+
+
typedef struct PrivateCurDir {
hlink link;
char fname[1];
/* 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);
+ jcr->path_list->insert(item->fname, item);
Dmsg1(dbglvl, "add fname=<%s>\n", fname);
return ret;
if (mkdir(path, mode) != 0) {
berrno be;
*created = false;
- if (stat(path, &statp) != 0) {
+ if (lstat(path, &statp) != 0) {
Jmsg2(jcr, M_ERROR, 0, _("Cannot create directory %s: ERR=%s\n"),
path, be.bstrerror());
return false;
}
return true; /* directory exists */
}
-
+#if 0
+ /* TODO: This code rely on statp that is not initialized, we need to do a stat() */
+ if (S_ISLNK(statp.st_mode)) {
+ /*
+ * Note, we created a directory, not a link, so if we find a
+ * link, there is a security problem here.
+ */
+ Jmsg1(jcr, M_FATAL, 0, _("Security problem!! We created directory %s, but it is a link.\n"),
+ path);
+ return false;
+ }
+#endif
if (jcr->keep_path_list) {
/* When replace=NEVER, we keep track of all directories newly created */
path_list_add(jcr, strlen(path), path);
return true;
}
+/*
+ * Restore the owner and permissions (mode) of a Directory.
+ * See attribs.c for the equivalent for files.
+ */
static void set_own_mod(ATTR *attr, char *path, uid_t owner, gid_t group, mode_t mode)
{
- if (chown(path, owner, group) != 0 && attr->uid == 0
+ if (lchown(path, owner, group) != 0 && attr->uid == 0
#ifdef AFS
&& errno != EPERM
#endif
Jmsg2(attr->jcr, M_WARNING, 0, _("Cannot change owner and/or group of %s: ERR=%s\n"),
path, be.bstrerror());
}
- if (chmod(path, mode) != 0 && attr->uid == 0) {
+ if (lchmod(path, mode) != 0 && attr->uid == 0) {
berrno be;
Jmsg2(attr->jcr, M_WARNING, 0, _("Cannot change permissions of %s: ERR=%s\n"),
path, be.bstrerror());
/*
* mode is the mode bits to use in creating a new directory
*
- * parent_mode are the parent's modes if we need to create parent
+ * parent_mode are the parent's modes if we need to create parent
* directories.
*
* owner and group are to set on any created dirs
*/
tmode = 0777;
-#if defined(HAVE_WIN32)
- /* Validate drive letter */
- if (path[1] == ':') {
- char drive[4] = "X:\\";
-
- drive[0] = path[0];
-
- UINT drive_type = GetDriveType(drive);
-
- if (drive_type == DRIVE_UNKNOWN || drive_type == DRIVE_NO_ROOT_DIR) {
- Jmsg1(jcr, M_ERROR, 0, _("%c: is not a valid drive.\n"), path[0]);
- goto bail_out;
- }
-
- if (path[2] == '\0') { /* attempt to create a drive */
- ok = true;
- goto bail_out; /* OK, it is already there */
- }
-
- p = &path[3];
- } else {
- p = path;
- }
-#else
p = path;
-#endif
/* Skip leading slash(es) */
while (IsPathSeparator(*p)) {
}
/* Now set the proper owner and modes */
-#if defined(HAVE_WIN32)
-
- /* Don't propagate the hidden attribute to parent directories */
- parent_mode &= ~S_ISVTX;
-
- if (path[1] == ':') {
- p = &path[3];
- } else {
- p = path;
- }
-#else
p = path;
-#endif
/* Skip leading slash(es) */
while (IsPathSeparator(*p)) {
p++;