1 /***************************************************************************
2 *
3 * $Header: /usr/local/cvsroot/utils/ytree/archive.c,v 1.16 2000/05/20 20:41:11 werner Exp $
4 *
5 * Allg. Funktionen zum Bearbeiten von Archiven
6 *
7 ***************************************************************************/
8
9
10 #include "ytree.h"
11
12
13
14 static int GetArchiveDirEntry(DirEntry *tree, char *path, DirEntry **dir_entry);
15
16
InsertArchiveDirEntry(DirEntry * tree,char * path,struct stat * stat)17 static int InsertArchiveDirEntry(DirEntry *tree, char *path, struct stat *stat)
18 {
19 DirEntry *df_ptr, *de_ptr, *ds_ptr;
20 char father_path[PATH_LENGTH + 1];
21 char *p;
22 char name[PATH_LENGTH + 1];
23
24
25 #ifdef DEBUG
26 fprintf( stderr, "Insert Dir \"%s\"\n", path );
27 #endif
28
29 /* Format: .../dir/ */
30 /*------------------*/
31
32 (void) strcpy( father_path, path );
33
34 if( ( p = strrchr( father_path, FILE_SEPARATOR_CHAR ) ) ) *p = '\0';
35 else
36 {
37 (void) sprintf( message, "path mismatch*missing '%c' in*%s",
38 FILE_SEPARATOR_CHAR,
39 path
40 );
41 ERROR_MSG( message );
42 return( -1 );
43 }
44
45 p = strrchr( father_path, FILE_SEPARATOR_CHAR );
46
47 if( p == NULL )
48 {
49 df_ptr = tree;
50 if( !strcmp( path, FILE_SEPARATOR_STRING ) )
51 (void) strcpy( name, path );
52 else
53 (void) strcpy( name, father_path );
54 }
55 else
56 {
57 (void) strcpy( name, ++p );
58 *p = '\0';
59 if( GetArchiveDirEntry( tree, father_path, &df_ptr ) )
60 {
61 (void) sprintf( message, "can't find subdir*%s", father_path );
62 ERROR_MSG( message );
63 return( -1 );
64 }
65 }
66
67 if( ( de_ptr = (DirEntry *) malloc( sizeof( DirEntry ) + strlen( name ) ) ) == NULL )
68 {
69 ERROR_MSG( "Malloc failed*ABORT" );
70 exit( 1 );
71 }
72
73 (void) memset( (char *) de_ptr, 0, sizeof( DirEntry ) );
74 (void) strcpy( de_ptr->name, name );
75 (void) memcpy( (char *) &de_ptr->stat_struct, (char *) stat, sizeof( struct stat ) );
76
77 #ifdef DEBUG
78 fprintf( stderr, "new dir: \"%s\"\n", name );
79 #endif
80
81
82
83 /* Directory einklinken */
84 /*----------------------*/
85
86 if( p == NULL )
87 {
88 /* in tree (=df_ptr) einklinken */
89 /*------------------------------*/
90
91 de_ptr->up_tree = df_ptr->up_tree;
92
93 for( ds_ptr = df_ptr; ds_ptr; ds_ptr = ds_ptr->next )
94 {
95 if( strcmp( ds_ptr->name, de_ptr->name ) > 0 )
96 {
97 /* ds-Element ist groesser */
98 /*-------------------------*/
99
100 de_ptr->next = ds_ptr;
101 de_ptr->prev = ds_ptr->prev;
102 if( ds_ptr->prev) ds_ptr->prev->next = de_ptr;
103 ds_ptr->prev = de_ptr;
104 if( de_ptr->up_tree && de_ptr->up_tree->sub_tree == de_ptr->next )
105 de_ptr->up_tree->sub_tree = de_ptr;
106 break;
107 }
108
109 if( ds_ptr->next == NULL )
110 {
111 /* Ende der Liste erreicht; ==> einfuegen */
112 /*----------------------------------------*/
113
114 de_ptr->prev = ds_ptr;
115 de_ptr->next = ds_ptr->next;
116 ds_ptr->next = de_ptr;
117 break;
118 }
119 }
120 }
121 else if( df_ptr->sub_tree == NULL )
122 {
123 de_ptr->up_tree = df_ptr;
124 df_ptr->sub_tree = de_ptr;
125 }
126 else
127 {
128 de_ptr->up_tree = df_ptr;
129
130 for( ds_ptr = df_ptr->sub_tree; ds_ptr; ds_ptr = ds_ptr->next )
131 {
132 if( strcmp( ds_ptr->name, de_ptr->name ) > 0 )
133 {
134 /* ds-Element ist groesser */
135 /*-------------------------*/
136
137 de_ptr->next = ds_ptr;
138 de_ptr->prev = ds_ptr->prev;
139 if( ds_ptr->prev ) ds_ptr->prev->next = de_ptr;
140 ds_ptr->prev = de_ptr;
141 if( de_ptr->up_tree->sub_tree == de_ptr->next )
142 de_ptr->up_tree->sub_tree = de_ptr;
143 break;
144 }
145
146 if( ds_ptr->next == NULL )
147 {
148 /* Ende der Liste erreicht; ==> einfuegen */
149 /*----------------------------------------*/
150
151 de_ptr->prev = ds_ptr;
152 de_ptr->next = ds_ptr->next;
153 ds_ptr->next = de_ptr;
154 break;
155 }
156 }
157 }
158 statistic.disk_total_directories++;
159 return( 0 );
160 }
161
162
163
164
165
InsertArchiveFileEntry(DirEntry * tree,char * path,struct stat * stat)166 int InsertArchiveFileEntry(DirEntry *tree, char *path, struct stat *stat)
167 {
168 char dir[PATH_LENGTH + 1];
169 char file[PATH_LENGTH + 1];
170 DirEntry *de_ptr;
171 FileEntry *fs_ptr, *fe_ptr;
172 struct stat stat_struct;
173 int n;
174
175
176 if( KeyPressed() )
177 {
178 Quit(); /* Abfrage, ob ytree verlassen werden soll */
179 }
180
181
182 Fnsplit( path, dir, file );
183
184 if( GetArchiveDirEntry( tree, dir, &de_ptr ) )
185 {
186 #ifdef DEBUG
187 fprintf( stderr, "can't get directory for file*%s*trying recover", path );
188 #endif
189
190 (void) memset( (char *) &stat_struct, 0, sizeof( struct stat ) );
191 stat_struct.st_mode = S_IFDIR;
192
193 if( TryInsertArchiveDirEntry( tree, dir, &stat_struct ) )
194 {
195 ERROR_MSG( "inserting directory failed" );
196 return( -1 );
197 }
198 if( GetArchiveDirEntry( tree, dir, &de_ptr ) )
199 {
200 (void) sprintf( message, "again: can't get directory for file*%s*giving up", path );
201 ERROR_MSG( message );
202 return( -1 );
203 }
204 }
205
206 if( S_ISLNK( stat->st_mode ) )
207 n = strlen( &path[ strlen( path ) + 1 ] ) + 1;
208 else
209 n = 0;
210
211 if( ( fe_ptr = (FileEntry *) malloc( sizeof( FileEntry ) + strlen( file ) + n ) ) == NULL )
212 {
213 ERROR_MSG( "Malloc failed*ABORT" );
214 exit( 1 );
215 }
216
217 (void) memset( fe_ptr, 0, sizeof( FileEntry ) );
218 (void) memcpy( (char *) &fe_ptr->stat_struct, (char *) stat, sizeof( struct stat ) );
219 (void) strcpy( fe_ptr->name, file );
220
221 if( S_ISLNK( stat->st_mode ) )
222 {
223 (void) strcpy( &fe_ptr->name[ strlen( fe_ptr->name ) + 1 ],
224 &path[ strlen( path ) + 1 ]
225 );
226 }
227
228 fe_ptr->dir_entry = de_ptr;
229 de_ptr->total_files++;
230 de_ptr->total_bytes += stat->st_size;
231 statistic.disk_total_files++;
232 statistic.disk_total_bytes += stat->st_size;
233
234 /* Einklinken */
235 /*------------*/
236
237 if( de_ptr->file == NULL )
238 {
239 de_ptr->file = fe_ptr;
240 }
241 else
242 {
243 for( fs_ptr = de_ptr->file; fs_ptr->next; fs_ptr = fs_ptr->next )
244 ;
245
246 fe_ptr->prev = fs_ptr;
247 fs_ptr->next = fe_ptr;
248 }
249 return( 0 );
250 }
251
252
253
254
255
GetArchiveDirEntry(DirEntry * tree,char * path,DirEntry ** dir_entry)256 static int GetArchiveDirEntry(DirEntry *tree, char *path, DirEntry **dir_entry)
257 {
258 int n;
259 DirEntry *de_ptr;
260 BOOL is_root = FALSE;
261
262 #ifdef DEBUG
263 fprintf( stderr, "GetArchiveDirEntry: tree=%s, path=%s\n",
264 (tree) ? tree->name : "NULL", path );
265 #endif
266
267 if( strchr( path, FILE_SEPARATOR_CHAR ) != NULL )
268 {
269 for( de_ptr = tree; de_ptr; de_ptr = de_ptr->next )
270 {
271 n = strlen( de_ptr->name );
272 if( !strcmp( de_ptr->name, FILE_SEPARATOR_STRING ) ) is_root = TRUE;
273
274 if( n && !strncmp( de_ptr->name, path, n ) &&
275 (is_root || path[n] == '\0' || path[n] == FILE_SEPARATOR_CHAR ) )
276 {
277 if( ( is_root && path[n] == '\0' ) ||
278 ( path[n] == FILE_SEPARATOR_CHAR && path[n+1] == '\0' ) )
279 {
280 /* Pfad abgearbeitet; ==> fertig */
281 /*-------------------------------*/
282
283 *dir_entry = de_ptr;
284 return( 0 );
285 }
286 else
287 {
288 return( GetArchiveDirEntry( de_ptr->sub_tree,
289 ( is_root ) ? &path[n] : &path[n+1],
290 dir_entry
291 ) );
292 }
293 }
294 }
295 }
296 if( *path == '\0' )
297 {
298 *dir_entry = tree;
299 return( 0 );
300 }
301 return( -1 );
302 }
303
304
305
306
307
TryInsertArchiveDirEntry(DirEntry * tree,char * dir,struct stat * stat)308 int TryInsertArchiveDirEntry(DirEntry *tree, char *dir, struct stat *stat)
309 {
310 DirEntry *de_ptr;
311 char dir_path[PATH_LENGTH + 1];
312 char *s, *t;
313
314 (void) memset( dir_path, 0, sizeof( dir_path ) );
315
316 #ifdef DEBUG
317 fprintf( stderr, "Try install start \n" );
318 #endif
319
320 for( s=dir, t=dir_path; *s; s++, t++ )
321 {
322 if( (*t = *s) == FILE_SEPARATOR_CHAR )
323 {
324 if( GetArchiveDirEntry( tree, dir_path, &de_ptr ) == -1 )
325 {
326 /* Evtl. fehlender teil; ==> einfuegen */
327 /*-------------------------------------*/
328
329 if( InsertArchiveDirEntry( tree, dir_path, stat ) ) return( -1 );
330 }
331 }
332 }
333
334 #ifdef DEBUG
335 fprintf( stderr, "Try install end\n" );
336 #endif
337
338 return( 0 );
339 }
340
341
342
343
344
345
MinimizeArchiveTree(DirEntry * tree)346 int MinimizeArchiveTree(DirEntry *tree)
347 {
348 DirEntry *de_ptr, *de1_ptr;
349 DirEntry *next_ptr;
350 FileEntry *fe_ptr;
351
352
353 /* Falls tree einen Nachfolger hat und
354 * tree selbst leer ist, wird tree gestrichen
355 */
356
357 if( tree->prev == NULL &&
358 tree->next != NULL &&
359 tree->file == NULL )
360 {
361 next_ptr = tree->next;
362 (void) memcpy( (char *) tree,
363 (char *) tree->next,
364 sizeof( DirEntry ) + strlen( tree->next->name )
365 );
366 tree->prev = NULL;
367 if( tree->next ) tree->next->prev = tree;
368 statistic.disk_total_directories--;
369 free( next_ptr );
370 for( fe_ptr=tree->file; fe_ptr; fe_ptr=fe_ptr->next)
371 fe_ptr->dir_entry = tree;
372 for( de_ptr=tree->sub_tree; de_ptr; de_ptr=de_ptr->next)
373 de_ptr->up_tree = tree;
374 }
375
376
377 /* Test, ob *de_ptr weder Vorgaenger noch Nachfolger noch Dateien hat */
378 /*--------------------------------------------------------------------*/
379
380 for( de_ptr = tree->sub_tree; de_ptr; de_ptr = next_ptr )
381 {
382 if( de_ptr->prev == NULL && de_ptr->next == NULL && de_ptr->file == NULL )
383 {
384 /* Zusammenfassung moeglich */
385 /*--------------------------*/
386
387 if( strcmp( tree->name, FILE_SEPARATOR_STRING ) )
388 (void) strcat( tree->name, FILE_SEPARATOR_STRING );
389 (void) strcat( tree->name, de_ptr->name );
390 statistic.disk_total_directories--;
391 tree->sub_tree = de_ptr->sub_tree;
392 for( de1_ptr = de_ptr->sub_tree; de1_ptr; de1_ptr = de1_ptr->next )
393 de1_ptr->up_tree = tree;
394 next_ptr = de_ptr->sub_tree;
395 free( de_ptr );
396 #ifdef DEBUG
397 fprintf( stderr, "new root-dir: \"%s\"\n", tree->name );
398 #endif
399 continue;
400 }
401 break;
402 }
403
404 /* Letzter Optimierungsschritt:
405 * Falls tree weder Vorgaenger noch Nachfolger hat, aber
406 * einen Subtree der Files hat, wird zusammengefasst
407 */
408
409 if( tree->prev == NULL &&
410 tree->next == NULL &&
411 tree->file == NULL &&
412 tree->sub_tree &&
413 tree->sub_tree->prev == NULL &&
414 tree->sub_tree->next == NULL
415 )
416 {
417 de_ptr = tree->sub_tree;
418 (void) strcat( tree->name, FILE_SEPARATOR_STRING );
419 (void) strcat( tree->name, de_ptr->name );
420 tree->file = de_ptr->file;
421 for( fe_ptr=tree->file; fe_ptr; fe_ptr=fe_ptr->next )
422 fe_ptr->dir_entry = tree;
423 (void) memcpy( (char *) &tree->stat_struct,
424 (char *) &de_ptr->stat_struct,
425 sizeof( struct stat )
426 );
427 statistic.disk_total_directories--;
428 tree->sub_tree = de_ptr->sub_tree;
429 for( de1_ptr = de_ptr->sub_tree; de1_ptr; de1_ptr = de1_ptr->next )
430 de1_ptr->up_tree = tree;
431 free( de_ptr );
432 }
433 return( 0 );
434 }
435
436
437
MakeExtractCommandLine(char * command_line,char * path,char * file,char * cmd)438 void MakeExtractCommandLine(char *command_line, char *path, char *file, char *cmd)
439 {
440 int l;
441 char cat_path[PATH_LENGTH+1];
442 int compress_method;
443
444 compress_method = GetFileMethod( path );
445
446 l = strlen( path );
447
448 if( compress_method == ZOO_COMPRESS )
449 {
450 /* zoo xp FILE ?? */
451 /*----------------*/
452
453 (void) sprintf( command_line, "%s '%s' '%s' %s",
454 ZOOEXPAND,
455 path,
456 file,
457 cmd
458 );
459 }
460 else if( compress_method == LHA_COMPRESS )
461 {
462 /* xlharc p FILE ?? */
463 /*------------------*/
464
465 (void) sprintf( command_line, "%s '%s' '%s' %s",
466 LHAEXPAND,
467 path,
468 file,
469 cmd
470 );
471 }
472 else if( compress_method == ZIP_COMPRESS )
473 {
474 /* unzip -c FILE ?? */
475 /*------------------*/
476
477 (void) sprintf( command_line, "%s '%s' '%s' %s",
478 ZIPEXPAND,
479 path,
480 file,
481 cmd
482 );
483 }
484 else if( compress_method == ARC_COMPRESS )
485 {
486 /* arc p FILE ?? */
487 /*---------------*/
488
489 (void) sprintf( command_line, "%s '%s' '%s' %s",
490 ARCEXPAND,
491 path,
492 file,
493 cmd
494 );
495 }
496 else if( compress_method == RPM_COMPRESS )
497 {
498 /* TF=/tmp/ytree.$$; mkdir $TF; cd $TF; rpm2cpio RPM_FILE | cpio -id FILE;
499 * cat $TF/$2; cd /tmp; rm -rf $TF; exit 0
500 */
501
502
503 if(!strcmp(RPMEXPAND, "builtin")) {
504 (void) sprintf( command_line,
505 "(TF=/tmp/ytree.$$; mkdir $TF; rpm2cpio '%s' | (cd $TF; cpio --no-absolute-filenames -i -d '%s'); cat \"$TF/%s\"; cd /tmp; rm -rf $TF; exit 0) %s",
506 path,
507 (*file == FILE_SEPARATOR_CHAR) ? &file[1] : file,
508 file,
509 cmd
510 );
511 } else {
512 (void) sprintf( command_line, "%s '%s' '%s' %s",
513 RPMEXPAND,
514 path,
515 file,
516 cmd
517 );
518 }
519 }
520 else if( compress_method == RAR_COMPRESS )
521 {
522 /* rar p FILE ?? */
523 /*---------------*/
524
525 (void) sprintf( command_line, "%s '%s' '%s' %s",
526 RAREXPAND,
527 path,
528 file,
529 cmd
530 );
531 }
532 else if( compress_method == FREEZE_COMPRESS )
533 {
534 /* melt < TAR_FILE | gtar xOf - FILE ?? */
535 /*--------------------------------------*/
536
537 (void) sprintf( command_line, "%s < '%s' | %s '%s' %s",
538 MELT,
539 path,
540 TAREXPAND,
541 file,
542 cmd
543 );
544 }
545 else if( compress_method == MULTIPLE_FREEZE_COMPRESS )
546 {
547 /* CAT TAR_FILEs | melt | gtar xOf - FILE ?? */
548 /*-------------------------------------------*/
549
550 (void) strncpy( cat_path, path, l - 2 );
551 (void) strcpy( &cat_path[l-2], "*" );
552
553 (void) sprintf( command_line, "%s %s | %s | %s '%s' %s",
554 CAT,
555 cat_path,
556 MELT,
557 TAREXPAND,
558 file,
559 cmd
560 );
561 }
562 else if( compress_method == COMPRESS_COMPRESS )
563 {
564 /* uncompress < TAR_FILE | gtar xOf - FILE ?? */
565 /*--------------------------------------------*/
566
567 (void) sprintf( command_line, "%s < %s | %s '%s' %s",
568 UNCOMPRESS,
569 path,
570 TAREXPAND,
571 file,
572 cmd
573 );
574 }
575 else if( compress_method == MULTIPLE_COMPRESS_COMPRESS )
576 {
577 /* CAT TAR_FILEs | uncompress | gtar xOf - FILE ?? */
578 /*-------------------------------------------------*/
579
580 (void) strncpy( cat_path, path, l - 2 );
581 (void) strcpy( &cat_path[l-2], "*" );
582
583 (void) sprintf( command_line, "%s %s | %s | %s '%s' %s",
584 CAT,
585 cat_path,
586 UNCOMPRESS,
587 TAREXPAND,
588 file,
589 cmd
590 );
591 }
592 else if( compress_method == GZIP_COMPRESS )
593 {
594 /* gunzip < TAR_FILE | gtar xOf - FILE ?? */
595 /*----------------------------------------*/
596
597 (void) sprintf( command_line, "%s < '%s' | %s '%s' %s",
598 GNUUNZIP,
599 path,
600 TAREXPAND,
601 file,
602 cmd
603 );
604 }
605 else if( compress_method == MULTIPLE_GZIP_COMPRESS )
606 {
607 /* CAT TAR_FILEs | gunzip | gtar xOf - FILE ?? */
608 /*---------------------------------------------*/
609
610 (void) strncpy( cat_path, path, l - 2 );
611 (void) strcpy( &cat_path[l-2], "*" );
612
613 (void) sprintf( command_line, "%s %s | %s | %s '%s' %s",
614 CAT,
615 cat_path,
616 GNUUNZIP,
617 TAREXPAND,
618 file,
619 cmd
620 );
621 }
622 else if( compress_method == BZIP_COMPRESS )
623 {
624 /* bunzip2 < TAR_FILE | gtar xOf - FILE ?? */
625 /*----------------------------------------*/
626
627 (void) sprintf( command_line, "%s < '%s' | %s '%s' %s",
628 BUNZIP,
629 path,
630 TAREXPAND,
631 file,
632 cmd
633 );
634 }
635 else
636 {
637 /* gtar xOf - FILE < TAR_FILE ?? */
638 /*-------------------------------*/
639
640 (void) sprintf( command_line, "%s '%s' < '%s' %s",
641 TAREXPAND,
642 file,
643 path,
644 cmd
645 );
646 }
647
648 #ifdef DEBUG
649 fprintf( stderr, "system( \"%s\" )\n", command_line );
650 #endif
651
652 }
653
654