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

📄 fuse.c

📁 Linux下fuse用户文件系统的的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
}static void fuse_do_finish_interrupt(struct fuse *f, fuse_req_t req,                                     struct fuse_intr_data *d){    pthread_mutex_lock(&f->lock);    d->finished = 1;    pthread_cond_broadcast(&d->cond);    pthread_mutex_unlock(&f->lock);    fuse_req_interrupt_func(req, NULL, NULL);    pthread_cond_destroy(&d->cond);}static void fuse_do_prepare_interrupt(fuse_req_t req, struct fuse_intr_data *d){    d->id = pthread_self();    pthread_cond_init(&d->cond, NULL);    d->finished = 0;    fuse_req_interrupt_func(req, fuse_interrupt, d);}static inline void fuse_finish_interrupt(struct fuse *f, fuse_req_t req,                                         struct fuse_intr_data *d){    if (f->conf.intr)        fuse_do_finish_interrupt(f, req, d);}static inline void fuse_prepare_interrupt(struct fuse *f, fuse_req_t req,                                          struct fuse_intr_data *d){    if (f->conf.intr)        fuse_do_prepare_interrupt(req, d);}static int fuse_do_getattr(struct fuse *f, fuse_req_t req, const char *path,                           struct stat *buf){    int res;    struct fuse_intr_data d;    fuse_prepare_interrupt(f, req, &d);    res = f->op.getattr(path, buf);    fuse_finish_interrupt(f, req, &d);    return res;}static int fuse_do_fgetattr(struct fuse *f, fuse_req_t req, const char *path,                            struct stat *buf, struct fuse_file_info *fi){    int res;    struct fuse_intr_data d;    fuse_prepare_interrupt(f, req, &d);    res = f->op.fgetattr(path, buf, fi);    fuse_finish_interrupt(f, req, &d);    return res;}static int fuse_do_rename(struct fuse *f, fuse_req_t req, const char *oldpath,                          const char *newpath){    int res;    struct fuse_intr_data d;    fuse_prepare_interrupt(f, req, &d);    res = f->op.rename(oldpath, newpath);    fuse_finish_interrupt(f, req, &d);    return res;}static int fuse_do_unlink(struct fuse *f, fuse_req_t req, const char *path){    int res;    struct fuse_intr_data d;    fuse_prepare_interrupt(f, req, &d);    res = f->op.unlink(path);    fuse_finish_interrupt(f, req, &d);    return res;}static void fuse_do_release(struct fuse *f, fuse_req_t req, const char *path,                            struct fuse_file_info *fi){    struct fuse_intr_data d;    fuse_prepare_interrupt(f, req, &d);    f->op.release(path, fi);    fuse_finish_interrupt(f, req, &d);}static int fuse_do_opendir(struct fuse *f, fuse_req_t req, char *path,                           struct fuse_file_info *fi){    int res;    struct fuse_intr_data d;    fuse_prepare_interrupt(f, req, &d);    res = f->op.opendir(path, fi);    fuse_finish_interrupt(f, req, &d);    return res;}static int fuse_do_open(struct fuse *f, fuse_req_t req, char *path,                           struct fuse_file_info *fi){    int res;    struct fuse_intr_data d;    fuse_prepare_interrupt(f, req, &d);    res = f->op.open(path, fi);    fuse_finish_interrupt(f, req, &d);    return res;}static int fuse_do_flush(struct fuse *f, fuse_req_t req, const char *path,                         struct fuse_file_info *fi){    int res;    struct fuse_intr_data d;    fuse_prepare_interrupt(f, req, &d);    res = f->op.flush(path, fi);    fuse_finish_interrupt(f, req, &d);    return res;}static int fuse_do_statfs(struct fuse *f, fuse_req_t req, const char *path,                          struct statvfs *buf){    int res;    struct fuse_intr_data d;    fuse_prepare_interrupt(f, req, &d);    res = f->op.statfs(path, buf);    fuse_finish_interrupt(f, req, &d);    return res;}static void fuse_do_releasedir(struct fuse *f, fuse_req_t req,                               const char *path, struct fuse_file_info *fi){    struct fuse_intr_data d;    fuse_prepare_interrupt(f, req, &d);    f->op.releasedir(path, fi);    fuse_finish_interrupt(f, req, &d);}static int fuse_do_create(struct fuse *f, fuse_req_t req, const char *path,                          mode_t mode, struct fuse_file_info *fi){    int res;    struct fuse_intr_data d;    fuse_prepare_interrupt(f, req, &d);    res = f->op.create(path, mode, fi);    fuse_finish_interrupt(f, req, &d);    return res;}static int fuse_do_lock(struct fuse *f, fuse_req_t req, const char *path,                        struct fuse_file_info *fi, int cmd, struct flock *lock){    int res;    struct fuse_intr_data d;    fuse_prepare_interrupt(f, req, &d);    res = f->op.lock(path, fi, cmd, lock);    fuse_finish_interrupt(f, req, &d);    return res;}static int is_open(struct fuse *f, fuse_ino_t dir, const char *name){    struct node *node;    int isopen = 0;    pthread_mutex_lock(&f->lock);    node = lookup_node(f, dir, name);    if (node && node->open_count > 0)        isopen = 1;    pthread_mutex_unlock(&f->lock);    return isopen;}static char *hidden_name(struct fuse *f, fuse_req_t req, fuse_ino_t dir,                         const char *oldname, char *newname, size_t bufsize){    struct stat buf;    struct node *node;    struct node *newnode;    char *newpath;    int res;    int failctr = 10;    if (!f->op.getattr)        return NULL;    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_do_getattr(f, req, newpath, &buf);        if (res != 0)            break;        free(newpath);        newpath = NULL;    } while(--failctr);    return newpath;}static int hide_node(struct fuse *f, fuse_req_t req, const char *oldpath,                     fuse_ino_t dir, const char *oldname){    char newname[64];    char *newpath;    int err = -EBUSY;    if (f->op.rename && f->op.unlink) {        newpath = hidden_name(f, req, dir, oldname, newname, sizeof(newname));        if (newpath) {            err = fuse_do_rename(f, req, 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#ifdef FUSE_STAT_HAS_NANOSEC        && ST_MTIM(stbuf).tv_nsec == ts->tv_nsec#endif        ;}static void mtime_set(const struct stat *stbuf, struct timespec *ts){#ifdef FUSE_STAT_HAS_NANOSEC    *ts = ST_MTIM(stbuf);#else    ts->tv_sec = stbuf->st_mtime;#endif}#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;    mtime_set(stbuf, &node->mtime);    node->size = stbuf->st_size;    curr_time(&node->stat_updated);}static int lookup_path(struct fuse *f, fuse_req_t req, 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 && f->op.fgetattr)        res = fuse_do_fgetattr(f, req, path, &e->attr, fi);    else        res = fuse_do_getattr(f, req, 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) {                printf("   NODEID: %lu\n", (unsigned long) e->ino);                fflush(stdout);            }        }    }    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;    c->ctx.private_data = c->ctx.fuse->user_data;    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);}static void fuse_data_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;    c->ctx.private_data = f->user_data;    if (f->op.init)        f->user_data = f->op.init(conn);}static void fuse_data_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;    c->ctx.private_data = f->user_data;    if (f->op.destroy)        f->op.destroy(f->user_data);}static void fuse_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) {        if (f->conf.debug) {            printf("LOOKUP %s\n", path);            fflush(stdout);        }        err = -ENOSYS;        if (f->op.getattr) {            err = lookup_path(f, req, 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;            }        }        free(path);    }    pthread_rwlock_unlock(&f->tree_lock);    reply_entry(req, &e, err);}static void fuse_forget(fuse_req_t req, fuse_ino_t ino, unsigned long nlookup){    struct fuse *f = req_fuse(req);    if (f->conf.debug) {        printf("FORGET %llu/%lu\n", (unsigned long long) ino, nlookup);        fflush(stdout);    }    forget_node(f, ino, nlookup);    fuse_reply_none(req);}static void fuse_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;

⌨️ 快捷键说明

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