1 /***************************************************************************
2  *
3  * $Header: /usr/local/cvsroot/utils/ytree/readtree.c,v 1.13 2000/07/13 18:26:06 werner Exp $
4  *
5  * Funktionen zum Lesen des Dateibaumes
6  *
7  ***************************************************************************/
8 
9 
10 #include "ytree.h"
11 
12 
13 
14 static void UnReadSubTree(DirEntry *dir_entry);
15 
16 
17 
18 /* Dateibaum lesen: path = "Root"-Pfad
19  * dir_entry wird von der Funktion gefuellt
20  */
21 
22 
ReadTree(DirEntry * dir_entry,char * path,int depth)23 int ReadTree(DirEntry *dir_entry, char *path, int depth)
24 {
25   DIR           *dir;
26   struct stat   stat_struct;
27   struct dirent *dirent;
28   char          new_path[PATH_LENGTH + 1];
29   DirEntry      first_dir_entry;
30   DirEntry      *des_ptr;
31   DirEntry      *den_ptr;
32   FileEntry     first_file_entry;
33   FileEntry     *fes_ptr;
34   FileEntry     *fen_ptr;
35   int		file_count;
36 
37 
38   /* dir_entry initialisieren */
39   /*--------------------------*/
40 
41   dir_entry->file           = NULL;
42 /*
43   dir_entry->next           = NULL;
44   dir_entry->prev           = NULL;
45 */
46   dir_entry->sub_tree       = NULL;
47   dir_entry->total_bytes    = 0L;
48   dir_entry->matching_bytes = 0L;
49   dir_entry->tagged_bytes   = 0L;
50   dir_entry->total_files    = 0;
51   dir_entry->matching_files = 0;
52   dir_entry->tagged_files   = 0;
53   dir_entry->access_denied  = FALSE;
54   dir_entry->start_file     = 0;
55   dir_entry->cursor_pos     = 0;
56   dir_entry->global_flag    = FALSE;
57   dir_entry->login_flag     = FALSE;
58   dir_entry->big_window     = FALSE;
59   dir_entry->not_scanned    = FALSE;
60 
61   if( S_ISBLK( dir_entry->stat_struct.st_mode ) )
62     return( 0 ); /* Block-Device */
63 
64   if( depth < 0 )
65   {
66     if( dir_entry->up_tree )
67     {
68       dir_entry->up_tree->not_scanned = TRUE;
69       return( 1 );
70     }
71   }
72 
73   statistic.disk_total_directories++;
74 
75   if( ( dir = opendir( path ) ) == NULL )
76   {
77     dir_entry->access_denied = TRUE;
78     return( 1 );
79   }
80 
81   first_dir_entry.prev  = NULL;
82   first_dir_entry.next  = NULL;
83   *first_dir_entry.name = '\0';
84   first_file_entry.next = NULL;
85   fes_ptr               = &first_file_entry;
86 
87   file_count = 0;
88   while( ( dirent = readdir( dir ) ) != NULL )
89   {
90     if( !strcmp( dirent->d_name, "." ) || !strcmp( dirent->d_name, ".." ) )
91       continue;
92 
93     if( EscapeKeyPressed() )
94     {
95       Quit();  /* Abfrage ob ytree verlassen werden soll */
96     }
97 
98     if( ( file_count++ % 100 ) == 0 ) {
99       DisplayDiskStatistic();
100       doupdate();
101     }
102 
103 
104     (void) strcpy( new_path, path );
105     if( strcmp( new_path, FILE_SEPARATOR_STRING ) )
106       (void) strcat( new_path, FILE_SEPARATOR_STRING );
107     (void) strcat( new_path, dirent->d_name );
108 
109     if( STAT_( new_path, &stat_struct ) )
110     {
111       if( errno == EACCES ) continue;
112       (void) sprintf( message, "Stat failed on*%s*IGNORED", new_path );
113       ERROR_MSG( message );
114       continue;
115     }
116 
117     if( S_ISDIR( stat_struct.st_mode ) )
118     {
119       /* Directory-Entry */
120       /*-----------------*/
121 
122       if( ( den_ptr = (DirEntry *)
123 		       malloc( sizeof( DirEntry ) + strlen( dirent->d_name ) )
124    	   ) == NULL )
125       {
126         ERROR_MSG( "Malloc Failed*ABORT" );
127         exit( 1 );
128       }
129 
130       den_ptr->up_tree = dir_entry;
131 
132       (void) strcpy( den_ptr->name, dirent->d_name );
133 
134       (void) memcpy( &den_ptr->stat_struct,
135 		     &stat_struct,
136 		     sizeof( stat_struct )
137 		    );
138       den_ptr->prev = den_ptr->next = NULL;
139 
140       (void) ReadTree( den_ptr, new_path, depth - 1);
141 
142       /* Sortieren durch direktes Einfuegen */
143       /*------------------------------------*/
144 
145       for( des_ptr = &first_dir_entry; des_ptr; des_ptr = des_ptr->next )
146       {
147         if( strcmp( des_ptr->name, den_ptr->name ) > 0 )
148         {
149 	  /* des-Element ist groesser */
150 	  /*--------------------------*/
151 
152 	  den_ptr->next = des_ptr;
153 	  den_ptr->prev = des_ptr->prev;
154 	  des_ptr->prev->next = den_ptr;
155 	  des_ptr->prev = den_ptr;
156 	  break;
157 	}
158 
159 	if( des_ptr->next == NULL )
160 	{
161 	  /* Ende der Liste erreicht; ==> einfuegen */
162 	  /*----------------------------------------*/
163 
164           den_ptr->prev = des_ptr;
165 	  den_ptr->next = des_ptr->next;
166           des_ptr->next = den_ptr;
167 	  break;
168 	}
169       }
170     }
171     else
172     {
173       /* File-Entry */
174       /*------------*/
175 
176       int n;
177       char link_path[PATH_LENGTH + 1];
178 
179       /* Test, ob Eintrag Symbolischer Link ist */
180       /*----------------------------------------*/
181 
182       n = 0; *link_path = '\0';
183 
184       if( S_ISLNK( stat_struct.st_mode ) )
185       {
186 	/* Ja, symbolischer Name wird an "echten" Namen angehaengt */
187 	/*---------------------------------------------------------*/
188 
189 	if( ( n = readlink( new_path, link_path, sizeof( link_path ) ) ) == -1 )
190 	{
191           (void) strcpy( link_path, "unknown" );
192 	  n = strlen( link_path );
193 	}
194 	link_path[n] = '\0';
195 
196         if( ( fen_ptr = (FileEntry *)
197 		        malloc( sizeof( FileEntry ) +
198 			strlen( dirent->d_name )    +
199 			n + 1 )
200 	    ) == NULL )
201         {
202           ERROR_MSG( "Malloc Failed*ABORT" );
203           exit( 1 );
204         }
205 
206         (void) strcpy( fen_ptr->name, dirent->d_name );
207         (void) strcpy( &fen_ptr->name[strlen(fen_ptr->name) + 1],
208 		       link_path );
209       }
210       else
211       {
212         if( ( fen_ptr = (FileEntry *)
213 		        malloc( sizeof( FileEntry ) + strlen( dirent->d_name ) )
214 	    ) == NULL )
215         {
216           ERROR_MSG( "Malloc Failed*ABORT" );
217           exit( 1 );
218         }
219 
220         (void) strcpy( fen_ptr->name, dirent->d_name );
221       }
222 
223       fen_ptr->next = NULL;
224       fen_ptr->prev = NULL;
225       fen_ptr->tagged = FALSE;
226 
227       (void) memcpy( &fen_ptr->stat_struct,
228 		     &stat_struct,
229 		     sizeof( stat_struct )
230 		    );
231 
232       fen_ptr->dir_entry = dir_entry;
233       fes_ptr->next      = fen_ptr;
234       fen_ptr->prev      = fes_ptr;
235       fes_ptr            = fen_ptr;
236       dir_entry->total_files++;
237       dir_entry->total_bytes += stat_struct.st_size;
238       statistic.disk_total_files++;
239       statistic.disk_total_bytes += stat_struct.st_size;
240     }
241   }
242 
243   (void) closedir( dir );
244 
245   if( first_file_entry.next ) first_file_entry.next->prev = NULL;
246   if( first_dir_entry.next )  first_dir_entry.next->prev = NULL;
247 
248   dir_entry->file = first_file_entry.next;
249   dir_entry->sub_tree = first_dir_entry.next;
250 
251   DisplayDiskStatistic();
252   doupdate();
253 
254   return( 0 );
255 }
256 
257 
258 
UnReadTree(DirEntry * dir_entry)259 void UnReadTree(DirEntry *dir_entry)
260 {
261   FileEntry *fe_ptr, *next_fe_ptr;
262 
263   if( dir_entry == statistic.tree )
264   {
265     MESSAGE( "Can't delete ROOT" );
266   }
267   else
268   {
269     for( fe_ptr=dir_entry->file; fe_ptr; fe_ptr=next_fe_ptr )
270     {
271       next_fe_ptr = fe_ptr->next;
272       RemoveFile( fe_ptr );
273     }
274     if( dir_entry->sub_tree )
275     {
276       UnReadSubTree( dir_entry->sub_tree );
277     }
278     statistic.disk_total_directories--;
279     (void) GetAvailBytes( &statistic.disk_space );
280     DisplayDiskStatistic();
281     doupdate();
282   }
283 }
284 
285 
UnReadSubTree(DirEntry * dir_entry)286 static void UnReadSubTree(DirEntry *dir_entry)
287 {
288   DirEntry *de_ptr, *next_de_ptr;
289   FileEntry *fe_ptr, *next_fe_ptr;
290 
291   for( de_ptr = dir_entry; de_ptr; de_ptr = next_de_ptr )
292   {
293     next_de_ptr = de_ptr->next;
294 
295     for( fe_ptr=de_ptr->file; fe_ptr; fe_ptr=next_fe_ptr )
296     {
297       next_fe_ptr = fe_ptr->next;
298       RemoveFile( fe_ptr );
299     }
300 
301     if( de_ptr->sub_tree )
302     {
303       UnReadSubTree( de_ptr->sub_tree );
304     }
305 
306     if( !de_ptr->up_tree->not_scanned )
307       statistic.disk_total_directories--;
308 
309     if( de_ptr->prev ) de_ptr->prev->next = de_ptr->next;
310     else de_ptr->up_tree->sub_tree = de_ptr->next;
311     if( de_ptr->next ) de_ptr->next->prev = de_ptr->prev;
312 
313     free( de_ptr );
314   }
315 }
316 
317