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

📄 fuse.c

📁 FUSE文件系统开发工具,将内核层面的文件系统开发过程平移到应用层面上来。
💻 C
📖 第 1 页 / 共 5 页
字号:
	struct fuse_dh *dh = get_dirhandle(llfi, &fi);	char *path;	pthread_rwlock_rdlock(&f->tree_lock);	path = get_path(f, ino);	fuse_prepare_interrupt(f, req, &d);	fuse_fs_releasedir(f->fs, path ? path : "-", &fi);	fuse_finish_interrupt(f, req, &d);	if (path)		free(path);	pthread_rwlock_unlock(&f->tree_lock);	pthread_mutex_lock(&dh->lock);	pthread_mutex_unlock(&dh->lock);	pthread_mutex_destroy(&dh->lock);	free(dh->contents);	free(dh);	reply_err(req, 0);}static void fuse_lib_fsyncdir(fuse_req_t req, fuse_ino_t ino, int datasync,			      struct fuse_file_info *llfi){	struct fuse *f = req_fuse_prepare(req);	struct fuse_file_info fi;	char *path;	int err;	get_dirhandle(llfi, &fi);	err = -ENOENT;	pthread_rwlock_rdlock(&f->tree_lock);	path = get_path(f, ino);	if (path != NULL) {		struct fuse_intr_data d;		fuse_prepare_interrupt(f, req, &d);		err = fuse_fs_fsyncdir(f->fs, path, datasync, &fi);		fuse_finish_interrupt(f, req, &d);		free(path);	}	pthread_rwlock_unlock(&f->tree_lock);	reply_err(req, err);}static void fuse_lib_statfs(fuse_req_t req, fuse_ino_t ino){	struct fuse *f = req_fuse_prepare(req);	struct statvfs buf;	char *path;	int err;	memset(&buf, 0, sizeof(buf));	pthread_rwlock_rdlock(&f->tree_lock);	if (!ino) {		err = -ENOMEM;		path = strdup("/");	} else {		err = -ENOENT;		path = get_path(f, ino);	}	if (path) {		struct fuse_intr_data d;		fuse_prepare_interrupt(f, req, &d);		err = fuse_fs_statfs(f->fs, path, &buf);		fuse_finish_interrupt(f, req, &d);		free(path);	}	pthread_rwlock_unlock(&f->tree_lock);	if (!err)		fuse_reply_statfs(req, &buf);	else		reply_err(req, err);}static void fuse_lib_setxattr(fuse_req_t req, fuse_ino_t ino, const char *name,			      const char *value, size_t size, int flags){	struct fuse *f = req_fuse_prepare(req);	char *path;	int err;	err = -ENOENT;	pthread_rwlock_rdlock(&f->tree_lock);	path = get_path(f, ino);	if (path != NULL) {		struct fuse_intr_data d;		fuse_prepare_interrupt(f, req, &d);		err = fuse_fs_setxattr(f->fs, path, name, value, size, flags);		fuse_finish_interrupt(f, req, &d);		free(path);	}	pthread_rwlock_unlock(&f->tree_lock);	reply_err(req, err);}static int common_getxattr(struct fuse *f, fuse_req_t req, fuse_ino_t ino,			   const char *name, char *value, size_t size){	int err;	char *path;	err = -ENOENT;	pthread_rwlock_rdlock(&f->tree_lock);	path = get_path(f, ino);	if (path != NULL) {		struct fuse_intr_data d;		fuse_prepare_interrupt(f, req, &d);		err = fuse_fs_getxattr(f->fs, path, name, value, size);		fuse_finish_interrupt(f, req, &d);		free(path);	}	pthread_rwlock_unlock(&f->tree_lock);	return err;}static void fuse_lib_getxattr(fuse_req_t req, fuse_ino_t ino, const char *name,			      size_t size){	struct fuse *f = req_fuse_prepare(req);	int res;	if (size) {		char *value = (char *) malloc(size);		if (value == NULL) {			reply_err(req, -ENOMEM);			return;		}		res = common_getxattr(f, req, ino, name, value, size);		if (res > 0)			fuse_reply_buf(req, value, res);		else			reply_err(req, res);		free(value);	} else {		res = common_getxattr(f, req, ino, name, NULL, 0);		if (res >= 0)			fuse_reply_xattr(req, res);		else			reply_err(req, res);	}}static int common_listxattr(struct fuse *f, fuse_req_t req, fuse_ino_t ino,			    char *list, size_t size){	char *path;	int err;	err = -ENOENT;	pthread_rwlock_rdlock(&f->tree_lock);	path = get_path(f, ino);	if (path != NULL) {		struct fuse_intr_data d;		fuse_prepare_interrupt(f, req, &d);		err = fuse_fs_listxattr(f->fs, path, list, size);		fuse_finish_interrupt(f, req, &d);		free(path);	}	pthread_rwlock_unlock(&f->tree_lock);	return err;}static void fuse_lib_listxattr(fuse_req_t req, fuse_ino_t ino, size_t size){	struct fuse *f = req_fuse_prepare(req);	int res;	if (size) {		char *list = (char *) malloc(size);		if (list == NULL) {			reply_err(req, -ENOMEM);			return;		}		res = common_listxattr(f, req, ino, list, size);		if (res > 0)			fuse_reply_buf(req, list, res);		else			reply_err(req, res);		free(list);	} else {		res = common_listxattr(f, req, ino, NULL, 0);		if (res >= 0)			fuse_reply_xattr(req, res);		else			reply_err(req, res);	}}static void fuse_lib_removexattr(fuse_req_t req, fuse_ino_t ino,				 const char *name){	struct fuse *f = req_fuse_prepare(req);	char *path;	int err;	err = -ENOENT;	pthread_rwlock_rdlock(&f->tree_lock);	path = get_path(f, ino);	if (path != NULL) {		struct fuse_intr_data d;		fuse_prepare_interrupt(f, req, &d);		err = fuse_fs_removexattr(f->fs, path, name);		fuse_finish_interrupt(f, req, &d);		free(path);	}	pthread_rwlock_unlock(&f->tree_lock);	reply_err(req, err);}static struct lock *locks_conflict(struct node *node, const struct lock *lock){	struct lock *l;	for (l = node->locks; l; l = l->next)		if (l->owner != lock->owner &&		    lock->start <= l->end && l->start <= lock->end &&		    (l->type == F_WRLCK || lock->type == F_WRLCK))			break;	return l;}static void delete_lock(struct lock **lockp){	struct lock *l = *lockp;	*lockp = l->next;	free(l);}static void insert_lock(struct lock **pos, struct lock *lock){	lock->next = *pos;	*pos = lock;}static int locks_insert(struct node *node, struct lock *lock){	struct lock **lp;	struct lock *newl1 = NULL;	struct lock *newl2 = NULL;	if (lock->type != F_UNLCK || lock->start != 0 ||	    lock->end != OFFSET_MAX) {		newl1 = malloc(sizeof(struct lock));		newl2 = malloc(sizeof(struct lock));		if (!newl1 || !newl2) {			free(newl1);			free(newl2);			return -ENOLCK;		}	}	for (lp = &node->locks; *lp;) {		struct lock *l = *lp;		if (l->owner != lock->owner)			goto skip;		if (lock->type == l->type) {			if (l->end < lock->start - 1)				goto skip;			if (lock->end < l->start - 1)				break;			if (l->start <= lock->start && lock->end <= l->end)				goto out;			if (l->start < lock->start)				lock->start = l->start;			if (lock->end < l->end)				lock->end = l->end;			goto delete;		} else {			if (l->end < lock->start)				goto skip;			if (lock->end < l->start)				break;			if (lock->start <= l->start && l->end <= lock->end)				goto delete;			if (l->end <= lock->end) {				l->end = lock->start - 1;				goto skip;			}			if (lock->start <= l->start) {				l->start = lock->end + 1;				break;			}			*newl2 = *l;			newl2->start = lock->end + 1;			l->end = lock->start - 1;			insert_lock(&l->next, newl2);			newl2 = NULL;		}	skip:		lp = &l->next;		continue;	delete:		delete_lock(lp);	}	if (lock->type != F_UNLCK) {		*newl1 = *lock;		insert_lock(lp, newl1);		newl1 = NULL;	}out:	free(newl1);	free(newl2);	return 0;}static void flock_to_lock(struct flock *flock, struct lock *lock){	memset(lock, 0, sizeof(struct lock));	lock->type = flock->l_type;	lock->start = flock->l_start;	lock->end =		flock->l_len ? flock->l_start + flock->l_len - 1 : OFFSET_MAX;	lock->pid = flock->l_pid;}static void lock_to_flock(struct lock *lock, struct flock *flock){	flock->l_type = lock->type;	flock->l_start = lock->start;	flock->l_len =		(lock->end == OFFSET_MAX) ? 0 : lock->end - lock->start + 1;	flock->l_pid = lock->pid;}static int fuse_flush_common(struct fuse *f, fuse_req_t req, fuse_ino_t ino,			     const char *path, struct fuse_file_info *fi){	struct fuse_intr_data d;	struct flock lock;	struct lock l;	int err;	int errlock;	fuse_prepare_interrupt(f, req, &d);	memset(&lock, 0, sizeof(lock));	lock.l_type = F_UNLCK;	lock.l_whence = SEEK_SET;	err = fuse_fs_flush(f->fs, path, fi);	errlock = fuse_fs_lock(f->fs, path, fi, F_SETLK, &lock);	fuse_finish_interrupt(f, req, &d);	if (errlock != -ENOSYS) {		flock_to_lock(&lock, &l);		l.owner = fi->lock_owner;		pthread_mutex_lock(&f->lock);		locks_insert(get_node(f, ino), &l);		pthread_mutex_unlock(&f->lock);		/* if op.lock() is defined FLUSH is needed regardless		   of op.flush() */		if (err == -ENOSYS)			err = 0;	}	return err;}static void fuse_lib_release(fuse_req_t req, fuse_ino_t ino,			     struct fuse_file_info *fi){	struct fuse *f = req_fuse_prepare(req);	struct fuse_intr_data d;	char *path;	int err = 0;	pthread_rwlock_rdlock(&f->tree_lock);	path = get_path(f, ino);	if (f->conf.debug)		fprintf(stderr, "RELEASE%s[%llu] flags: 0x%x\n",			fi->flush ? "+FLUSH" : "",			(unsigned long long) fi->fh, fi->flags);	if (fi->flush) {		err = fuse_flush_common(f, req, ino, path, fi);		if (err == -ENOSYS)			err = 0;	}	fuse_prepare_interrupt(f, req, &d);	fuse_do_release(f, ino, path, fi);	fuse_finish_interrupt(f, req, &d);	free(path);	pthread_rwlock_unlock(&f->tree_lock);	reply_err(req, err);}static void fuse_lib_flush(fuse_req_t req, fuse_ino_t ino,			   struct fuse_file_info *fi){	struct fuse *f = req_fuse_prepare(req);	char *path;	int err;	pthread_rwlock_rdlock(&f->tree_lock);	path = get_path(f, ino);	if (path && f->conf.debug)		fprintf(stderr, "FLUSH[%llu]\n", (unsigned long long) fi->fh);	err = fuse_flush_common(f, req, ino, path, fi);	free(path);	pthread_rwlock_unlock(&f->tree_lock);	reply_err(req, err);}static int fuse_lock_common(fuse_req_t req, fuse_ino_t ino,			    struct fuse_file_info *fi, struct flock *lock,			    int cmd){	struct fuse *f = req_fuse_prepare(req);	char *path;	int err;	err = -ENOENT;	pthread_rwlock_rdlock(&f->tree_lock);	path = get_path(f, ino);	if (path != NULL) {		struct fuse_intr_data d;		fuse_prepare_interrupt(f, req, &d);		err = fuse_fs_lock(f->fs, path, fi, cmd, lock);		fuse_finish_interrupt(f, req, &d);		free(path);	}	pthread_rwlock_unlock(&f->tree_lock);	return err;}static void fuse_lib_getlk(fuse_req_t req, fuse_ino_t ino,			   struct fuse_file_info *fi, struct flock *lock){	int err;	struct lock l;	struct lock *conflict;	struct fuse *f = req_fuse(req);	flock_to_lock(lock, &l);	l.owner = fi->lock_owner;	pthread_mutex_lock(&f->lock);	conflict = locks_conflict(get_node(f, ino), &l);	if (conflict)		lock_to_flock(conflict, lock);	pthread_mutex_unlock(&f->lock);	if (!conflict)		err = fuse_lock_common(req, ino, fi, lock, F_GETLK);	else		err = 0;	if (!err)		fuse_reply_lock(req, lock);	else		reply_err(req, err);}static void fuse_lib_setlk(fuse_req_t req, fuse_ino_t ino,			   struct fuse_file_info *fi, struct flock *lock,			   int sleep){	int err = fuse_lock_common(req, ino, fi, lock,				   sleep ? F_SETLKW : F_SETLK);	if (!err) {		struct fuse *f = req_fuse(req);		struct lock l;		flock_to_lock(lock, &l);		l.owner = fi->lock_owner;		pthread_mutex_lock(&f->lock);		locks_insert(get_node(f, ino), &l);		pthread_mutex_unlock(&f->lock);	}	reply_err(req, err);}static void fuse_lib_bmap(fuse_req_t req, fuse_ino_t ino, size_t blocksize,			  uint64_t idx){	struct fuse *f = req_fuse_prepare(req);	struct fuse_intr_data d;	char *path;	int err;	err = -ENOENT;	pthread_rwlock_rdlock(&f->tree_lock);	path = get_path(f, ino);	if (path != NULL) {		fuse_prepare_interrupt(f, req, &d);		err = fuse_fs_bmap(f->fs, path, blocksize, &idx);		fuse_finish_interrupt(f, req, &d);		free(path);	}	pthread_rwlock_unlock(&f->tree_lock);	if (!err)		fuse_reply_bmap(req, idx);	else		reply_err(req, err);}static struct fuse_lowlevel_ops fuse_path_ops = {	.init = fuse_lib_init,	.destroy = fuse_lib_destroy,	.lookup = fuse_lib_lookup,	.forget = fuse_lib_forget,	.getattr = fuse_lib_getattr,	.setattr = fuse_lib_setattr,	.access = fuse_lib_access,	.readlink = fuse_lib_readlink,	.mknod = fuse_lib_mknod,	.mkdir = fuse_lib_mkdir,	.unlink = fuse_lib_unlink,	.rmdir = fuse_lib_rmdir,	.symlink = fuse_lib_symlink,	.rename = fuse_lib_rename,	.link = fuse_lib_link,	.create = fuse_lib_create,	.open = fuse_lib_open,	.read = fuse_lib_read,	.write = fuse_lib_write,	.flush = fuse_lib_flush,	.release = fuse_lib_release,	.fsync = fuse_lib_fsync,	.opendir = fuse_lib_opendir,	.readdir = fuse_lib_readdir,	.releasedir = fuse_lib_releasedir,	.fsyncdir = fuse_lib_fsyncdir,	.statfs = fuse_lib_statfs,	.setxattr = fuse_lib_setxattr,	.getxattr = fuse_lib_getxattr,	.listxattr = fuse_lib_listxattr,	.removexattr = fuse_lib_removexattr,	.getlk = fuse_lib_getlk,	.setlk = fuse_lib_setlk,	.bmap = fuse_lib_bmap,};static void free_cmd(struct fuse_cmd *cmd){	free(cmd->buf);	free(cmd);}void fuse_process_cmd(struct fuse *f, struct fuse_cmd *cmd){	fuse_session_process(f->se, cmd->buf, cmd->buflen, cmd->ch);	free_cmd(cmd);}int fuse_exited(struct fuse *f){	return fuse_session_exited(f->se);}struct fuse_session *fuse_get_session(struct fuse *f){	return f->se;}static struct fuse_cmd *fuse_alloc_cmd(size_t bufsize){	struct fuse_cmd *cmd = (struct fuse_cmd *) malloc(sizeof(*cmd));	if (cmd == NULL) {		fprintf(stderr, "fuse: failed to

⌨️ 快捷键说明

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