public override void Release(ReadOnlySpan <byte> path, ref FuseFileInfo fi, Guid fileGuid) { path = base.TransformPath(path); if (debug) { Console.WriteLine($"NeoFS::Release({RawDirs.HR(path)})"); } if (FileContexts.TryGetValue(fi.fh, out var context)) { if (context.ExtAssetSha1 != null) // Asset Mode { base.AssetRelease(path, ref fi, fileGuid); } FileContexts.Remove(fi.fh); } if (fi.fh > 0) { LibC.close((int)fi.fh); } fi.fh = 0; }
// 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); }