diff options
author | Corinna Vinschen <corinna@vinschen.de> | 2024-12-10 22:26:50 +0100 |
---|---|---|
committer | Corinna Vinschen <corinna@vinschen.de> | 2024-12-11 00:24:44 +0100 |
commit | a0527e37869e8e3e467bbd106d6c77612df617c7 (patch) | |
tree | aa1220ac069ed1f3ac93d7b529a8e59ecb567d50 | |
parent | a0933cd17d19cca72b972a248e70210152f06808 (diff) | |
download | newlib-a0527e37869e8e3e467bbd106d6c77612df617c7.zip newlib-a0527e37869e8e3e467bbd106d6c77612df617c7.tar.gz newlib-a0527e37869e8e3e467bbd106d6c77612df617c7.tar.bz2 |
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>
-rw-r--r-- | winsup/cygwin/release/3.6.0 | 3 | ||||
-rw-r--r-- | winsup/doc/utils.xml | 35 | ||||
-rw-r--r-- | 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 8ca91f0..66f7e73 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 fbb39f5..6a55b3a 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 10c31f8..4ac1bef 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\ @@ -460,6 +465,29 @@ get_long_name (const char *filename, DWORD& len) } 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) { char *sbuf; @@ -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; |