Compare commits

...

69 Commits

Author SHA1 Message Date
Pin
dc69f665eb readme 2024-05-21 23:18:56 -04:00
Pin
ec6fac8537 . 2024-05-21 23:17:21 -04:00
Pin
4dd55da7e7 debug 2024-05-21 23:11:14 -04:00
Pin
8fa0c4b259 magic 2024-05-21 21:36:50 -04:00
Pin
84fffca8e5 format 2024-05-21 21:27:47 -04:00
Pin
e4d58ff94b testing 2024-05-21 21:08:35 -04:00
Pin
fdd643c528 efhjksedjksejkn.fk 2024-05-14 22:31:05 -04:00
Pin
81bc834b26 yes i try i 2024-05-14 22:09:54 -04:00
e4d2076fa2 Send message to a worker 2024-04-04 22:59:10 -04:00
3f8bd314b6 Make a frontend in front of an actor 2024-03-30 17:14:49 -04:00
8be9dfc093 Add a clean target 2024-03-30 16:18:47 -04:00
f11569691f Move build target to first target
This makes it so you can just run make to build both the client and the daemon.
2024-03-30 16:18:33 -04:00
873ed765f4 Do not modify the argument we are given.
By duplicating it, we make it so popping frames off the message does not modify the argument.
This make sure the value remains useful to the caller.
2024-03-07 18:50:47 -05:00
2493f8916a Update usage
Tell users they should specify the name for an image.
2024-03-07 18:42:05 -05:00
bc7ccbd805 Move function implementations out of the header file. 2024-03-06 23:32:07 -05:00
5f98d369fa Prefix libguestfs-inspect functions with guestfs_inspect_.
The functions are also made non-static.
This is in preparation to moving the header function implementations to a .c file.
2024-03-06 23:32:07 -05:00
1d17e047b7 Add header guard to libguestfs-inspect.h 2024-03-06 23:22:29 -05:00
3c9564cb3e Use environment variable for the socket.
The default behavior is to create a socket file at /tmp/guestfs-inspect.sock.
If XDG_RUNTIME_DIR is set, that will be used instead of /tmp.

One could instead specify GUESTFS_INSPECT_ENDPOINT, which requires the full endpoint, as specified by: https://libzmq.readthedocs.io/en/zeromq3-x/zmq_connect.html

You will likely want to use ipc://, but you can probably use tcp:// or (e)pgm:// if that is appropriate.
2024-03-06 23:22:29 -05:00
ba3ac50325 Remove unused include 2024-03-06 19:25:05 -05:00
465d6f0cd4 Set workdir in the Dockerfile 2024-03-06 19:24:34 -05:00
1378a5a31a Free the worker 2024-03-06 19:24:34 -05:00
Pin
46d9500d3a small fix 2024-03-05 20:40:11 -05:00
Pin
20fc94fb35 testing errors 2024-03-03 18:46:41 -05:00
c6f9204014 Cat seems to hang forever 2024-03-03 17:43:58 -05:00
6700d98ad6 Fully branch cat and ls 2024-03-03 17:41:06 -05:00
49b9f43c76 Initial branching by command in the client 2024-03-03 17:23:54 -05:00
ebc07d0cf7 Add common support for cat command. 2024-03-03 17:19:11 -05:00
75139f709d Start branching based on the command type 2024-03-03 17:15:03 -05:00
1e5357c4cf Added destroy command function 2024-03-03 17:14:43 -05:00
7d9c451799 Resolve leaks in the client 2024-03-03 17:02:24 -05:00
a7992436b1 Replace multi-worker attempt with simple single worker
Get things working before scaling it up
2024-03-03 16:54:02 -05:00
e94211e5f4 Cleanup socket 2024-03-03 16:52:47 -05:00
2b4aa5cbaf Add message to show the number of paths sent to the worker to ls 2024-03-03 16:51:03 -05:00
bdf9fc7718 Fix error reading from the wrong msg object 2024-03-03 16:50:45 -05:00
b99513c8b3 Fix serialization
Was putting new data in the front of the message instead of the end.
This mismatched with how I was deserializing the messages
2024-03-03 16:50:45 -05:00
32a03a3895 Add message to show when the daemon is ready 2024-03-03 16:50:45 -05:00
16e95af02a Serialize struct from the client 2024-03-03 16:48:44 -05:00
a4b56107aa Add deserialize function 2024-03-03 16:09:58 -05:00
8a814b1d93 Add basic serialization of the message 2024-03-03 15:57:53 -05:00
9422f77119 Update struct to use pointers instead of flexible length structs 2024-03-03 15:46:18 -05:00
859ee90048 Send message from daemon to client 2024-03-03 15:41:10 -05:00
83f62dc217 Remove router loop 2024-03-03 15:35:11 -05:00
ea58a6ebd3 Do not use redundant pointer to pointer 2024-03-03 15:22:36 -05:00
eaf8dde6c3 Do not use draft API 2024-03-03 15:22:15 -05:00
26af0a5a5d trying to use the draft api to get router ids 2024-03-03 15:18:18 -05:00
187acad82a Trying to send a reply string from the worker 2024-03-03 15:18:18 -05:00
d6c57e9e32 Automatically select the first worker for development 2024-03-03 14:19:32 -05:00
07ee70b002 Add print statements for debugging 2024-03-03 14:16:51 -05:00
d60c0d419b Add debug flag 2024-03-03 02:05:33 -05:00
ec9a78a459 Send the message and get the reply 2024-03-03 02:05:33 -05:00
2c4cb0e235 Uncomment worker loop 2024-03-03 02:05:33 -05:00
fd2ee16f79 Renamed enum 2024-03-03 02:05:33 -05:00
44a5f6773c Build command object 2024-03-03 02:05:33 -05:00
Pin
d01a6e593a Merge branch 'dev' of https://git.robbyzambito.me/robby/guestfs-inspect into dev 2024-03-03 01:13:14 -05:00
Pin
2505662cfb breaking out init_guestfs and cat_file 2024-03-03 01:12:59 -05:00
d09b118ad7 Build the client from the Makefile 2024-03-03 01:04:13 -05:00
ce8d3843a3 cleanup after junior engineer 2024-03-03 01:01:56 -05:00
2bdf450d65 Initial client 2024-03-03 01:01:56 -05:00
73d8b6716b Dispatch message to worker by name 2024-03-03 01:01:31 -05:00
26c742f017 Update dockerfile 2024-03-03 00:56:28 -05:00
052aa99a6c Fix Spencers HORRIBLE spelling. 2024-03-03 00:32:56 -05:00
Pin
cbb0a440e9 zmsg_send changes 2024-03-02 23:54:37 -05:00
Pin
ac70e240c8 format 2024-03-02 23:50:20 -05:00
Pin
991ffb5224 Merge branch 'dev' of https://git.robbyzambito.me/robby/guestfs-inspect into dev 2024-03-02 23:35:01 -05:00
15322a601b Add command union and name of the disk to be associated with. 2024-03-02 23:29:39 -05:00
6ca7727ee8 Add initial header file
This will be used in the client and the daemon
2024-03-02 23:29:39 -05:00
Pin
9899945354 Merge branch 'dev' of https://git.robbyzambito.me/robby/guestfs-inspect into dev 2024-03-02 23:08:00 -05:00
Pin
e3c82eabdd adding worker task 2024-03-02 23:07:58 -05:00
78cbc47487 Fix bug where I initialized the worker wrong. 2024-03-02 23:02:57 -05:00
9 changed files with 602 additions and 37 deletions

1
.gitignore vendored
View File

@@ -2,3 +2,4 @@ guestfs-inspect
guestfs-inspectd
*~
*.qcow2
venv/

View File

@@ -1,3 +1,11 @@
FROM debian
FROM debian as builder
RUN apt update && apt upgrade -y && apt install -y libczmq-dev libguestfs-dev gcc valgrind gdb make
RUN apt update && apt upgrade -y
RUN apt install -y libczmq-dev libguestfs-dev gcc valgrind gdb make pkg-config
COPY . /opt
WORKDIR /opt
FROM builder as compile
RUN make

View File

@@ -1,2 +1,17 @@
build:
gcc guestfs-inspectd.c -o guestfs-inspectd `pkg-config libguestfs libczmq --cflags --libs`
build: daemon client
debug: daemon-debug client-debug
daemon:
gcc -Wall guestfs-inspectd.c libguestfs-inspect.c -o guestfs-inspectd `pkg-config libguestfs libczmq --cflags --libs`
client:
gcc -Wall guestfs-inspect.c libguestfs-inspect.c -o guestfs-inspect `pkg-config libguestfs libczmq --cflags --libs`
daemon-debug:
gcc -ggdb3 -Wall guestfs-inspectd.c libguestfs-inspect.c -o guestfs-inspectd `pkg-config libguestfs libczmq --cflags --libs`
client-debug:
gcc -ggdb3 -Wall guestfs-inspect.c libguestfs-inspect.c -o guestfs-inspect `pkg-config libguestfs libczmq --cflags --libs`
clean:
rm guestfs-inspect guestfs-inspectd

17
README.md Normal file
View File

@@ -0,0 +1,17 @@
# Edda
```
,ggggggg,
,dP""""""Y8b 8I 8I
d8' a Y8 8I 8I
88 "Y8P' 8I 8I
`8baaaa 8I 8I
,d8P"""" ,gggg,8I ,gggg,8I ,gggg,gg
d8" dP" "Y8I dP" "Y8I dP" "Y8I
Y8, i8' ,8I i8' ,8I i8' ,8I
`Yba,,_____, ,d8, ,d8b,,d8, ,d8b,,d8, ,d8b,
`"Y8888888 P"Y8888P"`Y8P"Y8888P"`Y8P"Y8888P"`Y8
```

21
client.py Normal file
View File

@@ -0,0 +1,21 @@
import zmq
context = zmq.Context()
socket = context.socket(zmq.REQ)
socket.connect('ipc:///run/user/1000/guestfs-inspect.sock')
tt = 1
tt_size = 1
message = "test"
socket.send(message.encode('utf-8'), flags=zmq.SNDMORE)
socket.send(tt.to_bytes(4, 'little'), flags=zmq.SNDMORE)
socket.send(tt_size.to_bytes(8, 'little'), flags=zmq.SNDMORE)
socket.send('/etc/os-release'.encode('utf-8'), flags=zmq.SNDMORE)
socket.send(''.encode('utf-8'))
message = socket.recv()
print(message.decode('utf-8'))
socket.close()
context.destroy()

View File

@@ -0,0 +1,85 @@
#include <stdio.h>
#include <stdlib.h>
#include <czmq.h>
#include <guestfs.h>
#include "libguestfs-inspect.h"
#define STREQ(a, b) (strcmp((a), (b)) == 0)
void print_help(char *);
enum guestfs_inspect_command_const parse_command(const char *);
int main(int argc, char **argv) {
if (argc == 1) {
print_help(argv[0]);
return EXIT_SUCCESS;
}
char *ep = guestfs_inspect_endpoint();
zsock_t *daemon = zsock_new_req(ep);
free(ep);
struct guestfs_inpsect_command *command = malloc(sizeof(struct guestfs_inpsect_command));
command->name = calloc(strlen(argv[1]) + 1, sizeof(char));
strcpy(command->name, argv[1]);
command->command = parse_command(argv[2]);
switch (command->command) {
case GUESTFS_COMMAND_LS:
command->args.ls.paths_length = 1;
command->args.ls.paths = calloc(1, sizeof(char *));
command->args.ls.paths[0] = calloc(strlen(argv[3] + 1), sizeof(char));
strcpy(command->args.ls.paths[0], argv[3]);
break;
case GUESTFS_COMMAND_CAT:
command->args.cat.paths_length = 1;
command->args.cat.paths = calloc(1, sizeof(char *));
command->args.cat.paths[0] = calloc(strlen(argv[3] + 1), sizeof(char));
strcpy(command->args.cat.paths[0], argv[3]);
break;
}
zmsg_t *msg = guestfs_inspect_command_to_zmsg(command);
zmsg_send(&msg, daemon);
zmsg_t *rep = zmsg_recv(daemon);
char *res = NULL;
// process reply
switch (command->command) {
case GUESTFS_COMMAND_LS:
res = zmsg_popstr(rep);
printf("Res:\n%s\n", res);
free(res);
break;
case GUESTFS_COMMAND_CAT:
res = zmsg_popstr(rep);
printf("Res:\n%s\n", res);
free(res);
break;
}
zmsg_destroy(&msg);
zmsg_destroy(&rep);
zsock_destroy(&daemon);
guestfs_inspect_command_destroy(&command);
return EXIT_SUCCESS;
}
void print_help(char *name) {
printf("Usage: %s [name] [command] <arguments>\n", name);
printf("Commands:\n");
printf(" ls <path>\n");
printf(" cat <path>\n");
}
enum guestfs_inspect_command_const parse_command(const char *input) {
if (STREQ(input, "ls")) {
return GUESTFS_COMMAND_LS;
} else if (STREQ(input, "cat")) {
return GUESTFS_COMMAND_CAT;
}
exit(EXIT_FAILURE);
}

View File

@@ -1,62 +1,322 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <czmq.h>
#include <zmsg.h>
#include <zactor.h>
#include <guestfs.h>
#include <time.h>
#include "libguestfs-inspect.h"
#define STREQ(a, b) (strcmp((a), (b)) == 0)
void *worker_task;
static void worker_task(zsock_t*, const char*);
char *endpoint(void);
static int compare_key_len(const void*, const void*);
static int count_mountpoints(char *const *argv);
static int compare_key_len(const void *p1, const void *p2) {
const char *key1 = *(char* const*) p1;
const char *key2 = *(char* const*) p2;
return strlen(key1) - strlen(key2);
}
static void print_intro() {
printf("\n"
"\n"
" ,ggggggg,\n"
" ,dP\"\"\"\"\"\"Y8b 8I 8I\n"
" d8' a Y8 8I 8I\n"
" 88 \"Y8P\' 8I 8I\n"
" `8baaaa 8I 8I\n"
",d8P\"\"\"\" ,gggg,8I ,gggg,8I ,gggg,gg\n"
"d8\" dP\" \"Y8I dP\" \"Y8I dP\" \"Y8I\n"
"Y8, i8' ,8I i8' ,8I i8' ,8I\n"
"`Yba,,_____, ,d8, ,d8b,,d8, ,d8b,,d8, ,d8b,\n"
" `\"Y8888888 P\"Y8888P\"`Y8P\"Y8888P\"`Y8P\"Y8888P\"`Y8\n"
"\n");
}
static int count_mountpoints(char *const *argv) {
size_t c;
for (c = 0; argv[c]; c++) {}
return c;
}
static void cat_file(guestfs_h *g, const char *file_path, char **file_content, size_t *file_size) {
assert((*file_content) == NULL);
if (guestfs_is_file_opts(g, file_path, GUESTFS_IS_FILE_OPTS_FOLLOWSYMLINKS, 1, -1) > 0) {
(*file_content) = guestfs_read_file(g, file_path, file_size);
if ((*file_content) == NULL) {
exit(EXIT_FAILURE);
}
}
return;
}
static guestfs_h* init_guestfs(const char *disk_path) {
guestfs_h *g = NULL;
char **roots, **mountpoints;
char *root;
size_t i, j;
// Create a connection handle
g = guestfs_create();
if (g == NULL) {
exit(EXIT_FAILURE);
}
// Adding disk_path to connection handle
if (guestfs_add_drive_opts(g, disk_path, GUESTFS_ADD_DRIVE_OPTS_READONLY, 1, -1) == -1) {
exit(EXIT_FAILURE);
}
// Launching connection handle
if (guestfs_launch(g) == -1) {
exit(EXIT_FAILURE);
}
// Pulling rootfs information
roots = guestfs_inspect_os(g);
if (roots == NULL) {
exit(EXIT_FAILURE);
}
// Looping through roots to mount mountpoints
for (j = 0; roots[j] != NULL; j++) {
root = roots[j];
mountpoints = guestfs_inspect_get_mountpoints(g, root);
if (mountpoints == NULL) {
exit(EXIT_FAILURE);
}
// Sorting mountpoints to be in {'${device_path}', '${mount_path}'} format
qsort(mountpoints, count_mountpoints(mountpoints) / 2, 2 * sizeof (char*), compare_key_len);
for (i = 0; mountpoints[i] != NULL; i += 2) {
guestfs_mount_ro(g, mountpoints[i+1], mountpoints[i]);
free(mountpoints[i]);
free(mountpoints[i+1]);
}
free(mountpoints);
free(root);
}
free(roots);
return g;
}
static void worker_task(zsock_t *pipe, const char *disk_path) {
guestfs_h *g;
g = init_guestfs(disk_path);
zsock_t *worker = zsock_new_dealer("inproc://workers");
// ZeroMQ Opens here
zsock_signal(pipe, 0);
while (true) {
zmsg_t *msg = zmsg_recv(pipe);
if (!msg) {
break;
}
zframe_t *client_id = zmsg_pop(msg);
// Checking for term message
if (zframe_streq(client_id, "$TERM")) {
zframe_destroy(&client_id);
zmsg_destroy(&msg);
break;
}
struct guestfs_inpsect_command *command = guestfs_inspect_zmsg_to_command(msg);
zmsg_t *reply = zmsg_new();
if (!reply) {
printf("wuddahec\n");
exit(EXIT_FAILURE);
}
switch (command->command) {
case GUESTFS_COMMAND_LS:;
zmsg_pushstr(reply, "From worker! -- not implemented");
break;
case GUESTFS_COMMAND_CAT:;
char *res = NULL;
size_t s = 0;
cat_file(g, command->args.cat.paths[0], &res, &s);
zmsg_addmem(reply, res, s);
free(res);
break;
default:;
zmsg_pushstr(reply, "Unknown command");
break;
}
// Sending reply
zmsg_pushstr(reply, "");
zmsg_prepend(reply, &client_id);
zmsg_send(&reply, worker);
guestfs_inspect_command_destroy(&command);
zframe_destroy(&client_id);
zmsg_destroy(&msg);
zmsg_destroy(&reply);
}
guestfs_shutdown(g);
guestfs_close(g);
zsock_destroy(&worker);
exit(EXIT_SUCCESS);
}
typedef struct {
char *name;
zactor_t *worker;
} zactor_worker_map;
char *strdup(const char *);
void mapping_zactor_worker(const char *name, zactor_t *worker, zactor_worker_map **map, size_t mapper_size) {
map[mapper_size - 1] = malloc(sizeof(zactor_worker_map));
(*map[mapper_size - 1]).name = strdup(name);
(*map[mapper_size - 1]).worker = worker;
return;
}
zactor_t * zactor_worker_lookup(char *name, zactor_worker_map **map, size_t mapper_size) {
size_t i = 0;
for (i = 0; i < mapper_size; i++) {
if (strcmp((*map[i]).name, name) == 0) {
return map[i]->worker;
}
}
return NULL;
}
static void log_message(const char *message) {
time_t ltime;
struct tm *result;
char *stime;
ltime = time(NULL);
result = localtime(&ltime);
stime = asctime(result);
strtok(stime, "\n");
printf("[%s] %s\n", stime, message);
}
int main(int argc, char **argv) {
if (argc < 2) {
printf("Usage: %s <disk-path> ...\n", argv[0]);
return EXIT_FAILURE;
printf("Usage: %s <disk-path>:<name> ...\n", argv[0]);
exit(EXIT_FAILURE);
}
const int worker_count = argc - 1;
print_intro();
// One worker per disk image.
struct {
char *name;
zactor_t *worker;
} worker_map[worker_count];
// Zactor setup
size_t worker_map_size = 0;
zactor_worker_map **worker_map = NULL;
for (int i = 0; i < worker_count; i++) {
log_message("Starting Workers");
for (int i = 0; i < argc - 1; i++) {
worker_map_size++;
worker_map = realloc(worker_map, sizeof(zactor_worker_map *) * worker_map_size);
char *path = strtok(argv[i+1], ":");
worker_map[i].name = strtok(NULL, ":");
zactor_new(worker_map[i].worker, path);
char *name = strtok(NULL, ":");
mapping_zactor_worker(name, zactor_new((void *)worker_task, path), worker_map, worker_map_size);
}
char *ep = endpoint();
zsock_t *frontend = zsock_new_router(ep);
if (worker_map == NULL) {
log_message("Worker map was empty");
exit(EXIT_FAILURE);
}
// Setup daemon ipc endpoint
char *ep = guestfs_inspect_endpoint();
// Setting up endpoint log message
char *ep_log = (char *)malloc((strlen(ep) * sizeof(char)) + 32);
// Sending endpoint log message
sprintf(ep_log, "Endpoint: %s", ep); // NOLINT
log_message(ep_log);
free(ep_log);
// Setup ZMQ routers
zsock_t *frontend = zsock_new(ZMQ_ROUTER);
zsock_bind(frontend, "%s", ep);
free(ep);
zsock_t *backend = zsock_new(ZMQ_ROUTER);
zsock_bind(backend, "inproc://workers");
// Connecting frontend to backend
zpoller_t *poller = zpoller_new(frontend, backend, NULL);
assert(poller);
log_message("Server listening for requests");
zframe_t *message_pop = NULL;
while (true) {
zmsg_t *msg = zmsg_recv(frontend);
if (!msg) break;
// Find the worker with the given name.
zactor_t *worker = NULL;
for (int i = 0; i < worker_count; i++) {
void *sock = zpoller_wait(poller, -1);
if (!sock) {
break;
}
if (worker) {
zmsg_send(&msg, zactor_sock(worker));
if (sock == frontend) {
zmsg_t *msg = zmsg_recv(frontend);
// reply id
zframe_t *identity = zmsg_pop(msg);
// Null frame
message_pop = zmsg_pop(msg);
// Destroy immediately
zframe_destroy(&message_pop);
struct guestfs_inpsect_command *c = guestfs_inspect_zmsg_to_command(msg);
if (c == NULL) {
log_message("Error creating inspect command");
zmsg_destroy(&msg);
zframe_destroy(&identity);
continue;
}
zactor_t *zactor_tmp = zactor_worker_lookup(c->name, worker_map, worker_map_size);
if (zactor_tmp != NULL) {
// send request to worker
zmsg_prepend(msg, &identity);
zactor_send(zactor_tmp, &msg);
} else {
// add failure response
}
zactor_tmp = NULL;
guestfs_inspect_command_destroy(&c);
zmsg_destroy(&msg);
zframe_destroy(&identity);
} else if (sock == backend) {
zmsg_t *msg = zmsg_recv(backend);
message_pop = zmsg_pop(msg); // Removing backend id
// Destroy immediately
zframe_destroy(&message_pop);
zmsg_send(&msg, frontend);
zmsg_destroy(&msg);
} else {
// The name specified does not exist.
log_message("Socket found from unknown zsock");
}
}
return EXIT_SUCCESS;
log_message("Cleaning up workers");
// Cleanup
for (size_t i = 0; i < worker_map_size; i++) {
zactor_destroy(&worker_map[i]->worker);
free(worker_map[i]->name);
free(worker_map[i]);
}
free(worker_map);
zpoller_destroy(&poller);
zsock_destroy(&frontend);
zsock_destroy(&backend);
exit(EXIT_SUCCESS);
}
char *endpoint() {
// TODO: This should be based on GUESTFS_INSPECT_ENDPOINT, or XDG_RUNTIME_DIR if the former is not set, and default to a sensible path if neither are set.
const char* ep = "ipc:///tmp/guestfs-inspect.sock";
char *res = malloc(strlen(ep) + 1);
strcpy(res, ep);
return res;
}

122
libguestfs-inspect.c Normal file
View File

@@ -0,0 +1,122 @@
#include <czmq.h>
#include "libguestfs-inspect.h"
char *guestfs_inspect_endpoint() {
const char *guestfs_inspect_endpoint = getenv("GUESTFS_INSPECT_ENDPOINT");
const char *socket_file_name = "/guestfs-inspect.sock";
char *res = NULL;
if (guestfs_inspect_endpoint) {
res = malloc(strlen(guestfs_inspect_endpoint) + 1);
strcpy(res, guestfs_inspect_endpoint);
} else {
const char *xdg_runtime_dir = getenv("XDG_RUNTIME_DIR");
if (xdg_runtime_dir) {
res = malloc(strlen(xdg_runtime_dir) + strlen(socket_file_name) + strlen("ipc://") + 1);
strcpy(res, "ipc://");
strcat(res, xdg_runtime_dir);
strcat(res, socket_file_name);
} else {
const char *tmp_dir = "/tmp";
res = malloc(strlen(tmp_dir) + strlen(socket_file_name) + strlen("ipc://") + 1);
strcpy(res, "ipc://");
strcat(res, tmp_dir);
strcat(res, socket_file_name);
}
}
return res;
}
zmsg_t *guestfs_inspect_command_to_zmsg(const struct guestfs_inpsect_command *command) {
zmsg_t *res = zmsg_new();
zmsg_addstr(res, command->name);
zmsg_addmem(res, &(command->command), sizeof(command->command));
switch (command->command) {
case GUESTFS_COMMAND_LS:
zmsg_addmem(res, &(command->args.ls.paths_length), sizeof(command->args.ls.paths_length));
for (size_t i = 0; i < (command->args.ls.paths_length); i++) {
zmsg_addstr(res, command->args.ls.paths[i]);
}
break;
case GUESTFS_COMMAND_CAT:
zmsg_addmem(res, &(command->args.cat.paths_length), sizeof(command->args.cat.paths_length));
for (size_t i = 0; i < (command->args.cat.paths_length); i++) {
zmsg_addstr(res, command->args.cat.paths[i]);
}
break;
}
return res;
}
struct guestfs_inpsect_command *guestfs_inspect_zmsg_to_command(zmsg_t *external_msg) {
// This way we do not modify the argument we are given.
zmsg_t *msg = zmsg_dup(external_msg);
struct guestfs_inpsect_command *res = malloc(sizeof(struct guestfs_inpsect_command));
if (!(zmsg_size(msg) > 2)) {
free(res);
zmsg_destroy(&msg);
return NULL;
}
res->name = zmsg_popstr(msg);
zframe_t *next = zmsg_pop(msg);
res->command = *(zframe_data(next));
zframe_destroy(&next);
switch (res->command) {
case GUESTFS_COMMAND_LS:
next = zmsg_pop(msg);
res->args.ls.paths_length = *(zframe_data(next));
free(next);
res->args.ls.paths = calloc(res->args.ls.paths_length, sizeof(char *));
for (size_t i = 0; i < res->args.ls.paths_length; i++) {
res->args.ls.paths[i] = zmsg_popstr(msg);
}
break;
case GUESTFS_COMMAND_CAT:
next = zmsg_pop(msg);
res->args.cat.paths_length = *(zframe_data(next));
free(next);
res->args.cat.paths = calloc(res->args.cat.paths_length, sizeof(char *));
for (size_t i = 0; i < res->args.cat.paths_length; i++) {
res->args.cat.paths[i] = zmsg_popstr(msg);
}
break;
default:
printf("Command not found\n");
}
zmsg_destroy(&msg);
return res;
}
void guestfs_inspect_command_destroy(struct guestfs_inpsect_command **c) {
free((*c)->name);
switch ((*c)->command) {
case GUESTFS_COMMAND_LS:
for (size_t i = 0; i < (*c)->args.ls.paths_length; i++) {
free((*c)->args.ls.paths[i]);
}
free((*c)->args.ls.paths);
break;
case GUESTFS_COMMAND_CAT:
for (size_t i = 0; i < (*c)->args.cat.paths_length; i++) {
free((*c)->args.cat.paths[i]);
}
free((*c)->args.cat.paths);
break;
}
free(*c);
*c = NULL;
}

View File

@@ -0,0 +1,36 @@
#ifndef LIBGUESTFS_INSPECT_H
#define LIBGUESTFS_INSPECT_H
#include <czmq.h>
enum guestfs_inspect_command_const {
GUESTFS_COMMAND_LS,
/* GUESTFS_COMMAND_TOUCH, */
/* GUESTFS_COMMAND_MKDIR, */
GUESTFS_COMMAND_CAT
};
struct guestfs_ls_args {
size_t paths_length;
char **paths;
};
struct guestfs_cat_args {
size_t paths_length;
char **paths;
};
struct guestfs_inpsect_command {
char *name;
enum guestfs_inspect_command_const command;
union {
struct guestfs_ls_args ls;
struct guestfs_cat_args cat;
} args;
};
char *guestfs_inspect_endpoint(void);
zmsg_t *guestfs_inspect_command_to_zmsg(const struct guestfs_inpsect_command *command);
struct guestfs_inpsect_command *guestfs_inspect_zmsg_to_command(zmsg_t *msg);
void guestfs_inspect_command_destroy(struct guestfs_inpsect_command **c);
#endif // LIBGUESTFS_INSPECT_H