archive_read_support_format_raw.c 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. /*-
  2. * Copyright (c) 2003-2009 Tim Kientzle
  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 "archive_platform.h"
  26. __FBSDID("$FreeBSD$");
  27. #ifdef HAVE_ERRNO_H
  28. #include <errno.h>
  29. #endif
  30. #include <stdio.h>
  31. #ifdef HAVE_STDLIB_H
  32. #include <stdlib.h>
  33. #endif
  34. #include "archive.h"
  35. #include "archive_entry.h"
  36. #include "archive_private.h"
  37. #include "archive_read_private.h"
  38. struct raw_info {
  39. int64_t offset; /* Current position in the file. */
  40. int end_of_file;
  41. };
  42. static int archive_read_format_raw_bid(struct archive_read *);
  43. static int archive_read_format_raw_cleanup(struct archive_read *);
  44. static int archive_read_format_raw_read_data(struct archive_read *,
  45. const void **, size_t *, off_t *);
  46. static int archive_read_format_raw_read_data_skip(struct archive_read *);
  47. static int archive_read_format_raw_read_header(struct archive_read *,
  48. struct archive_entry *);
  49. int
  50. archive_read_support_format_raw(struct archive *_a)
  51. {
  52. struct raw_info *info;
  53. struct archive_read *a = (struct archive_read *)_a;
  54. int r;
  55. info = (struct raw_info *)calloc(1, sizeof(*info));
  56. if (info == NULL) {
  57. archive_set_error(&a->archive, ENOMEM,
  58. "Can't allocate raw_info data");
  59. return (ARCHIVE_FATAL);
  60. }
  61. r = __archive_read_register_format(a,
  62. info,
  63. "raw",
  64. archive_read_format_raw_bid,
  65. NULL,
  66. archive_read_format_raw_read_header,
  67. archive_read_format_raw_read_data,
  68. archive_read_format_raw_read_data_skip,
  69. archive_read_format_raw_cleanup);
  70. if (r != ARCHIVE_OK)
  71. free(info);
  72. return (r);
  73. }
  74. /*
  75. * Bid 1 if this is a non-empty file. Anyone who can really support
  76. * this should outbid us, so it should generally be safe to use "raw"
  77. * in conjunction with other formats. But, this could really confuse
  78. * folks if there are bid errors or minor file damage, so we don't
  79. * include "raw" as part of support_format_all().
  80. */
  81. static int
  82. archive_read_format_raw_bid(struct archive_read *a)
  83. {
  84. const char *p;
  85. if ((p = __archive_read_ahead(a, 1, NULL)) == NULL)
  86. return (-1);
  87. return (1);
  88. }
  89. /*
  90. * Mock up a fake header.
  91. */
  92. static int
  93. archive_read_format_raw_read_header(struct archive_read *a,
  94. struct archive_entry *entry)
  95. {
  96. struct raw_info *info;
  97. info = (struct raw_info *)(a->format->data);
  98. if (info->end_of_file)
  99. return (ARCHIVE_EOF);
  100. a->archive.archive_format = ARCHIVE_FORMAT_RAW;
  101. a->archive.archive_format_name = "Raw data";
  102. archive_entry_set_pathname(entry, "data");
  103. /* XXX should we set mode to mimic a regular file? XXX */
  104. /* I'm deliberately leaving most fields unset here. */
  105. return (ARCHIVE_OK);
  106. }
  107. static int
  108. archive_read_format_raw_read_data(struct archive_read *a,
  109. const void **buff, size_t *size, off_t *offset)
  110. {
  111. struct raw_info *info;
  112. ssize_t avail;
  113. info = (struct raw_info *)(a->format->data);
  114. if (info->end_of_file)
  115. return (ARCHIVE_EOF);
  116. /* Get whatever bytes are immediately available. */
  117. *buff = __archive_read_ahead(a, 1, &avail);
  118. if (avail > 0) {
  119. /* Consume and return the bytes we just read */
  120. __archive_read_consume(a, avail);
  121. *size = avail;
  122. *offset = info->offset;
  123. info->offset += *size;
  124. return (ARCHIVE_OK);
  125. } else if (0 == avail) {
  126. /* Record and return end-of-file. */
  127. info->end_of_file = 1;
  128. *size = 0;
  129. *offset = info->offset;
  130. return (ARCHIVE_EOF);
  131. } else {
  132. /* Record and return an error. */
  133. *size = 0;
  134. *offset = info->offset;
  135. return (avail);
  136. }
  137. }
  138. static int
  139. archive_read_format_raw_read_data_skip(struct archive_read *a)
  140. {
  141. struct raw_info *info;
  142. off_t bytes_skipped;
  143. int64_t request = 1024 * 1024 * 1024UL; /* Skip 1 GB at a time. */
  144. info = (struct raw_info *)(a->format->data);
  145. if (info->end_of_file)
  146. return (ARCHIVE_EOF);
  147. info->end_of_file = 1;
  148. for (;;) {
  149. bytes_skipped = __archive_read_skip_lenient(a, request);
  150. if (bytes_skipped < 0)
  151. return (ARCHIVE_FATAL);
  152. if (bytes_skipped < request)
  153. return (ARCHIVE_OK);
  154. /* We skipped all the bytes we asked for. There might
  155. * be more, so try again. */
  156. }
  157. }
  158. static int
  159. archive_read_format_raw_cleanup(struct archive_read *a)
  160. {
  161. struct raw_info *info;
  162. info = (struct raw_info *)(a->format->data);
  163. free(info);
  164. a->format->data = NULL;
  165. return (ARCHIVE_OK);
  166. }