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/trunk@29476 a592a061-630c-0410-9148-cb99ea01b6c8
This commit is contained in:
Enrico Forestieri 2009-05-01 15:18:11 +00:00
parent f2197de98a
commit b0936fac4c
15 changed files with 160 additions and 11 deletions

View File

@ -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(mythes,

View File

@ -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)

View File

@ -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)

View File

@ -1212,9 +1212,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',

View File

@ -1079,11 +1079,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, realtmp))
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");

View File

@ -21,7 +21,7 @@ EXTRA_DIST = Section.h \
pch.h
OTHERLIBS = $(BOOST_LIBS) $(INTLLIBS) $(MYTHES_LIBS) $(AIKSAURUS_LIBS) \
@LIBS@ $(SOCKET_LIBS) $(LIBSHLWAPI)
@LIBS@ $(SOCKET_LIBS) $(LIBSHLWAPI) $(LIBPSAPI)
noinst_LIBRARIES = liblyxcore.a
bin_PROGRAMS = lyx

View File

@ -13,7 +13,7 @@ AM_CPPFLAGS += -I$(srcdir)/.. $(BOOST_INCLUDES)
lyxclient_LDADD = \
$(top_builddir)/src/support/liblyxsupport.a \
$(BOOST_LIBS) $(INTLLIBS) @LIBS@ $(SOCKET_LIBS) \
$(QT4_LIB) $(QT4_LDFLAGS) $(LIBSHLWAPI)
$(QT4_LIB) $(QT4_LDFLAGS) $(LIBSHLWAPI) $(LIBPSAPI)
# everything below the line containing the single backslashs
# an ugly hack and needed because of the

View File

@ -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));
@ -923,6 +929,10 @@ docstring const FileName::relPath(string const & path) const
bool operator==(FileName const & lhs, FileName const & rhs)
{
// Avoid unnecessary checks below
if (lhs.empty() || rhs.empty())
return lhs.empty() && rhs.empty();
// Firstly, compare the filenames.
if (QString::compare(toqstr(lhs.absFilename()),
toqstr(rhs.absFilename()),

View File

@ -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.

View File

@ -112,9 +112,17 @@ bool canAutoOpenFile(std::string const & ext, auto_open_mode const mode = VIEW);
*/
bool autoOpenFile(std::string const & filename, auto_open_mode const mode = VIEW);
/// Check whether two filenames point to the same file.
/** Check whether two filenames point to the same file.
* \warning the filenames must already be in the filesystem encoding.
*/
bool isSameFile(std::string const & fileone, std::string const & filetwo);
/** 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

View File

@ -27,6 +27,7 @@
#include <shellapi.h>
#include <shlwapi.h>
#include <limits.h>
#include <stdlib.h>
#include <sys/cygwin.h>
#include <sys/stat.h>
@ -297,6 +298,14 @@ bool isSameFile(string const & fileone, string const & filetwo)
return false;
}
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

View File

@ -17,6 +17,8 @@
#include "support/FileName.h"
#include "support/lstrings.h"
#include <limits.h>
#include <stdlib.h>
#include <sys/stat.h>
#ifdef __APPLE__
@ -232,6 +234,14 @@ bool isSameFile(string const & fileone, string const & filetwo)
return false;
}
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

View File

@ -426,6 +426,102 @@ bool isSameFile(string const & fileone, string const & filetwo)
return samefile;
}
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

View File

@ -43,6 +43,8 @@
#endif
#include <windows.h>
#include <tchar.h>
#include <psapi.h>
namespace lyx {

View File

@ -72,4 +72,4 @@ tex2lyx_LDADD = \
$(top_builddir)/src/support/liblyxsupport.a \
$(LIBICONV) $(BOOST_LIBS) \
$(QT4_LIB) $(QT4_LDFLAGS) \
@LIBS@ $(LIBSHLWAPI)
@LIBS@ $(LIBSHLWAPI) $(LIBPSAPI)