1
0
mirror of https://git.savannah.gnu.org/git/coreutils.git synced 2026-10-24 02:08:57 +03:00

realpath: quote problematic names on tty

* doc/coreutils.texi: Mention $QUOTING_STYLE is significant.
* src/realpath.c (print_relative_path): New function to buffer
relative paths when quoting, and otherwise stream them.
(main): Look up $QUOTING_STYLE when outputting to a tty and
--zero is not specified.
* tests/misc/realpath.sh: Add a test case.
* NEWS: Mention the improvement.
This commit is contained in:
Pádraig Brady
2026-07-30 16:12:20 +01:00
parent b9ed8168ac
commit 05ab72f236
4 changed files with 69 additions and 2 deletions

4
NEWS
View File

@@ -84,6 +84,10 @@ GNU coreutils NEWS -*- outline -*-
'install -C' will now avoid updating file metadata when the destination
already has the appropriate ownership and permissions.
'realpath' now quotes output in shell-escape style when
standard output is a terminal. The QUOTING_STYLE environment variable
can be used to adjust or disable the quoting.
'ls -m' now quotes files names containing commas when appropriate,
so users can better distinguish separating commas.

View File

@@ -14596,6 +14596,11 @@ only on the file name, and does not touch any actual file.
@end table
When standard output is a terminal, file names are quoted using
the @samp{shell-escape} style. The environment variable
@env{QUOTING_STYLE} can select the quoting style. Valid quoting styles are:
@quotingStyles
@cindex exit status of @command{realpath}
Exit status:

View File

@@ -21,6 +21,7 @@
#include <stdio.h>
#include <sys/types.h>
#include "argmatch.h" /* argmatch($QUOTING_STYLE). */
#include "system.h"
#include "canonicalize.h"
#include "relpath.h"
@@ -39,6 +40,7 @@ enum
static bool verbose = true;
static bool logical;
static bool use_nuls;
static bool quote_output;
static char const *can_relative_to;
static char const *can_relative_base;
@@ -164,6 +166,34 @@ isdir (char const *path)
return S_ISDIR (sb.st_mode);
}
static void
print_path (char const *path)
{
fputs (quote_output ? quoteN (path) : path, stdout);
}
/* Print CAN_FNAME relative to can_relative_to, quoting the complete
relative file name when appropriate. */
static bool
print_relative_path (char const *can_fname)
{
if (!quote_output)
return relpath (can_fname, can_relative_to, NULL, 0);
size_t size;
if (ckd_mul (&size, strlen (can_relative_to), 2)
|| ckd_add (&size, size, strlen (can_fname))
|| ckd_add (&size, size, 1))
xalloc_die ();
char *relative_path = xmalloc (size);
bool success = relpath (can_fname, can_relative_to, relative_path, size);
if (success)
print_path (relative_path);
free (relative_path);
return success;
}
static bool
process_path (char const *fname, int can_mode)
{
@@ -177,8 +207,8 @@ process_path (char const *fname, int can_mode)
if (!can_relative_to
|| (can_relative_base && !path_prefix (can_relative_base, can_fname))
|| (can_relative_to && !relpath (can_fname, can_relative_to, NULL, 0)))
fputs (can_fname, stdout);
|| (can_relative_to && !print_relative_path (can_fname)))
print_path (can_fname);
putchar (use_nuls ? '\0' : '\n');
@@ -262,6 +292,18 @@ main (int argc, char **argv)
usage (EXIT_FAILURE);
}
if (! use_nuls && isatty (STDOUT_FILENO))
{
int qs = getenv_quoting_style ();
if (qs < 0)
qs = shell_escape_quoting_style;
if (qs != literal_quoting_style)
{
set_quoting_style (NULL, qs);
quote_output = true;
}
}
if (relative_base && !relative_to)
relative_to = relative_base;

View File

@@ -57,6 +57,22 @@ realpath -e -E --relative-to=dir1/f --relative-base=. . || fail=1
returns_ 1 realpath -m '' || fail=1
returns_ 1 realpath --relative-base= --relative-to=. . || fail=1
# QUOTING_STYLE does not affect redirected output.
printf 'q name\n' > exp || framework_failure_
for style in literal shell-always invalid; do
QUOTING_STYLE="$style" \
realpath -m --relative-to=. 'q name' > out 2> err || fail=1
compare exp out || fail=1
compare /dev/null err || fail=1
done
# --zero disables quoting, and does not inspect QUOTING_STYLE.
QUOTING_STYLE=invalid \
realpath -zm --relative-to=. 'q name' > out 2> err || fail=1
printf 'q name\0' > exp || framework_failure_
compare exp out || fail=1
compare /dev/null err || fail=1
# symlink resolution
this=$(realpath .)
test "$(realpath ldir2/..)" = "$this/dir1" || fail=1