200 lines
		
	
	
	
		
			5.3 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			200 lines
		
	
	
	
		
			5.3 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/**
 | 
						|
  (c) 2005 Peter Portmann (pp at bluewin.ch)
 | 
						|
  cinit.graph.text.c
 | 
						|
      
 | 
						|
  This script is written for the clinux-System and published
 | 
						|
  under the terms of GPL 2.0
 | 
						|
 | 
						|
  Version: 0.2
 | 
						|
 | 
						|
  ChangeLog:
 | 
						|
    Version 0.2 (Peter Portmann):
 | 
						|
      * Not assigned link destinies are marked by (!).
 | 
						|
      * Not readable directories are marked by "directory not readable".
 | 
						|
    
 | 
						|
    Version 0.1 (Peter Portmann):
 | 
						|
      * Print of the directory structure of the contained files and links
 | 
						|
        without following the links.
 | 
						|
 | 
						|
  Todo:
 | 
						|
 | 
						|
  Features:
 | 
						|
*/
 | 
						|
 
 | 
						|
//#include <sys/types.h>
 | 
						|
#include <sys/stat.h>
 | 
						|
#include <dirent.h>
 | 
						|
//#include <limits.h>
 | 
						|
#include <string.h>
 | 
						|
#include <unistd.h>
 | 
						|
#include <stdlib.h>
 | 
						|
#include <stdio.h>
 | 
						|
#include "cinit.h"
 | 
						|
#include "error.h"
 | 
						|
 | 
						|
#define FTW_F 1   /* file isn't a directory */
 | 
						|
#define FTW_D 2   /* file is a directory */
 | 
						|
#define FTW_DNR 3 /* not readable directory */
 | 
						|
#define FTW_NS 4  /* unsuccesfully stat on this file */
 | 
						|
#define MAX_CHAR   4096
 | 
						|
 | 
						|
/***********************************************************************
 | 
						|
 * cinit.gaph.text - textual representatio of the cinitdirectory
 | 
						|
 */
 | 
						|
 | 
						|
#define CSERVICE_BANNER    "cinit.gaph.text - textual representatio of the cinitdirectory\n\n"
 | 
						|
#define USAGE_TEXT         "\n\nUsage:\n\ncinit.gaph.text <path>\n"  \
 | 
						|
   "\tpath\t- cinit installationpath\n"
 | 
						|
 | 
						|
typedef int EACH_ENTRY(const char *, const struct stat *, int);
 | 
						|
typedef enum  { FALSE=0, TRUE=1 }  bool;
 | 
						|
 | 
						|
static char dirpath[PATH_MAX];
 | 
						|
static int depth = 0;
 | 
						|
static long int filecount = 0;
 | 
						|
 | 
						|
static EACH_ENTRY each_entry;
 | 
						|
static int pp_ftw(char *, EACH_ENTRY *);
 | 
						|
static int each_getinfo(EACH_ENTRY *);
 | 
						|
 | 
						|
/***********************************************************************
 | 
						|
 * pp_ftw: file tree walk
 | 
						|
 */
 | 
						|
static int pp_ftw(char *filepath, EACH_ENTRY *function)
 | 
						|
{
 | 
						|
   int n;
 | 
						|
 | 
						|
   if(chdir(filepath) < 0) /* In angegebenen Pfad wechseln */
 | 
						|
      err_msg(FATAL_SYS, "can't change to %s", filepath);
 | 
						|
 | 
						|
   if(getcwd(dirpath, PATH_MAX) == 0) /* Absoluten Pfadnamen ermitteln */
 | 
						|
      err_msg(FATAL_SYS, "error using getcwd for %s", filepath);
 | 
						|
 | 
						|
   n = each_getinfo(function);
 | 
						|
 | 
						|
   return(n);
 | 
						|
}
 | 
						|
 | 
						|
/***********************************************************************
 | 
						|
 * each_getinfo: get more info for each file.
 | 
						|
 */
 | 
						|
static int each_getinfo(EACH_ENTRY *function)
 | 
						|
{
 | 
						|
   struct stat statpuff;
 | 
						|
   struct dirent *direntz;
 | 
						|
   DIR *dirz;
 | 
						|
   int n;
 | 
						|
   char *zgr;
 | 
						|
 | 
						|
   if(lstat(dirpath, &statpuff) < 0)
 | 
						|
      return(function(dirpath, &statpuff, FTW_NS)); /* Error on stat */
 | 
						|
 | 
						|
   if(S_ISDIR(statpuff.st_mode) == 0)
 | 
						|
      return(function(dirpath, &statpuff, FTW_F)); /* no directory */
 | 
						|
 | 
						|
   /* It's a directory.
 | 
						|
    * Call function() for it. After that handel each file in the directory. */
 | 
						|
 | 
						|
   if((dirz = opendir(dirpath)) == NULL) { /* Directory not readable */
 | 
						|
      closedir(dirz);
 | 
						|
      return(function(dirpath, &statpuff, FTW_DNR));
 | 
						|
   }
 | 
						|
 | 
						|
   if((n = function(dirpath, &statpuff, FTW_D)) != 0) /* return the directorydirpath */
 | 
						|
      return(n);
 | 
						|
 | 
						|
   zgr = dirpath + strlen(dirpath); /* append slash to the dirpathname */
 | 
						|
   *zgr++ = '/';
 | 
						|
   *zgr = '\0';
 | 
						|
 | 
						|
   while((direntz = readdir(dirz)) != NULL) {
 | 
						|
      /* ignor . and .. */
 | 
						|
      if(strcmp(direntz->d_name, ".") && strcmp(direntz->d_name, "..")) {
 | 
						|
         strcpy(zgr, direntz->d_name); /* append filename after slash */
 | 
						|
         depth++;
 | 
						|
         if(each_getinfo(function) != 0) { /* Recursion */
 | 
						|
            depth--;
 | 
						|
            break;
 | 
						|
         }
 | 
						|
         depth--;
 | 
						|
      }
 | 
						|
   }
 | 
						|
   *(zgr-1) = '\0'; /* deleting evrything after the slash */
 | 
						|
 | 
						|
   if(closedir(dirz) < 0)
 | 
						|
      err_msg(WARNING, "closedir for %s failed", dirpath);
 | 
						|
 | 
						|
   return(n);
 | 
						|
}
 | 
						|
 | 
						|
/***********************************************************************
 | 
						|
 * each_entry: handling each file and build the graph step by step.
 | 
						|
 */
 | 
						|
static int each_entry(const char *filepath, const struct stat *statzgr, int filetype)
 | 
						|
{
 | 
						|
   struct stat statpuff;
 | 
						|
   static bool erstemal=TRUE;
 | 
						|
   int i;
 | 
						|
 
 | 
						|
   char link[MAX_CHAR];
 | 
						|
 | 
						|
   filecount++;
 | 
						|
   if(!erstemal) {
 | 
						|
      for(i=1 ; i<=depth ; i++)
 | 
						|
         printf("%4c|", ' ');
 | 
						|
      printf("----%s", strrchr(filepath, '/')+1);
 | 
						|
   } else {
 | 
						|
      printf("%s", filepath);
 | 
						|
      erstemal = FALSE;
 | 
						|
   }
 | 
						|
 | 
						|
   switch(filetype) {
 | 
						|
      case FTW_F:
 | 
						|
         switch(statzgr->st_mode & S_IFMT) {
 | 
						|
            case S_IFREG: break;
 | 
						|
            case S_IFCHR: printf(" c"); break;
 | 
						|
            case S_IFBLK: printf(" b"); break;
 | 
						|
            case S_IFIFO: printf(" f"); break;
 | 
						|
            case S_IFLNK: 
 | 
						|
               printf(" -> "); 
 | 
						|
               if(( i=readlink(filepath, link, MAX_CHAR)) != -1)
 | 
						|
                  printf("%.*s", i, link);
 | 
						|
                  if(stat(filepath, &statpuff) < 0)
 | 
						|
                     printf(" (!)");
 | 
						|
               break;
 | 
						|
            case S_IFSOCK: printf(" s"); break;
 | 
						|
            default: printf(" ?"); break;
 | 
						|
         }
 | 
						|
         printf("\n");
 | 
						|
         break;
 | 
						|
 | 
						|
      case FTW_D:
 | 
						|
         printf("/\n");
 | 
						|
         break;
 | 
						|
 | 
						|
      case FTW_DNR:
 | 
						|
         printf("/ directory not readable\n");
 | 
						|
         break;
 | 
						|
 | 
						|
      case FTW_NS:
 | 
						|
         err_msg(WARNING_SYS, "Error using 'stat' on file %s", filepath);
 | 
						|
         break;
 | 
						|
 | 
						|
      default:
 | 
						|
         err_msg(FATAL_SYS, "Unknown Filetype (%d) by file %s", filetype, filepath);
 | 
						|
         break;
 | 
						|
   }
 | 
						|
 | 
						|
   return(0);
 | 
						|
}
 | 
						|
 | 
						|
/***********************************************************************
 | 
						|
 * main:
 | 
						|
 */
 | 
						|
int main(int argc, char *argv[])
 | 
						|
{
 | 
						|
   if(argc != 2)
 | 
						|
      usage(CSERVICE_BANNER, USAGE_TEXT);
 | 
						|
 | 
						|
   exit(pp_ftw(argv[1], each_entry));
 | 
						|
}
 |