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

📄 fuse.c

📁 Linux下fuse用户文件系统的的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
    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, 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_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);        fuse_do_releasedir(f, req, 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) {            struct fuse_intr_data d;            fuse_prepare_interrupt(f, req, &d);            err = f->op.fsyncdir(path, datasync, &fi);            fuse_finish_interrupt(f, req, &d);        }        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, fuse_ino_t ino){    struct fuse *f = req_fuse_prepare(req);    struct statvfs buf;    int err;    memset(&buf, 0, sizeof(buf));    if (f->op.statfs) {        if (ino && (!f->compat || f->compat >= 26)) {            char *path;            pthread_rwlock_rdlock(&f->tree_lock);            err = -ENOENT;            path = get_path(f, ino);            if (path) {                err = fuse_do_statfs(f, req, path, &buf);                free(path);            }            pthread_rwlock_unlock(&f->tree_lock);        } else            err = fuse_compat_statfs(f, req, &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) {            struct fuse_intr_data d;            fuse_prepare_interrupt(f, req, &d);            err = f->op.setxattr(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) {        err = -ENOSYS;        if (f->op.getxattr) {            struct fuse_intr_data d;            fuse_prepare_interrupt(f, req, &d);            err = f->op.getxattr(path, name, value, size);            fuse_finish_interrupt(f, req, &d);        }        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, 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) {        err = -ENOSYS;        if (f->op.listxattr) {            struct fuse_intr_data d;            fuse_prepare_interrupt(f, req, &d);            err = f->op.listxattr(path, list, size);            fuse_finish_interrupt(f, req, &d);        }        free(path);    }    pthread_rwlock_unlock(&f->tree_lock);    return err;}static void fuse_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_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) {        err = -ENOSYS;        if (f->op.removexattr) {            struct fuse_intr_data d;            fuse_prepare_interrupt(f, req, &d);            err = f->op.removexattr(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 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 = fuse_do_flush(f, req, path, fi);    }    if (f->op.lock) {        struct flock lock;        struct lock l;        memset(&lock, 0, sizeof(lock));        lock.l_type = F_UNLCK;        lock.l_whence = SEEK_SET;        fuse_do_lock(f, req, path, fi, F_SETLK, &lock);        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;    }    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) {        err = fuse_do_lock(f, req, path, fi, cmd, lock);        free(path);    }    pthread_rwlock_unlock(&f->tree_lock);    return err;}static void fuse_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_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_

⌨️ 快捷键说明

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