From 1e212814cfb17579105ead4835410bd74dfb188a Mon Sep 17 00:00:00 2001 From: Christian Franke Date: Fri, 17 Nov 2023 21:20:26 +0100 Subject: [PATCH] Cygwin: /dev/disk: Mark duplicates, fix serial number format Keep ranges of duplicate names and append '#N' to each name. Add missing leading zeros to output format of NTFS serial number. No longer ignore null volume serial numbers. Signed-off-by: Christian Franke --- winsup/cygwin/fhandler/dev_disk.cc | 38 ++++++++++++++---------------- 1 file changed, 18 insertions(+), 20 deletions(-) diff --git a/winsup/cygwin/fhandler/dev_disk.cc b/winsup/cygwin/fhandler/dev_disk.cc index 016b4c7bc..131ffd935 100644 --- a/winsup/cygwin/fhandler/dev_disk.cc +++ b/winsup/cygwin/fhandler/dev_disk.cc @@ -64,10 +64,12 @@ sanitize_label_string (WCHAR *s) /* Linux does not skip leading spaces. */ return sanitize_string (s, L'\0', L' ', L'_', [] (WCHAR c) -> bool { - /* Labels may contain characters not allowed in filenames. - Linux replaces spaces with \x20 which is not an option here. */ + /* Labels may contain characters not allowed in filenames. Also + replace '#' to avoid that duplicate markers introduce new + duplicates. Linux replaces spaces with \x20 which is not an + option here. */ return !((0 <= c && c <= L' ') || c == L':' || c == L'/' || c == L'\\' - || c == L'"'); + || c == L'#' || c == L'"'); } ); } @@ -304,11 +306,10 @@ partition_to_label_or_uuid(bool uuid, const UNICODE_STRING *drive_uname, const NTFS_VOLUME_DATA_BUFFER *nvdb = reinterpret_cast(ioctl_buf); if (uuid && DeviceIoControl (volhdl, FSCTL_GET_NTFS_VOLUME_DATA, nullptr, 0, - ioctl_buf, NT_MAX_PATH, &bytes_read, nullptr) - && nvdb->VolumeSerialNumber.QuadPart) + ioctl_buf, NT_MAX_PATH, &bytes_read, nullptr)) { /* Print without any separator as on Linux. */ - __small_sprintf (name, "%16X", nvdb->VolumeSerialNumber.QuadPart); + __small_sprintf (name, "%016X", nvdb->VolumeSerialNumber.QuadPart); NtClose(volhdl); return true; } @@ -327,13 +328,9 @@ partition_to_label_or_uuid(bool uuid, const UNICODE_STRING *drive_uname, FILE_FS_VOLUME_INFORMATION *ffvi = reinterpret_cast(ioctl_buf); if (uuid) - { - if (!ffvi->VolumeSerialNumber) - return false; - /* Print with separator as on Linux. */ - __small_sprintf (name, "%04x-%04x", ffvi->VolumeSerialNumber >> 16, - ffvi->VolumeSerialNumber & 0xffff); - } + /* Print with separator as on Linux. */ + __small_sprintf (name, "%04x-%04x", ffvi->VolumeSerialNumber >> 16, + ffvi->VolumeSerialNumber & 0xffff); else { /* Label is not null terminated. */ @@ -610,7 +607,7 @@ get_by_id_table (by_id_entry * &table, fhandler_dev_disk::dev_disk_location loc) if (!table) return (errno_set ? -1 : 0); - /* Sort by name and remove duplicates. */ + /* Sort by name and mark duplicates. */ qsort (table, table_size, sizeof (*table), by_id_compare_name); for (unsigned i = 0; i < table_size; i++) { @@ -619,12 +616,13 @@ get_by_id_table (by_id_entry * &table, fhandler_dev_disk::dev_disk_location loc) j++; if (j == i + 1) continue; - /* Duplicate(s) found, remove all entries with this name. */ - debug_printf ("removing duplicates %d-%d: '%s'", i, j - 1, table[i].name); - if (j < table_size) - memmove (table + i, table + j, (table_size - j) * sizeof (*table)); - table_size -= j - i; - i--; + /* Duplicate(s) found, append "#N" to all entries. This never + introduces new duplicates because '#' never occurs in the + original names. */ + debug_printf ("mark duplicates %u-%u of '%s'", i, j - 1, table[i].name); + size_t len = strlen (table[i].name); + for (unsigned k = i; k < j; k++) + __small_sprintf (table[k].name + len, "#%u", k - i); } debug_printf ("table_size: %d", table_size); -- 2.42.1