+/*
+ * Test program for listing files during regression testing
+ */
+
+/*
+ Copyright (C) 2000-2003 Kern Sibbald and John Walker
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of
+ the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public
+ License along with this program; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ MA 02111-1307, USA.
+
+ */
+
+#include "bacula.h"
+#include "findlib/find.h"
+
+
+/* Global variables */
+int attrs = 0;
+
+static JCR *jcr;
+
+
+static int print_file(FF_PKT *ff, void *pkt);
+static void print_ls_output(char *fname, char *link, int type, struct stat *statp);
+
+static void usage()
+{
+ fprintf(stderr, _(
+"\n"
+"Usage: testls [-d debug_level] [-] [pattern1 ...]\n"
+" -a print extended attributes (Win32 debug)\n"
+" -dnn set debug level to nn\n"
+" -e specify file of exclude patterns\n"
+" -i specify file of include patterns\n"
+" - read pattern(s) from stdin\n"
+" -? print this message.\n"
+"\n"
+"Patterns are file inclusion -- normally directories.\n"
+"Debug level >= 1 prints each file found.\n"
+"Debug level >= 10 prints path/file for catalog.\n"
+"Errors always printed.\n"
+"Files/paths truncated is number with len > 255.\n"
+"Truncation is only in catalog.\n"
+"\n"));
+
+ exit(1);
+}
+
+
+int
+main (int argc, char *const *argv)
+{
+ FF_PKT *ff;
+ char name[1000];
+ int i, ch, hard_links;
+ char *inc = NULL;
+ char *exc = NULL;
+ FILE *fd;
+
+ while ((ch = getopt(argc, argv, "ad:e:i:?")) != -1) {
+ switch (ch) {
+ case 'a': /* print extended attributes *debug* */
+ attrs = 1;
+ break;
+
+ case 'd': /* set debug level */
+ debug_level = atoi(optarg);
+ if (debug_level <= 0) {
+ debug_level = 1;
+ }
+ break;
+
+ case 'e': /* exclude patterns */
+ exc = optarg;
+ break;
+
+ case 'i': /* include patterns */
+ inc = optarg;
+ break;
+
+ case '?':
+ default:
+ usage();
+
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ jcr = new_jcr(sizeof(JCR), NULL);
+
+ ff = init_find_files();
+ if (argc == 0 && !inc) {
+ add_fname_to_include_list(ff, 0, "/"); /* default to / */
+ } else {
+ for (i=0; i < argc; i++) {
+ if (strcmp(argv[i], "-") == 0) {
+ while (fgets(name, sizeof(name)-1, stdin)) {
+ strip_trailing_junk(name);
+ add_fname_to_include_list(ff, 0, name);
+ }
+ continue;
+ }
+ add_fname_to_include_list(ff, 0, argv[i]);
+ }
+ }
+ if (inc) {
+ fd = fopen(inc, "r");
+ if (!fd) {
+ printf("Could not open include file: %s\n", inc);
+ exit(1);
+ }
+ while (fgets(name, sizeof(name)-1, fd)) {
+ strip_trailing_junk(name);
+ add_fname_to_include_list(ff, 0, name);
+ }
+ fclose(fd);
+ }
+
+ if (exc) {
+ fd = fopen(exc, "r");
+ if (!fd) {
+ printf("Could not open exclude file: %s\n", exc);
+ exit(1);
+ }
+ while (fgets(name, sizeof(name)-1, fd)) {
+ strip_trailing_junk(name);
+ add_fname_to_exclude_list(ff, name);
+ }
+ fclose(fd);
+ }
+ find_files(jcr, ff, print_file, NULL);
+ hard_links = term_find_files(ff);
+
+ free_jcr(jcr);
+ close_memory_pool();
+ sm_dump(False);
+ exit(0);
+}
+
+static int print_file(FF_PKT *ff, void *pkt)
+{
+
+ switch (ff->type) {
+ case FT_LNKSAVED:
+ case FT_REGE:
+ case FT_REG:
+ case FT_LNK:
+ case FT_DIR:
+ case FT_SPEC:
+ print_ls_output(ff->fname, ff->link, ff->type, &ff->statp);
+ break;
+ case FT_NOACCESS:
+ printf(_("Err: Could not access %s: %s\n"), ff->fname, strerror(errno));
+ break;
+ case FT_NOFOLLOW:
+ printf(_("Err: Could not follow ff->link %s: %s\n"), ff->fname, strerror(errno));
+ break;
+ case FT_NOSTAT:
+ printf(_("Err: Could not stat %s: %s\n"), ff->fname, strerror(errno));
+ break;
+ case FT_NOCHG:
+ printf(_("Skip: File not saved. No change. %s\n"), ff->fname);
+ break;
+ case FT_ISARCH:
+ printf(_("Err: Attempt to backup archive. Not saved. %s\n"), ff->fname);
+ break;
+ case FT_NORECURSE:
+ printf(_("Recursion turned off. Directory not entered. %s\n"), ff->fname);
+ break;
+ case FT_NOFSCHG:
+ printf(_("Skip: File system change prohibited. Directory not entered. %s\n"), ff->fname);
+ break;
+ case FT_NOOPEN:
+ printf(_("Err: Could not open directory %s: %s\n"), ff->fname, strerror(errno));
+ break;
+ default:
+ printf(_("Err: Unknown file ff->type %d: %s\n"), ff->type, ff->fname);
+ break;
+ }
+ return 1;
+}
+
+static void print_ls_output(char *fname, char *link, int type, struct stat *statp)
+{
+ char buf[1000];
+ char ec1[30];
+ char *p, *f;
+ int n;
+
+ p = encode_mode(statp->st_mode, buf);
+ n = sprintf(p, " %2d ", (uint32_t)statp->st_nlink);
+ p += n;
+ n = sprintf(p, "%-4d %-4d", (int)statp->st_uid, (int)statp->st_gid);
+ p += n;
+ n = sprintf(p, "%7.7s ", edit_uint64(statp->st_size, ec1));
+ p += n;
+ if (S_ISCHR(statp->st_mode) || S_ISBLK(statp->st_mode)) {
+ n = sprintf(p, "%4x ", (int)statp->st_rdev);
+ } else {
+ n = sprintf(p, " ");
+ }
+ p += n;
+ if (type != FT_LNK) {
+ p = encode_time(statp->st_mtime, p);
+ } else {
+ p = encode_time(0, p);
+ }
+ *p++ = ' ';
+ /* Copy file name */
+ for (f=fname; *f && (p-buf) < (int)sizeof(buf); )
+ *p++ = *f++;
+ if (type == FT_LNK) {
+ *p++ = '-';
+ *p++ = '>';
+ *p++ = ' ';
+ /* Copy link name */
+ for (f=link; *f && (p-buf) < (int)sizeof(buf); )
+ *p++ = *f++;
+ }
+ *p++ = '\n';
+ *p = 0;
+ fputs(buf, stdout);
+}