diff options
| author | Sergey Prigogin | 2012-09-11 19:53:17 +0000 |
|---|---|---|
| committer | John Arthorne | 2012-09-26 19:32:00 +0000 |
| commit | ded2429478f74f10e906b63a82e665e593cee70a (patch) | |
| tree | bd2aa2940747660ebb1bddc49063b0f65e530494 | |
| parent | 1ee7648e5251c89243cc020a6f22e0cf3d1b73cb (diff) | |
| download | eclipse.platform.resources-ded2429478f74f10e906b63a82e665e593cee70a.tar.gz eclipse.platform.resources-ded2429478f74f10e906b63a82e665e593cee70a.tar.xz eclipse.platform.resources-ded2429478f74f10e906b63a82e665e593cee70a.zip | |
Fix for bug 379193 - Eclipse doesn't distinguish between I/O errors and
deleted files.
Change-Id: I6ce841a4ea40c3955077ba5c34176ccf4e6bf418
11 files changed, 98 insertions, 11 deletions
diff --git a/bundles/org.eclipse.core.filesystem.win32.x86/os/win32/x86/localfile_1_0_0.dll b/bundles/org.eclipse.core.filesystem.win32.x86/os/win32/x86/localfile_1_0_0.dll Binary files differindex 4952788c4..41793d272 100644 --- a/bundles/org.eclipse.core.filesystem.win32.x86/os/win32/x86/localfile_1_0_0.dll +++ b/bundles/org.eclipse.core.filesystem.win32.x86/os/win32/x86/localfile_1_0_0.dll diff --git a/bundles/org.eclipse.core.filesystem/META-INF/MANIFEST.MF b/bundles/org.eclipse.core.filesystem/META-INF/MANIFEST.MF index 00861e313..7adad0f45 100644 --- a/bundles/org.eclipse.core.filesystem/META-INF/MANIFEST.MF +++ b/bundles/org.eclipse.core.filesystem/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: %pluginName Bundle-SymbolicName: org.eclipse.core.filesystem; singleton:=true -Bundle-Version: 1.3.200.qualifier +Bundle-Version: 1.4.0.qualifier Bundle-Localization: plugin Require-Bundle: org.eclipse.equinox.common;bundle-version="[3.2.0,4.0.0)", org.eclipse.equinox.registry;bundle-version="[3.2.0,4.0.0)", diff --git a/bundles/org.eclipse.core.filesystem/natives/localfile.h b/bundles/org.eclipse.core.filesystem/natives/localfile.h index a7469c2ce..02572ac34 100644 --- a/bundles/org.eclipse.core.filesystem/natives/localfile.h +++ b/bundles/org.eclipse.core.filesystem/natives/localfile.h @@ -40,6 +40,10 @@ extern "C" { #undef SET_LAST_MODIFIED #define SET_LAST_MODIFIED 0x02l +// From FileInfo.java +#undef ATTRIBUTE_IO_ERROR +#define ATTRIBUTE_IO_ERROR 0x20000 + /* * Class: org_eclipse_core_internal_filesystem_local_LocalFileNatives * Method: nativeAttributes diff --git a/bundles/org.eclipse.core.filesystem/natives/win32/localfile.c b/bundles/org.eclipse.core.filesystem/natives/win32/localfile.c index f428b604b..d74e993e1 100644 --- a/bundles/org.eclipse.core.filesystem/natives/win32/localfile.c +++ b/bundles/org.eclipse.core.filesystem/natives/win32/localfile.c @@ -47,8 +47,6 @@ typedef struct _REPARSE_DATA_BUFFER { }; } REPARSE_DATA_BUFFER, *PREPARSE_DATA_BUFFER; - - /* * Converts a FILETIME in a java long (milliseconds). */ @@ -380,6 +378,20 @@ jboolean fillEmptyDirectory(JNIEnv *env, jobject fileInfo) { } /* + * Sets FileInfo.ATTRIBUTE_IO_ERROR flag. + */ +jboolean setIOError(JNIEnv *env, jobject fileInfo) { + jclass cls; + jmethodID mid; + cls = (*env)->GetObjectClass(env, fileInfo); + if (cls != 0) return JNI_FALSE; + mid = (*env)->GetMethodID(env, cls, "setAttribute", "(IZ)V"); + if (mid == 0) return JNI_FALSE; + (*env)->CallVoidMethod(env, fileInfo, mid, ATTRIBUTE_IO_ERROR, JNI_TRUE); + return JNI_TRUE; +} + +/* * Class: org_eclipse_core_internal_filesystem_local_LocalFileNatives * Method: internalGetFileInfo * Signature: ([CLorg/eclipse/core/filesystem/IFileInfo;)Z @@ -402,8 +414,11 @@ JNIEXPORT jboolean JNICALL Java_org_eclipse_core_internal_filesystem_local_Local } handle = FindFirstFile(name, &info); free(name); - if (handle == INVALID_HANDLE_VALUE) + if (handle == INVALID_HANDLE_VALUE) { + if (GetLastError() != ERROR_FILE_NOT_FOUND) + setIOError(env, fileInfo); return JNI_FALSE; + } FindClose(handle); return convertFindDataToFileInfo(env, info, fileInfo); } @@ -433,6 +448,8 @@ JNIEXPORT jboolean JNICALL Java_org_eclipse_core_internal_filesystem_local_Local handle = FindFirstFileW(name, &info); if (handle == INVALID_HANDLE_VALUE) { free(name); + if (GetLastError() != ERROR_FILE_NOT_FOUND) + setIOError(env, fileInfo); return JNI_FALSE; } diff --git a/bundles/org.eclipse.core.filesystem/pom.xml b/bundles/org.eclipse.core.filesystem/pom.xml index bc7e06815..cfc85ea1a 100644 --- a/bundles/org.eclipse.core.filesystem/pom.xml +++ b/bundles/org.eclipse.core.filesystem/pom.xml @@ -21,6 +21,6 @@ </parent> <groupId>eclipse.platform.resources</groupId> <artifactId>org.eclipse.core.filesystem</artifactId> - <version>1.3.200-SNAPSHOT</version> + <version>1.4.0-SNAPSHOT</version> <packaging>eclipse-plugin</packaging> </project> diff --git a/bundles/org.eclipse.core.filesystem/src/org/eclipse/core/filesystem/IFileInfo.java b/bundles/org.eclipse.core.filesystem/src/org/eclipse/core/filesystem/IFileInfo.java index 913bd6476..33b1290a0 100644 --- a/bundles/org.eclipse.core.filesystem/src/org/eclipse/core/filesystem/IFileInfo.java +++ b/bundles/org.eclipse.core.filesystem/src/org/eclipse/core/filesystem/IFileInfo.java @@ -27,16 +27,34 @@ import org.eclipse.core.runtime.IProgressMonitor; * implementations should use the concrete class {@link org.eclipse.core.filesystem.provider.FileStore} */ public interface IFileInfo extends Comparable, Cloneable { + /** + * The constant indicating that file information was retrieved successfully. + * @since 1.4 + */ + public static final int NONE = 0; + /** + * The constant indicating that an I/O error was encountered while retrieving file information. + * @since 1.4 + */ + public static final int IO_ERROR = 5; // The value is chosen to match EIO Linux errno value. /** * Returns whether this file or directory exists. * * @return <code>true</code> if this file exists, and <code>false</code> - * otherwise. + * if the file does not exist or an I/O error was encountered. */ public abstract boolean exists(); /** + * Checks whether an I/O error was encountered while accessing this file or directory. + * + * @return {@link #IO_ERROR} if an I/O error was encountered, or {@link #NONE} otherwise. + * @since 1.4 + */ + public abstract int getError(); + + /** * Returns the value of the specified attribute for this file. The attribute * must be one of the <code>EFS#ATTRIBUTE_*</code> * constants. Returns <code>false</code> if this file does not exist, diff --git a/bundles/org.eclipse.core.filesystem/src/org/eclipse/core/filesystem/provider/FileInfo.java b/bundles/org.eclipse.core.filesystem/src/org/eclipse/core/filesystem/provider/FileInfo.java index 48e00e438..b27ac1a9b 100644 --- a/bundles/org.eclipse.core.filesystem/src/org/eclipse/core/filesystem/provider/FileInfo.java +++ b/bundles/org.eclipse.core.filesystem/src/org/eclipse/core/filesystem/provider/FileInfo.java @@ -34,6 +34,12 @@ public class FileInfo implements IFileInfo { private static final int ATTRIBUTE_EXISTS = 1 << 16; /** + * Internal attribute indicating that an I/O error was encountered while retrieving + * the file information. + */ + private static final int ATTRIBUTE_IO_ERROR = 1 << 17; + + /** * Bit field of file attributes. Initialized to specify a writable resource. */ private int attributes = EFS.ATTRIBUTE_OWNER_WRITE | EFS.ATTRIBUTE_OWNER_READ; @@ -113,6 +119,14 @@ public class FileInfo implements IFileInfo { return getAttribute(ATTRIBUTE_EXISTS); } + /** + * @since 1.4 + * @see IFileInfo#getError() + */ + public int getError() { + return getAttribute(ATTRIBUTE_IO_ERROR) ? IO_ERROR : NONE; + } + public boolean getAttribute(int attribute) { if (attribute == EFS.ATTRIBUTE_READ_ONLY && isAttributeSuported(EFS.ATTRIBUTE_OWNER_WRITE)) return (!isSet(EFS.ATTRIBUTE_OWNER_WRITE)) || isSet(EFS.ATTRIBUTE_IMMUTABLE); @@ -222,6 +236,20 @@ public class FileInfo implements IFileInfo { clear(ATTRIBUTE_EXISTS); } + /** + * Sets a flag indicating that an I/O error was encountered when accessing the file. + * + * @param value <code>true</code> if this file has an I/O error, and <code>false</code> + * otherwise. + * @since 1.4 + */ + public void setError(boolean value) { + if (value) + set(ATTRIBUTE_IO_ERROR); + else + clear(ATTRIBUTE_IO_ERROR); + } + /* (non-Javadoc) * @see org.eclipse.core.filesystem.IFileInfo#setLastModified(long) */ diff --git a/bundles/org.eclipse.core.filesystem/src/org/eclipse/core/internal/filesystem/local/unix/UnixFileNatives.java b/bundles/org.eclipse.core.filesystem/src/org/eclipse/core/internal/filesystem/local/unix/UnixFileNatives.java index e0d52bf89..d936852d9 100644 --- a/bundles/org.eclipse.core.filesystem/src/org/eclipse/core/internal/filesystem/local/unix/UnixFileNatives.java +++ b/bundles/org.eclipse.core.filesystem/src/org/eclipse/core/internal/filesystem/local/unix/UnixFileNatives.java @@ -25,6 +25,7 @@ public abstract class UnixFileNatives { private static final String LIBRARY_NAME = "unixfile_1_0_0"; //$NON-NLS-1$ private static final int UNICODE_SUPPORTED = 1 << 0; private static final int CHFLAGS_SUPPORTED = 1 << 1; + private static final int ENOENT = 2; // errno value for "No such file or directory" private static final boolean usingNatives; private static final int libattr; @@ -72,10 +73,13 @@ public abstract class UnixFileNatives { StructStat stat = new StructStat(); if (lstat(name, stat) == 0) { if ((stat.st_mode & UnixFileFlags.S_IFMT) == UnixFileFlags.S_IFLNK) { - if (stat(name, stat) == 0) + if (stat(name, stat) == 0) { info = stat.toFileInfo(); - else + } else { info = new FileInfo(); + if (getErrno() != ENOENT) + info.setError(true); + } info.setAttribute(EFS.ATTRIBUTE_SYMLINK, true); byte target[] = new byte[UnixFileFlags.PATH_MAX]; int length = readlink(name, target, target.length); @@ -83,8 +87,11 @@ public abstract class UnixFileNatives { info.setStringAttribute(EFS.ATTRIBUTE_LINK_TARGET, bytesToFileName(target, length)); } else info = stat.toFileInfo(); - } else + } else { info = new FileInfo(); + if (getErrno() != ENOENT) + info.setError(true); + } return info; } diff --git a/bundles/org.eclipse.core.resources/src/org/eclipse/core/internal/localstore/CopyVisitor.java b/bundles/org.eclipse.core.resources/src/org/eclipse/core/internal/localstore/CopyVisitor.java index f350e6f39..45e17d8d6 100644 --- a/bundles/org.eclipse.core.resources/src/org/eclipse/core/internal/localstore/CopyVisitor.java +++ b/bundles/org.eclipse.core.resources/src/org/eclipse/core/internal/localstore/CopyVisitor.java @@ -149,6 +149,8 @@ public class CopyVisitor implements IUnifiedTreeVisitor { /* virtual resources are always deemed as being synchronized */ if (node.getResource().isVirtual()) return true; + if (node.isErrorInFileSystem()) + return true; // Assume synchronized unless proven otherwise /* does the resource exist in workspace and file system? */ if (!node.existsInWorkspace() || !node.existsInFileSystem()) return false; diff --git a/bundles/org.eclipse.core.resources/src/org/eclipse/core/internal/localstore/RefreshLocalVisitor.java b/bundles/org.eclipse.core.resources/src/org/eclipse/core/internal/localstore/RefreshLocalVisitor.java index 3e522389b..20670fd07 100644 --- a/bundles/org.eclipse.core.resources/src/org/eclipse/core/internal/localstore/RefreshLocalVisitor.java +++ b/bundles/org.eclipse.core.resources/src/org/eclipse/core/internal/localstore/RefreshLocalVisitor.java @@ -262,6 +262,8 @@ public class RefreshLocalVisitor implements IUnifiedTreeVisitor, ILocalStoreCons public boolean visit(UnifiedTreeNode node) throws CoreException { Policy.checkCanceled(monitor); try { + if (node.isErrorInFileSystem()) + return false; // Don't visit children if we encountered an I/O error Resource target = (Resource) node.getResource(); int targetType = target.getType(); if (targetType == IResource.PROJECT) diff --git a/bundles/org.eclipse.core.resources/src/org/eclipse/core/internal/localstore/UnifiedTreeNode.java b/bundles/org.eclipse.core.resources/src/org/eclipse/core/internal/localstore/UnifiedTreeNode.java index 764748b30..be26202af 100644 --- a/bundles/org.eclipse.core.resources/src/org/eclipse/core/internal/localstore/UnifiedTreeNode.java +++ b/bundles/org.eclipse.core.resources/src/org/eclipse/core/internal/localstore/UnifiedTreeNode.java @@ -41,6 +41,14 @@ public class UnifiedTreeNode implements ILocalStoreConstants { return fileInfo != null && fileInfo.exists(); } + /** + * Returns <code>true</code> if an I/O error was encountered while accessing + * the file or the directory in the file system. + */ + public boolean isErrorInFileSystem() { + return fileInfo != null && fileInfo.getError() != IFileInfo.NONE; + } + public boolean existsInWorkspace() { return existsWorkspace; } @@ -89,7 +97,7 @@ public class UnifiedTreeNode implements ILocalStoreConstants { public boolean isFolder() { return fileInfo == null ? false : fileInfo.isDirectory(); } - + public boolean isSymbolicLink() { return fileInfo == null ? false : fileInfo.getAttribute(EFS.ATTRIBUTE_SYMLINK); } @@ -109,7 +117,7 @@ public class UnifiedTreeNode implements ILocalStoreConstants { this.fileInfo = info; this.existsWorkspace = existsInWorkspace; } - + /** * Releases elements that won't be needed any more for garbage collection. * Should be called before adding a node to the free list. @@ -133,6 +141,7 @@ public class UnifiedTreeNode implements ILocalStoreConstants { this.resource = resource; } + @Override public String toString() { String s = resource == null ? "null" : resource.getFullPath().toString(); //$NON-NLS-1$ return "Node: " + s; //$NON-NLS-1$ |
