add opendir, readdir, and stat support for zipos root and directories not explicitly encoded in the zip file

Squashed commit of the following:

commit 793dde99bc71c7a6554b3afba5ddd46b0cfb6ecb
Author: Gavin Hayes <gavin@computoid.com>
Date:   Mon Aug 29 17:27:59 2022 -0400

    add opendir, readdir, and stat support for zipos root and directories not explicitly encoded in the zip file

commit dfc3eeb4db16d21c7b73aae12c7d4707f6286895
Author: Gavin Hayes <gavin@computoid.com>
Date:   Mon Aug 29 00:33:05 2022 -0400

    add root support to __zipos_find
This commit is contained in:
Gavin Hayes 2022-08-29 17:31:29 -04:00
parent adaaeb7dd0
commit 0363fb1ead
5 changed files with 73 additions and 10 deletions

View file

@ -326,6 +326,7 @@ static struct dirent *readdir_impl(DIR *dir) {
uint8_t *s, *p; uint8_t *s, *p;
struct Zipos *zip; struct Zipos *zip;
struct dirent *ent; struct dirent *ent;
struct dirent *lastent;
struct dirent_bsd *bsd; struct dirent_bsd *bsd;
struct dirent_netbsd *nbsd; struct dirent_netbsd *nbsd;
struct dirent_openbsd *obsd; struct dirent_openbsd *obsd;
@ -351,6 +352,20 @@ static struct dirent *readdir_impl(DIR *dir) {
ent->d_type = S_ISDIR(mode) ? DT_DIR : DT_REG; ent->d_type = S_ISDIR(mode) ? DT_DIR : DT_REG;
memcpy(ent->d_name, s, ent->d_reclen); memcpy(ent->d_name, s, ent->d_reclen);
ent->d_name[ent->d_reclen] = 0; ent->d_name[ent->d_reclen] = 0;
} else {
lastent = (struct dirent *)dir->buf;
n = p - s;
n = MIN(n, 255);
if (!lastent->d_ino || (n != lastent->d_reclen) ||
memcmp(lastent->d_name, s, n)) {
ent = lastent;
ent->d_ino++;
ent->d_off = -1;
ent->d_reclen = n;
ent->d_type = DT_DIR;
memcpy(ent->d_name, s, ent->d_reclen);
ent->d_name[ent->d_reclen] = 0;
}
} }
} }
dir->zip.offset += ZIP_CFILE_HDRSIZE(zip->map + dir->zip.offset); dir->zip.offset += ZIP_CFILE_HDRSIZE(zip->map + dir->zip.offset);

View file

@ -28,6 +28,9 @@
ssize_t __zipos_find(struct Zipos *zipos, const struct ZiposUri *name) { ssize_t __zipos_find(struct Zipos *zipos, const struct ZiposUri *name) {
const char *zname; const char *zname;
size_t i, n, c, znamesize; size_t i, n, c, znamesize;
if (!name->len) {
return 0;
}
c = GetZipCdirOffset(zipos->cdir); c = GetZipCdirOffset(zipos->cdir);
n = GetZipCdirRecords(zipos->cdir); n = GetZipCdirRecords(zipos->cdir);
for (i = 0; i < n; ++i, c += ZIP_CFILE_HDRSIZE(zipos->map + c)) { for (i = 0; i < n; ++i, c += ZIP_CFILE_HDRSIZE(zipos->map + c)) {
@ -38,6 +41,13 @@ ssize_t __zipos_find(struct Zipos *zipos, const struct ZiposUri *name) {
(name->len + 1 == znamesize && !memcmp(name->path, zname, name->len) && (name->len + 1 == znamesize && !memcmp(name->path, zname, name->len) &&
zname[name->len] == '/')) { zname[name->len] == '/')) {
return c; return c;
} else if ((name->len < znamesize &&
!memcmp(name->path, zname, name->len) &&
zname[name->len - 1] == '/') ||
(name->len + 1 < znamesize &&
!memcmp(name->path, zname, name->len) &&
zname[name->len] == '/')) {
return 0;
} }
} }
return -1; return -1;

View file

@ -16,9 +16,10 @@
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/safemacros.internal.h"
#include "libc/calls/struct/stat.h" #include "libc/calls/struct/stat.h"
#include "libc/intrin/safemacros.internal.h"
#include "libc/str/str.h" #include "libc/str/str.h"
#include "libc/sysv/consts/s.h"
#include "libc/sysv/errfuns.h" #include "libc/sysv/errfuns.h"
#include "libc/zip.h" #include "libc/zip.h"
#include "libc/zipos/zipos.internal.h" #include "libc/zipos/zipos.internal.h"
@ -27,14 +28,18 @@ int __zipos_stat_impl(struct Zipos *zipos, size_t cf, struct stat *st) {
size_t lf; size_t lf;
if (zipos && st) { if (zipos && st) {
bzero(st, sizeof(*st)); bzero(st, sizeof(*st));
lf = GetZipCfileOffset(zipos->map + cf); if (cf) {
st->st_mode = GetZipCfileMode(zipos->map + cf); lf = GetZipCfileOffset(zipos->map + cf);
st->st_size = GetZipLfileUncompressedSize(zipos->map + lf); st->st_mode = GetZipCfileMode(zipos->map + cf);
st->st_blocks = st->st_size = GetZipLfileUncompressedSize(zipos->map + lf);
roundup(GetZipLfileCompressedSize(zipos->map + lf), 512) / 512; st->st_blocks =
GetZipCfileTimestamps(zipos->map + cf, &st->st_mtim, &st->st_atim, roundup(GetZipLfileCompressedSize(zipos->map + lf), 512) / 512;
&st->st_ctim, 0); GetZipCfileTimestamps(zipos->map + cf, &st->st_mtim, &st->st_atim,
st->st_birthtim = st->st_ctim; &st->st_ctim, 0);
st->st_birthtim = st->st_ctim;
} else {
st->st_mode = 0444 | S_IFDIR | 0111;
}
return 0; return 0;
} else { } else {
return einval(); return einval();

View file

@ -64,6 +64,10 @@ TEST(stat, zipos) {
stat("/zip/.python/test/" stat("/zip/.python/test/"
"tokenize_tests-latin1-coding-cookie-and-utf8-bom-sig.txt", "tokenize_tests-latin1-coding-cookie-and-utf8-bom-sig.txt",
&st)); &st));
EXPECT_SYS(0, 0, stat("/zip", &st));
EXPECT_SYS(0, 0, stat("/zip/", &st));
EXPECT_SYS(0, 0, stat("/zip/.python", &st));
EXPECT_SYS(0, 0, stat("/zip/.python/", &st));
} }
static long Stat(const char *path, struct stat *st) { static long Stat(const char *path, struct stat *st) {

View file

@ -20,9 +20,9 @@
#include "libc/calls/struct/dirent.h" #include "libc/calls/struct/dirent.h"
#include "libc/dce.h" #include "libc/dce.h"
#include "libc/errno.h" #include "libc/errno.h"
#include "libc/stdio/rand.h"
#include "libc/runtime/gc.internal.h" #include "libc/runtime/gc.internal.h"
#include "libc/runtime/runtime.h" #include "libc/runtime/runtime.h"
#include "libc/stdio/rand.h"
#include "libc/str/str.h" #include "libc/str/str.h"
#include "libc/sysv/consts/dt.h" #include "libc/sysv/consts/dt.h"
#include "libc/testlib/testlib.h" #include "libc/testlib/testlib.h"
@ -57,6 +57,35 @@ TEST(opendir, enotdir) {
ASSERT_SYS(ENOTDIR, NULL, opendir("yo/there")); ASSERT_SYS(ENOTDIR, NULL, opendir("yo/there"));
} }
TEST(opendir, zipTest_fake) {
ASSERT_NE(NULL, (dir = opendir("/zip")));
EXPECT_NE(NULL, (ent = readdir(dir)));
EXPECT_STREQ("echo", ent->d_name);
EXPECT_NE(NULL, (ent = readdir(dir)));
EXPECT_STREQ("usr", ent->d_name);
EXPECT_EQ(NULL, (ent = readdir(dir)));
EXPECT_EQ(0, closedir(dir));
ASSERT_NE(NULL, (dir = opendir("/zip/")));
EXPECT_NE(NULL, (ent = readdir(dir)));
EXPECT_STREQ("echo", ent->d_name);
EXPECT_NE(NULL, (ent = readdir(dir)));
EXPECT_STREQ("usr", ent->d_name);
EXPECT_EQ(NULL, (ent = readdir(dir)));
EXPECT_EQ(0, closedir(dir));
ASSERT_NE(NULL, (dir = opendir("/zip/usr")));
EXPECT_NE(NULL, (ent = readdir(dir)));
EXPECT_STREQ("share", ent->d_name);
EXPECT_EQ(NULL, (ent = readdir(dir)));
EXPECT_EQ(0, closedir(dir));
ASSERT_NE(NULL, (dir = opendir("/zip/usr/")));
EXPECT_NE(NULL, (ent = readdir(dir)));
EXPECT_STREQ("share", ent->d_name);
EXPECT_EQ(NULL, (ent = readdir(dir)));
EXPECT_EQ(0, closedir(dir));
EXPECT_EQ(NULL, (dir = opendir("/zip/us")));
EXPECT_EQ(NULL, (dir = opendir("/zip/us/")));
}
TEST(dirstream, testDots) { TEST(dirstream, testDots) {
int hasdot = 0; int hasdot = 0;
int hasdotdot = 0; int hasdotdot = 0;