Skip to content

Commit

Permalink
fix icsharpcode#337: use absolute paths consistently, even under work…
Browse files Browse the repository at this point in the history
…ing dir

WIP. This change updates the behavior of adding files under the current working dir when the RootPath is set

If the rootpath is unset, the behavior is unchanged.

If the rootpath is a relative directory under the current directory, the current directory + root path will be removed from the start of the entry filepath

If the rootpath is an absolute directory under the current directory, the root path will be removed from the start of the entry filepath
  • Loading branch information
Chris-Johnston committed Aug 26, 2022
1 parent 519ed73 commit 4726baf
Show file tree
Hide file tree
Showing 3 changed files with 205 additions and 4 deletions.
20 changes: 20 additions & 0 deletions src/ICSharpCode.SharpZipLib/Tar/TarArchive.cs
Expand Up @@ -855,14 +855,34 @@ private void WriteEntryCore(TarEntry sourceEntry, bool recurse)

string newName = null;

// need to have a test if the root path is set to a child directory of the working directory
var currentDirectory = Directory.GetCurrentDirectory()
.ToTarArchivePath();

if (!String.IsNullOrEmpty(rootPath))
{
// hack: fix this

if (entry.Name.StartsWith(rootPath, StringComparison.OrdinalIgnoreCase))
{
newName = entry.Name.Substring(rootPath.Length + 1);
}
// root path is set, is root path under the current directory?
else if (entry.Name.StartsWith(currentDirectory + "/" + RootPath, StringComparison.OrdinalIgnoreCase))
{
newName = entry.Name.Substring(rootPath.Length + 2 + currentDirectory.Length);
}
}
else
{

if (entry.Name.StartsWith(currentDirectory, StringComparison.OrdinalIgnoreCase))
{
newName = entry.Name.Substring(currentDirectory.Length);
}
}


if (pathPrefix != null)
{
newName = (newName == null) ? pathPrefix + "/" + entry.Name : pathPrefix + "/" + newName;
Expand Down
14 changes: 10 additions & 4 deletions src/ICSharpCode.SharpZipLib/Tar/TarEntry.cs
Expand Up @@ -348,11 +348,17 @@ public void GetFileTarHeader(TarHeader header, string file)
// bugfix from torhovl from #D forum:
string name = file;

// not sure if I understand this comment, unsure if this needs to move
// 23-Jan-2004 GnuTar allows device names in path where the name is not local to the current directory
if (name.IndexOf(Directory.GetCurrentDirectory(), StringComparison.Ordinal) == 0)
{
name = name.Substring(Directory.GetCurrentDirectory().Length);
}

// the functional difference here is that TarEntry has changed
// is this something that we are concerned about?

// TODO: this has moved
//if (name.IndexOf(Directory.GetCurrentDirectory(), StringComparison.Ordinal) == 0)
//{
// name = name.Substring(Directory.GetCurrentDirectory().Length);
//}

/*
if (Path.DirectorySeparatorChar == '\\')
Expand Down
175 changes: 175 additions & 0 deletions test/ICSharpCode.SharpZipLib.Tests/Tar/TarTests.cs
Expand Up @@ -8,6 +8,7 @@
using System.Threading;
using System.Threading.Tasks;
using NUnit.Framework.Internal;
using System.Linq;

namespace ICSharpCode.SharpZipLib.Tests.Tar
{
Expand Down Expand Up @@ -916,5 +917,179 @@ public void RootPathIsRespected()
}
}
}

/// <summary>
/// This tests ensure that the <see cref="TarArchive.RootPath"/> property is respected, even if the
/// path is under the current working directory.
/// </summary>
[Test]
[Category("Tar")]
public void RootPathUnderWorkDirRespected()
{
// If a user specifies that the RootDir is a path under the working directory
// the RootDir properly must correctly trim away the root path
// this must not alter existing behavior
using (var workDir = new TempDir())
using (var tarFileName = new TempFile())
using (var extractDirectory = new TempDir())
{
// the files created must be under the current working dir
Environment.CurrentDirectory = workDir.FullName;

// create a temp dir and file under this path
var expectDir = Path.Combine(workDir.FullName, "temp"); // TODO: improve quality of this
Directory.CreateDirectory(expectDir);
var fileName = Path.Combine(expectDir, "testFile.txt");
File.WriteAllText(fileName, "test123");

// extract files under the given path
using (var tarFile = File.Open(tarFileName.FullName, FileMode.Create))
{
using (var tarOutputStream = TarArchive.CreateOutputTarArchive(tarFile))
{
tarOutputStream.RootPath = Path.Combine(Environment.CurrentDirectory, "temp");
var entry = TarEntry.CreateEntryFromFile(fileName);
tarOutputStream.WriteEntry(entry, true);
}
}

using (var file = File.OpenRead(tarFileName.FullName))
{
using (var archive = TarArchive.CreateInputTarArchive(file, Encoding.UTF8))
{
archive.ExtractContents(extractDirectory.FullName);
}
}

// the resulting files must be the same as the expectation dir, should no longer have the "temp" prefix
var expectationDirectory = new DirectoryInfo(expectDir);
var expectedFile = expectationDirectory.GetFiles("", SearchOption.AllDirectories)
.First();

// the archive should contain the entry "testFile.txt", not "temp/testFile.txt", because
// the root dir is configured to "{CurrentDirectory}/tmp/"
FileAssert.DoesNotExist(Path.Combine(extractDirectory.FullName, "temp", "testFile.txt"));
FileAssert.Exists(Path.Combine(extractDirectory.FullName, "testFile.txt"));

FileAssert.AreEqual(fileName, Path.Combine(extractDirectory.FullName, "testFile.txt"));
}
}

/// <summary>
/// This tests ensure that the <see cref="TarArchive.RootPath"/> property is respected, even if the
/// path is under the current working directory.
/// </summary>
[Test]
[Category("Tar")]
public void RootPathUnderWorkDirRespectedExistingBehavior()
{
// If a user specifies that the RootDir is a path under the working directory
// the RootDir properly must correctly trim away the root path
// this must not alter existing behavior
using (var workDir = new TempDir())
using (var tarFileName = new TempFile())
using (var extractDirectory = new TempDir())
{
// the files created must be under the current working dir
Environment.CurrentDirectory = workDir.FullName;

// create a temp dir and file under this path
var expectDir = Path.Combine(workDir.FullName, "temp"); // TODO: improve quality of this
Directory.CreateDirectory(expectDir);
var fileName = Path.Combine(expectDir, "testFile.txt");
File.WriteAllText(fileName, "test123");

// extract files under the given path
using (var tarFile = File.Open(tarFileName.FullName, FileMode.Create))
{
using (var tarOutputStream = TarArchive.CreateOutputTarArchive(tarFile))
{
// when root path is NOT included, maintain the existing behavior
// tarOutputStream.RootPath = Path.Combine(Environment.CurrentDirectory, "temp");
var entry = TarEntry.CreateEntryFromFile(fileName);
tarOutputStream.WriteEntry(entry, true);
}
}

using (var file = File.OpenRead(tarFileName.FullName))
{
using (var archive = TarArchive.CreateInputTarArchive(file, Encoding.UTF8))
{
archive.ExtractContents(extractDirectory.FullName);
}
}

// the resulting files must be the same as the expectation dir, should no longer have the "temp" prefix
var expectationDirectory = new DirectoryInfo(expectDir);
var expectedFile = expectationDirectory.GetFiles("", SearchOption.AllDirectories)
.First();

// the archive should contain the entry "testFile.txt", not "temp/testFile.txt", because
// the root dir is configured to "{CurrentDirectory}/tmp/"
FileAssert.Exists(Path.Combine(extractDirectory.FullName, "temp", "testFile.txt"));
FileAssert.DoesNotExist(Path.Combine(extractDirectory.FullName, "testFile.txt"));

FileAssert.AreEqual(fileName, Path.Combine(extractDirectory.FullName, "temp", "testFile.txt"));
}
}

/// <summary>
/// This tests ensure that the <see cref="TarArchive.RootPath"/> property is respected, even if the
/// path is under the current working directory.
/// </summary>
[Test]
[Category("Tar")]
public void RootPathUnderWorkDirRespectedExistingBehaviorRootPathIsRelative()
{
// If a user specifies that the RootDir is a path under the working directory
// the RootDir properly must correctly trim away the root path
// this must not alter existing behavior
using (var workDir = new TempDir())
using (var tarFileName = new TempFile())
using (var extractDirectory = new TempDir())
{
// the files created must be under the current working dir
Environment.CurrentDirectory = workDir.FullName;

// create a temp dir and file under this path
var expectDir = Path.Combine(workDir.FullName, "temp"); // TODO: improve quality of this
Directory.CreateDirectory(expectDir);
var fileName = Path.Combine(expectDir, "testFile.txt");
File.WriteAllText(fileName, "test123");

// extract files under the given path
using (var tarFile = File.Open(tarFileName.FullName, FileMode.Create))
{
using (var tarOutputStream = TarArchive.CreateOutputTarArchive(tarFile))
{
// when root path is NOT included, maintain the existing behavior
// tarOutputStream.RootPath = Path.Combine(Environment.CurrentDirectory, "temp");
tarOutputStream.RootPath = "temp";
var entry = TarEntry.CreateEntryFromFile(fileName);
tarOutputStream.WriteEntry(entry, true);
}
}

using (var file = File.OpenRead(tarFileName.FullName))
{
using (var archive = TarArchive.CreateInputTarArchive(file, Encoding.UTF8))
{
archive.ExtractContents(extractDirectory.FullName);
}
}

// the resulting files must be the same as the expectation dir, should no longer have the "temp" prefix
var expectationDirectory = new DirectoryInfo(expectDir);
var expectedFile = expectationDirectory.GetFiles("", SearchOption.AllDirectories)
.First();

// the archive should contain the entry "testFile.txt", not "temp/testFile.txt", because
// the root dir is configured to "{CurrentDirectory}/tmp/"
FileAssert.DoesNotExist(Path.Combine(extractDirectory.FullName, "temp", "testFile.txt"));
FileAssert.Exists(Path.Combine(extractDirectory.FullName, "testFile.txt"));

FileAssert.AreEqual(fileName, Path.Combine(extractDirectory.FullName, "temp", "testFile.txt"));
}
}
}
}

0 comments on commit 4726baf

Please sign in to comment.