'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.
#include <stdio.h>
#include <sys/types.h>
+#include "argmatch.h" /* argmatch($QUOTING_STYLE). */
#include "system.h"
#include "canonicalize.h"
#include "relpath.h"
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;
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)
{
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');
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;
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