aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMiklos Szeredi <miklos@szeredi.hu>2005-10-28 12:12:57 +0000
committerMiklos Szeredi <miklos@szeredi.hu>2005-10-28 12:12:57 +0000
commit642d16587c952aa5997643be2530fb4a42fe8aff (patch)
tree5503dafe699afdb60fe13495e4168ff1a42c8ee7
parent8bba944723364f2181404f17d13f1c00d33fb18f (diff)
downloadsshfs-642d16587c952aa5997643be2530fb4a42fe8aff.tar
sshfs-642d16587c952aa5997643be2530fb4a42fe8aff.tar.gz
sshfs-642d16587c952aa5997643be2530fb4a42fe8aff.tar.bz2
sshfs-642d16587c952aa5997643be2530fb4a42fe8aff.zip
fix
-rw-r--r--ChangeLog7
-rw-r--r--cache.c63
-rw-r--r--sshfs.c63
3 files changed, 125 insertions, 8 deletions
diff --git a/ChangeLog b/ChangeLog
index cabc129..d4e52b3 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2005-10-28 Miklos Szeredi <miklos@szeredi.hu>
+
+ * Add atomic create+open and ftruncate operation. This should fix
+ issues with 'cp' and other programs failing with "Permission
+ denied". Needs FUSE version 2.5 and kernel version 2.6.15 (just a
+ guess, since neither of them is released yet).
+
2005-10-27 Miklos Szeredi <miklos@szeredi.hu>
* Add support for SSH protocol version 1. Bug reported by Miklos
diff --git a/cache.c b/cache.c
index 733a451..40ad0e3 100644
--- a/cache.c
+++ b/cache.c
@@ -192,26 +192,31 @@ static void cache_add_link(const char *path, const char *link, size_t size)
pthread_mutex_unlock(&cache_lock);
}
-static int cache_getattr(const char *path, struct stat *stbuf)
+static int cache_get_attr(const char *path, struct stat *stbuf)
{
struct node *node;
- int err;
-
+ int err = -EAGAIN;
pthread_mutex_lock(&cache_lock);
node = cache_lookup(path);
if (node != NULL) {
time_t now = time(NULL);
if (node->stat_valid - now >= 0) {
*stbuf = node->stat;
- pthread_mutex_unlock(&cache_lock);
- return 0;
+ err = 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_getattr(const char *path, struct stat *stbuf)
+{
+ int err = cache_get_attr(path, stbuf);
+ if (err) {
+ err = next_oper->oper.getattr(path, stbuf);
+ if (!err)
+ cache_add_attr(path, stbuf);
+ }
return err;
}
@@ -403,6 +408,38 @@ static int cache_write(const char *path, const char *buf, size_t size,
return res;
}
+#if FUSE_VERSION >= 25
+static int cache_create(const char *path, mode_t mode,
+ struct fuse_file_info *fi)
+{
+ int err = next_oper->oper.create(path, mode, fi);
+ if (!err)
+ cache_invalidate_dir(path);
+ return err;
+}
+
+static int cache_ftruncate(const char *path, off_t size,
+ struct fuse_file_info *fi)
+{
+ int err = next_oper->oper.ftruncate(path, size, fi);
+ if (!err)
+ cache_invalidate(path);
+ return err;
+}
+
+static int cache_fgetattr(const char *path, struct stat *stbuf,
+ struct fuse_file_info *fi)
+{
+ int err = cache_get_attr(path, stbuf);
+ if (err) {
+ err = next_oper->oper.fgetattr(path, stbuf, fi);
+ if (!err)
+ cache_add_attr(path, stbuf);
+ }
+ return err;
+}
+#endif
+
static void cache_unity_fill(struct fuse_cache_operations *oper,
struct fuse_operations *cache_oper)
{
@@ -434,6 +471,11 @@ static void cache_unity_fill(struct fuse_cache_operations *oper,
cache_oper->getxattr = oper->oper.getxattr;
cache_oper->listxattr = oper->oper.listxattr;
cache_oper->removexattr = oper->oper.removexattr;
+#if FUSE_VERSION >= 25
+ cache_oper->create = oper->oper.create;
+ cache_oper->ftruncate = oper->oper.ftruncate;
+ cache_oper->fgetattr = oper->oper.fgetattr;
+#endif
}
struct fuse_operations *cache_init(struct fuse_cache_operations *oper)
@@ -458,6 +500,11 @@ struct fuse_operations *cache_init(struct fuse_cache_operations *oper)
cache_oper.truncate = oper->oper.truncate ? cache_truncate : NULL;
cache_oper.utime = oper->oper.utime ? cache_utime : NULL;
cache_oper.write = oper->oper.write ? cache_write : NULL;
+#if FUSE_VERSION >= 25
+ cache_oper.create = oper->oper.create ? cache_create : NULL;
+ cache_oper.ftruncate = oper->oper.ftruncate ? cache_ftruncate : NULL;
+ cache_oper.fgetattr = oper->oper.fgetattr ? cache_fgetattr : NULL;
+#endif
pthread_mutex_init(&cache_lock, NULL);
cache = g_hash_table_new_full(g_str_hash, g_str_equal, g_free,
free_node);
diff --git a/sshfs.c b/sshfs.c
index 20540e7..c512f76 100644
--- a/sshfs.c
+++ b/sshfs.c
@@ -1434,6 +1434,9 @@ static int sshfs_open_common(const char *path, mode_t mode,
if (fi->flags & O_EXCL)
pflags |= SSH_FXF_EXCL;
+ if (fi->flags & O_TRUNC)
+ pflags |= SSH_FXF_TRUNC;
+
sf = g_new0(struct sshfs_file, 1);
list_init(&sf->write_reqs);
pthread_cond_init(&sf->write_finished, NULL);
@@ -1778,6 +1781,61 @@ static int sshfs_statfs(const char *path, struct statfs *buf)
return 0;
}
+#if FUSE_VERSION >= 25
+static int sshfs_create(const char *path, mode_t mode,
+ struct fuse_file_info *fi)
+{
+ return sshfs_open_common(path, mode, fi);
+}
+
+static int sshfs_ftruncate(const char *path, off_t size,
+ struct fuse_file_info *fi)
+{
+ int err;
+ struct buffer buf;
+ struct sshfs_file *sf = (struct sshfs_file *) fi->fh;
+
+ (void) path;
+
+ if (!sshfs_file_is_conn(sf))
+ return -EIO;
+
+ buf_init(&buf, 0);
+ buf_add_buf(&buf, &sf->handle);
+ buf_add_uint32(&buf, SSH_FILEXFER_ATTR_SIZE);
+ buf_add_uint64(&buf, size);
+ err = sftp_request(SSH_FXP_FSETSTAT, &buf, SSH_FXP_STATUS, NULL);
+ buf_free(&buf);
+
+ return err;
+}
+
+static int sshfs_fgetattr(const char *path, struct stat *stbuf,
+ struct fuse_file_info *fi)
+{
+ int err;
+ struct buffer buf;
+ struct buffer outbuf;
+ struct sshfs_file *sf = (struct sshfs_file *) fi->fh;
+
+ (void) path;
+
+ if (!sshfs_file_is_conn(sf))
+ return -EIO;
+
+ buf_init(&buf, 0);
+ buf_add_buf(&buf, &sf->handle);
+ err = sftp_request(SSH_FXP_FSTAT, &buf, SSH_FXP_ATTRS, &outbuf);
+ if (!err) {
+ if (buf_get_attrs(&outbuf, stbuf, NULL) == -1)
+ err = -EPROTO;
+ buf_free(&outbuf);
+ }
+ buf_free(&buf);
+ return err;
+}
+#endif
+
static int processing_init(void)
{
pthread_mutex_init(&lock, NULL);
@@ -1813,6 +1871,11 @@ static struct fuse_cache_operations sshfs_oper = {
.read = sshfs_read,
.write = sshfs_write,
.statfs = sshfs_statfs,
+#if FUSE_VERSION >= 25
+ .create = sshfs_create,
+ .ftruncate = sshfs_ftruncate,
+ .fgetattr = sshfs_fgetattr,
+#endif
},
.cache_getdir = sshfs_getdir,
};