use of java.nio.file.attribute.PosixFilePermission in project buck by facebook.
the class Unzip method extractZipFile.
/**
* Unzips a file to a destination and returns the paths of the written files.
*/
public static ImmutableList<Path> extractZipFile(Path zipFile, ProjectFilesystem filesystem, Path relativePath, ExistingFileMode existingFileMode) throws IOException {
// if requested, clean before extracting
if (existingFileMode == ExistingFileMode.OVERWRITE_AND_CLEAN_DIRECTORIES) {
try (ZipFile zip = new ZipFile(zipFile.toFile())) {
Enumeration<ZipArchiveEntry> entries = zip.getEntries();
while (entries.hasMoreElements()) {
ZipArchiveEntry entry = entries.nextElement();
filesystem.deleteRecursivelyIfExists(relativePath.resolve(entry.getName()));
}
}
}
ImmutableList.Builder<Path> filesWritten = ImmutableList.builder();
try (ZipFile zip = new ZipFile(zipFile.toFile())) {
Enumeration<ZipArchiveEntry> entries = zip.getEntries();
while (entries.hasMoreElements()) {
ZipArchiveEntry entry = entries.nextElement();
String fileName = entry.getName();
Path target = relativePath.resolve(fileName);
if (entry.isDirectory()) {
// Create the directory and all its parent directories
filesystem.mkdirs(target);
} else {
// Create parent folder
filesystem.createParentDirs(target);
filesWritten.add(target);
// Write file
try (InputStream is = zip.getInputStream(entry)) {
if (entry.isUnixSymlink()) {
filesystem.createSymLink(target, filesystem.getPath(new String(ByteStreams.toByteArray(is), Charsets.UTF_8)), /* force */
true);
} else {
try (OutputStream out = filesystem.newFileOutputStream(target)) {
ByteStreams.copy(is, out);
}
}
}
// restore mtime for the file
filesystem.resolve(target).toFile().setLastModified(entry.getTime());
// TODO(shs96c): Implement what the comment below says we should do.
//
// Sets the file permissions of the output file given the information in {@code entry}'s
// extra data field. According to the docs at
// http://www.opensource.apple.com/source/zip/zip-6/unzip/unzip/proginfo/extra.fld there
// are two extensions that might support file permissions: Acorn and ASi UNIX. We shall
// assume that inputs are not from an Acorn SparkFS. The relevant section from the docs:
//
// <pre>
// The following is the layout of the ASi extra block for Unix. The
// local-header and central-header versions are identical.
// (Last Revision 19960916)
//
// Value Size Description
// ----- ---- -----------
// (Unix3) 0x756e Short tag for this extra block type ("nu")
// TSize Short total data size for this block
// CRC Long CRC-32 of the remaining data
// Mode Short file permissions
// SizDev Long symlink'd size OR major/minor dev num
// UID Short user ID
// GID Short group ID
// (var.) variable symbolic link filename
//
// Mode is the standard Unix st_mode field from struct stat, containing
// user/group/other permissions, setuid/setgid and symlink info, etc.
// </pre>
//
// From the stat man page, we see that the following mask values are defined for the file
// permissions component of the st_mode field:
//
// <pre>
// S_ISUID 0004000 set-user-ID bit
// S_ISGID 0002000 set-group-ID bit (see below)
// S_ISVTX 0001000 sticky bit (see below)
//
// S_IRWXU 00700 mask for file owner permissions
//
// S_IRUSR 00400 owner has read permission
// S_IWUSR 00200 owner has write permission
// S_IXUSR 00100 owner has execute permission
//
// S_IRWXG 00070 mask for group permissions
// S_IRGRP 00040 group has read permission
// S_IWGRP 00020 group has write permission
// S_IXGRP 00010 group has execute permission
//
// S_IRWXO 00007 mask for permissions for others
// (not in group)
// S_IROTH 00004 others have read permission
// S_IWOTH 00002 others have write permission
// S_IXOTH 00001 others have execute permission
// </pre>
//
// For the sake of our own sanity, we're going to assume that no-one is using symlinks,
// but we'll check and throw if they are.
//
// Before we do anything, we should check the header ID. Pfft!
//
// Having jumped through all these hoops, it turns out that InfoZIP's "unzip" store the
// values in the external file attributes of a zip entry (found in the zip's central
// directory) assuming that the OS creating the zip was one of an enormous list that
// includes UNIX but not Windows, it first searches for the extra fields, and if not found
// falls through to a code path that supports MS-DOS and which stores the UNIX file
// attributes in the upper 16 bits of the external attributes field.
//
// We'll support neither approach fully, but we encode whether this file was executable
// via storing 0100 in the fields that are typically used by zip implementations to store
// POSIX permissions. If we find it was executable, use the platform independent java
// interface to make this unpacked file executable.
Set<PosixFilePermission> permissions = MorePosixFilePermissions.fromMode(entry.getExternalAttributes() >> 16);
if (permissions.contains(PosixFilePermission.OWNER_EXECUTE)) {
MoreFiles.makeExecutable(filesystem.resolve(target));
}
}
}
}
return filesWritten.build();
}
use of java.nio.file.attribute.PosixFilePermission in project buck by facebook.
the class ProjectFilesystemTest method testCreateZipPreservesExecutablePermissions.
@Test
public void testCreateZipPreservesExecutablePermissions() throws IOException {
// Create a empty executable file.
Path exe = tmp.newFile("test.exe");
MoreFiles.makeExecutable(exe);
// Archive it into a zipfile using `ProjectFileSystem.createZip`.
Path zipFile = tmp.getRoot().resolve("test.zip");
filesystem.createZip(ImmutableList.of(exe), zipFile);
// permissions.
try (ZipFile zip = new ZipFile(zipFile.toFile())) {
Enumeration<ZipArchiveEntry> entries = zip.getEntries();
assertTrue(entries.hasMoreElements());
ZipArchiveEntry entry = entries.nextElement();
Set<PosixFilePermission> permissions = MorePosixFilePermissions.fromMode(entry.getExternalAttributes() >> 16);
assertTrue(permissions.contains(PosixFilePermission.OWNER_EXECUTE));
assertFalse(entries.hasMoreElements());
}
}
use of java.nio.file.attribute.PosixFilePermission in project buck by facebook.
the class ZipStepTest method zipMaintainsExecutablePermissions.
@Test
public void zipMaintainsExecutablePermissions() throws IOException {
assumeTrue(Platform.detect() != Platform.WINDOWS);
Path parent = tmp.newFolder("zipstep");
Path toZip = tmp.newFolder("zipdir");
Path file = toZip.resolve("foo.sh");
ImmutableSet<PosixFilePermission> filePermissions = ImmutableSet.of(PosixFilePermission.OWNER_READ, PosixFilePermission.OWNER_WRITE, PosixFilePermission.OWNER_EXECUTE, PosixFilePermission.GROUP_READ, PosixFilePermission.OTHERS_READ);
Files.createFile(file, PosixFilePermissions.asFileAttribute(filePermissions));
Path outputZip = parent.resolve("output.zip");
ZipStep step = new ZipStep(filesystem, outputZip, ImmutableSet.of(), false, ZipCompressionLevel.MIN_COMPRESSION_LEVEL, Paths.get("zipdir"));
assertEquals(0, step.execute(TestExecutionContext.newInstance()).getExitCode());
Path destination = tmp.newFolder("output");
Unzip.extractZipFile(outputZip, destination, Unzip.ExistingFileMode.OVERWRITE);
assertTrue(Files.isExecutable(destination.resolve("foo.sh")));
}
use of java.nio.file.attribute.PosixFilePermission in project jimfs by google.
the class PosixAttributeProvider method defaultValues.
@SuppressWarnings("unchecked")
@Override
public ImmutableMap<String, ?> defaultValues(Map<String, ?> userProvidedDefaults) {
Object userProvidedGroup = userProvidedDefaults.get("posix:group");
UserPrincipal group = DEFAULT_GROUP;
if (userProvidedGroup != null) {
if (userProvidedGroup instanceof String) {
group = createGroupPrincipal((String) userProvidedGroup);
} else {
throw new IllegalArgumentException("invalid type " + userProvidedGroup.getClass().getName() + " for attribute 'posix:group': should be one of " + String.class + " or " + GroupPrincipal.class);
}
}
Object userProvidedPermissions = userProvidedDefaults.get("posix:permissions");
Set<PosixFilePermission> permissions = DEFAULT_PERMISSIONS;
if (userProvidedPermissions != null) {
if (userProvidedPermissions instanceof String) {
permissions = Sets.immutableEnumSet(PosixFilePermissions.fromString((String) userProvidedPermissions));
} else if (userProvidedPermissions instanceof Set) {
permissions = toPermissions((Set<?>) userProvidedPermissions);
} else {
throw new IllegalArgumentException("invalid type " + userProvidedPermissions.getClass().getName() + " for attribute 'posix:permissions': should be one of " + String.class + " or " + Set.class);
}
}
return ImmutableMap.of("posix:group", group, "posix:permissions", permissions);
}
use of java.nio.file.attribute.PosixFilePermission in project camel by apache.
the class FileOperations method storeFile.
public boolean storeFile(String fileName, Exchange exchange) throws GenericFileOperationFailedException {
ObjectHelper.notNull(endpoint, "endpoint");
File file = new File(fileName);
// if an existing file already exists what should we do?
if (file.exists()) {
if (endpoint.getFileExist() == GenericFileExist.Ignore) {
// ignore but indicate that the file was written
LOG.trace("An existing file already exists: {}. Ignore and do not override it.", file);
return true;
} else if (endpoint.getFileExist() == GenericFileExist.Fail) {
throw new GenericFileOperationFailedException("File already exist: " + file + ". Cannot write new file.");
} else if (endpoint.getFileExist() == GenericFileExist.Move) {
// move any existing file first
doMoveExistingFile(fileName);
}
}
// Do an explicit test for a null body and decide what to do
if (exchange.getIn().getBody() == null) {
if (endpoint.isAllowNullBody()) {
LOG.trace("Writing empty file.");
try {
writeFileEmptyBody(file);
return true;
} catch (IOException e) {
throw new GenericFileOperationFailedException("Cannot store file: " + file, e);
}
} else {
throw new GenericFileOperationFailedException("Cannot write null body to file: " + file);
}
}
// 3. write stream to file
try {
// is there an explicit charset configured we must write the file as
String charset = endpoint.getCharset();
// we can optimize and use file based if no charset must be used, and the input body is a file
File source = null;
boolean fileBased = false;
if (charset == null) {
// if no charset, then we can try using file directly (optimized)
Object body = exchange.getIn().getBody();
if (body instanceof WrappedFile) {
body = ((WrappedFile<?>) body).getFile();
}
if (body instanceof File) {
source = (File) body;
fileBased = true;
}
}
if (fileBased) {
// okay we know the body is a file based
// so try to see if we can optimize by renaming the local work path file instead of doing
// a full file to file copy, as the local work copy is to be deleted afterwards anyway
// local work path
File local = exchange.getIn().getHeader(Exchange.FILE_LOCAL_WORK_PATH, File.class);
if (local != null && local.exists()) {
boolean renamed = writeFileByLocalWorkPath(local, file);
if (renamed) {
// try to keep last modified timestamp if configured to do so
keepLastModified(exchange, file);
// set permissions if the chmod option was set
if (ObjectHelper.isNotEmpty(endpoint.getChmod())) {
Set<PosixFilePermission> permissions = endpoint.getPermissions();
if (!permissions.isEmpty()) {
if (LOG.isTraceEnabled()) {
LOG.trace("Setting chmod: {} on file: {} ", PosixFilePermissions.toString(permissions), file);
}
Files.setPosixFilePermissions(file.toPath(), permissions);
}
}
// clear header as we have renamed the file
exchange.getIn().setHeader(Exchange.FILE_LOCAL_WORK_PATH, null);
// to the target.
return true;
}
} else if (source != null && source.exists()) {
// no there is no local work file so use file to file copy if the source exists
writeFileByFile(source, file);
// try to keep last modified timestamp if configured to do so
keepLastModified(exchange, file);
// set permissions if the chmod option was set
if (ObjectHelper.isNotEmpty(endpoint.getChmod())) {
Set<PosixFilePermission> permissions = endpoint.getPermissions();
if (!permissions.isEmpty()) {
if (LOG.isTraceEnabled()) {
LOG.trace("Setting chmod: {} on file: {} ", PosixFilePermissions.toString(permissions), file);
}
Files.setPosixFilePermissions(file.toPath(), permissions);
}
}
return true;
}
}
if (charset != null) {
// charset configured so we must use a reader so we can write with encoding
Reader in = exchange.getContext().getTypeConverter().tryConvertTo(Reader.class, exchange, exchange.getIn().getBody());
if (in == null) {
// okay no direct reader conversion, so use an input stream (which a lot can be converted as)
InputStream is = exchange.getIn().getMandatoryBody(InputStream.class);
in = new InputStreamReader(is);
}
// buffer the reader
in = IOHelper.buffered(in);
writeFileByReaderWithCharset(in, file, charset);
} else {
// fallback and use stream based
InputStream in = exchange.getIn().getMandatoryBody(InputStream.class);
writeFileByStream(in, file);
}
// try to keep last modified timestamp if configured to do so
keepLastModified(exchange, file);
// set permissions if the chmod option was set
if (ObjectHelper.isNotEmpty(endpoint.getChmod())) {
Set<PosixFilePermission> permissions = endpoint.getPermissions();
if (!permissions.isEmpty()) {
if (LOG.isTraceEnabled()) {
LOG.trace("Setting chmod: {} on file: {} ", PosixFilePermissions.toString(permissions), file);
}
Files.setPosixFilePermissions(file.toPath(), permissions);
}
}
return true;
} catch (IOException e) {
throw new GenericFileOperationFailedException("Cannot store file: " + file, e);
} catch (InvalidPayloadException e) {
throw new GenericFileOperationFailedException("Cannot store file: " + file, e);
}
}
Aggregations