#include "../lib/io.h"

bool open_file(const char* path, FILE** file, struct stat* file_stat) {
  (*file) = fopen(path, "r");
  if ((*file) == NULL) {
    if (errno == 0) errno = EIO;
    return false;
  }

  int status = fstat(fileno((*file)), file_stat);
  if (status == -1) {
    if (errno == 0) errno = EIO;
    fclose((*file));
    return false;
  };

  if ((file_stat->st_mode & S_IFMT) != S_IFREG) {
    printf("File is not a regular file!\n");
    errno = ENOENT;
    fclose((*file));
    return false;
  }

  return true;
}

uint8_t* read_file(const char* path, size_t* size) {
  // Read the contents of the file specified by path into a heap-allocated
  // buffer and return a pointer to that buffer.
  FILE* f;
  struct stat statOfFile;
  if (!open_file(path, &f, &statOfFile)) {
    return NULL;
  }

  struct sysinfo info;
  int r = sysinfo(&info);
  if (r != 0 || info.freeram < (unsigned long)(statOfFile.st_blksize *
                                               statOfFile.st_blocks * 2)) {
    errno = ENOMEM;
    return NULL;
  }

  uint8_t* data = malloc(statOfFile.st_blksize * statOfFile.st_blocks);
  if (data == NULL) {
    fclose(f);
    return NULL;
  }

  size_t bytesRead =
      fread(data, statOfFile.st_blksize, statOfFile.st_blocks, f);
  // size_t bytesRead = fread(data, sizeof(uint8_t), statOfFile.st_size, f);
  if (bytesRead != 0 && !feof(f)) {
    fclose(f);
    if (errno == 0) errno = EIO;
    return NULL;
  }

  fclose(f);

  (*size) = statOfFile.st_size;
  return data;
}