Skip to content

Commit 543a744

Browse files
authored
HDDS-15102. Avoid ArchiveOutputStream.createArchiveEntry due to libnss issue (#10117)
1 parent d5ec23e commit 543a744

2 files changed

Lines changed: 43 additions & 13 deletions

File tree

hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/utils/Archiver.java

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,13 +28,15 @@
2828
import java.nio.file.Files;
2929
import java.nio.file.Path;
3030
import java.nio.file.Paths;
31+
import java.nio.file.attribute.BasicFileAttributes;
3132
import java.util.stream.Stream;
3233
import org.apache.commons.compress.archivers.ArchiveEntry;
3334
import org.apache.commons.compress.archivers.ArchiveInputStream;
3435
import org.apache.commons.compress.archivers.ArchiveOutputStream;
3536
import org.apache.commons.compress.archivers.tar.TarArchiveEntry;
3637
import org.apache.commons.compress.archivers.tar.TarArchiveInputStream;
3738
import org.apache.commons.compress.archivers.tar.TarArchiveOutputStream;
39+
import org.apache.commons.compress.archivers.tar.TarConstants;
3840
import org.apache.commons.io.IOUtils;
3941
import org.apache.hadoop.hdds.HddsUtils;
4042
import org.apache.hadoop.ozone.OzoneConsts;
@@ -79,12 +81,42 @@ public static byte[] readEntry(InputStream input, final long size)
7981
return output.toByteArray();
8082
}
8183

84+
private static TarArchiveEntry createBasicTarArchiveEntry(File file, String entryName)
85+
throws IOException {
86+
final Path path = file.toPath();
87+
88+
final TarArchiveEntry entry;
89+
if (Files.isDirectory(path)) {
90+
final int nameLength = entryName.length();
91+
final String dirName = nameLength == 0 || entryName.charAt(nameLength - 1) != '/'
92+
? entryName + "/"
93+
: entryName;
94+
entry = new TarArchiveEntry(dirName, TarConstants.LF_DIR);
95+
entry.setMode(TarArchiveEntry.DEFAULT_DIR_MODE);
96+
} else {
97+
entry = new TarArchiveEntry(entryName);
98+
entry.setMode(TarArchiveEntry.DEFAULT_FILE_MODE);
99+
entry.setSize(Files.size(path));
100+
}
101+
102+
try {
103+
BasicFileAttributes attrs = Files.readAttributes(
104+
file.toPath(), BasicFileAttributes.class);
105+
entry.setLastModifiedTime(attrs.lastModifiedTime());
106+
entry.setLastAccessTime(attrs.lastAccessTime());
107+
entry.setCreationTime(attrs.creationTime());
108+
} catch (IOException e) {
109+
entry.setModTime(file.lastModified()); // fallback
110+
}
111+
return entry;
112+
}
113+
82114
public static void includePath(Path dir, String subdir,
83115
ArchiveOutputStream<TarArchiveEntry> archiveOutput) throws IOException {
84116

85117
// Add a directory entry before adding files, in case the directory is
86118
// empty.
87-
TarArchiveEntry entry = archiveOutput.createArchiveEntry(dir.toFile(), subdir);
119+
TarArchiveEntry entry = createBasicTarArchiveEntry(dir.toFile(), subdir);
88120
archiveOutput.putArchiveEntry(entry);
89121
archiveOutput.closeArchiveEntry();
90122

@@ -105,7 +137,7 @@ public static void includePath(Path dir, String subdir,
105137
public static long includeFile(File file, String entryName,
106138
ArchiveOutputStream<TarArchiveEntry> archiveOutput) throws IOException {
107139
final long bytes;
108-
TarArchiveEntry entry = archiveOutput.createArchiveEntry(file, entryName);
140+
TarArchiveEntry entry = createBasicTarArchiveEntry(file, entryName);
109141
archiveOutput.putArchiveEntry(entry);
110142
try (InputStream input = Files.newInputStream(file.toPath())) {
111143
bytes = IOUtils.copy(input, archiveOutput, getBufferSize(file.length()));
@@ -138,7 +170,7 @@ public static long linkAndIncludeFile(File file, String entryName,
138170
long bytes = 0;
139171
try {
140172
Files.createLink(link.toPath(), file.toPath());
141-
TarArchiveEntry entry = archiveOutput.createArchiveEntry(link, entryName);
173+
TarArchiveEntry entry = createBasicTarArchiveEntry(link, entryName);
142174
archiveOutput.putArchiveEntry(entry);
143175
try (InputStream input = Files.newInputStream(link.toPath())) {
144176
bytes = IOUtils.copyLarge(input, archiveOutput);

hadoop-hdds/framework/src/test/java/org/apache/hadoop/hdds/utils/TestArchiver.java

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
import org.junit.jupiter.api.Test;
4343
import org.junit.jupiter.params.ParameterizedTest;
4444
import org.junit.jupiter.params.provider.ValueSource;
45+
import org.mockito.ArgumentCaptor;
4546
import org.mockito.MockedStatic;
4647

4748
/** Test {@link Archiver}. */
@@ -76,22 +77,19 @@ void testLinkAndIncludeFileSuccessfulHardLink() throws IOException {
7677
Files.write(tempFile.toPath(), "Test Content".getBytes(StandardCharsets.UTF_8));
7778

7879
TarArchiveOutputStream mockArchiveOutput = mock(TarArchiveOutputStream.class);
79-
TarArchiveEntry mockEntry = new TarArchiveEntry(entryName);
80-
AtomicBoolean isHardLinkCreated = new AtomicBoolean(false);
81-
when(mockArchiveOutput.createArchiveEntry(any(File.class), eq(entryName)))
82-
.thenAnswer(invocation -> {
83-
File linkFile = invocation.getArgument(0);
84-
isHardLinkCreated.set(Files.isSameFile(tempFile.toPath(), linkFile.toPath()));
85-
return mockEntry;
86-
});
8780

8881
// Call method under test
8982
long bytesCopied = Archiver.linkAndIncludeFile(tempFile, entryName, mockArchiveOutput, tmpDir);
9083
assertEquals(Files.size(tempFile.toPath()), bytesCopied);
9184
// Verify archive interactions
92-
verify(mockArchiveOutput, times(1)).putArchiveEntry(mockEntry);
85+
ArgumentCaptor<TarArchiveEntry> entryCaptor = ArgumentCaptor.forClass(TarArchiveEntry.class);
86+
verify(mockArchiveOutput, times(1)).putArchiveEntry(entryCaptor.capture());
9387
verify(mockArchiveOutput, times(1)).closeArchiveEntry();
94-
assertTrue(isHardLinkCreated.get());
88+
89+
TarArchiveEntry capturedEntry = entryCaptor.getValue();
90+
assertEquals(entryName, capturedEntry.getName());
91+
assertEquals(Files.size(tempFile.toPath()), capturedEntry.getSize());
92+
9593
assertFalse(Files.exists(tmpDir.resolve(entryName)));
9694
// Cleanup
9795
assertTrue(tempFile.delete());

0 commit comments

Comments
 (0)