aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEduardo Casino <mail@eduardocasino.es>2022-05-16 20:12:19 +0200
committerJavier <dev.git@javispedro.com>2022-05-23 00:01:55 +0200
commit7b243074da3f4be6ed47426925f203c547c1c729 (patch)
treee200ebfbf6d3912458db78d26da4fb152bc1c4bb
parentb8eb74ac1d31ffc382e654e19bba4e5e48f0001e (diff)
downloadvbados-7b243074da3f4be6ed47426925f203c547c1c729.tar.gz
vbados-7b243074da3f4be6ed47426925f203c547c1c729.zip
Add support for windows host short file names
-rw-r--r--nls.h78
-rw-r--r--sfmain.c24
-rw-r--r--sftsr.c92
-rw-r--r--sftsr.h2
-rw-r--r--unicode.h42
5 files changed, 162 insertions, 76 deletions
diff --git a/nls.h b/nls.h
new file mode 100644
index 0000000..9699bb1
--- /dev/null
+++ b/nls.h
@@ -0,0 +1,78 @@
+/*
+ * VBSF - NLS support functions
+ * Copyright (C) 2011-2022 Eduardo Casino
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General License for more details.
+ *
+ * You should have received a copy of the GNU General License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifndef NLS_H
+#define NLS_H
+
+static bool illegal_char( unsigned char c )
+{
+ int i= 0;
+
+ for ( i= 0; i < data.file_char->n_illegal; ++i )
+ {
+ if ( c == data.file_char->illegal[i] )
+ {
+ return true;
+ }
+ }
+ if ( ( c < data.file_char->lowest || c > data.file_char->highest ) ||
+ !( c < data.file_char->first_x || c > data.file_char->last_x ) )
+ {
+ return true;
+ }
+
+ return false;
+}
+
+static unsigned char nls_toupper( unsigned char c )
+{
+ if ( c > 0x60 && c < 0x7b )
+ {
+ return c & 0xDF;
+ }
+
+ return ( c < 0x80 ? c : data.file_upper_case[c - 0x80] );
+}
+
+static inline void nls_uppercase(SHFLSTRING *str)
+{
+ int i;
+
+ for (i= 0; i < str->u16Length; ++i)
+ {
+ str->ach[i] = nls_toupper(str->ach[i]);
+ }
+}
+
+static inline bool valid_8_3_file_chars(char __far *fname )
+{
+ int i;
+
+ for (i = 0; i < 11; ++i)
+ {
+ if ( fname[i] != ' ' && illegal_char(fname[i]) )
+ {
+ break;
+ }
+ }
+
+ return ( i == 11 );
+}
+
+#endif // NLS_H
diff --git a/sfmain.c b/sfmain.c
index 9432508..3cbd336 100644
--- a/sfmain.c
+++ b/sfmain.c
@@ -452,7 +452,7 @@ error:
}
-static int configure_driver(LPTSRDATA data)
+static int configure_driver(LPTSRDATA data, bool short_fnames)
{
unsigned i;
int32_t err;
@@ -481,6 +481,16 @@ static int configure_driver(LPTSRDATA data)
data->tz_offset = 0;
}
+ // Get uppercase and valid file char tables
+ err = get_nls(&data->file_upper_case, &data->file_char);
+ if (err) {
+ puts("Cannot get the NLS tables.");
+ return -1;
+ }
+
+ // Set use of short file names from Windows hosts
+ data->short_fnames = short_fnames;
+
// Now try to initialize VirtualBox communication
err = vbox_init_device(&data->vb);
if (err) {
@@ -512,12 +522,6 @@ static int configure_driver(LPTSRDATA data)
return -1;
}
- err = get_nls(&data->file_upper_case, &data->file_char);
- if (err) {
- puts("Cannot get the NLS tables.");
- return -1;
- }
-
load_unicode_table( &data->unicode_table);
printf("Connected to VirtualBox shared folder service\n");
@@ -617,6 +621,7 @@ static void print_help(void)
"Supported actions:\n"
" install install the driver (default)\n"
" low install in conventional memory (otherwise UMB)\n"
+ " short use short file names from windows hosts\n"
" uninstall uninstall the driver from memory\n"
" list list available shared folders\n"
" mount <FOLD> <X:> mount a shared folder into drive X:\n"
@@ -668,6 +673,7 @@ int main(int argc, const char *argv[])
if (argi >= argc || stricmp(argv[argi], "install") == 0) {
bool high = true;
+ bool short_fnames = false;
argi++;
for (; argi < argc; argi++) {
@@ -675,6 +681,8 @@ int main(int argc, const char *argv[])
high = false;
} else if (stricmp(argv[argi], "high") == 0) {
high = true;
+ } else if (stricmp(argv[argi], "short") == 0) {
+ short_fnames = true;
} else {
return invalid_arg(argv[argi]);
}
@@ -695,7 +703,7 @@ int main(int argc, const char *argv[])
} else {
deallocate_environment(_psp);
}
- err = configure_driver(data);
+ err = configure_driver(data, short_fnames);
if (err) {
if (high) cancel_reallocation(FP_SEG(data));
return EXIT_FAILURE;
diff --git a/sftsr.c b/sftsr.c
index 5819ce5..86fb5b9 100644
--- a/sftsr.c
+++ b/sftsr.c
@@ -25,8 +25,6 @@
#include "unixtime.h"
#include "vboxshfl.h"
#include "sftsr.h"
-#define __IN_SFTSR__ 1
-#include "unicode.h"
TSRDATA data = {
// TSR installation data
@@ -56,6 +54,10 @@ TSRDATA data = {
0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0 }
};
+#define __IN_SFTSR__ 1
+#include "unicode.h"
+#include "nls.h"
+
/** Private buffer for VirtualBox filenames. */
static SHFLSTRING_WITH_BUF(shflstr, SHFL_MAX_LEN);
@@ -231,6 +233,17 @@ static int my_strrchr(const char __far *str, char c)
return last;
}
+static inline bool translate_filename_from_host(SHFLSTRING *str)
+{
+ bool valid;
+
+ valid = utf8_to_local( &data, str->ach, str->ach, &str->u16Length);
+
+ nls_uppercase(str);
+
+ return valid;
+}
+
static const char * get_basename(const char *path)
{
int last_sep = my_strrchr(path, '\\');
@@ -241,61 +254,6 @@ static const char * get_basename(const char *path)
}
}
-static bool illegal_char( unsigned char c )
-{
- int i= 0;
-
- for ( i= 0; i < data.file_char->n_illegal; ++i )
- {
- if ( c == data.file_char->illegal[i] )
- {
- return true;
- }
- }
- if ( ( c < data.file_char->lowest || c > data.file_char->highest ) ||
- !( c < data.file_char->first_x || c > data.file_char->last_x ) )
- {
- return true;
- }
-
- return false;
-}
-
-static unsigned char nls_toupper( unsigned char c )
-{
- if ( c > 0x60 && c < 0x7b )
- {
- return c & 0xDF;
- }
-
- return ( c < 0x80 ? c : data.file_upper_case[c - 0x80] );
-}
-
-static inline bool translate_filename_from_host(SHFLSTRING *str)
-{
- unsigned i;
- bool ret;
- unsigned dots = 0;
-
- ret = utf8_to_local(&data, str->ach, str->ach, &str->u16Length);
-
- for (i = 0; i < str->u16Length; i++) {
- if (str->ach[i] == '.') {
- ++dots;
- }
- else {
- if (illegal_char(str->ach[i])) {
- ret = false;
- }
- else {
- str->ach[i] = nls_toupper(str->ach[i]);
- }
- }
- }
-
- return ret && (dots <= 1);
-}
-
/** Tries to do some very simple heuristics to convert DOS-style wildcards
* into win32-like (as expected by VirtualBox). */
static void fix_wildcards(SHFLSTRING *str)
@@ -352,7 +310,7 @@ static bool copy_to_8_3_filename(char __far *dst, const SHFLSTRING *str)
{
int last_dot = my_strrchr(str->ach, '.');
unsigned namelen, extlen;
- bool valid_8_3 = true;
+ bool valid_8_3 = true, dotfile = false;
namelen = last_dot >= 0 ? last_dot : str->u16Length;
extlen = last_dot >= 0 ? str->u16Length - (last_dot + 1) : 0;
@@ -361,6 +319,7 @@ static bool copy_to_8_3_filename(char __far *dst, const SHFLSTRING *str)
// . , .. files
namelen = str->u16Length;
extlen = 0;
+ dotfile = true;
}
if (namelen == 0) {
@@ -381,7 +340,7 @@ static bool copy_to_8_3_filename(char __far *dst, const SHFLSTRING *str)
_fmemcpy(&dst[8], str->ach + last_dot + 1, extlen);
_fmemset(&dst[8+extlen], ' ', 3 - extlen);
- return valid_8_3;
+ return valid_8_3 && (dotfile || valid_8_3_file_chars(dst));
}
static bool is_8_3_wildcard(const char __far *name)
@@ -1089,10 +1048,17 @@ static vboxerr find_next_from_vbox(unsigned openfile, const char __far *path)
}
// Now convert the filename
- // TODO Use the short filename if available from a windows host
- // i.e. shfldirinfo.dirinfo.cucShortName
-
- if (!translate_filename_from_host(&shfldirinfo.dirinfo.name)) {
+ // Use the short filename if available from a windows host
+ if (data.short_fnames && shfldirinfo.dirinfo.cucShortName != 0) {
+ if (!utf16_to_local( &data, &shfldirinfo.dirinfo.name.ach, &shfldirinfo.dirinfo.uszShortName, shfldirinfo.dirinfo.cucShortName)) {
+ // Should not happen as Windows short names are pure ascii
+ dputs("hiding file with illegal character(s)");
+ continue;
+ }
+ shfldirinfo.dirinfo.name.u16Length = shfldirinfo.dirinfo.cucShortName;
+ dprintf(" Host short filename: '%s'\n", shfldirinfo.dirinfo.name.ach);
+ }
+ else if (!translate_filename_from_host(&shfldirinfo.dirinfo.name)) {
dputs("hiding file with illegal character(s)");
continue;
}
diff --git a/sftsr.h b/sftsr.h
index f318bd4..c832169 100644
--- a/sftsr.h
+++ b/sftsr.h
@@ -72,6 +72,8 @@ typedef struct {
FCHAR __far *file_char;
/** Codepage to unicode lookup table. */
uint16_t unicode_table[128];
+ /** LFN support */
+ bool short_fnames;
// Current status
/** Array of all possible DOS drives. */
diff --git a/unicode.h b/unicode.h
index 9e70895..81d187a 100644
--- a/unicode.h
+++ b/unicode.h
@@ -1,8 +1,5 @@
/*
- * VBSF - unix to DOS time conversion
- * Copyright (C) 2022 Javier S. Pedro
- *
- * unicode.h: Unicode conversion routines
+ * VBSF - Unicode conversion routines
* Copyright (C) 2011-2022 Eduardo Casino
*
* This program is free software; you can redistribute it and/or
@@ -212,4 +209,39 @@ cont:
}
-#endif
+// Returns true on success, false if any unsupported char is found
+//
+static bool utf16_to_local( TSRDATAPTR data, uint8_t *dst, uint16_t *src, uint16_t len )
+{
+ bool ret = true;
+ int i;
+ uint16_t cp;
+ uint8_t c;
+
+ for ( i = 0; i < len; ++i )
+ {
+ cp = src[i];
+
+ if ( cp < 0x80 )
+ {
+ *dst++ = ( uint8_t ) cp;
+ }
+ else
+ {
+ c = lookup_codepage( data, cp );
+ if ( c == '\0' )
+ {
+ c = '_';
+ ret = false;
+ }
+ *dst++ = c;
+ }
+ }
+
+ *dst = '\0';
+
+ return ret;
+
+}
+
+#endif // UNICODE_H