From 081b58b6724af2cba622504e2d72efe465f1ba91 Mon Sep 17 00:00:00 2001 From: Enrico Forestieri Date: Sat, 2 May 2009 21:51:06 +0000 Subject: [PATCH] When performing a reverse DVI search and the tmpdir is a symlink, the DVI viewer passes back the resolved path, such that the search fails, as internally LyX uses the unresolved path. This patch fixes this bug by using the new method FileName::realPath which resolves a path by getting rid of any '.', '..', or symlink path components. git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/branches/BRANCH_1_6_X@29504 a592a061-630c-0410-9148-cb99ea01b6c8 --- configure.ac | 2 + development/cmake/src/support/CMakeLists.txt | 2 +- development/cmake/src/tex2lyx/CMakeLists.txt | 2 +- development/scons/SConstruct | 4 +- src/LyXFunc.cpp | 12 ++- src/Makefile.am | 2 +- src/client/Makefile.am | 2 +- src/support/FileName.cpp | 6 ++ src/support/FileName.h | 6 ++ src/support/os.h | 6 ++ src/support/os_cygwin.cpp | 9 ++ src/support/os_unix.cpp | 11 +++ src/support/os_win32.cpp | 96 ++++++++++++++++++++ src/support/os_win32.h | 2 + src/tex2lyx/Makefile.am | 2 +- status.16x | 3 + 16 files changed, 157 insertions(+), 10 deletions(-) diff --git a/configure.ac b/configure.ac index 83383c3e67..5e65428b11 100644 --- a/configure.ac +++ b/configure.ac @@ -112,6 +112,8 @@ LYX_ADD_INC_DIR(CPPFLAGS,$dir/include) ### These are needed in windows AC_CHECK_LIB(shlwapi, main, [LIBSHLWAPI=-lshlwapi]) AC_SUBST(LIBSHLWAPI) +AC_CHECK_LIB(psapi, main, [LIBPSAPI=-lpsapi]) +AC_SUBST(LIBPSAPI) AC_CHECK_LIB(gdi32, main) AC_ARG_WITH(aiksaurus, diff --git a/development/cmake/src/support/CMakeLists.txt b/development/cmake/src/support/CMakeLists.txt index 46ca63eecb..7f9e0f3011 100644 --- a/development/cmake/src/support/CMakeLists.txt +++ b/development/cmake/src/support/CMakeLists.txt @@ -69,7 +69,7 @@ target_link_libraries(support boost_signals ${QT_QTCORE_LIBRARY} ${ZLIB_LIBRARY} if(APPLE) target_link_libraries(support "objc" "-framework Appkit" "-framework CoreFoundation") elseif(WIN32) - target_link_libraries(support shlwapi) + target_link_libraries(support shlwapi psapi) endif() project_source_group("${GROUP_CODE}" support_sources support_headers) diff --git a/development/cmake/src/tex2lyx/CMakeLists.txt b/development/cmake/src/tex2lyx/CMakeLists.txt index 0022e3efc5..12c52baaa1 100644 --- a/development/cmake/src/tex2lyx/CMakeLists.txt +++ b/development/cmake/src/tex2lyx/CMakeLists.txt @@ -46,7 +46,7 @@ target_link_libraries(${_tex2lyx} ${ICONV_LIBRARY}) if(WIN32) - target_link_libraries(${_tex2lyx} shlwapi ole32) + target_link_libraries(${_tex2lyx} shlwapi ole32 psapi) endif() if(APPLE) diff --git a/development/scons/SConstruct b/development/scons/SConstruct index b2c6f4e98e..9757d99c39 100644 --- a/development/scons/SConstruct +++ b/development/scons/SConstruct @@ -1218,9 +1218,9 @@ if platform_name in ['win32', 'cygwin']: # the final link step needs stdc++ to succeed under mingw # FIXME: shouldn't g++ automatically link to stdc++? if use_vc: - system_libs += ['ole32', 'shlwapi', 'shell32', 'advapi32', 'zdll'] + system_libs += ['ole32', 'shlwapi', 'psapi', 'shell32', 'advapi32', 'zdll'] else: - system_libs += ['shlwapi', 'stdc++', 'z'] + system_libs += ['shlwapi', 'psapi', 'stdc++', 'z'] elif platform_name == 'cygwin' and env['X11']: system_libs += ['GL', 'Xmu', 'Xi', 'Xrender', 'Xrandr', 'Xcursor', 'Xft', 'freetype', 'fontconfig', 'Xext', 'X11', 'SM', 'ICE', diff --git a/src/LyXFunc.cpp b/src/LyXFunc.cpp index f068d5ae13..e7d973a729 100644 --- a/src/LyXFunc.cpp +++ b/src/LyXFunc.cpp @@ -1150,11 +1150,17 @@ void LyXFunc::dispatch(FuncRequest const & cmd) is >> file_name >> row; Buffer * buf = 0; bool loaded = false; - if (prefixIs(file_name, package().temp_dir().absFilename())) + string const abstmp = package().temp_dir().absFilename(); + string const realtmp = package().temp_dir().realPath(); + if (prefixIs(file_name, abstmp) || prefixIs(file_name, realtmp)) { // Needed by inverse dvi search. If it is a file - // in tmpdir, call the apropriated function + // in tmpdir, call the apropriated function. + // If tmpdir is a symlink, we may have the real + // path passed back, so we correct for that. + if (!prefixIs(file_name, abstmp)) + file_name = subst(file_name, realtmp, abstmp); buf = theBufferList().getBufferFromTmp(file_name); - else { + } else { // Must replace extension of the file to be .lyx // and get full path FileName const s = fileSearch(string(), changeExtension(file_name, ".lyx"), "lyx"); diff --git a/src/Makefile.am b/src/Makefile.am index bc1ed18cd6..1361a00c10 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -19,7 +19,7 @@ EXTRA_DIST = Section.h \ paper.h \ pch.h -OTHERLIBS = $(BOOST_LIBS) $(INTLLIBS) $(MYTHES_LIBS) $(AIKSAURUS_LIBS) @LIBS@ $(SOCKET_LIBS) +OTHERLIBS = $(BOOST_LIBS) $(INTLLIBS) $(MYTHES_LIBS) $(AIKSAURUS_LIBS) @LIBS@ $(SOCKET_LIBS) $(LIBPSAPI) noinst_LTLIBRARIES = liblyxcore.la bin_PROGRAMS = lyx diff --git a/src/client/Makefile.am b/src/client/Makefile.am index 83fcb33353..81fad39d1a 100644 --- a/src/client/Makefile.am +++ b/src/client/Makefile.am @@ -12,7 +12,7 @@ AM_CPPFLAGS += -I$(srcdir)/.. $(BOOST_INCLUDES) lyxclient_LDADD = \ $(top_builddir)/src/support/liblyxsupport.la \ - $(BOOST_LIBS) $(INTLLIBS) @LIBS@ $(SOCKET_LIBS) + $(BOOST_LIBS) $(INTLLIBS) @LIBS@ $(SOCKET_LIBS) $(LIBPSAPI) # everything below the line containing the single backslashs # an ugly hack and needed because of the diff --git a/src/support/FileName.cpp b/src/support/FileName.cpp index 1beeb29194..a4e066a797 100644 --- a/src/support/FileName.cpp +++ b/src/support/FileName.cpp @@ -194,6 +194,12 @@ string FileName::absFilename() const } +string FileName::realPath() const +{ + return os::real_path(toFilesystemEncoding()); +} + + void FileName::set(string const & name) { d->fi.setFile(toqstr(name)); diff --git a/src/support/FileName.h b/src/support/FileName.h index 26d0179d19..eb82df990a 100644 --- a/src/support/FileName.h +++ b/src/support/FileName.h @@ -64,6 +64,12 @@ public: /// get the absolute file name in UTF-8 encoding std::string absFilename() const; + + /** returns an absolute pathname (whose resolution does not involve + * '.', '..', or symbolic links) in UTF-8 encoding + */ + std::string realPath() const; + /** * Get the file name in the encoding used by the file system. * Only use this for accessing the file, e.g. with an fstream. diff --git a/src/support/os.h b/src/support/os.h index c4277ef4fe..f96fa64384 100644 --- a/src/support/os.h +++ b/src/support/os.h @@ -112,6 +112,12 @@ bool canAutoOpenFile(std::string const & ext, auto_open_mode const mode = VIEW); */ bool autoOpenFile(std::string const & filename, auto_open_mode const mode = VIEW); +/** Resolves a path such that it does not contain '.', '..', or symbolic links. + * \warning the path must already be in the filesystem encoding. + * \returns the resolved path in utf8 encoding. + */ +std::string real_path(std::string const & path); + } // namespace os } // namespace support } // namespace lyx diff --git a/src/support/os_cygwin.cpp b/src/support/os_cygwin.cpp index 0e741a70c4..31ab68be78 100644 --- a/src/support/os_cygwin.cpp +++ b/src/support/os_cygwin.cpp @@ -26,6 +26,7 @@ #include #include #include +#include #include @@ -281,6 +282,14 @@ bool autoOpenFile(string const & filename, auto_open_mode const mode) win_path.c_str(), NULL, NULL, 1)) > 32; } + +string real_path(string const & path) +{ + char rpath[PATH_MAX + 1]; + char * result = realpath(path.c_str(), rpath); + return FileName::fromFilesystemEncoding(result ? rpath : path).absFilename(); +} + } // namespace os } // namespace support } // namespace lyx diff --git a/src/support/os_unix.cpp b/src/support/os_unix.cpp index 2c3f3262fd..4bbd76fe1c 100644 --- a/src/support/os_unix.cpp +++ b/src/support/os_unix.cpp @@ -17,6 +17,9 @@ #include "support/FileName.h" #include "support/lstrings.h" +#include +#include + #ifdef __APPLE__ #include #endif @@ -215,6 +218,14 @@ bool autoOpenFile(string const & filename, auto_open_mode const mode) #endif } + +string real_path(string const & path) +{ + char rpath[PATH_MAX + 1]; + char * result = realpath(path.c_str(), rpath); + return FileName::fromFilesystemEncoding(result ? rpath : path).absFilename(); +} + } // namespace os } // namespace support } // namespace lyx diff --git a/src/support/os_win32.cpp b/src/support/os_win32.cpp index fd1b6ad397..2e7b826203 100644 --- a/src/support/os_win32.cpp +++ b/src/support/os_win32.cpp @@ -389,6 +389,102 @@ bool autoOpenFile(string const & filename, auto_open_mode const mode) to_local8bit(from_utf8(filename)).c_str(), NULL, NULL, 1)) > 32; } + +string real_path(string const & path) +{ + // See http://msdn.microsoft.com/en-us/library/aa366789(VS.85).aspx + HANDLE hpath = CreateFile(subst(path, '/', '\\').c_str(), GENERIC_READ, + FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); + + if (hpath == INVALID_HANDLE_VALUE) { + // The file cannot be accessed. + return FileName::fromFilesystemEncoding(path).absFilename(); + } + + // Get the file size. + DWORD size_hi = 0; + DWORD size_lo = GetFileSize(hpath, &size_hi); + + if (size_lo == 0 && size_hi == 0) { + // A zero-length file cannot be mapped. + CloseHandle(hpath); + return FileName::fromFilesystemEncoding(path).absFilename(); + } + + // Create a file mapping object. + HANDLE hmap = CreateFileMapping(hpath, NULL, PAGE_READONLY, 0, 1, NULL); + + if (!hmap) { + CloseHandle(hpath); + return FileName::fromFilesystemEncoding(path).absFilename(); + } + + // Create a file mapping to get the file name. + void * pmem = MapViewOfFile(hmap, FILE_MAP_READ, 0, 0, 1); + + if (!pmem) { + CloseHandle(hmap); + CloseHandle(hpath); + return FileName::fromFilesystemEncoding(path).absFilename(); + } + + TCHAR realpath[MAX_PATH + 1]; + + if (!GetMappedFileName(GetCurrentProcess(), pmem, realpath, MAX_PATH)) { + UnmapViewOfFile(pmem); + CloseHandle(hmap); + CloseHandle(hpath); + return FileName::fromFilesystemEncoding(path).absFilename(); + } + + // Translate device name to UNC prefix or drive letters. + TCHAR tmpbuf[MAX_PATH] = TEXT("\\Device\\Mup\\"); + UINT namelen = _tcslen(tmpbuf); + if (_tcsnicmp(realpath, tmpbuf, namelen) == 0) { + // UNC path + _snprintf(tmpbuf, MAX_PATH, "\\\\%s", realpath + namelen); + strncpy(realpath, tmpbuf, MAX_PATH); + realpath[MAX_PATH] = '\0'; + } else if (GetLogicalDriveStrings(MAX_PATH - 1, tmpbuf)) { + // Check whether device name corresponds to some local drive. + TCHAR name[MAX_PATH]; + TCHAR drive[3] = TEXT(" :"); + bool found = false; + TCHAR * p = tmpbuf; + do { + // Copy the drive letter to the template string + drive[0] = *p; + // Look up each device name + if (QueryDosDevice(drive, name, MAX_PATH)) { + namelen = _tcslen(name); + if (namelen < MAX_PATH) { + found = _tcsnicmp(realpath, name, namelen) == 0; + if (found) { + // Repl. device spec with drive + TCHAR tempfile[MAX_PATH]; + _snprintf(tempfile, + MAX_PATH, + "%s%s", + drive, + realpath + namelen); + strncpy(realpath, + tempfile, + MAX_PATH); + realpath[MAX_PATH] = '\0'; + } + } + } + // Advance p to the next NULL character. + while (*p++) ; + } while (!found && *p); + } + UnmapViewOfFile(pmem); + CloseHandle(hmap); + CloseHandle(hpath); + string const retpath = subst(string(realpath), '\\', '/'); + return FileName::fromFilesystemEncoding(retpath).absFilename(); +} + } // namespace os } // namespace support } // namespace lyx diff --git a/src/support/os_win32.h b/src/support/os_win32.h index bf748f629a..618c5315ef 100644 --- a/src/support/os_win32.h +++ b/src/support/os_win32.h @@ -43,6 +43,8 @@ #endif #include +#include +#include namespace lyx { diff --git a/src/tex2lyx/Makefile.am b/src/tex2lyx/Makefile.am index 22a3a65cd0..6fb555a11a 100644 --- a/src/tex2lyx/Makefile.am +++ b/src/tex2lyx/Makefile.am @@ -66,4 +66,4 @@ tex2lyx_SOURCES = \ tex2lyx_LDADD = \ $(top_builddir)/src/support/liblyxsupport.la \ - $(LIBICONV) $(BOOST_LIBS) @LIBS@ + $(LIBICONV) $(BOOST_LIBS) @LIBS@ $(LIBPSAPI) diff --git a/status.16x b/status.16x index fcfaf1f8ca..027f8eca29 100644 --- a/status.16x +++ b/status.16x @@ -294,6 +294,9 @@ What's new Frontmatter of the layout combo box. - Hide the "Navigate->Go to Label" menuitem when disabled (bug 4124). + +- Fix bug causing reverse DVI search to fail when the temporary directory + is a symbolic link. * DOCUMENTATION AND LOCALIZATION