Commit b5b8f8556365b70a207fd5dd4924d041c378a394
1 parent
1e868e43
Made return codes a bit more sane, and used the return codes from libnbt
Showing
1 changed file
with
111 additions
and
70 deletions
mcpetbackup.c
1 | 1 | #include <stdio.h> |
2 | 2 | #include <getopt.h> |
3 | 3 | #include <dirent.h> |
4 | +#include <fcntl.h> | |
5 | +#include <errno.h> | |
6 | +#include <unistd.h> | |
7 | +#include <sys/stat.h> | |
8 | +#include <stdint.h> | |
4 | 9 | |
5 | 10 | #include "nbt.h" |
6 | 11 | #include "chunk.h" |
7 | 12 | |
8 | -enum paramIndex | |
9 | -{ | |
13 | +enum paramIndex { | |
10 | 14 | UNKNOWN = 0, |
11 | 15 | HELP, |
12 | 16 | REGION, |
... | ... | @@ -36,13 +40,17 @@ static struct option longopts[] = { |
36 | 40 | |
37 | 41 | int savePetToFile(Tag* pet, const char* filename) { |
38 | 42 | void* petData; |
39 | - size_t petDataLength = composeTag(*pet, &petData); | |
43 | + ssize_t petDataLength = composeTag(*pet, &petData); | |
44 | + if(petDataLength < 0) { | |
45 | + fprintf(stderr,"Error while composing pet tag: code %d\n",(int)petDataLength); | |
46 | + return petDataLength; | |
47 | + } | |
40 | 48 | |
41 | 49 | int fd = open(filename,O_CREAT|O_WRONLY,0644); |
42 | 50 | if(fd == -1) { |
43 | 51 | fprintf(stderr,"Unable to open file to save pet: %s\n",strerror(errno)); |
44 | 52 | free(petData); |
45 | - return 1; | |
53 | + return -1; | |
46 | 54 | } |
47 | 55 | ssize_t nWritten = 0; |
48 | 56 | size_t totalWritten = 0; |
... | ... | @@ -55,7 +63,7 @@ int savePetToFile(Tag* pet, const char* filename) { |
55 | 63 | fprintf(stderr,"Unable to write pet data: %s\n",strerror(errno)); |
56 | 64 | close(fd); |
57 | 65 | free(petData); |
58 | - return 2; | |
66 | + return -2; | |
59 | 67 | } |
60 | 68 | totalWritten += nWritten; |
61 | 69 | } |
... | ... | @@ -69,14 +77,14 @@ int loadPetFromFile(Tag* pet, const char* filename) { |
69 | 77 | int fd = open(filename,O_RDONLY); |
70 | 78 | if(fd == -1) { |
71 | 79 | fprintf(stderr,"Unable to open file to load pet: %s\n",strerror(errno)); |
72 | - return 1; | |
80 | + return -1; | |
73 | 81 | } |
74 | 82 | |
75 | 83 | struct stat sb; |
76 | 84 | if(stat(filename,&sb) == -1) { |
77 | 85 | fprintf(stderr,"Unable to stat() file to load pet: %s\n",strerror(errno)); |
78 | 86 | close(fd); |
79 | - return 2; | |
87 | + return -2; | |
80 | 88 | } |
81 | 89 | void* petData = calloc(sb.st_size,sizeof(uint8_t)); |
82 | 90 | |
... | ... | @@ -91,17 +99,22 @@ int loadPetFromFile(Tag* pet, const char* filename) { |
91 | 99 | fprintf(stderr,"Unable to write pet data: %s\n",strerror(errno)); |
92 | 100 | close(fd); |
93 | 101 | free(petData); |
94 | - return 3; | |
102 | + return -3; | |
95 | 103 | } |
96 | 104 | totalRead += nRead; |
97 | 105 | } |
98 | 106 | close(fd); |
99 | 107 | |
100 | - size_t pos = parseTag(petData,pet); | |
108 | + ssize_t pos = parseTag(petData,pet); | |
109 | + if(pos < 0) { | |
110 | + fprintf(stderr,"Error parsing pet data: code %d\n",(int)pos); | |
111 | + free(petData); | |
112 | + return pos; | |
113 | + } | |
101 | 114 | if(pos != sb.st_size) { |
102 | - fprintf(stderr,"Error parsing pet data\n"); | |
115 | + fprintf(stderr,"Didn't reach end of database while parsing\n"); | |
103 | 116 | free(petData); |
104 | - return 4; | |
117 | + return -4; | |
105 | 118 | } |
106 | 119 | |
107 | 120 | free(petData); |
... | ... | @@ -120,7 +133,7 @@ int getEntitiesTag(TagCompound* chunkRoot,Tag** entities) { |
120 | 133 | } |
121 | 134 | if(!found) { |
122 | 135 | fprintf(stderr,"Unable to locate Level tag\n"); |
123 | - return 1; | |
136 | + return -1; | |
124 | 137 | } |
125 | 138 | found = 0; |
126 | 139 | |
... | ... | @@ -135,7 +148,7 @@ int getEntitiesTag(TagCompound* chunkRoot,Tag** entities) { |
135 | 148 | } |
136 | 149 | if(!found) { |
137 | 150 | fprintf(stderr,"Unable to locate Entities tag\n"); |
138 | - return 2; | |
151 | + return -2; | |
139 | 152 | } |
140 | 153 | *entities = t; |
141 | 154 | return 0; |
... | ... | @@ -188,22 +201,35 @@ ssize_t insertPetIntoChunk(void** chunkData, Tag chunkRoot, Tag* entities, Tag p |
188 | 201 | Tag* newPet = &entitiesList->list[(entitiesList->size) - 1]; |
189 | 202 | |
190 | 203 | void* rawPetData; |
191 | - size_t rawPetDataLength = composeTag(pet,&rawPetData); | |
192 | - size_t parsePos = parseTag(rawPetData,newPet); | |
204 | + ssize_t rawPetDataLength = composeTag(pet,&rawPetData); | |
205 | + if(rawPetDataLength < 0) { | |
206 | + fprintf(stderr,"Error while composing pet tag: code %d\n",(int)rawPetDataLength); | |
207 | + return -2; | |
208 | + } | |
209 | + ssize_t parsePos = parseTag(rawPetData,newPet); | |
210 | + if(parsePos < 0) { | |
211 | + fprintf(stderr,"Error while parsing pet tag: code %d\n",(int)parsePos); | |
212 | + free(rawPetData); | |
213 | + return -3; | |
214 | + } | |
193 | 215 | if(parsePos != rawPetDataLength) { |
194 | 216 | fprintf(stderr,"Error while duplicating pet. New pet data does not match original\n"); |
195 | 217 | free(rawPetData); |
196 | - return -2; | |
218 | + return -4; | |
197 | 219 | } |
198 | 220 | free(rawPetData); |
199 | 221 | |
200 | 222 | void* newChunkData; |
201 | - size_t chunkDataLength = composeTag(chunkRoot, &newChunkData); | |
223 | + ssize_t chunkDataLength = composeTag(chunkRoot, &newChunkData); | |
224 | + if(chunkDataLength < 0) { | |
225 | + fprintf(stderr,"Error while composing new chunk tag: code %d\n",(int)chunkDataLength); | |
226 | + return -5; | |
227 | + } | |
202 | 228 | newptr = realloc(*chunkData,chunkDataLength); |
203 | 229 | if(newptr == NULL) { |
204 | 230 | fprintf(stderr,"Unable to realloc chunkData to fit new data\n"); |
205 | 231 | free(newChunkData); |
206 | - return -4; | |
232 | + return -6; | |
207 | 233 | } |
208 | 234 | *chunkData = newptr; |
209 | 235 | memcpy(*chunkData,newChunkData,chunkDataLength); |
... | ... | @@ -250,7 +276,7 @@ int main(int argc, char** argv) { |
250 | 276 | fprintf(stderr,"No options specified\n\n"); |
251 | 277 | fprintf(stderr,"Examples:\n"); |
252 | 278 | printHelp(); |
253 | - return 0; | |
279 | + return 3; | |
254 | 280 | } |
255 | 281 | |
256 | 282 | while ((c = getopt_long(argc, argv, "r:s:l:n:o:c:h", longopts, &longIndex)) != -1) |
... | ... | @@ -265,19 +291,19 @@ int main(int argc, char** argv) { |
265 | 291 | else { |
266 | 292 | fprintf(stderr,"Unrecognised argument: %s\n",optarg); |
267 | 293 | printHelp(); |
268 | - return 1; | |
294 | + return 3; | |
269 | 295 | } |
270 | 296 | } |
271 | 297 | if(optind != argc) { |
272 | 298 | fprintf(stderr,"Unrecognised argument: %s\n",argv[optind+1]); |
273 | 299 | printHelp(); |
274 | - return 1; | |
300 | + return 3; | |
275 | 301 | } |
276 | 302 | |
277 | 303 | if(regionFolder == NULL) { |
278 | 304 | fprintf(stderr,"Region path not specified (--regionpath PATH_TO_REGION_FOLDER)\n"); |
279 | 305 | printHelp(); |
280 | - return 2; | |
306 | + return 3; | |
281 | 307 | } else if(!load && (petName == NULL && ownerUUID == NULL)) { |
282 | 308 | fprintf(stderr,"OwnerUUID and petName were unspecified (--owner UUID, --name PET_NAME)\n"); |
283 | 309 | printHelp(); |
... | ... | @@ -289,7 +315,7 @@ int main(int argc, char** argv) { |
289 | 315 | } else if(save && coords == NULL) { |
290 | 316 | fprintf(stderr,"Coordinates were not specified\n"); |
291 | 317 | printHelp(); |
292 | - return 4; | |
318 | + return 3; | |
293 | 319 | } |
294 | 320 | |
295 | 321 | if(!load) { |
... | ... | @@ -298,7 +324,7 @@ int main(int argc, char** argv) { |
298 | 324 | |
299 | 325 | if((dirp = opendir(regionFolder)) == NULL) { |
300 | 326 | fprintf(stderr,"Unable to open region folder '%s'\n",regionFolder); |
301 | - return 1; | |
327 | + return 2; | |
302 | 328 | } |
303 | 329 | |
304 | 330 | do { |
... | ... | @@ -326,16 +352,22 @@ int main(int argc, char** argv) { |
326 | 352 | (chunk.z + 1) * BLOCKS_PER_CHUNK |
327 | 353 | ); |
328 | 354 | ssize_t chunkLen = loadChunk(regionFolder, chunk, &chunkData); |
329 | - if(chunkLen < 0) { | |
330 | - fprintf(stderr, "Unable to load chunk\n"); | |
331 | - return 5; | |
355 | + if(chunkLen == CHUNK_NOT_PRESENT) { | |
356 | + continue; | |
357 | + } else if(chunkLen < 0) { | |
358 | + fprintf(stderr, "Unable to load chunk: code %d\n",(int)chunkLen); | |
359 | + return 2; | |
332 | 360 | } else if(chunkLen != 0) { |
333 | 361 | Tag t; |
334 | - unsigned int pos = parseTag(chunkData,&t); | |
362 | + ssize_t pos = parseTag(chunkData,&t); | |
363 | + if(pos < 0) { | |
364 | + fprintf(stderr, "Error parsing chunk root tag: code %d\n",(int)pos); | |
365 | + return 2; | |
366 | + } | |
335 | 367 | if(pos != chunkLen) { |
336 | 368 | fprintf(stderr, "Didn't reach end of NBT file\n"); |
337 | 369 | free(chunkData); |
338 | - return 5; | |
370 | + return 2; | |
339 | 371 | } |
340 | 372 | |
341 | 373 | Tag* entities; |
... | ... | @@ -343,7 +375,7 @@ int main(int argc, char** argv) { |
343 | 375 | fprintf(stderr, "Unable to find Entities tag\n"); |
344 | 376 | free(chunkData); |
345 | 377 | destroyTag(&t); |
346 | - return 6; | |
378 | + return 2; | |
347 | 379 | } |
348 | 380 | Tag* pet; |
349 | 381 | if(searchForPet(*entities,petName,ownerUUID,&pet) == 0) { |
... | ... | @@ -354,7 +386,7 @@ int main(int argc, char** argv) { |
354 | 386 | fprintf(stderr, "Unable to save pet to file: %s\n",file); |
355 | 387 | free(chunkData); |
356 | 388 | closedir(dirp); |
357 | - return 8; | |
389 | + return 2; | |
358 | 390 | } |
359 | 391 | } |
360 | 392 | destroyTag(&t); |
... | ... | @@ -376,55 +408,64 @@ int main(int argc, char** argv) { |
376 | 408 | Coords location; |
377 | 409 | if(sscanf(coords,"%d,%d,%d",&location.x,&location.y,&location.z) != 3) { |
378 | 410 | fprintf(stderr, "Unable to parse coordinates, please specify coordinates correctly (--coords X,Y,Z)\n"); |
379 | - return 5; | |
411 | + return 3; | |
380 | 412 | } |
381 | 413 | |
382 | 414 | void *chunkData; |
383 | 415 | ChunkID chunk = translateCoordsToChunk(location.x, location.y, location.z); |
384 | 416 | ssize_t chunkLen = loadChunk(regionFolder, chunk, &chunkData); |
385 | - if(chunkLen <= 0) { | |
386 | - fprintf(stderr, "Unable to load chunk\n"); | |
387 | - return 5; | |
388 | - } | |
389 | - | |
390 | - Tag t; | |
391 | - unsigned int pos = parseTag(chunkData,&t); | |
392 | - if(pos != chunkLen) { | |
393 | - fprintf(stderr, "Didn't reach end of NBT file\n"); | |
394 | - free(chunkData); | |
395 | - return 5; | |
417 | + if(chunkLen == CHUNK_NOT_PRESENT) { | |
418 | + fprintf(stderr, "Tried to spawn pet in a chunk that has not been generated!\n"); | |
419 | + return 2; | |
420 | + } else if(chunkLen < 0) { | |
421 | + fprintf(stderr, "Unable to load chunk: code %d\n",(int)chunkLen); | |
422 | + return 2; | |
396 | 423 | } |
424 | + if(chunkLen != 0) { | |
425 | + Tag t; | |
426 | + ssize_t pos = parseTag(chunkData,&t); | |
427 | + if(pos < 0) { | |
428 | + fprintf(stderr, "Error parsing chunk root tag: code %d\n",(int)pos); | |
429 | + return 2; | |
430 | + } | |
431 | + if(pos != chunkLen) { | |
432 | + fprintf(stderr, "Didn't reach end of NBT file\n"); | |
433 | + free(chunkData); | |
434 | + return 2; | |
435 | + } | |
397 | 436 | |
398 | - Tag* entities; | |
399 | - if(getEntitiesTag((TagCompound*)t.payload,&entities)) { | |
400 | - fprintf(stderr, "Unable to find Entities tag\n"); | |
401 | - free(chunkData); | |
402 | - destroyTag(&t); | |
403 | - return 6; | |
404 | - } | |
405 | - Tag pet; | |
406 | - if(loadPetFromFile(&pet,file)) { | |
407 | - fprintf(stderr, "Unable to load pet from file: %s\n",file); | |
408 | - free(chunkData); | |
409 | - destroyTag(&t); | |
410 | - return 9; | |
411 | - } | |
412 | - chunkLen = insertPetIntoChunk(&chunkData,t,entities,pet,location.x,location.y,location.z); | |
413 | - if(chunkLen <= 0) { | |
414 | - fprintf(stderr, "Unable to insert pet into chunk\n"); | |
415 | - free(chunkData); | |
437 | + Tag* entities; | |
438 | + if(getEntitiesTag((TagCompound*)t.payload,&entities)) { | |
439 | + fprintf(stderr, "Unable to find Entities tag\n"); | |
440 | + free(chunkData); | |
441 | + destroyTag(&t); | |
442 | + return 2; | |
443 | + } | |
444 | + Tag pet; | |
445 | + if(loadPetFromFile(&pet,file)) { | |
446 | + fprintf(stderr, "Unable to load pet from file: %s\n",file); | |
447 | + free(chunkData); | |
448 | + destroyTag(&t); | |
449 | + return 2; | |
450 | + } | |
451 | + chunkLen = insertPetIntoChunk(&chunkData,t,entities,pet,location.x,location.y,location.z); | |
452 | + if(chunkLen <= 0) { | |
453 | + fprintf(stderr, "Unable to insert pet into chunk\n"); | |
454 | + free(chunkData); | |
455 | + destroyTag(&t); | |
456 | + return 2; | |
457 | + } | |
458 | + destroyTag(&pet); | |
459 | + int res = overwriteChunk(regionFolder, chunk, chunkData, chunkLen); | |
460 | + if(res) { | |
461 | + fprintf(stderr, "Unable to write new chunk: code %d\n",res); | |
462 | + free(chunkData); | |
463 | + destroyTag(&t); | |
464 | + return 2; | |
465 | + } | |
416 | 466 | destroyTag(&t); |
417 | - return 10; | |
418 | - } | |
419 | - destroyTag(&pet); | |
420 | - if(overwriteChunk(regionFolder, chunk, chunkData, chunkLen)) { | |
421 | - fprintf(stderr, "Unable to write new chunk\n"); | |
422 | 467 | free(chunkData); |
423 | - destroyTag(&t); | |
424 | - return 11; | |
425 | 468 | } |
426 | - destroyTag(&t); | |
427 | - free(chunkData); | |
428 | 469 | } |
429 | 470 | return 0; |
430 | 471 | } |
431 | 472 | \ No newline at end of file | ... | ... |