static direntry_t *create_short_filename(BDRVVVFATState *s, const char *filename, unsigned int directory_start) { int i, j = 0; direntry_t *entry = array_get_next(&(s->directory)); const gchar *p, *last_dot = NULL; gunichar c; bool lossy_conversion = false; char tail[11]; if (!entry) { return NULL; } memset(entry->name, 0x20, sizeof(entry->name)); /* copy filename and search last dot */ for (p = filename; ; p = g_utf8_next_char(p)) { c = g_utf8_get_char(p); if (c == '\0') { break; } else if (c == '.') { if (j == 0) { /* '.' at start of filename */ lossy_conversion = true; } else { if (last_dot) { lossy_conversion = true; } last_dot = p; } } else if (!last_dot) { /* first part of the name; copy it */ uint8_t v = to_valid_short_char(c); if (j < 8 && v) { entry->name[j++] = v; } else { lossy_conversion = true; } } } /* copy extension (if any) */ if (last_dot) { j = 0; for (p = g_utf8_next_char(last_dot); ; p = g_utf8_next_char(p)) { c = g_utf8_get_char(p); if (c == '\0') { break; } else { /* extension; copy it */ uint8_t v = to_valid_short_char(c); if (j < 3 && v) { entry->name[8 + (j++)] = v; } else { lossy_conversion = true; } } } } if (entry->name[0] == DIR_KANJI) { entry->name[0] = DIR_KANJI_FAKE; } /* numeric-tail generation */ for (j = 0; j < 8; j++) { if (entry->name[j] == ' ') { break; } } for (i = lossy_conversion ? 1 : 0; i < 999999; i++) { direntry_t *entry1; if (i > 0) { int len = sprintf(tail, "~%d", i); memcpy(entry->name + MIN(j, 8 - len), tail, len); } for (entry1 = array_get(&(s->directory), directory_start); entry1 < entry; entry1++) { if (!is_long_name(entry1) && !memcmp(entry1->name, entry->name, 11)) { break; /* found dupe */ } } if (entry1 == entry) { /* no dupe found */ return entry; } } return NULL; }