예제 #1
0
static int64 MojoInput_uz2_read(MojoInput *io, void *_buf, uint32 bufsize)
{
    uint8 *buf = (uint8 *) _buf;
    UZ2input *input = (UZ2input *) io->opaque;
    int64 retval = 0;
    while (bufsize > 0)
    {
        const uint32 available = input->uncompsize - input->uncompindex;
        const uint32 cpy = (available < bufsize) ? available : bufsize;
        if (available == 0)
        {
            if (input->position == input->fsize)
                return 0;
            else if (!MojoInput_readui32(input->io, &input->compsize))
                return (retval == 0) ? -1 : retval;
            else if (!MojoInput_readui32(input->io, &input->uncompsize))
                return (retval == 0) ? -1 : retval;
            else if (!unpack(input))
                return (retval == 0) ? -1 : retval;
            continue;  // try again.
        } // if

        memcpy(buf, input->uncompbuf + input->uncompindex, cpy);
        buf += cpy;
        bufsize -= cpy;
        retval += cpy;
        input->uncompindex += cpy;
        input->position += cpy;
    } // while

    return retval;
} // MojoInput_uz2_read
예제 #2
0
// Unfortunately, we have to walk the whole file, but we don't have to actually
//  do any decompression work here. Just seek, read 8 bytes, repeat until EOF.
static int64 calculate_uz2_outsize(MojoInput *io)
{
    int64 retval = 0;
    uint32 compsize = 0;
    uint32 uncompsize = 0;
    int64 pos = 0;

    if (!io->seek(io, 0))
        return -1;

    while (MojoInput_readui32(io, &compsize))
    {
        if (!MojoInput_readui32(io, &uncompsize))
            return -1;
        else if ((compsize > MAXCOMPSIZE) || (uncompsize > MAXUNCOMPSIZE))
            return -1;
        else if ((compsize == 0) || (uncompsize == 0))
            return -1;
        retval += uncompsize;
        pos += (sizeof (uint32) * 2) + compsize;
        if (!io->seek(io, pos))
            return -1;
    } // while

    if (!io->seek(io, 0))  // make sure we're back to the start.
        return -1;

    return retval;
} // calculate_uz2_outsize
MojoArchive *MojoArchive_createPCK(MojoInput *io)
{
    MojoArchive *ar = NULL;
    PCKinfo *pckInfo = NULL;
    PCKheader pckHeader;

    if (!MojoInput_readui32(io, &pckHeader.Magic))
        return NULL;
    else if (!MojoInput_readui32(io, &pckHeader.StartOfBinaryData))
        return NULL;

    // Check if this is a *.pck file.
    if (pckHeader.Magic != PCK_MAGIC)
        return NULL;

    pckInfo = (PCKinfo *) xmalloc(sizeof (PCKinfo));
    pckInfo->dataStart = pckHeader.StartOfBinaryData + sizeof (PCKheader);

    ar = (MojoArchive *) xmalloc(sizeof (MojoArchive));
    ar->opaque = pckInfo;
    ar->enumerate = MojoArchive_pck_enumerate;
    ar->enumNext = MojoArchive_pck_enumNext;
    ar->openCurrentEntry = MojoArchive_pck_openCurrentEntry;
    ar->close = MojoArchive_pck_close;
    ar->io = io;

    return ar;
} // MojoArchive_createPCK
예제 #4
0
static boolean MojoInput_uz2_seek(MojoInput *io, uint64 pos)
{
    UZ2input *input = (UZ2input *) io->opaque;
    int64 seekpos = 0;

    // in a perfect world, this wouldn't seek from the start if moving
    //  forward. But oh well.
    input->position = 0;
    while (input->position < pos)
    {
        if (!input->io->seek(input->io, seekpos))
            return false;
        else if (!MojoInput_readui32(io, &input->compsize))
            return false;
        else if (!MojoInput_readui32(io, &input->uncompsize))
            return false;

        // we checked these formally elsewhere.
        assert(input->compsize > 0);
        assert(input->uncompsize > 0);
        assert(input->compsize <= MAXCOMPSIZE);
        assert(input->uncompsize <= MAXUNCOMPSIZE);

        input->position += input->uncompsize;
        seekpos += (sizeof (uint32) * 2) + input->compsize;
    } // while

    // we are positioned on the compressed block that contains the seek target.
    if (!unpack(input))
        return false;

    input->position -= input->uncompsize;
    input->uncompindex = (uint32) (pos - input->position);
    input->position += input->uncompindex;

    return true;
} // MojoInput_uz2_seek
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