Another missing mkdir() race pointed out by chuq. Factor out the mkdir code.

This commit is contained in:
christos 2005-09-16 16:48:18 +00:00
parent c4b850a8a6
commit b60b306ef2
4 changed files with 36 additions and 36 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: ar_subs.c,v 1.42 2005/05/22 17:41:50 christos Exp $ */
/* $NetBSD: ar_subs.c,v 1.43 2005/09/16 16:48:18 christos Exp $ */
/*-
* Copyright (c) 1992 Keith Muller.
@ -42,7 +42,7 @@
#if 0
static char sccsid[] = "@(#)ar_subs.c 8.2 (Berkeley) 4/18/94";
#else
__RCSID("$NetBSD: ar_subs.c,v 1.42 2005/05/22 17:41:50 christos Exp $");
__RCSID("$NetBSD: ar_subs.c,v 1.43 2005/09/16 16:48:18 christos Exp $");
#endif
#endif /* not lint */
@ -124,6 +124,29 @@ fdochroot(int fcwd)
}
#endif
/*
* mkdir(), but if we failed, check if someone else made it for us
* already and don't error out.
*/
int
domkdir(const char *fname, mode_t mode)
{
int error;
struct stat sb;
if ((error = mkdir(fname, mode)) != -1 || errno != EEXIST)
return error;
error = errno;
if (stat(fname, &sb) == 0 && S_ISDIR(sb.st_mode))
return 0;
errno = error;
return -1;
}
static int
path_check(ARCHD *arcn, int level)
{

View File

@ -1,4 +1,4 @@
/* $NetBSD: extern.h,v 1.48 2005/04/24 01:45:04 christos Exp $ */
/* $NetBSD: extern.h,v 1.49 2005/09/16 16:48:18 christos Exp $ */
/*-
* Copyright (c) 1992 Keith Muller.
@ -85,6 +85,7 @@ extern ARCHD archd;
int updatepath(void);
int dochdir(const char *);
int fdochdir(int);
int domkdir(const char *, mode_t);
void list(void);
void extract(void);
void append(void);

View File

@ -1,4 +1,4 @@
/* $NetBSD: file_subs.c,v 1.55 2005/09/13 20:09:55 christos Exp $ */
/* $NetBSD: file_subs.c,v 1.56 2005/09/16 16:48:18 christos Exp $ */
/*-
* Copyright (c) 1992 Keith Muller.
@ -42,7 +42,7 @@
#if 0
static char sccsid[] = "@(#)file_subs.c 8.1 (Berkeley) 5/31/93";
#else
__RCSID("$NetBSD: file_subs.c,v 1.55 2005/09/13 20:09:55 christos Exp $");
__RCSID("$NetBSD: file_subs.c,v 1.56 2005/09/16 16:48:18 christos Exp $");
#endif
#endif /* not lint */
@ -464,18 +464,7 @@ node_creat(ARCHD *arcn)
nm = target;
}
}
res = mkdir(nm, file_mode);
if (res == -1 && errno == EEXIST) {
/*
* Something's in the way.
* If it's a directory, say we're done.
*/
if (stat(nm, &sb) == 0 &&
S_ISDIR(sb.st_mode)) {
res = 0;
break;
}
}
res = domkdir(nm, file_mode);
badlink:
if (ign)
res = 0;
@ -730,7 +719,7 @@ chk_path(char *name, uid_t st_uid, gid_t st_gid)
* the path fails at this point, see if we can create the
* needed directory and continue on
*/
if (mkdir(name, S_IRWXU | S_IRWXG | S_IRWXO) < 0) {
if (domkdir(name, S_IRWXU | S_IRWXG | S_IRWXO) == -1) {
*spt = '/';
retval = -1;
break;

View File

@ -1,4 +1,4 @@
/* $NetBSD: options.c,v 1.91 2005/09/13 20:09:55 christos Exp $ */
/* $NetBSD: options.c,v 1.92 2005/09/16 16:48:18 christos Exp $ */
/*-
* Copyright (c) 1992 Keith Muller.
@ -42,7 +42,7 @@
#if 0
static char sccsid[] = "@(#)options.c 8.2 (Berkeley) 4/18/94";
#else
__RCSID("$NetBSD: options.c,v 1.91 2005/09/13 20:09:55 christos Exp $");
__RCSID("$NetBSD: options.c,v 1.92 2005/09/16 16:48:18 christos Exp $");
#endif
#endif /* not lint */
@ -1322,9 +1322,8 @@ int
mkpath(path)
char *path;
{
struct stat sb;
char *slash;
int done = 0, sverrno;
int done = 0;
slash = path;
@ -1335,20 +1334,8 @@ mkpath(path)
done = (*slash == '\0');
*slash = '\0';
if (stat(path, &sb) == -1) {
if ((sverrno = errno) != ENOENT)
goto out;
if (mkdir(path, 0777) == -1) {
sverrno = errno;
/* Check again, to avoid races */
if (stat(path, &sb) == -1
|| !S_ISDIR(sb.st_mode))
goto out;
}
} else if (!S_ISDIR(sb.st_mode)) {
sverrno = ENOTDIR;
if (domkdir(path, 0777) == -1)
goto out;
}
if (!done)
*slash = '/';
@ -1357,7 +1344,7 @@ mkpath(path)
return 0;
out:
/* Can't create or or not a directory */
syswarn(1, sverrno, "Cannot create directory `%s'", path);
syswarn(1, errno, "Cannot create directory `%s'", path);
return -1;
}