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

📄 fuse.c

📁 linux下的用户文件系统fuse-2.5.2
💻 C
📖 第 1 页 / 共 4 页
字号:
        if (fuse_reply_open(req, fi) == -ENOENT) {            /* The open syscall was interrupted, so it must be cancelled */            if(f->op.release && path != NULL)                fuse_do_release(f, path, fi);        } else {            struct node *node = get_node(f, ino);            node->open_count ++;        }        pthread_mutex_unlock(&f->lock);    } else        reply_err(req, err);    if (path)        free(path);    pthread_rwlock_unlock(&f->tree_lock);}static void fuse_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) {        if (f->conf.debug) {            printf("READ[%llu] %u bytes from %llu\n",                   (unsigned long long) fi->fh, size, off);            fflush(stdout);        }        res = -ENOSYS;        if (f->op.read)            res = f->op.read(path, buf, size, off, fi);        free(path);    }    pthread_rwlock_unlock(&f->tree_lock);    if (res >= 0) {        if (f->conf.debug) {            printf("   READ[%llu] %u bytes\n", (unsigned long long) fi->fh,                   res);            fflush(stdout);        }        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_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) {        if (f->conf.debug) {            printf("WRITE%s[%llu] %u bytes to %llu\n",                   fi->writepage ? "PAGE" : "", (unsigned long long) fi->fh,                   size, off);            fflush(stdout);        }        res = -ENOSYS;        if (f->op.write)            res = f->op.write(path, buf, size, off, fi);        free(path);    }    pthread_rwlock_unlock(&f->tree_lock);    if (res >= 0) {        if (f->conf.debug) {            printf("   WRITE%s[%llu] %u bytes\n",                   fi->writepage ? "PAGE" : "", (unsigned long long) fi->fh,                   res);            fflush(stdout);        }        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_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;    err = -ENOENT;    pthread_rwlock_rdlock(&f->tree_lock);    path = get_path(f, ino);    if (path != NULL) {        if (f->conf.debug) {            printf("FLUSH[%llu]\n", (unsigned long long) fi->fh);            fflush(stdout);        }        err = -ENOSYS;        if (f->op.flush)            err = f->op.flush(path, fi);        free(path);    }    pthread_rwlock_unlock(&f->tree_lock);    reply_err(req, err);}static void fuse_release(fuse_req_t req, fuse_ino_t ino,                         struct fuse_file_info *fi){    struct fuse *f = req_fuse_prepare(req);    char *path;    struct node *node;    int unlink_hidden;    pthread_mutex_lock(&f->lock);    node = get_node(f, ino);    assert(node->open_count > 0);    --node->open_count;    unlink_hidden = (node->is_hidden && !node->open_count);    pthread_mutex_unlock(&f->lock);    pthread_rwlock_rdlock(&f->tree_lock);    path = get_path(f, ino);    if (f->conf.debug) {        printf("RELEASE[%llu] flags: 0x%x\n", (unsigned long long) fi->fh,               fi->flags);        fflush(stdout);    }    if (f->op.release)        fuse_do_release(f, path, fi);    if(unlink_hidden && path)        f->op.unlink(path);    if (path)        free(path);    pthread_rwlock_unlock(&f->tree_lock);    reply_err(req, 0);}static void fuse_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) {        if (f->conf.debug) {            printf("FSYNC[%llu]\n", (unsigned long long) fi->fh);            fflush(stdout);        }        err = -ENOSYS;        if (f->op.fsync)            err = f->op.fsync(path, datasync, fi);        free(path);    }    pthread_rwlock_unlock(&f->tree_lock);    reply_err(req, err);}static struct fuse_dirhandle *get_dirhandle(const struct fuse_file_info *llfi,                                            struct fuse_file_info *fi){    struct fuse_dirhandle *dh = (struct fuse_dirhandle *) (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_opendir(fuse_req_t req, fuse_ino_t ino,                       struct fuse_file_info *llfi){    struct fuse *f = req_fuse_prepare(req);    struct fuse_dirhandle *dh;    dh = (struct fuse_dirhandle *) malloc(sizeof(struct fuse_dirhandle));    if (dh == NULL) {        reply_err(req, -ENOMEM);        return;    }    memset(dh, 0, sizeof(struct fuse_dirhandle));    dh->fuse = f;    dh->contents = NULL;    dh->len = 0;    dh->filled = 0;    dh->nodeid = ino;    mutex_init(&dh->lock);    llfi->fh = (uintptr_t) dh;    if (f->op.opendir) {        struct fuse_file_info fi;        char *path;        int err;        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) {            err = fuse_do_opendir(f, path, &fi);            dh->fh = fi.fh;        }        if (!err) {            pthread_mutex_lock(&f->lock);            if (fuse_reply_open(req, llfi) == -ENOENT) {                /* The opendir syscall was interrupted, so it must be                   cancelled */                if(f->op.releasedir)                    f->op.releasedir(path, &fi);                pthread_mutex_destroy(&dh->lock);                free(dh);            }            pthread_mutex_unlock(&f->lock);        } else {            reply_err(req, err);            free(dh);        }        free(path);        pthread_rwlock_unlock(&f->tree_lock);    } else        fuse_reply_open(req, llfi);}static int fill_dir_common(struct fuse_dirhandle *dh, const char *name,                           const struct stat *statp, off_t off){    struct stat stbuf;    unsigned namelen = strlen(name);    unsigned entsize;    unsigned 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);        }    }    entsize = fuse_dirent_size(namelen);    newlen = dh->len + entsize;    if (off) {        dh->filled = 0;        if (newlen > dh->needlen)            return 1;    }    if (newlen > dh->size) {        char *newptr;        if (!dh->size)            dh->size = 1024;        while (newlen > dh->size)            dh->size *= 2;        newptr = (char *) realloc(dh->contents, dh->size);        if (!newptr) {            dh->error = -ENOMEM;            return 1;        }        dh->contents = newptr;    }    fuse_add_dirent(dh->contents + dh->len, name, &stbuf, off ? off : newlen);    dh->len = newlen;    return 0;}static int fill_dir(void *buf, const char *name, const struct stat *stbuf,                    off_t off){    return fill_dir_common((struct fuse_dirhandle *) buf, name, stbuf, off);}static int fill_dir_old(struct fuse_dirhandle *dh, const char *name, int type,                        ino_t ino){    struct stat stbuf;    memset(&stbuf, 0, sizeof(stbuf));    stbuf.st_mode = type << 12;    stbuf.st_ino = ino;    fill_dir_common(dh, name, &stbuf, 0);    return dh->error;}static int readdir_fill(struct fuse *f, fuse_ino_t ino, size_t size,                        off_t off, struct fuse_dirhandle *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) {        dh->len = 0;        dh->error = 0;        dh->needlen = size;        dh->filled = 1;        err = -ENOSYS;        if (f->op.readdir)            err = f->op.readdir(path, dh, fill_dir, off, fi);        else if (f->op.getdir)            err = f->op.getdir(path, dh, fill_dir_old);        if (!err)            err = dh->error;        if (err)            dh->filled = 0;        free(path);    }    pthread_rwlock_unlock(&f->tree_lock);    return err;}static void fuse_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_dirhandle *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, 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_releasedir(fuse_req_t req, fuse_ino_t ino,                            struct fuse_file_info *llfi){    struct fuse *f = req_fuse_prepare(req);    struct fuse_file_info fi;    struct fuse_dirhandle *dh = get_dirhandle(llfi, &fi);    if (f->op.releasedir) {        char *path;        pthread_rwlock_rdlock(&f->tree_lock);        path = get_path(f, ino);        f->op.releasedir(path ? path : "-", &fi);        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_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) {        err = -ENOSYS;        if (f->op.fsyncdir)            err = f->op.fsyncdir(path, datasync, &fi);        free(path);    }    pthread_rwlock_unlock(&f->tree_lock);    reply_err(req, err);}static int default_statfs(struct statvfs *buf){    buf->f_namemax = 255;    buf->f_bsize = 512;    return 0;}static void fuse_statfs(fuse_req_t req){    struct fuse *f = req_fuse_prepare(req);    struct statvfs buf;    int err;    memset(&buf, 0, sizeof(buf));    if (f->op.statfs) {        err = fuse_do_statfs(f, "/", &buf);    } else        err = default_statfs(&buf);    if (!err)        fuse_reply_statfs(req, &buf);    else        reply_err(req, err);}static void fuse_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) {        err = -ENOSYS;        if (f->op.setxattr)            err = f->op.setxattr(path, name, value, size, flags);        free(path);    }    pthread_rwlock_unlock(&f->tree_lock);    reply_err(req, err);}static int common_getxattr(struct fuse *f, 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) {        err = -ENOSYS;        if (f->op.getxattr)            err = f->op.getxattr(path, name, value, size);        free(path);    }    pthread_rwlock_unlock(&f->tree_lock);    return err;}static void fuse_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, 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, 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_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) {        err = -ENOSYS;        if (f->op.listxattr)            err = f->op.listxattr(path, list, size);        free(path);    }    pthread_rwlock_unlock(&f->tree_lock);    return err;}

⌨️ 快捷键说明

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