3636import java .nio .charset .CharsetEncoder ;
3737import java .nio .charset .StandardCharsets ;
3838import java .nio .file .AccessDeniedException ;
39+ import java .nio .file .attribute .PosixFilePermission ;
3940import java .nio .file .FileSystems ;
4041import java .nio .file .Files ;
4142import java .nio .file .LinkOption ;
4243import java .nio .file .Paths ;
4344import java .util .ArrayList ;
4445import java .util .Enumeration ;
46+ import java .util .EnumSet ;
4547import java .util .List ;
4648import java .util .Map ;
4749import java .util .Objects ;
50+ import java .util .Set ;
4851import java .util .concurrent .ExecutionException ;
4952import java .util .concurrent .ExecutorService ;
5053import java .util .concurrent .Executors ;
5356import java .util .jar .JarOutputStream ;
5457import java .util .jar .Manifest ;
5558import java .util .zip .GZIPInputStream ;
56- import java .util .zip .ZipEntry ;
57- import java .util .zip .ZipFile ;
58- import java .util .zip .ZipInputStream ;
5959
6060import org .apache .commons .collections .map .CaseInsensitiveMap ;
6161import org .apache .commons .compress .archivers .tar .TarArchiveEntry ;
6262import org .apache .commons .compress .archivers .tar .TarArchiveInputStream ;
63+ import org .apache .commons .compress .archivers .zip .ZipArchiveEntry ;
64+ import org .apache .commons .compress .archivers .zip .ZipArchiveInputStream ;
65+ import org .apache .commons .compress .archivers .zip .ZipFile ;
6366import org .apache .commons .io .FileUtils ;
6467import org .apache .hadoop .classification .InterfaceAudience ;
6568import org .apache .hadoop .classification .InterfaceStability ;
@@ -644,12 +647,12 @@ public static long getDU(File dir) {
644647 */
645648 public static void unZip (InputStream inputStream , File toDir )
646649 throws IOException {
647- try (ZipInputStream zip = new ZipInputStream (inputStream )) {
650+ try (ZipArchiveInputStream zip = new ZipArchiveInputStream (inputStream )) {
648651 int numOfFailedLastModifiedSet = 0 ;
649652 String targetDirPath = toDir .getCanonicalPath () + File .separator ;
650- for (ZipEntry entry = zip .getNextEntry ();
653+ for (ZipArchiveEntry entry = zip .getNextZipEntry ();
651654 entry != null ;
652- entry = zip .getNextEntry ()) {
655+ entry = zip .getNextZipEntry ()) {
653656 if (!entry .isDirectory ()) {
654657 File file = new File (toDir , entry .getName ());
655658 if (!file .getCanonicalPath ().startsWith (targetDirPath )) {
@@ -668,6 +671,9 @@ public static void unZip(InputStream inputStream, File toDir)
668671 if (!file .setLastModified (entry .getTime ())) {
669672 numOfFailedLastModifiedSet ++;
670673 }
674+ if (entry .getPlatform () == ZipArchiveEntry .PLATFORM_UNIX ) {
675+ Files .setPosixFilePermissions (file .toPath (), permissionsFromMode (entry .getUnixMode ()));
676+ }
671677 }
672678 }
673679 if (numOfFailedLastModifiedSet > 0 ) {
@@ -677,6 +683,49 @@ public static void unZip(InputStream inputStream, File toDir)
677683 }
678684 }
679685
686+ /**
687+ * The permission operation of this method only involves users, user groups, and others.
688+ * If SUID is set, only executable permissions are reserved.
689+ * @param mode Permissions are represented by numerical values
690+ * @return The original permissions for files are stored in collections
691+ */
692+ private static Set <PosixFilePermission > permissionsFromMode (int mode ) {
693+ EnumSet <PosixFilePermission > permissions =
694+ EnumSet .noneOf (PosixFilePermission .class );
695+ addPermissions (permissions , mode , PosixFilePermission .OTHERS_READ ,
696+ PosixFilePermission .OTHERS_WRITE , PosixFilePermission .OTHERS_EXECUTE );
697+ addPermissions (permissions , mode >> 3 , PosixFilePermission .GROUP_READ ,
698+ PosixFilePermission .GROUP_WRITE , PosixFilePermission .GROUP_EXECUTE );
699+ addPermissions (permissions , mode >> 6 , PosixFilePermission .OWNER_READ ,
700+ PosixFilePermission .OWNER_WRITE , PosixFilePermission .OWNER_EXECUTE );
701+ return permissions ;
702+ }
703+
704+ /**
705+ * Assign the original permissions to the file
706+ * @param permissions The original permissions for files are stored in collections
707+ * @param mode Use a value of type int to indicate permissions
708+ * @param r Read permission
709+ * @param w Write permission
710+ * @param x Execute permission
711+ */
712+ private static void addPermissions (
713+ Set <PosixFilePermission > permissions ,
714+ int mode ,
715+ PosixFilePermission r ,
716+ PosixFilePermission w ,
717+ PosixFilePermission x ) {
718+ if ((mode & 1L ) == 1L ) {
719+ permissions .add (x );
720+ }
721+ if ((mode & 2L ) == 2L ) {
722+ permissions .add (w );
723+ }
724+ if ((mode & 4L ) == 4L ) {
725+ permissions .add (r );
726+ }
727+ }
728+
680729 /**
681730 * Given a File input it will unzip it in the unzip directory.
682731 * passed as the second parameter
@@ -685,14 +734,14 @@ public static void unZip(InputStream inputStream, File toDir)
685734 * @throws IOException An I/O exception has occurred
686735 */
687736 public static void unZip (File inFile , File unzipDir ) throws IOException {
688- Enumeration <? extends ZipEntry > entries ;
737+ Enumeration <? extends ZipArchiveEntry > entries ;
689738 ZipFile zipFile = new ZipFile (inFile );
690739
691740 try {
692- entries = zipFile .entries ();
741+ entries = zipFile .getEntries ();
693742 String targetDirPath = unzipDir .getCanonicalPath () + File .separator ;
694743 while (entries .hasMoreElements ()) {
695- ZipEntry entry = entries .nextElement ();
744+ ZipArchiveEntry entry = entries .nextElement ();
696745 if (!entry .isDirectory ()) {
697746 InputStream in = zipFile .getInputStream (entry );
698747 try {
@@ -717,6 +766,9 @@ public static void unZip(File inFile, File unzipDir) throws IOException {
717766 } finally {
718767 out .close ();
719768 }
769+ if (entry .getPlatform () == ZipArchiveEntry .PLATFORM_UNIX ) {
770+ Files .setPosixFilePermissions (file .toPath (), permissionsFromMode (entry .getUnixMode ()));
771+ }
720772 } finally {
721773 in .close ();
722774 }
0 commit comments