📄 fuse.c
字号:
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 + -