bsdcat.c 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. /*-
  2. * SPDX-License-Identifier: BSD-2-Clause
  3. *
  4. * Copyright (c) 2011-2014, Mike Kazantsev
  5. * All rights reserved.
  6. */
  7. #include "bsdcat_platform.h"
  8. #include <stdio.h>
  9. #ifdef HAVE_STDLIB_H
  10. #include <stdlib.h>
  11. #endif
  12. #ifdef HAVE_UNISTD_H
  13. #include <unistd.h>
  14. #endif
  15. #ifdef HAVE_STRING_H
  16. #include <string.h>
  17. #endif
  18. #include <archive.h>
  19. #include <archive_entry.h>
  20. #include "bsdcat.h"
  21. #include "err.h"
  22. #define BYTES_PER_BLOCK (20*512)
  23. static struct archive *a;
  24. static struct archive_entry *ae;
  25. static const char *bsdcat_current_path;
  26. static int exit_status = 0;
  27. static __LA_NORETURN void
  28. usage(FILE *stream, int eval)
  29. {
  30. const char *p;
  31. p = lafe_getprogname();
  32. fprintf(stream,
  33. "Usage: %s [-h] [--help] [--version] [--] [filenames...]\n", p);
  34. exit(eval);
  35. }
  36. static __LA_NORETURN void
  37. version(void)
  38. {
  39. printf("bsdcat %s - %s \n",
  40. BSDCAT_VERSION_STRING,
  41. archive_version_details());
  42. exit(0);
  43. }
  44. static void
  45. bsdcat_print_error(void)
  46. {
  47. lafe_warnc(0, "%s: %s",
  48. bsdcat_current_path, archive_error_string(a));
  49. exit_status = 1;
  50. }
  51. static void
  52. bsdcat_next(void)
  53. {
  54. if (a != NULL) {
  55. if (archive_read_close(a) != ARCHIVE_OK)
  56. bsdcat_print_error();
  57. archive_read_free(a);
  58. }
  59. a = archive_read_new();
  60. archive_read_support_filter_all(a);
  61. archive_read_support_format_empty(a);
  62. archive_read_support_format_raw(a);
  63. }
  64. static void
  65. bsdcat_read_to_stdout(const char* filename)
  66. {
  67. int r;
  68. if (archive_read_open_filename(a, filename, BYTES_PER_BLOCK)
  69. != ARCHIVE_OK)
  70. bsdcat_print_error();
  71. else if (r = archive_read_next_header(a, &ae),
  72. r != ARCHIVE_OK && r != ARCHIVE_EOF)
  73. bsdcat_print_error();
  74. else if (r == ARCHIVE_EOF)
  75. /* for empty payloads don't try and read data */
  76. ;
  77. else if (archive_read_data_into_fd(a, 1) != ARCHIVE_OK)
  78. bsdcat_print_error();
  79. if (archive_read_close(a) != ARCHIVE_OK)
  80. bsdcat_print_error();
  81. archive_read_free(a);
  82. a = NULL;
  83. }
  84. int
  85. main(int argc, char **argv)
  86. {
  87. struct bsdcat *bsdcat, bsdcat_storage;
  88. int c;
  89. bsdcat = &bsdcat_storage;
  90. memset(bsdcat, 0, sizeof(*bsdcat));
  91. lafe_setprogname(*argv, "bsdcat");
  92. bsdcat->argv = argv;
  93. bsdcat->argc = argc;
  94. while ((c = bsdcat_getopt(bsdcat)) != -1) {
  95. switch (c) {
  96. case 'h':
  97. usage(stdout, 0);
  98. /* NOTREACHED */
  99. /* Fallthrough */
  100. case OPTION_VERSION:
  101. version();
  102. /* NOTREACHED */
  103. /* Fallthrough */
  104. default:
  105. usage(stderr, 1);
  106. /* Fallthrough */
  107. /* NOTREACHED */
  108. }
  109. }
  110. bsdcat_next();
  111. if (*bsdcat->argv == NULL) {
  112. bsdcat_current_path = "<stdin>";
  113. bsdcat_read_to_stdout(NULL);
  114. } else {
  115. while (*bsdcat->argv) {
  116. bsdcat_current_path = *bsdcat->argv++;
  117. bsdcat_read_to_stdout(bsdcat_current_path);
  118. bsdcat_next();
  119. }
  120. archive_read_free(a); /* Help valgrind & friends */
  121. }
  122. exit(exit_status);
  123. }