/* * CDE - Common Desktop Environment * * Copyright (c) 1993-2012, The Open Group. All rights reserved. * * These libraries and programs are free software; you can * redistribute them and/or modify them under the terms of the GNU * Lesser General Public License as published by the Free Software * Foundation; either version 2 of the License, or (at your option) * any later version. * * These libraries and programs are distributed in the hope that * they will be useful, but WITHOUT ANY WARRANTY; without even the * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public * License along with these libraries and programs; if not, write * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth * Floor, Boston, MA 02110-1301 USA */ //%% (c) Copyright 1993, 1994 Hewlett-Packard Company //%% (c) Copyright 1993, 1994 International Business Machines Corp. //%% (c) Copyright 1993, 1994 Sun Microsystems, Inc. //%% (c) Copyright 1993, 1994 Novell, Inc. //%% $XConsortium: tttar_api.C /main/4 1995/10/20 16:59:54 rswiston $ /* * tttar_api.cc - ToolTalk object archiving interface functions. * * Copyright (c) 1990 by Sun Microsystems, Inc. * */ #include #if defined(__linux__) || defined(CSRG_BASED) || defined(sun) #include #else #include #endif #include #include "api/c/api_api.h" #include "api/c/tt_c.h" #include "util/tt_path.h" #include "util/tt_gettext.h" #include "tttar_utils.h" #include "tttar_file_utils.h" #include "tttar_spec.h" #include "tttar_api.h" /* * Type definitions */ /* * Constants */ // Number of buckets in a hash table of interesting specs in an archive. #define SPEC_MAP_SIZE 1000 /* * Private functions */ static bool_t path_lstt_archive( _Tt_string path, int verbosity, XDR *xdrs ); bool_t dearchive_this_path( char *path, void *ppaths_to_extract ); static Tt_filter_action gather_specs( const char *spec_id, void *, void *specs); /* * pathlist_lstt_archive() - Archive the LS/TT objects in the given paths. */ bool_t pathlist_lstt_archive( _Tt_string_list_ptr paths, bool_t recurse, bool_t follow_symlinks, int verbosity, XDR *xdrs ) { _Tt_string_list_ptr realpaths2tar; Object_kind obj_kind; _Tt_string_list_ptr paths_copy(new _Tt_string_list); _Tt_string_list_cursor path_cursor( paths ); while (path_cursor.next()) { paths_copy->append( *path_cursor ); } bool_t need_preliminary_pass = follow_symlinks && recurse; realpaths2tar = realtrees( paths_copy, need_preliminary_pass ); obj_kind = VERSION_NUM; int version = CURRENT_ARCHIVE_VERSION; if ( (! xdr_enum( xdrs, (enum_t *)&obj_kind )) || (! xdr_int( xdrs, &version ))) { fprintf( stderr, "%s: ! xdr_enum() || ! xdr_int()\n", (char *)our_process_name ); return FALSE; } while (! paths_copy->is_empty()) { _Tt_string_list_ptr children; _Tt_string path( paths_copy->top() ); paths_copy->pop(); if (! path_lstt_archive( path, verbosity, xdrs )) { return FALSE; } if (recurse) { children = _tt_dir_entries( path, follow_symlinks ); children->append_destructive( paths_copy ); paths_copy = children; } } obj_kind = ARCHIVE_END; if (! xdr_enum( xdrs, (enum_t *)&obj_kind )) { fprintf( stderr, "%s: ! xdr_enum()\n", (char *)our_process_name ); return FALSE; } return TRUE; } /* pathlist_lstt_archive() */ /* * pathlist_lstt_dearchive() - Extract the LS/TT objects of the given paths. * If no paths are given, extract everything in the archive. */ bool_t pathlist_lstt_dearchive( _Tt_string_list_ptr paths_to_extract, Lstar_string_map_list_ptr renamings, _Tt_string where_to_dearchive, bool_t preserve__props, int verbosity, XDR *xdrs ) { _Tt_string last_path; char *this_path = NULL; int num_specs = 0; int num_links = 0; bool_t last_path_valid = FALSE; Object_kind obj_kind = NO_KIND; Lstar_string_map_table_ptr spec_map; int mem_mark = tt_mark(); spec_map = new Lstar_string_map_table(Lstar_string_map_old_string, SPEC_MAP_SIZE ); do { bool_t just_dearchived_spec = FALSE; bool_t just_dearchived_link = FALSE; if (! xdr_enum( xdrs, (enum_t *)&obj_kind )) { fprintf( stderr, catgets(_ttcatd, 7, 4, "%s: Could not read object kind " "from archive stream.\n"), (char *)our_process_name ); return FALSE; } switch (obj_kind) { case VERSION_NUM: int version; if (! xdr_int( xdrs, &version)) { fprintf( stderr, catgets(_ttcatd, 7, 5, "%s: Could not read archive ver" "sion from archive stream.\n"), (char *)our_process_name ); return FALSE; } if (version != CURRENT_ARCHIVE_VERSION) { fprintf( stderr, catgets(_ttcatd, 7, 6, "%s: Found archive version %d, " "but expected version %d.\n"), (char *)our_process_name, version, CURRENT_ARCHIVE_VERSION ); return FALSE; } break; case SPEC: char *old_spec_id; char *new_spec_id; Tt_status err; old_spec_id = NULL; new_spec_id = NULL; err = TT_OK; if (! spec_dearchive( &old_spec_id, &new_spec_id, &this_path, renamings, (char *)where_to_dearchive, preserve__props, dearchive_this_path, (void *)&paths_to_extract, verbosity, xdrs, &err )) { my_tt_release( mem_mark ); return FALSE; } if (new_spec_id != NULL) { Lstar_string_map_ptr m = new Lstar_string_map; m->old_string_set( old_spec_id ); m->new_string_set( new_spec_id ); m->extra_set( this_path ); spec_map->insert( m ); num_specs++; just_dearchived_spec = TRUE; } break; case ARCHIVE_END: break; case NO_KIND: default: fprintf( stderr, catgets(_ttcatd, 7, 7, "%s: found object of unknown kind " "%d in archive.\n"), (char *)our_process_name, (int)obj_kind ); return FALSE; } if (verbosity && ( (last_path != (const char *)this_path) || (obj_kind == ARCHIVE_END))) { if (last_path_valid) { if (just_dearchived_spec) { num_specs--; } else if (just_dearchived_link) { num_links--; } if (verbosity > 1) { fprintf( stderr, "\n" ); } if ( (num_specs > 0) || (num_links > 0)) { fprintf( stderr, "x %s %d %s\n", (char *)last_path, num_specs, ( num_specs == 1 ? "spec" : "specs" )); } num_specs = 0; num_links = 0; if (just_dearchived_spec) { num_specs = 1; } else if (just_dearchived_link) { num_links = 1; } } last_path = this_path; if (! last_path_valid) { last_path_valid = TRUE; } } } while (obj_kind != ARCHIVE_END); my_tt_release( mem_mark ); return TRUE; } /* pathlist_lstt_dearchive() */ /* * pathlist_lstt_archive_list() - List the LS/TT objects of the given paths. * If no paths are given, list everything in the archive. */ bool_t pathlist_lstt_archive_list( _Tt_string_list_ptr paths_to_list, int verbosity, XDR *xdrs ) { _Tt_string last_path; _Tt_string this_path; int num_specs = 0; int num_links = 0; bool_t last_path_valid = FALSE; Object_kind obj_kind = NO_KIND; Lstar_string_map_table_ptr spec_map; int mem_mark = tt_mark(); spec_map = new Lstar_string_map_table(Lstar_string_map_old_string, SPEC_MAP_SIZE ); do { Lstar_spec spec; if (! xdr_enum( xdrs, (enum_t *)&obj_kind )) { fprintf( stderr, catgets(_ttcatd, 7, 8, "%s: Could not read object kind " "from archive stream.\n"), (char *)our_process_name ); return FALSE; } switch (obj_kind) { case VERSION_NUM: int version; if (! xdr_int( xdrs, &version)) { fprintf( stderr, catgets(_ttcatd, 7, 9, "%s: Could not read archive ver" "sion from archive stream.\n"), (char *)our_process_name ); return FALSE; } if (version != CURRENT_ARCHIVE_VERSION) { fprintf( stderr, catgets(_ttcatd, 7, 10, "%s: Found archive version %d, " "but expected version %d.\n"), (char *)our_process_name, version, CURRENT_ARCHIVE_VERSION ); return FALSE; } break; case SPEC: if (! spec.xdr(xdrs)) { my_tt_release( mem_mark ); return FALSE; } if (dearchive_this_path( (char *)spec.path(), &paths_to_list )) { Lstar_string_map_ptr m = new Lstar_string_map; /* * Insert it into this "map" just so that * we can use the map to figure out if * a given link counts under paths_to_list. */ m->old_string_set( spec.id() ); m->extra_set( spec.path() ); spec_map->insert( m ); this_path = spec.path(); num_specs++; if (verbosity > 1) { spec.print( stdout ); } } else { continue; } break; case ARCHIVE_END: break; case NO_KIND: default: fprintf( stderr, catgets(_ttcatd, 7, 11, "%s: found object of unknown kind " "%d in archive.\n"), (char *)our_process_name, (int)obj_kind ); return FALSE; } if ( (last_path != this_path) || (obj_kind == ARCHIVE_END)) { if (last_path_valid) { if (obj_kind == SPEC) { num_specs--; } else if (obj_kind == SUN_LINK) { num_links--; } printf( "%s %d %s\n", (char *)last_path, num_specs, (num_specs == 1 ? "spec" : "specs" )); num_specs = 0; num_links = 0; if (obj_kind == SPEC) { num_specs = 1; } else if (obj_kind == SUN_LINK) { num_links = 1; } } last_path = this_path; if (! last_path_valid) { last_path_valid = TRUE; } } } while (obj_kind != ARCHIVE_END); my_tt_release( mem_mark ); return TRUE; } /* pathlist_lstt_archive_list() */ /* * path_lstt_archive() - Archive the specs on the given path. */ static bool_t path_lstt_archive( _Tt_string path, int verbosity, XDR *xdrs ) { _Tt_string_list *specs; Object_kind obj_kind; int num_specs_archived = 0; int num_links_archived = 0; bool_t val2return = TRUE; specs = new _Tt_string_list; note_err( tt_file_objects_query( (char *)path, gather_specs, NULL, specs )); if (IS_TT_ERR(err_noted)) { delete specs; return TRUE; } while (! specs->is_empty()) { _Tt_string spec = specs->top(); Tt_status tt_err; obj_kind = SPEC; specs->pop(); if (! xdr_enum( xdrs, (enum_t *)&obj_kind )) { fprintf( stderr, "%s: ! xdr_enum()\n", (char *)our_process_name ); val2return = FALSE; break; } if (! spec_archive( (char *)spec, (char *)path, verbosity, xdrs, &tt_err )) { val2return = FALSE; break; } num_specs_archived++; } if ((verbosity && num_specs_archived > 0 ) || (verbosity > 1)) { if (verbosity > 1) { fprintf( stderr, "\n" ); } fprintf( stderr, "a %s: %d %s\n", (char *)path, num_specs_archived, ((num_specs_archived == 1) ? "spec" : "specs" )); } delete specs; return val2return; } /* path_lstt_archive() */ /* * spec_archive() - Archive a spec onto the given XDR stream. */ bool_t spec_archive( char *id, char *path, int verbosity, XDR *xdrs, Tt_status *err ) { _Tt_string _path( path ); _Tt_string _id( id ); *err = TT_OK; if (xdrs->x_op == XDR_ENCODE) { Lstar_spec spec( _id, _path ); *err = spec.read_self(); if (IS_TT_ERR(*err)) { return FALSE; } if (! spec.xdr(xdrs)) { return FALSE; } if (verbosity > 1) { spec.print( stderr ); } } else { return FALSE; } return TRUE; } /* spec_archive() */ /* * spec_dearchive() - Recreate a spec that was archived on this XDR stream. */ bool_t spec_dearchive( char **old_spec_id_ptr, char **new_spec_id_ptr, char **path_as_archived, Lstar_string_map_list_ptr renamings, char *where_to_create, bool_t preserve__props, bool_t (*dearchive_this_path)(char *, void *), void *context, int verbosity, XDR *xdrs, Tt_status *err ) { _Tt_string where( where_to_create ); *err = TT_OK; *old_spec_id_ptr = NULL; *new_spec_id_ptr = NULL; *path_as_archived = NULL; if (xdrs->x_op == XDR_ENCODE) { return FALSE; } else if (xdrs->x_op == XDR_DECODE) { Lstar_spec spec; _Tt_string path; if (! spec.xdr(xdrs)) { return FALSE; } *old_spec_id_ptr = _tt_strdup( spec.id() ); *path_as_archived = _tt_strdup( spec.path() ); path = spec.path(); if ( (dearchive_this_path == NULL) || (dearchive_this_path( (char *)path, context ))) { _Tt_string _new_name = new_name( spec.path(), renamings ); if (_new_name.len() > 0) { if (verbosity > 2) { fprintf( stderr, "%s => ", (char *)spec.path() ); } spec.path_set( _new_name ); if (verbosity > 2) { fprintf( stderr, "%s\n", (char *)spec.path() ); } } *new_spec_id_ptr = spec.write_self( where, preserve__props, err ); if (! IS_TT_ERR(*err) && (verbosity > 1)) { spec.print( stdout ); } } } return TRUE; } /* spec_dearchive() */ /* * dearchive_this_path() - Should we extract this from its archive? * * Returns true if *ppaths_to_extract is an empty list. */ bool_t dearchive_this_path( char *path, void *ppaths_to_extract ) { _Tt_string_list_ptr paths; _Tt_string _path( path ); if (ppaths_to_extract == NULL) { return TRUE; } paths = *(_Tt_string_list_ptr *)ppaths_to_extract; if (paths->count() <= 0) { return TRUE; } return is_child_in( _path, paths ); } /* dearchive_this_path() */ /* * gather_specs() */ static Tt_filter_action gather_specs( const char *spec_id, void *, void *specs ) { _Tt_string id = spec_id; ((_Tt_string_list *)specs)->push( id ); return TT_FILTER_CONTINUE; }