aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Serpell <daniel.serpell@gmail.com>2020-05-09 00:49:52 -0400
committerDaniel Serpell <daniel.serpell@gmail.com>2020-05-09 00:59:35 -0400
commit9fc1a0e56ee9008f2f407208c4ed6a1e6d259c5c (patch)
tree8b456e5fc6fcf82afe2ba11e8ad54681b5b5ccb6
parentcc32a3879ddff11becbb2e84329bb1bfd15c298c (diff)
downloademu2-9fc1a0e56ee9008f2f407208c4ed6a1e6d259c5c.tar.gz
Adds a function to transform unix paths to absolute DOS paths.
This allows to correctly set the current-working-directory and the executable name at program start.
-rw-r--r--src/dos.c18
-rw-r--r--src/dosnames.c75
-rw-r--r--src/dosnames.h3
3 files changed, 95 insertions, 1 deletions
diff --git a/src/dos.c b/src/dos.c
index a6745ee..4ac59ec 100644
--- a/src/dos.c
+++ b/src/dos.c
@@ -1969,6 +1969,18 @@ void init_dos(int argc, char **argv)
strncpy(path, getenv(ENV_CWD), 63);
dos_change_cwd(path);
}
+ else
+ {
+ // No CWD given, translate from base path of default drive
+ char *cwd = dos_real_path(dos_get_default_drive(), ".");
+ if(cwd)
+ {
+ dos_change_cwd(cwd);
+ free(cwd);
+ }
+ else
+ debug(debug_dos, "\tWARNING: working directory outside default drive\n");
+ }
// Concat rest of arguments
int i;
@@ -2002,7 +2014,11 @@ void init_dos(int argc, char **argv)
const char *progname = getenv(ENV_PROGNAME);
if(!progname)
- progname = argv[0];
+ {
+ progname = dos_real_path(dos_get_default_drive(), argv[0]);
+ if(!progname)
+ progname = argv[0];
+ }
// Create main PSP
int psp_mcb = create_PSP(args, environ, p - environ + 1, progname);
diff --git a/src/dosnames.c b/src/dosnames.c
index b98b8d3..f1e060f 100644
--- a/src/dosnames.c
+++ b/src/dosnames.c
@@ -74,6 +74,17 @@ static int dos_search_name(const struct dos_file_list *dl, const uint8_t *name)
return 0;
}
+static const struct dos_file_list *dos_search_unix_name(const struct dos_file_list *dl,
+ const char *name)
+{
+ for(; dl && dl->unixname; dl++)
+ {
+ if(!strcmp(dl->unixname, name))
+ return dl;
+ }
+ return 0;
+}
+
// Sort unix entries so that '~' and '.' comes before other chars
static int dos_unix_sort(const struct dirent **s1, const struct dirent **s2)
{
@@ -608,3 +619,67 @@ struct dos_file_list *dos_find_first_file_fcb(int addr)
{
return find_first_file(dos_unix_path_fcb(addr, 1));
}
+
+char *dos_real_path(char drive, const char *unix_path)
+{
+ char *ret = 0;
+ // Start by normalizing both base and given paths
+ char *base = realpath(get_base_path(drive), 0);
+ if(!base)
+ return 0;
+ char *path = realpath(unix_path, 0);
+ if(!path)
+ {
+ free(base);
+ return 0;
+ }
+ debug(debug_dos, "dos_real_path: base='%s' path='%s'\n", base, path);
+ // Now, see if the path is actually a descendent of base
+ size_t l = strlen(base), k = strlen(path);
+ if(strncmp(base, path, l) || (path[l] != '/' && path[l]))
+ {
+ debug(debug_dos, "dos_real_path: no common base\n");
+ }
+ else if(k - l > 62)
+ {
+ debug(debug_dos, "dos_real_path: path too long for DOS\n");
+ }
+ else
+ {
+ // Convert remaining components
+ ret = calloc(1, 64);
+ strncat(ret, "C:", 64);
+
+ path[l] = 0;
+ while(++l < k)
+ {
+ // Extract one component
+ char *sep = strchr(path + l, '/');
+ // Cut string there
+ if(!sep)
+ sep = path + k;
+ else
+ *sep = 0;
+ // And search the DOS path name
+ struct dos_file_list *fl = dos_read_dir(path, "*.*");
+ path[l - 1] = '/';
+ const struct dos_file_list *sl = dos_search_unix_name(fl, path);
+ if(!sl)
+ {
+ dos_free_file_list(fl);
+ debug(debug_dos, "dos_real_path: path not found: '%s' in '%s'\n",
+ path + l, path);
+ free(base);
+ free(path);
+ return 0;
+ }
+ strncat(ret, "\\", 64);
+ strncat(ret, (const char *)sl->dosname, 64);
+ dos_free_file_list(fl);
+ l = sep - path;
+ }
+ }
+ free(base);
+ free(path);
+ return ret;
+}
diff --git a/src/dosnames.h b/src/dosnames.h
index 63a5771..c75b786 100644
--- a/src/dosnames.h
+++ b/src/dosnames.h
@@ -22,6 +22,9 @@ char *dos_unix_path_fcb(int addr, int force);
int dos_change_cwd(char *path);
int dos_change_dir(int addr);
+// Returns a DOS path representing given Unix path in drive
+char *dos_real_path(char drive, const char *unix_path);
+
// Gets current working directory
const uint8_t *dos_get_cwd(int drive);
Un proyecto texto-plano.xyz