]> Sergey Matveev's repositories - nnn.git/commitdiff
Document that filenames are not unquoted
authorArun Prakash Jana <engineerarun@gmail.com>
Wed, 15 Aug 2018 03:09:31 +0000 (08:39 +0530)
committerArun Prakash Jana <engineerarun@gmail.com>
Thu, 16 Aug 2018 14:43:31 +0000 (20:13 +0530)
README.md
nnn.1
nnn.c

index c7fd3e3735088058e6c24563863dce884a7ec809..4f0f72d9f3696c9d2b12b686e8b5022fa625f6cc 100644 (file)
--- a/README.md
+++ b/README.md
@@ -389,6 +389,8 @@ To wrap each file path within single quotes, export `NNN_QUOTE_ON`:
     export NNN_QUOTE_ON=1
 This is particularly useful if you are planning to copy the whole string to the shell to run a command. Quotes can be toggled at runtime using <kbd>^T</kbd>.
 
+Note that the filename is not escaped. So copying may still fail for filenames having quote(s) in them.
+
 #### copy file paths when X is missing
 
 A very common scenario on headless remote servers connected via SSH. As the clipboard is missing, `nnn` copies the path names to the tmp file `/tmp/nnncp$USER`.
diff --git a/nnn.1 b/nnn.1
index f44281f0d9c311cb7eb685dd75e72d1bbccb48a5..e420593480868500565449bf5681639011e9b5d2 100644 (file)
--- a/nnn.1
+++ b/nnn.1
@@ -263,7 +263,8 @@ screensaver.
 .Ed
 .Pp
 \fBNNN_QUOTE_ON:\fR wrap copied paths within single quotes. Useful for pasting
-names in the shell.
+names in the shell. Note that the filename is not escaped. So copying may still fail
+for filenames having quote(s) in them.
 .Pp
 \fBNNN_SCRIPT:\fR path to a custom script to invoke with currently selected file name as argument 1.
 .Bd -literal
diff --git a/nnn.c b/nnn.c
index 3e90509401b0c43fea21ab03107d4a7111912897..0e5e5ea722c7ecc23fd36287dbb2692fccb25433 100644 (file)
--- a/nnn.c
+++ b/nnn.c
@@ -1752,6 +1752,19 @@ xgetgrgid(gid_t gid)
        return grp->gr_name;
 }
 
+static bool
+istgtdir(const char *tgtpath)
+{
+       if (tgtpath) {
+               struct stat tgtsb;
+               int r = stat(tgtpath, &tgtsb);
+               if ((r == 0) && (tgtsb.st_mode & S_IFMT) == S_IFDIR)
+                       return TRUE;
+       }
+
+       return FALSE;
+}
+
 /*
  * Follows the stat(1) output closely
  */
@@ -1772,16 +1785,19 @@ show_stats(char *fpath, char *fname, struct stat *sb)
        /* Show file name or 'symlink' -> 'target' */
        if (perms[0] == 'l') {
                /* Note that MAX_CMD_LEN > PATH_MAX */
-               ssize_t len = readlink(fpath, g_buf, MAX_CMD_LEN);
-
-               if (len != -1) {
-                       g_buf[len] = '\0';
+               char *tgt = realpath(fpath, g_buf);
+               if (tgt) {
+                       char ch[] = {'\'', '\0', '\0'};
+                       if (istgtdir(g_buf)) {
+                               ch[1] = ch[0];
+                               ch[0] = '/';
+                       }
 
                        /*
                         * We pass g_buf but unescape() operates on g_buf too!
                         * Read the API notes for information on how this works.
                         */
-                       dprintf(fd, " -> '%s'", unescape(g_buf, 0));
+                       dprintf(fd, " -> '%s%s", unescape(g_buf, 0), ch);
                }
        }