Introduction
Introduction Statistics Contact Development Disclaimer Help
added ls - 9base - revived minimalist port of Plan 9 userland to Unix
git clone git://git.suckless.org/9base
Log
Files
Refs
README
LICENSE
---
commit 6ccdc8cffd953f6dae2692e687d19ac6e58a7e2b
parent b7abc7dd08640a98b0af92b05bb0a57e614f3160
Author: Anselm R. Garbe <[email protected]>
Date: Tue, 31 Jan 2006 20:37:59 +0200
added ls
Diffstat:
M Makefile | 4 ++--
M config.mk | 2 +-
A ls/Makefile | 7 +++++++
A ls/ls.1 | 172 ++++++++++++++++++++++++++++++
A ls/ls.c | 309 +++++++++++++++++++++++++++++…
5 files changed, 491 insertions(+), 3 deletions(-)
---
diff --git a/Makefile b/Makefile
@@ -3,8 +3,8 @@
include config.mk
-SUBDIRS = lib9 yacc awk basename bc dc cat cleanname date echo grep mk \
- rc read sed seq sleep sort tee test touch tr uniq
+SUBDIRS = lib9 yacc awk basename bc dc cat cleanname date echo grep ls \
+ mk rc read sed seq sleep sort tee test touch tr uniq
all:
@echo 9base build options:
diff --git a/config.mk b/config.mk
@@ -4,7 +4,7 @@
PREFIX = /usr/local/9
MANPREFIX = ${PREFIX}/share/man
-VERSION = 2
+VERSION = 20060129
# Linux/BSD
CFLAGS = -Wall -Wno-missing-braces -Wno-parentheses -Wno-switch -c -I. -D…
diff --git a/ls/Makefile b/ls/Makefile
@@ -0,0 +1,7 @@
+# ls - ls unix port from plan9
+#
+# Depends on ../lib9
+
+TARG = ls
+
+include ../std.mk
diff --git a/ls/ls.1 b/ls/ls.1
@@ -0,0 +1,172 @@
+.TH LS 1
+.SH NAME
+ls, lc \- list contents of directory
+.SH SYNOPSIS
+.B ls
+[
+.B -dlmnpqrstuFQ
+]
+.I name ...
+.PP
+.B lc
+[
+.B -dlmnpqrstuFQ
+]
+.I name ...
+.SH DESCRIPTION
+For each directory argument,
+.I ls
+lists the contents of the directory;
+for each file argument,
+.I ls
+repeats its name and any other information requested.
+When no argument is given, the current directory is listed.
+By default, the output is sorted alphabetically by name.
+.PP
+.I Lc
+is the same as
+.IR ls ,
+but sets the
+.B -p
+option and pipes the output through
+.IR mc (1).
+.PP
+There are a number of options:
+.TP
+.B -d
+If argument is a directory, list it, not
+its contents.
+.TP
+.B -l
+List in long format, giving mode (see below), file system type
+(e.g., for devices, the
+.B #
+code letter that names it; see
+.IR intro (3)),
+the instance or subdevice number, owner, group,
+size in bytes, and time of last modification
+for each file.
+.TP
+.B -m
+List the name of the user who most recently modified the file.
+.TP
+.B -n
+Don't sort the listing.
+.TP
+.B -p
+Print only the final path element of each file name.
+.TP
+.B -q
+List the
+.I qid
+(see
+.IR stat (3))
+of each file; the printed fields are in the order
+path, version, and type.
+.TP
+.B -r
+Reverse the order of sort.
+.TP
+.B -s
+Give size in Kbytes for each entry.
+.TP
+.B -t
+Sort by time modified (latest first) instead of
+by name.
+.TP
+.B -u
+Under
+.B -t
+sort by time of last access;
+under
+.B -l
+print time of last access.
+.TP
+.B -F
+Add the character
+.B /
+after all directory names
+and the character
+.B *
+after all executable files.
+.TP
+.B -L
+Print the character
+.B t
+before each file if it has the temporary flag set, and
+.B -
+otherwise.
+.TP
+.B -Q
+By default, printed file names are quoted if they contain characters special to
+.IR rc (1).
+The
+.B -Q
+flag disables this behavior.
+.PP
+The mode printed under the
+.B -l
+option contains 11 characters,
+interpreted
+as follows:
+the first character is
+.TP
+.B d
+if the entry is a directory;
+.TP
+.B a
+if the entry is an append-only file;
+.TP
+.B D
+if the entry is a Unix device;
+.TP
+.B L
+if the entry is a symbolic link;
+.TP
+.B P
+if the entry is a named pipe;
+.TP
+.B S
+if the entry is a socket;
+.TP
+.B -
+if the entry is a plain file.
+.PD
+.PP
+The next letter is
+.B l
+if the file is exclusive access (one writer or reader at a time).
+.PP
+The last 9 characters are interpreted
+as three sets of three bits each.
+The first set refers to owner permissions;
+the next to permissions to others in the same user-group;
+and the last to all others.
+Within each set the three characters indicate
+permission respectively to read, to write, or to
+execute the file as a program.
+For a directory, `execute' permission is interpreted
+to mean permission to search the directory
+for a specified file.
+The permissions are indicated as follows:
+.TP 3
+.B r
+if the file is readable;
+.PD 0
+.TP 3
+.B w
+if the file is writable;
+.TP 3
+.B x
+if the file is executable;
+.TP 3
+.B -
+if none of the above permissions is granted.
+.PD
+.SH SOURCE
+.B \*9/src/cmd/ls.c
+.br
+.B \*9/bin/lc
+.SH SEE ALSO
+.IR stat (3),
+.IR mc (1)
diff --git a/ls/ls.c b/ls/ls.c
@@ -0,0 +1,309 @@
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+
+#define dirbuf p9dirbuf /* avoid conflict on sun */
+
+typedef struct NDir NDir;
+struct NDir
+{
+ Dir *d;
+ char *prefix;
+};
+
+int errs = 0;
+int dflag;
+int lflag;
+int mflag;
+int nflag;
+int pflag;
+int qflag;
+int Qflag;
+int rflag;
+int sflag;
+int tflag;
+int uflag;
+int Fflag;
+int ndirbuf;
+int ndir;
+NDir* dirbuf;
+int ls(char*, int);
+int compar(NDir*, NDir*);
+char* asciitime(long);
+char* darwx(long);
+void rwx(long, char*);
+void growto(long);
+void dowidths(Dir*);
+void format(Dir*, char*);
+void output(void);
+ulong clk;
+int swidth; /* max width of -s size */
+int qwidth; /* max width of -q version */
+int vwidth; /* max width of dev */
+int uwidth; /* max width of userid */
+int mwidth; /* max width of muid */
+int glwidth; /* max width of groupid and length */
+Biobuf bin;
+
+void
+main(int argc, char *argv[])
+{
+ int i;
+
+ Binit(&bin, 1, OWRITE);
+ ARGBEGIN{
+ case 'F': Fflag++; break;
+ case 'd': dflag++; break;
+ case 'l': lflag++; break;
+ case 'm': mflag++; break;
+ case 'n': nflag++; break;
+ case 'p': pflag++; break;
+ case 'q': qflag++; break;
+ case 'Q': Qflag++; break;
+ case 'r': rflag++; break;
+ case 's': sflag++; break;
+ case 't': tflag++; break;
+ case 'u': uflag++; break;
+ default: fprint(2, "usage: ls [-dlmnpqrstuFQ] [file ...]\n");
+ exits("usage");
+ }ARGEND
+
+ doquote = needsrcquote;
+ quotefmtinstall();
+ fmtinstall('M', dirmodefmt);
+
+ if(lflag)
+ clk = time(0);
+ if(argc == 0)
+ errs = ls(".", 0);
+ else for(i=0; i<argc; i++)
+ errs |= ls(argv[i], 1);
+ output();
+ exits(errs? "errors" : 0);
+}
+
+int
+ls(char *s, int multi)
+{
+ int fd;
+ long i, n;
+ char *p;
+ Dir *db;
+
+ for(;;) {
+ p = utfrrune(s, '/');
+ if(p == 0 || p[1] != 0 || p == s)
+ break;
+ *p = 0;
+ }
+ db = dirstat(s);
+ if(db == nil){
+ error:
+ fprint(2, "ls: %s: %r\n", s);
+ return 1;
+ }
+ if(db->qid.type&QTDIR && dflag==0){
+ free(db);
+ db = nil;
+ output();
+ fd = open(s, OREAD);
+ if(fd == -1)
+ goto error;
+ n = dirreadall(fd, &db);
+ if(n < 0)
+ goto error;
+ growto(ndir+n);
+ for(i=0; i<n; i++){
+ dirbuf[ndir+i].d = db+i;
+ dirbuf[ndir+i].prefix = multi? s : 0;
+ }
+ ndir += n;
+ close(fd);
+ output();
+ }else{
+ growto(ndir+1);
+ dirbuf[ndir].d = db;
+ dirbuf[ndir].prefix = 0;
+ p = utfrrune(s, '/');
+ if(p){
+ dirbuf[ndir].prefix = s;
+ *p = 0;
+ /* restore original name; don't use result of stat */
+ dirbuf[ndir].d->name = strdup(p+1);
+ }
+ ndir++;
+ }
+ return 0;
+}
+
+void
+output(void)
+{
+ int i;
+ char buf[4096];
+ char *s;
+
+ if(!nflag)
+ qsort(dirbuf, ndir, sizeof dirbuf[0], (int (*)(const void*, co…
+ for(i=0; i<ndir; i++)
+ dowidths(dirbuf[i].d);
+ for(i=0; i<ndir; i++) {
+ if(!pflag && (s = dirbuf[i].prefix)) {
+ if(strcmp(s, "/") ==0) /* / is a special case */
+ s = "";
+ sprint(buf, "%s/%s", s, dirbuf[i].d->name);
+ format(dirbuf[i].d, buf);
+ } else
+ format(dirbuf[i].d, dirbuf[i].d->name);
+ }
+ ndir = 0;
+ Bflush(&bin);
+}
+
+void
+dowidths(Dir *db)
+{
+ char buf[256];
+ int n;
+
+ if(sflag) {
+ n = sprint(buf, "%llud", (db->length+1023)/1024);
+ if(n > swidth)
+ swidth = n;
+ }
+ if(qflag) {
+ n = sprint(buf, "%lud", db->qid.vers);
+ if(n > qwidth)
+ qwidth = n;
+ }
+ if(mflag) {
+ n = snprint(buf, sizeof buf, "[%s]", db->muid);
+ if(n > mwidth)
+ mwidth = n;
+ }
+ if(lflag) {
+ n = sprint(buf, "%ud", db->dev);
+ if(n > vwidth)
+ vwidth = n;
+ n = strlen(db->uid);
+ if(n > uwidth)
+ uwidth = n;
+ n = sprint(buf, "%llud", db->length);
+ n += strlen(db->gid);
+ if(n > glwidth)
+ glwidth = n;
+ }
+}
+
+char*
+fileflag(Dir *db)
+{
+ if(Fflag == 0)
+ return "";
+ if(QTDIR & db->qid.type)
+ return "/";
+ if(0111 & db->mode)
+ return "*";
+ return "";
+}
+
+void
+format(Dir *db, char *name)
+{
+ int i;
+
+ if(sflag)
+ Bprint(&bin, "%*llud ",
+ swidth, (db->length+1023)/1024);
+ if(mflag){
+ Bprint(&bin, "[%s] ", db->muid);
+ for(i=2+strlen(db->muid); i<mwidth; i++)
+ Bprint(&bin, " ");
+ }
+ if(qflag)
+ Bprint(&bin, "(%.16llux %*lud %.2ux) ",
+ db->qid.path,
+ qwidth, db->qid.vers,
+ db->qid.type);
+ if(lflag)
+ Bprint(&bin,
+ Qflag? "%M %C %*ud %*s %s %*llud %s %s\n" : "%M %C %*u…
+ db->mode, db->type,
+ vwidth, db->dev,
+ -uwidth, db->uid,
+ db->gid,
+ (int)(glwidth-strlen(db->gid)), db->length,
+ asciitime(uflag? db->atime : db->mtime), name);
+ else
+ Bprint(&bin,
+ Qflag? "%s%s\n" : "%q%s\n",
+ name, fileflag(db));
+}
+
+void
+growto(long n)
+{
+ if(n <= ndirbuf)
+ return;
+ ndirbuf = n;
+ dirbuf=(NDir *)realloc(dirbuf, ndirbuf*sizeof(NDir));
+ if(dirbuf == 0){
+ fprint(2, "ls: malloc fail\n");
+ exits("malloc fail");
+ }
+}
+
+int
+compar(NDir *a, NDir *b)
+{
+ long i;
+ Dir *ad, *bd;
+
+ ad = a->d;
+ bd = b->d;
+
+ if(tflag){
+ if(uflag)
+ i = bd->atime-ad->atime;
+ else
+ i = bd->mtime-ad->mtime;
+ }else{
+ if(a->prefix && b->prefix){
+ i = strcmp(a->prefix, b->prefix);
+ if(i == 0)
+ i = strcmp(ad->name, bd->name);
+ }else if(a->prefix){
+ i = strcmp(a->prefix, bd->name);
+ if(i == 0)
+ i = 1; /* a is longer than b */
+ }else if(b->prefix){
+ i = strcmp(ad->name, b->prefix);
+ if(i == 0)
+ i = -1; /* b is longer than a */
+ }else
+ i = strcmp(ad->name, bd->name);
+ }
+ if(i == 0)
+ i = (ad<bd? -1 : 1);
+ if(rflag)
+ i = -i;
+ return i;
+}
+
+char*
+asciitime(long l)
+{
+ static char buf[32];
+ char *t;
+
+ t = ctime(l);
+ /* 6 months in the past or a day in the future */
+ if(l<clk-180L*24*60*60 || clk+24L*60*60<l){
+ memmove(buf, t+4, 7); /* month and day */
+ memmove(buf+7, t+23, 5); /* year */
+ }else
+ memmove(buf, t+4, 12); /* skip day of week */
+ buf[12] = 0;
+ return buf;
+}
+
You are viewing proxied material from suckless.org. The copyright of proxied material belongs to its original authors. Any comments or complaints in relation to proxied material should be directed to the original authors of the content concerned. Please see the disclaimer for more details.