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

📄 fuse.c

📁 FUSE文件系统开发工具,将内核层面的文件系统开发过程平移到应用层面上来。
💻 C
📖 第 1 页 / 共 5 页
字号:
	do {		pthread_mutex_lock(&f->lock);		node = lookup_node(f, dir, oldname);		if (node == NULL) {			pthread_mutex_unlock(&f->lock);			return NULL;		}		do {			f->hidectr ++;			snprintf(newname, bufsize, ".fuse_hidden%08x%08x",				 (unsigned int) node->nodeid, f->hidectr);			newnode = lookup_node(f, dir, newname);		} while(newnode);		pthread_mutex_unlock(&f->lock);		newpath = get_path_name(f, dir, newname);		if (!newpath)			break;		res = fuse_fs_getattr(f->fs, newpath, &buf);		if (res == -ENOENT)			break;		free(newpath);		newpath = NULL;	} while(res == 0 && --failctr);	return newpath;}static int hide_node(struct fuse *f, const char *oldpath,		     fuse_ino_t dir, const char *oldname){	char newname[64];	char *newpath;	int err = -EBUSY;	newpath = hidden_name(f, dir, oldname, newname, sizeof(newname));	if (newpath) {		err = fuse_fs_rename(f->fs, oldpath, newpath);		if (!err)			err = rename_node(f, dir, oldname, dir, newname, 1);		free(newpath);	}	return err;}static int mtime_eq(const struct stat *stbuf, const struct timespec *ts){	return stbuf->st_mtime == ts->tv_sec &&		ST_MTIM_NSEC(stbuf) == ts->tv_nsec;}#ifndef CLOCK_MONOTONIC#define CLOCK_MONOTONIC CLOCK_REALTIME#endifstatic void curr_time(struct timespec *now){	static clockid_t clockid = CLOCK_MONOTONIC;	int res = clock_gettime(clockid, now);	if (res == -1 && errno == EINVAL) {		clockid = CLOCK_REALTIME;		res = clock_gettime(clockid, now);	}	if (res == -1) {		perror("fuse: clock_gettime");		abort();	}}static void update_stat(struct node *node, const struct stat *stbuf){	if (node->cache_valid && (!mtime_eq(stbuf, &node->mtime) ||				  stbuf->st_size != node->size))		node->cache_valid = 0;	node->mtime.tv_sec = stbuf->st_mtime;	node->mtime.tv_nsec = ST_MTIM_NSEC(stbuf);	node->size = stbuf->st_size;	curr_time(&node->stat_updated);}static int lookup_path(struct fuse *f, fuse_ino_t nodeid,		       const char *name, const char *path,		       struct fuse_entry_param *e, struct fuse_file_info *fi){	int res;	memset(e, 0, sizeof(struct fuse_entry_param));	if (fi)		res = fuse_fs_fgetattr(f->fs, path, &e->attr, fi);	else		res = fuse_fs_getattr(f->fs, path, &e->attr);	if (res == 0) {		struct node *node;		node = find_node(f, nodeid, name);		if (node == NULL)			res = -ENOMEM;		else {			e->ino = node->nodeid;			e->generation = node->generation;			e->entry_timeout = f->conf.entry_timeout;			e->attr_timeout = f->conf.attr_timeout;			if (f->conf.auto_cache) {				pthread_mutex_lock(&f->lock);				update_stat(node, &e->attr);				pthread_mutex_unlock(&f->lock);			}			set_stat(f, e->ino, &e->attr);			if (f->conf.debug)				fprintf(stderr, "   NODEID: %lu\n",					(unsigned long) e->ino);		}	}	return res;}static struct fuse_context_i *fuse_get_context_internal(void){	struct fuse_context_i *c;	c = (struct fuse_context_i *) pthread_getspecific(fuse_context_key);	if (c == NULL) {		c = (struct fuse_context_i *)			malloc(sizeof(struct fuse_context_i));		if (c == NULL) {			/* This is hard to deal with properly, so just			   abort.  If memory is so low that the			   context cannot be allocated, there's not			   much hope for the filesystem anyway */			fprintf(stderr, "fuse: failed to allocate thread specific data\n");			abort();		}		pthread_setspecific(fuse_context_key, c);	}	return c;}static void fuse_freecontext(void *data){	free(data);}static int fuse_create_context_key(void){	int err = 0;	pthread_mutex_lock(&fuse_context_lock);	if (!fuse_context_ref) {		err = pthread_key_create(&fuse_context_key, fuse_freecontext);		if (err) {			fprintf(stderr, "fuse: failed to create thread specific key: %s\n",				strerror(err));			pthread_mutex_unlock(&fuse_context_lock);			return -1;		}	}	fuse_context_ref++;	pthread_mutex_unlock(&fuse_context_lock);	return 0;}static void fuse_delete_context_key(void){	pthread_mutex_lock(&fuse_context_lock);	fuse_context_ref--;	if (!fuse_context_ref) {		free(pthread_getspecific(fuse_context_key));		pthread_key_delete(fuse_context_key);	}	pthread_mutex_unlock(&fuse_context_lock);}static struct fuse *req_fuse_prepare(fuse_req_t req){	struct fuse_context_i *c = fuse_get_context_internal();	const struct fuse_ctx *ctx = fuse_req_ctx(req);	c->req = req;	c->ctx.fuse = req_fuse(req);	c->ctx.uid = ctx->uid;	c->ctx.gid = ctx->gid;	c->ctx.pid = ctx->pid;	return c->ctx.fuse;}static inline void reply_err(fuse_req_t req, int err){	/* fuse_reply_err() uses non-negated errno values */	fuse_reply_err(req, -err);}static void reply_entry(fuse_req_t req, const struct fuse_entry_param *e,			int err){	if (!err) {		struct fuse *f = req_fuse(req);		if (fuse_reply_entry(req, e) == -ENOENT)			forget_node(f, e->ino, 1);	} else		reply_err(req, err);}void fuse_fs_init(struct fuse_fs *fs, struct fuse_conn_info *conn){	fuse_get_context()->private_data = fs->user_data;	if (fs->op.init)		fs->user_data = fs->op.init(conn);}static void fuse_lib_init(void *data, struct fuse_conn_info *conn){	struct fuse *f = (struct fuse *) data;	struct fuse_context_i *c = fuse_get_context_internal();	memset(c, 0, sizeof(*c));	c->ctx.fuse = f;	fuse_fs_init(f->fs, conn);}void fuse_fs_destroy(struct fuse_fs *fs){	fuse_get_context()->private_data = fs->user_data;	if (fs->op.destroy)		fs->op.destroy(fs->user_data);	if (fs->m)		fuse_put_module(fs->m);	free(fs);}static void fuse_lib_destroy(void *data){	struct fuse *f = (struct fuse *) data;	struct fuse_context_i *c = fuse_get_context_internal();	memset(c, 0, sizeof(*c));	c->ctx.fuse = f;	fuse_fs_destroy(f->fs);	f->fs = NULL;}static void fuse_lib_lookup(fuse_req_t req, fuse_ino_t parent,			    const char *name){	struct fuse *f = req_fuse_prepare(req);	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 != NULL) {		struct fuse_intr_data d;		if (f->conf.debug)			fprintf(stderr, "LOOKUP %s\n", path);		fuse_prepare_interrupt(f, req, &d);		err = lookup_path(f, parent, name, path, &e, NULL);		if (err == -ENOENT && f->conf.negative_timeout != 0.0) {			e.ino = 0;			e.entry_timeout = f->conf.negative_timeout;			err = 0;		}		fuse_finish_interrupt(f, req, &d);		free(path);	}	pthread_rwlock_unlock(&f->tree_lock);	reply_entry(req, &e, err);}static void fuse_lib_forget(fuse_req_t req, fuse_ino_t ino,			    unsigned long nlookup){	struct fuse *f = req_fuse(req);	if (f->conf.debug)		fprintf(stderr, "FORGET %llu/%lu\n", (unsigned long long)ino,			nlookup);	forget_node(f, ino, nlookup);	fuse_reply_none(req);}static void fuse_lib_getattr(fuse_req_t req, fuse_ino_t ino,			     struct fuse_file_info *fi){	struct fuse *f = req_fuse_prepare(req);	struct stat buf;	char *path;	int err;	(void) fi;	memset(&buf, 0, sizeof(buf));	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_getattr(f->fs, path, &buf);		fuse_finish_interrupt(f, req, &d);		free(path);	}	pthread_rwlock_unlock(&f->tree_lock);	if (!err) {		if (f->conf.auto_cache) {			pthread_mutex_lock(&f->lock);			update_stat(get_node(f, ino), &buf);			pthread_mutex_unlock(&f->lock);		}		set_stat(f, ino, &buf);		fuse_reply_attr(req, &buf, f->conf.attr_timeout);	} else		reply_err(req, err);}int fuse_fs_chmod(struct fuse_fs *fs, const char *path, mode_t mode){	fuse_get_context()->private_data = fs->user_data;	if (fs->op.chmod)		return fs->op.chmod(path, mode);	else		return -ENOSYS;}static void fuse_lib_setattr(fuse_req_t req, fuse_ino_t ino, struct stat *attr,			     int valid, struct fuse_file_info *fi){	struct fuse *f = req_fuse_prepare(req);	struct stat buf;	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 = 0;		if (!err && (valid & FUSE_SET_ATTR_MODE))			err = fuse_fs_chmod(f->fs, path, attr->st_mode);		if (!err && (valid & (FUSE_SET_ATTR_UID | FUSE_SET_ATTR_GID))) {			uid_t uid = (valid & FUSE_SET_ATTR_UID) ?				attr->st_uid : (uid_t) -1;			gid_t gid = (valid & FUSE_SET_ATTR_GID) ?				attr->st_gid : (gid_t) -1;			err = fuse_fs_chown(f->fs, path, uid, gid);		}		if (!err && (valid & FUSE_SET_ATTR_SIZE)) {			if (fi)				err = fuse_fs_ftruncate(f->fs, path,							attr->st_size, fi);			else				err = fuse_fs_truncate(f->fs, path,						       attr->st_size);		}		if (!err &&		    (valid & (FUSE_SET_ATTR_ATIME | FUSE_SET_ATTR_MTIME)) ==		    (FUSE_SET_ATTR_ATIME | FUSE_SET_ATTR_MTIME)) {			struct timespec tv[2];			tv[0].tv_sec = attr->st_atime;			tv[0].tv_nsec = ST_ATIM_NSEC(attr);			tv[1].tv_sec = attr->st_mtime;			tv[1].tv_nsec = ST_MTIM_NSEC(attr);			err = fuse_fs_utimens(f->fs, path, tv);		}		if (!err)			err = fuse_fs_getattr(f->fs,  path, &buf);		fuse_finish_interrupt(f, req, &d);		free(path);	}	pthread_rwlock_unlock(&f->tree_lock);	if (!err) {		if (f->conf.auto_cache) {			pthread_mutex_lock(&f->lock);			update_stat(get_node(f, ino), &buf);			pthread_mutex_unlock(&f->lock);		}		set_stat(f, ino, &buf);		fuse_reply_attr(req, &buf, f->conf.attr_timeout);	} else		reply_err(req, err);}static void fuse_lib_access(fuse_req_t req, fuse_ino_t ino, int mask){	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, "ACCESS %s 0%o\n", path, mask);		fuse_prepare_interrupt(f, req, &d);		err = fuse_fs_access(f->fs, path, mask);		fuse_finish_interrupt(f, req, &d);		free(path);	}	pthread_rwlock_unlock(&f->tree_lock);	reply_err(req, err);}static void fuse_lib_readlink(fuse_req_t req, fuse_ino_t ino){	struct fuse *f = req_fuse_prepare(req);	char linkname[PATH_MAX + 1];	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_readlink(f->fs, path, linkname, sizeof(linkname));		fuse_finish_interrupt(f, req, &d);		free(path);	}	pthread_rwlock_unlock(&f->tree_lock);	if (!err) {		linkname[PATH_MAX] = '\0';		fuse_reply_readlink(req, linkname);	} else		reply_err(req, err);}static void fuse_lib_mknod(fuse_req_t req, fuse_ino_t parent, const char *name,			   mode_t mode, dev_t rdev){	struct fuse *f = req_fuse_prepare(req);	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) {		struct fuse_intr_data d;		if (f->conf.debug)			fprintf(stderr, "MKNOD %s\n", path);		fuse_prepare_interrupt(f, req, &d);		err = -ENOSYS;		if (S_ISREG(mode)) {			struct fuse_file_info fi;			memset(&fi, 0, sizeof(fi));			fi.flags = O_CREAT | O_EXCL | O_WRONLY;			err = fuse_fs_create(f->fs, path, mode, &fi);			if (!err) {				err = lookup_path(f, parent, name, path, &e,						  &fi);				fuse_fs_release(f->fs, path, &fi);			}		}		if (err == -ENOSYS) {			err = fuse_fs_mknod(f->fs, path, mode, rdev);			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_mkdir(fuse_req_t req, fuse_ino_t parent, const char *name,			   mode_t mode){	struct fuse *f = req_fuse_prepare(req);	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 != NULL) {		struct fuse_intr_data d;		if (f->conf.debug)			fprintf(stderr, "MKDIR %s\n", path);		fuse_prepare_interrupt(f, req, &d);		err = fuse_fs_mkdir(f->fs, path, mode);		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_unlink(fuse_req_t req, fuse_ino_t parent,			    const char *name){	struct fuse *f = req_fuse_prepare(req);	char *path;	int err;	err = -ENOENT;	pthread_rwlock_wrlock(&f->tree_lock);	path = get_path_name(f, parent, name);	if (path != NULL) {		struct fuse_intr_data d;		if (f->conf.debug)			fprintf(stderr, "UNLINK %s\n", path);		fuse_prepare_interrupt(f, req, &d);		if (!f->conf.hard_remove && is_open(f, parent, name))			err = hide_node(f, path, parent, name);		else {			err = fuse_fs_unlink(f->fs, path);			if (!err)				remove_node(f, parent, name);		}		fuse_finish_interrupt(f, req, &d);		free(path);	}	pthread_rwlock_unlock(&f->tree_lock);	reply_err(req, err);}static void fuse_lib_rmdir(fuse_req_t req, fuse_ino_t parent, const char *name){	struct fuse *f = req_fuse_prepare(req);	char *path;	int err;	err = -ENOENT;	pthread_rwlock_wrlock(&f->tree_lock);	path = get_path_name(f, parent, name);	if (path != NULL) {		struct fuse_intr_data d;		if (f->conf.debug)			fprintf(stderr, "RMDIR %s\n", path);		fuse_prepare_interrupt(f, req, &d);		err = fuse_fs_rmdir(f->fs, path);		fuse_finish_interrupt(f, req, &d);		if (!err)			remove_node(f, parent, name);		free(path);	}	pthread_rwlock_unlock(&f->tree_lock);	reply_err(req, err);}static void fuse_lib_symlink(fuse_req_t req, const char *linkname,			     fuse_ino_t parent, const char *name){	struct fuse *f = req_fuse_prepare(req);	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 != NULL) {

⌨️ 快捷键说明

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