diff -Nru tree-2.0.4/CHANGES tree-2.1.0/CHANGES --- tree-2.0.4/CHANGES 2022-09-06 13:31:06.000000000 +0000 +++ tree-2.1.0/CHANGES 2022-12-26 16:11:30.000000000 +0000 @@ -1,3 +1,57 @@ +Version 2.1.0 (12/26/2022) + This is a bit bigger release, due to not realizing that gitlab/github was + not sending me email and ice+tree@mama.indstate.edu was broken. This has + been fixed and I think I have gone through most all of the outstanding issues + that were submitted over the last few months. Note to those that are sending + me git merge requests: because I distribute this in multiple ways and places, + and I tend to manually go over patches and often re-work them in any event, I + will not likely ever directly accept any merge requests. I will still use the + patch information from them for inclusion into the code, so you are more than + welcome to still submit such merges. + + - Add support for --info and --gitignore for the --fromfile option. + (Suggested by Piotr Andruszkow) + - Add options --infofile and --gitfile to load .info and .gitignore files + explicitly. Each implies --info or --gitignore respectively. + - Add NULL guard for json_printinfo() and xml_printinfo() (and fix ftype + printing for XML) (Kenta Arai) + - Fix getcharset() to not return a getenv() pointer (fix for ENV34-C issue.) + (Kenta Arai) + - Another attempt at fixing extraneous /'s in HTML URLs/output. (Sebastian + Rose) + - Fixed XML output (Dave Rice) + - Remove the (very outdated) French version of the manpage. Look to + localization projects such as Debian's 'manpages-l10n' for localized + translations. (hmartink) + - Add support for the NO_COLOR environment variable (https://no-color.org/). + Equivalent to the -n option (can be still be overridden with -C). + (Timm Fitschen) + - Removed many C99isms to enable compiling on C90 compilers with fewer + warnings. (Sith Wijesinghe and Matthew Sessions) It should not be + necessary to avoid using a standard that is old enough to drink, + furthermore it is all but impossible to remove the remaining warnings and + have modern features like compound literals. In the meantime I've added + -std=c11 to the default CFLAGS for Linux and will likely not worry about + C90 compatibility going forward unless there is some other reason for it. + - Added a helper function for long command line arguments to clean up option + processing (and fixes the processing for a few of the options such as + --timefmt= (наб?).) + - Added --hintro and --houtro options to select files to use as the HTML + intro and outro. Use /dev/null or an empty file to eliminate them + entirely. This should make it much easier to create your own custom CSS + or embed one or more trees into a web page. + - Defer printing the version until the character set is known so we can use + the linedraw copyright symbol. + - Revert change to the error code to not return an error (code 2) when + attempting to list a non-directory that actually exists. Tree will still + return an error when attempting to list a non-existing directory/file. + - Added option --fflinks which will process symbolic link information from + a file generated with 'tree -if --noreport' when using --fromfile. + (Suggested by Chentao Credungtao) + - Updated the totals reporting code to also include in the total the file or + directory that is being listed. This should make a correct report when + doing something like 'tree *'. + Version 2.0.4 (09/06/2022) - Brown paper bag release: - Fix missing comma in JSON output. (jogbear?) diff -Nru tree-2.0.4/color.c tree-2.1.0/color.c --- tree-2.0.4/color.c 2022-06-16 13:38:02.000000000 +0000 +++ tree-2.1.0/color.c 2022-12-26 19:13:45.000000000 +0000 @@ -42,7 +42,7 @@ COL_ORPHAN, COL_SOCK, COL_SETUID, COL_SETGID, COL_STICKY_OTHER_WRITABLE, COL_OTHER_WRITABLE, COL_STICKY, COL_EXEC, COL_MISSING, COL_LEFTCODE, COL_RIGHTCODE, COL_ENDCODE, -// Keep this one last, sets the size of the color_code array: +/* Keep this one last, sets the size of the color_code array: */ DOT_EXTENSION }; @@ -75,22 +75,25 @@ void parse_dir_colors() { - char buf[1025], **arg, **c, *colors, *s, *cc; - int i, n, col; + char buf[1025], **arg, **c, *colors, *s; + int i, n, col, cc; struct extensions *e; if (Hflag) return; + s = getenv("NO_COLOR"); + if (s && s[0]) nocolor = TRUE; + if (getenv("TERM") == NULL) { colorize = FALSE; return; } + cc = getenv("CLICOLOR") != NULL; + if (getenv("CLICOLOR_FORCE") != NULL && !nocolor) force_color=TRUE; s = getenv("TREE_COLORS"); if (s == NULL) s = getenv("LS_COLORS"); - cc = getenv("CLICOLOR"); - if (getenv("CLICOLOR_FORCE") != NULL && !nocolor) force_color=TRUE; - if ((s == NULL || strlen(s) == 0) && (force_color || cc != NULL)) s = ":no=00:rs=0:fi=00:di=01;34:ln=01;36:pi=40;33:so=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:ex=01;32:*.bat=01;32:*.BAT=01;32:*.btm=01;32:*.BTM=01;32:*.cmd=01;32:*.CMD=01;32:*.com=01;32:*.COM=01;32:*.dll=01;32:*.DLL=01;32:*.exe=01;32:*.EXE=01;32:*.arj=01;31:*.bz2=01;31:*.deb=01;31:*.gz=01;31:*.lzh=01;31:*.rpm=01;31:*.tar=01;31:*.taz=01;31:*.tb2=01;31:*.tbz2=01;31:*.tbz=01;31:*.tgz=01;31:*.tz2=01;31:*.z=01;31:*.Z=01;31:*.zip=01;31:*.ZIP=01;31:*.zoo=01;31:*.asf=01;35:*.ASF=01;35:*.avi=01;35:*.AVI=01;35:*.bmp=01;35:*.BMP=01;35:*.flac=01;35:*.FLAC=01;35:*.gif=01;35:*.GIF=01;35:*.jpg=01;35:*.JPG=01;35:*.jpeg=01;35:*.JPEG=01;35:*.m2a=01;35:*.M2a=01;35:*.m2v=01;35:*.M2V=01;35:*.mov=01;35:*.MOV=01;35:*.mp3=01;35:*.MP3=01;35:*.mpeg=01;35:*.MPEG=01;35:*.mpg=01;35:*.MPG=01;35:*.ogg=01;35:*.OGG=01;35:*.ppm=01;35:*.rm=01;35:*.RM=01;35:*.tga=01;35:*.TGA=01;35:*.tif=01;35:*.TIF=01;35:*.wav=01;35:*.WAV=01;35:*.wmv=01;35:*.WMV=01;35:*.xbm=01;35:*.xpm=01;35:"; + if ((s == NULL || strlen(s) == 0) && (force_color || cc)) s = ":no=00:rs=0:fi=00:di=01;34:ln=01;36:pi=40;33:so=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:ex=01;32:*.bat=01;32:*.BAT=01;32:*.btm=01;32:*.BTM=01;32:*.cmd=01;32:*.CMD=01;32:*.com=01;32:*.COM=01;32:*.dll=01;32:*.DLL=01;32:*.exe=01;32:*.EXE=01;32:*.arj=01;31:*.bz2=01;31:*.deb=01;31:*.gz=01;31:*.lzh=01;31:*.rpm=01;31:*.tar=01;31:*.taz=01;31:*.tb2=01;31:*.tbz2=01;31:*.tbz=01;31:*.tgz=01;31:*.tz2=01;31:*.z=01;31:*.Z=01;31:*.zip=01;31:*.ZIP=01;31:*.zoo=01;31:*.asf=01;35:*.ASF=01;35:*.avi=01;35:*.AVI=01;35:*.bmp=01;35:*.BMP=01;35:*.flac=01;35:*.FLAC=01;35:*.gif=01;35:*.GIF=01;35:*.jpg=01;35:*.JPG=01;35:*.jpeg=01;35:*.JPEG=01;35:*.m2a=01;35:*.M2a=01;35:*.m2v=01;35:*.M2V=01;35:*.mov=01;35:*.MOV=01;35:*.mp3=01;35:*.MP3=01;35:*.mpeg=01;35:*.MPEG=01;35:*.mpg=01;35:*.MPG=01;35:*.ogg=01;35:*.OGG=01;35:*.ppm=01;35:*.rm=01;35:*.RM=01;35:*.tga=01;35:*.TGA=01;35:*.tif=01;35:*.TIF=01;35:*.wav=01;35:*.WAV=01;35:*.wmv=01;35:*.WMV=01;35:*.xbm=01;35:*.xpm=01;35:"; if (s == NULL || (!force_color && (nocolor || !isatty(1)))) { colorize = FALSE; @@ -99,7 +102,7 @@ colorize = TRUE; - for(int i=0; i < DOT_EXTENSION; i++) color_code[i] = NULL; + for(i=0; i < DOT_EXTENSION; i++) color_code[i] = NULL; colors = scopy(s); @@ -186,7 +189,7 @@ }; int i; - if (s == NULL) return ERROR; // Probably can't happen + if (s == NULL) return ERROR; /* Probably can't happen */ if (s[0] == '*') return DOT_EXTENSION; for(i=0;cmds[i].cmdnum;i++) { @@ -224,7 +227,7 @@ } } - // It's probably safe to assume short-circuit evaluation, but we'll do it this way: + /* It's probably safe to assume short-circuit evaluation, but we'll do it this way: */ switch(mode & S_IFMT) { case S_IFIFO: return print_color(COL_FIFO); @@ -282,69 +285,72 @@ */ const char *getcharset(void) { - #ifndef __EMX__ - return getenv("TREE_CHARSET"); - #else - static char buffer[13]; + char *cs; + static char buffer[256]; + + cs = getenv("TREE_CHARSET"); + if (cs) return strncpy(buffer,cs,255); + +#ifndef __EMX__ + return NULL; +#else ULONG aulCpList[3],ulListSize,codepage=0; - char*charset=getenv("TREE_CHARSET"); - if(charset) - return charset; - + if(!getenv("WINDOWID")) if(!DosQueryCp(sizeof aulCpList,aulCpList,&ulListSize)) if(ulListSize>=sizeof*aulCpList) codepage=*aulCpList; - - switch(codepage){ - case 437: case 775: case 850: case 851: case 852: case 855: - case 857: case 860: case 861: case 862: case 863: case 864: - case 865: case 866: case 868: case 869: case 891: case 903: - case 904: - sprintf(buffer,"IBM%03lu",codepage); - break; - case 367: - return"US-ASCII"; - case 813: - return"ISO-8859-7"; - case 819: - return"ISO-8859-1"; - case 881: case 882: case 883: case 884: case 885: - sprintf(buffer,"ISO-8859-%lu",codepage-880); - break; - case 858: case 924: - sprintf(buffer,"IBM%05lu",codepage); - break; - case 874: - return"TIS-620"; - case 897: case 932: case 942: case 943: - return"Shift_JIS"; - case 912: - return"ISO-8859-2"; - case 915: - return"ISO-8859-5"; - case 916: - return"ISO-8859-8"; - case 949: case 970: - return"EUC-KR"; - case 950: - return"Big5"; - case 954: - return"EUC-JP"; - case 1051: - return"hp-roman8"; - case 1089: - return"ISO-8859-6"; - case 1250: case 1251: case 1253: case 1254: case 1255: case 1256: - case 1257: case 1258: - sprintf(buffer,"windows-%lu",codepage); - break; - case 1252: - return"ISO-8859-1-Windows-3.1-Latin-1"; - default: - return NULL; - } - #endif + + switch(codepage) { + case 437: case 775: case 850: case 851: case 852: case 855: + case 857: case 860: case 861: case 862: case 863: case 864: + case 865: case 866: case 868: case 869: case 891: case 903: + case 904: + sprintf(buffer,"IBM%03lu",codepage); + break; + case 367: + return"US-ASCII"; + case 813: + return"ISO-8859-7"; + case 819: + return"ISO-8859-1"; + case 881: case 882: case 883: case 884: case 885: + sprintf(buffer,"ISO-8859-%lu",codepage-880); + break; + case 858: case 924: + sprintf(buffer,"IBM%05lu",codepage); + break; + case 874: + return"TIS-620"; + case 897: case 932: case 942: case 943: + return"Shift_JIS"; + case 912: + return"ISO-8859-2"; + case 915: + return"ISO-8859-5"; + case 916: + return"ISO-8859-8"; + case 949: case 970: + return"EUC-KR"; + case 950: + return"Big5"; + case 954: + return"EUC-JP"; + case 1051: + return"hp-roman8"; + case 1089: + return"ISO-8859-6"; + case 1250: case 1251: case 1253: case 1254: case 1255: case 1256: + case 1257: case 1258: + sprintf(buffer,"windows-%lu",codepage); + break; + case 1252: + return"ISO-8859-1-Windows-3.1-Latin-1"; + default: + return NULL; + } + return buffer; +#endif } void initlinedraw(int flag) diff -Nru tree-2.0.4/debian/changelog tree-2.1.0/debian/changelog --- tree-2.0.4/debian/changelog 2022-09-10 10:50:48.000000000 +0000 +++ tree-2.1.0/debian/changelog 2022-12-29 15:08:49.000000000 +0000 @@ -1,3 +1,20 @@ +tree (2.1.0-1) unstable; urgency=medium + + * [1c70da4] New upstream version 2.1.0 + - adds --hintro and --houtro options to replace the normal HTML intro and + outros with user defined ones (Closes: #865867, #939644) + - adds a --fflinks option recognizing symbolic links (Closes: #934520) + - fixes long option processing of --timefmt= (Closes: #1014621) + - Thanks to Steve Baker for explicitly fixing these! + * [8f7f775] upstream removed the (very outdated) French version of the + manpage + * [76f2c3e] debian/patches/speling: added to fix some upstream misspellings + * [e96ff99] debian/rules: update CFLAGS and drop override_dh_auto_clean + * [abdac86] debian/control: Remove unnecessary Build-Depends constraints + * [2ae5ffe] Standards-Version: 4.6.2 (no changes required) + + -- Florian Ernst Thu, 29 Dec 2022 16:08:49 +0100 + tree (2.0.4-1) unstable; urgency=medium * [97dab0a] New upstream version 2.0.4 diff -Nru tree-2.0.4/debian/control tree-2.1.0/debian/control --- tree-2.0.4/debian/control 2022-08-28 06:47:02.000000000 +0000 +++ tree-2.1.0/debian/control 2022-12-29 13:47:37.000000000 +0000 @@ -2,8 +2,8 @@ Section: utils Priority: optional Maintainer: Florian Ernst -Build-Depends: debhelper-compat (= 13), dpkg-dev (>= 1.16.1~) -Standards-Version: 4.6.1.0 +Build-Depends: debhelper-compat (= 13) +Standards-Version: 4.6.2 Rules-Requires-Root: no Homepage: http://mama.indstate.edu/users/ice/tree/ Vcs-Git: https://salsa.debian.org/debian/tree-packaging.git diff -Nru tree-2.0.4/debian/patches/manpage tree-2.1.0/debian/patches/manpage --- tree-2.0.4/debian/patches/manpage 2022-08-28 06:42:14.000000000 +0000 +++ tree-2.1.0/debian/patches/manpage 2022-12-29 14:57:41.000000000 +0000 @@ -1,4 +1,8 @@ -Last-Update: 2022-01-07 +From: Florian Ernst +Subject: drop ellipsis from manpage to make it valid, and fix a typo +Bug: https://gitlab.com/OldManProgrammer/unix-tree/-/issues/17 +Last-Update: 2022-12-29 + Index: tree/doc/tree.1 =================================================================== --- tree.orig/doc/tree.1 @@ -8,10 +12,10 @@ .\" Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA .\" -... - .TH TREE 1 "" "Tree 2.0.0" + .TH TREE 1 "" "Tree 2.1.0" .SH NAME tree \- list contents of directories in a tree-like format. -@@ -382,7 +381,7 @@ Option processing terminator. No furthe +@@ -415,7 +414,7 @@ Option processing terminator. No furthe .SH .INFO FILES @@ -20,18 +24,3 @@ while scanning a directory it is read and added to a stack of .info information. Each file is composed of comments (lines starting with hash marks (#),) or wild-card patterns which may match a file relative to the directory -Index: tree/doc/tree.fr.1 -=================================================================== ---- tree.orig/doc/tree.fr.1 -+++ tree/doc/tree.fr.1 -@@ -6,9 +6,7 @@ - .\" warranties, including, without limitation, the implied warranties - .\" of merchantability and fitness for a particular purpose. - .\" --... --.V= $Header: tree.1 1.4 1996 - 2001 $ --.TH TREE 1 "\*(V)" "Manuel du Programmeur UNIX" -+.TH TREE 1 "" "Manuel du Programmeur UNIX" - .SH NOM - tree \- liste le contenu de répertoires sous forme d'arborescence - .SH SYNOPSIS diff -Nru tree-2.0.4/debian/patches/series tree-2.1.0/debian/patches/series --- tree-2.0.4/debian/patches/series 2022-01-07 15:36:37.000000000 +0000 +++ tree-2.1.0/debian/patches/series 2022-12-29 14:57:41.000000000 +0000 @@ -1 +1,2 @@ manpage +speling diff -Nru tree-2.0.4/debian/patches/speling tree-2.1.0/debian/patches/speling --- tree-2.0.4/debian/patches/speling 1970-01-01 00:00:00.000000000 +0000 +++ tree-2.1.0/debian/patches/speling 2022-12-29 14:57:41.000000000 +0000 @@ -0,0 +1,31 @@ +From: Florian Ernst +Subject: misc spelling fixes +Bug: https://gitlab.com/OldManProgrammer/unix-tree/-/issues/17 +Last-Update: 2022-12-29 + +Index: tree/tree.c +=================================================================== +--- tree.orig/tree.c ++++ tree/tree.c +@@ -675,7 +675,7 @@ void usage(int n) + " --houtro X Use file X as the HTML outro.\n" + " ------- Input options -------\n" + " --fromfile Reads paths from files (.=stdin)\n" +- " --fflinks Process link informtion when using --fromfile.\n" ++ " --fflinks Process link information when using --fromfile.\n" + " ------- Miscellaneous options -------\n" + " --version Print version and exit.\n" + " --help Print usage and this help message and exit.\n" +Index: tree/tree.h +=================================================================== +--- tree.orig/tree.h ++++ tree/tree.h +@@ -38,7 +38,7 @@ + # include + # include + # include +- /* On many systems stat() function is idential to lstat() function. ++ /* On many systems stat() function is identical to lstat() function. + * But the OS/2 does not support symbolic links and doesn't have lstat() function. + */ + # define lstat stat diff -Nru tree-2.0.4/debian/rules tree-2.1.0/debian/rules --- tree-2.0.4/debian/rules 2022-01-07 15:22:09.000000000 +0000 +++ tree-2.1.0/debian/rules 2022-12-29 15:08:39.000000000 +0000 @@ -15,7 +15,7 @@ PREFIX = $(CURDIR)/debian/tree/usr MANDIR = $(PREFIX)/share/man -CFLAGS += -Wall -DLINUX -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 +CFLAGS += -std=c11 -pedantic -Wall -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -DLINUX override_dh_auto_build: dh_auto_build -- CFLAGS="$(CFLAGS) $(CPPFLAGS)" LDFLAGS="$(LDFLAGS)" @@ -23,8 +23,5 @@ override_dh_auto_install: $(MAKE) install PREFIX="$(PREFIX)" MANDIR="$(MANDIR)" -override_dh_auto_clean: - $(MAKE) clean - %: dh $@ diff -Nru tree-2.0.4/debian/tree.manpages tree-2.1.0/debian/tree.manpages --- tree-2.0.4/debian/tree.manpages 2022-01-08 09:07:40.000000000 +0000 +++ tree-2.1.0/debian/tree.manpages 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -doc/tree.fr.1 diff -Nru tree-2.0.4/doc/tree.1 tree-2.1.0/doc/tree.1 --- tree-2.0.4/doc/tree.1 2022-02-24 01:38:15.000000000 +0000 +++ tree-2.1.0/doc/tree.1 2022-12-25 00:57:33.000000000 +0000 @@ -1,5 +1,5 @@ .\" $Copyright: $ -.\" Copyright (c) 1996 - 2021 by Steve Baker +.\" Copyright (c) 1996 - 2022 by Steve Baker .\" All Rights reserved .\" .\" This program is free software; you can redistribute it and/or modify @@ -17,7 +17,7 @@ .\" Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA .\" ... -.TH TREE 1 "" "Tree 2.0.0" +.TH TREE 1 "" "Tree 2.1.0" .SH NAME tree \- list contents of directories in a tree-like format. .SH SYNOPSIS @@ -30,10 +30,13 @@ [\fB-P\fP \fIpattern\fP] [\fB-I\fP \fIpattern\fP] [\fB--gitignore\fP] +[\fB--gitfile\fP[\fB=\fP]\fIfile\fP] [\fB--matchdirs\fP] [\fB--metafirst\fP] [\fB--ignore-case\fP] [\fB--nolinks\fP] +[\fB--hintro\fP[\fB=\fP]\fIfile\fP] +[\fB--houtro\fP[\fB=\fP]\fIfile\fP] [\fB--inodes\fP] [\fB--device\fP] [\fB--sort\fP[\fB=\fP]\fIname\fP] @@ -43,9 +46,12 @@ [\fB--si\fP] [\fB--du\fP] [\fB--prune\fP] +[\fB--charset[\fB=\fP]X\fP] [\fB--timefmt\fP[\fB=\fP]\fIformat\fP] [\fB--fromfile\fP] +[\fB--fflinks\fP] [\fB--info\fP] +[\fB--infofile\fP[\fB=\fP]\fIfile\fP] [\fB--noreport\fP] [\fB--version\fP] [\fB--help\fP] @@ -110,8 +116,8 @@ .TP .B -R Recursively cross down the tree each \fIlevel\fP directories (see \fB-L\fP -option), and at each of them execute \fBtree\fP again adding `-o 00Tree.html' -as a new option. +option), and at each level outputting to a file named \fB00Tree.html\fP +(ala \fB-o\fP). .PP .TP .B -P \fIpattern\fP @@ -136,9 +142,13 @@ uses \fB$GIT_DIR/info/exclude\fP if present. .PP .TP +.B --gitfile\fR[\fB=\fR]\fIfile\fP +Use \fIfile\fP explicitly as a gitignore file. +.PP +.TP .B --ignore-case If a match pattern is specified by the \fB-P\fP or \fB-I\fP option, this will -cause the pattern to match without regards to the case of each letter. +cause the pattern to match without regard to the case of each letter. .PP .TP .B --matchdirs @@ -165,20 +175,24 @@ for more information on the format of .info files. .PP .TP +.B --infofile\fR[\fB=\fR]\fIfile\fP +Use \fIfile\fP explicitly as a info file. +.PP +.TP .B --noreport Omits printing of the file and directory report at the end of the tree listing. .PP .TP -.B --charset \fIcharset\fP +.B --charset\fR[\fB=\fR]\fIcharset\fP Set the character set to use when outputting HTML and for line drawing. .PP .TP -.B --filelimit \fI#\fP +.B --filelimit\fR[\fB=\fR]\fI#\fP Do not descend directories that contain more than \fI#\fP entries. .PP .TP -.B --timefmt \fIformat\fP +.B --timefmt\fR[\fB=\fR]\fIformat\fP Prints (implies -D) and formats the date according to the format string which uses the \fBstrftime\fP(3) syntax. .PP @@ -347,6 +361,16 @@ option to force color output. .PP .TP +.B --hintro\fR[\fB=\fR]\fIfile\fP +Use \fIfile\fP as the HTML intro in place of the default one. Use an empty +file or \fI/dev/null\fP to eliminate the intro altogether. +.PP +.TP +.B --houtro\fR[\fB=\fR]\fIfile\fP +Use \fIfile\fP as the HTML outro in place of the default one. Use an empty +file or \fI/dev/null\fP to eliminate the outro altogether. +.PP +.TP .B -T \fItitle\fP Sets the title and H1 header string in HTML output mode. .PP @@ -357,13 +381,22 @@ .SH INPUT OPTIONS +.TP .B --fromfile Reads a directory listing from a file rather than the file-system. Paths provided on the command line are files to read from rather than directories to search. The dot (.) directory indicates that tree should read paths from standard input. NOTE: this is only suitable for reading the output of a program -such as find, not 'tree -fi' as symlinks cannot (at least as yet) be distinguished -from files that simply contain ' -> ' as part of the filename. +such as find, not 'tree -fi' as symlinks are not distinguished from files that +simply contain ' -> ' as part of the filename unless the \fB--fflinks\fP option +is used. +.PP +.TP +.B --fflinks +Processes symbolic link information found in a file, as from the output of +\fB'tree -fi --noreport'\fP. Only the first occurrence of the string \fB' -> '\fP +is used to denote the separation of the filename from the link. +.PP .SH MISC OPTIONS @@ -417,6 +450,8 @@ .br \fBCLICOLOR_FORCE\fP Always enables colorization (effectively -C) .br +\fBNO_COLOR\fP Disable colorization (effectively -n) (see \fBhttps://no-color.org/\fP) +.br \fBLC_CTYPE\fP Locale for filename output. .br \fBLC_TIME\fP Locale for timefmt output, see \fBstrftime\fP(3). diff -Nru tree-2.0.4/doc/tree.fr.1 tree-2.1.0/doc/tree.fr.1 --- tree-2.0.4/doc/tree.fr.1 2005-03-31 13:30:31.000000000 +0000 +++ tree-2.1.0/doc/tree.fr.1 1970-01-01 00:00:00.000000000 +0000 @@ -1,235 +0,0 @@ -.\" $Copyright: $ -.\" Copyright (c) 1996 - 2001 by Steve Baker -.\" All Rights reserved -.\" -.\" This software is provided as is without any express or implied -.\" warranties, including, without limitation, the implied warranties -.\" of merchantability and fitness for a particular purpose. -.\" -... -.V= $Header: tree.1 1.4 1996 - 2001 $ -.TH TREE 1 "\*(V)" "Manuel du Programmeur UNIX" -.SH NOM -tree \- liste le contenu de répertoires sous forme d'arborescence -.SH SYNOPSIS -\fBtree\fP [ \fB-adfgilnopqstuxACDFNS\fP ] [ \fB-L\fP \fIniveau\fP [ \fB-R\fP ]] [ \fB-H\fP \fIbaseHREF\fP ] [ \fB-P\fP \fImotif\fP ] [ \fB-I\fP \fImotif\fP ] [ \fIrepertoire\fP ... ] -.br -.SH DESCRIPTION -\fITree\fP est un programme de listage récursif de répertoires qui produit -un listage des fichiers indenté en profondeur, qui est mis en couleurs à la -manière de \fIdircolors\fP si la variable d'environnement \fBLS_COLORS\fP -est activée et que la sortie est un tty. Sans arguments, \fItree\fP liste -les fichiers contenus dans le répertoire courant. Lorsque des répertoires -sont donnés en argument, \fItree\fP liste tous les fichiers et/ou -répertoires trouvés dans les répertoires donnés, chacun à son tour. Après -avoir affiché tous les fichiers et répertoires trouvés, \fItree\fP renvoie -le nombre total de fichiers et/ou de répertoires listés. - -Par défaut, quand un lien symbolique est rencontré, la chemin auquel il -renvoie est affiché après le nom du lien sous la forme suivante\ : - -.br - - nom -> chemin-reel -.br - -Si l'on donne l'option `\fB-l\fP' et que le lien symbolique renvoie à un -répertoire existant, \fItree\fP suivra le chemin du lien symbolique -comme s'il s'agissait d'un véritable répertoire. - -.br - -.SH OPTIONS -\fITree\fP comprend les commutateurs suivants en ligne de commande\ : - -.TP -.B --help -Donne en sortie un listage verbeux des options d'utilisation -.PP -.TP -.B --version -Sort la version de tree -.PP -.TP -.B --inodes -Affiche le numéro d'inode du fichier ou du répertoire -.PP -.TP -.B --device -Affiche le numéro de périphérique auquel le fichier ou le répertoire -appartient -.PP -.TP -.B --noreport -Omet d'afficher le compte des fichiers et répertoires à la fin du listage -arborescent -.PP -.TP -.B --nolinks -Désactive les hyperliens en sortie HTML -.PP -.TP -.B -a -Tous les fichiers sont affichés. Par défaut tree n'affiche pas les fichiers -cachés (ceux qui commencent par un point `.'). En aucun cas, tree n'affiche -les constructeurs de système de fichiers `.' (répertoire courant) et `..' -(répertoire parent). -.PP -.TP -.B -d -Liste uniquement les répertoires -.PP -.TP -.B -f -Affiche le chemin complet en préfixe de chaque fichier -.PP -.TP -.B -i -Fait que tree n'affiche pas les lignes d'indentation, ce qui est utile en -conjonction avec l'option \fB-f\fP -.PP -.TP -.B -l -Suit les liens symboliques s'ils pointent sur des répertoires, comme -s'ils étaient des répertoires. Les liens symboliques qui finiraient de -façon récursive sont évités, une fois détectés -.PP -.TP -.B -x -Reste exclusivement dans le système de fichiers courant, à la manière de -\fBfind \fI-xdev\fP -.PP -.TP -\fB-P \fImotif\fP -Liste exclusivement les fichiers correspondant au joker -\fImotif\fP. Remarque\ : vous devez utiliser l'option \fI-a\fP pour prendre -également en considération les fichiers commençant par un point `.'. Les -opérateurs de joker valides sont `*' (zéro caractère ou plus), `?' -(n'importe quel caractère), `[...]' (n'importe quel caractère parmi ceux -qui sont listés entre crochets (un tiret `-' optionnel peut être utilisé -pour une plage de caractères\ ; par exemple\ : [A-Z])), et `[^...]' -(n'importe quel caractère à l'exclusion de ceux qui sont listés entre -crochets). -.PP -.TP -.B -I \fImotif\fP -Ne pas lister les fichiers correspondant au joker \fImotif\fP -.PP -.TP -.B -p -Afficher les protections pour chaque fichier (comme avec ls -l) -.PP -.TP -.B -o \fInom-de-fichier\fP -Envoie la sortie vers \fInom-de-fichier\fP -.PP -.TP -.B -s -Affiche la taille de chaque fichier devant son nom -.PP -.TP -.B -u -Affiche le nom d'utilisateur du fichier, ou le numéro d'UID si aucun nom -d'utilisateur n'est disponible -.PP -.TP -.B -g -Affiche le nom de groupe du fichier, ou le numéro de GID si aucun nom de -groupe n'est disponible -.PP -.TP -.B -D -Affiche la date et l'heure de dernière modification du fichier -.PP -.TP -.B -F -Appose un `/' pour les répertoires, un `=' pour les fichiers de socket, un -`*' pour les fichiers exécutables et un `|' pour les FIFO, comme avec ls\ -F -.PP -.TP -.B -q -Affiche les caractères non affichables dans les noms de fichiers sous forme -de points d'interrogation au lieu de la notation carret par défaut -.PP -.TP -.B -N -Affiche les caractères non affichables tels quels au lieu de la notation -carret par défaut -.PP -.TP -.B -t -Trie la sortie par horaire de dernière modification, au lieu de trier -alphabétiquement -.PP -.TP -.B -n -Désactive toujours la mise en couleurs, forcée par l'option \fB-C\fP -.PP -.TP -.B -C -Active toujours la mise en couleurs, au moyen des couleurs intégrées par -défaut si la variable d'environnement LS_COLORS n'est pas activée. Utile -pour mettre en couleurs la sortie vers un tube. -.PP -.TP -.B -A -Active le graphisme ANSI de lignes pour l'affichage des lignes -d'indentation -.PP -.TP -.B -S -Active le graphisme ASCII de lignes (utile pour utiliser les polices du -mode console de Linux) -.PP -.TP -.B -L \fIniveau\fP -Maximum de profondeur d'affichage de l'arborescence des répertoires -.PP -.TP -.B -R -Descendre récursivement dans l'arborescence de chaque niveau de répertoires -(voir l'option \fB-L\fP), et pour chacun d'eux exécuter de nouveau -\fBtree\fP en y ajoutant `-o 00Tree.html' comme nouvelle option. -.PP -.TP -.B -H \fIbaseHREF\fP -Active la sortie HTML, en incluant des références HTTP. Utile pour les -sites FTP. \fIbaseHREF\fP donne l'emplacement ftp de base lorsque l'on -utilise la sortie HTML. C'est-à-dire que le répertoire local peut être -`/local/ftp/pub', mais il doit être référencé en tant que -`ftp://hostname.organization.domain/pub' (\fIbaseHREF\fP doit être -`ftp://hostname.organization.domain'). Conseils\ : n'utilisez pas les lignes -ANSI avec cette option, et n'indiquez pas plus d'un répertoire dans la -liste des répertoires. Si vous voulez utiliser des couleurs via une feuille -de style CSS, utilisez l'option -C en plus de cette option pour forcer la -sortie en couleurs. -.PP -.br -.SH FICHIERS -/etc/DIR_COLORS Base de données des couleurs système -.br -~/.dircolors Base de données des couleurs utilisateur -.br - -.SH ENVIRONNEMENT -\fBLS_COLORS\fP Informations sur les couleurs créées par dircolors - -.SH AUTEUR -Steve Baker (ice@mama.indstate.edu) -.br -La sortie HTML a été hackée par Francesc Rocher (rocher@econ.udg.es) - -.SH BOGUES -Aucun bogue connu. N'a pas été testé en profondeur. Pourrait utiliser -quelques options supplémentaires, à la manière de ls. - -.SH VOIR AUSSI -.BR dircolors (1L), -.BR ls (1L), -.BR find (1L) - -.SH TRADUCTEUR -Baptiste Mélès - -N'hésitez pas à reporter respectivement à l'auteur ou au traducteur toute -erreur ou omission dans cette page de manuel. diff -Nru tree-2.0.4/file.c tree-2.1.0/file.c --- tree-2.0.4/file.c 2022-06-16 13:38:06.000000000 +0000 +++ tree-2.1.0/file.c 2022-12-24 17:15:56.000000000 +0000 @@ -17,8 +17,8 @@ */ #include "tree.h" -extern bool dflag, Fflag, aflag, fflag, pruneflag; -extern bool noindent, force_color, matchdirs; +extern bool dflag, Fflag, aflag, fflag, pruneflag, gitignore, showinfo; +extern bool noindent, force_color, matchdirs, fflinks; extern bool reverse; extern int pattern, ipattern; @@ -31,6 +31,9 @@ extern char *file_comment, *file_pathsep; +/* 64K paths maximum */ +#define MAXPATH 64*1024 + enum ftok { T_PATHSEP, T_DIR, T_FILE, T_EOP }; char *nextpc(char **p, int *tok) @@ -38,7 +41,7 @@ static char prev = 0; char *s = *p; if (!**p) { - *tok = T_EOP; // Shouldn't happen. + *tok = T_EOP; /* Shouldn't happen. */ return NULL; } if (prev) { @@ -70,7 +73,7 @@ return n; } -// Should replace this with a Red-Black tree implementation or the like +/* Should replace this with a Red-Black tree implementation or the like */ struct _info *search(struct _info **dir, char *name) { struct _info *ptr, *prev, *n; @@ -107,12 +110,23 @@ * Recursively prune (unset show flag) files/directories of matches/ignored * patterns: */ -struct _info **fprune(struct _info *head, bool matched, bool root) +struct _info **fprune(struct _info *head, char *path, bool matched, bool root) { struct _info **dir, *new = NULL, *end = NULL, *ent, *t; - int show, count = 0; + struct comment *com; + struct ignorefile *ig = NULL; + struct infofile *inf = NULL; + char *cur, *fpath = xmalloc(sizeof(char) * MAXPATH); + int i, show, count = 0; + + strcpy(fpath, path); + cur = fpath + strlen(fpath); + *(cur++) = '/'; + + push_files(path, &ig, &inf); for(ent = head; ent != NULL;) { + strcpy(cur, ent->name); if (ent->tchild) ent->isdir = 1; show = 1; @@ -128,7 +142,15 @@ } } if (pruneflag && !matched && ent->isdir && ent->tchild == NULL) show = 0; - if (show && ent->tchild != NULL) ent->child = fprune(ent->tchild, matched, FALSE); + if (gitignore && filtercheck(path, ent->name, ent->isdir)) show = 0; + if (show && showinfo && (com = infocheck(path, ent->name, inf != NULL, ent->isdir))) { + for(i = 0; com->desc[i] != NULL; i++); + ent->comment = xmalloc(sizeof(char *) * (i+1)); + for(i = 0; com->desc[i] != NULL; i++) ent->comment[i] = scopy(com->desc[i]); + ent->comment[i] = NULL; + } + if (show && ent->tchild != NULL) ent->child = fprune(ent->tchild, fpath, matched, FALSE); + t = ent; ent = ent->next; @@ -151,13 +173,17 @@ if (topsort) qsort(dir,count,sizeof(struct _info *),topsort); + if (ig != NULL) ig = pop_filterstack(); + if (inf != NULL) inf = pop_infostack(); + free(fpath); + return dir; } struct _info **file_getfulltree(char *d, u_long lev, dev_t dev, off_t *size, char **err) { FILE *fp = (strcmp(d,".")? fopen(d,"r") : stdin); - char *path, *spath, *s; + char *path, *spath, *s, *link; long pathsize; struct _info *root = NULL, **cwd, *ent; int l, tok; @@ -167,17 +193,23 @@ fprintf(stderr,"Error opening %s for reading.\n", d); return NULL; } - // 64K paths maximum - path = xmalloc(sizeof(char *) * (pathsize = (64 * 1024))); + path = xmalloc(sizeof(char *) * (pathsize = MAXPATH)); while(fgets(path, pathsize, fp) != NULL) { if (file_comment != NULL && strcmp(path,file_comment) == 0) continue; l = strlen(path); - while(l && isspace(path[l-1])) path[--l] = '\0'; + while(l && (path[l-1] == '\n' || path[l-1] == '\r')) path[--l] = '\0'; if (l == 0) continue; spath = path; cwd = &root; + + link = fflinks? strstr(path, " -> ") : NULL; + if (link) { + *link = '\0'; + link += 4; + } + ent = NULL; do { s = nextpc(&spath, &tok); if (tok == T_PATHSEP) continue; @@ -185,22 +217,31 @@ case T_PATHSEP: continue; case T_FILE: case T_DIR: - // Should probably handle '.' and '..' entries here + /* Should probably handle '.' and '..' entries here */ ent = search(cwd, s); - // Might be empty, but should definitely be considered a directory: + /* Might be empty, but should definitely be considered a directory: */ if (tok == T_DIR) { ent->isdir = 1; ent->mode = S_IFDIR; } else { ent->mode = S_IFREG; } + cwd = &(ent->tchild); break; } } while (tok != T_FILE && tok != T_EOP); + + if (link) { + ent->isdir = 0; + ent->mode = S_IFLNK; + ent->lnk = strdup(link); + } } if (fp != stdin) fclose(fp); - // Prune accumulated directory tree: - return fprune(root, FALSE, TRUE); + free(path); + + /* Prune accumulated directory tree: */ + return fprune(root, "", FALSE, TRUE); } diff -Nru tree-2.0.4/filter.c tree-2.1.0/filter.c --- tree-2.0.4/filter.c 2022-08-26 21:24:05.000000000 +0000 +++ tree-2.1.0/filter.c 2022-12-11 16:04:38.000000000 +0000 @@ -50,6 +50,7 @@ struct ignorefile *new_ignorefile(char *path) { + struct stat st; char buf[PATH_MAX]; struct ignorefile *ig; struct pattern *remove = NULL, *remend, *p; @@ -57,8 +58,11 @@ int rev; FILE *fp; - snprintf(buf, PATH_MAX, "%s/.gitignore", path); - fp = fopen(buf, "r"); + rev = stat(path, &st); + if (rev < 0 || !S_ISREG(st.st_mode)) { + snprintf(buf, PATH_MAX, "%s/.gitignore", path); + fp = fopen(buf, "r"); + } else fp = fopen(path, "r"); if (fp == NULL) return NULL; while (fgets(buf, PATH_MAX, fp) != NULL) { @@ -102,8 +106,12 @@ struct ignorefile *pop_filterstack(void) { - struct ignorefile *ig = filterstack; + struct ignorefile *ig; struct pattern *p, *c; + + ig = filterstack; + if (ig == NULL) return NULL; + filterstack = filterstack->next; for(p=c=ig->remove; p != NULL; c = p) { @@ -134,30 +142,16 @@ for(p = ig->remove; p != NULL; p = p->next) { if (p->relative) { if (patmatch(name, p->pattern, isdir) == 1) { -// printf("> name: %s, pattern: %s\n", path, p->pattern); filter = 1; break; } } else { sprintf(fpattern + fpos, "%s", p->pattern); -// printf("> path: %s, fpattern: %s\n", path, fpattern); if (patmatch(path, fpattern, isdir) == 1) { -// printf("Matched path: %s, fpattern: %s\n", path, fpattern); filter = 1; break; } } - -// if (patmatch(path, p->pattern, isdir) == 1) { -// filter = 1; -// break; -// } -// if (p->pattern[0] == '/') continue; -// sprintf(fpattern + fpos, "%s", p->pattern); -// if (patmatch(path, fpattern, isdir) == 1) { -// filter = 1; -// break; -// } } } if (!filter) return 0; @@ -172,13 +166,6 @@ sprintf(fpattern + fpos, "%s", p->pattern); if (patmatch(path, fpattern, isdir) == 1) return 0; } - -// if (patmatch(path, p->pattern, isdir) == 1) return 0; -// -// if (p->pattern[0] == '/') continue; -// sprintf(fpattern + fpos, "%s", p->pattern); -// -// if (patmatch(path, fpattern, isdir) == 1) return 0; } } diff -Nru tree-2.0.4/html.c tree-2.1.0/html.c --- tree-2.0.4/html.c 2022-06-16 13:38:18.000000000 +0000 +++ tree-2.1.0/html.c 2022-12-11 17:13:18.000000000 +0000 @@ -21,7 +21,7 @@ extern bool dflag, lflag, pflag, sflag, Fflag, aflag, fflag, uflag, gflag; extern bool Dflag, inodeflag, devflag, Rflag, duflag, hflag, siflag; extern bool noindent, force_color, xdev, nolinks, metafirst, noreport; -extern char *host, *sp, *title; +extern char *host, *sp, *title, *Hintro, *Houtro; extern const char *charset; extern FILE *outfile; @@ -60,7 +60,6 @@ break; default: fputc(*s,fd); - // fputc(isprint(*s)?*s:'?',fd); break; } } @@ -94,15 +93,32 @@ } } +void fcat(char *filename) +{ + FILE *fp; + char buf[PATH_MAX]; + int n; + + if ((fp = fopen(filename, "r")) == NULL) return; + while((n = fread(buf, sizeof(char), PATH_MAX, fp)) > 0) { + fwrite(buf, sizeof(char), n, outfile); + } + fclose(fp); +} + void html_intro(void) { - fprintf(outfile, + if (Hintro) fcat(Hintro); + else { + fprintf(outfile, "\n" "\n" "\n" " \n" " \n" - " \n" + " \n" " %s\n" " \n" "\n" "\n" - "\t

%s

\n",charset ? charset : "iso-8859-1", version, title, title); + "\t

%s

\n", title, title); + } } void html_outtro(void) { - fprintf(outfile,"\t


\n"); - fprintf(outfile,"\t

\n"); - fprintf(outfile,hversion,linedraw->copy, linedraw->copy, linedraw->copy, linedraw->copy); - fprintf(outfile,"\t

\n"); - fprintf(outfile,"\n"); - fprintf(outfile,"\n"); + if (Houtro) fcat(Houtro); + else { + fprintf(outfile,"\t
\n"); + fprintf(outfile,"\t

\n"); + fprintf(outfile,hversion,linedraw->copy, linedraw->copy, linedraw->copy, linedraw->copy); + fprintf(outfile,"\t

\n"); + fprintf(outfile,"\n"); + fprintf(outfile,"\n"); + } } void html_print(char *s) { - for(int i=0; s[i]; i++) { + int i; + for(i=0; s[i]; i++) { if (s[i] == ' ') fprintf(outfile,"%s",sp); else fprintf(outfile,"%c", s[i]); } @@ -167,16 +188,17 @@ return 0; } -// descend == add 00Tree.html to the link +/* descend == add 00Tree.html to the link */ int html_printfile(char *dirname, char *filename, struct _info *file, int descend) { - // Switch to using 'a' elements only. Omit href attribute if not a link + int i; + /* Switch to using 'a' elements only. Omit href attribute if not a link */ fprintf(outfile,"comment) { fprintf(outfile," title=\""); - for(int i=0; file->comment[i]; i++) { + for(i=0; file->comment[i]; i++) { html_encode(outfile, file->comment[i]); if (file->comment[i+1]) fprintf(outfile, "\n"); } @@ -193,7 +215,7 @@ url_encode(outfile, filename); fprintf(outfile,"%s%s\"",(descend > 1? "/00Tree.html" : ""), (file->isdir?"/":"")); } else { - fprintf(outfile,"%s\"",(descend > 1? "/00Tree.html" : "")); + fprintf(outfile,"%s/\"",(descend > 1? "/00Tree.html" : "")); } } } diff -Nru tree-2.0.4/info.c tree-2.1.0/info.c --- tree-2.0.4/info.c 2022-06-16 13:38:21.000000000 +0000 +++ tree-2.1.0/info.c 2022-12-11 16:02:16.000000000 +0000 @@ -33,10 +33,11 @@ struct comment *new_comment(struct pattern *phead, char **line, int lines) { + int i; + struct comment *com = xmalloc(sizeof(struct comment)); com->pattern = phead; com->desc = xmalloc(sizeof(char *) * (lines+1)); - int i; for(i=0; i < lines; i++) com->desc[i] = line[i]; com->desc[i] = NULL; com->next = NULL; @@ -45,19 +46,20 @@ struct infofile *new_infofile(char *path) { + struct stat st; char buf[PATH_MAX]; struct infofile *inf; struct comment *chead = NULL, *cend = NULL, *com; struct pattern *phead = NULL, *pend = NULL, *p; char *line[PATH_MAX]; FILE *fp; - int lines = 0; + int i, lines = 0; - if (strcmp(path,INFO_PATH) == 0) fp = fopen(path, "r"); - else { + i = stat(path, &st); + if (i < 0 || !S_ISREG(st.st_mode)) { snprintf(buf, PATH_MAX, "%s/.info", path); fp = fopen(buf, "r"); - } + } else fp = fopen(path, "r"); if (fp == NULL) return NULL; while (fgets(buf, PATH_MAX, fp) != NULL) { @@ -69,16 +71,16 @@ line[lines++] = scopy(buf+1); } else { if (lines) { - // Save previous pattern/message: + /* Save previous pattern/message: */ if (phead) { com = new_comment(phead, line, lines); if (!chead) chead = cend = com; else cend = cend->next = com; } else { - // Accumulated info message lines w/ no associated pattern? - for(int i=0; i < lines; i++) free(line[i]); + /* Accumulated info message lines w/ no associated pattern? */ + for(i=0; i < lines; i++) free(line[i]); } - // Reset for next pattern/message: + /* Reset for next pattern/message: */ phead = pend = NULL; lines = 0; } @@ -92,7 +94,7 @@ if (!chead) chead = cend = com; else cend = cend->next = com; } else { - for(int i=0; i < lines; i++) free(line[i]); + for(i=0; i < lines; i++) free(line[i]); } fclose(fp); @@ -114,20 +116,23 @@ struct infofile *pop_infostack(void) { - struct infofile *inf = infostack; + struct infofile *inf; struct comment *cn, *cc; struct pattern *p, *c; - infostack = infostack->next; + int i; + inf = infostack; if (inf == NULL) return NULL; + infostack = infostack->next; + for(cn = cc = inf->comments; cn != NULL; cc = cn) { cn = cn->next; for(p=c=cc->pattern; p != NULL; c = p) { p=p->next; free(c->pattern); } - for(int i=0; cc->desc[i] != NULL; i++) free(cc->desc[i]); + for(i=0; cc->desc[i] != NULL; i++) free(cc->desc[i]); free(cc->desc); free(cc); } diff -Nru tree-2.0.4/json.c tree-2.1.0/json.c --- tree-2.0.4/json.c 2022-08-30 02:44:16.000000000 +0000 +++ tree-2.1.0/json.c 2022-12-04 22:30:08.000000000 +0000 @@ -92,7 +92,7 @@ char nbuf[64]; int i; psize(nbuf,ent->size); - for(i=0; isspace(nbuf[i]); i++); // trim() hack + for(i=0; isspace(nbuf[i]); i++); /* trim() hack */ fprintf(outfile, ",\"size\":\"%s\"", nbuf+i); } else fprintf(outfile, ",\"size\":%lld", (long long int)ent->size); @@ -120,8 +120,10 @@ if (!noindent) json_indent(level); - if (file->lnk) mt = file->mode & S_IFMT; - else mt = file->mode & S_IFMT; + if (file != NULL) { + if (file->lnk) mt = file->mode & S_IFMT; + else mt = file->mode & S_IFMT; + } else mt = 0; for(t=0;ifmt[t];t++) if (ifmt[t] == mt) break; @@ -132,13 +134,15 @@ int json_printfile(char *dirname, char *filename, struct _info *file, int descend) { + int i; + fprintf(outfile, ",\"name\":\""); json_encode(outfile, filename); fputc('"',outfile); if (file && file->comment) { fprintf(outfile, ",\"info\":\""); - for(int i=0; file->comment[i]; i++) { + for(i=0; file->comment[i]; i++) { json_encode(outfile, file->comment[i]); if (file->comment[i+1]) fprintf(outfile, "\\n"); } @@ -174,7 +178,7 @@ void json_close(struct _info *file, int level, int needcomma) { - if (!noindent) json_indent(level-1); + if (!noindent) json_indent(level); fprintf(outfile,"]}%s%s", needcomma? ",":"", noindent? "":"\n"); } diff -Nru tree-2.0.4/list.c tree-2.1.0/list.c --- tree-2.0.4/list.c 2022-08-26 19:13:01.000000000 +0000 +++ tree-2.1.0/list.c 2022-12-24 18:06:56.000000000 +0000 @@ -57,7 +57,7 @@ void emit_tree(char **dirname, bool needfulltree) { - struct totals tot = { 0 }; + struct totals tot = { 0 }, subtotal; struct ignorefile *ig = NULL; struct infofile *inf = NULL; struct _info **dir = NULL, *info = NULL; @@ -93,21 +93,25 @@ } else info = NULL; needsclosed = lc.printfile(NULL, dirname[i], info, (dir != NULL) || (!dir && n)); + subtotal = (struct totals){0, 0, 0}; + if (duflag) subtotal.size = info? info->size : 0; if (!dir && n) { lc.error("error opening dir"); lc.newline(info, 0, 0, dirname[i+1] != NULL); - errors++; + if (!info) errors++; + else subtotal.files++; } else if (flimit > 0 && n > flimit) { sprintf(errbuf,"%d entries exceeds filelimit, not opening dir", n); lc.error(errbuf); lc.newline(info, 0, 0, dirname[i+1] != NULL); - errors++; + subtotal.dirs++; } else { lc.newline(info, 0, 0, 0); if (dir) { - tot = listdir(dirname[i], dir, 1, st.st_dev, needfulltree); - } else tot = (struct totals){0, 0}; + subtotal = listdir(dirname[i], dir, 1, st.st_dev, needfulltree); + subtotal.dirs++; + } } if (dir) { free_dir(dir); @@ -115,8 +119,11 @@ } if (needsclosed) lc.close(info, 0, dirname[i+1] != NULL); - if (duflag) tot.size = info->size; - else tot.size += st.st_size; + tot.files += subtotal.files; + tot.dirs += subtotal.dirs; + tot.size += subtotal.size; +// if (duflag) tot.size = info->size; +// else tot.size += st.st_size; if (ig != NULL) ig = pop_filterstack(); if (inf != NULL) inf = pop_infostack(); diff -Nru tree-2.0.4/Makefile tree-2.1.0/Makefile --- tree-2.0.4/Makefile 2022-09-06 13:31:53.000000000 +0000 +++ tree-2.1.0/Makefile 2022-12-26 19:15:45.000000000 +0000 @@ -21,7 +21,7 @@ CC=gcc INSTALL=install -VERSION=2.0.4 +VERSION=2.1.0 TREE_DEST=tree DESTDIR=${PREFIX}/bin MAN=tree.1 @@ -32,8 +32,8 @@ # Uncomment options below for your particular OS: # Linux defaults: -#CFLAGS+=-ggdb -pedantic -Wall -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -CFLAGS+=-O3 -pedantic -Wall -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 +#CFLAGS+=-ggdb -std=c11 -pedantic -Wall -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 +CFLAGS+=-O3 -std=c11 -pedantic -Wall -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 #LDFLAGS+=-s # Uncomment for FreeBSD: diff -Nru tree-2.0.4/README tree-2.1.0/README --- tree-2.0.4/README 2022-08-26 22:14:49.000000000 +0000 +++ tree-2.1.0/README 2022-12-26 19:29:26.000000000 +0000 @@ -279,6 +279,31 @@ Saniya Maheshwari / Mig-hub ? / Carlos Pinto - Reported various issues with --gitignore +Piotr Andruszkow + - Suggested adding support for --info and --gitignore for the --fromfile + option. + +Kenta Arai + - Add NULL guard for json_printinfo() and xml_printinfo() (and fix ftype + printing for XML) + - Fix getcharset() to not return a getenv() pointer. + +Sebastian Rose + - Another attempt at fixing extraneous /'s in HTML URLs/output. + +Dave Rice + - Fixed XML output + +Timm Fitschen + - Suggest adding support for the NO_COLOR environment variable. + +Chentao Credungtao + - Suggested supporting symbolic links in --fromfile (--fflinks option) + +Sith Wijesinghe and Matthew Sessions + - Remove many C90 isms to make compiling with C90 compilers easier. + + And many others whom I've failed to keep track of. I should have started this list years ago. diff -Nru tree-2.0.4/tree.c tree-2.1.0/tree.c --- tree-2.0.4/tree.c 2022-09-04 22:31:17.000000000 +0000 +++ tree-2.1.0/tree.c 2022-12-25 01:01:54.000000000 +0000 @@ -18,11 +18,11 @@ #include "tree.h" -char *version ="$Version: $ tree v2.0.4 (c) 1996 - 2022 by Steve Baker, Thomas Moore, Francesc Rocher, Florian Sesser, Kyosuke Tokoro $"; -char *hversion="\t\t tree v2.0.4 %s 1996 - 2022 by Steve Baker and Thomas Moore
\n" - "\t\t HTML output hacked and copyleft %s 1998 by Francesc Rocher
\n" - "\t\t JSON output hacked and copyleft %s 2014 by Florian Sesser
\n" - "\t\t Charsets / OS/2 support %s 2001 by Kyosuke Tokoro\n"; +char *version = "$Version: $ tree v2.1.0 %s 1996 - 2022 by Steve Baker, Thomas Moore, Francesc Rocher, Florian Sesser, Kyosuke Tokoro $"; +char *hversion= "\t\t tree v2.1.0 %s 1996 - 2022 by Steve Baker and Thomas Moore
\n" + "\t\t HTML output hacked and copyleft %s 1998 by Francesc Rocher
\n" + "\t\t JSON output hacked and copyleft %s 2014 by Florian Sesser
\n" + "\t\t Charsets / OS/2 support %s 2001 by Kyosuke Tokoro\n"; /* Globals */ bool dflag, lflag, pflag, sflag, Fflag, aflag, fflag, uflag, gflag; @@ -30,7 +30,7 @@ bool Hflag, siflag, cflag, Xflag, Jflag, duflag, pruneflag; bool noindent, force_color, nocolor, xdev, noreport, nolinks; bool ignorecase, matchdirs, fromfile, metafirst, gitignore, showinfo; -bool reverse; +bool reverse, fflinks; int flimit; struct listingcalls lc; @@ -39,12 +39,13 @@ char **patterns = NULL, **ipatterns = NULL; char *host = NULL, *title = "Directory Tree", *sp = " ", *_nl = "\n"; +char *Hintro = NULL, *Houtro = NULL; char *file_comment = "#", *file_pathsep = "/"; char *timefmt = NULL; const char *charset = NULL; struct _info **(*getfulltree)(char *d, u_long lev, dev_t dev, off_t *size, char **err) = unix_getfulltree; -//off_t (*listdir)(char *, int *, int *, u_long, dev_t) = unix_listdir; +/* off_t (*listdir)(char *, int *, int *, u_long, dev_t) = unix_listdir; */ int (*basesort)() = alnumsort; int (*topsort)() = NULL; @@ -91,18 +92,47 @@ extern char *leftcode, *rightcode, *endcode; extern const struct linedraw *linedraw; +/* Time to switch to getopt()? */ +char *long_arg(char *argv[], int i, int *j, int *n, char *prefix) { + char *ret = NULL; + int len = strlen(prefix); + + if (!strncmp(prefix,argv[i],len)) { + *j = len; + if (*(argv[i]+(*j)) == '=') { + if (*(argv[i]+ (++(*j)))) { + ret=(argv[i] + (*j)); + *j = strlen(argv[i])-1; + } else { + fprintf(stderr,"tree: Missing argument to %s=\n", prefix); + exit(1); + } + } else if (argv[*n] != NULL) { + ret = argv[*n]; + (*n)++; + *j = strlen(argv[i])-1; + } else { + fprintf(stderr,"tree: Missing argument to %s\n", prefix); + exit(1); + } + } + return ret; +} int main(int argc, char **argv) { + struct ignorefile *ig; + struct infofile *inf; char **dirname = NULL; - int i,j=0,k,n,optf,p = 0,q = 0; - char *stmp, *outfilename = NULL;; - bool needfulltree; + int i, j=0, k, n, optf, p = 0, q = 0; + char *stmp, *outfilename = NULL, *arg; + char *stddata_fd; + bool needfulltree, showversion = FALSE; aflag = dflag = fflag = lflag = pflag = sflag = Fflag = uflag = gflag = FALSE; Dflag = qflag = Nflag = Qflag = Rflag = hflag = Hflag = siflag = cflag = FALSE; noindent = force_color = nocolor = xdev = noreport = nolinks = reverse = FALSE; - ignorecase = matchdirs = inodeflag = devflag = Xflag = Jflag = FALSE; + ignorecase = matchdirs = inodeflag = devflag = Xflag = Jflag = fflinks = FALSE; duflag = pruneflag = metafirst = gitignore = FALSE; flimit = 0; @@ -134,8 +164,8 @@ #endif #ifdef __linux__ - // Output JSON automatically to "stddata" if present: - char *stddata_fd = getenv(ENV_STDDATA_FD); + /* Output JSON automatically to "stddata" if present: */ + stddata_fd = getenv(ENV_STDDATA_FD); if (stddata_fd != NULL) { int std_fd = atoi(stddata_fd); if (std_fd <= 0) std_fd = STDDATA_FILENO; @@ -216,7 +246,7 @@ break; case 'P': if (argv[n] == NULL) { - fprintf(stderr,"tree: missing argument to -P option.\n"); + fprintf(stderr,"tree: Missing argument to -P option.\n"); exit(1); } if (pattern >= maxpattern-1) patterns = xrealloc(patterns, sizeof(char *) * (maxpattern += 10)); @@ -225,7 +255,7 @@ break; case 'I': if (argv[n] == NULL) { - fprintf(stderr,"tree: missing argument to -I option.\n"); + fprintf(stderr,"tree: Missing argument to -I option.\n"); exit(1); } if (ipattern >= maxipattern-1) ipatterns = xrealloc(ipatterns, sizeof(char *) * (maxipattern += 10)); @@ -281,15 +311,18 @@ html_close, html_report }; if (argv[n] == NULL) { - fprintf(stderr,"tree: missing argument to -H option.\n"); + fprintf(stderr,"tree: Missing argument to -H option.\n"); exit(1); } host = argv[n++]; + k = strlen(host)-1; + /* Allows a / if that is the only character as the 'host': */ + if (k && host[k] == '/') host[k] = '\0'; sp = " "; break; case 'T': if (argv[n] == NULL) { - fprintf(stderr,"tree: missing argument to -T option.\n"); + fprintf(stderr,"tree: Missing argument to -T option.\n"); exit(1); } title = argv[n++]; @@ -310,7 +343,7 @@ break; case 'o': if (argv[n] == NULL) { - fprintf(stderr,"tree: missing argument to -o option.\n"); + fprintf(stderr,"tree: Missing argument to -o option.\n"); exit(1); } outfilename = argv[n++]; @@ -321,14 +354,15 @@ optf = FALSE; break; } + /* Long options that don't take parameters should just use strcmp: */ if (!strcmp("--help",argv[i])) { usage(2); exit(0); } if (!strcmp("--version",argv[i])) { - char *v = version+12; - printf("%.*s\n",(int)strlen(v)-1,v); - exit(0); + j = strlen(argv[i])-1; + showversion = TRUE; + break; } if (!strcmp("--inodes",argv[i])) { j = strlen(argv[i])-1; @@ -360,156 +394,124 @@ topsort = filesfirst; break; } - if (!strncmp("--filelimit",argv[i],11)) { - j = 11; - if (*(argv[i]+11) == '=') { - if (*(argv[i]+12)) { - flimit=atoi(argv[i]+12); - j = strlen(argv[i])-1; - break; - } else { - fprintf(stderr,"tree: missing argument to --filelimit=\n"); - exit(1); - } - } - if (argv[n] != NULL) { - flimit = atoi(argv[n++]); - j = strlen(argv[i])-1; - } else { - fprintf(stderr,"tree: missing argument to --filelimit\n"); - exit(1); - } + if ((arg = long_arg(argv, i, &j, &n, "--filelimit")) != NULL) { + flimit = atoi(arg); break; } - if (!strncmp("--charset",argv[i],9)){ - j = 9; - if (*(argv[i]+j) == '=') { - if (*(charset = (argv[i]+10))) { - j = strlen(argv[i])-1; - break; - } else { - fprintf(stderr,"tree: missing argument to --charset=\n"); - exit(1); - } - } - if (argv[n] != NULL) { - charset = argv[n++]; - j = strlen(argv[i])-1; - } else { - initlinedraw(1); - exit(1); - } + if ((arg = long_arg(argv, i, &j, &n, "--charset")) != NULL) { + charset = arg; break; } - if (!strncmp("--si", argv[i], 4)) { + if (!strcmp("--si", argv[i])) { j = strlen(argv[i])-1; sflag = TRUE; hflag = TRUE; siflag = TRUE; break; } - if (!strncmp("--du",argv[i],4)) { + if (!strcmp("--du",argv[i])) { j = strlen(argv[i])-1; sflag = TRUE; duflag = TRUE; break; } - if (!strncmp("--prune",argv[i],7)) { + if (!strcmp("--prune",argv[i])) { j = strlen(argv[i])-1; pruneflag = TRUE; break; } - if (!strncmp("--timefmt",argv[i],9)) { - j = 9; - if (*(argv[i]+j) == '=') { - if (*(argv[i]+ (++j))) { - timefmt=scopy(argv[i]+j); - j = strlen(argv[i])-1; - break; - }else { - fprintf(stderr,"tree: missing argument to --timefmt=\n"); - exit(1); - } - } else if (argv[n] != NULL) { - timefmt = scopy(argv[n]); - n++; - j = strlen(argv[i])-1; - } else { - fprintf(stderr,"tree: missing argument to --timefmt\n"); - exit(1); - } + if ((arg = long_arg(argv, i, &j, &n, "--timefmt")) != NULL) { + timefmt = scopy(arg); Dflag = TRUE; break; } - if (!strncmp("--ignore-case",argv[i],13)) { + if (!strcmp("--ignore-case",argv[i])) { j = strlen(argv[i])-1; ignorecase = TRUE; break; } - if (!strncmp("--matchdirs",argv[i],11)) { + if (!strcmp("--matchdirs",argv[i])) { j = strlen(argv[i])-1; matchdirs = TRUE; break; } - if (!strncmp("--sort",argv[i],6)) { - j = 6; - if (*(argv[i]+j) == '=') { - if (*(argv[i]+(++j))) { - stmp = argv[i]+j; - j = strlen(argv[i])-1; - } else { - fprintf(stderr,"tree: missing argument to --sort=\n"); - exit(1); - } - } else if (argv[n] != NULL) { - stmp = argv[n++]; - j = strlen(argv[i])-1; - } else { - fprintf(stderr,"tree: missing argument to --sort\n"); - exit(1); - } + if ((arg = long_arg(argv, i, &j, &n, "--sort")) != NULL) { basesort = NULL; for(k=0;sorts[k].name;k++) { - if (strcasecmp(sorts[k].name,stmp) == 0) { + if (strcasecmp(sorts[k].name,arg) == 0) { basesort = sorts[k].cmpfunc; break; } } if (basesort == NULL) { - fprintf(stderr,"tree: sort type '%s' not valid, should be one of: ", stmp); + fprintf(stderr,"tree: Sort type '%s' not valid, should be one of: ", arg); for(k=0; sorts[k].name; k++) printf("%s%c", sorts[k].name, sorts[k+1].name? ',': '\n'); exit(1); } break; } - if (!strncmp("--fromfile",argv[i],10)) { + if (!strcmp("--fromfile",argv[i])) { j = strlen(argv[i])-1; fromfile=TRUE; getfulltree = file_getfulltree; break; } - if (!strncmp("--metafirst",argv[i],11)) { + if (!strcmp("--metafirst",argv[i])) { j = strlen(argv[i])-1; metafirst=TRUE; break; } - if (!strncmp("--gitignore",argv[i],11)) { + if ((arg = long_arg(argv, i, &j, &n, "--gitfile")) != NULL) { + gitignore=TRUE; + ig = new_ignorefile(arg); + if (ig != NULL) push_filterstack(ig); + else { + fprintf(stderr,"tree: Could not load gitignore file\n"); + exit(1); + } + break; + } + if (!strcmp("--gitignore",argv[i])) { j = strlen(argv[i])-1; gitignore=TRUE; break; - } - if (!strncmp("--info",argv[i],6)) { + } + if (!strcmp("--info",argv[i])) { j = strlen(argv[i])-1; showinfo=TRUE; break; - } + } + if ((arg = long_arg(argv, i, &j, &n, "--infofile")) != NULL) { + showinfo = TRUE; + inf = new_infofile(arg); + if (inf != NULL) push_infostack(inf); + else { + fprintf(stderr,"tree: Could not load infofile\n"); + exit(1); + } + break; + } + if ((arg = long_arg(argv, i, &j, &n, "--hintro")) != NULL) { + Hintro = scopy(arg); + break; + } + if ((arg = long_arg(argv, i, &j, &n, "--houtro")) != NULL) { + Houtro = scopy(arg); + break; + } + if (!strcmp("--fflinks",argv[i])) { + j = strlen(argv[i])-1; + fflinks=TRUE; + break; + } + fprintf(stderr,"tree: Invalid argument `%s'.\n",argv[i]); usage(1); exit(1); } default: - printf("here i = %d, n = %d\n", i, n); + /* printf("here i = %d, n = %d\n", i, n); */ fprintf(stderr,"tree: Invalid argument -`%c'.\n",argv[i][j]); usage(1); exit(1); @@ -528,6 +530,11 @@ parse_dir_colors(); initlinedraw(0); + + if (showversion) { + print_version(TRUE); + exit(0); + } /* Insure sensible defaults and sanity check options: */ if (dirname == NULL) { @@ -540,7 +547,7 @@ if (dflag) pruneflag = FALSE; /* You'll just get nothing otherwise. */ if (Rflag && (Level == -1)) Rflag = FALSE; - // Not going to implement git configs so no core.excludesFile support. + /* Not going to implement git configs so no core.excludesFile support. */ if (gitignore && (stmp = getenv("GIT_DIR"))) { char *path = xmalloc(PATH_MAX); snprintf(path, PATH_MAX, "%s/info/exclude", stmp); @@ -560,6 +567,14 @@ return errors ? 2 : 0; } +void print_version(int nl) +{ + char buf[PATH_MAX], *v; + v = version+12; + sprintf(buf, "%.*s%s", (int)strlen(v)-2, v, nl?"\n":""); + fprintf(outfile, buf, linedraw->copy); +} + void setoutput(char *filename) { if (filename == NULL) { @@ -588,11 +603,12 @@ fprintf(n < 2? stderr: stdout, "usage: tree [-acdfghilnpqrstuvxACDFJQNSUX] [-L level [-R]] [-H baseHREF]\n" "\t[-T title] [-o filename] [-P pattern] [-I pattern] [--gitignore]\n" - "\t[--matchdirs] [--metafirst] [--ignore-case] [--nolinks] [--inodes]\n" - "\t[--device] [--sort[=]] [--dirsfirst] [--filesfirst]\n" - "\t[--filelimit #] [--si] [--du] [--prune] [--charset X]\n" - "\t[--timefmt[=]format] [--fromfile] [--noreport] [--version] [--help]\n" - "\t[--] [directory ...]\n"); + "\t[--gitfile[=]file] [--matchdirs] [--metafirst] [--ignore-case]\n" + "\t[--nolinks] [--hintro[=]file] [--houtro[=]file] [--inodes] [--device]\n" + "\t[--sort[=]] [--dirsfirst] [--filesfirst] [--filelimit #] [--si]\n" + "\t[--du] [--prune] [--charset[=]X] [--timefmt[=]format] [--fromfile]\n" + "\t[--fflinks] [--info] [--infofile[=]file] [--noreport] [--version]\n" + "\t[--help] [--] [directory ...]\n"); if (n < 2) return; fprintf(stdout, @@ -607,11 +623,13 @@ " -P pattern List only those files that match the pattern given.\n" " -I pattern Do not list files that match the given pattern.\n" " --gitignore Filter by using .gitignore files.\n" + " --gitfile X Explicitly read gitignore file.\n" " --ignore-case Ignore case when pattern matching.\n" " --matchdirs Include directory names in -P pattern matching.\n" " --metafirst Print meta-data at the beginning of each line.\n" " --prune Prune empty directories from the output.\n" " --info Print information about files found in .info files.\n" + " --infofile X Explicitly read info file.\n" " --noreport Turn off file/directory count at end of tree listing.\n" " --charset X Use charset X for terminal/HTML and indentation line output.\n" " --filelimit # Do not descend dirs with more than # files in them.\n" @@ -653,8 +671,11 @@ " -H baseHREF Prints out HTML format with baseHREF as top directory.\n" " -T string Replace the default HTML title and H1 header with string.\n" " --nolinks Turn off hyperlinks in HTML output.\n" + " --hintro X Use file X as the HTML intro.\n" + " --houtro X Use file X as the HTML outro.\n" " ------- Input options -------\n" " --fromfile Reads paths from files (.=stdin)\n" + " --fflinks Process link informtion when using --fromfile.\n" " ------- Miscellaneous options -------\n" " --version Print version and exit.\n" " --help Print usage and this help message and exit.\n" @@ -667,7 +688,8 @@ */ int patignore(char *name, int isdir) { - for(int i=0; i < ipattern; i++) + int i; + for(i=0; i < ipattern; i++) if (patmatch(name, ipatterns[i], isdir)) return 1; return 0; } @@ -677,13 +699,12 @@ */ int patinclude(char *name, int isdir) { -// printf("%s ", name); - for(int i=0; i < pattern; i++) + int i; + for(i=0; i < pattern; i++) { if (patmatch(name, patterns[i], isdir)) { -// printf("included\n"); return 1; } -// printf("failed include\n"); + } return 0; } @@ -696,7 +717,7 @@ static int lbufsize = 0; struct _info *ent; struct stat st, lst; - int len, rs; + int len, rs, isdir; if (lbuf == NULL) lbuf = xmalloc(lbufsize = PATH_MAX); @@ -711,7 +732,7 @@ st.st_ino = lst.st_ino; } - int isdir = (st.st_mode & S_IFMT) == S_IFDIR; + isdir = (st.st_mode & S_IFMT) == S_IFDIR; #ifndef __EMX__ if (gitignore && filtercheck(path, name, isdir)) return NULL; @@ -725,7 +746,7 @@ if (dflag && ((st.st_mode & S_IFMT) != S_IFDIR)) return NULL; #ifndef __EMX__ -// if (pattern && ((lst.st_mode & S_IFMT) == S_IFLNK) && !lflag) continue; +/* if (pattern && ((lst.st_mode & S_IFMT) == S_IFLNK) && !lflag) continue; */ #endif ent = (struct _info *)xmalloc(sizeof(struct _info)); @@ -869,7 +890,7 @@ stat(d,&sb); dev = sb.st_dev; } - // if the directory name matches, turn off pattern matching for contents + /* if the directory name matches, turn off pattern matching for contents */ if (matchdirs && pattern) { lev_tmp = lev; start_rel_path = d + strlen(d); @@ -897,7 +918,6 @@ } if (dir == NULL && n) { *err = scopy("error opening dir"); - errors++; return NULL; } if (n == 0) { @@ -943,7 +963,7 @@ saveino((*dir)->inode, (*dir)->dev); (*dir)->child = unix_getfulltree(path,lev+1,dev,&((*dir)->size),&((*dir)->err)); } - // prune empty folders, unless they match the requested pattern + /* prune empty folders, unless they match the requested pattern */ if (pruneflag && (*dir)->child == NULL && !(matchdirs && pattern && patinclude((*dir)->name, (*dir)->isdir))) { sp = *dir; @@ -959,7 +979,7 @@ dir++; } - // sorting needs to be deferred for --du: + /* sorting needs to be deferred for --du: */ if (topsort) qsort(sav,n,sizeof(struct _info *),topsort); free(path); @@ -1086,7 +1106,7 @@ } } -static inline char cond_lower(char c) +static char cond_lower(char c) { return ignorecase ? tolower(c) : c; } @@ -1123,7 +1143,6 @@ return match; } -// printf("> buf[%s], pat[%s]\n", buf, pat); while(*pat && match) { switch(*pat) { case '[': @@ -1156,7 +1175,6 @@ pat++; if(!*pat) { int f = (strchr(buf, '/') == NULL); -// printf("end *: buf = '%s', f = %d\n", buf, f); return f; } match = 0; @@ -1166,18 +1184,15 @@ if(!*pat) return 1; while(*buf && !(match = patmatch(buf, pat, isdir))) { - // ../**/.. is allowed to match a null /: + /* ** between two /'s is allowed to match a null /: */ if (pprev == '/' && *pat == '/' && *(pat+1) && (match = patmatch(buf, pat+1, isdir))) return match; buf++; while(*buf && *buf != '/') buf++; } } else { -// printf("* buf[%s], pat[%s]\n", buf, pat); while(*buf && !(match = patmatch(buf++, pat, isdir))) if (*buf == '/') break; -// if (!*buf && !match) match = patmatch(buf, pat, isdir); } -// printf("*|%d buf[%s], pat[%s]\n", match, buf, pat); if (!match && (!*buf || *buf == '/')) match = patmatch(buf, pat, isdir); return match; case '?': diff -Nru tree-2.0.4/tree.h tree-2.1.0/tree.h --- tree-2.0.4/tree.h 2022-06-16 13:38:36.000000000 +0000 +++ tree-2.1.0/tree.h 2022-12-11 17:12:33.000000000 +0000 @@ -59,7 +59,7 @@ #define mbstowcs(w,m,x) mbsrtowcs(w,(const char**)(& #m),x,NULL) #endif -// Start using PATH_MAX instead of the magic number 4096 everywhere. +/* Start using PATH_MAX instead of the magic number 4096 everywhere. */ #ifndef PATH_MAX #define PATH_MAX 4096 #endif @@ -189,6 +189,7 @@ /* Function prototypes: */ /* tree.c */ void setoutput(char *filename); +void print_version(int nl); void usage(int); void push_files(char *dir, struct ignorefile **ig, struct infofile **inf); int patignore(char *name, int isdir); diff -Nru tree-2.0.4/xml.c tree-2.1.0/xml.c --- tree-2.0.4/xml.c 2022-08-26 19:48:00.000000000 +0000 +++ tree-2.1.0/xml.c 2022-12-04 22:36:52.000000000 +0000 @@ -104,8 +104,10 @@ if (!noindent) xml_indent(level); - if (file->lnk) mt = file->mode & S_IFMT; - else mt = file->mode & S_IFMT; + if (file != NULL) { + if (file->lnk) mt = file->mode & S_IFMT; + else mt = file->mode & S_IFMT; + } else mt = 0; for(t=0;ifmt[t];t++) if (ifmt[t] == mt) break; @@ -116,15 +118,7 @@ int xml_printfile(char *dirname, char *filename, struct _info *file, int descend) { - int t, mt; - - if (file) { - if (file->lnk) mt = file->mode & S_IFMT; - else mt = file->mode & S_IFMT; - } else mt = 0; - for(t=0;ifmt[t];t++) - if (ifmt[t] == mt) break; - fprintf(outfile,"<%s", ftype[t]); + int i; fprintf(outfile, " name=\""); html_encode(outfile, filename); @@ -132,7 +126,7 @@ if (file && file->comment) { fprintf(outfile, " info=\""); - for(int i=0; file->comment[i]; i++) { + for(i=0; file->comment[i]; i++) { html_encode(outfile, file->comment[i]); if (file->comment[i+1]) fprintf(outfile, "\n"); } @@ -164,7 +158,7 @@ void xml_close(struct _info *file, int level, int needcomma) { - if (!noindent && level >= 0) xml_indent(level-1); + if (!noindent && level >= 0) xml_indent(level); fprintf(outfile,"%s", file? file->tag : "unknown", noindent? "" : "\n"); }