First version

This commit is contained in:
alhimik45
2018-01-05 01:24:49 +07:00
commit 86ebf4962a
19 changed files with 6695 additions and 0 deletions

270
example/HelloFS/HelloFS.cs Normal file
View File

@@ -0,0 +1,270 @@
//
// HelloFS.cs
//
// Authors:
// Jonathan Pryor (jonpryor@vt.edu)
//
// (C) 2006 Jonathan Pryor
//
// Mono.Fuse.NETStandard example program
//
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text;
using Mono.Unix.Native;
namespace Mono.Fuse.NETStandard.Samples {
internal class HelloFs : FileSystem {
static readonly byte[] hello_str = Encoding.UTF8.GetBytes ("Hello World!\n");
const string hello_path = "/hello";
const string data_path = "/data";
const string data_im_path = "/data.im";
const int data_size = 100000000;
byte[] data_im_str;
bool have_data_im = false;
object data_im_str_lock = new object ();
Dictionary<string, byte[]> hello_attrs = new Dictionary<string, byte[]>();
public HelloFs ()
{
Trace.Listeners.Add(new TextWriterTraceListener(Console.Out));
Trace.WriteLine ("(HelloFS creating)");
hello_attrs ["foo"] = Encoding.UTF8.GetBytes ("bar");
}
protected override Errno OnGetPathStatus (string path, out Stat stbuf)
{
Trace.WriteLine ("(OnGetPathStatus {0})", path);
stbuf = new Stat ();
switch (path) {
case "/":
stbuf.st_mode = FilePermissions.S_IFDIR |
NativeConvert.FromOctalPermissionString ("0755");
stbuf.st_nlink = 2;
return 0;
case hello_path:
case data_path:
case data_im_path:
stbuf.st_mode = FilePermissions.S_IFREG |
NativeConvert.FromOctalPermissionString ("0444");
stbuf.st_nlink = 1;
int size = 0;
switch (path) {
case hello_path: size = hello_str.Length; break;
case data_path:
case data_im_path: size = data_size; break;
}
stbuf.st_size = size;
return 0;
default:
return Errno.ENOENT;
}
}
protected override Errno OnReadDirectory (string path, OpenedPathInfo fi,
out IEnumerable<DirectoryEntry> paths)
{
Trace.WriteLine ("(OnReadDirectory {0})", path);
paths = null;
if (path != "/")
return Errno.ENOENT;
paths = GetEntries ();
return 0;
}
private IEnumerable<DirectoryEntry> GetEntries ()
{
yield return new DirectoryEntry (".");
yield return new DirectoryEntry ("..");
yield return new DirectoryEntry ("hello");
yield return new DirectoryEntry ("data");
if (have_data_im)
yield return new DirectoryEntry ("data.im");
}
protected override Errno OnOpenHandle (string path, OpenedPathInfo fi)
{
Trace.WriteLine (string.Format ("(OnOpen {0} Flags={1})", path, fi.OpenFlags));
if (path != hello_path && path != data_path && path != data_im_path)
return Errno.ENOENT;
if (path == data_im_path && !have_data_im)
return Errno.ENOENT;
if (fi.OpenAccess != OpenFlags.O_RDONLY)
return Errno.EACCES;
return 0;
}
protected override Errno OnReadHandle (string path, OpenedPathInfo fi, byte[] buf, long offset, out int bytesWritten)
{
Trace.WriteLine ("(OnRead {0})", path);
bytesWritten = 0;
int size = buf.Length;
if (path == data_im_path)
FillData ();
if (path == hello_path || path == data_im_path) {
byte[] source = path == hello_path ? hello_str : data_im_str;
if (offset < (long) source.Length) {
if (offset + (long) size > (long) source.Length)
size = (int) ((long) source.Length - offset);
Buffer.BlockCopy (source, (int) offset, buf, 0, size);
}
else
size = 0;
}
else if (path == data_path) {
int max = System.Math.Min ((int) data_size, (int) (offset + buf.Length));
for (int i = 0, j = (int) offset; j < max; ++i, ++j) {
if ((j % 27) == 0)
buf [i] = (byte) '\n';
else
buf [i] = (byte) ((j % 26) + 'a');
}
}
else
return Errno.ENOENT;
bytesWritten = size;
return 0;
}
protected override Errno OnGetPathExtendedAttribute (string path, string name, byte[] value, out int bytesWritten)
{
Trace.WriteLine ("(OnGetPathExtendedAttribute {0})", path);
bytesWritten = 0;
if (path != hello_path) {
return 0;
}
byte[] _value;
lock (hello_attrs) {
if (!hello_attrs.ContainsKey (name))
return 0;
_value = hello_attrs [name];
}
if (value.Length < _value.Length) {
return Errno.ERANGE;
}
Array.Copy (_value, value, _value.Length);
bytesWritten = _value.Length;
return 0;
}
protected override Errno OnSetPathExtendedAttribute (string path, string name, byte[] value, XattrFlags flags)
{
Trace.WriteLine ("(OnSetPathExtendedAttribute {0})", path);
if (path != hello_path) {
return Errno.ENOSPC;
}
lock (hello_attrs) {
hello_attrs [name] = value;
}
return 0;
}
protected override Errno OnRemovePathExtendedAttribute (string path, string name)
{
Trace.WriteLine ("(OnRemovePathExtendedAttribute {0})", path);
if (path != hello_path)
return Errno.ENODATA;
lock (hello_attrs) {
if (!hello_attrs.ContainsKey (name))
return Errno.ENODATA;
hello_attrs.Remove (name);
}
return 0;
}
protected override Errno OnListPathExtendedAttributes (string path, out string[] names)
{
Trace.WriteLine ("(OnListPathExtendedAttributes {0})", path);
if (path != hello_path) {
names = new string[]{};
return 0;
}
List<string> _names = new List<string> ();
lock (hello_attrs) {
_names.AddRange (hello_attrs.Keys);
}
names = _names.ToArray ();
return 0;
}
private bool ParseArguments (string[] args)
{
for (int i = 0; i < args.Length; ++i) {
switch (args [i]) {
case "--data.im-in-memory":
have_data_im = true;
break;
case "-h":
case "--help":
Console.Error.WriteLine ("usage: hellofs [options] mountpoint");
FileSystem.ShowFuseHelp ("hellofs");
Console.Error.WriteLine ("hellofs options:");
Console.Error.WriteLine (" --data.im-in-memory Add data.im file");
return false;
default:
base.MountPoint = args [i];
break;
}
}
return true;
}
private void FillData ()
{
lock (data_im_str_lock) {
if (data_im_str != null)
return;
data_im_str = new byte [data_size];
for (int i = 0; i < data_im_str.Length; ++i) {
if ((i % 27) == 0)
data_im_str [i] = (byte) '\n';
else
data_im_str [i] = (byte) ((i % 26) + 'a');
}
}
}
public static void Main (string[] args)
{
using (HelloFs fs = new HelloFs ()) {
string[] unhandled = fs.ParseFuseArguments (args);
foreach (string key in fs.FuseOptions.Keys) {
Console.WriteLine ("Option: {0}={1}", key, fs.FuseOptions [key]);
}
if (!fs.ParseArguments (unhandled))
return;
// fs.MountAt ("path" /* , args? */);
fs.Start ();
}
}
}
}

View File

@@ -0,0 +1,13 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<RootNamespace>Mono.Fuse.NETStandard.Samples</RootNamespace>
<TargetFramework>netcoreapp2.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\Mono.Fuse.NETStandard\Mono.Fuse.NETStandard.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Mono.Posix.NETStandard" Version="1.0.0-beta3" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,421 @@
//
// RedirectFS-FH.cs: Port of
// http://fuse.cvs.sourceforge.net/fuse/fuse/example/fusexmp_fh.c?view=log
//
// Authors:
// Jonathan Pryor (jonpryor@vt.edu)
//
// (C) 2006 Jonathan Pryor
//
// Mono.Fuse.NETStandard example program
//
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Text;
using Mono.Fuse.NETStandard;
using Mono.Unix.Native;
namespace Mono.Fuse.NETStandard.Samples {
class RedirectFHFS : FileSystem {
private string basedir;
public RedirectFHFS ()
{
}
protected override Errno OnGetPathStatus (string path, out Stat buf)
{
int r = Syscall.lstat (basedir+path, out buf);
if (r == -1)
return Stdlib.GetLastError ();
return 0;
}
protected override Errno OnGetHandleStatus (string path, OpenedPathInfo info, out Stat buf)
{
int r = Syscall.fstat ((int) info.Handle, out buf);
if (r == -1)
return Stdlib.GetLastError ();
return 0;
}
protected override Errno OnAccessPath (string path, AccessModes mask)
{
int r = Syscall.access (basedir+path, mask);
if (r == -1)
return Stdlib.GetLastError ();
return 0;
}
protected override Errno OnReadSymbolicLink (string path, out string target)
{
target = null;
StringBuilder buf = new StringBuilder (256);
do {
int r = Syscall.readlink (basedir+path, buf);
if (r < 0) {
return Stdlib.GetLastError ();
}
else if (r == buf.Capacity) {
buf.Capacity *= 2;
}
else {
target = buf.ToString (0, r);
return 0;
}
} while (true);
}
protected override Errno OnOpenDirectory (string path, OpenedPathInfo info)
{
IntPtr dp = Syscall.opendir (basedir+path);
if (dp == IntPtr.Zero)
return Stdlib.GetLastError ();
info.Handle = dp;
return 0;
}
protected override Errno OnReadDirectory (string path, OpenedPathInfo fi,
out IEnumerable<DirectoryEntry> paths)
{
IntPtr dp = (IntPtr) fi.Handle;
paths = ReadDirectory (dp);
return 0;
}
private IEnumerable<DirectoryEntry> ReadDirectory (IntPtr dp)
{
Dirent de;
while ((de = Syscall.readdir (dp)) != null) {
DirectoryEntry e = new DirectoryEntry (de.d_name);
e.Stat.st_ino = de.d_ino;
e.Stat.st_mode = (FilePermissions) (de.d_type << 12);
yield return e;
}
}
protected override Errno OnReleaseDirectory (string path, OpenedPathInfo info)
{
IntPtr dp = (IntPtr) info.Handle;
Syscall.closedir (dp);
return 0;
}
protected override Errno OnCreateSpecialFile (string path, FilePermissions mode, ulong rdev)
{
int r;
// On Linux, this could just be `mknod(basedir+path, mode, rdev)' but
// this is more portable.
if ((mode & FilePermissions.S_IFMT) == FilePermissions.S_IFREG) {
r = Syscall.open (basedir+path, OpenFlags.O_CREAT | OpenFlags.O_EXCL |
OpenFlags.O_WRONLY, mode);
if (r >= 0)
r = Syscall.close (r);
}
else if ((mode & FilePermissions.S_IFMT) == FilePermissions.S_IFIFO) {
r = Syscall.mkfifo (basedir+path, mode);
}
else {
r = Syscall.mknod (basedir+path, mode, rdev);
}
if (r == -1)
return Stdlib.GetLastError ();
return 0;
}
protected override Errno OnCreateDirectory (string path, FilePermissions mode)
{
int r = Syscall.mkdir (basedir+path, mode);
if (r == -1)
return Stdlib.GetLastError ();
return 0;
}
protected override Errno OnRemoveFile (string path)
{
int r = Syscall.unlink (basedir+path);
if (r == -1)
return Stdlib.GetLastError ();
return 0;
}
protected override Errno OnRemoveDirectory (string path)
{
int r = Syscall.rmdir (basedir+path);
if (r == -1)
return Stdlib.GetLastError ();
return 0;
}
protected override Errno OnCreateSymbolicLink (string from, string to)
{
int r = Syscall.symlink (from, basedir+to);
if (r == -1)
return Stdlib.GetLastError ();
return 0;
}
protected override Errno OnRenamePath (string from, string to)
{
int r = Syscall.rename (basedir+from, basedir+to);
if (r == -1)
return Stdlib.GetLastError ();
return 0;
}
protected override Errno OnCreateHardLink (string from, string to)
{
int r = Syscall.link (basedir+from, basedir+to);
if (r == -1)
return Stdlib.GetLastError ();
return 0;
}
protected override Errno OnChangePathPermissions (string path, FilePermissions mode)
{
int r = Syscall.chmod (basedir+path, mode);
if (r == -1)
return Stdlib.GetLastError ();
return 0;
}
protected override Errno OnChangePathOwner (string path, long uid, long gid)
{
int r = Syscall.lchown (basedir+path, (uint) uid, (uint) gid);
if (r == -1)
return Stdlib.GetLastError ();
return 0;
}
protected override Errno OnTruncateFile (string path, long size)
{
int r = Syscall.truncate (basedir+path, size);
if (r == -1)
return Stdlib.GetLastError ();
return 0;
}
protected override Errno OnTruncateHandle (string path, OpenedPathInfo info, long size)
{
int r = Syscall.ftruncate ((int) info.Handle, size);
if (r == -1)
return Stdlib.GetLastError ();
return 0;
}
protected override Errno OnChangePathTimes (string path, ref Utimbuf buf)
{
int r = Syscall.utime (basedir+path, ref buf);
if (r == -1)
return Stdlib.GetLastError ();
return 0;
}
protected override Errno OnCreateHandle (string path, OpenedPathInfo info, FilePermissions mode)
{
int fd = Syscall.open (basedir+path, info.OpenFlags, mode);
if (fd == -1)
return Stdlib.GetLastError ();
info.Handle = (IntPtr) fd;
return 0;
}
protected override Errno OnOpenHandle (string path, OpenedPathInfo info)
{
int fd = Syscall.open (basedir+path, info.OpenFlags);
if (fd == -1)
return Stdlib.GetLastError ();
info.Handle = (IntPtr) fd;
return 0;
}
protected override unsafe Errno OnReadHandle (string path, OpenedPathInfo info, byte[] buf,
long offset, out int bytesRead)
{
int r;
fixed (byte *pb = buf) {
r = bytesRead = (int) Syscall.pread ((int) info.Handle,
pb, (ulong) buf.Length, offset);
}
if (r == -1)
return Stdlib.GetLastError ();
return 0;
}
protected override unsafe Errno OnWriteHandle (string path, OpenedPathInfo info,
byte[] buf, long offset, out int bytesWritten)
{
int r;
fixed (byte *pb = buf) {
r = bytesWritten = (int) Syscall.pwrite ((int) info.Handle,
pb, (ulong) buf.Length, offset);
}
if (r == -1)
return Stdlib.GetLastError ();
return 0;
}
protected override Errno OnGetFileSystemStatus (string path, out Statvfs stbuf)
{
int r = Syscall.statvfs (basedir+path, out stbuf);
if (r == -1)
return Stdlib.GetLastError ();
return 0;
}
protected override Errno OnFlushHandle (string path, OpenedPathInfo info)
{
/* This is called from every close on an open file, so call the
close on the underlying filesystem. But since flush may be
called multiple times for an open file, this must not really
close the file. This is important if used on a network
filesystem like NFS which flush the data/metadata on close() */
int r = Syscall.close (Syscall.dup ((int) info.Handle));
if (r == -1)
return Stdlib.GetLastError ();
return 0;
}
protected override Errno OnReleaseHandle (string path, OpenedPathInfo info)
{
int r = Syscall.close ((int) info.Handle);
if (r == -1)
return Stdlib.GetLastError ();
return 0;
}
protected override Errno OnSynchronizeHandle (string path, OpenedPathInfo info, bool onlyUserData)
{
int r;
if (onlyUserData)
r = Syscall.fdatasync ((int) info.Handle);
else
r = Syscall.fsync ((int) info.Handle);
if (r == -1)
return Stdlib.GetLastError ();
return 0;
}
protected override Errno OnSetPathExtendedAttribute (string path, string name, byte[] value, XattrFlags flags)
{
int r = Syscall.lsetxattr (basedir+path, name, value, (ulong) value.Length, flags);
if (r == -1)
return Stdlib.GetLastError ();
return 0;
}
protected override Errno OnGetPathExtendedAttribute (string path, string name, byte[] value, out int bytesWritten)
{
int r = bytesWritten = (int) Syscall.lgetxattr (basedir+path, name, value, (ulong) value.Length);
if (r == -1)
return Stdlib.GetLastError ();
return 0;
}
protected override Errno OnListPathExtendedAttributes (string path, out string[] names)
{
int r = (int) Syscall.llistxattr (basedir+path, out names);
if (r == -1)
return Stdlib.GetLastError ();
return 0;
}
protected override Errno OnRemovePathExtendedAttribute (string path, string name)
{
int r = Syscall.lremovexattr (basedir+path, name);
if (r == -1)
return Stdlib.GetLastError ();
return 0;
}
protected override Errno OnLockHandle (string file, OpenedPathInfo info, FcntlCommand cmd, ref Flock @lock)
{
int r = Syscall.fcntl ((int) info.Handle, cmd, ref @lock);
if (r == -1)
return Stdlib.GetLastError ();
return 0;
}
private bool ParseArguments (string[] args)
{
for (int i = 0; i < args.Length; ++i) {
switch (args [i]) {
case "-h":
case "--help":
ShowHelp ();
return false;
default:
if (base.MountPoint == null)
base.MountPoint = args [i];
else
basedir = args [i];
break;
}
}
if (base.MountPoint == null) {
return Error ("missing mountpoint");
}
if (basedir == null) {
return Error ("missing basedir");
}
return true;
}
private static void ShowHelp ()
{
Console.Error.WriteLine ("usage: redirectfs [options] mountpoint:");
FileSystem.ShowFuseHelp ("redirectfs-fh");
Console.Error.WriteLine ();
Console.Error.WriteLine ("redirectfs-fh options");
Console.Error.WriteLine (" basedir Directory to mirror");
}
private static bool Error (string message)
{
Console.Error.WriteLine ("redirectfs-fh: error: {0}", message);
return false;
}
public static void Main (string[] args)
{
using (RedirectFHFS fs = new RedirectFHFS ()) {
string[] unhandled = fs.ParseFuseArguments (args);
if (!fs.ParseArguments (unhandled))
return;
fs.Start ();
}
}
}
}

View File

@@ -0,0 +1,19 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<RootNamespace>Mono.Fuse.NETStandard.Samples</RootNamespace>
<TargetFramework>netcoreapp2.0</TargetFramework>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\Mono.Fuse.NETStandard\Mono.Fuse.NETStandard.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Mono.Posix.NETStandard" Version="1.0.0-beta3" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,368 @@
//
// RedirectFS.cs: Port of
// http://fuse.cvs.sourceforge.net/fuse/fuse/example/fusexmp.c?view=log
//
// Authors:
// Jonathan Pryor (jonpryor@vt.edu)
//
// (C) 2006 Jonathan Pryor
//
// Mono.Fuse.NETStandard example program
//
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Text;
using Mono.Fuse.NETStandard;
using Mono.Unix.Native;
namespace Mono.Fuse.NETStandard.Samples {
class RedirectFS : FileSystem {
private string basedir;
public RedirectFS ()
{
}
protected override Errno OnGetPathStatus (string path, out Stat buf)
{
int r = Syscall.lstat (basedir+path, out buf);
if (r == -1)
return Stdlib.GetLastError ();
return 0;
}
protected override Errno OnAccessPath (string path, AccessModes mask)
{
int r = Syscall.access (basedir+path, mask);
if (r == -1)
return Stdlib.GetLastError ();
return 0;
}
protected override Errno OnReadSymbolicLink (string path, out string target)
{
target = null;
StringBuilder buf = new StringBuilder (256);
do {
int r = Syscall.readlink (basedir+path, buf);
if (r < 0) {
return Stdlib.GetLastError ();
}
else if (r == buf.Capacity) {
buf.Capacity *= 2;
}
else {
target = buf.ToString (0, r);
return 0;
}
} while (true);
}
protected override Errno OnReadDirectory (string path, OpenedPathInfo fi,
out IEnumerable<DirectoryEntry> paths)
{
IntPtr dp = Syscall.opendir (basedir+path);
if (dp == IntPtr.Zero) {
paths = null;
return Stdlib.GetLastError ();
}
Dirent de;
List<DirectoryEntry> entries = new List<DirectoryEntry> ();
while ((de = Syscall.readdir (dp)) != null) {
DirectoryEntry e = new DirectoryEntry (de.d_name);
e.Stat.st_ino = de.d_ino;
e.Stat.st_mode = (FilePermissions) (de.d_type << 12);
entries.Add (e);
}
Syscall.closedir (dp);
paths = entries;
return 0;
}
protected override Errno OnCreateSpecialFile (string path, FilePermissions mode, ulong rdev)
{
int r;
// On Linux, this could just be `mknod(basedir+path, mode, rdev)' but this is
// more portable.
if ((mode & FilePermissions.S_IFMT) == FilePermissions.S_IFREG) {
r = Syscall.open (basedir+path, OpenFlags.O_CREAT | OpenFlags.O_EXCL |
OpenFlags.O_WRONLY, mode);
if (r >= 0)
r = Syscall.close (r);
}
else if ((mode & FilePermissions.S_IFMT) == FilePermissions.S_IFIFO) {
r = Syscall.mkfifo (basedir+path, mode);
}
else {
r = Syscall.mknod (basedir+path, mode, rdev);
}
if (r == -1)
return Stdlib.GetLastError ();
return 0;
}
protected override Errno OnCreateDirectory (string path, FilePermissions mode)
{
int r = Syscall.mkdir (basedir+path, mode);
if (r == -1)
return Stdlib.GetLastError ();
return 0;
}
protected override Errno OnRemoveFile (string path)
{
int r = Syscall.unlink (basedir+path);
if (r == -1)
return Stdlib.GetLastError ();
return 0;
}
protected override Errno OnRemoveDirectory (string path)
{
int r = Syscall.rmdir (basedir+path);
if (r == -1)
return Stdlib.GetLastError ();
return 0;
}
protected override Errno OnCreateSymbolicLink (string from, string to)
{
int r = Syscall.symlink (from, basedir+to);
if (r == -1)
return Stdlib.GetLastError ();
return 0;
}
protected override Errno OnRenamePath (string from, string to)
{
int r = Syscall.rename (basedir+from, basedir+to);
if (r == -1)
return Stdlib.GetLastError ();
return 0;
}
protected override Errno OnCreateHardLink (string from, string to)
{
int r = Syscall.link (basedir+from, basedir+to);
if (r == -1)
return Stdlib.GetLastError ();
return 0;
}
protected override Errno OnChangePathPermissions (string path, FilePermissions mode)
{
int r = Syscall.chmod (basedir+path, mode);
if (r == -1)
return Stdlib.GetLastError ();
return 0;
}
protected override Errno OnChangePathOwner (string path, long uid, long gid)
{
int r = Syscall.lchown (basedir+path, (uint) uid, (uint) gid);
if (r == -1)
return Stdlib.GetLastError ();
return 0;
}
protected override Errno OnTruncateFile (string path, long size)
{
int r = Syscall.truncate (basedir+path, size);
if (r == -1)
return Stdlib.GetLastError ();
return 0;
}
protected override Errno OnChangePathTimes (string path, ref Utimbuf buf)
{
int r = Syscall.utime (basedir+path, ref buf);
if (r == -1)
return Stdlib.GetLastError ();
return 0;
}
protected override Errno OnOpenHandle (string path, OpenedPathInfo info)
{
return ProcessFile (basedir+path, info.OpenFlags, delegate (int fd) {return 0;});
}
private delegate int FdCb (int fd);
private static Errno ProcessFile (string path, OpenFlags flags, FdCb cb)
{
int fd = Syscall.open (path, flags);
if (fd == -1)
return Stdlib.GetLastError ();
int r = cb (fd);
Errno res = 0;
if (r == -1)
res = Stdlib.GetLastError ();
Syscall.close (fd);
return res;
}
protected override unsafe Errno OnReadHandle (string path, OpenedPathInfo info, byte[] buf,
long offset, out int bytesRead)
{
int br = 0;
Errno e = ProcessFile (basedir+path, OpenFlags.O_RDONLY, delegate (int fd) {
fixed (byte *pb = buf) {
return br = (int) Syscall.pread (fd, pb, (ulong) buf.Length, offset);
}
});
bytesRead = br;
return e;
}
protected override unsafe Errno OnWriteHandle (string path, OpenedPathInfo info,
byte[] buf, long offset, out int bytesWritten)
{
int bw = 0;
Errno e = ProcessFile (basedir+path, OpenFlags.O_WRONLY, delegate (int fd) {
fixed (byte *pb = buf) {
return bw = (int) Syscall.pwrite (fd, pb, (ulong) buf.Length, offset);
}
});
bytesWritten = bw;
return e;
}
protected override Errno OnGetFileSystemStatus (string path, out Statvfs stbuf)
{
int r = Syscall.statvfs (basedir+path, out stbuf);
if (r == -1)
return Stdlib.GetLastError ();
return 0;
}
protected override Errno OnReleaseHandle (string path, OpenedPathInfo info)
{
return 0;
}
protected override Errno OnSynchronizeHandle (string path, OpenedPathInfo info, bool onlyUserData)
{
return 0;
}
protected override Errno OnSetPathExtendedAttribute (string path, string name, byte[] value, XattrFlags flags)
{
int r = Syscall.lsetxattr (basedir+path, name, value, (ulong) value.Length, flags);
if (r == -1)
return Stdlib.GetLastError ();
return 0;
}
protected override Errno OnGetPathExtendedAttribute (string path, string name, byte[] value, out int bytesWritten)
{
int r = bytesWritten = (int) Syscall.lgetxattr (basedir+path, name, value, (ulong) value.Length);
if (r == -1)
return Stdlib.GetLastError ();
return 0;
}
protected override Errno OnListPathExtendedAttributes (string path, out string[] names)
{
int r = (int) Syscall.llistxattr (basedir+path, out names);
if (r == -1)
return Stdlib.GetLastError ();
return 0;
}
protected override Errno OnRemovePathExtendedAttribute (string path, string name)
{
int r = Syscall.lremovexattr (basedir+path, name);
if (r == -1)
return Stdlib.GetLastError ();
return 0;
}
protected override Errno OnLockHandle (string file, OpenedPathInfo info, FcntlCommand cmd, ref Flock @lock)
{
Flock _lock = @lock;
Errno e = ProcessFile (basedir+file, info.OpenFlags, fd => Syscall.fcntl (fd, cmd, ref _lock));
@lock = _lock;
return e;
}
private bool ParseArguments (string[] args)
{
for (int i = 0; i < args.Length; ++i) {
switch (args [i]) {
case "-h":
case "--help":
ShowHelp ();
return false;
default:
if (base.MountPoint == null)
base.MountPoint = args [i];
else
basedir = args [i];
break;
}
}
if (base.MountPoint == null) {
return Error ("missing mountpoint");
}
if (basedir == null) {
return Error ("missing basedir");
}
return true;
}
private static void ShowHelp ()
{
Console.Error.WriteLine ("usage: redirectfs [options] mountpoint basedir:");
FileSystem.ShowFuseHelp ("redirectfs");
Console.Error.WriteLine ();
Console.Error.WriteLine ("redirectfs options:");
Console.Error.WriteLine (" basedir Directory to mirror");
}
private static bool Error (string message)
{
Console.Error.WriteLine ("redirectfs: error: {0}", message);
return false;
}
public static void Main (string[] args)
{
using (RedirectFS fs = new RedirectFS ()) {
string[] unhandled = fs.ParseFuseArguments (args);
if (!fs.ParseArguments (unhandled))
return;
fs.Start ();
}
}
}
}

View File

@@ -0,0 +1,19 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<RootNamespace>Mono.Fuse.NETStandard.Samples</RootNamespace>
<TargetFramework>netcoreapp2.0</TargetFramework>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\Mono.Fuse.NETStandard\Mono.Fuse.NETStandard.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Mono.Posix.NETStandard" Version="1.0.0-beta3" />
</ItemGroup>
</Project>