/*
 * Copyright (C) 2009 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#include "applypatch.h"
#include "edify/expr.h"
#include "mincrypt/sha.h"

int CheckMode(int argc, char** argv) {
    if (argc < 3) {
        return 2;
    }
    return applypatch_check(argv[2], argc-3, argv+3);
}

int SpaceMode(int argc, char** argv) {
    if (argc != 3) {
        return 2;
    }
    char* endptr;
    size_t bytes = strtol(argv[2], &endptr, 10);
    if (bytes == 0 && endptr == argv[2]) {
        printf("can't parse \"%s\" as byte count\n\n", argv[2]);
        return 1;
    }
    return CacheSizeCheck(bytes);
}

// Parse arguments (which should be of the form "<sha1>" or
// "<sha1>:<filename>" into the new parallel arrays *sha1s and
// *patches (loading file contents into the patches).  Returns 0 on
// success.
static int ParsePatchArgs(int argc, char** argv,
                          char*** sha1s, Value*** patches, int* num_patches) {
    *num_patches = argc;
    *sha1s = malloc(*num_patches * sizeof(char*));
    *patches = malloc(*num_patches * sizeof(Value*));
    memset(*patches, 0, *num_patches * sizeof(Value*));

    uint8_t digest[SHA_DIGEST_SIZE];

    int i;
    for (i = 0; i < *num_patches; ++i) {
        char* colon = strchr(argv[i], ':');
        if (colon != NULL) {
            *colon = '\0';
            ++colon;
        }

        if (ParseSha1(argv[i], digest) != 0) {
            printf("failed to parse sha1 \"%s\"\n", argv[i]);
            return -1;
        }

        (*sha1s)[i] = argv[i];
        if (colon == NULL) {
            (*patches)[i] = NULL;
        } else {
            FileContents fc;
            if (LoadFileContents(colon, &fc) != 0) {
                goto abort;
            }
            (*patches)[i] = malloc(sizeof(Value));
            (*patches)[i]->type = VAL_BLOB;
            (*patches)[i]->size = fc.size;
            (*patches)[i]->data = (char*)fc.data;
        }
    }

    return 0;

  abort:
    for (i = 0; i < *num_patches; ++i) {
        Value* p = (*patches)[i];
        if (p != NULL) {
            free(p->data);
            free(p);
        }
    }
    free(*sha1s);
    free(*patches);
    return -1;
}

int PatchMode(int argc, char** argv) {
    Value* bonus = NULL;
    if (argc >= 3 && strcmp(argv[1], "-b") == 0) {
        FileContents fc;
        if (LoadFileContents(argv[2], &fc) != 0) {
            printf("failed to load bonus file %s\n", argv[2]);
            return 1;
        }
        bonus = malloc(sizeof(Value));
        bonus->type = VAL_BLOB;
        bonus->size = fc.size;
        bonus->data = (char*)fc.data;
        argc -= 2;
        argv += 2;
    }

    if (argc < 6) {
        return 2;
    }

    char* endptr;
    size_t target_size = strtol(argv[4], &endptr, 10);
    if (target_size == 0 && endptr == argv[4]) {
        printf("can't parse \"%s\" as byte count\n\n", argv[4]);
        return 1;
    }

    char** sha1s;
    Value** patches;
    int num_patches;
    if (ParsePatchArgs(argc-5, argv+5, &sha1s, &patches, &num_patches) != 0) {
        printf("failed to parse patch args\n");
        return 1;
    }

    int result = applypatch(argv[1], argv[2], argv[3], target_size,
                            num_patches, sha1s, patches, bonus);

    int i;
    for (i = 0; i < num_patches; ++i) {
        Value* p = patches[i];
        if (p != NULL) {
            free(p->data);
            free(p);
        }
    }
    if (bonus) {
        free(bonus->data);
        free(bonus);
    }
    free(sha1s);
    free(patches);

    return result;
}

// This program applies binary patches to files in a way that is safe
// (the original file is not touched until we have the desired
// replacement for it) and idempotent (it's okay to run this program
// multiple times).
//
// - if the sha1 hash of <tgt-file> is <tgt-sha1>, does nothing and exits
//   successfully.
//
// - otherwise, if the sha1 hash of <src-file> is <src-sha1>, applies the
//   bsdiff <patch> to <src-file> to produce a new file (the type of patch
//   is automatically detected from the file header).  If that new
//   file has sha1 hash <tgt-sha1>, moves it to replace <tgt-file>, and
//   exits successfully.  Note that if <src-file> and <tgt-file> are
//   not the same, <src-file> is NOT deleted on success.  <tgt-file>
//   may be the string "-" to mean "the same as src-file".
//
// - otherwise, or if any error is encountered, exits with non-zero
//   status.
//
// <src-file> (or <file> in check mode) may refer to an MTD partition
// to read the source data.  See the comments for the
// LoadMTDContents() function above for the format of such a filename.

int main(int argc, char** argv) {
    if (argc < 2) {
      usage:
        printf(
            "usage: %s [-b <bonus-file>] <src-file> <tgt-file> <tgt-sha1> <tgt-size> "
            "[<src-sha1>:<patch> ...]\n"
            "   or  %s -c <file> [<sha1> ...]\n"
            "   or  %s -s <bytes>\n"
            "   or  %s -l\n"
            "\n"
            "Filenames may be of the form\n"
            "  MTD:<partition>:<len_1>:<sha1_1>:<len_2>:<sha1_2>:...\n"
            "to specify reading from or writing to an MTD partition.\n\n",
            argv[0], argv[0], argv[0], argv[0]);
        return 2;
    }

    int result;

    if (strncmp(argv[1], "-l", 3) == 0) {
        result = ShowLicenses();
    } else if (strncmp(argv[1], "-c", 3) == 0) {
        result = CheckMode(argc, argv);
    } else if (strncmp(argv[1], "-s", 3) == 0) {
        result = SpaceMode(argc, argv);
    } else {
        result = PatchMode(argc, argv);
    }

    if (result == 2) {
        goto usage;
    }
    return result;
}
