mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-03-03 07:29:23 +00:00
Fix a bunch of Windows bugs reported on Discord
This change addresses everything from stack smashing to %SYSTEMROOT% breaking socket(). Issues relating to compile.com not reporting text printed to stderr has been resolved for Windows builds.
This commit is contained in:
parent
b0e3258709
commit
5018171fa5
10 changed files with 104 additions and 46 deletions
|
@ -18,11 +18,13 @@
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
#include "libc/calls/ntspawn.h"
|
#include "libc/calls/ntspawn.h"
|
||||||
#include "libc/fmt/conv.h"
|
#include "libc/fmt/conv.h"
|
||||||
|
#include "libc/intrin/_getenv.internal.h"
|
||||||
#include "libc/intrin/bits.h"
|
#include "libc/intrin/bits.h"
|
||||||
#include "libc/macros.internal.h"
|
#include "libc/macros.internal.h"
|
||||||
#include "libc/mem/alloca.h"
|
#include "libc/mem/alloca.h"
|
||||||
#include "libc/mem/arraylist2.internal.h"
|
#include "libc/mem/arraylist2.internal.h"
|
||||||
#include "libc/mem/mem.h"
|
#include "libc/mem/mem.h"
|
||||||
|
#include "libc/runtime/runtime.h"
|
||||||
#include "libc/str/str.h"
|
#include "libc/str/str.h"
|
||||||
#include "libc/str/thompike.h"
|
#include "libc/str/thompike.h"
|
||||||
#include "libc/str/utf16.h"
|
#include "libc/str/utf16.h"
|
||||||
|
@ -91,12 +93,15 @@ static textwindows void FixPath(char *path) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static textwindows void InsertString(char **a, size_t i, char *s,
|
static textwindows void InsertString(char **a, size_t i, char *s,
|
||||||
char buf[ARG_MAX], size_t *bufi) {
|
char buf[ARG_MAX], size_t *bufi,
|
||||||
|
bool *have_systemroot) {
|
||||||
char *v;
|
char *v;
|
||||||
size_t j, k;
|
size_t j, k;
|
||||||
|
|
||||||
|
v = StrChr(s, '=');
|
||||||
|
|
||||||
// apply fixups to var=/c/...
|
// apply fixups to var=/c/...
|
||||||
if ((v = StrChr(s, '=')) && v[1] == '/' && IsAlpha(v[2]) && v[3] == '/') {
|
if (v && v[1] == '/' && IsAlpha(v[2]) && v[3] == '/') {
|
||||||
v = buf + *bufi;
|
v = buf + *bufi;
|
||||||
for (k = 0; s[k]; ++k) {
|
for (k = 0; s[k]; ++k) {
|
||||||
if (*bufi + 1 < ARG_MAX) {
|
if (*bufi + 1 < ARG_MAX) {
|
||||||
|
@ -136,11 +141,25 @@ textwindows int mkntenvblock(char16_t envvars[ARG_MAX / 2], char *const envp[],
|
||||||
uint64_t w;
|
uint64_t w;
|
||||||
char **vars;
|
char **vars;
|
||||||
wint_t x, y;
|
wint_t x, y;
|
||||||
|
bool have_systemroot = false;
|
||||||
size_t i, j, k, n, m, bufi = 0;
|
size_t i, j, k, n, m, bufi = 0;
|
||||||
for (n = 0; envp[n];) n++;
|
for (n = 0; envp[n];) n++;
|
||||||
vars = alloca((n + 1) * sizeof(char *));
|
vars = alloca((n + 1) * sizeof(char *));
|
||||||
for (i = 0; i < n; ++i) InsertString(vars, i, envp[i], buf, &bufi);
|
for (i = 0; i < n; ++i) {
|
||||||
if (extravar) InsertString(vars, n++, extravar, buf, &bufi);
|
InsertString(vars, i, envp[i], buf, &bufi, &have_systemroot);
|
||||||
|
}
|
||||||
|
if (extravar) {
|
||||||
|
InsertString(vars, n++, extravar, buf, &bufi, &have_systemroot);
|
||||||
|
}
|
||||||
|
if (!have_systemroot && environ) {
|
||||||
|
// https://jpassing.com/2009/12/28/the-hidden-danger-of-forgetting-to-specify-systemroot-in-a-custom-environment-block/
|
||||||
|
struct Env systemroot;
|
||||||
|
systemroot = _getenv(environ, "SYSTEMROOT");
|
||||||
|
if (systemroot.s) {
|
||||||
|
InsertString(vars, n++, environ[systemroot.i], buf, &bufi,
|
||||||
|
&have_systemroot);
|
||||||
|
}
|
||||||
|
}
|
||||||
for (k = i = 0; i < n; ++i) {
|
for (k = i = 0; i < n; ++i) {
|
||||||
j = 0;
|
j = 0;
|
||||||
v = false;
|
v = false;
|
||||||
|
|
|
@ -31,17 +31,15 @@
|
||||||
* @param shdr is from GetElfSectionHeaderAddress(), or null
|
* @param shdr is from GetElfSectionHeaderAddress(), or null
|
||||||
* @return pointer to section data within image, or null if
|
* @return pointer to section data within image, or null if
|
||||||
* 1. `shdr` was null, or
|
* 1. `shdr` was null, or
|
||||||
* 2. `sh_size` was zero, or
|
* 2. content wasn't contained within `[elf,elf+mapsize)`, or
|
||||||
* 3, `sh_type` was `SHT_NOBITS`, or
|
* 3. an arithmetic overflow occurred
|
||||||
* 4. content wasn't contained within `[elf,elf+mapsize)`, or
|
|
||||||
* 5. an arithmetic overflow occurred
|
|
||||||
*/
|
*/
|
||||||
void *GetElfSectionAddress(const Elf64_Ehdr *elf, // validated
|
void *GetElfSectionAddress(const Elf64_Ehdr *elf, // validated
|
||||||
size_t mapsize, // validated
|
size_t mapsize, // validated
|
||||||
const Elf64_Shdr *shdr) { // foreign
|
const Elf64_Shdr *shdr) { // foreign
|
||||||
Elf64_Off last;
|
Elf64_Off last;
|
||||||
if (!shdr) return 0;
|
if (!shdr) return 0;
|
||||||
if (shdr->sh_size <= 0) return 0;
|
if (!shdr->sh_size) return elf;
|
||||||
if (shdr->sh_type == SHT_NOBITS) return 0;
|
if (shdr->sh_type == SHT_NOBITS) return 0;
|
||||||
if (ckd_add(&last, shdr->sh_offset, shdr->sh_size)) return 0;
|
if (ckd_add(&last, shdr->sh_offset, shdr->sh_size)) return 0;
|
||||||
if (last > mapsize) return 0;
|
if (last > mapsize) return 0;
|
||||||
|
|
|
@ -18,16 +18,24 @@
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
#include "libc/intrin/describeflags.internal.h"
|
#include "libc/intrin/describeflags.internal.h"
|
||||||
#include "libc/macros.internal.h"
|
#include "libc/macros.internal.h"
|
||||||
|
#include "libc/nt/enum/accessmask.h"
|
||||||
|
#include "libc/nt/enum/fileflagandattributes.h"
|
||||||
#include "libc/nt/enum/filemapflags.h"
|
#include "libc/nt/enum/filemapflags.h"
|
||||||
#include "libc/nt/ipc.h"
|
#include "libc/nt/ipc.h"
|
||||||
|
|
||||||
static const struct DescribeFlags kPipeOpenFlags[] = {
|
static const struct DescribeFlags kPipeOpenFlags[] = {
|
||||||
{kNtPipeAccessDuplex, "Duplex"}, // 0x00000003
|
{kNtPipeAccessDuplex, "kNtPipeAccessDuplex"},
|
||||||
{kNtPipeAccessOutbound, "Outbound"}, // 0x00000002
|
{kNtPipeAccessOutbound, "kNtPipeAccessOutbound"},
|
||||||
{kNtPipeAccessInbound, "Inbound"}, // 0x00000001
|
{kNtPipeAccessInbound, "kNtPipeAccessInbound"},
|
||||||
|
{kNtFileFlagOverlapped, "kNtFileFlagOverlapped"},
|
||||||
|
{kNtFileFlagFirstPipeInstance, "kNtFileFlagFirstPipeInstance"},
|
||||||
|
{kNtFileFlagWriteThrough, "kNtFileFlagWriteThrough"},
|
||||||
|
{kNtWriteDac, "kNtWriteDac"},
|
||||||
|
{kNtWriteOwner, "kNtWriteOwner"},
|
||||||
|
{kNtAccessSystemSecurity, "kNtAccessSystemSecurity"},
|
||||||
};
|
};
|
||||||
|
|
||||||
const char *(DescribeNtPipeOpenFlags)(char buf[64], uint32_t x) {
|
const char *(DescribeNtPipeOpenFlags)(char buf[64], uint32_t x) {
|
||||||
return DescribeFlags(buf, 64, kPipeOpenFlags, ARRAYLEN(kPipeOpenFlags),
|
return DescribeFlags(buf, 64, kPipeOpenFlags, ARRAYLEN(kPipeOpenFlags), "",
|
||||||
"kNtPipeAccess", x);
|
x);
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,10 +17,13 @@
|
||||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
#include "libc/calls/state.internal.h"
|
#include "libc/calls/state.internal.h"
|
||||||
|
#include "libc/fmt/itoa.h"
|
||||||
#include "libc/intrin/describeflags.internal.h"
|
#include "libc/intrin/describeflags.internal.h"
|
||||||
#include "libc/nt/struct/securityattributes.h"
|
#include "libc/nt/struct/securityattributes.h"
|
||||||
|
|
||||||
const char *DescribeNtSecurityAttributes(struct NtSecurityAttributes *p) {
|
const char *(DescribeNtSecurityAttributes)(char buf[32],
|
||||||
|
struct NtSecurityAttributes *p) {
|
||||||
if (p == &kNtIsInheritable) return "&kNtIsInheritable";
|
if (p == &kNtIsInheritable) return "&kNtIsInheritable";
|
||||||
return "0";
|
FormatInt64(buf, (uintptr_t)p);
|
||||||
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#ifndef COSMOPOLITAN_LIBC_NT_STRUCT_SECURITYATTRIBUTES_H_
|
#ifndef COSMOPOLITAN_LIBC_NT_STRUCT_SECURITYATTRIBUTES_H_
|
||||||
#define COSMOPOLITAN_LIBC_NT_STRUCT_SECURITYATTRIBUTES_H_
|
#define COSMOPOLITAN_LIBC_NT_STRUCT_SECURITYATTRIBUTES_H_
|
||||||
|
#include "libc/mem/alloca.h"
|
||||||
#include "libc/nt/struct/securitydescriptor.h"
|
#include "libc/nt/struct/securitydescriptor.h"
|
||||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||||
|
|
||||||
|
@ -9,7 +10,10 @@ struct NtSecurityAttributes {
|
||||||
bool32 bInheritHandle;
|
bool32 bInheritHandle;
|
||||||
};
|
};
|
||||||
|
|
||||||
const char *DescribeNtSecurityAttributes(struct NtSecurityAttributes *);
|
const char *DescribeNtSecurityAttributes(char[32],
|
||||||
|
struct NtSecurityAttributes *);
|
||||||
|
#define DescribeNtSecurityAttributes(x) \
|
||||||
|
DescribeNtSecurityAttributes(alloca(32), x)
|
||||||
|
|
||||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||||
#endif /* COSMOPOLITAN_LIBC_NT_STRUCT_SECURITYATTRIBUTES_H_ */
|
#endif /* COSMOPOLITAN_LIBC_NT_STRUCT_SECURITYATTRIBUTES_H_ */
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
#include "libc/log/log.h"
|
#include "libc/log/log.h"
|
||||||
#include "libc/mem/gc.internal.h"
|
#include "libc/mem/gc.internal.h"
|
||||||
#include "libc/mem/mem.h"
|
#include "libc/mem/mem.h"
|
||||||
|
#include "libc/runtime/runtime.h"
|
||||||
#include "libc/sock/sock.h"
|
#include "libc/sock/sock.h"
|
||||||
#include "libc/sock/struct/ifconf.h"
|
#include "libc/sock/struct/ifconf.h"
|
||||||
#include "libc/sock/struct/ifreq.h"
|
#include "libc/sock/struct/ifreq.h"
|
||||||
|
@ -32,6 +33,7 @@
|
||||||
#include "libc/sysv/consts/ipproto.h"
|
#include "libc/sysv/consts/ipproto.h"
|
||||||
#include "libc/sysv/consts/sio.h"
|
#include "libc/sysv/consts/sio.h"
|
||||||
#include "libc/sysv/consts/sock.h"
|
#include "libc/sysv/consts/sock.h"
|
||||||
|
#include "libc/testlib/subprocess.h"
|
||||||
#include "libc/testlib/testlib.h"
|
#include "libc/testlib/testlib.h"
|
||||||
|
|
||||||
TEST(siocgifconf, test) {
|
TEST(siocgifconf, test) {
|
||||||
|
@ -70,3 +72,12 @@ TEST(siocgifconf, test) {
|
||||||
EXPECT_TRUE(foundloopback);
|
EXPECT_TRUE(foundloopback);
|
||||||
ASSERT_NE(-1, close(socketfd));
|
ASSERT_NE(-1, close(socketfd));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(siocgifconf, mkntenvblock_systemroot) {
|
||||||
|
if (__argc != 1) return;
|
||||||
|
SPAWN(fork);
|
||||||
|
execve(GetProgramExecutableName(),
|
||||||
|
(char *[]){GetProgramExecutableName(), "hi", NULL}, (char *[]){NULL});
|
||||||
|
abort();
|
||||||
|
EXITS(0);
|
||||||
|
}
|
||||||
|
|
|
@ -201,17 +201,18 @@ char buf[PAGESIZE];
|
||||||
char tmpout[PATH_MAX];
|
char tmpout[PATH_MAX];
|
||||||
|
|
||||||
const char *const kSafeEnv[] = {
|
const char *const kSafeEnv[] = {
|
||||||
"ADDR2LINE", // needed by GetAddr2linePath
|
"ADDR2LINE", // needed by GetAddr2linePath
|
||||||
"HOME", // needed by ~/.runit.psk
|
"HOME", // needed by ~/.runit.psk
|
||||||
"HOMEDRIVE", // needed by ~/.runit.psk
|
"HOMEDRIVE", // needed by ~/.runit.psk
|
||||||
"HOMEPATH", // needed by ~/.runit.psk
|
"HOMEPATH", // needed by ~/.runit.psk
|
||||||
"MAKEFLAGS", // needed by IsRunningUnderMake
|
"MAKEFLAGS", // needed by IsRunningUnderMake
|
||||||
"MODE", // needed by test scripts
|
"MODE", // needed by test scripts
|
||||||
"PATH", // needed by clang
|
"PATH", // needed by clang
|
||||||
"PWD", // just seems plain needed
|
"PWD", // just seems plain needed
|
||||||
"STRACE", // useful for troubleshooting
|
"STRACE", // useful for troubleshooting
|
||||||
"TERM", // needed to detect colors
|
"TERM", // needed to detect colors
|
||||||
"TMPDIR", // needed by compiler
|
"TMPDIR", // needed by compiler
|
||||||
|
"SYSTEMROOT", // needed by socket()
|
||||||
};
|
};
|
||||||
|
|
||||||
const char *const kGccOnlyFlags[] = {
|
const char *const kGccOnlyFlags[] = {
|
||||||
|
@ -373,7 +374,11 @@ bool IsSafeEnv(const char *s) {
|
||||||
r = ARRAYLEN(kSafeEnv) - 1;
|
r = ARRAYLEN(kSafeEnv) - 1;
|
||||||
while (l <= r) {
|
while (l <= r) {
|
||||||
m = (l & r) + ((l ^ r) >> 1); // floor((a+b)/2)
|
m = (l & r) + ((l ^ r) >> 1); // floor((a+b)/2)
|
||||||
x = strncmp(s, kSafeEnv[m], n);
|
if (IsWindows()) {
|
||||||
|
x = strncasecmp(s, kSafeEnv[m], n);
|
||||||
|
} else {
|
||||||
|
x = strncmp(s, kSafeEnv[m], n);
|
||||||
|
}
|
||||||
if (x < 0) {
|
if (x < 0) {
|
||||||
r = m - 1;
|
r = m - 1;
|
||||||
} else if (x > 0) {
|
} else if (x > 0) {
|
||||||
|
@ -643,10 +648,6 @@ int Launch(void) {
|
||||||
close(pipefds[1]);
|
close(pipefds[1]);
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if (gotchld) {
|
|
||||||
rc = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (gotalrm) {
|
if (gotalrm) {
|
||||||
PrintRed();
|
PrintRed();
|
||||||
appends(&output, "\n\n`");
|
appends(&output, "\n\n`");
|
||||||
|
|
|
@ -176,13 +176,13 @@ static void RewriteTlsCode(void) {
|
||||||
uint32_t *p, *pe;
|
uint32_t *p, *pe;
|
||||||
for (i = 0; i < elf->e_shnum; ++i) {
|
for (i = 0; i < elf->e_shnum; ++i) {
|
||||||
if (!(shdr = GetElfSectionHeaderAddress(elf, esize, i))) {
|
if (!(shdr = GetElfSectionHeaderAddress(elf, esize, i))) {
|
||||||
Die("elf header overflow");
|
Die("elf header overflow #1");
|
||||||
}
|
}
|
||||||
if (shdr->sh_type == SHT_PROGBITS && //
|
if (shdr->sh_type == SHT_PROGBITS && //
|
||||||
(shdr->sh_flags & SHF_ALLOC) && //
|
(shdr->sh_flags & SHF_ALLOC) && //
|
||||||
(shdr->sh_flags & SHF_EXECINSTR)) {
|
(shdr->sh_flags & SHF_EXECINSTR)) {
|
||||||
if (!(p = GetElfSectionAddress(elf, esize, shdr))) {
|
if (!(p = GetElfSectionAddress(elf, esize, shdr))) {
|
||||||
Die("elf header overflow");
|
Die("elf header overflow #2");
|
||||||
}
|
}
|
||||||
for (pe = p + shdr->sh_size / 4; p <= pe; ++p) {
|
for (pe = p + shdr->sh_size / 4; p <= pe; ++p) {
|
||||||
if ((*p & -32) == MRS_TPIDR_EL0) {
|
if ((*p & -32) == MRS_TPIDR_EL0) {
|
||||||
|
@ -213,11 +213,11 @@ static void OptimizePatchableFunctionEntries(void) {
|
||||||
if (!syms[i].st_size) continue;
|
if (!syms[i].st_size) continue;
|
||||||
if (ELF64_ST_TYPE(syms[i].st_info) != STT_FUNC) continue;
|
if (ELF64_ST_TYPE(syms[i].st_info) != STT_FUNC) continue;
|
||||||
if (!(shdr = GetElfSectionHeaderAddress(elf, esize, syms[i].st_shndx))) {
|
if (!(shdr = GetElfSectionHeaderAddress(elf, esize, syms[i].st_shndx))) {
|
||||||
Die("elf header overflow");
|
Die("elf header overflow #3");
|
||||||
}
|
}
|
||||||
if (shdr->sh_type != SHT_PROGBITS) continue;
|
if (shdr->sh_type != SHT_PROGBITS) continue;
|
||||||
if (!(p = GetElfSectionAddress(elf, esize, shdr))) {
|
if (!(p = GetElfSectionAddress(elf, esize, shdr))) {
|
||||||
Die("elf header overflow");
|
Die("elf header overflow #4");
|
||||||
}
|
}
|
||||||
if (syms[i].st_value < shdr->sh_addr) {
|
if (syms[i].st_value < shdr->sh_addr) {
|
||||||
Die("elf symbol beneath section");
|
Die("elf symbol beneath section");
|
||||||
|
|
|
@ -651,9 +651,9 @@ int main(int argc, char *argv[]) {
|
||||||
if (argc == 2 && !strcmp(argv[1], "-n")) {
|
if (argc == 2 && !strcmp(argv[1], "-n")) {
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
if (!IsOptimized()) {
|
#ifndef NDEBUG
|
||||||
ShowCrashReports();
|
ShowCrashReports();
|
||||||
}
|
#endif
|
||||||
bzero(&pkg, sizeof(pkg));
|
bzero(&pkg, sizeof(pkg));
|
||||||
bzero(&deps, sizeof(deps));
|
bzero(&deps, sizeof(deps));
|
||||||
Package(argc, argv, &pkg, &deps);
|
Package(argc, argv, &pkg, &deps);
|
||||||
|
|
|
@ -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/assert.h"
|
||||||
#include "libc/calls/calls.h"
|
#include "libc/calls/calls.h"
|
||||||
#include "libc/calls/struct/stat.h"
|
#include "libc/calls/struct/stat.h"
|
||||||
#include "libc/elf/def.h"
|
#include "libc/elf/def.h"
|
||||||
|
@ -139,16 +140,27 @@ void ProcessFile(struct ElfWriter *elf, const char *path) {
|
||||||
size_t pathlen;
|
size_t pathlen;
|
||||||
struct stat st;
|
struct stat st;
|
||||||
const char *name;
|
const char *name;
|
||||||
CHECK_NE(-1, (fd = open(path, O_RDONLY)));
|
if (stat(path, &st)) {
|
||||||
CHECK_NE(-1, fstat(fd, &st));
|
perror(path);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
if (S_ISDIR(st.st_mode)) {
|
if (S_ISDIR(st.st_mode)) {
|
||||||
|
if ((fd = open(path, O_RDONLY | O_DIRECTORY)) == -1) {
|
||||||
|
perror(path);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
map = "";
|
map = "";
|
||||||
st.st_size = 0;
|
st.st_size = 0;
|
||||||
} else if (st.st_size) {
|
} else if (st.st_size) {
|
||||||
CHECK_NE(MAP_FAILED,
|
if ((fd = open(path, O_RDONLY)) == -1 ||
|
||||||
(map = mmap(NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0)));
|
(map = mmap(0, st.st_size, PROT_READ, MAP_SHARED, fd, 0)) ==
|
||||||
|
MAP_FAILED) {
|
||||||
|
perror(path);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
map = NULL;
|
fd = -1;
|
||||||
|
map = 0;
|
||||||
}
|
}
|
||||||
if (name_) {
|
if (name_) {
|
||||||
name = name_;
|
name = name_;
|
||||||
|
@ -166,7 +178,9 @@ void ProcessFile(struct ElfWriter *elf, const char *path) {
|
||||||
}
|
}
|
||||||
elfwriter_zip(elf, name, name, strlen(name), map, st.st_size, st.st_mode,
|
elfwriter_zip(elf, name, name, strlen(name), map, st.st_size, st.st_mode,
|
||||||
timestamp, timestamp, timestamp, nocompress_);
|
timestamp, timestamp, timestamp, nocompress_);
|
||||||
if (st.st_size) CHECK_NE(-1, munmap(map, st.st_size));
|
if (st.st_size) {
|
||||||
|
unassert(!munmap(map, st.st_size));
|
||||||
|
}
|
||||||
close(fd);
|
close(fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue