Beispiel #1
0
int mcr_chunk_set(MCR *mcr, int x, int z, nbt_node *root)
{
    assert(mcr && x < 32 && z < 32 && x >= 0 && z >= 0);
    if (mcr->readonly) {
        errno = EPERM;
        return -1;
    }
    struct MCRChunk *chunk = &mcr->chunk[x][z];
    if (root == NULL) {
        // delete chunk
        free(chunk->data);
        chunk->data = NULL;
        chunk->len = 0;
        chunk->timestamp = 0;
    } else {
        // compress chunk
        struct buffer compressed = nbt_dump_compressed(root, STRAT_INFLATE);
        chunk->len = compressed.len+1;
        uint8_t *data = (uint8_t*)malloc(chunk->len);
        if (data == NULL) {
            buffer_free(&compressed);
            return -1;
        }
        data[0] = 2; // compression type
        memcpy(data+1, compressed.data, compressed.len);
        buffer_free(&compressed);
        chunk->timestamp = mcr->last_timestamp;
        free(chunk->data);
        chunk->data = data;
    }
    
    return 0;
}
Beispiel #2
0
/*
 * Once again, all we're doing is handing the actual compression off to
 * nbt_dump_compressed, then dumping it into the file.
 */
nbt_status nbt_dump_file(const nbt_node* tree, FILE* fp, nbt_compression_strategy strat)
{
    struct buffer compressed = nbt_dump_compressed(tree, strat);

    if(compressed.data == NULL)
        return (nbt_status)errno;

    nbt_status ret = write_file(fp, compressed.data, compressed.len);

    buffer_free(&compressed);
    return ret;
}
Beispiel #3
0
int write_chunk(regionfile* region, int32_t cx, int32_t cz, chunk* chunk) {
    if (region == NULL)
        return -1;
    if (chunk == NULL)
        return -1;
    cx &= 0x1f;
    cz &= 0x1f;
    uint32_t offset = region->offsets[cx + cz * 32];
    if (offset == 0)
        return -2;
    uint32_t numSectors = offset & 0xff;
    if (numSectors == 0)
        return -3;
    nbt_node* raw = new_chunk_data_to_nbt(chunk);
    if (raw == NULL)
        return -1;
    uint32_t sectorStart = offset >> 8;
    FILE* f;
    if (region->keepopen == 1) {
        if (region->file)
            f = region->file;
        else {
            f = fopen(region->filename, "rb+");
            region->file = f;
        }
    } else
        f = fopen(region->filename, "rb+");
    struct buffer buf = nbt_dump_compressed(raw, STRAT_INFLATE);
    uint16_t sectorsNeeded = (buf.len + 5) / SECTOR_BYTES + 1;
    if (sectorsNeeded >= 256)
        goto error;
    if (sectorStart != 0 && numSectors >= sectorsNeeded) {
        if (fseek(f, sectorStart*SECTOR_BYTES, SEEK_SET) != 0)
            goto error;
        uint32_t size = htobe32(buf.len);
        if (fwrite(&size, 1, sizeof(uint32_t), f) != sizeof(uint32_t))
            goto error;
        static const char COMPRESSION = 2;
        if (fwrite(&COMPRESSION, 1, sizeof(COMPRESSION), f) != sizeof(COMPRESSION))
            goto error;
        if (fwrite(buf.data, 1, buf.len, f) != buf.len)
            goto error;
        goto success;
    } else {
        size_t i;
        size_t runLength = 0;
        uint32_t runStart = 0;
        unsigned char* curSector = region->freeSectors;
        for (i = 0; curSector[i] != 0x00; i++) {
            if (runLength > 0) {
                if (curSector[i] == 0x01)
                    runLength++;
                else
                    runLength = 0;
            } else if (curSector[i] == 0x01) {
                runStart = i;
                runLength = 1;
            }
            if (runLength >= sectorsNeeded)
                break;
        }
        if (runLength >= sectorsNeeded) {
            region->offsets[cx + cz * 32] = runStart << 8 | sectorsNeeded;
            if (__region_write_offsets(region) != 0)
                goto error;
            if (fseek(f, runStart*SECTOR_BYTES, SEEK_SET) != 0)
                goto error;
            uint32_t size = htobe32(buf.len);
            if (fwrite(&size, 1, sizeof(uint32_t), f) != sizeof(uint32_t))
                goto error;
            static const char COMPRESSION = 2;
            if (fwrite(&COMPRESSION, 1, sizeof(COMPRESSION), f) != sizeof(COMPRESSION))
                goto error;
            if (fwrite(buf.data, 1, buf.len, f) != buf.len)
                goto error;
            goto success;
        } else {
            if (fseek(f, 0L, SEEK_END) != 0)
                goto error;
            long filesize = ftell(f);
            uint32_t sectorNumber = filesize/SECTOR_BYTES;
            filesize += sectorsNeeded * SECTOR_BYTES;
            if (ftruncate(fileno(f), filesize) != 0)
                goto error;
            region->offsets[cx + cz * 32] = sectorNumber << 8 | sectorsNeeded;
            if (__region_write_offsets(region) != 0)
                goto error;
            if (fseek(f, sectorNumber*SECTOR_BYTES, SEEK_SET) != 0)
                goto error;
            uint32_t size = htobe32(buf.len);
            if (fwrite(&size, 1, sizeof(uint32_t), f) != sizeof(uint32_t))
                goto error;
            static const char COMPRESSION = 2;
            if (fwrite(&COMPRESSION, 1, sizeof(COMPRESSION), f) != sizeof(COMPRESSION))
                goto error;
            if (fwrite(buf.data, 1, buf.len, f) != buf.len)
                goto error;

            uint32_t freeSectorsLength = filesize/SECTOR_BYTES;
            region->freeSectors = realloc(region->freeSectors, sizeof(unsigned char) * (freeSectorsLength+1));
            region->freeSectors[freeSectorsLength] = 0x00;
            for (; sectorNumber < freeSectorsLength; sectorNumber++)
                region->freeSectors[sectorNumber] = 0x02;
            goto success;
        }
    }
error:
    nbt_free(raw);
    if (f && region->file != f)
        fclose(f);
    buffer_free(&buf);
    return 1;
success:
    nbt_free(raw);
    buffer_free(&buf);
    if (region->file != f)
        fclose(f);
    region->timestamps[cx + cz * 32] = time(NULL);
    __region_write_timestamps(region);
    return 0;
};