EvaluateInternal() { #if __MonoCS__ if (this.IsPrebuilt) { return; } this.ReasonToExecute = null; var symlinkPath = this.GeneratedPaths[Key].ToString(); var symlinkInfo = new Mono.Unix.UnixSymbolicLinkInfo(symlinkPath); if (!symlinkInfo.Exists) { this.ReasonToExecute = Bam.Core.ExecuteReasoning.FileDoesNotExist(this.GeneratedPaths[Key]); return; } var targetPath = symlinkInfo.ContentsPath; if (targetPath != System.IO.Path.GetFileName(this.SharedObject.GeneratedPaths[ConsoleApplication.Key].ToString())) { this.ReasonToExecute = Bam.Core.ExecuteReasoning.InputFileNewer(this.GeneratedPaths[Key], this.SharedObject.Macros[this.Macros["SymlinkUsage"].ToString()]); return; } #else throw new System.NotSupportedException("Symbolic links not supported for shared objects on this platform"); #endif }
public void Tar_GZip_With_Symlink_Entries() { var isWindows = System.Runtime.InteropServices.RuntimeInformation.IsOSPlatform( System.Runtime.InteropServices.OSPlatform.Windows); using (Stream stream = File.OpenRead(Path.Combine(TEST_ARCHIVES_PATH, "TarWithSymlink.tar.gz"))) using (var reader = TarReader.Open(stream)) { List <string> names = new List <string>(); while (reader.MoveToNextEntry()) { if (reader.Entry.IsDirectory) { continue; } reader.WriteEntryToDirectory(SCRATCH_FILES_PATH, new ExtractionOptions() { ExtractFullPath = true, Overwrite = true, WriteSymbolicLink = (sourcePath, targetPath) => { if (!isWindows) { var link = new Mono.Unix.UnixSymbolicLinkInfo(sourcePath); if (File.Exists(sourcePath)) { link.Delete(); // equivalent to ln -s -f } link.CreateSymbolicLinkTo(targetPath); } } }); if (!isWindows) { if (reader.Entry.LinkTarget != null) { var path = System.IO.Path.Combine(SCRATCH_FILES_PATH, reader.Entry.Key); var link = new Mono.Unix.UnixSymbolicLinkInfo(path); if (link.HasContents) { // need to convert the link to an absolute path for comparison var target = reader.Entry.LinkTarget; var realTarget = System.IO.Path.GetFullPath( System.IO.Path.Combine($"{System.IO.Path.GetDirectoryName(path)}", target) ); Assert.Equal(realTarget, link.GetContents().ToString()); } else { Assert.True(false, "Symlink has no target"); } } } } } }
private static bool CanPosix() { try // https://stackoverflow.com/questions/19428170/detecting-symbolic-links-and-pipes-in-mono { Mono.Unix.UnixSymbolicLinkInfo info = new Mono.Unix.UnixSymbolicLinkInfo("/"); } catch (TypeLoadException e) { return(false); } return(true); }
} // NormalizePath /// <summary> /// Returns the real path for a path containing a symbolic link /// </summary> /// <returns> /// A resolved path. /// </returns> /// <param name='path'> /// A path that may traverse a symbolic link. /// </param> /// <exception cref='ArgumentException'> /// Is thrown when path is empty. /// </exception> internal static string ResolveSymlink(string path) { if (string.IsNullOrEmpty(path)) { throw new ArgumentException("Empty path not allowed", "path"); } if (!(File.Exists(path) || Directory.Exists(path))) { return(path); } #if !WINDOWS try { string[] chunks = path.Split(new[] { Path.DirectorySeparatorChar }, StringSplitOptions.RemoveEmptyEntries); string subpath = chunks[0]; Mono.Unix.UnixSymbolicLinkInfo link; if (Path.IsPathRooted(path)) { subpath = Path.Combine(Path.GetPathRoot(path), subpath); } for (int i = 1; i < chunks.Length; ++i) { link = new Mono.Unix.UnixSymbolicLinkInfo(subpath); if (link.IsSymbolicLink) { subpath = link.GetContents().FullName; --i; continue; } subpath = Path.Combine(subpath, chunks[i]); } link = new Mono.Unix.UnixSymbolicLinkInfo(subpath); if (link.IsSymbolicLink) { subpath = link.GetContents().FullName; } // if (path != subpath) // Console.WriteLine ("Subsituting {0} for {1}", subpath, path); path = subpath; } catch (Exception ex) { LoggingService.LogWarning(string.Format("Error checking symlink status for {0}", path), ex); } #endif return(path); }
AssignLinkTarget( TokenizedString path = null) { #if __MonoCS__ if (path == null) { var symlink = new Mono.Unix.UnixSymbolicLinkInfo(this.SourcePath.Parse()); this.Macros["LinkTarget"] = Bam.Core.TokenizedString.CreateVerbatim(symlink.ContentsPath); } else { this.Macros["LinkTarget"] = path; } #else throw new System.NotSupportedException("Unable to get symbolic link target on Windows"); #endif }
AssignLinkTarget( TokenizedString path = null) { #if __MonoCS__ if (path == null) { var symlink = new Mono.Unix.UnixSymbolicLinkInfo(this.SourcePath.Parse()); this.Macros["LinkTarget"] = Bam.Core.TokenizedString.CreateVerbatim(symlink.ContentsPath); } else { this.Macros["LinkTarget"] = path; } #else throw new System.NotSupportedException("Unable to get symbolic link target on Windows"); #endif }
// Needed so that UnixSymbolicLinkInfo doesn't have to // be JITted on windows private void Symlink_helper() { string path = TempFolder + DSC + "DIT.Symlink"; string dir = path + DSC + "dir"; string link = path + DSC + "link"; DeleteDir(path); try { Directory.CreateDirectory(path); Directory.CreateDirectory(dir); Mono.Unix.UnixSymbolicLinkInfo li = new Mono.Unix.UnixSymbolicLinkInfo(link); li.CreateSymbolicLinkTo(dir); DirectoryInfo info = new DirectoryInfo(path); DirectoryInfo[] dirs = info.GetDirectories(); Assert.AreEqual(2, dirs.Length, "#1"); } finally { DeleteDir(path); } }
internal static bool TryGetSymLinkTarget(string path, [NotNullWhen(true)] out string?target) { var symbolicLinkInfo = new Mono.Unix.UnixSymbolicLinkInfo(path); if (symbolicLinkInfo.IsSymbolicLink) { var root = Path.GetDirectoryName(path); if (root == null) { target = symbolicLinkInfo.ContentsPath; } else { target = Path.Combine(root, symbolicLinkInfo.ContentsPath); } return(true); } target = null; return(false); }
Evaluate() { base.Evaluate(); if (null != this.ReasonToExecute) { // a reason has been found already return; } if (this.IsPrebuilt) { return; } if (!this.BuildEnvironment.Platform.Includes(Bam.Core.EPlatform.Linux)) { // symlinks only on Linux return; } if (this is Plugin) { // plugins don't have symlinks return; } var fullSONamePath = this.CreateTokenizedString("@dir($(0))/$(1)", this.GeneratedPaths[Key], this.Macros["SOName"]); var soName = new Mono.Unix.UnixSymbolicLinkInfo(fullSONamePath.Parse()); if (!soName.Exists) { this.ReasonToExecute = Bam.Core.ExecuteReasoning.FileDoesNotExist(fullSONamePath); return; } var fullLinkerNamePath = this.CreateTokenizedString("@dir($(0))/$(1)", this.GeneratedPaths[Key], this.Macros["LinkerName"]); var linkerName = new Mono.Unix.UnixSymbolicLinkInfo(fullLinkerNamePath.Parse()); if (!linkerName.Exists) { this.ReasonToExecute = Bam.Core.ExecuteReasoning.FileDoesNotExist(fullLinkerNamePath); return; } }
/// <summary> /// returns the partition name (sdX format) from any by-xxxx value (by-path, by-uuid...) /// </summary> /// <param name='partitionName'> /// Partition name. /// </param>/ private string GetPartitionFromPathOrUuid(string partitionName) { string[] disksBy = new string[] { "by-uuid", "by-path", "by-label", "by-id" }; foreach (string byType in disksBy) { Mono.Unix.UnixDirectoryInfo byUuidParts = new Mono.Unix.UnixDirectoryInfo("/dev/disk/" + byType); foreach (Mono.Unix.Native.Dirent d in byUuidParts.GetEntries()) { //Console.WriteLine ("______GetPartitionFromPathOrUuid looking cur entry="+d.d_name+", type="+d.d_type); if (d.d_type == 10 /*Mono.Unix.FileTypes.SymbolicLink*/) { string partOnlyName = ""; if (partitionName.LastIndexOf("/") >= 0) { partOnlyName = partitionName.Substring(partitionName.LastIndexOf("/") + 1); } else if (partitionName.IndexOf("UUID=") == 0) { partOnlyName = partitionName.Replace("UUID=", ""); } else { partOnlyName = partitionName; } //Console.WriteLine ("______GetPartitionFromPathOrUuid :d_name="+d.d_name+", partonlyname="+partOnlyName); if (d.d_name == partOnlyName) { Mono.Unix.UnixSymbolicLinkInfo devLink = new Mono.Unix.UnixSymbolicLinkInfo(byUuidParts + "/" + d.d_name); //Console.WriteLine ("______GetPartitionFromPathOrUuid : "+partitionName+" --> /dev/"+devLink.ContentsPath.Substring(devLink.ContentsPath.LastIndexOf('/')+1)); return("/dev/" + devLink.ContentsPath.Substring(devLink.ContentsPath.LastIndexOf('/') + 1)); } } } } // partition was probably referenced by its devics (/dev/sdXX) path, nothing to do return(partitionName); }
static FilePath ResolveSymbolicLink(FilePath fileName) { if (fileName.IsEmpty) { return(fileName); } try { var alreadyVisted = new HashSet <FilePath> (); while (true) { if (alreadyVisted.Contains(fileName)) { LoggingService.LogError("Cyclic links detected: " + fileName); return(FilePath.Empty); } alreadyVisted.Add(fileName); var linkInfo = new Mono.Unix.UnixSymbolicLinkInfo(fileName); if (linkInfo.IsSymbolicLink && linkInfo.HasContents) { FilePath contentsPath = linkInfo.ContentsPath; if (contentsPath.IsAbsolute) { fileName = linkInfo.ContentsPath; } else { fileName = fileName.ParentDirectory.Combine(contentsPath); } fileName = fileName.CanonicalPath; continue; } return(ResolveSymbolicLink(fileName.ParentDirectory).Combine(fileName.FileName).CanonicalPath); } } catch (Exception) { return(fileName); } }
void RecursiveCopy( FolderInfo folder, string path ) { try { string s = folder.Name + ":" + MatchPath.AbsoluteDirectoryPath( path ?? string.Empty ); status.update.current = s; if( debug ) { Log( ".u.recursive copy [{0}]", s ); } //..check if cancelled if( IsCancelRequested ) { throw new Exception( "Update cancelled." ); } if( ! folder.IsIncludedFolder( path ) ) { if( debug ) { Log( ".u.not included", path ); } return; } string fp = PathCombine( folder.Root, path ); if( debug ) { Log( ".u.folder path [{0}]", fp ); } try { #if __MonoCS__ { Mono.Unix.UnixSymbolicLinkInfo i = new Mono.Unix.UnixSymbolicLinkInfo( fp ); if( ! i.Exists || ! i.IsDirectory ) { return; } } #endif if( ! DirectoryExists( fp ) ) { throw new Exception( "Folder path does not exist." ); } string cp = PathCombine( current, folder.Name, path ); if( debug ) { Log( ".u.current path [{0}]", cp ); } try { if( debug ) { Log( ".u.create current directory" ); } DirectoryCreate( cp ); //..copy all included files at this level if( debug ) { Log( ".u.-----> files [{0}]", MatchPath.AbsoluteDirectoryPath( path ?? string.Empty ) ); } foreach( string n in Ctrl.ListFiles( fp ) ) { try { status.update.current = folder.Name + ":" + MatchPath.AbsoluteDirectoryPath( path ?? string.Empty ) + n; if( IsCancelRequested ) { throw new Exception( "Update cancelled." ); } string pn = PathCombine( path, n ); if( debug ) { Log( ".u.file [{0}]", pn ); } if( folder.IsIncludedFile( pn ) ) { if( debug ) { Log( ".u.is included" ); } string fpn = PathCombine( fp, n ); try { #if __MonoCS__ Mono.Unix.UnixSymbolicLinkInfo i = new Mono.Unix.UnixSymbolicLinkInfo( fpn ); if( i.Exists && i.IsRegularFile ) #endif { string cpn = PathCombine( cp, n ); try { if( debug ) { Log( ".u.copy folder file to current" ); } FileCopy( fpn, cpn ); LogStatus( StatusType.Created, folder.Name, path, n ); Interlocked.Increment( ref status.update.created ); } catch( Exception ex ) { ex.Data[ExCurrentFilename] = cpn; Log( "Update {0}", Except.ToString( ex, debug ) ); Interlocked.Increment( ref status.update.skipped ); LogStatus( StatusType.Skipped, folder.Name, path, n ); } } } catch( Exception ex ) { ex.Data[ExFolderFilename] = fpn; throw; } } } catch( Exception ex ) { ex.Data[ExFilename] = n; throw; } } //..recursively copy all subdirectories at this level if( debug ) { Log( ".u.-----> directories [{0}]", MatchPath.AbsoluteDirectoryPath( path ?? string.Empty ) ); } foreach( string n in Ctrl.ListDirectories( fp ) ) { string pn = PathCombine( path, n ); if( debug ) { Log( ".u.directory [{0}]", pn ); } RecursiveCopy( folder, pn ); } } catch( Exception ex ) { ex.Data[ExCurrentPath] = cp; throw; } } catch( Exception ex ) { ex.Data[ExFolderPath] = fp; throw; } } catch( Exception ex ) { ex.Data[ExPath] = path; Msg( "Update: {0}", Except.ToString( ex, debug ) ); } }
private async Task <IActionResult> PushDeployAsync(ZipDeploymentInfo deploymentInfo, bool isAsync, HttpContext context) { var zipFilePath = Path.Combine(_environment.ZipTempPath, Guid.NewGuid() + ".zip"); if (_settings.RunFromLocalZip()) { await WriteSitePackageZip(deploymentInfo, _tracer); } else { var oryxManifestFile = Path.Combine(_environment.WebRootPath, "oryx-manifest.toml"); if (FileSystemHelpers.FileExists(oryxManifestFile)) { _tracer.Step("Removing previous build artifact's manifest file"); FileSystemHelpers.DeleteFileSafe(oryxManifestFile); } try { var nodeModulesSymlinkFile = Path.Combine(_environment.WebRootPath, "node_modules"); Mono.Unix.UnixSymbolicLinkInfo i = new Mono.Unix.UnixSymbolicLinkInfo(nodeModulesSymlinkFile); if (i.FileType == Mono.Unix.FileTypes.SymbolicLink) { _tracer.Step("Removing node_modules symlink"); // TODO: Add support to remove Unix Symlink File in DeleteFileSafe // FileSystemHelpers.DeleteFileSafe(nodeModulesSymlinkFile); FileSystemHelpers.RemoveUnixSymlink(nodeModulesSymlinkFile, TimeSpan.FromSeconds(5)); } } catch (Exception) { // best effort } using (_tracer.Step("Writing zip file to {0}", zipFilePath)) { if (!string.IsNullOrEmpty(context.Request.ContentType) && context.Request.ContentType.Contains("multipart/form-data", StringComparison.OrdinalIgnoreCase)) { FormValueProvider formModel; using (_tracer.Step("Writing zip file to {0}", zipFilePath)) { using (var file = System.IO.File.Create(zipFilePath)) { formModel = await Request.StreamFile(file); } } } else if (deploymentInfo.ZipURL != null) { using (_tracer.Step("Writing zip file from packageUri to {0}", zipFilePath)) { using (var httpClient = new HttpClient()) using (var fileStream = new FileStream(zipFilePath, FileMode.Create, FileAccess.Write, FileShare.None, bufferSize: 4096, useAsync: true)) { var zipUrlRequest = new HttpRequestMessage(HttpMethod.Get, deploymentInfo.ZipURL); var zipUrlResponse = await httpClient.SendAsync(zipUrlRequest); try { zipUrlResponse.EnsureSuccessStatusCode(); } catch (HttpRequestException hre) { _tracer.TraceError(hre, "Failed to get file from packageUri {0}", deploymentInfo.ZipURL); throw; } using (var content = await zipUrlResponse.Content.ReadAsStreamAsync()) { await content.CopyToAsync(fileStream); } } } } else { using (var file = System.IO.File.Create(zipFilePath)) { await Request.Body.CopyToAsync(file); } } } deploymentInfo.RepositoryUrl = zipFilePath; } var result = await _deploymentManager.FetchDeploy(deploymentInfo, isAsync, UriHelper.GetRequestUri(Request), "HEAD"); switch (result) { case FetchDeploymentRequestResult.RunningAynschronously: if (isAsync) { // latest deployment keyword reserved to poll till deployment done Response.GetTypedHeaders().Location = new Uri(UriHelper.GetRequestUri(Request), String.Format("/api/deployments/{0}?deployer={1}&time={2}", Constants.LatestDeployment, deploymentInfo.Deployer, DateTime.UtcNow.ToString("yyy-MM-dd_HH-mm-ssZ"))); } return(Accepted()); case FetchDeploymentRequestResult.ForbiddenScmDisabled: // Should never hit this for zip push deploy _tracer.Trace("Scm is not enabled, reject all requests."); return(Forbid()); case FetchDeploymentRequestResult.ConflictAutoSwapOngoing: return(StatusCode(StatusCodes.Status409Conflict, Resources.Error_AutoSwapDeploymentOngoing)); case FetchDeploymentRequestResult.Pending: // Shouldn't happen here, as we disallow deferral for this use case return(Accepted()); case FetchDeploymentRequestResult.RanSynchronously: return(Ok()); case FetchDeploymentRequestResult.ConflictDeploymentInProgress: return(StatusCode(StatusCodes.Status409Conflict, Resources.Error_DeploymentInProgress)); case FetchDeploymentRequestResult.ConflictRunFromRemoteZipConfigured: return(StatusCode(StatusCodes.Status409Conflict, Resources.Error_RunFromRemoteZipConfigured)); default: return(BadRequest()); } }
void BackupFile( string fp, string cp, string hp, string pn, string n, bool history ) { string fpn = PathCombine( fp, n ); string cpn = PathCombine( cp, n ); FileInfo ffi = FileInfo( fpn ); FileInfo cfi = FileInfo( cpn ); if( (ffi == null) || (cfi == null) ) { return; } #if __MonoCS__ { Mono.Unix.UnixSymbolicLinkInfo i = new Mono.Unix.UnixSymbolicLinkInfo( fpn ); if( ! i.Exists || ! i.IsRegularFile ) { LogReason( Reason.Skipped, fpn, false ); return; } } #endif if( ! cfi.Exists ) { //..file does not exist in current, simply copy action( Action.File, n ); LogReason( Reason.Created, pn, FileCopy( fpn, cpn, false ) ); return; } /* ..check for file property changes * The date of the file is adjusted to fit within the min and max dates the archive filesystem can support. * The dates are checked to be within 1 second of each other to avoid slight inconsistencies at the millisecond level. * The file length must match. */ if( DateCompare( DateAdjust( ffi.LastWriteTimeUtc ), DateAdjust( cfi.LastWriteTimeUtc ) ) && (ffi.Length == cfi.Length ) ) { //..file has not changed, ignore return; } action( Action.File, n ); if( debug ) { StringBuilder sbf = new StringBuilder(); StringBuilder sbc = new StringBuilder(); if( ffi.CreationTime != cfi.CreationTime ) { sbf.Append( " CR[" + DisplayDate( ffi.CreationTime ) + "]" ); sbc.Append( " CR[" + DisplayDate( cfi.CreationTime ) + "]" ); } if( ffi.CreationTimeUtc != cfi.CreationTimeUtc ) { sbf.Append( " CRU[" + DisplayDate( ffi.CreationTimeUtc ) + "]" ); sbc.Append( " CRU[" + DisplayDate( cfi.CreationTimeUtc ) + "]" ); } if( ffi.LastAccessTime != cfi.LastAccessTime ) { sbf.Append( " LA[" + DisplayDate( ffi.LastAccessTime ) + "]" ); sbc.Append( " LA[" + DisplayDate( cfi.LastAccessTime ) + "]" ); } if( ffi.LastAccessTimeUtc != cfi.LastAccessTimeUtc ) { sbf.Append( " LAU[" + DisplayDate( ffi.LastAccessTimeUtc ) + "]" ); sbc.Append( " LAU[" + DisplayDate( cfi.LastAccessTimeUtc ) + "]" ); } if( ffi.LastWriteTime != cfi.LastWriteTime ) { sbf.Append( " LW[" + DisplayDate( ffi.LastWriteTime ) + "]" ); sbc.Append( " LW[" + DisplayDate( cfi.LastWriteTime ) + "]" ); } if( ffi.LastWriteTimeUtc != cfi.LastWriteTimeUtc ) { sbf.Append( " LWU[" + DisplayDate( ffi.LastWriteTimeUtc ) + "]" ); sbc.Append( " LWU[" + DisplayDate( cfi.LastWriteTimeUtc ) + "]" ); } if( ffi.Length != cfi.Length ) { sbf.Append( " LEN[" + ffi.Length .ToString() + "]" ); sbc.Append( " LEN[" + cfi.Length .ToString() + "]" ); } if( ffi.Attributes != cfi.Attributes ) { sbf.Append( " AT[" + ffi.Attributes .ToString() + "]" ); sbc.Append( " AT[" + cfi.Attributes .ToString() + "]" ); } if( ffi.IsReadOnly != cfi.IsReadOnly ) { sbf.Append( " RO[" + ffi.IsReadOnly .ToString() + "]" ); sbc.Append( " RO[" + cfi.IsReadOnly .ToString() + "]" ); } Log( "" ); LogStatus( " file" , sbf.ToString() ); LogStatus( " archive", sbc.ToString() ); } //?? Is there a better way to do this combination that tests if a file can be copied first ?? //..perhaps copy to a different file name first, move old file to history, rename copied file bool replace = false; //..move old file from current to history if( ! history ) { //..remove old file from current if( ! FileDelete( cpn ) ) { LogInfo( "Backup. failed to delete previous backup file" ); replace = true; } //..copy file to current LogReason( Reason.Modified, pn, FileCopy( fpn, cpn, replace ) ); return; } if( (hp == null) || ! DirectoryCreateDirectory( hp ) ) { return; } //..move old file from current to history string hpn = PathCombine( hp, n ); #if CHECK_HISTORY_BUG if( File.Exists( hpn ) ) { LogInfo( "Backup. file already exists in history [" + hpn + "], replacing" ); FileDelete( hpn ); } #endif if( ! FileMove( cpn, hpn ) ) { LogInfo( "Backup. failed moving current to history" ); replace = true; } //..copy new file from folder to current if( ! FileCopy( fpn, cpn, replace ) ) { LogReason( Reason.Skipped, pn, false ); return; } LogReason( Reason.Modified, pn, true ); return; }
/// <summary> /// Copy a folder and all sub-folders as quickly as possible without /// checking their contents first. /// Before calling this function, make sure the destination folder /// does not already exist. /// </summary> bool CopyFolder( string path, bool include ) { if( cancel ) { return include; } if( ! include && inc.MatchDirectory( path ) ) { include = true; } if( exc.MatchDirectory( path ) ) { return false; } bool rc = include; string cp = PathCombine( curr, path ); if( ! include || DirectoryCreateDirectory( cp ) ) { if( include ) { LogReason( Reason.Created, DisplayDirectory( path ), true ); rc = true; } string fp = PathCombine( fold, path ); foreach( string n in ListDirectories( fp ) ) { if( cancel ) { return rc; } #if __MonoCS__ { string fpn = PathCombine( fp, n ); Mono.Unix.UnixSymbolicLinkInfo i = new Mono.Unix.UnixSymbolicLinkInfo( fpn ); if( ! i.Exists || ! i.IsDirectory ) { LogReason( Reason.Skipped, fpn, false ); continue; } } #endif rc |= CopyFolder( PathCombine( path, n ), include ); } action( Action.Directory, path ); // action( Action.File, "" ); foreach( string n in ListFiles( fp ) ) { if( cancel ) { return rc; } #if __MonoCS__ { string fpn = PathCombine( fp, n ); Mono.Unix.UnixSymbolicLinkInfo i = new Mono.Unix.UnixSymbolicLinkInfo( fpn ); if( ! i.Exists || ! i.IsRegularFile ) { LogReason( Reason.Skipped, fpn, false ); continue; } } #endif string pn = PathCombine( path, n ); if( (include || inc.MatchFile( pn )) && ! exc.MatchFile( pn ) ) { if( include || DirectoryCreateDirectory( cp ) ) { action( Action.File, n ); LogReason( Reason.Created, pn, FileCopy( PathCombine( fp, n ), PathCombine( cp, n ), false ) ); rc = true; } } } } return rc; }
bool BackupCompareFolder( string path, bool include, bool history ) { /* The 'include' flag indicates an item has specifically been included * by a filter. * The 'history' flag indicates an item has specifically been marked for * a single backup only (no historical copies). * If a folder is specifically excluded with a filter, then no further * analysis is done on it. * If the folder has not specifically been included or excluded, then a * deeper analysis is done. The folder and its descendants are scanned * for files and folders which do match an include filter. */ if( ! include && inc.MatchDirectory( path ) ) { include = true ; } if( exc.MatchDirectory( path ) ) { return false; } if( history && his.MatchDirectory( path ) ) { history = false; } if( cancel ) { return include; } string cp = PathCombine( curr, path ); if( ! Directory.Exists( cp ) ) { //..if directory doesn't exist in current, then the entire tree can simply be copied. return CopyFolder( path, include ); } bool rc = include; List<string> a = new List<string>( ListDirectories( cp ) ); string fp = PathCombine( fold, path ); string hp = (hist == null) ? null : PathCombine( hist, path ); foreach( string n in ListDirectories( fp ) ) { if( cancel ) { return rc; } //..check each sub-directory in folder. #if __MonoCS__ { string fpn = PathCombine( fp, n ); Mono.Unix.UnixSymbolicLinkInfo i = new Mono.Unix.UnixSymbolicLinkInfo( fpn ); if( ! i.Exists || ! i.IsDirectory ) { LogReason( Reason.Skipped, fpn, false ); continue; } } #endif if( BackupCompareFolder( PathCombine( path, n ), include, history ) ) { foreach( string s in ListDirectories( cp, n ) ) { a.Remove( s ); } rc = true; } } action( Action.Directory, path ); // action( Action.File, "" ); if( a.Count > 0 ) { //..move deleted, renamed or excluded directories from current to history. if( ! history || ((hp != null) && DirectoryCreateDirectory( hp )) ) { foreach( string n in a ) { if( cancel ) { return rc; } action( Action.File, DisplayDirectory( n ) ); string pn = PathCombine( path, n ); if( ! history || his.MatchDirectory( pn ) ) { LogReason( Reason.Deleted, DisplayDirectory( pn ), DirectoryDelete( PathCombine( cp, n ), true ) ); } else { LogReason( Reason.Deleted, DisplayDirectory( pn ), DirectoryMove( PathCombine( cp, n ), PathCombine( hp, n ) ) ); } } } } a = new List<string>( ListFiles( cp ) ); foreach( string n in ListFiles( fp ) ) { if( cancel ) { return rc; } string pn = PathCombine( path, n ); if( (include || inc.MatchFile( pn )) && ! exc.MatchFile( pn ) ) { foreach( string s in ListFiles( cp, n ) ) { a.Remove( s ); } BackupFile( fp, cp, hp, pn, n, history && ! his.MatchFile( pn ) ); rc = true; } } if( a.Count > 0 ) { //..move deleted, renamed or excluded files from current to history. if( ! history || ((hp != null) && DirectoryCreateDirectory( hp )) ) { foreach( string n in a ) { if( cancel ) { return rc; } string pn = PathCombine( path, n ); RemoveFile( cp, hp, pn, n, history && ! his.MatchFile( pn ) ); } } } return rc; }
void ScanFolder( FolderInfo folder, string path ) { try { //..record current location string s = MatchPath.AbsoluteDirectoryPath( path ?? string.Empty ); status.scan.current = folder.Name + ":" + s; if( debug ) { Log( ".s.scan path [{0}]", s ); } Interlocked.Increment( ref status.scan.folders ); //..check if cancelled if( IsCancelRequested ) { throw new Exception( "Scan cancelled." ); } if( ! folder.IsIncludedFolder( path ) ) { if( debug ) { Log( " .s.not included" ); } return; } //..find out if folder path exists string fp = PathCombine( folder.Root, path ); if( debug ) { Log( ".s.folder path [{0}]", fp ); } try { #if __MonoCS__ { Mono.Unix.UnixSymbolicLinkInfo i = new Mono.Unix.UnixSymbolicLinkInfo( fp ); if( ! i.Exists || ! i.IsDirectory ) { return; } } #endif if( ! DirectoryExists( fp ) ) { throw new DirectoryNotFoundException( "Folder path does not exist." ); } //..find out if path exists in current string cp = PathCombine( current, folder.Name, path ); if( debug ) { Log( ".s.current path [{0}]", cp ); } try { if( ! DirectoryExists( cp ) ) { if( debug ) { Log( ".s.current path absent, copy everything" ); } //..when the folder does not exist in current, copy everything without comparing ScanQueue( ActionType.Copy, folder, path, null ); return; } List<string> a; //..scan files first if( debug ) { Log( ".s.-----> files [{0}]", MatchPath.AbsoluteDirectoryPath( path ?? string.Empty ) ); } a = new List<string>( Ctrl.ListFiles( cp ) ); foreach( string n in Ctrl.ListFiles( fp ) ) { try { if( IsCancelRequested ) { throw new Exception( "Scan cancelled." ); } Interlocked.Increment( ref status.scan.files ); string pn = PathCombine( path, n ); if( debug ) { Log( ".s.file [{0}]", pn ); } if( folder.IsIncludedFile( pn ) ) { if( debug ) { Log( ".s.is included" ); } string fpn = PathCombine( fp, n ); try { #if __MonoCS__ Mono.Unix.UnixSymbolicLinkInfo i = new Mono.Unix.UnixSymbolicLinkInfo( fpn ); if( i.Exists && i.IsRegularFile ) #endif { string cpn = PathCombine( cp, n ); try { FileInfo fi = new FileInfo( fpn ); FileInfo ci = new FileInfo( cpn ); if( debug ) { Log( ".s.compare folder file [{0}]\n with current [{1}]", fpn, cpn ); } if( ! ci.Exists || ! ctrl.FileDateMatches( fi.LastWriteTimeUtc, ci.LastWriteTimeUtc ) || (fi.Length != ci.Length) ) { if( debug ) { Log( ".s.file has changed" ); } ScanQueue( ActionType.Copy, folder, path, n ); } ListFilenameRemove( a, n ); } catch( Exception ex ) { ex.Data[ExFolderFilename ] = fpn; ex.Data[ExCurrentFilename] = cpn; Log( "Scan {0}", Except.ToString( ex, debug ) ); Interlocked.Increment( ref status.update.skipped ); LogStatus( StatusType.Skipped, folder.Name, path, n ); } } } catch( Exception ex ) { ex.Data[ExFolderFilename] = fpn; throw; } } } catch( Exception ex ) { ex.Data[ExFilename] = n; throw; } } if( a.Count > 0 ) { if( debug ) { Log( ".s.flag deleted files for removal" ); } foreach( string n in a ) { if( debug ) { Log( ".s.deleted file [{0}]", n ); } ScanQueue( ActionType.Delete, folder, path, n ); } } //..scan folders second if( debug ) { Log( ".s.-----> directories [{0}]", MatchPath.AbsoluteDirectoryPath( path ?? string.Empty ) ); } a = new List<string>( Ctrl.ListDirectories( cp ) ); foreach( string n in Ctrl.ListDirectories( fp ) ) { if( IsCancelRequested ) { throw new Exception( "Scan cancelled." ); } string pn = PathCombine( path, n ); if( debug ) { Log( ".s.directory [{0}]", pn ); } ScanFolder( folder, pn ); ListFilenameRemove( a, n ); } if( a.Count > 0 ) { if( debug ) { Log( ".s.flag deleted directories for removal" ); } foreach( string n in a ) { if( debug ) { Log( ".s.deleted directory [{0}]", n ); } ScanQueue( ActionType.Delete, folder, PathCombine( path, n ), null ); } } } catch( Exception ex ) { ex.Data[ExCurrentPath] = cp; throw; } } catch( Exception ex ) { ex.Data[ExFolderPath] = fp; throw; } } catch( Exception ex ) { ex.Data[ExPath] = path; Msg( "Scan: {0}", Except.ToString( ex, debug ) ); } }
internal static bool IsSymbolicLink(string path) { var symbolicLinkInfo = new Mono.Unix.UnixSymbolicLinkInfo(path); return(symbolicLinkInfo.IsSymbolicLink); }
static void WalkDirectoryTree(System.IO.DirectoryInfo root, Action <System.IO.FileInfo> action) { System.IO.FileInfo[] files = null; System.IO.DirectoryInfo[] subDirs = null; // First, process all the files directly under this folder try { files = root.GetFiles(); } // This is thrown if even one of the files requires permissions greater // than the application provides. catch (UnauthorizedAccessException e) { DeniedFilesAccess.Add(e.Message); } catch (System.IO.DirectoryNotFoundException e) { Console.WriteLine(e.Message); } if (files != null) { foreach (System.IO.FileInfo fi in files) { if (canPosix) { try // https://stackoverflow.com/questions/19428170/detecting-symbolic-links-and-pipes-in-mono { Mono.Unix.UnixSymbolicLinkInfo info = new Mono.Unix.UnixSymbolicLinkInfo(fi.FullName); if (info.FileType != Mono.Unix.FileTypes.RegularFile && info.FileType != Mono.Unix.FileTypes.Directory) { continue; } } catch (Exception e) { Console.WriteLine(e); continue; } } if (LinuxPathsToIgnore.Any(x => fi.FullName.StartsWith(x))) { continue; } try { action(fi); } catch (UnauthorizedAccessException e) { DeniedFilesAccess.Add(fi.FullName); continue; } catch (IOException e) { Console.WriteLine(e); continue; } catch (Exception e) { Console.WriteLine(e); continue; } } // Now find all the subdirectories under this directory. subDirs = root.GetDirectories(); foreach (System.IO.DirectoryInfo dirInfo in subDirs) { if (canPosix) { try // https://stackoverflow.com/questions/19428170/detecting-symbolic-links-and-pipes-in-mono { Mono.Unix.UnixSymbolicLinkInfo info = new Mono.Unix.UnixSymbolicLinkInfo(dirInfo.FullName); if (info.FileType != Mono.Unix.FileTypes.RegularFile && info.FileType != Mono.Unix.FileTypes.Directory) { continue; } } catch (Exception e) { Console.WriteLine(e); continue; } } // Recursive call for each subdirectory. WalkDirectoryTree(dirInfo, action); } } }
// Needed so that UnixSymbolicLinkInfo doesn't have to // be JITted on windows private void Symlink_helper () { string path = TempFolder + DSC + "DIT.Symlink"; string dir = path + DSC + "dir"; string link = path + DSC + "link"; DeleteDir (path); try { Directory.CreateDirectory (path); Directory.CreateDirectory (dir); Mono.Unix.UnixSymbolicLinkInfo li = new Mono.Unix.UnixSymbolicLinkInfo (link); li.CreateSymbolicLinkTo (dir); DirectoryInfo info = new DirectoryInfo (path); DirectoryInfo[] dirs = info.GetDirectories (); Assert.AreEqual (2, dirs.Length, "#1"); } finally { DeleteDir (path); } }
void RecursiveDelete( FolderInfo folder, string path ) { /* This method does not actually delete files, it merely counts the number of files * moved from Current to History - as in, flagged for deletion */ try { string s = folder.Name + ":" + MatchPath.AbsoluteDirectoryPath( path ?? string.Empty ); status.update.current = s; if( debug ) { Log( ".u.recursive delete [{0}]", s ); } //..check if cancelled if( IsCancelRequested ) { throw new Exception( "Update cancelled." ); } string hp = PathCombine( history, folder.Name, path ); if( debug ) { Log( ".u.history path [{0}]", hp ); } try { #if __MonoCS__ { Mono.Unix.UnixSymbolicLinkInfo i = new Mono.Unix.UnixSymbolicLinkInfo( hp ); if( ! i.Exists || ! i.IsDirectory ) { return; } } #endif if( ! DirectoryExists( hp ) ) { if( debug ) { Log( ".u.history path does not exist" ); } return; } //..flag as deleted the number of files in the folder if( debug ) { Log( ".u.-----> files [{0}]", MatchPath.AbsoluteDirectoryPath( path ?? string.Empty ) ); } foreach( string n in Ctrl.ListFiles( hp ) ) { string pn = PathCombine( path, n ); if( debug ) { Log( ".u.file [{0}]", pn ); } LogStatus( StatusType.Deleted, folder.Name, path, n ); Interlocked.Increment( ref status.update.deleted ); } //..recurse into all subdirectories if( debug ) { Log( ".u.-----> directories [{0}]", MatchPath.AbsoluteDirectoryPath( path ?? string.Empty ) ); } foreach( string n in Ctrl.ListDirectories( hp ) ) { string pn = PathCombine( path, n ); if( debug ) { Log( ".u.directory [{0}]", pn ); } RecursiveDelete( folder, pn ); } } catch( Exception ex ) { ex.Data[ExHistoryPath] = hp; throw; } } catch( Exception ex ) { ex.Data[ExPath] = path; throw; } }