private void NodeCacheInvalidate(NeoAssets.Mongo.NeoVirtFS node)
        {
            var key = NodeKey(node);

            lock (nodeCache)
            {
                nodeCache.Remove(key);
            }
        }
        private void NodeCacheSet(NeoAssets.Mongo.NeoVirtFS node, int expireMins)
        {
            var key = NodeKey(node);

            lock (nodeCache)
            {
                var exp = DateTimeOffset.Now.AddMinutes(expireMins);
                nodeCache.Set(key, node, exp);
            }
        }
        public override int MkDir(ReadOnlySpan <byte> path, mode_t mode)
        {
            if (verbosity > 5)
            {
                Console.WriteLine($"MkDir {path.GetString()} mode={mode}");
            }

            int error = 0, level = 0;
            var procs = ProcPath(path, ref error, ref level, mustExist: false, isADir: true);

            if (error != 0)
            {
                return(-LibC.ENOENT);
            }


            if (procs.Count < 2)
            {
                Console.WriteLine($"Mkdir - path < 2");
                return(-LibC.EPERM);
            }

            var cNode  = procs.Pop();
            var inNode = procs.Pop();

            if (cNode.Item2 != null)
            {
                return(-LibC.EEXIST);  // File (or directory) already exists
            }
            if (inNode.Item2 == null)
            {
                return(-LibC.ENOENT);   // SHouldn't happen (2nd level will get error)
            }
            var createIn = inNode.Item2;

            if (createIn.MaintLevel)
            {
                return(-LibC.EPERM);     // Nobody can create in the maintenance levels (Namespace levels)
            }
            var newRec = new NeoAssets.Mongo.NeoVirtFS()
            {
                _id        = ObjectId.GenerateNewId(),
                Content    = NeoVirtFSContent.Dir(),
                Stat       = NeoVirtFSStat.DirDefault((uint)mode),
                Name       = cNode.Item1,
                VolumeId   = createIn.VolumeId,
                ParentId   = createIn._id,
                MaintLevel = false,
            };  // It will assign it's own objectId _id

            NeoVirtFSCol.InsertOne(newRec);
            Console.WriteLine($"Create Directory {cNode.Item1.GetString()} id={newRec._id}");

            return(0);
        }
示例#4
0
        public FileDescriptorMounted(NeoAssets.Mongo.NeoVirtFS myFile) : base(myFile)
        {
            if (!myFile.Content.MountedVolume.HasValue ||
                !myFile.Content.AtFilePath.HasValue)
            {
                throw new ArgumentException("MountedVolume or AtFilePath not set");
            }

            VolumeId   = myFile.Content.MountedVolume.Value;
            MountPoint = myFile.Content.AtFilePath.Value;
        }
        private string NodeKey(NeoAssets.Mongo.NeoVirtFS node)
        {
            var sb = new StringBuilder();

            sb.Append(node.ParentId.ToString());
            sb.Append('_');
            sb.Append(Convert.ToHexString(node.Name));
            //Console.WriteLine($"KeyN: {sb}");

            return(sb.ToString());
        }
        public FileDescriptorAsset(NeoAssets.Mongo.NeoVirtFS myFile,
                                   MongoDB.Driver.IMongoDatabase db,
                                   MongoDB.Driver.IMongoCollection <NeoBakedVolumes.Mongo.BakedAssets> bac,
                                   MongoDB.Driver.IMongoCollection <NeoBakedVolumes.Mongo.BakedVolumes> bVol) : base(myFile)
        {
            // Just load this stuff - we become active if we get an open call

            asset = null;

            this.db   = db;
            this.bac  = bac;
            this.bVol = bVol;
            this.file = myFile;
        }
示例#7
0
        public static NeoVirtFS CreateDirectory(ObjectId parId, ObjectId volId, byte[] name, mode_t mode)
        {
            var newRec = new NeoVirtFS()
            {
                _id        = ObjectId.GenerateNewId(),
                Content    = NeoVirtFSContent.Dir(),
                Stat       = NeoVirtFSStat.DirDefault((uint)mode),
                Name       = name,
                VolumeId   = volId,
                ParentId   = parId,
                MaintLevel = false,
            };

            return(newRec);
        }
        private void fileDelete(NeoAssets.Mongo.NeoVirtFS rec, DeleteTypes dType)
        {
            // Remove file node from main file, move to the deleted list

            // Don't forget to mark the dtim

            rec.Stat.st_dtim = DateTimeOffset.UtcNow;
            rec.DeleteType   = dType;

            // Upsert to the deleted collection  - maybe this should be in a unit of work?

            var filter = Builders <NeoAssets.Mongo.NeoVirtFS> .Filter.Eq(x => x._id, rec._id);

            var insert = NeoVirtFSDeletedCol.ReplaceOneAsync(filter, rec, options: new ReplaceOptions {
                IsUpsert = true
            });

            // Remove from the original collection

            NeoVirtFSCol.DeleteOne(filter);
        }
示例#9
0
        public static NeoVirtFS CreateNewFile(ObjectId parId, ObjectId volId, byte[] name, ReadOnlySpan <byte> path, mode_t mode, NeoVirtFSContent cont = null)
        {
            var id = ObjectId.GenerateNewId();

            if (cont == null)
            {
                cont = NeoVirtFSContent.NewCache(path, id);
            }

            //Console.WriteLine($"Set newId for file to {id}");
            var newRec = new NeoVirtFS
            {
                _id        = id,
                Name       = name,
                VolumeId   = volId,
                ParentId   = parId,
                Stat       = NeoVirtFSStat.FileDefault((uint)mode),
                Content    = cont,
                MaintLevel = false
            };

            return(newRec);
        }
        public override int Rename(ReadOnlySpan <byte> path, ReadOnlySpan <byte> newPath, int flags)
        {
            if (verbosity > 5)
            {
                Console.WriteLine($"Rename {path.GetString()} to {newPath.GetString()}");
            }

            // Rename's a bit link link, except it's literally changing the 'Name' on the
            // fromPath.   And the Name can also be a directory (you can rename a directory)

            int error = 0, level = 0;
            var procs = ProcPath(path, ref error, ref level, mustExist: true);

            if (error != 0)
            {
                return(-LibC.ENOENT);
            }

            var fromProc = procs.Pop();
            var fromRec  = fromProc.Item2;

            //Console.WriteLine($"From: {fromProc.Item1.GetString()}");

            if (fromRec == null)
            {
                return(-LibC.ENOENT);                  // From must exist
            }
            //if (fromRec.IsDirectory) return -LibC.EISDIR;  // Can't be a dir
            //if (!fromRec.IsFile) return -LibC.EPERM;   // Must be a file
            if (fromRec.MaintLevel)
            {
                return(-LibC.EPERM);                     // Not in a maint level
            }
            int derror = 0, dlevel = 0;
            var dprocs = ProcPath(newPath, ref derror, ref dlevel, mustExist: false);

            if (derror != 0)
            {
                Console.WriteLine($" derror={derror}");
                return(-LibC.ENOENT);
            }

            var toProc = dprocs.Pop();
            var toRec  = toProc.Item2;

            //Console.WriteLine($"To: {toProc.Item1.GetString()}");

            Byte[] newFile = null;

            NeoAssets.Mongo.NeoVirtFS par = null;

            if (toRec != null && toRec.IsFile)  // This is permitted but we obliterate the Output File
            {
                //Console.WriteLine($" -- to file - remove output {toRec.Name.GetString()}");
                if (toRec.MaintLevel)
                {
                    return(-LibC.EPERM);
                }

                fileDelete(toRec, DeleteTypes.RENAMEOVER);

                var parProc = dprocs.Pop();
                var parrec  = parProc.Item2;

                par     = parrec;
                newFile = toRec.Name;
            }
            else
            if (toRec != null && toRec.IsDirectory)
            {
                //Console.WriteLine($" -- to dir - parent to new dir");

                if (toRec.MaintLevel)
                {
                    return(-LibC.EPERM);                   // Not in a maint level
                }
                par     = toRec;
                newFile = fromRec.Name;
            }
            else
            { // Doesn't exist, so this is our new file (par is it's parent)
                var parProc = dprocs.Pop();
                if (parProc.Item2 == null)
                {
                    return(-LibC.ENOENT);
                }

                par     = parProc.Item2;
                newFile = toProc.Item1;

                if (par.MaintLevel)
                {
                    return(-LibC.EPERM);                 // Not in a maint level
                }
                //
                //Console.WriteLine($" -- nonexist - parent to new dir");
            }

            NodeCacheInvalidate(fromRec);  // Old version's going away

            fromRec.Rename(par, newFile);

            var filter = Builders <NeoAssets.Mongo.NeoVirtFS> .Filter.Eq(x => x._id, fromRec._id);

            var insert = NeoVirtFSCol.ReplaceOne(filter, fromRec, options: new ReplaceOptions {
                IsUpsert = false
            });

            //Console.WriteLine($"Rename File: {fromRec.Name.GetString()} Match={insert.MatchedCount} Mod={insert.ModifiedCount}");

            return(0);
        }
        public override int Link(ReadOnlySpan <byte> fromPath, ReadOnlySpan <byte> toPath)
        {
            if (verbosity > 5)
            {
                Console.WriteLine($"Link {fromPath.GetString()} {toPath.GetString()} ");
            }

            // Link only creates links to files, not directories, so ultimate of fromPath must be a file
            // if ultimate of toPath is a directory then we create fromPath ultimate name in that directory
            // or we close fromPath and copy it to toPath name

            int error = 0, level = 0;
            var procs = ProcPath(fromPath, ref error, ref level, mustExist: true);

            if (error != 0)
            {
                return(-LibC.ENOENT);
            }

            var fromProc = procs.Pop();
            var fromRec  = fromProc.Item2;

            if (fromRec == null)
            {
                return(-LibC.ENOENT);                  // From must exist
            }
            if (fromRec.IsDirectory)
            {
                return(-LibC.EISDIR);                      // Can't be a dir
            }
            if (!fromRec.IsFile)
            {
                return(-LibC.EPERM);                   // Must be a file
            }
            if (fromRec.MaintLevel)
            {
                return(-LibC.EPERM);                     // Not in a maint level
            }
            int derror = 0, dlevel = 0;
            var dprocs = ProcPath(toPath, ref derror, ref dlevel, mustExist: false);

            if (derror != 0)
            {
                return(-LibC.ENOENT);
            }

            var toProc = dprocs.Pop();
            var toRec  = toProc.Item2;

            Byte[] newFile = null;

            NeoAssets.Mongo.NeoVirtFS par = null;

            if (toRec != null)
            {
                if (toRec.IsFile)
                {
                    return(-LibC.EEXIST);                   // If a file it must not exist
                }
                if (!toRec.IsDirectory)
                {
                    return(-LibC.EPERM);                    // Must be a dir otherwise
                }
                if (toRec.MaintLevel)
                {
                    return(-LibC.EPERM);                   // Not in a maint level
                }
                par     = toRec;
                newFile = fromRec.Name;
            }
            else
            { // Doesn't exist, so this is our new file (par is it's parent)
                var parProc = dprocs.Pop();
                if (parProc.Item2 == null)
                {
                    return(-LibC.ENOENT);
                }

                par     = parProc.Item2;
                newFile = toProc.Item1;

                if (par.MaintLevel)
                {
                    return(-LibC.EPERM);                 // Not in a maint level
                }
            }

            var newLink = fromRec.MakeLink(par, newFile);

            NeoVirtFSCol.InsertOne(newLink);

            Console.WriteLine($"Create File Link: {newLink.Name.GetString()}");

            return(0);
        }
示例#12
0
 public FileDescriptorNotFile(NeoAssets.Mongo.NeoVirtFS myFile) : base(myFile)
 {
 }
        public NodeMark(FileNode m, int level, NodeMark[] stack, ObjectId rootOfVolume, IMongoDatabase db)
        {
            NeoVirtFSCol        = db.NeoVirtFS();
            NeoVirtFSDeletedCol = db.NeoVirtFSDeleted();

            this.m     = m;
            this.level = level;

            Name = m.Name;
            this.rootOfVolume = rootOfVolume;

            var v = new NeoAssets.Mongo.NeoVirtFS
            {
                Name = Name
            };

            if (stack == null)
            {
                v.NARPImport = v.Name.GetString();
                Console.WriteLine($"NARP Import {v.NARPImport}");

                var vol = NeoVirtFSVolumesCol.FindSync(x => x._id == rootOfVolume).FirstOrDefault();
                if (vol == null)
                {
                    throw new Exception($"Can't find volume {v.NARPImport}");
                }

                // Make sure everything exists - this should make the filesystem nodes

                namespaceId = vol.NameSpace;
                nodeId      = vol.NodeId;

                v.VolumeId = rootOfVolume;
                return;
            }
            else
            {
                v.NARPImport = stack[0].Name.GetString();
                //Console.WriteLine($"NARP Import {v.NARPImport}");

                v.VolumeId = rootOfVolume;
            }

            // Need potential uuid5 handle - build our raw full path

            var realPath = new List <byte>(Encoding.ASCII.GetBytes("/NARP"));

            foreach (var p in stack)
            {
                realPath.Add((byte)'/');
                realPath.AddRange(p.Name);
            }

            // Work the contents

            Broken = true;


            if (m.IsLnk)
            {
                var link = m.SymbolicLink.GetString();

                if (link.StartsWith(AssetTag))
                {
                    var sha1 = link.Substring(AssetTag.Length);

                    realPath.Add((byte)'/');
                    realPath.AddRange(m.Name);

                    var fileuuid = GuidUtility.Create(GuidUtility.UrlNamespace, realPath.ToArray());

                    AssetFiles?baRec = null;
                    try
                    {
                        var theFilter = Builders <AssetFiles> .Filter.Eq("_id", fileuuid);

                        baRec = af.FindSync(theFilter).FirstOrDefault();
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine($"Bad assetfile {ex.Message} {Encoding.UTF8.GetString(realPath.ToArray())} - id {fileuuid}");
                        baRec = null;
                    }
                    if (baRec == null)
                    {
                        Console.WriteLine($"Can't find assetfile {Encoding.UTF8.GetString(realPath.ToArray())} - using file defaults");
                        v.Stat = NeoVirtFSStat.FileDefault();
                    }
                    else
                    {
                        baRec.CheckStat(); // Recover old format stat

                        //Console.WriteLine($"Found baRec {baRec._id}");
                        v.Stat = new NeoVirtFSStat(baRec.Stat).ToFile();
                    }

                    // We've got to check the asset to see if it's actually annealed -- it could be lost
                    // If we're a mirror we'll skip it

                    var assFilter = Builders <BakedAssets> .Filter.Eq("_id", sha1);

                    var ass = bac.FindSync(assFilter).FirstOrDefault();

                    if (ass == null)
                    {
                        Console.WriteLine($"Can't find the asset - {Encoding.UTF8.GetString(realPath.ToArray())} / {Encoding.UTF8.GetString(m.Name)}");

                        v.Stat.st_size = 0;   // We could conceivably try to look on the Asset for this - restore will need to fix the stat
                        GenerateAssetFile(m, stack, rootOfVolume, v.Stat, sha1, realPath, true);

                        return;   // Should handle as 'lost' node
                    }

                    v.Stat.st_size = ass.FileLength;  // RealLength is the compressed size

                    if (!ass.Annealed.Value)
                    {
                        //Console.WriteLine($"Asset lost -- skipping - {Encoding.UTF8.GetString(realPath.ToArray())} / {Encoding.UTF8.GetString(m.Name.ToArray())}");
                        GenerateAssetFile(m, stack, rootOfVolume, v.Stat, sha1, realPath, true);

                        return;
                    }

                    // If we get to here, we have an annealed asset type, so we need to process
                    Broken = false;

                    GenerateAssetFile(m, stack, rootOfVolume, v.Stat, sha1, realPath, false);
                    return;
                }
                else
                {
                    // Let's see if we can handle the simple link to an archive directory
                    // If the original archive exists we can just do that.

                    var dirs = link.Split("/");
                    if (dirs.Length == 4 && dirs[3].StartsWith("ARC-"))
                    {
                        Console.WriteLine($"Archive Link: {link} dirs={dirs.Length}");

                        // ARC-56a6f879e8cb392b22bb7577bc5d4ba117587261-ZIP
                        // 01234567890123456789012345678901234567890123456789
                        // 000000000011111111112222222222333333333344444444

                        var sha1 = dirs[3][4..44].ToLowerInvariant();
示例#14
0
 public FileDescriptorPhysical(NeoAssets.Mongo.NeoVirtFS myFile) : base(myFile)
 {
 }