Pass a writable flag to Main_SetObjdir to control writable check

For curdir and an explicit .OBJDIR target, we allow for
the directory to be read-only.
During InitObjdir we otherwise default to requiring objdir to be
writable - this can be controlled by env variable
MAKE_OBJDIR_CHECK_WRITABLE

Add unit-tests/objdir-writable

Reviewed by: christos rillig
This commit is contained in:
sjg 2020-11-12 23:35:21 +00:00
parent a3a0dc2a39
commit aa03bcf7d6
7 changed files with 74 additions and 23 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: main.c,v 1.455 2020/11/08 23:38:02 rillig Exp $ */
/* $NetBSD: main.c,v 1.456 2020/11/12 23:35:21 sjg Exp $ */
/*
* Copyright (c) 1988, 1989, 1990, 1993
@ -109,7 +109,7 @@
#include "trace.h"
/* "@(#)main.c 8.3 (Berkeley) 3/19/94" */
MAKE_RCSID("$NetBSD: main.c,v 1.455 2020/11/08 23:38:02 rillig Exp $");
MAKE_RCSID("$NetBSD: main.c,v 1.456 2020/11/12 23:35:21 sjg Exp $");
#if defined(MAKE_NATIVE) && !defined(lint)
__COPYRIGHT("@(#) Copyright (c) 1988, 1989, 1990, 1993 "
"The Regents of the University of California. "
@ -710,7 +710,7 @@ Main_ParseArgLine(const char *line)
}
Boolean
Main_SetObjdir(const char *fmt, ...)
Main_SetObjdir(Boolean writable, const char *fmt, ...)
{
struct stat sb;
char *path;
@ -730,8 +730,7 @@ Main_SetObjdir(const char *fmt, ...)
/* look for the directory and try to chdir there */
if (stat(path, &sb) == 0 && S_ISDIR(sb.st_mode)) {
/* if not .CURDIR it must be writable */
if ((strcmp(path, curdir) != 0 && access(path, W_OK) != 0) ||
if ((writable && access(path, W_OK) != 0) ||
(chdir(path) != 0)) {
(void)fprintf(stderr, "make warning: %s: %s.\n",
path, strerror(errno));
@ -751,7 +750,7 @@ Main_SetObjdir(const char *fmt, ...)
}
static Boolean
Main_SetVarObjdir(const char *var, const char *suffix)
Main_SetVarObjdir(Boolean writable, const char *var, const char *suffix)
{
void *path_freeIt;
const char *path = Var_Value(var, VAR_CMDLINE, &path_freeIt);
@ -772,7 +771,7 @@ Main_SetVarObjdir(const char *var, const char *suffix)
xpath = xpath_freeIt;
}
(void)Main_SetObjdir("%s%s", xpath, suffix);
(void)Main_SetObjdir(writable, "%s%s", xpath, suffix);
bmake_free(xpath_freeIt);
bmake_free(path_freeIt);
@ -1093,15 +1092,18 @@ ignore_pwd:
static void
InitObjdir(const char *machine, const char *machine_arch)
{
Dir_InitDir(curdir);
(void)Main_SetObjdir("%s", curdir);
Boolean writable;
if (!Main_SetVarObjdir("MAKEOBJDIRPREFIX", curdir) &&
!Main_SetVarObjdir("MAKEOBJDIR", "") &&
!Main_SetObjdir("%s.%s-%s", _PATH_OBJDIR, machine, machine_arch) &&
!Main_SetObjdir("%s.%s", _PATH_OBJDIR, machine) &&
!Main_SetObjdir("%s", _PATH_OBJDIR))
(void)Main_SetObjdir("%s%s", _PATH_OBJDIRPREFIX, curdir);
Dir_InitDir(curdir);
writable = GetBooleanVar("MAKE_OBJDIR_CHECK_WRITABLE", TRUE);
(void)Main_SetObjdir(FALSE, "%s", curdir);
if (!Main_SetVarObjdir(writable, "MAKEOBJDIRPREFIX", curdir) &&
!Main_SetVarObjdir(writable, "MAKEOBJDIR", "") &&
!Main_SetObjdir(writable, "%s.%s-%s", _PATH_OBJDIR, machine, machine_arch) &&
!Main_SetObjdir(writable, "%s.%s", _PATH_OBJDIR, machine) &&
!Main_SetObjdir(writable, "%s", _PATH_OBJDIR))
(void)Main_SetObjdir(writable, "%s%s", _PATH_OBJDIRPREFIX, curdir);
}
/* get rid of resource limit on file descriptors */

View File

@ -1,4 +1,4 @@
.\" $NetBSD: make.1,v 1.290 2020/11/01 20:24:45 rillig Exp $
.\" $NetBSD: make.1,v 1.291 2020/11/12 23:35:21 sjg Exp $
.\"
.\" Copyright (c) 1990, 1993
.\" The Regents of the University of California. All rights reserved.
@ -29,7 +29,7 @@
.\"
.\" from: @(#)make.1 8.4 (Berkeley) 3/19/94
.\"
.Dd November 1, 2020
.Dd November 12, 2020
.Dt MAKE 1
.Os
.Sh NAME
@ -1089,6 +1089,15 @@ to the specified directory if it exists, and set
and
.Ql Ev PWD
to that directory before executing any targets.
.Pp
Except in the case of an explicit
.Ql Ic .OBJDIR
target,
.Nm
will check that the specified directory is writable and ignore it if not.
This check can be skipped by setting the environment variable
.Ql Ev MAKE_OBJDIR_CHECK_WRITABLE
to "no".
.
.It Va .PARSEDIR
A path to the directory of the current

View File

@ -1,4 +1,4 @@
/* $NetBSD: make.h,v 1.205 2020/11/10 00:32:12 rillig Exp $ */
/* $NetBSD: make.h,v 1.206 2020/11/12 23:35:21 sjg Exp $ */
/*
* Copyright (c) 1988, 1989, 1990, 1993
@ -652,7 +652,7 @@ Boolean Make_Run(GNodeList *);
Boolean shouldDieQuietly(GNode *, int);
void PrintOnError(GNode *, const char *);
void Main_ExportMAKEFLAGS(Boolean);
Boolean Main_SetObjdir(const char *, ...) MAKE_ATTR_PRINTFLIKE(1, 2);
Boolean Main_SetObjdir(Boolean, const char *, ...) MAKE_ATTR_PRINTFLIKE(2, 3);
int mkTempFile(const char *, char **);
int str2Lst_Append(StringList *, char *, const char *);
void GNode_FprintDetails(FILE *, const char *, const GNode *, const char *);

View File

@ -1,4 +1,4 @@
/* $NetBSD: parse.c,v 1.437 2020/11/08 23:38:02 rillig Exp $ */
/* $NetBSD: parse.c,v 1.438 2020/11/12 23:35:21 sjg Exp $ */
/*
* Copyright (c) 1988, 1989, 1990, 1993
@ -117,7 +117,7 @@
#include "pathnames.h"
/* "@(#)parse.c 8.3 (Berkeley) 3/19/94" */
MAKE_RCSID("$NetBSD: parse.c,v 1.437 2020/11/08 23:38:02 rillig Exp $");
MAKE_RCSID("$NetBSD: parse.c,v 1.438 2020/11/12 23:35:21 sjg Exp $");
/* types and constants */
@ -1429,7 +1429,7 @@ ParseDoDependencySourceSpecial(ParseSpecial specType, char *word,
Suff_SetNull(word);
break;
case SP_OBJDIR:
Main_SetObjdir("%s", word);
Main_SetObjdir(FALSE, "%s", word);
break;
default:
break;

View File

@ -1,4 +1,4 @@
# $NetBSD: Makefile,v 1.197 2020/11/10 22:23:37 rillig Exp $
# $NetBSD: Makefile,v 1.198 2020/11/12 23:35:21 sjg Exp $
#
# Unit tests for make(1)
#
@ -188,6 +188,7 @@ TESTS+= modmatch
TESTS+= modmisc
TESTS+= modts
TESTS+= modword
TESTS+= objdir-writable
TESTS+= opt
TESTS+= opt-backwards
TESTS+= opt-chdir
@ -379,10 +380,16 @@ TESTS+= varparse-mod
TESTS+= varparse-undef-partial
TESTS+= varquote
.if ${.OBJDIR} != ${.CURDIR}
RO_OBJDIR:= ${.OBJDIR}/roobj
.else
RO_OBJDIR:= ${TMPDIR:U/tmp}/roobj
.endif
# Additional environment variables for some of the tests.
# The base environment is -i PATH="$PATH".
ENV.depsrc-optional+= TZ=UTC
ENV.envfirst= FROM_ENV=value-from-env
ENV.objdir-writable+= RO_OBJDIR=${RO_OBJDIR}
ENV.varmisc= FROM_ENV=env
ENV.varmisc+= FROM_ENV_BEFORE=env
ENV.varmisc+= FROM_ENV_AFTER=env
@ -409,6 +416,7 @@ SED_CMDS.job-output-long-lines= \
${:D marker should always be at the beginning of the line. } \
-e '/^aa*--- job-b ---$$/d' \
-e '/^bb*--- job-a ---$$/d'
SED_CMDS.objdir-writable= -e 's,${RO_OBJDIR},OBJDIR/roobj,g'
SED_CMDS.opt-debug-graph1= \
-e 's,${.CURDIR},CURDIR,'
SED_CMDS.opt-debug-graph1+= \

View File

@ -0,0 +1,5 @@
make warning: OBJDIR/roobj: Permission denied.
/tmp
OBJDIR/roobj
OBJDIR/roobj
exit status 0

View File

@ -0,0 +1,27 @@
# $NetBSD: objdir-writable.mk,v 1.1 2020/11/12 23:35:21 sjg Exp $
# test checking for writable objdir
RO_OBJDIR?= ${TMPDIR:U/tmp}/roobj
.if make(do-objdir)
# this should succeed
.OBJDIR: ${RO_OBJDIR}
do-objdir:
.else
all: no-objdir ro-objdir explicit-objdir
# make it now
x!= echo; mkdir -p ${RO_OBJDIR}; chmod 555 ${RO_OBJDIR}
no-objdir:
@MAKEOBJDIR=${RO_OBJDIR} ${.MAKE} -r -f /dev/null -C /tmp -V .OBJDIR
ro-objdir:
@MAKEOBJDIR=${RO_OBJDIR} ${.MAKE} -r -f /dev/null -C /tmp -V .OBJDIR MAKE_OBJDIR_CHECK_WRITABLE=no
explicit-objdir:
@${.MAKE} -r -f ${MAKEFILE} -C /tmp do-objdir -V .OBJDIR
.endif