From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 2155) id A8E743858C66; Fri, 17 Nov 2023 12:11:01 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org A8E743858C66 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1700223061; bh=znZgqI+BXd5i+/3eDXNstZ/7pLdQoEcY+xJaUWQaH9c=; h=From:To:Subject:Date:From; b=dW5KjTIEWJ+Dx7UmVvnSj3WIJQpzPG5Pr8SeTN08ie97It2NYS/07Ua/nRSJfmqHo GlVeYvHHe6luOWXQWatwMCcqZvfD1p0JJvpYm66scv2EN17AxNuoHsyUq5+mE5U1xF b2DNBQ4XH8/+2HPZcejbWvSaaw/ubNwotBygUj5g= Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable From: Corinna Vinschen To: cygwin-cvs@sourceware.org Subject: [newlib-cygwin/main] Cygwin: Add /dev/disk/by-drive and /dev/disk/by-voluuid symlinks X-Act-Checkin: newlib-cygwin X-Git-Author: Christian Franke X-Git-Refname: refs/heads/main X-Git-Oldrev: 324ace778f70e3e89d16c5460d2f9b4454acddb2 X-Git-Newrev: 2cc109be1d332a0e8e488f35b8b1e112f3b7b284 Message-Id: <20231117121101.A8E743858C66@sourceware.org> Date: Fri, 17 Nov 2023 12:11:01 +0000 (GMT) List-Id: https://sourceware.org/git/gitweb.cgi?p=3Dnewlib-cygwin.git;h=3D2cc109be1d3= 32a0e8e488f35b8b1e112f3b7b284 commit 2cc109be1d332a0e8e488f35b8b1e112f3b7b284 Author: Christian Franke AuthorDate: Thu Nov 16 17:51:08 2023 +0100 Commit: Corinna Vinschen CommitDate: Fri Nov 17 13:10:20 2023 +0100 Cygwin: Add /dev/disk/by-drive and /dev/disk/by-voluuid symlinks =20 The new directory '/dev/disk/by-drive' provides symlinks for each disk related drive letter: 'x' -> '../../sdXN' The new directory '/dev/disk/by-voluuid' provides symlinks for each disk related storage volume: 'MBR_SERIAL-OFFSET' -> '../../sdXN' 'VOLUME_GUID' -> '../../sdXN' Both directories provide Windows specific information and do not exist on Linux. =20 Signed-off-by: Christian Franke Diff: --- winsup/cygwin/fhandler/dev_disk.cc | 143 +++++++++++++++++++++++++++-= ---- winsup/cygwin/local_includes/fhandler.h | 3 +- 2 files changed, 126 insertions(+), 20 deletions(-) diff --git a/winsup/cygwin/fhandler/dev_disk.cc b/winsup/cygwin/fhandler/de= v_disk.cc index 11b24042f54a..5f79ab5e9f59 100644 --- a/winsup/cygwin/fhandler/dev_disk.cc +++ b/winsup/cygwin/fhandler/dev_disk.cc @@ -158,6 +158,92 @@ storprop_to_id_name (HANDLE devhdl, const UNICODE_STRI= NG *upath, return 1; } =20 +/* ("HarddiskN", PART_NUM) -> "\\\\?\\Volume{GUID}\\" */ +static bool +partition_to_volpath (const UNICODE_STRING *drive_uname, DWORD part_num, + WCHAR (& volpath)[MAX_PATH]) +{ + WCHAR gpath[MAX_PATH]; + __small_swprintf (gpath, L"\\\\?\\GLOBALROOT\\Device\\%S\\Partition%u\\", + drive_uname, part_num); + if (!GetVolumeNameForVolumeMountPointW (gpath, volpath, sizeof(volpath))) + { + debug_printf ("GetVolumeNameForVolumeMountPointW(%W): %E", gpath); + return false; + } + debug_printf ("%W -> %W", gpath, volpath); + return true; +} + +/* ("HarddiskN", PART_NUM) -> "x" */ +static bool +partition_to_drive(const UNICODE_STRING *drive_uname, DWORD part_num, + WCHAR *w_buf, char *name) +{ + WCHAR volpath[MAX_PATH]; + if (!partition_to_volpath (drive_uname, part_num, volpath)) + return false; + + DWORD len; + if (!GetVolumePathNamesForVolumeNameW (volpath, w_buf, NT_MAX_PATH, &len= )) + { + debug_printf ("GetVolumePathNamesForVolumeNameW(%W): %E", volpath); + return false; + } + debug_printf ("%W -> '%W'%s", volpath, w_buf, + (w_buf[0] && wcschr (w_buf, L'\0')[1] ? ", ..." : "")); + + /* Find first "X:\\", skip if not found. + FIXME: Support multiple drive letters. */ + WCHAR *p; + for (p =3D w_buf; ; p =3D wcschr (p, L'\0') + 1) + { + if (!*p) + return false; + if (L'A' <=3D p[0] && p[0] <=3D L'Z' && p[1] =3D=3D L':' && p[2] =3D=3D L= '\\' && !p[3]) + break; + } + name[0] =3D (p[0] - L'A') + 'a'; + name[1] =3D '\0'; + return true; +} + +/* ("HarddiskN", PART_NUM) -> "VOLUME_GUID" */ +static bool +partition_to_voluuid(const UNICODE_STRING *drive_uname, DWORD part_num, + char *name) +{ + WCHAR volpath[MAX_PATH]; + if (!partition_to_volpath (drive_uname, part_num, volpath)) + return false; + + /* Skip if not "\\\\?\\Volume{GUID}...". */ + static const WCHAR prefix[] =3D L"\\\\?\\Volume{"; + const size_t prefix_len =3D sizeof (prefix) / sizeof(WCHAR) - 1, uuid_le= n =3D 36; + if (!(!wcsncmp (volpath, prefix, prefix_len) + && volpath[prefix_len + uuid_len] =3D=3D L'}')) + return false; + + /* Extract GUID. */ + volpath[prefix_len + uuid_len] =3D 0; + __small_sprintf (name, "%W", volpath + prefix_len); + + if (!strncmp (name + 9, "0000-0000-00", 12) && !strcmp (name + 32, "0000= ")) + { + /* MBR "GUID": Use same SERIAL-OFFSET format as in by-partuuid direc= tory. + SERIAL-0000-0000-009a-785634120000 -> SERIAL-123456789a00 */ + for (int i =3D 9, j =3D 30; i < 19; i +=3D 2, j -=3D 2) + { + if (j =3D=3D 22) // name[j + 1] =3D=3D '-' + j--; + name[i] =3D name[j]; + name[i + 1] =3D name[j + 1]; + } + name[21] =3D '\0'; + } + return true; +} + struct by_id_entry { char name[NAME_MAX + 1]; @@ -208,6 +294,7 @@ format_partuuid (char *name, const PARTITION_INFORMATIO= N_EX *pix) guid->Data1, guid->Data2, guid->Data3, guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3], guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7]); + return true; } =20 @@ -237,6 +324,7 @@ get_by_id_table (by_id_entry * &table, fhandler_dev_dis= k::dev_disk_location loc) unsigned alloc_size =3D 0, table_size =3D 0; tmp_pathbuf tp; char *ioctl_buf =3D tp.c_get (); + WCHAR *w_buf =3D tp.w_get (); DIRECTORY_BASIC_INFORMATION *dbi_buf =3D reinterpret_cast(tp.w_get ()); =20 @@ -365,6 +453,11 @@ get_by_id_table (by_id_entry * &table, fhandler_dev_di= sk::dev_disk_location loc) char *name =3D table[table_size].name; switch (loc) { + case fhandler_dev_disk::disk_by_drive: + if (!partition_to_drive (&dbi->ObjectName, part_num, w_buf, name)) + continue; + break; + case fhandler_dev_disk::disk_by_id: __small_sprintf (name, "%s-part%u", drive_name, part_num); break; @@ -374,6 +467,11 @@ get_by_id_table (by_id_entry * &table, fhandler_dev_di= sk::dev_disk_location loc) continue; break; =20 + case fhandler_dev_disk::disk_by_voluuid: + if (!partition_to_voluuid (&dbi->ObjectName, part_num, name)) + continue; + break; + default: continue; /* Should not happen. */ } table[table_size].drive =3D drive_num; @@ -417,10 +515,17 @@ get_by_id_table (by_id_entry * &table, fhandler_dev_d= isk::dev_disk_location loc) =20 const char dev_disk[] =3D "/dev/disk"; const size_t dev_disk_len =3D sizeof (dev_disk) - 1; -static const char by_id[] =3D "/by-id"; -const size_t by_id_len =3D sizeof(by_id) - 1; -static const char by_partuuid[] =3D "/by-partuuid"; -const size_t by_partuuid_len =3D sizeof(by_partuuid) - 1; +static const char by_drive[] =3D "/by-drive"; +const size_t by_drive_len =3D sizeof(by_drive) - 1; + +/* Keep this in sync with enum fhandler_dev_disk::dev_disk_location starti= ng + at disk_by_drive. */ +static const char * const by_dir_names[] { + "/by-drive", "/by-id", "/by-partuuid", "/by-voluuid" +}; +const size_t by_dir_names_size =3D sizeof(by_dir_names) / sizeof(by_dir_na= mes[0]); +static_assert((size_t) fhandler_dev_disk::disk_by_drive + by_dir_names_siz= e - 1 + =3D=3D (size_t) fhandler_dev_disk::disk_by_voluuid); =20 fhandler_dev_disk::fhandler_dev_disk (): fhandler_virtual (), @@ -440,22 +545,23 @@ fhandler_dev_disk::init_dev_disk () /* Determine location. */ const char *path =3D get_name (); size_t dirlen =3D 0; + loc =3D invalid_loc; // "/dev/disk/invalid" if (!path_prefix_p (dev_disk, path, dev_disk_len, false)) - loc =3D invalid_loc; // should not happen + ; // should not happen else if (!path[dev_disk_len]) loc =3D disk_dir; // "/dev/disk" - else if (path_prefix_p (by_id, path + dev_disk_len, by_id_len, false)) - { - loc =3D disk_by_id; // "/dev/disk/by-id.." - dirlen =3D dev_disk_len + by_id_len; - } - else if (path_prefix_p (by_partuuid, path + dev_disk_len, by_partuuid_le= n, false)) - { - loc =3D disk_by_partuuid; // "/dev/disk/by-partuuid..." - dirlen =3D dev_disk_len + by_partuuid_len; - } else - loc =3D invalid_loc; // "/dev/disk/invalid" + for (size_t i =3D 0; i < by_dir_names_size; i++) + { + const char *dir =3D by_dir_names[i]; + size_t len =3D strlen(dir); + if (path_prefix_p (dir, path + dev_disk_len, len, false)) + { + loc =3D (dev_disk_location) (disk_by_drive + i); // "/dev/disk/by-..." + dirlen =3D dev_disk_len + len; + break; + } + } =20 loc_is_link =3D false; if (dirlen) @@ -594,10 +700,9 @@ fhandler_dev_disk::readdir (DIR *dir, dirent *de) dir->__d_position++; res =3D 0; } - else if (loc =3D=3D disk_dir && dir->__d_position < 2 + 2) + else if (loc =3D=3D disk_dir && dir->__d_position < 2 + (int) by_dir_nam= es_size) { - static const char * const names[2] {by_id, by_partuuid}; - strcpy (de->d_name, names[dir->__d_position - 2] + 1); + strcpy (de->d_name, by_dir_names[dir->__d_position - 2] + 1); de->d_type =3D DT_DIR; dir->__d_position++; res =3D 0; diff --git a/winsup/cygwin/local_includes/fhandler.h b/winsup/cygwin/local_= includes/fhandler.h index 6013496d5d37..86c7b20a261c 100644 --- a/winsup/cygwin/local_includes/fhandler.h +++ b/winsup/cygwin/local_includes/fhandler.h @@ -3197,7 +3197,8 @@ class fhandler_dev_disk: public fhandler_virtual public: enum dev_disk_location { unknown_loc, invalid_loc, disk_dir, - disk_by_id, disk_by_partuuid + /* Keep these in sync with dev_disk.cc:by_dir_names array: */ + disk_by_drive, disk_by_id, disk_by_partuuid, disk_by_voluuid }; =20 private: