⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 subdir.c

📁 FUSE文件系统开发工具,将内核层面的文件系统开发过程平移到应用层面上来。
💻 C
字号:
/*  fuse subdir module: offset paths with a base directory  Copyright (C) 2007  Miklos Szeredi <miklos@szeredi.hu>  This program can be distributed under the terms of the GNU LGPLv2.  See the file COPYING.LIB*/#define FUSE_USE_VERSION 26#include <fuse.h>#include <stdio.h>#include <stdlib.h>#include <stddef.h>#include <string.h>#include <errno.h>struct subdir {	char *base;	size_t baselen;	int rellinks;	struct fuse_fs *next;};static struct subdir *subdir_get(void){	return fuse_get_context()->private_data;}static char *subdir_addpath(struct subdir *d, const char *path){	unsigned newlen = d->baselen + strlen(path);	char *newpath = malloc(newlen + 2);	if (newpath) {		if (path[0] == '/')			path++;		strcpy(newpath, d->base);		strcpy(newpath + d->baselen, path);		if (!newpath[0])			strcpy(newpath, ".");	}	return newpath;}static int subdir_getattr(const char *path, struct stat *stbuf){	struct subdir *d = subdir_get();	char *newpath = subdir_addpath(d, path);	int err = -ENOMEM;	if (newpath) {		err = fuse_fs_getattr(d->next, newpath, stbuf);		free(newpath);	}	return err;}static int subdir_fgetattr(const char *path, struct stat *stbuf,			   struct fuse_file_info *fi){	struct subdir *d = subdir_get();	char *newpath = subdir_addpath(d, path);	int err = -ENOMEM;	if (newpath) {		err = fuse_fs_fgetattr(d->next, newpath, stbuf, fi);		free(newpath);	}	return err;}static int subdir_access(const char *path, int mask){	struct subdir *d = subdir_get();	char *newpath = subdir_addpath(d, path);	int err = -ENOMEM;	if (newpath) {		err = fuse_fs_access(d->next, newpath, mask);		free(newpath);	}	return err;}static int count_components(const char *p){	int ctr;	for (; *p == '/'; p++);	for (ctr = 0; *p; ctr++) {		for (; *p && *p != '/'; p++);		for (; *p == '/'; p++);	}	return ctr;}static void strip_common(const char **sp, const char **tp){	const char *s = *sp;	const char *t = *tp;	do {		for (; *s == '/'; s++);		for (; *t == '/'; t++);		*tp = t;		*sp = s;		for (; *s == *t && *s && *s != '/'; s++, t++);	} while ((*s == *t && *s) || (!*s && *t == '/') || (*s == '/' && !*t));}static void transform_symlink(struct subdir *d, const char *path,			      char *buf, size_t size){	const char *l = buf;	size_t llen;	char *s;	int dotdots;	int i;	if (l[0] != '/' || d->base[0] != '/')		return;	strip_common(&l, &path);	if (l - buf < (long) d->baselen)		return;	dotdots = count_components(path);	if (!dotdots)		return;	dotdots--;	llen = strlen(l);	if (dotdots * 3 + llen + 2 > size)		return;	s = buf + dotdots * 3;	if (llen)		memmove(s, l, llen + 1);	else if (!dotdots)		strcpy(s, ".");	else		*s = '\0';	for (s = buf, i = 0; i < dotdots; i++, s += 3)		memcpy(s, "../", 3);}static int subdir_readlink(const char *path, char *buf, size_t size){	struct subdir *d = subdir_get();	char *newpath = subdir_addpath(d, path);	int err = -ENOMEM;	if (newpath) {		err = fuse_fs_readlink(d->next, newpath, buf, size);		if (!err && d->rellinks)			transform_symlink(d, newpath, buf, size);		free(newpath);	}	return err;}static int subdir_opendir(const char *path, struct fuse_file_info *fi){	struct subdir *d = subdir_get();	char *newpath = subdir_addpath(d, path);	int err = -ENOMEM;	if (newpath) {		err = fuse_fs_opendir(d->next, newpath, fi);		free(newpath);	}	return err;}static int subdir_readdir(const char *path, void *buf,			  fuse_fill_dir_t filler, off_t offset,			  struct fuse_file_info *fi){	struct subdir *d = subdir_get();	char *newpath = subdir_addpath(d, path);	int err = -ENOMEM;	if (newpath) {		err = fuse_fs_readdir(d->next, newpath, buf, filler, offset,				      fi);		free(newpath);	}	return err;}static int subdir_releasedir(const char *path, struct fuse_file_info *fi){	struct subdir *d = subdir_get();	char *newpath = subdir_addpath(d, path);	int err = -ENOMEM;	if (newpath) {		err = fuse_fs_releasedir(d->next, newpath, fi);		free(newpath);	}	return err;}static int subdir_mknod(const char *path, mode_t mode, dev_t rdev){	struct subdir *d = subdir_get();	char *newpath = subdir_addpath(d, path);	int err = -ENOMEM;	if (newpath) {		err = fuse_fs_mknod(d->next, newpath, mode, rdev);		free(newpath);	}	return err;}static int subdir_mkdir(const char *path, mode_t mode){	struct subdir *d = subdir_get();	char *newpath = subdir_addpath(d, path);	int err = -ENOMEM;	if (newpath) {		err = fuse_fs_mkdir(d->next, newpath, mode);		free(newpath);	}	return err;}static int subdir_unlink(const char *path){	struct subdir *d = subdir_get();	char *newpath = subdir_addpath(d, path);	int err = -ENOMEM;	if (newpath) {		err = fuse_fs_unlink(d->next, newpath);		free(newpath);	}	return err;}static int subdir_rmdir(const char *path){	struct subdir *d = subdir_get();	char *newpath = subdir_addpath(d, path);	int err = -ENOMEM;	if (newpath) {		err = fuse_fs_rmdir(d->next, newpath);		free(newpath);	}	return err;}static int subdir_symlink(const char *from, const char *path){	struct subdir *d = subdir_get();	char *newpath = subdir_addpath(d, path);	int err = -ENOMEM;	if (newpath) {		err = fuse_fs_symlink(d->next, from, newpath);		free(newpath);	}	return err;}static int subdir_rename(const char *from, const char *to){	struct subdir *d = subdir_get();	char *newfrom = subdir_addpath(d, from);	char *newto = subdir_addpath(d, to);	int err = -ENOMEM;	if (newfrom && newto)		err = fuse_fs_rename(d->next, newfrom, newto);	free(newfrom);	free(newto);	return err;}static int subdir_link(const char *from, const char *to){	struct subdir *d = subdir_get();	char *newfrom = subdir_addpath(d, from);	char *newto = subdir_addpath(d, to);	int err = -ENOMEM;	if (newfrom && newto)		err = fuse_fs_link(d->next, newfrom, newto);	free(newfrom);	free(newto);	return err;}static int subdir_chmod(const char *path, mode_t mode){	struct subdir *d = subdir_get();	char *newpath = subdir_addpath(d, path);	int err = -ENOMEM;	if (newpath) {		err = fuse_fs_chmod(d->next, newpath, mode);		free(newpath);	}	return err;}static int subdir_chown(const char *path, uid_t uid, gid_t gid){	struct subdir *d = subdir_get();	char *newpath = subdir_addpath(d, path);	int err = -ENOMEM;	if (newpath) {		err = fuse_fs_chown(d->next, newpath, uid, gid);		free(newpath);	}	return err;}static int subdir_truncate(const char *path, off_t size){	struct subdir *d = subdir_get();	char *newpath = subdir_addpath(d, path);	int err = -ENOMEM;	if (newpath) {		err = fuse_fs_truncate(d->next, newpath, size);		free(newpath);	}	return err;}static int subdir_ftruncate(const char *path, off_t size,			    struct fuse_file_info *fi){	struct subdir *d = subdir_get();	char *newpath = subdir_addpath(d, path);	int err = -ENOMEM;	if (newpath) {		err = fuse_fs_ftruncate(d->next, newpath, size, fi);		free(newpath);	}	return err;}static int subdir_utimens(const char *path, const struct timespec ts[2]){	struct subdir *d = subdir_get();	char *newpath = subdir_addpath(d, path);	int err = -ENOMEM;	if (newpath) {		err = fuse_fs_utimens(d->next, newpath, ts);		free(newpath);	}	return err;}static int subdir_create(const char *path, mode_t mode,			 struct fuse_file_info *fi){	struct subdir *d = subdir_get();	char *newpath = subdir_addpath(d, path);	int err = -ENOMEM;	if (newpath) {		err = fuse_fs_create(d->next, newpath, mode, fi);		free(newpath);	}	return err;}static int subdir_open(const char *path, struct fuse_file_info *fi){	struct subdir *d = subdir_get();	char *newpath = subdir_addpath(d, path);	int err = -ENOMEM;	if (newpath) {		err = fuse_fs_open(d->next, newpath, fi);		free(newpath);	}	return err;}static int subdir_read(const char *path, char *buf, size_t size, off_t offset,		       struct fuse_file_info *fi){	struct subdir *d = subdir_get();	char *newpath = subdir_addpath(d, path);	int err = -ENOMEM;	if (newpath) {		err = fuse_fs_read(d->next, newpath, buf, size, offset, fi);		free(newpath);	}	return err;}static int subdir_write(const char *path, const char *buf, size_t size,			off_t offset, struct fuse_file_info *fi){	struct subdir *d = subdir_get();	char *newpath = subdir_addpath(d, path);	int err = -ENOMEM;	if (newpath) {		err = fuse_fs_write(d->next, newpath, buf, size, offset, fi);		free(newpath);	}	return err;}static int subdir_statfs(const char *path, struct statvfs *stbuf){	struct subdir *d = subdir_get();	char *newpath = subdir_addpath(d, path);	int err = -ENOMEM;	if (newpath) {		err = fuse_fs_statfs(d->next, newpath, stbuf);		free(newpath);	}	return err;}static int subdir_flush(const char *path, struct fuse_file_info *fi){	struct subdir *d = subdir_get();	char *newpath = subdir_addpath(d, path);	int err = -ENOMEM;	if (newpath) {		err = fuse_fs_flush(d->next, newpath, fi);		free(newpath);	}	return err;}static int subdir_release(const char *path, struct fuse_file_info *fi){	struct subdir *d = subdir_get();	char *newpath = subdir_addpath(d, path);	int err = -ENOMEM;	if (newpath) {		err = fuse_fs_release(d->next, newpath, fi);		free(newpath);	}	return err;}static int subdir_fsync(const char *path, int isdatasync,			struct fuse_file_info *fi){	struct subdir *d = subdir_get();	char *newpath = subdir_addpath(d, path);	int err = -ENOMEM;	if (newpath) {		err = fuse_fs_fsync(d->next, newpath, isdatasync, fi);		free(newpath);	}	return err;}static int subdir_fsyncdir(const char *path, int isdatasync,			   struct fuse_file_info *fi){	struct subdir *d = subdir_get();	char *newpath = subdir_addpath(d, path);	int err = -ENOMEM;	if (newpath) {		err = fuse_fs_fsyncdir(d->next, newpath, isdatasync, fi);		free(newpath);	}	return err;}static int subdir_setxattr(const char *path, const char *name,			   const char *value, size_t size, int flags){	struct subdir *d = subdir_get();	char *newpath = subdir_addpath(d, path);	int err = -ENOMEM;	if (newpath) {		err = fuse_fs_setxattr(d->next, newpath, name, value, size,				       flags);		free(newpath);	}	return err;}static int subdir_getxattr(const char *path, const char *name, char *value,			   size_t size){	struct subdir *d = subdir_get();	char *newpath = subdir_addpath(d, path);	int err = -ENOMEM;	if (newpath) {		err = fuse_fs_getxattr(d->next, newpath, name, value, size);		free(newpath);	}	return err;}static int subdir_listxattr(const char *path, char *list, size_t size){	struct subdir *d = subdir_get();	char *newpath = subdir_addpath(d, path);	int err = -ENOMEM;	if (newpath) {		err = fuse_fs_listxattr(d->next, newpath, list, size);		free(newpath);	}	return err;}static int subdir_removexattr(const char *path, const char *name){	struct subdir *d = subdir_get();	char *newpath = subdir_addpath(d, path);	int err = -ENOMEM;	if (newpath) {		err = fuse_fs_removexattr(d->next, newpath, name);		free(newpath);	}	return err;}static int subdir_lock(const char *path, struct fuse_file_info *fi, int cmd,		       struct flock *lock){	struct subdir *d = subdir_get();	char *newpath = subdir_addpath(d, path);	int err = -ENOMEM;	if (newpath) {		err = fuse_fs_lock(d->next, newpath, fi, cmd, lock);		free(newpath);	}	return err;}static int subdir_bmap(const char *path, size_t blocksize, uint64_t *idx){	struct subdir *d = subdir_get();	char *newpath = subdir_addpath(d, path);	int err = -ENOMEM;	if (newpath) {		err = fuse_fs_bmap(d->next, newpath, blocksize, idx);		free(newpath);	}	return err;}static void *subdir_init(struct fuse_conn_info *conn){	struct subdir *d = subdir_get();	fuse_fs_init(d->next, conn);	return d;}static void subdir_destroy(void *data){	struct subdir *d = data;	fuse_fs_destroy(d->next);	free(d->base);	free(d);}static struct fuse_operations subdir_oper = {	.destroy	= subdir_destroy,	.init		= subdir_init,	.getattr	= subdir_getattr,	.fgetattr	= subdir_fgetattr,	.access		= subdir_access,	.readlink	= subdir_readlink,	.opendir	= subdir_opendir,	.readdir	= subdir_readdir,	.releasedir	= subdir_releasedir,	.mknod		= subdir_mknod,	.mkdir		= subdir_mkdir,	.symlink	= subdir_symlink,	.unlink		= subdir_unlink,	.rmdir		= subdir_rmdir,	.rename		= subdir_rename,	.link		= subdir_link,	.chmod		= subdir_chmod,	.chown		= subdir_chown,	.truncate	= subdir_truncate,	.ftruncate	= subdir_ftruncate,	.utimens	= subdir_utimens,	.create		= subdir_create,	.open		= subdir_open,	.read		= subdir_read,	.write		= subdir_write,	.statfs		= subdir_statfs,	.flush		= subdir_flush,	.release	= subdir_release,	.fsync		= subdir_fsync,	.fsyncdir	= subdir_fsyncdir,	.setxattr	= subdir_setxattr,	.getxattr	= subdir_getxattr,	.listxattr	= subdir_listxattr,	.removexattr	= subdir_removexattr,	.lock		= subdir_lock,	.bmap		= subdir_bmap,};static struct fuse_opt subdir_opts[] = {	FUSE_OPT_KEY("-h", 0),	FUSE_OPT_KEY("--help", 0),	{ "subdir=%s", offsetof(struct subdir, base), 0 },	{ "rellinks", offsetof(struct subdir, rellinks), 1 },	{ "norellinks", offsetof(struct subdir, rellinks), 0 },	FUSE_OPT_END};static void subdir_help(void){	fprintf(stderr,"    -o subdir=DIR	    prepend this directory to all paths (mandatory)\n""    -o [no]rellinks	    transform absolute symlinks to relative\n");}static int subdir_opt_proc(void *data, const char *arg, int key,			   struct fuse_args *outargs){	(void) data; (void) arg; (void) outargs;	if (!key) {		subdir_help();		return -1;	}	return 1;}static struct fuse_fs *subdir_new(struct fuse_args *args,				  struct fuse_fs *next[]){	struct fuse_fs *fs;	struct subdir *d;	d = calloc(1, sizeof(struct subdir));	if (d == NULL) {		fprintf(stderr, "fuse-subdir: memory allocation failed\n");		return NULL;	}	if (fuse_opt_parse(args, d, subdir_opts, subdir_opt_proc) == -1)		goto out_free;	if (!next[0] || next[1]) {		fprintf(stderr, "fuse-subdir: exactly one next filesystem required\n");		goto out_free;	}	if (!d->base) {		fprintf(stderr, "fuse-subdir: missing 'subdir' option\n");		goto out_free;	}	if (d->base[0] && d->base[strlen(d->base)-1] != '/') {		char *tmp = realloc(d->base, strlen(d->base) + 2);		if (!tmp) {			fprintf(stderr, "fuse-subdir: memory allocation failed\n");			goto out_free;		}		d->base = tmp;		strcat(d->base, "/");	}	d->baselen = strlen(d->base);	d->next = next[0];	fs = fuse_fs_new(&subdir_oper, sizeof(subdir_oper), d);	if (!fs)		goto out_free;	return fs;out_free:	free(d->base);	free(d);	return NULL;}FUSE_REGISTER_MODULE(subdir, subdir_new);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -