Example #1
0
static pak_file_t *pak_open(const char *file, const char *mode) {
    if (!file || !mode)
        return NULL;

    switch (*mode) {
        case 'r': return pak_open_read (file);
        case 'w': return pak_open_write(file);
    }

    return NULL;
}
Example #2
0
void make_pak(char *input, char *output, bool compress, bool verbose) {

    time_last = time(NULL);
    DIR* dir;
    struct dirent * dent;
    char* basepath = input;
    dir = opendir(basepath);
    if (!dir) {
        exit(EXIT_FAILURE);
    }

    pak_handle_t* handle = pak_open_write(output);

    printf("Building entry, string and data files...");
    fflush(stdout);

    char dataTempNam[FILENAME_MAX];
    gen_random(dataTempNam, 44);
    char dataTempPath[FILENAME_MAX];
    memset(dataTempPath, 0, FILENAME_MAX);
    sprintf(dataTempPath, "/tmp/%s.data", dataTempNam);
    char stringTempPath[FILENAME_MAX];
    memset(stringTempPath, 0, FILENAME_MAX);
    sprintf(stringTempPath, "/tmp/%s.string", dataTempNam);
    char entryTempPath[FILENAME_MAX];
    memset(entryTempPath, 0, FILENAME_MAX);
    sprintf(entryTempPath, "/tmp/%s.entry", dataTempNam);
    FILE* dataFile = fopen(dataTempPath, "wb");
    FILE* entryFile  = fopen(entryTempPath, "wb");
    FILE* stringFile = fopen(stringTempPath, "wb");

    uint64_t idx = 0;
    while ((dent = readdir(dir)) != NULL)
    {
        if ((time(NULL) - time_last) > 1)
        {
            printf(".");
            fflush(stdout);
            time_last = time(NULL);
        }
        if (!strcmp(dent->d_name, ".") || !strcmp(dent->d_name, ".."))
            continue;

        curpath[0] = '\0';
        strcat(curpath, basepath);
        idx = pak_file_or_dir(dent, idx, entryFile, stringFile, dataFile, compress, verbose);
    }

    printf("\nBuilding pak...\n");
    closedir(dir);
    fclose(dataFile);
    fclose(stringFile);
    fclose(entryFile);

    // now to build the file
    // first reopen the temp data
    struct stat64 st;
    entryFile = fopen(entryTempPath, "rb");
    stringFile = fopen(stringTempPath, "rb");
    dataFile = fopen(dataTempPath, "rb");

    // read entry table
    stat64(entryTempPath, &st);
    size_t entryTableSize = st.st_size;
    size_t entryCount = entryTableSize / sizeof(pak_entry_t);
    char* entryTableBuf = malloc(entryTableSize);
    fread(entryTableBuf, 1, entryTableSize, entryFile);

    // read string table
    stat64(stringTempPath, &st);
    size_t stringTableSize = st.st_size;
    char* stringTableBuf = malloc(stringTableSize);
    fread(stringTableBuf, 1, stringTableSize, stringFile);

    // read data table
    stat64(dataTempPath, &st);
    size_t dataTableSize = st.st_size;

    // close files
    fclose(entryFile);
    fclose(stringFile);

    // TODO: Make this manageable
    pak_set_entry_start(handle, (sizeof(pak_header_t) + 31) & ~31);
    pak_set_entry_count(handle, entryCount);
    pak_set_string_table_offset(handle, (handle->header->entry_start + entryTableSize + 31) & ~31);
    pak_set_string_table_size(handle, stringTableSize);
    pak_set_data_offset(handle, (handle->header->string_table_offset + stringTableSize + 31) & ~31);

    // pad buffers
    size_t paddedEntryBufSize = (entryTableSize + 31) & ~31;
    char* paddedEntryBuf = malloc(paddedEntryBufSize);
    pak_clear(paddedEntryBuf, paddedEntryBufSize);
    memcpy(paddedEntryBuf, entryTableBuf, entryTableSize);
    free(entryTableBuf);

    size_t paddedStringBufSize = (stringTableSize + 31) & ~31;
    char* paddedStringBuf = malloc(paddedStringBufSize);

    pak_clear(paddedStringBuf, paddedStringBufSize);
    memcpy(paddedStringBuf, stringTableBuf, stringTableSize);
    free(stringTableBuf);

    // write pak
    FILE* pak = handle->file;
    if (pak)
    {
        fwrite(handle->header, 1, sizeof(pak_header_t), pak);
        fseeko64(pak, (sizeof(pak_header_t) + 31) & ~31, SEEK_SET);
        fwrite(paddedEntryBuf, 1, paddedEntryBufSize, pak);
        fwrite(paddedStringBuf, 1, paddedStringBufSize, pak);

        size_t bytesRead = 0;
        size_t blockSize = BUF_SIZ;
        while(bytesRead < dataTableSize)
        {
            if (blockSize > dataTableSize - bytesRead)
                blockSize = dataTableSize - bytesRead;
            char buf[blockSize];
            size_t nextReadSize = fread(buf, 1, blockSize, dataFile);
            if (nextReadSize <= 0)
                break;  // error or early EOF!

            fwrite(buf, 1, nextReadSize, pak);
            bytesRead += nextReadSize;
        }
    }

    fclose(dataFile);

    printf("Stored %" PRIu64 " files (%s)\n", pak_get_entry_count(handle), (compress ? "compressed" : "uncompressed"));
    pak_close(handle);
    free(paddedEntryBuf);
    free(paddedStringBuf);
    remove(entryTempPath);
    remove(stringTempPath);
    remove(dataTempPath);
}