2 * CDE - Common Desktop Environment
4 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
6 * These libraries and programs are free software; you can
7 * redistribute them and/or modify them under the terms of the GNU
8 * Lesser General Public License as published by the Free Software
9 * Foundation; either version 2 of the License, or (at your option)
12 * These libraries and programs are distributed in the hope that
13 * they will be useful, but WITHOUT ANY WARRANTY; without even the
14 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU Lesser General Public License for more
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with these libraries and programs; if not, write
20 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21 * Floor, Boston, MA 02110-1301 USA
23 //%% (c) Copyright 1993, 1994 Hewlett-Packard Company
24 //%% (c) Copyright 1993, 1994 International Business Machines Corp.
25 //%% (c) Copyright 1993, 1994 Sun Microsystems, Inc.
26 //%% (c) Copyright 1993, 1994 Novell, Inc.
27 //%% $XConsortium: tttar_api.C /main/4 1995/10/20 16:59:54 rswiston $
29 * tttar_api.cc - ToolTalk object archiving interface functions.
31 * Copyright (c) 1990 by Sun Microsystems, Inc.
36 #if defined(__linux__) || defined(CSRG_BASED) || defined(sun)
41 #include <sys/param.h>
42 #include "api/c/api_api.h"
43 #include "api/c/tt_c.h"
44 #include "util/tt_path.h"
45 #include "util/tt_gettext.h"
46 #include "tttar_utils.h"
47 #include "tttar_file_utils.h"
48 #include "tttar_spec.h"
49 #include "tttar_api.h"
60 // Number of buckets in a hash table of interesting specs in an archive.
61 #define SPEC_MAP_SIZE 1000
66 static bool_t path_lstt_archive(
70 bool_t dearchive_this_path(
71 char *path, void *ppaths_to_extract );
72 static Tt_filter_action gather_specs( const char *spec_id, void *,
76 * pathlist_lstt_archive() - Archive the LS/TT objects in the given paths.
79 pathlist_lstt_archive(
80 _Tt_string_list_ptr paths,
82 bool_t follow_symlinks,
86 _Tt_string_list_ptr realpaths2tar;
88 _Tt_string_list_ptr paths_copy(new _Tt_string_list);
89 _Tt_string_list_cursor path_cursor( paths );
90 while (path_cursor.next()) {
91 paths_copy->append( *path_cursor );
94 bool_t need_preliminary_pass = follow_symlinks && recurse;
95 realpaths2tar = realtrees( paths_copy, need_preliminary_pass );
97 obj_kind = VERSION_NUM;
98 int version = CURRENT_ARCHIVE_VERSION;
99 if ( (! xdr_enum( xdrs, (enum_t *)&obj_kind ))
100 || (! xdr_int( xdrs, &version )))
102 fprintf( stderr, "%s: ! xdr_enum() || ! xdr_int()\n",
103 (char *)our_process_name );
106 while (! paths_copy->is_empty()) {
107 _Tt_string_list_ptr children;
108 _Tt_string path( paths_copy->top() );
111 if (! path_lstt_archive( path, verbosity, xdrs ))
116 children = _tt_dir_entries( path, follow_symlinks );
117 children->append_destructive( paths_copy );
118 paths_copy = children;
121 obj_kind = ARCHIVE_END;
122 if (! xdr_enum( xdrs, (enum_t *)&obj_kind )) {
123 fprintf( stderr, "%s: ! xdr_enum()\n",
124 (char *)our_process_name );
129 } /* pathlist_lstt_archive() */
132 * pathlist_lstt_dearchive() - Extract the LS/TT objects of the given paths.
133 * If no paths are given, extract everything in the archive.
136 pathlist_lstt_dearchive(
137 _Tt_string_list_ptr paths_to_extract,
138 Lstar_string_map_list_ptr renamings,
139 _Tt_string where_to_dearchive,
140 bool_t preserve__props,
144 _Tt_string last_path;
145 char *this_path = NULL;
148 bool_t last_path_valid = FALSE;
149 Object_kind obj_kind = NO_KIND;
150 Lstar_string_map_table_ptr spec_map;
151 int mem_mark = tt_mark();
153 spec_map = new Lstar_string_map_table(Lstar_string_map_old_string,
156 bool_t just_dearchived_spec = FALSE;
157 bool_t just_dearchived_link = FALSE;
159 if (! xdr_enum( xdrs, (enum_t *)&obj_kind )) {
161 catgets(_ttcatd, 7, 4,
162 "%s: Could not read object kind "
163 "from archive stream.\n"),
164 (char *)our_process_name );
170 if (! xdr_int( xdrs, &version)) {
172 catgets(_ttcatd, 7, 5,
173 "%s: Could not read archive ver"
174 "sion from archive stream.\n"),
175 (char *)our_process_name );
178 if (version != CURRENT_ARCHIVE_VERSION) {
180 catgets(_ttcatd, 7, 6,
181 "%s: Found archive version %d, "
182 "but expected version %d.\n"),
183 (char *)our_process_name, version,
184 CURRENT_ARCHIVE_VERSION );
197 if (! spec_dearchive( &old_spec_id, &new_spec_id,
198 &this_path, renamings,
199 (char *)where_to_dearchive,
202 (void *)&paths_to_extract,
206 my_tt_release( mem_mark );
209 if (new_spec_id != NULL) {
210 Lstar_string_map_ptr m = new Lstar_string_map;
212 m->old_string_set( old_spec_id );
213 m->new_string_set( new_spec_id );
214 m->extra_set( this_path );
215 spec_map->insert( m );
217 just_dearchived_spec = TRUE;
225 catgets(_ttcatd, 7, 7,
226 "%s: found object of unknown kind "
228 (char *)our_process_name, (int)obj_kind );
231 if (verbosity && ( (last_path != (const char *)this_path)
232 || (obj_kind == ARCHIVE_END)))
234 if (last_path_valid) {
235 if (just_dearchived_spec) {
237 } else if (just_dearchived_link) {
241 fprintf( stderr, "\n" );
243 if ( (num_specs > 0) || (num_links > 0)) {
244 fprintf( stderr, "x %s %d %s\n",
245 (char *)last_path, num_specs,
247 ? "spec" : "specs" ));
251 if (just_dearchived_spec) {
253 } else if (just_dearchived_link) {
257 last_path = this_path;
258 if (! last_path_valid) {
259 last_path_valid = TRUE;
262 } while (obj_kind != ARCHIVE_END);
263 my_tt_release( mem_mark );
266 } /* pathlist_lstt_dearchive() */
269 * pathlist_lstt_archive_list() - List the LS/TT objects of the given paths.
270 * If no paths are given, list everything in the archive.
273 pathlist_lstt_archive_list(
274 _Tt_string_list_ptr paths_to_list,
278 _Tt_string last_path;
279 _Tt_string this_path;
282 bool_t last_path_valid = FALSE;
283 Object_kind obj_kind = NO_KIND;
284 Lstar_string_map_table_ptr spec_map;
285 int mem_mark = tt_mark();
287 spec_map = new Lstar_string_map_table(Lstar_string_map_old_string,
292 if (! xdr_enum( xdrs, (enum_t *)&obj_kind )) {
294 catgets(_ttcatd, 7, 8,
295 "%s: Could not read object kind "
296 "from archive stream.\n"),
297 (char *)our_process_name );
303 if (! xdr_int( xdrs, &version)) {
305 catgets(_ttcatd, 7, 9,
306 "%s: Could not read archive ver"
307 "sion from archive stream.\n"),
308 (char *)our_process_name );
311 if (version != CURRENT_ARCHIVE_VERSION) {
313 catgets(_ttcatd, 7, 10,
314 "%s: Found archive version %d, "
315 "but expected version %d.\n"),
316 (char *)our_process_name, version,
317 CURRENT_ARCHIVE_VERSION );
322 if (! spec.xdr(xdrs)) {
323 my_tt_release( mem_mark );
326 if (dearchive_this_path( (char *)spec.path(),
329 Lstar_string_map_ptr m = new Lstar_string_map;
332 * Insert it into this "map" just so that
333 * we can use the map to figure out if
334 * a given link counts under paths_to_list.
336 m->old_string_set( spec.id() );
337 m->extra_set( spec.path() );
338 spec_map->insert( m );
339 this_path = spec.path();
342 spec.print( stdout );
353 catgets(_ttcatd, 7, 11,
354 "%s: found object of unknown kind "
356 (char *)our_process_name, (int)obj_kind );
359 if ( (last_path != this_path)
360 || (obj_kind == ARCHIVE_END))
362 if (last_path_valid) {
363 if (obj_kind == SPEC) {
365 } else if (obj_kind == SUN_LINK) {
368 printf( "%s %d %s\n",
369 (char *)last_path, num_specs,
370 (num_specs == 1 ? "spec" : "specs" ));
373 if (obj_kind == SPEC) {
375 } else if (obj_kind == SUN_LINK) {
379 last_path = this_path;
380 if (! last_path_valid) {
381 last_path_valid = TRUE;
384 } while (obj_kind != ARCHIVE_END);
385 my_tt_release( mem_mark );
388 } /* pathlist_lstt_archive_list() */
391 * path_lstt_archive() - Archive the specs on the given path.
399 _Tt_string_list *specs;
400 Object_kind obj_kind;
401 int num_specs_archived = 0;
402 int num_links_archived = 0;
403 bool_t val2return = TRUE;
405 specs = new _Tt_string_list;
406 note_err( tt_file_objects_query( (char *)path, gather_specs, NULL, specs ));
407 if (IS_TT_ERR(err_noted)) {
411 while (! specs->is_empty()) {
412 _Tt_string spec = specs->top();
417 if (! xdr_enum( xdrs, (enum_t *)&obj_kind )) {
418 fprintf( stderr, "%s: ! xdr_enum()\n",
419 (char *)our_process_name );
423 if (! spec_archive( (char *)spec, (char *)path, verbosity,
429 num_specs_archived++;
431 if ((verbosity && num_specs_archived > 0 ) || (verbosity > 1)) {
433 fprintf( stderr, "\n" );
435 fprintf( stderr, "a %s: %d %s\n", (char *)path,
437 ((num_specs_archived == 1) ? "spec" : "specs" ));
442 } /* path_lstt_archive() */
446 * spec_archive() - Archive a spec onto the given XDR stream.
449 spec_archive( char *id, char *path, int verbosity, XDR *xdrs, Tt_status *err )
451 _Tt_string _path( path );
452 _Tt_string _id( id );
455 if (xdrs->x_op == XDR_ENCODE) {
456 Lstar_spec spec( _id, _path );
458 *err = spec.read_self();
459 if (IS_TT_ERR(*err)) {
462 if (! spec.xdr(xdrs)) {
466 spec.print( stderr );
473 } /* spec_archive() */
476 * spec_dearchive() - Recreate a spec that was archived on this XDR stream.
480 char **old_spec_id_ptr,
481 char **new_spec_id_ptr,
482 char **path_as_archived,
483 Lstar_string_map_list_ptr renamings,
484 char *where_to_create,
485 bool_t preserve__props,
486 bool_t (*dearchive_this_path)(char *, void *),
492 _Tt_string where( where_to_create );
495 *old_spec_id_ptr = NULL;
496 *new_spec_id_ptr = NULL;
497 *path_as_archived = NULL;
498 if (xdrs->x_op == XDR_ENCODE) {
500 } else if (xdrs->x_op == XDR_DECODE) {
504 if (! spec.xdr(xdrs)) {
507 *old_spec_id_ptr = _tt_strdup( spec.id() );
508 *path_as_archived = _tt_strdup( spec.path() );
510 if ( (dearchive_this_path == NULL)
511 || (dearchive_this_path( (char *)path, context )))
513 _Tt_string _new_name = new_name( spec.path(),
515 if (_new_name.len() > 0) {
517 fprintf( stderr, "%s => ",
518 (char *)spec.path() );
520 spec.path_set( _new_name );
522 fprintf( stderr, "%s\n",
523 (char *)spec.path() );
527 spec.write_self( where, preserve__props, err );
528 if (! IS_TT_ERR(*err) && (verbosity > 1)) {
529 spec.print( stdout );
535 } /* spec_dearchive() */
539 * dearchive_this_path() - Should we extract this <path> from its archive?
541 * Returns true if *ppaths_to_extract is an empty list.
544 dearchive_this_path( char *path, void *ppaths_to_extract )
546 _Tt_string_list_ptr paths;
547 _Tt_string _path( path );
549 if (ppaths_to_extract == NULL) {
552 paths = *(_Tt_string_list_ptr *)ppaths_to_extract;
553 if (paths->count() <= 0) {
556 return is_child_in( _path, paths );
558 } /* dearchive_this_path() */
563 static Tt_filter_action
564 gather_specs( const char *spec_id, void *, void *specs )
566 _Tt_string id = spec_id;
567 ((_Tt_string_list *)specs)->push( id );
568 return TT_FILTER_CONTINUE;