/* makepath.c -- Ensure that a directory path exists.
- Copyright (C) 1990, 1997 Free Software Foundation, Inc.
+ Copyright (C) 1990, 1997, 1998 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
# endif
#endif
+#ifndef S_IWUSR
+# define S_IWUSR 0200
+#endif
+
+#ifndef S_IXUSR
+# define S_IXUSR 0100
+#endif
+
+#define WX_USR (S_IWUSR | S_IXUSR)
+
#ifdef __MSDOS__
typedef int uid_t;
typedef int gid_t;
Return 0 if ARGPATH exists as a directory with the proper
ownership and permissions when done, otherwise 1. */
-#if __STDC__
int
make_path (const char *argpath,
int mode,
gid_t group,
int preserve_existing,
const char *verbose_fmt_string)
-#else
-int
-make_path (argpath, mode, parent_mode, owner, group, preserve_existing,
- verbose_fmt_string)
- const char *argpath;
- int mode;
- int parent_mode;
- uid_t owner;
- gid_t group;
- int preserve_existing;
- const char *verbose_fmt_string;
-#endif
{
struct stat stats;
int retval = 0;
/* If leading directories shouldn't be writable or executable,
or should have set[ug]id or sticky bits set and we are setting
their owners, we need to fix their permissions after making them. */
- if (((parent_mode & 0300) != 0300)
- || (owner != (uid_t) -1 && group != (gid_t) -1
+ if (((parent_mode & WX_USR) != WX_USR)
+ || ((owner != (uid_t) -1 || group != (gid_t) -1)
&& (parent_mode & 07000) != 0))
{
tmp_mode = 0700;
while (1)
{
+ int newly_created_dir = 1;
+
/* slash points to the leftmost unprocessed component of dirpath. */
basename_dir = slash;
if (!do_chdir)
basename_dir = dirpath;
+ /* The mkdir and stat calls below appear to be reversed.
+ They are not. It is important to call mkdir first and then to
+ call stat (to distinguish the three cases) only if mkdir fails.
+ The alternative to this approach is to `stat' each directory,
+ then to call mkdir if it doesn't exist. But if some other process
+ were to create the directory between the stat & mkdir, the mkdir
+ would fail with EEXIST. */
+
*slash = '\0';
if (mkdir (basename_dir, tmp_mode))
{
else
{
/* DIRPATH already exists and is a directory. */
+ newly_created_dir = 0;
}
}
- if (verbose_fmt_string != NULL)
- error (0, 0, verbose_fmt_string, dirpath);
+ if (newly_created_dir)
+ {
+ if (verbose_fmt_string)
+ fprintf (stderr, verbose_fmt_string, dirpath);
- if (owner != (uid_t) -1 && group != (gid_t) -1
- && chown (basename_dir, owner, group)
+ if ((owner != (uid_t) -1 || group != (gid_t) -1)
+ && chown (basename_dir, owner, group)
#if defined(AFS) && defined (EPERM)
- && errno != EPERM
+ && errno != EPERM
#endif
- )
- {
- error (0, errno, "%s", dirpath);
- CLEANUP;
- return 1;
- }
+ )
+ {
+ error (0, errno, "%s", dirpath);
+ CLEANUP;
+ return 1;
+ }
- if (re_protect)
- {
- struct ptr_list *new = (struct ptr_list *)
- alloca (sizeof (struct ptr_list));
- new->dirname_end = slash;
- new->next = leading_dirs;
- leading_dirs = new;
+ if (re_protect)
+ {
+ struct ptr_list *new = (struct ptr_list *)
+ alloca (sizeof (struct ptr_list));
+ new->dirname_end = slash;
+ new->next = leading_dirs;
+ leading_dirs = new;
+ }
}
/* If we were able to save the initial working directory,
On System V, users can give away files with chown and then not
be able to chmod them. So don't give files away. */
- if (owner != (uid_t) -1 && group != (gid_t) -1
+ if ((owner != (uid_t) -1 || group != (gid_t) -1)
&& chown (dirpath, owner, group)
#ifdef AFS
&& errno != EPERM