예제 #1
0
        /// <inheritdoc />
        public IEnumerable <FileInfo> EnumerateFiles(AbsolutePath path, EnumerateOptions options)
        {
            path.ThrowIfPathTooLong();

            var dirInfo = new DirectoryInfo(path.Path);

            foreach (System.IO.FileInfo fi in dirInfo.EnumerateFiles(
                         "*",
                         (options & EnumerateOptions.Recurse) != 0 ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly))
            {
                bool     foundValidFile = false;
                FileInfo newFi          = default(FileInfo);

                try
                {
                    newFi = new FileInfo {
                        FullPath = new AbsolutePath(fi.FullName), Length = fi.Length
                    };
                    foundValidFile = true;
                }
                catch (FileNotFoundException)
                {
                    // Ignore FileNotFoundException here. EnumerateFiles returns a cached FileInfo and does not validate
                    // whether the underlying file exists. Calling Length on this FileInfo for the first time prompts it to
                    // refresh its properties/fields, leading to a FileNotFoundException if the file no longer exists.
                }

                if (foundValidFile)
                {
                    yield return(newFi);
                }
            }
        }
        private async Task <(bool isValid, string error)> ValidateFileAsync(Context context, ContentHash expectedHash, FileInfo fileInfo)
        {
            try
            {
                var path = fileInfo.FullPath;

                // The cache entry is invalid if the size in content directory doesn't mach an actual size
                if (_contentStoreInternal.TryGetFileInfo(expectedHash, out var contentFileInfo) && contentFileInfo.FileSize != fileInfo.Length)
                {
                    return(isValid : false, error : $"File size mismatch. Expected size is {contentFileInfo.FileSize} and size on disk is {fileInfo.Length}.");
                }

                // Or if the content doesn't match the hash.
                var actualHashAndSize = await _contentStoreInternal.TryHashFileAsync(context, path, expectedHash.HashType);

                if (actualHashAndSize != null && actualHashAndSize.Value.Hash != expectedHash)
                {
                    // Don't need to add an expected hash into the error string because the client code will always put it into the final error message.
                    return(isValid : false, error : $"Hash mismatch. Actual hash is {actualHashAndSize.Value.Hash.ToShortString()}");
                }

                return(isValid : true, error : string.Empty);
            }
            catch (Exception e)
            {
                _tracer.Warning(context, $"SelfCheck: Content hash is invalid. Hash={expectedHash.ToShortString()}, Error={e}");

                return(isValid : true, error : string.Empty);
            }
        }