/modules/libmar/src/mar_create.c

http://github.com/zpao/v8monkey · C · 186 lines · 113 code · 28 blank · 45 comment · 24 complexity · e4f9a47011be0c8e6d832062460288d1 MD5 · raw file

  1. /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
  2. /* vim:set ts=2 sw=2 sts=2 et cindent: */
  3. /* ***** BEGIN LICENSE BLOCK *****
  4. * Version: MPL 1.1/GPL 2.0/LGPL 2.1
  5. *
  6. * The contents of this file are subject to the Mozilla Public License Version
  7. * 1.1 (the "License"); you may not use this file except in compliance with
  8. * the License. You may obtain a copy of the License at
  9. * http://www.mozilla.org/MPL/
  10. *
  11. * Software distributed under the License is distributed on an "AS IS" basis,
  12. * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  13. * for the specific language governing rights and limitations under the
  14. * License.
  15. *
  16. * The Original Code is Mozilla Archive code.
  17. *
  18. * The Initial Developer of the Original Code is Google Inc.
  19. * Portions created by the Initial Developer are Copyright (C) 2005
  20. * the Initial Developer. All Rights Reserved.
  21. *
  22. * Contributor(s):
  23. * Darin Fisher <darin@meer.net>
  24. *
  25. * Alternatively, the contents of this file may be used under the terms of
  26. * either the GNU General Public License Version 2 or later (the "GPL"), or
  27. * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  28. * in which case the provisions of the GPL or the LGPL are applicable instead
  29. * of those above. If you wish to allow use of your version of this file only
  30. * under the terms of either the GPL or the LGPL, and not to allow others to
  31. * use your version of this file under the terms of the MPL, indicate your
  32. * decision by deleting the provisions above and replace them with the notice
  33. * and other provisions required by the GPL or the LGPL. If you do not delete
  34. * the provisions above, a recipient may use your version of this file under
  35. * the terms of any one of the MPL, the GPL or the LGPL.
  36. *
  37. * ***** END LICENSE BLOCK ***** */
  38. #include <sys/types.h>
  39. #include <sys/stat.h>
  40. #include <fcntl.h>
  41. #include <stdlib.h>
  42. #include <stdio.h>
  43. #include <string.h>
  44. #include "mar.h"
  45. #include "mar_private.h"
  46. #ifdef XP_WIN
  47. #include <winsock2.h>
  48. #else
  49. #include <netinet/in.h>
  50. #include <unistd.h>
  51. #endif
  52. struct MarItemStack {
  53. void *head;
  54. PRUint32 size_used;
  55. PRUint32 size_allocated;
  56. PRUint32 last_offset;
  57. };
  58. /**
  59. * Push a new item onto the stack of items. The stack is a single block
  60. * of memory.
  61. */
  62. static int mar_push(struct MarItemStack *stack, PRUint32 length, PRUint32 flags,
  63. const char *name) {
  64. int namelen;
  65. PRUint32 n_offset, n_length, n_flags;
  66. PRUint32 size;
  67. char *data;
  68. namelen = strlen(name);
  69. size = MAR_ITEM_SIZE(namelen);
  70. if (stack->size_allocated - stack->size_used < size) {
  71. /* increase size of stack */
  72. size_t size_needed = ROUND_UP(stack->size_used + size, BLOCKSIZE);
  73. stack->head = realloc(stack->head, size_needed);
  74. if (!stack->head)
  75. return -1;
  76. stack->size_allocated = size_needed;
  77. }
  78. data = (((char *) stack->head) + stack->size_used);
  79. n_offset = htonl(stack->last_offset);
  80. n_length = htonl(length);
  81. n_flags = htonl(flags);
  82. memcpy(data, &n_offset, sizeof(n_offset));
  83. data += sizeof(n_offset);
  84. memcpy(data, &n_length, sizeof(n_length));
  85. data += sizeof(n_length);
  86. memcpy(data, &n_flags, sizeof(n_flags));
  87. data += sizeof(n_flags);
  88. memcpy(data, name, namelen + 1);
  89. stack->size_used += size;
  90. stack->last_offset += length;
  91. return 0;
  92. }
  93. static int mar_concat_file(FILE *fp, const char *path) {
  94. FILE *in;
  95. char buf[BLOCKSIZE];
  96. size_t len;
  97. int rv = 0;
  98. in = fopen(path, "rb");
  99. if (!in)
  100. return -1;
  101. while ((len = fread(buf, 1, BLOCKSIZE, in)) > 0) {
  102. if (fwrite(buf, len, 1, fp) != 1) {
  103. rv = -1;
  104. break;
  105. }
  106. }
  107. fclose(in);
  108. return rv;
  109. }
  110. int mar_create(const char *dest, int num_files, char **files) {
  111. struct MarItemStack stack;
  112. PRUint32 offset_to_index = 0, size_of_index;
  113. struct stat st;
  114. FILE *fp;
  115. int i, rv = -1;
  116. memset(&stack, 0, sizeof(stack));
  117. fp = fopen(dest, "wb");
  118. if (!fp) {
  119. fprintf(stderr, "ERROR: could not create target file: %s\n", dest);
  120. return -1;
  121. }
  122. if (fwrite(MAR_ID, MAR_ID_SIZE, 1, fp) != 1)
  123. goto failure;
  124. if (fwrite(&offset_to_index, sizeof(PRUint32), 1, fp) != 1)
  125. goto failure;
  126. stack.last_offset = MAR_ID_SIZE + sizeof(PRUint32);
  127. for (i = 0; i < num_files; ++i) {
  128. if (stat(files[i], &st)) {
  129. fprintf(stderr, "ERROR: file not found: %s\n", files[i]);
  130. goto failure;
  131. }
  132. if (mar_push(&stack, st.st_size, st.st_mode & 0777, files[i]))
  133. goto failure;
  134. /* concatenate input file to archive */
  135. if (mar_concat_file(fp, files[i]))
  136. goto failure;
  137. }
  138. /* write out the index (prefixed with length of index) */
  139. size_of_index = htonl(stack.size_used);
  140. if (fwrite(&size_of_index, sizeof(size_of_index), 1, fp) != 1)
  141. goto failure;
  142. if (fwrite(stack.head, stack.size_used, 1, fp) != 1)
  143. goto failure;
  144. /* write out offset to index file in network byte order */
  145. offset_to_index = htonl(stack.last_offset);
  146. if (fseek(fp, MAR_ID_SIZE, SEEK_SET))
  147. goto failure;
  148. if (fwrite(&offset_to_index, sizeof(offset_to_index), 1, fp) != 1)
  149. goto failure;
  150. rv = 0;
  151. failure:
  152. if (stack.head)
  153. free(stack.head);
  154. fclose(fp);
  155. if (rv)
  156. remove(dest);
  157. return rv;
  158. }