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 librararies 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: archiver.C /main/3 1995/10/20 16:59:21 rswiston $
28 /* @(#)archiver.C 1.17 93/07/30
29 * archiver.cc - ToolTalk wrapper for tar(1).
31 * Copyright (c) 1990 by Sun Microsystems, Inc.
35 #include "tt_options.h"
39 #include <sys/param.h>
45 #include "api/c/tt_c.h"
46 #include "util/copyright.h"
47 #include "util/tt_gettext.h"
48 #include "tttar_utils.h"
49 #include "tttar_file_utils.h"
50 #include "tttar_api.h"
58 * archiver::archiver()
61 archiver( char *arg0 )
64 char *base = strrchr( arg0, '/' );
71 _process_name = _prog_name;
73 _process_name = "(No process name)";
74 _prog_name = "(No program name)";
78 _follow_symlinks = FALSE;
80 _archive_links = TRUE;
81 _archive_external_links = TRUE;
82 _preserve_modes = FALSE;
83 _preserve__props = TRUE;
85 _only_1_look_at_tarfile = FALSE;
87 _paths2tar = new _Tt_string_list;
88 _renamings = new Lstar_string_map_list;
97 * archiver::do_tar() - Invoke tar(1) using system()
98 * If _mode is CREATE, do_tttarfile means "also archive tttarfile".
99 * If _mode is EXTRACT, do_tttarfile means "only extract tttarfile".
102 do_tar( _Tt_string tttardir, bool_t do_tttarfile )
104 char _curdir[ MAXPATHLEN+1 ];
107 _Tt_string cmd( "tar " );
108 _Tt_string exclude_file;
111 * Further down, we use the X option to exclude the tttarfile when
112 * extracting so we can extract it into a different place.
113 * Unfortunately AIX and HPUX don\'t have the X option, so
114 * their users will just have to suffer with having the extra
115 * tttarfile appear when doing extracting, and we hope we
116 * have permission to do so..
119 #if !defined(OPT_TAR_HAS_EXCLUDE_OPTION)
120 _only_1_look_at_tarfile = TRUE;
123 * If we're extracting just the tttarfile, chdir() to
124 * a place where we can extract it with permission and
125 * without collisions.
127 if (do_tttarfile && (_mode == EXTRACT)) {
128 #if !defined(OPT_BUG_SUNOS_4)
129 curdir = getcwd( _curdir, MAXPATHLEN );
131 curdir = getwd( _curdir );
133 int status = chdir( (char *)tttardir );
140 cmd = cmd.cat( "c" );
143 cmd = cmd.cat( "x" );
146 cmd = cmd.cat( "t" );
152 for (int n = 0; n < _verbosity; n++) {
153 cmd = cmd.cat( "v" );
155 if (_follow_symlinks) {
156 cmd = cmd.cat( "h" );
158 if (_preserve_modes) {
159 cmd = cmd.cat( "p" );
161 if (_tarfile_arg.len() != 0) {
162 cmd = cmd.cat( "f" );
165 * If we're extracting and we don't want the tttarfile, we
166 * need to pass the X option to exclude the tttarfile.
167 * But if we're extracting from stdin, we only get one chance
168 * to read the input, so in that case we can't exclude the
169 * tttarfile from being extracted.
172 if ((_mode == EXTRACT) && (! do_tttarfile) && (!_only_1_look_at_tarfile))
174 cmd = cmd.cat( "X" );
176 if (_tarfile_arg.len() != 0) {
177 cmd = cmd.cat( " " );
179 * If we've chdir()'d to our temp dir to extract the
180 * tttarfile, then be sure to prepend the old cwd
181 * to the tarfile's name if it's relative.
184 && (_mode == EXTRACT)
185 && (_tarfile_arg[0] != '/'))
187 cmd = cmd.cat( curdir ).cat( "/" );
189 cmd = cmd.cat( _tarfile_arg );
191 _Tt_string_list_cursor pathc( _paths2tar );
194 while (pathc.next()) {
195 cmd = cmd.cat( " " ).cat( *pathc );
198 * Have tar dip into our temporary directory and
199 * pick up the tttarfile.
202 cmd = cmd.cat( " -C " ).cat( tttardir ).
209 * Only extract the tttarfile.
211 cmd = cmd.cat( " tttarfile" );
213 if (_only_1_look_at_tarfile) {
215 * If we're extracting from stdin, we
216 * can only invoke tar(1) once, so
217 * hope we have write permission
218 * on the current directory, 'cuz that's
219 * where we've got to put the tttarfile.
220 * Only explicitly ask for the tttarfile
221 * if we are being picky in what we extract.
223 if (_paths2tar->count() > 0) {
224 cmd = cmd.cat( " tttarfile" );
228 * Extract everything _but_ the tttarfile.
230 exclude_file = tttardir.cat( "/tar.exclude" );
231 FILE *fp = fopen( (char *)exclude_file, "w" );
233 cmd = cmd.cat( " /dev/null" );
235 fprintf( fp, "tttarfile\n" );
237 cmd = cmd.cat( " " ).cat( exclude_file );
240 while (pathc.next()) {
241 cmd = cmd.cat( " " ).cat( *pathc );
251 //printf( "Invoking: %s\n", (char *)cmd );
252 int sys_status = system( (char *)cmd );
253 if (WIFEXITED(sys_status)) {
254 status2return = WEXITSTATUS(sys_status);
257 "%s: system(\"%s\"): %d\n",
258 (char *)_process_name, (char *)cmd, sys_status );
261 if (_mode == EXTRACT) {
264 status = chdir( (char *)curdir );
266 fprintf( stderr, "%s: chdir(\"%s\"): %s\n",
267 (char *)_process_name,
268 (char *)curdir, strerror(errno) );
271 } else if (exclude_file.len() > 0) {
272 status = unlink( (char *)exclude_file );
274 perror( (char *)exclude_file );
278 return status2return;
280 } /* archiver::do_tar() */
283 * archiver::do_tttar() - Perform just the LS/TT part of tttar
286 do_tttar( char *tttarfile_name, bool_t silent )
291 bool_t val2return = TRUE;
292 char _curdir[ MAXPATHLEN+1 ];
295 _io_stream = this->_open_io_stream( tttarfile_name, silent );
296 if (_io_stream == NULL) {
301 xdrstdio_create( &xdrs, _io_stream, XDR_ENCODE );
305 xdrstdio_create( &xdrs, _io_stream, XDR_DECODE );
309 fprintf( stderr, "%s: Archive_mode: %d\n",
310 (char *)_process_name, (int)_mode );
317 first_ttmalloc = tt_mark();
318 note_ptr_err( tt_open() );
319 if (IS_TT_ERR(err_noted)) {
322 process_id = ptr_returned;
326 val2return = pathlist_lstt_archive(
327 _paths2tar, _recurse, _follow_symlinks,
331 val2return = pathlist_lstt_archive_list(_paths2tar, _verbosity,
335 #if !defined(OPT_BUG_SUNOS_4)
336 curdir = getcwd( _curdir, MAXPATHLEN );
338 curdir = getwd( _curdir );
340 val2return = pathlist_lstt_dearchive( _paths2tar, _renamings,
341 curdir, _preserve__props,
352 note_err( tt_close() );
353 my_tt_release( first_ttmalloc );
355 xdr_destroy( &xdrs );
356 if ((_io_stream != stdin) && (_io_stream != stdout)) {
357 fclose( _io_stream );
363 * archiver::parse_args()
366 parse_args( int argc, char **argv )
368 bool_t next_arg_is_tarfile = FALSE;
370 for ( int argnum = 1; argnum < argc; argnum++ ) {
371 char *cp = argv[argnum];
372 _Tt_string arg( cp );
375 * Process mode setting and other flags.
377 while (*cp != '\0') {
382 if (_mode == NO_MODE) {
418 next_arg_is_tarfile = TRUE;
424 _follow_symlinks = TRUE;
427 _preserve_modes = TRUE;
430 _preserve__props = FALSE;
433 _archive_links = FALSE;
436 _archive_external_links = FALSE;
450 } else if (next_arg_is_tarfile) {
452 next_arg_is_tarfile = FALSE;
453 } else if (arg == "-rename") {
454 Lstar_string_map_ptr m = new Lstar_string_map;
456 if (++argnum >= argc) {
460 m->old_string_set( argv[argnum] );
461 if (++argnum >= argc) {
465 m->new_string_set( argv[argnum] );
466 _renamings->append( m );
471 * Add this pathname to the list.
473 _Tt_string path = cp;
474 _paths2tar->append( path );
477 if ( ((_tarfile_arg.len() == 0) && (! _should_tar))
478 || (_mode == NO_MODE)
479 || (_should_tar && (! _recurse)))
484 _only_1_look_at_tarfile =
485 (_tarfile_arg.len() == 0) || (_tarfile_arg == "-");
487 * Renaming as you dearchive is not a tar(1) option.
489 if ( (_renamings->count() > 0)
490 && (_should_tar || (_mode != EXTRACT)))
498 * archiver::_open_io_stream() - Returns an file pointer opened according
499 * to _mode. Uses stdin/stdout if filename is NULL or "-".
500 * Exits with an error message if the _mode is not set,
501 * or if the named file cannot be opened.
504 _open_io_stream(char *filename, bool_t silent)
509 in_pipe = ( (filename == NULL)
510 || (strcmp( filename, "-" ) == 0));
516 fp = fopen( filename, "w" );
524 fp = fopen( filename, "r" );
529 fprintf( stderr, "%s: Archive_mode: %d\n",
530 (char *)_process_name, (int)_mode );
532 if ((fp == NULL) && (! silent)) {
533 fprintf( stderr, "%s: %s: %s\n",
534 (char *)_process_name, filename, strerror(errno) );
538 } /* archiver::_open_io_stream() */
544 usage( FILE *fs ) const
547 catgets(_ttcatd, 7, 2,
548 "Usage: %s {ctx}[fhpPv[v]] [tarfile] pathname ...\n"
549 " %s {ctx}fL[hpPRv[v]] tttarfile pathname ...\n"
552 (char *)_prog_name, (char *)_prog_name, (char *)_prog_name,
553 (char *)_prog_name );
555 catgets(_ttcatd, 7, 3,
556 "\tc create an archive\n"
557 "\tt list an archive's contents\n"
558 "\tx extract from an archive\n"
559 "\tf use next arg <tarfile> as archive\n"
560 "\th follow symbolic links\n"
561 "\tL do not invoke tar(1)\n"
562 "\tp preserve file modes\n"
563 "\tP (root) do not preserve objects' "
564 "owner, mod time, etc.\n"
565 "\tR do not recurse into directories\n"
567 "\tvv be very verbose\n"
568 "\t-v print the version number and quit\n"
569 "\t-h[elp] print this message\n"));