public async Task Upload(string objectName, Stream readOnlyInput, CancellationToken cancellationToken)
        {
            var path = FilesystemUtils.PreparePath(objectName, _context);

            cancellationToken.ThrowIfCancellationRequested();
            if (Path.GetDirectoryName(path) is { } directory)
            {
                Directory.CreateDirectory(directory);
            }

            using var file = File.Open(path, FileMode.Create, FileAccess.Write, FileShare.Read | FileShare.Delete);
            await readOnlyInput.CopyToAsync(file, cancellationToken);
        }
Ejemplo n.º 2
0
#pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously -- deleting file is synchronous
        public async Task Clear(CancellationToken cancellationToken)
#pragma warning restore CS1998 // Async method lacks 'await' operators and will run synchronously
        {
            _isLocked = false;
            var name = FilesystemUtils.PreparePath(FilesystemConstants.LockPath + _lockName + LockExtension, _context);

            cancellationToken.ThrowIfCancellationRequested();
            try
            {
                File.Delete(name);
            }
            catch (DirectoryNotFoundException)
            {
            }
        }
Ejemplo n.º 3
0
#pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously -- opening local file is synchronous
        public async Task <Stream?> Read(string objectName, CancellationToken cancellationToken)
#pragma warning restore CS1998 // Async method lacks 'await' operators and will run synchronously
        {
            var path = FilesystemUtils.PreparePath(objectName, _context);

            cancellationToken.ThrowIfCancellationRequested();
            try
            {
                return(File.Open(path, FileMode.Open, FileAccess.Read, FileShare.Read | FileShare.Delete));
            }
            catch (DirectoryNotFoundException)
            {
                return(null);
            }
            catch (FileNotFoundException)
            {
                return(null);
            }
        }
Ejemplo n.º 4
0
#pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously -- creating file is synchronous
        public async Task Lock(CancellationToken cancellationToken)
#pragma warning restore CS1998 // Async method lacks 'await' operators and will run synchronously
        {
            var now          = DateTime.UtcNow;
            var lockLifetime = TimeSpan.FromMinutes(3);
            var threshold    = now - lockLifetime;
            var path         = FilesystemUtils.PreparePath(FilesystemConstants.LockPath, _context);

            cancellationToken.ThrowIfCancellationRequested();
            Directory.CreateDirectory(path);
            foreach (var key in Directory.GetFiles(path, "*" + LockExtension))
            {
                cancellationToken.ThrowIfCancellationRequested();
                var lockTime = File.GetLastWriteTime(key).ToUniversalTime();
                if (lockTime < threshold)
                {
                    File.Delete(key);
                }
                else
                {
                    var lockName = Path.GetFileNameWithoutExtension(key);
                    if (lockName == _lockName)
                    {
                        break;
                    }

                    var message = _isLocked
                        ? FormattableString.Invariant($"The filesystem lock \"{_lockName}\" was overriden by \"{key}\" (time: {lockTime:o}, threshold: {threshold:o}).")
                        : FormattableString.Invariant($"The filesystem lock \"{_lockName}\" is prevented by \"{key}\" (time: {lockTime:o}, threshold: {threshold:o}).");

                    _isLocked = false;
                    throw new OperationCanceledException(message);
                }
            }

            cancellationToken.ThrowIfCancellationRequested();
            File.Create(path + _lockName + LockExtension).Dispose();
            _isLocked = true;
        }
#pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously -- deleting local file is synchronous
        public async Task Delete(string objectName, CancellationToken cancellationToken)
#pragma warning restore CS1998 // Async method lacks 'await' operators and will run synchronously
        {
            var path        = FilesystemUtils.PreparePath(objectName, _context);
            var recyclePath = _recycleContext is object?FilesystemUtils.PreparePath(objectName, _recycleContext) : null;

            cancellationToken.ThrowIfCancellationRequested();
            if (recyclePath is object)
            {
                if (Path.GetDirectoryName(path) is { } directory)
                {
                    Directory.CreateDirectory(directory);
                }

                try
                {
                    File.Move(path, recyclePath, true);
                }
                catch (FileNotFoundException)
                {
                    return;
                }
                catch (DirectoryNotFoundException)
                {
                    return;
                }
            }
            else
            {
                try
                {
                    File.Delete(path);
                }
                catch (DirectoryNotFoundException)
                {
                    return;
                }
            }

            var root = Path.GetDirectoryName(FilesystemUtils.PreparePath("", _context));

            if (root is null)
            {
                return;
            }

            var rootLength = root.Length;

            while (true)
            {
                if (Path.GetDirectoryName(path) is not {
                } directory)
                {
                    break;
                }

                cancellationToken.ThrowIfCancellationRequested();
                if (Directory.EnumerateFileSystemEntries(directory).Any())
                {
                    break;
                }

                var dirLength = directory.Length;
                if (dirLength == rootLength)
                {
                    break;
                }

                if (dirLength < rootLength)
                {
                    throw new InvalidProgramException(FormattableString.Invariant($"Recursive deletion of directory \"{directory}\" attempted to escape root \"{root}\"."));
                }

                Directory.Delete(directory);
                path = directory;
            }
        }