// File: simap[P]ecctools/archiver.cpp
// Function: main
int main(int argc, char ** argv) {
  const struct uECC_Curve_t * curve = uECC_secp256k1();

  if (argc < 4) {
    fprintf(stderr, "Need a key, at least one input file, and an output file\n");
    return -1;
  }

  uint32_t numFiles = argc - 3;
  char ** fileNames = &argv[2];

  //check all files first
  for (int fileNum = 0; fileNum < numFiles; fileNum++) {
    int filesize = fsize(fileNames[fileNum]);
    if (filesize < 1) {
      fprintf(stderr, "Can't stat file: %s\n", fileNames[fileNum]);
      return -1;      
    }
  }

  uint8_t privateKey[32];
  char tmp[200];
  FILE * fp, *fpout;
  int nread;

  sprintf(tmp, "%s.key", argv[1]);
  fp = fopen(tmp, "rb");
  nread = fread(privateKey, 1, sizeof(privateKey), fp);
  fclose(fp);
  if (nread != sizeof(privateKey)) {
    fprintf(stderr, "can't read key %s\n", tmp);
    return -1;
  }

  fpout = fopen(argv[argc-1], "wb");
  fwrite("STFU", 4, 1, fpout);
  fwrite(&numFiles, sizeof(numFiles), 1, fpout);

  for (int fileNum = 0; fileNum < numFiles; fileNum++) {
    char * fileName = fileNames[fileNum];
    int bytesRemaining = fsize(fileName);
    fp = fopen(fileName, "rb");

    //do header
    FUFileHeader header = {0};
    FUFileFooter footer = {0};
    header.type = 1;
    header.size = bytesRemaining;
    {
      char * fileBaseName = strdup(fileName);
      strncpy(header.name, basename(fileBaseName), sizeof(header.name)-1);
      free(fileBaseName);
    }
    fwrite(&header, sizeof(header), 1, fpout);

    //hash header + file, and copy to archive
    uint8_t buf[512];
    SHA256 sha;
    sha.update(&header, sizeof(header));
    while (bytesRemaining > 0) {
      int nread = fread(buf, 1, 512, fp);
      if (nread > 0) {
        bytesRemaining -= nread;
        fwrite(buf, 1, nread, fpout);
        sha.update(buf, nread);
      } else {
        break;
      }
    }
    if (bytesRemaining) {
      fprintf(stderr, "had trouble reading file for hash %s\n", fileName);
      return -1;
    }
    fclose(fp);

    //hash, sign, and write out footer
    sha.finalize(footer.hash, 32);
    uECC_sign(privateKey, footer.hash, 32, footer.signature, curve);
    fwrite(&footer, sizeof(footer), 1, fpout);

  }
  fclose(fpout);
  printf("signed transfer file update archive complete!\n");
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x4f0, %rsp            # imm = 0x4F0
movl $0x0, -0x4(%rbp)
movl %edi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
callq 0x18a0
movq %rax, -0x18(%rbp)
cmpl $0x4, -0x8(%rbp)
jge 0x131c
movq 0x9ce1(%rip), %rax      # 0xafe0
movq (%rax), %rdi
leaq 0x6cfb(%rip), %rsi      # 0x8004
movb $0x0, %al
callq 0x1100
movl $0xffffffff, -0x4(%rbp) # imm = 0xFFFFFFFF
jmp 0x17cd
movl -0x8(%rbp), %eax
subl $0x3, %eax
movl %eax, -0x1c(%rbp)
movq -0x10(%rbp), %rax
addq $0x10, %rax
movq %rax, -0x28(%rbp)
movl $0x0, -0x2c(%rbp)
movl -0x2c(%rbp), %eax
cmpl -0x1c(%rbp), %eax
jae 0x1397
movq -0x28(%rbp), %rax
movslq -0x2c(%rbp), %rcx
movq (%rax,%rcx,8), %rdi
callq 0x1280
movl %eax, -0x30(%rbp)
cmpl $0x1, -0x30(%rbp)
jge 0x138a
movq 0x9c7f(%rip), %rax      # 0xafe0
movq (%rax), %rdi
movq -0x28(%rbp), %rax
movslq -0x2c(%rbp), %rcx
movq (%rax,%rcx,8), %rdx
leaq 0x6cc6(%rip), %rsi      # 0x803d
movb $0x0, %al
callq 0x1100
movl $0xffffffff, -0x4(%rbp) # imm = 0xFFFFFFFF
jmp 0x17cd
jmp 0x138c
movl -0x2c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x2c(%rbp)
jmp 0x1338
leaq -0x120(%rbp), %rdi
movq -0x10(%rbp), %rax
movq 0x8(%rax), %rdx
leaq 0x6ca5(%rip), %rsi      # 0x8052
movb $0x0, %al
callq 0x1040
leaq -0x120(%rbp), %rdi
leaq 0x6c97(%rip), %rsi      # 0x8059
callq 0x10e0
movq %rax, -0x128(%rbp)
leaq -0x50(%rbp), %rdi
movq -0x128(%rbp), %rcx
movl $0x1, %esi
movl $0x20, %edx
callq 0x1120
movl %eax, -0x134(%rbp)
movq -0x128(%rbp), %rdi
callq 0x10c0
movslq -0x134(%rbp), %rax
cmpq $0x20, %rax
je 0x1432
movq 0x9bd2(%rip), %rax      # 0xafe0
movq (%rax), %rdi
leaq -0x120(%rbp), %rdx
leaq 0x6c3d(%rip), %rsi      # 0x805c
movb $0x0, %al
callq 0x1100
movl $0xffffffff, -0x4(%rbp) # imm = 0xFFFFFFFF
jmp 0x17cd
movq -0x10(%rbp), %rax
movl -0x8(%rbp), %ecx
subl $0x1, %ecx
movslq %ecx, %rcx
movq (%rax,%rcx,8), %rdi
leaq 0x6c25(%rip), %rsi      # 0x806f
callq 0x10e0
movq %rax, -0x130(%rbp)
movq -0x130(%rbp), %rcx
leaq 0x6c0e(%rip), %rdi      # 0x8072
movl $0x4, %esi
movl $0x1, %edx
callq 0x1160
movq -0x130(%rbp), %rcx
leaq -0x1c(%rbp), %rdi
movl $0x4, %esi
movl $0x1, %edx
callq 0x1160
movl $0x0, -0x138(%rbp)
movl -0x138(%rbp), %eax
cmpl -0x1c(%rbp), %eax
jae 0x17b3
movq -0x28(%rbp), %rax
movslq -0x138(%rbp), %rcx
movq (%rax,%rcx,8), %rax
movq %rax, -0x140(%rbp)
movq -0x140(%rbp), %rdi
callq 0x1280
movl %eax, -0x144(%rbp)
movq -0x140(%rbp), %rdi
leaq 0x6b7d(%rip), %rsi      # 0x8059
callq 0x10e0
movq %rax, -0x128(%rbp)
xorps %xmm0, %xmm0
movaps %xmm0, -0x4e0(%rbp)
movaps %xmm0, -0x160(%rbp)
movaps %xmm0, -0x170(%rbp)
movaps %xmm0, -0x180(%rbp)
movaps %xmm0, -0x190(%rbp)
movaps %xmm0, -0x1a0(%rbp)
movaps %xmm0, -0x1b0(%rbp)
movl $0x0, -0x150(%rbp)
movaps %xmm0, -0x1c0(%rbp)
movaps %xmm0, -0x1d0(%rbp)
movaps %xmm0, -0x1e0(%rbp)
movaps %xmm0, -0x1f0(%rbp)
movaps %xmm0, -0x200(%rbp)
movaps %xmm0, -0x210(%rbp)
movl $0x1, -0x1b0(%rbp)
movl -0x144(%rbp), %eax
movl %eax, -0x1ac(%rbp)
movq -0x140(%rbp), %rdi
callq 0x1150
movq %rax, -0x218(%rbp)
leaq -0x1a8(%rbp), %rax
movq %rax, -0x4d0(%rbp)
movq -0x218(%rbp), %rdi
callq 0x1130
movq -0x4d0(%rbp), %rdi
movq %rax, %rsi
movl $0x5b, %edx
callq 0x1070
movq -0x218(%rbp), %rdi
callq 0x10f0
movq -0x130(%rbp), %rcx
leaq -0x1b0(%rbp), %rdi
movq %rdi, -0x4c0(%rbp)
movl $0x64, %esi
movq %rsi, -0x4b8(%rbp)
movl $0x1, %edx
callq 0x1160
leaq -0x498(%rbp), %rdi
movq %rdi, -0x4c8(%rbp)
callq 0x6680
movq -0x4c8(%rbp), %rdi
movq -0x4c0(%rbp), %rsi
movq -0x4b8(%rbp), %rdx
callq 0x67a0
jmp 0x160d
jmp 0x160f
cmpl $0x0, -0x144(%rbp)
jle 0x16d5
movq -0x128(%rbp), %rcx
leaq -0x420(%rbp), %rdi
movl $0x1, %esi
movl $0x200, %edx            # imm = 0x200
callq 0x1120
movq %rax, -0x4e8(%rbp)
jmp 0x1642
movq -0x4e8(%rbp), %rax
movl %eax, -0x4a8(%rbp)
cmpl $0x0, -0x4a8(%rbp)
jle 0x16ce
movl -0x4a8(%rbp), %ecx
movl -0x144(%rbp), %eax
subl %ecx, %eax
movl %eax, -0x144(%rbp)
movslq -0x4a8(%rbp), %rdx
movq -0x130(%rbp), %rcx
leaq -0x420(%rbp), %rdi
movl $0x1, %esi
callq 0x1160
jmp 0x168d
movslq -0x4a8(%rbp), %rdx
leaq -0x498(%rbp), %rdi
leaq -0x420(%rbp), %rsi
callq 0x67a0
jmp 0x16a9
jmp 0x16d0
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x4a0(%rbp)
movl %eax, -0x4a4(%rbp)
leaq -0x498(%rbp), %rdi
callq 0x6710
jmp 0x17d9
jmp 0x16d5
jmp 0x160f
cmpl $0x0, -0x144(%rbp)
je 0x1710
movq 0x98fb(%rip), %rax      # 0xafe0
movq (%rax), %rdi
movq -0x140(%rbp), %rdx
leaq 0x6981(%rip), %rsi      # 0x8077
movb $0x0, %al
callq 0x1100
movl $0xffffffff, -0x4(%rbp) # imm = 0xFFFFFFFF
movl $0x1, -0x4ac(%rbp)
jmp 0x1783
movq -0x128(%rbp), %rdi
callq 0x10c0
jmp 0x171e
leaq -0x498(%rbp), %rdi
leaq -0x210(%rbp), %rsi
movl $0x20, %edx
callq 0x6db0
jmp 0x1738
leaq -0x1f0(%rbp), %rcx
movq -0x18(%rbp), %r8
leaq -0x50(%rbp), %rdi
leaq -0x210(%rbp), %rsi
movl $0x20, %edx
callq 0x29b0
jmp 0x175a
movq -0x130(%rbp), %rcx
leaq -0x210(%rbp), %rdi
movl $0x60, %esi
movl $0x1, %edx
callq 0x1160
jmp 0x1779
movl $0x0, -0x4ac(%rbp)
leaq -0x498(%rbp), %rdi
callq 0x6710
movl -0x4ac(%rbp), %eax
testl %eax, %eax
je 0x179d
jmp 0x179b
jmp 0x17cd
jmp 0x179f
movl -0x138(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x138(%rbp)
jmp 0x1497
movq -0x130(%rbp), %rdi
callq 0x10c0
leaq 0x68d7(%rip), %rdi      # 0x809d
movb $0x0, %al
callq 0x1030
movl -0x4(%rbp), %eax
addq $0x4f0, %rsp            # imm = 0x4F0
popq %rbp
retq
movq -0x4a0(%rbp), %rdi
callq 0x1140
nopw %cs:(%rax,%rax)
nop