Date: Wed, 28 May 2014 10:02:26 GMT From: zkorchev@FreeBSD.org To: svn-soc-all@FreeBSD.org Subject: socsvn commit: r268756 - soc2014/zkorchev/freebsd_head/bin/ls Message-ID: <201405281002.s4SA2QQb043532@socsvn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: zkorchev Date: Wed May 28 10:02:26 2014 New Revision: 268756 URL: http://svnweb.FreeBSD.org/socsvn/?view=rev&rev=268756 Log: first modified version of ls Added: soc2014/zkorchev/freebsd_head/bin/ls/sol.c soc2014/zkorchev/freebsd_head/bin/ls/sol.h Modified: soc2014/zkorchev/freebsd_head/bin/ls/Makefile soc2014/zkorchev/freebsd_head/bin/ls/extern.h soc2014/zkorchev/freebsd_head/bin/ls/ls.c soc2014/zkorchev/freebsd_head/bin/ls/ls.h soc2014/zkorchev/freebsd_head/bin/ls/print.c soc2014/zkorchev/freebsd_head/bin/ls/util.c Modified: soc2014/zkorchev/freebsd_head/bin/ls/Makefile ============================================================================== --- soc2014/zkorchev/freebsd_head/bin/ls/Makefile Wed May 28 09:06:36 2014 (r268755) +++ soc2014/zkorchev/freebsd_head/bin/ls/Makefile Wed May 28 10:02:26 2014 (r268756) @@ -4,9 +4,10 @@ .include <src.opts.mk> PROG= ls -SRCS= cmp.c ls.c print.c util.c +SRCS= cmp.c ls.c print.c util.c sol.c DPADD= ${LIBUTIL} -LDADD= -lutil +LDADD= -L/usr/local/lib -lutil -lyajl +CFLAGS+= -DSOL_ON -I/usr/local/include -Wno-format-invalid-specifier .if !defined(RELEASE_CRUNCH) && \ ${MK_LS_COLORS} != no Modified: soc2014/zkorchev/freebsd_head/bin/ls/extern.h ============================================================================== --- soc2014/zkorchev/freebsd_head/bin/ls/extern.h Wed May 28 09:06:36 2014 (r268755) +++ soc2014/zkorchev/freebsd_head/bin/ls/extern.h Wed May 28 10:02:26 2014 (r268756) @@ -48,6 +48,10 @@ int printname(const char *); void printscol(const DISPLAY *); void printstream(const DISPLAY *); +#if defined(SOL_ON) +void printsollong(const DISPLAY *dp); +void printsolshort(const DISPLAY *dp); +#endif void usage(void); int prn_normal(const char *); size_t len_octal(const char *, int); Modified: soc2014/zkorchev/freebsd_head/bin/ls/ls.c ============================================================================== --- soc2014/zkorchev/freebsd_head/bin/ls/ls.c Wed May 28 09:06:36 2014 (r268755) +++ soc2014/zkorchev/freebsd_head/bin/ls/ls.c Wed May 28 10:02:26 2014 (r268756) @@ -69,6 +69,7 @@ #include "ls.h" #include "extern.h" +#include "sol.h" /* * Upward approximation of the maximum number of characters needed to @@ -99,6 +100,10 @@ static void (*printfcn)(const DISPLAY *); static int (*sortfcn)(const FTSENT *, const FTSENT *); +#if defined(SOL_ON) +struct sol_stream sol_stream; +#endif + long blocksize; /* block size units */ int termwidth = 80; /* default terminal width */ @@ -113,12 +118,15 @@ static int f_listdir; /* list actual directory, not contents */ static int f_listdot; /* list files beginning with . */ int f_longform; /* long listing format */ +#if defined(SOL_ON) + int f_solformat; /* structured output format */ +#endif static int f_noautodot; /* do not automatically enable -A for root */ static int f_nofollow; /* don't follow symbolic link arguments */ int f_nonprint; /* show unprintables as ? */ static int f_nosort; /* don't sort output */ int f_notabs; /* don't use tab-separated multi-col output */ -static int f_numericonly; /* don't convert uid/gid to name */ + int f_numericonly; /* don't convert uid/gid to name */ int f_octal; /* show unprintables as \xxx */ int f_octal_escape; /* like f_octal but use C escapes if possible */ static int f_recursive; /* ls subdirectories also */ @@ -186,7 +194,11 @@ if (getenv("LS_SAMESORT")) f_samesort = 1; while ((ch = getopt(argc, argv, +#if defined(SOL_ON) + "1ABCD:FGHILOPRSTUWXZabcdfghiklmnopqrstuwxy,")) != -1) { +#else "1ABCD:FGHILPRSTUWXZabcdfghiklmnopqrstuwxy,")) != -1) { +#endif switch (ch) { /* * The -1, -C, -x and -l options all override each other so @@ -210,6 +222,11 @@ f_longform = 0; f_singlecol = 0; break; +#if defined(SOL_ON) + case 'O': + f_solformat = 1; + break; +#endif /* The -c, -u, and -U options override each other. */ case 'c': f_statustime = 1; @@ -361,6 +378,9 @@ if (!f_listdot && getuid() == (uid_t)0 && !f_noautodot) f_listdot = 1; + // TODO zaro: + // make SOL_ON and COLORLS mutually exclusive + /* Enabling of colours is conditional on the environment. */ if (getenv("CLICOLOR") && (isatty(STDOUT_FILENO) || getenv("CLICOLOR_FORCE"))) @@ -465,19 +485,41 @@ } /* Select a print function. */ - if (f_singlecol) - printfcn = printscol; - else if (f_longform) - printfcn = printlong; - else if (f_stream) - printfcn = printstream; +#if defined(SOL_ON) + if (f_solformat) + { + // TODO zaro compact and formatted output support, etc. + if (f_longform) + printfcn = printsollong; + else + printfcn = printsolshort; + } else - printfcn = printcol; +#endif + { + if (f_singlecol) + printfcn = printscol; + else if (f_longform) + printfcn = printlong; + else if (f_stream) + printfcn = printstream; + else + printfcn = printcol; + } + +#if defined(SOL_ON) + if (f_solformat) sol_init(&sol_stream, SOL_JSON); +#endif if (argc) traverse(argc, argv, fts_options); else traverse(1, dotav, fts_options); + +#if defined(SOL_ON) + if (f_solformat) sol_term(&sol_stream); +#endif + exit(rval); } @@ -537,6 +579,7 @@ * a separator. If multiple arguments, precede each * directory with its name. */ +#if !defined(SOL_ON) if (output) { putchar('\n'); (void)printname(p->fts_path); @@ -546,6 +589,10 @@ puts(":"); output = 1; } +#else + (void)argc; // TODO remove this + // TODO zaro what to do on multiple directory listing? +#endif chp = fts_children(ftsp, ch_options); display(p, chp, options); @@ -588,6 +635,8 @@ char ngroup[STRBUF_SIZEOF(uid_t) + 1]; char nuser[STRBUF_SIZEOF(gid_t) + 1]; + // TODO zaro: don't calculate widths when using SOL + needstats = f_inode || f_longform || f_size; flen = 0; btotal = 0; Modified: soc2014/zkorchev/freebsd_head/bin/ls/ls.h ============================================================================== --- soc2014/zkorchev/freebsd_head/bin/ls/ls.h Wed May 28 09:06:36 2014 (r268755) +++ soc2014/zkorchev/freebsd_head/bin/ls/ls.h Wed May 28 10:02:26 2014 (r268756) @@ -46,6 +46,9 @@ extern int f_label; /* show MAC label */ extern int f_inode; /* print inode */ extern int f_longform; /* long listing format */ +#if defined(SOL_ON) +extern int f_solformat; /* structured output format */ +#endif extern int f_octal; /* print unprintables in octal */ extern int f_octal_escape; /* like f_octal but use C escapes if possible */ extern int f_nonprint; /* show unprintables as ? */ @@ -58,11 +61,16 @@ extern int f_thousands; /* show file sizes with thousands separators */ extern char *f_timeformat; /* user-specified time format */ extern int f_notabs; /* don't use tab-separated multi-col output */ +extern int f_numericonly; /* don't convert uid/gid to name */ extern int f_type; /* add type character for non-regular files */ #ifdef COLORLS extern int f_color; /* add type in color for non-regular files */ #endif +#if defined(SOL_ON) +extern struct sol_stream sol_stream; +#endif + typedef struct { FTSENT *list; u_long btotal; Modified: soc2014/zkorchev/freebsd_head/bin/ls/print.c ============================================================================== --- soc2014/zkorchev/freebsd_head/bin/ls/print.c Wed May 28 09:06:36 2014 (r268755) +++ soc2014/zkorchev/freebsd_head/bin/ls/print.c Wed May 28 10:02:26 2014 (r268756) @@ -61,6 +61,7 @@ #include "ls.h" #include "extern.h" +#include "sol.h" static int printaname(const FTSENT *, u_long, u_long); static void printdev(size_t, dev_t); @@ -354,7 +355,6 @@ static void printdev(size_t width, dev_t dev) { - (void)printf("%#*jx ", (u_int)width, (uintmax_t)dev); } @@ -365,6 +365,7 @@ static time_t now = 0; const char *format; static int d_first = -1; + size_t len; if (d_first < 0) d_first = (*nl_langinfo(D_MD_ORDER) == 'd'); @@ -383,18 +384,37 @@ else /* mmm dd yyyy || dd mmm yyyy */ format = d_first ? "%e %b %Y" : "%b %e %Y"; - strftime(longstring, sizeof(longstring), format, localtime(&ftime)); - fputs(longstring, stdout); - fputc(' ', stdout); + len = strftime(longstring, sizeof(longstring), format, localtime(&ftime)); + +#if defined(SOL_ON) + if (f_solformat) + { + sol_map_key(&sol_stream, "time", 4); + sol_map_string(&sol_stream, longstring, len); + } + else +#endif + { + fputs(longstring, stdout); + fputc(' ', stdout); + } } static int printtype(u_int mode) { + char type; if (f_slash) { if ((mode & S_IFMT) == S_IFDIR) { - (void)putchar('/'); +#if defined(SOL_ON) + if (f_solformat) { + sol_map_key(&sol_stream, "type", 4); + sol_map_string(&sol_stream, "/", 1); + } + else +#endif + (void)putchar('/'); return (1); } return (0); @@ -402,28 +422,37 @@ switch (mode & S_IFMT) { case S_IFDIR: - (void)putchar('/'); - return (1); + type = '/'; + break; case S_IFIFO: - (void)putchar('|'); - return (1); + type = '|'; + break; case S_IFLNK: - (void)putchar('@'); - return (1); + type = '@'; + break; case S_IFSOCK: - (void)putchar('='); - return (1); + type = '='; + break; case S_IFWHT: - (void)putchar('%'); - return (1); - default: + type = '%'; break; + default: + if (mode & (S_IXUSR | S_IXGRP | S_IXOTH)) { + type = '*'; + break; + } + return (0); } - if (mode & (S_IXUSR | S_IXGRP | S_IXOTH)) { - (void)putchar('*'); - return (1); + +#if defined(SOL_ON) + if (f_solformat) { + sol_map_key(&sol_stream, "type", 4); + sol_map_string(&sol_stream, &type, 1); } - return (0); + else +#endif + (void)putchar(type); + return (1); } #ifdef COLORLS @@ -587,15 +616,25 @@ (void)fprintf(stderr, "\nls: %s: %s\n", name, strerror(errno)); return; } - path[lnklen] = '\0'; - (void)printf(" -> "); - (void)printname(path); + +#if defined(SOL_ON) + if (f_solformat) + { + sol_map_key(&sol_stream, "link", 4); + sol_map_string(&sol_stream, path, lnklen); + } + else +#endif + { + path[lnklen] = '\0'; + (void)printf(" -> "); + (void)printname(path); + } } static void printsize(size_t width, off_t bytes) { - if (f_humanval) { /* * Reserve one space before the size and allocate room for @@ -684,3 +723,137 @@ buf[10] = '+'; acl_free(facl); } + +#if defined(SOL_ON) +void +printsollong(const DISPLAY *dp) +{ + struct stat *sp; + FTSENT *p; + NAMES *np; + char buf[20]; + + /*if ((dp->list == NULL || dp->list->fts_level != FTS_ROOTLEVEL) && + (f_longform || f_size)) { + (void)printf("total %lu\n", howmany(dp->btotal, blocksize)); + }*/ + + sol_array_start(&sol_stream); + + for (p = dp->list; p; p = p->fts_link) { + if (IS_NOPRINT(p)) + continue; + + sol_map_start(&sol_stream); + + sp = p->fts_statp; + if (f_inode) { + sol_map_key(&sol_stream, "inode", 5); + sol_map_integer(&sol_stream, sp->st_ino); + } + if (f_size) { + sol_map_key(&sol_stream, "bsize", 5); + sol_map_integer(&sol_stream, howmany(sp->st_blocks, blocksize)); + } + strmode(sp->st_mode, buf); + aclmode(buf, p); + np = p->fts_pointer; + + sol_map_key(&sol_stream, "mode", 4); + sol_map_string(&sol_stream, buf, strlen(buf)); + + sol_map_key(&sol_stream, "nlink", 5); + sol_map_integer(&sol_stream, sp->st_nlink); + + if (f_numericonly) { + sol_map_key(&sol_stream, "uid", 3); + sol_map_integer(&sol_stream, sp->st_uid); + sol_map_key(&sol_stream, "gid", 3); + sol_map_integer(&sol_stream, sp->st_gid); + } + else { + sol_map_key(&sol_stream, "user", 4); + sol_map_string(&sol_stream, np->user, strlen(np->user)); + sol_map_key(&sol_stream, "group", 5); + sol_map_string(&sol_stream, np->group, strlen(np->group)); + } + + if (f_flags) { + sol_map_key(&sol_stream, "flags", 5); + sol_map_string(&sol_stream, np->flags, strlen(np->flags)); + } + if (f_label) { + sol_map_key(&sol_stream, "label", 5); + sol_map_string(&sol_stream, np->label, strlen(np->label)); + } + + if (S_ISCHR(sp->st_mode) || S_ISBLK(sp->st_mode)) { + sol_map_key(&sol_stream, "dev", 3); + sol_map_integer(&sol_stream, sp->st_rdev); // TODO hex? + } + else { + if (f_humanval) { + /* + * Reserve one space before the size and allocate room for + * the trailing '\0'. + */ + char buffer[HUMANVALSTR_LEN - 1 + 1]; + size_t len = humanize_number(buffer, sizeof(buffer), (int64_t)sp->st_size, + "", HN_AUTOSCALE, HN_B | HN_NOSPACE | HN_DECIMAL); + + sol_map_key(&sol_stream, "hsize", 5); + sol_map_string(&sol_stream, buffer, len); + } else if (f_thousands) { /* with commas */ + /* + * Reserve 4 bytes for each byte of the size. + */ + char buffer[sizeof(sp->st_size) * 4 + 1]; + /* This format assignment needed to work round gcc bug. */ + const char *format = "%j'd "; + size_t len = snprintf(buffer, sizeof(buffer), format, sp->st_size); + + sol_map_key(&sol_stream, "csize", 5); + sol_map_string(&sol_stream, buffer, len); + } else { + sol_map_key(&sol_stream, "size", 4); + sol_map_integer(&sol_stream, sp->st_size); + } + } + + if (f_accesstime) + printtime(sp->st_atime); + else if (f_birthtime) + printtime(sp->st_birthtime); + else if (f_statustime) + printtime(sp->st_ctime); + else + printtime(sp->st_mtime); + + sol_map_key(&sol_stream, "name", 4); + sol_map_string(&sol_stream, p->fts_name, p->fts_namelen); + + if (f_type) + (void)printtype(sp->st_mode); + if (S_ISLNK(sp->st_mode)) + printlink(p); + + sol_map_end(&sol_stream); + } + + sol_array_end(&sol_stream); +} + +void +printsolshort(const DISPLAY *dp) +{ + FTSENT *p; + + sol_array_start(&sol_stream); + for (p = dp->list; p; p = p->fts_link) { + if (IS_NOPRINT(p)) + continue; + sol_string(&sol_stream, p->fts_name, p->fts_namelen); + } + sol_array_end(&sol_stream); +} +#endif Added: soc2014/zkorchev/freebsd_head/bin/ls/sol.c ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ soc2014/zkorchev/freebsd_head/bin/ls/sol.c Wed May 28 10:02:26 2014 (r268756) @@ -0,0 +1,142 @@ +/*- + * Copyright (c) 2014 + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <unistd.h> + +#include "sol.h" + +//static struct sol_stream sol; + +// TODO error checks + +int sol_init(struct sol_stream *restrict stream, enum sol_format format) +{ + stream->f = format; + stream->ctx.g = yajl_gen_alloc(0); + + //sol.f = format; + //sol.ctx.g = yajl_gen_alloc(0); + + return 0; +} + +void sol_term(struct sol_stream *restrict stream) +{ + const char *buffer; + size_t length; + + switch (stream->f) + { + case SOL_JSON: + yajl_gen_get_buf(stream->ctx.g, (const unsigned char **)&buffer, &length); + write(1, buffer, length); + write(1, "\n", 1); // TODO change this + yajl_gen_clear(stream->ctx.g); + break; + } + + yajl_gen_free(stream->ctx.g); + + /*switch (sol.f) + { + case SOL_JSON: + yajl_gen_get_buf(sol.ctx.g, (const unsigned char **)&buffer, &length); + write(1, buffer, length); + write(1, "\n", 1); // TODO change this + yajl_gen_clear(sol.ctx.g); + break; + } + + yajl_gen_free(sol.ctx.g);*/ +} + +int sol_array_start(struct sol_stream *restrict stream) +{ + yajl_gen_array_open(stream->ctx.g); + + return 0; +} + +int sol_array_end(struct sol_stream *restrict stream) +{ + yajl_gen_array_close(stream->ctx.g); + + return 0; +} + +int sol_string(struct sol_stream *restrict stream, const char *data, size_t length) +{ + // TODO ?handle special characters + yajl_gen_string(stream->ctx.g, (const unsigned char *)data, length); + + return 0; +} + +int sol_map_start(struct sol_stream *restrict stream) +{ + yajl_gen_map_open(stream->ctx.g); + + return 0; +} + +int sol_map_end(struct sol_stream *restrict stream) +{ + yajl_gen_map_close(stream->ctx.g); + + return 0; +} + +int sol_map_key(struct sol_stream *restrict stream, const char *key, size_t length) +{ + // TODO error if value is expected + + // TODO ?handle special characters + yajl_gen_string(stream->ctx.g, (const unsigned char *)key, length); + + return 0; +} + +int sol_map_string(struct sol_stream *restrict stream, const char *value, size_t length) +{ + // TODO error if key is expected? + + // TODO ?handle special characters + yajl_gen_string(stream->ctx.g, (const unsigned char *)value, length); + + return 0; +} + +int sol_map_integer(struct sol_stream *restrict stream, long long value) +{ + // TODO error if key is expected? + + // TODO ?handle special characters + yajl_gen_integer(stream->ctx.g, value); + + return 0; +} Added: soc2014/zkorchev/freebsd_head/bin/ls/sol.h ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ soc2014/zkorchev/freebsd_head/bin/ls/sol.h Wed May 28 10:02:26 2014 (r268756) @@ -0,0 +1,30 @@ +#include <yajl/yajl_gen.h> // libyajl + +enum sol_format +{ + SOL_JSON = 1, +}; + +struct sol_stream +{ + enum sol_format f; + union + { + yajl_gen g; + } ctx; +}; + +int sol_init(struct sol_stream *restrict stream, enum sol_format format); +void sol_term(struct sol_stream *restrict stream); + +int sol_array_start(struct sol_stream *restrict stream); +int sol_array_end(struct sol_stream *restrict stream); + +int sol_string(struct sol_stream *restrict stream, const char *data, size_t length); + +int sol_map_start(struct sol_stream *restrict stream); +int sol_map_end(struct sol_stream *restrict stream); + +int sol_map_key(struct sol_stream *restrict stream, const char *key, size_t length); +int sol_map_string(struct sol_stream *restrict stream, const char *value, size_t length); +int sol_map_integer(struct sol_stream *restrict stream, long long value); Modified: soc2014/zkorchev/freebsd_head/bin/ls/util.c ============================================================================== --- soc2014/zkorchev/freebsd_head/bin/ls/util.c Wed May 28 09:06:36 2014 (r268755) +++ soc2014/zkorchev/freebsd_head/bin/ls/util.c Wed May 28 10:02:26 2014 (r268756) @@ -224,11 +224,14 @@ usage(void) { (void)fprintf(stderr, -#ifdef COLORLS - "usage: ls [-ABCFGHILPRSTUWZabcdfghiklmnopqrstuwxy1,] [-D format]" -#else - "usage: ls [-ABCFHILPRSTUWZabcdfghiklmnopqrstuwxy1,] [-D format]" + "usage: ls [-ABCF" +#if defined(COLORLS) + "G" #endif - " [file ...]\n"); + "HIL" +#if defined(SOL_ON) + "O" +#endif + "PRSTUWZabcdfghiklmnopqrstuwxy1,] [-D format] [file ...]\n"); exit(1); }
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201405281002.s4SA2QQb043532>