mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-07-06 19:28:29 +00:00
Make fixes and improvements
- Fix handling of precision in hex float formatting - Enhance the cocmd interpreter for system() and popen() - Manually ran the Lua unit tests, which are now passing - Let stdio i/o operations happen when file is in error state - We're now saving and restoring xmm in ftrace out of paranoia
This commit is contained in:
parent
95fbdb4f76
commit
41396ff48a
43 changed files with 495 additions and 261 deletions
|
@ -727,7 +727,6 @@ haveinc:
|
|||
* - `%e` double (expo formatting)
|
||||
* - `%f` double (ugly formatting)
|
||||
* - `%a` double (hex formatting)
|
||||
* - `%Lg` long double
|
||||
*
|
||||
* Size Modifiers
|
||||
*
|
||||
|
@ -738,6 +737,7 @@ haveinc:
|
|||
* - `%lx` unsigned long (64-bit hexadecimal)
|
||||
* - `%jd` intmax_t (64-bit)
|
||||
* - `%jjd` int128_t (128-bit)
|
||||
* - `%Lg` long double
|
||||
*
|
||||
* Width Modifiers
|
||||
*
|
||||
|
@ -1251,19 +1251,23 @@ _Hide int __fmt(void *fn, void *arg, const char *format, va_list va) {
|
|||
__FMT_PUT(*s++);
|
||||
if (prec || (flags & FLAGS_HASH)) __FMT_PUT('.');
|
||||
while (--prec >= 0) {
|
||||
if ((c = *s))
|
||||
if ((c = *s)) {
|
||||
s++;
|
||||
else
|
||||
} else {
|
||||
c = '0';
|
||||
}
|
||||
__FMT_PUT(c);
|
||||
}
|
||||
__FMT_PUT(d);
|
||||
if (decpt < 0) {
|
||||
__FMT_PUT('-');
|
||||
decpt = -decpt;
|
||||
} else
|
||||
} else {
|
||||
__FMT_PUT('+');
|
||||
for (c = 2, k = 10; 10 * k <= decpt; c++, k *= 10) donothing;
|
||||
}
|
||||
for (c = 2, k = 10; 10 * k <= decpt; c++, k *= 10) {
|
||||
donothing;
|
||||
}
|
||||
for (;;) {
|
||||
i1 = decpt / k;
|
||||
__FMT_PUT(i1 + '0');
|
||||
|
@ -1271,7 +1275,9 @@ _Hide int __fmt(void *fn, void *arg, const char *format, va_list va) {
|
|||
decpt -= i1 * k;
|
||||
decpt *= 10;
|
||||
}
|
||||
while (--width >= 0) __FMT_PUT(' ');
|
||||
while (--width >= 0) {
|
||||
__FMT_PUT(' ');
|
||||
}
|
||||
freedtoa(s0);
|
||||
break;
|
||||
|
||||
|
@ -1321,7 +1327,7 @@ _Hide int __fmt(void *fn, void *arg, const char *format, va_list va) {
|
|||
}
|
||||
if (sign) __FMT_PUT(sign);
|
||||
__FMT_PUT('0');
|
||||
__FMT_PUT(alphabet[17]);
|
||||
__FMT_PUT(alphabet[17]); // x or X
|
||||
if ((flags & FLAGS_ZEROPAD) && width > 0 && !(flags & FLAGS_LEFT)) {
|
||||
do __FMT_PUT('0');
|
||||
while (--width > 0);
|
||||
|
@ -1329,29 +1335,31 @@ _Hide int __fmt(void *fn, void *arg, const char *format, va_list va) {
|
|||
i1 = prec1 & 7;
|
||||
k = prec1 >> 3;
|
||||
__FMT_PUT(alphabet[(fpb.bits[k] >> 4 * i1) & 0xf]);
|
||||
if (prec1 > 0 || (flags & FLAGS_HASH)) __FMT_PUT('.');
|
||||
if (prec1 > 0) {
|
||||
prec -= prec1;
|
||||
while (prec1 > 0) {
|
||||
if (--i1 < 0) {
|
||||
if (--k < 0) break;
|
||||
i1 = 7;
|
||||
}
|
||||
__FMT_PUT(alphabet[(fpb.bits[k] >> 4 * i1) & 0xf]);
|
||||
--prec1;
|
||||
}
|
||||
if ((flags & FLAGS_HASH) && prec > 0) {
|
||||
do __FMT_PUT(0);
|
||||
while (--prec > 0);
|
||||
}
|
||||
if (prec1 > 0 || prec > 0) {
|
||||
__FMT_PUT('.');
|
||||
}
|
||||
__FMT_PUT(alphabet[16]);
|
||||
while (prec1 > 0) {
|
||||
if (--i1 < 0) {
|
||||
if (--k < 0) break;
|
||||
i1 = 7;
|
||||
}
|
||||
__FMT_PUT(alphabet[(fpb.bits[k] >> 4 * i1) & 0xf]);
|
||||
--prec1;
|
||||
--prec;
|
||||
}
|
||||
while (prec-- > 0) {
|
||||
__FMT_PUT('0');
|
||||
}
|
||||
__FMT_PUT(alphabet[16]); // p or P
|
||||
if (bex < 0) {
|
||||
__FMT_PUT('-');
|
||||
bex = -bex;
|
||||
} else
|
||||
} else {
|
||||
__FMT_PUT('+');
|
||||
for (c = 1; 10 * c <= bex; c *= 10) donothing;
|
||||
}
|
||||
for (c = 1; 10 * c <= bex; c *= 10) {
|
||||
donothing;
|
||||
}
|
||||
for (;;) {
|
||||
i1 = bex / c;
|
||||
__FMT_PUT('0' + i1);
|
||||
|
@ -1359,7 +1367,9 @@ _Hide int __fmt(void *fn, void *arg, const char *format, va_list va) {
|
|||
bex -= i1 * c;
|
||||
bex *= 10;
|
||||
}
|
||||
while (--width >= 0) __FMT_PUT(' ');
|
||||
while (--width >= 0) {
|
||||
__FMT_PUT(' ');
|
||||
}
|
||||
break;
|
||||
|
||||
case '%':
|
||||
|
|
|
@ -43,7 +43,7 @@ size_t fread_unlocked(void *buf, size_t stride, size_t count, FILE *f) {
|
|||
ssize_t rc;
|
||||
size_t n, m;
|
||||
struct iovec iov[2];
|
||||
if (f->state) {
|
||||
if (!stride) {
|
||||
return 0;
|
||||
}
|
||||
if ((f->iomode & O_ACCMODE) == O_WRONLY) {
|
||||
|
|
53
libc/stdio/ftw.c
Normal file
53
libc/stdio/ftw.c
Normal file
|
@ -0,0 +1,53 @@
|
|||
/*-*- mode:c;indent-tabs-mode:t;c-basic-offset:8;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set et ft=c ts=8 tw=8 fenc=utf-8 :vi│
|
||||
╚──────────────────────────────────────────────────────────────────────────────╝
|
||||
│ │
|
||||
│ Musl Libc │
|
||||
│ Copyright © 2005-2014 Rich Felker, et al. │
|
||||
│ │
|
||||
│ Permission is hereby granted, free of charge, to any person obtaining │
|
||||
│ a copy of this software and associated documentation files (the │
|
||||
│ "Software"), to deal in the Software without restriction, including │
|
||||
│ without limitation the rights to use, copy, modify, merge, publish, │
|
||||
│ distribute, sublicense, and/or sell copies of the Software, and to │
|
||||
│ permit persons to whom the Software is furnished to do so, subject to │
|
||||
│ the following conditions: │
|
||||
│ │
|
||||
│ The above copyright notice and this permission notice shall be │
|
||||
│ included in all copies or substantial portions of the Software. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, │
|
||||
│ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF │
|
||||
│ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. │
|
||||
│ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY │
|
||||
│ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, │
|
||||
│ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE │
|
||||
│ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. │
|
||||
│ │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/stdio/ftw.h"
|
||||
|
||||
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
|
||||
|
||||
/**
|
||||
* 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 *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(dirpath, (int (*)())fn, fd_limit, FTW_PHYS);
|
||||
}
|
90
libc/stdio/ftw.h
Normal file
90
libc/stdio/ftw.h
Normal file
|
@ -0,0 +1,90 @@
|
|||
#ifndef COSMOPOLITAN_THIRD_PARTY_MUSL_FTW_H_
|
||||
#define COSMOPOLITAN_THIRD_PARTY_MUSL_FTW_H_
|
||||
#include "libc/calls/struct/stat.h"
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
/**
|
||||
* Type for file.
|
||||
*/
|
||||
#define FTW_F 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;
|
||||
};
|
||||
|
||||
int ftw(const char *, int (*)(const char *, const struct stat *, int), int);
|
||||
int nftw(const char *,
|
||||
int (*)(const char *, const struct stat *, int, struct FTW *), int,
|
||||
int);
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_THIRD_PARTY_MUSL_FTW_H_ */
|
|
@ -45,7 +45,7 @@ size_t fwrite_unlocked(const void *data, size_t stride, size_t count, FILE *f) {
|
|||
size_t n, m;
|
||||
const char *p;
|
||||
struct iovec iov[2];
|
||||
if (f->state) {
|
||||
if (!stride) {
|
||||
return 0;
|
||||
}
|
||||
if ((f->iomode & O_ACCMODE) == O_RDONLY) {
|
||||
|
|
189
libc/stdio/nftw.c
Normal file
189
libc/stdio/nftw.c
Normal file
|
@ -0,0 +1,189 @@
|
|||
/*-*- mode:c;indent-tabs-mode:t;c-basic-offset:8;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set et ft=c ts=8 tw=8 fenc=utf-8 :vi│
|
||||
╚──────────────────────────────────────────────────────────────────────────────╝
|
||||
│ │
|
||||
│ Musl Libc │
|
||||
│ Copyright © 2005-2014 Rich Felker, et al. │
|
||||
│ │
|
||||
│ Permission is hereby granted, free of charge, to any person obtaining │
|
||||
│ a copy of this software and associated documentation files (the │
|
||||
│ "Software"), to deal in the Software without restriction, including │
|
||||
│ without limitation the rights to use, copy, modify, merge, publish, │
|
||||
│ distribute, sublicense, and/or sell copies of the Software, and to │
|
||||
│ permit persons to whom the Software is furnished to do so, subject to │
|
||||
│ the following conditions: │
|
||||
│ │
|
||||
│ The above copyright notice and this permission notice shall be │
|
||||
│ included in all copies or substantial portions of the Software. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, │
|
||||
│ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF │
|
||||
│ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. │
|
||||
│ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY │
|
||||
│ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, │
|
||||
│ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE │
|
||||
│ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. │
|
||||
│ │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/struct/dirent.h"
|
||||
#include "libc/calls/weirdtypes.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/o.h"
|
||||
#include "libc/sysv/consts/s.h"
|
||||
#include "libc/thread/thread.h"
|
||||
#include "libc/stdio/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\"");
|
||||
// clang-format off
|
||||
|
||||
struct history
|
||||
{
|
||||
struct history *chain;
|
||||
dev_t dev;
|
||||
ino_t ino;
|
||||
int level;
|
||||
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)
|
||||
{
|
||||
size_t l = strlen(path), j = l && path[l-1]=='/' ? l-1 : l;
|
||||
struct stat st;
|
||||
struct history new;
|
||||
int type;
|
||||
int r;
|
||||
int dfd=-1;
|
||||
int err=0;
|
||||
struct FTW lev;
|
||||
|
||||
if ((flags & FTW_PHYS) ? lstat(path, &st) : stat(path, &st) < 0) {
|
||||
if (!(flags & FTW_PHYS) && errno==ENOENT && !lstat(path, &st))
|
||||
type = FTW_SLN;
|
||||
else if (errno != EACCES) return -1;
|
||||
else type = FTW_NS;
|
||||
} else if (S_ISDIR(st.st_mode)) {
|
||||
if (flags & FTW_DEPTH) type = FTW_DP;
|
||||
else type = FTW_D;
|
||||
} else if (S_ISLNK(st.st_mode)) {
|
||||
if (flags & FTW_PHYS) type = FTW_SL;
|
||||
else type = FTW_SLN;
|
||||
} else {
|
||||
type = FTW_F;
|
||||
}
|
||||
|
||||
if ((flags & FTW_MOUNT) && h && st.st_dev != h->dev)
|
||||
return 0;
|
||||
|
||||
new.chain = h;
|
||||
new.dev = st.st_dev;
|
||||
new.ino = st.st_ino;
|
||||
new.level = h ? h->level+1 : 0;
|
||||
new.base = j+1;
|
||||
|
||||
lev.level = new.level;
|
||||
if (h) {
|
||||
lev.base = h->base;
|
||||
} else {
|
||||
size_t k;
|
||||
for (k=j; k && path[k]=='/'; k--);
|
||||
for (; k && path[k-1]!='/'; k--);
|
||||
lev.base = k;
|
||||
}
|
||||
|
||||
if (type == FTW_D || type == FTW_DP) {
|
||||
dfd = open(path, O_RDONLY | O_DIRECTORY);
|
||||
err = errno;
|
||||
if (dfd < 0 && err == EACCES) type = FTW_DNR;
|
||||
if (!fd_limit) close(dfd);
|
||||
}
|
||||
|
||||
if (!(flags & FTW_DEPTH) && (r=fn(path, &st, type, &lev)))
|
||||
return r;
|
||||
|
||||
for (; h; h = h->chain)
|
||||
if (h->dev == st.st_dev && h->ino == st.st_ino)
|
||||
return 0;
|
||||
|
||||
if ((type == FTW_D || type == FTW_DP) && fd_limit) {
|
||||
if (dfd < 0) {
|
||||
errno = err;
|
||||
return -1;
|
||||
}
|
||||
DIR *d = fdopendir(dfd);
|
||||
if (d) {
|
||||
struct dirent *de;
|
||||
while ((de = readdir(d))) {
|
||||
if (de->d_name[0] == '.'
|
||||
&& (!de->d_name[1]
|
||||
|| (de->d_name[1]=='.'
|
||||
&& !de->d_name[2]))) continue;
|
||||
if (strlen(de->d_name) >= PATH_MAXIMUS-l) {
|
||||
errno = ENAMETOOLONG;
|
||||
closedir(d);
|
||||
return -1;
|
||||
}
|
||||
path[j]='/';
|
||||
strcpy(path+j+1, de->d_name);
|
||||
if ((r=do_nftw(path, fn, fd_limit-1, flags, &new))) {
|
||||
closedir(d);
|
||||
return r;
|
||||
}
|
||||
}
|
||||
closedir(d);
|
||||
} else {
|
||||
close(dfd);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
path[l] = 0;
|
||||
if ((flags & FTW_DEPTH) && (r=fn(path, &st, type, &lev)))
|
||||
return r;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 *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_MAXIMUS+1];
|
||||
|
||||
if (fd_limit <= 0) return 0;
|
||||
|
||||
l = strlen(dirpath);
|
||||
if (l > PATH_MAXIMUS) {
|
||||
errno = ENAMETOOLONG;
|
||||
return -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;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue