+2004-02-20 Miklos Szeredi <mszeredi@inf.bme.hu>
+
+ * more kernel interface changes:
+
+ * added nanosecond precision to file times
+
2004-02-19 Miklos Szeredi <mszeredi@inf.bme.hu>
* statfs library API changed to match other methods. Since this
unsigned int gid;
unsigned int rdev;
unsigned long long size;
- unsigned long _dummy;
unsigned long blocks;
unsigned long atime;
+ unsigned long atimensec;
unsigned long mtime;
+ unsigned long mtimensec;
unsigned long ctime;
+ unsigned long ctimensec;
};
struct fuse_kstatfs {
#define FATTR_UID (1 << 1)
#define FATTR_GID (1 << 2)
#define FATTR_SIZE (1 << 3)
-#define FATTR_UTIME (1 << 4)
+#define FATTR_ATIME (1 << 4)
+#define FATTR_MTIME (1 << 5)
+#define FATTR_CTIME (1 << 6)
enum fuse_opcode {
FUSE_LOOKUP = 1,
inode->i_blocks = attr->blocks;
#ifdef KERNEL_2_6
inode->i_atime.tv_sec = attr->atime;
- inode->i_atime.tv_nsec = 0;
+ inode->i_atime.tv_nsec = attr->atimensec;
inode->i_mtime.tv_sec = attr->mtime;
- inode->i_mtime.tv_nsec = 0;
+ inode->i_mtime.tv_nsec = attr->mtimensec;
inode->i_ctime.tv_sec = attr->ctime;
- inode->i_ctime.tv_nsec = 0;
+ inode->i_ctime.tv_nsec = attr->ctimensec;
#else
inode->i_atime = attr->atime;
inode->i_mtime = attr->mtime;
return lookup_new_entry(dir, entry, &outarg, out.h.unique, S_IFLNK);
}
-static int fuse_remove(struct inode *dir, struct dentry *entry,
- enum fuse_opcode op)
+static int fuse_unlink(struct inode *dir, struct dentry *entry)
{
struct fuse_conn *fc = INO_FC(dir);
struct fuse_in in = FUSE_IN_INIT;
struct fuse_out out = FUSE_OUT_INIT;
- in.h.opcode = op;
+ in.h.opcode = FUSE_UNLINK;
in.h.ino = dir->i_ino;
in.numargs = 1;
in.args[0].size = entry->d_name.len + 1;
in.args[0].value = entry->d_name.name;
request_send(fc, &in, &out);
- return out.h.error;
-}
-
-static int fuse_unlink(struct inode *dir, struct dentry *entry)
-{
- int err = fuse_remove(dir, entry, FUSE_UNLINK);
- if(!err) {
- /* FIXME: the new i_nlink could be returned by the
- unlink operation */
- err = fuse_do_getattr(entry->d_inode);
- if(err == -ENOENT)
- entry->d_inode->i_nlink = 0;
- return 0;
+ if(!out.h.error) {
+ /* Set nlink to zero so the inode can be cleared, if
+ the inode does have more links this will be
+ discovered at the next lookup/getattr */
+ /* FIXME: mark inode "not uptodate" */
+ entry->d_inode->i_nlink = 0;
}
- return err;
+
+ return out.h.error;
}
static int fuse_rmdir(struct inode *dir, struct dentry *entry)
{
- int err = fuse_remove(dir, entry, FUSE_RMDIR);
- if(!err)
+ struct fuse_conn *fc = INO_FC(dir);
+ struct fuse_in in = FUSE_IN_INIT;
+ struct fuse_out out = FUSE_OUT_INIT;
+
+ in.h.opcode = FUSE_RMDIR;
+ in.h.ino = dir->i_ino;
+ in.numargs = 1;
+ in.args[0].size = entry->d_name.len + 1;
+ in.args[0].value = entry->d_name.name;
+ request_send(fc, &in, &out);
+ if(!out.h.error)
entry->d_inode->i_nlink = 0;
- return err;
+
+ return out.h.error;
}
static int fuse_rename(struct inode *olddir, struct dentry *oldent,
fvalid |= FATTR_SIZE, fattr->size = iattr->ia_size;
/* You can only _set_ these together (they may change by themselves) */
if((ivalid & (ATTR_ATIME | ATTR_MTIME)) == (ATTR_ATIME | ATTR_MTIME)) {
- fvalid |= FATTR_UTIME;
+ fvalid |= FATTR_ATIME | FATTR_MTIME;
#ifdef KERNEL_2_6
fattr->atime = iattr->ia_atime.tv_sec;
fattr->mtime = iattr->ia_mtime.tv_sec;
static void convert_stat(struct stat *stbuf, struct fuse_attr *attr)
{
- attr->mode = stbuf->st_mode;
- attr->nlink = stbuf->st_nlink;
- attr->uid = stbuf->st_uid;
- attr->gid = stbuf->st_gid;
- attr->rdev = stbuf->st_rdev;
- attr->size = stbuf->st_size;
- attr->blocks = stbuf->st_blocks;
- attr->atime = stbuf->st_atime;
- attr->mtime = stbuf->st_mtime;
- attr->ctime = stbuf->st_ctime;
- attr->_dummy = 4096;
+ attr->mode = stbuf->st_mode;
+ attr->nlink = stbuf->st_nlink;
+ attr->uid = stbuf->st_uid;
+ attr->gid = stbuf->st_gid;
+ attr->rdev = stbuf->st_rdev;
+ attr->size = stbuf->st_size;
+ attr->blocks = stbuf->st_blocks;
+ attr->atime = stbuf->st_atime;
+ attr->atimensec = stbuf->st_atim.tv_nsec;
+ attr->mtime = stbuf->st_mtime;
+ attr->mtimensec = stbuf->st_mtim.tv_nsec;
+ attr->ctime = stbuf->st_ctime;
+ attr->ctimensec = stbuf->st_ctim.tv_nsec;
}
static int fill_dir(struct fuse_dirhandle *dh, char *name, int type)
res = do_chown(f, path, attr, valid);
if(!res && (valid & FATTR_SIZE))
res = do_truncate(f, path, attr);
- if(!res && (valid & FATTR_UTIME))
+ if(!res && (valid & (FATTR_ATIME | FATTR_MTIME)) ==
+ (FATTR_ATIME | FATTR_MTIME))
res = do_utime(f, path, attr);
if(!res) {
struct stat buf;
send_reply(f, in, res, &outarg, sizeof(outarg));
}
-static void do_remove(struct fuse *f, struct fuse_in_header *in, char *name)
+static void do_unlink(struct fuse *f, struct fuse_in_header *in, char *name)
{
int res;
char *path;
path = get_path_name(f, in->ino, name);
if(path != NULL) {
res = -ENOSYS;
- if(in->opcode == FUSE_UNLINK) {
- if(f->op.unlink)
- res = f->op.unlink(path);
+ if(f->op.unlink) {
+ res = f->op.unlink(path);
+ if(res == 0)
+ remove_node(f, in->ino, name);
}
- else {
- if(f->op.rmdir)
- res = f->op.rmdir(path);
+ free(path);
+ }
+ send_reply(f, in, res, NULL, 0);
+}
+
+static void do_rmdir(struct fuse *f, struct fuse_in_header *in, char *name)
+{
+ int res;
+ char *path;
+
+ res = -ENOENT;
+ path = get_path_name(f, in->ino, name);
+ if(path != NULL) {
+ res = -ENOSYS;
+ if(f->op.rmdir) {
+ res = f->op.rmdir(path);
+ if(res == 0)
+ remove_node(f, in->ino, name);
}
free(path);
}
- if(res == 0)
- remove_node(f, in->ino, name);
send_reply(f, in, res, NULL, 0);
}
break;
case FUSE_UNLINK:
+ do_unlink(f, in, (char *) inarg);
+ break;
+
case FUSE_RMDIR:
- do_remove(f, in, (char *) inarg);
+ do_rmdir(f, in, (char *) inarg);
break;
case FUSE_SYMLINK: