/***************************************************************************
*
* $Header: /usr/local/cvsroot/utils/ytree/readtree.c,v 1.13 2000/07/13 18:26:06 werner Exp $
*
* Funktionen zum Lesen des Dateibaumes
*
***************************************************************************/
#include "ytree.h"
static void UnReadSubTree(DirEntry *dir_entry);
/* Dateibaum lesen: path = "Root"-Pfad
* dir_entry wird von der Funktion gefuellt
*/
int ReadTree(DirEntry *dir_entry, char *path, int depth)
{
DIR *dir;
struct stat stat_struct;
struct dirent *dirent;
char new_path[PATH_LENGTH + 1];
DirEntry first_dir_entry;
DirEntry *des_ptr;
DirEntry *den_ptr;
FileEntry first_file_entry;
FileEntry *fes_ptr;
FileEntry *fen_ptr;
int file_count;
/* dir_entry initialisieren */
/*--------------------------*/
dir_entry->file = NULL;
/*
dir_entry->next = NULL;
dir_entry->prev = NULL;
*/
dir_entry->sub_tree = NULL;
dir_entry->total_bytes = 0L;
dir_entry->matching_bytes = 0L;
dir_entry->tagged_bytes = 0L;
dir_entry->total_files = 0;
dir_entry->matching_files = 0;
dir_entry->tagged_files = 0;
dir_entry->access_denied = FALSE;
dir_entry->start_file = 0;
dir_entry->cursor_pos = 0;
dir_entry->global_flag = FALSE;
dir_entry->login_flag = FALSE;
dir_entry->big_window = FALSE;
dir_entry->not_scanned = FALSE;
if( S_ISBLK( dir_entry->stat_struct.st_mode ) )
return( 0 ); /* Block-Device */
if( depth < 0 )
{
if( dir_entry->up_tree )
{
dir_entry->up_tree->not_scanned = TRUE;
return( 1 );
}
}
statistic.disk_total_directories++;
if( ( dir = opendir( path ) ) == NULL )
{
dir_entry->access_denied = TRUE;
return( 1 );
}
first_dir_entry.prev = NULL;
first_dir_entry.next = NULL;
*first_dir_entry.name = '\0';
first_file_entry.next = NULL;
fes_ptr = &first_file_entry;
file_count = 0;
while( ( dirent = readdir( dir ) ) != NULL )
{
if( !strcmp( dirent->d_name, "." ) || !strcmp( dirent->d_name, ".." ) )
continue;
if( EscapeKeyPressed() )
{
Quit(); /* Abfrage ob ytree verlassen werden soll */
}
if( ( file_count++ % 100 ) == 0 ) {
DisplayDiskStatistic();
doupdate();
}
(void) strcpy( new_path, path );
if( strcmp( new_path, FILE_SEPARATOR_STRING ) )
(void) strcat( new_path, FILE_SEPARATOR_STRING );
(void) strcat( new_path, dirent->d_name );
if( STAT_( new_path, &stat_struct ) )
{
if( errno == EACCES ) continue;
(void) sprintf( message, "Stat failed on*%s*IGNORED", new_path );
ERROR_MSG( message );
continue;
}
if( S_ISDIR( stat_struct.st_mode ) )
{
/* Directory-Entry */
/*-----------------*/
if( ( den_ptr = (DirEntry *)
malloc( sizeof( DirEntry ) + strlen( dirent->d_name ) )
) == NULL )
{
ERROR_MSG( "Malloc Failed*ABORT" );
exit( 1 );
}
den_ptr->up_tree = dir_entry;
(void) strcpy( den_ptr->name, dirent->d_name );
(void) memcpy( &den_ptr->stat_struct,
&stat_struct,
sizeof( stat_struct )
);
den_ptr->prev = den_ptr->next = NULL;
(void) ReadTree( den_ptr, new_path, depth - 1);
/* Sortieren durch direktes Einfuegen */
/*------------------------------------*/
for( des_ptr = &first_dir_entry; des_ptr; des_ptr = des_ptr->next )
{
if( strcmp( des_ptr->name, den_ptr->name ) > 0 )
{
/* des-Element ist groesser */
/*--------------------------*/
den_ptr->next = des_ptr;
den_ptr->prev = des_ptr->prev;
des_ptr->prev->next = den_ptr;
des_ptr->prev = den_ptr;
break;
}
if( des_ptr->next == NULL )
{
/* Ende der Liste erreicht; ==> einfuegen */
/*----------------------------------------*/
den_ptr->prev = des_ptr;
den_ptr->next = des_ptr->next;
des_ptr->next = den_ptr;
break;
}
}
}
else
{
/* File-Entry */
/*------------*/
int n;
char link_path[PATH_LENGTH + 1];
/* Test, ob Eintrag Symbolischer Link ist */
/*----------------------------------------*/
n = 0; *link_path = '\0';
if( S_ISLNK( stat_struct.st_mode ) )
{
/* Ja, symbolischer Name wird an "echten" Namen angehaengt */
/*---------------------------------------------------------*/
if( ( n = readlink( new_path, link_path, sizeof( link_path ) ) ) == -1 )
{
(void) strcpy( link_path, "unknown" );
n = strlen( link_path );
}
link_path[n] = '\0';
if( ( fen_ptr = (FileEntry *)
malloc( sizeof( FileEntry ) +
strlen( dirent->d_name ) +
n + 1 )
) == NULL )
{
ERROR_MSG( "Malloc Failed*ABORT" );
exit( 1 );
}
(void) strcpy( fen_ptr->name, dirent->d_name );
(void) strcpy( &fen_ptr->name[strlen(fen_ptr->name) + 1],
link_path );
}
else
{
if( ( fen_ptr = (FileEntry *)
malloc( sizeof( FileEntry ) + strlen( dirent->d_name ) )
) == NULL )
{
ERROR_MSG( "Malloc Failed*ABORT" );
exit( 1 );
}
(void) strcpy( fen_ptr->name, dirent->d_name );
}
fen_ptr->next = NULL;
fen_ptr->prev = NULL;
fen_ptr->tagged = FALSE;
(void) memcpy( &fen_ptr->stat_struct,
&stat_struct,
sizeof( stat_struct )
);
fen_ptr->dir_entry = dir_entry;
fes_ptr->next = fen_ptr;
fen_ptr->prev = fes_ptr;
fes_ptr = fen_ptr;
dir_entry->total_files++;
dir_entry->total_bytes += stat_struct.st_size;
statistic.disk_total_files++;
statistic.disk_total_bytes += stat_struct.st_size;
}
}
(void) closedir( dir );
if( first_file_entry.next ) first_file_entry.next->prev = NULL;
if( first_dir_entry.next ) first_dir_entry.next->prev = NULL;
dir_entry->file = first_file_entry.next;
dir_entry->sub_tree = first_dir_entry.next;
DisplayDiskStatistic();
doupdate();
return( 0 );
}
void UnReadTree(DirEntry *dir_entry)
{
FileEntry *fe_ptr, *next_fe_ptr;
if( dir_entry == statistic.tree )
{
MESSAGE( "Can't delete ROOT" );
}
else
{
for( fe_ptr=dir_entry->file; fe_ptr; fe_ptr=next_fe_ptr )
{
next_fe_ptr = fe_ptr->next;
RemoveFile( fe_ptr );
}
if( dir_entry->sub_tree )
{
UnReadSubTree( dir_entry->sub_tree );
}
statistic.disk_total_directories--;
(void) GetAvailBytes( &statistic.disk_space );
DisplayDiskStatistic();
doupdate();
}
}
static void UnReadSubTree(DirEntry *dir_entry)
{
DirEntry *de_ptr, *next_de_ptr;
FileEntry *fe_ptr, *next_fe_ptr;
for( de_ptr = dir_entry; de_ptr; de_ptr = next_de_ptr )
{
next_de_ptr = de_ptr->next;
for( fe_ptr=de_ptr->file; fe_ptr; fe_ptr=next_fe_ptr )
{
next_fe_ptr = fe_ptr->next;
RemoveFile( fe_ptr );
}
if( de_ptr->sub_tree )
{
UnReadSubTree( de_ptr->sub_tree );
}
if( !de_ptr->up_tree->not_scanned )
statistic.disk_total_directories--;
if( de_ptr->prev ) de_ptr->prev->next = de_ptr->next;
else de_ptr->up_tree->sub_tree = de_ptr->next;
if( de_ptr->next ) de_ptr->next->prev = de_ptr->prev;
free( de_ptr );
}
}