summaryrefslogtreecommitdiff
path: root/file_name.c
diff options
context:
space:
mode:
Diffstat (limited to 'file_name.c')
-rw-r--r--file_name.c220
1 files changed, 220 insertions, 0 deletions
diff --git a/file_name.c b/file_name.c
new file mode 100644
index 0000000..963a137
--- /dev/null
+++ b/file_name.c
@@ -0,0 +1,220 @@
+/* Copyright 1995 David C. Niemi
+ * Copyright 1996-1998,2000-2002,2008,2009 Alain Knaff.
+ * This file is part of mtools.
+ *
+ * Mtools is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Mtools 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 Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Mtools. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "sysincludes.h"
+#include "msdos.h"
+#include "mtools.h"
+#include "vfat.h"
+#include "codepage.h"
+#include "file_name.h"
+
+/* Write a DOS name + extension into a legal unix-style name. */
+char *unix_normalize (doscp_t *cp, char *ans, dos_name_t *dn)
+{
+ char buffer[13];
+ wchar_t wbuffer[13];
+ char *a;
+ int j;
+
+ for (a=buffer,j=0; (j<8) && (dn->base[j] > ' '); ++j,++a)
+ *a = dn->base[j];
+ if(dn->ext[0] > ' ') {
+ *a++ = '.';
+ for (j=0; j<3 && dn->ext[j] > ' '; ++j,++a)
+ *a = dn->ext[j];
+ }
+ *a++ = '\0';
+ dos_to_wchar(cp, buffer, wbuffer, 13);
+ wchar_to_native(wbuffer, ans, 13);
+ return ans;
+}
+
+typedef enum Case_l {
+ NONE,
+ UPPER,
+ LOWER
+} Case_t;
+
+static void TranslateToDos(doscp_t *toDos, const char *in, char *out, int count,
+ char *end, Case_t *Case, int *mangled)
+{
+ wchar_t buffer[12];
+ wchar_t *s=buffer;
+ wchar_t *t=buffer;
+
+ /* first convert to wchar, so we get to use towupper etc. */
+ native_to_wchar(in, buffer, count, end, mangled);
+ buffer[count]='\0';
+
+ *Case = NONE;
+ for( ; *s ; s++) {
+ /* skip spaces & dots */
+ if(*s == ' ' || *s == '.') {
+ *mangled |= 3;
+ continue;
+ }
+
+ if (iswcntrl(*s)) {
+ /* "control" characters */
+ *mangled |= 3;
+ *t = '_';
+ } else if (iswlower(*s)) {
+ *t = towupper(*s);
+ if(*Case == UPPER && !mtools_no_vfat)
+ *mangled |= 1;
+ else
+ *Case = LOWER;
+ } else if (iswupper(*s)) {
+ *t = *s;
+ if(*Case == LOWER && !mtools_no_vfat)
+ *mangled |= 1;
+ else
+ *Case = UPPER;
+ } else
+ *t = *s;
+ t++;
+ }
+ wchar_to_dos(toDos, buffer, out, t - buffer, mangled);
+}
+
+/* dos_name
+ *
+ * Convert a Unix-style filename to a legal MSDOS name and extension.
+ * Will truncate file and extension names, will substitute
+ * the character '~' for any illegal character(s) in the name.
+ */
+void dos_name(doscp_t *toDos, const char *name, int verbose UNUSEDP,
+ int *mangled, dos_name_t *dn)
+{
+ char *s, *ext;
+ register int i;
+ Case_t BaseCase, ExtCase;
+
+ *mangled = 0;
+
+ /* skip drive letter */
+ if (name[0] && name[1] == ':')
+ name = &name[2];
+
+ /* zap the leading path */
+ name = (char *) _basename(name);
+ if ((s = strrchr(name, '\\')))
+ name = s + 1;
+
+ memset(dn, ' ', 11);
+
+ /* skip leading dots and spaces */
+ i = strspn(name, ". ");
+ if(i) {
+ name += i;
+ *mangled = 3;
+ }
+
+ ext = strrchr(name, '.');
+
+ /* main name */
+ TranslateToDos(toDos, name, dn->base, 8, ext, &BaseCase, mangled);
+ if(ext)
+ TranslateToDos(toDos, ext+1, dn->ext, 3, 0, &ExtCase, mangled);
+
+ if(*mangled & 2)
+ autorename_short(dn, 0);
+
+ if(!*mangled) {
+ if(BaseCase == LOWER)
+ *mangled |= BASECASE;
+ if(ExtCase == LOWER)
+ *mangled |= EXTCASE;
+ }
+}
+
+
+/*
+ * Get rid of spaces in an MSDOS 'raw' name (one that has come from the
+ * directory structure) so that it can be used for regular expression
+ * matching with a Unix filename. Also used to 'unfix' a name that has
+ * been altered by dos_name().
+ */
+
+wchar_t *unix_name(doscp_t *dosCp,
+ const char *base, const char *ext, char Case, wchar_t *ret)
+{
+ char *s, tname[9], text[4], ans[13];
+ int i;
+
+ strncpy(tname, base, 8);
+ tname[8] = '\0';
+ if ((s = strchr(tname, ' ')))
+ *s = '\0';
+
+ if(!(Case & (BASECASE | EXTCASE)) && mtools_ignore_short_case)
+ Case |= BASECASE | EXTCASE;
+
+ if(Case & BASECASE)
+ for(i=0;i<8 && tname[i];i++)
+ tname[i] = tolower(tname[i]);
+
+ strncpy(text, ext, 3);
+ text[3] = '\0';
+ if ((s = strchr(text, ' ')))
+ *s = '\0';
+
+ if(Case & EXTCASE)
+ for(i=0;i<3 && text[i];i++)
+ text[i] = tolower(text[i]);
+
+ if (*text) {
+ strcpy(ans, tname);
+ strcat(ans, ".");
+ strcat(ans, text);
+ } else
+ strcpy(ans, tname);
+
+ /* fix special characters (above 0x80) */
+ dos_to_wchar(dosCp, ans, ret, 12);
+ return ret;
+}
+
+/* If null encountered, set *end to 0x40 and write nulls rest of way
+ * 950820: Win95 does not like this! It complains about bad characters.
+ * So, instead: If null encountered, set *end to 0x40, write the null, and
+ * write 0xff the rest of the way (that is what Win95 seems to do; hopefully
+ * that will make it happy)
+ */
+/* Always return num */
+int unicode_write(wchar_t *in, struct unicode_char *out, int num, int *end_p)
+{
+ int j;
+
+ for (j=0; j<num; ++j) {
+ if (*end_p)
+ /* Fill with 0xff */
+ out->uchar = out->lchar = (char) 0xff;
+ else {
+ out->uchar = *in >> 8;
+ out->lchar = *in;
+ if (! *in) {
+ *end_p = VSE_LAST;
+ }
+ }
+
+ ++out;
+ ++in;
+ }
+ return num;
+}