summaryrefslogtreecommitdiff
path: root/onlineupdate/source/update/src/mar_create.c
diff options
context:
space:
mode:
Diffstat (limited to 'onlineupdate/source/update/src/mar_create.c')
-rw-r--r--onlineupdate/source/update/src/mar_create.c398
1 files changed, 0 insertions, 398 deletions
diff --git a/onlineupdate/source/update/src/mar_create.c b/onlineupdate/source/update/src/mar_create.c
deleted file mode 100644
index 4e4e2b4058c2..000000000000
--- a/onlineupdate/source/update/src/mar_create.c
+++ /dev/null
@@ -1,398 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim:set ts=2 sw=2 sts=2 et cindent: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <stdlib.h>
-#include <string.h>
-#include "mar_private.h"
-#include "mar_cmdline.h"
-#include "mar.h"
-
-#ifdef _WIN32
-#include <winsock2.h>
-#else
-#include <netinet/in.h>
-#include <unistd.h>
-#endif
-
-struct MarItemStack {
- void *head;
- uint32_t size_used;
- uint32_t size_allocated;
- uint32_t last_offset;
-};
-
-/**
- * Push a new item onto the stack of items. The stack is a single block
- * of memory.
- */
-static int mar_push(struct MarItemStack *stack, uint32_t length, uint32_t flags,
- const char *name) {
- int namelen;
- uint32_t n_offset, n_length, n_flags;
- uint32_t size;
- char *data;
-
- namelen = strlen(name);
- size = MAR_ITEM_SIZE(namelen);
-
- if (stack->size_allocated - stack->size_used < size) {
- /* increase size of stack */
- size_t size_needed = ROUND_UP(stack->size_used + size, BLOCKSIZE);
- stack->head = realloc(stack->head, size_needed);
- if (!stack->head)
- return -1;
- stack->size_allocated = size_needed;
- }
-
- data = (((char *) stack->head) + stack->size_used);
-
- n_offset = htonl(stack->last_offset);
- n_length = htonl(length);
- n_flags = htonl(flags);
-
- memcpy(data, &n_offset, sizeof(n_offset));
- data += sizeof(n_offset);
-
- memcpy(data, &n_length, sizeof(n_length));
- data += sizeof(n_length);
-
- memcpy(data, &n_flags, sizeof(n_flags));
- data += sizeof(n_flags);
-
- memcpy(data, name, namelen + 1);
-
- stack->size_used += size;
- stack->last_offset += length;
- return 0;
-}
-
-static int mar_concat_file(FILE *fp, const char *path) {
- FILE *in;
- char buf[BLOCKSIZE];
- size_t len;
- int rv = 0;
-
- in = fopen(path, "rb");
- if (!in) {
- fprintf(stderr, "ERROR: could not open file in mar_concat_file()\n");
- perror(path);
- return -1;
- }
-
- while ((len = fread(buf, 1, BLOCKSIZE, in)) > 0) {
- if (fwrite(buf, len, 1, fp) != 1) {
- rv = -1;
- break;
- }
- }
-
- fclose(in);
- return rv;
-}
-
-/**
- * Writes out the product information block to the specified file.
- *
- * @param fp The opened MAR file being created.
- * @param stack A pointer to the MAR item stack being used to create
- * the MAR
- * @param infoBlock The product info block to store in the file.
- * @return 0 on success.
-*/
-static int
-mar_concat_product_info_block(FILE *fp,
- struct MarItemStack *stack,
- struct ProductInformationBlock *infoBlock)
-{
- char buf[PIB_MAX_MAR_CHANNEL_ID_SIZE + PIB_MAX_PRODUCT_VERSION_SIZE];
- uint32_t additionalBlockID = 1, infoBlockSize, unused;
- if (!fp || !infoBlock ||
- !infoBlock->MARChannelID ||
- !infoBlock->productVersion) {
- return -1;
- }
-
- /* The MAR channel name must be < 64 bytes per the spec */
- if (strlen(infoBlock->MARChannelID) > PIB_MAX_MAR_CHANNEL_ID_SIZE) {
- return -1;
- }
-
- /* The product version must be < 32 bytes per the spec */
- if (strlen(infoBlock->productVersion) > PIB_MAX_PRODUCT_VERSION_SIZE) {
- return -1;
- }
-
- /* Although we don't need the product information block size to include the
- maximum MAR channel name and product version, we allocate the maximum
- amount to make it easier to modify the MAR file for repurposing MAR files
- to different MAR channels. + 2 is for the NULL terminators. */
- infoBlockSize = sizeof(infoBlockSize) +
- sizeof(additionalBlockID) +
- PIB_MAX_MAR_CHANNEL_ID_SIZE +
- PIB_MAX_PRODUCT_VERSION_SIZE + 2;
- if (stack) {
- stack->last_offset += infoBlockSize;
- }
-
- /* Write out the product info block size */
- infoBlockSize = htonl(infoBlockSize);
- if (fwrite(&infoBlockSize,
- sizeof(infoBlockSize), 1, fp) != 1) {
- return -1;
- }
- infoBlockSize = ntohl(infoBlockSize);
-
- /* Write out the product info block ID */
- additionalBlockID = htonl(additionalBlockID);
- if (fwrite(&additionalBlockID,
- sizeof(additionalBlockID), 1, fp) != 1) {
- return -1;
- }
- additionalBlockID = ntohl(additionalBlockID);
-
- /* Write out the channel name and NULL terminator */
- if (fwrite(infoBlock->MARChannelID,
- strlen(infoBlock->MARChannelID) + 1, 1, fp) != 1) {
- return -1;
- }
-
- /* Write out the product version string and NULL terminator */
- if (fwrite(infoBlock->productVersion,
- strlen(infoBlock->productVersion) + 1, 1, fp) != 1) {
- return -1;
- }
-
- /* Write out the rest of the block that is unused */
- unused = infoBlockSize - (sizeof(infoBlockSize) +
- sizeof(additionalBlockID) +
- strlen(infoBlock->MARChannelID) +
- strlen(infoBlock->productVersion) + 2);
- memset(buf, 0, sizeof(buf));
- if (fwrite(buf, unused, 1, fp) != 1) {
- return -1;
- }
- return 0;
-}
-
-/**
- * Refreshes the product information block with the new information.
- * The input MAR must not be signed or the function call will fail.
- *
- * @param path The path to the MAR file whose product info block
- * should be refreshed.
- * @param infoBlock Out parameter for where to store the result to
- * @return 0 on success, -1 on failure
-*/
-int
-refresh_product_info_block(const char *path,
- struct ProductInformationBlock *infoBlock)
-{
- FILE *fp ;
- int rv;
- uint32_t numSignatures, additionalBlockSize, additionalBlockID,
- offsetAdditionalBlocks, numAdditionalBlocks, i;
- int additionalBlocks, hasSignatureBlock;
-
- rv = get_mar_file_info(path,
- &hasSignatureBlock,
- &numSignatures,
- &additionalBlocks,
- &offsetAdditionalBlocks,
- &numAdditionalBlocks);
- if (rv) {
- fprintf(stderr, "ERROR: Could not obtain MAR information.\n");
- return -1;
- }
-
- if (hasSignatureBlock && numSignatures) {
- fprintf(stderr, "ERROR: Cannot refresh a signed MAR\n");
- return -1;
- }
-
- fp = fopen(path, "r+b");
- if (!fp) {
- fprintf(stderr, "ERROR: could not open target file: %s\n", path);
- return -1;
- }
-
- if (fseeko(fp, offsetAdditionalBlocks, SEEK_SET)) {
- fprintf(stderr, "ERROR: could not seek to additional blocks\n");
- fclose(fp);
- return -1;
- }
-
- for (i = 0; i < numAdditionalBlocks; ++i) {
- /* Get the position of the start of this block */
- int64_t oldPos = ftello(fp);
-
- /* Read the additional block size */
- if (fread(&additionalBlockSize,
- sizeof(additionalBlockSize),
- 1, fp) != 1) {
- fclose(fp);
- return -1;
- }
- additionalBlockSize = ntohl(additionalBlockSize);
-
- /* Read the additional block ID */
- if (fread(&additionalBlockID,
- sizeof(additionalBlockID),
- 1, fp) != 1) {
- fclose(fp);
- return -1;
- }
- additionalBlockID = ntohl(additionalBlockID);
-
- if (PRODUCT_INFO_BLOCK_ID == additionalBlockID) {
- if (fseeko(fp, oldPos, SEEK_SET)) {
- fprintf(stderr, "Could not seek back to Product Information Block\n");
- fclose(fp);
- return -1;
- }
-
- if (mar_concat_product_info_block(fp, NULL, infoBlock)) {
- fprintf(stderr, "Could not concat Product Information Block\n");
- fclose(fp);
- return -1;
- }
-
- fclose(fp);
- return 0;
- } else {
- /* This is not the additional block you're looking for. Move along. */
- if (fseek(fp, additionalBlockSize, SEEK_CUR)) {
- fprintf(stderr, "ERROR: Could not seek past current block.\n");
- fclose(fp);
- return -1;
- }
- }
- }
-
- /* If we had a product info block we would have already returned */
- fclose(fp);
- fprintf(stderr, "ERROR: Could not refresh because block does not exist\n");
- return -1;
-}
-
-/**
- * Create a MAR file from a set of files.
- * @param dest The path to the file to create. This path must be
- * compatible with fopen.
- * @param numfiles The number of files to store in the archive.
- * @param files The list of null-terminated file paths. Each file
- * path must be compatible with fopen.
- * @param infoBlock The information to store in the product information block.
- * @return A non-zero value if an error occurs.
- */
-int mar_create(const char *dest, int
- num_files, char **files,
- struct ProductInformationBlock *infoBlock) {
- struct MarItemStack stack;
- uint32_t offset_to_index = 0, size_of_index,
- numSignatures, numAdditionalSections;
- uint64_t sizeOfEntireMAR = 0;
- struct stat st;
- FILE *fp;
- int i, rv = -1;
-
- memset(&stack, 0, sizeof(stack));
-
- fp = fopen(dest, "wb");
- if (!fp) {
- fprintf(stderr, "ERROR: could not create target file: %s\n", dest);
- return -1;
- }
-
- if (fwrite(MAR_ID, MAR_ID_SIZE, 1, fp) != 1)
- goto failure;
- if (fwrite(&offset_to_index, sizeof(uint32_t), 1, fp) != 1)
- goto failure;
-
- stack.last_offset = MAR_ID_SIZE +
- sizeof(offset_to_index) +
- sizeof(numSignatures) +
- sizeof(numAdditionalSections) +
- sizeof(sizeOfEntireMAR);
-
- /* We will circle back on this at the end of the MAR creation to fill it */
- if (fwrite(&sizeOfEntireMAR, sizeof(sizeOfEntireMAR), 1, fp) != 1) {
- goto failure;
- }
-
- /* Write out the number of signatures, for now only at most 1 is supported */
- numSignatures = 0;
- if (fwrite(&numSignatures, sizeof(numSignatures), 1, fp) != 1) {
- goto failure;
- }
-
- /* Write out the number of additional sections, for now just 1
- for the product info block */
- numAdditionalSections = htonl(1);
- if (fwrite(&numAdditionalSections,
- sizeof(numAdditionalSections), 1, fp) != 1) {
- goto failure;
- }
- numAdditionalSections = ntohl(numAdditionalSections);
-
- if (mar_concat_product_info_block(fp, &stack, infoBlock)) {
- goto failure;
- }
-
- for (i = 0; i < num_files; ++i) {
- if (stat(files[i], &st)) {
- fprintf(stderr, "ERROR: file not found: %s\n", files[i]);
- goto failure;
- }
-
- if (mar_push(&stack, st.st_size, st.st_mode & 0777, files[i]))
- goto failure;
-
- /* concatenate input file to archive */
- if (mar_concat_file(fp, files[i]))
- goto failure;
- }
-
- /* write out the index (prefixed with length of index) */
- size_of_index = htonl(stack.size_used);
- if (fwrite(&size_of_index, sizeof(size_of_index), 1, fp) != 1)
- goto failure;
- if (fwrite(stack.head, stack.size_used, 1, fp) != 1)
- goto failure;
-
- /* To protect against invalid MAR files, we assumes that the MAR file
- size is less than or equal to MAX_SIZE_OF_MAR_FILE. */
- if (ftell(fp) > MAX_SIZE_OF_MAR_FILE) {
- goto failure;
- }
-
- /* write out offset to index file in network byte order */
- offset_to_index = htonl(stack.last_offset);
- if (fseek(fp, MAR_ID_SIZE, SEEK_SET))
- goto failure;
- if (fwrite(&offset_to_index, sizeof(offset_to_index), 1, fp) != 1)
- goto failure;
- offset_to_index = ntohl(stack.last_offset);
-
- sizeOfEntireMAR = ((uint64_t)stack.last_offset) +
- stack.size_used +
- sizeof(size_of_index);
- sizeOfEntireMAR = HOST_TO_NETWORK64(sizeOfEntireMAR);
- if (fwrite(&sizeOfEntireMAR, sizeof(sizeOfEntireMAR), 1, fp) != 1)
- goto failure;
- sizeOfEntireMAR = NETWORK_TO_HOST64(sizeOfEntireMAR);
-
- rv = 0;
-failure:
- if (stack.head)
- free(stack.head);
- fclose(fp);
- if (rv)
- remove(dest);
- return rv;
-}