summaryrefslogtreecommitdiffstats
path: root/vfat.c
diff options
context:
space:
mode:
Diffstat (limited to 'vfat.c')
-rw-r--r--vfat.c32
1 files changed, 24 insertions, 8 deletions
diff --git a/vfat.c b/vfat.c
index 801156b..45d468a 100644
--- a/vfat.c
+++ b/vfat.c
@@ -24,9 +24,6 @@
#include "fat.h"
#include "minmax.h"
-#define VFAT_MAX_LEN 64
-#define VFAT_MAX_SLOTS ((VFAT_MAX_LEN+12)/13)
-
extern const char *program;
static iconv_t iconv_utf16;
@@ -50,22 +47,38 @@ int vfat_make_long_name(struct fat_vfat_slot *slots,
char *inb, *outb;
int inbl, outbl, xl, nx;
int seq = 1;
-
+ int i;
+ uint16_t cv;
+ static const char *vfat_bad_long =
+ "\1\2\3\4\5\6\7\10\11\12\13\14\15\16\17"
+ "\20\21\22\23\24\25\26\27\30\31\32\33\34\35\36\37"
+ "\"*/:<>?\\|\177";
+
inb = str;
inbl = strlen(inb);
outb = (char *)buffer;
- outbl = VFAT_MAX_LEN << 1;
-
+ outbl = VFAT_MAX_LEN << 1;
+
iconv(iconv_utf16, NULL, NULL, NULL, NULL); /* Reset input state */
iconv(iconv_utf16, &inb, &inbl, &outb, &outbl);
-
+
xl = VFAT_MAX_LEN - (outbl >> 1);
xb = buffer;
+ /* The VFAT spec says trailing periods and leading and trailing spaces
+ are ignored. However, it doesn't specify if those should actually
+ be stripped. Ignore that for now and let the filesystem worry about it. */
+
+ for ( i = 0 ; i < xl ; i++ ) {
+ cv = read16((le16_t *)&buffer[i]);
+ if ( cv <= 127 && strchr(vfat_bad_long, cv) )
+ write16((le16_t *)&buffer[i], '_'); /* Bad character, replace with _ */
+ }
+
while ( xl ) {
memset(slots, 0, sizeof(*slots));
slots->id = seq++;
- slots->attribute = 0xef; /* FIX */
+ slots->attribute = 0x0f; /* Part of a long name */
slots->alias_csum = csum;
nx = min(xl,5);
@@ -80,6 +93,9 @@ int vfat_make_long_name(struct fat_vfat_slot *slots,
memcpy(slots->name11, xb, nx<<1);
xl -= nx;
+ if ( !xl )
+ slots->id |= 0x40; /* Last slot */
+
slots++;
}