cleanup
This commit is contained in:
parent
cdc0da7956
commit
386a7f67ab
|
|
@ -1,3 +1,7 @@
|
|||
2005-02-07 Miklos Szeredi <miklos@szeredi.hu>
|
||||
|
||||
* Separate attribute caching to a separate layer
|
||||
|
||||
2005-02-03 Miklos Szeredi <miklos@szeredi.hu>
|
||||
|
||||
Fix PKG_CONFIG_PATH setting in configure.ac (reported by Alpar
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
## Process this file with automake to produce Makefile.in
|
||||
|
||||
bin_PROGRAMS = sshfs
|
||||
sshfs_SOURCES = sshfs.c
|
||||
sshfs_SOURCES = sshfs.c cache.c
|
||||
|
|
|
|||
|
|
@ -0,0 +1,244 @@
|
|||
/*
|
||||
Caching file system proxy
|
||||
Copyright (C) 2004 Miklos Szeredi <miklos@szeredi.hu>
|
||||
|
||||
This program can be distributed under the terms of the GNU GPL.
|
||||
See the file COPYING.
|
||||
*/
|
||||
|
||||
#define FUSE_USE_VERSION 22
|
||||
#include "cache.h"
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <glib.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#define CACHE_TIMEOUT 20
|
||||
#define MAX_CACHE_SIZE 10000
|
||||
#define CACHE_CLEAN_INTERVAL 60
|
||||
|
||||
struct node_attr {
|
||||
struct stat stat;
|
||||
time_t stat_valid;
|
||||
time_t valid;
|
||||
};
|
||||
|
||||
struct fuse_cache_dirhandle {
|
||||
const char *path;
|
||||
fuse_dirh_t h;
|
||||
fuse_dirfil_t filler;
|
||||
};
|
||||
|
||||
static struct fuse_cache_operations *next_oper;
|
||||
static GHashTable *cache;
|
||||
static pthread_mutex_t cache_lock;
|
||||
static time_t last_cleaned;
|
||||
|
||||
static int cache_clean_entry(void *_key, struct node_attr *node, time_t *now)
|
||||
{
|
||||
(void) _key;
|
||||
if (*now > node->valid)
|
||||
return TRUE;
|
||||
else
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void cache_clean(void)
|
||||
{
|
||||
time_t now = time(NULL);
|
||||
if (g_hash_table_size(cache) > MAX_CACHE_SIZE ||
|
||||
now > last_cleaned + CACHE_CLEAN_INTERVAL) {
|
||||
g_hash_table_foreach_remove(cache, (GHRFunc) cache_clean_entry, &now);
|
||||
last_cleaned = now;
|
||||
}
|
||||
}
|
||||
|
||||
static struct node_attr *cache_lookup(const char *path)
|
||||
{
|
||||
return (struct node_attr *) g_hash_table_lookup(cache, path);
|
||||
}
|
||||
|
||||
static void cache_remove(const char *path)
|
||||
{
|
||||
pthread_mutex_lock(&cache_lock);
|
||||
g_hash_table_remove(cache, path);
|
||||
pthread_mutex_unlock(&cache_lock);
|
||||
}
|
||||
|
||||
static void cache_invalidate(const char *path)
|
||||
{
|
||||
cache_remove(path);
|
||||
}
|
||||
|
||||
static void cache_do_rename(const char *from, const char *to)
|
||||
{
|
||||
cache_remove(from);
|
||||
cache_remove(to);
|
||||
}
|
||||
|
||||
static struct node_attr *cache_get(const char *path)
|
||||
{
|
||||
struct node_attr *node = cache_lookup(path);
|
||||
if (node == NULL) {
|
||||
char *pathcopy = g_strdup(path);
|
||||
node = g_new0(struct node_attr, 1);
|
||||
g_hash_table_insert(cache, pathcopy, node);
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
static void cache_add_attr(const char *path, const struct stat *stbuf)
|
||||
{
|
||||
struct node_attr *node;
|
||||
time_t now;
|
||||
|
||||
pthread_mutex_lock(&cache_lock);
|
||||
node = cache_get(path);
|
||||
now = time(NULL);
|
||||
node->stat = *stbuf;
|
||||
node->stat_valid = time(NULL) + CACHE_TIMEOUT;
|
||||
if (node->stat_valid > node->valid)
|
||||
node->valid = node->stat_valid;
|
||||
cache_clean();
|
||||
pthread_mutex_unlock(&cache_lock);
|
||||
}
|
||||
|
||||
static int cache_getattr(const char *path, struct stat *stbuf)
|
||||
{
|
||||
struct node_attr *node;
|
||||
int err;
|
||||
|
||||
pthread_mutex_lock(&cache_lock);
|
||||
node = cache_lookup(path);
|
||||
if (node != NULL) {
|
||||
time_t now = time(NULL);
|
||||
if (node->valid - now >= 0) {
|
||||
*stbuf = node->stat;
|
||||
pthread_mutex_unlock(&cache_lock);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
pthread_mutex_unlock(&cache_lock);
|
||||
err = next_oper->oper.getattr(path, stbuf);
|
||||
if (!err)
|
||||
cache_add_attr(path, stbuf);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int cache_dirfill(fuse_cache_dirh_t ch, const char *name,
|
||||
const struct stat *stbuf)
|
||||
{
|
||||
int err = ch->filler(ch->h, name, 0, 0);
|
||||
if (!err) {
|
||||
char *fullpath = g_strdup_printf("%s/%s",
|
||||
!ch->path[1] ? "" : ch->path, name);
|
||||
cache_add_attr(fullpath, stbuf);
|
||||
g_free(fullpath);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
static int cache_getdir(const char *path, fuse_dirh_t h, fuse_dirfil_t filler)
|
||||
{
|
||||
struct fuse_cache_dirhandle ch;
|
||||
ch.path = path;
|
||||
ch.h = h;
|
||||
ch.filler = filler;
|
||||
return next_oper->cache_getdir(path, &ch, cache_dirfill);
|
||||
}
|
||||
|
||||
static int cache_unlink(const char *path)
|
||||
{
|
||||
int err = next_oper->oper.unlink(path);
|
||||
if (!err)
|
||||
cache_remove(path);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int cache_rmdir(const char *path)
|
||||
{
|
||||
int err = next_oper->oper.rmdir(path);
|
||||
if (!err)
|
||||
cache_remove(path);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int cache_rename(const char *from, const char *to)
|
||||
{
|
||||
int err = next_oper->oper.rename(from, to);
|
||||
if (!err)
|
||||
cache_do_rename(from, to);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int cache_chmod(const char *path, mode_t mode)
|
||||
{
|
||||
int err = next_oper->oper.chmod(path, mode);
|
||||
if (!err)
|
||||
cache_invalidate(path);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int cache_chown(const char *path, uid_t uid, gid_t gid)
|
||||
{
|
||||
int err = next_oper->oper.chown(path, uid, gid);
|
||||
if (!err)
|
||||
cache_invalidate(path);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int cache_truncate(const char *path, off_t size)
|
||||
{
|
||||
int err = next_oper->oper.truncate(path, size);
|
||||
if (!err)
|
||||
cache_invalidate(path);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int cache_utime(const char *path, struct utimbuf *buf)
|
||||
{
|
||||
int err = next_oper->oper.utime(path, buf);
|
||||
if (!err)
|
||||
cache_invalidate(path);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
struct fuse_operations *cache_init(struct fuse_cache_operations *oper)
|
||||
{
|
||||
static struct fuse_operations cache_oper;
|
||||
next_oper = oper;
|
||||
|
||||
cache_oper.getattr = oper->oper.getattr ? cache_getattr : NULL;
|
||||
cache_oper.readlink = oper->oper.readlink;
|
||||
cache_oper.getdir = oper->cache_getdir ? cache_getdir : oper->oper.getdir;
|
||||
cache_oper.mknod = oper->oper.mknod;
|
||||
cache_oper.mkdir = oper->oper.mkdir;
|
||||
cache_oper.symlink = oper->oper.symlink;
|
||||
cache_oper.unlink = oper->oper.unlink ? cache_unlink : NULL;
|
||||
cache_oper.rmdir = oper->oper.rmdir ? cache_rmdir : NULL;
|
||||
cache_oper.rename = oper->oper.rename ? cache_rename : NULL;
|
||||
cache_oper.link = oper->oper.link;
|
||||
cache_oper.chmod = oper->oper.chmod ? cache_chmod : NULL;
|
||||
cache_oper.chown = oper->oper.chown ? cache_chown : NULL;
|
||||
cache_oper.truncate = oper->oper.truncate ? cache_truncate : NULL;
|
||||
cache_oper.utime = oper->oper.utime ? cache_utime : NULL;
|
||||
cache_oper.open = oper->oper.open;
|
||||
cache_oper.read = oper->oper.read;
|
||||
cache_oper.write = oper->oper.write;
|
||||
cache_oper.statfs = oper->oper.statfs;
|
||||
cache_oper.release = oper->oper.release;
|
||||
cache_oper.fsync = oper->oper.fsync;
|
||||
cache_oper.setxattr = oper->oper.setxattr;
|
||||
cache_oper.getxattr = oper->oper.getxattr;
|
||||
cache_oper.listxattr = oper->oper.listxattr;
|
||||
cache_oper.removexattr = oper->oper.removexattr;
|
||||
pthread_mutex_init(&cache_lock, NULL);
|
||||
cache = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
|
||||
if (cache == NULL) {
|
||||
fprintf(stderr, "failed to create cache\n");
|
||||
return NULL;
|
||||
}
|
||||
return &cache_oper;
|
||||
}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
/*
|
||||
Caching file system proxy
|
||||
Copyright (C) 2004 Miklos Szeredi <miklos@szeredi.hu>
|
||||
|
||||
This program can be distributed under the terms of the GNU GPL.
|
||||
See the file COPYING.
|
||||
*/
|
||||
|
||||
#include <fuse.h>
|
||||
|
||||
typedef struct fuse_cache_dirhandle *fuse_cache_dirh_t;
|
||||
typedef int (*fuse_cache_dirfil_t) (fuse_cache_dirh_t h, const char *name,
|
||||
const struct stat *stbuf);
|
||||
|
||||
struct fuse_cache_operations {
|
||||
struct fuse_operations oper;
|
||||
int (*cache_getdir) (const char *, fuse_cache_dirh_t, fuse_cache_dirfil_t);
|
||||
|
||||
};
|
||||
|
||||
struct fuse_operations *cache_init(struct fuse_cache_operations *oper);
|
||||
179
sshfs.c
179
sshfs.c
|
|
@ -23,6 +23,8 @@
|
|||
#include <netinet/in.h>
|
||||
#include <glib.h>
|
||||
|
||||
#include "cache.h"
|
||||
|
||||
#define SSH_FXP_INIT 1
|
||||
#define SSH_FXP_VERSION 2
|
||||
#define SSH_FXP_OPEN 3
|
||||
|
|
@ -79,9 +81,6 @@
|
|||
#define MY_EOF 1
|
||||
|
||||
#define MAX_REPLY_LEN (1 << 17)
|
||||
#define CACHE_TIMEOUT 20
|
||||
#define MAX_CACHE_SIZE 10000
|
||||
#define CACHE_CLEAN_INTERVAL 60
|
||||
|
||||
static int infd;
|
||||
static int outfd;
|
||||
|
|
@ -110,18 +109,11 @@ struct openfile {
|
|||
struct buffer write_handle;
|
||||
};
|
||||
|
||||
struct node_attr {
|
||||
struct stat stat;
|
||||
time_t updated;
|
||||
};
|
||||
|
||||
struct sshfs_file {
|
||||
struct buffer handle;
|
||||
};
|
||||
|
||||
static GHashTable *reqtab;
|
||||
static GHashTable *cache;
|
||||
static time_t last_cleaned;
|
||||
static pthread_mutex_t lock;
|
||||
static int processing_thread_started;
|
||||
|
||||
|
|
@ -379,75 +371,8 @@ static int buf_get_attrs(struct buffer *buf, struct stat *stbuf)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int cache_clean_entry(void *_key, struct node_attr *node, time_t *now)
|
||||
{
|
||||
(void) _key;
|
||||
if (*now > node->updated + CACHE_TIMEOUT)
|
||||
return TRUE;
|
||||
else
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void cache_clean(void)
|
||||
{
|
||||
time_t now = time(NULL);
|
||||
if (g_hash_table_size(cache) > MAX_CACHE_SIZE ||
|
||||
now > last_cleaned + CACHE_CLEAN_INTERVAL) {
|
||||
g_hash_table_foreach_remove(cache, (GHRFunc) cache_clean_entry, &now);
|
||||
last_cleaned = now;
|
||||
}
|
||||
}
|
||||
|
||||
static struct node_attr *cache_lookup(const char *path)
|
||||
{
|
||||
return (struct node_attr *) g_hash_table_lookup(cache, path);
|
||||
}
|
||||
|
||||
static void cache_remove(const char *path)
|
||||
{
|
||||
pthread_mutex_lock(&lock);
|
||||
g_hash_table_remove(cache, path);
|
||||
pthread_mutex_unlock(&lock);
|
||||
}
|
||||
|
||||
static void cache_invalidate(const char *path)
|
||||
{
|
||||
cache_remove(path);
|
||||
}
|
||||
|
||||
static void cache_rename(const char *from, const char *to)
|
||||
{
|
||||
cache_remove(from);
|
||||
cache_remove(to);
|
||||
}
|
||||
|
||||
static struct node_attr *cache_get(const char *path)
|
||||
{
|
||||
struct node_attr *node = cache_lookup(path);
|
||||
if (node == NULL) {
|
||||
char *pathcopy = g_strdup(path);
|
||||
node = g_new0(struct node_attr, 1);
|
||||
g_hash_table_insert(cache, pathcopy, node);
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
static void cache_add_attr(const char *path, const struct stat *stbuf)
|
||||
{
|
||||
struct node_attr *node;
|
||||
time_t now;
|
||||
|
||||
pthread_mutex_lock(&lock);
|
||||
node = cache_get(path);
|
||||
now = time(NULL);
|
||||
node->stat = *stbuf;
|
||||
node->updated = time(NULL);
|
||||
cache_clean();
|
||||
pthread_mutex_unlock(&lock);
|
||||
}
|
||||
|
||||
static int buf_get_entries(struct buffer *buf, fuse_dirh_t h,
|
||||
fuse_dirfil_t filler, const char *path)
|
||||
static int buf_get_entries(struct buffer *buf, fuse_cache_dirh_t h,
|
||||
fuse_cache_dirfil_t filler)
|
||||
{
|
||||
uint32_t count;
|
||||
unsigned i;
|
||||
|
|
@ -465,11 +390,7 @@ static int buf_get_entries(struct buffer *buf, fuse_dirh_t h,
|
|||
if (buf_get_string(buf, &longname) != -1) {
|
||||
free(longname);
|
||||
if (buf_get_attrs(buf, &stbuf) != -1) {
|
||||
char *fullpath;
|
||||
filler(h, name, stbuf.st_mode >> 12, 0);
|
||||
fullpath = g_strdup_printf("%s/%s", !path[1] ? "" : path, name);
|
||||
cache_add_attr(fullpath, &stbuf);
|
||||
g_free(fullpath);
|
||||
filler(h, name, &stbuf);
|
||||
err = 0;
|
||||
}
|
||||
}
|
||||
|
|
@ -780,7 +701,7 @@ static int sftp_request(uint8_t type, const struct buffer *buf,
|
|||
|
||||
}
|
||||
|
||||
static int sshfs_send_getattr(const char *path, struct stat *stbuf)
|
||||
static int sshfs_getattr(const char *path, struct stat *stbuf)
|
||||
{
|
||||
int err;
|
||||
struct buffer buf;
|
||||
|
|
@ -794,29 +715,9 @@ static int sshfs_send_getattr(const char *path, struct stat *stbuf)
|
|||
buf_free(&outbuf);
|
||||
}
|
||||
buf_free(&buf);
|
||||
if (!err)
|
||||
cache_add_attr(path, stbuf);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int sshfs_getattr(const char *path, struct stat *stbuf)
|
||||
{
|
||||
struct node_attr *node;
|
||||
|
||||
pthread_mutex_lock(&lock);
|
||||
node = cache_lookup(path);
|
||||
if (node != NULL) {
|
||||
time_t now = time(NULL);
|
||||
if (now - node->updated < CACHE_TIMEOUT) {
|
||||
*stbuf = node->stat;
|
||||
pthread_mutex_unlock(&lock);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
pthread_mutex_unlock(&lock);
|
||||
return sshfs_send_getattr(path, stbuf);
|
||||
}
|
||||
|
||||
static int sshfs_readlink(const char *path, char *linkbuf, size_t size)
|
||||
{
|
||||
int err;
|
||||
|
|
@ -842,7 +743,8 @@ static int sshfs_readlink(const char *path, char *linkbuf, size_t size)
|
|||
return err;
|
||||
}
|
||||
|
||||
static int sshfs_getdir(const char *path, fuse_dirh_t h, fuse_dirfil_t filler)
|
||||
static int sshfs_getdir(const char *path, fuse_cache_dirh_t h,
|
||||
fuse_cache_dirfil_t filler)
|
||||
{
|
||||
int err;
|
||||
struct buffer buf;
|
||||
|
|
@ -857,7 +759,7 @@ static int sshfs_getdir(const char *path, fuse_dirh_t h, fuse_dirfil_t filler)
|
|||
struct buffer name;
|
||||
err = sftp_request(SSH_FXP_READDIR, &handle, SSH_FXP_NAME, &name);
|
||||
if (!err) {
|
||||
if (buf_get_entries(&name, h, filler, path) == -1)
|
||||
if (buf_get_entries(&name, h, filler) == -1)
|
||||
err = -EPROTO;
|
||||
buf_free(&name);
|
||||
}
|
||||
|
|
@ -935,8 +837,6 @@ static int sshfs_unlink(const char *path)
|
|||
buf_init(&buf, 0);
|
||||
buf_add_path(&buf, path);
|
||||
err = sftp_request(SSH_FXP_REMOVE, &buf, SSH_FXP_STATUS, NULL);
|
||||
if (!err)
|
||||
cache_remove(path);
|
||||
buf_free(&buf);
|
||||
return err;
|
||||
}
|
||||
|
|
@ -948,8 +848,6 @@ static int sshfs_rmdir(const char *path)
|
|||
buf_init(&buf, 0);
|
||||
buf_add_path(&buf, path);
|
||||
err = sftp_request(SSH_FXP_RMDIR, &buf, SSH_FXP_STATUS, NULL);
|
||||
if (!err)
|
||||
cache_remove(path);
|
||||
buf_free(&buf);
|
||||
return err;
|
||||
}
|
||||
|
|
@ -962,8 +860,6 @@ static int sshfs_rename(const char *from, const char *to)
|
|||
buf_add_path(&buf, from);
|
||||
buf_add_path(&buf, to);
|
||||
err = sftp_request(SSH_FXP_RENAME, &buf, SSH_FXP_STATUS, NULL);
|
||||
if (!err)
|
||||
cache_rename(from, to);
|
||||
buf_free(&buf);
|
||||
return err;
|
||||
}
|
||||
|
|
@ -977,8 +873,6 @@ static int sshfs_chmod(const char *path, mode_t mode)
|
|||
buf_add_uint32(&buf, SSH_FILEXFER_ATTR_PERMISSIONS);
|
||||
buf_add_uint32(&buf, mode);
|
||||
err = sftp_request(SSH_FXP_SETSTAT, &buf, SSH_FXP_STATUS, NULL);
|
||||
if (!err)
|
||||
cache_invalidate(path);
|
||||
buf_free(&buf);
|
||||
return err;
|
||||
}
|
||||
|
|
@ -1006,8 +900,6 @@ static int sshfs_truncate(const char *path, off_t size)
|
|||
buf_add_uint32(&buf, SSH_FILEXFER_ATTR_SIZE);
|
||||
buf_add_uint64(&buf, size);
|
||||
err = sftp_request(SSH_FXP_SETSTAT, &buf, SSH_FXP_STATUS, NULL);
|
||||
if (!err)
|
||||
cache_invalidate(path);
|
||||
buf_free(&buf);
|
||||
return err;
|
||||
}
|
||||
|
|
@ -1016,15 +908,12 @@ static int sshfs_utime(const char *path, struct utimbuf *ubuf)
|
|||
{
|
||||
int err;
|
||||
struct buffer buf;
|
||||
cache_remove(path);
|
||||
buf_init(&buf, 0);
|
||||
buf_add_path(&buf, path);
|
||||
buf_add_uint32(&buf, SSH_FILEXFER_ATTR_ACMODTIME);
|
||||
buf_add_uint32(&buf, ubuf->actime);
|
||||
buf_add_uint32(&buf, ubuf->modtime);
|
||||
err = sftp_request(SSH_FXP_SETSTAT, &buf, SSH_FXP_STATUS, NULL);
|
||||
if (!err)
|
||||
cache_invalidate(path);
|
||||
buf_free(&buf);
|
||||
return err;
|
||||
}
|
||||
|
|
@ -1110,6 +999,7 @@ static int sshfs_write(const char *path, const char *wbuf, size_t size,
|
|||
struct buffer data;
|
||||
struct sshfs_file *sf = (struct sshfs_file *) fi->fh;
|
||||
struct buffer *handle = &sf->handle;
|
||||
(void) path;
|
||||
data.p = (uint8_t *) wbuf;
|
||||
data.len = size;
|
||||
buf_init(&buf, 0);
|
||||
|
|
@ -1117,8 +1007,6 @@ static int sshfs_write(const char *path, const char *wbuf, size_t size,
|
|||
buf_add_uint64(&buf, offset);
|
||||
buf_add_data(&buf, &data);
|
||||
err = sftp_request(SSH_FXP_WRITE, &buf, SSH_FXP_STATUS, NULL);
|
||||
if (!err)
|
||||
cache_invalidate(path);
|
||||
buf_free(&buf);
|
||||
return err ? err : (int) size;
|
||||
}
|
||||
|
|
@ -1157,32 +1045,33 @@ static int processing_init(void)
|
|||
{
|
||||
pthread_mutex_init(&lock, NULL);
|
||||
reqtab = g_hash_table_new(NULL, NULL);
|
||||
cache = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
|
||||
if (!reqtab || !cache) {
|
||||
fprintf(stderr, "failed to create hash tables\n");
|
||||
if (!reqtab) {
|
||||
fprintf(stderr, "failed to create hash table\n");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct fuse_operations sshfs_oper = {
|
||||
.getattr = sshfs_getattr,
|
||||
.readlink = sshfs_readlink,
|
||||
.getdir = sshfs_getdir,
|
||||
.mknod = sshfs_mknod,
|
||||
.mkdir = sshfs_mkdir,
|
||||
.symlink = sshfs_symlink,
|
||||
.unlink = sshfs_unlink,
|
||||
.rmdir = sshfs_rmdir,
|
||||
.rename = sshfs_rename,
|
||||
.chmod = sshfs_chmod,
|
||||
.chown = sshfs_chown,
|
||||
.truncate = sshfs_truncate,
|
||||
.utime = sshfs_utime,
|
||||
.open = sshfs_open,
|
||||
.release = sshfs_release,
|
||||
.read = sshfs_read,
|
||||
.write = sshfs_write,
|
||||
static struct fuse_cache_operations sshfs_oper = {
|
||||
.oper = {
|
||||
.getattr = sshfs_getattr,
|
||||
.readlink = sshfs_readlink,
|
||||
.mknod = sshfs_mknod,
|
||||
.mkdir = sshfs_mkdir,
|
||||
.symlink = sshfs_symlink,
|
||||
.unlink = sshfs_unlink,
|
||||
.rmdir = sshfs_rmdir,
|
||||
.rename = sshfs_rename,
|
||||
.chmod = sshfs_chmod,
|
||||
.chown = sshfs_chown,
|
||||
.truncate = sshfs_truncate,
|
||||
.utime = sshfs_utime,
|
||||
.open = sshfs_open,
|
||||
.release = sshfs_release,
|
||||
.read = sshfs_read,
|
||||
.write = sshfs_write,
|
||||
},
|
||||
.cache_getdir = sshfs_getdir,
|
||||
};
|
||||
|
||||
static void usage(const char *progname)
|
||||
|
|
@ -1196,7 +1085,7 @@ static void usage(const char *progname)
|
|||
" -p port remote port\n"
|
||||
" -c port directly connect to port bypassing ssh\n"
|
||||
"\n", progname);
|
||||
fuse_main(2, (char **) fusehelp, &sshfs_oper);
|
||||
fuse_main(2, (char **) fusehelp, NULL);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
|
@ -1278,5 +1167,5 @@ int main(int argc, char *argv[])
|
|||
newargv[newargc++] = g_strdup_printf("-ofsname=sshfs#%s", fsname);
|
||||
g_free(fsname);
|
||||
newargv[newargc] = NULL;
|
||||
return fuse_main(newargc, newargv, &sshfs_oper);
|
||||
return fuse_main(newargc, newargv, cache_init(&sshfs_oper));
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue