Some files were trying to access the global includes directy in the build area with things like #include <api/c/tt_c.h>, which is now wrong. Se we fix all of those up. tt_c.h and tttk.h are now global, so we no longer need to root around various build dirs to find them. TT builds again.
571 lines
13 KiB
C
571 lines
13 KiB
C
/*
|
|
* 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: archiver.C /main/3 1995/10/20 16:59:21 rswiston $
|
|
/* @(#)archiver.C 1.17 93/07/30
|
|
* archiver.cc - ToolTalk wrapper for tar(1).
|
|
*
|
|
* Copyright (c) 1990 by Sun Microsystems, Inc.
|
|
*
|
|
*/
|
|
|
|
#include "tt_options.h"
|
|
#include <errno.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <sys/param.h>
|
|
#include <sys/stat.h>
|
|
#include <sys/wait.h>
|
|
#include <string.h>
|
|
#include <unistd.h>
|
|
#include <errno.h>
|
|
#include "Tt/tt_c.h"
|
|
#include "util/copyright.h"
|
|
#include "util/tt_gettext.h"
|
|
#include "tttar_utils.h"
|
|
#include "tttar_file_utils.h"
|
|
#include "tttar_api.h"
|
|
#include "archiver.h"
|
|
|
|
/*
|
|
* External variables
|
|
*/
|
|
|
|
/*
|
|
* archiver::archiver()
|
|
*/
|
|
archiver::
|
|
archiver( char *arg0 )
|
|
{
|
|
if (arg0 != NULL) {
|
|
char *base = strrchr( arg0, '/' );
|
|
if (base == NULL) {
|
|
base = arg0;
|
|
} else {
|
|
base++;
|
|
}
|
|
_prog_name = base;
|
|
_process_name = _prog_name;
|
|
} else {
|
|
_process_name = "(No process name)";
|
|
_prog_name = "(No program name)";
|
|
}
|
|
_mode = NO_MODE;
|
|
_verbosity = 0;
|
|
_follow_symlinks = FALSE;
|
|
_recurse = TRUE;
|
|
_archive_links = TRUE;
|
|
_archive_external_links = TRUE;
|
|
_preserve_modes = FALSE;
|
|
_preserve__props = TRUE;
|
|
_should_tar = TRUE;
|
|
_only_1_look_at_tarfile = FALSE;
|
|
_io_stream = NULL;
|
|
_paths2tar = new _Tt_string_list;
|
|
_renamings = new Lstar_string_map_list;
|
|
}
|
|
|
|
archiver::
|
|
~archiver()
|
|
{
|
|
}
|
|
|
|
/*
|
|
* archiver::do_tar() - Invoke tar(1) using system()
|
|
* If _mode is CREATE, do_tttarfile means "also archive tttarfile".
|
|
* If _mode is EXTRACT, do_tttarfile means "only extract tttarfile".
|
|
*/
|
|
int archiver::
|
|
do_tar( _Tt_string tttardir, bool_t do_tttarfile )
|
|
{
|
|
char _curdir[ MAXPATHLEN+1 ];
|
|
_Tt_string curdir;
|
|
int status2return;
|
|
_Tt_string cmd( "tar " );
|
|
_Tt_string exclude_file;
|
|
|
|
/*
|
|
* Further down, we use the X option to exclude the tttarfile when
|
|
* extracting so we can extract it into a different place.
|
|
* Unfortunately AIX and HPUX don\'t have the X option, so
|
|
* their users will just have to suffer with having the extra
|
|
* tttarfile appear when doing extracting, and we hope we
|
|
* have permission to do so..
|
|
*/
|
|
|
|
#if !defined(OPT_TAR_HAS_EXCLUDE_OPTION)
|
|
_only_1_look_at_tarfile = TRUE;
|
|
#endif
|
|
/*
|
|
* If we're extracting just the tttarfile, chdir() to
|
|
* a place where we can extract it with permission and
|
|
* without collisions.
|
|
*/
|
|
if (do_tttarfile && (_mode == EXTRACT)) {
|
|
#if !defined(OPT_BUG_SUNOS_4)
|
|
curdir = getcwd( _curdir, MAXPATHLEN );
|
|
#else
|
|
curdir = getwd( _curdir );
|
|
#endif
|
|
int status = chdir( (char *)tttardir );
|
|
if (status != 0) {
|
|
return status;
|
|
}
|
|
}
|
|
switch (_mode) {
|
|
case CREATE:
|
|
cmd = cmd.cat( "c" );
|
|
break;
|
|
case EXTRACT:
|
|
cmd = cmd.cat( "x" );
|
|
break;
|
|
case LIST:
|
|
cmd = cmd.cat( "t" );
|
|
break;
|
|
case NO_MODE:
|
|
default:
|
|
return 1;
|
|
}
|
|
for (int n = 0; n < _verbosity; n++) {
|
|
cmd = cmd.cat( "v" );
|
|
}
|
|
if (_follow_symlinks) {
|
|
cmd = cmd.cat( "h" );
|
|
}
|
|
if (_preserve_modes) {
|
|
cmd = cmd.cat( "p" );
|
|
}
|
|
if (_tarfile_arg.len() != 0) {
|
|
cmd = cmd.cat( "f" );
|
|
}
|
|
/*
|
|
* If we're extracting and we don't want the tttarfile, we
|
|
* need to pass the X option to exclude the tttarfile.
|
|
* But if we're extracting from stdin, we only get one chance
|
|
* to read the input, so in that case we can't exclude the
|
|
* tttarfile from being extracted.
|
|
*/
|
|
|
|
if ((_mode == EXTRACT) && (! do_tttarfile) && (!_only_1_look_at_tarfile))
|
|
{
|
|
cmd = cmd.cat( "X" );
|
|
}
|
|
if (_tarfile_arg.len() != 0) {
|
|
cmd = cmd.cat( " " );
|
|
/*
|
|
* If we've chdir()'d to our temp dir to extract the
|
|
* tttarfile, then be sure to prepend the old cwd
|
|
* to the tarfile's name if it's relative.
|
|
*/
|
|
if ( do_tttarfile
|
|
&& (_mode == EXTRACT)
|
|
&& (_tarfile_arg[0] != '/'))
|
|
{
|
|
cmd = cmd.cat( curdir ).cat( "/" );
|
|
}
|
|
cmd = cmd.cat( _tarfile_arg );
|
|
}
|
|
_Tt_string_list_cursor pathc( _paths2tar );
|
|
switch (_mode) {
|
|
case CREATE:
|
|
while (pathc.next()) {
|
|
cmd = cmd.cat( " " ).cat( *pathc );
|
|
}
|
|
/*
|
|
* Have tar dip into our temporary directory and
|
|
* pick up the tttarfile.
|
|
*/
|
|
if (do_tttarfile) {
|
|
cmd = cmd.cat( " -C " ).cat( tttardir ).
|
|
cat( " tttarfile" );
|
|
}
|
|
break;
|
|
case EXTRACT:
|
|
if (do_tttarfile) {
|
|
/*
|
|
* Only extract the tttarfile.
|
|
*/
|
|
cmd = cmd.cat( " tttarfile" );
|
|
} else {
|
|
if (_only_1_look_at_tarfile) {
|
|
/*
|
|
* If we're extracting from stdin, we
|
|
* can only invoke tar(1) once, so
|
|
* hope we have write permission
|
|
* on the current directory, 'cuz that's
|
|
* where we've got to put the tttarfile.
|
|
* Only explicitly ask for the tttarfile
|
|
* if we are being picky in what we extract.
|
|
*/
|
|
if (_paths2tar->count() > 0) {
|
|
cmd = cmd.cat( " tttarfile" );
|
|
}
|
|
} else {
|
|
/*
|
|
* Extract everything _but_ the tttarfile.
|
|
*/
|
|
exclude_file = tttardir.cat( "/tar.exclude" );
|
|
FILE *fp = fopen( (char *)exclude_file, "w" );
|
|
if (fp == NULL) {
|
|
cmd = cmd.cat( " /dev/null" );
|
|
} else {
|
|
fprintf( fp, "tttarfile\n" );
|
|
fclose( fp );
|
|
cmd = cmd.cat( " " ).cat( exclude_file );
|
|
}
|
|
}
|
|
while (pathc.next()) {
|
|
cmd = cmd.cat( " " ).cat( *pathc );
|
|
}
|
|
}
|
|
break;
|
|
case LIST:
|
|
break;
|
|
case NO_MODE:
|
|
default:
|
|
return 1;
|
|
}
|
|
//printf( "Invoking: %s\n", (char *)cmd );
|
|
int sys_status = system( (char *)cmd );
|
|
if (WIFEXITED(sys_status)) {
|
|
status2return = WEXITSTATUS(sys_status);
|
|
} else {
|
|
fprintf( stderr,
|
|
"%s: system(\"%s\"): %d\n",
|
|
(char *)_process_name, (char *)cmd, sys_status );
|
|
status2return = 1;
|
|
}
|
|
if (_mode == EXTRACT) {
|
|
int status;
|
|
if (do_tttarfile) {
|
|
status = chdir( (char *)curdir );
|
|
if (status != 0) {
|
|
fprintf( stderr, "%s: chdir(\"%s\"): %s\n",
|
|
(char *)_process_name,
|
|
(char *)curdir, strerror(errno) );
|
|
exit( status );
|
|
}
|
|
} else if (exclude_file.len() > 0) {
|
|
status = unlink( (char *)exclude_file );
|
|
if (status != 0) {
|
|
perror( (char *)exclude_file );
|
|
}
|
|
}
|
|
}
|
|
return status2return;
|
|
|
|
} /* archiver::do_tar() */
|
|
|
|
/*
|
|
* archiver::do_tttar() - Perform just the LS/TT part of tttar
|
|
*/
|
|
bool_t archiver::
|
|
do_tttar( char *tttarfile_name, bool_t silent )
|
|
{
|
|
char *process_id;
|
|
int first_ttmalloc;
|
|
XDR xdrs;
|
|
bool_t val2return = TRUE;
|
|
char _curdir[ MAXPATHLEN+1 ];
|
|
_Tt_string curdir;
|
|
|
|
_io_stream = this->_open_io_stream( tttarfile_name, silent );
|
|
if (_io_stream == NULL) {
|
|
return FALSE;
|
|
}
|
|
switch (_mode) {
|
|
case CREATE:
|
|
xdrstdio_create( &xdrs, _io_stream, XDR_ENCODE );
|
|
break;
|
|
case LIST:
|
|
case EXTRACT:
|
|
xdrstdio_create( &xdrs, _io_stream, XDR_DECODE );
|
|
break;
|
|
case NO_MODE:
|
|
default:
|
|
fprintf( stderr, "%s: Archive_mode: %d\n",
|
|
(char *)_process_name, (int)_mode );
|
|
return FALSE;
|
|
}
|
|
|
|
/*
|
|
* Tooltalk setup
|
|
*/
|
|
first_ttmalloc = tt_mark();
|
|
note_ptr_err( tt_open() );
|
|
if (IS_TT_ERR(err_noted)) {
|
|
return FALSE;
|
|
}
|
|
process_id = ptr_returned;
|
|
|
|
switch (_mode) {
|
|
case CREATE:
|
|
val2return = pathlist_lstt_archive(
|
|
_paths2tar, _recurse, _follow_symlinks,
|
|
_verbosity, &xdrs );
|
|
break;
|
|
case LIST:
|
|
val2return = pathlist_lstt_archive_list(_paths2tar, _verbosity,
|
|
&xdrs);
|
|
break;
|
|
case EXTRACT:
|
|
#if !defined(OPT_BUG_SUNOS_4)
|
|
curdir = getcwd( _curdir, MAXPATHLEN );
|
|
#else
|
|
curdir = getwd( _curdir );
|
|
#endif
|
|
val2return = pathlist_lstt_dearchive( _paths2tar, _renamings,
|
|
curdir, _preserve__props,
|
|
_verbosity, &xdrs);
|
|
break;
|
|
case NO_MODE:
|
|
default:
|
|
break;
|
|
}
|
|
|
|
/*
|
|
* Tooltalk teardown
|
|
*/
|
|
note_err( tt_close() );
|
|
my_tt_release( first_ttmalloc );
|
|
|
|
xdr_destroy( &xdrs );
|
|
if ((_io_stream != stdin) && (_io_stream != stdout)) {
|
|
fclose( _io_stream );
|
|
}
|
|
return val2return;
|
|
}
|
|
|
|
/*
|
|
* archiver::parse_args()
|
|
*/
|
|
void archiver::
|
|
parse_args( int argc, char **argv )
|
|
{
|
|
bool_t next_arg_is_tarfile = FALSE;
|
|
|
|
for ( int argnum = 1; argnum < argc; argnum++ ) {
|
|
char *cp = argv[argnum];
|
|
_Tt_string arg( cp );
|
|
if (argnum == 1) {
|
|
/*
|
|
* Process mode setting and other flags.
|
|
*/
|
|
while (*cp != '\0') {
|
|
switch (*cp) {
|
|
case 'c':
|
|
case 't':
|
|
case 'x':
|
|
if (_mode == NO_MODE) {
|
|
switch (*cp) {
|
|
case 'c':
|
|
_mode = CREATE;
|
|
break;
|
|
case 't':
|
|
_mode = LIST;
|
|
break;
|
|
case 'x':
|
|
_mode = EXTRACT;
|
|
break;
|
|
}
|
|
} else {
|
|
this->usage();
|
|
exit(1);
|
|
}
|
|
break;
|
|
case '-':
|
|
cp++;
|
|
switch (*cp) {
|
|
case 'v':
|
|
_TT_PRINT_VERSIONS
|
|
((char *)_prog_name)
|
|
exit(0);
|
|
break;
|
|
case 'h':
|
|
this->usage();
|
|
exit(0);
|
|
break;
|
|
default:
|
|
this->usage();
|
|
exit(1);
|
|
break;
|
|
}
|
|
break;
|
|
case 'f':
|
|
next_arg_is_tarfile = TRUE;
|
|
break;
|
|
case 'R':
|
|
_recurse = FALSE;
|
|
break;
|
|
case 'h':
|
|
_follow_symlinks = TRUE;
|
|
break;
|
|
case 'p':
|
|
_preserve_modes = TRUE;
|
|
break;
|
|
case 'P':
|
|
_preserve__props = FALSE;
|
|
break;
|
|
case 'S':
|
|
_archive_links = FALSE;
|
|
break;
|
|
case 'E':
|
|
_archive_external_links = FALSE;
|
|
break;
|
|
case 'L':
|
|
_should_tar = FALSE;
|
|
break;
|
|
case 'v':
|
|
_verbosity++;
|
|
break;
|
|
default:
|
|
this->usage();
|
|
exit(1);
|
|
}
|
|
cp++;
|
|
}
|
|
} else if (next_arg_is_tarfile) {
|
|
_tarfile_arg = cp;
|
|
next_arg_is_tarfile = FALSE;
|
|
} else if (arg == "-rename") {
|
|
Lstar_string_map_ptr m = new Lstar_string_map;
|
|
|
|
if (++argnum >= argc) {
|
|
this->usage();
|
|
exit(1);
|
|
} else {
|
|
m->old_string_set( argv[argnum] );
|
|
if (++argnum >= argc) {
|
|
this->usage();
|
|
exit(1);
|
|
} else {
|
|
m->new_string_set( argv[argnum] );
|
|
_renamings->append( m );
|
|
}
|
|
}
|
|
} else {
|
|
/*
|
|
* Add this pathname to the list.
|
|
*/
|
|
_Tt_string path = cp;
|
|
_paths2tar->append( path );
|
|
}
|
|
}
|
|
if ( ((_tarfile_arg.len() == 0) && (! _should_tar))
|
|
|| (_mode == NO_MODE)
|
|
|| (_should_tar && (! _recurse)))
|
|
{
|
|
this->usage();
|
|
exit(1);
|
|
}
|
|
_only_1_look_at_tarfile =
|
|
(_tarfile_arg.len() == 0) || (_tarfile_arg == "-");
|
|
/*
|
|
* Renaming as you dearchive is not a tar(1) option.
|
|
*/
|
|
if ( (_renamings->count() > 0)
|
|
&& (_should_tar || (_mode != EXTRACT)))
|
|
{
|
|
this->usage();
|
|
exit(1);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* archiver::_open_io_stream() - Returns an file pointer opened according
|
|
* to _mode. Uses stdin/stdout if filename is NULL or "-".
|
|
* Exits with an error message if the _mode is not set,
|
|
* or if the named file cannot be opened.
|
|
*/
|
|
FILE * archiver::
|
|
_open_io_stream(char *filename, bool_t silent)
|
|
{
|
|
bool_t in_pipe;
|
|
FILE *fp = NULL;
|
|
|
|
in_pipe = ( (filename == NULL)
|
|
|| (strcmp( filename, "-" ) == 0));
|
|
switch (_mode) {
|
|
case CREATE:
|
|
if (in_pipe) {
|
|
return stdout;
|
|
} else {
|
|
fp = fopen( filename, "w" );
|
|
}
|
|
break;
|
|
case EXTRACT:
|
|
case LIST:
|
|
if (in_pipe) {
|
|
return stdin;
|
|
} else {
|
|
fp = fopen( filename, "r" );
|
|
}
|
|
break;
|
|
case NO_MODE:
|
|
default:
|
|
fprintf( stderr, "%s: Archive_mode: %d\n",
|
|
(char *)_process_name, (int)_mode );
|
|
}
|
|
if ((fp == NULL) && (! silent)) {
|
|
fprintf( stderr, "%s: %s: %s\n",
|
|
(char *)_process_name, filename, strerror(errno) );
|
|
}
|
|
return fp;
|
|
|
|
} /* archiver::_open_io_stream() */
|
|
|
|
/*
|
|
* archiver::usage()
|
|
*/
|
|
void archiver::
|
|
usage( FILE *fs ) const
|
|
{
|
|
fprintf( fs,
|
|
catgets(_ttcatd, 7, 2,
|
|
"Usage: %s {ctx}[fhpPv[v]] [tarfile] pathname ...\n"
|
|
" %s {ctx}fL[hpPRv[v]] tttarfile pathname ...\n"
|
|
" %s -v\n"
|
|
" %s -h\n"),
|
|
(char *)_prog_name, (char *)_prog_name, (char *)_prog_name,
|
|
(char *)_prog_name );
|
|
fprintf( fs, "%s",
|
|
catgets(_ttcatd, 7, 3,
|
|
"\tc create an archive\n"
|
|
"\tt list an archive's contents\n"
|
|
"\tx extract from an archive\n"
|
|
"\tf use next arg <tarfile> as archive\n"
|
|
"\th follow symbolic links\n"
|
|
"\tL do not invoke tar(1)\n"
|
|
"\tp preserve file modes\n"
|
|
"\tP (root) do not preserve objects' "
|
|
"owner, mod time, etc.\n"
|
|
"\tR do not recurse into directories\n"
|
|
"\tv be verbose\n"
|
|
"\tvv be very verbose\n"
|
|
"\t-v print the version number and quit\n"
|
|
"\t-h[elp] print this message\n"));
|
|
}
|