awesome assets from gffs code
[feisty_meow.git] / kona / src / org / gffs / compression / UnpackTar.java
1 package org.gffs.compression;
2
3 import java.io.BufferedOutputStream;
4 import java.io.File;
5 import java.io.FileInputStream;
6 import java.io.FileOutputStream;
7 import java.io.IOException;
8 import java.nio.file.Files;
9 import java.nio.file.Paths;
10 import java.nio.file.attribute.PosixFilePermission;
11 import java.util.HashSet;
12 import org.apache.commons.compress.archivers.ArchiveEntry;
13 import org.apache.commons.compress.archivers.ArchiveInputStream;
14 import org.apache.commons.compress.archivers.tar.TarArchiveInputStream;
15 import org.apache.commons.compress.archivers.zip.ZipArchiveInputStream;
16 import org.apache.commons.compress.compressors.gzip.GzipCompressorInputStream;
17 import org.apache.commons.compress.archivers.tar.TarArchiveEntry;
18 import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
19 import org.apache.commons.logging.Log;
20 import org.apache.commons.logging.LogFactory;
21
22 public class UnpackTar
23 {
24         static private Log _logger = LogFactory.getLog(UnpackTar.class);
25
26         /**
27          * takes a tar.gz file as the "tarFile" parameter, then decompresses and unpacks the file into the "dest" location.
28          */
29
30         public enum archiveType {
31                 TAR,
32                 ZIP,
33                 TGZ
34         };
35
36         public static void uncompressArchive(ArchiveInputStream tarIn, File dest, archiveType archType, boolean grantUserPermsToGroup)
37                 throws IOException
38         {
39
40                 if (dest.exists()) {
41                         // Don't unpack into an existing directory
42                         throw new IOException("Directory " + dest.getAbsolutePath() + " already exists. Unpacking exiting");
43                 }
44                 dest.mkdir();
45
46                 ArchiveEntry tarEntry = tarIn.getNextEntry();
47                 while (tarEntry != null) {
48                         // New code by ASG 2016-02-21. Added extracting user permission bits and OR ing them with group permissions
49                         int mode = 0;
50                         int defaultMode = 0750; // assume somewhat standard executable permissions if we cannot get the mode.
51                         switch (archType) {
52                                 case TAR:
53                                 case TGZ:
54                                         mode = ((TarArchiveEntry) tarEntry).getMode();
55                                         break;
56                                 case ZIP:
57                                         mode = ((ZipArchiveEntry) tarEntry).getUnixMode();
58                                         break;
59                         }
60                         if (mode == 0) {
61                                 mode = defaultMode;
62                         }
63                         if (_logger.isTraceEnabled())
64                                 _logger.debug("The mode on '" + tarEntry.getName() + "' is " + Integer.toOctalString(mode));
65                         if (grantUserPermsToGroup) {
66                                 int temp = mode & 0700;
67                                 temp = temp / 8; // Shift it right 3 bit positions
68                                 mode = mode | temp;
69                                 if (_logger.isTraceEnabled())
70                                         _logger.debug("Now mode on '" + tarEntry.getName() + "' is " + Integer.toOctalString(mode));
71                         }
72                         // End of extracting and Or ing the permission bits.
73
74                         // create a file with the same name as the tarEntry
75                         File destPath = new File(dest, tarEntry.getName());
76                         if (_logger.isTraceEnabled())
77                                 _logger.debug("working on: " + destPath.getCanonicalPath());
78                         if (tarEntry.isDirectory()) {
79                                 destPath.mkdirs();
80                         } else {
81                                 destPath.createNewFile();
82
83                                 // byte [] btoRead = new byte[(int)tarEntry.getSize()];
84                                 byte[] btoRead = new byte[8192];
85                                 BufferedOutputStream bout = new BufferedOutputStream(new FileOutputStream(destPath));
86                                 int len = 0;
87                                 boolean wroteAnything = false;
88                                 while ((len = tarIn.read(btoRead)) != -1) {
89                                         if (_logger.isTraceEnabled())
90                                                 _logger.debug("read " + len + " bytes");
91                                         wroteAnything = true;
92                                         bout.write(btoRead, 0, len);
93                                 }
94                                 if (!wroteAnything) {
95                                         _logger.error("zero bytes read from: " + destPath.getCanonicalPath());
96                                 }
97
98                                 bout.close();
99                         }
100                         // using PosixFilePermission to set file permissions that we extracted earlier.
101                         HashSet<PosixFilePermission> perms = new HashSet<PosixFilePermission>();
102                         // add owners permission
103                         if ((mode & 0400) != 0)
104                                 perms.add(PosixFilePermission.OWNER_READ);
105                         if ((mode & 0200) != 0)
106                                 perms.add(PosixFilePermission.OWNER_WRITE);
107                         if ((mode & 0100) != 0)
108                                 perms.add(PosixFilePermission.OWNER_EXECUTE);
109                         // add group permissions
110                         if ((mode & 0040) != 0)
111                                 perms.add(PosixFilePermission.GROUP_READ);
112                         if ((mode & 0020) != 0)
113                                 perms.add(PosixFilePermission.GROUP_WRITE);
114                         if ((mode & 0010) != 0)
115                                 perms.add(PosixFilePermission.GROUP_EXECUTE);
116                         // add others permissions
117                         if ((mode & 0004) != 0)
118                                 perms.add(PosixFilePermission.OTHERS_READ);
119                         if ((mode & 0002) != 0)
120                                 perms.add(PosixFilePermission.OTHERS_WRITE);
121                         if ((mode & 0001) != 0)
122                                 perms.add(PosixFilePermission.OTHERS_EXECUTE);
123
124                         Files.setPosixFilePermissions(Paths.get(destPath.getCanonicalPath()), perms);
125                         tarEntry = tarIn.getNextEntry();
126                 }
127                 tarIn.close();
128         }
129
130         public synchronized static void uncompressTarGZ(File tarFile, File dest, boolean grantUserPermsToGroup) throws IOException
131         {
132                 TarArchiveInputStream tarIn = new TarArchiveInputStream(new GzipCompressorInputStream(new FileInputStream(tarFile)));
133
134                 uncompressArchive(tarIn, dest, archiveType.TGZ, grantUserPermsToGroup);
135         }
136
137         public synchronized static void uncompressTar(File tarFile, File dest, boolean grantUserPermsToGroup) throws IOException
138         {
139                 TarArchiveInputStream tarIn = new TarArchiveInputStream(new FileInputStream(tarFile));
140
141                 uncompressArchive(tarIn, dest, archiveType.TAR, grantUserPermsToGroup);
142         }
143
144         public synchronized static void uncompressZip(File zipFile, File dest, boolean grantUserPermsToGroup) throws IOException
145         {
146                 ZipArchiveInputStream tarIn = new ZipArchiveInputStream(new FileInputStream(zipFile));
147
148                 uncompressArchive(tarIn, dest, archiveType.ZIP, grantUserPermsToGroup);
149         }
150
151         static public void main(String[] args) throws Throwable
152         {
153                 if (args.length != 2) {
154                         System.err.println("USAGE: UnpackTar {tar.gz file} {output location}");
155                         System.exit(1);
156                 }
157
158                 try {
159                         UnpackTar.uncompressTarGZ(new File(args[0]), new File(args[1]), false);
160                 } catch (Throwable t) {
161                         _logger.error("failed to uncompress tar file " + args[0] + " into " + args[1]);
162                         System.exit(1);
163                 }
164
165                 System.out.println("successfully uncompressed tar file " + args[0] + " into " + args[1]);
166         }
167
168 }