sonnyx / nfs-client Goto Github PK
View Code? Open in Web Editor NEWThis project forked from nekoni/nekodrive
NFS Client library for C#/.NET
License: GNU Lesser General Public License v3.0
This project forked from nekoni/nekodrive
NFS Client library for C#/.NET
License: GNU Lesser General Public License v3.0
On Windows, the result of CorrectPath
when called during an NfsClient.Write
invocation works correctly, but fails on Ubuntu 22.04.
I added a simple Console.WriteLine
on the output of CorrectPath
and tested on both Windows and Ubuntu.
Using the example in issue #2
Windows:
Initializing client
Mounting device
Listing shares
| /share
Listing root directory
Writing file: .\root.txt
Destination filename: .\root.txt <-----
Creating directory .\dir1
Creating directory .\dir1\dir2
Creating directory .\dir1\dir2\dir3
Writing file: .\dir1\1.txt
Destination filename: .\dir1\1.txt <-----
Writing file: .\dir1\dir2\2.txt
Destination filename: .\dir1\dir2\2.txt <-----
Writing file: .\dir1\dir2\dir3\3.txt
Destination filename: .\dir1\dir2\dir3\3.txt <-----
Ubuntu:
Initializing client
Mounting device
Listing shares
| /share
Listing root directory
Writing file: root.txt
Destination filename: .\root.txt <-----
System.NullReferenceException: Object reference not set to an instance of an object.
at NFSLibrary.Protocols.V3.NFSv3.Write(String FileFullName, Int64 Offset, Int32 Count, Byte[] Buffer) in /home/joel/Code/NFS2/NFSLibrary/Protocols/V3/NFSv3.cs:line 527
at NFSLibrary.NfsClient.Write(String destinationFileFullName, Int64 inputOffset, Stream inputStream) in /home/joel/Code/NFS2/NFSLibrary/NFS.cs:line 576
at NFSLibrary.NfsClient.Write(String destinationFileFullName, Stream inputStream) in /home/joel/Code/NFS2/NFSLibrary/NFS.cs:line 546
at Test.Nfs.Program.WriteFile(NfsClient client, String file, String contents) in /home/joel/Code/NFS2/Test.Nfs/Program.cs:line 353
at Test.Nfs.Program.Main(String[] args) in /home/joel/Code/NFS2/Test.Nfs/Program.cs:line 78
Hi @SonnyX thanks again for putting together this wonderful library. It took some digging, but I figured out how to use this library to be able to enumerate and deal with files in nested folders. The documentation and examples weren't super clear, so I'm pasting them here in hopes that this saves someone else some headache in the future, and, that you'll consider updating the documentation to include them.
For context, I set up an Ubuntu 22.04 machine and created a share called /share
with the following file and folder structure:
/
|-- root.txt
|-- dir1
|-- 1.txt
|-- dir2
|-- 2.txt
|-- dir3
|-- 3.txt
I then modified /etc/exports
to include it:
/share/ *(rw,sync,subtree_check,anonuid=0,anongid=0)
And exported it using exportfs -a
.
Then, I created a new console project and referenced your library. The code below connects, mounts, enumerates each directory, reads each file, all in succession. The missing link for me was client.Combine
and figuring out which slash to use (\
or /
) and how to handle nested folders.
And voila, it worked.
namespace Test.Nfs
{
using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Text;
using NFSLibrary;
using NFSLibrary.Protocols.Commons;
public static class Program
{
private static string _Hostname = "192.168.226.132";
private static NfsClient.NfsVersion _Version = NfsClient.NfsVersion.V3;
private static string _Share = "/share";
/*
/
|-- root.txt
|-- dir1
|-- 1.txt
|-- dir2
|-- 2.txt
|-- dir3
|-- 3.txt
*/
public static void Main(string[] args)
{
NfsClient client = null;
Stream stream = null;
string file = "";
string folder = "";
try
{
#region Initialize-and-Mount
Console.WriteLine("");
Console.WriteLine("Initializing client");
client = new NfsClient(_Version);
client.Connect(IPAddress.Parse(_Hostname));
Console.WriteLine("Mounting device");
client.MountDevice(_Share);
#endregion
#region List-Shares
Console.WriteLine("");
Console.WriteLine("Listing shares");
List<string> exports = client.GetExportedDevices();
if (exports != null && exports.Count > 0)
foreach (var share in exports)
Console.WriteLine("| " + share);
#endregion
#region Enumerate-Root
Console.WriteLine("");
Console.WriteLine("Listing root directory");
foreach (string item in client.GetItemList("."))
{
NFSAttributes attrib = client.GetItemAttributes(item);
if (attrib == null) continue;
bool isDirectory = client.IsDirectory(item);
Console.WriteLine("| " + item + " " + (isDirectory ? "(dir)" : null) + " " + attrib.Size + " bytes");
}
#endregion
#region Read /root.txt
Console.WriteLine("");
file = client.Combine("root.txt", null);
Console.WriteLine("Reading file root.txt: " + file);
stream = new MemoryStream();
client.Read("root.txt", ref stream);
if (stream != null)
{
stream.Seek(0, SeekOrigin.Begin);
int read = 0;
byte[] buf = new byte[4096];
while (true)
{
read = stream.Read(buf, 0, buf.Length);
if (read > 0)
{
byte[] segment = new byte[read];
Buffer.BlockCopy(buf, 0, segment, 0, read);
Console.WriteLine(Encoding.UTF8.GetString(segment));
}
else
{
break;
}
}
}
#endregion
#region Enumerate /dir1
Console.WriteLine("");
folder = client.Combine("dir1", ".");
Console.WriteLine("Listing dir1 directory: " + folder);
foreach (string item in client.GetItemList(folder))
{
NFSAttributes attrib = client.GetItemAttributes(client.Combine(item, "dir1"));
if (attrib == null) continue;
bool isDirectory = client.IsDirectory(client.Combine(item, "dir1"));
Console.WriteLine("| " + item + " " + (isDirectory ? "(dir)" : null) + " " + attrib.Size + " bytes");
}
#endregion
#region Read /root.txt
Console.WriteLine("");
file = client.Combine("1.txt", "dir1");
Console.WriteLine("Reading file 1.txt: " + file);
stream = new MemoryStream();
client.Read(file, ref stream);
if (stream != null)
{
stream.Seek(0, SeekOrigin.Begin);
int read = 0;
byte[] buf = new byte[4096];
while (true)
{
read = stream.Read(buf, 0, buf.Length);
if (read > 0)
{
byte[] segment = new byte[read];
Buffer.BlockCopy(buf, 0, segment, 0, read);
Console.WriteLine(Encoding.UTF8.GetString(segment));
}
else
{
break;
}
}
}
#endregion
#region Enumerate /dir2
Console.WriteLine("");
folder = client.Combine("dir2", "dir1");
Console.WriteLine("Listing dir2 directory: " + folder);
foreach (string item in client.GetItemList(folder))
{
Console.WriteLine("Processing item " + item);
NFSAttributes attrib = client.GetItemAttributes(client.Combine(item, "dir1"));
if (attrib == null) continue;
bool isDirectory = client.IsDirectory(client.Combine(item, "dir1"));
Console.WriteLine("| " + item + " " + (isDirectory ? "(dir)" : null) + " " + attrib.Size + " bytes");
}
#endregion
#region Read /dir1/dir2/2.txt
Console.WriteLine("");
file = client.Combine("2.txt", "dir1\\dir2");
Console.WriteLine("Reading file 2.txt: " + file);
stream = new MemoryStream();
client.Read(file, ref stream);
if (stream != null)
{
stream.Seek(0, SeekOrigin.Begin);
int read = 0;
byte[] buf = new byte[4096];
while (true)
{
read = stream.Read(buf, 0, buf.Length);
if (read > 0)
{
byte[] segment = new byte[read];
Buffer.BlockCopy(buf, 0, segment, 0, read);
Console.WriteLine(Encoding.UTF8.GetString(segment));
}
else
{
break;
}
}
}
#endregion
#region Enumerate /dir3
Console.WriteLine("");
folder = client.Combine("dir3", "dir1\\dir2");
Console.WriteLine("Listing dir3 directory: " + folder);
foreach (string item in client.GetItemList(folder))
{
Console.WriteLine("Processing item " + item);
NFSAttributes attrib = client.GetItemAttributes(folder);
if (attrib == null) continue;
bool isDirectory = client.IsDirectory(client.Combine(item, "dir1\\dir2\\dir3"));
Console.WriteLine("| " + item + " " + (isDirectory ? "(dir)" : null) + " " + attrib.Size + " bytes");
}
#endregion
#region Read /dir1/dir2/dir3/3.txt
Console.WriteLine("");
file = client.Combine("3.txt", "dir1\\dir2\\dir3");
Console.WriteLine("Reading file 3.txt: " + file);
stream = new MemoryStream();
client.Read(file, ref stream);
if (stream != null)
{
stream.Seek(0, SeekOrigin.Begin);
int read = 0;
byte[] buf = new byte[4096];
while (true)
{
read = stream.Read(buf, 0, buf.Length);
if (read > 0)
{
byte[] segment = new byte[read];
Buffer.BlockCopy(buf, 0, segment, 0, read);
Console.WriteLine(Encoding.UTF8.GetString(segment));
}
else
{
break;
}
}
}
#endregion
Console.WriteLine("");
Console.WriteLine("Finished");
Console.WriteLine("");
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
finally
{
if (client != null)
{
if (client.IsMounted)
{
Console.WriteLine("Unmounting device");
client.UnMountDevice();
}
Console.WriteLine("Disconnecting client");
client.Disconnect();
}
}
}
}
}
Output:
C:\Code\Misc\NFS-Client\src\Test.Nfs\bin\Debug\net8.0>test.nfs
Initializing client
Mounting device
Listing shares
| /share
Listing root directory
| dir1 (dir) 4096 bytes
| root.txt 10 bytes
Reading file root.txt: \root.txt
Root file
Listing dir1 directory: .\dir1
| dir2 (dir) 4096 bytes
| 1.txt 16 bytes
Reading file 1.txt: .\dir1\1.txt
this is file 1
Listing dir2 directory: .\dir1\dir2
Processing item 2.txt
Processing item dir3
Reading file 2.txt: .\dir1\dir2\2.txt
This is file 2
Listing dir3 directory: .\dir1\dir2\dir3
Processing item 3.txt
| 3.txt 4096 bytes
Reading file 3.txt: .\dir1\dir2\dir3\3.txt
This is file 3
Finished
Unmounting device
Disconnecting client
NfsClient.Connect
fails when running on Ubuntu 22.04 without root/sudo privileges.
System.Net.Sockets.SocketException (13): Permission denied
at System.Net.Sockets.Socket.UpdateStatusAfterSocketErrorAndThrowException(SocketError error, Boolean disconnectOnFailure, String callerName)
at System.Net.Sockets.Socket.DoBind(EndPoint endPointSnapshot, SocketAddress socketAddress)
at System.Net.Sockets.Socket.Bind(EndPoint localEP)
at org.acplt.oncrpc.OncRpcUdpClient..ctor(IPAddress host, Int32 program, Int32 version, Int32 port, Int32 bufferSize, Boolean useSecurePort) in /home/joel/Code/NFS2/NFSLibrary/RPC/org/acplt/oncrpc/OncRpcUdpClient.cs:line 130
at org.acplt.oncrpc.OncRpcUdpClient..ctor(IPAddress host, Int32 program, Int32 version, Int32 port, Boolean useSecurePort) in /home/joel/Code/NFS2/NFSLibrary/RPC/org/acplt/oncrpc/OncRpcUdpClient.cs:line 73
at org.acplt.oncrpc.OncRpcClient.newOncRpcClient(IPAddress host, Int32 program, Int32 version, Int32 port, Int32 protocol, Boolean useSecurePort) in /home/joel/Code/NFS2/NFSLibrary/RPC/org/acplt/oncrpc/OncRpcClient.cs:line 384
at org.acplt.oncrpc.OncRpcClientStub..ctor(IPAddress host, Int32 program, Int32 version, Int32 port, Int32 protocol, Boolean useSecurePort) in /home/joel/Code/NFS2/NFSLibrary/RPC/org/acplt/oncrpc/OncRpcClientStub.cs:line 81
at NFSLibrary.Protocols.V3.RPC.Mount.NFSv3MountProtocolClient..ctor(IPAddress host, Int32 protocol, Boolean useSecurePort) in /home/joel/Code/NFS2/NFSLibrary/Protocols/V3/RPC/Mount/NFSv3MountProtocolClient.cs:line 37
at NFSLibrary.Protocols.V3.NFSv3.Connect(IPAddress Address, Int32 UserID, Int32 GroupID, Int32 ClientTimeout, Encoding characterEncoding, Boolean useSecurePort, Boolean useCache) in /home/joel/Code/NFS2/NFSLibrary/Protocols/V3/NFSv3.cs:line 52
at NFSLibrary.NfsClient.Connect(IPAddress address, Int32 userId, Int32 groupId, Int32 commandTimeout, Encoding characterEncoding, Boolean useSecurePort, Boolean useCache) in /home/joel/Code/NFS2/NFSLibrary/NFS.cs:line 176
at NFSLibrary.NfsClient.Connect(IPAddress address) in /home/joel/Code/NFS2/NFSLibrary/NFS.cs:line 150
Works great on Windows, i.e. client.CreateDirectory(".\dir1\dir2")
works, but when used on Ubuntu, you end up with a directory named '.\dir1'
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.