#define FUSE_USE_VERSION 35 #include #include #include #include #include #include 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