Fix small matters and improve sysconf()

- Fix mkdeps.com out of memory error
- Remove static memory from __get_cpu_count()
- Add support for passing hyphen to cat in cocmd
- Change more ZipOS errors from ENOTSUP to EROFS
- Specify mem_unit in sysinfo() output on BSD OSes
This commit is contained in:
Justine Tunney 2023-08-17 00:25:01 -07:00
parent eebc24b9cd
commit 3a9cac4892
No known key found for this signature in database
GPG key ID: BE714B4575D6E328
55 changed files with 411 additions and 262 deletions

View file

@ -24,6 +24,7 @@
#define _POSIX_SEMAPHORES _POSIX_VERSION
#define _POSIX_SHARED_MEMORY_OBJECTS _POSIX_VERSION
#define _POSIX_MEMLOCK_RANGE _POSIX_VERSION
#define _POSIX_SPAWN _POSIX_VERSION
#define EOF -1 /* end of file */
#define WEOF -1u /* end of file (multibyte) */

View file

@ -29,6 +29,6 @@
* @see chmod()
*/
int fchmod(int fd, uint32_t mode) {
/* TODO(jart): Windows */
// TODO(jart): Windows
return sys_fchmod(fd, mode);
}

View file

@ -24,8 +24,8 @@
#include "libc/intrin/describeflags.internal.h"
#include "libc/intrin/strace.internal.h"
#include "libc/intrin/weaken.h"
#include "libc/sysv/errfuns.h"
#include "libc/runtime/zipos.internal.h"
#include "libc/sysv/errfuns.h"
int sys_fchmodat_linux(int, const char *, unsigned, int);
@ -39,7 +39,7 @@ int sys_fchmodat_linux(int, const char *, unsigned, int);
* @param path must exist
* @param mode contains octal flags (base 8)
* @param flags can have `AT_SYMLINK_NOFOLLOW`
* @raise ENOTSUP if `dirfd` or `path` use zip file system
* @raise EROFS if `dirfd` or `path` use zip file system
* @errors ENOENT, ENOTDIR, ENOSYS
* @asyncsignalsafe
* @see fchmod()
@ -50,7 +50,7 @@ int fchmodat(int dirfd, const char *path, uint32_t mode, int flags) {
rc = efault();
} else if (_weaken(__zipos_notat) &&
(rc = __zipos_notat(dirfd, path)) == -1) {
rc = enotsup();
rc = erofs();
} else if (!IsWindows()) {
if (IsLinux() && flags) {
rc = sys_fchmodat_linux(dirfd, path, mode, flags);

View file

@ -23,8 +23,8 @@
#include "libc/intrin/describeflags.internal.h"
#include "libc/intrin/strace.internal.h"
#include "libc/intrin/weaken.h"
#include "libc/sysv/errfuns.h"
#include "libc/runtime/zipos.internal.h"
#include "libc/sysv/errfuns.h"
/**
* Changes owner and/or group of path.
@ -34,7 +34,7 @@
* @param gid is group id, or -1 to not change
* @param flags can have AT_SYMLINK_NOFOLLOW, etc.
* @return 0 on success, or -1 w/ errno
* @raise ENOTSUP if `dirfd` or `path` use zip file system
* @raise EROFS if `dirfd` or `path` use zip file system
* @see chown(), lchown() for shorthand notation
* @see /etc/passwd for user ids
* @see /etc/group for group ids
@ -47,7 +47,7 @@ int fchownat(int dirfd, const char *path, uint32_t uid, uint32_t gid,
rc = efault();
} else if (_weaken(__zipos_notat) &&
(rc = __zipos_notat(dirfd, path)) == -1) {
rc = enotsup();
rc = erofs();
} else {
rc = sys_fchownat(dirfd, path, uid, gid, flags);
}

View file

@ -53,10 +53,10 @@
* @raise ECANCELED if thread was cancelled in masked mode
* @raise EIO if a low-level i/o error happened
* @raise EFBIG or EINVAL if `length` is too huge
* @raise ENOTSUP if `fd` is a zip file descriptor
* @raise EBADF if `fd` isn't an open file descriptor
* @raise EINVAL if `fd` is a non-file, e.g. pipe, socket
* @raise EINVAL if `fd` wasn't opened in a writeable mode
* @raise EROFS if `fd` is on a read-only filesystem (e.g. zipos)
* @raise ENOSYS on bare metal
* @cancellationpoint
* @asyncsignalsafe
@ -69,7 +69,7 @@ int ftruncate(int fd, int64_t length) {
if (fd < 0) {
rc = ebadf();
} else if (__isfdkind(fd, kFdZip)) {
rc = enotsup();
rc = erofs();
} else if (IsMetal()) {
rc = enosys();
} else if (!IsWindows()) {

View file

@ -32,10 +32,10 @@
* @param fd is file descriptor of file whose timestamps will change
* @param ts is {access, modified} timestamps, or null for current time
* @return 0 on success, or -1 w/ errno
* @raise ENOTSUP if `fd` is on the zip filesystem
* @raise EINVAL if `flags` had an unrecognized value
* @raise EPERM if pledge() is in play without `fattr` promise
* @raise EINVAL if `ts` specifies a nanosecond value that's out of range
* @raise EROFS if `fd` is a zip file or on a read-only filesystem
* @raise EBADF if `fd` isn't an open file descriptor
* @raise EFAULT if `ts` memory was invalid
* @raise ENOSYS on RHEL5 or bare metal

View file

@ -30,8 +30,8 @@
*
* @param ts is atime/mtime, or null for current time
* @return 0 on success, or -1 w/ errno
* @raise ENOTSUP if `fd` is on zip filesystem
* @raise EBADF if `fd` isn't an open file descriptor
* @raise EROFS if `fd` is on zip or read-only filesystem
* @raise EPERM if pledge() is in play without `fattr` promise
* @raise EINVAL if `tv` specifies a microsecond value that's out of range
* @raise ENOSYS on RHEL5 or bare metal

View file

@ -19,13 +19,9 @@
#include "libc/calls/calls.h"
#include "libc/calls/sched-sysv.internal.h"
#include "libc/calls/struct/cpuset.h"
#include "libc/calls/weirdtypes.h"
#include "libc/calls/syscall_support-nt.internal.h"
#include "libc/dce.h"
#include "libc/macros.internal.h"
#include "libc/nt/accounting.h"
#include "libc/nt/dll.h"
#include "libc/nt/struct/systeminfo.h"
#include "libc/nt/systeminfo.h"
#include "libc/runtime/runtime.h"
#define CTL_HW 6
@ -34,16 +30,16 @@
#define HW_NCPUONLINE_NETBSD 16
#define ALL_PROCESSOR_GROUPS 0xffff
static unsigned _getcpucount_linux(void) {
cpu_set_t s = {0};
if (sys_sched_getaffinity(0, sizeof(s), &s) != -1) {
return CPU_COUNT(&s);
static int __get_cpu_count_linux(void) {
cpu_set_t cs = {0};
if (sys_sched_getaffinity(0, sizeof(cs), &cs) != -1) {
return CPU_COUNT(&cs);
} else {
return 0;
return -1;
}
}
static unsigned _getcpucount_bsd(void) {
static int __get_cpu_count_bsd(void) {
size_t n;
int c, cmd[2];
n = sizeof(c);
@ -58,29 +54,19 @@ static unsigned _getcpucount_bsd(void) {
if (!sys_sysctl(cmd, 2, &c, &n, 0, 0)) {
return c;
} else {
return 0;
return -1;
}
}
static unsigned _getcpucount_impl(void) {
if (!IsWindows()) {
if (!IsBsd()) {
return _getcpucount_linux();
} else {
return _getcpucount_bsd();
}
static textwindows int __get_cpu_count_nt(void) {
uint32_t res;
if ((res = GetMaximumProcessorCount(ALL_PROCESSOR_GROUPS))) {
return res;
} else {
return GetMaximumProcessorCount(ALL_PROCESSOR_GROUPS);
return __winerr();
}
}
static int g_cpucount;
// precompute because process affinity on linux may change later
__attribute__((__constructor__)) static void _getcpucount_init(void) {
g_cpucount = _getcpucount_impl();
}
/**
* Returns number of CPUs in system.
*
@ -88,13 +74,20 @@ __attribute__((__constructor__)) static void _getcpucount_init(void) {
*
* sysconf(_SC_NPROCESSORS_ONLN);
*
* Except this function isn't a bloated diamond dependency.
*
* On Intel systems with HyperThreading this will return the number of
* cores multiplied by two.
* cores multiplied by two. On Linux, if you change cpu affinity it'll
* change the cpu count, which also gets inherited by child processes.
*
* @return cpu count or 0 if it couldn't be determined
* @return cpu count, or -1 w/ errno
*/
int _getcpucount(void) {
return g_cpucount;
int __get_cpu_count(void) {
if (!IsWindows()) {
if (!IsBsd()) {
return __get_cpu_count_linux();
} else {
return __get_cpu_count_bsd();
}
} else {
return __get_cpu_count_nt();
}
}

View file

@ -60,7 +60,7 @@ static textstartup void sys_getloadavg_nt_init(void) {
double a[3];
if (IsWindows()) {
load = 1;
cpus = _getcpucount() / 2;
cpus = __get_cpu_count() / 2;
cpus = MAX(1, cpus);
GetSystemTimes(&idle1, &kern1, &user1);
}

View file

@ -18,6 +18,7 @@
*/
#include "libc/calls/calls.h"
#include "libc/calls/struct/sysinfo.h"
#include "libc/calls/struct/sysinfo.internal.h"
#include "libc/calls/syscall-nt.internal.h"
#include "libc/dce.h"
#include "libc/intrin/strace.internal.h"
@ -40,7 +41,7 @@ struct loadavg {
* @raise ENOSYS on metal
*/
int getloadavg(double *a, int n) {
/* cat /proc/loadavg */
// cat /proc/loadavg
int i, rc;
if (n > 3) n = 3;
if (!n) {
@ -51,7 +52,7 @@ int getloadavg(double *a, int n) {
return sys_getloadavg_nt(a, n);
} else if (IsLinux()) {
struct sysinfo si;
if ((rc = sysinfo(&si)) != -1) {
if ((rc = sys_sysinfo(&si)) != -1) {
for (i = 0; i < n; i++) {
a[i] = 1. / 65536 * si.loads[i];
}

View file

@ -24,8 +24,7 @@
* Creates session and sets the process group id.
*/
int getsid(int pid) {
int rc;
rc = sys_getsid(pid);
int rc = sys_getsid(pid);
STRACE("%s(%d) → %d% m", "getsid", pid, rc);
return rc;
}

View file

@ -16,11 +16,14 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/calls/internal.h"
#include "libc/calls/struct/fd.internal.h"
#include "libc/calls/syscall-sysv.internal.h"
#include "libc/calls/syscall_support-sysv.internal.h"
#include "libc/calls/termios.h"
#include "libc/dce.h"
#include "libc/intrin/strace.internal.h"
#include "libc/sysv/errfuns.h"
#define TIOCPTYGRANT 0x20007454
@ -34,7 +37,9 @@
*/
int grantpt(int fd) {
int rc;
if (IsXnu()) {
if (fd < g_fds.n && g_fds.p[fd].kind == kFdZip) {
rc = enotty();
} else if (IsXnu()) {
rc = sys_ioctl(fd, TIOCPTYGRANT);
} else {
rc = _isptmaster(fd);

View file

@ -1,34 +0,0 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2022 Justine Alexandra Roberts Tunney
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/calls/calls.h"
#include "libc/calls/struct/timespec.h"
#include "libc/time/time.h"
/**
* Returns nanoseconds since UNIX epoch.
*/
int128_t _nanos(int timer) {
int128_t nanos;
struct timespec ts;
clock_gettime(timer, &ts);
nanos = ts.tv_sec;
nanos *= 1000000000;
nanos += ts.tv_nsec;
return nanos;
}

View file

@ -1,10 +0,0 @@
#ifndef COSMOPOLITAN_LIBC_CALLS_NANOS_H_
#define COSMOPOLITAN_LIBC_CALLS_NANOS_H_
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
int128_t _nanos(int);
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_LIBC_CALLS_NANOS_H_ */

View file

@ -27,6 +27,12 @@
/**
* Creates file-less file descriptors for interprocess communication.
*
* This function offers atomic operation on all supported platforms
* except for XNU and RHEL5 where it's polyfilled.
*
* @params flags may contain `O_CLOEXEC`, `O_NONBLOCK`, and `O_DIRECT`
* @raise EINVAL if flags has invalid or unsupported bits
* @raise EFAULT if `pipefd` doesn't point to valid memory
* @raise EMFILE if process `RLIMIT_NOFILE` has been reached
* @raise ENFILE if system-wide file limit has been reached
* @param pipefd is used to return (reader, writer) file descriptors

View file

@ -16,10 +16,13 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/calls/internal.h"
#include "libc/calls/struct/fd.internal.h"
#include "libc/calls/syscall_support-sysv.internal.h"
#include "libc/calls/termios.h"
#include "libc/errno.h"
#include "libc/intrin/strace.internal.h"
#include "libc/sysv/errfuns.h"
static char g_ptsname[16];
@ -30,7 +33,10 @@ static char g_ptsname[16];
*/
char *ptsname(int fd) {
char *res;
if (!_ptsname(fd, g_ptsname, sizeof(g_ptsname))) {
if (fd < g_fds.n && g_fds.p[fd].kind == kFdZip) {
enotty();
res = 0;
} else if (!_ptsname(fd, g_ptsname, sizeof(g_ptsname))) {
res = g_ptsname;
} else {
res = 0;

View file

@ -53,6 +53,8 @@ static int64_t GetPhysmem(void) {
static int sys_sysinfo_bsd(struct sysinfo *info) {
info->uptime = GetUptime();
info->totalram = GetPhysmem();
info->bufferram = GetPhysmem();
info->mem_unit = 1;
return 0;
}

View file

@ -25,8 +25,8 @@
#include "libc/intrin/asan.internal.h"
#include "libc/intrin/strace.internal.h"
#include "libc/intrin/weaken.h"
#include "libc/sysv/errfuns.h"
#include "libc/runtime/zipos.internal.h"
#include "libc/sysv/errfuns.h"
/**
* Changes size of file.
@ -50,15 +50,14 @@
* @raise ECANCELED if thread was cancelled in masked mode
* @raise EFBIG or EINVAL if `length` is too huge
* @raise EFAULT if `path` points to invalid memory
* @raise ENOTSUP if `path` is a zip filesystem path
* @raise EACCES if we don't have permission to search a component of `path`
* @raise ENOTDIR if a directory component in `path` exists as non-directory
* @raise ENAMETOOLONG if symlink-resolved `path` length exceeds `PATH_MAX`
* @raise ENAMETOOLONG if component in `path` exists longer than `NAME_MAX`
* @raise ELOOP if a loop was detected resolving components of `path`
* @raise EROFS if `path` is on a read-only filesystem (e.g. zip)
* @raise ENOENT if `path` doesn't exist or is an empty string
* @raise ETXTBSY if `path` is an executable being executed
* @raise EROFS if `path` is on a read-only filesystem
* @raise ENOSYS on bare metal
* @cancellationpoint
* @see ftruncate()
@ -75,7 +74,7 @@ int truncate(const char *path, int64_t length) {
rc = efault();
} else if (_weaken(__zipos_parseuri) &&
_weaken(__zipos_parseuri)(path, &zipname) != -1) {
rc = enotsup();
rc = erofs();
} else if (!IsWindows()) {
rc = sys_truncate(path, length, length);
if (IsNetbsd() && rc == -1 && errno == ENOSPC) {

View file

@ -17,6 +17,8 @@
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/calls/struct/fd.internal.h"
#include "libc/calls/syscall-sysv.internal.h"
#include "libc/calls/syscall_support-sysv.internal.h"
#include "libc/calls/termios.h"
@ -37,7 +39,9 @@
*/
int unlockpt(int fd) {
int rc, unlock = 0;
if (IsFreebsd() || IsOpenbsd() || IsNetbsd()) {
if (fd < g_fds.n && g_fds.p[fd].kind == kFdZip) {
rc = enotty();
} else if (IsFreebsd() || IsOpenbsd() || IsNetbsd()) {
rc = _isptmaster(fd);
} else if (IsXnu()) {
rc = sys_ioctl(fd, TIOCPTYUNLK);

View file

@ -28,9 +28,9 @@
#include "libc/intrin/describeflags.internal.h"
#include "libc/intrin/strace.internal.h"
#include "libc/intrin/weaken.h"
#include "libc/runtime/zipos.internal.h"
#include "libc/sysv/consts/at.h"
#include "libc/sysv/errfuns.h"
#include "libc/runtime/zipos.internal.h"
int __utimens(int fd, const char *path, const struct timespec ts[2],
int flags) {
@ -47,7 +47,7 @@ int __utimens(int fd, const char *path, const struct timespec ts[2],
} else if (__isfdkind(fd, kFdZip) ||
(path && (_weaken(__zipos_parseuri) &&
_weaken(__zipos_parseuri)(path, &zipname) != -1))) {
rc = enotsup();
rc = erofs();
} else if (IsLinux() && !__is_linux_2_6_23() && fd == AT_FDCWD && !flags) {
rc = sys_utimes(path, (void *)ts); // rhel5 truncates to seconds
} else if (!IsWindows()) {

View file

@ -25,9 +25,9 @@
#include "libc/intrin/describeflags.internal.h"
#include "libc/intrin/strace.internal.h"
#include "libc/intrin/weaken.h"
#include "libc/runtime/zipos.internal.h"
#include "libc/sysv/consts/at.h"
#include "libc/sysv/errfuns.h"
#include "libc/runtime/zipos.internal.h"
/**
* Sets access/modified time on file, the modern way.
@ -48,13 +48,12 @@
* @raise EINVAL if `flags` had an unrecognized value
* @raise EPERM if pledge() is in play without `fattr` promise
* @raise EACCES if unveil() is in play and `path` isn't unveiled
* @raise ENOTSUP if `path` is a zip filesystem path or `dirfd` is zip
* @raise EINVAL if `ts` specifies a nanosecond value that's out of range
* @raise ENAMETOOLONG if symlink-resolved `path` length exceeds `PATH_MAX`
* @raise ENAMETOOLONG if component in `path` exists longer than `NAME_MAX`
* @raise EBADF if `dirfd` isn't a valid fd or `AT_FDCWD`
* @raise EFAULT if `path` or `ts` memory was invalid
* @raise EROFS if `path` is on read-only filesystem
* @raise EROFS if `path` is on read-only filesystem (e.g. zipos)
* @raise ENOSYS on bare metal or on rhel5 when `dirfd` or `flags` is used
* @asyncsignalsafe
* @threadsafe