private IEnumerable <IAdapterItem> GetItemsFromDirectory(DirectoryInfo directory, IAdapterItem parent) { return (directory.GetFileSystemInfos() .Where(d => SuppressedDirectories.Contains(d.Name, StringComparer.OrdinalIgnoreCase) == false) .Select(info => FileSystemFolder.Create(info, parent, this))); }
public override bool IsEntryUpdated(SyncEntry childEntry, IAdapterItem adapterItem, out EntryUpdateResult result) { const long TicksPerMillisecond = 10000; // 2017/11/24: There appears to be a discrepency when reading ModifiedDateTimeUtc and CreationTimeUtc // from FileSystemInfo objects. The Ticks value is being rounded to the nearest 10000 ticks, causing // some directories to appear to be modified. For now, we will set the threshold for an item being // changed to 10ms const long Epsilon = TicksPerMillisecond * 10; FileSystemFolder fileSystemItem = adapterItem as FileSystemFolder; if (fileSystemItem == null) { throw new ArgumentException("The adapter item is not of the correct type.", nameof(adapterItem)); } result = new EntryUpdateResult(); if (Math.Abs(childEntry.ModifiedDateTimeUtc.Ticks - fileSystemItem.FileSystemInfo.LastWriteTimeUtc.Ticks) > Epsilon) { result.ChangeFlags |= SyncEntryChangedFlags.ModifiedTimestamp; result.ModifiedTime = fileSystemItem.FileSystemInfo.LastWriteTimeUtc; } if (Math.Abs(childEntry.CreationDateTimeUtc.Ticks - fileSystemItem.FileSystemInfo.CreationTimeUtc.Ticks) > Epsilon) { result.ChangeFlags |= SyncEntryChangedFlags.CreatedTimestamp; result.CreationTime = fileSystemItem.FileSystemInfo.CreationTimeUtc; } FileInfo fileInfo = fileSystemItem.FileSystemInfo as FileInfo; SyncEntryType fileType = SyncEntryType.Directory; if (fileInfo != null) { fileType = SyncEntryType.File; if (fileInfo.Length != childEntry.GetSize(this.Relationship, SyncEntryPropertyLocation.Source)) { result.ChangeFlags |= SyncEntryChangedFlags.FileSize; } } if (!string.Equals(fileSystemItem.Name, childEntry.Name, StringComparison.Ordinal)) { result.ChangeFlags |= SyncEntryChangedFlags.Renamed; } // It is possible that a directory was created over a file that previously existed (with the same name). To // handle this, we need to check if the type changed. if (childEntry.Type != fileType) { // TODO: Handle this throw new NotImplementedException(); } return(result.ChangeFlags != SyncEntryChangedFlags.None); }
public override SyncEntry CreateSyncEntryForAdapterItem(IAdapterItem item, SyncEntry parentEntry) { FileSystemFolder fileSystemItem = item as FileSystemFolder; if (fileSystemItem == null) { throw new InvalidOperationException("Item type is incorrect."); } return(this.CreateEntry(fileSystemItem.FileSystemInfo, parentEntry)); }
public override async Task <IAdapterItem> GetRootFolder() { return(await Task.Factory.StartNew(() => { if (this.Config.RootDirectory == null) { throw new InvalidOperationException("The root directory has not been set."); } DirectoryInfo rootDirectoryInfo = new DirectoryInfo(this.Config.RootDirectory); return FileSystemFolder.Create(rootDirectoryInfo, this, false); }).ConfigureAwait(false)); }
public override byte[] GetItemHash(HashType hashType, IAdapterItem adapterItem) { if (hashType == HashType.SHA1) { if (adapterItem.Sha1Hash != null) { return(adapterItem.Sha1Hash); } FileSystemFolder item = (FileSystemFolder)adapterItem; string newPath = string.Join("\\", item.FullName.Split('\\').Skip(1)); string fullPath = Path.Combine(this.Config.RootDirectory, newPath); using (SHA1Cng sha1 = new SHA1Cng()) using (var fileStream = File.OpenRead(fullPath)) { return(sha1.ComputeHash(fileStream)); } } if (hashType == HashType.MD5) { if (adapterItem.Md5Hash != null) { return(adapterItem.Md5Hash); } FileSystemFolder item = (FileSystemFolder)adapterItem; string newPath = string.Join("\\", item.FullName.Split('\\').Skip(1)); string fullPath = Path.Combine(this.Config.RootDirectory, newPath); using (MD5Cng md5 = new MD5Cng()) using (var fileStream = File.OpenRead(fullPath)) { return(md5.ComputeHash(fileStream)); } } throw new NotImplementedException("Unknown hash type"); }
/// <summary> /// Get the <see cref="FileSystemFolder"/> items that are children to the provided /// <see cref="FileSystemFolder"/>. /// </summary> /// <param name="folder">The parent folder</param> /// <returns>The list of child items under the parent folder.</returns> /// <remarks> /// An errors encountered when querying for the list of child should be thrown for the /// caller to handle. However, any errors related to querying the children themselves /// should be caught and returned as error information for that child (the original /// call should not fail in this case). /// </remarks> public override IEnumerable <IAdapterItem> GetAdapterItems(IAdapterItem folder) { // If folder is null, return the list of top-level folders on the computer (aka drives). if (folder == null) { DriveInfo[] allDrives = DriveInfo.GetDrives(); List <IAdapterItem> folders = new List <IAdapterItem>(); foreach (DriveInfo driveInfo in allDrives) { try { folders.Add(FileSystemFolder.Create(driveInfo.RootDirectory, this, true)); } catch (Exception exception) { Logger.Info( "Failed to enumerate drive {0} ({1}). The error was: {2}", driveInfo.Name, driveInfo.DriveType, exception.Message.Trim()); } } return(folders); } FileSystemFolder fileSystemFolder = folder as FileSystemFolder; if (fileSystemFolder == null) { throw new InvalidOperationException("folder item is not a FileSystemFolder"); } if (fileSystemFolder.ItemType != SyncAdapterItemType.Directory) { throw new InvalidOperationException("Invalid FileSystemFolder type"); } return(this.GetItemsFromDirectory((DirectoryInfo)fileSystemFolder.FileSystemInfo, folder)); }