archive_entry_sparse.c 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. /*-
  2. * Copyright (c) 2003-2007 Tim Kientzle
  3. * Copyright (c) 2010-2011 Michihiro NAKAJIMA
  4. * All rights reserved.
  5. *
  6. * Redistribution and use in source and binary forms, with or without
  7. * modification, are permitted provided that the following conditions
  8. * are met:
  9. * 1. Redistributions of source code must retain the above copyright
  10. * notice, this list of conditions and the following disclaimer.
  11. * 2. Redistributions in binary form must reproduce the above copyright
  12. * notice, this list of conditions and the following disclaimer in the
  13. * documentation and/or other materials provided with the distribution.
  14. *
  15. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
  16. * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  17. * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  18. * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
  19. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  20. * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  21. * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  22. * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  23. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  24. * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  25. */
  26. #include "archive_platform.h"
  27. #include "archive.h"
  28. #include "archive_entry.h"
  29. #include "archive_private.h"
  30. #include "archive_entry_private.h"
  31. /*
  32. * sparse handling
  33. */
  34. void
  35. archive_entry_sparse_clear(struct archive_entry *entry)
  36. {
  37. struct ae_sparse *sp;
  38. while (entry->sparse_head != NULL) {
  39. sp = entry->sparse_head->next;
  40. free(entry->sparse_head);
  41. entry->sparse_head = sp;
  42. }
  43. entry->sparse_tail = NULL;
  44. }
  45. void
  46. archive_entry_sparse_add_entry(struct archive_entry *entry,
  47. la_int64_t offset, la_int64_t length)
  48. {
  49. struct ae_sparse *sp;
  50. if (offset < 0 || length < 0)
  51. /* Invalid value */
  52. return;
  53. if (offset > INT64_MAX - length ||
  54. offset + length > archive_entry_size(entry))
  55. /* A value of "length" parameter is too large. */
  56. return;
  57. if ((sp = entry->sparse_tail) != NULL) {
  58. if (sp->offset + sp->length > offset)
  59. /* Invalid value. */
  60. return;
  61. if (sp->offset + sp->length == offset) {
  62. if (sp->offset + sp->length + length < 0)
  63. /* A value of "length" parameter is
  64. * too large. */
  65. return;
  66. /* Expand existing sparse block size. */
  67. sp->length += length;
  68. return;
  69. }
  70. }
  71. if ((sp = malloc(sizeof(*sp))) == NULL)
  72. /* XXX Error XXX */
  73. return;
  74. sp->offset = offset;
  75. sp->length = length;
  76. sp->next = NULL;
  77. if (entry->sparse_head == NULL)
  78. entry->sparse_head = entry->sparse_tail = sp;
  79. else {
  80. /* Add a new sparse block to the tail of list. */
  81. if (entry->sparse_tail != NULL)
  82. entry->sparse_tail->next = sp;
  83. entry->sparse_tail = sp;
  84. }
  85. }
  86. /*
  87. * returns number of the sparse entries
  88. */
  89. int
  90. archive_entry_sparse_count(struct archive_entry *entry)
  91. {
  92. struct ae_sparse *sp;
  93. int count = 0;
  94. for (sp = entry->sparse_head; sp != NULL; sp = sp->next)
  95. count++;
  96. /*
  97. * Sanity check if this entry is exactly sparse.
  98. * If amount of sparse blocks is just one and it indicates the whole
  99. * file data, we should remove it and return zero.
  100. */
  101. if (count == 1) {
  102. sp = entry->sparse_head;
  103. if (sp->offset == 0 &&
  104. sp->length >= archive_entry_size(entry)) {
  105. count = 0;
  106. archive_entry_sparse_clear(entry);
  107. }
  108. }
  109. return (count);
  110. }
  111. int
  112. archive_entry_sparse_reset(struct archive_entry * entry)
  113. {
  114. entry->sparse_p = entry->sparse_head;
  115. return archive_entry_sparse_count(entry);
  116. }
  117. int
  118. archive_entry_sparse_next(struct archive_entry * entry,
  119. la_int64_t *offset, la_int64_t *length)
  120. {
  121. if (entry->sparse_p) {
  122. *offset = entry->sparse_p->offset;
  123. *length = entry->sparse_p->length;
  124. entry->sparse_p = entry->sparse_p->next;
  125. return (ARCHIVE_OK);
  126. } else {
  127. *offset = 0;
  128. *length = 0;
  129. return (ARCHIVE_WARN);
  130. }
  131. }
  132. /*
  133. * end of sparse handling
  134. */