tar.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 804 行 · 第 1/2 页
C
804 行
/****************************************************************************
*
* Open Watcom Project
*
* Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved.
*
* ========================================================================
*
* This file contains Original Code and/or Modifications of Original
* Code as defined in and that are subject to the Sybase Open Watcom
* Public License version 1.0 (the 'License'). You may not use this file
* except in compliance with the License. BY USING THIS FILE YOU AGREE TO
* ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is
* provided with the Original Code and Modifications, and is also
* available at www.sybase.com/developer/opensource.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM
* ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR
* NON-INFRINGEMENT. Please see the License for the specific language
* governing rights and limitations under the License.
*
* ========================================================================
*
* Description: A public domain tar(1) program.
*
****************************************************************************/
/*
* A public domain tar(1) program.
*
* Written by John Gilmore, ihnp4!hoptoad!gnu, starting 25 Aug 85.
* MS-DOS port 2/87 by Eric Roskos.
* Minix port 3/88 by Eric Roskos.
*
* @(#)tar.c 1.21 10/29/86 Public Domain - gnu
*/
#include <stdio.h>
#include <sys/types.h> /* Needed for typedefs in tar.h */
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#ifdef MSDOS
#include <conio.h>
#include <fcntl.h>
#endif
#ifdef V7
FILE *fopen();
char *fgets();
#endif
/*
* The following causes "tar.h" to produce definitions of all the
* global variables, rather than just "extern" declarations of them.
*/
#define TAR_EXTERN /**/
#include "tar.h"
#include "port.h"
#include "list.h"
#include "create.h"
#include "extract.h"
#include "buffer.h"
#include "getopt.h"
/*
* We should use a conversion routine that does reasonable error
* checking -- atoi doesn't. For now, punt. FIXME.
*/
#define intconv atoi
static FILE *namef; /* File to read names from */
static char **n_argv; /* Argv used by name routines */
static int n_argc; /* Argc used by name routines */
/* They also use "optind" from getopt(). */
#ifdef MSDOS
/*
* see convmode, below. This list is the list of files that should be
* opened with mode O_BINARY to prevent CR/LF conversions while they
* are being read in. FIXME: it is my intent to eventually add an
* option to the command line that lets you add arbitrarily many new
* extensions to this list, so people won't have problems with the
* list being inadequate for them. I wish there was an easier way, but
* this one is fairly consistent if you think about it.
*/
#define NBINEXTS 20
static char *binexts[NBINEXTS] = /* extensions for O_BINARY files */
{
"com",
"exe",
"obj",
0 /* required */
};
#endif
static void name_init( int argc, char **argv );
static void addbinext( char *s );
/*
* Main routine for tar.
*/
int main( int argc, char **argv )
{
/*
* Uncomment this message in particularly buggy versions...
* fprintf(stderr, "tar: You are running an experimental PD tar, maybe
* use /bin/tar.\n");
*/
tar = "tar"; /* Set program name */
#ifdef MSDOS
physdrv = 0; /* set default drive */
devsize = 720; /* default drive size */
ftty = open("CON", O_RDWR); /* open console */
#else /* !MSDOS */
ftty = open("/dev/tty", 2);
#endif /* !MSDOS */
if (ftty < 0) {
fprintf(stderr, "Can't open %s for I/O\n",
#ifdef MSDOS
"console"
#else
"/dev/tty"
#endif
);
exit(EX_SYSTEM);
}
options(argc, argv);
name_init(argc, argv);
#if defined(MSDOS) && !defined(__NO_PHYS__)
if (f_phys) {
uprintf(ftty,"tar: archive on %dK drive %c\n",
devsize/2, 'A' + physdrv);
uprintf(ftty,"tar: insert %s disk in drive '%c' and press [Enter]: ",
f_create? "formatted" : "first",
'A' + physdrv);
while (ugetc(ftty)!='\n') ;
}
#endif
if (f_create) {
if (f_extract || f_list)
goto dupflags;
create_archive();
} else if (f_extract) {
if (f_list)
goto dupflags;
read_and(extract_archive);
} else if (f_list) {
read_and(list_archive);
} else {
dupflags:
fprintf(stderr,
"tar: you must specify exactly one of the c, t, or x options\n");
describe();
exit(EX_ARGSBAD);
}
putchar('\n');
fflush(stdout);
#ifndef MSDOS
sync(); /* insure all floppy buffers are written out */
#endif
return( 0 );
}
/*
* Parse the options for tar.
*/
void options( int argc, char **argv )
{
int c; /* Option letter */
/* Set default option values */
blocking = DEFBLOCKING; /* From Makefile */
ar_file = DEF_AR_FILE; /* From Makefile */
/* Parse options */
while ((c = getoldopt(argc, argv, "b:BcdDf:hikmopsS:tT:u:vV:xzZ")
) != EOF)
{
switch (c)
{
case 'b':
blocking = intconv(optarg);
break;
case 'B':
f_reblock++; /* For reading 4.2BSD pipes */
break;
case 'c':
f_create++;
break;
case 'd':
f_debug++; /* Debugging code */
break; /* Yes, even with dbx */
case 'D':
f_sayblock++; /* Print block #s for debug */
break; /* of bad tar archives */
case 'f':
ar_file = optarg;
break;
case 'h':
f_follow_links++; /* follow symbolic links */
break;
case 'i':
f_ignorez++; /* Ignore zero records (eofs) */
/*
* This can't be the default, because Unix tar writes two records
* of zeros, then pads out the block with garbage.
*/
break;
case 'k': /* Don't overwrite files */
f_keep++;
break;
case 'm':
f_modified++;
break;
case 'o': /* Generate old archive */
f_oldarch++;
break;
case 'p':
f_use_protection++;
(void) umask(0); /* Turn off kernel "help" */
break;
case 's':
f_sorted_names++; /* Names to extr are sorted */
break;
#ifdef MSDOS
case 'S':
devsize = atoi(optarg); /* size of DOS disk drive */
devsize <<= 1; /* convert K to blocks */
break;
#endif
case 't':
f_list++;
break;
case 'T':
name_file = optarg;
f_namefile++;
break;
#ifdef MSDOS
case 'u':
addbinext(optarg);
break;
#endif
case 'v':
f_verbose++;
break;
#if defined(MSDOS) && !defined(__NO_PHYS__)
case 'V':
f_phys++;
physdrv = toupper(*optarg) - 'A';
if (physdrv > 4 || physdrv < 0)
{
fprintf(stderr, "tar: drive letter for -V must be A-D\n");
exit(EX_ARGSBAD);
}
break;
#endif /* MSDOS */
case 'x':
f_extract++;
break;
case 'z': /* Easy to type */
case 'Z': /* Like the filename extension .Z */
#ifndef MSDOS
f_compress++;
#else
fprintf(stderr, "Running compress as a subprocess is not supported under DOS.\n");
fprintf(stderr, "Run compress separately instead, for same effect.\n");
#endif
break;
default:
case '?':
describe();
exit(EX_ARGSBAD);
}
}
blocksize = blocking * RECORDSIZE;
}
/* FIXME, describe tar options here */
void describe( void )
{
fputs("tar: valid options:\n\
-b N blocking factor N (block size = Nx512 bytes)\n\
-B reblock as we read (for reading 4.2BSD pipes)\n\
-c create an archive\n\
-D dump record number within archive with each message\n\
-f F read/write archive from file or device F\n", stderr);
fputs("-h don't dump symbolic links; dump the files they point to\n\
-i ignore blocks of zeros in the archive, which normally mean EOF\n\
-k keep existing files, don't overwrite them from the archive\n\
-m don't extract file modified time\n\
-o write an old V7 format archive, rather than ANSI [draft 6] format\n\
-p do extract all protection information\n", stderr);
#ifdef MSDOS
fputs("-S X device for -V option is X Kbyte drive\n", stderr);
#endif
fputs("-s list of names to extract is sorted to match the archive\n\
-t list a table of contents of an archive\n\
-T F get names to extract or create from file F\n", stderr);
#ifdef MSDOS
fputs("\
-u X add X to list of file extensions to be opened in BINARY mode\n\
(use '.' to denote 'files with no extension')\n\
-V X use drive X (X=A..D) in multivolume mode; ignore -f if present\n",
stderr);
#endif
fputs("\
-v verbosely list what files we process\n\
-x extract files from an archive\n", stderr);
#ifndef MSDOS
/*
* regrettably, DOS doesn't have real pipes, just artificial shell-level
* ones. It is better to just use those.
*/
fputs("\
-z or Z run the archive through compress(1)\n", stderr);
#endif
}
/*
* Set up to gather file names for tar.
*
* They can either come from stdin or from argv.
*/
static void name_init( int argc, char **argv )
{
if (f_namefile) {
if (optind < argc) {
fprintf(stderr, "tar: too many args with -T option\n");
exit(EX_ARGSBAD);
}
if (!strcmp(name_file, "-")) {
namef = stdin;
} else {
namef = fopen(name_file, "r");
if (namef == NULL) {
fprintf(stderr, "tar: ");
perror(name_file);
exit(EX_BADFILE);
}
}
} else {
/* Get file names from argv, after options. */
n_argc = argc;
n_argv = argv;
}
}
/*
* Name translation function for MS-DOS support; can also be
* extended via #ifdef for other os's.
*
* Convert a name to one suitable to this OS. If this can't be done
* automatically, let the user choose a name.
*
* The user prompting is done only if stdin isatty.
*
* It is important to understand the name translation, which occurs
* in two steps. First, the actual name string passed in s is modified
* in place to change case and direction of slashes, because DOS's
* directory routines return uppercase names with backslashes, which
* are not suitable for Unix. This changes the string into a unix-like
* filename. Second, this string is copied into a local buffer and
* transformed, if necessary, into a filename that is syntactically
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?