#include <errno.h>
#include <sys/stat.h>
+#include <unistd.h>
#include "gettext.h"
#define _(msgid) gettext (msgid)
-#include "dirchownmod.c"
+#include "dirchownmod.h"
#include "dirname.h"
#include "error.h"
#include "quote.h"
#include "mkancesdirs.h"
#include "savewd.h"
-#include "stat-macros.h"
+
+#ifndef HAVE_FCHMOD
+# define HAVE_FCHMOD false
+#endif
/* Ensure that the directory DIR exists.
WD is the working directory, as in savewd.c.
If MAKE_ANCESTOR is not null, create any ancestor directories that
- don't already exist, by invoking MAKE_ANCESTOR (ANCESTOR, OPTIONS).
+ don't already exist, by invoking MAKE_ANCESTOR (DIR, ANCESTOR, OPTIONS).
This function should return zero if successful, -1 (setting errno)
otherwise. In this case, DIR may be modified by storing '\0' bytes
into it, to access the ancestor directories, and this modification
bool
make_dir_parents (char *dir,
struct savewd *wd,
- int (*make_ancestor) (char const *, void *),
+ int (*make_ancestor) (char const *, char const *, void *),
void *options,
mode_t mode,
void (*announce) (char const *, void *),
if (0 <= prefix_len)
{
- if (mkdir (dir + prefix_len, mode) == 0)
+ /* If the ownership will change, create the directory with
+ more restrictive permissions at first, so unauthorized
+ users cannot nip in before the directory is ready. */
+ mode_t mkdir_mode = mode;
+ if (! (owner == (uid_t) -1 && group == (gid_t) -1))
+ mkdir_mode &= S_IRWXU;
+
+ if (mkdir (dir + prefix_len, mkdir_mode) == 0)
{
announce (dir, options);
preserve_existing =
| (mode & S_IRUSR ? SAVEWD_CHDIR_READABLE : 0));
}
else
- mkdir_errno = errno;
+ {
+ mkdir_errno = errno;
+ mkdir_mode = -1;
+ }
if (preserve_existing)
{
}
else
{
- mode_t mkdir_mode = (mkdir_errno == 0 ? mode : -1);
char const *subdir = (chdir_ok ? "." : dir + prefix_len);
if (dirchownmod (fd, subdir, mkdir_mode, owner, group,
mode, mode_bits)