]> Sergey Matveev's repositories - nnn.git/commitdiff
Use symbol @/ to denote symbolic link to directory
authorArun Prakash Jana <engineerarun@gmail.com>
Thu, 16 Aug 2018 14:38:26 +0000 (20:08 +0530)
committerArun Prakash Jana <engineerarun@gmail.com>
Thu, 16 Aug 2018 14:44:07 +0000 (20:14 +0530)
README.md
nnn.c

index 4f0f72d9f3696c9d2b12b686e8b5022fa625f6cc..39bc8f191b69e89bd60e8693a89c996155bb4f27 100644 (file)
--- a/README.md
+++ b/README.md
@@ -289,6 +289,7 @@ The following indicators are used in the detail view:
 | <code>&#124;</code> | Fifo |
 | `=` | Socket |
 | `@` | Symbolic Link |
+| `@/` | Symbolic Link to directory |
 | `b` | Block Device |
 | `c` | Character Device |
 
diff --git a/nnn.c b/nnn.c
index 0e5e5ea722c7ecc23fd36287dbb2692fccb25433..1016d66bbc2c3cbc35b661c77ee7b8d91560cbea 100644 (file)
--- a/nnn.c
+++ b/nnn.c
@@ -160,6 +160,7 @@ disabledbg()
 #define DESCRIPTOR_LEN 32
 #define _ALIGNMENT 0x10
 #define _ALIGNMENT_MASK 0xF
+#define SYMLINK_TO_DIR 0x1
 
 /* Macros to define process spawn behaviour as flags */
 #define F_NONE     0x00  /* no flag set */
@@ -202,6 +203,7 @@ disabledbg()
 typedef unsigned long ulong;
 typedef unsigned int uint;
 typedef unsigned char uchar;
+typedef unsigned short ushort;
 
 /* STRUCTURES */
 
@@ -212,7 +214,8 @@ typedef struct entry {
        off_t size;
        blkcnt_t blocks; /* number of 512B blocks allocated */
        mode_t mode;
-       uint nlen; /* Length of file name; can be uchar (< NAME_MAX + 1) */
+       ushort nlen; /* Length of file name; can be uchar (< NAME_MAX + 1) */
+       uchar flags; /* Flags specific to the file */
 } __attribute__ ((packed, aligned(_ALIGNMENT))) *pEntry;
 
 /* Bookmark */
@@ -1560,9 +1563,12 @@ printent_long(struct entry *ent, int sel, uint namecols)
                        printw("%s%-16.16s %8.8s/ %s/\n", CURSYM(sel), buf, coolsize(ent->blocks << 9), pname);
                else
                        printw("%s%-16.16s        /  %s/\n", CURSYM(sel), buf, pname);
-       } else if (S_ISLNK(ent->mode))
-               printw("%s%-16.16s        @  %s@\n", CURSYM(sel), buf, pname);
-       else if (S_ISSOCK(ent->mode))
+       } else if (S_ISLNK(ent->mode)) {
+               if (ent->flags & SYMLINK_TO_DIR)
+                       printw("%s%-16.16s       @/  %s@\n", CURSYM(sel), buf, pname);
+               else
+                       printw("%s%-16.16s        @  %s@\n", CURSYM(sel), buf, pname);
+       } else if (S_ISSOCK(ent->mode))
                printw("%s%-16.16s        =  %s=\n", CURSYM(sel), buf, pname);
        else if (S_ISFIFO(ent->mode))
                printw("%s%-16.16s        |  %s|\n", CURSYM(sel), buf, pname);
@@ -1752,19 +1758,6 @@ 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
  */
@@ -1785,19 +1778,16 @@ 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 */
-               char *tgt = realpath(fpath, g_buf);
-               if (tgt) {
-                       char ch[] = {'\'', '\0', '\0'};
-                       if (istgtdir(g_buf)) {
-                               ch[1] = ch[0];
-                               ch[0] = '/';
-                       }
+               ssize_t len = readlink(fpath, g_buf, MAX_CMD_LEN);
+
+               if (len != -1) {
+                       g_buf[len] = '\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%s", unescape(g_buf, 0), ch);
+                       dprintf(fd, " -> '%s'", unescape(g_buf, 0));
                }
        }
 
@@ -2210,6 +2200,15 @@ dentfill(char *path, struct entry **dents,
                        }
                }
 
+               /* Flag if this is a symlink to a dir */
+               if (S_ISLNK(sb.st_mode))
+                       if (!fstatat(fd, namep, &sb, 0)) {
+                               if (S_ISDIR(sb.st_mode))
+                                       dentp->flags |= SYMLINK_TO_DIR;
+                               else
+                                       dentp->flags &= ~SYMLINK_TO_DIR;
+                       }
+
                ++n;
        }