Remove files that were removed in CVS, but reappeared after migration to Git

This commit is contained in:
Sergey Poznyakoff
2009-06-18 14:24:50 +03:00
parent b216fed634
commit c30c4ffb9f
17 changed files with 0 additions and 5265 deletions

View File

@@ -1,445 +0,0 @@
/* modechange.c -- file mode manipulation
Copyright (C) 1989, 1990, 1997, 1998, 1999 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software Foundation,
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
/* Written by David MacKenzie <djm@ai.mit.edu> */
/* The ASCII mode string is compiled into a linked list of `struct
modechange', which can then be applied to each file to be changed.
We do this instead of re-parsing the ASCII string for each file
because the compiled form requires less computation to use; when
changing the mode of many files, this probably results in a
performance gain. */
#if HAVE_CONFIG_H
# include <config.h>
#endif
#include "modechange.h"
#include <sys/stat.h>
#include "xstrtol.h"
#if STDC_HEADERS
# include <stdlib.h>
#else
char *malloc ();
#endif
#ifndef NULL
# define NULL 0
#endif
#if STAT_MACROS_BROKEN
# undef S_ISDIR
#endif
#if !defined(S_ISDIR) && defined(S_IFDIR)
# define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
#endif
#ifndef S_ISUID
# define S_ISUID 04000
#endif
#ifndef S_ISGID
# define S_ISGID 04000
#endif
#ifndef S_ISVTX
# define S_ISVTX 01000
#endif
#ifndef S_IRUSR
# define S_IRUSR 0400
#endif
#ifndef S_IWUSR
# define S_IWUSR 0200
#endif
#ifndef S_IXUSR
# define S_IXUSR 0100
#endif
#ifndef S_IRGRP
# define S_IRGRP 0040
#endif
#ifndef S_IWGRP
# define S_IWGRP 0020
#endif
#ifndef S_IXGRP
# define S_IXGRP 0010
#endif
#ifndef S_IROTH
# define S_IROTH 0004
#endif
#ifndef S_IWOTH
# define S_IWOTH 0002
#endif
#ifndef S_IXOTH
# define S_IXOTH 0001
#endif
#ifndef S_IRWXU
# define S_IRWXU 0700
#endif
#ifndef S_IRWXG
# define S_IRWXG 0070
#endif
#ifndef S_IRWXO
# define S_IRWXO 0007
#endif
/* All the mode bits that can be affected by chmod. */
#define CHMOD_MODE_BITS \
(S_ISUID | S_ISGID | S_ISVTX | S_IRWXU | S_IRWXG | S_IRWXO)
/* Return newly allocated memory to hold one element of type TYPE. */
#define talloc(type) ((type *) malloc (sizeof (type)))
/* Create a mode_change entry with the specified `=ddd'-style
mode change operation, where NEW_MODE is `ddd'. Return the
new entry, or NULL upon failure. */
static struct mode_change *
make_node_op_equals (mode_t new_mode)
{
struct mode_change *p;
p = talloc (struct mode_change);
if (p == NULL)
return p;
p->next = NULL;
p->op = '=';
p->flags = 0;
p->value = new_mode;
p->affected = CHMOD_MODE_BITS; /* Affect all permissions. */
return p;
}
/* Append entry E to the end of the link list with the specified
HEAD and TAIL. */
static void
mode_append_entry (struct mode_change **head,
struct mode_change **tail,
struct mode_change *e)
{
if (*head == NULL)
*head = *tail = e;
else
{
(*tail)->next = e;
*tail = e;
}
}
/* Return a linked list of file mode change operations created from
MODE_STRING, an ASCII string that contains either an octal number
specifying an absolute mode, or symbolic mode change operations with
the form:
[ugoa...][[+-=][rwxXstugo...]...][,...]
MASKED_OPS is a bitmask indicating which symbolic mode operators (=+-)
should not affect bits set in the umask when no users are given.
Operators not selected in MASKED_OPS ignore the umask.
Return MODE_INVALID if `mode_string' does not contain a valid
representation of file mode change operations;
return MODE_MEMORY_EXHAUSTED if there is insufficient memory. */
struct mode_change *
mode_compile (const char *mode_string, unsigned int masked_ops)
{
struct mode_change *head; /* First element of the linked list. */
struct mode_change *tail; /* An element of the linked list. */
uintmax_t mode_value; /* The mode value, if octal. */
char *string_end; /* Pointer to end of parsed value. */
mode_t umask_value; /* The umask value (surprise). */
head = NULL;
#ifdef lint
tail = NULL;
#endif
if (xstrtoumax (mode_string, &string_end, 8, &mode_value, "") == LONGINT_OK)
{
struct mode_change *p;
if (mode_value != (mode_value & CHMOD_MODE_BITS))
return MODE_INVALID;
p = make_node_op_equals ((mode_t) mode_value);
if (p == NULL)
return MODE_MEMORY_EXHAUSTED;
mode_append_entry (&head, &tail, p);
return head;
}
umask_value = umask (0);
umask (umask_value); /* Restore the old value. */
--mode_string;
/* One loop iteration for each "ugoa...=+-rwxXstugo...[=+-rwxXstugo...]". */
do
{
/* Which bits in the mode are operated on. */
mode_t affected_bits = 0;
/* `affected_bits' modified by umask. */
mode_t affected_masked;
/* Operators to actually use umask on. */
unsigned ops_to_mask = 0;
int who_specified_p;
affected_bits = 0;
ops_to_mask = 0;
/* Turn on all the bits in `affected_bits' for each group given. */
for (++mode_string;; ++mode_string)
switch (*mode_string)
{
case 'u':
affected_bits |= S_ISUID | S_IRWXU;
break;
case 'g':
affected_bits |= S_ISGID | S_IRWXG;
break;
case 'o':
affected_bits |= S_ISVTX | S_IRWXO;
break;
case 'a':
affected_bits |= CHMOD_MODE_BITS;
break;
default:
goto no_more_affected;
}
no_more_affected:
/* If none specified, affect all bits, except perhaps those
set in the umask. */
if (affected_bits)
who_specified_p = 1;
else
{
who_specified_p = 0;
affected_bits = CHMOD_MODE_BITS;
ops_to_mask = masked_ops;
}
while (*mode_string == '=' || *mode_string == '+' || *mode_string == '-')
{
struct mode_change *change = talloc (struct mode_change);
if (change == NULL)
{
mode_free (head);
return MODE_MEMORY_EXHAUSTED;
}
change->next = NULL;
change->op = *mode_string; /* One of "=+-". */
affected_masked = affected_bits;
/* Per the Single Unix Spec, if `who' is not specified and the
`=' operator is used, then clear all the bits first. */
if (!who_specified_p &&
ops_to_mask & (*mode_string == '=' ? MODE_MASK_EQUALS : 0))
{
struct mode_change *p = make_node_op_equals (0);
if (p == NULL)
return MODE_MEMORY_EXHAUSTED;
mode_append_entry (&head, &tail, p);
}
if (ops_to_mask & (*mode_string == '=' ? MODE_MASK_EQUALS
: *mode_string == '+' ? MODE_MASK_PLUS
: MODE_MASK_MINUS))
affected_masked &= ~umask_value;
change->affected = affected_masked;
change->value = 0;
change->flags = 0;
/* Add the element to the tail of the list, so the operations
are performed in the correct order. */
mode_append_entry (&head, &tail, change);
/* Set `value' according to the bits set in `affected_masked'. */
for (++mode_string;; ++mode_string)
switch (*mode_string)
{
case 'r':
change->value |= ((S_IRUSR | S_IRGRP | S_IROTH)
& affected_masked);
break;
case 'w':
change->value |= ((S_IWUSR | S_IWGRP | S_IWOTH)
& affected_masked);
break;
case 'X':
change->flags |= MODE_X_IF_ANY_X;
/* Fall through. */
case 'x':
change->value |= ((S_IXUSR | S_IXGRP | S_IXOTH)
& affected_masked);
break;
case 's':
/* Set the setuid/gid bits if `u' or `g' is selected. */
change->value |= (S_ISUID | S_ISGID) & affected_masked;
break;
case 't':
/* Set the "save text image" bit if `o' is selected. */
change->value |= S_ISVTX & affected_masked;
break;
case 'u':
/* Set the affected bits to the value of the `u' bits
on the same file. */
if (change->value)
goto invalid;
change->value = S_IRWXU;
change->flags |= MODE_COPY_EXISTING;
break;
case 'g':
/* Set the affected bits to the value of the `g' bits
on the same file. */
if (change->value)
goto invalid;
change->value = S_IRWXG;
change->flags |= MODE_COPY_EXISTING;
break;
case 'o':
/* Set the affected bits to the value of the `o' bits
on the same file. */
if (change->value)
goto invalid;
change->value = S_IRWXO;
change->flags |= MODE_COPY_EXISTING;
break;
default:
goto no_more_values;
}
no_more_values:;
}
} while (*mode_string == ',');
if (*mode_string == 0)
return head;
invalid:
mode_free (head);
return MODE_INVALID;
}
/* Return a file mode change operation that sets permissions to match those
of REF_FILE. Return MODE_BAD_REFERENCE if REF_FILE can't be accessed. */
struct mode_change *
mode_create_from_ref (const char *ref_file)
{
struct mode_change *change; /* the only change element */
struct stat ref_stats;
if (stat (ref_file, &ref_stats))
return MODE_BAD_REFERENCE;
change = talloc (struct mode_change);
if (change == NULL)
return MODE_MEMORY_EXHAUSTED;
change->op = '=';
change->flags = 0;
change->affected = CHMOD_MODE_BITS;
change->value = ref_stats.st_mode;
change->next = NULL;
return change;
}
/* Return file mode OLDMODE, adjusted as indicated by the list of change
operations CHANGES. If OLDMODE is a directory, the type `X'
change affects it even if no execute bits were set in OLDMODE.
The returned value has the S_IFMT bits cleared. */
mode_t
mode_adjust (mode_t oldmode, const struct mode_change *changes)
{
mode_t newmode; /* The adjusted mode and one operand. */
mode_t value; /* The other operand. */
newmode = oldmode & CHMOD_MODE_BITS;
for (; changes; changes = changes->next)
{
if (changes->flags & MODE_COPY_EXISTING)
{
/* Isolate in `value' the bits in `newmode' to copy, given in
the mask `changes->value'. */
value = newmode & changes->value;
if (changes->value & S_IRWXU)
/* Copy `u' permissions onto `g' and `o'. */
value |= ((value & S_IRUSR ? S_IRGRP | S_IROTH : 0)
| (value & S_IWUSR ? S_IWGRP | S_IROTH : 0)
| (value & S_IXUSR ? S_IXGRP | S_IXOTH : 0));
else if (changes->value & S_IRWXG)
/* Copy `g' permissions onto `u' and `o'. */
value |= ((value & S_IRGRP ? S_IRUSR | S_IROTH : 0)
| (value & S_IWGRP ? S_IWUSR | S_IROTH : 0)
| (value & S_IXGRP ? S_IXUSR | S_IXOTH : 0));
else
/* Copy `o' permissions onto `u' and `g'. */
value |= ((value & S_IROTH ? S_IRUSR | S_IRGRP : 0)
| (value & S_IWOTH ? S_IWUSR | S_IRGRP : 0)
| (value & S_IXOTH ? S_IXUSR | S_IXGRP : 0));
/* In order to change only `u', `g', or `o' permissions,
or some combination thereof, clear unselected bits.
This can not be done in mode_compile because the value
to which the `changes->affected' mask is applied depends
on the old mode of each file. */
value &= changes->affected;
}
else
{
value = changes->value;
/* If `X', do not affect the execute bits if the file is not a
directory and no execute bits are already set. */
if ((changes->flags & MODE_X_IF_ANY_X)
&& !S_ISDIR (oldmode)
&& (newmode & (S_IXUSR | S_IXGRP | S_IXOTH)) == 0)
/* Clear the execute bits. */
value &= ~ (S_IXUSR | S_IXGRP | S_IXOTH);
}
switch (changes->op)
{
case '=':
/* Preserve the previous values in `newmode' of bits that are
not affected by this change operation. */
newmode = (newmode & ~changes->affected) | value;
break;
case '+':
newmode |= value;
break;
case '-':
newmode &= ~value;
break;
}
}
return newmode;
}
/* Free the memory used by the list of file mode change operations
CHANGES. */
void
mode_free (register struct mode_change *changes)
{
register struct mode_change *next;
while (changes)
{
next = changes->next;
free (changes);
changes = next;
}
}

View File

@@ -1,42 +0,0 @@
.\" $Id: ansi2knr.1 $
.TH ANSI2KNR 1 "9 September 1998" \" -*- nroff -*-
.SH NAME
ansi2knr \- convert ANSI C to Kernighan & Ritchie C
.SH SYNOPSIS
\fBansi2knr\fR [\fB--filename\fR \fIfilename\fR] [\fIinput_file\fR [\fIoutput_file\fR]]
.br
.SH DESCRIPTION
\fB--filename\fR provides the file name for the #line directive in the output,
overriding \fIinput_file\fR (if present).
.sp
If no \fIinput_file\fR is supplied, input is read from stdin.
.sp
If no \fIoutput_file\fR is supplied, output goes to stdout.
.sp
There are no error messages.
.sp
\fBansi2knr\fR
recognizes function definitions by seeing a non-keyword identifier at the left
margin, followed by a left parenthesis, with a right parenthesis as the last
character on the line, and with a left brace as the first token on the
following line (ignoring possible intervening comments). It will recognize a
multi-line header provided that no intervening line ends with a left or right
brace or a semicolon. These algorithms ignore whitespace and comments, except
that the function name must be the first thing on the line.
.sp
The following constructs will confuse it:
.br
- Any other construct that starts at the left margin and follows the
above syntax (such as a macro or function call).
.br
- Some macros that tinker with the syntax of the function header.
.sp
The --varargs switch is obsolete, and is recognized only for
backwards compatibility. The present version of
\fBansi2knr\fR
will always attempt to convert a ... argument to va_alist and va_dcl.
.SH AUTHOR
L. Peter Deutsch <ghost@aladdin.com> wrote the original ansi2knr and
continues to maintain the current version; most of the code in the current
version is his work. ansi2knr also includes contributions by Francois
Pinard <pinard@iro.umontreal.ca> and Jim Avera <jima@netcom.com>.

View File

@@ -1,720 +0,0 @@
/* Copyright (C) 1989, 1997, 1998, 1999 Aladdin Enterprises. All rights reserved. */
/*$Id: ansi2knr.c $*/
/* Convert ANSI C function definitions to K&R ("traditional C") syntax */
/*
ansi2knr is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY. No author or distributor accepts responsibility to anyone for the
consequences of using it or for whether it serves any particular purpose or
works at all, unless he says so in writing. Refer to the GNU General Public
License (the "GPL") for full details.
Everyone is granted permission to copy, modify and redistribute ansi2knr,
but only under the conditions described in the GPL. A copy of this license
is supposed to have been given to you along with ansi2knr so you can know
your rights and responsibilities. It should be in a file named COPYLEFT,
or, if there is no file named COPYLEFT, a file named COPYING. Among other
things, the copyright notice and this notice must be preserved on all
copies.
We explicitly state here what we believe is already implied by the GPL: if
the ansi2knr program is distributed as a separate set of sources and a
separate executable file which are aggregated on a storage medium together
with another program, this in itself does not bring the other program under
the GPL, nor does the mere fact that such a program or the procedures for
constructing it invoke the ansi2knr executable bring any other part of the
program under the GPL.
*/
/*
* Usage:
ansi2knr [--filename FILENAME] [INPUT_FILE [OUTPUT_FILE]]
* --filename provides the file name for the #line directive in the output,
* overriding input_file (if present).
* If no input_file is supplied, input is read from stdin.
* If no output_file is supplied, output goes to stdout.
* There are no error messages.
*
* ansi2knr recognizes function definitions by seeing a non-keyword
* identifier at the left margin, followed by a left parenthesis, with a
* right parenthesis as the last character on the line, and with a left
* brace as the first token on the following line (ignoring possible
* intervening comments and/or preprocessor directives), except that a line
* consisting of only
* identifier1(identifier2)
* will not be considered a function definition unless identifier2 is
* the word "void", and a line consisting of
* identifier1(identifier2, <<arbitrary>>)
* will not be considered a function definition.
* ansi2knr will recognize a multi-line header provided that no intervening
* line ends with a left or right brace or a semicolon. These algorithms
* ignore whitespace, comments, and preprocessor directives, except that
* the function name must be the first thing on the line. The following
* constructs will confuse it:
* - Any other construct that starts at the left margin and
* follows the above syntax (such as a macro or function call).
* - Some macros that tinker with the syntax of function headers.
*/
/*
* The original and principal author of ansi2knr is L. Peter Deutsch
* <ghost@aladdin.com>. Other authors are noted in the change history
* that follows (in reverse chronological order):
lpd 1999-08-17 added code to allow preprocessor directives
wherever comments are allowed
lpd 1999-04-12 added minor fixes from Pavel Roskin
<pavel_roskin@geocities.com> for clean compilation with
gcc -W -Wall
lpd 1999-03-22 added hack to recognize lines consisting of
identifier1(identifier2, xxx) as *not* being procedures
lpd 1999-02-03 made indentation of preprocessor commands consistent
lpd 1999-01-28 fixed two bugs: a '/' in an argument list caused an
endless loop; quoted strings within an argument list
confused the parser
lpd 1999-01-24 added a check for write errors on the output,
suggested by Jim Meyering <meyering@ascend.com>
lpd 1998-11-09 added further hack to recognize identifier(void)
as being a procedure
lpd 1998-10-23 added hack to recognize lines consisting of
identifier1(identifier2) as *not* being procedures
lpd 1997-12-08 made input_file optional; only closes input and/or
output file if not stdin or stdout respectively; prints
usage message on stderr rather than stdout; adds
--filename switch (changes suggested by
<ceder@lysator.liu.se>)
lpd 1996-01-21 added code to cope with not HAVE_CONFIG_H and with
compilers that don't understand void, as suggested by
Tom Lane
lpd 1996-01-15 changed to require that the first non-comment token
on the line following a function header be a left brace,
to reduce sensitivity to macros, as suggested by Tom Lane
<tgl@sss.pgh.pa.us>
lpd 1995-06-22 removed #ifndefs whose sole purpose was to define
undefined preprocessor symbols as 0; changed all #ifdefs
for configuration symbols to #ifs
lpd 1995-04-05 changed copyright notice to make it clear that
including ansi2knr in a program does not bring the entire
program under the GPL
lpd 1994-12-18 added conditionals for systems where ctype macros
don't handle 8-bit characters properly, suggested by
Francois Pinard <pinard@iro.umontreal.ca>;
removed --varargs switch (this is now the default)
lpd 1994-10-10 removed CONFIG_BROKETS conditional
lpd 1994-07-16 added some conditionals to help GNU `configure',
suggested by Francois Pinard <pinard@iro.umontreal.ca>;
properly erase prototype args in function parameters,
contributed by Jim Avera <jima@netcom.com>;
correct error in writeblanks (it shouldn't erase EOLs)
lpd 1989-xx-xx original version
*/
/* Most of the conditionals here are to make ansi2knr work with */
/* or without the GNU configure machinery. */
#if HAVE_CONFIG_H
# include <config.h>
#endif
#include <stdio.h>
#include <ctype.h>
#if HAVE_CONFIG_H
/*
For properly autoconfiguring ansi2knr, use AC_CONFIG_HEADER(config.h).
This will define HAVE_CONFIG_H and so, activate the following lines.
*/
# if STDC_HEADERS || HAVE_STRING_H
# include <string.h>
# else
# include <strings.h>
# endif
#else /* not HAVE_CONFIG_H */
/* Otherwise do it the hard way */
# ifdef BSD
# include <strings.h>
# else
# ifdef VMS
extern int strlen(), strncmp();
# else
# include <string.h>
# endif
# endif
#endif /* not HAVE_CONFIG_H */
#if STDC_HEADERS
# include <stdlib.h>
#else
/*
malloc and free should be declared in stdlib.h,
but if you've got a K&R compiler, they probably aren't.
*/
# ifdef MSDOS
# include <malloc.h>
# else
# ifdef VMS
extern char *malloc();
extern void free();
# else
extern char *malloc();
extern int free();
# endif
# endif
#endif
/* Define NULL (for *very* old compilers). */
#ifndef NULL
# define NULL (0)
#endif
/*
* The ctype macros don't always handle 8-bit characters correctly.
* Compensate for this here.
*/
#ifdef isascii
# undef HAVE_ISASCII /* just in case */
# define HAVE_ISASCII 1
#else
#endif
#if STDC_HEADERS || !HAVE_ISASCII
# define is_ascii(c) 1
#else
# define is_ascii(c) isascii(c)
#endif
#define is_space(c) (is_ascii(c) && isspace(c))
#define is_alpha(c) (is_ascii(c) && isalpha(c))
#define is_alnum(c) (is_ascii(c) && isalnum(c))
/* Scanning macros */
#define isidchar(ch) (is_alnum(ch) || (ch) == '_')
#define isidfirstchar(ch) (is_alpha(ch) || (ch) == '_')
/* Forward references */
char *ppdirforward();
char *ppdirbackward();
char *skipspace();
char *scanstring();
int writeblanks();
int test1();
int convert1();
/* The main program */
int
main(argc, argv)
int argc;
char *argv[];
{ FILE *in = stdin;
FILE *out = stdout;
char *filename = 0;
char *program_name = argv[0];
char *output_name = 0;
#define bufsize 5000 /* arbitrary size */
char *buf;
char *line;
char *more;
char *usage =
"Usage: ansi2knr [--filename FILENAME] [INPUT_FILE [OUTPUT_FILE]]\n";
/*
* In previous versions, ansi2knr recognized a --varargs switch.
* If this switch was supplied, ansi2knr would attempt to convert
* a ... argument to va_alist and va_dcl; if this switch was not
* supplied, ansi2knr would simply drop any such arguments.
* Now, ansi2knr always does this conversion, and we only
* check for this switch for backward compatibility.
*/
int convert_varargs = 1;
int output_error;
while ( argc > 1 && argv[1][0] == '-' ) {
if ( !strcmp(argv[1], "--varargs") ) {
convert_varargs = 1;
argc--;
argv++;
continue;
}
if ( !strcmp(argv[1], "--filename") && argc > 2 ) {
filename = argv[2];
argc -= 2;
argv += 2;
continue;
}
fprintf(stderr, "%s: Unrecognized switch: %s\n", program_name,
argv[1]);
fprintf(stderr, usage);
exit(1);
}
switch ( argc )
{
default:
fprintf(stderr, usage);
exit(0);
case 3:
output_name = argv[2];
out = fopen(output_name, "w");
if ( out == NULL ) {
fprintf(stderr, "%s: Cannot open output file %s\n",
program_name, output_name);
exit(1);
}
/* falls through */
case 2:
in = fopen(argv[1], "r");
if ( in == NULL ) {
fprintf(stderr, "%s: Cannot open input file %s\n",
program_name, argv[1]);
exit(1);
}
if ( filename == 0 )
filename = argv[1];
/* falls through */
case 1:
break;
}
if ( filename )
fprintf(out, "#line 1 \"%s\"\n", filename);
buf = malloc(bufsize);
if ( buf == NULL )
{
fprintf(stderr, "Unable to allocate read buffer!\n");
exit(1);
}
line = buf;
while ( fgets(line, (unsigned)(buf + bufsize - line), in) != NULL )
{
test: line += strlen(line);
switch ( test1(buf) )
{
case 2: /* a function header */
convert1(buf, out, 1, convert_varargs);
break;
case 1: /* a function */
/* Check for a { at the start of the next line. */
more = ++line;
f: if ( line >= buf + (bufsize - 1) ) /* overflow check */
goto wl;
if ( fgets(line, (unsigned)(buf + bufsize - line), in) == NULL )
goto wl;
switch ( *skipspace(ppdirforward(more), 1) )
{
case '{':
/* Definitely a function header. */
convert1(buf, out, 0, convert_varargs);
fputs(more, out);
break;
case 0:
/* The next line was blank or a comment: */
/* keep scanning for a non-comment. */
line += strlen(line);
goto f;
default:
/* buf isn't a function header, but */
/* more might be. */
fputs(buf, out);
strcpy(buf, more);
line = buf;
goto test;
}
break;
case -1: /* maybe the start of a function */
if ( line != buf + (bufsize - 1) ) /* overflow check */
continue;
/* falls through */
default: /* not a function */
wl: fputs(buf, out);
break;
}
line = buf;
}
if ( line != buf )
fputs(buf, out);
free(buf);
if ( output_name ) {
output_error = ferror(out);
output_error |= fclose(out);
} else { /* out == stdout */
fflush(out);
output_error = ferror(out);
}
if ( output_error ) {
fprintf(stderr, "%s: error writing to %s\n", program_name,
(output_name ? output_name : "stdout"));
exit(1);
}
if ( in != stdin )
fclose(in);
return 0;
}
/*
* Skip forward or backward over one or more preprocessor directives.
*/
char *
ppdirforward(p)
char *p;
{
for (; *p == '#'; ++p) {
for (; *p != '\r' && *p != '\n'; ++p)
if (*p == 0)
return p;
if (*p == '\r' && p[1] == '\n')
++p;
}
return p;
}
char *
ppdirbackward(p, limit)
char *p;
char *limit;
{
char *np = p;
for (;; p = --np) {
if (*np == '\n' && np[-1] == '\r')
--np;
for (; np > limit && np[-1] != '\r' && np[-1] != '\n'; --np)
if (np[-1] == 0)
return np;
if (*np != '#')
return p;
}
}
/*
* Skip over whitespace, comments, and preprocessor directives,
* in either direction.
*/
char *
skipspace(p, dir)
char *p;
int dir; /* 1 for forward, -1 for backward */
{
for ( ; ; ) {
while ( is_space(*p) )
p += dir;
if ( !(*p == '/' && p[dir] == '*') )
break;
p += dir; p += dir;
while ( !(*p == '*' && p[dir] == '/') ) {
if ( *p == 0 )
return p; /* multi-line comment?? */
p += dir;
}
p += dir; p += dir;
}
return p;
}
/* Scan over a quoted string, in either direction. */
char *
scanstring(p, dir)
char *p;
int dir;
{
for (p += dir; ; p += dir)
if (*p == '"' && p[-dir] != '\\')
return p + dir;
}
/*
* Write blanks over part of a string.
* Don't overwrite end-of-line characters.
*/
int
writeblanks(start, end)
char *start;
char *end;
{ char *p;
for ( p = start; p < end; p++ )
if ( *p != '\r' && *p != '\n' )
*p = ' ';
return 0;
}
/*
* Test whether the string in buf is a function definition.
* The string may contain and/or end with a newline.
* Return as follows:
* 0 - definitely not a function definition;
* 1 - definitely a function definition;
* 2 - definitely a function prototype (NOT USED);
* -1 - may be the beginning of a function definition,
* append another line and look again.
* The reason we don't attempt to convert function prototypes is that
* Ghostscript's declaration-generating macros look too much like
* prototypes, and confuse the algorithms.
*/
int
test1(buf)
char *buf;
{ char *p = buf;
char *bend;
char *endfn;
int contin;
if ( !isidfirstchar(*p) )
return 0; /* no name at left margin */
bend = skipspace(ppdirbackward(buf + strlen(buf) - 1, buf), -1);
switch ( *bend )
{
case ';': contin = 0 /*2*/; break;
case ')': contin = 1; break;
case '{': return 0; /* not a function */
case '}': return 0; /* not a function */
default: contin = -1;
}
while ( isidchar(*p) )
p++;
endfn = p;
p = skipspace(p, 1);
if ( *p++ != '(' )
return 0; /* not a function */
p = skipspace(p, 1);
if ( *p == ')' )
return 0; /* no parameters */
/* Check that the apparent function name isn't a keyword. */
/* We only need to check for keywords that could be followed */
/* by a left parenthesis (which, unfortunately, is most of them). */
{ static char *words[] =
{ "asm", "auto", "case", "char", "const", "double",
"extern", "float", "for", "if", "int", "long",
"register", "return", "short", "signed", "sizeof",
"static", "switch", "typedef", "unsigned",
"void", "volatile", "while", 0
};
char **key = words;
char *kp;
unsigned len = endfn - buf;
while ( (kp = *key) != 0 )
{ if ( strlen(kp) == len && !strncmp(kp, buf, len) )
return 0; /* name is a keyword */
key++;
}
}
{
char *id = p;
int len;
/*
* Check for identifier1(identifier2) and not
* identifier1(void), or identifier1(identifier2, xxxx).
*/
while ( isidchar(*p) )
p++;
len = p - id;
p = skipspace(p, 1);
if (*p == ',' ||
(*p == ')' && (len != 4 || strncmp(id, "void", 4)))
)
return 0; /* not a function */
}
/*
* If the last significant character was a ), we need to count
* parentheses, because it might be part of a formal parameter
* that is a procedure.
*/
if (contin > 0) {
int level = 0;
for (p = skipspace(buf, 1); *p; p = skipspace(p + 1, 1))
level += (*p == '(' ? 1 : *p == ')' ? -1 : 0);
if (level > 0)
contin = -1;
}
return contin;
}
/* Convert a recognized function definition or header to K&R syntax. */
int
convert1(buf, out, header, convert_varargs)
char *buf;
FILE *out;
int header; /* Boolean */
int convert_varargs; /* Boolean */
{ char *endfn;
char *p;
/*
* The breaks table contains pointers to the beginning and end
* of each argument.
*/
char **breaks;
unsigned num_breaks = 2; /* for testing */
char **btop;
char **bp;
char **ap;
char *vararg = 0;
/* Pre-ANSI implementations don't agree on whether strchr */
/* is called strchr or index, so we open-code it here. */
for ( endfn = buf; *(endfn++) != '('; )
;
top: p = endfn;
breaks = (char **)malloc(sizeof(char *) * num_breaks * 2);
if ( breaks == NULL )
{ /* Couldn't allocate break table, give up */
fprintf(stderr, "Unable to allocate break table!\n");
fputs(buf, out);
return -1;
}
btop = breaks + num_breaks * 2 - 2;
bp = breaks;
/* Parse the argument list */
do
{ int level = 0;
char *lp = NULL;
char *rp = NULL;
char *end = NULL;
if ( bp >= btop )
{ /* Filled up break table. */
/* Allocate a bigger one and start over. */
free((char *)breaks);
num_breaks <<= 1;
goto top;
}
*bp++ = p;
/* Find the end of the argument */
for ( ; end == NULL; p++ )
{ switch(*p)
{
case ',':
if ( !level ) end = p;
break;
case '(':
if ( !level ) lp = p;
level++;
break;
case ')':
if ( --level < 0 ) end = p;
else rp = p;
break;
case '/':
if (p[1] == '*')
p = skipspace(p, 1) - 1;
break;
case '"':
p = scanstring(p, 1) - 1;
break;
default:
;
}
}
/* Erase any embedded prototype parameters. */
if ( lp && rp )
writeblanks(lp + 1, rp);
p--; /* back up over terminator */
/* Find the name being declared. */
/* This is complicated because of procedure and */
/* array modifiers. */
for ( ; ; )
{ p = skipspace(p - 1, -1);
switch ( *p )
{
case ']': /* skip array dimension(s) */
case ')': /* skip procedure args OR name */
{ int level = 1;
while ( level )
switch ( *--p )
{
case ']': case ')':
level++;
break;
case '[': case '(':
level--;
break;
case '/':
if (p > buf && p[-1] == '*')
p = skipspace(p, -1) + 1;
break;
case '"':
p = scanstring(p, -1) + 1;
break;
default: ;
}
}
if ( *p == '(' && *skipspace(p + 1, 1) == '*' )
{ /* We found the name being declared */
while ( !isidfirstchar(*p) )
p = skipspace(p, 1) + 1;
goto found;
}
break;
default:
goto found;
}
}
found: if ( *p == '.' && p[-1] == '.' && p[-2] == '.' )
{ if ( convert_varargs )
{ *bp++ = "va_alist";
vararg = p-2;
}
else
{ p++;
if ( bp == breaks + 1 ) /* sole argument */
writeblanks(breaks[0], p);
else
writeblanks(bp[-1] - 1, p);
bp--;
}
}
else
{ while ( isidchar(*p) ) p--;
*bp++ = p+1;
}
p = end;
}
while ( *p++ == ',' );
*bp = p;
/* Make a special check for 'void' arglist */
if ( bp == breaks+2 )
{ p = skipspace(breaks[0], 1);
if ( !strncmp(p, "void", 4) )
{ p = skipspace(p+4, 1);
if ( p == breaks[2] - 1 )
{ bp = breaks; /* yup, pretend arglist is empty */
writeblanks(breaks[0], p + 1);
}
}
}
/* Put out the function name and left parenthesis. */
p = buf;
while ( p != endfn ) putc(*p, out), p++;
/* Put out the declaration. */
if ( header )
{ fputs(");", out);
for ( p = breaks[0]; *p; p++ )
if ( *p == '\r' || *p == '\n' )
putc(*p, out);
}
else
{ for ( ap = breaks+1; ap < bp; ap += 2 )
{ p = *ap;
while ( isidchar(*p) )
putc(*p, out), p++;
if ( ap < bp - 1 )
fputs(", ", out);
}
fputs(") ", out);
/* Put out the argument declarations */
for ( ap = breaks+2; ap <= bp; ap += 2 )
(*ap)[-1] = ';';
if ( vararg != 0 )
{ *vararg = 0;
fputs(breaks[0], out); /* any prior args */
fputs("va_dcl", out); /* the final arg */
fputs(bp[0], out);
}
else
fputs(breaks[0], out);
}
free((char *)breaks);
return 0;
}

View File

@@ -1,163 +0,0 @@
/* Arithmetic for numbers greater than a long int, for GNU tar.
Copyright (C) 1996, 1997 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 2, or (at your option) any later
version.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
59 Place - Suite 330, Boston, MA 02111-1307, USA. */
#include "system.h"
/* common.h is needed to define FATAL_ERROR. It also includes arith.h. */
#include "common.h"
/* GNU tar needs handling numbers exceeding 32 bits, which is the size of
unsigned long ints for many C compilers. This module should provide
machinery for handling at least BITS_PER_TARLONG bits per number. If
`long long' ints are available and are sufficient for the task, they will
be used preferrably.
Russell Cattelan reports 165 Gb single tapes (digital video D2 tapes on
Ampex drives), so requiring 38 bits for the tape length in bytes. He
also reports breaking the terabyte limit with a single file (using SGI
xFS file system over 37 28GB disk arrays attached to a Power Challenge
XL; check out http://www.lcse.umn.edu/ for a picture), so requiring a
little more than 40 bits for the file size in bytes. The POSIX header
structure allows for 12 octal digits to represent file lengths, that is,
up to 36 bits for the byte size of files.
If `long long' is not supported by the compiler, SIZEOF_LONG_LONG will be
set to zero by configure. In this case, or if `long long' ints does not
have enough bits, then huge numbers are rather represented by an array of
longs, with the least significant super-digit at position 0. For making
multiplication and decimal input/output easy, the base of a super-digit
is an exact exponent of 10, and is such that base*base fits in a long. */
#if SUPERDIGIT
/*-------------------------------.
| Check if ACCUMULATOR is zero. |
`-------------------------------*/
int
zerop_tarlong_helper (unsigned long *accumulator)
{
int counter;
for (counter = LONGS_PER_TARLONG - 1; counter >= 0; counter--)
if (accumulator[counter])
return 0;
return 1;
}
/*----------------------------------------------.
| Check if FIRST is strictly less than SECOND. |
`----------------------------------------------*/
int
lessp_tarlong_helper (unsigned long *first, unsigned long *second)
{
int counter;
for (counter = LONGS_PER_TARLONG - 1; counter >= 0; counter--)
if (first[counter] != second[counter])
return first[counter] < second[counter];
return 0;
}
/*----------------------------.
| Reset ACCUMULATOR to zero. |
`----------------------------*/
void
clear_tarlong_helper (unsigned long *accumulator)
{
int counter;
for (counter = 0; counter < LONGS_PER_TARLONG; counter++)
accumulator[counter] = 0;
}
/*----------------------------.
| To ACCUMULATOR, add VALUE. |
`----------------------------*/
void
add_to_tarlong_helper (unsigned long *accumulator, int value)
{
int counter;
if (value < 0)
for (counter = 0; counter < LONGS_PER_TARLONG; counter++)
{
if (accumulator[counter] >= -value)
{
accumulator[counter] += value;
return;
}
accumulator[counter] += value + SUPERDIGIT;
value = -1;
}
else
for (counter = 0; counter < LONGS_PER_TARLONG; counter++)
{
if (accumulator[counter] + value < SUPERDIGIT)
{
accumulator[counter] += value;
return;
}
accumulator[counter] += value - SUPERDIGIT;
value = 1;
}
FATAL_ERROR ((0, 0, _("Arithmetic overflow")));
}
/*--------------------------------.
| Multiply ACCUMULATOR by VALUE. |
`--------------------------------*/
void
mult_tarlong_helper (unsigned long *accumulator, int value)
{
int carry = 0;
int counter;
for (counter = 0; counter < LONGS_PER_TARLONG; counter++)
{
carry += accumulator[counter] * value;
accumulator[counter] = carry % SUPERDIGIT;
carry /= SUPERDIGIT;
}
if (carry)
FATAL_ERROR ((0, 0, _("Arithmetic overflow")));
}
/*----------------------------------------------------------.
| Print the decimal representation of ACCUMULATOR on FILE. |
`----------------------------------------------------------*/
void
print_tarlong_helper (unsigned long *accumulator, FILE *file)
{
int counter = LONGS_PER_TARLONG - 1;
while (counter > 0 && accumulator[counter] == 0)
counter--;
fprintf (file, "%uld", accumulator[counter]);
while (counter > 0)
fprintf (file, TARLONG_FORMAT, accumulator[--counter]);
}
#endif /* SUPERDIGIT */

View File

@@ -1,759 +0,0 @@
/* Diff files from a tar archive.
Copyright (C) 1988, 1992, 1993 Free Software Foundation
This file is part of GNU Tar.
GNU Tar is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Tar is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Tar; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
/*
* Diff files from a tar archive.
*
* Written 30 April 1987 by John Gilmore, ihnp4!hoptoad!gnu.
*/
#include <stdio.h>
#include <errno.h>
#ifndef STDC_HEADERS
extern int errno;
#endif
#include <sys/types.h>
#ifdef BSD42
#include <sys/file.h>
#else
#ifndef V7
#include <fcntl.h>
#endif
#endif
#ifdef HAVE_SYS_MTIO_H
#include <sys/ioctl.h>
#include <sys/mtio.h>
#endif
#include "tar.h"
#include "port.h"
#include "rmt.h"
#ifndef S_ISLNK
#define lstat stat
#endif
extern void *valloc ();
extern union record *head; /* Points to current tape header */
extern struct stat hstat; /* Stat struct corresponding */
extern int head_standard; /* Tape header is in ANSI format */
void decode_header ();
void diff_sparse_files ();
void fill_in_sparse_array ();
void fl_read ();
long from_oct ();
int do_stat ();
extern void print_header ();
int read_header ();
void saverec ();
void sigh ();
extern void skip_file ();
extern void skip_extended_headers ();
int wantbytes ();
extern FILE *msg_file;
int now_verifying = 0; /* Are we verifying at the moment? */
int diff_fd; /* Descriptor of file we're diffing */
char *diff_buf = 0; /* Pointer to area for reading
file contents into */
char *diff_dir; /* Directory contents for LF_DUMPDIR */
int different = 0;
/*struct sp_array *sparsearray;
int sp_ar_size = 10;*/
/*
* Initialize for a diff operation
*/
void
diff_init ()
{
/*NOSTRICT*/
diff_buf = (char *) valloc ((unsigned) blocksize);
if (!diff_buf)
{
msg ("could not allocate memory for diff buffer of %d bytes",
blocksize);
exit (EX_ARGSBAD);
}
}
/*
* Diff a file against the archive.
*/
void
diff_archive ()
{
register char *data;
int check, namelen;
int err;
long offset;
struct stat filestat;
int compare_chunk ();
int compare_dir ();
int no_op ();
#ifndef __MSDOS__
dev_t dev;
ino_t ino;
#endif
char *get_dir_contents ();
long from_oct ();
errno = EPIPE; /* FIXME, remove perrors */
saverec (&head); /* Make sure it sticks around */
userec (head); /* And go past it in the archive */
decode_header (head, &hstat, &head_standard, 1); /* Snarf fields */
/* Print the record from 'head' and 'hstat' */
if (f_verbose)
{
if (now_verifying)
fprintf (msg_file, "Verify ");
print_header ();
}
switch (head->header.linkflag)
{
default:
msg ("Unknown file type '%c' for %s, diffed as normal file",
head->header.linkflag, current_file_name);
/* FALL THRU */
case LF_OLDNORMAL:
case LF_NORMAL:
case LF_SPARSE:
case LF_CONTIG:
/*
* Appears to be a file.
* See if it's really a directory.
*/
namelen = strlen (current_file_name) - 1;
if (current_file_name[namelen] == '/')
goto really_dir;
if (do_stat (&filestat))
{
if (head->header.isextended)
skip_extended_headers ();
skip_file ((long) hstat.st_size);
different++;
goto quit;
}
if (!S_ISREG (filestat.st_mode))
{
fprintf (msg_file, "%s: not a regular file\n",
current_file_name);
skip_file ((long) hstat.st_size);
different++;
goto quit;
}
filestat.st_mode &= 07777;
if (filestat.st_mode != hstat.st_mode)
sigh ("mode");
if (filestat.st_uid != hstat.st_uid)
sigh ("uid");
if (filestat.st_gid != hstat.st_gid)
sigh ("gid");
if (filestat.st_mtime != hstat.st_mtime)
sigh ("mod time");
if (head->header.linkflag != LF_SPARSE &&
filestat.st_size != hstat.st_size)
{
sigh ("size");
skip_file ((long) hstat.st_size);
goto quit;
}
diff_fd = open (current_file_name, O_NDELAY | O_RDONLY | O_BINARY);
if (diff_fd < 0 && !f_absolute_paths)
{
char tmpbuf[NAMSIZ + 2];
tmpbuf[0] = '/';
strcpy (&tmpbuf[1], current_file_name);
diff_fd = open (tmpbuf, O_NDELAY | O_RDONLY);
}
if (diff_fd < 0)
{
msg_perror ("cannot open %s", current_file_name);
if (head->header.isextended)
skip_extended_headers ();
skip_file ((long) hstat.st_size);
different++;
goto quit;
}
/*
* Need to treat sparse files completely differently here.
*/
if (head->header.linkflag == LF_SPARSE)
diff_sparse_files (hstat.st_size);
else
wantbytes ((long) (hstat.st_size), compare_chunk);
check = close (diff_fd);
if (check < 0)
msg_perror ("Error while closing %s", current_file_name);
quit:
break;
#ifndef __MSDOS__
case LF_LINK:
if (do_stat (&filestat))
break;
dev = filestat.st_dev;
ino = filestat.st_ino;
err = stat (current_link_name, &filestat);
if (err < 0)
{
if (errno == ENOENT)
{
fprintf (msg_file, "%s: does not exist\n", current_file_name);
}
else
{
msg_perror ("cannot stat file %s", current_file_name);
}
different++;
break;
}
if (filestat.st_dev != dev || filestat.st_ino != ino)
{
fprintf (msg_file, "%s not linked to %s\n", current_file_name, current_link_name);
break;
}
break;
#endif
#ifdef S_ISLNK
case LF_SYMLINK:
{
char linkbuf[NAMSIZ + 3];
check = readlink (current_file_name, linkbuf,
(sizeof linkbuf) - 1);
if (check < 0)
{
if (errno == ENOENT)
{
fprintf (msg_file,
"%s: no such file or directory\n",
current_file_name);
}
else
{
msg_perror ("cannot read link %s", current_file_name);
}
different++;
break;
}
linkbuf[check] = '\0'; /* Null-terminate it */
if (strncmp (current_link_name, linkbuf, check) != 0)
{
fprintf (msg_file, "%s: symlink differs\n",
current_link_name);
different++;
}
}
break;
#endif
#ifdef S_IFCHR
case LF_CHR:
hstat.st_mode |= S_IFCHR;
goto check_node;
#endif
#ifdef S_IFBLK
/* If local system doesn't support block devices, use default case */
case LF_BLK:
hstat.st_mode |= S_IFBLK;
goto check_node;
#endif
#ifdef S_ISFIFO
/* If local system doesn't support FIFOs, use default case */
case LF_FIFO:
#ifdef S_IFIFO
hstat.st_mode |= S_IFIFO;
#endif
hstat.st_rdev = 0; /* FIXME, do we need this? */
goto check_node;
#endif
check_node:
/* FIXME, deal with umask */
if (do_stat (&filestat))
break;
if (hstat.st_rdev != filestat.st_rdev)
{
fprintf (msg_file, "%s: device numbers changed\n", current_file_name);
different++;
break;
}
#ifdef S_IFMT
if (hstat.st_mode != filestat.st_mode)
#else /* POSIX lossage */
if ((hstat.st_mode & 07777) != (filestat.st_mode & 07777))
#endif
{
fprintf (msg_file, "%s: mode or device-type changed\n", current_file_name);
different++;
break;
}
break;
case LF_DUMPDIR:
data = diff_dir = get_dir_contents (current_file_name, 0);
if (data)
{
wantbytes ((long) (hstat.st_size), compare_dir);
free (data);
}
else
wantbytes ((long) (hstat.st_size), no_op);
/* FALL THROUGH */
case LF_DIR:
/* Check for trailing / */
namelen = strlen (current_file_name) - 1;
really_dir:
while (namelen && current_file_name[namelen] == '/')
current_file_name[namelen--] = '\0'; /* Zap / */
if (do_stat (&filestat))
break;
if (!S_ISDIR (filestat.st_mode))
{
fprintf (msg_file, "%s is no longer a directory\n", current_file_name);
different++;
break;
}
if ((filestat.st_mode & 07777) != (hstat.st_mode & 07777))
sigh ("mode");
break;
case LF_VOLHDR:
break;
case LF_MULTIVOL:
namelen = strlen (current_file_name) - 1;
if (current_file_name[namelen] == '/')
goto really_dir;
if (do_stat (&filestat))
break;
if (!S_ISREG (filestat.st_mode))
{
fprintf (msg_file, "%s: not a regular file\n",
current_file_name);
skip_file ((long) hstat.st_size);
different++;
break;
}
filestat.st_mode &= 07777;
offset = from_oct (1 + 12, head->header.offset);
if (filestat.st_size != hstat.st_size + offset)
{
sigh ("size");
skip_file ((long) hstat.st_size);
different++;
break;
}
diff_fd = open (current_file_name, O_NDELAY | O_RDONLY | O_BINARY);
if (diff_fd < 0)
{
msg_perror ("cannot open file %s", current_file_name);
skip_file ((long) hstat.st_size);
different++;
break;
}
err = lseek (diff_fd, offset, 0);
if (err != offset)
{
msg_perror ("cannot seek to %ld in file %s", offset, current_file_name);
different++;
break;
}
wantbytes ((long) (hstat.st_size), compare_chunk);
check = close (diff_fd);
if (check < 0)
{
msg_perror ("Error while closing %s", current_file_name);
}
break;
}
/* We don't need to save it any longer. */
saverec ((union record **) 0);/* Unsave it */
}
int
compare_chunk (bytes, buffer)
long bytes;
char *buffer;
{
int err;
err = read (diff_fd, diff_buf, bytes);
if (err != bytes)
{
if (err < 0)
{
msg_perror ("can't read %s", current_file_name);
}
else
{
fprintf (msg_file, "%s: could only read %d of %d bytes\n", current_file_name, err, bytes);
}
different++;
return -1;
}
if (bcmp (buffer, diff_buf, bytes))
{
fprintf (msg_file, "%s: data differs\n", current_file_name);
different++;
return -1;
}
return 0;
}
int
compare_dir (bytes, buffer)
long bytes;
char *buffer;
{
if (bcmp (buffer, diff_dir, bytes))
{
fprintf (msg_file, "%s: data differs\n", current_file_name);
different++;
return -1;
}
diff_dir += bytes;
return 0;
}
/*
* Sigh about something that differs.
*/
void
sigh (what)
char *what;
{
fprintf (msg_file, "%s: %s differs\n",
current_file_name, what);
}
void
verify_volume ()
{
int status;
#ifdef MTIOCTOP
struct mtop t;
int er;
#endif
if (!diff_buf)
diff_init ();
#ifdef MTIOCTOP
t.mt_op = MTBSF;
t.mt_count = 1;
if ((er = rmtioctl (archive, MTIOCTOP, &t)) < 0)
{
if (errno != EIO || (er = rmtioctl (archive, MTIOCTOP, &t)) < 0)
{
#endif
if (rmtlseek (archive, 0L, 0) != 0)
{
/* Lseek failed. Try a different method */
msg_perror ("Couldn't rewind archive file for verify");
return;
}
#ifdef MTIOCTOP
}
}
#endif
ar_reading = 1;
now_verifying = 1;
fl_read ();
for (;;)
{
status = read_header ();
if (status == 0)
{
unsigned n;
n = 0;
do
{
n++;
status = read_header ();
}
while (status == 0);
msg ("VERIFY FAILURE: %d invalid header%s detected!", n, n == 1 ? "" : "s");
}
if (status == 2 || status == EOF)
break;
diff_archive ();
}
ar_reading = 0;
now_verifying = 0;
}
int
do_stat (statp)
struct stat *statp;
{
int err;
err = f_follow_links ? stat (current_file_name, statp) : lstat (current_file_name, statp);
if (err < 0)
{
if (errno == ENOENT)
{
fprintf (msg_file, "%s: does not exist\n", current_file_name);
}
else
msg_perror ("can't stat file %s", current_file_name);
/* skip_file((long)hstat.st_size);
different++;*/
return 1;
}
else
return 0;
}
/*
* JK
* Diff'ing a sparse file with its counterpart on the tar file is a
* bit of a different story than a normal file. First, we must know
* what areas of the file to skip through, i.e., we need to contruct
* a sparsearray, which will hold all the information we need. We must
* compare small amounts of data at a time as we find it.
*/
void
diff_sparse_files (filesize)
int filesize;
{
int sparse_ind = 0;
char *buf;
int buf_size = RECORDSIZE;
union record *datarec;
int err;
long numbytes;
/* int amt_read = 0;*/
int size = filesize;
buf = (char *) ck_malloc (buf_size * sizeof (char));
fill_in_sparse_array ();
while (size > 0)
{
datarec = findrec ();
if (!sparsearray[sparse_ind].numbytes)
break;
/*
* 'numbytes' is nicer to write than
* 'sparsearray[sparse_ind].numbytes' all the time ...
*/
numbytes = sparsearray[sparse_ind].numbytes;
lseek (diff_fd, sparsearray[sparse_ind].offset, 0);
/*
* take care to not run out of room in our buffer
*/
while (buf_size < numbytes)
{
buf = (char *) ck_realloc (buf, buf_size * 2 * sizeof (char));
buf_size *= 2;
}
while (numbytes > RECORDSIZE)
{
if ((err = read (diff_fd, buf, RECORDSIZE)) != RECORDSIZE)
{
if (err < 0)
msg_perror ("can't read %s", current_file_name);
else
fprintf (msg_file, "%s: could only read %d of %d bytes\n",
current_file_name, err, numbytes);
break;
}
if (bcmp (buf, datarec->charptr, RECORDSIZE))
{
different++;
break;
}
numbytes -= err;
size -= err;
userec (datarec);
datarec = findrec ();
}
if ((err = read (diff_fd, buf, numbytes)) != numbytes)
{
if (err < 0)
msg_perror ("can't read %s", current_file_name);
else
fprintf (msg_file, "%s: could only read %d of %d bytes\n",
current_file_name, err, numbytes);
break;
}
if (bcmp (buf, datarec->charptr, numbytes))
{
different++;
break;
}
/* amt_read += numbytes;
if (amt_read >= RECORDSIZE) {
amt_read = 0;
userec(datarec);
datarec = findrec();
}*/
userec (datarec);
sparse_ind++;
size -= numbytes;
}
/*
* if the number of bytes read isn't the
* number of bytes supposedly in the file,
* they're different
*/
/* if (amt_read != filesize)
different++;*/
userec (datarec);
free (sparsearray);
if (different)
fprintf (msg_file, "%s: data differs\n", current_file_name);
}
/*
* JK
* This routine should be used more often than it is ... look into
* that. Anyhow, what it does is translate the sparse information
* on the header, and in any subsequent extended headers, into an
* array of structures with true numbers, as opposed to character
* strings. It simply makes our life much easier, doing so many
* comparisong and such.
*/
void
fill_in_sparse_array ()
{
int ind;
/*
* allocate space for our scratch space; it's initially
* 10 elements long, but can change in this routine if
* necessary
*/
sp_array_size = 10;
sparsearray = (struct sp_array *) ck_malloc (sp_array_size * sizeof (struct sp_array));
/*
* there are at most five of these structures in the header
* itself; read these in first
*/
for (ind = 0; ind < SPARSE_IN_HDR; ind++)
{
if (!head->header.sp[ind].numbytes)
break;
sparsearray[ind].offset =
from_oct (1 + 12, head->header.sp[ind].offset);
sparsearray[ind].numbytes =
from_oct (1 + 12, head->header.sp[ind].numbytes);
}
/*
* if the header's extended, we gotta read in exhdr's till
* we're done
*/
if (head->header.isextended)
{
/* how far into the sparsearray we are 'so far' */
static int so_far_ind = SPARSE_IN_HDR;
union record *exhdr;
for (;;)
{
exhdr = findrec ();
for (ind = 0; ind < SPARSE_EXT_HDR; ind++)
{
if (ind + so_far_ind > sp_array_size - 1)
{
/*
* we just ran out of room in our
* scratch area - realloc it
*/
sparsearray = (struct sp_array *)
ck_realloc (sparsearray,
sp_array_size * 2 * sizeof (struct sp_array));
sp_array_size *= 2;
}
/*
* convert the character strings into longs
*/
sparsearray[ind + so_far_ind].offset =
from_oct (1 + 12, exhdr->ext_hdr.sp[ind].offset);
sparsearray[ind + so_far_ind].numbytes =
from_oct (1 + 12, exhdr->ext_hdr.sp[ind].numbytes);
}
/*
* if this is the last extended header for this
* file, we can stop
*/
if (!exhdr->ext_hdr.isextended)
break;
else
{
so_far_ind += SPARSE_EXT_HDR;
userec (exhdr);
}
}
/* be sure to skip past the last one */
userec (exhdr);
}
}

View File

@@ -1,96 +0,0 @@
/* Replacement for getopt() that can be used by tar.
Copyright (C) 1988 Free Software Foundation
This file is part of GNU Tar.
GNU Tar is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Tar is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Tar; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
/*
* Plug-compatible replacement for getopt() for parsing tar-like
* arguments. If the first argument begins with "-", it uses getopt;
* otherwise, it uses the old rules used by tar, dump, and ps.
*
* Written 25 August 1985 by John Gilmore (ihnp4!hoptoad!gnu)
*/
#include <stdio.h>
#include "getopt.h"
#include "tar.h" /* For msg() declaration if STDC_MSG. */
#include <sys/types.h>
#include "port.h"
int
getoldopt (argc, argv, optstring, long_options, opt_index)
int argc;
char **argv;
char *optstring;
struct option *long_options;
int *opt_index;
{
extern char *optarg; /* Points to next arg */
extern int optind; /* Global argv index */
static char *key; /* Points to next keyletter */
static char use_getopt; /* !=0 if argv[1][0] was '-' */
char c;
char *place;
optarg = NULL;
if (key == NULL)
{ /* First time */
if (argc < 2)
return EOF;
key = argv[1];
if ((*key == '-') || (*key == '+'))
use_getopt++;
else
optind = 2;
}
if (use_getopt)
return getopt_long (argc, argv, optstring,
long_options, opt_index);
c = *key++;
if (c == '\0')
{
key--;
return EOF;
}
place = index (optstring, c);
if (place == NULL || c == ':')
{
msg ("unknown option %c", c);
return ('?');
}
place++;
if (*place == ':')
{
if (optind < argc)
{
optarg = argv[optind];
optind++;
}
else
{
msg ("%c argument missing", c);
return ('?');
}
}
return (c);
}

677
src/gnu.c
View File

@@ -1,677 +0,0 @@
/* GNU dump extensions to tar.
Copyright (C) 1988, 1992, 1993 Free Software Foundation
This file is part of GNU Tar.
GNU Tar is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Tar is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Tar; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include <stdio.h>
#include <sys/types.h>
#include <ctype.h>
#include <errno.h>
#ifndef STDC_HEADERS
extern int errno;
#endif
#include <time.h>
time_t time ();
#include "tar.h"
#include "port.h"
#ifndef S_ISLNK
#define lstat stat
#endif
extern time_t new_time;
extern FILE *msg_file;
void addname ();
int check_exclude ();
extern PTR ck_malloc ();
extern PTR ck_realloc ();
int confirm ();
extern PTR init_buffer ();
extern char *get_buffer ();
int is_dot_or_dotdot ();
extern void add_buffer ();
extern void flush_buffer ();
void name_gather ();
int recursively_delete ();
void skip_file ();
char *un_quote_string ();
extern char *new_name ();
static void add_dir_name ();
struct dirname
{
struct dirname *next;
char *name;
char *dir_text;
int dev;
int ino;
int allnew;
};
static struct dirname *dir_list;
static time_t this_time;
void
add_dir (name, dev, ino, text)
char *name;
char *text;
dev_t dev;
ino_t ino;
{
struct dirname *dp;
dp = (struct dirname *) ck_malloc (sizeof (struct dirname));
if (!dp)
abort ();
dp->next = dir_list;
dir_list = dp;
dp->dev = dev;
dp->ino = ino;
dp->name = ck_malloc (strlen (name) + 1);
strcpy (dp->name, name);
dp->dir_text = text;
dp->allnew = 0;
}
void
read_dir_file ()
{
int dev;
int ino;
char *strp;
FILE *fp;
char buf[512];
static char *path = 0;
if (path == 0)
path = ck_malloc (PATH_MAX);
time (&this_time);
if (gnu_dumpfile[0] != '/')
{
#if defined(__MSDOS__) || defined(HAVE_GETCWD) || defined(_POSIX_VERSION)
if (!getcwd (path, PATH_MAX))
{
msg ("Couldn't get current directory.");
exit (EX_SYSTEM);
}
#else
char *getwd ();
if (!getwd (path))
{
msg ("Couldn't get current directory: %s", path);
exit (EX_SYSTEM);
}
#endif
/* If this doesn't fit, we're in serious trouble */
strcat (path, "/");
strcat (path, gnu_dumpfile);
gnu_dumpfile = path;
}
fp = fopen (gnu_dumpfile, "r");
if (fp == 0 && errno != ENOENT)
{
msg_perror ("Can't open %s", gnu_dumpfile);
return;
}
if (!fp)
return;
fgets (buf, sizeof (buf), fp);
if (!f_new_files)
{
f_new_files++;
new_time = atol (buf);
}
while (fgets (buf, sizeof (buf), fp))
{
strp = &buf[strlen (buf)];
if (strp[-1] == '\n')
strp[-1] = '\0';
strp = buf;
dev = atol (strp);
while (isdigit (*strp))
strp++;
ino = atol (strp);
while (isspace (*strp))
strp++;
while (isdigit (*strp))
strp++;
strp++;
add_dir (un_quote_string (strp), dev, ino, (char *) 0);
}
fclose (fp);
}
void
write_dir_file ()
{
FILE *fp;
struct dirname *dp;
char *str;
extern char *quote_copy_string ();
fp = fopen (gnu_dumpfile, "w");
if (fp == 0)
{
msg_perror ("Can't write to %s", gnu_dumpfile);
return;
}
fprintf (fp, "%lu\n", this_time);
for (dp = dir_list; dp; dp = dp->next)
{
if (!dp->dir_text)
continue;
str = quote_copy_string (dp->name);
if (str)
{
fprintf (fp, "%u %u %s\n", dp->dev, dp->ino, str);
free (str);
}
else
fprintf (fp, "%u %u %s\n", dp->dev, dp->ino, dp->name);
}
fclose (fp);
}
struct dirname *
get_dir (name)
char *name;
{
struct dirname *dp;
for (dp = dir_list; dp; dp = dp->next)
{
if (!strcmp (dp->name, name))
return dp;
}
return 0;
}
/* Collect all the names from argv[] (or whatever), then expand them into
a directory tree, and put all the directories at the beginning. */
void
collect_and_sort_names ()
{
struct name *n, *n_next;
int num_names;
struct stat statbuf;
int name_cmp ();
char *merge_sort ();
name_gather ();
if (gnu_dumpfile)
read_dir_file ();
if (!namelist)
addname (".");
for (n = namelist; n; n = n_next)
{
n_next = n->next;
if (n->found || n->dir_contents)
continue;
if (n->regexp) /* FIXME just skip regexps for now */
continue;
if (n->change_dir)
if (chdir (n->change_dir) < 0)
{
msg_perror ("can't chdir to %s", n->change_dir);
continue;
}
#ifdef AIX
if (statx (n->name, &statbuf, STATSIZE, STX_HIDDEN | STX_LINK))
#else
if (lstat (n->name, &statbuf) < 0)
#endif /* AIX */
{
msg_perror ("can't stat %s", n->name);
continue;
}
if (S_ISDIR (statbuf.st_mode))
{
n->found++;
add_dir_name (n->name, statbuf.st_dev);
}
}
num_names = 0;
for (n = namelist; n; n = n->next)
num_names++;
namelist = (struct name *) merge_sort ((PTR) namelist, num_names, (char *) (&(namelist->next)) - (char *) namelist, name_cmp);
for (n = namelist; n; n = n->next)
{
n->found = 0;
}
if (gnu_dumpfile)
write_dir_file ();
}
int
name_cmp (n1, n2)
struct name *n1, *n2;
{
if (n1->found)
{
if (n2->found)
return strcmp (n1->name, n2->name);
else
return -1;
}
else if (n2->found)
return 1;
else
return strcmp (n1->name, n2->name);
}
int
dirent_cmp (p1, p2)
const PTR p1;
const PTR p2;
{
char *frst, *scnd;
frst = (*(char **) p1) + 1;
scnd = (*(char **) p2) + 1;
return strcmp (frst, scnd);
}
char *
get_dir_contents (p, device)
char *p;
int device;
{
DIR *dirp;
register struct dirent *d;
char *new_buf;
char *namebuf;
int bufsiz;
int len;
PTR the_buffer;
char *buf;
size_t n_strs;
/* int n_size;*/
char *p_buf;
char **vec, **p_vec;
extern int errno;
errno = 0;
dirp = opendir (p);
bufsiz = strlen (p) + NAMSIZ;
namebuf = ck_malloc (bufsiz + 2);
if (!dirp)
{
if (errno)
msg_perror ("can't open directory %s", p);
else
msg ("error opening directory %s", p);
new_buf = NULL;
}
else
{
struct dirname *dp;
int all_children;
dp = get_dir (p);
all_children = dp ? dp->allnew : 0;
(void) strcpy (namebuf, p);
if (p[strlen (p) - 1] != '/')
(void) strcat (namebuf, "/");
len = strlen (namebuf);
the_buffer = init_buffer ();
while (d = readdir (dirp))
{
struct stat hs;
/* Skip . and .. */
if (is_dot_or_dotdot (d->d_name))
continue;
if (NLENGTH (d) + len >= bufsiz)
{
bufsiz += NAMSIZ;
namebuf = ck_realloc (namebuf, bufsiz + 2);
}
(void) strcpy (namebuf + len, d->d_name);
#ifdef AIX
if (0 != f_follow_links ?
statx (namebuf, &hs, STATSIZE, STX_HIDDEN) :
statx (namebuf, &hs, STATSIZE, STX_HIDDEN | STX_LINK))
#else
if (0 != f_follow_links ? stat (namebuf, &hs) : lstat (namebuf, &hs))
#endif
{
msg_perror ("can't stat %s", namebuf);
continue;
}
if ((f_local_filesys && device != hs.st_dev)
|| (f_exclude && check_exclude (namebuf)))
add_buffer (the_buffer, "N", 1);
#ifdef AIX
else if (S_ISHIDDEN (hs.st_mode))
{
add_buffer (the_buffer, "D", 1);
strcat (d->d_name, "A");
d->d_namlen++;
}
#endif /* AIX */
else if (S_ISDIR (hs.st_mode))
{
if (dp = get_dir (namebuf))
{
if (dp->dev != hs.st_dev
|| dp->ino != hs.st_ino)
{
if (f_verbose)
msg ("directory %s has been renamed.", namebuf);
dp->allnew = 1;
dp->dev = hs.st_dev;
dp->ino = hs.st_ino;
}
dp->dir_text = "";
}
else
{
if (f_verbose)
msg ("Directory %s is new", namebuf);
add_dir (namebuf, hs.st_dev, hs.st_ino, "");
dp = get_dir (namebuf);
dp->allnew = 1;
}
if (all_children)
dp->allnew = 1;
add_buffer (the_buffer, "D", 1);
}
else if (!all_children
&& f_new_files
&& new_time > hs.st_mtime
&& (f_new_files > 1
|| new_time > hs.st_ctime))
add_buffer (the_buffer, "N", 1);
else
add_buffer (the_buffer, "Y", 1);
add_buffer (the_buffer, d->d_name, (int) (NLENGTH (d) + 1));
}
add_buffer (the_buffer, "\000\000", 2);
closedir (dirp);
/* Well, we've read in the contents of the dir, now sort them */
buf = get_buffer (the_buffer);
if (buf[0] == '\0')
{
flush_buffer (the_buffer);
new_buf = NULL;
}
else
{
n_strs = 0;
for (p_buf = buf; *p_buf;)
{
int tmp;
tmp = strlen (p_buf) + 1;
n_strs++;
p_buf += tmp;
}
vec = (char **) ck_malloc (sizeof (char *) * (n_strs + 1));
for (p_vec = vec, p_buf = buf; *p_buf; p_buf += strlen (p_buf) + 1)
*p_vec++ = p_buf;
*p_vec = 0;
qsort ((PTR) vec, n_strs, sizeof (char *), dirent_cmp);
new_buf = (char *) ck_malloc (p_buf - buf + 2);
for (p_vec = vec, p_buf = new_buf; *p_vec; p_vec++)
{
char *p_tmp;
for (p_tmp = *p_vec; *p_buf++ = *p_tmp++;)
;
}
*p_buf++ = '\0';
free (vec);
flush_buffer (the_buffer);
}
}
free (namebuf);
return new_buf;
}
/* p is a directory. Add all the files in P to the namelist. If any of the
files is a directory, recurse on the subdirectory. . . */
static void
add_dir_name (p, device)
char *p;
int device;
{
char *new_buf;
char *p_buf;
char *namebuf;
int buflen;
register int len;
int sublen;
/* PTR the_buffer;*/
/* char *buf;*/
/* char **vec,**p_vec;*/
/* int n_strs,n_size;*/
struct name *n;
int dirent_cmp ();
new_buf = get_dir_contents (p, device);
for (n = namelist; n; n = n->next)
{
if (!strcmp (n->name, p))
{
n->dir_contents = new_buf ? new_buf : "\0\0\0\0";
break;
}
}
if (new_buf)
{
len = strlen (p);
buflen = NAMSIZ <= len ? len + NAMSIZ : NAMSIZ;
namebuf = ck_malloc (buflen + 1);
(void) strcpy (namebuf, p);
if (namebuf[len - 1] != '/')
{
namebuf[len++] = '/';
namebuf[len] = '\0';
}
for (p_buf = new_buf; *p_buf; p_buf += sublen + 1)
{
sublen = strlen (p_buf);
if (*p_buf == 'D')
{
if (len + sublen >= buflen)
{
buflen += NAMSIZ;
namebuf = ck_realloc (namebuf, buflen + 1);
}
(void) strcpy (namebuf + len, p_buf + 1);
addname (namebuf);
add_dir_name (namebuf, device);
}
}
free (namebuf);
}
}
/* Returns non-zero if p is . or .. This could be a macro for speed. */
int
is_dot_or_dotdot (p)
char *p;
{
return (p[0] == '.' && (p[1] == '\0' || (p[1] == '.' && p[2] == '\0')));
}
void
gnu_restore (skipcrud)
int skipcrud;
{
char *current_dir;
/* int current_dir_length; */
char *archive_dir;
/* int archive_dir_length; */
PTR the_buffer;
char *p;
DIR *dirp;
struct dirent *d;
char *cur, *arc;
extern struct stat hstat; /* Stat struct corresponding */
long size, copied;
char *from, *to;
extern union record *head;
dirp = opendir (skipcrud + current_file_name);
if (!dirp)
{
/* The directory doesn't exist now. It'll be created.
In any case, we don't have to delete any files out
of it */
skip_file ((long) hstat.st_size);
return;
}
the_buffer = init_buffer ();
while (d = readdir (dirp))
{
if (is_dot_or_dotdot (d->d_name))
continue;
add_buffer (the_buffer, d->d_name, (int) (NLENGTH (d) + 1));
}
closedir (dirp);
add_buffer (the_buffer, "", 1);
current_dir = get_buffer (the_buffer);
archive_dir = (char *) ck_malloc (hstat.st_size);
if (archive_dir == 0)
{
msg ("Can't allocate %d bytes for restore", hstat.st_size);
skip_file ((long) hstat.st_size);
return;
}
to = archive_dir;
for (size = hstat.st_size; size > 0; size -= copied)
{
from = findrec ()->charptr;
if (!from)
{
msg ("Unexpected EOF in archive\n");
break;
}
copied = endofrecs ()->charptr - from;
if (copied > size)
copied = size;
bcopy ((PTR) from, (PTR) to, (int) copied);
to += copied;
userec ((union record *) (from + copied - 1));
}
for (cur = current_dir; *cur; cur += strlen (cur) + 1)
{
for (arc = archive_dir; *arc; arc += strlen (arc) + 1)
{
arc++;
if (!strcmp (arc, cur))
break;
}
if (*arc == '\0')
{
p = new_name (skipcrud + current_file_name, cur);
if (f_confirm && !confirm ("delete", p))
{
free (p);
continue;
}
if (f_verbose)
fprintf (msg_file, "%s: deleting %s\n", tar, p);
if (recursively_delete (p))
{
msg ("%s: Error while deleting %s\n", tar, p);
}
free (p);
}
}
flush_buffer (the_buffer);
free (archive_dir);
}
int
recursively_delete (path)
char *path;
{
struct stat sbuf;
DIR *dirp;
struct dirent *dp;
char *path_buf;
/* int path_len; */
if (lstat (path, &sbuf) < 0)
return 1;
if (S_ISDIR (sbuf.st_mode))
{
/* path_len=strlen(path); */
dirp = opendir (path);
if (dirp == 0)
return 1;
while (dp = readdir (dirp))
{
if (is_dot_or_dotdot (dp->d_name))
continue;
path_buf = new_name (path, dp->d_name);
if (recursively_delete (path_buf))
{
free (path_buf);
closedir (dirp);
return 1;
}
free (path_buf);
}
closedir (dirp);
if (rmdir (path) < 0)
return 1;
return 0;
}
if (unlink (path) < 0)
return 1;
return 0;
}

View File

@@ -1,57 +0,0 @@
# Makefile for GNU tar on MS-DOS using Turbo C 2.0.
# Copyright (C) 1991 Free Software Foundation, Inc.
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, or (at your option)
# any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
CC = tcc
RM = rm -f
MODEL = m
DEFS = -DNONAMES -DNO_REMOTE -DNO_MTIO -DSTDC_HEADERS -m$(MODEL) -Dmain=_main
LIBS =
DEF_AR_FILE = tar.out
DEFBLOCKING = 20
CFLAGS = -I. $(DEFS) \
-DDEF_AR_FILE="$(DEF_AR_FILE)" \
-DDEFBLOCKING=$(DEFBLOCKING)
LDFLAGS = -m$(MODEL)
OBJ1 = tar.obj create.obj extract.obj buffer.obj getoldopt.obj update.obj gnu.obj mangle.obj
OBJ2 = version.obj list.obj names.obj diffarch.obj port.obj wildmat.obj getopt.obj
OBJ3 = getopt1.obj regex.obj getdate.obj alloca.obj tcexparg.obj msd_dir.obj
OBJS = $(OBJ1) $(OBJ2) $(OBJ3)
all: tar
tar: testpad.h getdate.c $(OBJS)
$(RM) testpad.obj
$(CC) $(LDFLAGS) -etar *.obj $(LIBS)
.c.obj:
$(CC) -c $(CFLAGS) $<
testpad.h: testpad.exe
testpad
testpad.exe: testpad.c
$(CC) $(LDFLAGS) -etestpad testpad.c $(LIBS)
clean:
$(RM) errs *.obj tar testpad testpad.h
distclean: clean
realclean: clean

View File

@@ -1,218 +0,0 @@
/*
* @(#)msd_dir.c 1.4 87/11/06 Public Domain.
*
* A public domain implementation of BSD directory routines for
* MS-DOS. Written by Michael Rendell ({uunet,utai}michael@garfield),
* August 1897
*/
#include <sys/types.h>
#include <sys/stat.h>
#include "msd_dir.h"
#ifndef __TURBOC__
#include <malloc.h>
#endif
#include <string.h>
#include <dos.h>
#ifndef NULL
# define NULL 0
#endif /* NULL */
#ifndef MAXPATHLEN
# define MAXPATHLEN 255
#endif /* MAXPATHLEN */
/* attribute stuff */
#define A_RONLY 0x01
#define A_HIDDEN 0x02
#define A_SYSTEM 0x04
#define A_LABEL 0x08
#define A_DIR 0x10
#define A_ARCHIVE 0x20
/* dos call values */
#define DOSI_FINDF 0x4e
#define DOSI_FINDN 0x4f
#define DOSI_SDTA 0x1a
#define Newisnull(a, t) ((a = (t *) malloc(sizeof(t))) == (t *) NULL)
/* #define ATTRIBUTES (A_DIR | A_HIDDEN | A_SYSTEM) */
#define ATTRIBUTES (A_RONLY | A_SYSTEM | A_DIR)
/* what find first/next calls look use */
typedef struct {
char d_buf[21];
char d_attribute;
unsigned short d_time;
unsigned short d_date;
long d_size;
char d_name[13];
} Dta_buf;
static char *getdirent();
static void mysetdta();
static void free_dircontents();
static Dta_buf dtabuf;
static Dta_buf *dtapnt = &dtabuf;
static union REGS reg, nreg;
#if defined(M_I86LM)
static struct SREGS sreg;
#endif
DIR *
opendir(name)
char *name;
{
struct stat statb;
DIR *dirp;
char c;
char *s;
struct _dircontents *dp;
char nbuf[MAXPATHLEN + 1];
if (stat(name, &statb) < 0 || (statb.st_mode & S_IFMT) != S_IFDIR)
return (DIR *) NULL;
if (Newisnull(dirp, DIR))
return (DIR *) NULL;
if (*name && (c = name[strlen(name) - 1]) != '\\' && c != '/')
(void) strcat(strcpy(nbuf, name), "\\*.*");
else
(void) strcat(strcpy(nbuf, name), "*.*");
dirp->dd_loc = 0;
mysetdta();
dirp->dd_contents = dirp->dd_cp = (struct _dircontents *) NULL;
if ((s = getdirent(nbuf)) == (char *) NULL)
return dirp;
do {
if (Newisnull(dp, struct _dircontents) || (dp->_d_entry =
malloc((unsigned) (strlen(s) + 1))) == (char *) NULL)
{
if (dp)
free((char *) dp);
free_dircontents(dirp->dd_contents);
return (DIR *) NULL;
}
if (dirp->dd_contents)
dirp->dd_cp = dirp->dd_cp->_d_next = dp;
else
dirp->dd_contents = dirp->dd_cp = dp;
(void) strcpy(dp->_d_entry, s);
dp->_d_next = (struct _dircontents *) NULL;
} while ((s = getdirent((char *) NULL)) != (char *) NULL);
dirp->dd_cp = dirp->dd_contents;
return dirp;
}
void
closedir(dirp)
DIR *dirp;
{
free_dircontents(dirp->dd_contents);
free((char *) dirp);
}
struct dirent *
readdir(dirp)
DIR *dirp;
{
static struct dirent dp;
if (dirp->dd_cp == (struct _dircontents *) NULL)
return (struct dirent *) NULL;
dp.d_namlen = dp.d_reclen =
strlen(strcpy(dp.d_name, dirp->dd_cp->_d_entry));
strlwr(dp.d_name); /* JF */
dp.d_ino = 0;
dirp->dd_cp = dirp->dd_cp->_d_next;
dirp->dd_loc++;
return &dp;
}
void
seekdir(dirp, off)
DIR *dirp;
long off;
{
long i = off;
struct _dircontents *dp;
if (off < 0)
return;
for (dp = dirp->dd_contents ; --i >= 0 && dp ; dp = dp->_d_next)
;
dirp->dd_loc = off - (i + 1);
dirp->dd_cp = dp;
}
long
telldir(dirp)
DIR *dirp;
{
return dirp->dd_loc;
}
static void
free_dircontents(dp)
struct _dircontents *dp;
{
struct _dircontents *odp;
while (dp) {
if (dp->_d_entry)
free(dp->_d_entry);
dp = (odp = dp)->_d_next;
free((char *) odp);
}
}
static char *
getdirent(dir)
char *dir;
{
if (dir != (char *) NULL) { /* get first entry */
reg.h.ah = DOSI_FINDF;
reg.h.cl = ATTRIBUTES;
#if defined(M_I86LM)
reg.x.dx = FP_OFF(dir);
sreg.ds = FP_SEG(dir);
#else
reg.x.dx = (unsigned) dir;
#endif
} else { /* get next entry */
reg.h.ah = DOSI_FINDN;
#if defined(M_I86LM)
reg.x.dx = FP_OFF(dtapnt);
sreg.ds = FP_SEG(dtapnt);
#else
reg.x.dx = (unsigned) dtapnt;
#endif
}
#if defined(M_I86LM)
intdosx(&reg, &nreg, &sreg);
#else
intdos(&reg, &nreg);
#endif
if (nreg.x.cflag)
return (char *) NULL;
return dtabuf.d_name;
}
static void
mysetdta()
{
reg.h.ah = DOSI_SDTA;
#if defined(M_I86LM)
reg.x.dx = FP_OFF(dtapnt);
sreg.ds = FP_SEG(dtapnt);
intdosx(&reg, &nreg, &sreg);
#else
reg.x.dx = (int) dtapnt;
intdos(&reg, &nreg);
#endif
}

View File

@@ -1,41 +0,0 @@
/*
* @(#)msd_dir.h 1.4 87/11/06 Public Domain.
*
* A public domain implementation of BSD directory routines for
* MS-DOS. Written by Michael Rendell ({uunet,utai}michael@garfield),
* August 1897
*/
#define rewinddir(dirp) seekdir(dirp, 0L)
#define MAXNAMLEN 12
#ifdef __TURBOC__
typedef int ino_t;
typedef int dev_t;
#endif
struct direct {
ino_t d_ino; /* a bit of a farce */
int d_reclen; /* more farce */
int d_namlen; /* length of d_name */
char d_name[MAXNAMLEN + 1]; /* garentee null termination */
};
struct _dircontents {
char *_d_entry;
struct _dircontents *_d_next;
};
typedef struct _dirdesc {
int dd_id; /* uniquely identify each open directory */
long dd_loc; /* where we are in directory entry is this */
struct _dircontents *dd_contents; /* pointer to contents of dir */
struct _dircontents *dd_cp; /* pointer to current position */
} DIR;
extern DIR *opendir();
extern struct direct *readdir();
extern void seekdir();
extern long telldir();
extern void closedir();

View File

@@ -1,178 +0,0 @@
/* Defines for Sys V style 3-argument open call.
Copyright (C) 1988, 1994, 1995, 1996 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 2, or (at your option) any later
version.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
59 Place - Suite 330, Boston, MA 02111-1307, USA. */
#include "system.h"
#if EMUL_OPEN3
/* open3.h -- #defines for the various flags for the Sys V style 3-argument
open() call. On BSD or System 5, the system already has this in an
include file. This file is needed for V7 and MINIX systems for the
benefit of open3() in port.c, a routine that emulates the 3-argument call
using system calls available on V7/MINIX.
Written 1987-06-10 by Richard Todd.
The names have been changed by John Gilmore, 1987-07-31, since Richard
called it "bsdopen", and really this change was introduced in AT&T Unix
systems before BSD picked it up. */
/*-----------------------------------------------------------------------.
| open3 -- routine to emulate the 3-argument open system. |
| |
| open3 (path, flag, mode); |
| |
| Attempts to open the file specified by the given pathname. The |
| following flag bits specify options to the routine. Needless to say, |
| you should only specify one of the first three. Function returns file |
| descriptor if successful, -1 and errno if not. |
`-----------------------------------------------------------------------*/
/* The routine obeys the following mode arguments:
O_RDONLY file open for read only
O_WRONLY file open for write only
O_RDWR file open for both read & write
O_CREAT file is created with specified mode if it needs to be
O_TRUNC if file exists, it is truncated to 0 bytes
O_EXCL used with O_CREAT--routine returns error if file exists */
/* Call that if present in most modern Unix systems. This version attempts
to support all the flag bits except for O_NDELAY and O_APPEND, which are
silently ignored. The emulation is not as efficient as the real thing
(at worst, 4 system calls instead of one), but there's not much I can do
about that. */
/* Array to give arguments to access for various modes FIXME, this table
depends on the specific integer values of O_*, and also contains
integers (args to 'access') that should be #define's. */
static int modes[] =
{
04, /* O_RDONLY */
02, /* O_WRONLY */
06, /* O_RDWR */
06, /* invalid, just cope: O_WRONLY+O_RDWR */
};
/* Shut off the automatic emulation of open(), we'll need it. */
#undef open
int
open3 (char *path, int flags, int mode)
{
int exists = 1;
int call_creat = 0;
/* We actually do the work by calling the open() or creat() system
call, depending on the flags. Call_creat is true if we will use
creat(), false if we will use open(). */
/* See if the file exists and is accessible in the requested mode.
Strictly speaking we shouldn't be using access, since access checks
against real uid, and the open call should check against euid. Most
cases real uid == euid, so it won't matter. FIXME. FIXME, the
construction "flags & 3" and the modes table depends on the specific
integer values of the O_* #define's. Foo! */
if (access (path, modes[flags & 3]) < 0)
{
if (errno == ENOENT)
{
/* The file does not exist. */
exists = 0;
}
else
{
/* Probably permission violation. */
if (flags & O_EXCL)
{
/* Oops, the file exists, we didn't want it. No matter
what the error, claim EEXIST. */
errno = EEXIST; /* FIXME: errno should be read-only */
}
return -1;
}
}
/* If we have the O_CREAT bit set, check for O_EXCL. */
if (flags & O_CREAT)
{
if ((flags & O_EXCL) && exists)
{
/* Oops, the file exists and we didn't want it to. */
errno = EEXIST; /* FIXME: errno should be read-only */
return -1;
}
/* If the file doesn't exist, be sure to call creat() so that it
will be created with the proper mode. */
if (!exists)
call_creat = 1;
}
else
{
/* If O_CREAT isn't set and the file doesn't exist, error. */
if (!exists)
{
errno = ENOENT; /* FIXME: errno should be read-only */
return -1;
}
}
/* If the O_TRUNC flag is set and the file exists, we want to call
creat() anyway, since creat() guarantees that the file will be
truncated and open()-for-writing doesn't. (If the file doesn't
exist, we're calling creat() anyway and the file will be created
with zero length.) */
if ((flags & O_TRUNC) && exists)
call_creat = 1;
/* Actually do the call. */
if (call_creat)
/* Call creat. May have to close and reopen the file if we want
O_RDONLY or O_RDWR access -- creat() only gives O_WRONLY. */
{
int fd = creat (path, mode);
if (fd < 0 || (flags & O_WRONLY))
return fd;
if (close (fd) < 0)
return -1;
/* Fall out to reopen the file we've created. */
}
/* Calling old open, we strip most of the new flags just in case. */
return open (path, flags & (O_RDONLY | O_WRONLY | O_RDWR | O_BINARY));
}
#endif /* EMUL_OPEN3 */

View File

@@ -1,69 +0,0 @@
/* Defines for Sys V style 3-argument open call.
Copyright (C) 1988 Free Software Foundation
This file is part of GNU Tar.
GNU Tar is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Tar is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Tar; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
/*
* @(#)open3.h 1.4 87/11/11
*
* open3.h -- #defines for the various flags for the Sys V style 3-argument
* open() call. On BSD or System 5, the system already has this in an
* include file. This file is needed for V7 and MINIX systems for the
* benefit of open3() in port.c, a routine that emulates the 3-argument
* call using system calls available on V7/MINIX.
*
* This file is needed by PD tar even if we aren't using the
* emulator, since the #defines for O_WRONLY, etc. are used in
* a couple of places besides the open() calls, (e.g. in the assignment
* to openflag in extract.c). We just #include this rather than
* #ifdef them out.
*
* Written 6/10/87 by rmtodd@uokmax (Richard Todd).
*
* The names have been changed by John Gilmore, 31 July 1987, since
* Richard called it "bsdopen", and really this change was introduced in
* AT&T Unix systems before BSD picked it up.
*/
/* Only one of the next three should be specified */
#define O_RDONLY 0 /* only allow read */
#define O_WRONLY 1 /* only allow write */
#define O_RDWR 2 /* both are allowed */
/* The rest of these can be OR-ed in to the above. */
/*
* O_NDELAY isn't implemented by the emulator. It's only useful (to tar) on
* systems that have named pipes anyway; it prevents tar's hanging by
* opening a named pipe. We #ifndef it because some systems already have
* it defined.
*/
#ifndef O_NDELAY
#define O_NDELAY 4 /* don't block on opening devices that would
* block on open -- ignored by emulator. */
#endif
#define O_CREAT 8 /* create file if needed */
#define O_EXCL 16 /* file cannot already exist */
#define O_TRUNC 32 /* truncate file on open */
#define O_APPEND 64 /* always write at end of file -- ignored by emul */
#ifdef EMUL_OPEN3
/*
* make emulation transparent to rest of file -- redirect all open() calls
* to our routine
*/
#define open open3
#endif

1256
src/port.c

File diff suppressed because it is too large Load Diff

View File

@@ -1,215 +0,0 @@
/* Portability declarations. Requires sys/types.h.
Copyright (C) 1988, 1992 Free Software Foundation
This file is part of GNU Tar.
GNU Tar is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Tar is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Tar; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
/* AIX requires this to be the first thing in the file. */
#ifdef __GNUC__
#define alloca __builtin_alloca
#else /* not __GNUC__ */
#if HAVE_ALLOCA_H
#include <alloca.h>
#else /* not HAVE_ALLOCA_H */
#ifdef _AIX
#pragma alloca
#else /* not _AIX */
char *alloca ();
#endif /* not _AIX */
#endif /* not HAVE_ALLOCA_H */
#endif /* not __GNUC__ */
#include "pathmax.h"
#ifdef _POSIX_VERSION
#include <sys/wait.h>
#else /* !_POSIX_VERSION */
#define WIFSTOPPED(w) (((w) & 0xff) == 0x7f)
#define WIFSIGNALED(w) (((w) & 0xff) != 0x7f && ((w) & 0xff) != 0)
#define WIFEXITED(w) (((w) & 0xff) == 0)
#define WSTOPSIG(w) (((w) >> 8) & 0xff)
#define WTERMSIG(w) ((w) & 0x7f)
#define WEXITSTATUS(w) (((w) >> 8) & 0xff)
#endif /* _POSIX_VERSION */
/* nonstandard */
#ifndef WIFCOREDUMPED
#define WIFCOREDUMPED(w) (((w) & 0x80) != 0)
#endif
#ifdef __MSDOS__
/* missing things from sys/stat.h */
#define S_ISUID 0
#define S_ISGID 0
#define S_ISVTX 0
/* device stuff */
#define makedev(ma, mi) ((ma << 8) | mi)
#define major(dev) (dev)
#define minor(dev) (dev)
typedef long off_t;
#endif /* __MSDOS__ */
#if defined(__STDC__) || defined(__TURBOC__)
#define PTR void *
#else
#define PTR char *
#define const
#endif
/* Since major is a function on SVR4, we can't just use `ifndef major'. */
#ifdef major /* Might be defined in sys/types.h. */
#define HAVE_MAJOR
#endif
#if !defined(HAVE_MAJOR) && defined(MAJOR_IN_MKDEV)
#include <sys/mkdev.h>
#define HAVE_MAJOR
#endif
#if !defined(HAVE_MAJOR) && defined(MAJOR_IN_SYSMACROS)
#include <sys/sysmacros.h>
#define HAVE_MAJOR
#endif
#ifndef HAVE_MAJOR
#define major(dev) (((dev) >> 8) & 0xff)
#define minor(dev) ((dev) & 0xff)
#define makedev(maj, min) (((maj) << 8) | (min))
#endif
#undef HAVE_MAJOR
#if defined(STDC_HEADERS) || defined(HAVE_STRING_H)
#include <string.h>
#if !defined(__MSDOS__) && !defined(STDC_HEADERS)
#include <memory.h>
#endif
#ifdef index
#undef index
#endif
#ifdef rindex
#undef rindex
#endif
#define index strchr
#define rindex strrchr
#define bcopy(s, d, n) memcpy(d, s, n)
#define bzero(s, n) memset(s, 0, n)
#define bcmp memcmp
#else
#include <strings.h>
#endif
#if defined(STDC_HEADERS)
#include <stdlib.h>
#else
char *malloc (), *realloc ();
char *getenv ();
#endif
#ifndef _POSIX_VERSION
#ifdef __MSDOS__
#include <io.h>
#else /* !__MSDOS__ */
off_t lseek ();
#endif /* !__MSDOS__ */
char *getcwd ();
#endif /* !_POSIX_VERSION */
#ifndef NULL
#define NULL 0
#endif
#ifndef O_BINARY
#define O_BINARY 0
#endif
#ifndef O_CREAT
#define O_CREAT 0
#endif
#ifndef O_NDELAY
#define O_NDELAY 0
#endif
#ifndef O_RDONLY
#define O_RDONLY 0
#endif
#ifndef O_RDWR
#define O_RDWR 2
#endif
#include <sys/stat.h>
#ifndef S_ISREG /* Doesn't have POSIX.1 stat stuff. */
#define mode_t unsigned short
#endif
#if !defined(S_ISBLK) && defined(S_IFBLK)
#define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK)
#endif
#if !defined(S_ISCHR) && defined(S_IFCHR)
#define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR)
#endif
#if !defined(S_ISDIR) && defined(S_IFDIR)
#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
#endif
#if !defined(S_ISREG) && defined(S_IFREG)
#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
#endif
#if !defined(S_ISFIFO) && defined(S_IFIFO)
#define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO)
#define mkfifo(path, mode) (mknod ((path), (mode) | S_IFIFO, 0))
#endif
#if !defined(S_ISLNK) && defined(S_IFLNK)
#define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)
#endif
#if !defined(S_ISSOCK) && defined(S_IFSOCK)
#define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK)
#endif
#if !defined(S_ISMPB) && defined(S_IFMPB) /* V7 */
#define S_ISMPB(m) (((m) & S_IFMT) == S_IFMPB)
#define S_ISMPC(m) (((m) & S_IFMT) == S_IFMPC)
#endif
#if !defined(S_ISNWK) && defined(S_IFNWK) /* HP/UX */
#define S_ISNWK(m) (((m) & S_IFMT) == S_IFNWK)
#endif
#if !defined(S_ISCTG) && defined(S_IFCTG) /* contiguous file */
#define S_ISCTG(m) (((m) & S_IFMT) == S_IFCTG)
#endif
#if !defined(S_ISVTX)
#define S_ISVTX 0001000
#endif
#ifdef __MSDOS__
#include "msd_dir.h"
#define NLENGTH(direct) ((direct)->d_namlen)
#else /* not __MSDOS__ */
#if defined(DIRENT) || defined(_POSIX_VERSION)
#include <dirent.h>
#define NLENGTH(direct) (strlen((direct)->d_name))
#else /* not (DIRENT or _POSIX_VERSION) */
#define dirent direct
#define NLENGTH(direct) ((direct)->d_namlen)
#ifdef SYSNDIR
#include <sys/ndir.h>
#endif /* SYSNDIR */
#ifdef SYSDIR
#include <sys/dir.h>
#endif /* SYSDIR */
#ifdef NDIR
#include <ndir.h>
#endif /* NDIR */
#endif /* DIRENT or _POSIX_VERSION */
#endif /* not __MSDOS__ */

View File

@@ -1,22 +0,0 @@
/* Read files directly from the fast file system
Copyright (C) 1992 Free Software Foundation
This file is part of GNU Tar.
GNU Tar is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2, or (at
your option) any later version.
GNU Tar is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Tar; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */

View File

@@ -1,240 +0,0 @@
/* tcexparg.c - Unix-style command line wildcards for Turbo C 2.0
This file is in the public domain.
Compile your main program with -Dmain=_main and link with this file.
After that, it is just as if the operating system had expanded the
arguments, except that they are not sorted. The program name and all
arguments that are expanded from wildcards are lowercased.
Syntax for wildcards:
* Matches zero or more of any character (except a '.' at
the beginning of a name).
? Matches any single character.
[r3z] Matches 'r', '3', or 'z'.
[a-d] Matches a single character in the range 'a' through 'd'.
[!a-d] Matches any single character except a character in the
range 'a' through 'd'.
The period between the filename root and its extension need not be
given explicitly. Thus, the pattern `a*e' will match 'abacus.exe'
and 'axyz.e' as well as 'apple'. Comparisons are not case sensitive.
Authors:
The expargs code is a modification of wildcard expansion code
written for Turbo C 1.0 by
Richard Hargrove
Texas Instruments, Inc.
P.O. Box 869305, m/s 8473
Plano, Texas 75086
214/575-4128
and posted to USENET in September, 1987.
The wild_match code was written by Rich Salz, rsalz@bbn.com,
posted to net.sources in November, 1986.
The code connecting the two is by Mike Slomin, bellcore!lcuxa!mike2,
posted to comp.sys.ibm.pc in November, 1988.
Major performance enhancements and bug fixes, and source cleanup,
by David MacKenzie, djm@gnu.ai.mit.edu. */
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <dos.h>
#include <dir.h>
/* Number of new arguments to allocate space for at a time. */
#define ARGS_INCREMENT 10
/* The name this program was run with, for error messages. */
static char *program_name;
static char **grow_argv (char **new_argv, int new_argc);
static void fatal_error (const char *message);
int wild_match (char *string, char *pattern);
char *basename (char *path);
char **expargs (int *, char **);
#ifdef main
#undef main
#endif
int
main (int argc, char **argv, char **envp)
{
argv = expargs (&argc, argv);
return _main (argc, argv, envp);
}
char **
expargs (int *pargc, char **argv)
{
char path[MAXPATH + 1];
char **new_argv;
struct ffblk block;
char *path_base;
char *arg_base;
int argind;
int new_argc;
int path_length;
int matched;
program_name = argv[0];
if (program_name && *program_name)
strlwr (program_name);
new_argv = grow_argv (NULL, 0);
new_argv[0] = argv[0];
new_argc = 1;
for (argind = 1; argind < *pargc; ++argind)
{
matched = 0;
if (strpbrk (argv[argind], "?*[") != NULL)
{
strncpy (path, argv[argind], MAXPATH - 3);
path_base = basename (path);
strcpy (path_base, "*.*");
arg_base = argv[argind] + (path_base - path);
if (!findfirst (path, &block, FA_DIREC))
{
strlwr (path);
do
{
/* Only match "." and ".." explicitly. */
if (*block.ff_name == '.' && *arg_base != '.')
continue;
path_length = stpcpy (path_base, block.ff_name) - path + 1;
strlwr (path_base);
if (wild_match (path, argv[argind]))
{
matched = 1;
new_argv[new_argc] = (char *) malloc (path_length);
if (new_argv[new_argc] == NULL)
fatal_error ("memory exhausted");
strcpy (new_argv[new_argc++], path);
new_argv = grow_argv (new_argv, new_argc);
}
} while (!findnext (&block));
}
}
if (matched == 0)
new_argv[new_argc++] = argv[argind];
new_argv = grow_argv (new_argv, new_argc);
}
*pargc = new_argc;
new_argv[new_argc] = NULL;
return &new_argv[0];
}
/* Return a pointer to the last element of PATH. */
char *
basename (char *path)
{
char *tail;
for (tail = path; *path; ++path)
if (*path == ':' || *path == '\\')
tail = path + 1;
return tail;
}
static char **
grow_argv (char **new_argv, int new_argc)
{
if (new_argc % ARGS_INCREMENT == 0)
{
new_argv = (char **) realloc
(new_argv, sizeof (char *) * (new_argc + ARGS_INCREMENT));
if (new_argv == NULL)
fatal_error ("memory exhausted");
}
return new_argv;
}
static void
fatal_error (const char *message)
{
putc ('\n', stderr);
if (program_name && *program_name)
{
fputs (program_name, stderr);
fputs (": ", stderr);
}
fputs (message, stderr);
putc ('\n', stderr);
exit (1);
}
/* Shell-style pattern matching for ?, \, [], and * characters.
I'm putting this replacement in the public domain.
Written by Rich $alz, mirror!rs, Wed Nov 26 19:03:17 EST 1986. */
/* The character that inverts a character class; '!' or '^'. */
#define INVERT '!'
static int star (char *string, char *pattern);
/* Return nonzero if `string' matches Unix-style wildcard pattern
`pattern'; zero if not. */
int
wild_match (char *string, char *pattern)
{
int prev; /* Previous character in character class. */
int matched; /* If 1, character class has been matched. */
int reverse; /* If 1, character class is inverted. */
for (; *pattern; string++, pattern++)
switch (*pattern)
{
case '\\':
/* Literal match with following character; fall through. */
pattern++;
default:
if (*string != *pattern)
return 0;
continue;
case '?':
/* Match anything. */
if (*string == '\0')
return 0;
continue;
case '*':
/* Trailing star matches everything. */
return *++pattern ? star (string, pattern) : 1;
case '[':
/* Check for inverse character class. */
reverse = pattern[1] == INVERT;
if (reverse)
pattern++;
for (prev = 256, matched = 0; *++pattern && *pattern != ']';
prev = *pattern)
if (*pattern == '-'
? *string <= *++pattern && *string >= prev
: *string == *pattern)
matched = 1;
if (matched == reverse)
return 0;
continue;
}
return *string == '\0';
}
static int
star (char *string, char *pattern)
{
while (wild_match (string, pattern) == 0)
if (*++string == '\0')
return 0;
return 1;
}

View File

@@ -1,67 +0,0 @@
/* Find out if we need the pad field in the header for this machine
Copyright (C) 1991 Free Software Foundation
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2, or (at
your option) any later version.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <stdio.h>
struct inc
{
char a[20];
char b[20];
};
struct test1
{
char a;
struct inc in[5];
};
struct test2
{
char a;
char b;
struct inc in[5];
};
void
main ()
{
struct test1 t1;
struct test2 t2;
int t1diff, t2diff;
FILE *fp = fopen ("testpad.h", "w");
if (fp == 0)
{
fprintf (stderr, "testpad: cannot open ");
fflush (stderr);
perror ("testpad.h");
exit (1);
}
t1diff = (char *) &t1.in[0] - (char *) &t1;
t2diff = (char *) &t2.in[0] - (char *) &t2;
if (t2diff == t1diff + 1)
fprintf (fp, "#define NEEDPAD\n");
else if (t1diff != t2diff)
fprintf (stderr, "Cannot determine padding for tar struct, \n\
will try with none.\n");
fclose (fp);
exit (0);
}