]> git.unchartedbackwaters.co.uk Git - francis/winuae.git/commitdiff
Fix softlinks not resolving if it was not already cached by filesystem emulation.
authorToni Wilen <twilen@winuae.net>
Fri, 16 Sep 2022 17:49:00 +0000 (20:49 +0300)
committerToni Wilen <twilen@winuae.net>
Fri, 16 Sep 2022 17:49:00 +0000 (20:49 +0300)
filesys.cpp
include/fsdb.h
od-win32/fsdb_mywin32.cpp
od-win32/fsdb_win32.cpp

index 1e7e6e9f948d472dddd97378767a32fda749e0ca..b9c2201b967b41402624d875ca997760aa753a43 100644 (file)
@@ -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);
index 16b7435e82c2fc77adae937cf42f4c6c1c4e2796..5fe8f7296e3b67277fc520385e39426ae77ac5a9 100644 (file)
@@ -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 *);
index ea4612870b8e90c3feb9d6dce9fa19aad86f6466..9d2eb2ddc5187ef1ed03228081a9a0ca5b411b41 100644 (file)
@@ -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) {
index e112128bfb703e7e09c7989f48cedc9caa3405a7..94f22e3d2e289971161a822fa27cfcd14772bb79 100644 (file)
@@ -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;