/* Copyright © Triad National Security, LLC, and others.

   This interface contains Charliecloud’s core containerization features. */

#define _GNU_SOURCE
#pragma once

#include <sched.h>
#include <stdbool.h>
#include <stdint.h>
#include <sys/types.h>

#include "misc.h"


/** Types **/

typedef uint64_t bindflags;  // lower 32 bits used by mount(2)

struct bind {
   char *src;
   char *dst;
   bindflags flags;
};

struct container;  // forward declaration to avoid definition loop
typedef void (hookf_t)(struct container *, void *);
struct hook {
   const char *name;
   hookf_t *f;
   void *data;
};

enum hook_dup {    // see hook_add()
   HOOK_DUP_OK,
   HOOK_DUP_SKIP,
   HOOK_DUP_FAIL
};

enum img_type {
   IMG_DIRECTORY,  // normal directory, perhaps an external mount of some kind
   IMG_SQUASH,     // SquashFS archive file (not yet mounted)
   IMG_NAME,       // name of image in storage
   IMG_NONE,       // image type is not set yet
};

struct container {
   struct bind *binds;
   gid_t container_gid;  // GID to use in container
   uid_t container_uid;  // UID to use in container
   char **environ;       // container environment
   bool env_expand;      // expand variables in --set-env
   bool fuse_threaded;   // use multi-threaded FUSE
   struct hook *hooks_all;    // after pivot_root(2) all join members
   struct hook *hooks_guest;  // after pivot_root(2)
   struct hook *hooks_host;   // before pivot_root(2)
   char *host_home;      // if --home, host path to user homedir, else NULL
   char *img_ref;        // image description from command line
   char *initial_dir;    // path of initial CWD of user command
   char *newroot;        // path to new root directory
   bool join;            // is this a synchronized join?
   int join_ct;          // number of peers in a synchronized join
   pid_t join_pid;       // process in existing namespace to join
   char *join_tag;       // identifier for synchronized join
   char *overlay_size;   // size of overlaid tmpfs (NULL for no overlay)
   bool private_passwd;  // don’t bind custom /etc/{passwd,group}
   bool private_tmp;     // don’t bind host's /tmp
   enum img_type type;   // directory, SquashFS, etc.
   bool writable;        // re-mount image read-write
};


/** Constants **/

#define BD_MASK          0xff00000000000000
#define BD_SRC_OPTIONAL  0x8000000000000000
#define BD_DST_OPTIONAL  0x4000000000000000
#define BD_DST_CREATE    0x2000000000000000
#define BD_DST_MERGE     0x1000000000000000
#define BD_OPTIONAL      (BD_SRC_OPTIONAL | BD_DST_OPTIONAL)


/** Function prototypes **/

void bind_mount(const char *src, const char *dst, const char *newroot,
                bindflags flags, const char *scratch);
void containerize(struct container *c);
void hook_add(struct hook **hook_list, enum hook_dup dup,
              const char *name, hookf_t *f, void *d);
void hooks_run(struct container *c, const char *tag, struct hook *hook_list);
enum img_type image_type(const char *ref, const char *images_dir);
char *img_name2path(const char *name, const char *storage_dir);
noreturn run_user_command(struct container *c, char *argv[]);
