dll: fuse: multiple improvements and fixes

- Symlinks: Now supports conventing a directory into a symlink reparse
point.

- Symlinks: The determination of whether a symlink is a file or
directory is now possible for file systems that do not support slashdot
(/.) queries.

- EA: Now allows the removal of non-existant EA without error (this is
allowed on Windows).
This commit is contained in:
Bill Zissimopoulos
2021-11-13 23:27:34 +00:00
parent ec3386c2b3
commit 0b94e8bc6a
8 changed files with 215 additions and 65 deletions

View File

@ -160,6 +160,29 @@ static NTSTATUS fsp_fuse_loop_start(struct fuse *f)
/* this should always fail with ENOSYS or EINVAL */
err = f->ops.readlink("/", buf, sizeof buf);
f->has_symlinks = -ENOSYS_(f->env) != err;
if (f->has_symlinks)
{
/*
* Determine if the file system supports "/." queries.
*
* Symlinks on Windows are differentiated as "file" symlinks or "directory" symlinks.
* When we need to make the distinction we can follow one of two techniques:
*
* - Slashdot technique: We issue a getattr(path + "/.") and check the stat result.
* In general this is not a getattr() query that FUSE file systems are expected
* to handle. For this reason we issue a getattr("/.") below to determine
* if the file system handles this kind of query against the root directory.
*
* - Resolve technique: If the file system cannot handle slashdot queries, we resolve
* the path using readlink on each path component, then issue getattr on the resolved
* path and check the stat result.
*/
struct fuse_stat_ex stbuf;
memset(&stbuf, 0, sizeof stbuf);
err = f->ops.getattr("/.", (void *)&stbuf);
f->has_slashdot = 0 == err && 0040000 == (stbuf.st_mode & 0170000);
}
}
if (0 != f->ops.listxattr && 0 != f->ops.getxattr &&
0 != f->ops.setxattr && 0 != f->ops.removexattr)