mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-01-31 03:27:39 +00:00
Fix some zipos directory related bugs
This commit is contained in:
parent
ec480f5aa0
commit
ececec4c94
8 changed files with 114 additions and 30 deletions
|
@ -16,6 +16,7 @@
|
||||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
|
#include "libc/intrin/kprintf.h"
|
||||||
#include "libc/macros.internal.h"
|
#include "libc/macros.internal.h"
|
||||||
#include "libc/runtime/zipos.internal.h"
|
#include "libc/runtime/zipos.internal.h"
|
||||||
#include "libc/str/str.h"
|
#include "libc/str/str.h"
|
||||||
|
@ -23,6 +24,22 @@
|
||||||
#include "libc/sysv/errfuns.h"
|
#include "libc/sysv/errfuns.h"
|
||||||
#include "libc/zip.internal.h"
|
#include "libc/zip.internal.h"
|
||||||
|
|
||||||
|
static ssize_t __zipos_match(struct Zipos *z, struct ZiposUri *name, int len,
|
||||||
|
int i) {
|
||||||
|
size_t cfile = z->index[i];
|
||||||
|
const char *zname = ZIP_CFILE_NAME(z->map + cfile);
|
||||||
|
int zsize = ZIP_CFILE_NAMESIZE(z->map + cfile);
|
||||||
|
if ((len == zsize || (len + 1 == zsize && zname[len] == '/')) &&
|
||||||
|
!memcmp(name->path, zname, len)) {
|
||||||
|
return cfile;
|
||||||
|
} else if (len + 1 < zsize && zname[len] == '/' &&
|
||||||
|
!memcmp(name->path, zname, len)) {
|
||||||
|
return ZIPOS_SYNTHETIC_DIRECTORY;
|
||||||
|
} else {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ssize_t __zipos_scan(struct Zipos *zipos, struct ZiposUri *name) {
|
ssize_t __zipos_scan(struct Zipos *zipos, struct ZiposUri *name) {
|
||||||
|
|
||||||
// strip trailing slash from search name
|
// strip trailing slash from search name
|
||||||
|
@ -61,17 +78,32 @@ ssize_t __zipos_scan(struct Zipos *zipos, struct ZiposUri *name) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// return pointer to leftmost record if it matches
|
|
||||||
if (l < zipos->records) {
|
if (l < zipos->records) {
|
||||||
|
int dx;
|
||||||
size_t cfile = zipos->index[l];
|
size_t cfile = zipos->index[l];
|
||||||
const char *zname = ZIP_CFILE_NAME(zipos->map + cfile);
|
const char *zname = ZIP_CFILE_NAME(zipos->map + cfile);
|
||||||
int zsize = ZIP_CFILE_NAMESIZE(zipos->map + cfile);
|
int zsize = ZIP_CFILE_NAMESIZE(zipos->map + cfile);
|
||||||
if ((len == zsize || (len + 1 == zsize && zname[len] == '/')) &&
|
if (zsize > len && (dx = '/' - (zname[len] & 255))) {
|
||||||
!memcmp(name->path, zname, len)) {
|
// since the index is asciibetical, we need to specially handle
|
||||||
return cfile;
|
// the case where, when searching for a directory, regular files
|
||||||
} else if (len + 1 < zsize && zname[len] == '/' &&
|
// exist whose names share the same prefix as the directory name.
|
||||||
!memcmp(name->path, zname, len)) {
|
dx = dx > +1 ? +1 : dx;
|
||||||
return ZIPOS_SYNTHETIC_DIRECTORY;
|
dx = dx < -1 ? -1 : dx;
|
||||||
|
for (l += dx; 0 <= l && l < zipos->records; l += dx) {
|
||||||
|
ssize_t cf;
|
||||||
|
if ((cf = __zipos_match(zipos, name, len, l)) != -1) {
|
||||||
|
return cf;
|
||||||
|
}
|
||||||
|
cfile = zipos->index[l];
|
||||||
|
zname = ZIP_CFILE_NAME(zipos->map + cfile);
|
||||||
|
zsize = ZIP_CFILE_NAMESIZE(zipos->map + cfile);
|
||||||
|
if (zsize < len || (len && zname[len - 1] != name->path[len - 1])) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// otherwise just return pointer to leftmost record if it matches
|
||||||
|
return __zipos_match(zipos, name, len, l);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -62,8 +62,7 @@ static void __zipos_dismiss(uint8_t *map, const uint8_t *cdir, long pg) {
|
||||||
mo = ROUNDDOWN(lo, FRAMESIZE);
|
mo = ROUNDDOWN(lo, FRAMESIZE);
|
||||||
if (mo) munmap(map, mo);
|
if (mo) munmap(map, mo);
|
||||||
|
|
||||||
// this is supposed to reduce our rss usage but does it
|
// this is supposed to reduce our rss usage but does it really?
|
||||||
pg = getauxval(AT_PAGESZ);
|
|
||||||
lo = ROUNDDOWN(lo, pg);
|
lo = ROUNDDOWN(lo, pg);
|
||||||
hi = MIN(ROUNDUP(hi, pg), ROUNDDOWN(c, pg));
|
hi = MIN(ROUNDUP(hi, pg), ROUNDDOWN(c, pg));
|
||||||
if (hi > lo) {
|
if (hi > lo) {
|
||||||
|
|
|
@ -404,16 +404,22 @@ static struct dirent *readdir_zipos(DIR *dir) {
|
||||||
s += dir->zip.prefix.len;
|
s += dir->zip.prefix.len;
|
||||||
n -= dir->zip.prefix.len;
|
n -= dir->zip.prefix.len;
|
||||||
const char *p = memchr(s, '/', n);
|
const char *p = memchr(s, '/', n);
|
||||||
if (p) n = p - s;
|
int d_type;
|
||||||
|
if (p) {
|
||||||
|
n = p - s;
|
||||||
|
d_type = DT_DIR;
|
||||||
|
} else if (S_ISDIR(GetZipCfileMode(dir->zip.zipos->map +
|
||||||
|
dir->zip.offset))) {
|
||||||
|
d_type = DT_DIR;
|
||||||
|
} else {
|
||||||
|
d_type = DT_REG;
|
||||||
|
}
|
||||||
if ((n = MIN(n, sizeof(ent->d_name) - 1)) &&
|
if ((n = MIN(n, sizeof(ent->d_name) - 1)) &&
|
||||||
critbit0_emplace(&dir->zip.found, s, n) == 1) {
|
critbit0_emplace(&dir->zip.found, s, n) == 1) {
|
||||||
ent = &dir->ent;
|
ent = &dir->ent;
|
||||||
ent->d_ino = dir->zip.offset;
|
ent->d_ino = dir->zip.offset;
|
||||||
ent->d_off = dir->tell;
|
ent->d_off = dir->tell;
|
||||||
ent->d_type =
|
ent->d_type = d_type;
|
||||||
S_ISDIR(GetZipCfileMode(dir->zip.zipos->map + dir->zip.offset))
|
|
||||||
? DT_DIR
|
|
||||||
: DT_REG;
|
|
||||||
memcpy(ent->d_name, s, n);
|
memcpy(ent->d_name, s, n);
|
||||||
ent->d_name[n] = 0;
|
ent->d_name[n] = 0;
|
||||||
}
|
}
|
||||||
|
|
1
libc/testlib-test.txt
Normal file
1
libc/testlib-test.txt
Normal file
|
@ -0,0 +1 @@
|
||||||
|
ignore this file
|
|
@ -87,7 +87,8 @@ LIBC_TESTLIB_A_SRCS = \
|
||||||
LIBC_TESTLIB_A_OBJS = \
|
LIBC_TESTLIB_A_OBJS = \
|
||||||
$(LIBC_TESTLIB_A_SRCS_C:%.c=o/$(MODE)/%.o) \
|
$(LIBC_TESTLIB_A_SRCS_C:%.c=o/$(MODE)/%.o) \
|
||||||
$(LIBC_TESTLIB_A_SRCS_S:%.S=o/$(MODE)/%.o) \
|
$(LIBC_TESTLIB_A_SRCS_S:%.S=o/$(MODE)/%.o) \
|
||||||
$(LIBC_TESTLIB_A_ASSETS:%=o/$(MODE)/%.zip.o)
|
$(LIBC_TESTLIB_A_ASSETS:%=o/$(MODE)/%.zip.o) \
|
||||||
|
o/$(MODE)/libc/testlib-test.txt.zip.o
|
||||||
|
|
||||||
LIBC_TESTLIB_A_DIRECTDEPS = \
|
LIBC_TESTLIB_A_DIRECTDEPS = \
|
||||||
LIBC_CALLS \
|
LIBC_CALLS \
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
|
#include "libc/calls/calls.h"
|
||||||
#include "libc/calls/struct/dirent.h"
|
#include "libc/calls/struct/dirent.h"
|
||||||
#include "libc/calls/struct/stat.h"
|
#include "libc/calls/struct/stat.h"
|
||||||
#include "libc/errno.h"
|
#include "libc/errno.h"
|
||||||
|
@ -28,48 +29,99 @@
|
||||||
#include "libc/str/str.h"
|
#include "libc/str/str.h"
|
||||||
#include "libc/sysv/consts/at.h"
|
#include "libc/sysv/consts/at.h"
|
||||||
#include "libc/sysv/consts/dt.h"
|
#include "libc/sysv/consts/dt.h"
|
||||||
|
#include "libc/sysv/consts/o.h"
|
||||||
|
#include "libc/sysv/consts/s.h"
|
||||||
#include "libc/testlib/testlib.h"
|
#include "libc/testlib/testlib.h"
|
||||||
|
|
||||||
__static_yoink("zipos");
|
__static_yoink("zipos");
|
||||||
__static_yoink("libc/testlib/hyperion.txt");
|
__static_yoink("libc/testlib/hyperion.txt");
|
||||||
__static_yoink("libc/testlib/moby.txt");
|
__static_yoink("libc/testlib/moby.txt");
|
||||||
|
__static_yoink("libc/testlib-test.txt");
|
||||||
|
__static_yoink("usr/share/zoneinfo/");
|
||||||
__static_yoink("usr/share/zoneinfo/New_York");
|
__static_yoink("usr/share/zoneinfo/New_York");
|
||||||
|
|
||||||
DIR *dir;
|
DIR *dir;
|
||||||
struct dirent *ent;
|
struct dirent *ent;
|
||||||
|
|
||||||
TEST(zipdir, test) {
|
TEST(zipdir, testDirectoryThatHasRealZipEntry) {
|
||||||
const char *path = "/zip/libc/testlib///";
|
const char *path = "/zip/libc/testlib///";
|
||||||
ASSERT_NE(NULL, (dir = opendir(path)));
|
ASSERT_NE(NULL, (dir = opendir(path)));
|
||||||
ASSERT_EQ(0, telldir(dir));
|
ASSERT_EQ(0, telldir(dir));
|
||||||
ASSERT_NE(NULL, (ent = readdir(dir)));
|
ASSERT_NE(NULL, (ent = readdir(dir)));
|
||||||
ASSERT_EQ(0, strcmp(ent->d_name, "."));
|
ASSERT_STREQ(".", ent->d_name);
|
||||||
ASSERT_EQ(DT_DIR, ent->d_type);
|
ASSERT_EQ(DT_DIR, ent->d_type);
|
||||||
ASSERT_NE(NULL, (ent = readdir(dir)));
|
ASSERT_NE(NULL, (ent = readdir(dir)));
|
||||||
ASSERT_EQ(0, strcmp(ent->d_name, ".."));
|
ASSERT_STREQ("..", ent->d_name);
|
||||||
ASSERT_EQ(DT_DIR, ent->d_type);
|
ASSERT_EQ(DT_DIR, ent->d_type);
|
||||||
ASSERT_NE(NULL, (ent = readdir(dir)));
|
ASSERT_NE(NULL, (ent = readdir(dir)));
|
||||||
ASSERT_EQ(0, strcmp(ent->d_name, "hyperion.txt"));
|
ASSERT_STREQ("hyperion.txt", ent->d_name);
|
||||||
ASSERT_EQ(DT_REG, ent->d_type);
|
ASSERT_EQ(DT_REG, ent->d_type);
|
||||||
long pos = telldir(dir);
|
long pos = telldir(dir);
|
||||||
ASSERT_NE(NULL, (ent = readdir(dir)));
|
ASSERT_NE(NULL, (ent = readdir(dir)));
|
||||||
ASSERT_EQ(0, strcmp(ent->d_name, "moby.txt"));
|
ASSERT_STREQ("moby.txt", ent->d_name);
|
||||||
ASSERT_EQ(DT_REG, ent->d_type);
|
ASSERT_EQ(DT_REG, ent->d_type);
|
||||||
ASSERT_EQ(NULL, (ent = readdir(dir)));
|
ASSERT_EQ(NULL, (ent = readdir(dir)));
|
||||||
seekdir(dir, pos);
|
seekdir(dir, pos);
|
||||||
ASSERT_NE(NULL, (ent = readdir(dir)));
|
ASSERT_NE(NULL, (ent = readdir(dir)));
|
||||||
ASSERT_EQ(0, strcmp(ent->d_name, "moby.txt"));
|
ASSERT_STREQ("moby.txt", ent->d_name);
|
||||||
ASSERT_EQ(DT_REG, ent->d_type);
|
ASSERT_EQ(DT_REG, ent->d_type);
|
||||||
ASSERT_EQ(NULL, (ent = readdir(dir)));
|
ASSERT_EQ(NULL, (ent = readdir(dir)));
|
||||||
ASSERT_EQ(NULL, (ent = readdir(dir)));
|
ASSERT_EQ(NULL, (ent = readdir(dir)));
|
||||||
ASSERT_SYS(0, 0, closedir(dir));
|
ASSERT_SYS(0, 0, closedir(dir));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(zipdir, testDirectoryWithSyntheticOrMissingEntry) {
|
||||||
|
const char *path = "/zip/libc/";
|
||||||
|
ASSERT_NE(NULL, (dir = opendir(path)));
|
||||||
|
ASSERT_EQ(0, telldir(dir));
|
||||||
|
ASSERT_NE(NULL, (ent = readdir(dir)));
|
||||||
|
ASSERT_STREQ(".", ent->d_name);
|
||||||
|
ASSERT_EQ(DT_DIR, ent->d_type);
|
||||||
|
ASSERT_NE(NULL, (ent = readdir(dir)));
|
||||||
|
ASSERT_STREQ("..", ent->d_name);
|
||||||
|
ASSERT_EQ(DT_DIR, ent->d_type);
|
||||||
|
ASSERT_NE(NULL, (ent = readdir(dir)));
|
||||||
|
ASSERT_STREQ("testlib", ent->d_name);
|
||||||
|
ASSERT_EQ(DT_DIR, ent->d_type);
|
||||||
|
ASSERT_NE(NULL, (ent = readdir(dir)));
|
||||||
|
ASSERT_STREQ("testlib-test.txt", ent->d_name);
|
||||||
|
ASSERT_EQ(DT_REG, ent->d_type);
|
||||||
|
ASSERT_EQ(NULL, (ent = readdir(dir)));
|
||||||
|
ASSERT_SYS(0, 0, closedir(dir));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(zipdir, testListZip) {
|
||||||
|
const char *path = "/zip";
|
||||||
|
ASSERT_NE(NULL, (dir = opendir(path)));
|
||||||
|
ASSERT_EQ(0, telldir(dir));
|
||||||
|
ASSERT_NE(NULL, (ent = readdir(dir)));
|
||||||
|
ASSERT_STREQ(".", ent->d_name);
|
||||||
|
ASSERT_EQ(DT_DIR, ent->d_type);
|
||||||
|
ASSERT_NE(NULL, (ent = readdir(dir)));
|
||||||
|
ASSERT_STREQ("..", ent->d_name);
|
||||||
|
ASSERT_EQ(DT_DIR, ent->d_type);
|
||||||
|
ASSERT_NE(NULL, (ent = readdir(dir)));
|
||||||
|
ASSERT_STREQ("echo.com", ent->d_name);
|
||||||
|
ASSERT_EQ(DT_REG, ent->d_type);
|
||||||
|
ASSERT_NE(NULL, (ent = readdir(dir)));
|
||||||
|
ASSERT_STREQ("libc", ent->d_name);
|
||||||
|
ASSERT_EQ(DT_DIR, ent->d_type);
|
||||||
|
ASSERT_NE(NULL, (ent = readdir(dir)));
|
||||||
|
ASSERT_STREQ("usr", ent->d_name);
|
||||||
|
ASSERT_EQ(DT_DIR, ent->d_type);
|
||||||
|
ASSERT_NE(NULL, (ent = readdir(dir)));
|
||||||
|
ASSERT_STREQ(".cosmo", ent->d_name);
|
||||||
|
ASSERT_EQ(DT_REG, ent->d_type);
|
||||||
|
ASSERT_EQ(NULL, (ent = readdir(dir)));
|
||||||
|
ASSERT_SYS(0, 0, closedir(dir));
|
||||||
|
}
|
||||||
|
|
||||||
TEST(dirstream, hasDirectoryEntry) {
|
TEST(dirstream, hasDirectoryEntry) {
|
||||||
struct stat st;
|
struct stat st;
|
||||||
bool gotsome = false;
|
bool gotsome = false;
|
||||||
const char *path = "/zip/usr/share/zoneinfo";
|
const char *path = "/zip/usr/share/zoneinfo";
|
||||||
ASSERT_SYS(0, 0, fstatat(AT_FDCWD, path, &st, 0));
|
ASSERT_SYS(0, 0, fstatat(AT_FDCWD, path, &st, 0));
|
||||||
|
ASSERT_TRUE(S_ISDIR(st.st_mode));
|
||||||
ASSERT_NE(NULL, (dir = opendir(path)));
|
ASSERT_NE(NULL, (dir = opendir(path)));
|
||||||
while ((ent = readdir(dir))) {
|
while ((ent = readdir(dir))) {
|
||||||
gotsome = true;
|
gotsome = true;
|
||||||
|
|
7
third_party/mbedtls/test/lib.c
vendored
7
third_party/mbedtls/test/lib.c
vendored
|
@ -172,16 +172,9 @@ int mbedtls_test_write(const char *fmt, ...) {
|
||||||
n = vfprintf(stderr, fmt, va);
|
n = vfprintf(stderr, fmt, va);
|
||||||
} else {
|
} else {
|
||||||
char buf[512];
|
char buf[512];
|
||||||
const char *s;
|
|
||||||
vsnprintf(buf, 512, fmt, va);
|
vsnprintf(buf, 512, fmt, va);
|
||||||
if ((s = strchr(buf, '\n')) && //
|
|
||||||
s == buf + strlen(buf) - 1 && //
|
|
||||||
strstr(buf, "PASS")) {
|
|
||||||
n = 0; // ignore pointless success lines
|
|
||||||
} else {
|
|
||||||
n = appends(&output, buf);
|
n = appends(&output, buf);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
va_end(va);
|
va_end(va);
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue