Fix some zipos directory related bugs

This commit is contained in:
Justine Tunney 2023-09-18 22:17:56 -07:00
parent ec480f5aa0
commit ececec4c94
No known key found for this signature in database
GPG key ID: BE714B4575D6E328
8 changed files with 114 additions and 30 deletions

View file

@ -16,6 +16,7 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/intrin/kprintf.h"
#include "libc/macros.internal.h"
#include "libc/runtime/zipos.internal.h"
#include "libc/str/str.h"
@ -23,6 +24,22 @@
#include "libc/sysv/errfuns.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) {
// 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) {
int dx;
size_t cfile = zipos->index[l];
const char *zname = ZIP_CFILE_NAME(zipos->map + cfile);
int zsize = ZIP_CFILE_NAMESIZE(zipos->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;
if (zsize > len && (dx = '/' - (zname[len] & 255))) {
// since the index is asciibetical, we need to specially handle
// the case where, when searching for a directory, regular files
// exist whose names share the same prefix as the directory name.
dx = dx > +1 ? +1 : dx;
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);
}
}

View file

@ -62,8 +62,7 @@ static void __zipos_dismiss(uint8_t *map, const uint8_t *cdir, long pg) {
mo = ROUNDDOWN(lo, FRAMESIZE);
if (mo) munmap(map, mo);
// this is supposed to reduce our rss usage but does it
pg = getauxval(AT_PAGESZ);
// this is supposed to reduce our rss usage but does it really?
lo = ROUNDDOWN(lo, pg);
hi = MIN(ROUNDUP(hi, pg), ROUNDDOWN(c, pg));
if (hi > lo) {

View file

@ -948,7 +948,7 @@ static textwindows int sock_update(struct PortState *port_state,
updated event mask. */
} else if (sock_state->poll_status == kPollPending) {
/* A poll operation is already pending, but it's not monitoring for
all the *events that the user is interested in .Therefore, cancel
all the *events that the user is interested in. Therefore, cancel
the pending *poll operation; when we receive it's completion
package, a new poll *operation will be submitted with the correct
event mask. */

View file

@ -404,16 +404,22 @@ static struct dirent *readdir_zipos(DIR *dir) {
s += dir->zip.prefix.len;
n -= dir->zip.prefix.len;
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)) &&
critbit0_emplace(&dir->zip.found, s, n) == 1) {
ent = &dir->ent;
ent->d_ino = dir->zip.offset;
ent->d_off = dir->tell;
ent->d_type =
S_ISDIR(GetZipCfileMode(dir->zip.zipos->map + dir->zip.offset))
? DT_DIR
: DT_REG;
ent->d_type = d_type;
memcpy(ent->d_name, s, n);
ent->d_name[n] = 0;
}

1
libc/testlib-test.txt Normal file
View file

@ -0,0 +1 @@
ignore this file

View file

@ -87,7 +87,8 @@ LIBC_TESTLIB_A_SRCS = \
LIBC_TESTLIB_A_OBJS = \
$(LIBC_TESTLIB_A_SRCS_C:%.c=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_CALLS \