Skip to content

Commit

Permalink
Add experimental rename support
Browse files Browse the repository at this point in the history
  • Loading branch information
bfleischer committed May 3, 2018
1 parent 5abbc87 commit f95e939
Show file tree
Hide file tree
Showing 9 changed files with 161 additions and 4 deletions.
7 changes: 5 additions & 2 deletions include/fuse.h
Expand Up @@ -614,8 +614,9 @@ struct fuse_operations {
void *, void *);
int (*reserved01)(void *, void *, void *, void *, void *, void *,
void *, void *);
int (*reserved02)(void *, void *, void *, void *, void *, void *,
void *, void *);

/** Rename a file */
int (*renamex) (const char *, const char *, unsigned int);

int (*statfs_x) (const char *, struct statfs *);

Expand Down Expand Up @@ -887,6 +888,8 @@ int fuse_fs_fgetattr(struct fuse_fs *fs, const char *path, struct stat *buf,
int fuse_fs_rename(struct fuse_fs *fs, const char *oldpath,
const char *newpath);
#ifdef __APPLE__
int fuse_fs_renamex(struct fuse_fs *fs, const char *oldpath,
const char *newpath, unsigned int flags);
int fuse_fs_setvolname(struct fuse_fs *fs, const char *volname);
int fuse_fs_exchange(struct fuse_fs *fs, const char *oldpath,
const char *newpath, unsigned long flags);
Expand Down
4 changes: 4 additions & 0 deletions include/fuse_kernel.h
Expand Up @@ -437,6 +437,10 @@ struct fuse_mkdir_in {

struct fuse_rename_in {
__u64 newdir;
#ifdef __APPLE__
__u32 flags;
__u32 padding;
#endif
};

#ifdef __APPLE__
Expand Down
24 changes: 22 additions & 2 deletions include/fuse_lowlevel.h
Expand Up @@ -1055,8 +1055,28 @@ struct fuse_lowlevel_ops {
void *, void *, void *, void *, void *, void *);
void (*reserved02) (fuse_req_t req, fuse_ino_t ino,
void *, void *, void *, void *, void *, void *);
void (*reserved03) (fuse_req_t req, fuse_ino_t ino,
void *, void *, void *, void *, void *, void *);

/** Rename a file
*
* If the target exists it should be atomically replaced. If
* the target's inode's lookup count is non-zero, the file
* system is expected to postpone any removal of the inode
* until the lookup count reaches zero (see description of the
* forget function).
*
* Valid replies:
* fuse_reply_err
*
* @param req request handle
* @param parent inode number of the old parent directory
* @param name old name
* @param newparent inode number of the new parent directory
* @param newname new name
* @param flags flags, see renamex_np(2)
*/
void (*renamex) (fuse_req_t req, fuse_ino_t parent, const char *name,
fuse_ino_t newparent, const char *newname,
unsigned int flags);

void (*setvolname) (fuse_req_t req, const char *name);

Expand Down
57 changes: 57 additions & 0 deletions lib/fuse.c
Expand Up @@ -1722,6 +1722,21 @@ int fuse_fs_rename(struct fuse_fs *fs, const char *oldpath,

#ifdef __APPLE__

int fuse_fs_renamex(struct fuse_fs *fs, const char *oldpath,
const char *newpath, unsigned int flags)
{
fuse_get_context()->private_data = fs->user_data;
if (fs->op.renamex) {
if (fs->debug)
fprintf(stderr, "renamex %s %s flags: 0x%x\n", oldpath,
newpath, flags);

return fs->op.renamex(oldpath, newpath, flags);
} else {
return -ENOSYS;
}
}

int fuse_fs_setvolname(struct fuse_fs *fs, const char *volname)
{
fuse_get_context()->private_data = fs->user_data;
Expand Down Expand Up @@ -3449,6 +3464,47 @@ static void fuse_lib_rename(fuse_req_t req, fuse_ino_t olddir,

#ifdef __APPLE__

#define FUSE_RENAME_SWAP 0x00000002
#define FUSE_RENAME_EXCL 0x00000004

static void fuse_lib_renamex(fuse_req_t req, fuse_ino_t olddir,
const char *oldname, fuse_ino_t newdir,
const char *newname, unsigned int flags)
{
struct fuse *f = req_fuse_prepare(req);
char *oldpath;
char *newpath;
struct node *wnode1;
struct node *wnode2;
int err;

err = get_path2(f, olddir, oldname, newdir, newname,
&oldpath, &newpath, &wnode1, &wnode2);
if (!err) {
bool rename_swap = flags & FUSE_RENAME_SWAP == FUSE_RENAME_SWAP;
bool rename_excl = flags & FUSE_RENAME_EXCL == FUSE_RENAME_EXCL;
struct fuse_intr_data d;
err = 0;
fuse_prepare_interrupt(f, req, &d);
if (rename_excl && wnode2) {
err = EEXIST;
}
if (!err && !rename_swap && !f->conf.hard_remove
&& is_open(f, newdir, newname)) {
err = hide_node(f, newpath, newdir, newname);
}
if (!err) {
err = fuse_fs_renamex(f->fs, oldpath, newpath, flags);
if (!err && !rename_swap)
err = rename_node(f, olddir, oldname, newdir,
newname, 0);
}
fuse_finish_interrupt(f, req, &d);
free_path2(f, olddir, newdir, wnode1, wnode2, oldpath, newpath);
}
reply_err(req, err);
}

static int exchange_node(struct fuse *f, fuse_ino_t olddir, const char *oldname,
fuse_ino_t newdir, const char *newname,
unsigned long options)
Expand Down Expand Up @@ -4768,6 +4824,7 @@ static struct fuse_lowlevel_ops fuse_path_ops = {
.poll = fuse_lib_poll,
.fallocate = fuse_lib_fallocate,
#ifdef __APPLE__
.renamex = fuse_lib_renamex,
.setvolname = fuse_lib_setvolname,
.exchange = fuse_lib_exchange,
.getxtimes = fuse_lib_getxtimes,
Expand Down
9 changes: 9 additions & 0 deletions lib/fuse_lowlevel.c
Expand Up @@ -1295,6 +1295,15 @@ static void do_rename(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
char *oldname = PARAM(arg);
char *newname = oldname + strlen(oldname) + 1;

#ifdef __APPLE__
if (arg->flags != 0) {
if (req->f->op.renamex)
req->f->op.renamex(req, nodeid, oldname, arg->newdir,
newname, arg->flags);
else
fuse_reply_err(req, ENOSYS);
} else
#endif /* __APPLE__ */
if (req->f->op.rename)
req->f->op.rename(req, nodeid, oldname, arg->newdir, newname);
else
Expand Down
22 changes: 22 additions & 0 deletions lib/modules/iconv.c
Expand Up @@ -332,6 +332,27 @@ static int iconv_rename(const char *from, const char *to)
return err;
}

#ifdef __APPLE__

static int iconv_renamex(const char *from, const char *to, unsigned int flags)
{
struct iconv *ic = iconv_get();
char *newfrom;
char *newto;
int err = iconv_convpath(ic, from, &newfrom, 0);
if (!err) {
err = iconv_convpath(ic, to, &newto, 0);
if (!err) {
err = fuse_fs_renamex(ic->next, newfrom, newto, flags);
free(newto);
}
free(newfrom);
}
return err;
}

#endif /* __APPLE__ */

static int iconv_link(const char *from, const char *to)
{
struct iconv *ic = iconv_get();
Expand Down Expand Up @@ -808,6 +829,7 @@ static const struct fuse_operations iconv_oper = {
.bmap = iconv_bmap,
.fallocate = iconv_fallocate,
#ifdef __APPLE__
.renamex = iconv_renamex,
.statfs_x = iconv_statfs_x,
.setvolname = iconv_setvolname,
.exchange = iconv_exchange,
Expand Down
22 changes: 22 additions & 0 deletions lib/modules/subdir.c
Expand Up @@ -317,6 +317,27 @@ static int subdir_rename(const char *from, const char *to)
return err;
}

#ifdef __APPLE__

static int subdir_renamex(const char *from, const char *to, unsigned int flags)
{
struct subdir *d = subdir_get();
char *newfrom;
char *newto;
int err = subdir_addpath(d, from, &newfrom);
if (!err) {
err = subdir_addpath(d, to, &newto);
if (!err) {
err = fuse_fs_renamex(d->next, newfrom, newto, flags);
free(newto);
}
free(newfrom);
}
return err;
}

#endif /* __APPLE__ */

static int subdir_link(const char *from, const char *to)
{
struct subdir *d = subdir_get();
Expand Down Expand Up @@ -788,6 +809,7 @@ static const struct fuse_operations subdir_oper = {
.bmap = subdir_bmap,
.fallocate = subdir_fallocate,
#ifdef __APPLE__
.renamex = subdir_renamex,
.statfs_x = subdir_statfs_x,
.setvolname = subdir_setvolname,
.exchange = subdir_exchange,
Expand Down
11 changes: 11 additions & 0 deletions lib/modules/threadid.c
Expand Up @@ -149,6 +149,16 @@ static int threadid_rename(const char *from, const char *to)
return res;
}

static int threadid_renamex(const char *from, const char *to,
unsigned int flags)
{
THREADID_PRE()
int res = fuse_fs_renamex(threadid_get()->next, from, to, flags);
THREADID_POST()

return res;
}

static int
threadid_link(const char *from, const char *to)
{
Expand Down Expand Up @@ -548,6 +558,7 @@ static struct fuse_operations threadid_oper = {
.rmdir = threadid_rmdir,
.symlink = threadid_symlink,
.rename = threadid_rename,
.renamex = threadid_renamex,
.link = threadid_link,
.chmod = threadid_chmod,
.chown = threadid_chown,
Expand Down
9 changes: 9 additions & 0 deletions lib/modules/volicon.c
Expand Up @@ -186,6 +186,14 @@ static int volicon_rename(const char *from, const char *to)
return fuse_fs_rename(volicon_get()->next, from, to);
}

static int volicon_renamex(const char *from, const char *to, unsigned int flags)
{
ERROR_IF_MAGIC_FILE(from, EACCES);
ERROR_IF_MAGIC_FILE(to, EACCES);

return fuse_fs_renamex(volicon_get()->next, from, to, flags);
}

static int
volicon_link(const char *from, const char *to)
{
Expand Down Expand Up @@ -690,6 +698,7 @@ static struct fuse_operations volicon_oper = {
.rmdir = volicon_rmdir,
.symlink = volicon_symlink,
.rename = volicon_rename,
.renamex = volicon_renamex,
.link = volicon_link,
.chmod = volicon_chmod,
.chown = volicon_chown,
Expand Down

0 comments on commit f95e939

Please sign in to comment.