Пример #1
0
static boolean MojoArchive_uz2_enumerate(MojoArchive *ar)
{
    UZ2info *info = (UZ2info *) ar->opaque;
    MojoArchive_resetEntry(&ar->prevEnum);
    info->enumerated = false;
    return true;
} // MojoArchive_uz2_enumerate
static void MojoArchive_tar_close(MojoArchive *ar)
{
    TARinfo *info = (TARinfo *) ar->opaque;
    MojoArchive_resetEntry(&ar->prevEnum);
    ar->io->close(ar->io);
    free(info);
    free(ar);
} // MojoArchive_tar_close
static boolean MojoArchive_tar_enumerate(MojoArchive *ar)
{
    TARinfo *info = (TARinfo *) ar->opaque;
    MojoArchive_resetEntry(&ar->prevEnum);
    if (info->input != NULL)
        fatal("BUG: tar entry still open on new enumeration");
    info->curFileStart = info->nextEnumPos = 0;
    return true;
} // MojoArchive_tar_enumerate
Пример #4
0
static void MojoArchive_uz2_close(MojoArchive *ar)
{
    UZ2info *info = (UZ2info *) ar->opaque;
    MojoArchive_resetEntry(&ar->prevEnum);
    ar->io->close(ar->io);
    free(info->outname);
    free(info);
    free(ar);
} // MojoArchive_uz2_close
Пример #5
0
static void MojoArchive_dir_close(MojoArchive *ar)
{
    MojoArchiveDirInstance *inst = (MojoArchiveDirInstance *) ar->opaque;
    freeDirStack(&inst->dirs);
    free(inst->base);
    free(inst);
    MojoArchive_resetEntry(&ar->prevEnum);
    free(ar);
} // MojoArchive_dir_close
Пример #6
0
static boolean MojoArchive_dir_enumerate(MojoArchive *ar)
{
    MojoArchiveDirInstance *inst = (MojoArchiveDirInstance *) ar->opaque;
    void *dir = NULL;

    freeDirStack(&inst->dirs);
    MojoArchive_resetEntry(&ar->prevEnum);

    dir = MojoPlatform_opendir(inst->base);
    if (dir != NULL)
        pushDirStack(&inst->dirs, inst->base, dir);

    return (dir != NULL);
} // MojoArchive_dir_enumerate
Пример #7
0
static const MojoArchiveEntry *MojoArchive_uz2_enumNext(MojoArchive *ar)
{
    UZ2info *info = (UZ2info *) ar->opaque;

    MojoArchive_resetEntry(&ar->prevEnum);
    if (info->enumerated)
        return NULL;  // only one file in this "archive".

    ar->prevEnum.perms = MojoPlatform_defaultFilePerms();
    ar->prevEnum.filesize = info->outsize;
    ar->prevEnum.filename = xstrdup(info->outname);
    ar->prevEnum.type = MOJOARCHIVE_ENTRY_FILE;

    info->enumerated = true;
    return &ar->prevEnum;
} // MojoArchive_uz2_enumNext
static const MojoArchiveEntry *MojoArchive_tar_enumNext(MojoArchive *ar)
{
    TARinfo *info = (TARinfo *) ar->opaque;
    boolean zeroes = true;
    boolean ustar = false;
    uint8 scratch[512];
    uint8 block[512];
    size_t fnamelen = 0;
    int type = 0;

    memset(scratch, '\0', sizeof (scratch));

    MojoArchive_resetEntry(&ar->prevEnum);
    if (info->input != NULL)
        fatal("BUG: tar entry still open on new enumeration");

    if (!ar->io->seek(ar->io, info->nextEnumPos))
        return NULL;

    // Find a non-zero block of data. Tarballs have two 512 blocks filled with
    //  null bytes at the end of the archive, but you can cat tarballs
    //  together, so you can't treat them as EOF indicators. Just skip them.
    while (zeroes)
    {
        if (ar->io->read(ar->io, block, sizeof (block)) != sizeof (block))
            return NULL;  // !!! FIXME: fatal() ?
        zeroes = (memcmp(block, scratch, sizeof (block)) == 0);
    } // while

    // !!! FIXME We should probably check the checksum.

    ustar = is_ustar(block);

    ar->prevEnum.perms = (uint16) octal_convert(&block[TAR_MODE], TAR_MODELEN);
    ar->prevEnum.filesize = octal_convert(&block[TAR_SIZE], TAR_SIZELEN);
    info->curFileStart = info->nextEnumPos + 512;
    info->nextEnumPos += 512 + ar->prevEnum.filesize;
    if (ar->prevEnum.filesize % 512)
        info->nextEnumPos += 512 - (ar->prevEnum.filesize % 512);

    // We count on (scratch) being zeroed out here!
    // prefix of filename is at the end for legacy compat.
    if (ustar)
        memcpy(scratch, &block[TAR_FNAMEPRE], TAR_FNAMEPRELEN);
    fnamelen = strlen((const char *) scratch);
    memcpy(&scratch[fnamelen], &block[TAR_FNAME], TAR_FNAMELEN);
    fnamelen += strlen((const char *) &scratch[fnamelen]);

    if (fnamelen == 0)
        return NULL;   // corrupt file.  !!! FIXME: fatal() ?

    ar->prevEnum.filename = xstrdup((const char *) scratch);

    type = block[TAR_TYPE];
    if (type == 0)  // some archivers do the file type as 0 instead of '0'.
        type = TAR_TYPE_FILE;

    if (ar->prevEnum.filename[fnamelen-1] == '/')
    {
        while (ar->prevEnum.filename[fnamelen-1] == '/')
            ar->prevEnum.filename[--fnamelen] = '\0';

        // legacy tar entries don't have a dir type, they just append a '/' to
        //  the filename...
        if ((!ustar) && (type == TAR_TYPE_FILE))
            type = TAR_TYPE_DIRECTORY;
    } // if

    ar->prevEnum.type = MOJOARCHIVE_ENTRY_UNKNOWN;
    if (type == TAR_TYPE_FILE)
        ar->prevEnum.type = MOJOARCHIVE_ENTRY_FILE;
    else if (type == TAR_TYPE_DIRECTORY)
        ar->prevEnum.type = MOJOARCHIVE_ENTRY_DIR;
    else if (type == TAR_TYPE_SYMLINK)
    {
        ar->prevEnum.type = MOJOARCHIVE_ENTRY_SYMLINK;
        memcpy(scratch, &block[TAR_LINKNAME], TAR_LINKNAMELEN);
        scratch[TAR_LINKNAMELEN] = '\0';  // just in case.
        ar->prevEnum.linkdest = xstrdup((const char *) scratch);
    } // else if

    return &ar->prevEnum;
} // MojoArchive_tar_enumNext
Пример #9
0
static const MojoArchiveEntry *MojoArchive_dir_enumNext(MojoArchive *ar)
{
    uint16 perms = 0644; //(S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
    char *fullpath = NULL;
    char *dent = NULL;  // "dent" == "directory entry"
    MojoArchiveDirInstance *inst = (MojoArchiveDirInstance *) ar->opaque;
    const char *basepath;

    MojoArchive_resetEntry(&ar->prevEnum);

    if (inst->dirs == NULL)
        return NULL;

    basepath = inst->dirs->basepath;

    // if readdir fails, it's end of dir (!!! FIXME: what about i/o failures?)
    dent = MojoPlatform_readdir(inst->dirs->dir);
    if (dent == NULL)  // end of dir?
    {
        popDirStack(&inst->dirs);
        return MojoArchive_dir_enumNext(ar);  // try higher level in tree.
    } // if

    // MojoPlatform layer shouldn't return "." or ".." paths.
    assert((strcmp(dent, ".") != 0) && (strcmp(dent, "..") != 0));

    fullpath = (char *) xmalloc(strlen(basepath) + strlen(dent) + 2);
    sprintf(fullpath, "%s/%s", basepath, dent);
    free(dent);

    ar->prevEnum.filename = xstrdup(fullpath + strlen(inst->base) + 1);
    ar->prevEnum.filesize = 0;
    ar->prevEnum.type = MOJOARCHIVE_ENTRY_UNKNOWN;

    // We currently force the perms from physical files, since CDs on
    //  Linux tend to mark every files as executable and read-only. If you
    //  want to install something with specific permissions, wrap it in a
    //  tarball, or use Setup.File.permissions, or return a permissions
    //  string from Setup.File.filter.
    //MojoPlatform_perms(fullpath, &perms);
    ar->prevEnum.perms = perms;

    if (MojoPlatform_isfile(fullpath))
    {
        ar->prevEnum.type = MOJOARCHIVE_ENTRY_FILE;
        ar->prevEnum.filesize = MojoPlatform_filesize(fullpath);
    } // if

    else if (MojoPlatform_issymlink(fullpath))
    {
        ar->prevEnum.type = MOJOARCHIVE_ENTRY_SYMLINK;
        ar->prevEnum.linkdest = MojoPlatform_readlink(fullpath);
        if (ar->prevEnum.linkdest == NULL)
        {
            free(fullpath);
            return MojoArchive_dir_enumNext(ar);
        } // if
    } // else if

    else if (MojoPlatform_isdir(fullpath))
    {
        void *dir = MojoPlatform_opendir(fullpath);
        ar->prevEnum.type = MOJOARCHIVE_ENTRY_DIR;
        if (dir == NULL)
        {
            free(fullpath);
            return MojoArchive_dir_enumNext(ar);
        } // if

        // push this dir on the stack. Next enum will start there.
        pushDirStack(&inst->dirs, fullpath, dir);
    } // else if

    else
    {
        assert(false && "possible file i/o error?");
    } // else

    free(fullpath);
    return &ar->prevEnum;
} // MojoArchive_dir_enumNext
Пример #10
0
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