+ for (i = 0; i < lbx->nfiles; i++) {
+ struct lbx_statbuf stat;
+
+ lbx_file_stat(lbx, i, &stat);
+
+ switch (filematch(argv, stat.name)) {
+ case -1: continue;
+ case 0: break;
+ default: return EXIT_FAILURE;
+ }
+
+ printf("%s", stat.name);
+ if (verbose) {
+ printf(" size=%zu bytes", stat.size);
+ }
+
+ putchar('\n');
+ }
+
+ return EXIT_SUCCESS;
+}
+
+int extract_file(LBXfile *f, const struct lbx_statbuf *stat)
+{
+ int ret = -1;
+ size_t rc;
+ FILE *of;
+
+ of = fopen(stat->name, "wb");
+ if (!of) {
+ tool_err(0, "%s: fopen", stat->name);
+ return -1;
+ }
+
+ while (1) {
+ unsigned char buf[1024];
+
+ rc = lbx_file_read(f, buf, sizeof buf);
+ if (rc == 0) {
+ if (lbx_file_eof(f))
+ ret = 0;
+ break;
+ }
+
+ if (fwrite(buf, rc, 1, of) != 1) {
+ tool_err(0, "%s: fwrite", stat->name);
+ break;
+ }
+
+ if (rc < sizeof buf) {
+ if (lbx_file_eof(f))
+ ret = 0;
+ break;
+ }
+ }
+
+ if (fclose(of) == EOF) {
+ tool_err(0, "%s: fclose", stat->name);
+ return -1;
+ }
+
+ return ret;
+}
+
+int extract(struct lbx *lbx, int verbose, char **argv)
+{
+ unsigned int i;
+
+ if (verbose) {
+ printf("Files in archive: %u\n", lbx->nfiles);
+ }
+
+ for (i = 0; i < lbx->nfiles; i++) {
+ struct lbx_statbuf stat;
+ LBXfile *file;
+
+ lbx_file_stat(lbx, i, &stat);
+
+ switch (filematch(argv, stat.name)) {
+ case -1: continue;
+ case 0: break;
+ default: return EXIT_FAILURE;
+ }
+
+ file = lbx_file_open(lbx, i);
+ if (!file) {
+ tool_err(-1, "%s: %s", stat.name, lbx_errmsg());
+ continue;
+ }
+
+ if (extract_file(file, &stat) == -1)
+ return EXIT_FAILURE;
+ lbx_file_close(file);
+ }
+
+ return EXIT_SUCCESS;