mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
clone only 'executable' permissions during copying to avoid read-only files in the output (IDEA-133984)
This commit is contained in:
@@ -56,7 +56,7 @@ public class FileSystemUtil {
|
||||
@Nullable
|
||||
protected abstract String resolveSymLink(@NotNull String path) throws Exception;
|
||||
|
||||
protected boolean clonePermissions(@NotNull String source, @NotNull String target) throws Exception { return false; }
|
||||
protected boolean clonePermissions(@NotNull String source, @NotNull String target, boolean onlyPermissionsToExecute) throws Exception { return false; }
|
||||
|
||||
@NotNull
|
||||
private String getName() { return getClass().getSimpleName().replace("MediatorImpl", ""); }
|
||||
@@ -196,7 +196,21 @@ public class FileSystemUtil {
|
||||
*/
|
||||
public static boolean clonePermissions(@NotNull String source, @NotNull String target) {
|
||||
try {
|
||||
return ourMediator.clonePermissions(source, target);
|
||||
return ourMediator.clonePermissions(source, target, false);
|
||||
}
|
||||
catch (Exception e) {
|
||||
LOG.warn(e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gives the second file permissions to execute of the first one if possible; returns true if succeed.
|
||||
* Will do nothing on Windows.
|
||||
*/
|
||||
public static boolean clonePermissionsToExecute(@NotNull String source, @NotNull String target) {
|
||||
try {
|
||||
return ourMediator.clonePermissions(source, target, true);
|
||||
}
|
||||
catch (Exception e) {
|
||||
LOG.warn(e);
|
||||
@@ -303,22 +317,44 @@ public class FileSystemUtil {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean clonePermissions(@NotNull String source, @NotNull String target) throws Exception {
|
||||
protected boolean clonePermissions(@NotNull String source, @NotNull String target, boolean onlyPermissionsToExecute) throws Exception {
|
||||
if (SystemInfo.isUnix) {
|
||||
Object sourcePath = myGetPath.invoke(myDefaultFileSystem, source, ArrayUtil.EMPTY_STRING_ARRAY);
|
||||
Object targetPath = myGetPath.invoke(myDefaultFileSystem, target, ArrayUtil.EMPTY_STRING_ARRAY);
|
||||
Map attributes = (Map)myReadAttributes.invoke(null, sourcePath, "posix:permissions", myLinkOptions);
|
||||
if (attributes != null) {
|
||||
Object permissions = attributes.get("permissions");
|
||||
if (permissions instanceof Collection) {
|
||||
mySetAttribute.invoke(null, targetPath, "posix:permissions", permissions, myLinkOptions);
|
||||
return true;
|
||||
Collection sourcePermissions = getPermissions(sourcePath);
|
||||
if (sourcePermissions != null) {
|
||||
Collection permissionsToSet;
|
||||
if (onlyPermissionsToExecute) {
|
||||
Collection targetPermissions = getPermissions(targetPath);
|
||||
permissionsToSet = new HashSet();
|
||||
for (Object permission : targetPermissions) {
|
||||
if (!permission.toString().endsWith("_EXECUTE")) {
|
||||
permissionsToSet.add(permission);
|
||||
}
|
||||
}
|
||||
for (Object permission : sourcePermissions) {
|
||||
if (permission.toString().endsWith("_EXECUTE")) {
|
||||
permissionsToSet.add(permission);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
permissionsToSet = sourcePermissions;
|
||||
}
|
||||
mySetAttribute.invoke(null, targetPath, "posix:permissions", permissionsToSet, myLinkOptions);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private Collection getPermissions(Object sourcePath) throws IllegalAccessException, InvocationTargetException {
|
||||
Map attributes = (Map)myReadAttributes.invoke(null, sourcePath, "posix:permissions", myLinkOptions);
|
||||
if (attributes == null) return null;
|
||||
Object permissions = attributes.get("permissions");
|
||||
return permissions instanceof Collection<?> ? (Collection)permissions : null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -347,6 +383,7 @@ public class FileSystemUtil {
|
||||
int S_IFREG = 0100000; // regular file
|
||||
int S_IFDIR = 0040000; // directory
|
||||
int PERM_MASK = 0777;
|
||||
int EXECUTE_MASK = 0111;
|
||||
int WRITE_MASK = 0222;
|
||||
int W_OK = 2; // write permission flag for access(2)
|
||||
|
||||
@@ -397,14 +434,13 @@ public class FileSystemUtil {
|
||||
int res = SystemInfo.isLinux ? myLibC.__lxstat64(0, path, buffer) : myLibC.lstat(path, buffer);
|
||||
if (res != 0) return null;
|
||||
|
||||
int mode = (SystemInfo.isLinux ? buffer.getInt(myOffsets[OFF_MODE]) : buffer.getShort(myOffsets[OFF_MODE])) & LibC.S_MASK;
|
||||
int mode = getModeFlags(buffer) & LibC.S_MASK;
|
||||
boolean isSymlink = (mode & LibC.S_IFLNK) == LibC.S_IFLNK;
|
||||
if (isSymlink) {
|
||||
res = SystemInfo.isLinux ? myLibC.__xstat64(0, path, buffer) : myLibC.stat(path, buffer);
|
||||
if (res != 0) {
|
||||
if (!loadFileStatus(path, buffer)) {
|
||||
return FileAttributes.BROKEN_SYMLINK;
|
||||
}
|
||||
mode = (SystemInfo.isLinux ? buffer.getInt(myOffsets[OFF_MODE]) : buffer.getShort(myOffsets[OFF_MODE])) & LibC.S_MASK;
|
||||
mode = getModeFlags(buffer) & LibC.S_MASK;
|
||||
}
|
||||
|
||||
boolean isDirectory = (mode & LibC.S_IFDIR) == LibC.S_IFDIR;
|
||||
@@ -419,6 +455,10 @@ public class FileSystemUtil {
|
||||
return new FileAttributes(isDirectory, isSpecial, isSymlink, false, size, mTime, writable);
|
||||
}
|
||||
|
||||
private boolean loadFileStatus(@NotNull String path, Memory buffer) {
|
||||
return (SystemInfo.isLinux ? myLibC.__xstat64(0, path, buffer) : myLibC.stat(path, buffer)) == 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String resolveSymLink(@NotNull final String path) throws Exception {
|
||||
try {
|
||||
@@ -435,15 +475,25 @@ public class FileSystemUtil {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean clonePermissions(@NotNull String source, @NotNull String target) throws Exception {
|
||||
protected boolean clonePermissions(@NotNull String source, @NotNull String target, boolean onlyPermissionsToExecute) throws Exception {
|
||||
Memory buffer = new Memory(256);
|
||||
int res = SystemInfo.isLinux ? myLibC.__xstat64(0, source, buffer) : myLibC.stat(source, buffer);
|
||||
if (res == 0) {
|
||||
int permissions = (SystemInfo.isLinux ? buffer.getInt(myOffsets[OFF_MODE]) : buffer.getShort(myOffsets[OFF_MODE])) & LibC.PERM_MASK;
|
||||
return myLibC.chmod(target, permissions) == 0;
|
||||
}
|
||||
if (!loadFileStatus(source, buffer)) return false;
|
||||
|
||||
return false;
|
||||
int permissions;
|
||||
int sourcePermissions = getModeFlags(buffer) & LibC.PERM_MASK;
|
||||
if (onlyPermissionsToExecute) {
|
||||
if (!loadFileStatus(target, buffer)) return false;
|
||||
int targetPermissions = getModeFlags(buffer) & LibC.PERM_MASK;
|
||||
permissions = targetPermissions & ~LibC.EXECUTE_MASK | sourcePermissions & LibC.EXECUTE_MASK;
|
||||
}
|
||||
else {
|
||||
permissions = sourcePermissions;
|
||||
}
|
||||
return myLibC.chmod(target, permissions) == 0;
|
||||
}
|
||||
|
||||
private int getModeFlags(Memory buffer) {
|
||||
return SystemInfo.isLinux ? buffer.getInt(myOffsets[OFF_MODE]) : buffer.getShort(myOffsets[OFF_MODE]);
|
||||
}
|
||||
|
||||
private boolean ownFile(Memory buffer) {
|
||||
@@ -510,11 +560,14 @@ public class FileSystemUtil {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean clonePermissions(@NotNull String source, @NotNull String target) throws Exception {
|
||||
protected boolean clonePermissions(@NotNull String source, @NotNull String target, boolean onlyPermissionsToExecute) throws Exception {
|
||||
if (SystemInfo.isUnix) {
|
||||
File srcFile = new File(source);
|
||||
File dstFile = new File(target);
|
||||
return dstFile.setWritable(srcFile.canWrite(), true) && dstFile.setExecutable(srcFile.canExecute(), true);
|
||||
if (!onlyPermissionsToExecute) {
|
||||
if (!dstFile.setWritable(srcFile.canWrite(), true)) return false;
|
||||
}
|
||||
return dstFile.setExecutable(srcFile.canExecute(), true);
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
@@ -497,7 +497,7 @@ public class FileUtil extends FileUtilRt {
|
||||
}
|
||||
|
||||
if (SystemInfo.isUnix && fromFile.canExecute()) {
|
||||
FileSystemUtil.clonePermissions(fromFile.getPath(), toFile.getPath());
|
||||
FileSystemUtil.clonePermissionsToExecute(fromFile.getPath(), toFile.getPath());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user