Commit 5d5390ce5b3dcafbcd6f691b68c742ea8ee7f125
1 parent
20237a82
Showing
2 changed files
with
118 additions
and
2 deletions
nbt.c
1 | 1 | #include "nbt.h" |
2 | 2 | |
3 | +ssize_t loadDB(const char* filename, void** data); | |
3 | 4 | void destroyTag(Tag* t); |
4 | 5 | void destroyTagList(TagList* l); |
5 | 6 | void destroyTagCompound(TagCompound* tc); |
7 | +size_t getTypeSize(uint8_t type); | |
8 | +unsigned int parseList(void* addr, TagList* tl, uint8_t type); | |
9 | +unsigned int parseCompound(void* addr, TagCompound* tc); | |
6 | 10 | unsigned int parsePayload(void* addr,Tag* t); |
11 | +unsigned int parseTag(void* addr, Tag* t); | |
12 | + | |
13 | +ssize_t loadDB(const char* filename, void** data) { | |
14 | + if(access(filename,R_OK) == -1) { | |
15 | + perror("Can't access file"); | |
16 | + return -1; | |
17 | + } | |
18 | + | |
19 | + struct stat sb; | |
20 | + unsigned int pos = 0; | |
21 | + | |
22 | + int fd = open(filename,O_RDONLY); | |
23 | + if(fd == -1) { | |
24 | + perror("Can't open file"); | |
25 | + return -2; | |
26 | + } | |
27 | + fstat(fd, &sb); | |
28 | + | |
29 | + uint16_t header = 0; | |
30 | + if(pread(fd,&header,sizeof(uint16_t),0) == -1) { | |
31 | + perror("Unable to read header"); | |
32 | + close(fd); | |
33 | + return -3; | |
34 | + } | |
35 | + | |
36 | + void* filedata; | |
37 | + ssize_t filesize = sb.st_size; | |
38 | + | |
39 | + if(header == GZIP_MAGIC) { | |
40 | + close(fd); | |
41 | + filedata = calloc(GZIP_BUFFER,sizeof(char)); | |
42 | + gzFile file = gzopen(filename,"r"); | |
43 | + if(!file) { | |
44 | + perror("Failed to gzopen() file"); | |
45 | + free(filedata); | |
46 | + return -4; | |
47 | + } | |
48 | + int err; | |
49 | + int nRead; | |
50 | + size_t totalBytes = 0; | |
51 | + while((nRead = gzread(file, filedata+totalBytes, GZIP_BUFFER)) != 0) { | |
52 | + totalBytes += nRead; | |
53 | + if(!(totalBytes % GZIP_BUFFER)) { | |
54 | + void* newptr = realloc(filedata,totalBytes + GZIP_BUFFER); | |
55 | + if(newptr == NULL) { | |
56 | + perror("Unable to realloc for decompression"); | |
57 | + gzclose(file); | |
58 | + free(filedata); | |
59 | + return -6; | |
60 | + } | |
61 | + filedata = newptr; | |
62 | + } | |
63 | + } | |
64 | + if(!gzeof(file)) { | |
65 | + const char * errorStr; | |
66 | + errorStr = gzerror(file, &err); | |
67 | + fprintf(stderr, "libz error: %s.\n", errorStr); | |
68 | + gzclose(file); | |
69 | + free(filedata); | |
70 | + return -5; | |
71 | + } | |
72 | + filesize = totalBytes; | |
73 | + gzclose (file); | |
74 | + } else { | |
75 | + filedata = malloc(filesize); | |
76 | + ssize_t nRead = 0; | |
77 | + size_t totalRead = 0; | |
78 | + | |
79 | + while((nRead = read(fd,filedata+totalRead,filesize-totalRead))) { | |
80 | + if(nRead == -1) { | |
81 | + if(errno == EINTR) { | |
82 | + continue; | |
83 | + } | |
84 | + perror("Error reading file"); | |
85 | + return -7; | |
86 | + } | |
87 | + totalRead += nRead; | |
88 | + } | |
89 | + } | |
90 | + *data = filedata; | |
91 | + return filesize; | |
92 | +} | |
7 | 93 | |
8 | 94 | void destroyTag(Tag* t) { |
9 | 95 | if(t->nameLength) { |
... | ... | @@ -112,15 +198,33 @@ unsigned int parsePayload(void* addr,Tag* t) { |
112 | 198 | t->payloadLength = getTypeSize(t->type); // initially, then particularly for lists/compounds/strings |
113 | 199 | TagCompound* tc; |
114 | 200 | TagList *tl; |
201 | + uint16_t u16 = 0; | |
202 | + uint32_t u32 = 0; | |
203 | + uint64_t u64 = 0; | |
115 | 204 | switch(t->type) { |
116 | 205 | case TAG_BYTE: |
206 | + t->payload = calloc(1,t->payloadLength); | |
207 | + memcpy(t->payload,pos,t->payloadLength); | |
208 | + pos += t->payloadLength; | |
209 | + break; | |
117 | 210 | case TAG_SHORT: |
211 | + u16 = __bswap_16(*(uint16_t*)pos); | |
212 | + t->payload = calloc(1,t->payloadLength); | |
213 | + memcpy(t->payload,&u16,t->payloadLength); | |
214 | + pos += t->payloadLength; | |
215 | + break; | |
118 | 216 | case TAG_INT: |
119 | - case TAG_LONG: | |
120 | 217 | case TAG_FLOAT: |
218 | + u32 = __bswap_32(*(uint32_t*)pos); | |
219 | + t->payload = calloc(1,t->payloadLength); | |
220 | + memcpy(t->payload,&u32,t->payloadLength); | |
221 | + pos += t->payloadLength; | |
222 | + break; | |
223 | + case TAG_LONG: | |
121 | 224 | case TAG_DOUBLE: |
225 | + u64 = __bswap_64(*(uint64_t*)pos); | |
122 | 226 | t->payload = calloc(1,t->payloadLength); |
123 | - memcpy(t->payload,pos,t->payloadLength); | |
227 | + memcpy(t->payload,&u64,t->payloadLength); | |
124 | 228 | pos += t->payloadLength; |
125 | 229 | break; |
126 | 230 | case TAG_STRING: | ... | ... |
nbt.h
... | ... | @@ -7,11 +7,22 @@ |
7 | 7 | #include <stdio.h> |
8 | 8 | #include <malloc.h> |
9 | 9 | #include <string.h> |
10 | +#include <unistd.h> | |
11 | +#include <fcntl.h> | |
12 | +#include <sys/stat.h> | |
13 | +#include <errno.h> | |
14 | +#include <zlib.h> | |
10 | 15 | |
11 | 16 | #ifndef REALLOC_SIZE |
12 | 17 | #define REALLOC_SIZE 10 |
13 | 18 | #endif |
14 | 19 | |
20 | +#ifndef GZIP_BUFFER | |
21 | +#define GZIP_BUFFER 4096 | |
22 | +#endif | |
23 | + | |
24 | +#define GZIP_MAGIC 0x8B1F | |
25 | + | |
15 | 26 | typedef struct Tag { |
16 | 27 | uint8_t type; |
17 | 28 | char* name; |
... | ... | @@ -46,6 +57,7 @@ enum TAG { |
46 | 57 | TAG_INTARRAY |
47 | 58 | }; |
48 | 59 | |
60 | +ssize_t loadDB(const char* filename, void** data); | |
49 | 61 | void destroyTag(Tag* t); |
50 | 62 | unsigned int parseTag(void* addr, Tag* t); |
51 | 63 | ... | ... |