bool emptydrive = false;
bool iscd;
struct uaedev_config_info c;
- TCHAR newrootdir[MAX_DPATH];
memcpy (&c, ci, sizeof (struct uaedev_config_info));
}
}
- my_resolveshortcut (c.rootdir, MAX_DPATH);
+ my_resolvesoftlink (c.rootdir, MAX_DPATH);
iscd = nr >= cd_unit_offset && nr < cd_unit_offset + cd_unit_number;
for (i = 0; i < MAX_FILESYSTEM_UNITS; i++) {
#define DOS_TRUE ((uae_u32)-1L)
#define DOS_FALSE (0L)
+/* DirEntryTypes */
+#define ST_PIPEFILE -5
+#define ST_LINKFILE -4
+#define ST_FILE -3
+#define ST_ROOT 1
+#define ST_USERDIR 2
+#define ST_SOFTLINK 3
+#define ST_LINKDIR 4
+
#define MAXFILESIZE32 (0x7fffffff)
/* Passed as type to Lock() */
au_fs_copy (unit->tmpbuf3, sizeof (unit->tmpbuf3) / sizeof (TCHAR), buf);
return unit->tmpbuf3;
}
+static TCHAR *cstr (Unit *unit, uaecptr addr)
+{
+ int i;
+ uae_char buf[257];
+
+ for (i = 0;;i++,addr++) {
+ buf[i] = get_byte (addr);
+ if (!buf[i])
+ break;
+ }
+ au_fs_copy (unit->tmpbuf3, sizeof (unit->tmpbuf3) / sizeof (TCHAR), buf);
+ return unit->tmpbuf3;
+}
static TCHAR *bstr_cut (Unit *unit, uaecptr addr)
{
{
TCHAR *tmp;
TCHAR *p;
- a_inode *curr;
+ a_inode *curr, *prev;
int i;
aino_test (base);
tmp = my_strdup (rel);
p = tmp;
curr = base;
+ prev = NULL;
while (*p) {
/* start with a slash? go up a level. */
} else {
a_inode *next;
+
+ if (prev && prev->softlink) {
+ *err = ERROR_IS_SOFT_LINK;
+ curr = NULL;
+ break;
+ }
+
TCHAR *component_end;
component_end = _tcschr (p, '/');
if (component_end != 0)
if (next == 0) {
/* if only last component not found, return parent dir. */
if (*err != ERROR_OBJECT_NOT_AROUND || component_end != 0)
- curr = 0;
+ curr = NULL;
/* ? what error is appropriate? */
break;
}
+ prev = next;
curr = next;
if (component_end)
p = component_end+1;
else
break;
-
}
}
xfree (tmp);
DUMPLOCK(unit, lock);
a = find_aino (unit, lock, bstr (unit, name), &err);
+ if (err == 0 && a->softlink)
+ err = ERROR_IS_SOFT_LINK;
if (err == 0 && (a->elock || (mode != SHARED_LOCK && a->shlock > 0))) {
err = ERROR_OBJECT_IN_USE;
}
de_recycle_aino (unit, a);
PUT_PCK_RES1 (packet, make_lock (unit, a->uniq, mode) >> 2);
}
+static void action_read_link_add_parent (Unit *u, a_inode *a, TCHAR *path)
+{
+ if (a == NULL)
+ return;
+ action_read_link_add_parent(u, a->parent, path);
+ if (a == &u->rootnode) {
+ _tcscat (path, a->aname);
+ _tcscat (path, _T(":"));
+ } else {
+ if (path[0] && path[_tcslen (path) - 1] != ':')
+ _tcscat (path, _T("/"));
+ _tcscat (path, a->aname);
+ }
+}
+
+#if 0
+#define LINK_HARD 0
+#define LINK_SOFT 1
+
+static void action_make_link (Unit *unit, dpacket packet)
+{
+ uaecptr lock = GET_PCK_ARG1 (packet) << 2;
+ uaecptr name = GET_PCK_ARG2 (packet) << 2;
+ uaecptr linkname = GET_PCK_ARG3 (packet);
+ int type = GET_PCK_ARG4 (packet);
+ a_inode *a1, *a2;
+ int err;
+
+ if (type == LINK_HARD) {
+ PUT_PCK_RES1 (packet, DOS_FALSE);
+ PUT_PCK_RES2 (packet, ERROR_NOT_IMPLEMENTED);
+ return;
+ }
+ a1 = find_aino (unit, lock, bstr (unit, name), &err);
+ if (err != 0) {
+ PUT_PCK_RES1 (packet, DOS_FALSE);
+ PUT_PCK_RES2 (packet, err);
+ return;
+ }
+ a2 = find_aino (unit, lock, cstr (unit, linkname), &err);
+ if (err != 0) {
+ PUT_PCK_RES1 (packet, DOS_FALSE);
+ PUT_PCK_RES2 (packet, err);
+ return;
+ }
+ if (!my_createsoftlink (a1->nname, a2->nname)) {
+ PUT_PCK_RES1 (packet, DOS_FALSE);
+ PUT_PCK_RES2 (packet, ERROR_OBJECT_NOT_AROUND);
+ return;
+ }
+}
+#endif
+
+static void action_read_link (Unit *unit, dpacket packet)
+{
+ uaecptr lock = GET_PCK_ARG1 (packet) << 2;
+ uaecptr name = GET_PCK_ARG2 (packet);
+ uaecptr newname = GET_PCK_ARG3 (packet);
+ int size = GET_PCK_ARG4 (packet);
+ a_inode *a;
+ Unit *u = NULL;
+ int err, i;
+ TCHAR tmp[MAX_DPATH];
+ TCHAR *namep, *extrapath;
+
+ extrapath = NULL;
+ namep = cstr (unit, name);
+ for (;;) {
+ a = find_aino (unit, lock, namep, &err);
+ if (err != ERROR_IS_SOFT_LINK)
+ break;
+ for (i = _tcslen (namep) - 1; i > 0; i--) {
+ if (namep[i] == '/') {
+ namep[i] = 0;
+ xfree (extrapath);
+ extrapath = my_strdup (namep + i + 1);
+ break;
+ }
+ }
+ }
+ if (err != 0) {
+ PUT_PCK_RES1 (packet, DOS_FALSE);
+ PUT_PCK_RES2 (packet, err);
+ return;
+ }
+ _tcscpy (tmp, a->nname);
+ if (!my_resolvesoftlink (tmp, sizeof tmp / sizeof (TCHAR))) {
+ PUT_PCK_RES1 (packet, DOS_FALSE);
+ // not sure what to return
+ PUT_PCK_RES2 (packet, ERROR_OBJECT_NOT_AROUND);
+ return;
+ }
+ // TODO:
+ // now we have full absolute path, need to check if it can
+ // mapped to any Amiga side filesystem
+ // not that trivial..
+ a = NULL;
+ err = 0;
+ for (u = units; u; u = u->next) {
+ if (!(u->volflags & (MYVOLUMEINFO_ARCHIVE | MYVOLUMEINFO_CDFS))) {
+ TCHAR path[MAX_DPATH];
+ if (my_issamevolume (u->rootnode.nname, tmp, path)) {
+ a = find_aino (u, 0, path, &err);
+ if (a && !err)
+ break;
+ }
+ }
+ }
+ if (!a || err) {
+ PUT_PCK_RES1 (packet, DOS_FALSE);
+ PUT_PCK_RES2 (packet, ERROR_OBJECT_NOT_AROUND);
+ return;
+ }
+ tmp[0] = 0;
+ action_read_link_add_parent (u, a, tmp);
+ if (extrapath) {
+ _tcscat (tmp, _T("/"));
+ _tcscat (tmp, extrapath);
+ }
+ xfree (extrapath);
+ char *s = ua_fs (tmp, -1);
+ for (i = 0; s[i]; i++) {
+ if (i >= size - 1)
+ break;
+ put_byte (newname + i, s[i]);
+ }
+ xfree (s);
+ put_byte (newname + i, 0);
+}
static void action_free_lock (Unit *unit, dpacket packet)
{
/* Guru book says ST_ROOT = 1 (root directory, not currently used)
* but some programs really expect 2 from root dir..
*/
- entrytype = 2;
+ entrytype = ST_USERDIR;
xs = unit->ui.volname;
} else {
- entrytype = aino->dir ? 2 : -3;
+ entrytype = aino->softlink ? ST_SOFTLINK : (aino->dir ? ST_USERDIR : ST_FILE);
xs = aino->aname;
}
put_long (info + 4, entrytype);
my_stat (aino->nname, &statbuf);
if (aino->parent == 0) {
- entrytype = 2;
+ entrytype = ST_USERDIR;
xs = unit->ui.volname;
} else {
- entrytype = aino->dir ? 2 : -3;
+ entrytype = aino->softlink ? ST_SOFTLINK : (aino->dir ? ST_USERDIR : ST_FILE);
xs = aino->aname;
}
x = ua_fs (xs, -1);
return 1;
}
-static uae_u32 exall_helpder(TrapContext *context)
+static uae_u32 exall_helpder (TrapContext *context)
{
int i;
Unit *u;
PUT_PCK_RES2 (packet, err);
return;
}
+ if (aino->softlink) {
+ PUT_PCK_RES1 (packet, DOS_FALSE);
+ PUT_PCK_RES2 (packet, ERROR_IS_SOFT_LINK);
+ return;
+ }
if (err == 0) {
/* Object exists. */
if (aino->dir) {
aino = lookup_aino (unit, get_long (lock + 4));
if (aino == 0)
aino = &unit->rootnode;
+ if (aino->softlink) {
+ PUT_PCK_RES1 (packet, DOS_FALSE);
+ PUT_PCK_RES2 (packet, ERROR_IS_SOFT_LINK);
+ return;
+ }
+
mode = aino->amigaos_mode; /* Use same mode for opened filehandle as existing Lock() */
prepare_for_open (aino->nname);
case ACTION_EXAMINE_ALL_END: return action_examine_all_end (unit, pck);
case ACTION_LOCK_RECORD: return action_lock_record (unit, pck, msg); break;
case ACTION_FREE_RECORD: action_free_record (unit, pck); break;
-
+ case ACTION_READ_LINK: action_read_link (unit, pck); break;
+#if 0
+ case ACTION_MAKE_LINK: action_make_link (unit, pck); break;
+#endif
/* OS4+ packet types */
case ACTION_CHANGE_FILE_POSITION64: action_change_file_position64 (unit, pck); break;
case ACTION_GET_FILE_POSITION64: action_get_file_position64 (unit, pck); break;
case ACTION_GET_FILE_SIZE64: action_get_file_size64 (unit, pck); break;
/* unsupported packets */
- case ACTION_MAKE_LINK:
- case ACTION_READ_LINK:
case ACTION_FORMAT:
+ case ACTION_MAKE_LINK:
+ write_log (_T("FILESYS: UNSUPPORTED PACKET %x\n"), type);
return 0;
default:
write_log (_T("FILESYS: UNKNOWN PACKET %x\n"), type);
put_long (parmpacket + 56, 1); /* hiCyl */
} else {
uae_u8 buf[512] = { 0 };
- buf[36] = _tcslen (uip[unit_no].devname);
+ char *s = ua_fs (uip[unit_no].devname, -1);
+ buf[36] = strlen (s);
for (int i = 0; i < buf[36]; i++)
- buf[37 + i] = uip[unit_no].devname[i];
+ buf[37 + i] = s[i];
+ xfree (s);
put_long (parmpacket + 4, ROM_hardfile_resname);
put_long (parmpacket + 20, ci->blocksize >> 2); /* longwords per block */
put_long (parmpacket + 28, ci->surfaces); /* heads */
fpu_op_illg2 (opcode, 0, oldpc);
}
-static bool fault_if_no_fpu (uae_u16 opcode, uaecptr ea, uaecptr oldpc)
+static bool fault_if_no_fpu (uae_u16 opcode, uae_u32 extra, uaecptr ea, uaecptr oldpc)
{
if ((regs.pcr & 2) || currprefs.fpu_model <= 0) {
+// write_log (_T("no FPU: %04x %08x PC=%08x\n"), opcode, extra, oldpc);
fpu_op_illg2 (opcode, ea, oldpc);
return true;
}
return false;
}
-static bool fault_if_no_6888x (uae_u16 opcode, uaecptr oldpc)
+static bool fault_if_no_6888x (uae_u16 opcode, uae_u32 extra, uaecptr oldpc)
{
if (currprefs.cpu_model < 68040 && currprefs.fpu_model <= 0) {
+// write_log (_T("6888x no FPU: %04x %08x PC=%08x\n"), opcode, extra, oldpc);
m68k_setpc (oldpc);
op_illg (opcode);
return true;
static void fpu_noinst (uae_u16 opcode, uaecptr pc)
{
- write_log (_T("Unknown FPU instruction %04X %08X\n"), opcode, pc);
+// write_log (_T("Unknown FPU instruction %04X %08X\n"), opcode, pc);
m68k_setpc (pc);
op_illg (opcode);
}
static const int sz2[8] = { 4, 4, 12, 12, 2, 8, 2, 0 };
if (!(extra & 0x4000)) {
- if (fault_if_no_fpu (opcode, 0, oldpc))
+ if (fault_if_no_fpu (opcode, extra, 0, oldpc))
return -1;
*src = regs.fp[(extra >> 10) & 7];
return 1;
}
}
- if (fault_if_no_fpu (opcode, ad, oldpc))
+ if (fault_if_no_fpu (opcode, extra, ad, oldpc))
return -1;
switch (size)
write_log (_T("PUTFP: %f %04X %04X\n"), value, opcode, extra);
#endif
if (!(extra & 0x4000)) {
- if (fault_if_no_fpu (opcode, 0, oldpc))
+ if (fault_if_no_fpu (opcode, extra, 0, oldpc))
return 1;
regs.fp[(extra >> 10) & 7] = value;
return 1;
}
}
- if (fault_if_no_fpu (opcode, ad, oldpc))
+ if (fault_if_no_fpu (opcode, extra, ad, oldpc))
return 1;
switch (size)
if (!isinrom ())
write_log (_T("fdbcc_opp at %08lx\n"), m68k_getpc ());
#endif
- if (fault_if_no_6888x (opcode, pc - 4))
+ if (fault_if_no_6888x (opcode, extra, pc - 4))
return;
disp = (uae_s32) (uae_s16) x_next_iword ();
- if (fault_if_no_fpu (opcode, pc + disp, pc))
+ if (fault_if_no_fpu (opcode, extra, pc + disp, pc - 4))
return;
- regs.fpiar = m68k_getpc () - 4;
+ regs.fpiar = pc - 4;
cc = fpp_cond (extra & 0x3f);
if (cc == -1) {
fpu_op_illg (opcode, regs.fpiar);
{
uae_u32 ad;
int cc;
+ uaecptr pc = m68k_getpc () - 4;
#if DEBUG_FPP
if (!isinrom ())
write_log (_T("fscc_opp at %08lx\n"), m68k_getpc ());
#endif
- if (fault_if_no_fpu (opcode, 0, 4))
+ if (fault_if_no_fpu (opcode, extra, 0, pc))
return;
- regs.fpiar = m68k_getpc () - 4;
+ regs.fpiar = pc;
cc = fpp_cond (extra & 0x3f);
if (cc == -1) {
fpu_op_illg (opcode, regs.fpiar);
} else if ((opcode & 0x38) == 0) {
- if (fault_if_no_fpu (opcode, 0, 4))
+ if (fault_if_no_fpu (opcode, extra, 0, pc))
return;
m68k_dreg (regs, opcode & 7) = (m68k_dreg (regs, opcode & 7) & ~0xff) | (cc ? 0xff : 0x00);
} else {
void fpuop_trapcc (uae_u32 opcode, uaecptr oldpc, uae_u16 extra)
{
int cc;
- uaecptr pc = m68k_getpc ();
#if DEBUG_FPP
if (!isinrom ())
write_log (_T("ftrapcc_opp at %08lx\n"), m68k_getpc ());
#endif
- if (fault_if_no_fpu (opcode, 0, pc))
+ if (fault_if_no_fpu (opcode, extra, 0, oldpc))
return;
regs.fpiar = oldpc;
void fpuop_bcc (uae_u32 opcode, uaecptr oldpc, uae_u32 extra)
{
int cc;
- uaecptr pc = m68k_getpc ();
#if DEBUG_FPP
if (!isinrom ())
write_log (_T("fbcc_opp at %08lx\n"), m68k_getpc ());
#endif
- if (fault_if_no_fpu (opcode, 0, pc))
+ if (fault_if_no_fpu (opcode, extra, 0, oldpc - 2))
return;
- regs.fpiar = oldpc;
+ regs.fpiar = oldpc - 2;
cc = fpp_cond (opcode & 0x3f);
if (cc == -1) {
- fpu_op_illg (opcode, oldpc);
+ fpu_op_illg (opcode, oldpc - 2);
} else if (cc) {
if ((opcode & 0x40) == 0)
extra = (uae_s32) (uae_s16) extra;
write_log (_T("fsave_opp at %08lx\n"), m68k_getpc ());
#endif
- if (fault_if_no_6888x (opcode, pc))
+ if (fault_if_no_6888x (opcode, 0, pc))
return;
if (get_fp_ad (opcode, &ad) == 0) {
return;
}
- if (fault_if_no_fpu (opcode, ad, pc))
+ if (fault_if_no_fpu (opcode, 0, ad, pc))
return;
regs.fpiar = pc;
write_log (_T("frestore_opp at %08lx\n"), m68k_getpc ());
#endif
- if (fault_if_no_6888x (opcode, pc))
+ if (fault_if_no_6888x (opcode, 0, pc))
return;
if (get_fp_ad (opcode, &ad) == 0) {
return;
}
- if (fault_if_no_fpu (opcode, ad, pc))
+ if (fault_if_no_fpu (opcode, 0, ad, pc))
return;
regs.fpiar = pc;
if (!isinrom ())
write_log (_T("FPP %04lx %04x at %08lx\n"), opcode & 0xffff, extra, pc);
#endif
- if (fault_if_no_6888x (opcode, pc))
+ if (fault_if_no_6888x (opcode, extra, pc))
return;
switch ((extra >> 13) & 0x7)
case 4:
case 5:
if ((opcode & 0x38) == 0) {
- if (fault_if_no_fpu (opcode, 0, pc))
+ if (fault_if_no_fpu (opcode, extra, 0, pc))
return;
if (extra & 0x2000) {
if (extra & 0x1000)
regs.fpiar = m68k_dreg (regs, opcode & 7);
}
} else if ((opcode & 0x38) == 0x08) {
- if (fault_if_no_fpu (opcode, 0, pc))
+ if (fault_if_no_fpu (opcode, extra, 0, pc))
return;
if (extra & 0x2000) {
if (extra & 0x1000)
regs.fpiar = m68k_areg (regs, opcode & 7);
}
} else if ((opcode & 0x3f) == 0x3c) {
- if (fault_if_no_fpu (opcode, 0, pc))
+ if (fault_if_no_fpu (opcode, extra, 0, pc))
return;
if ((extra & 0x2000) == 0) {
if (extra & 0x1000) {
fpu_noinst (opcode, pc);
return;
}
- if (fault_if_no_fpu (opcode, ad, pc))
+ if (fault_if_no_fpu (opcode, extra, ad, pc))
return;
if ((opcode & 0x38) == 0x20) {
fpu_noinst (opcode, pc);
return;
}
- if (fault_if_no_fpu (opcode, ad, pc))
+ if (fault_if_no_fpu (opcode, extra, ad, pc))
return;
if((opcode & 0x38) == 0x20) {
fpu_noinst (opcode, pc);
return;
}
- if (fault_if_no_fpu (opcode, ad, pc))
+ if (fault_if_no_fpu (opcode, extra, ad, pc))
return;
switch ((extra >> 11) & 3)
fpu_noinst (opcode, pc);
return;
}
- if (fault_if_no_fpu (opcode, ad, pc))
+ if (fault_if_no_fpu (opcode, extra, ad, pc))
return;
switch ((extra >> 11) & 3)
{
regs.fpiar = pc;
reg = (extra >> 7) & 7;
if ((extra & 0xfc00) == 0x5c00) {
- if (fault_if_no_fpu (opcode, 0, pc))
+ if (fault_if_no_fpu (opcode, extra, 0, pc))
return;
switch (extra & 0x7f)
{
printf ("\tuae_u16 newv_lo = - (src & 0xF) - (GET_XFLG () ? 1 : 0);\n");
printf ("\tuae_u16 newv_hi = - (src & 0xF0);\n");
printf ("\tuae_u16 newv;\n");
- printf ("\tint cflg;\n");
+ printf ("\tint cflg, tmp_newv;\n");
printf ("\tif (newv_lo > 9) { newv_lo -= 6; }\n");
- printf ("\tnewv = newv_hi + newv_lo;");
+ printf ("\ttmp_newv = newv = newv_hi + newv_lo;\n");
printf ("\tcflg = (newv & 0x1F0) > 0x90;\n");
printf ("\tif (cflg) newv -= 0x60;\n");
printf ("\tSET_CFLG (cflg);\n");
}
else {
genflags (flag_zn, curi->size, "newv", "", "");
+ printf ("\tSET_VFLG ((tmp_newv & 0x80) != 0 && (newv & 0x80) == 0);\n");
}
genastore ("newv", curi->smode, "srcreg", curi->size, "src");
break;
#define ERROR_NOT_A_DOS_DISK 225
#define ERROR_NO_DISK 226
#define ERROR_NO_MORE_ENTRIES 232
+#define ERROR_IS_SOFT_LINK 233
#define ERROR_NOT_IMPLEMENTED 236
#define ERROR_RECORD_NOT_LOCKED 240
#define ERROR_LOCK_COLLISION 241
int shlock;
long db_offset;
unsigned int dir:1;
+ unsigned int softlink:1;
unsigned int elock:1;
/* Nonzero if this came from an entry in our database. */
unsigned int has_dbentry:1;
extern bool my_utime (const TCHAR *name, struct mytimeval *tv);
extern bool my_chmod (const TCHAR *name, uae_u32 mode);
extern bool my_resolveshortcut(TCHAR *linkfile, int size);
+extern bool my_resolvessymboliclink(TCHAR *linkfile, int size);
+extern bool my_resolvesoftlink(TCHAR *linkfile, int size);
+extern bool my_issamevolume(const TCHAR *path1, const TCHAR *path2, TCHAR *path);
+extern bool my_createsoftlink(const TCHAR *path, const TCHAR *target);
extern char *custom_fsdb_search_dir (const char *dirname, TCHAR *rel);
extern a_inode *custom_fsdb_lookup_aino_aname (a_inode *base, const TCHAR *aname);
#define MOVEC_DEBUG 0
#define MMUOP_DEBUG 2
#define DEBUG_CD32CDTVIO 0
-#define EXCEPTION3_DEBUG 0
+#define EXCEPTION3_DEBUG 1
#define CPUTRACE_DEBUG 0
#include "sysconfig.h"
set_special (SPCFLAG_INT);
}
- if ((regs.spcflags & (SPCFLAG_BRK | SPCFLAG_MODE_CHANGE))) {
- unset_special (SPCFLAG_BRK | SPCFLAG_MODE_CHANGE);
+ if ((regs.spcflags & (SPCFLAG_BRK | SPCFLAG_MODE_CHANGE)))
return 1;
- }
return 0;
}
gui_led (LED_CPU, 0);
}
while (regs.halted) {
- do_cycles (8 * CYCLE_UNIT);
+ x_do_cycles (8 * CYCLE_UNIT);
cpu_cycles = adjust_cycles (cpu_cycles);
if (regs.spcflags) {
if (do_specialties (cpu_cycles))
}
#endif
run_func ();
+ unset_special (SPCFLAG_BRK | SPCFLAG_MODE_CHANGE);
}
protect_roms (false);
in_m68k_go--;
pc = ShowEA (0, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, deaddr, safemode);
_tcscat (instrname, _T(","));
movemout (instrname, mask, dp->dmode);
- pc += 2;
} else if (lookup->mnemo == i_MVMLE) {
uae_u16 mask = get_word_debug (pc);
pc += 2;
#include <sys/timeb.h>
#include <Shobjidl.h>
#include <ShlGuid.h>
+#include <Shlwapi.h>
bool my_isfilehidden (const TCHAR *path)
{
return false;
}
+bool my_createsoftlink(const TCHAR *path, const TCHAR *target)
+{
+ return CreateSymbolicLink(path, target, my_existsdir(target) ? SYMBOLIC_LINK_FLAG_DIRECTORY : 0) != 0;
+}
+
+bool my_issamevolume(const TCHAR *path1, const TCHAR *path2, TCHAR *path)
+{
+ TCHAR p1[MAX_DPATH];
+ TCHAR p2[MAX_DPATH];
+ TCHAR p1b[MAX_DPATH];
+ TCHAR p2b[MAX_DPATH];
+ int len;
+
+ if (!GetFullPathName(path1, sizeof p1 / sizeof (TCHAR), p1, NULL))
+ return false;
+ if (!GetFullPathName(path2, sizeof p2 / sizeof (TCHAR), p2, NULL))
+ return false;
+ PathCanonicalize(p1b, p1);
+ PathCanonicalize(p2b, p2);
+ len = _tcslen (p1b);
+ if (len > _tcslen (p2b))
+ len = _tcslen (p2b);
+ if (_tcsnicmp (p1b, p2b, len))
+ return false;
+ _tcscpy (path, p2b + len);
+ for (int i = 0; i < _tcslen (path); i++) {
+ if (path[i] == '\\')
+ path[i] = '/';
+ }
+ return true;
+}
+
+bool my_resolvesoftlink(TCHAR *linkfile, int size)
+{
+ if (my_resolvessymboliclink(linkfile, size))
+ return true;
+ if (my_resolveshortcut(linkfile,size))
+ return true;
+ return false;
+}
+
+typedef struct _REPARSE_DATA_BUFFER {
+ ULONG ReparseTag;
+ USHORT ReparseDataLength;
+ USHORT Reserved;
+ union {
+ struct {
+ USHORT SubstituteNameOffset;
+ USHORT SubstituteNameLength;
+ USHORT PrintNameOffset;
+ USHORT PrintNameLength;
+ ULONG Flags;
+ WCHAR PathBuffer[1];
+ } SymbolicLinkReparseBuffer;
+ struct {
+ USHORT SubstituteNameOffset;
+ USHORT SubstituteNameLength;
+ USHORT PrintNameOffset;
+ USHORT PrintNameLength;
+ WCHAR PathBuffer[1];
+ } MountPointReparseBuffer;
+ struct {
+ UCHAR DataBuffer[1];
+ } GenericReparseBuffer;
+ };
+} REPARSE_DATA_BUFFER, *PREPARSE_DATA_BUFFER;
+
+bool my_resolvessymboliclink(TCHAR *linkfile, int size)
+{
+ WIN32_FIND_DATA fd;
+ HANDLE h;
+ bool ret = false;
+ DWORD returnedDataSize;
+ uae_u8 tmp[MAX_DPATH * 2];
+
+ h = FindFirstFile (linkfile, &fd);
+ if (h == INVALID_HANDLE_VALUE)
+ return false;
+ FindClose(h);
+ if (fd.dwReserved0 != IO_REPARSE_TAG_SYMLINK || !(fd.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT))
+ return false;
+ 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);
+ if (h == INVALID_HANDLE_VALUE)
+ return false;
+ if (DeviceIoControl(h, FSCTL_GET_REPARSE_POINT, NULL, 0, tmp, sizeof tmp, &returnedDataSize, NULL)) {
+ REPARSE_DATA_BUFFER *rdb = (REPARSE_DATA_BUFFER*)tmp;
+ if (rdb->SymbolicLinkReparseBuffer.Flags & 1) { // SYMLINK_FLAG_RELATIVE
+ PathRemoveFileSpec (linkfile);
+ _tcscat (linkfile, _T("\\"));
+ TCHAR *p = linkfile + _tcslen (linkfile);
+ memcpy (p,
+ (uae_u8*)rdb->SymbolicLinkReparseBuffer.PathBuffer + rdb->SymbolicLinkReparseBuffer.SubstituteNameOffset,
+ rdb->SymbolicLinkReparseBuffer.SubstituteNameLength);
+ p[rdb->SymbolicLinkReparseBuffer.SubstituteNameLength / 2] = 0;
+ } else {
+ memcpy (linkfile,
+ (uae_u8*)rdb->SymbolicLinkReparseBuffer.PathBuffer + rdb->SymbolicLinkReparseBuffer.SubstituteNameOffset,
+ rdb->SymbolicLinkReparseBuffer.SubstituteNameLength);
+ linkfile[rdb->SymbolicLinkReparseBuffer.SubstituteNameLength / 2] = 0;
+ }
+ ret = true;
+ if (!_tcsnicmp (linkfile, _T("\\??\\"), 4)) {
+ memmove (linkfile, linkfile + 4, (_tcslen (linkfile + 4) + 1) * sizeof (TCHAR));
+ }
+ }
+ CloseHandle(h);
+ return ret;
+}
+
// http://msdn.microsoft.com/en-us/library/aa969393.aspx
bool my_resolveshortcut(TCHAR *linkfile, int size)
{
WIN32_FIND_DATA wfd;
const TCHAR *ext = _tcsrchr (linkfile, '.');
- if (!ext || _tcsicmp (ext, _T("lnk")) == 0)
+ if (!ext || _tcsicmp (ext, _T(".lnk")) != 0)
return false;
// Get a pointer to the IShellLink interface. It is assumed that CoInitialize
return 0;
}
aino->dir = (mode & FILE_ATTRIBUTE_DIRECTORY) ? 1 : 0;
+
+ if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
+ WIN32_FIND_DATA fd;
+ HANDLE h = FindFirstFile (aino->nname, &fd);
+ if (h != INVALID_HANDLE_VALUE) {
+ FindClose(h);
+ if (fd.dwReserved0 == IO_REPARSE_TAG_SYMLINK && (fd.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)) {
+ aino->softlink = true;
+ }
+ }
+ }
+
mode &= FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_ARCHIVE | FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN;
if ((base->volflags & MYVOLUMEINFO_STREAMS) && read_uaefsdb (aino->nname, NULL, fsdb)) {
create_uaefsdb (aino, fsdb, mode);
write_uaefsdb (aino->nname, fsdb);
}
+
+ if (!aino->softlink && !aino->dir) {
+ const TCHAR *ext = _tcsrchr (aino->nname, '.');
+ if (ext && !_tcsicmp (ext, _T(".lnk"))) {
+ TCHAR tmp[MAX_DPATH];
+ _tcscpy (tmp, aino->nname);
+ if (my_resolvesoftlink (tmp, sizeof tmp / sizeof (TCHAR))) {
+ aino->softlink = true;
+ }
+ }
+ }
+
return 1;
}
#define LANG_DLL 1
#if WINUAEPUBLICBETA
-#define WINUAEBETA _T("8")
+#define WINUAEBETA _T("9")
#else
#define WINUAEBETA _T("")
#endif
-#define WINUAEDATE MAKEBD(2013, 2, 23)
+#define WINUAEDATE MAKEBD(2013, 2, 24)
#define WINUAEEXTRA _T("")
//#define WINUAEEXTRA _T("AmiKit Preview")
#define WINUAEREV _T("")
int mask;
DragQueryFile (hd, i, file, sizeof (file) / sizeof (TCHAR));
- my_resolveshortcut (file, sizeof file / sizeof (TCHAR));
+ my_resolvesoftlink (file, sizeof file / sizeof (TCHAR));
filepart = _tcsrchr (file, '/');
if (!filepart)
filepart = _tcsrchr (file, '\\');
- restore only single input target to default.
+Beta 9:
+
+- 68000 NBCD didn't emulate undocumented V-flag behavior. (Probably forgotten long time ago because SBCD had correct
+ implementation)
+- It was impossible to get out of halted CPU state in some situations.
+- FDBcc and FScc 6888x FPU instructions without installed FPU returned wrong f-line exception PC field.
+- Directory filesystem: emulate Windows shortcut (.lnk) files and symbolic links as Amiga side soft links.
+ Implements ACTION_READ_LINK. Works also across drives if shortcut/link target exists in any mounted directory harddrive.
+ Not guaranteed to be 100% correct implementation, Amiga softlinks are a bit strange.
+
Beta 8:
- CD SCSI emulation: implemented mode sense CD/DVD page code 0x2A. Used to detect drive capabilities, for example