summaryrefslogtreecommitdiff
path: root/unoidl
diff options
context:
space:
mode:
authorStephan Bergmann <sbergman@redhat.com>2013-09-19 12:37:46 +0200
committerStephan Bergmann <sbergman@redhat.com>2013-09-19 12:37:46 +0200
commit63f1fc40fbed426e702de3d22c4bc487c2fe446c (patch)
tree0d7fa8e5ad34103f6e89800bf6ecef4a13bdc676 /unoidl
parentb9e333bc03a4dd6fb0ebef54c69b15d32feeda5d (diff)
Prevent conflicts on case-preserving file systems
Change-Id: Ia40f0ce43086fd73cba60011001640a945fb3e26
Diffstat (limited to 'unoidl')
-rwxr-xr-xunoidl/source/sourcetreeprovider.cxx73
1 files changed, 67 insertions, 6 deletions
diff --git a/unoidl/source/sourcetreeprovider.cxx b/unoidl/source/sourcetreeprovider.cxx
index dd87ea32b7bf..f9ae3e9b7a0d 100755
--- a/unoidl/source/sourcetreeprovider.cxx
+++ b/unoidl/source/sourcetreeprovider.cxx
@@ -25,10 +25,74 @@
#include "sourceprovider-scanner.hxx"
#include "sourcetreeprovider.hxx"
+#if defined MACOSX
+#include <dirent.h>
+#include "osl/thread.h"
+#endif
+
namespace unoidl { namespace detail {
namespace {
+//TODO: Bad hack to work around osl::FileStatus::getFileName not determining the
+// original spelling of a file name (not even with
+// osl_FileStatus_Mask_Validate):
+OUString getFileName(OUString const & uri, osl::FileStatus & status) {
+#if defined MACOSX
+ sal_Int32 i = uri.lastIndexOf('/') + 1;
+ OUString path;
+ if (osl::FileBase::getSystemPathFromFileURL(uri.copy(0, i), path)
+ != osl::FileBase::E_None)
+ {
+ SAL_WARN(
+ "unoidl",
+ "cannot getSystemPathFromFileURL(" << uri.copy(0, i) << ")");
+ return status.getFileName();
+ }
+ OString dir(OUStringToOString(path, osl_getThreadTextEncoding()));
+ OString name(OUStringToOString(uri.copy(i), osl_getThreadTextEncoding()));
+ DIR * d = opendir(dir.getStr());
+ if (d == 0) {
+ SAL_WARN("unoidl", "cannot opendir(" << dir << ")");
+ return status.getFileName();
+ }
+ for (;;) {
+ dirent ent;
+ dirent * p;
+ int e = readdir_r(d, &ent, &p);
+ if (e != 0) {
+ SAL_WARN("unoidl", "cannot readdir_r");
+ closedir(d);
+ return status.getFileName();
+ }
+ if (p == 0) {
+ SAL_WARN(
+ "unoidl", "cannot find " << name << " via readdir of " << dir);
+ closedir(d);
+ return status.getFileName();
+ }
+ if (name.equalsIgnoreAsciiCase(p->d_name)) {
+ closedir(d);
+ return OUString(
+ p->d_name, std::strlen(p->d_name),
+ osl_getThreadTextEncoding());
+ }
+ }
+#else
+ return status.getFileName();
+#endif
+}
+
+bool exists(OUString const & uri, bool directory) {
+ osl::DirectoryItem item;
+ osl::FileStatus status(
+ osl_FileStatus_Mask_Type | osl_FileStatus_Mask_FileName);
+ return osl::DirectoryItem::get(uri, item) == osl::FileBase::E_None
+ && item.getFileStatus(status) == osl::FileBase::E_None
+ && (status.getFileType() == osl::FileStatus::Directory) == directory
+ && getFileName(uri, status) == uri.copy(uri.lastIndexOf('/') + 1);
+}
+
class Cursor: public MapCursor {
public:
Cursor() {}
@@ -119,12 +183,9 @@ rtl::Reference<Entity> SourceTreeProvider::findEntity(OUString const & name)
}
OUString uri(uri_ + buf.makeStringAndClear());
rtl::Reference<Entity> ent;
- osl::DirectoryItem item;
- osl::FileStatus status(osl_FileStatus_Mask_Type);
- if (osl::DirectoryItem::get(uri, item) == osl::FileBase::E_None
- && item.getFileStatus(status) == osl::FileBase::E_None
- && status.getFileType() == osl::FileStatus::Directory)
- {
+ // Prevent conflicts between foo/ and Foo.idl on case-preserving file
+ // systems:
+ if (exists(uri, true) && !exists(uri + ".idl", false)) {
ent = new SourceModuleEntity;
} else {
uri += ".idl";