Beispiel #1
0
 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)));
 }
Beispiel #2
0
        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);
        }
Beispiel #3
0
        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));
        }
Beispiel #4
0
        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));
        }
Beispiel #5
0
        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");
        }
Beispiel #6
0
        /// <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));
        }