mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Fix listing file attributes in IdeaWin32
This commit is contained in:
Binary file not shown.
Binary file not shown.
@@ -31,13 +31,6 @@ static jclass getFileInfoClass(JNIEnv *env) {
|
||||
return env->FindClass("com/intellij/openapi/util/io/win32/FileInfo");
|
||||
}
|
||||
|
||||
static HANDLE FindFileInner(JNIEnv *env, jstring path, LPWIN32_FIND_DATA lpData) {
|
||||
const jchar* str = env->GetStringChars(path, 0);
|
||||
const HANDLE h = FindFirstFile((LPCWSTR)str, lpData);
|
||||
env->ReleaseStringChars(path, str);
|
||||
return h;
|
||||
}
|
||||
|
||||
static bool CopyObjectArray(JNIEnv *env, jobjectArray dst, jobjectArray src, jint count) {
|
||||
for (int i = 0; i < count; i++) {
|
||||
jobject p = env->GetObjectArrayElement(src, i);
|
||||
@@ -142,11 +135,12 @@ 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) {
|
||||
const jchar* pathStr = env->GetStringChars(path, 0);
|
||||
|
||||
WIN32_FILE_ATTRIBUTE_DATA attrData;
|
||||
const jchar* str = env->GetStringChars(path, 0);
|
||||
BOOL res = GetFileAttributesEx((LPCWSTR)str, GetFileExInfoStandard, &attrData);
|
||||
env->ReleaseStringChars(path, str);
|
||||
BOOL res = GetFileAttributesEx((LPCWSTR)pathStr, GetFileExInfoStandard, &attrData);
|
||||
if (!res) {
|
||||
env->ReleaseStringChars(path, pathStr);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -159,7 +153,7 @@ JNIEXPORT jobject JNICALL Java_com_intellij_openapi_util_io_win32_IdeaWin32_getI
|
||||
|
||||
if (IS_SET(attrData.dwFileAttributes, FILE_ATTRIBUTE_REPARSE_POINT)) {
|
||||
WIN32_FIND_DATA findData;
|
||||
HANDLE h = FindFileInner(env, path, &findData);
|
||||
HANDLE h = FindFirstFile((LPCWSTR)pathStr, &findData);
|
||||
if (h != INVALID_HANDLE_VALUE) {
|
||||
FindClose(h);
|
||||
data.dwFileAttributes = findData.dwFileAttributes;
|
||||
@@ -170,6 +164,8 @@ JNIEXPORT jobject JNICALL Java_com_intellij_openapi_util_io_win32_IdeaWin32_getI
|
||||
}
|
||||
}
|
||||
|
||||
env->ReleaseStringChars(path, pathStr);
|
||||
|
||||
jclass fileInfoClass = getFileInfoClass(env);
|
||||
if (fileInfoClass == NULL) {
|
||||
return NULL;
|
||||
@@ -184,58 +180,65 @@ JNIEXPORT jstring JNICALL Java_com_intellij_openapi_util_io_win32_IdeaWin32_reso
|
||||
return NULL; // XP
|
||||
}
|
||||
|
||||
WIN32_FIND_DATA data;
|
||||
HANDLE h = FindFileInner(env, path, &data);
|
||||
if (h == INVALID_HANDLE_VALUE) {
|
||||
return NULL;
|
||||
}
|
||||
FindClose(h);
|
||||
|
||||
if (!IS_SET(data.dwFileAttributes, FILE_ATTRIBUTE_REPARSE_POINT) || !IS_SET(data.dwReserved0, IO_REPARSE_TAG_SYMLINK)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const jchar* str = env->GetStringChars(path, 0);
|
||||
HANDLE th = CreateFile((LPCWSTR)str, 0, FILE_SHARE_ATTRIBUTES, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
|
||||
env->ReleaseStringChars(path, str);
|
||||
if (th == INVALID_HANDLE_VALUE) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const jchar* pathStr = env->GetStringChars(path, 0);
|
||||
jstring result = NULL;
|
||||
|
||||
TCHAR name[MAX_PATH];
|
||||
DWORD len = __GetFinalPathNameByHandle(th, name, MAX_PATH, 0);
|
||||
if (len > 0) {
|
||||
if (len < MAX_PATH) {
|
||||
result = env->NewString((jchar *)name, len);
|
||||
}
|
||||
else {
|
||||
TCHAR *name = (TCHAR *)malloc(sizeof(TCHAR) * (len + 1));
|
||||
if (name != NULL) {
|
||||
len = __GetFinalPathNameByHandle(th, name, len, 0);
|
||||
WIN32_FIND_DATA data;
|
||||
HANDLE h = FindFirstFile((LPCWSTR)pathStr, &data);
|
||||
if (h != INVALID_HANDLE_VALUE) {
|
||||
FindClose(h);
|
||||
|
||||
if (IS_SET(data.dwFileAttributes, FILE_ATTRIBUTE_REPARSE_POINT) && IS_SET(data.dwReserved0, IO_REPARSE_TAG_SYMLINK)) {
|
||||
HANDLE th = CreateFile((LPCWSTR)pathStr, 0, FILE_SHARE_ATTRIBUTES, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
|
||||
if (th != INVALID_HANDLE_VALUE) {
|
||||
TCHAR name[MAX_PATH];
|
||||
DWORD len = __GetFinalPathNameByHandle(th, name, MAX_PATH, 0);
|
||||
if (len > 0) {
|
||||
result = env->NewString((jchar *)name, len);
|
||||
if (len < MAX_PATH) {
|
||||
result = env->NewString((jchar *)name, len);
|
||||
}
|
||||
else {
|
||||
TCHAR *name = (TCHAR *)malloc(sizeof(TCHAR) * (len + 1));
|
||||
if (name != NULL) {
|
||||
len = __GetFinalPathNameByHandle(th, name, len, 0);
|
||||
if (len > 0) {
|
||||
result = env->NewString((jchar *)name, len);
|
||||
}
|
||||
free(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
free(name);
|
||||
CloseHandle(th);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CloseHandle(th);
|
||||
env->ReleaseStringChars(path, pathStr);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT jobjectArray JNICALL Java_com_intellij_openapi_util_io_win32_IdeaWin32_listChildren0(JNIEnv *env, jobject method, jstring path) {
|
||||
WIN32_FIND_DATA data;
|
||||
HANDLE h = FindFileInner(env, path, &data);
|
||||
if (h == INVALID_HANDLE_VALUE) {
|
||||
jclass fileInfoClass = getFileInfoClass(env);
|
||||
if (fileInfoClass == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
jclass fileInfoClass = getFileInfoClass(env);
|
||||
if (fileInfoClass == NULL) {
|
||||
size_t pathLen = env->GetStringLength(path) + 3;
|
||||
wchar_t* pathStr = (wchar_t *)malloc(pathLen * sizeof(wchar_t));
|
||||
if (pathStr == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
const jchar* str = env->GetStringChars(path, 0);
|
||||
wcscpy_s(pathStr, pathLen, (LPCWSTR)str);
|
||||
wcscat_s(pathStr, pathLen, L"\\*");
|
||||
env->ReleaseStringChars(path, str);
|
||||
|
||||
WIN32_FIND_DATA data;
|
||||
HANDLE h = FindFirstFile((LPCWSTR)pathStr, &data);
|
||||
if (h == INVALID_HANDLE_VALUE) {
|
||||
free(pathStr);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -261,17 +264,20 @@ JNIEXPORT jobjectArray JNICALL Java_com_intellij_openapi_util_io_win32_IdeaWin32
|
||||
}
|
||||
while (FindNextFile(h, &data));
|
||||
|
||||
FindClose(h);
|
||||
free(pathStr);
|
||||
FindClose(h);
|
||||
|
||||
old = rv;
|
||||
rv = env->NewObjectArray(len, fileInfoClass, NULL);
|
||||
if (rv == NULL || !CopyObjectArray(env, rv, old, len)) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
return rv;
|
||||
|
||||
error:
|
||||
FindClose(h);
|
||||
free(pathStr);
|
||||
FindClose(h);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
+8
-5
@@ -109,11 +109,14 @@ public class SymlinkHandlingTest extends LightPlatformLangTestCase {
|
||||
assertEquals(upDir.getPath(), upLinkVFile.getCanonicalPath());
|
||||
assertVisitedPaths(upDir.getPath(), upLinkVFile.getPath());
|
||||
|
||||
final File nestedLinksFile = new File(upDir.getPath() + StringUtil.repeat(File.separator + upLinkFile.getName(), 4));
|
||||
assertTrue(nestedLinksFile.getPath(), nestedLinksFile.isDirectory());
|
||||
final VirtualFile nestedLinksVFile = refreshAndFind(nestedLinksFile);
|
||||
assertNotNull(nestedLinksFile.getPath(), nestedLinksVFile);
|
||||
assertEquals(upLinkVFile.getCanonicalFile(), nestedLinksVFile.getCanonicalFile());
|
||||
final File repeatedLinksFile = new File(upDir.getPath() + StringUtil.repeat(File.separator + upLinkFile.getName(), 4));
|
||||
assertTrue(repeatedLinksFile.getPath(), repeatedLinksFile.isDirectory());
|
||||
final VirtualFile repeatedLinksVFile = refreshAndFind(repeatedLinksFile);
|
||||
assertNotNull(repeatedLinksFile.getPath(), repeatedLinksVFile);
|
||||
assertTrue(repeatedLinksVFile.isSymLink());
|
||||
assertTrue(repeatedLinksVFile.isDirectory());
|
||||
assertEquals(upDir.getPath(), repeatedLinksVFile.getCanonicalPath());
|
||||
assertEquals(upLinkVFile.getCanonicalFile(), repeatedLinksVFile.getCanonicalFile());
|
||||
}
|
||||
|
||||
public void testMutualRecursiveLinks() throws Exception {
|
||||
|
||||
@@ -36,7 +36,6 @@ public class IdeaWin32 {
|
||||
|
||||
private static final String PATH_PREFIX = "\\\\?\\";
|
||||
private static final int PREFIX_SIZE = PATH_PREFIX.length();
|
||||
private static final String PATH_SUFFIX = "\\*.*";
|
||||
private static final int MAX_PATH = 260;
|
||||
|
||||
private static final IdeaWin32 ourInstance;
|
||||
@@ -111,7 +110,7 @@ public class IdeaWin32 {
|
||||
@Nullable
|
||||
public FileInfo[] listChildren(@NotNull final String path) {
|
||||
LogUtil.debug(LOG, "list(%s)", path);
|
||||
return listChildren0(path(path) + PATH_SUFFIX);
|
||||
return listChildren0(path(path));
|
||||
}
|
||||
|
||||
private static String path(final String path) {
|
||||
|
||||
@@ -208,6 +208,22 @@ public class FileAttributesReadingTest {
|
||||
assertNull(target);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void selfLink() throws Exception {
|
||||
assumeTrue(SystemInfo.areSymLinksSupported);
|
||||
|
||||
final File dir = FileUtil.createTempDirectory(myTempDirectory, "test.", ".dir");
|
||||
final File link = IoTestUtil.createTempLink(dir.getPath(), new File(dir, "link").getPath());
|
||||
|
||||
final FileAttributes attributes = getAttributes(link);
|
||||
assertEquals(FileAttributes.Type.DIRECTORY, attributes.type);
|
||||
assertEquals(FileAttributes.SYM_LINK, attributes.flags);
|
||||
assertTimestampsEqual(dir.lastModified(), attributes.lastModified);
|
||||
|
||||
final String target = FileSystemUtil.resolveSymLink(link);
|
||||
assertEquals(dir.getPath(), target);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void junction() throws Exception {
|
||||
assumeTrue(SystemInfo.isWindows);
|
||||
@@ -235,7 +251,7 @@ public class FileAttributesReadingTest {
|
||||
final File file = new File("C:\\Documents and Settings\\desktop.ini");
|
||||
assumeTrue(file.exists());
|
||||
|
||||
final FileAttributes attributes = getAttributes(file);
|
||||
final FileAttributes attributes = getAttributes(file, false);
|
||||
assertEquals(FileAttributes.Type.FILE, attributes.type);
|
||||
assertEquals(FileAttributes.HIDDEN, attributes.flags);
|
||||
assertEquals(file.length(), attributes.length);
|
||||
@@ -302,9 +318,30 @@ public class FileAttributesReadingTest {
|
||||
|
||||
@NotNull
|
||||
private static FileAttributes getAttributes(@NotNull final File file) {
|
||||
return getAttributes(file, true);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static FileAttributes getAttributes(@NotNull final File file, final boolean checkList) {
|
||||
final FileAttributes attributes = FileSystemUtil.getAttributes(file);
|
||||
assertNotNull(attributes);
|
||||
System.out.println(attributes);
|
||||
|
||||
if (SystemInfo.isWindows && checkList) {
|
||||
final String parent = file.getParent();
|
||||
if (parent != null) {
|
||||
final FileInfo[] infos = IdeaWin32.getInstance().listChildren(parent);
|
||||
assertNotNull(infos);
|
||||
for (FileInfo info : infos) {
|
||||
if (file.getName().equals(info.getName())) {
|
||||
assertEquals(attributes, info.toFileAttributes());
|
||||
return attributes;
|
||||
}
|
||||
}
|
||||
fail(file + " not listed");
|
||||
}
|
||||
}
|
||||
|
||||
return attributes;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user