Skip to content
Snippets Groups Projects
auxiliary.c 3.72 KiB
Newer Older
/**
 * Use a fifo to signal that we want to stop the api server.
 */
void stop_server()
{
    printf("Stopping cryptops-api server...\n");
    int fifo;
    char fifo_path[] = FIFO_PATH;
    fifo = open(fifo_path, O_WRONLY);
    char * msg = "stop";
    write(fifo, msg, strlen(msg) + 1);
}

/**
 * Read a file completely into a string.
 * @param  filename Path to the file to read.
 * @return          Contents of the file.
 */
char * read_file(const char * filename)
{
    char * buffer = NULL;
    long length;
    FILE * file = fopen(filename, "rb");
    if (filename != NULL)
    {
        if (file)
            fseek(file, 0, SEEK_END);
            length = ftell(file);
            fseek(file, 0, SEEK_SET);
            buffer = o_malloc(length + 1);
            if (buffer)
            {
                fread(buffer, 1, length, file);
            }
            buffer[length] = '\0';
            fclose (file);
        }
        return buffer;
    }
    else
    {
        return NULL;
    }
}

/**
 * Respond to the request with a simple json structure '{$field: $value}'.
 * @param  response    response struct to use
 * @param  http_status HTTP status code to return
 * @param  field       name of the json field to return
 * @param  value       json value to return
int send_simple_response(struct _u_response * response, int http_status,
    const char * field, const char * value)
{
    json_t * json_body = NULL;
    json_body = json_object();
    json_object_set_new(json_body, field, json_string(value));
    ulfius_set_json_body_response(response, http_status, json_body);
    json_decref(json_body);
    return U_CALLBACK_CONTINUE;
}

/**
 * Determine the size of a block device.
 * @param  device_path Path to the block device.
 * @return             Size of the device in bytes.
 */
unsigned long device_size(char * device_path)
{
    int fd;
    unsigned long numblocks = 0;

    fd = open(device_path, O_RDONLY);
    ioctl(fd, BLKGETSIZE, &numblocks);
    close(fd);
    printf("Number of blocks: %lu, this makes %.3f GB\n",
        numblocks, (double)numblocks * 512.0 / (1024 * 1024 * 1024));
    return (numblocks * 512);
}

/**
 * Determine available memory.
 * @return Available memory in bytes.
 */
unsigned long available_memory()
{
  struct sysinfo myinfo;
  unsigned long free_bytes;
  sysinfo(&myinfo);
  free_bytes = myinfo.mem_unit * myinfo.freeram;
  printf("Free memory: %lu B, %lu MB\n",
      free_bytes, free_bytes / 1024 / 1024);
  return free_bytes;
}

/**
 * Determine the usage of the given filesystem.
 * @param  path Path of the mounted filesystem.
 * @return      Number of bytes used, or -1 in case of failure.
 */
unsigned long filesystem_usage(const char * path)
{
    struct statvfs s;
    int r = statvfs(path, &s);
    if (r != 0)
    {
        return -1;
    }
    return (s.f_blocks - s.f_bfree) * s.f_bsize;
}

/**
 * Mount a filesystem; create the mount target if it doesn't exist.
 * @param  device_path Path to the device to mount.
 * @param  mount_path  Path to the mount target.
 * @return             Status code.
 */
int temporary_mount(char * device_path, char * mount_path,
    char * filesystem_type)
{
    struct stat st = {0};
    if (stat(mount_path, &st) == -1)
    {
        mkdir(mount_path, 0700);
    }
    // Mount the device.
    unsigned long mount_flags = MS_NOATIME | MS_NODEV | MS_NOEXEC;
    int r = mount(device_path, mount_path, filesystem_type,
        mount_flags, "");
    return r;
}
Arie Peterson's avatar
Arie Peterson committed
/**
 * Reboot the system. We cannot simply use the `reboot` command because
 * we're running as init (pid 0).
 */
void reboot_initrd()
{
    pid_t pid;
    pid = vfork();
    if (pid == 0)
    {
        // Child.
Arie Peterson's avatar
Arie Peterson committed
        reboot(RB_AUTOBOOT);
        _exit(EXIT_SUCCESS);
    }
    // Parent (init) waits.
    while (1);
}