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 .Paths ;
4243import java .util .ArrayList ;
4344import java .util .Enumeration ;
45+ import java .util .EnumSet ;
4446import java .util .List ;
4547import java .util .Map ;
4648import java .util .Objects ;
49+ import java .util .Set ;
4750import java .util .concurrent .ExecutionException ;
4851import java .util .concurrent .ExecutorService ;
4952import java .util .concurrent .Executors ;
5255import java .util .jar .JarOutputStream ;
5356import java .util .jar .Manifest ;
5457import java .util .zip .GZIPInputStream ;
55- import java .util .zip .ZipEntry ;
56- import java .util .zip .ZipFile ;
57- import java .util .zip .ZipInputStream ;
5858
5959import org .apache .commons .collections .map .CaseInsensitiveMap ;
6060import org .apache .commons .compress .archivers .tar .TarArchiveEntry ;
6161import org .apache .commons .compress .archivers .tar .TarArchiveInputStream ;
62+ import org .apache .commons .compress .archivers .zip .ZipArchiveEntry ;
63+ import org .apache .commons .compress .archivers .zip .ZipArchiveInputStream ;
64+ import org .apache .commons .compress .archivers .zip .ZipFile ;
65+ import org .apache .commons .io .FileUtils ;
6266import org .apache .hadoop .classification .InterfaceAudience ;
6367import org .apache .hadoop .classification .InterfaceStability ;
6468import org .apache .hadoop .conf .Configuration ;
@@ -622,12 +626,12 @@ public static long getDU(File dir) {
622626 */
623627 public static void unZip (InputStream inputStream , File toDir )
624628 throws IOException {
625- try (ZipInputStream zip = new ZipInputStream (inputStream )) {
629+ try (ZipArchiveInputStream zip = new ZipArchiveInputStream (inputStream )) {
626630 int numOfFailedLastModifiedSet = 0 ;
627631 String targetDirPath = toDir .getCanonicalPath () + File .separator ;
628- for (ZipEntry entry = zip .getNextEntry ();
632+ for (ZipArchiveEntry entry = zip .getNextZipEntry ();
629633 entry != null ;
630- entry = zip .getNextEntry ()) {
634+ entry = zip .getNextZipEntry ()) {
631635 if (!entry .isDirectory ()) {
632636 File file = new File (toDir , entry .getName ());
633637 if (!file .getCanonicalPath ().startsWith (targetDirPath )) {
@@ -646,6 +650,9 @@ public static void unZip(InputStream inputStream, File toDir)
646650 if (!file .setLastModified (entry .getTime ())) {
647651 numOfFailedLastModifiedSet ++;
648652 }
653+ if (entry .getPlatform () == ZipArchiveEntry .PLATFORM_UNIX ) {
654+ Files .setPosixFilePermissions (file .toPath (), permissionsFromMode (entry .getUnixMode ()));
655+ }
649656 }
650657 }
651658 if (numOfFailedLastModifiedSet > 0 ) {
@@ -655,6 +662,49 @@ public static void unZip(InputStream inputStream, File toDir)
655662 }
656663 }
657664
665+ /**
666+ * The permission operation of this method only involves users, user groups, and others.
667+ * If SUID is set, only executable permissions are reserved.
668+ * @param mode Permissions are represented by numerical values
669+ * @return The original permissions for files are stored in collections
670+ */
671+ private static Set <PosixFilePermission > permissionsFromMode (int mode ) {
672+ EnumSet <PosixFilePermission > permissions =
673+ EnumSet .noneOf (PosixFilePermission .class );
674+ addPermissions (permissions , mode , PosixFilePermission .OTHERS_READ ,
675+ PosixFilePermission .OTHERS_WRITE , PosixFilePermission .OTHERS_EXECUTE );
676+ addPermissions (permissions , mode >> 3 , PosixFilePermission .GROUP_READ ,
677+ PosixFilePermission .GROUP_WRITE , PosixFilePermission .GROUP_EXECUTE );
678+ addPermissions (permissions , mode >> 6 , PosixFilePermission .OWNER_READ ,
679+ PosixFilePermission .OWNER_WRITE , PosixFilePermission .OWNER_EXECUTE );
680+ return permissions ;
681+ }
682+
683+ /**
684+ * Assign the original permissions to the file
685+ * @param permissions The original permissions for files are stored in collections
686+ * @param mode Use a value of type int to indicate permissions
687+ * @param r Read permission
688+ * @param w Write permission
689+ * @param x Execute permission
690+ */
691+ private static void addPermissions (
692+ Set <PosixFilePermission > permissions ,
693+ int mode ,
694+ PosixFilePermission r ,
695+ PosixFilePermission w ,
696+ PosixFilePermission x ) {
697+ if ((mode & 1L ) == 1L ) {
698+ permissions .add (x );
699+ }
700+ if ((mode & 2L ) == 2L ) {
701+ permissions .add (w );
702+ }
703+ if ((mode & 4L ) == 4L ) {
704+ permissions .add (r );
705+ }
706+ }
707+
658708 /**
659709 * Given a File input it will unzip it in the unzip directory.
660710 * passed as the second parameter
@@ -663,14 +713,14 @@ public static void unZip(InputStream inputStream, File toDir)
663713 * @throws IOException An I/O exception has occurred
664714 */
665715 public static void unZip (File inFile , File unzipDir ) throws IOException {
666- Enumeration <? extends ZipEntry > entries ;
716+ Enumeration <? extends ZipArchiveEntry > entries ;
667717 ZipFile zipFile = new ZipFile (inFile );
668718
669719 try {
670- entries = zipFile .entries ();
720+ entries = zipFile .getEntries ();
671721 String targetDirPath = unzipDir .getCanonicalPath () + File .separator ;
672722 while (entries .hasMoreElements ()) {
673- ZipEntry entry = entries .nextElement ();
723+ ZipArchiveEntry entry = entries .nextElement ();
674724 if (!entry .isDirectory ()) {
675725 InputStream in = zipFile .getInputStream (entry );
676726 try {
@@ -695,6 +745,9 @@ public static void unZip(File inFile, File unzipDir) throws IOException {
695745 } finally {
696746 out .close ();
697747 }
748+ if (entry .getPlatform () == ZipArchiveEntry .PLATFORM_UNIX ) {
749+ Files .setPosixFilePermissions (file .toPath (), permissionsFromMode (entry .getUnixMode ()));
750+ }
698751 } finally {
699752 in .close ();
700753 }
0 commit comments