Example #1
0
File: xml.c Project: execjosh/tree
off_t xml_listdir(char *d, int *dt, int *ft, u_long lev, dev_t dev)
{
  char *path;
  bool nlf = FALSE;
  long pathsize = 0;
  struct _info **dir, **sav;
  struct stat sb;
  int t, n, mt;

  if ((Level >= 0) && (lev > Level)) {
    if (!noindent) fputc('\n',outfile);
    return 0;
  }

  if (xdev && lev == 0) {
    stat(d,&sb);
    dev = sb.st_dev;
  }

  sav = dir = read_dir(d,&n);
  if (!dir && n) {
    fprintf(outfile,"<error>opening dir</error>\n");
    return 0;
  }
  if (!n) {
    if (!noindent) fputc('\n', outfile);
    free_dir(sav);
    return 0;
  }
  if (flimit > 0 && n > flimit) {
    fprintf(outfile,"<error>%d entries exceeds filelimit, not opening dir</error>%s",n,noindent?"":"\n");
    free_dir(sav);
    return 0;
  }

  if (cmpfunc) qsort(dir,n,sizeof(struct _info *), cmpfunc);
  if (lev >= maxdirs-1) {
    dirs = xrealloc(dirs,sizeof(int) * (maxdirs += 1024));
    memset(dirs+(maxdirs-1024), 0, sizeof(int) * 1024);
  }
  dirs[lev] = 1;
  if (!*(dir+1)) dirs[lev] = 2;
  if (!noindent) fprintf(outfile,"\n");

  path = malloc(pathsize=4096);

  while(*dir) {
    if (!noindent) xml_indent(lev);

    if ((*dir)->lnk) mt = (*dir)->mode & S_IFMT;
    else mt = (*dir)->mode & S_IFMT;
    for(t=0;ifmt[t];t++)
      if (ifmt[t] == mt) break;
    fprintf(outfile,"<%s", ftype[t]);

    if (fflag) {
      if (sizeof(char) * (strlen(d)+strlen((*dir)->name)+2) > pathsize)
	path=xrealloc(path,pathsize=(sizeof(char) * (strlen(d)+strlen((*dir)->name)+1024)));
      if (!strcmp(d,"/")) sprintf(path,"%s%s",d,(*dir)->name);
      else sprintf(path,"%s/%s",d,(*dir)->name);
    } else {
      if (sizeof(char) * (strlen((*dir)->name)+1) > pathsize)
	path=xrealloc(path,pathsize=(sizeof(char) * (strlen((*dir)->name)+1024)));
      sprintf(path,"%s",(*dir)->name);
    }

    fprintf(outfile, " name=\"");
    html_encode(outfile,path);
    fputc('"',outfile);

    if ((*dir)->lnk) {
      fprintf(outfile, " target=\"");
      html_encode(outfile,(*dir)->lnk);
      fputc('"',outfile);
    }
    xml_fillinfo(*dir);
    fputc('>',outfile);

    if ((*dir)->isdir) {
      if ((*dir)->lnk) {
	if (lflag && !(xdev && dev != (*dir)->dev)) {
	  if (findino((*dir)->inode,(*dir)->dev)) {
	    fprintf(outfile,"<error>recursive, not followed</error>");
	  } else {
	    saveino((*dir)->inode, (*dir)->dev);
	    if (*(*dir)->lnk == '/')
	      listdir((*dir)->lnk,dt,ft,lev+1,dev);
	    else {
	      if (strlen(d)+strlen((*dir)->lnk)+2 > pathsize) path=xrealloc(path,pathsize=(strlen(d)+strlen((*dir)->name)+1024));
	      if (fflag && !strcmp(d,"/")) sprintf(path,"%s%s",d,(*dir)->lnk);
	      else sprintf(path,"%s/%s",d,(*dir)->lnk);
	      listdir(path,dt,ft,lev+1,dev);
	    }
	    nlf = TRUE;
	  }
	}
      } else if (!(xdev && dev != (*dir)->dev)) {
	if (strlen(d)+strlen((*dir)->name)+2 > pathsize) path=xrealloc(path,pathsize=(strlen(d)+strlen((*dir)->name)+1024));
	if (fflag && !strcmp(d,"/")) sprintf(path,"%s%s",d,(*dir)->name);
	else sprintf(path,"%s/%s",d,(*dir)->name);
	saveino((*dir)->inode, (*dir)->dev);
	listdir(path,dt,ft,lev+1,dev);
	nlf = TRUE;
      }
      *dt += 1;
    } else *ft += 1;
    if (*(dir+1) && !*(dir+2)) dirs[lev] = 2;
    if (nlf) {
      nlf = FALSE;
      if (!noindent) xml_indent(lev);
    }
    fprintf(outfile,"</%s>%s",ftype[t],noindent?"":"\n");
    dir++;
  }
  dirs[lev] = 0;
  free(path);
  free_dir(sav);
  return 0;
}
Example #2
0
int main(int argc, char **argv)
{
  char **dirname = NULL;
  int i,j=0,k,n,optf,p,q,dtotal,ftotal,colored = FALSE;
  struct stat st;
  char sizebuf[64], *stmp;
  off_t size = 0;
  mode_t mt;
  bool needfulltree;

  q = p = dtotal = ftotal = 0;
  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 = dirsfirst = inodeflag = devflag = Xflag = Jflag = FALSE;
  duflag = pruneflag = FALSE;
  flimit = 0;
  dirs = xmalloc(sizeof(int) * (maxdirs=4096));
  memset(dirs, 0, sizeof(int) * maxdirs);
  dirs[0] = 0;
  Level = -1;

  setlocale(LC_CTYPE, "");
  setlocale(LC_COLLATE, "");

  charset = getcharset();
  if (charset == NULL) {
    charset = "UTF-8";
  }

/* Until I get rid of this hack, make it linux/cygwin/HP nonstop only: */
#if defined (LINUX) || defined (CYGWIN) || defined (__TANDEM)
  mb_cur_max = (int)MB_CUR_MAX;
#else
  mb_cur_max = 1;
#endif

  memset(utable,0,sizeof(utable));
  memset(gtable,0,sizeof(gtable));
  memset(itable,0,sizeof(itable));

  optf = TRUE;
  for(n=i=1;i<argc;i=n) {
    n++;
    if (optf && argv[i][0] == '-' && argv[i][1]) {
      for(j=1;argv[i][j];j++) {
	switch(argv[i][j]) {
	case 'N':
	  Nflag = TRUE;
	  break;
	case 'q':
	  qflag = TRUE;
	  break;
	case 'Q':
	  Qflag = TRUE;
	  break;
	case 'd':
	  dflag = TRUE;
	  break;
	case 'l':
	  lflag = TRUE;
	  break;
	case 's':
	  sflag = TRUE;
	  break;
	case 'h':
	  hflag = TRUE;
	  sflag = TRUE; /* Assume they also want -s */
	  break;
	case 'u':
	  uflag = TRUE;
	  break;
	case 'g':
	  gflag = TRUE;
	  break;
	case 'f':
	  fflag = TRUE;
	  break;
	case 'F':
	  Fflag = TRUE;
	  break;
	case 'a':
	  aflag = TRUE;
	  break;
	case 'p':
	  pflag = TRUE;
	  break;
	case 'i':
	  noindent = TRUE;
	  _nl = "";
	  break;
	case 'C':
	  force_color = TRUE;
	  break;
	case 'n':
	  nocolor = TRUE;
	  break;
	case 'x':
	  xdev = TRUE;
	  break;
	case 'P':
	  if (argv[n] == NULL) {
	    fprintf(stderr,"tree: missing argument to -P option.\n");
	    exit(1);
	  }
	  pattern = argv[n++];
	  break;
	case 'I':
	  if (argv[n] == NULL) {
	    fprintf(stderr,"tree: missing argument to -I option.\n");
	    exit(1);
	  }
	  ipattern = argv[n++];
	  break;
	case 'A':
	  ansilines = TRUE;
	  break;
	case 'S':
	  charset = "IBM437";
	  break;
	case 'D':
	  Dflag = TRUE;
	  break;
	case 't':
	  cmpfunc = mtimesort;
	  break;
	case 'c':
	  cmpfunc = ctimesort;
	  cflag = TRUE;
	  break;
	case 'r':
	  reverse = TRUE;
	  break;
	case 'v':
	  cmpfunc = versort;
	  break;
	case 'U':
	  cmpfunc = NULL;
	  break;
	case 'X':
	  Hflag = FALSE;
	  Xflag = TRUE;
	  break;
	case 'J':
	  Jflag = TRUE;
	  break;
	case 'H':
	  Hflag = TRUE;
	  Xflag = FALSE;
	  if (argv[n] == NULL) {
	    fprintf(stderr,"tree: missing argument to -H option.\n");
	    exit(1);
	  }
	  host = argv[n++];
	  sp = "&nbsp;";
	  break;
	case 'T':
	  if (argv[n] == NULL) {
	    fprintf(stderr,"tree: missing argument to -T option.\n");
	    exit(1);
	  }
	  title = argv[n++];
	  break;
	case 'R':
	  Rflag = TRUE;
	  break;
	case 'L':
	  if ((sLevel = argv[n++]) == NULL) {
	    fprintf(stderr,"tree: Missing argument to -L option.\n");
	    exit(1);
	  }
	  Level = strtoul(sLevel,NULL,0)-1;
	  if (Level < 0) {
	    fprintf(stderr,"tree: Invalid level, must be greater than 0.\n");
	    exit(1);
	  }
	  break;
	case 'o':
	  if (argv[n] == NULL) {
	    fprintf(stderr,"tree: missing argument to -o option.\n");
	    exit(1);
	  }
	  outfilename = argv[n++];
	  break;
	case '-':
	  if (j == 1) {
	    if (!strcmp("--", argv[i])) {
	      optf = FALSE;
	      break;
	    }
	    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);
	    }
	    if (!strcmp("--inodes",argv[i])) {
	      j = strlen(argv[i])-1;
	      inodeflag=TRUE;
	      break;
	    }
	    if (!strcmp("--device",argv[i])) {
	      j = strlen(argv[i])-1;
	      devflag=TRUE;
	      break;
	    }
	    if (!strcmp("--noreport",argv[i])) {
	      j = strlen(argv[i])-1;
	      noreport = TRUE;
	      break;
	    }
	    if (!strcmp("--nolinks",argv[i])) {
	      j = strlen(argv[i])-1;
	      nolinks = TRUE;
	      break;
	    }
	    if (!strcmp("--dirsfirst",argv[i])) {
	      j = strlen(argv[i])-1;
	      dirsfirst = TRUE;
	      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;
		}
	      }
	      if (argv[n] != NULL) {
		flimit = atoi(argv[n++]);
		j = strlen(argv[i])-1;
	      } else {
		fprintf(stderr,"tree: missing argument to --filelimit\n");
		exit(1);
	      }
	      break;
	    }
	    if (!strncmp("--charset",argv[i],9)){
	      j = 9;
	      if (*(argv[i]+j) == '=') {
		if (*(charset = (argv[i]+10))) {
		  j = strlen(argv[i])-1;
		  break;
		}
	      }
	      if (argv[n] != NULL) {
		charset = argv[n++];
		j = strlen(argv[i])-1;
	      } else {
		initlinedraw(1);
		exit(1);
	      }
	      break;
	    }
	    if (!strncmp("--si", argv[i], 4)) {
	      j = strlen(argv[i])-1;
	      sflag = TRUE;
	      hflag = TRUE;
	      siflag = TRUE;
	      break;
	    }
	    if (!strncmp("--du",argv[i],4)) {
	      j = strlen(argv[i])-1;
	      sflag = TRUE;
	      duflag = TRUE;
	      break;
	    }
	    if (!strncmp("--prune",argv[i],7)) {
	      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 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);
	      }
	      Dflag = TRUE;
	      break;
	    }
	    if (!strncmp("--ignore-case",argv[i],13)) {
	      j = strlen(argv[i])-1;
	      ignorecase = TRUE;
	      break;
	    }
	    if (!strncmp("--matchdirs",argv[i],11)) {
	      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++];
	      } else {
		fprintf(stderr,"tree: missing argument to --sort\n");
		exit(1);
	      }
	      cmpfunc = (void *)1;
	      for(k=0;sorts[k].name;k++) {
		if (strcasecmp(sorts[k].name,stmp) == 0) {
		  cmpfunc = sorts[k].cmpfunc;
		  break;
		}
	      }
	      if (cmpfunc == (void *)1) {
		fprintf(stderr,"tree: sort type '%s' not valid, should be one of: ", stmp);
		for(k=0; sorts[k].name; k++)
		  printf("%s%c", sorts[k].name, sorts[k+1].name? ',': '\n');
		exit(1);
	      }
	      break;
	    }
	  }
	default:
	  fprintf(stderr,"tree: Invalid argument -`%c'.\n",argv[i][j]);
	  usage(1);
	  exit(1);
	  break;
	}
      }
    } else {
      if (!dirname) dirname = (char **)xmalloc(sizeof(char *) * (q=MINIT));
      else if (p == (q-2)) dirname = (char **)xrealloc(dirname,sizeof(char *) * (q+=MINC));
      dirname[p++] = scopy(argv[i]);
    }
  }
  if (p) dirname[p] = NULL;

  if (outfilename == NULL) {
#ifdef __EMX__
    _fsetmode(outfile=stdout,Hflag?"b":"t");
#else
    outfile = stdout;
#endif
  } else {
#ifdef __EMX__
    outfile = fopen(outfilename,Hflag?"wb":"wt");
#else
    outfile = fopen(outfilename,"w");
#endif
    if (outfile == NULL) {
      fprintf(stderr,"tree: invalid filename '%s'\n",outfilename);
      exit(1);
    }
  }

  parse_dir_colors();
  initlinedraw(0);

  needfulltree = duflag || pruneflag || matchdirs;

  /* Set our listdir function and sanity check options. */
  if (Hflag) {
    listdir = needfulltree ? html_rlistdir : html_listdir;
    Xflag = FALSE;
  } else if (Xflag) {
    listdir = needfulltree ? xml_rlistdir : xml_listdir;
    colorize = FALSE;
    colored = FALSE; /* Do people want colored XML output? */
  } else if (Jflag) {
    listdir = needfulltree ? json_rlistdir : json_listdir;
    colorize = FALSE;
    colored = FALSE; /* Do people want colored JSON output? */
  } else {
    listdir = needfulltree ? unix_rlistdir : unix_listdir;
  }
  if (dflag) pruneflag = FALSE;	/* You'll just get nothing otherwise. */


  if (Rflag && (Level == -1))
    Rflag = FALSE;

  if (Hflag) {
    emit_html_header(charset, title, version);

    fflag = FALSE;
    if (nolinks) {
      if (force_color) fprintf(outfile, "<b class=\"NORM\">%s</b>",host);
      else fprintf(outfile,"%s",host);
    } else {
      if (force_color) fprintf(outfile,"<a class=\"NORM\" href=\"%s\">%s</a>",host,host);
      else fprintf(outfile,"<a href=\"%s\">%s</a>",host,host);
    }
    curdir = gnu_getcwd();
  } else if (Xflag) {
    fprintf(outfile,"<?xml version=\"1.0\"");
    if (charset) fprintf(outfile," encoding=\"%s\"",charset);
    fprintf(outfile,"?>%s<tree>%s",_nl,_nl);
  } else if (Jflag)
    fputc('[',outfile);

  if (dirname) {
    for(colored=i=0;dirname[i];i++,colored=0) {
      if (fflag) {
	do {
	  j=strlen(dirname[i]);
	  if (j > 1 && dirname[i][j-1] == '/') dirname[i][--j] = 0;
	} while (j > 1 && dirname[i][j-1] == '/');
      }
      if ((n = lstat(dirname[i],&st)) >= 0) {
	saveino(st.st_ino, st.st_dev);
	if (colorize) colored = color(st.st_mode,dirname[i],n<0,FALSE);
	size += st.st_size;
      }
      if (Xflag || Jflag) {
	mt = st.st_mode & S_IFMT;
	for(j=0;ifmt[j];j++)
	  if (ifmt[j] == mt) break;
        if (Xflag)
	  fprintf(outfile,"%s<%s name=\"%s\">", noindent?"":"  ", ftype[j], dirname[i]);
        else if (Jflag) {
	  if (i) fprintf(outfile, ",");
          fprintf(outfile,"%s{\"type\":\"%s\",\"name\":\"%s\",\"contents\":[", noindent?"":"\n  ", ftype[j], dirname[i]);
	}
      } else if (!Hflag) printit(dirname[i]);
      if (colored) fprintf(outfile,"%s",endcode);
      if (!Hflag) size += listdir(dirname[i],&dtotal,&ftotal,0,0);
      else {
	if (chdir(dirname[i])) {
	  fprintf(outfile,"%s [error opening dir]\n",dirname[i]);
	  exit(1);
	} else {
	  size += listdir(".",&dtotal,&ftotal,0,0);
	  chdir(curdir);
	}
      }
      if (Xflag) fprintf(outfile,"%s</%s>\n",noindent?"":"  ", ftype[j]);
      if (Jflag) fprintf(outfile,"%s]}",noindent?"":"  ");
    }
  } else {
    if ((n = lstat(".",&st)) >= 0) {
      saveino(st.st_ino, st.st_dev);
      if (colorize) colored = color(st.st_mode,".",n<0,FALSE);
      size = st.st_size;
    }
    if (Xflag) fprintf(outfile,"%s<directory name=\".\">",noindent?"":"  ");
    else if (Jflag) fprintf(outfile, "{\"type\":\"directory\",\"name\": \".\",\"contents\":[");
    else if (!Hflag) fprintf(outfile,".");
    if (colored) fprintf(outfile,"%s",endcode);
    size += listdir(".",&dtotal,&ftotal,0,0);
    if (Xflag) fprintf(outfile,"%s</directory>%s",noindent?"":"  ", _nl);
    if (Jflag) fprintf(outfile,"%s]}",noindent?"":"  ");
  }

  if (Hflag)
    fprintf(outfile,"\t<br><br>\n\t</p>\n\t<p>\n");

  if (!noreport) {
    if (Xflag) {
      fprintf(outfile,"%s<report>%s",noindent?"":"  ", _nl);
      if (duflag) fprintf(outfile,"%s<size>%lld</size>%s", noindent?"":"    ", (long long int)size, _nl);
      fprintf(outfile,"%s<directories>%d</directories>%s", noindent?"":"    ", dtotal, _nl);
      if (!dflag) fprintf(outfile,"%s<files>%d</files>%s", noindent?"":"    ", ftotal, _nl);
      fprintf(outfile,"%s</report>%s",noindent?"":"  ", _nl);
    } else if (Jflag) {
      fprintf(outfile, ",%s{\"type\":\"report\"",noindent?"":"\n  ");
      if (duflag) fprintf(outfile,",\"size\":%lld", (long long int)size);
      fprintf(outfile,",\"directories\":%d", dtotal);
      if (!dflag) fprintf(outfile,",\"files\":%d", ftotal);
      fprintf(outfile, "}");
    } else {
      if (duflag) {
	psize(sizebuf, size);
	fprintf(outfile,"\n%s%s used in ", sizebuf, hflag || siflag? "" : " bytes");
      } else fputc('\n', outfile);
      if (dflag)
	fprintf(outfile,"%d director%s\n",dtotal,(dtotal==1? "y":"ies"));
      else
	fprintf(outfile,"%d director%s, %d file%s\n",dtotal,(dtotal==1? "y":"ies"),ftotal,(ftotal==1? "":"s"));
    }
  }

  if (Hflag) {
    fprintf(outfile,"\t<br><br>\n\t</p>\n");
    fprintf(outfile,"\t<hr>\n");
    fprintf(outfile,"\t<p class=\"VERSION\">\n");
    fprintf(outfile,hversion,linedraw->copy, linedraw->copy, linedraw->copy, linedraw->copy);
    fprintf(outfile,"\t</p>\n");
    fprintf(outfile,"</body>\n");
    fprintf(outfile,"</html>\n");
  } else if (Xflag) {
    fprintf(outfile,"</tree>\n");
  } else if (Jflag) {
      fprintf(outfile, "%s]\n",_nl);
  }

  if (outfilename != NULL) fclose(outfile);

  return 0;
}