From ffac943c03af2b065704974d16bcc984657bf9e9 Mon Sep 17 00:00:00 2001 From: Toni Wilen Date: Fri, 16 Sep 2022 20:49:00 +0300 Subject: [PATCH] Fix softlinks not resolving if it was not already cached by filesystem emulation. --- filesys.cpp | 75 ++++++++++++++++++++++++++------------- include/fsdb.h | 2 +- od-win32/fsdb_mywin32.cpp | 58 +++++++++++++++--------------- od-win32/fsdb_win32.cpp | 29 ++++++++++++++- 4 files changed, 109 insertions(+), 55 deletions(-) diff --git a/filesys.cpp b/filesys.cpp index 1e7e6e9f..b9c2201b 100644 --- a/filesys.cpp +++ b/filesys.cpp @@ -2446,6 +2446,14 @@ static void de_recycle_aino (Unit *unit, a_inode *aino) unit->aino_cache_size--; } +static void free_aino(a_inode *aino) +{ + xfree(aino->aname); + xfree(aino->comment); + xfree(aino->nname); + xfree(aino); +} + static void dispose_aino (Unit *unit, a_inode **aip, a_inode *aino) { int hash = aino->uniq % MAX_AINO_HASH; @@ -2463,10 +2471,7 @@ static void dispose_aino (Unit *unit, a_inode **aip, a_inode *aino) isofs_dispose_inode (unit->ui.cdfs_superblock, aino->uniq_external); } - xfree (aino->aname); - xfree (aino->comment); - xfree (aino->nname); - xfree (aino); + free_aino(aino); } static void free_all_ainos (Unit *u, a_inode *parent) @@ -2761,13 +2766,25 @@ static TCHAR *get_nname (Unit *unit, a_inode *base, TCHAR *rel, TCHAR **modified /* See if we have a file that has the same name as the aname we are * looking for. */ - found = fsdb_search_dir (base->nname, rel); - if (found == 0) + TCHAR *relalt = NULL; + found = fsdb_search_dir (base->nname, rel, &relalt); + if (found == 0) { return found; - if (found == rel) - return build_nname (base->nname, rel); - + } + if (found == rel) { + if (relalt) { + TCHAR *v = build_nname(base->nname, relalt); + xfree(relalt); + return v; + } + return build_nname(base->nname, rel); + } *modified_rel = found; + if (relalt) { + TCHAR *v = build_nname(base->nname, relalt); + xfree(relalt); + return v; + } return build_nname (base->nname, found); } @@ -2900,7 +2917,7 @@ static void init_child_aino (Unit *unit, a_inode *base, a_inode *aino) aino_test (aino); } -static a_inode *new_child_aino (Unit *unit, a_inode *base, TCHAR *rel) +static a_inode *new_child_aino(Unit *unit, a_inode *base, TCHAR *rel) { TCHAR *modified_rel; TCHAR *nn; @@ -2909,34 +2926,42 @@ static a_inode *new_child_aino (Unit *unit, a_inode *base, TCHAR *rel) TRACE((_T("new_child_aino %s, %s\n"), base->aname, rel)); - if (!isvirtual) - aino = fsdb_lookup_aino_aname (base, rel); - if (aino == 0) { + if (!isvirtual) { + aino = fsdb_lookup_aino_aname(base, rel); + } + + if (aino == NULL) { uae_u64 uniq_ext = 0; - nn = get_nname (unit, base, rel, &modified_rel, &uniq_ext); - if (nn == 0) + nn = get_nname(unit, base, rel, &modified_rel, &uniq_ext); + if (nn == NULL) { + xfree(modified_rel); return 0; + } - aino = xcalloc (a_inode, 1); - if (aino == 0) + aino = xcalloc(a_inode, 1); + if (aino == 0) { + xfree(modified_rel); return 0; + } + aino->uniq_external = uniq_ext; - aino->aname = modified_rel ? modified_rel : my_strdup (rel); + aino->aname = modified_rel ? modified_rel : my_strdup(rel); aino->nname = nn; aino->comment = 0; aino->has_dbentry = 0; - if (!fill_file_attrs (unit, base, aino)) { - xfree (aino); + if (!fill_file_attrs(unit, base, aino)) { + free_aino(aino); return 0; } - if (aino->dir && !isvirtual) - fsdb_clean_dir (aino); + if (aino->dir && !isvirtual) { + fsdb_clean_dir(aino); + } } - init_child_aino (unit, base, aino); + init_child_aino(unit, base, aino); - recycle_aino (unit, aino); + recycle_aino(unit, aino); TRACE((_T("created aino %x, lookup, amigaos_mode %d\n"), aino->uniq, aino->amigaos_mode)); return aino; } @@ -2949,7 +2974,7 @@ static a_inode *create_child_aino (Unit *unit, a_inode *base, TCHAR *rel, int is aino->nname = create_nname (unit, base, rel); if (!aino->nname) { - free (aino); + free_aino(aino); return 0; } aino->aname = my_strdup (rel); diff --git a/include/fsdb.h b/include/fsdb.h index 16b7435e..5fe8f729 100644 --- a/include/fsdb.h +++ b/include/fsdb.h @@ -126,7 +126,7 @@ extern TCHAR *build_aname (const TCHAR *d, const TCHAR *n); /* Filesystem-independent functions. */ extern void fsdb_clean_dir (a_inode *); -extern TCHAR *fsdb_search_dir (const TCHAR *dirname, TCHAR *rel); +extern TCHAR *fsdb_search_dir (const TCHAR *dirname, TCHAR *rel, TCHAR **relalt); extern void fsdb_dir_writeback (a_inode *); extern int fsdb_used_as_nname (a_inode *base, const TCHAR *); extern a_inode *fsdb_lookup_aino_aname (a_inode *base, const TCHAR *); diff --git a/od-win32/fsdb_mywin32.cpp b/od-win32/fsdb_mywin32.cpp index ea461287..9d2eb2dd 100644 --- a/od-win32/fsdb_mywin32.cpp +++ b/od-win32/fsdb_mywin32.cpp @@ -882,7 +882,7 @@ static int my_resolvessymboliclink2(TCHAR *linkfile, int size) if (h == INVALID_HANDLE_VALUE) return -1; FindClose(h); - if (fd.dwReserved0 != IO_REPARSE_TAG_SYMLINK || !(fd.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)) + if (!(fd.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) || fd.dwReserved0 != IO_REPARSE_TAG_SYMLINK) return -1; h = CreateFile (linkfile, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_ATTRIBUTE_REPARSE_POINT | FILE_FLAG_OPEN_REPARSE_POINT , NULL); @@ -991,41 +991,43 @@ bool my_resolveshortcut(TCHAR *linkfile, int size) // http://msdn.microsoft.com/en-us/library/aa969393.aspx bool my_createshortcut(const TCHAR *source, const TCHAR *target, const TCHAR *description) { - HRESULT hres; - IShellLink* psl; - TCHAR tmp[MAX_DPATH]; + HRESULT hres; + IShellLink *psl; - // Get a pointer to the IShellLink interface. It is assumed that CoInitialize - // has already been called. - hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (LPVOID*)&psl); - if (SUCCEEDED(hres)) - { - IPersistFile* ppf; + // Get a pointer to the IShellLink interface. It is assumed that CoInitialize + // has already been called. + hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (LPVOID*)&psl); + if (SUCCEEDED(hres)) + { + IPersistFile *ppf; - // Set the path to the shortcut target and add the description. - psl->SetPath(target); - psl->SetDescription(description); + // Set the path to the shortcut target and add the description. + TCHAR target2[MAX_DPATH]; + my_canonicalize_path(target, target2, sizeof(target2) / sizeof(TCHAR)); + psl->SetPath(target2); + psl->SetDescription(description); - // Query IShellLink for the IPersistFile interface, used for saving the - // shortcut in persistent storage. - hres = psl->QueryInterface(IID_IPersistFile, (LPVOID*)&ppf); + // Query IShellLink for the IPersistFile interface, used for saving the + // shortcut in persistent storage. + hres = psl->QueryInterface(IID_IPersistFile, (LPVOID*)&ppf); - if (SUCCEEDED(hres)) - { - // Save the link by calling IPersistFile::Save. - _tcscpy (tmp, source); + if (SUCCEEDED(hres)) + { + // Save the link by calling IPersistFile::Save. + TCHAR tmp[MAX_DPATH]; + my_canonicalize_path(source, tmp, sizeof(tmp) / sizeof(TCHAR)); const TCHAR *ext = _tcsrchr (tmp, '.'); - if (!ext || _tcsicmp (ext, _T(".lnk")) != 0) - _tcscat (tmp, _T(".lnk")); - hres = ppf->Save(tmp, TRUE); - ppf->Release(); - } - psl->Release(); - } + if (!ext || _tcsicmp(ext, _T(".lnk")) != 0) { + _tcscat(tmp, _T(".lnk")); + } + hres = ppf->Save(tmp, TRUE); + ppf->Release(); + } + psl->Release(); + } return SUCCEEDED(hres); } - bool my_resolvesoftlink(TCHAR *linkfile, int size, bool linkonly) { if (!linkonly) { diff --git a/od-win32/fsdb_win32.cpp b/od-win32/fsdb_win32.cpp index e112128b..94f22e3d 100644 --- a/od-win32/fsdb_win32.cpp +++ b/od-win32/fsdb_win32.cpp @@ -635,7 +635,7 @@ TCHAR *fsdb_create_unique_nname (a_inode *base, const TCHAR *suggestion) } } -TCHAR *fsdb_search_dir (const TCHAR *dirname, TCHAR *rel) +TCHAR *fsdb_search_dir(const TCHAR *dirname, TCHAR *rel, TCHAR **relalt) { WIN32_FIND_DATA fd; HANDLE h; @@ -643,6 +643,7 @@ TCHAR *fsdb_search_dir (const TCHAR *dirname, TCHAR *rel) const TCHAR *namep; TCHAR path[MAX_DPATH]; + *relalt = NULL; tmp = build_nname (dirname, rel); if (!tmp) return NULL; @@ -660,6 +661,32 @@ TCHAR *fsdb_search_dir (const TCHAR *dirname, TCHAR *rel) else p = my_strdup (fd.cFileName); FindClose (h); + } else { + // check if it is *.lnk shortcut + TCHAR tmp[MAX_DPATH]; + _tcscpy(tmp, namep); + _tcscat(tmp, _T(".lnk")); + DWORD flags = GetFileAttributesSafe(tmp); + if (flags != INVALID_FILE_ATTRIBUTES && !(flags & FILE_ATTRIBUTE_SYSTEM) && !(flags & FILE_ATTRIBUTE_DIRECTORY)) { + h = FindFirstFile(tmp, &fd); + if (h != INVALID_HANDLE_VALUE) { + TCHAR tmp2[MAX_DPATH]; + _tcscpy(tmp2, tmp); + if (my_resolvesoftlink(tmp2, sizeof tmp2 / sizeof(TCHAR), false)) { + if (_tcslen(fd.cFileName) > 4 && !_tcsicmp(fd.cFileName + _tcslen(fd.cFileName) - 4, _T(".lnk"))) { + fd.cFileName[_tcslen(fd.cFileName) - 4] = 0; + } + if (_tcscmp(fd.cFileName, rel) == 0) + p = rel; + else + p = my_strdup(fd.cFileName); + _tcscpy(tmp2, p); + _tcscat(tmp2, _T(".lnk")); + *relalt = my_strdup(tmp2); + } + FindClose(h); + } + } } xfree (tmp); return p; -- 2.47.3