Commit b5b8f8556365b70a207fd5dd4924d041c378a394

Authored by Imanol-Mikel Barba Sabariego
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 #include <stdio.h> 1 #include <stdio.h>
2 #include <getopt.h> 2 #include <getopt.h>
3 #include <dirent.h> 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 #include "nbt.h" 10 #include "nbt.h"
6 #include "chunk.h" 11 #include "chunk.h"
7 12
8 -enum paramIndex  
9 -{ 13 +enum paramIndex {
10 UNKNOWN = 0, 14 UNKNOWN = 0,
11 HELP, 15 HELP,
12 REGION, 16 REGION,
@@ -36,13 +40,17 @@ static struct option longopts[] = { @@ -36,13 +40,17 @@ static struct option longopts[] = {
36 40
37 int savePetToFile(Tag* pet, const char* filename) { 41 int savePetToFile(Tag* pet, const char* filename) {
38 void* petData; 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 int fd = open(filename,O_CREAT|O_WRONLY,0644); 49 int fd = open(filename,O_CREAT|O_WRONLY,0644);
42 if(fd == -1) { 50 if(fd == -1) {
43 fprintf(stderr,"Unable to open file to save pet: %s\n",strerror(errno)); 51 fprintf(stderr,"Unable to open file to save pet: %s\n",strerror(errno));
44 free(petData); 52 free(petData);
45 - return 1; 53 + return -1;
46 } 54 }
47 ssize_t nWritten = 0; 55 ssize_t nWritten = 0;
48 size_t totalWritten = 0; 56 size_t totalWritten = 0;
@@ -55,7 +63,7 @@ int savePetToFile(Tag* pet, const char* filename) { @@ -55,7 +63,7 @@ int savePetToFile(Tag* pet, const char* filename) {
55 fprintf(stderr,"Unable to write pet data: %s\n",strerror(errno)); 63 fprintf(stderr,"Unable to write pet data: %s\n",strerror(errno));
56 close(fd); 64 close(fd);
57 free(petData); 65 free(petData);
58 - return 2; 66 + return -2;
59 } 67 }
60 totalWritten += nWritten; 68 totalWritten += nWritten;
61 } 69 }
@@ -69,14 +77,14 @@ int loadPetFromFile(Tag* pet, const char* filename) { @@ -69,14 +77,14 @@ int loadPetFromFile(Tag* pet, const char* filename) {
69 int fd = open(filename,O_RDONLY); 77 int fd = open(filename,O_RDONLY);
70 if(fd == -1) { 78 if(fd == -1) {
71 fprintf(stderr,"Unable to open file to load pet: %s\n",strerror(errno)); 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 struct stat sb; 83 struct stat sb;
76 if(stat(filename,&sb) == -1) { 84 if(stat(filename,&sb) == -1) {
77 fprintf(stderr,"Unable to stat() file to load pet: %s\n",strerror(errno)); 85 fprintf(stderr,"Unable to stat() file to load pet: %s\n",strerror(errno));
78 close(fd); 86 close(fd);
79 - return 2; 87 + return -2;
80 } 88 }
81 void* petData = calloc(sb.st_size,sizeof(uint8_t)); 89 void* petData = calloc(sb.st_size,sizeof(uint8_t));
82 90
@@ -91,17 +99,22 @@ int loadPetFromFile(Tag* pet, const char* filename) { @@ -91,17 +99,22 @@ int loadPetFromFile(Tag* pet, const char* filename) {
91 fprintf(stderr,"Unable to write pet data: %s\n",strerror(errno)); 99 fprintf(stderr,"Unable to write pet data: %s\n",strerror(errno));
92 close(fd); 100 close(fd);
93 free(petData); 101 free(petData);
94 - return 3; 102 + return -3;
95 } 103 }
96 totalRead += nRead; 104 totalRead += nRead;
97 } 105 }
98 close(fd); 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 if(pos != sb.st_size) { 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 free(petData); 116 free(petData);
104 - return 4; 117 + return -4;
105 } 118 }
106 119
107 free(petData); 120 free(petData);
@@ -120,7 +133,7 @@ int getEntitiesTag(TagCompound* chunkRoot,Tag** entities) { @@ -120,7 +133,7 @@ int getEntitiesTag(TagCompound* chunkRoot,Tag** entities) {
120 } 133 }
121 if(!found) { 134 if(!found) {
122 fprintf(stderr,"Unable to locate Level tag\n"); 135 fprintf(stderr,"Unable to locate Level tag\n");
123 - return 1; 136 + return -1;
124 } 137 }
125 found = 0; 138 found = 0;
126 139
@@ -135,7 +148,7 @@ int getEntitiesTag(TagCompound* chunkRoot,Tag** entities) { @@ -135,7 +148,7 @@ int getEntitiesTag(TagCompound* chunkRoot,Tag** entities) {
135 } 148 }
136 if(!found) { 149 if(!found) {
137 fprintf(stderr,"Unable to locate Entities tag\n"); 150 fprintf(stderr,"Unable to locate Entities tag\n");
138 - return 2; 151 + return -2;
139 } 152 }
140 *entities = t; 153 *entities = t;
141 return 0; 154 return 0;
@@ -188,22 +201,35 @@ ssize_t insertPetIntoChunk(void** chunkData, Tag chunkRoot, Tag* entities, Tag p @@ -188,22 +201,35 @@ ssize_t insertPetIntoChunk(void** chunkData, Tag chunkRoot, Tag* entities, Tag p
188 Tag* newPet = &entitiesList->list[(entitiesList->size) - 1]; 201 Tag* newPet = &entitiesList->list[(entitiesList->size) - 1];
189 202
190 void* rawPetData; 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 if(parsePos != rawPetDataLength) { 215 if(parsePos != rawPetDataLength) {
194 fprintf(stderr,"Error while duplicating pet. New pet data does not match original\n"); 216 fprintf(stderr,"Error while duplicating pet. New pet data does not match original\n");
195 free(rawPetData); 217 free(rawPetData);
196 - return -2; 218 + return -4;
197 } 219 }
198 free(rawPetData); 220 free(rawPetData);
199 221
200 void* newChunkData; 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 newptr = realloc(*chunkData,chunkDataLength); 228 newptr = realloc(*chunkData,chunkDataLength);
203 if(newptr == NULL) { 229 if(newptr == NULL) {
204 fprintf(stderr,"Unable to realloc chunkData to fit new data\n"); 230 fprintf(stderr,"Unable to realloc chunkData to fit new data\n");
205 free(newChunkData); 231 free(newChunkData);
206 - return -4; 232 + return -6;
207 } 233 }
208 *chunkData = newptr; 234 *chunkData = newptr;
209 memcpy(*chunkData,newChunkData,chunkDataLength); 235 memcpy(*chunkData,newChunkData,chunkDataLength);
@@ -250,7 +276,7 @@ int main(int argc, char** argv) { @@ -250,7 +276,7 @@ int main(int argc, char** argv) {
250 fprintf(stderr,"No options specified\n\n"); 276 fprintf(stderr,"No options specified\n\n");
251 fprintf(stderr,"Examples:\n"); 277 fprintf(stderr,"Examples:\n");
252 printHelp(); 278 printHelp();
253 - return 0; 279 + return 3;
254 } 280 }
255 281
256 while ((c = getopt_long(argc, argv, "r:s:l:n:o:c:h", longopts, &longIndex)) != -1) 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,19 +291,19 @@ int main(int argc, char** argv) {
265 else { 291 else {
266 fprintf(stderr,"Unrecognised argument: %s\n",optarg); 292 fprintf(stderr,"Unrecognised argument: %s\n",optarg);
267 printHelp(); 293 printHelp();
268 - return 1; 294 + return 3;
269 } 295 }
270 } 296 }
271 if(optind != argc) { 297 if(optind != argc) {
272 fprintf(stderr,"Unrecognised argument: %s\n",argv[optind+1]); 298 fprintf(stderr,"Unrecognised argument: %s\n",argv[optind+1]);
273 printHelp(); 299 printHelp();
274 - return 1; 300 + return 3;
275 } 301 }
276 302
277 if(regionFolder == NULL) { 303 if(regionFolder == NULL) {
278 fprintf(stderr,"Region path not specified (--regionpath PATH_TO_REGION_FOLDER)\n"); 304 fprintf(stderr,"Region path not specified (--regionpath PATH_TO_REGION_FOLDER)\n");
279 printHelp(); 305 printHelp();
280 - return 2; 306 + return 3;
281 } else if(!load && (petName == NULL && ownerUUID == NULL)) { 307 } else if(!load && (petName == NULL && ownerUUID == NULL)) {
282 fprintf(stderr,"OwnerUUID and petName were unspecified (--owner UUID, --name PET_NAME)\n"); 308 fprintf(stderr,"OwnerUUID and petName were unspecified (--owner UUID, --name PET_NAME)\n");
283 printHelp(); 309 printHelp();
@@ -289,7 +315,7 @@ int main(int argc, char** argv) { @@ -289,7 +315,7 @@ int main(int argc, char** argv) {
289 } else if(save && coords == NULL) { 315 } else if(save && coords == NULL) {
290 fprintf(stderr,"Coordinates were not specified\n"); 316 fprintf(stderr,"Coordinates were not specified\n");
291 printHelp(); 317 printHelp();
292 - return 4; 318 + return 3;
293 } 319 }
294 320
295 if(!load) { 321 if(!load) {
@@ -298,7 +324,7 @@ int main(int argc, char** argv) { @@ -298,7 +324,7 @@ int main(int argc, char** argv) {
298 324
299 if((dirp = opendir(regionFolder)) == NULL) { 325 if((dirp = opendir(regionFolder)) == NULL) {
300 fprintf(stderr,"Unable to open region folder '%s'\n",regionFolder); 326 fprintf(stderr,"Unable to open region folder '%s'\n",regionFolder);
301 - return 1; 327 + return 2;
302 } 328 }
303 329
304 do { 330 do {
@@ -326,16 +352,22 @@ int main(int argc, char** argv) { @@ -326,16 +352,22 @@ int main(int argc, char** argv) {
326 (chunk.z + 1) * BLOCKS_PER_CHUNK 352 (chunk.z + 1) * BLOCKS_PER_CHUNK
327 ); 353 );
328 ssize_t chunkLen = loadChunk(regionFolder, chunk, &chunkData); 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 } else if(chunkLen != 0) { 360 } else if(chunkLen != 0) {
333 Tag t; 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 if(pos != chunkLen) { 367 if(pos != chunkLen) {
336 fprintf(stderr, "Didn't reach end of NBT file\n"); 368 fprintf(stderr, "Didn't reach end of NBT file\n");
337 free(chunkData); 369 free(chunkData);
338 - return 5; 370 + return 2;
339 } 371 }
340 372
341 Tag* entities; 373 Tag* entities;
@@ -343,7 +375,7 @@ int main(int argc, char** argv) { @@ -343,7 +375,7 @@ int main(int argc, char** argv) {
343 fprintf(stderr, "Unable to find Entities tag\n"); 375 fprintf(stderr, "Unable to find Entities tag\n");
344 free(chunkData); 376 free(chunkData);
345 destroyTag(&t); 377 destroyTag(&t);
346 - return 6; 378 + return 2;
347 } 379 }
348 Tag* pet; 380 Tag* pet;
349 if(searchForPet(*entities,petName,ownerUUID,&pet) == 0) { 381 if(searchForPet(*entities,petName,ownerUUID,&pet) == 0) {
@@ -354,7 +386,7 @@ int main(int argc, char** argv) { @@ -354,7 +386,7 @@ int main(int argc, char** argv) {
354 fprintf(stderr, "Unable to save pet to file: %s\n",file); 386 fprintf(stderr, "Unable to save pet to file: %s\n",file);
355 free(chunkData); 387 free(chunkData);
356 closedir(dirp); 388 closedir(dirp);
357 - return 8; 389 + return 2;
358 } 390 }
359 } 391 }
360 destroyTag(&t); 392 destroyTag(&t);
@@ -376,55 +408,64 @@ int main(int argc, char** argv) { @@ -376,55 +408,64 @@ int main(int argc, char** argv) {
376 Coords location; 408 Coords location;
377 if(sscanf(coords,"%d,%d,%d",&location.x,&location.y,&location.z) != 3) { 409 if(sscanf(coords,"%d,%d,%d",&location.x,&location.y,&location.z) != 3) {
378 fprintf(stderr, "Unable to parse coordinates, please specify coordinates correctly (--coords X,Y,Z)\n"); 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 void *chunkData; 414 void *chunkData;
383 ChunkID chunk = translateCoordsToChunk(location.x, location.y, location.z); 415 ChunkID chunk = translateCoordsToChunk(location.x, location.y, location.z);
384 ssize_t chunkLen = loadChunk(regionFolder, chunk, &chunkData); 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 destroyTag(&t); 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 free(chunkData); 467 free(chunkData);
423 - destroyTag(&t);  
424 - return 11;  
425 } 468 }
426 - destroyTag(&t);  
427 - free(chunkData);  
428 } 469 }
429 return 0; 470 return 0;
430 } 471 }
431 \ No newline at end of file 472 \ No newline at end of file