/*
 * Copyright (C) 2019 The LineageOS 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 <stdarg.h>
#include <stdio.h>
#include <stdlib.h>

#include <dirent.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/vfs.h>
#include <unistd.h>

#include <cutils/log.h>
#include <cutils/properties.h>

#include <selinux/label.h>

#include <fs_mgr.h>
#include "roots.h"

#include "bu.h"

#define PATHNAME_RC "/tmp/burc"

using namespace std;

using namespace android;

struct selabel_handle* sehandle;

int adb_ifd;
int adb_ofd;
TAR* tar;
gzFile gzf;

char* hash_name;
size_t hash_datalen;
SHA_CTX sha_ctx;
MD5_CTX md5_ctx;

void ui_print(const char* format, ...) {
  char buffer[256];

  va_list ap;
  va_start(ap, format);
  vsnprintf(buffer, sizeof(buffer), format, ap);
  va_end(ap);

  fputs(buffer, stdout);
}

void logmsg(const char* fmt, ...) {
  char msg[1024];
  FILE* fp;
  va_list ap;

  va_start(ap, fmt);
  vsnprintf(msg, sizeof(msg), fmt, ap);
  va_end(ap);

  fp = fopen("/tmp/bu.log", "a");
  if (fp) {
    fprintf(fp, "[%d] %s", getpid(), msg);
    fclose(fp);
  }
}

static partspec partlist[MAX_PART];
static partspec* curpart;

int part_add(const char* name) {
  Volume* vol = NULL;
  char* path = NULL;
  int i;

  path = (char*)malloc(1 + strlen(name) + 1);
  sprintf(path, "/%s", name);
  vol = volume_for_mount_point(path);
  if (vol == NULL || vol->fs_type == NULL) {
    logmsg("missing vol info for %s, ignoring\n", name);
    goto err;
  }

  for (i = 0; i < MAX_PART; ++i) {
    if (partlist[i].name == NULL) {
      partlist[i].name = strdup(name);
      partlist[i].path = path;
      partlist[i].vol = vol;
      logmsg("part_add: i=%d, name=%s, path=%s\n", i, name, path);
      return 0;
    }
    if (strcmp(partlist[i].name, name) == 0) {
      logmsg("duplicate partition %s, ignoring\n", name);
      goto err;
    }
  }

err:
  free(path);
  return -1;
}

partspec* part_get(int i) {
  if (i >= 0 && i < MAX_PART) {
    if (partlist[i].name != NULL) {
      return &partlist[i];
    }
  }
  return NULL;
}

partspec* part_find(const char* name) {
  for (int i = 0; i < MAX_PART; ++i) {
    if (partlist[i].name && !strcmp(name, partlist[i].name)) {
      return &partlist[i];
    }
  }
  return NULL;
}

void part_set(partspec* part) {
  curpart = part;
  curpart->off = 0;
}

int update_progress(uint64_t off) {
  static time_t last_time = 0;
  static int last_pct = 0;
  if (curpart) {
    curpart->off += off;
    time_t now = time(NULL);
    int pct = min(100, (int)((uint64_t)100 * curpart->off / curpart->used));
    if (now != last_time && pct != last_pct) {
      char msg[256];
      sprintf(msg, "%s: %d%% complete", curpart->name, pct);
      ui_print(msg);
      last_time = now;
      last_pct = pct;
    }
  }
  return 0;
}

static int tar_cb_open(const char* path, int mode, ...) {
  errno = EINVAL;
  return -1;
}

static int tar_cb_close(int fd) {
  return 0;
}

static ssize_t tar_cb_read(int fd, void* buf, size_t len) {
  ssize_t nread;
  nread = ::read(fd, buf, len);
  if (nread > 0 && hash_name) {
    SHA1_Update(&sha_ctx, (u_char*)buf, nread);
    MD5_Update(&md5_ctx, buf, nread);
    hash_datalen += nread;
  }
  update_progress(nread);
  return nread;
}

static ssize_t tar_cb_write(int fd, const void* buf, size_t len) {
  ssize_t written = 0;

  if (hash_name) {
    SHA1_Update(&sha_ctx, (u_char*)buf, len);
    MD5_Update(&md5_ctx, buf, len);
    hash_datalen += len;
  }

  while (len > 0) {
    ssize_t n = ::write(fd, buf, len);
    if (n < 0) {
      logmsg("tar_cb_write: error: n=%d\n", n);
      return n;
    }
    if (n == 0) break;
    buf = (const char*)buf + n;
    len -= n;
    written += n;
  }
  update_progress(written);
  return written;
}

static tartype_t tar_io = { tar_cb_open, tar_cb_close, tar_cb_read, tar_cb_write };

static ssize_t tar_gz_cb_read(int fd, void* buf, size_t len) {
  int nread;
  nread = gzread(gzf, buf, len);
  if (nread > 0 && hash_name) {
    SHA1_Update(&sha_ctx, (u_char*)buf, nread);
    MD5_Update(&md5_ctx, buf, nread);
    hash_datalen += nread;
  }
  update_progress(nread);
  return nread;
}

static ssize_t tar_gz_cb_write(int fd, const void* buf, size_t len) {
  ssize_t written = 0;

  if (hash_name) {
    SHA1_Update(&sha_ctx, (u_char*)buf, len);
    MD5_Update(&md5_ctx, buf, len);
    hash_datalen += len;
  }

  while (len > 0) {
    ssize_t n = gzwrite(gzf, buf, len);
    if (n < 0) {
      logmsg("tar_gz_cb_write: error: n=%d\n", n);
      return n;
    }
    if (n == 0) break;
    buf = (const char*)buf + n;
    len -= n;
    written += n;
  }
  update_progress(written);
  return written;
}

static tartype_t tar_io_gz = { tar_cb_open, tar_cb_close, tar_gz_cb_read, tar_gz_cb_write };

int create_tar(int fd, const char* compress, const char* mode) {
  int rc = -1;

  SHA1_Init(&sha_ctx);
  MD5_Init(&md5_ctx);

  if (!compress || strcasecmp(compress, "none") == 0) {
    rc = tar_fdopen(&tar, fd, "foobar", &tar_io, 0, /* oflags: unused */
                    0,                              /* mode: unused */
                    TAR_GNU | TAR_STORE_SELINUX /* options */);
  } else if (strcasecmp(compress, "gzip") == 0) {
    gzf = gzdopen(fd, mode);
    if (gzf != NULL) {
      rc = tar_fdopen(&tar, 0, "foobar", &tar_io_gz, 0, /* oflags: unused */
                      0,                                /* mode: unused */
                      TAR_GNU | TAR_STORE_SELINUX /* options */);
    }
  }
  return rc;
}

static void do_exit(int rc) {
  char rcstr[80];
  int len;
  len = sprintf(rcstr, "%d\n", rc);

  unlink(PATHNAME_RC);
  int fd = open(PATHNAME_RC, O_RDWR | O_CREAT, 0644);
  write(fd, rcstr, len);
  close(fd);
  exit(rc);
}

int main(int argc, char** argv) {
  int rc = 1;

  const char* logfile = "/tmp/recovery.log";
  adb_ifd = dup(STDIN_FILENO);
  adb_ofd = dup(STDOUT_FILENO);
  freopen(logfile, "a", stdout);
  setbuf(stdout, NULL);
  freopen(logfile, "a", stderr);
  setbuf(stderr, NULL);

  logmsg("bu: invoked with %d args\n", argc);

  if (argc < 2) {
    logmsg("Not enough args (%d)\n", argc);
    do_exit(1);
  }

  // progname args...
  int optidx = 1;
  const char* opname = argv[optidx++];

  struct selinux_opt seopts[] = { { SELABEL_OPT_PATH, "/file_contexts" } };
  sehandle = selabel_open(SELABEL_CTX_FILE, seopts, 1);

  load_volume_table();

  if (!strcmp(opname, "backup")) {
    ui_print("Backup in progress...");
    rc = do_backup(argc - optidx, &argv[optidx]);
  } else if (!strcmp(opname, "restore")) {
    ui_print("Restore in progress...");
    rc = do_restore(argc - optidx, &argv[optidx]);
  } else {
    logmsg("Unknown operation %s\n", opname);
    rc = 1;
  }

  close(adb_ofd);
  close(adb_ifd);

  sleep(1);

  logmsg("bu exiting\n");

  do_exit(rc);

  return rc;
}
