about summary refs log tree commit diff
path: root/lr.c
diff options
context:
space:
mode:
authorChristian Neukirchen <chneukirchen@gmail.com>2016-02-27 22:55:15 +0100
committerChristian Neukirchen <chneukirchen@gmail.com>2016-02-27 22:55:15 +0100
commit0c08c3399deb71f8a3ffa65d431aa9d97eb3d7c6 (patch)
tree0bd13ccb428f6f64c913d147f64d3c012084f336 /lr.c
parent8d7673c963982829d9205ea51436d4e59aa44e19 (diff)
downloadlr-0c08c3399deb71f8a3ffa65d431aa9d97eb3d7c6.tar.gz
lr-0c08c3399deb71f8a3ffa65d431aa9d97eb3d7c6.tar.xz
lr-0c08c3399deb71f8a3ffa65d431aa9d97eb3d7c6.zip
highlight symlink targets, needs an additional lstat for -G
Diffstat (limited to 'lr.c')
-rw-r--r--lr.c28
1 files changed, 26 insertions, 2 deletions
diff --git a/lr.c b/lr.c
index c882b07..786cbc7 100644
--- a/lr.c
+++ b/lr.c
@@ -1493,6 +1493,8 @@ color_name_on(const char *f, mode_t m)
 		fg256(242);
 	else if (S_ISREG(m) && (m & S_IXUSR))
 		fg256(154);
+	else if (m == 0)  /* broken link */
+		fg256(160);
 }
 
 // unused format codes: BEHJKLNOQVWXZ achjoqrvwz
@@ -1558,8 +1560,30 @@ print_format(struct fileinfo *fi)
 			fgdefault();
 			break;
 		case 'l':
-			if (S_ISLNK(fi->sb.st_mode))
-				print_shquoted(readlin(fi->fpath, ""));
+			if (S_ISLNK(fi->sb.st_mode)) {
+				char target[PATH_MAX];
+				size_t j = strlen(fi->fpath);
+				struct stat st;
+				st.st_mode = 0;
+
+				strcpy(target, fi->fpath);
+				while (j && target[j-1] != '/')
+					j--;
+				ssize_t l = readlink(fi->fpath,
+				    target+j, sizeof target - j);
+				if (l > 0 && (size_t)l < sizeof target - j) {
+					target[j+l] = 0;
+					if (Gflag)
+						lstat(target[j] == '/' ?
+						    target + j : target,
+						    &st);
+				} else {
+					*target = 0;
+				}
+				color_name_on(target, st.st_mode);
+				print_shquoted(target + j);
+				fgdefault();
+			}
 			break;
 		case 'n': printf("%*jd", intlen(maxnlink), (intmax_t)fi->sb.st_nlink); break;
 		case 'F':