/// <summary> /// Creates a new symbolic link to a file or directory. /// </summary> /// <param name="sourcePath">The path of the link to create.</param> /// <param name="targetPath">The path of the existing file or directory to point to (relative to <paramref name="sourcePath" />).</param> public static void CreateSymlink(string sourcePath, string targetPath) { try { FileUtils.CreateSymlink(sourcePath, targetPath); } catch (IOException) when(WindowsUtils.IsWindows) { Log.Debug("Creating Cygwin symlink instead of NTFS symlink due to insufficient permissions: " + sourcePath); CygwinUtils.CreateSymlink(sourcePath, targetPath); } }
public override void Verify(string parentPath) { string path = Path.Combine(parentPath, Name); (File.Exists(path) || Directory.Exists(path)).Should().BeTrue(because: $"Symlink '{path}' should exist."); bool isSymlink = UnixUtils.IsUnix ? FileUtils.IsSymlink(path, out string?target) : CygwinUtils.IsSymlink(path, out target); isSymlink.Should().BeTrue(because: $"'{path}' should be a symlink."); target.Should().Be(Target, because: $"Symlink '{path}' should point to correct target."); }
public override void Build(string parentPath) { string path = Path.Combine(parentPath, Name); if (UnixUtils.IsUnix) { FileUtils.CreateSymlink(path, Target); } else { CygwinUtils.CreateSymlink(path, Target); } }
/// <summary> /// Checks whether a file is a symbolic link. /// </summary> /// <param name="path">The path of the file to check.</param> /// <param name="manifestElement">The file's equivalent manifest entry, if available.</param> /// <param name="target">Returns the target the symbolic link points to if it exists.</param> /// <returns><c>true</c> if <paramref name="manifestElement"/> points to a symbolic link; <c>false</c> otherwise.</returns> public static bool IsSymlink(string path, [NotNullWhen(true)] out string?target, ManifestElement?manifestElement = null) { if (FileUtils.IsSymlink(path, out target) || WindowsUtils.IsWindowsNT && CygwinUtils.IsSymlink(path, out target)) { return(true); } if (manifestElement is ManifestSymlink) { target = File.ReadAllText(path, Encoding.UTF8); return(true); } return(false); }
protected void CreateSymlink(string name) { if (WindowsUtils.IsWindows) { CygwinUtils.CreateSymlink( sourcePath: Path.Combine(_sourceDirectory, name), targetPath: Contents); } else { FileUtils.CreateSymlink( sourcePath: Path.Combine(_sourceDirectory, name), targetPath: Contents); } }
public void TestExtractUnixArchiveWithSymlink() { using (var extractor = new TarExtractor(typeof(TarExtractorTest).GetEmbeddedStream("testArchive.tar"), _sandbox)) extractor.Run(); string target; string source = Path.Combine(_sandbox, "symlink"); if (UnixUtils.IsUnix) { FileUtils.IsSymlink(source, out target).Should().BeTrue(); } else { CygwinUtils.IsSymlink(source, out target).Should().BeTrue(); } target.Should().Be("subdir1/regular", because: "Symlink should point to 'regular'"); }
/// <summary> /// Handles a file system entry the OS reports as a file. /// </summary> /// <param name="entry">The file entry to handle.</param> /// <param name="externalXbits">A list of fully qualified paths of files that are named in the <see cref="FlagUtils.SymlinkFile"/>.</param> /// <param name="externalSymlinks">A list of fully qualified paths of files that are named in the <see cref="FlagUtils.SymlinkFile"/>.</param> /// <exception cref="NotSupportedException">The <paramref name="entry"/> has illegal properties (e.g. is a device file, has line breaks in the filename, etc.).</exception> /// <exception cref="IOException">There was an error reading the file.</exception> /// <exception cref="UnauthorizedAccessException">You have insufficient rights to read the file.</exception> private void HandleEntry([NotNull] FileInfo entry, [NotNull] ICollection <string> externalXbits, [NotNull] ICollection <string> externalSymlinks) { if (_isUnixFS) { string symlinkTarget; if (FileUtils.IsSymlink(entry.FullName, out symlinkTarget)) { HandleSymlink(entry, Encoding.UTF8.GetBytes(symlinkTarget)); } else if (FileUtils.IsExecutable(entry.FullName)) { HandleFile(entry, executable: true); } else if (!FileUtils.IsRegularFile(entry.FullName)) { throw new NotSupportedException(string.Format(Resources.IllegalFileType, entry.FullName)); } else { HandleFile(entry); } } else { string symlinkTarget; if (CygwinUtils.IsSymlink(entry.FullName, out symlinkTarget)) { HandleSymlink(entry, Encoding.UTF8.GetBytes(symlinkTarget)); } else if (externalSymlinks.Contains(entry.FullName)) { HandleSymlink(entry, File.ReadAllBytes(entry.FullName)); } else if (externalXbits.Contains(entry.FullName)) { HandleFile(entry, executable: true); } else { HandleFile(entry); } } }
/// <summary> /// Creates a symbolic link in the filesystem if possible; stores it in a <see cref="FlagUtils.SymlinkFile"/> otherwise. /// </summary> /// <param name="source">A path relative to <see cref="SubDir"/>.</param> /// <param name="target">The target the symbolic link shall point to relative to <paramref name="source"/>. May use non-native path separators!</param> protected void CreateSymlink([NotNull] string source, [NotNull] string target) { #region Sanity checks if (string.IsNullOrEmpty(source)) { throw new ArgumentNullException(nameof(source)); } if (string.IsNullOrEmpty(target)) { throw new ArgumentNullException(nameof(target)); } #endregion string sourceAbsolute = CombinePath(source); string sourceDirectory = Path.GetDirectoryName(sourceAbsolute); if (sourceDirectory != null && !Directory.Exists(sourceDirectory)) { Directory.CreateDirectory(sourceDirectory); } if (_isUnixFS) { FileUtils.CreateSymlink(sourceAbsolute, target); } else if (WindowsUtils.IsWindowsNT) { // NOTE: NTFS symbolic links require admin privileges; use Cygwin symlinks instead CygwinUtils.CreateSymlink(sourceAbsolute, target); } else { // Write link data as a normal file File.WriteAllText(sourceAbsolute, target); // Some OSes can't store the symlink flag directly in the filesystem; remember in a text-file instead string flagRelativePath = string.IsNullOrEmpty(Destination) ? source : Path.Combine(Destination, source); FlagUtils.Set(Path.Combine(TargetDir, FlagUtils.SymlinkFile), flagRelativePath); } }
public void TestApplyRecipeArchiv() { using (var archiveFile = new TemporaryFile("0install-unit-tests")) { typeof(ArchiveExtractorTest).CopyEmbeddedToFile("testArchive.zip", archiveFile); var downloadedFiles = new[] { archiveFile }; var recipe = new Recipe { Steps = { new Archive { MimeType = Archive.MimeTypeZip, Destination = "subDir" } } }; using (TemporaryDirectory recipeDir = recipe.Apply(downloadedFiles, new SilentTaskHandler())) { // /dest/symlink [S] string path = Path.Combine(recipeDir, "subDir", "symlink"); File.Exists(path).Should().BeTrue(because: "File should exist: " + path); if (UnixUtils.IsUnix) { FileUtils.IsSymlink(path).Should().BeTrue(); } else { CygwinUtils.IsSymlink(path).Should().BeTrue(); } // /dest/subdir2/executable [deleted] path = Path.Combine(recipeDir, "subDir", "subdir2", "executable"); File.Exists(path).Should().BeTrue(because: "File should exist: " + path); if (!UnixUtils.IsUnix) { FlagUtils.GetFiles(FlagUtils.XbitFile, recipeDir).Should().BeEquivalentTo(path); } } } }