Skip to content

Commit 3ef4bb1

Browse files
chrfrankegithub-cygwin
authored andcommitted
Cygwin: /dev/disk: Append '#N' if the same name appears more than once
No longer drop ranges of identical link names. Append '#0, #1, ...' to each name instead. Enhance charset allowed in label names. No longer ignore null volume serial numbers. Signed-off-by: Christian Franke <[email protected]>
1 parent 3cacedb commit 3ef4bb1

File tree

1 file changed

+33
-21
lines changed

1 file changed

+33
-21
lines changed

winsup/cygwin/fhandler/dev_disk.cc

Lines changed: 33 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -64,10 +64,11 @@ sanitize_label_string (WCHAR *s)
6464
/* Linux does not skip leading spaces. */
6565
return sanitize_string (s, L'\0', L' ', L'_', [] (WCHAR c) -> bool
6666
{
67-
/* Labels may contain characters not allowed in filenames.
68-
Linux replaces spaces with \x20 which is not an option here. */
69-
return !((0 <= c && c <= L' ') || c == L':' || c == L'/' || c == L'\\'
70-
|| c == L'"');
67+
/* Labels may contain characters not allowed in filenames. Also
68+
replace '#' to avoid that duplicate markers introduce new
69+
duplicates. Linux replaces spaces with \x20 which is not an
70+
option here. */
71+
return !(c == L'/' || c == L'\\' || c == L'#');
7172
}
7273
);
7374
}
@@ -304,8 +305,7 @@ partition_to_label_or_uuid(bool uuid, const UNICODE_STRING *drive_uname,
304305
const NTFS_VOLUME_DATA_BUFFER *nvdb =
305306
reinterpret_cast<const NTFS_VOLUME_DATA_BUFFER *>(ioctl_buf);
306307
if (uuid && DeviceIoControl (volhdl, FSCTL_GET_NTFS_VOLUME_DATA, nullptr, 0,
307-
ioctl_buf, NT_MAX_PATH, &bytes_read, nullptr)
308-
&& nvdb->VolumeSerialNumber.QuadPart)
308+
ioctl_buf, NT_MAX_PATH, &bytes_read, nullptr))
309309
{
310310
/* Print without any separator as on Linux. */
311311
__small_sprintf (name, "%016X", nvdb->VolumeSerialNumber.QuadPart);
@@ -327,13 +327,9 @@ partition_to_label_or_uuid(bool uuid, const UNICODE_STRING *drive_uname,
327327
FILE_FS_VOLUME_INFORMATION *ffvi =
328328
reinterpret_cast<FILE_FS_VOLUME_INFORMATION *>(ioctl_buf);
329329
if (uuid)
330-
{
331-
if (!ffvi->VolumeSerialNumber)
332-
return false;
333-
/* Print with separator as on Linux. */
334-
__small_sprintf (name, "%04x-%04x", ffvi->VolumeSerialNumber >> 16,
335-
ffvi->VolumeSerialNumber & 0xffff);
336-
}
330+
/* Print with separator as on Linux. */
331+
__small_sprintf (name, "%04x-%04x", ffvi->VolumeSerialNumber >> 16,
332+
ffvi->VolumeSerialNumber & 0xffff);
337333
else
338334
{
339335
/* Label is not null terminated. */
@@ -361,6 +357,20 @@ by_id_compare_name (const void *a, const void *b)
361357
return strcmp (ap->name, bp->name);
362358
}
363359

360+
static int
361+
by_id_compare_name_drive_part (const void *a, const void *b)
362+
{
363+
const by_id_entry *ap = reinterpret_cast<const by_id_entry *>(a);
364+
const by_id_entry *bp = reinterpret_cast<const by_id_entry *>(b);
365+
int cmp = strcmp (ap->name, bp->name);
366+
if (cmp)
367+
return cmp;
368+
cmp = ap->drive - bp->drive;
369+
if (cmp)
370+
return cmp;
371+
return ap->part - bp->part;
372+
}
373+
364374
static by_id_entry *
365375
by_id_realloc (by_id_entry *p, size_t n)
366376
{
@@ -610,21 +620,23 @@ get_by_id_table (by_id_entry * &table, fhandler_dev_disk::dev_disk_location loc)
610620
if (!table)
611621
return (errno_set ? -1 : 0);
612622

613-
/* Sort by name and remove duplicates. */
614-
qsort (table, table_size, sizeof (*table), by_id_compare_name);
623+
/* Sort by {name, drive, part} to ensure stable sort order. */
624+
qsort (table, table_size, sizeof (*table), by_id_compare_name_drive_part);
625+
/* Mark duplicate names. */
615626
for (unsigned i = 0; i < table_size; i++)
616627
{
617628
unsigned j = i + 1;
618629
while (j < table_size && !strcmp (table[i].name, table[j].name))
619630
j++;
620631
if (j == i + 1)
621632
continue;
622-
/* Duplicate(s) found, remove all entries with this name. */
623-
debug_printf ("removing duplicates %d-%d: '%s'", i, j - 1, table[i].name);
624-
if (j < table_size)
625-
memmove (table + i, table + j, (table_size - j) * sizeof (*table));
626-
table_size -= j - i;
627-
i--;
633+
/* Duplicate(s) found, append "#N" to all entries. This never
634+
introduces new duplicates because '#' never occurs in the
635+
original names. */
636+
debug_printf ("mark duplicates %u-%u of '%s'", i, j - 1, table[i].name);
637+
size_t len = strlen (table[i].name);
638+
for (unsigned k = i; k < j; k++)
639+
__small_sprintf (table[k].name + len, "#%u", k - i);
628640
}
629641

630642
debug_printf ("table_size: %d", table_size);

0 commit comments

Comments
 (0)