Beispiel #1
0
static struct cdir_entry *
find_cdir_entry (struct cdir_entry *entry, int count, const char *name)
{
  size_t name_size = strlen(name);
  while (count--) {
    if (letoh16(entry->filename_size) == name_size &&
        !memcmp(entry->data, name, name_size))
      return entry;
    entry = (struct cdir_entry *)((char *)entry + cdir_entry_size(entry));
  }
  return NULL;
}
Beispiel #2
0
static uint32_t find_lowest_offset(struct cdir_entry *entry, int count)
{
	uint32_t lowest_offset = zip_size;
	while (count--) {
		uint32_t entry_offset = le32toh(entry->offset);
		if (lowest_offset > entry_offset)
			lowest_offset = entry_offset;

		if (le32toh(entry->signature) != 0x02014b50) {
			printf("invalid signature on cdir_entry! (count=%d)\n", count);
			exit(-1);
		}

		entry = (struct cdir_entry *)((char *)entry + cdir_entry_size(entry));
	}
	return lowest_offset;
}
Beispiel #3
0
static int
repack(bool flatten, const char *dstpath, const char *srcpath)
{
	char *src_zip = (char *)map_file(srcpath);
	if (!src_zip) {
		printf("Could not open zip file.\n");
		return -1;
	}

	int fd = creat(dstpath, 0777);
	if (fd == -1) {
		printf("can't open output file\n");
		return -1;
	}

	struct cdir_end *dirend = (struct cdir_end *)(src_zip + zip_size - sizeof(*dirend));
	while ((void *)dirend > src_zip &&
	       le32toh(dirend->signature) != 0x06054b50)
		dirend = (struct cdir_end *)((char *)dirend - 1);

	if (le32toh(dirend->signature) != 0x06054b50) {
		printf("couldn't find end of central directory record!\n");
		return -1;
	}

	uint32_t cdir_offset = le32toh(dirend->cdir_offset);
	uint16_t cdir_entries = le16toh(dirend->cdir_entries);
	uint32_t cdir_size = le32toh(dirend->cdir_size);

	TRACE("Found %d entries. cdir offset at %d\n",
	      cdir_entries, cdir_offset);

	struct cdir_entry *cdir_start = (struct cdir_entry *)(src_zip + cdir_offset);
	struct cdir_entry *new_cdir_start = (struct cdir_entry *)malloc(cdir_size);
	if (!new_cdir_start) {
		TRACE("couldn't allocate central directory copy\n");
		return -1;
	}

	memcpy(new_cdir_start, cdir_start, cdir_size);

	uint32_t lowest_offset = find_lowest_offset(cdir_start, cdir_entries);	
	uint32_t out_offset = simple_write(fd, src_zip, lowest_offset);

	struct cdir_entry *current_entry = new_cdir_start;
	uint16_t i = cdir_entries;
	while (i--) {
		struct local_file_header *file = (struct local_file_header *)(src_zip + le32toh(current_entry->offset));

		int rc;
		if (flatten)
			rc = flatten_entry(fd, file, current_entry, out_offset);
		else
			rc = squeeze_entry(fd, file, current_entry, out_offset);
		if (rc)
			return rc;

		current_entry = (struct cdir_entry *)((char *)current_entry + cdir_entry_size(current_entry));
	}

	uint32_t new_cdir_offset;
	if (cdir_offset < lowest_offset) {
		TRACE("Doing in place cdir replacement at %d\n", cdir_offset);
		new_cdir_offset = cdir_offset;
		lseek(fd, SEEK_SET, cdir_offset);
		simple_write(fd, (char *)new_cdir_start, cdir_size);
		lseek(fd, SEEK_END, 0);
	} else {
		new_cdir_offset = out_offset;
		TRACE("Appending cdir at %d\n", new_cdir_offset);
		simple_write(fd, (char *)new_cdir_start, cdir_size);
	}

	struct cdir_end end;
	memcpy(&end, dirend, sizeof(end));
	end.cdir_offset = htole32(new_cdir_offset);
	simple_write(fd, (char *)&end, sizeof(end));
	close(fd);
	munmap(src_zip, zip_size);

	return 0;
}