private void GetSourceProperites(out CloudFileNtfsAttributes?fileAttributes,
                                         out string portableSDDL,
                                         out DateTimeOffset?creationTime,
                                         out DateTimeOffset?lastWriteTime,
                                         out IDictionary <string, string> metadata,
                                         CancellationToken cancellationToken)
        {
            fileAttributes = null;
            portableSDDL   = null;
            creationTime   = null;
            lastWriteTime  = null;
            metadata       = null;

            if (this.source.Type == TransferLocationType.LocalDirectory)
            {
                if ((this.baseDirectoryTransfer.PreserveSMBAttributes) ||
                    (PreserveSMBPermissions.None != this.baseDirectoryTransfer.PreserveSMBPermissions))
                {
                    var    sourceLocalDirLocation = this.source as DirectoryLocation;
                    string directoryPath          = sourceLocalDirLocation.DirectoryPath.ToLongPath();

                    if (this.baseDirectoryTransfer.PreserveSMBAttributes)
                    {
                        FileAttributes?localFileAttributes = null;
#if DOTNET5_4
                        LongPathFile.GetFileProperties(directoryPath, out creationTime, out lastWriteTime, out localFileAttributes, true);
#else
                        LongPathFile.GetFileProperties(directoryPath, out creationTime, out lastWriteTime, out localFileAttributes);
#endif
                        fileAttributes = Utils.LocalAttributesToAzureFileNtfsAttributes(localFileAttributes.Value);
                    }

                    portableSDDL = FileSecurityOperations.GetFilePortableSDDL(directoryPath, this.baseDirectoryTransfer.PreserveSMBPermissions);
                }
            }
            else if (this.source.Type == TransferLocationType.AzureFileDirectory)
            {
                if (this.baseDirectoryTransfer.PreserveSMBAttributes ||
                    (PreserveSMBPermissions.None != this.baseDirectoryTransfer.PreserveSMBPermissions) ||
                    this.dest.Type == TransferLocationType.AzureFileDirectory)
                {
                    AzureFileDirectoryLocation sourceFileDirLocation = this.source as AzureFileDirectoryLocation;

                    var sourceFileDirectory = sourceFileDirLocation.FileDirectory;
                    sourceFileDirectory.FetchAttributesAsync(
                        null,
                        Utils.GenerateFileRequestOptions(sourceFileDirLocation.FileRequestOptions),
                        Utils.GenerateOperationContext(this.baseDirectoryTransfer.Context),
                        cancellationToken).GetAwaiter().GetResult();

                    if (this.baseDirectoryTransfer.PreserveSMBAttributes)
                    {
                        fileAttributes = sourceFileDirectory.Properties.NtfsAttributes;
                        creationTime   = sourceFileDirectory.Properties.CreationTime;
                        lastWriteTime  = sourceFileDirectory.Properties.LastWriteTime;
                    }

                    metadata = sourceFileDirectory.Metadata;

                    if (PreserveSMBPermissions.None != this.baseDirectoryTransfer.PreserveSMBPermissions)
                    {
                        if (!string.IsNullOrEmpty(sourceFileDirectory.FilePermission))
                        {
                            portableSDDL = sourceFileDirectory.FilePermission;
                        }
                        else if (!string.IsNullOrEmpty(sourceFileDirectory.Properties.FilePermissionKey))
                        {
                            this.baseDirectoryTransfer.SDDLCache.TryGetValue(sourceFileDirectory.Properties.FilePermissionKey, out portableSDDL);

                            if (null == portableSDDL)
                            {
                                portableSDDL = sourceFileDirectory.Share.GetFilePermissionAsync(
                                    sourceFileDirectory.Properties.FilePermissionKey,
                                    Utils.GenerateFileRequestOptions(sourceFileDirLocation.FileRequestOptions),
                                    Utils.GenerateOperationContext(this.baseDirectoryTransfer.Context),
                                    cancellationToken).GetAwaiter().GetResult();
                                this.baseDirectoryTransfer.SDDLCache.TryAddValue(sourceFileDirectory.Properties.FilePermissionKey,
                                                                                 portableSDDL);
                            }
                        }
                        else
                        {
                            portableSDDL = null;
                        }
                    }
                }
            }
        }
        private void CreateDestinationDirectory(CancellationToken cancellationToken)
        {
            if (this.dest.Type == TransferLocationType.AzureBlobDirectory)
            {
                // No physical destination directory needed.
                return;
            }

            if ((this.dest.Type == TransferLocationType.AzureFileDirectory) &&
                (null == (this.dest as AzureFileDirectoryLocation).FileDirectory.Parent))
            {
                //Root Azure File directory, no need to create.
                return;
            }

            CloudFileNtfsAttributes?     fileAttributes = null;
            DateTimeOffset?              creationTime   = null;
            DateTimeOffset?              lastWriteTime  = null;
            IDictionary <string, string> metadata       = null;

            if (this.source.Type == TransferLocationType.LocalDirectory)
            {
                if (this.baseDirectoryTransfer.PreserveSMBAttributes)
                {
                    var sourceLocalDirLocation = this.source as DirectoryLocation;

                    FileAttributes?localFileAttributes = null;

                    string longDirectoryPath = sourceLocalDirLocation.DirectoryPath;

                    if (Interop.CrossPlatformHelpers.IsWindows)
                    {
                        longDirectoryPath = LongPath.ToUncPath(longDirectoryPath);
                    }

#if DOTNET5_4
                    LongPathFile.GetFileProperties(longDirectoryPath, out creationTime, out lastWriteTime, out localFileAttributes, true);
#else
                    LongPathFile.GetFileProperties(longDirectoryPath, out creationTime, out lastWriteTime, out localFileAttributes);
#endif
                    fileAttributes = Utils.LocalAttributesToAzureFileNtfsAttributes(localFileAttributes.Value);
                }
            }
            else if (this.source.Type == TransferLocationType.AzureFileDirectory)
            {
                if (this.baseDirectoryTransfer.PreserveSMBAttributes || this.dest.Type == TransferLocationType.AzureFileDirectory)
                {
                    AzureFileDirectoryLocation sourceFileDirLocation = this.source as AzureFileDirectoryLocation;

                    var sourceFileDirectory = sourceFileDirLocation.FileDirectory;
                    sourceFileDirectory.FetchAttributesAsync(
                        null,
                        Utils.GenerateFileRequestOptions(sourceFileDirLocation.FileRequestOptions),
                        Utils.GenerateOperationContext(this.baseDirectoryTransfer.Context),
                        cancellationToken).GetAwaiter().GetResult();

                    if (this.baseDirectoryTransfer.PreserveSMBAttributes)
                    {
                        fileAttributes = sourceFileDirectory.Properties.NtfsAttributes;
                        creationTime   = sourceFileDirectory.Properties.CreationTime;
                        lastWriteTime  = sourceFileDirectory.Properties.LastWriteTime;
                    }

                    metadata = sourceFileDirectory.Metadata;
                }
            }

            if (this.dest.Type == TransferLocationType.LocalDirectory)
            {
                var localFileDestLocation = this.dest as DirectoryLocation;
                if (!LongPathDirectory.Exists(localFileDestLocation.DirectoryPath))
                {
                    LongPathDirectory.CreateDirectory(localFileDestLocation.DirectoryPath);
                }

                if (fileAttributes.HasValue)
                {
                    LongPathFile.SetFileTime(localFileDestLocation.DirectoryPath, creationTime.Value, lastWriteTime.Value, true);
                    LongPathFile.SetAttributes(localFileDestLocation.DirectoryPath, Utils.AzureFileNtfsAttributesToLocalAttributes(fileAttributes.Value));
                }
            }
            else if (this.dest.Type == TransferLocationType.AzureFileDirectory)
            {
                AzureFileDirectoryLocation fileDirLocation = this.dest as AzureFileDirectoryLocation;

                var fileDirectory = fileDirLocation.FileDirectory;

                if (string.Equals(fileDirectory.SnapshotQualifiedUri.AbsolutePath, fileDirectory.Share.SnapshotQualifiedUri.AbsolutePath))
                {
                    return;
                }

                try
                {
                    CreateCloudFileDestinationDirectory(fileDirectory,
                                                        fileAttributes,
                                                        creationTime,
                                                        lastWriteTime,
                                                        metadata,
                                                        cancellationToken);
                }
                catch (StorageException storageException)
                {
                    if ((null != storageException.InnerException) &&
                        (storageException.InnerException is OperationCanceledException))
                    {
                        throw storageException.InnerException;
                    }
                    else
                    {
                        throw new TransferException(TransferErrorCode.FailToVadlidateDestination,
                                                    string.Format(CultureInfo.CurrentCulture,
                                                                  Resources.FailedToValidateDestinationException,
                                                                  storageException.ToErrorDetail()),
                                                    storageException);
                    }
                }
            }
        }
        private void CreateDestinationDirectory(CancellationToken cancellationToken)
        {
            if (this.dest.Type == TransferLocationType.AzureBlobDirectory)
            {
                // No physical destination directory needed.
                return;
            }

            if ((this.dest.Type == TransferLocationType.AzureFileDirectory) &&
                (null == (this.dest as AzureFileDirectoryLocation).FileDirectory.Parent))
            {
                //Root Azure File directory, no need to create.
                return;
            }

            CloudFileNtfsAttributes?fileAttributes = null;
            string         portableSDDL            = null;
            DateTimeOffset?creationTime            = null;
            DateTimeOffset?lastWriteTime           = null;
            IDictionary <string, string> metadata  = null;

            this.GetSourceProperites(out fileAttributes, out portableSDDL, out creationTime, out lastWriteTime, out metadata, cancellationToken);

            if (this.dest.Type == TransferLocationType.LocalDirectory)
            {
                string directoryPath = (this.dest as DirectoryLocation).DirectoryPath.ToLongPath();

                if (!LongPathDirectory.Exists(directoryPath))
                {
                    LongPathDirectory.CreateDirectory(directoryPath);
                }

                if (fileAttributes.HasValue)
                {
                    LongPathFile.SetFileTime(directoryPath, creationTime.Value, lastWriteTime.Value, true);
                    LongPathFile.SetAttributes(directoryPath, Utils.AzureFileNtfsAttributesToLocalAttributes(fileAttributes.Value));
                }

                if (!string.IsNullOrEmpty(portableSDDL))
                {
                    FileSecurityOperations.SetFileSecurity(directoryPath, portableSDDL, this.baseDirectoryTransfer.PreserveSMBPermissions);
                }
            }
            else if (this.dest.Type == TransferLocationType.AzureFileDirectory)
            {
                AzureFileDirectoryLocation fileDirLocation = this.dest as AzureFileDirectoryLocation;

                var fileDirectory = fileDirLocation.FileDirectory;

                if (string.Equals(fileDirectory.SnapshotQualifiedUri.AbsolutePath, fileDirectory.Share.SnapshotQualifiedUri.AbsolutePath))
                {
                    return;
                }

                try
                {
                    CreateCloudFileDestinationDirectory(fileDirectory,
                                                        fileAttributes,
                                                        creationTime,
                                                        lastWriteTime,
                                                        metadata,
                                                        portableSDDL,
                                                        cancellationToken);
                }
                catch (StorageException storageException)
                {
                    if ((null != storageException.InnerException) &&
                        (storageException.InnerException is OperationCanceledException))
                    {
                        throw storageException.InnerException;
                    }
                    else
                    {
                        throw new TransferException(TransferErrorCode.FailToVadlidateDestination,
                                                    string.Format(CultureInfo.CurrentCulture,
                                                                  Resources.FailedToValidateDestinationException,
                                                                  storageException.ToErrorDetail()),
                                                    storageException);
                    }
                }
            }
        }