290 lines
9.4 KiB
C
290 lines
9.4 KiB
C
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <unistd.h>
|
|
#include <sys/socket.h>
|
|
#include <sys/un.h>
|
|
#include "proto/ipc_proto.h"
|
|
|
|
#define SOCKET_PATH "/tmp/zvfs.sock"
|
|
#define BUF_SIZE 4096
|
|
|
|
int connect_to_server() {
|
|
int fd = socket(AF_UNIX, SOCK_STREAM, 0);
|
|
if (fd < 0) {
|
|
perror("socket");
|
|
return -1;
|
|
}
|
|
|
|
struct sockaddr_un addr;
|
|
memset(&addr, 0, sizeof(addr));
|
|
addr.sun_family = AF_UNIX;
|
|
strncpy(addr.sun_path, SOCKET_PATH, sizeof(addr.sun_path)-1);
|
|
|
|
if (connect(fd, (struct sockaddr*)&addr, sizeof(addr)) < 0) {
|
|
perror("connect");
|
|
close(fd);
|
|
return -1;
|
|
}
|
|
|
|
return fd;
|
|
}
|
|
|
|
// -------------------- 操作函数 --------------------
|
|
|
|
void do_create(int fd) {
|
|
struct zvfs_req req;
|
|
memset(&req, 0, sizeof(req));
|
|
req.opcode = ZVFS_OP_CREATE;
|
|
req.size_hint = 1024; // 1KB
|
|
|
|
uint8_t buf[BUF_SIZE];
|
|
size_t n = zvfs_serialize_req(&req, buf, sizeof(buf));
|
|
if (n == 0) { fprintf(stderr,"serialize failed\n"); return; }
|
|
|
|
if (write(fd, buf, n) != n) { perror("write"); return; }
|
|
|
|
uint8_t resp_buf[BUF_SIZE];
|
|
ssize_t r = read(fd, resp_buf, sizeof(resp_buf));
|
|
if (r <= 0) { perror("read"); return; }
|
|
|
|
struct zvfs_resp resp;
|
|
memset(&resp, 0, sizeof(resp));
|
|
size_t consumed = zvfs_deserialize_resp(resp_buf, r, &resp);
|
|
if (consumed == 0) { fprintf(stderr, "deserialize failed\n"); return; }
|
|
|
|
printf("Received CREATE response: status=%d, blob_id=%lu, handle_id=%lu\n",
|
|
resp.status, resp.blob_id, resp.handle_id);
|
|
|
|
if(resp.data) free(resp.data);
|
|
}
|
|
|
|
void do_open(int fd, uint64_t blob_id) {
|
|
struct zvfs_req req;
|
|
memset(&req,0,sizeof(req));
|
|
req.opcode = ZVFS_OP_OPEN;
|
|
req.blob_id = blob_id;
|
|
|
|
uint8_t buf[BUF_SIZE];
|
|
size_t n = zvfs_serialize_req(&req, buf, sizeof(buf));
|
|
if (n == 0) { fprintf(stderr,"serialize failed\n"); return; }
|
|
|
|
if (write(fd, buf, n) != n) { perror("write"); return; }
|
|
|
|
uint8_t resp_buf[BUF_SIZE];
|
|
ssize_t r = read(fd, resp_buf, sizeof(resp_buf));
|
|
if (r <= 0) { perror("read"); return; }
|
|
|
|
struct zvfs_resp resp;
|
|
memset(&resp,0,sizeof(resp));
|
|
size_t consumed = zvfs_deserialize_resp(resp_buf, r, &resp);
|
|
if (consumed == 0) { fprintf(stderr, "deserialize failed\n"); return; }
|
|
|
|
printf("Received OPEN response: status=%d, handle_id=%lu, size=%lu\n",
|
|
resp.status, resp.handle_id, resp.size);
|
|
|
|
if(resp.data) free(resp.data);
|
|
}
|
|
|
|
void do_read(int fd, uint64_t handle_id, uint64_t offset, uint64_t length) {
|
|
struct zvfs_req req;
|
|
memset(&req,0,sizeof(req));
|
|
req.opcode = ZVFS_OP_READ;
|
|
req.handle_id = handle_id;
|
|
req.offset = offset;
|
|
req.length = length;
|
|
|
|
uint8_t buf[BUF_SIZE];
|
|
size_t n = zvfs_serialize_req(&req, buf, sizeof(buf));
|
|
if (n == 0) { fprintf(stderr,"serialize failed\n"); return; }
|
|
|
|
if (write(fd, buf, n) != n) { perror("write"); return; }
|
|
|
|
uint8_t resp_buf[BUF_SIZE];
|
|
ssize_t r = read(fd, resp_buf, sizeof(resp_buf));
|
|
if (r <= 0) { perror("read"); return; }
|
|
|
|
struct zvfs_resp resp;
|
|
memset(&resp,0,sizeof(resp));
|
|
size_t consumed = zvfs_deserialize_resp(resp_buf, r, &resp);
|
|
if (consumed == 0) { fprintf(stderr, "deserialize failed\n"); return; }
|
|
|
|
printf("Received READ response: status=%d, length=%lu\n",
|
|
resp.status, resp.length);
|
|
|
|
if(resp.data) {
|
|
printf("Data: ");
|
|
for(size_t i=0;i<resp.length;i++)
|
|
printf("%02x ", ((uint8_t*)resp.data)[i]);
|
|
printf("\n");
|
|
free(resp.data);
|
|
}
|
|
}
|
|
|
|
void do_write(int fd, uint64_t handle_id, uint64_t offset,
|
|
const char *data, size_t len, uint32_t write_flags) {
|
|
struct zvfs_req req;
|
|
memset(&req,0,sizeof(req));
|
|
req.opcode = ZVFS_OP_WRITE;
|
|
req.handle_id = handle_id;
|
|
req.offset = offset;
|
|
req.length = len;
|
|
req.write_flags = write_flags;
|
|
req.data = (void*)data;
|
|
|
|
uint8_t buf[BUF_SIZE];
|
|
size_t n = zvfs_serialize_req(&req, buf, sizeof(buf));
|
|
if (n == 0) { fprintf(stderr,"serialize failed\n"); return; }
|
|
|
|
if (write(fd, buf, n) != n) { perror("write"); return; }
|
|
|
|
uint8_t resp_buf[BUF_SIZE];
|
|
ssize_t r = read(fd, resp_buf, sizeof(resp_buf));
|
|
if (r <= 0) { perror("read"); return; }
|
|
|
|
struct zvfs_resp resp;
|
|
memset(&resp,0,sizeof(resp));
|
|
size_t consumed = zvfs_deserialize_resp(resp_buf, r, &resp);
|
|
if (consumed == 0) { fprintf(stderr, "deserialize failed\n"); return; }
|
|
|
|
printf("Received WRITE response: status=%d, bytes_written=%lu\n",
|
|
resp.status, resp.bytes_written);
|
|
|
|
if(resp.data) free(resp.data);
|
|
}
|
|
|
|
void do_close(int fd, uint64_t handle_id) {
|
|
struct zvfs_req req;
|
|
memset(&req,0,sizeof(req));
|
|
req.opcode = ZVFS_OP_CLOSE;
|
|
req.handle_id = handle_id;
|
|
|
|
uint8_t buf[BUF_SIZE];
|
|
size_t n = zvfs_serialize_req(&req, buf, sizeof(buf));
|
|
if (n == 0) { fprintf(stderr,"serialize failed\n"); return; }
|
|
if (write(fd, buf, n) != n) { perror("write"); return; }
|
|
|
|
uint8_t resp_buf[BUF_SIZE];
|
|
ssize_t r = read(fd, resp_buf, sizeof(resp_buf));
|
|
if (r <= 0) { perror("read"); return; }
|
|
|
|
struct zvfs_resp resp;
|
|
memset(&resp,0,sizeof(resp));
|
|
size_t consumed = zvfs_deserialize_resp(resp_buf, r, &resp);
|
|
if (consumed == 0) { fprintf(stderr, "deserialize failed\n"); return; }
|
|
|
|
printf("Received CLOSE response: status=%d\n", resp.status);
|
|
if(resp.data) free(resp.data);
|
|
}
|
|
|
|
void do_delete(int fd, uint64_t blob_id) {
|
|
struct zvfs_req req;
|
|
memset(&req,0,sizeof(req));
|
|
req.opcode = ZVFS_OP_DELETE;
|
|
req.blob_id = blob_id;
|
|
|
|
uint8_t buf[BUF_SIZE];
|
|
size_t n = zvfs_serialize_req(&req, buf, sizeof(buf));
|
|
if (n == 0) { fprintf(stderr,"serialize failed\n"); return; }
|
|
if (write(fd, buf, n) != n) { perror("write"); return; }
|
|
|
|
uint8_t resp_buf[BUF_SIZE];
|
|
ssize_t r = read(fd, resp_buf, sizeof(resp_buf));
|
|
if (r <= 0) { perror("read"); return; }
|
|
|
|
struct zvfs_resp resp;
|
|
memset(&resp,0,sizeof(resp));
|
|
size_t consumed = zvfs_deserialize_resp(resp_buf, r, &resp);
|
|
if (consumed == 0) { fprintf(stderr, "deserialize failed\n"); return; }
|
|
|
|
printf("Received DELETE response: status=%d\n", resp.status);
|
|
if(resp.data) free(resp.data);
|
|
}
|
|
|
|
void do_resize(int fd, uint64_t handle_id, uint64_t new_size) {
|
|
struct zvfs_req req;
|
|
memset(&req,0,sizeof(req));
|
|
req.opcode = ZVFS_OP_RESIZE;
|
|
req.handle_id = handle_id;
|
|
req.size_hint = new_size;
|
|
|
|
uint8_t buf[BUF_SIZE];
|
|
size_t n = zvfs_serialize_req(&req, buf, sizeof(buf));
|
|
if (n == 0) { fprintf(stderr,"serialize failed\n"); return; }
|
|
if (write(fd, buf, n) != n) { perror("write"); return; }
|
|
|
|
uint8_t resp_buf[BUF_SIZE];
|
|
ssize_t r = read(fd, resp_buf, sizeof(resp_buf));
|
|
if (r <= 0) { perror("read"); return; }
|
|
|
|
struct zvfs_resp resp;
|
|
memset(&resp,0,sizeof(resp));
|
|
size_t consumed = zvfs_deserialize_resp(resp_buf, r, &resp);
|
|
if (consumed == 0) { fprintf(stderr, "deserialize failed\n"); return; }
|
|
|
|
printf("Received RESIZE response: status=%d\n", resp.status);
|
|
if(resp.data) free(resp.data);
|
|
}
|
|
|
|
void do_reset(int fd) {
|
|
struct zvfs_req req;
|
|
memset(&req, 0, sizeof(req));
|
|
req.opcode = ZVFS_OP_RESET_BLOBSTORE;
|
|
|
|
uint8_t buf[BUF_SIZE];
|
|
size_t n = zvfs_serialize_req(&req, buf, sizeof(buf));
|
|
if (n == 0) { fprintf(stderr, "serialize failed\n"); return; }
|
|
if (write(fd, buf, n) != n) { perror("write"); return; }
|
|
|
|
uint8_t resp_buf[BUF_SIZE];
|
|
ssize_t r = read(fd, resp_buf, sizeof(resp_buf));
|
|
if (r <= 0) { perror("read"); return; }
|
|
|
|
struct zvfs_resp resp;
|
|
memset(&resp, 0, sizeof(resp));
|
|
size_t consumed = zvfs_deserialize_resp(resp_buf, r, &resp);
|
|
if (consumed == 0) { fprintf(stderr, "deserialize failed\n"); return; }
|
|
|
|
printf("Received RESET_BLOBSTORE response: status=%d\n", resp.status);
|
|
if (resp.data) free(resp.data);
|
|
}
|
|
|
|
// -------------------- main --------------------
|
|
|
|
int main() {
|
|
int fd = connect_to_server();
|
|
if(fd < 0) return 1;
|
|
|
|
printf("Connected to server at %s\n", SOCKET_PATH);
|
|
printf("Commands:\n create\n open <blob>\n read <handle> <offset> <len>\n write <handle> <offset> <data>\n writeg <handle> <offset> <data>\n close <handle>\n delete <blob>\n resize <handle> <size>\n reset\n quit\n");
|
|
|
|
char line[256];
|
|
while (1) {
|
|
printf("> ");
|
|
if(!fgets(line, sizeof(line), stdin)) break;
|
|
|
|
char cmd[32];
|
|
uint64_t a,b,c;
|
|
char data[128];
|
|
|
|
if (sscanf(line, "%31s", cmd) != 1) continue;
|
|
|
|
if (strcmp(cmd,"quit")==0) break;
|
|
else if (strcmp(cmd,"create")==0) do_create(fd);
|
|
else if (strcmp(cmd,"open")==0 && sscanf(line,"%*s %lu",&a)==1) do_open(fd,a);
|
|
else if (strcmp(cmd,"read")==0 && sscanf(line,"%*s %lu %lu %lu",&a,&b,&c)==3) do_read(fd,a,b,c);
|
|
else if (strcmp(cmd,"write")==0 && sscanf(line,"%*s %lu %lu %127s",&a,&b,data)==3)
|
|
do_write(fd, a, b, data, strlen(data), 0);
|
|
else if (strcmp(cmd,"writeg")==0 && sscanf(line,"%*s %lu %lu %127s",&a,&b,data)==3)
|
|
do_write(fd, a, b, data, strlen(data), ZVFS_WRITE_F_AUTO_GROW);
|
|
else if (strcmp(cmd,"close")==0 && sscanf(line,"%*s %lu",&a)==1) do_close(fd,a);
|
|
else if (strcmp(cmd,"delete")==0 && sscanf(line,"%*s %lu",&a)==1) do_delete(fd,a);
|
|
else if (strcmp(cmd,"resize")==0 && sscanf(line,"%*s %lu %lu",&a,&b)==2) do_resize(fd,a,b);
|
|
else if (strcmp(cmd,"reset")==0) do_reset(fd);
|
|
else printf("Unknown or invalid command\n");
|
|
}
|
|
|
|
close(fd);
|
|
return 0;
|
|
}
|