public unsafe static string Readlink(string path) { var pathBytes = Encoding.UTF8.GetBytes(path); int bufferLength = 1024; byte *buffer = stackalloc byte[bufferLength]; long size; fixed(byte *pathname = pathBytes) { size = LibC.readlink(pathname, buffer, bufferLength); if (size == -1) { PlatformException.Throw(); } } return(Encoding.UTF8.GetString(buffer, (int)size)); }
public override int ReadLink(ReadOnlySpan <byte> path, Span <byte> buffer, Guid fileGuid) { path = base.TransformPath(path); if (debug) { Console.WriteLine($"NeoFS::ReadLink({RawDirs.HR(path)}"); } ssize_t retl; fixed(byte *b = buffer) { retl = LibC.readlink(toBp(path), b, buffer.Length); } if (retl < 0) { return(-LibC.errno); } return(0); }
public override int GetAttr(ReadOnlySpan <byte> path, ref stat stat, FuseFileInfoRef fiRef, Guid fileGuid) { try { path = base.TransformPath(path); if (debug) { Console.WriteLine($"NeoFS::GetAttr({RawDirs.HR(path)})"); fixed(stat *st = &stat) { var lc = LibC.lstat(toBp(path), st); if (lc < 0) { // Windows file explorer hits lot of files that don't exist //Console.WriteLine($"Stat error: {lc} errno={LibC.errno} path={RawDirs.HR(path)}"); return(-LibC.errno); } } // Intercept an asset - we must provide the asset's Attr, not the link of the baked file if ((stat.st_mode & LibC.S_IFMT) == LibC.S_IFLNK) { if (debug) { Console.WriteLine($"Link Seen: Stat mode={stat.st_mode}, S_IFMT={LibC.S_IFMT}, link={LibC.S_IFLNK}"); } ssize_t retl; var buffer = new byte[1024]; fixed(byte *b = buffer) { retl = LibC.readlink(toBp(path), b, buffer.Length); } // Trying to do something like startswith for bytes that's fast var link = MemoryExtensions.AsSpan(buffer, 0, assetTag.Length); if (debug) { Console.WriteLine($"NeoFS::GetAttr Asset Detected - ({RawDirs.HR(path)}, {RawDirs.HR(link)}"); } if (link.SequenceEqual(assetTag)) { link = MemoryExtensions.AsSpan(buffer, 0, (int)retl); if (debug) { Console.WriteLine($"Found ASSET {RawDirs.HR(link)}"); } base.GetAssetAttr(path, link, ref stat, fileGuid); return(0); } } if (debug) { Console.WriteLine($"Stat Dump: size={stat.st_size}, mode={stat.st_mode}, mtim={stat.st_mtim}"); } return(0); } catch (Exception ex) { Console.WriteLine($"GetAttr error: {ex.Message} {ex.StackTrace}"); return(-LibC.ENOENT); } }
// File read public override int Open(ReadOnlySpan <byte> path, ref FuseFileInfo fi, Guid fileGuid) { path = base.TransformPath(path); if (path.Length < 1) { return(-LibC.ENOENT); } if (debug) { Console.WriteLine($"NeoFS::Open()"); } // Stat the file var stat = new stat(); var lc = LibC.lstat(toBp(path), &stat); if (lc < 0) { return(-LibC.errno); } string extAssetSha1 = null; // Intercept an asset - we must provide the asset's Attr, not the link of the baked file if ((stat.st_mode & LibC.S_IFMT) == LibC.S_IFLNK) { if (debug) { Console.WriteLine($"Stat mode={stat.st_mode}, S_IFMT={LibC.S_IFMT}, link={LibC.S_IFLNK}"); } // Get the link ssize_t retl; var buffer = new byte[1024]; fixed(byte *b = buffer) { retl = LibC.readlink(toBp(path), b, buffer.Length); } // Trying to do something like startswith for bytes that's fast var link = MemoryExtensions.AsSpan <byte>(buffer, 0, assetTag.Length); if (debug) { Console.WriteLine($"NeoFS::GetAttr Asset Detected - ({RawDirs.HR(path)}, {RawDirs.HR(link)}"); } if (link.SequenceEqual(assetTag)) { link = MemoryExtensions.AsSpan <byte>(buffer, 0, (int)retl); if (debug) { Console.WriteLine($"Found ASSET {RawDirs.HR(link)}"); } var asset = link.Slice(assetTag.Length); extAssetSha1 = Encoding.ASCII.GetString(asset); } else { link = MemoryExtensions.AsSpan <byte>(buffer, 0, (int)retl); //path = base.TransformPath() - have to figure out how to pass to our mountmapper // Probably a dependancy injection // These links shouldn't happen, but it would be a nice attack vector } } // See if asset -- if so, set to asset mode and call base if (extAssetSha1 != null) // Asset Mode { var fakeFd = LibC.open(toBp(fakeFile), 0); if (fakeFd > 0) { fi.fh = (ulong)fakeFd; FileContexts.Add(fi.fh, new FileContext { AssetLink = null, ExtAssetSha1 = extAssetSha1, ExtFileHandle = null, }); //Console.WriteLine($"Create Context (sha1) ID={fi.fh}"); } else { Console.WriteLine($"Error Opening /dev/null? Error={LibC.errno}"); } return(base.AssetOpen(path, ref fi, fileGuid)); } // transform the link var newFd = LibC.open(toBp(path), fi.flags); if (newFd > 0) { fi.fh = (ulong)newFd; // Make a context anyway FileContexts.Add(fi.fh, new FileContext { AssetLink = null, ExtAssetSha1 = null, ExtFileHandle = null, }); //Console.WriteLine($"Create Context (null) ID={fi.fh}"); return(0); } return(-LibC.errno); }