Skip to content

Commit a278e6b

Browse files
authored
return exit; fix ignored unused entries
1 parent 7b847bb commit a278e6b

1 file changed

Lines changed: 85 additions & 72 deletions

File tree

acftool.c

Lines changed: 85 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -154,16 +154,16 @@ int write_file(const char *path, const uint8_t *data, size_t size) {
154154
}
155155

156156
fclose(f);
157-
return 0;
157+
return EXIT_SUCCESS;
158158
}
159159

160160
// check if extension needs reversing
161161
int is_invertible(const char *ext) {
162162
const char *invertible[] = { "RGCN", "RLCN", "RECN", "RNAN", "RCSN", "RTFN" };
163163
for (size_t i = 0; i < sizeof(invertible)/sizeof(invertible[0]); ++i) {
164-
if (strcasecmp(ext, invertible[i]) == 0) return 1;
164+
if (strcasecmp(ext, invertible[i]) == 0) return EXIT_FAILURE;
165165
}
166-
return 0;
166+
return EXIT_SUCCESS;
167167
}
168168

169169
// reverse string in place
@@ -207,19 +207,19 @@ const char *try_get_extension(
207207

208208
// extract files from acf archive
209209
int extract_acf(const char *path) {
210-
if (!path) return 1;
210+
if (!path) return EXIT_FAILURE;
211211

212212
size_t fileSize;
213213
uint8_t *fileData = read_file(path, &fileSize);
214214
if (!fileData) {
215215
fprintf(stderr, "Can't read %s\n", path);
216-
return 1;
216+
return EXIT_FAILURE;
217217
}
218218

219219
if (fileSize < sizeof(ACFHeader)) {
220220
fprintf(stderr, "%s: too small to be an ACF\n", path);
221221
free(fileData);
222-
return 1;
222+
return EXIT_FAILURE;
223223
}
224224

225225
// read header
@@ -229,14 +229,14 @@ int extract_acf(const char *path) {
229229
if (memcmp(hdr.magic, "acf", 3) != 0) {
230230
fprintf(stderr, "%s doesn't have an 'acf\\0' header\n", path);
231231
free(fileData);
232-
return 1;
232+
return EXIT_FAILURE;
233233
}
234234

235235
size_t fatOffset = hdr.headerSize;
236236
if (hdr.numFiles * sizeof(FATEntry) > fileSize - fatOffset) {
237237
fprintf(stderr, "%s: FAT table exceeds file size\n", path);
238238
free(fileData);
239-
return 1;
239+
return EXIT_FAILURE;
240240
}
241241

242242
FATEntry *entries = (FATEntry*)(fileData + fatOffset);
@@ -255,13 +255,16 @@ int extract_acf(const char *path) {
255255
if (!mf) {
256256
fprintf(stderr, "Cannot create metadata file\n");
257257
free(fileData);
258-
return 1;
258+
return EXIT_FAILURE;
259259
}
260260

261261
char extBuf[16];
262262
for (uint32_t i = 0; i < hdr.numFiles; ++i) {
263263
FATEntry e = entries[i];
264-
if (e.relativeOffset == 0xFFFFFFFFu) continue;
264+
if (e.relativeOffset == 0xFFFFFFFFu) { // unused entry
265+
fprintf(mf, "%04u -1\n", i);
266+
continue;
267+
}
265268

266269
size_t dataOffset = (size_t)hdr.dataStart + (size_t)e.relativeOffset;
267270
if (dataOffset >= fileSize) {
@@ -285,7 +288,7 @@ int extract_acf(const char *path) {
285288
fprintf(stderr, "OOME\n");
286289
free(fileData);
287290
fclose(mf);
288-
return 1;
291+
return EXIT_FAILURE;
289292
}
290293
memcpy(outBuf, src, outSize);
291294
} else {
@@ -298,7 +301,7 @@ int extract_acf(const char *path) {
298301
fprintf(stderr, "OOME\n");
299302
free(fileData);
300303
fclose(mf);
301-
return 1;
304+
return EXIT_FAILURE;
302305
}
303306
memcpy(outBuf, src, outSize);
304307
}
@@ -325,7 +328,7 @@ int extract_acf(const char *path) {
325328
printf("\n");
326329
fclose(mf);
327330
free(fileData);
328-
return 0;
331+
return EXIT_SUCCESS;
329332
}
330333

331334
// process all acf archives in a directory
@@ -374,69 +377,86 @@ void process_directory(const char *directory) {
374377

375378
// build an acf archive from a directory
376379
int build_acf(const char *directory) {
377-
if (!directory) return 1;
380+
if (!directory) return EXIT_FAILURE;
378381

379382
// read metadata from filelist.txt
380383
char metafile[512];
381384
snprintf(metafile, sizeof(metafile), "%s/filelist.txt", directory);
382385
FILE *mf = fopen(metafile, "r");
383386
char **files = NULL;
384-
uint32_t *compressFlags = NULL;
387+
int *compressFlags = NULL; // use int to hold -1 for unused entries
385388
size_t numFiles = 0;
386389

387390
if (mf) {
388391
char line[1024];
389392
while (fgets(line, sizeof(line), mf)) {
390393
if (line[0] == '#' || strlen(line) < 3) continue;
391394

392-
char fname[512];
393-
unsigned int comp;
394-
if (sscanf(line, "%s %u", fname, &comp) == 2) {
395-
char **tmpFiles = realloc(files, (numFiles+1) * sizeof(char*));
395+
char id[32];
396+
int flag;
397+
if (sscanf(line, "%31s %d", id, &flag) != 2) continue;
398+
399+
// determine the index from the ID
400+
int index = atoi(id);
401+
if ((size_t)(index + 1) > numFiles) {
402+
// expand arrays if needed
403+
char **tmpFiles = realloc(files, (index + 1) * sizeof(char*));
396404
if (!tmpFiles) {
397-
for (size_t i = 0; i < numFiles; i++) free(files[i]);
405+
for (size_t j = 0; j < numFiles; j++) free(files[j]);
398406
free(files);
399407
free(compressFlags);
400408
fclose(mf);
401409
fprintf(stderr, "Memory allocation failed\n");
402-
return 1;
410+
return EXIT_FAILURE;
403411
}
404412
files = tmpFiles;
405413

406-
uint32_t *tmpFlags = realloc(compressFlags, (numFiles+1) * sizeof(uint32_t));
414+
int *tmpFlags = realloc(compressFlags, (index + 1) * sizeof(int));
407415
if (!tmpFlags) {
408-
for (size_t i = 0; i < numFiles; i++) free(files[i]);
416+
for (size_t j = 0; j < numFiles; j++) free(files[j]);
409417
free(files);
410418
free(compressFlags);
411419
fclose(mf);
412420
fprintf(stderr, "Memory allocation failed\n");
413-
return 1;
421+
return EXIT_FAILURE;
414422
}
415423
compressFlags = tmpFlags;
416424

417-
size_t pathlen = strlen(directory) + strlen(fname) + 2;
418-
files[numFiles] = malloc(pathlen);
419-
if (!files[numFiles]) {
420-
for (size_t i = 0; i < numFiles; i++) free(files[i]);
425+
// initialize new entries
426+
for (size_t j = numFiles; j <= (size_t)index; j++) {
427+
files[j] = NULL;
428+
compressFlags[j] = -1; // default to unused
429+
}
430+
431+
numFiles = index + 1;
432+
}
433+
434+
// store file path if not unused
435+
if (flag == -1) {
436+
files[index] = NULL; // mark unused
437+
compressFlags[index] = -1;
438+
} else {
439+
size_t pathlen = strlen(directory) + strlen(id) + 8; // allow for extension
440+
files[index] = malloc(pathlen);
441+
if (!files[index]) {
442+
for (size_t j = 0; j < numFiles; j++) free(files[j]);
421443
free(files);
422444
free(compressFlags);
423445
fclose(mf);
424446
fprintf(stderr, "Memory allocation failed\n");
425-
return 1;
447+
return EXIT_FAILURE;
426448
}
427-
428-
snprintf(files[numFiles], pathlen, "%s/%s", directory, fname);
429-
compressFlags[numFiles] = comp;
430-
numFiles++;
449+
snprintf(files[index], pathlen, "%s/%s", directory, id);
450+
compressFlags[index] = flag;
431451
}
432452
}
433453
fclose(mf);
434454
} else {
435455
fprintf(stderr, "Metadata file not found in %s\n", directory);
436-
return 1;
456+
return EXIT_FAILURE;
437457
}
438458

439-
if (numFiles == 0) { fprintf(stderr, "No files to pack\n"); return 1; }
459+
if (numFiles == 0) { fprintf(stderr, "No files to pack\n"); return EXIT_FAILURE; }
440460

441461
// create output acf archive
442462
char outname[512];
@@ -447,7 +467,7 @@ int build_acf(const char *directory) {
447467
for (size_t i = 0; i < numFiles; i++) free(files[i]);
448468
free(files);
449469
free(compressFlags);
450-
return 1;
470+
return EXIT_FAILURE;
451471
}
452472

453473
// initialize header
@@ -468,7 +488,7 @@ int build_acf(const char *directory) {
468488
for (size_t i = 0; i < numFiles; i++) free(files[i]);
469489
free(files);
470490
free(compressFlags);
471-
return 1;
491+
return EXIT_FAILURE;
472492
}
473493

474494
memcpy(headerBuf, &hdr, sizeof(hdr));
@@ -483,19 +503,31 @@ int build_acf(const char *directory) {
483503
for (size_t i = 0; i < numFiles; i++) free(files[i]);
484504
free(files);
485505
free(compressFlags);
486-
return 1;
506+
return EXIT_FAILURE;
507+
}
508+
509+
// initialize FAT to unused
510+
for (size_t i = 0; i < numFiles; i++) {
511+
fat[i].relativeOffset = 0xFFFFFFFFu;
512+
fat[i].inputSize = 0;
513+
fat[i].outputSize = 0;
487514
}
488515

489516
fwrite(fat, sizeof(FATEntry), numFiles, out);
490517

491518
// write files
492519
size_t offset = 0;
493-
494520
for (size_t i = 0; i < numFiles; i++) {
521+
// skip unused entries
522+
if (compressFlags[i] == -1 || files[i] == NULL) {
523+
fat[i].relativeOffset = 0xFFFFFFFFu;
524+
fat[i].inputSize = 0;
525+
fat[i].outputSize = 0;
526+
continue;
527+
}
495528

496529
size_t sz = 0;
497530
uint8_t *buf = read_file(files[i], &sz);
498-
499531
if (!buf) {
500532
fprintf(stderr, "Skipping %s\n", files[i]);
501533
fat[i].relativeOffset = 0xFFFFFFFFu;
@@ -505,18 +537,15 @@ int build_acf(const char *directory) {
505537
}
506538

507539
int doCompress = compressFlags[i];
508-
if (i == 0) {
509-
doCompress = 0; // fat[0] is always raw
510-
}
511-
fat[i].relativeOffset = (uint32_t)offset;
540+
if (i == 0) doCompress = 0; // first file always raw
512541

513-
if (doCompress) {
542+
fat[i].relativeOffset = (uint32_t)offset;
514543

544+
if (doCompress) {
515545
size_t compSize = 0;
516546
uint8_t *comp = lz10_compress(buf, sz, &compSize);
517547

518548
size_t paddedComp = pad_size(compSize, 4);
519-
520549
fwrite(comp, 1, compSize, out);
521550

522551
// padding
@@ -527,20 +556,17 @@ int build_acf(const char *directory) {
527556
fat[i].outputSize = (uint32_t)pad_size(sz, 4);
528557

529558
offset += paddedComp;
530-
}
531-
532-
if (!doCompress) {
559+
free(comp);
560+
} else {
533561
size_t padded = pad_size(sz, 4);
534-
535-
fat[i].outputSize = (uint32_t)padded;
536-
fat[i].inputSize = 0;
537-
538562
fwrite(buf, 1, sz, out);
539563

540564
// padding
541565
for (size_t p = sz; p < padded; p++)
542566
fputc(0x00, out);
543567

568+
fat[i].inputSize = 0;
569+
fat[i].outputSize = (uint32_t)padded;
544570
offset += padded;
545571
}
546572

@@ -556,21 +582,8 @@ int build_acf(const char *directory) {
556582

557583
// update header and fat table
558584
hdr.dataStart = (uint32_t)(hdr.headerSize + numFiles * sizeof(FATEntry));
559-
headerBuf = calloc(1, hdr.headerSize);
560-
if (!headerBuf) {
561-
fprintf(stderr, "Memory allocation failed\n");
562-
fclose(out);
563-
free(fat);
564-
for (size_t i = 0; i < numFiles; i++) free(files[i]);
565-
free(files);
566-
free(compressFlags);
567-
return 1;
568-
}
569-
570-
memcpy(headerBuf, &hdr, sizeof(hdr));
571585
fseek(out, 0, SEEK_SET);
572586
fwrite(&hdr, 1, sizeof(hdr), out);
573-
free(headerBuf);
574587

575588
fseek(out, hdr.headerSize, SEEK_SET);
576589
fwrite(fat, sizeof(FATEntry), numFiles, out);
@@ -586,7 +599,7 @@ int build_acf(const char *directory) {
586599
printf("Built %s with %zu files. headerSize=0x%X dataStart=0x%X\n",
587600
outname, numFiles, (unsigned)hdr.headerSize, (unsigned)hdr.dataStart);
588601

589-
return 0;
602+
return EXIT_SUCCESS;
590603
}
591604

592605
int main(int argc, char **argv) {
@@ -596,7 +609,7 @@ int main(int argc, char **argv) {
596609
printf("Usage:\n");
597610
printf(" %s -x|--extract <in.acf|indir>\n", argv[0]);
598611
printf(" %s -b|--build <indir>\n", argv[0]);
599-
return 0;
612+
return EXIT_SUCCESS;
600613
}
601614

602615
const char *mode = argv[1];
@@ -606,7 +619,7 @@ int main(int argc, char **argv) {
606619
struct stat st;
607620
if (stat(path, &st) != 0) {
608621
fprintf(stderr, "Invalid path: %s\n", path);
609-
return 1;
622+
return EXIT_FAILURE;
610623
}
611624

612625
if (S_ISDIR(st.st_mode)) { // directory
@@ -620,16 +633,16 @@ int main(int argc, char **argv) {
620633
struct stat st;
621634
if (stat(path, &st) != 0 || !S_ISDIR(st.st_mode)) {
622635
fprintf(stderr, "Invalid path: %s\n", path);
623-
return 1;
636+
return EXIT_FAILURE;
624637
}
625638

626639
printf("Building ACF from directory: %s\n", path);
627640
build_acf(path);
628641
}
629642
else {
630643
fprintf(stderr, "Unknown mode %s\n", mode);
631-
return 1;
644+
return EXIT_FAILURE;
632645
}
633646

634-
return 0;
647+
return EXIT_SUCCESS;
635648
}

0 commit comments

Comments
 (0)