From e9fe5b86788ea20aec7c50bf0d7977b9857e9bd1 Mon Sep 17 00:00:00 2001 From: Kelvin Sherlock Date: Mon, 18 Sep 2017 23:28:39 -0400 Subject: [PATCH 1/4] host fst fixup: 1. if file_type = 0x0f, storage_type = 0x01, create a directory 2. only read pathname if pathname is expected 3. log path for calls that take a path 4. differentiate fileNotFound vs pathNotFound errors. --- src/host_fst.c | 94 +++++++++++++++++++++++++++++++++++--------- src/win32_host_fst.c | 43 +++++++++++++++++--- 2 files changed, 114 insertions(+), 23 deletions(-) diff --git a/src/host_fst.c b/src/host_fst.c index 33b8ae3..6a464c6 100644 --- a/src/host_fst.c +++ b/src/host_fst.c @@ -12,6 +12,7 @@ #include #include #include +#include #include "defc.h" #include "gsos.h" @@ -204,6 +205,22 @@ static char *gc_strdup(const char *src) { return cp; } +static word32 enoent(const char *path) { + /* + some op on path return ENOENT. check if it's + fileNotFound or pathNotFound + */ + char *p = (char *)path; + for(;;) { + struct stat st; + p = dirname(p); + if (p == NULL) break; + if (p[0] == '.' && p[1] == 0) break; + if (p[0] == '/' && p[1] == 0) break; + if (stat(p, &st) < 0) return pathNotFound; + } + return fileNotFound; +} static word32 map_errno() { switch(errno) { @@ -226,6 +243,11 @@ static word32 map_errno() { } } +static word32 map_errno_path(const char *path) { + if (errno == ENOENT) return enoent(path); + return map_errno(); +} + static struct fd_entry *find_fd(int cookie) { struct fd_entry *head = fd_head; @@ -478,12 +500,12 @@ static void get_file_xinfo(const char *path, struct file_info *fi) { static void get_file_xinfo(const char *path, struct file_info *fi) { ssize_t tmp; - tmp = getxattr(path, "user.apple.ResourceFork", NULL, 0); + tmp = getxattr(path, "user.com.apple.ResourceFork", NULL, 0); if (tmp < 0) tmp = 0; fi->resource_eof = tmp; fi->resource_blocks = (tmp + 511) / 512; - tmp = getxattr(path, "user.apple.FinderInfo", fi->finder_info, 32); + tmp = getxattr(path, "user.com.apple.FinderInfo", fi->finder_info, 32); if (tmp == 16 || tmp == 32){ fi->has_fi = 1; @@ -1021,24 +1043,38 @@ static word32 fst_create(int class, const char *path) { } int ok; + if (fi.storage_type == 0 && fi.file_type == 0x0f) + fi.storage_type = 0x0d; + if (fi.storage_type == 0x0d) { ok = mkdir(path, 0777); - if (ok < 0) return map_errno(); + if (ok < 0) { + return map_errno_path(path); + } + + if (class) { + if (pcount >= 5) set_memory16_c(pb + CreateRecGS_storageType, fi.storage_type, 0); + } else { + set_memory16_c(pb + CreateRec_storageType, fi.storage_type, 0); + } + return 0; } if (fi.storage_type <= 3 || fi.storage_type == 0x05) { // normal file. // 0x05 is an extended/resource file but we don't do anything special. ok = open(path, O_WRONLY | O_CREAT | O_EXCL, 0666); - if (ok < 0) return map_errno(); + if (ok < 0) return map_errno_path(path); // set ftype, auxtype... set_file_info(path, &fi); close(ok); + fi.storage_type = 1; + if (class) { - if (pcount >= 5) set_memory16_c(pb + CreateRecGS_storageType, 1, 0); + if (pcount >= 5) set_memory16_c(pb + CreateRecGS_storageType, fi.storage_type, 0); } else { - set_memory16_c(pb + CreateRec_storageType, 1, 0); + set_memory16_c(pb + CreateRec_storageType, fi.storage_type, 0); } return 0; @@ -1067,7 +1103,7 @@ static word32 fst_destroy(int class, const char *path) { if (!path) return badStoreType; if (stat(path, &st) < 0) { - return map_errno(); + return map_errno_path(path); } // can't delete volume root. @@ -1078,7 +1114,7 @@ static word32 fst_destroy(int class, const char *path) { int ok = S_ISDIR(st.st_mode) ? rmdir(path) : unlink(path); - if (ok < 0) return map_errno(); + if (ok < 0) return map_errno_path(path); return 0; } @@ -1295,7 +1331,7 @@ static int open_data_fork(const char *path, word16 *access, word16 *error) { break; } if (fd < 0) { - *error = map_errno(); + *error = map_errno_path(path); } return fd; @@ -1333,7 +1369,7 @@ static int open_resource_fork(const char *path, word16 *access, word16 *error) { break; } if (fd < 0) { - *error = map_errno(); + *error = map_errno_path(path); } return fd; @@ -1345,7 +1381,7 @@ static int open_resource_fork(const char *path, word16 *access, word16 *error) { static int open_resource_fork(const char *path, word16 *access, word16 *error) { int tmp = open(path, O_RDONLY); if (tmp < 0) { - *error = map_errno(); + *error = map_errno_path(path); return -1; } @@ -1376,7 +1412,7 @@ static int open_resource_fork(const char *path, word16 *access, word16 *error) { } if (fd < 0) { - *error = map_errno(); + *error = map_errno_path(path); close(tmp); return -1; } @@ -1879,7 +1915,7 @@ static struct directory *read_directory(const char *path, word16 *error) { dirp = opendir(path); if (!dirp) { - *error = map_errno(); + *error = map_errno_path(path); return NULL; } @@ -2046,12 +2082,12 @@ static word32 fst_change_path(int class, const char *path1, const char *path2) { /* make sure they're not trying to rename the volume... */ struct stat st; - if (stat(path1, &st) < 0) return map_errno(); + if (stat(path1, &st) < 0) return map_errno_path(path1); if (st.st_dev == root_dev && st.st_ino == root_ino) return invalidAccess; // rename will delete any previous file. - if (rename(path1, path2) < 0) return map_errno(); + if (rename(path1, path2) < 0) return map_errno_path(path2); return 0; } @@ -2365,10 +2401,11 @@ void host_fst(void) { word32 acc = 0; word16 call = engine.xreg; - fprintf(stderr, "Host FST: %04x %s\n", call, call_name(call)); + fprintf(stderr, "Host FST: %04x %s", call, call_name(call)); if (call & 0x8000) { + fputs("\n", stderr); // system level. switch(call) { case 0x8001: @@ -2391,12 +2428,33 @@ void host_fst(void) { engine.acc = invalidClass; return; } - char *path1 = get_path1(); - char *path2 = get_path2(); + char *path1 = NULL; + char *path2 = NULL; char *path3 = NULL; char *path4 = NULL; const char *cp; + switch(call & 0xff) { + case 0x01: + case 0x02: + case 0x05: + case 0x06: + case 0x07: + case 0x0b: + case 0x10: + path1 = get_path1(); + break; + case 0x04: + path1 = get_path1(); + path2 = get_path2(); + break; + + } + + if (path1) fprintf(stderr, " - %s", path1); + if (path2) fprintf(stderr, " - %s", path2); + fputs("\n", stderr); + switch(call & 0xff) { case 0x01: cp = check_path(path1, &acc); diff --git a/src/win32_host_fst.c b/src/win32_host_fst.c index 9b28777..079aef5 100644 --- a/src/win32_host_fst.c +++ b/src/win32_host_fst.c @@ -1111,9 +1111,19 @@ static word32 fst_create(int class, const char *path) { } int ok; + if (fi.storage_type == 0 && fi.file_type == 0x0f) + fi.storage_type = 0x0d; + if (fi.storage_type == 0x0d || fi.storage_type == 0x0f) { ok = CreateDirectory(path, NULL); if (!ok) return map_last_error(); + + if (class) { + if (pcount >= 5) set_memory16_c(pb + CreateRecGS_storageType, fi.storage_type, 0); + } else { + set_memory16_c(pb + CreateRec_storageType, fi.storage_type, 0); + } + return 0; } if (fi.storage_type <= 3 || fi.storage_type == 0x05) { @@ -1131,10 +1141,12 @@ static word32 fst_create(int class, const char *path) { set_file_info(path, &fi); // set_file_info_handle(...); CloseHandle(h); + fi.storage_type = 1; + if (class) { - if (pcount >= 5) set_memory16_c(pb + CreateRecGS_storageType, 1, 0); + if (pcount >= 5) set_memory16_c(pb + CreateRecGS_storageType, fi.storage_type, 0); } else { - set_memory16_c(pb + CreateRec_storageType, 1, 0); + set_memory16_c(pb + CreateRec_storageType, fi.storage_type, 0); } return 0; @@ -2513,10 +2525,11 @@ void host_fst(void) { word32 acc = 0; word16 call = engine.xreg; - fprintf(stderr, "Host FST: %04x %s\n", call, call_name(call)); + fprintf(stderr, "Host FST: %04x %s", call, call_name(call)); if (call & 0x8000) { + fputs("\n", stderr); // system level. switch(call) { case 0x8001: @@ -2539,12 +2552,32 @@ void host_fst(void) { engine.acc = invalidClass; return; } - char *path1 = get_path1(); - char *path2 = get_path2(); + char *path1 = NULL; + char *path2 = NULL; char *path3 = NULL; char *path4 = NULL; const char *cp; + switch(call & 0xff) { + case 0x01: + case 0x02: + case 0x05: + case 0x06: + case 0x07: + case 0x0b: + case 0x10: + path1 = get_path1(); + break; + case 0x04: + path1 = get_path1(); + path2 = get_path2(); + break; + } + + if (path1) fprintf(stderr, " - %s", path1); + if (path2) fprintf(stderr, " - %s", path2); + fputs("\n", stderr); + switch(call & 0xff) { case 0x01: cp = check_path(path1, &acc); From d1057c52f38e30f7e685e02e7a72049359bae6fd Mon Sep 17 00:00:00 2001 From: Kelvin Sherlock Date: Sat, 7 Jul 2018 00:49:36 -0400 Subject: [PATCH 2/4] Host FST updates: 1. slightly improved logging 2. option to automatically translate cr/lf in text/source files 3. option to merlin encode text .S files 4. default file type for common source code files extensions. --- src/config.c | 4 + src/host_fst.c | 185 +++++++++++++++++++++++++++++++++++++++---- src/win32_host_fst.c | 169 +++++++++++++++++++++++++++++++++++---- 3 files changed, 327 insertions(+), 31 deletions(-) diff --git a/src/config.c b/src/config.c index 536b6f4..443fa8c 100644 --- a/src/config.c +++ b/src/config.c @@ -118,6 +118,8 @@ extern int g_win_status_debug_request; extern char *g_cfg_host_path; extern int g_cfg_host_read_only; +extern int g_cfg_host_crlf; +extern int g_cfg_host_merlin; extern int g_screen_index[]; extern word32 g_full_refresh_needed; @@ -244,6 +246,8 @@ Cfg_menu g_cfg_host_menu[] = { { "Host FST Configuration", g_cfg_host_menu, 0, 0, CFGTYPE_MENU }, { "Shared Host Folder", KNMP(g_cfg_host_path), CFGTYPE_DIR }, { "Read Only,0,No,1,Yes", KNMP(g_cfg_host_read_only), CFGTYPE_INT }, +{ "CR/LF conversion,0,No,1,Yes", KNMP(g_cfg_host_crlf), CFGTYPE_INT }, +{ "Merlin conversion,0,No,1,Yes", KNMP(g_cfg_host_merlin), CFGTYPE_INT }, { "", 0, 0, 0, 0 }, { "Back to Main Config", g_cfg_main_menu, 0, 0, CFGTYPE_MENU }, { 0, 0, 0, 0, 0 }, diff --git a/src/host_fst.c b/src/host_fst.c index 6a464c6..b0d13cb 100644 --- a/src/host_fst.c +++ b/src/host_fst.c @@ -74,6 +74,12 @@ enum { directory_file, }; +enum { + translate_none, + translate_crlf, + translate_merlin, +}; + struct directory { int displacement; @@ -88,6 +94,7 @@ struct fd_entry { int type; int access; int fd; + int translate; struct directory *dir; }; @@ -137,7 +144,8 @@ static int read_only = 0; char *g_cfg_host_path = ""; // must not be null. int g_cfg_host_read_only = 0; - +int g_cfg_host_crlf = 1; +int g_cfg_host_merlin = 0; /* * simple malloc pool to simplify code. Should never need > 4 allocations. @@ -296,16 +304,92 @@ static word32 remove_fd(int cookie) { return rv; } -static ssize_t safe_read(int fd, void *buffer, size_t count) { +static void cr_to_lf(byte *buffer, size_t size) { + size_t i; + for (i = 0; i < size; ++i) { + if (buffer[i] == '\r') buffer[i] = '\n'; + } +} + +static void lf_to_cr(byte *buffer, size_t size) { + size_t i; + for (i = 0; i < size; ++i) { + if (buffer[i] == '\n') buffer[i] = '\r'; + } +} + +static void merlin_to_text(byte *buffer, size_t size) { + size_t i; + for (i = 0; i < size; ++i) { + byte b = buffer[i]; + if (b == 0xa0) b = '\t'; + b &= 0x7f; + if (b == '\r') b = '\n'; + buffer[i] = b; + } +} + +static void text_to_merlin(byte *buffer, size_t size) { + size_t i; + for (i = 0; i < size; ++i) { + byte b = buffer[i]; + if (b == '\t') b = 0xa0; + if (b == '\n') b = '\r'; + if (b != ' ') b |= 0x80; + buffer[i] = b; + } +} + +static ssize_t safe_read(struct fd_entry *e, byte *buffer, size_t count) { + int fd = e->fd; + int tr = e->translate; + for (;;) { ssize_t ok = read(fd, buffer, count); - if (ok >= 0) return ok; + if (ok >= 0) { + size_t i; + if (tr == translate_crlf) { + for (i = 0; i < ok; ++i) { + if (buffer[i] == '\n') buffer[i] = '\r'; + } + } + if (tr == translate_merlin) { + for (i = 0; i < ok; ++i) { + unsigned char c = buffer[i]; + if (c == '\t') c = 0xa0; + if (c == '\n') c = '\r'; + if (c != ' ') c |= 0x80; + buffer[i] = c; + } + } + return ok; + } if (ok < 0 && errno == EINTR) continue; return ok; } } -static ssize_t safe_write(int fd, const void *buffer, size_t count) { +static ssize_t safe_write(struct fd_entry *e, byte *buffer, size_t count) { + int fd = e->fd; + int tr = e->translate; + + if (tr == translate_crlf) { + size_t i; + for (i = 0; i < count; ++i) { + if (buffer[i] == '\r') buffer[i] = '\n'; + } + } + if (tr == translate_merlin) { + size_t i; + for (i = 0; i < count; ++i) { + unsigned char c = buffer[i]; + if (c == 0xa0) c = '\t'; + c &= 0x7f; + if (c == '\r') c = '\n'; + buffer[i] = c; + } + } + for (;;) { ssize_t ok = write(fd, buffer, count); if (ok >= 0) return ok; @@ -517,6 +601,37 @@ static void get_file_xinfo(const char *path, struct file_info *fi) { } #endif +#undef _ +#define _(a, b, c) { a, sizeof(a) - 1, b, c } +struct ftype_entry { + char *ext; + unsigned length; + unsigned file_type; + unsigned aux_type; +}; + +static struct ftype_entry suffixes[] = { + _("c", 0xb0, 0x0008), + _("cc", 0xb0, 0x0008), + _("h", 0xb0, 0x0008), + _("rez", 0xb0, 0x0015), + _("asm", 0xb0, 0x0003), + _("mac", 0xb0, 0x0003), + _("pas", 0xb0, 0x0005), + _("txt", 0x04, 0x0000), + _("text", 0x04, 0x0000), + _("s", 0x04, 0x0000), + { 0, 0, 0, 0} +}; + +static struct ftype_entry prefixes[] = { + _("m16.", 0xb0, 0x0003), + _("e16.", 0xb0, 0x0003), + { 0, 0, 0, 0} +}; + +#undef _ + static word32 get_file_info(const char *path, struct file_info *fi) { struct stat st; memset(fi, 0, sizeof(*fi)); @@ -564,6 +679,31 @@ static word32 get_file_info(const char *path, struct file_info *fi) { if (S_ISREG(st.st_mode)) { get_file_xinfo(path, fi); + + if (!fi->has_fi) { + /* guess the file type / auxtype based on extension */ + int n; + const char *dot = NULL; + const char *slash = NULL; + + for(n = 0; ; ++n) { + char c = path[n]; + if (c == 0) break; + else if (c == '/') { slash = path + n + 1; dot = NULL; } + else if (c == '.') dot = path + n + 1; + } + + if (dot && *dot) { + for (n = 0; n < sizeof(suffixes) / sizeof(suffixes[0]); ++n) { + if (!suffixes[n].ext) break; + if (!strcasecmp(dot, suffixes[n].ext)) { + fi->file_type = suffixes[n].file_type; + fi->aux_type = suffixes[n].aux_type; + break; + } + } + } + } } // get file type/aux type @@ -1551,6 +1691,20 @@ static word32 fst_open(int class, const char *path) { return tooManyFilesOpen; } + if (type == regular_file){ + + if (g_cfg_host_crlf) { + if (fi.file_type == 0x04 || fi.file_type == 0xb0) + e->translate = translate_crlf; + } + + if (g_cfg_host_merlin && fi.file_type == 0x04) { + int n = strlen(path); + if (n >= 3 && path[n-1] == 'S' && path[n-2] == '.') + e->translate = translate_merlin; + } + } + e->access = access; e->path = strdup(path); e->type = type; @@ -1610,7 +1764,7 @@ static word32 fst_read(int class) { for (word32 i = 0 ; i < request_count; ++i) { byte b; - ok = safe_read(e->fd, &b, 1); + ok = safe_read(e, &b, 1); if (ok < 0) return map_errno(); if (ok == 0) break; transfer_count++; @@ -1623,7 +1777,8 @@ static word32 fst_read(int class) { byte *data = gc_malloc(request_count); if (!data) return outOfMem; - ok = safe_read(e->fd, data, request_count); + + ok = safe_read(e, data, request_count); if (ok < 0) rv = map_errno(); if (ok == 0) rv = eofEncountered; if (ok > 0) { @@ -1685,7 +1840,7 @@ static word32 fst_write(int class) { } word32 rv = 0; - ssize_t ok = safe_write(e->fd, data, request_count); + ssize_t ok = safe_write(e, data, request_count); if (ok < 0) rv = map_errno(); if (ok > 0) { if (class) @@ -2026,7 +2181,7 @@ static word32 fst_get_dir_entry(int class) { struct file_info fi; rv = get_file_info(fullpath, &fi); - + if (dname) fprintf(stderr, " - %s", dname); // p16 and gs/os both use truncating c1 output string. rv = set_gsstr_truncate(name, dname); @@ -2403,7 +2558,6 @@ void host_fst(void) { fprintf(stderr, "Host FST: %04x %s", call, call_name(call)); - if (call & 0x8000) { fputs("\n", stderr); // system level. @@ -2444,16 +2598,14 @@ void host_fst(void) { case 0x10: path1 = get_path1(); break; - case 0x04: - path1 = get_path1(); - path2 = get_path2(); - break; - + case 0x04: + path1 = get_path1(); + path2 = get_path2(); + break; } if (path1) fprintf(stderr, " - %s", path1); if (path2) fprintf(stderr, " - %s", path2); - fputs("\n", stderr); switch(call & 0xff) { case 0x01: @@ -2551,8 +2703,7 @@ void host_fst(void) { acc = invalidFSTop; break; } - - + fputs("\n", stderr); } if (acc) fprintf(stderr, " %02x %s\n", acc, error_name(acc)); diff --git a/src/win32_host_fst.c b/src/win32_host_fst.c index 079aef5..399ce25 100644 --- a/src/win32_host_fst.c +++ b/src/win32_host_fst.c @@ -36,6 +36,11 @@ enum { directory_file, }; +enum { + translate_none, + translate_crlf, + translate_merlin, +}; struct directory { int displacement; @@ -50,6 +55,7 @@ struct fd_entry { int type; int access; HANDLE handle; + int translate; struct directory *dir; }; @@ -171,6 +177,8 @@ static int read_only = 0; char *g_cfg_host_path = ""; // must not be null. int g_cfg_host_read_only = 0; +int g_cfg_host_crlf = 1; +int g_cfg_host_merlin = 0; /* @@ -342,6 +350,42 @@ static word32 remove_fd(int cookie) { } +static void cr_to_lf(byte *buffer, size_t size) { + size_t i; + for (i = 0; i < size; ++i) { + if (buffer[i] == '\r') buffer[i] = '\n'; + } +} + +static void lf_to_cr(byte *buffer, size_t size) { + size_t i; + for (i = 0; i < size; ++i) { + if (buffer[i] == '\n') buffer[i] = '\r'; + } +} + +static void merlin_to_text(byte *buffer, size_t size) { + size_t i; + for (i = 0; i < size; ++i) { + byte b = buffer[i]; + if (b == 0xa0) b = '\t'; + b &= 0x7f; + if (b == '\r') b = '\n'; + buffer[i] = b; + } +} + +static void text_to_merlin(byte *buffer, size_t size) { + size_t i; + for (i = 0; i < size; ++i) { + byte b = buffer[i]; + if (b == '\t') b = 0xa0; + if (b == '\n') b = '\r'; + if (b != ' ') b |= 0x80; + buffer[i] = b; + } +} + struct file_info { FILETIME create_date; @@ -542,6 +586,39 @@ static word16 map_attributes(DWORD dwFileAttributes) { return access; } +#undef _ +#define _(a, b, c) { a, sizeof(a) - 1, b, c } +struct ftype_entry { + char *ext; + unsigned length; + unsigned file_type; + unsigned aux_type; +}; + +static struct ftype_entry suffixes[] = { + _("c", 0xb0, 0x0008), + _("cc", 0xb0, 0x0008), + _("h", 0xb0, 0x0008), + _("rez", 0xb0, 0x0015), + _("asm", 0xb0, 0x0003), + _("mac", 0xb0, 0x0003), + _("pas", 0xb0, 0x0005), + _("txt", 0x04, 0x0000), + _("text", 0x04, 0x0000), + _("s", 0x04, 0x0000), + { 0, 0, 0, 0} +}; + +static struct ftype_entry prefixes[] = { + _("m16.", 0xb0, 0x0003), + _("e16.", 0xb0, 0x0003), + { 0, 0, 0, 0} +}; + +#undef _ + + + static word32 get_file_info(const char *path, struct file_info *fi) { @@ -587,7 +664,33 @@ static word32 get_file_info(const char *path, struct file_info *fi) { get_file_xinfo(path, fi); if (fi->resource_eof) fi->storage_type = extendedFile; + + if (!fi->has_fi) { + /* guess the file type / auxtype based on extension */ + int n; + const char *dot = NULL; + const char *slash = NULL; + + for(n = 0; ; ++n) { + char c = path[n]; + if (c == 0) break; + else if (c == '/') { slash = path + n + 1; dot = NULL; } + else if (c == '.') dot = path + n + 1; + } + + if (dot && *dot) { + for (n = 0; n < sizeof(suffixes) / sizeof(suffixes[0]); ++n) { + if (!suffixes[n].ext) break; + if (!strcasecmp(dot, suffixes[n].ext)) { + fi->file_type = suffixes[n].file_type; + fi->aux_type = suffixes[n].aux_type; + break; + } + } + } + } } + // 0x01 = read enable // 0x02 = write enable // 0x04 = invisible @@ -1092,8 +1195,7 @@ static word32 fst_create(int class, const char *path) { if (pcount >= 4) { - afp_init - (&fi.afp, fi.file_type, fi.aux_type); + afp_init(&fi.afp, fi.file_type, fi.aux_type); fi.has_fi = 1; } @@ -1105,8 +1207,7 @@ static word32 fst_create(int class, const char *path) { fi.storage_type = get_memory16_c(pb + CreateRec_storageType, 0); fi.create_date = get_date_time(pb + CreateRec_createDate); - afp_init - (&fi.afp, fi.file_type, fi.aux_type); + afp_init(&fi.afp, fi.file_type, fi.aux_type); fi.has_fi = 1; } int ok; @@ -1114,7 +1215,7 @@ static word32 fst_create(int class, const char *path) { if (fi.storage_type == 0 && fi.file_type == 0x0f) fi.storage_type = 0x0d; - if (fi.storage_type == 0x0d || fi.storage_type == 0x0f) { + if (fi.storage_type == 0x0d) { ok = CreateDirectory(path, NULL); if (!ok) return map_last_error(); @@ -1720,6 +1821,22 @@ static word32 fst_open(int class, const char *path) { return tooManyFilesOpen; } + if (type == regular_file){ + + if (g_cfg_host_crlf) { + if (fi.file_type == 0x04 || fi.file_type == 0xb0) + e->translate = translate_crlf; + } + + if (g_cfg_host_merlin && fi.file_type == 0x04) { + int n = strlen(path); + if (n >= 3 && path[n-1] == 'S' && path[n-2] == '.') + e->translate = translate_merlin; + } + } + + + e->access = access; e->path = strdup(path); e->type = type; @@ -1787,6 +1904,16 @@ static word32 fst_read(int class) { if (!ok) return map_last_error(); if (read_count == 0) break; transfer_count++; + + switch(e->translate) { + case translate_crlf: + lf_to_cr(&b, 1); + break; + case translate_merlin: + text_to_merlin(&b, 1); + break; + } + set_memory_c(data_buffer++, b, 0); if (newline_table[b & newline_mask]) break; } @@ -1802,6 +1929,14 @@ static word32 fst_read(int class) { else if (read_count == 0) rv = eofEncountered; if (read_count > 0) { transfer_count = read_count; + switch(e->translate) { + case translate_crlf: + lf_to_cr(data, transfer_count); + break; + case translate_merlin: + text_to_merlin(data, transfer_count); + break; + } for (size_t i = 0; i < transfer_count; ++i) { set_memory_c(data_buffer + i, data[i], 0); } @@ -1858,6 +1993,14 @@ static word32 fst_write(int class) { data[i] = get_memory_c(data_buffer + i,0); } + switch (e->translate) { + case translate_crlf: + cr_to_lf(data, request_count); + break; + case translate_merlin: + merlin_to_text(data, request_count); + break; + } word32 rv = 0; DWORD write_count = 0; int ok = WriteFile(e->handle, data, request_count, &write_count, NULL); @@ -2128,6 +2271,7 @@ static word32 fst_get_dir_entry(int class) { struct file_info fi; rv = get_file_info(fullpath, &fi); + if (dname) fprintf(stderr, " - %s", dname); // p16 and gs/os both use truncating c1 output string. rv = set_gsstr_truncate(name, dname); @@ -2527,9 +2671,7 @@ void host_fst(void) { fprintf(stderr, "Host FST: %04x %s", call, call_name(call)); - if (call & 0x8000) { - fputs("\n", stderr); // system level. switch(call) { case 0x8001: @@ -2568,15 +2710,15 @@ void host_fst(void) { case 0x10: path1 = get_path1(); break; - case 0x04: - path1 = get_path1(); - path2 = get_path2(); - break; + case 0x04: + path1 = get_path1(); + path2 = get_path2(); + break; } if (path1) fprintf(stderr, " - %s", path1); if (path2) fprintf(stderr, " - %s", path2); - fputs("\n", stderr); + switch(call & 0xff) { case 0x01: @@ -2693,8 +2835,7 @@ void host_fst(void) { acc = invalidFSTop; break; } - - + fputs("\n", stderr); } if (acc) fprintf(stderr, " %02x %s\n", acc, error_name(acc)); From e886532dbe38a2d7489a8fd7ac64131aacc33e6e Mon Sep 17 00:00:00 2001 From: Kelvin Sherlock Date: Mon, 16 Jul 2018 13:52:56 -0400 Subject: [PATCH 3/4] host fst - error out if not initialized (prevents null deference later) --- src/host_fst.c | 16 +++++++++++++++- src/win32_host_fst.c | 16 +++++++++++++++- 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/src/host_fst.c b/src/host_fst.c index b0d13cb..faffd0a 100644 --- a/src/host_fst.c +++ b/src/host_fst.c @@ -2558,6 +2558,7 @@ void host_fst(void) { fprintf(stderr, "Host FST: %04x %s", call, call_name(call)); + if (call & 0x8000) { fputs("\n", stderr); // system level. @@ -2574,14 +2575,27 @@ void host_fst(void) { } } else { + if (!root) { + acc = networkError; + engine.acc = acc; + SEC(); + fprintf(stderr, " %02x %s\n", acc, error_name(acc)); + + return; + } + int class = call >> 13; call &= 0x1fff; if (class > 1) { + acc = invalidClass; + engine.acc = acc; SEC(); - engine.acc = invalidClass; + fprintf(stderr, " %02x %s\n", acc, error_name(acc)); + return; } + char *path1 = NULL; char *path2 = NULL; char *path3 = NULL; diff --git a/src/win32_host_fst.c b/src/win32_host_fst.c index 399ce25..a061478 100644 --- a/src/win32_host_fst.c +++ b/src/win32_host_fst.c @@ -2686,14 +2686,28 @@ void host_fst(void) { } } else { + if (!root) { + acc = networkError; + engine.acc = acc; + SEC(); + fprintf(stderr, " %02x %s\n", acc, error_name(acc)); + + return; + } + + int class = call >> 13; call &= 0x1fff; if (class > 1) { + acc = invalidClass; + engine.acc = acc; SEC(); - engine.acc = invalidClass; + fprintf(stderr, " %02x %s\n", acc, error_name(acc)); + return; } + char *path1 = NULL; char *path2 = NULL; char *path3 = NULL; From efbd79264d1a55cc5698b3b98d3d50064cbbd36b Mon Sep 17 00:00:00 2001 From: Kelvin Sherlock Date: Tue, 24 Jul 2018 09:16:03 -0400 Subject: [PATCH 4/4] host fst - JudgeName doesn't necessarily have a pathname. --- src/host_fst.c | 1 - src/win32_host_fst.c | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/host_fst.c b/src/host_fst.c index faffd0a..16bd27a 100644 --- a/src/host_fst.c +++ b/src/host_fst.c @@ -2607,7 +2607,6 @@ void host_fst(void) { case 0x02: case 0x05: case 0x06: - case 0x07: case 0x0b: case 0x10: path1 = get_path1(); diff --git a/src/win32_host_fst.c b/src/win32_host_fst.c index a061478..b5e2366 100644 --- a/src/win32_host_fst.c +++ b/src/win32_host_fst.c @@ -2672,6 +2672,7 @@ void host_fst(void) { fprintf(stderr, "Host FST: %04x %s", call, call_name(call)); if (call & 0x8000) { + fputs("\n", stderr); // system level. switch(call) { case 0x8001: @@ -2719,7 +2720,6 @@ void host_fst(void) { case 0x02: case 0x05: case 0x06: - case 0x07: case 0x0b: case 0x10: path1 = get_path1();