libclod
C library for interacting with NBTs, region files, LOD data and other things.
Loading...
Searching...
No Matches
format.c
1#include "format.h"
2#include "clod_config.h"
4#include <assert.h>
5#include <stdlib.h>
6#include <string.h>
7
8static void *default_malloc(size_t size, void*) { return malloc(size); }
9static void default_free(void *ptr, void*) { free(ptr); }
10struct clod_rfmt *rfmt_new(struct clod_rfmt_opts *opts) {
11 struct clod_rfmt *rfmt;
12 if (opts->malloc_func)
13 rfmt = opts->malloc_func(sizeof(*rfmt), opts->user);
14 else
15 rfmt = default_malloc(sizeof(*rfmt), opts->user);
16 if (!rfmt) return nullptr;
17
18 rfmt->opts = *opts;
19 if (rfmt->opts.dead_lock_timeout_ms == 0) rfmt->opts.dead_lock_timeout_ms = 5000;
20 if (!rfmt->opts.malloc_func) opts->malloc_func = default_malloc;
21 if (!rfmt->opts.free_func) opts->free_func = default_free;
22 rfmt->data = nullptr;
23 rfmt->data_size = 0;
24
25#if CLOD_REGION_DEBUG
26 rfmt->file_locked = false;
27 bitarray_unset_all(rfmt->held_locks);
28 bitarray_unset_all(rfmt->observing_locks);
29#endif
30
31 return rfmt;
32}
34#if CLOD_REGION_DEBUG
35 if (
36 rfmt->file_locked ||
37 !bitarray_all_unset(rfmt->held_locks) ||
38 !bitarray_all_unset(rfmt->observing_locks)
39 ) {
40 rfmt->opts.free_func(rfmt, rfmt->opts.user);
41 return CLOD_RFMT_MISUSE;
42 }
43#endif
44 rfmt->opts.free_func(rfmt, rfmt->opts.user);
45 return CLOD_RFMT_OK;
46}
47
49 struct clod_rfmt **rfmt_out,
50 struct clod_rfmt_opts *opts,
51 char *chunk_filename_prefix,
52 char *chunk_filename_extension,
53 uint32_t sector_size
54) {
55 struct clod_rfmt *rfmt = rfmt_new(opts);
56 if (!rfmt) return CLOD_RFMT_ALLOCATION_FAILURE;
57 if (!rfmt->opts.file_manage(&rfmt->data, &rfmt->data_size, &HEADER_SIZE, rfmt->opts.user)) {
58 clod_rfmt_free(rfmt);
60 }
61
62 if (!rfmt->data || rfmt->data_size < HEADER_SIZE) {
63 clod_rfmt_free(rfmt);
65 }
66
67 memset(rfmt->data, 0, HEADER_SIZE);
68 memset(rfmt->data + LIBCLOD_MAG)
69}
70
71enum clod_rfmt_result clod_rfmt_init_rw(struct clod_rfmt **rfmt_out, struct clod_rfmt_opts *opts) {
72 struct clod_rfmt *rfmt = rfmt_new(opts);
73 if (!rfmt) return nullptr;
74}
75
76enum clod_rfmt_result clod_rfmt_init_ro(struct clod_rfmt **rfmt_out, struct clod_rfmt_opts *opts) {
77 struct clod_rfmt *rfmt = rfmt_new(opts);
78 if (!rfmt) return nullptr;
79
80}
81
82/*
83typedef struct {
84 uint32_t offset: 24;
85 uint8_t size: 8;
86} chunk_loc;
87
88static inline chunk_loc chunk_loc_dec(uint32_t loc) { return (chunk_loc){loc >> 8, loc & 0xFF}; }
89static inline uint32_t chunk_loc_enc(chunk_loc loc) { return (uint32_t)(loc.offset << 8 | loc.size); }
90
91static inline uint32_t sector_size(const uint8_t *data) { return beu32_dec(data + 8360); }
92static inline uint32_t file_sectors_add(uint8_t *data, uint32_t delta) { return atomic_beu32_add(data + 8364 , delta); }
93static inline void file_sectors_set(uint8_t *data, uint32_t val) { atomic_beu32_store(data + 8364, val); }
94static inline uint32_t checkpoint_crc(const uint8_t *data) { return beu32_dec(data + 8372); }
95static inline void checkpoint_crc_set(uint8_t *data, uint32_t val) { beu32_enc(data + 8372, val); }
96static inline uint32_t shadowed_chunk_count(const uint8_t *data) { return atomic_beu32_load(data + 8376); }
97static inline void shadowed_chunk_count_set(uint8_t *data, uint32_t val) { atomic_beu32_store(data + 8376, val); }
98static inline uint32_t shadowed_chunk_count_add(uint8_t *data, uint32_t val) { return atomic_beu32_add(data + 8376, val); }
99static inline chunk_loc shadowed(const uint8_t *data, int chunk_index) { return chunk_loc_dec(beu32_dec(data + chunk_index * 4)); }
100static inline void shadowed_set(uint8_t *data, int chunk_index, chunk_loc loc) { beu32_enc(data + chunk_index * 4, chunk_loc_enc(loc)); }
101static inline chunk_loc checkpoint_set(const uint8_t *data, int chunk_index) { return chunk_loc_dec(beu32_dec(data + 16384 + chunk_index * 4)); }
102static inline void checkpoint(uint8_t *data, int chunk_index, chunk_loc loc) { beu32_enc(data + 16384 + chunk_index * 4, chunk_loc_enc(loc)); }
103static inline uint32_t mtime(const uint8_t *data, int chunk_index) { return beu32_dec(data + 4096 + chunk_index * 4); }
104static inline void mtime_set(uint8_t *data, int chunk_index, uint32_t mtime) { beu32_enc(data + 4096 + chunk_index * 4, mtime); }
105static inline uint32_t generation(const uint8_t *data, int chunk_index) { return atomic_beu32_load(data + 12288 + chunk_index * 4); }
106static inline void generation_set(uint8_t *data, int chunk_index, uint32_t generation) { atomic_beu32_store(data + 12288 + chunk_index * 4, generation); }
107static inline uint32_t generation_cas(uint8_t *data, int chunk_index, uint32_t *expected, uint32_t desired) { return atomic_beu32_cas(data + 12288 + chunk_index * 4, expected, desired); }
108
109
110static enum clod_rhdr_result lock_one(const uint8_t *data) {
111
112}
113
114static enum clod_rhdr_result lock_all(const uint8_t *data) {
115
116}
117
118enum clod_rhdr_type clod_rhdr_detect_type(const uint8_t *data, size_t data_size) {
119 if (data_size >= HEADER_LIBCLOD_SIZE && memcmp(data + 8192, LIBCLOD_MAGIC, LIBCLOD_MAGIC_LEN) == 0) {
120 // Appears to be a libclod header.
121 // Make sure a vanilla implementation hasn't overwritten the libclod header.
122 const uint32_t min_offset_sectors = ceil_div(HEADER_LIBCLOD_SIZE, sector_size(data));
123
124 for (int i = 0; i < 1024; i++) {
125 bool ok = true;
126 observe_gen(data, i) {
127 const chunk_loc loc = shadowed(data, i);
128 if (loc.size == 0) ok = true;
129 else if (loc.offset < min_offset_sectors) ok = false;
130 }
131 if (!ok) return CLOD_RHDR_VANILLA;
132 }
133
134 return CLOD_RHDR_LIBCLOD;
135 }
136
137 if (data_size >= HEADER_VANILLA_SIZE) {
138 return CLOD_RHDR_VANILLA;
139 }
140
141 return CLOD_RHDR_UNKNOWN;
142}
143
144
145*/
clod_rfmt_result
enum clod_rfmt_result clod_rfmt_init_rw(struct clod_rfmt **rfmt_out, struct clod_rfmt_opts *opts)
Definition format.c:71
enum clod_rfmt_result clod_rfmt_init_new(struct clod_rfmt **rfmt_out, struct clod_rfmt_opts *opts, char *chunk_filename_prefix, char *chunk_filename_extension, uint32_t sector_size)
Definition format.c:48
enum clod_rfmt_result clod_rfmt_init_ro(struct clod_rfmt **rfmt_out, struct clod_rfmt_opts *opts)
Definition format.c:76
enum clod_rfmt_result clod_rfmt_free(struct clod_rfmt *rfmt)
Definition format.c:33
@ CLOD_RFMT_ALLOCATION_FAILURE
@ CLOD_RFMT_FILE_MANAGE_ERROR
@ CLOD_RFMT_MISUSE
@ CLOD_RFMT_OK
Sized string helpers.
void *(* malloc_func)(size_t size, void *user)
uint32_t dead_lock_timeout_ms
void(* free_func)(void *ptr, void *user)
bool(* file_manage)(uint8_t **data, size_t *size, const size_t *new_size, void *user)