275 lines
7.5 KiB
C#
275 lines
7.5 KiB
C#
//
|
|
// 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.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 != null)
|
|
{
|
|
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 ();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|