mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Read root path attributes by IdeaWin32
This commit is contained in:
Binary file not shown.
Binary file not shown.
@@ -142,15 +142,24 @@ JNIEXPORT void JNICALL Java_com_intellij_openapi_util_io_win32_IdeaWin32_initIDs
|
||||
|
||||
|
||||
JNIEXPORT jobject JNICALL Java_com_intellij_openapi_util_io_win32_IdeaWin32_getInfo0(JNIEnv *env, jobject method, jstring path) {
|
||||
WIN32_FIND_DATA data;
|
||||
HANDLE h = FindFileInner(env, path, &data);
|
||||
bool isDrive = false;
|
||||
if (env->GetStringLength(path) == 2) {
|
||||
const jchar* str = env->GetStringChars(path, NULL);
|
||||
isDrive = (str[1] == ':');
|
||||
env->ReleaseStringChars(path, str);
|
||||
}
|
||||
|
||||
if (h == INVALID_HANDLE_VALUE) {
|
||||
if (GetLastError() != ERROR_ACCESS_DENIED) {
|
||||
WIN32_FIND_DATA data;
|
||||
HANDLE h = INVALID_HANDLE_VALUE;
|
||||
|
||||
if (!isDrive) {
|
||||
h = FindFileInner(env, path, &data);
|
||||
if (h == INVALID_HANDLE_VALUE && GetLastError() != ERROR_ACCESS_DENIED) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
// there is a chance that directory listing is denied but direct file access will succeed
|
||||
if (h == INVALID_HANDLE_VALUE) {
|
||||
WIN32_FILE_ATTRIBUTE_DATA attrData;
|
||||
const jchar* str = env->GetStringChars(path, 0);
|
||||
BOOL res = GetFileAttributesEx((LPCWSTR)str, GetFileExInfoStandard, &attrData);
|
||||
|
||||
+12
-29
@@ -15,13 +15,13 @@
|
||||
*/
|
||||
package com.intellij.openapi.vfs.local;
|
||||
|
||||
import com.intellij.execution.configurations.GeneralCommandLine;
|
||||
import com.intellij.openapi.application.AccessToken;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.openapi.util.SystemInfo;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.util.io.IoTestUtil;
|
||||
import com.intellij.openapi.vfs.*;
|
||||
import com.intellij.openapi.vfs.impl.local.FileWatcher;
|
||||
import com.intellij.openapi.vfs.newvfs.BulkFileListener;
|
||||
@@ -417,35 +417,16 @@ public class FileWatcherTest extends PlatformLangTestCase {
|
||||
return;
|
||||
}
|
||||
|
||||
final Set<Character> roots = ContainerUtil.map2Set(File.listRoots(), new Function<File, Character>() {
|
||||
@Override
|
||||
public Character fun(File root) {
|
||||
return root.getPath().toLowerCase(Locale.US).charAt(0);
|
||||
}
|
||||
});
|
||||
char subst = 0;
|
||||
for (char c = 'e'; c <= 'z'; c++) {
|
||||
if (!roots.contains(c)) {
|
||||
subst = c;
|
||||
break;
|
||||
}
|
||||
}
|
||||
assertFalse("Occupied: " + roots.toString(), subst == 0);
|
||||
|
||||
final File targetDir = FileUtil.createTempDirectory("top.", null);
|
||||
final File subDir = FileUtil.createTempDirectory(targetDir, "sub.", null);
|
||||
final File file = FileUtil.createTempFile(subDir, "test.", ".txt", true, false);
|
||||
final int rv = new GeneralCommandLine("subst", subst + ":", targetDir.getAbsolutePath()).createProcess().waitFor();
|
||||
assertEquals(0, rv);
|
||||
|
||||
final String substRoot = (subst + ":").toUpperCase(Locale.US);
|
||||
VirtualDirectoryImpl.allowRootAccess(substRoot);
|
||||
|
||||
final VirtualFile vfsRoot = myFileSystem.findFileByPath(substRoot);
|
||||
assertNotNull(substRoot, vfsRoot);
|
||||
final File rootFile = IoTestUtil.createSubst(targetDir.getAbsolutePath());
|
||||
VirtualDirectoryImpl.allowRootAccess(rootFile.getPath());
|
||||
final VirtualFile vfsRoot = myFileSystem.findFileByIoFile(rootFile);
|
||||
|
||||
try {
|
||||
final File substDir = new File(substRoot, subDir.getName());
|
||||
assertNotNull(rootFile.getPath(), vfsRoot);
|
||||
final File substDir = new File(rootFile, subDir.getName());
|
||||
final File substFile = new File(substDir, file.getName());
|
||||
refresh(targetDir);
|
||||
refresh(substDir);
|
||||
@@ -476,10 +457,12 @@ public class FileWatcherTest extends PlatformLangTestCase {
|
||||
}
|
||||
finally {
|
||||
delete(targetDir);
|
||||
new GeneralCommandLine("subst", subst + ":", "/d").createProcess().waitFor();
|
||||
((NewVirtualFile)vfsRoot).markDirty();
|
||||
myFileSystem.refresh(false);
|
||||
VirtualDirectoryImpl.disallowRootAccess(substRoot);
|
||||
IoTestUtil.deleteSubst(rootFile.getPath());
|
||||
if (vfsRoot != null) {
|
||||
((NewVirtualFile)vfsRoot).markDirty();
|
||||
myFileSystem.refresh(false);
|
||||
}
|
||||
VirtualDirectoryImpl.disallowRootAccess(rootFile.getPath());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -97,22 +97,33 @@ public class IdeaWin32 {
|
||||
|
||||
@Nullable
|
||||
public FileInfo getInfo(@NotNull final String path) {
|
||||
return getInfo0(unc(path));
|
||||
return getInfo0(path(path));
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String resolveSymLink(@NotNull final String path) {
|
||||
final String result = resolveSymLink0(unc(path));
|
||||
final String result = resolveSymLink0(path(path));
|
||||
return result != null && result.startsWith(PATH_PREFIX) ? result.substring(PREFIX_SIZE) : result;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public FileInfo[] listChildren(@NotNull final String path) {
|
||||
return listChildren0(unc(path) + PATH_SUFFIX);
|
||||
return listChildren0(path(path) + PATH_SUFFIX);
|
||||
}
|
||||
|
||||
private static String unc(final String path) {
|
||||
return path.length() < MAX_PATH ? path : PATH_PREFIX + path;
|
||||
private static String path(final String path) {
|
||||
final int length = path.length();
|
||||
if (length > 0 && path.charAt(length - 1) == '\\' || length >= MAX_PATH) {
|
||||
final StringBuilder sb = new StringBuilder(path);
|
||||
while (sb.length() > 0 && sb.charAt(sb.length() - 1) == '\\') {
|
||||
sb.deleteCharAt(sb.length() - 1);
|
||||
}
|
||||
if (sb.length() >= MAX_PATH) {
|
||||
sb.insert(0, PATH_PREFIX);
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
||||
private native FileInfo getInfo0(String path);
|
||||
|
||||
@@ -26,6 +26,7 @@ import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Arrays;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import static org.junit.Assume.assumeTrue;
|
||||
@@ -67,12 +68,7 @@ public class FileAttributesReadingTest {
|
||||
final File file = FileUtil.createTempFile(myTempDirectory, "test.", ".txt", true);
|
||||
FileUtil.writeToFile(file, myTestData);
|
||||
|
||||
final FileAttributes attributes = getAttributes(file);
|
||||
assertEquals(FileAttributes.Type.FILE, attributes.type);
|
||||
assertEquals(0, attributes.flags);
|
||||
assertEquals(myTestData.length, attributes.length);
|
||||
assertTimestampEquals(file.lastModified(), attributes.lastModified);
|
||||
assertTrue(attributes.isWritable());
|
||||
assertFileAttributes(file);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -83,8 +79,34 @@ public class FileAttributesReadingTest {
|
||||
assertEquals(FileAttributes.Type.DIRECTORY, attributes.type);
|
||||
assertEquals(0, attributes.flags);
|
||||
assertEquals(file.length(), attributes.length);
|
||||
assertTimestampEquals(file.lastModified(), attributes.lastModified);
|
||||
assertTimestampsEqual(file.lastModified(), attributes.lastModified);
|
||||
assertTrue(attributes.isWritable());
|
||||
if (SystemInfo.isWindows) {
|
||||
assertDirectoriesEqual(file);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void root() throws Exception {
|
||||
final File file = new File(SystemInfo.isWindows ? "C:\\" : "/");
|
||||
|
||||
final FileAttributes attributes = getAttributes(file);
|
||||
assertEquals(FileAttributes.Type.DIRECTORY, attributes.type);
|
||||
if (SystemInfo.isWindows) {
|
||||
assertDirectoriesEqual(file);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void badNames() throws Exception {
|
||||
final File file = FileUtil.createTempFile(myTempDirectory, "test.", ".txt", true);
|
||||
FileUtil.writeToFile(file, myTestData);
|
||||
|
||||
assertFileAttributes(new File(file.getPath() + StringUtil.repeat(File.separator, 3)));
|
||||
assertFileAttributes(new File(file.getPath().replace(File.separator, StringUtil.repeat(File.separator, 3))));
|
||||
assertFileAttributes(new File(file.getPath().replace(File.separator, File.separator + "." + File.separator)));
|
||||
assertFileAttributes(new File(myTempDirectory,
|
||||
File.separator + ".." + File.separator + myTempDirectory.getName() + File.separator + file.getName()));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -113,7 +135,7 @@ public class FileAttributesReadingTest {
|
||||
assertEquals(FileAttributes.Type.FILE, attributes.type);
|
||||
assertEquals(FileAttributes.SYM_LINK, attributes.flags);
|
||||
assertEquals(myTestData.length, attributes.length);
|
||||
assertTimestampEquals(file.lastModified(), attributes.lastModified);
|
||||
assertTimestampsEqual(file.lastModified(), attributes.lastModified);
|
||||
assertFalse(attributes.isWritable());
|
||||
|
||||
final String target = FileSystemUtil.resolveSymLink(link);
|
||||
@@ -135,7 +157,7 @@ public class FileAttributesReadingTest {
|
||||
assertEquals(FileAttributes.Type.FILE, attributes.type);
|
||||
assertEquals(FileAttributes.SYM_LINK, attributes.flags);
|
||||
assertEquals(myTestData.length, attributes.length);
|
||||
assertTimestampEquals(file.lastModified(), attributes.lastModified);
|
||||
assertTimestampsEqual(file.lastModified(), attributes.lastModified);
|
||||
assertFalse(attributes.isWritable());
|
||||
|
||||
final String target = FileSystemUtil.resolveSymLink(link2);
|
||||
@@ -155,7 +177,7 @@ public class FileAttributesReadingTest {
|
||||
assertEquals(FileAttributes.Type.DIRECTORY, attributes.type);
|
||||
assertEquals(FileAttributes.SYM_LINK, attributes.flags);
|
||||
assertEquals(file.length(), attributes.length);
|
||||
assertTimestampEquals(file.lastModified(), attributes.lastModified);
|
||||
assertTimestampsEqual(file.lastModified(), attributes.lastModified);
|
||||
if (SystemInfo.isUnix) assertFalse(attributes.isWritable());
|
||||
|
||||
final String target = FileSystemUtil.resolveSymLink(link);
|
||||
@@ -209,7 +231,7 @@ public class FileAttributesReadingTest {
|
||||
assertEquals(FileAttributes.Type.FILE, attributes.type);
|
||||
assertEquals(FileAttributes.HIDDEN, attributes.flags);
|
||||
assertEquals(file.length(), attributes.length);
|
||||
assertTimestampEquals(file.lastModified(), attributes.lastModified);
|
||||
assertTimestampsEqual(file.lastModified(), attributes.lastModified);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -231,19 +253,25 @@ public class FileAttributesReadingTest {
|
||||
assertTrue(file.exists());
|
||||
FileUtil.writeToFile(file, myTestData);
|
||||
|
||||
final FileAttributes attributes = getAttributes(file);
|
||||
assertEquals(FileAttributes.Type.FILE, attributes.type);
|
||||
assertEquals(0, attributes.flags);
|
||||
assertEquals(myTestData.length, attributes.length);
|
||||
assertTimestampEquals(file.lastModified(), attributes.lastModified);
|
||||
assertTrue(attributes.isWritable());
|
||||
|
||||
assertFileAttributes(file);
|
||||
if (SystemInfo.isWindows) {
|
||||
final String[] list1 = dir.list();
|
||||
assertNotNull(list1);
|
||||
final FileInfo[] list2 = IdeaWin32.getInstance().listChildren(dir.getPath());
|
||||
assertNotNull(list2);
|
||||
assertEquals(list1.length + 2, list2.length);
|
||||
assertDirectoriesEqual(dir);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void subst() throws Exception {
|
||||
assumeTrue(SystemInfo.isWindows);
|
||||
|
||||
FileUtil.createTempFile(myTempDirectory, "test.", ".txt", true); // just to populate a directory
|
||||
final File substRoot = IoTestUtil.createSubst(myTempDirectory.getPath());
|
||||
try {
|
||||
final FileAttributes attributes = getAttributes(substRoot);
|
||||
assertEquals(FileAttributes.Type.DIRECTORY, attributes.type);
|
||||
assertDirectoriesEqual(substRoot);
|
||||
}
|
||||
finally {
|
||||
IoTestUtil.deleteSubst(substRoot.getPath());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -255,10 +283,29 @@ public class FileAttributesReadingTest {
|
||||
return attributes;
|
||||
}
|
||||
|
||||
private static void assertTimestampEquals(final long expected, final long actual) {
|
||||
private static void assertFileAttributes(@NotNull final File file) {
|
||||
final FileAttributes attributes = getAttributes(file);
|
||||
assertEquals(FileAttributes.Type.FILE, attributes.type);
|
||||
assertEquals(0, attributes.flags);
|
||||
assertEquals(file.length(), attributes.length);
|
||||
assertTimestampsEqual(file.lastModified(), attributes.lastModified);
|
||||
assertTrue(attributes.isWritable());
|
||||
}
|
||||
|
||||
private static void assertTimestampsEqual(final long expected, final long actual) {
|
||||
final long roundedExpected = (expected / 1000) * 1000;
|
||||
final long roundedActual = (actual / 1000) * 1000;
|
||||
assertEquals("expected: " + expected + ", actual: " + actual,
|
||||
roundedExpected, roundedActual);
|
||||
}
|
||||
|
||||
private static void assertDirectoriesEqual(@NotNull final File dir) {
|
||||
final String[] list1 = dir.list();
|
||||
assertNotNull(list1);
|
||||
final FileInfo[] list2 = IdeaWin32.getInstance().listChildren(dir.getPath());
|
||||
assertNotNull(list2);
|
||||
if (list1.length + 2 != list2.length) {
|
||||
assertEquals(Arrays.toString(list1), Arrays.toString(list2));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,6 +17,8 @@ package com.intellij.openapi.util.io;
|
||||
|
||||
import com.intellij.openapi.util.SystemInfo;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.util.Function;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
@@ -24,9 +26,10 @@ import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.URL;
|
||||
import java.util.Locale;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
public class IoTestUtil {
|
||||
private IoTestUtil() { }
|
||||
@@ -92,6 +95,47 @@ public class IoTestUtil {
|
||||
return junctionFile;
|
||||
}
|
||||
|
||||
public static File createSubst(@NotNull final String target) throws InterruptedException, IOException {
|
||||
assertTrue(SystemInfo.isWindows);
|
||||
|
||||
final File targetFile = new File(target);
|
||||
assertTrue(targetFile.getPath(), targetFile.isDirectory());
|
||||
|
||||
final String substRoot = getFirstFreeDriveLetter() + ":";
|
||||
|
||||
final ProcessBuilder command = new ProcessBuilder("subst", substRoot, target);
|
||||
final int res = runCommand(command);
|
||||
assertEquals(command.command().toString(), 0, res);
|
||||
|
||||
final File rootFile = new File(substRoot);
|
||||
assertTrue("target=" + target + ", subst=" + rootFile, rootFile.isDirectory());
|
||||
return rootFile;
|
||||
}
|
||||
|
||||
public static void deleteSubst(@NotNull final String substRoot) throws InterruptedException, IOException {
|
||||
runCommand(new ProcessBuilder("subst", substRoot, "/d"));
|
||||
}
|
||||
|
||||
private static char getFirstFreeDriveLetter() {
|
||||
final Set<Character> roots = ContainerUtil.map2Set(File.listRoots(), new Function<File, Character>() {
|
||||
@Override
|
||||
public Character fun(File root) {
|
||||
return root.getPath().toUpperCase(Locale.US).charAt(0);
|
||||
}
|
||||
});
|
||||
|
||||
char drive = 0;
|
||||
for (char c = 'E'; c <= 'Z'; c++) {
|
||||
if (!roots.contains(c)) {
|
||||
drive = c;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
assertFalse("Occupied: " + roots.toString(), drive == 0);
|
||||
return drive;
|
||||
}
|
||||
|
||||
private static File getFullLinkPath(final String link) {
|
||||
final boolean isAbsolute = SystemInfo.isUnix && StringUtil.startsWithChar(link, '/') ||
|
||||
SystemInfo.isWindows && link.matches("^[c-zC-Z]:[/\\\\].*$");
|
||||
|
||||
Reference in New Issue
Block a user