mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-05-23 05:42:29 +00:00
Generate ZIP files the same way as Windows
This commit is contained in:
parent
d932948fb4
commit
f4298f10c2
11 changed files with 112 additions and 43 deletions
|
@ -25,19 +25,17 @@
|
|||
.hidden __zip_start
|
||||
.globl __zip_start
|
||||
.type __zip_start,@object
|
||||
.align kZipCdirAlign
|
||||
__zip_start:
|
||||
.previous/*
|
||||
...
|
||||
decentralized content
|
||||
...
|
||||
*/.section .zip.5,"",@progbits
|
||||
.align kZipCdirAlign
|
||||
__zip_end:
|
||||
.long kZipCdirHdrMagic # magic
|
||||
.short 0 # disk
|
||||
.short 0 # starting disk
|
||||
.short v_zip_records # records on disk
|
||||
.short v_zip_records # number of records on disk
|
||||
.short v_zip_records # records
|
||||
.long v_zip_cdirsize # size of central directory
|
||||
.long RVA(__zip_start) # central directory offset
|
||||
|
|
|
@ -18,16 +18,34 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/zip.h"
|
||||
|
||||
uint8_t *zipfindcentraldir(const uint8_t *map, size_t mapsize) {
|
||||
const uint8_t *p, *pe;
|
||||
for (p = map + mapsize - kZipCdirHdrMinSize,
|
||||
pe = mapsize > 65536 + kZipCdirHdrMinSize
|
||||
? map + mapsize - 65536 - kZipCdirHdrMinSize
|
||||
: map;
|
||||
p >= pe; --p) {
|
||||
if (ZIP_CDIR_MAGIC(p) == kZipCdirHdrMagic) {
|
||||
return (/*unconst*/ uint8_t *)p;
|
||||
}
|
||||
/**
|
||||
* Locates End Of Central Directory record in ZIP file.
|
||||
*
|
||||
* We search backwards for the End Of Central Directory Record magnum.
|
||||
* The ZIP spec says this can be anywhere in the last 64kb. We go all
|
||||
* the way since .com.dbg binaries will have lots of DWARF stuff after
|
||||
* the embedded .com binary. As such, we sanity check the other fields
|
||||
* too to make sure the record seems legit and it's not just a random
|
||||
* occurrence of the magnum.
|
||||
*
|
||||
* @param p points to file memory
|
||||
* @param n is byte size of file
|
||||
*/
|
||||
uint8_t *zipfindcentraldir(const uint8_t *p, size_t n) {
|
||||
size_t i;
|
||||
if (n >= kZipCdirHdrMinSize) {
|
||||
i = n - kZipCdirHdrMinSize;
|
||||
do {
|
||||
if (ZIP_CDIR_MAGIC(p + i) == kZipCdirHdrMagic &&
|
||||
i + ZIP_CDIR_HDRSIZE(p + i) <= n &&
|
||||
ZIP_CDIR_DISK(p + i) == ZIP_CDIR_STARTINGDISK(p + i) &&
|
||||
ZIP_CDIR_RECORDSONDISK(p + i) == ZIP_CDIR_RECORDS(p + i) &&
|
||||
ZIP_CDIR_RECORDS(p + i) * kZipCdirHdrMinSize <=
|
||||
ZIP_CDIR_SIZE(p + i) &&
|
||||
ZIP_CDIR_OFFSET(p + i) + ZIP_CDIR_SIZE(p + i) <= i) {
|
||||
return (/*unconst*/ uint8_t *)(p + i);
|
||||
}
|
||||
} while (i--);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
|
||||
#define kZipAlign 2
|
||||
|
||||
#define kZipCosmopolitanVersion 1
|
||||
#define kZipCosmopolitanVersion 20
|
||||
|
||||
#define kZipOsDos 0
|
||||
#define kZipOsAmiga 1
|
||||
|
@ -45,7 +45,7 @@
|
|||
|
||||
#define kZipCdirHdrMagic 0x06054b50 /* PK♣♠ "PK\5\6" */
|
||||
#define kZipCdirHdrMinSize 22
|
||||
#define kZipCdirAlign 64 /* our choice; actually 2 */
|
||||
#define kZipCdirAlign kZipAlign
|
||||
#define kZipCdirHdrLinkableSize \
|
||||
ROUNDUP(kZipCfileHdrMinSize + PATH_MAX, kZipCdirAlign)
|
||||
|
||||
|
|
|
@ -29,6 +29,7 @@ ssize_t __zipos_find(struct Zipos *zipos, const struct ZiposUri *name) {
|
|||
for (i = 0, cf = ZIP_CDIR_OFFSET(zipos->cdir);
|
||||
i < ZIP_CDIR_RECORDS(zipos->cdir);
|
||||
++i, cf += ZIP_CFILE_HDRSIZE(zipos->map + cf)) {
|
||||
if (ZIP_CFILE_MAGIC(zipos->map + cf) != kZipCfileHdrMagic) DebugBreak();
|
||||
assert(ZIP_CFILE_MAGIC(zipos->map + cf) == kZipCfileHdrMagic);
|
||||
if (name->len == ZIP_CFILE_NAMESIZE(zipos->map + cf) &&
|
||||
memcmp(name->path, ZIP_CFILE_NAME(zipos->map + cf), name->len) == 0) {
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include "libc/calls/struct/stat.h"
|
||||
#include "libc/limits.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/auxv.h"
|
||||
#include "libc/sysv/consts/map.h"
|
||||
#include "libc/sysv/consts/o.h"
|
||||
|
@ -36,9 +37,8 @@ struct Zipos *__zipos_get(void) {
|
|||
static bool once;
|
||||
const char *exe, *dir;
|
||||
char path[PATH_MAX];
|
||||
size_t mapsize;
|
||||
uint8_t *cdir;
|
||||
void *map;
|
||||
size_t size;
|
||||
uint8_t *map, *base, *cdir;
|
||||
if (!once) {
|
||||
dir = nulltoempty(getenv("PWD")); /* suboptimal */
|
||||
exe = (const char *)getauxval(AT_EXECFN);
|
||||
|
@ -47,14 +47,23 @@ struct Zipos *__zipos_get(void) {
|
|||
exe = path;
|
||||
}
|
||||
if ((zipos.fd = open(exe, O_RDONLY)) != -1) {
|
||||
if ((mapsize = getfiledescriptorsize(zipos.fd)) != SIZE_MAX &&
|
||||
(map = mmap(NULL, mapsize, PROT_READ, MAP_SHARED, zipos.fd, 0)) !=
|
||||
if ((size = getfiledescriptorsize(zipos.fd)) != SIZE_MAX &&
|
||||
(map = mmap(NULL, size, PROT_READ, MAP_SHARED, zipos.fd, 0)) !=
|
||||
MAP_FAILED) {
|
||||
if ((cdir = zipfindcentraldir(map, mapsize))) {
|
||||
zipos.map = map;
|
||||
if (endswith(exe, ".com.dbg")) {
|
||||
if ((base = memmem(map, size, "MZqFpD", 6))) {
|
||||
size -= base - map;
|
||||
} else {
|
||||
base = map;
|
||||
}
|
||||
} else {
|
||||
base = map;
|
||||
}
|
||||
if ((cdir = zipfindcentraldir(base, size))) {
|
||||
zipos.map = base;
|
||||
zipos.cdir = cdir;
|
||||
} else {
|
||||
munmap(map, mapsize);
|
||||
munmap(map, size);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue