Plan 9 from Bell Labs’s /usr/web/sources/contrib/jas/src/cmd/lsproto.c

Copyright © 2021 Plan 9 Foundation.
Distributed under the MIT License.
Download the Plan 9 distribution.


/*
 * a modified 'ls' that works by processing proto(3) files
 */

#include <u.h>
#include <libc.h>
#include <bio.h>
#include <fcall.h>	/* dirmodefmt */
#include <disk.h>
#include <libsec.h>

#include <String.h>

#define dirbuf p9dirbuf	/* avoid conflict on sun */

int	errs = 0;
int	aflag;
int	lflag;
int	mflag;
int	pflag;
int	qflag;
int	Qflag;
int	sflag;
int	Fflag;
int	Dflag;
int	ls(char*, int);
char*	asciitime(long);
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 */

void usage(void);

char *argv0;

Biobuf	*b;
Biobuf	bin;
char	*proto;
char    *root;

static void addprotofile(char *new, char *old, Dir *d, void *a);

static int
digestfmt(Fmt *fmt)
{
	char buf[MD5dlen*2+1];
	uchar *p;
	int i;
    
	p = va_arg(fmt->args, uchar*);
	for(i=0; i<MD5dlen; i++)
		sprint(buf+2*i, "%.2ux", p[i]);
	return fmtstrcpy(fmt, buf);
}


void
usage(void)
{
    fprint(2, "usage: %s [-almpqsDFQ] [-R root] proto...\n", argv0);
    exits("usage");
}

void
main(int argc, char **argv)
{
    int i, errs;
    void *a = nil;
    
    root = ".";
    
    Binit(&bin, 1, OWRITE);
    ARGBEGIN{
        case 'a':	aflag++; break;
        case 'F':	Fflag++; break;
        case 'l':	lflag++; break;
        case 'm':	mflag++; break;
        case 'p':	pflag++; break;
        case 'q':	qflag++; break;
        case 'Q':	Qflag++; break;
        case 's':	sflag++; break;
        case 'D':	Dflag++; break;
        case 'R':
            root = EARGF(usage());
            break;
        default:
            usage();
    }ARGEND
    
    doquote = needsrcquote;
	quotefmtinstall();
	fmtinstall('M', dirmodefmt);
	fmtinstall('m', digestfmt);

    if(argc < 1)
        usage();
    
	if(lflag)
		clk = time(0);

    errs = 0;
    for(i = 0; i< argc; i++){
        proto = argv[i];
        b = Bopen(proto, OREAD);
        if(b == nil)
            sysfatal("can't open %s: %r", argv[i]);
        if((errs = rdproto(proto, root, addprotofile, 0, a)) < 0)
            sysfatal("rdproto: %r");
        Bterm(b);
    }

	exits(errs? "errors" : 0);
}

static void
addprotofile(char *new, char *old, Dir *d, void *a)
{
    if(Dflag){
        Bprint(&bin, "  new: %s\n", new);
        Bprint(&bin, "  old: %s\n", old);
        Bprint(&bin, "  name: %s\n", d->name);
    }
    // skip directories if listing for tar format
    if(!(aflag && (QTDIR & d->qid.type))){
        char *p, *name;
        
        p = utfrune(new, '/');
        name = p+1; // skips the default '/'
        format(d, name);
        Bflush(&bin);
    }
}

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)
{    
	if(sflag)
		Bprint(&bin, "%*llud ",
               swidth, (db->length+1023)/1024);
	if(qflag)
		Bprint(&bin, "(%.16llux %*lud %.2ux) ",
               db->qid.path,
               qwidth, db->qid.vers,
               db->qid.type);
	if(lflag)
		Bprint(&bin,
               "%M %C %*ud %*s %s %*llud %s ",
               db->mode, db->type,
               vwidth, db->dev,
               -uwidth, db->uid,
               db->gid,
               (int)(glwidth-strlen(db->gid)), db->length,
               asciitime(db->mtime));
    if(mflag) {
        uchar digest[MD5dlen];
        memset(digest, 0, sizeof digest);
        if(!(QTDIR & db->qid.type)) {
            int n, fd;
            uchar buf[8192];
            DigestState *s;
            String *path = nil;
            path = s_new();
            s_append(path, root);
            s_append(path, "/");
            s_append(path, name);
            fd = open(s_to_c(path), OREAD);
            if(path)
                s_free(path);
            if(fd < 0){
                Bprint(&bin, "md5sum: can't open %s: %r\n", name);
                return;
            }
            s = md5(nil, 0, nil, nil);
            while((n = read(fd, buf, sizeof buf)) > 0)
                md5(buf, n, nil, s);
            md5(nil, 0, digest, s);
            close(fd);
        }
        Bprint(&bin, "%m\t", digest);
    }
    if(!pflag)
        if(strcmp(root, ".") != 0)
            Bprint(&bin, "%s/", root);
    if(pflag) {
        char *p = utfrrune(name, '/');
        if(p){
            name = p+1;
        }
    }    
	Bprint(&bin,
           Qflag? "%s%s\n" : "%q%s\n",
           name, fileflag(db));
}

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;
}

Bell Labs OSI certified Powered by Plan 9

(Return to Plan 9 Home Page)

Copyright © 2021 Plan 9 Foundation. All Rights Reserved.
Comments to [email protected].