-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathcontainer.c
More file actions
98 lines (82 loc) · 2.76 KB
/
container.c
File metadata and controls
98 lines (82 loc) · 2.76 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
#define _GNU_SOURCE
#include <err.h>
#include <errno.h>
#include <linux/limits.h>
#include <sched.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mount.h>
#include <sys/stat.h>
#include <wait.h>
#include "change_root.h"
#define CONTAINER_ID_MAX 16
#define CHILD_STACK_SIZE 4096 * 10
typedef struct container {
char id[CONTAINER_ID_MAX];
// TODO: Add fields
} container_t;
/**
* `usage` prints the usage of `client` and exists the program with
* `EXIT_FAILURE`
*/
void usage(char* cmd) {
printf("Usage: %s [ID] [IMAGE] [CMD]...\n", cmd);
exit(EXIT_FAILURE);
}
/**
* `container_exec` is an entry point of a child process and responsible for
* creating an overlay filesystem, calling `change_root` and executing the
* command given as arguments.
*/
int container_exec(void* arg) {
container_t* container = (container_t*)arg;
// this line is required on some systems
if (mount("/", "/", "none", MS_PRIVATE | MS_REC, NULL) < 0) {
err(1, "mount / private");
}
// TODO: Create a overlay filesystem
// `lowerdir` should be the image directory: ${cwd}/images/${image}
// `upperdir` should be `/tmp/container/{id}/upper`
// `workdir` should be `/tmp/container/{id}/work`
// `merged` should be `/tmp/container/{id}/merged`
// ensure all directories exist (create if not exists) and
// call `mount("overlay", merged, "overlay", MS_RELATIME,
// lowerdir={lowerdir},upperdir={upperdir},workdir={workdir})`
// TODO: Call `change_root` with the `merged` directory
// change_root(merged)
// TODO: use `execvp` to run the given command and return its return value
return 0;
}
int main(int argc, char** argv) {
if (argc < 4) {
usage(argv[0]);
}
/* Create tmpfs and mount it to `/tmp/container` so overlayfs can be used
* inside Docker containers */
if (mkdir("/tmp/container", 0700) < 0 && errno != EEXIST) {
err(1, "Failed to create a directory to store container file systems");
}
if (errno != EEXIST) {
if (mount("tmpfs", "/tmp/container", "tmpfs", 0, "") < 0) {
err(1, "Failed to mount tmpfs on /tmp/container");
}
}
/* cwd contains the absolute path to the current working directory which can
* be useful constructing path for image */
char cwd[PATH_MAX];
getcwd(cwd, PATH_MAX);
container_t container;
strncpy(container.id, argv[1], CONTAINER_ID_MAX);
// TODO: store all necessary information to `container`
/* Use `clone` to create a child process */
char child_stack[CHILD_STACK_SIZE]; // statically allocate stack for child
int clone_flags = SIGCHLD | CLONE_NEWNS | CLONE_NEWPID;
int pid = clone(container_exec, &child_stack, clone_flags, &container);
if (pid < 0) {
err(1, "Failed to clone");
}
waitpid(pid, NULL, 0);
return EXIT_SUCCESS;
}