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

📄 fuse.c

📁 FUSE文件系统开发工具,将内核层面的文件系统开发过程平移到应用层面上来。
💻 C
📖 第 1 页 / 共 5 页
字号:
		struct fuse_intr_data d;		if (f->conf.debug)			fprintf(stderr, "SYMLINK %s\n", path);		fuse_prepare_interrupt(f, req, &d);		err = fuse_fs_symlink(f->fs, linkname, path);		if (!err)			err = lookup_path(f, parent, name, path, &e, NULL);		fuse_finish_interrupt(f, req, &d);		free(path);	}	pthread_rwlock_unlock(&f->tree_lock);	reply_entry(req, &e, err);}static void fuse_lib_rename(fuse_req_t req, fuse_ino_t olddir,			    const char *oldname, fuse_ino_t newdir,			    const char *newname){	struct fuse *f = req_fuse_prepare(req);	char *oldpath;	char *newpath;	int err;	err = -ENOENT;	pthread_rwlock_wrlock(&f->tree_lock);	oldpath = get_path_name(f, olddir, oldname);	if (oldpath != NULL) {		newpath = get_path_name(f, newdir, newname);		if (newpath != NULL) {			struct fuse_intr_data d;			if (f->conf.debug)				fprintf(stderr, "RENAME %s -> %s\n", oldpath,					newpath);			err = 0;			fuse_prepare_interrupt(f, req, &d);			if (!f->conf.hard_remove && is_open(f, newdir, newname))				err = hide_node(f, newpath, newdir, newname);			if (!err) {				err = fuse_fs_rename(f->fs, oldpath, newpath);				if (!err)					err = rename_node(f, olddir, oldname,							  newdir, newname, 0);			}			fuse_finish_interrupt(f, req, &d);			free(newpath);		}		free(oldpath);	}	pthread_rwlock_unlock(&f->tree_lock);	reply_err(req, err);}static void fuse_lib_link(fuse_req_t req, fuse_ino_t ino, fuse_ino_t newparent,			  const char *newname){	struct fuse *f = req_fuse_prepare(req);	struct fuse_entry_param e;	char *oldpath;	char *newpath;	int err;	err = -ENOENT;	pthread_rwlock_rdlock(&f->tree_lock);	oldpath = get_path(f, ino);	if (oldpath != NULL) {		newpath =  get_path_name(f, newparent, newname);		if (newpath != NULL) {			struct fuse_intr_data d;			if (f->conf.debug)				fprintf(stderr, "LINK %s\n", newpath);			fuse_prepare_interrupt(f, req, &d);			err = fuse_fs_link(f->fs, oldpath, newpath);			if (!err)				err = lookup_path(f, newparent, newname,						  newpath, &e, NULL);			fuse_finish_interrupt(f, req, &d);			free(newpath);		}		free(oldpath);	}	pthread_rwlock_unlock(&f->tree_lock);	reply_entry(req, &e, err);}static void fuse_do_release(struct fuse *f, fuse_ino_t ino, const char *path,			    struct fuse_file_info *fi){	struct node *node;	int unlink_hidden = 0;	fuse_fs_release(f->fs, path ? path : "-", fi);	pthread_mutex_lock(&f->lock);	node = get_node(f, ino);	assert(node->open_count > 0);	--node->open_count;	if (node->is_hidden && !node->open_count) {		unlink_hidden = 1;		node->is_hidden = 0;	}	pthread_mutex_unlock(&f->lock);	if(unlink_hidden && path)		fuse_fs_unlink(f->fs, path);}static void fuse_lib_create(fuse_req_t req, fuse_ino_t parent,			    const char *name, mode_t mode,			    struct fuse_file_info *fi){	struct fuse *f = req_fuse_prepare(req);	struct fuse_intr_data d;	struct fuse_entry_param e;	char *path;	int err;	err = -ENOENT;	pthread_rwlock_rdlock(&f->tree_lock);	path = get_path_name(f, parent, name);	if (path) {		fuse_prepare_interrupt(f, req, &d);		err = fuse_fs_create(f->fs, path, mode, fi);		if (!err) {			err = lookup_path(f, parent, name, path, &e, fi);			if (err)				fuse_fs_release(f->fs, path, fi);			else if (!S_ISREG(e.attr.st_mode)) {				err = -EIO;				fuse_fs_release(f->fs, path, fi);				forget_node(f, e.ino, 1);			} else {				if (f->conf.direct_io)					fi->direct_io = 1;				if (f->conf.kernel_cache)					fi->keep_cache = 1;			}		}		fuse_finish_interrupt(f, req, &d);	}	if (!err) {		pthread_mutex_lock(&f->lock);		get_node(f, e.ino)->open_count++;		pthread_mutex_unlock(&f->lock);		if (fuse_reply_create(req, &e, fi) == -ENOENT) {			/* The open syscall was interrupted, so it			   must be cancelled */			fuse_prepare_interrupt(f, req, &d);			fuse_do_release(f, e.ino, path, fi);			fuse_finish_interrupt(f, req, &d);			forget_node(f, e.ino, 1);		} else if (f->conf.debug) {			fprintf(stderr, "  CREATE[%llu] flags: 0x%x %s\n",				(unsigned long long) fi->fh, fi->flags, path);		}	} else		reply_err(req, err);	if (path)		free(path);	pthread_rwlock_unlock(&f->tree_lock);}static double diff_timespec(const struct timespec *t1,			    const struct timespec *t2){	return (t1->tv_sec - t2->tv_sec) +		((double) t1->tv_nsec - (double) t2->tv_nsec) / 1000000000.0;}static void open_auto_cache(struct fuse *f, fuse_ino_t ino, const char *path,			    struct fuse_file_info *fi){	struct node *node;	pthread_mutex_lock(&f->lock);	node = get_node(f, ino);	if (node->cache_valid) {		struct timespec now;		curr_time(&now);		if (diff_timespec(&now, &node->stat_updated) >		    f->conf.ac_attr_timeout) {			struct stat stbuf;			int err;			pthread_mutex_unlock(&f->lock);			err = fuse_fs_fgetattr(f->fs, path, &stbuf, fi);			pthread_mutex_lock(&f->lock);			if (!err)				update_stat(node, &stbuf);			else				node->cache_valid = 0;		}	}	if (node->cache_valid)		fi->keep_cache = 1;	node->cache_valid = 1;	pthread_mutex_unlock(&f->lock);}static void fuse_lib_open(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 = NULL;	int err = 0;	err = -ENOENT;	pthread_rwlock_rdlock(&f->tree_lock);	path = get_path(f, ino);	if (path) {		fuse_prepare_interrupt(f, req, &d);		err = fuse_fs_open(f->fs, path, fi);		if (!err) {			if (f->conf.direct_io)				fi->direct_io = 1;			if (f->conf.kernel_cache)				fi->keep_cache = 1;			if (f->conf.auto_cache)				open_auto_cache(f, ino, path, fi);		}		fuse_finish_interrupt(f, req, &d);	}	if (!err) {		pthread_mutex_lock(&f->lock);		get_node(f, ino)->open_count++;		pthread_mutex_unlock(&f->lock);		if (fuse_reply_open(req, fi) == -ENOENT) {			/* The open syscall was interrupted, so it			   must be cancelled */			fuse_prepare_interrupt(f, req, &d);			fuse_do_release(f, ino, path, fi);			fuse_finish_interrupt(f, req, &d);		} else if (f->conf.debug) {			fprintf(stderr, "OPEN[%llu] flags: 0x%x %s\n",				(unsigned long long) fi->fh, fi->flags, path);		}	} else		reply_err(req, err);	if (path)		free(path);	pthread_rwlock_unlock(&f->tree_lock);}static void fuse_lib_read(fuse_req_t req, fuse_ino_t ino, size_t size,			  off_t off, struct fuse_file_info *fi){	struct fuse *f = req_fuse_prepare(req);	char *path;	char *buf;	int res;	buf = (char *) malloc(size);	if (buf == NULL) {		reply_err(req, -ENOMEM);		return;	}	res = -ENOENT;	pthread_rwlock_rdlock(&f->tree_lock);	path = get_path(f, ino);	if (path != NULL) {		struct fuse_intr_data d;		if (f->conf.debug)			fprintf(stderr, "READ[%llu] %lu bytes from %llu\n",				(unsigned long long) fi->fh,				(unsigned long) size, (unsigned long long) off);		fuse_prepare_interrupt(f, req, &d);		res = fuse_fs_read(f->fs, path, buf, size, off, fi);		fuse_finish_interrupt(f, req, &d);		free(path);	}	pthread_rwlock_unlock(&f->tree_lock);	if (res >= 0) {		if (f->conf.debug)			fprintf(stderr, "   READ[%llu] %u bytes\n",				(unsigned long long)fi->fh, res);		if ((size_t) res > size)			fprintf(stderr, "fuse: read too many bytes");		fuse_reply_buf(req, buf, res);	} else		reply_err(req, res);	free(buf);}static void fuse_lib_write(fuse_req_t req, fuse_ino_t ino, const char *buf,			   size_t size, off_t off, struct fuse_file_info *fi){	struct fuse *f = req_fuse_prepare(req);	char *path;	int res;	res = -ENOENT;	pthread_rwlock_rdlock(&f->tree_lock);	path = get_path(f, ino);	if (path != NULL) {		struct fuse_intr_data d;		if (f->conf.debug)			fprintf(stderr, "WRITE%s[%llu] %lu bytes to %llu\n",				fi->writepage ? "PAGE" : "",				(unsigned long long) fi->fh,				(unsigned long) size, (unsigned long long) off);		fuse_prepare_interrupt(f, req, &d);		res = fuse_fs_write(f->fs, path, buf, size, off, fi);		fuse_finish_interrupt(f, req, &d);		free(path);	}	pthread_rwlock_unlock(&f->tree_lock);	if (res >= 0) {		if (f->conf.debug)			fprintf(stderr, "   WRITE%s[%llu] %u bytes\n",				fi->writepage ? "PAGE" : "",				(unsigned long long) fi->fh, res);		if ((size_t) res > size)			fprintf(stderr, "fuse: wrote too many bytes");		fuse_reply_write(req, res);	} else		reply_err(req, res);}static void fuse_lib_fsync(fuse_req_t req, fuse_ino_t ino, int datasync,			   struct fuse_file_info *fi){	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;		if (f->conf.debug)			fprintf(stderr, "FSYNC[%llu]\n",				(unsigned long long) fi->fh);		fuse_prepare_interrupt(f, req, &d);		err = fuse_fs_fsync(f->fs, path, datasync, fi);		fuse_finish_interrupt(f, req, &d);		free(path);	}	pthread_rwlock_unlock(&f->tree_lock);	reply_err(req, err);}static struct fuse_dh *get_dirhandle(const struct fuse_file_info *llfi,				     struct fuse_file_info *fi){	struct fuse_dh *dh = (struct fuse_dh *) (uintptr_t) llfi->fh;	memset(fi, 0, sizeof(struct fuse_file_info));	fi->fh = dh->fh;	fi->fh_old = dh->fh;	return dh;}static void fuse_lib_opendir(fuse_req_t req, fuse_ino_t ino,			     struct fuse_file_info *llfi){	struct fuse *f = req_fuse_prepare(req);	struct fuse_intr_data d;	struct fuse_dh *dh;	struct fuse_file_info fi;	char *path;	int err;	dh = (struct fuse_dh *) malloc(sizeof(struct fuse_dh));	if (dh == NULL) {		reply_err(req, -ENOMEM);		return;	}	memset(dh, 0, sizeof(struct fuse_dh));	dh->fuse = f;	dh->contents = NULL;	dh->len = 0;	dh->filled = 0;	dh->nodeid = ino;	fuse_mutex_init(&dh->lock);	llfi->fh = (uintptr_t) dh;	memset(&fi, 0, sizeof(fi));	fi.flags = llfi->flags;	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_opendir(f->fs, path, &fi);		fuse_finish_interrupt(f, req, &d);		dh->fh = fi.fh;	}	if (!err) {		if (fuse_reply_open(req, llfi) == -ENOENT) {			/* The opendir syscall was interrupted, so it			   must be cancelled */			fuse_prepare_interrupt(f, req, &d);			fuse_fs_releasedir(f->fs, path, &fi);			fuse_finish_interrupt(f, req, &d);			pthread_mutex_destroy(&dh->lock);			free(dh);		}	} else {		reply_err(req, err);		pthread_mutex_destroy(&dh->lock);		free(dh);	}	free(path);	pthread_rwlock_unlock(&f->tree_lock);}static int extend_contents(struct fuse_dh *dh, unsigned minsize){	if (minsize > dh->size) {		char *newptr;		unsigned newsize = dh->size;		if (!newsize)			newsize = 1024;		while (newsize < minsize)			newsize *= 2;		newptr = (char *) realloc(dh->contents, newsize);		if (!newptr) {			dh->error = -ENOMEM;			return -1;		}		dh->contents = newptr;		dh->size = newsize;	}	return 0;}static int fill_dir(void *dh_, const char *name, const struct stat *statp,		    off_t off){	struct fuse_dh *dh = (struct fuse_dh *) dh_;	struct stat stbuf;	size_t newlen;	if (statp)		stbuf = *statp;	else {		memset(&stbuf, 0, sizeof(stbuf));		stbuf.st_ino = FUSE_UNKNOWN_INO;	}	if (!dh->fuse->conf.use_ino) {		stbuf.st_ino = FUSE_UNKNOWN_INO;		if (dh->fuse->conf.readdir_ino) {			struct node *node;			pthread_mutex_lock(&dh->fuse->lock);			node = lookup_node(dh->fuse, dh->nodeid, name);			if (node)				stbuf.st_ino  = (ino_t) node->nodeid;			pthread_mutex_unlock(&dh->fuse->lock);		}	}	if (off) {		if (extend_contents(dh, dh->needlen) == -1)			return 1;		dh->filled = 0;		newlen = dh->len +			fuse_add_direntry(dh->req, dh->contents + dh->len,					  dh->needlen - dh->len, name,					  &stbuf, off);		if (newlen > dh->needlen)			return 1;	} else {		newlen = dh->len +			fuse_add_direntry(dh->req, NULL, 0, name, NULL, 0);		if (extend_contents(dh, newlen) == -1)			return 1;		fuse_add_direntry(dh->req, dh->contents + dh->len,				  dh->size - dh->len, name, &stbuf, newlen);	}	dh->len = newlen;	return 0;}static int readdir_fill(struct fuse *f, fuse_req_t req, fuse_ino_t ino,			size_t size, off_t off, struct fuse_dh *dh,			struct fuse_file_info *fi){	int err = -ENOENT;	char *path;	pthread_rwlock_rdlock(&f->tree_lock);	path = get_path(f, ino);	if (path != NULL) {		struct fuse_intr_data d;		dh->len = 0;		dh->error = 0;		dh->needlen = size;		dh->filled = 1;		dh->req = req;		fuse_prepare_interrupt(f, req, &d);		err = fuse_fs_readdir(f->fs, path, dh, fill_dir, off, fi);		fuse_finish_interrupt(f, req, &d);		dh->req = NULL;		if (!err)			err = dh->error;		if (err)			dh->filled = 0;		free(path);	}	pthread_rwlock_unlock(&f->tree_lock);	return err;}static void fuse_lib_readdir(fuse_req_t req, fuse_ino_t ino, size_t size,			     off_t off, struct fuse_file_info *llfi){	struct fuse *f = req_fuse_prepare(req);	struct fuse_file_info fi;	struct fuse_dh *dh = get_dirhandle(llfi, &fi);	pthread_mutex_lock(&dh->lock);	/* According to SUS, directory contents need to be refreshed on	   rewinddir() */	if (!off)		dh->filled = 0;	if (!dh->filled) {		int err = readdir_fill(f, req, ino, size, off, dh, &fi);		if (err) {			reply_err(req, err);			goto out;		}	}	if (dh->filled) {		if (off < dh->len) {			if (off + size > dh->len)				size = dh->len - off;		} else			size = 0;	} else {		size = dh->len;		off = 0;	}	fuse_reply_buf(req, dh->contents + off, size);out:	pthread_mutex_unlock(&dh->lock);}static void fuse_lib_releasedir(fuse_req_t req, fuse_ino_t ino,				struct fuse_file_info *llfi){	struct fuse *f = req_fuse_prepare(req);	struct fuse_intr_data d;	struct fuse_file_info fi;

⌨️ 快捷键说明

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