static int64 MojoInput_xz_read(MojoInput *io, void *buf, uint32 bufsize) { XZinfo *info = (XZinfo *) io->opaque; MojoInput *origio = info->origio; int64 retval = 0; if (bufsize == 0) return 0; // quick rejection. info->stream.next_out = buf; info->stream.avail_out = bufsize; while (retval < ((int64) bufsize)) { const uint32 before = info->stream.total_out; lzma_ret rc; lzma_action action = LZMA_FINISH; if (info->stream.avail_in == 0) { int64 br = origio->length(origio) - origio->tell(origio); if (br > 0) { action = LZMA_RUN; if (br > XZ_READBUFSIZE) br = XZ_READBUFSIZE; br = origio->read(origio, info->buffer, (uint32) br); if (br <= 0) return -1; info->stream.next_in = info->buffer; info->stream.avail_in = (uint32) br; } // if } // if rc = lzma_code(&info->stream, LZMA_RUN); retval += (info->stream.total_out - before); if (rc != LZMA_OK) return -1; } // while assert(retval >= 0); info->uncompressed_position += (uint32) retval; return retval; } // MojoInput_xz_read
static int64 MojoInput_gzip_read(MojoInput *io, void *buf, uint32 bufsize) { GZIPinfo *info = (GZIPinfo *) io->opaque; MojoInput *origio = info->origio; int64 retval = 0; if (bufsize == 0) return 0; // quick rejection. info->stream.next_out = buf; info->stream.avail_out = bufsize; while (retval < ((int64) bufsize)) { const uint32 before = info->stream.total_out; int rc; if (info->stream.avail_in == 0) { int64 br = origio->length(origio) - origio->tell(origio); if (br > 0) { if (br > GZIP_READBUFSIZE) br = GZIP_READBUFSIZE; br = origio->read(origio, info->buffer, (uint32) br); if (br <= 0) return -1; info->stream.next_in = info->buffer; info->stream.avail_in = (uint32) br; } // if } // if rc = inflate(&info->stream, Z_SYNC_FLUSH); retval += (info->stream.total_out - before); if ((rc == Z_STREAM_END) && (retval == 0)) return 0; else if ((rc != Z_OK) && (rc != Z_STREAM_END)) return -1; } // while assert(retval >= 0); info->uncompressed_position += (uint32) retval; return retval; } // MojoInput_gzip_read
static int64 MojoInput_bzip2_read(MojoInput *io, void *buf, uint32 bufsize) { BZIP2info *info = (BZIP2info *) io->opaque; MojoInput *origio = info->origio; int64 retval = 0; if (bufsize == 0) return 0; // quick rejection. info->stream.next_out = buf; info->stream.avail_out = bufsize; while (retval < ((int64) bufsize)) { const uint32 before = info->stream.total_out_lo32; int rc; if (info->stream.avail_in == 0) { int64 br = origio->length(origio) - origio->tell(origio); if (br > 0) { if (br > BZIP2_READBUFSIZE) br = BZIP2_READBUFSIZE; br = origio->read(origio, info->buffer, (uint32) br); if (br <= 0) return -1; info->stream.next_in = (char *) info->buffer; info->stream.avail_in = (uint32) br; } // if } // if rc = BZ2_bzDecompress(&info->stream); retval += (info->stream.total_out_lo32 - before); if (rc != BZ_OK) return -1; } // while assert(retval >= 0); info->uncompressed_position += (uint32) retval; return retval; } // MojoInput_bzip2_read
static void trySwitchBinary(MojoArchive *ar) { MojoInput *io = ar->openCurrentEntry(ar); if (io != NULL) { const uint32 imglen = (uint32) io->length(io); uint8 *img = (uint8 *) xmalloc(imglen); const uint32 br = io->read(io, img, imglen); io->close(io); if (br == imglen) { logInfo("Switching binary with '%0'...", ar->prevEnum.filename); MojoPlatform_switchBin(img, imglen); // no return on success. logError("...Switch binary failed."); } // if free(img); } // if } // trySwitchBinary
static boolean unpack(UZ2input *inp) { MojoInput *io = inp->io; uLongf ul = (uLongf) inp->uncompsize; // we checked these formally elsewhere. assert(inp->compsize > 0); assert(inp->uncompsize > 0); assert(inp->compsize <= MAXCOMPSIZE); assert(inp->uncompsize <= MAXUNCOMPSIZE); if (io->read(io, inp->compbuf, inp->compsize) != inp->compsize) return false; if (uncompress(inp->uncompbuf, &ul, inp->compbuf, inp->compsize) != Z_OK) return false; if (ul != ((uLongf) inp->uncompsize)) // corrupt data. return false; inp->uncompindex = 0; return true; } // unpack
int MojoSetup_testNetworkCode(int argc, char **argv) { int i; fprintf(stderr, "Testing networking code...\n\n"); for (i = 1; i < argc; i++) { static char buf[64 * 1024]; uint32 start = 0; const char *url = argv[i]; int64 length = -1; int64 total_br = 0; int64 br = 0; printf("\n\nFetching '%s' ...\n", url); MojoInput *io = MojoInput_newFromURL(url); if (io == NULL) { fprintf(stderr, "failed!\n"); continue; } // if start = MojoPlatform_ticks(); while (!io->ready(io)) MojoPlatform_sleep(10); fprintf(stderr, "took about %d ticks to get started\n", (int) (MojoPlatform_ticks() - start)); length = io->length(io); fprintf(stderr, "Ready to read (%lld) bytes.\n", (long long) length); do { start = MojoPlatform_ticks(); if (!io->ready(io)) { fprintf(stderr, "Not ready!\n"); while (!io->ready(io)) MojoPlatform_sleep(10); fprintf(stderr, "took about %d ticks to get ready\n", (int) (MojoPlatform_ticks() - start)); } // if start = MojoPlatform_ticks(); br = io->read(io, buf, sizeof (buf)); fprintf(stderr, "read blocked for about %d ticks\n", (int) (MojoPlatform_ticks() - start)); if (br > 0) { total_br += br; fprintf(stderr, "read %lld bytes\n", (long long) br); fwrite(buf, br, 1, stdout); } // if } while (br > 0); if (br < 0) fprintf(stderr, "ERROR IN TRANSMISSION.\n\n"); else { fprintf(stderr, "TRANSMISSION COMPLETE!\n\n"); fprintf(stderr, "(Read %lld bytes, expected %lld.)\n", (long long) total_br, length); } // else io->close(io); } // for return 0; } // MojoSetup_testNetworkCode
MojoArchive *MojoArchive_initBaseArchive(void) { char *basepath = NULL; const char *cmd = NULL; MojoInput *io = NULL; if (GBaseArchive != NULL) return GBaseArchive; // already initialized. if ((cmd = cmdlinestr("base", "MOJOSETUP_BASE", NULL)) != NULL) { char *real = MojoPlatform_realpath(cmd); if (real != NULL) { if (MojoPlatform_isdir(real)) GBaseArchive = MojoArchive_newFromDirectory(real); else { io = MojoInput_newFromFile(real); if (io != NULL) GBaseArchive = MojoArchive_newFromInput(io, real); } // else if (GBaseArchive != NULL) basepath = real; else free(real); } // if } // else if else { basepath = MojoPlatform_appBinaryPath(); if (basepath != NULL) { io = MojoInput_newFromFile(basepath); if (io != NULL) { // See if there's a MOJOBASE signature at the end of the // file. This means we appended an archive to the executable, // for a self-extracting installer. This method works with // any archive type, even if it wasn't specifically designed // to be appended. uint8 buf[8]; uint64 size = 0; const int64 flen = io->length(io) - 16; if ( (flen > 0) && (io->seek(io, flen)) && (io->read(io, buf, 8) == 8) && (memcmp(buf, "MOJOBASE", 8) == 0) && (MojoInput_readui64(io, &size)) && (size < flen) ) { MojoInput *newio; newio = MojoInput_newFromSubset(io, flen - size, flen); if (newio != NULL) io = newio; } // if GBaseArchive = MojoArchive_newFromInput(io, basepath); } // if if (GBaseArchive == NULL) { // Just use the same directory as the binary instead. char *ptr = strrchr(basepath, '/'); if (ptr != NULL) *ptr = '\0'; else { free(basepath); // oh well, try cwd. basepath = MojoPlatform_currentWorkingDir(); } // else GBaseArchive = MojoArchive_newFromDirectory(basepath); // !!! FIXME: failing this, maybe default.mojosetup? } // if } // if } // else if (GBaseArchive == NULL) { free(basepath); basepath = NULL; } // if GBaseArchivePath = basepath; return GBaseArchive; } // MojoArchive_initBaseArchive
static boolean MojoArchive_pck_enumerate(MojoArchive *ar) { MojoArchiveEntry *archiveEntries = NULL; PCKinfo *info = (PCKinfo *) ar->opaque; const int dataStart = info->dataStart; const int fileCount = dataStart / sizeof (PCKentry); const size_t len = fileCount * sizeof (MojoArchiveEntry); PCKentry fileEntry; uint64 i, realFileCount = 0; char directory[256] = {'\0'}; MojoInput *io = ar->io; MojoArchive_resetEntry(&ar->prevEnum); archiveEntries = (MojoArchiveEntry *) xmalloc(len); for (i = 0; i < fileCount; i++) { int dotdot; int64 br; br = io->read(io, fileEntry.filename, sizeof (fileEntry.filename)); if (br != sizeof (fileEntry.filename)) return false; else if (!MojoInput_readui32(io, &fileEntry.filesize)) return false; dotdot = (strcmp(fileEntry.filename, "..") == 0); if ((!dotdot) && (fileEntry.filesize == 0x80000000)) { MojoArchiveEntry *entry = &archiveEntries[realFileCount]; strcat(directory, fileEntry.filename); strcat(directory, "/"); entry->filename = xstrdup(directory); entry->type = MOJOARCHIVE_ENTRY_DIR; entry->perms = MojoPlatform_defaultDirPerms(); entry->filesize = 0; realFileCount++; } // if else if ((dotdot) && (fileEntry.filesize == 0x80000000)) { // remove trailing path separator char *pathSep; const size_t strLength = strlen(directory); directory[strLength - 1] = '\0'; pathSep = strrchr(directory, '/'); if(pathSep != NULL) { pathSep++; *pathSep = '\0'; } // if } // else if else { MojoArchiveEntry *entry = &archiveEntries[realFileCount]; if (directory[0] == '\0') entry->filename = xstrdup(fileEntry.filename); else { const size_t len = sizeof (char) * strlen(directory) + strlen(fileEntry.filename) + 1; entry->filename = (char *) xmalloc(len); strcat(entry->filename, directory); strcat(entry->filename, fileEntry.filename); } // else entry->perms = MojoPlatform_defaultFilePerms(); entry->type = MOJOARCHIVE_ENTRY_FILE; entry->filesize = fileEntry.filesize; realFileCount++; } // else } // for info->fileCount = realFileCount; info->archiveEntries = archiveEntries; info->nextEnumPos = 0; info->nextFileStart = dataStart; return true; } // MojoArchive_pck_enumerate