archive_entry_sparse.c 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  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. __FBSDID("$FreeBSD$");
  28. #include "archive.h"
  29. #include "archive_entry.h"
  30. #include "archive_private.h"
  31. #include "archive_entry_private.h"
  32. /*
  33. * sparse handling
  34. */
  35. void
  36. archive_entry_sparse_clear(struct archive_entry *entry)
  37. {
  38. struct ae_sparse *sp;
  39. while (entry->sparse_head != NULL) {
  40. sp = entry->sparse_head->next;
  41. free(entry->sparse_head);
  42. entry->sparse_head = sp;
  43. }
  44. entry->sparse_tail = NULL;
  45. }
  46. void
  47. archive_entry_sparse_add_entry(struct archive_entry *entry,
  48. la_int64_t offset, la_int64_t length)
  49. {
  50. struct ae_sparse *sp;
  51. if (offset < 0 || length < 0)
  52. /* Invalid value */
  53. return;
  54. if (offset > INT64_MAX - length ||
  55. offset + length > archive_entry_size(entry))
  56. /* A value of "length" parameter is too large. */
  57. return;
  58. if ((sp = entry->sparse_tail) != NULL) {
  59. if (sp->offset + sp->length > offset)
  60. /* Invalid value. */
  61. return;
  62. if (sp->offset + sp->length == offset) {
  63. if (sp->offset + sp->length + length < 0)
  64. /* A value of "length" parameter is
  65. * too large. */
  66. return;
  67. /* Expand existing sparse block size. */
  68. sp->length += length;
  69. return;
  70. }
  71. }
  72. if ((sp = (struct ae_sparse *)malloc(sizeof(*sp))) == NULL)
  73. /* XXX Error XXX */
  74. return;
  75. sp->offset = offset;
  76. sp->length = length;
  77. sp->next = NULL;
  78. if (entry->sparse_head == NULL)
  79. entry->sparse_head = entry->sparse_tail = sp;
  80. else {
  81. /* Add a new sparse block to the tail of list. */
  82. if (entry->sparse_tail != NULL)
  83. entry->sparse_tail->next = sp;
  84. entry->sparse_tail = sp;
  85. }
  86. }
  87. /*
  88. * returns number of the sparse entries
  89. */
  90. int
  91. archive_entry_sparse_count(struct archive_entry *entry)
  92. {
  93. struct ae_sparse *sp;
  94. int count = 0;
  95. for (sp = entry->sparse_head; sp != NULL; sp = sp->next)
  96. count++;
  97. /*
  98. * Sanity check if this entry is exactly sparse.
  99. * If amount of sparse blocks is just one and it indicates the whole
  100. * file data, we should remove it and return zero.
  101. */
  102. if (count == 1) {
  103. sp = entry->sparse_head;
  104. if (sp->offset == 0 &&
  105. sp->length >= archive_entry_size(entry)) {
  106. count = 0;
  107. archive_entry_sparse_clear(entry);
  108. }
  109. }
  110. return (count);
  111. }
  112. int
  113. archive_entry_sparse_reset(struct archive_entry * entry)
  114. {
  115. entry->sparse_p = entry->sparse_head;
  116. return archive_entry_sparse_count(entry);
  117. }
  118. int
  119. archive_entry_sparse_next(struct archive_entry * entry,
  120. la_int64_t *offset, la_int64_t *length)
  121. {
  122. if (entry->sparse_p) {
  123. *offset = entry->sparse_p->offset;
  124. *length = entry->sparse_p->length;
  125. entry->sparse_p = entry->sparse_p->next;
  126. return (ARCHIVE_OK);
  127. } else {
  128. *offset = 0;
  129. *length = 0;
  130. return (ARCHIVE_WARN);
  131. }
  132. }
  133. /*
  134. * end of sparse handling
  135. */