xrsh-buildroot/buildroot-v86/package/fusescript/fusescript.c

219 lines
6.0 KiB
C

#define FUSE_USE_VERSION 35
#include <fuse3/fuse.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
static const char *script_path;
static int call_script(const char *action, const char *path, char **output) {
char command[4096];
FILE *fp;
snprintf(command, sizeof(command), "%s %s '%s'", script_path, action, path);
fp = popen(command, "r");
if (!fp) {
return -errno;
}
size_t size = 0;
*output = NULL;
char line[1024];
while (fgets(line, sizeof(line), fp)) {
size_t len = strlen(line);
*output = realloc(*output, size + len + 1);
memcpy(*output + size, line, len);
size += len;
}
if (*output) {
(*output)[size] = '\0';
}
return pclose(fp);
}
static int fusescript_getattr(const char *path, struct stat *stbuf, struct fuse_file_info *fi) {
(void) fi;
memset(stbuf, 0, sizeof(struct stat));
if( path == NULL ) return -EINVAL;
if (strcmp(path, "/") == 0) {
// Root directory
stbuf->st_mode = S_IFDIR | 0755; // Directory with permissions 0755
stbuf->st_nlink = 2; // Standard for directories
return 0;
}
// Call the script for other paths
char *output = NULL;
int ret = call_script("getattr", path, &output);
if (ret != 0) {
free(output);
return -EIO;
}
// Parse the script output
int mode, nlink, uid, gid, size, blocks;
if( output == NULL ) return -EIO;
if (sscanf(output, "%d %d %d %d %d %d", &mode, &nlink, &uid, &gid, &size, &blocks) != 6) {
free(output);
return -EIO; // Error parsing the output
}
// Populate the stat structure
stbuf->st_mode = mode; // File mode (e.g., regular file, directory)
stbuf->st_nlink = nlink; // Number of hard links
stbuf->st_uid = uid; // User ID (owner)
stbuf->st_gid = gid; // Group ID
stbuf->st_size = size; // File size in bytes
stbuf->st_blocks = blocks; // Number of 512-byte blocks allocated
stbuf->st_blksize = 512; // Block size (optional)
// Set default values for atime, mtime, ctime (if not handled by your script)
stbuf->st_atime = time(NULL); // Last access time
stbuf->st_mtime = time(NULL); // Last modification time
stbuf->st_ctime = time(NULL); // Last status change time
free(output);
return 0;
}
static int fusescript_access(const char *path, int mask) {
// Call the script for permission checks (optional)
char *output = NULL;
int ret = call_script("access", path, &output);
if (ret != 0) {
free(output);
return 0; //-EIO;
}
free(output);
return 0; // Allow all accesses for simplicity
}
static int fusescript_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
off_t offset, struct fuse_file_info *fi, enum fuse_readdir_flags flags) {
(void) offset;
(void) fi;
(void) flags;
if (strcmp(path, "/") != 0) {
// If the path is not the root, return an error
return -ENOENT;
}
// Add default entries for directories
filler(buf, ".", NULL, 0, 0); // Current directory
filler(buf, "..", NULL, 0, 0); // Parent directory
// Call the script for additional entries
char *output = NULL;
int ret = call_script("readdir", path, &output);
if (ret != 0) {
free(output);
return -EIO;
}
// Parse script output, assuming it provides one entry per line
char *line = strtok(output, "\n");
while (line) {
filler(buf, line, NULL, 0, 0);
line = strtok(NULL, "\n");
}
free(output);
return 0;
}
static int fusescript_open(const char *path, struct fuse_file_info *fi) {
(void) fi;
char *output = NULL;
int ret = call_script("open", path, &output);
free(output);
return ret == 0 ? 0 : -EIO;
}
static int fusescript_read(const char *path, char *buf, size_t size, off_t offset, struct fuse_file_info *fi) {
(void) fi;
char command[4096];
snprintf(command, sizeof(command), "%s read '%s' %zu %jd", script_path, path, size, (intmax_t)offset);
FILE *fp = popen(command, "r");
if (!fp) {
return -errno;
}
size_t bytes_read = fread(buf, 1, size, fp);
int ret = pclose(fp);
return ret == 0 ? bytes_read : -EIO;
}
static int fusescript_write(const char *path, const char *buf, size_t size, off_t offset, struct fuse_file_info *fi) {
(void) fi;
char command[4096];
snprintf(command, sizeof(command), "echo -n '%.*s' | %s write '%s' %zu %jd", (int)size, buf, script_path, path, size, (intmax_t)offset);
int ret = system(command);
return ret == 0 ? size : -EIO;
}
static int fusescript_mkdir(const char *path, mode_t mode) {
char command[4096];
snprintf(command, sizeof(command), "%s mkdir '%s' %o", script_path, path, mode);
int ret = system(command);
return ret == 0 ? 0 : -EIO;
}
static int fusescript_unlink(const char *path) {
char command[4096];
snprintf(command, sizeof(command), "%s unlink '%s'", script_path, path);
int ret = system(command);
return ret == 0 ? 0 : -EIO;
}
static int fusescript_rmdir(const char *path) {
char command[4096];
snprintf(command, sizeof(command), "%s rmdir '%s'", script_path, path);
int ret = system(command);
return ret == 0 ? 0 : -EIO;
}
static const struct fuse_operations fusescript_ops = {
.getattr = fusescript_getattr,
.readdir = fusescript_readdir,
.open = fusescript_open,
.access = fusescript_access,
.read = fusescript_read,
.write = fusescript_write,
.mkdir = fusescript_mkdir,
.unlink = fusescript_unlink,
.rmdir = fusescript_rmdir,
};
int main(int argc, char *argv[]) {
if (argc < 3) {
fprintf(stderr, "Usage: %s <script> <mountpoint>\n", argv[0]);
return 1;
}
script_path = realpath(argv[1], NULL);
if (!script_path) {
perror("realpath");
return 1;
}
argv[1] = argv[2];
return fuse_main(argc - 1, argv + 1, &fusescript_ops, NULL);
}