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

📄 fuse.c

📁 UNIX/LINUX下面的用户文件系统
💻 C
📖 第 1 页 / 共 5 页
字号:
/*    FUSE: Filesystem in Userspace    Copyright (C) 2001-2007  Miklos Szeredi <miklos@szeredi.hu>    This program can be distributed under the terms of the GNU LGPL.    See the file COPYING.LIB*//* For pthread_rwlock_t */#define _GNU_SOURCE#include "fuse_i.h"#include "fuse_lowlevel.h"#include "fuse_opt.h"#include "fuse_misc.h"#include "fuse_common_compat.h"#include "fuse_compat.h"#include <stdio.h>#include <string.h>#include <stdlib.h>#include <stddef.h>#include <unistd.h>#include <time.h>#include <fcntl.h>#include <limits.h>#include <errno.h>#include <signal.h>#include <dlfcn.h>#include <assert.h>#include <sys/param.h>#include <sys/uio.h>#include <sys/time.h>#define FUSE_MAX_PATH 4096#define FUSE_DEFAULT_INTR_SIGNAL SIGUSR1#define FUSE_UNKNOWN_INO 0xffffffff#define OFFSET_MAX 0x7fffffffffffffffLLstruct fuse_config {    unsigned int uid;    unsigned int gid;    unsigned int  umask;    double entry_timeout;    double negative_timeout;    double attr_timeout;    double ac_attr_timeout;    int ac_attr_timeout_set;    int debug;    int hard_remove;    int use_ino;    int readdir_ino;    int set_mode;    int set_uid;    int set_gid;    int direct_io;    int kernel_cache;    int auto_cache;    int intr;    int intr_signal;    int help;    char *modules;};struct fuse_fs {    struct fuse_operations op;    struct fuse_module *m;    void *user_data;    int compat;};struct fusemod_so {    void *handle;    int ctr;};struct fuse {    struct fuse_session *se;    struct node **name_table;    size_t name_table_size;    struct node **id_table;    size_t id_table_size;    fuse_ino_t ctr;    unsigned int generation;    unsigned int hidectr;    pthread_mutex_t lock;    pthread_rwlock_t tree_lock;    struct fuse_config conf;    int intr_installed;    struct fuse_fs *fs;};struct lock {    int type;    off_t start;    off_t end;    pid_t pid;    uint64_t owner;    struct lock *next;};struct node {    struct node *name_next;    struct node *id_next;    fuse_ino_t nodeid;    unsigned int generation;    int refctr;    struct node *parent;    char *name;    uint64_t nlookup;    int open_count;    int is_hidden;    struct timespec stat_updated;    struct timespec mtime;    off_t size;    int cache_valid;    struct lock *locks;};struct fuse_dh {    pthread_mutex_t lock;    struct fuse *fuse;    fuse_req_t req;    char *contents;    int allocated;    unsigned len;    unsigned size;    unsigned needlen;    int filled;    uint64_t fh;    int error;    fuse_ino_t nodeid;};/* old dir handle */struct fuse_dirhandle {    fuse_fill_dir_t filler;    void *buf;};struct fuse_context_i {    struct fuse_context ctx;    fuse_req_t req;};static pthread_key_t fuse_context_key;static pthread_mutex_t fuse_context_lock = PTHREAD_MUTEX_INITIALIZER;static int fuse_context_ref;static struct fusemod_so *fuse_current_so;static struct fuse_module *fuse_modules;static int fuse_load_so_name(const char *soname){    struct fusemod_so *so;    so = calloc(1, sizeof(struct fusemod_so));    if (!so) {        fprintf(stderr, "fuse: memory allocation failed\n");        return -1;    }    fuse_current_so = so;    so->handle = dlopen(soname, RTLD_NOW);    fuse_current_so = NULL;    if (!so->handle) {        fprintf(stderr, "fuse: %s\n", dlerror());        goto err;    }    if (!so->ctr) {        fprintf(stderr, "fuse: %s did not register any modules", soname);        goto err;    }    return 0; err:    if (so->handle)        dlclose(so->handle);    free(so);    return -1;}static int fuse_load_so_module(const char *module){    int res;    char *soname = malloc(strlen(module) + 64);    if (!soname) {        fprintf(stderr, "fuse: memory allocation failed\n");        return -1;    }    sprintf(soname, "libfusemod_%s.so", module);    res = fuse_load_so_name(soname);    free(soname);    return res;}static struct fuse_module *fuse_find_module(const char *module){    struct fuse_module *m;    for (m = fuse_modules; m; m = m->next) {        if (strcmp(module, m->name) == 0) {            m->ctr++;            break;        }    }    return m;}static struct fuse_module *fuse_get_module(const char *module){    struct fuse_module *m;    pthread_mutex_lock(&fuse_context_lock);    m = fuse_find_module(module);    if (!m) {        int err = fuse_load_so_module(module);        if (!err)            m = fuse_find_module(module);    }    pthread_mutex_unlock(&fuse_context_lock);    return m;}static void fuse_put_module(struct fuse_module *m){    pthread_mutex_lock(&fuse_context_lock);    assert(m->ctr > 0);    m->ctr--;    if (!m->ctr && m->so) {        struct fusemod_so *so = m->so;        assert(so->ctr > 0);        so->ctr--;        if (!so->ctr) {            struct fuse_module **mp;            for (mp = &fuse_modules; *mp;) {                if ((*mp)->so == so)                    *mp = (*mp)->next;                else                    mp = &(*mp)->next;            }            dlclose(so->handle);            free(so);        }    }    pthread_mutex_unlock(&fuse_context_lock);}static struct node *get_node_nocheck(struct fuse *f, fuse_ino_t nodeid){    size_t hash = nodeid % f->id_table_size;    struct node *node;    for (node = f->id_table[hash]; node != NULL; node = node->id_next)        if (node->nodeid == nodeid)            return node;    return NULL;}static struct node *get_node(struct fuse *f, fuse_ino_t nodeid){    struct node *node = get_node_nocheck(f, nodeid);    if (!node) {        fprintf(stderr, "fuse internal error: node %llu not found\n",                (unsigned long long) nodeid);        abort();    }    return node;}static void free_node(struct node *node){    free(node->name);    free(node);}static void unhash_id(struct fuse *f, struct node *node){    size_t hash = node->nodeid % f->id_table_size;    struct node **nodep = &f->id_table[hash];    for (; *nodep != NULL; nodep = &(*nodep)->id_next)        if (*nodep == node) {            *nodep = node->id_next;            return;        }}static void hash_id(struct fuse *f, struct node *node){    size_t hash = node->nodeid % f->id_table_size;    node->id_next = f->id_table[hash];    f->id_table[hash] = node;}static unsigned int name_hash(struct fuse *f, fuse_ino_t parent,                              const char *name){    unsigned int hash = *name;    if (hash)        for (name += 1; *name != '\0'; name++)            hash = (hash << 5) - hash + *name;    return (hash + parent) % f->name_table_size;}static void unref_node(struct fuse *f, struct node *node);static void unhash_name(struct fuse *f, struct node *node){    if (node->name) {        size_t hash = name_hash(f, node->parent->nodeid, node->name);        struct node **nodep = &f->name_table[hash];        for (; *nodep != NULL; nodep = &(*nodep)->name_next)            if (*nodep == node) {                *nodep = node->name_next;                node->name_next = NULL;                unref_node(f, node->parent);                free(node->name);                node->name = NULL;                node->parent = NULL;                return;            }        fprintf(stderr, "fuse internal error: unable to unhash node: %llu\n",                (unsigned long long) node->nodeid);        abort();    }}static int hash_name(struct fuse *f, struct node *node, fuse_ino_t parentid,                     const char *name){    size_t hash = name_hash(f, parentid, name);    struct node *parent = get_node(f, parentid);    node->name = strdup(name);    if (node->name == NULL)        return -1;    parent->refctr ++;    node->parent = parent;    node->name_next = f->name_table[hash];    f->name_table[hash] = node;    return 0;}static void delete_node(struct fuse *f, struct node *node){    if (f->conf.debug)        fprintf(stderr, "delete: %llu\n", (unsigned long long) node->nodeid);    assert(!node->name);    unhash_id(f, node);    free_node(node);}static void unref_node(struct fuse *f, struct node *node){    assert(node->refctr > 0);    node->refctr --;    if (!node->refctr)        delete_node(f, node);}static fuse_ino_t next_id(struct fuse *f){    do {        f->ctr = (f->ctr + 1) & 0xffffffff;        if (!f->ctr)            f->generation ++;    } while (f->ctr == 0 || f->ctr == FUSE_UNKNOWN_INO ||             get_node_nocheck(f, f->ctr) != NULL);    return f->ctr;}static struct node *lookup_node(struct fuse *f, fuse_ino_t parent,                                const char *name){    size_t hash = name_hash(f, parent, name);    struct node *node;    for (node = f->name_table[hash]; node != NULL; node = node->name_next)        if (node->parent->nodeid == parent && strcmp(node->name, name) == 0)            return node;    return NULL;}static struct node *find_node(struct fuse *f, fuse_ino_t parent,                              const char *name){    struct node *node;    pthread_mutex_lock(&f->lock);    node = lookup_node(f, parent, name);    if (node == NULL) {        node = (struct node *) calloc(1, sizeof(struct node));        if (node == NULL)            goto out_err;        node->refctr = 1;        node->nodeid = next_id(f);        node->open_count = 0;        node->is_hidden = 0;        node->generation = f->generation;        if (hash_name(f, node, parent, name) == -1) {            free(node);            node = NULL;            goto out_err;        }        hash_id(f, node);    }    node->nlookup ++; out_err:    pthread_mutex_unlock(&f->lock);    return node;}static char *add_name(char *buf, char *s, const char *name){    size_t len = strlen(name);    s -= len;    if (s <= buf) {        fprintf(stderr, "fuse: path too long: ...%s\n", s + len);        return NULL;    }    strncpy(s, name, len);    s--;    *s = '/';    return s;}static char *get_path_name(struct fuse *f, fuse_ino_t nodeid, const char *name){    char buf[FUSE_MAX_PATH];    char *s = buf + FUSE_MAX_PATH - 1;    struct node *node;    *s = '\0';    if (name != NULL) {        s = add_name(buf, s, name);        if (s == NULL)            return NULL;    }    pthread_mutex_lock(&f->lock);    for (node = get_node(f, nodeid); node && node->nodeid != FUSE_ROOT_ID;         node = node->parent) {        if (node->name == NULL) {            s = NULL;            break;        }        s = add_name(buf, s, node->name);        if (s == NULL)            break;    }    pthread_mutex_unlock(&f->lock);    if (node == NULL || s == NULL)        return NULL;    else if (*s == '\0')        return strdup("/");    else        return strdup(s);}static char *get_path(struct fuse *f, fuse_ino_t nodeid){    return get_path_name(f, nodeid, NULL);}

⌨️ 快捷键说明

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