Also, implement the -H and -L options.
---
Again, not sure how to handle the long line.

 ls.1 |  9 ++++++++-
 ls.c | 32 ++++++++++++++++++++------------
 2 files changed, 28 insertions(+), 13 deletions(-)

diff --git a/ls.1 b/ls.1
index ec61bee..792b07b 100644
--- a/ls.1
+++ b/ls.1
@@ -3,7 +3,7 @@
 ls \- list directory contents
 .SH SYNOPSIS
 .B ls
-.RB [ \-adFiltU ]
+.RB [ \-adFHhiLlrtU ]
 .RI [ file ...]
 .SH DESCRIPTION
 .B ls
@@ -20,12 +20,19 @@ lists directories themselves, not their contents.
 .B \-F
 append a file type indicator to files.
 .TP
+.B \-H
+list information about the targets of symbolic links specified on the command
+line instead of the links themselves.
+.TP
 .B \-h
 show filesizes in human\-readable format.
 .TP
 .B \-i
 print the index number of each file.
 .TP
+.B \-L
+list information about the targets of symbolic links instead of the links
+themselves.
 .B \-l
 lists detailed information about each file, including their type, permissions,
 links, owner, group, size, and modification time.
diff --git a/ls.c b/ls.c
index b48391b..24af998 100644
--- a/ls.c
+++ b/ls.c
@@ -14,7 +14,7 @@
 
 typedef struct {
        char *name;
-       mode_t mode;
+       mode_t mode, tmode;
        nlink_t nlink;
        uid_t uid;
        gid_t gid;
@@ -26,14 +26,16 @@ typedef struct {
 static int entcmp(const void *, const void *);
 static void ls(Entry *);
 static void lsdir(const char *);
-static void mkent(Entry *, char *, int);
+static void mkent(Entry *, char *, int, int);
 static void output(Entry *);
 
 static int aflag = 0;
 static int dflag = 0;
 static int Fflag = 0;
+static int Hflag = 0;
 static int hflag = 0;
 static int iflag = 0;
+static int Lflag = 0;
 static int lflag = 0;
 static int rflag = 0;
 static int tflag = 0;
@@ -66,12 +68,18 @@ main(int argc, char *argv[])
        case 'F':
                Fflag = 1;
                break;
+       case 'H':
+               Hflag = 1;
+               break;
        case 'h':
                hflag = 1;
                break;
        case 'i':
                iflag = 1;
                break;
+       case 'L':
+               Lflag = 1;
+               break;
        case 'l':
                lflag = 1;
                break;
@@ -95,7 +103,7 @@ main(int argc, char *argv[])
        ents = emalloc(argc * sizeof(*ents));
 
        for (i = 0; i < argc; i++)
-               mkent(&ents[i], argv[i], 1);
+               mkent(&ents[i], argv[i], 1, Hflag || Lflag);
        qsort(ents, argc, sizeof *ents, entcmp);
        for (i = 0; i < argc; i++)
                ls(&ents[rflag ? argc-i-1 : i]);
@@ -117,7 +125,7 @@ entcmp(const void *va, const void *vb)
 static void
 ls(Entry *ent)
 {
-       if (S_ISDIR(ent->mode) && !dflag) {
+       if ((S_ISDIR(ent->mode) || (S_ISLNK(ent->mode) && S_ISDIR(ent->tmode) 
&& !Fflag && !lflag)) && !dflag) {
                lsdir(ent->name);
        } else {
                output(ent);
@@ -151,13 +159,13 @@ lsdir(const char *path)
                if (d->d_name[0] == '.' && !aflag)
                        continue;
                if (Uflag){
-                       mkent(&ent, d->d_name, Fflag || lflag || iflag);
+                       mkent(&ent, d->d_name, Fflag || lflag || iflag, Lflag);
                        output(&ent);
                } else {
                        ents = erealloc(ents, ++n * sizeof *ents);
                        p = emalloc((sz = strlen(d->d_name)+1));
                        memcpy(p, d->d_name, sz);
-                       mkent(&ents[n-1], p, tflag || Fflag || lflag || iflag);
+                       mkent(&ents[n-1], p, tflag || Fflag || lflag || iflag, 
Lflag);
                }
        }
        closedir(dp);
@@ -175,15 +183,15 @@ lsdir(const char *path)
 }
 
 static void
-mkent(Entry *ent, char *path, int dostat)
+mkent(Entry *ent, char *path, int dostat, int follow)
 {
        struct stat st;
 
        ent->name   = path;
        if (!dostat)
                return;
-       if (lstat(path, &st) < 0)
-               eprintf("lstat %s:", path);
+       if ((follow ? stat : lstat)(path, &st) < 0)
+               eprintf("%s %s:", follow ? "stat" : "lstat", path);
        ent->mode   = st.st_mode;
        ent->nlink  = st.st_nlink;
        ent->uid    = st.st_uid;
@@ -191,6 +199,8 @@ mkent(Entry *ent, char *path, int dostat)
        ent->size   = st.st_size;
        ent->mtime  = st.st_mtime;
        ent->ino    = st.st_ino;
+       if (S_ISLNK(ent->mode))
+               ent->tmode = stat(path, &st) == 0 ? st.st_mode : 0;
 }
 
 static char *
@@ -225,7 +235,6 @@ output(Entry *ent)
        struct passwd *pw;
        char pwname[_SC_LOGIN_NAME_MAX];
        char grname[_SC_LOGIN_NAME_MAX];
-       Entry entlnk;
 
        if (iflag)
                printf("%lu ", (unsigned long)ent->ino);
@@ -294,8 +303,7 @@ output(Entry *ent)
                if ((len = readlink(ent->name, buf, sizeof buf)) < 0)
                        eprintf("readlink %s:", ent->name);
                buf[len] = '\0';
-               mkent(&entlnk, buf, Fflag);
-               printf(" -> %s%s", buf, indicator(entlnk.mode));
+               printf(" -> %s%s", buf, indicator(ent->tmode));
        }
        putchar('\n');
 }
-- 
2.1.3.1.g339ec9c


Reply via email to