bsdcat.c 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. /*-
  2. * Copyright (c) 2011-2014, Mike Kazantsev
  3. * All rights reserved.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions
  7. * are met:
  8. * 1. Redistributions of source code must retain the above copyright
  9. * notice, this list of conditions and the following disclaimer.
  10. * 2. Redistributions in binary form must reproduce the above copyright
  11. * notice, this list of conditions and the following disclaimer in the
  12. * documentation and/or other materials provided with the distribution.
  13. *
  14. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
  15. * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  16. * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  17. * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
  18. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  19. * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  20. * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  21. * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  22. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  23. * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  24. */
  25. #include "bsdcat_platform.h"
  26. __FBSDID("$FreeBSD$");
  27. #include <stdio.h>
  28. #ifdef HAVE_STDLIB_H
  29. #include <stdlib.h>
  30. #endif
  31. #ifdef HAVE_UNISTD_H
  32. #include <unistd.h>
  33. #endif
  34. #ifdef HAVE_STRING_H
  35. #include <string.h>
  36. #endif
  37. #include "bsdcat.h"
  38. #include "err.h"
  39. #define BYTES_PER_BLOCK (20*512)
  40. static struct archive *a;
  41. static struct archive_entry *ae;
  42. static const char *bsdcat_current_path;
  43. static int exit_status = 0;
  44. void
  45. usage(FILE *stream, int eval)
  46. {
  47. const char *p;
  48. p = lafe_getprogname();
  49. fprintf(stream,
  50. "Usage: %s [-h] [--help] [--version] [--] [filenames...]\n", p);
  51. exit(eval);
  52. }
  53. static void
  54. version(void)
  55. {
  56. printf("bsdcat %s - %s \n",
  57. BSDCAT_VERSION_STRING,
  58. archive_version_details());
  59. exit(0);
  60. }
  61. void
  62. bsdcat_next(void)
  63. {
  64. if (a != NULL) {
  65. if (archive_read_close(a) != ARCHIVE_OK)
  66. bsdcat_print_error();
  67. archive_read_free(a);
  68. }
  69. a = archive_read_new();
  70. archive_read_support_filter_all(a);
  71. archive_read_support_format_empty(a);
  72. archive_read_support_format_raw(a);
  73. }
  74. void
  75. bsdcat_print_error(void)
  76. {
  77. lafe_warnc(0, "%s: %s",
  78. bsdcat_current_path, archive_error_string(a));
  79. exit_status = 1;
  80. }
  81. void
  82. bsdcat_read_to_stdout(const char* filename)
  83. {
  84. int r;
  85. if (archive_read_open_filename(a, filename, BYTES_PER_BLOCK)
  86. != ARCHIVE_OK)
  87. bsdcat_print_error();
  88. else if (r = archive_read_next_header(a, &ae),
  89. r != ARCHIVE_OK && r != ARCHIVE_EOF)
  90. bsdcat_print_error();
  91. else if (r == ARCHIVE_EOF)
  92. /* for empty payloads don't try and read data */
  93. ;
  94. else if (archive_read_data_into_fd(a, 1) != ARCHIVE_OK)
  95. bsdcat_print_error();
  96. if (archive_read_close(a) != ARCHIVE_OK)
  97. bsdcat_print_error();
  98. archive_read_free(a);
  99. a = NULL;
  100. }
  101. int
  102. main(int argc, char **argv)
  103. {
  104. struct bsdcat *bsdcat, bsdcat_storage;
  105. int c;
  106. bsdcat = &bsdcat_storage;
  107. memset(bsdcat, 0, sizeof(*bsdcat));
  108. lafe_setprogname(*argv, "bsdcat");
  109. bsdcat->argv = argv;
  110. bsdcat->argc = argc;
  111. while ((c = bsdcat_getopt(bsdcat)) != -1) {
  112. switch (c) {
  113. case 'h':
  114. usage(stdout, 0);
  115. break;
  116. case OPTION_VERSION:
  117. version();
  118. break;
  119. default:
  120. usage(stderr, 1);
  121. }
  122. }
  123. bsdcat_next();
  124. if (*bsdcat->argv == NULL) {
  125. bsdcat_current_path = "<stdin>";
  126. bsdcat_read_to_stdout(NULL);
  127. } else {
  128. while (*bsdcat->argv) {
  129. bsdcat_current_path = *bsdcat->argv++;
  130. bsdcat_read_to_stdout(bsdcat_current_path);
  131. bsdcat_next();
  132. }
  133. archive_read_free(a); /* Help valgrind & friends */
  134. }
  135. exit(exit_status);
  136. }