PageRenderTime 32ms CodeModel.GetById 14ms app.highlight 14ms RepoModel.GetById 1ms app.codeStats 0ms

/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
 39#include <sys/types.h>
 40#include <sys/stat.h>
 41#include <fcntl.h>
 42#include <stdlib.h>
 43#include <stdio.h>
 44#include <string.h>
 45#include "mar.h"
 46#include "mar_private.h"
 47
 48#ifdef XP_WIN
 49#include <winsock2.h>
 50#else
 51#include <netinet/in.h>
 52#include <unistd.h>
 53#endif
 54
 55struct MarItemStack {
 56  void *head;
 57  PRUint32 size_used;
 58  PRUint32 size_allocated;
 59  PRUint32 last_offset;
 60};
 61
 62/**
 63 * Push a new item onto the stack of items.  The stack is a single block
 64 * of memory.
 65 */
 66static int mar_push(struct MarItemStack *stack, PRUint32 length, PRUint32 flags,
 67                    const char *name) {
 68  int namelen;
 69  PRUint32 n_offset, n_length, n_flags;
 70  PRUint32 size;
 71  char *data;
 72  
 73  namelen = strlen(name);
 74  size = MAR_ITEM_SIZE(namelen);
 75
 76  if (stack->size_allocated - stack->size_used < size) {
 77    /* increase size of stack */
 78    size_t size_needed = ROUND_UP(stack->size_used + size, BLOCKSIZE);
 79    stack->head = realloc(stack->head, size_needed);
 80    if (!stack->head)
 81      return -1;
 82    stack->size_allocated = size_needed;
 83  }
 84
 85  data = (((char *) stack->head) + stack->size_used);
 86
 87  n_offset = htonl(stack->last_offset);
 88  n_length = htonl(length);
 89  n_flags = htonl(flags);
 90
 91  memcpy(data, &n_offset, sizeof(n_offset));
 92  data += sizeof(n_offset);
 93
 94  memcpy(data, &n_length, sizeof(n_length));
 95  data += sizeof(n_length);
 96
 97  memcpy(data, &n_flags, sizeof(n_flags));
 98  data += sizeof(n_flags);
 99
100  memcpy(data, name, namelen + 1);
101  
102  stack->size_used += size;
103  stack->last_offset += length;
104  return 0;
105}
106
107static int mar_concat_file(FILE *fp, const char *path) {
108  FILE *in;
109  char buf[BLOCKSIZE];
110  size_t len;
111  int rv = 0;
112
113  in = fopen(path, "rb");
114  if (!in)
115    return -1;
116
117  while ((len = fread(buf, 1, BLOCKSIZE, in)) > 0) {
118    if (fwrite(buf, len, 1, fp) != 1) {
119      rv = -1;
120      break;
121    }
122  }
123
124  fclose(in);
125  return rv;
126}
127
128int mar_create(const char *dest, int num_files, char **files) {
129  struct MarItemStack stack;
130  PRUint32 offset_to_index = 0, size_of_index;
131  struct stat st;
132  FILE *fp;
133  int i, rv = -1;
134
135  memset(&stack, 0, sizeof(stack));
136
137  fp = fopen(dest, "wb");
138  if (!fp) {
139    fprintf(stderr, "ERROR: could not create target file: %s\n", dest);
140    return -1;
141  }
142
143  if (fwrite(MAR_ID, MAR_ID_SIZE, 1, fp) != 1)
144    goto failure;
145  if (fwrite(&offset_to_index, sizeof(PRUint32), 1, fp) != 1)
146    goto failure;
147
148  stack.last_offset = MAR_ID_SIZE + sizeof(PRUint32);
149
150  for (i = 0; i < num_files; ++i) {
151    if (stat(files[i], &st)) {
152      fprintf(stderr, "ERROR: file not found: %s\n", files[i]);
153      goto failure;
154    }
155
156    if (mar_push(&stack, st.st_size, st.st_mode & 0777, files[i]))
157      goto failure;
158
159    /* concatenate input file to archive */
160    if (mar_concat_file(fp, files[i]))
161      goto failure;
162  }
163
164  /* write out the index (prefixed with length of index) */
165  size_of_index = htonl(stack.size_used);
166  if (fwrite(&size_of_index, sizeof(size_of_index), 1, fp) != 1)
167    goto failure;
168  if (fwrite(stack.head, stack.size_used, 1, fp) != 1)
169    goto failure;
170
171  /* write out offset to index file in network byte order */
172  offset_to_index = htonl(stack.last_offset);
173  if (fseek(fp, MAR_ID_SIZE, SEEK_SET))
174    goto failure;
175  if (fwrite(&offset_to_index, sizeof(offset_to_index), 1, fp) != 1)
176    goto failure;
177
178  rv = 0;
179failure: 
180  if (stack.head)
181    free(stack.head);
182  fclose(fp);
183  if (rv)
184    remove(dest);
185  return rv;
186}