[newlib-cygwin/main] Cygwin: utils: cygpath: add -r option to emit paths with root-local prefix
Corinna Vinschen
corinna@sourceware.org
Tue Dec 10 23:25:27 GMT 2024
https://sourceware.org/git/gitweb.cgi?p=newlib-cygwin.git;h=a0527e37869e8e3e467bbd106d6c77612df617c7
commit a0527e37869e8e3e467bbd106d6c77612df617c7
Author: Corinna Vinschen <corinna@vinschen.de>
AuthorDate: Tue Dec 10 22:26:50 2024 +0100
Commit: Corinna Vinschen <corinna@vinschen.de>
CommitDate: Wed Dec 11 00:24:44 2024 +0100
Cygwin: utils: cygpath: add -r option to emit paths with root-local prefix
cygpath automatically adds the root-local prefix \\?\ automatically
for paths exceeding 260 bytes. However, it does not add the root-local
prefix if the path contains path components invalid in DOS paths, for
instance path components with trailing dots or spaces.
Add the -r option to always add the root-local prefix to the path.
Add the option to the documentation and improve the help text.
Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
Diff:
---
winsup/cygwin/release/3.6.0 | 3 +++
winsup/doc/utils.xml | 35 ++++++++++++++++++++------
winsup/utils/cygpath.cc | 60 ++++++++++++++++++++++++++++++++++++++-------
3 files changed, 82 insertions(+), 16 deletions(-)
diff --git a/winsup/cygwin/release/3.6.0 b/winsup/cygwin/release/3.6.0
index 8ca91f0c99c1..66f7e73deb8c 100644
--- a/winsup/cygwin/release/3.6.0
+++ b/winsup/cygwin/release/3.6.0
@@ -16,6 +16,9 @@ What's new:
- New libaio.a provided for projects checking for POSIX aio support
by looking for this library at configure time.
+- cygpath -r option allows to generate all Windows paths with root-local
+ path prefix \\?\.
+
What changed:
-------------
diff --git a/winsup/doc/utils.xml b/winsup/doc/utils.xml
index fbb39f5f2791..6a55b3a0e790 100644
--- a/winsup/doc/utils.xml
+++ b/winsup/doc/utils.xml
@@ -528,11 +528,15 @@ Output type options:
Path conversion options:
-a, --absolute output absolute path
- -l, --long-name print Windows long form of NAMEs (with -w, -m only)
+ -l, --long-name print Windows long form of NAMEs (with -w, -m only,
+ don't mix with -r and -s)
+ -r, --root-local print Windows path with root-local path prefix (\\?\,
+ with -w only)
-p, --path NAME is a PATH list (i.e., '/bin:/usr/bin')
-U, --proc-cygdrive Emit /proc/cygdrive path instead of cygdrive prefix
when converting Windows path to UNIX path.
- -s, --short-name print DOS (short) form of NAMEs (with -w, -m only)
+ -s, --short-name print DOS (short) form of NAMEs (with -w, -m only,
+ don't mix with -l and -r)
-C, --codepage CP print DOS, Windows, or mixed pathname in Windows
codepage CP. CP can be a numeric codepage identifier,
or one of the reserved words ANSI, OEM, or UTF8.
@@ -574,15 +578,32 @@ Other options:
<para>The <literal>-u</literal> and <literal>-w</literal> options indicate
whether you want a conversion to UNIX (POSIX) format
(<literal>-u</literal>) or to Windows format (<literal>-w</literal>). Use
- the <literal>-d</literal> to get DOS-style (8.3) file and path names. The
+ the <literal>-d</literal> to get DOS-style 8.3 file and path names. The
<literal>-m</literal> option will output Windows-style format but with
forward slashes instead of backslashes. This option is especially useful
in shell scripts, which use backslashes as an escape character.</para>
- <para> In combination with the <literal>-w</literal> option, you can use
- the <literal>-l</literal> and <literal>-s</literal> options to use normal
- (long) or DOS-style (short) form. The <literal>-d</literal> option is
- identical to <literal>-w</literal> and <literal>-s</literal> together. </para>
+ <para>In combination with the <literal>-w</literal> and
+ <literal>-m</literal> options, you can use the <literal>-l</literal> and
+ <literal>-s</literal> options to use normal (long) or DOS-style 8.3
+ (short) form. The <literal>-d</literal> option is identical to
+ <literal>-w</literal> and <literal>-s</literal> together.</para>
+
+ <para>Note that short DOS-style 8.3 names are not always available.
+ The generation of additional 8.3 filenames is the responsibility of
+ the underlying filesystem. Modern Windows OS allows to switch off
+ 8.3 filename generation and some filesystems never generate 8.3 names.
+ In these cases, using the <literal>-s</literal> option may fail or
+ may be ignored.</para>
+
+ <para>In combination with the <literal>-w</literal> option, you can use
+ the <literal>-r</literal> option to generate root-local paths with
+ leading \\?\ prefix. This is especially useful if your path contains
+ path components invalid in DOS paths, for instance file or directory
+ names with trailing dot.</para>
+
+ <para>Note that the root-local path prefix is automatically prepended for
+ paths exceeding a length of MAX_PATH (260) bytes.</para>
<para>The <literal>-C</literal> option allows to specify a Windows codepage
to print DOS and Windows paths created with one of the
diff --git a/winsup/utils/cygpath.cc b/winsup/utils/cygpath.cc
index 10c31f8962a0..4ac1bef94cbf 100644
--- a/winsup/utils/cygpath.cc
+++ b/winsup/utils/cygpath.cc
@@ -33,7 +33,7 @@ details. */
static char *prog_name;
static char *file_arg, *output_arg;
static int path_flag, unix_flag, windows_flag, absolute_flag, cygdrive_flag;
-static int shortname_flag, longname_flag;
+static int shortname_flag, longname_flag, rootlocal_flag;
static int ignore_flag, allusers_flag, output_flag;
static int mixed_flag, options_from_file_flag, mode_flag;
static UINT codepage;
@@ -55,6 +55,7 @@ static struct option long_options[] = {
{(char *) "proc-cygdrive", no_argument, NULL, 'U'},
{(char *) "short-name", no_argument, NULL, 's'},
{(char *) "type", required_argument, NULL, 't'},
+ {(char *) "root-local", no_argument, NULL, 'L'},
{(char *) "unix", no_argument, NULL, 'u'},
{(char *) "version", no_argument, NULL, 'V'},
{(char *) "windows", no_argument, NULL, 'w'},
@@ -70,7 +71,7 @@ static struct option long_options[] = {
{0, no_argument, 0, 0}
};
-static char options[] = "ac:df:hilmMopst:uUVwAC:DHOPSWF:";
+static char options[] = "ac:df:hilmMoprst:uUVwAC:DHOPSWF:";
static void __attribute__ ((__noreturn__))
usage (FILE * stream, int status)
@@ -96,11 +97,15 @@ Output type options:\n\
Path conversion options:\n\
\n\
-a, --absolute output absolute path\n\
- -l, --long-name print Windows long form of NAMEs (with -w, -m only)\n\
+ -l, --long-name print Windows long form of NAMEs (with -w, -m only,\n\
+ don't mix with -r and -s)\n\
+ -r, --root-local print Windows path with root-local path prefix (\\\\?\\,\n\
+ with -w only, don't mix with -l and -s)\n\
-p, --path NAME is a PATH list (i.e., '/bin:/usr/bin')\n\
-U, --proc-cygdrive Emit /proc/cygdrive path instead of cygdrive prefix\n\
when converting Windows path to UNIX path.\n\
- -s, --short-name print DOS (short) form of NAMEs (with -w, -m only)\n\
+ -s, --short-name print DOS (short) form of NAMEs (with -w, -m only,\n\
+ don't mix with -l and -r)\n\
-C, --codepage CP print DOS, Windows, or mixed pathname in Windows\n\
codepage CP. CP can be a numeric codepage identifier,\n\
or one of the reserved words ANSI, OEM, or UTF8.\n\
@@ -459,6 +464,29 @@ get_long_name (const char *filename, DWORD& len)
return sbuf;
}
+static char *
+get_rootlocal_name (const char *filename, DWORD& len)
+{
+ if (!strncmp (filename, "\\\\?\\", 4))
+ return strdup (filename);
+
+ char *buf = (char *) malloc (strlen (filename) + 7);
+ if (!buf)
+ {
+ fprintf (stderr, "%s: out of memory\n", prog_name);
+ exit (1);
+ }
+
+ char *p = stpcpy (buf, "\\\\?\\");
+ if (!strncmp (filename, "\\\\", 2))
+ {
+ p = stpcpy (p, "UNC");
+ ++filename;
+ }
+ stpcpy (p, filename);
+ return buf;
+}
+
static char *
get_long_paths (char *path)
{
@@ -757,8 +785,13 @@ do_pathconv (char *filename)
buf = get_long_name (tmp = buf, len);
free (tmp);
}
+ if (rootlocal_flag)
+ {
+ buf = get_rootlocal_name (tmp = buf, len);
+ free (tmp);
+ }
tmp = buf;
- if (strncmp (buf, "\\\\?\\", 4) == 0)
+ if (!rootlocal_flag && strncmp (buf, "\\\\?\\", 4) == 0)
{
len = 0;
if (buf[5] == ':')
@@ -808,6 +841,7 @@ do_options (int argc, char **argv, int from_file)
windows_flag = 0;
shortname_flag = 0;
longname_flag = 0;
+ rootlocal_flag = 0;
mixed_flag = 0;
ignore_flag = 0;
allusers_flag = 0;
@@ -880,6 +914,10 @@ do_options (int argc, char **argv, int from_file)
shortname_flag = 1;
break;
+ case 'r':
+ rootlocal_flag = 1;
+ break;
+
case 't':
if (!optarg)
usage (stderr, 1);
@@ -980,12 +1018,16 @@ do_options (int argc, char **argv, int from_file)
if (!from_file && options_from_file_flag && !file_arg)
usage (stderr, 1);
- /* longname and shortname don't play well together. */
- if (longname_flag && shortname_flag)
+ /* longname, shortname and root-local don't play well together. */
+ if (longname_flag + shortname_flag + rootlocal_flag > 1)
+ usage (stderr, 1);
+
+ /* longname, shortname and root-local only make sense with Windows paths. */
+ if ((longname_flag || shortname_flag || rootlocal_flag) && !windows_flag)
usage (stderr, 1);
- /* longname and shortname only make sense with Windows paths. */
- if ((longname_flag || shortname_flag) && !windows_flag)
+ /* root-local with mixed mode doesn't make sense. */
+ if (rootlocal_flag && mixed_flag)
usage (stderr, 1);
return o;
More information about the Cygwin-cvs
mailing list