Fix several problems with mkdir:
1) Fix mkdir -p to exit with the proper exit status and issue an error message if it was unable to create all of the specified directories and they did not previously exist. POSIX says: The mkdir utility shall exit with one of the following values: 0 All the specified directories were created successfully or the -p option was specified and all the specified directories now exist. E.g. % mkdir -p /var/mkdir mkdir: /var/mkdir: Permission denied % touch /tmp/file % mkdir -p /tmp/file/dir mkdir: /tmp/file: Not a directory Previously the above examples would exit with a zero exit status and no error message. Something like the following run as a normal user will still not produce an error: % id uid=629(mpp) gid=629(mpp).... % mkdir -p /usr/local/etc % ls -ld /usr/local/etc drwxr-xr-x 4 bin bin 512 Dec 26 14:55 /usr/local/etc/ 2) Cleaned up the mode handling to be more efficient when multiple directories are being created. 3) Fixed a problem where directories could be created with the wrong mode if the the -p option was specified and the build() routine returned and error. It would leave the umask set incorrectly at this point. 4) Removed an unused variable. Closes PR# 2304.
This commit is contained in:
parent
72daaae383
commit
1a8d9bc1f7
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=24524
@ -30,7 +30,7 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: mkdir.c,v 1.8 1997/02/22 14:04:08 peter Exp $
|
||||
* $Id: mkdir.c,v 1.9 1997/03/28 15:24:25 imp Exp $
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
@ -53,7 +53,7 @@ static char const sccsid[] = "@(#)mkdir.c 8.2 (Berkeley) 1/25/94";
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
int build __P((char *));
|
||||
int build __P((char *, mode_t));
|
||||
void usage __P((void));
|
||||
|
||||
int
|
||||
@ -61,9 +61,9 @@ main(argc, argv)
|
||||
int argc;
|
||||
char *argv[];
|
||||
{
|
||||
int ch, exitval, oct, omode, pflag;
|
||||
int ch, exitval, omode, pflag;
|
||||
mode_t *set = (mode_t *)NULL;
|
||||
char *ep, *mode;
|
||||
char *mode;
|
||||
|
||||
omode = pflag = 0;
|
||||
mode = NULL;
|
||||
@ -87,53 +87,49 @@ main(argc, argv)
|
||||
|
||||
if (mode == NULL) {
|
||||
omode = S_IRWXU | S_IRWXG | S_IRWXO;
|
||||
oct = 1;
|
||||
} else if (*mode >= '0' && *mode <= '7') {
|
||||
omode = (int)strtol(mode, &ep, 8);
|
||||
if (omode < 0 || *ep)
|
||||
errx(1, "invalid file mode: %s", mode);
|
||||
oct = 1;
|
||||
} else {
|
||||
if ((set = setmode(mode)) == NULL)
|
||||
errx(1, "invalid file mode: %s", mode);
|
||||
oct = 0;
|
||||
omode = getmode(set, S_IRWXU | S_IRWXG | S_IRWXO);
|
||||
}
|
||||
|
||||
for (exitval = 0; *argv != NULL; ++argv) {
|
||||
if (pflag && build(*argv)) {
|
||||
exitval = 1;
|
||||
if (pflag) {
|
||||
if (build(*argv, omode))
|
||||
exitval = 1;
|
||||
continue;
|
||||
}
|
||||
if (mkdir(*argv, oct ?
|
||||
omode : getmode(set, S_IRWXU | S_IRWXG | S_IRWXO)) < 0) {
|
||||
if (!pflag) {
|
||||
warn("%s", *argv);
|
||||
exitval = 1;
|
||||
}
|
||||
if (mkdir(*argv, omode) < 0) {
|
||||
warn("%s", *argv);
|
||||
exitval = 1;
|
||||
}
|
||||
}
|
||||
exit(exitval);
|
||||
}
|
||||
|
||||
int
|
||||
build(path)
|
||||
build(path, omode)
|
||||
char *path;
|
||||
mode_t omode;
|
||||
{
|
||||
struct stat sb;
|
||||
mode_t numask, oumask;
|
||||
int first;
|
||||
int first, last, retval;
|
||||
char *p;
|
||||
|
||||
p = path;
|
||||
oumask = 0;
|
||||
retval = 0;
|
||||
if (p[0] == '/') /* Skip leading '/'. */
|
||||
++p;
|
||||
for (first = 1;; ++p) {
|
||||
if (p[0] == '\0' || (p[0] == '/' && p[1] == '\0'))
|
||||
break;
|
||||
if (p[0] != '/')
|
||||
for (first = 1, last = 0; !last ; ++p) {
|
||||
if (p[0] == '\0')
|
||||
last = 1;
|
||||
else if (p[0] != '/')
|
||||
continue;
|
||||
*p = '\0';
|
||||
if (p[1] == '\0')
|
||||
last = 1;
|
||||
if (first) {
|
||||
/*
|
||||
* POSIX 1003.2:
|
||||
@ -152,18 +148,31 @@ build(path)
|
||||
(void)umask(numask);
|
||||
first = 0;
|
||||
}
|
||||
if (last)
|
||||
(void)umask(oumask);
|
||||
if (stat(path, &sb)) {
|
||||
if (errno != ENOENT ||
|
||||
mkdir(path, S_IRWXU | S_IRWXG | S_IRWXO) < 0) {
|
||||
mkdir(path, last ? omode :
|
||||
S_IRWXU | S_IRWXG | S_IRWXO) < 0) {
|
||||
warn("%s", path);
|
||||
return (1);
|
||||
retval = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if ((sb.st_mode & S_IFMT) != S_IFDIR) {
|
||||
if (last)
|
||||
errno = EEXIST;
|
||||
else
|
||||
errno = ENOTDIR;
|
||||
warn("%s", path);
|
||||
retval = 1;
|
||||
break;
|
||||
}
|
||||
*p = '/';
|
||||
}
|
||||
if (!first)
|
||||
if (!first && !last)
|
||||
(void)umask(oumask);
|
||||
return (0);
|
||||
return (retval);
|
||||
}
|
||||
|
||||
void
|
||||
|
Loading…
Reference in New Issue
Block a user