| 1449 | } |
| 1450 | |
| 1451 | static int is_ntfs_dot_generic(const char *name, |
| 1452 | const char *dotgit_name, |
| 1453 | size_t len, |
| 1454 | const char *dotgit_ntfs_shortname_prefix) |
| 1455 | { |
| 1456 | int saw_tilde; |
| 1457 | size_t i; |
| 1458 | |
| 1459 | if ((name[0] == '.' && !strncasecmp(name + 1, dotgit_name, len))) { |
| 1460 | i = len + 1; |
| 1461 | only_spaces_and_periods: |
| 1462 | for (;;) { |
| 1463 | char c = name[i++]; |
| 1464 | if (!c || c == ':') |
| 1465 | return 1; |
| 1466 | if (c != ' ' && c != '.') |
| 1467 | return 0; |
| 1468 | } |
| 1469 | } |
| 1470 | |
| 1471 | /* |
| 1472 | * Is it a regular NTFS short name, i.e. shortened to 6 characters, |
| 1473 | * followed by ~1, ... ~4? |
| 1474 | */ |
| 1475 | if (!strncasecmp(name, dotgit_name, 6) && name[6] == '~' && |
| 1476 | name[7] >= '1' && name[7] <= '4') { |
| 1477 | i = 8; |
| 1478 | goto only_spaces_and_periods; |
| 1479 | } |
| 1480 | |
| 1481 | /* |
| 1482 | * Is it a fall-back NTFS short name (for details, see |
| 1483 | * https://en.wikipedia.org/wiki/8.3_filename? |
| 1484 | */ |
| 1485 | for (i = 0, saw_tilde = 0; i < 8; i++) |
| 1486 | if (name[i] == '\0') |
| 1487 | return 0; |
| 1488 | else if (saw_tilde) { |
| 1489 | if (name[i] < '0' || name[i] > '9') |
| 1490 | return 0; |
| 1491 | } else if (name[i] == '~') { |
| 1492 | if (name[++i] < '1' || name[i] > '9') |
| 1493 | return 0; |
| 1494 | saw_tilde = 1; |
| 1495 | } else if (i >= 6) |
| 1496 | return 0; |
| 1497 | else if (name[i] & 0x80) { |
| 1498 | /* |
| 1499 | * We know our needles contain only ASCII, so we clamp |
| 1500 | * here to make the results of tolower() sane. |
| 1501 | */ |
| 1502 | return 0; |
| 1503 | } else if (tolower(name[i]) != dotgit_ntfs_shortname_prefix[i]) |
| 1504 | return 0; |
| 1505 | |
| 1506 | goto only_spaces_and_periods; |
| 1507 | } |
| 1508 | |