View Javadoc
1   /*
2    *  Licensed to the Apache Software Foundation (ASF) under one or more
3    *  contributor license agreements.  See the NOTICE file distributed with
4    *  this work for additional information regarding copyright ownership.
5    *  The ASF licenses this file to You under the Apache License, Version 2.0
6    *  (the "License"); you may not use this file except in compliance with
7    *  the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   *  Unless required by applicable law or agreed to in writing, software
12   *  distributed under the License is distributed on an "AS IS" BASIS,
13   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   *  See the License for the specific language governing permissions and
15   *  limitations under the License.
16   */
17  
18  package org.apache.commons.compress.archivers.tar;
19  
20  import static org.junit.jupiter.api.Assertions.assertEquals;
21  import static org.junit.jupiter.api.Assertions.assertNotNull;
22  import static org.junit.jupiter.api.Assertions.assertNull;
23  import static org.junit.jupiter.api.Assertions.assertTrue;
24  
25  import java.io.BufferedInputStream;
26  import java.io.InputStream;
27  import java.nio.file.Files;
28  import java.nio.file.attribute.FileTime;
29  import java.time.Instant;
30  
31  import org.apache.commons.compress.AbstractTest;
32  import org.junit.jupiter.api.Test;
33  
34  public class FileTimesIT extends AbstractTest {
35  
36      private void assertGlobalHeaders(final TarArchiveEntry e) {
37          assertEquals(5, e.getExtraPaxHeaders().size());
38          assertEquals("exustar", e.getExtraPaxHeader("SCHILY.archtype"), "SCHILY.archtype");
39          assertEquals("1647478879.579980900", e.getExtraPaxHeader("SCHILY.volhdr.dumpdate"), "SCHILY.volhdr.dumpdate");
40          assertEquals("star 1.6 (x86_64-unknown-linux-gnu) 2019/04/01", e.getExtraPaxHeader("SCHILY.release"), "SCHILY.release");
41          assertEquals("20", e.getExtraPaxHeader("SCHILY.volhdr.blocksize"), "SCHILY.volhdr.blocksize");
42          assertEquals("1", e.getExtraPaxHeader("SCHILY.volhdr.volno"), "SCHILY.volhdr.volno");
43      }
44  
45      // Extended POSIX.1-2001 standard tar + x-header
46      // Created using s-tar 1.6
47      @Test
48      public void testReadTimeFromTarEpax() throws Exception {
49          final String file = "COMPRESS-612/test-times-epax-folder.tar";
50          try (InputStream in = new BufferedInputStream(Files.newInputStream(getPath(file)));
51                  TarArchiveInputStream tin = new TarArchiveInputStream(in)) {
52              TarArchiveEntry e = tin.getNextTarEntry();
53              assertNotNull(e);
54              assertTrue(e.getExtraPaxHeaders().isEmpty());
55              assertEquals("test/", e.getName());
56              assertEquals(TarConstants.LF_DIR, e.getLinkFlag());
57              assertTrue(e.isDirectory());
58              assertEquals(toFileTime("2022-03-17T00:24:44.147126600Z"), e.getLastModifiedTime(), "mtime");
59              assertEquals(toFileTime("2022-03-17T01:02:11.910960100Z"), e.getLastAccessTime(), "atime");
60              assertEquals(toFileTime("2022-03-17T00:24:44.147126600Z"), e.getStatusChangeTime(), "ctime");
61              assertNull(e.getCreationTime(), "birthtime");
62              e = tin.getNextTarEntry();
63              assertNotNull(e);
64              assertTrue(e.getExtraPaxHeaders().isEmpty());
65              assertEquals("test/test-times.txt", e.getName());
66              assertEquals(TarConstants.LF_NORMAL, e.getLinkFlag());
67              assertTrue(e.isFile());
68              assertEquals(toFileTime("2022-03-17T00:38:20.470751500Z"), e.getLastModifiedTime(), "mtime");
69              assertEquals(toFileTime("2022-03-17T00:38:20.536752000Z"), e.getLastAccessTime(), "atime");
70              assertEquals(toFileTime("2022-03-17T00:38:20.470751500Z"), e.getStatusChangeTime(), "ctime");
71              assertNull(e.getCreationTime(), "birthtime");
72              assertNull(tin.getNextTarEntry());
73          }
74      }
75  
76      // 'xustar' format - always x-header
77      @Test
78      public void testReadTimeFromTarExustar() throws Exception {
79          final String file = "COMPRESS-612/test-times-exustar-folder.tar";
80          try (InputStream in = new BufferedInputStream(Files.newInputStream(getPath(file)));
81                  TarArchiveInputStream tin = new TarArchiveInputStream(in)) {
82              TarArchiveEntry e = tin.getNextTarEntry();
83              assertNotNull(e);
84              assertEquals("test/", e.getName());
85              assertEquals(TarConstants.LF_DIR, e.getLinkFlag());
86              assertTrue(e.isDirectory());
87              assertEquals(toFileTime("2022-03-17T00:24:44.147126600Z"), e.getLastModifiedTime(), "mtime");
88              assertEquals(toFileTime("2022-03-17T00:47:00.367783300Z"), e.getLastAccessTime(), "atime");
89              assertEquals(toFileTime("2022-03-17T00:24:44.147126600Z"), e.getStatusChangeTime(), "ctime");
90              assertNull(e.getCreationTime(), "birthtime");
91              assertGlobalHeaders(e);
92              e = tin.getNextTarEntry();
93              assertEquals("test/test-times.txt", e.getName());
94              assertEquals(TarConstants.LF_NORMAL, e.getLinkFlag());
95              assertTrue(e.isFile());
96              assertEquals(toFileTime("2022-03-17T00:38:20.470751500Z"), e.getLastModifiedTime(), "mtime");
97              assertEquals(toFileTime("2022-03-17T00:38:20.536752000Z"), e.getLastAccessTime(), "atime");
98              assertEquals(toFileTime("2022-03-17T00:38:20.470751500Z"), e.getStatusChangeTime(), "ctime");
99              assertNull(e.getCreationTime(), "birthtime");
100             assertGlobalHeaders(e);
101             assertNull(tin.getNextTarEntry());
102         }
103     }
104 
105     // GNU tar format 1989 (violates POSIX)
106     // Created using GNU tar
107     @Test
108     public void testReadTimeFromTarGnu() throws Exception {
109         final String file = "COMPRESS-612/test-times-gnu.tar";
110         try (InputStream in = new BufferedInputStream(Files.newInputStream(getPath(file)));
111                 TarArchiveInputStream tin = new TarArchiveInputStream(in)) {
112             final TarArchiveEntry e = tin.getNextTarEntry();
113             assertNotNull(e);
114             assertTrue(e.getExtraPaxHeaders().isEmpty());
115             assertEquals(toFileTime("2022-03-14T01:25:03Z"), e.getLastModifiedTime(), "mtime");
116             assertNull(e.getLastAccessTime(), "atime");
117             assertNull(e.getStatusChangeTime(), "ctime");
118             assertNull(e.getCreationTime(), "birthtime");
119             assertNull(tin.getNextTarEntry());
120         }
121     }
122 
123     // GNU tar format 1989 (violates POSIX)
124     // Created using GNU tar
125     @Test
126     public void testReadTimeFromTarGnuIncremental() throws Exception {
127         final String file = "COMPRESS-612/test-times-gnu-incremental.tar";
128         try (InputStream in = new BufferedInputStream(Files.newInputStream(getPath(file)));
129                 TarArchiveInputStream tin = new TarArchiveInputStream(in)) {
130             TarArchiveEntry e = tin.getNextTarEntry();
131             assertNotNull(e);
132             assertTrue(e.getExtraPaxHeaders().isEmpty());
133             assertEquals("test-times.txt", e.getName());
134             assertEquals(toFileTime("2022-03-14T01:25:03Z"), e.getLastModifiedTime(), "mtime");
135             assertNull(e.getLastAccessTime(), "atime");
136             assertNull(e.getStatusChangeTime(), "ctime");
137             assertNull(e.getCreationTime(), "birthtime");
138             e = tin.getNextTarEntry();
139             assertNotNull(e);
140             assertTrue(e.getExtraPaxHeaders().isEmpty());
141             assertEquals("test-times.txt", e.getName());
142             assertEquals(toFileTime("2022-03-14T03:17:05Z"), e.getLastModifiedTime(), "mtime");
143             assertEquals(toFileTime("2022-03-14T03:17:10Z"), e.getLastAccessTime(), "atime");
144             assertEquals(toFileTime("2022-03-14T03:17:10Z"), e.getStatusChangeTime(), "ctime");
145             assertNull(e.getCreationTime(), "birthtime");
146             assertNull(tin.getNextTarEntry());
147         }
148     }
149 
150     // GNU tar format 1989 (violates POSIX)
151     // Created using s-tar 1.6, which somehow differs from GNU tar's.
152     @Test
153     public void testReadTimeFromTarGnuTar() throws Exception {
154         final String file = "COMPRESS-612/test-times-gnutar.tar";
155         try (InputStream in = new BufferedInputStream(Files.newInputStream(getPath(file)));
156                 TarArchiveInputStream tin = new TarArchiveInputStream(in)) {
157             final TarArchiveEntry e = tin.getNextTarEntry();
158             assertNotNull(e);
159             assertTrue(e.getExtraPaxHeaders().isEmpty());
160             assertEquals(toFileTime("2022-03-17T01:52:25Z"), e.getLastModifiedTime(), "mtime");
161             assertEquals(toFileTime("2022-03-17T01:52:25Z"), e.getLastAccessTime(), "atime");
162             assertEquals(toFileTime("2022-03-17T01:52:25Z"), e.getStatusChangeTime(), "ctime");
163             assertNull(e.getCreationTime(), "birthtime");
164             assertNull(tin.getNextTarEntry());
165         }
166     }
167 
168     // Old BSD tar format
169     @Test
170     public void testReadTimeFromTarOldBsdTar() throws Exception {
171         final String file = "COMPRESS-612/test-times-oldbsdtar.tar";
172         try (InputStream in = new BufferedInputStream(Files.newInputStream(getPath(file)));
173                 TarArchiveInputStream tin = new TarArchiveInputStream(in)) {
174             final TarArchiveEntry e = tin.getNextTarEntry();
175             assertNotNull(e);
176             assertTrue(e.getExtraPaxHeaders().isEmpty());
177             assertEquals(toFileTime("2022-03-17T01:52:25Z"), e.getLastModifiedTime(), "mtime");
178             assertNull(e.getLastAccessTime(), "atime");
179             assertNull(e.getStatusChangeTime(), "ctime");
180             assertNull(e.getCreationTime(), "birthtime");
181             assertNull(tin.getNextTarEntry());
182         }
183     }
184 
185     // Format used by GNU tar of versions prior to 1.12
186     // Created using GNU tar
187     @Test
188     public void testReadTimeFromTarOldGnu() throws Exception {
189         final String file = "COMPRESS-612/test-times-oldgnu.tar";
190         try (InputStream in = new BufferedInputStream(Files.newInputStream(getPath(file)));
191                 TarArchiveInputStream tin = new TarArchiveInputStream(in)) {
192             final TarArchiveEntry e = tin.getNextTarEntry();
193             assertNotNull(e);
194             assertTrue(e.getExtraPaxHeaders().isEmpty());
195             assertEquals(toFileTime("2022-03-14T01:25:03Z"), e.getLastModifiedTime(), "mtime");
196             assertNull(e.getLastAccessTime(), "atime");
197             assertNull(e.getStatusChangeTime(), "ctime");
198             assertNull(e.getCreationTime(), "birthtime");
199             assertNull(tin.getNextTarEntry());
200         }
201     }
202 
203     // Format used by GNU tar of versions prior to 1.12
204     // Created using GNU tar
205     @Test
206     public void testReadTimeFromTarOldGnuIncremental() throws Exception {
207         final String file = "COMPRESS-612/test-times-oldgnu-incremental.tar";
208         try (InputStream in = new BufferedInputStream(Files.newInputStream(getPath(file)));
209                 TarArchiveInputStream tin = new TarArchiveInputStream(in)) {
210             TarArchiveEntry e = tin.getNextTarEntry();
211             assertNotNull(e);
212             assertTrue(e.getExtraPaxHeaders().isEmpty());
213             assertEquals("test-times.txt", e.getName());
214             assertEquals(toFileTime("2022-03-14T01:25:03Z"), e.getLastModifiedTime(), "mtime");
215             assertNull(e.getLastAccessTime(), "atime");
216             assertNull(e.getStatusChangeTime(), "ctime");
217             assertNull(e.getCreationTime(), "birthtime");
218             e = tin.getNextTarEntry();
219             assertNotNull(e);
220             assertTrue(e.getExtraPaxHeaders().isEmpty());
221             assertEquals("test-times.txt", e.getName());
222             assertEquals(toFileTime("2022-03-14T03:17:05Z"), e.getLastModifiedTime(), "mtime");
223             assertEquals(toFileTime("2022-03-14T03:17:06Z"), e.getLastAccessTime(), "atime");
224             assertEquals(toFileTime("2022-03-14T03:17:05Z"), e.getStatusChangeTime(), "ctime");
225             assertNull(e.getCreationTime(), "birthtime");
226             assertNull(tin.getNextTarEntry());
227         }
228     }
229 
230     // Extended POSIX.1-2001 standard tar
231     // Created using s-tar 1.6, which somehow differs from GNU tar's.
232     @Test
233     public void testReadTimeFromTarPax() throws Exception {
234         final String file = "COMPRESS-612/test-times-pax-folder.tar";
235         try (InputStream in = new BufferedInputStream(Files.newInputStream(getPath(file)));
236                 TarArchiveInputStream tin = new TarArchiveInputStream(in)) {
237             TarArchiveEntry e = tin.getNextTarEntry();
238             assertNotNull(e);
239             assertTrue(e.getExtraPaxHeaders().isEmpty());
240             assertEquals("test/", e.getName());
241             assertEquals(TarConstants.LF_DIR, e.getLinkFlag());
242             assertTrue(e.isDirectory());
243             assertEquals(toFileTime("2022-03-17T00:24:44.147126600Z"), e.getLastModifiedTime(), "mtime");
244             assertEquals(toFileTime("2022-03-17T01:01:53.369146300Z"), e.getLastAccessTime(), "atime");
245             assertEquals(toFileTime("2022-03-17T00:24:44.147126600Z"), e.getStatusChangeTime(), "ctime");
246             assertNull(e.getCreationTime(), "birthtime");
247             e = tin.getNextTarEntry();
248             assertNotNull(e);
249             assertTrue(e.getExtraPaxHeaders().isEmpty());
250             assertEquals("test/test-times.txt", e.getName());
251             assertEquals(TarConstants.LF_NORMAL, e.getLinkFlag());
252             assertTrue(e.isFile());
253             assertEquals(toFileTime("2022-03-17T00:38:20.470751500Z"), e.getLastModifiedTime(), "mtime");
254             assertEquals(toFileTime("2022-03-17T00:38:20.536752000Z"), e.getLastAccessTime(), "atime");
255             assertEquals(toFileTime("2022-03-17T00:38:20.470751500Z"), e.getStatusChangeTime(), "ctime");
256             assertNull(e.getCreationTime(), "birthtime");
257             assertNull(tin.getNextTarEntry());
258         }
259     }
260 
261     // Extended POSIX.1-2001 standard tar
262     // Created using GNU tar
263     @Test
264     public void testReadTimeFromTarPosix() throws Exception {
265         final String file = "COMPRESS-612/test-times-posix.tar";
266         try (InputStream in = new BufferedInputStream(Files.newInputStream(getPath(file)));
267                 TarArchiveInputStream tin = new TarArchiveInputStream(in)) {
268             final TarArchiveEntry e = tin.getNextTarEntry();
269             assertNotNull(e);
270             assertTrue(e.getExtraPaxHeaders().isEmpty());
271             assertEquals(toFileTime("2022-03-14T01:25:03.599853900Z"), e.getLastModifiedTime(), "mtime");
272             assertEquals(toFileTime("2022-03-14T01:31:00.706927200Z"), e.getLastAccessTime(), "atime");
273             assertEquals(toFileTime("2022-03-14T01:28:59.700505300Z"), e.getStatusChangeTime(), "ctime");
274             assertNull(e.getCreationTime(), "birthtime");
275             assertNull(tin.getNextTarEntry());
276         }
277     }
278 
279     // Extended POSIX.1-2001 standard tar
280     // Created using BSD tar on Windows
281     @Test
282     public void testReadTimeFromTarPosixLibArchive() throws Exception {
283         final String file = "COMPRESS-612/test-times-bsd-folder.tar";
284         try (InputStream in = new BufferedInputStream(Files.newInputStream(getPath(file)));
285                 TarArchiveInputStream tin = new TarArchiveInputStream(in)) {
286             TarArchiveEntry e = tin.getNextTarEntry();
287             assertNotNull(e);
288             assertTrue(e.getExtraPaxHeaders().isEmpty());
289             assertEquals("test/", e.getName());
290             assertEquals(TarConstants.LF_DIR, e.getLinkFlag());
291             assertTrue(e.isDirectory());
292             assertEquals(toFileTime("2022-03-16T10:19:43.382883700Z"), e.getLastModifiedTime(), "mtime");
293             assertEquals(toFileTime("2022-03-16T10:21:01.251181000Z"), e.getLastAccessTime(), "atime");
294             assertEquals(toFileTime("2022-03-16T10:19:24.105111500Z"), e.getStatusChangeTime(), "ctime");
295             assertEquals(toFileTime("2022-03-16T10:19:24.105111500Z"), e.getCreationTime(), "birthtime");
296             e = tin.getNextTarEntry();
297             assertNotNull(e);
298             assertTrue(e.getExtraPaxHeaders().isEmpty());
299             assertEquals("test/test-times.txt", e.getName());
300             assertEquals(TarConstants.LF_NORMAL, e.getLinkFlag());
301             assertTrue(e.isFile());
302             assertEquals(toFileTime("2022-03-16T10:21:00.249238500Z"), e.getLastModifiedTime(), "mtime");
303             assertEquals(toFileTime("2022-03-16T10:21:01.251181000Z"), e.getLastAccessTime(), "atime");
304             assertEquals(toFileTime("2022-03-14T01:25:03.599853900Z"), e.getStatusChangeTime(), "ctime");
305             assertEquals(toFileTime("2022-03-14T01:25:03.599853900Z"), e.getCreationTime(), "birthtime");
306             assertNull(tin.getNextTarEntry());
307         }
308     }
309 
310     // Extended POSIX.1-2001 standard tar
311     // Created using GNU tar on Linux
312     @Test
313     public void testReadTimeFromTarPosixLinux() throws Exception {
314         final String file = "COMPRESS-612/test-times-posix-linux.tar";
315         try (InputStream in = new BufferedInputStream(Files.newInputStream(getPath(file)));
316                 TarArchiveInputStream tin = new TarArchiveInputStream(in)) {
317             final TarArchiveEntry e = tin.getNextTarEntry();
318             assertNotNull(e);
319             assertTrue(e.getExtraPaxHeaders().isEmpty());
320             assertEquals(toFileTime("2022-03-14T01:25:03.599853900Z"), e.getLastModifiedTime(), "mtime");
321             assertEquals(toFileTime("2022-03-14T01:32:13.837251500Z"), e.getLastAccessTime(), "atime");
322             assertEquals(toFileTime("2022-03-14T01:31:00.706927200Z"), e.getStatusChangeTime(), "ctime");
323             assertNull(e.getCreationTime(), "birthtime");
324             assertNull(tin.getNextTarEntry());
325         }
326     }
327 
328     // Old star format from 1985
329     @Test
330     public void testReadTimeFromTarStarFolder() throws Exception {
331         final String file = "COMPRESS-612/test-times-star-folder.tar";
332         try (InputStream in = new BufferedInputStream(Files.newInputStream(getPath(file)));
333                 TarArchiveInputStream tin = new TarArchiveInputStream(in)) {
334             TarArchiveEntry e = tin.getNextTarEntry();
335             assertNotNull(e);
336             assertTrue(e.getExtraPaxHeaders().isEmpty());
337             assertEquals("test/", e.getName());
338             assertEquals(TarConstants.LF_DIR, e.getLinkFlag());
339             assertTrue(e.isDirectory());
340             assertEquals(toFileTime("2022-03-17T00:24:44Z"), e.getLastModifiedTime(), "mtime");
341             assertNull(e.getLastAccessTime(), "atime");
342             assertNull(e.getStatusChangeTime(), "ctime");
343             assertNull(e.getCreationTime(), "birthtime");
344             e = tin.getNextTarEntry();
345             assertTrue(e.getExtraPaxHeaders().isEmpty());
346             assertEquals("test/test-times.txt", e.getName());
347             assertEquals(TarConstants.LF_NORMAL, e.getLinkFlag());
348             assertTrue(e.isFile());
349             assertEquals(toFileTime("2022-03-17T00:38:20Z"), e.getLastModifiedTime(), "mtime");
350             assertNull(e.getLastAccessTime(), "atime");
351             assertNull(e.getStatusChangeTime(), "ctime");
352             assertNull(e.getCreationTime(), "birthtime");
353             assertNull(tin.getNextTarEntry());
354         }
355     }
356 
357     // Standard POSIX.1-1988 tar format
358     @Test
359     public void testReadTimeFromTarUstar() throws Exception {
360         final String file = "COMPRESS-612/test-times-ustar.tar";
361         try (InputStream in = new BufferedInputStream(Files.newInputStream(getPath(file)));
362                 TarArchiveInputStream tin = new TarArchiveInputStream(in)) {
363             final TarArchiveEntry e = tin.getNextTarEntry();
364             assertNotNull(e);
365             assertTrue(e.getExtraPaxHeaders().isEmpty());
366             assertEquals(toFileTime("2022-03-14T01:25:03Z"), e.getLastModifiedTime(), "mtime");
367             assertNull(e.getLastAccessTime(), "atime");
368             assertNull(e.getStatusChangeTime(), "ctime");
369             assertNull(e.getCreationTime(), "birthtime");
370             assertNull(tin.getNextTarEntry());
371         }
372     }
373 
374     // Old UNIX V7 tar format
375     @Test
376     public void testReadTimeFromTarV7() throws Exception {
377         final String file = "COMPRESS-612/test-times-v7.tar";
378         try (InputStream in = new BufferedInputStream(Files.newInputStream(getPath(file)));
379                 TarArchiveInputStream tin = new TarArchiveInputStream(in)) {
380             final TarArchiveEntry e = tin.getNextTarEntry();
381             assertNotNull(e);
382             assertTrue(e.getExtraPaxHeaders().isEmpty());
383             assertEquals(toFileTime("2022-03-14T01:25:03Z"), e.getLastModifiedTime(), "mtime");
384             assertNull(e.getLastAccessTime(), "atime");
385             assertNull(e.getStatusChangeTime(), "ctime");
386             assertNull(e.getCreationTime(), "birthtime");
387             assertNull(tin.getNextTarEntry());
388         }
389     }
390 
391     // Extended standard tar (star 1994)
392     @Test
393     public void testReadTimeFromTarXstar() throws Exception {
394         final String file = "COMPRESS-612/test-times-xstar.tar";
395         try (InputStream in = new BufferedInputStream(Files.newInputStream(getPath(file)));
396                 TarArchiveInputStream tin = new TarArchiveInputStream(in)) {
397             final TarArchiveEntry e = tin.getNextTarEntry();
398             assertNotNull(e);
399             assertTrue(e.getExtraPaxHeaders().isEmpty());
400             assertEquals(toFileTime("2022-03-14T04:11:22Z"), e.getLastModifiedTime(), "mtime");
401             assertEquals(toFileTime("2022-03-14T04:12:48Z"), e.getLastAccessTime(), "atime");
402             assertEquals(toFileTime("2022-03-14T04:12:47Z"), e.getStatusChangeTime(), "ctime");
403             assertNull(e.getCreationTime(), "birthtime");
404             assertNull(tin.getNextTarEntry());
405         }
406     }
407 
408     // Extended standard tar (star 1994)
409     @Test
410     public void testReadTimeFromTarXstarFolder() throws Exception {
411         final String file = "COMPRESS-612/test-times-xstar-folder.tar";
412         try (InputStream in = new BufferedInputStream(Files.newInputStream(getPath(file)));
413                 TarArchiveInputStream tin = new TarArchiveInputStream(in)) {
414             TarArchiveEntry e = tin.getNextTarEntry();
415             assertNotNull(e);
416             assertTrue(e.getExtraPaxHeaders().isEmpty());
417             assertEquals("test/", e.getName());
418             assertEquals(TarConstants.LF_DIR, e.getLinkFlag());
419             assertTrue(e.isDirectory());
420             assertEquals(toFileTime("2022-03-17T00:24:44Z"), e.getLastModifiedTime(), "mtime");
421             assertEquals(toFileTime("2022-03-17T01:01:34Z"), e.getLastAccessTime(), "atime");
422             assertEquals(toFileTime("2022-03-17T00:24:44Z"), e.getStatusChangeTime(), "ctime");
423             assertNull(e.getCreationTime(), "birthtime");
424             e = tin.getNextTarEntry();
425             assertEquals("test/test-times.txt", e.getName());
426             assertEquals(TarConstants.LF_NORMAL, e.getLinkFlag());
427             assertTrue(e.isFile());
428             assertTrue(e.getExtraPaxHeaders().isEmpty());
429             assertEquals(toFileTime("2022-03-17T00:38:20Z"), e.getLastModifiedTime(), "mtime");
430             assertEquals(toFileTime("2022-03-17T00:38:20Z"), e.getLastAccessTime(), "atime");
431             assertEquals(toFileTime("2022-03-17T00:38:20Z"), e.getStatusChangeTime(), "ctime");
432             assertNull(e.getCreationTime(), "birthtime");
433             assertNull(tin.getNextTarEntry());
434         }
435     }
436 
437     // Extended standard tar (star 1994)
438     @Test
439     public void testReadTimeFromTarXstarIncremental() throws Exception {
440         final String file = "COMPRESS-612/test-times-xstar-incremental.tar";
441         try (InputStream in = new BufferedInputStream(Files.newInputStream(getPath(file)));
442                 TarArchiveInputStream tin = new TarArchiveInputStream(in)) {
443             TarArchiveEntry e = tin.getNextTarEntry();
444             assertNotNull(e);
445             assertTrue(e.getExtraPaxHeaders().isEmpty());
446             assertEquals("test-times.txt", e.getName());
447             assertEquals(toFileTime("2022-03-14T04:03:29Z"), e.getLastModifiedTime(), "mtime");
448             assertEquals(toFileTime("2022-03-14T04:03:29Z"), e.getLastAccessTime(), "atime");
449             assertEquals(toFileTime("2022-03-14T04:03:29Z"), e.getStatusChangeTime(), "ctime");
450             assertNull(e.getCreationTime(), "birthtime");
451             e = tin.getNextTarEntry();
452             assertNotNull(e);
453             assertTrue(e.getExtraPaxHeaders().isEmpty());
454             assertEquals("test-times.txt", e.getName(), "name");
455             assertEquals(toFileTime("2022-03-14T04:11:22Z"), e.getLastModifiedTime(), "mtime");
456             assertEquals(toFileTime("2022-03-14T04:11:23Z"), e.getLastAccessTime(), "atime");
457             assertEquals(toFileTime("2022-03-14T04:11:22Z"), e.getStatusChangeTime(), "ctime");
458             assertNull(e.getCreationTime(), "birthtime");
459             assertNull(tin.getNextTarEntry());
460         }
461     }
462 
463     // 'xstar' format without tar signature
464     @Test
465     public void testReadTimeFromTarXustar() throws Exception {
466         final String file = "COMPRESS-612/test-times-xustar.tar";
467         try (InputStream in = new BufferedInputStream(Files.newInputStream(getPath(file)));
468                 TarArchiveInputStream tin = new TarArchiveInputStream(in)) {
469             final TarArchiveEntry e = tin.getNextTarEntry();
470             assertNotNull(e);
471             assertTrue(e.getExtraPaxHeaders().isEmpty());
472             assertEquals(toFileTime("2022-03-17T00:38:20.470751500Z"), e.getLastModifiedTime(), "mtime");
473             assertEquals(toFileTime("2022-03-17T00:38:20.536752000Z"), e.getLastAccessTime(), "atime");
474             assertEquals(toFileTime("2022-03-17T00:38:20.470751500Z"), e.getStatusChangeTime(), "ctime");
475             assertNull(e.getCreationTime(), "birthtime");
476             assertNull(tin.getNextTarEntry());
477         }
478     }
479 
480     // 'xstar' format without tar signature
481     @Test
482     public void testReadTimeFromTarXustarFolder() throws Exception {
483         final String file = "COMPRESS-612/test-times-xustar-folder.tar";
484         try (InputStream in = new BufferedInputStream(Files.newInputStream(getPath(file)));
485                 TarArchiveInputStream tin = new TarArchiveInputStream(in)) {
486             TarArchiveEntry e = tin.getNextTarEntry();
487             assertNotNull(e);
488             assertTrue(e.getExtraPaxHeaders().isEmpty());
489             assertEquals("test/", e.getName());
490             assertEquals(TarConstants.LF_DIR, e.getLinkFlag());
491             assertTrue(e.isDirectory());
492             assertEquals(toFileTime("2022-03-17T00:24:44.147126600Z"), e.getLastModifiedTime(), "mtime");
493             assertEquals(toFileTime("2022-03-17T01:01:19.581236400Z"), e.getLastAccessTime(), "atime");
494             assertEquals(toFileTime("2022-03-17T00:24:44.147126600Z"), e.getStatusChangeTime(), "ctime");
495             assertNull(e.getCreationTime(), "birthtime");
496             e = tin.getNextTarEntry();
497             assertTrue(e.getExtraPaxHeaders().isEmpty());
498             assertEquals("test/test-times.txt", e.getName());
499             assertEquals(TarConstants.LF_NORMAL, e.getLinkFlag());
500             assertTrue(e.isFile());
501             assertEquals(toFileTime("2022-03-17T00:38:20.470751500Z"), e.getLastModifiedTime(), "mtime");
502             assertEquals(toFileTime("2022-03-17T00:38:20.536752000Z"), e.getLastAccessTime(), "atime");
503             assertEquals(toFileTime("2022-03-17T00:38:20.470751500Z"), e.getStatusChangeTime(), "ctime");
504             assertNull(e.getCreationTime(), "birthtime");
505             assertNull(tin.getNextTarEntry());
506         }
507     }
508 
509     // 'xstar' format without tar signature
510     @Test
511     public void testReadTimeFromTarXustarIncremental() throws Exception {
512         final String file = "COMPRESS-612/test-times-xustar-incremental.tar";
513         try (InputStream in = new BufferedInputStream(Files.newInputStream(getPath(file)));
514                 TarArchiveInputStream tin = new TarArchiveInputStream(in)) {
515             TarArchiveEntry e = tin.getNextTarEntry();
516             assertNotNull(e);
517             assertTrue(e.getExtraPaxHeaders().isEmpty());
518             assertEquals("test-times.txt", e.getName(), "name");
519             assertEquals(TarConstants.LF_NORMAL, e.getLinkFlag());
520             assertEquals(toFileTime("2022-03-17T00:38:20.470751500Z"), e.getLastModifiedTime(), "mtime");
521             assertEquals(toFileTime("2022-03-17T00:38:20.536752000Z"), e.getLastAccessTime(), "atime");
522             assertEquals(toFileTime("2022-03-17T00:38:20.470751500Z"), e.getStatusChangeTime(), "ctime");
523             assertNull(e.getCreationTime(), "birthtime");
524             e = tin.getNextTarEntry();
525             assertNotNull(e);
526             assertTrue(e.getExtraPaxHeaders().isEmpty());
527             assertEquals("test-times.txt", e.getName(), "name");
528             assertEquals(TarConstants.LF_NORMAL, e.getLinkFlag());
529             assertEquals(toFileTime("2022-03-17T01:52:25.592262900Z"), e.getLastModifiedTime(), "mtime");
530             assertEquals(toFileTime("2022-03-17T01:52:25.724278500Z"), e.getLastAccessTime(), "atime");
531             assertEquals(toFileTime("2022-03-17T01:52:25.592262900Z"), e.getStatusChangeTime(), "ctime");
532             assertNull(e.getCreationTime(), "birthtime");
533             assertNull(tin.getNextTarEntry());
534         }
535     }
536 
537     private FileTime toFileTime(final String text) {
538         return FileTime.from(Instant.parse(text));
539     }
540 }