Make build hermetically sealed again

It turned out that Landlock Make hasn't been applying sandboxing for a
while, due to a mistyped if statement for `$(USE_SYSTEM_TOOLCHAIN)` it
should have had the opposite meaning. Regressions in the build configs
have been fixed. The rmrf() function works better now. The rm.com tool
works according to POSIX with the exception of supporting prompts.
This commit is contained in:
Justine Tunney 2023-07-08 06:58:21 -07:00
parent 0c43c98de1
commit a75175fe94
No known key found for this signature in database
GPG key ID: BE714B4575D6E328
14 changed files with 202 additions and 93 deletions

View file

@ -86,7 +86,7 @@ o/$(MODE): \
o/$(MODE)/examples \
o/$(MODE)/third_party
ifneq ($(USE_SYSTEM_TOOLCHAIN),)
ifeq ($(USE_SYSTEM_TOOLCHAIN),)
.STRICT = 1
endif
@ -100,6 +100,7 @@ endif
r:build/portcosmo.h \
/proc/stat \
rw:/dev/null \
rw:/dev/full \
w:o/stack.log \
/etc/hosts \
~/.runit.psk \
@ -148,13 +149,13 @@ include libc/log/log.mk # │
include third_party/getopt/getopt.mk # │
include third_party/bzip2/bzip2.mk # │
include dsp/core/core.mk # │
include third_party/musl/musl.mk # │
include libc/x/x.mk # │
include third_party/stb/stb.mk # │
include dsp/scale/scale.mk # │
include dsp/mpeg/mpeg.mk # │
include dsp/dsp.mk # │
include third_party/zlib/gz/gz.mk # │
include third_party/musl/musl.mk # │
include third_party/intel/intel.mk # │
include third_party/aarch64/aarch64.mk # │
include libc/libc.mk #─┘
@ -436,7 +437,7 @@ aarch64:
$(MAKE) m=aarch64
clean:
rm -rf o
$(RM) -r o
# UNSPECIFIED PREREQUISITES TUTORIAL
#

View file

@ -129,6 +129,7 @@ o/$(MODE)/ape/ape-no-modify-self.o: \
ape/ape.internal.h \
libc/dce.h \
libc/elf/def.h \
libc/thread/tls.h \
libc/intrin/asancodes.h \
libc/macho.internal.h \
libc/macros.internal.h \
@ -158,6 +159,7 @@ o/$(MODE)/ape/ape-copy-self.o: \
ape/ape.internal.h \
libc/dce.h \
libc/elf/def.h \
libc/thread/tls.h \
libc/intrin/asancodes.h \
libc/macho.internal.h \
libc/macros.internal.h \

Binary file not shown.

View file

@ -18,6 +18,7 @@
*/
#include "libc/calls/calls.h"
#include "libc/errno.h"
#include "libc/sysv/consts/at.h"
/**
* Deletes "file" or empty directory associtaed with name.
@ -26,5 +27,9 @@
* @see unlink() and rmdir() which this abstracts
*/
int remove(const char *name) {
return unlink(name) != -1 || (errno == EISDIR && rmdir(name) != -1) ? 0 : -1;
int e = errno;
if (!unlinkat(AT_FDCWD, name, 0)) return 0;
if (errno != EISDIR) return -1;
errno = e;
return unlinkat(AT_FDCWD, name, AT_REMOVEDIR);
}

View file

@ -85,9 +85,9 @@ o/$(MODE)/libc/nexgen32e/gclongjmp.o: libc/nexgen32e/gclongjmp.S
@$(COMPILE) -AOBJECTIFY.S $(OBJECTIFY.S) $(OUTPUT_OPTION) -c $<
o/$(MODE)/libc/nexgen32e/checkstackalign.o: libc/nexgen32e/checkstackalign.S
@$(COMPILE) -AOBJECTIFY.S $(OBJECTIFY.S) $(OUTPUT_OPTION) -c $<
o/$(MODE)/libc/nexgen32e/blink_xnu_aarch64.o: libc/nexgen32e/blink_xnu_aarch64.S
o/$(MODE)/libc/nexgen32e/blink_xnu_aarch64.o: libc/nexgen32e/blink_xnu_aarch64.S ape/blink-xnu-aarch64.gz
@$(COMPILE) -AOBJECTIFY.S $(OBJECTIFY.S) $(OUTPUT_OPTION) -c $<
o/$(MODE)/libc/nexgen32e/blink_linux_aarch64.o: libc/nexgen32e/blink_linux_aarch64.S
o/$(MODE)/libc/nexgen32e/blink_linux_aarch64.o: libc/nexgen32e/blink_linux_aarch64.S ape/blink-linux-aarch64.gz
@$(COMPILE) -AOBJECTIFY.S $(OBJECTIFY.S) $(OUTPUT_OPTION) -c $<
LIBC_NEXGEN32E_LIBS = $(foreach x,$(LIBC_NEXGEN32E_ARTIFACTS),$($(x)))

View file

@ -16,66 +16,38 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/assert.h"
#include "libc/calls/calls.h"
#include "libc/calls/struct/dirent.h"
#include "libc/calls/struct/stat.h"
#include "libc/errno.h"
#include "libc/mem/mem.h"
#include "libc/runtime/runtime.h"
#include "libc/stdio/stdio.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/dt.h"
#include "libc/sysv/consts/s.h"
#include "libc/sysv/errfuns.h"
#include "libc/x/x.h"
#include "third_party/musl/ftw.h"
static int rmrfdir(const char *dirpath) {
static int rmrf_callback(const char *fpath, //
const struct stat *st, //
int typeflag, //
struct FTW *ftwbuf) { //
int rc;
DIR *d;
char *path;
struct dirent *e;
if (!(d = opendir(dirpath))) return -1;
while ((e = readdir(d))) {
if (!strcmp(e->d_name, ".")) continue;
if (!strcmp(e->d_name, "..")) continue;
_npassert(!strchr(e->d_name, '/'));
path = xjoinpaths(dirpath, e->d_name);
if (e->d_type == DT_DIR) {
rc = rmrfdir(path);
} else {
rc = unlink(path);
}
free(path);
if (rc == -1) {
closedir(d);
return -1;
if (typeflag == FTW_DNR) {
if (!(rc = chmod(fpath, 0700))) {
return nftw(fpath, rmrf_callback, 128 - ftwbuf->level,
FTW_PHYS | FTW_DEPTH);
}
} else if (typeflag == FTW_DP) {
rc = rmdir(fpath);
} else {
rc = unlink(fpath);
}
if (rc == -1 && errno == ENOENT) {
rc = 0;
}
rc = closedir(d);
rc |= rmdir(dirpath);
return rc;
}
/**
* Recursively removes file or directory.
*
* @return 0 on success, or -1 w/ errno
*/
int rmrf(const char *path) {
int e;
struct stat st;
e = errno;
if (stat(path, &st) == -1) {
if (errno == ENOENT) {
errno = e;
return 0;
} else {
return -1;
}
}
if (!S_ISDIR(st.st_mode)) {
return unlink(path);
} else {
return rmrfdir(path);
}
if (path[0] == '/' && !path[1]) return enotsup();
return nftw(path, rmrf_callback, 128, FTW_PHYS | FTW_DEPTH);
}

View file

@ -35,6 +35,7 @@ LIBC_X_A_DIRECTDEPS = \
LIBC_STR \
LIBC_SYSV \
THIRD_PARTY_GDTOA \
THIRD_PARTY_MUSL \
THIRD_PARTY_ZLIB
LIBC_X_A_DEPS := \

View file

@ -27,6 +27,8 @@
#include "libc/str/str.h"
#include "libc/testlib/testlib.h"
STATIC_YOINK("realloc");
TEST(grow, testNull_hasAllocatingBehavior) {
void *p = NULL;
size_t capacity = 0;

View file

@ -101,6 +101,7 @@ TEST(pthread_setname_np, GetNameOfOtherThread) {
while (!atomic_load(&sync1)) pthread_yield();
errno_t e = pthread_getname_np(id, me, sizeof(me));
if (IsLinux() && e == ENOENT) return; // bah old kernel
if (IsLinux() && e == EACCES) return; // meh landlock
ASSERT_EQ(0, e);
EXPECT_STREQ("justine", me);
ASSERT_EQ(0, pthread_setname_np(id, "tunney"));

View file

@ -31,19 +31,23 @@ asm(".ident\t\"\\n\\n\
Musl libc (MIT License)\\n\
Copyright 2005-2014 Rich Felker, et. al.\"");
asm(".include \"libc/disclaimer.inc\"");
/* clang-format off */
// clang-format off
/**
* Walks file tree.
*
* @return 0 on success, -1 on error, or non-zero `fn` result
* @see examples/walk.c for example
* @see nftw()
*/
int ftw(const char *path, int (*fn)(const char *, const struct stat *, int), int fd_limit)
int ftw(const char *dirpath,
int fn(const char *fpath,
const struct stat *st,
int typeflag),
int fd_limit)
{
/* The following cast assumes that calling a function with one
* argument more than it needs behaves as expected. This is
* actually undefined, but works on all real-world machines. */
return nftw(path, (int (*)())fn, fd_limit, FTW_PHYS);
return nftw(dirpath, (int (*)())fn, fd_limit, FTW_PHYS);
}

View file

@ -4,21 +4,79 @@
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
#define FTW_F 1 /* file */
#define FTW_D 2 /* directory */
#define FTW_DNR 3 /* directory that cannot be read */
#define FTW_NS 4 /* not a symbolic link and stat failed */
#define FTW_SL 5 /* symbolic link */
#define FTW_DP 6 /* directory and FTW_DEPTH was specified */
#define FTW_SLN 7 /* symbolic link pointing to nonexistent file */
/**
* Type for file.
*/
#define FTW_F 1
#define FTW_PHYS 1
/**
* Type for directory.
*/
#define FTW_D 2
/**
* Type for directory that cannot be read.
*/
#define FTW_DNR 3
/**
* Type for stat() failed and not a symbolic link.
*/
#define FTW_NS 4
/**
* Type for symbolic link when `FTW_PHYS` is in flags.
*/
#define FTW_SL 5
/**
* Directory and `FTW_DEPTH` in flags.
*/
#define FTW_DP 6
/**
* Type for broken symbolic link when `FTW_PHYS` is not in flags.
*/
#define FTW_SLN 7
/**
* Flag to prevent following symbolic links (recommended).
* @see nftw() flags
*/
#define FTW_PHYS 1
/**
* Flag to prevent crossing mount points.
* @see nftw() flags
*/
#define FTW_MOUNT 2
/**
* Unsupported.
* @see nftw() flags
*/
#define FTW_CHDIR 4
/**
* Flag for post-order traversal.
*
* 1. Will use `FTW_DP` instead of `FTW_D` as type.
* 2. Directory callback happens *after* rather than before.
*
* @see nftw() flags
*/
#define FTW_DEPTH 8
struct FTW {
/**
* Byte offset of basename component in `fpath` passed to callback.
*/
int base;
/**
* Depth relative to `dirpath` whose level is zero.
*/
int level;
};

View file

@ -35,17 +35,13 @@
#include "libc/thread/thread.h"
#include "third_party/musl/ftw.h"
#define PATH_MAXIMUS 4096
asm(".ident\t\"\\n\\n\
Musl libc (MIT License)\\n\
Copyright 2005-2014 Rich Felker, et. al.\"");
asm(".include \"libc/disclaimer.inc\"");
/* no reason to impose windows limit
small enough to fit in stack frame
should be changed to use realloc */
#define PATH_MAX2 2048
/* clang-format off */
// clang-format off
struct history
{
@ -56,7 +52,11 @@ struct history
int base;
};
static int do_nftw(char *path, int (*fn)(const char *, const struct stat *, int, struct FTW *), int fd_limit, int flags, struct history *h)
static int do_nftw(char *path,
int fn(const char *, const struct stat *, int, struct FTW *),
int fd_limit,
int flags,
struct history *h)
{
size_t l = strlen(path), j = l && path[l-1]=='/' ? l-1 : l;
struct stat st;
@ -128,7 +128,7 @@ static int do_nftw(char *path, int (*fn)(const char *, const struct stat *, int,
&& (!de->d_name[1]
|| (de->d_name[1]=='.'
&& !de->d_name[2]))) continue;
if (strlen(de->d_name) >= PATH_MAX2-l) {
if (strlen(de->d_name) >= PATH_MAXIMUS-l) {
errno = ENAMETOOLONG;
closedir(d);
return -1;
@ -157,25 +157,33 @@ static int do_nftw(char *path, int (*fn)(const char *, const struct stat *, int,
/**
* Walks file tree.
*
* @return 0 on success, -1 on error, or non-zero `fn` result
* @see examples/walk.c for example
*/
int nftw(const char *path, int (*fn)(const char *, const struct stat *, int, struct FTW *), int fd_limit, int flags)
int nftw(const char *dirpath,
int fn(const char *fpath,
const struct stat *st,
int typeflag,
struct FTW *ftwbuf),
int fd_limit,
int flags)
{
int r, cs;
size_t l;
char pathbuf[PATH_MAX2+1];
char pathbuf[PATH_MAXIMUS+1];
if (fd_limit <= 0) return 0;
l = strlen(path);
if (l > PATH_MAX2) {
l = strlen(dirpath);
if (l > PATH_MAXIMUS) {
errno = ENAMETOOLONG;
return -1;
}
memcpy(pathbuf, path, l+1);
memcpy(pathbuf, dirpath, l+1);
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cs);
r = do_nftw(pathbuf, fn, fd_limit, flags, NULL);
pthread_setcancelstate(cs, 0);
return r;
}

View file

@ -17,13 +17,17 @@
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/calls/calls.h"
#include "libc/calls/struct/stat.h"
#include "libc/errno.h"
#include "libc/fmt/magnumstrs.internal.h"
#include "libc/intrin/kprintf.h"
#include "libc/runtime/runtime.h"
#include "libc/stdio/stdio.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/ok.h"
#include "libc/sysv/consts/s.h"
#include "third_party/getopt/getopt.internal.h"
#include "third_party/musl/ftw.h"
#define USAGE \
" FILE...\n\
@ -34,11 +38,15 @@ SYNOPSIS\n\
\n\
FLAGS\n\
\n\
-h help\n\
-f force\n\
-h help\n\
-f force\n\
-f or -R recursive\n\
-d remove empty dirs\n\
\n"
static bool force;
static bool recursive;
static bool doemptydirs;
static const char *prog;
static wontreturn void PrintUsage(int rc, int fd) {
@ -48,11 +56,18 @@ static wontreturn void PrintUsage(int rc, int fd) {
static void GetOpts(int argc, char *argv[]) {
int opt;
while ((opt = getopt(argc, argv, "hf")) != -1) {
while ((opt = getopt(argc, argv, "rRdhf")) != -1) {
switch (opt) {
case 'f':
force = true;
break;
case 'd':
doemptydirs = true;
break;
case 'r':
case 'R':
recursive = true;
break;
case 'h':
PrintUsage(0, 1);
default:
@ -61,12 +76,56 @@ static void GetOpts(int argc, char *argv[]) {
}
}
static void Remove(const char *path) {
if (!force && access(path, W_OK) == -1) {
perror(path);
static int OnFile(const char *fpath, const struct stat *st, int typeflag,
struct FTW *ftwbuf) {
int rc;
if (!force && typeflag == FTW_DNR) {
rc = -1;
} else if (!force && !S_ISLNK(st->st_mode) && access(fpath, W_OK)) {
rc = -1;
} else if (typeflag == FTW_DNR) {
if (!(rc = chmod(fpath, 0700))) {
rc = nftw(fpath, OnFile, 128 - ftwbuf->level, FTW_PHYS | FTW_DEPTH);
}
} else if (typeflag == FTW_DP) {
rc = rmdir(fpath);
} else {
rc = unlink(fpath);
}
if (rc == -1) {
if (force && errno == ENOENT) return 0;
perror(fpath);
exit(1);
}
if (unlink(path) == -1) {
return 0;
}
static void Remove(const char *path) {
int rc;
struct stat st;
if (path[0] == '/' && !path[1]) {
tinyprint(2, prog, ": add a dot if you want\n", NULL);
exit(1);
}
if (recursive) {
rc = nftw(path, OnFile, 128, FTW_PHYS | FTW_DEPTH);
} else {
if (lstat(path, &st)) {
if (force && errno == ENOENT) return;
perror(path);
exit(1);
}
if (!force && !S_ISLNK(st.st_mode) && access(path, W_OK)) {
perror(path);
exit(1);
}
if (S_ISDIR(st.st_mode) && doemptydirs) {
rc = rmdir(path);
} else {
rc = unlink(path);
}
}
if (rc == -1) {
if (force && errno == ENOENT) return;
perror(path);
exit(1);
@ -75,17 +134,13 @@ static void Remove(const char *path) {
int main(int argc, char *argv[]) {
int i;
prog = argv[0];
if (!prog) prog = "rm";
if (argc < 2) {
GetOpts(argc, argv);
if (optind == argc) {
tinyprint(2, prog, ": missing operand\n", NULL);
exit(1);
}
GetOpts(argc, argv);
for (i = optind; i < argc; ++i) {
Remove(argv[i]);
}

View file

@ -71,7 +71,7 @@ ORIGINAL="$0 $*"
PLATFORM="-D__COSMOPOLITAN__"
PREDEF="-include libc/integral/normalize.inc"
CCFLAGS="-fdata-sections -ffunction-sections -fno-pie -mno-tls-direct-seg-refs -mno-red-zone -fportcosmo"
CXXFLAGS="-fno-exceptions -fuse-cxa-atexit -fno-threadsafe-statics"
CXXFLAGS="-fno-rtti -fno-exceptions -fuse-cxa-atexit -fno-threadsafe-statics"
CPPFLAGS="-nostdinc -iquote $COSMO -isystem $COSMOS/include -isystem $COSMO/libc/isystem"
LDFLAGS="-static -no-pie -nostdlib -fuse-ld=bfd -Wl,-melf_x86_64"
APEFLAGS="-L$COSMOS/lib -Wl,--gc-sections -Wl,-T,$COSMO/o/$MODE/ape/public/ape.lds $COSMO/o/$MODE/ape/ape-no-modify-self.o $COSMO/o/$MODE/libc/crt/crt.o"