diff options
| -rw-r--r-- | fake-winterop.c | 17 | ||||
| -rwxr-xr-x | makecab.py | 107 |
2 files changed, 112 insertions, 12 deletions
diff --git a/fake-winterop.c b/fake-winterop.c index eb891c4..cc69179 100644 --- a/fake-winterop.c +++ b/fake-winterop.c | |||
| @@ -26,7 +26,6 @@ uint32_t ResetAcls(const char16_t **pwzFiles, uint32_t cFiles) | |||
| 26 | } | 26 | } |
| 27 | 27 | ||
| 28 | typedef struct CabCreateContext { | 28 | typedef struct CabCreateContext { |
| 29 | char *tempdir; | ||
| 30 | char *outdir; | 29 | char *outdir; |
| 31 | char *outfile; | 30 | char *outfile; |
| 32 | 31 | ||
| @@ -43,14 +42,11 @@ uint32_t CreateCabBegin(const char16_t *wzCab, const char16_t *wzCabDir, | |||
| 43 | ctx->outdir = ascii(wzCabDir, true); | 42 | ctx->outdir = ascii(wzCabDir, true); |
| 44 | ctx->outfile = dupcat(ctx->outdir, "/", | 43 | ctx->outfile = dupcat(ctx->outdir, "/", |
| 45 | ascii(wzCab, true), (const char *)NULL); | 44 | ascii(wzCab, true), (const char *)NULL); |
| 46 | ctx->tempdir = dupcat(ctx->outdir, "/cabXXXXXX", (const char *)NULL); | ||
| 47 | if (!mkdtemp(ctx->tempdir)) | ||
| 48 | err(1, "mkdtemp"); | ||
| 49 | ctx->nargs = 0; | 45 | ctx->nargs = 0; |
| 50 | ctx->argsize = 16; | 46 | ctx->argsize = 16; |
| 51 | ctx->args = snewn(ctx->argsize, char *); | 47 | ctx->args = snewn(ctx->argsize, char *); |
| 52 | ctx->args[ctx->nargs++] = dupcat("lcab", (const char *)NULL); | 48 | ctx->args[ctx->nargs++] = dupcat("makecab.py", (const char *)NULL); |
| 53 | ctx->args[ctx->nargs++] = dupcat("-n", (const char *)NULL); | 49 | ctx->args[ctx->nargs++] = ctx->outfile; |
| 54 | *out_ctx = ctx; | 50 | *out_ctx = ctx; |
| 55 | return 0; | 51 | return 0; |
| 56 | } | 52 | } |
| @@ -61,16 +57,14 @@ uint32_t CreateCabAddFile(const char16_t *wzFile, const char16_t *wzToken, | |||
| 61 | char *file = ascii(wzFile, true); | 57 | char *file = ascii(wzFile, true); |
| 62 | char *file_abs = realpath(file, NULL); | 58 | char *file_abs = realpath(file, NULL); |
| 63 | char *cabname = ascii(wzToken, true); | 59 | char *cabname = ascii(wzToken, true); |
| 64 | char *cab_abs = dupcat(ctx->tempdir, "/", cabname, (const char *)NULL); | ||
| 65 | printf("CreateCabAddFile: %s :: %s <- %s\n", ctx->outfile, | 60 | printf("CreateCabAddFile: %s :: %s <- %s\n", ctx->outfile, |
| 66 | cabname, file_abs); | 61 | cabname, file_abs); |
| 67 | if (symlink(file_abs, cab_abs) < 0) | ||
| 68 | err(1, "symlink"); | ||
| 69 | if (ctx->nargs + 1 >= ctx->argsize) { | 62 | if (ctx->nargs + 1 >= ctx->argsize) { |
| 70 | ctx->argsize = ctx->nargs * 5 / 4 + 16; | 63 | ctx->argsize = ctx->nargs * 5 / 4 + 16; |
| 71 | ctx->args = sresize(ctx->args, ctx->argsize, char *); | 64 | ctx->args = sresize(ctx->args, ctx->argsize, char *); |
| 72 | } | 65 | } |
| 73 | ctx->args[ctx->nargs++] = cab_abs; | 66 | ctx->args[ctx->nargs++] = cabname; |
| 67 | ctx->args[ctx->nargs++] = file_abs; | ||
| 74 | return 0; | 68 | return 0; |
| 75 | } | 69 | } |
| 76 | 70 | ||
| @@ -86,11 +80,10 @@ uint32_t CreateCabAddFiles(const char16_t *const *pwzFiles, | |||
| 86 | 80 | ||
| 87 | uint32_t CreateCabFinish(CabCreateContext *ctx, void (*split_callback)(void)) | 81 | uint32_t CreateCabFinish(CabCreateContext *ctx, void (*split_callback)(void)) |
| 88 | { | 82 | { |
| 89 | if (ctx->nargs + 2 >= ctx->argsize) { | 83 | if (ctx->nargs + 1 >= ctx->argsize) { |
| 90 | ctx->argsize = ctx->nargs * 5 / 4 + 16; | 84 | ctx->argsize = ctx->nargs * 5 / 4 + 16; |
| 91 | ctx->args = sresize(ctx->args, ctx->argsize, char *); | 85 | ctx->args = sresize(ctx->args, ctx->argsize, char *); |
| 92 | } | 86 | } |
| 93 | ctx->args[ctx->nargs++] = ctx->outfile; | ||
| 94 | ctx->args[ctx->nargs++] = NULL; | 87 | ctx->args[ctx->nargs++] = NULL; |
| 95 | system_argv_array(ctx->args); | 88 | system_argv_array(ctx->args); |
| 96 | return 0; | 89 | return 0; |
diff --git a/makecab.py b/makecab.py new file mode 100755 index 0000000..befa94a --- /dev/null +++ b/makecab.py | |||
| @@ -0,0 +1,107 @@ | |||
| 1 | #!/usr/bin/env python | ||
| 2 | |||
| 3 | import sys | ||
| 4 | import os | ||
| 5 | import time | ||
| 6 | import zlib | ||
| 7 | import struct | ||
| 8 | from collections import namedtuple | ||
| 9 | |||
| 10 | CFHEADER_s = struct.Struct("<4sLLLLLBBHHHHH") | ||
| 11 | CFHEADER = namedtuple("CFHEADER", "sig res0 size res1 firstfile res2 " | ||
| 12 | "verminor vermajor folders files flags setid icabinet") | ||
| 13 | CFHEADER_sig = "MSCF" | ||
| 14 | |||
| 15 | CFFOLDER_s = struct.Struct("<LHH") | ||
| 16 | CFFOLDER = namedtuple("CFFOLDER", "firstdata ndata compresstype") | ||
| 17 | |||
| 18 | CFFILE_s = struct.Struct("<LLHHHH") | ||
| 19 | CFFILE = namedtuple("CFFILE", "size offset ifolder date time attrs") | ||
| 20 | |||
| 21 | CFDATA_s = struct.Struct("<LHH") | ||
| 22 | CFDATA = namedtuple("CFDATA", "checksum compressedlen uncompressedlen") | ||
| 23 | |||
| 24 | def mszip(data): | ||
| 25 | compressor = zlib.compressobj(9, zlib.DEFLATED, -zlib.MAX_WBITS, | ||
| 26 | zlib.DEF_MEM_LEVEL, zlib.Z_DEFAULT_STRATEGY) | ||
| 27 | compressed = compressor.compress(data) | ||
| 28 | compressed += compressor.flush() | ||
| 29 | return "CK" + compressed # add MSZIP header | ||
| 30 | |||
| 31 | def packdate(y,m,d): | ||
| 32 | return ((y - 1980) << 9) | (m << 5) | d | ||
| 33 | def packtime(h,m,s): | ||
| 34 | return ((h << 11) | (m << 5) | (s >> 1)) | ||
| 35 | |||
| 36 | def checksum(data): | ||
| 37 | data += "\0" * (3 & -len(data)) # pad to multiple of 4 bytes | ||
| 38 | toret = 0 | ||
| 39 | for offset in xrange(0, len(data), 4): | ||
| 40 | toret ^= struct.unpack_from("<L", data, offset)[0] | ||
| 41 | return toret | ||
| 42 | |||
| 43 | def build_cab(files): | ||
| 44 | uncompressed_data = "" | ||
| 45 | fileheaders = "" | ||
| 46 | for name, data, mtime in files: | ||
| 47 | mtime_u = time.gmtime(mtime) | ||
| 48 | fileheader = CFFILE( | ||
| 49 | size=len(data), offset=len(uncompressed_data), ifolder=0, attrs=0, | ||
| 50 | date=packdate(mtime_u.tm_year, mtime_u.tm_mon, mtime_u.tm_mday), | ||
| 51 | time=packtime(mtime_u.tm_hour, mtime_u.tm_min, mtime_u.tm_sec)) | ||
| 52 | uncompressed_data += data | ||
| 53 | fileheaders += CFFILE_s.pack(*fileheader) + name + "\0" | ||
| 54 | |||
| 55 | compressed_data = "" | ||
| 56 | offset = 0 | ||
| 57 | n_data_blocks = 0 | ||
| 58 | while offset < len(uncompressed_data): | ||
| 59 | uncompressed_block = uncompressed_data[offset:offset+0x8000] | ||
| 60 | compressed_block = mszip(uncompressed_block) | ||
| 61 | blockheader = CFDATA( | ||
| 62 | checksum=0, | ||
| 63 | compressedlen=len(compressed_block), | ||
| 64 | uncompressedlen=len(uncompressed_block)) | ||
| 65 | header_after_checksum = CFDATA_s.pack(*blockheader)[4:] | ||
| 66 | blockheader = blockheader._replace( | ||
| 67 | checksum=checksum(header_after_checksum + compressed_block)) | ||
| 68 | compressed_data += CFDATA_s.pack(*blockheader) + compressed_block | ||
| 69 | offset += len(uncompressed_block) | ||
| 70 | n_data_blocks += 1 | ||
| 71 | |||
| 72 | totalsize = (CFHEADER_s.size + | ||
| 73 | CFFOLDER_s.size + | ||
| 74 | len(fileheaders) + | ||
| 75 | len(compressed_data)) | ||
| 76 | |||
| 77 | header = CFHEADER( | ||
| 78 | sig=CFHEADER_sig, res0=0, res1=0, res2=0, | ||
| 79 | vermajor=1, verminor=3, folders=1, files=len(files), | ||
| 80 | flags=0, setid=0, icabinet=0, size=totalsize, | ||
| 81 | firstfile=CFHEADER_s.size + CFFOLDER_s.size) | ||
| 82 | |||
| 83 | folder = CFFOLDER( | ||
| 84 | ndata=n_data_blocks, compresstype=1, | ||
| 85 | firstdata = (CFHEADER_s.size + CFFOLDER_s.size + len(fileheaders))) | ||
| 86 | |||
| 87 | return (CFHEADER_s.pack(*header) + | ||
| 88 | CFFOLDER_s.pack(*folder) + | ||
| 89 | fileheaders + | ||
| 90 | compressed_data) | ||
| 91 | |||
| 92 | def main(): | ||
| 93 | args = sys.argv[1:] | ||
| 94 | outfile = args.pop(0) | ||
| 95 | files = [] | ||
| 96 | while len(args) > 0: | ||
| 97 | cabname = args.pop(0) | ||
| 98 | filename = args.pop(0) | ||
| 99 | with open(filename, "rb") as f: | ||
| 100 | filedata = f.read() | ||
| 101 | files.append((cabname, filedata, os.stat(filename).st_mtime)) | ||
| 102 | cabdata = build_cab(files) | ||
| 103 | with open(outfile, "wb") as f: | ||
| 104 | f.write(cabdata) | ||
| 105 | |||
| 106 | if __name__ == '__main__': | ||
| 107 | main() | ||
