original openbsd diff
This commit is contained in:
parent
4c0a9db684
commit
e68d8eb1ff
7
commands/diff/Makefile
Normal file
7
commands/diff/Makefile
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
# $OpenBSD: Makefile,v 1.3 2007/05/29 18:24:56 ray Exp $
|
||||||
|
|
||||||
|
PROG= diff
|
||||||
|
SRCS= diff.c diffdir.c diffreg.c xmalloc.c
|
||||||
|
COPTS+= -Wall
|
||||||
|
|
||||||
|
.include <bsd.prog.mk>
|
506
commands/diff/diff.1
Normal file
506
commands/diff/diff.1
Normal file
@ -0,0 +1,506 @@
|
|||||||
|
.\" $OpenBSD: diff.1,v 1.37 2010/02/21 15:24:01 sobrado Exp $
|
||||||
|
.\"
|
||||||
|
.\" Copyright (c) 1980, 1990, 1993
|
||||||
|
.\" The Regents of the University of California. All rights reserved.
|
||||||
|
.\"
|
||||||
|
.\" Redistribution and use in source and binary forms, with or without
|
||||||
|
.\" modification, are permitted provided that the following conditions
|
||||||
|
.\" are met:
|
||||||
|
.\" 1. Redistributions of source code must retain the above copyright
|
||||||
|
.\" notice, this list of conditions and the following disclaimer.
|
||||||
|
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
.\" notice, this list of conditions and the following disclaimer in the
|
||||||
|
.\" documentation and/or other materials provided with the distribution.
|
||||||
|
.\" 3. Neither the name of the University nor the names of its contributors
|
||||||
|
.\" may be used to endorse or promote products derived from this software
|
||||||
|
.\" without specific prior written permission.
|
||||||
|
.\"
|
||||||
|
.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||||
|
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
.\" SUCH DAMAGE.
|
||||||
|
.\"
|
||||||
|
.\" @(#)diff.1 8.1 (Berkeley) 6/30/93
|
||||||
|
.\"
|
||||||
|
.Dd $Mdocdate: February 21 2010 $
|
||||||
|
.Dt DIFF 1
|
||||||
|
.Os
|
||||||
|
.Sh NAME
|
||||||
|
.Nm diff
|
||||||
|
.Nd differential file and directory comparator
|
||||||
|
.Sh SYNOPSIS
|
||||||
|
.Nm diff
|
||||||
|
.Op Fl abdilpTtw
|
||||||
|
.Oo
|
||||||
|
.Fl c | e | f |
|
||||||
|
.Fl n | q | u
|
||||||
|
.Oc
|
||||||
|
.Op Fl I Ar pattern
|
||||||
|
.Op Fl L Ar label
|
||||||
|
.Ar file1 file2
|
||||||
|
.Nm diff
|
||||||
|
.Op Fl abdilpTtw
|
||||||
|
.Op Fl I Ar pattern
|
||||||
|
.Op Fl L Ar label
|
||||||
|
.Fl C Ar number
|
||||||
|
.Ar file1 file2
|
||||||
|
.Nm diff
|
||||||
|
.Op Fl abdiltw
|
||||||
|
.Op Fl I Ar pattern
|
||||||
|
.Fl D Ar string
|
||||||
|
.Ar file1 file2
|
||||||
|
.Nm diff
|
||||||
|
.Op Fl abdilpTtw
|
||||||
|
.Op Fl I Ar pattern
|
||||||
|
.Op Fl L Ar label
|
||||||
|
.Fl U Ar number
|
||||||
|
.Ar file1 file2
|
||||||
|
.Nm diff
|
||||||
|
.Op Fl abdilNPprsTtw
|
||||||
|
.Oo
|
||||||
|
.Fl c | e | f |
|
||||||
|
.Fl n | q | u
|
||||||
|
.Oc
|
||||||
|
.Op Fl I Ar pattern
|
||||||
|
.Bk -words
|
||||||
|
.Op Fl L Ar label
|
||||||
|
.Op Fl S Ar name
|
||||||
|
.Op Fl X Ar file
|
||||||
|
.Op Fl x Ar pattern
|
||||||
|
.Ek
|
||||||
|
.Ar dir1 dir2
|
||||||
|
.Sh DESCRIPTION
|
||||||
|
The
|
||||||
|
.Nm
|
||||||
|
utility compares the contents of
|
||||||
|
.Ar file1
|
||||||
|
and
|
||||||
|
.Ar file2
|
||||||
|
and writes to the standard output the list of changes necessary to
|
||||||
|
convert one file into the other.
|
||||||
|
No output is produced if the files are identical.
|
||||||
|
.Pp
|
||||||
|
Output options (mutually exclusive):
|
||||||
|
.Bl -tag -width Ds
|
||||||
|
.It Fl C Ar number
|
||||||
|
Like
|
||||||
|
.Fl c
|
||||||
|
but produces a diff with
|
||||||
|
.Ar number
|
||||||
|
lines of context.
|
||||||
|
.It Fl c
|
||||||
|
Produces a diff with 3 lines of context.
|
||||||
|
With
|
||||||
|
.Fl c
|
||||||
|
the output format is modified slightly:
|
||||||
|
the output begins with identification of the files involved and
|
||||||
|
their creation dates and then each change is separated
|
||||||
|
by a line with fifteen
|
||||||
|
.Li * Ns 's .
|
||||||
|
The lines removed from
|
||||||
|
.Ar file1
|
||||||
|
are marked with
|
||||||
|
.Sq \&-\ \& ;
|
||||||
|
those added to
|
||||||
|
.Ar file2
|
||||||
|
are marked
|
||||||
|
.Sq \+\ \& .
|
||||||
|
Lines which are changed from one file to the other are marked in
|
||||||
|
both files with
|
||||||
|
.Sq !\ \& .
|
||||||
|
Changes which lie within 3 lines of each other are grouped together on
|
||||||
|
output.
|
||||||
|
.It Fl D Ar string
|
||||||
|
Creates a merged version of
|
||||||
|
.Ar file1
|
||||||
|
and
|
||||||
|
.Ar file2
|
||||||
|
on the standard output, with C preprocessor controls included so that
|
||||||
|
a compilation of the result without defining
|
||||||
|
.Ar string
|
||||||
|
is equivalent to compiling
|
||||||
|
.Ar file1 ,
|
||||||
|
while defining
|
||||||
|
.Ar string
|
||||||
|
will yield
|
||||||
|
.Ar file2 .
|
||||||
|
.It Fl e
|
||||||
|
Produces output in a form suitable as input for the editor utility,
|
||||||
|
.Xr ed 1 ,
|
||||||
|
which can then be used to convert file1 into file2.
|
||||||
|
.Pp
|
||||||
|
Extra commands are added to the output when comparing directories with
|
||||||
|
.Fl e ,
|
||||||
|
so that the result is a
|
||||||
|
.Xr sh 1
|
||||||
|
script for converting text files which are common to the two directories
|
||||||
|
from their state in
|
||||||
|
.Ar dir1
|
||||||
|
to their state in
|
||||||
|
.Ar dir2 .
|
||||||
|
.It Fl f
|
||||||
|
Identical output to that of the
|
||||||
|
.Fl e
|
||||||
|
flag, but in reverse order.
|
||||||
|
It cannot be digested by
|
||||||
|
.Xr ed 1 .
|
||||||
|
.It Fl n
|
||||||
|
Produces a script similar to that of
|
||||||
|
.Fl e ,
|
||||||
|
but in the opposite order and with a count of changed lines on each
|
||||||
|
insert or delete command.
|
||||||
|
This is the form used by
|
||||||
|
.Xr rcsdiff 1 .
|
||||||
|
.It Fl q
|
||||||
|
Just print a line when the files differ.
|
||||||
|
Does not output a list of changes.
|
||||||
|
.It Fl U Ar number
|
||||||
|
Like
|
||||||
|
.Fl u
|
||||||
|
but produces a diff with
|
||||||
|
.Ar number
|
||||||
|
lines of context.
|
||||||
|
.It Fl u
|
||||||
|
Produces a
|
||||||
|
.Em unified
|
||||||
|
diff with 3 lines of context.
|
||||||
|
A unified diff is similar to the context diff produced by the
|
||||||
|
.Fl c
|
||||||
|
option.
|
||||||
|
However, unlike with
|
||||||
|
.Fl c ,
|
||||||
|
all lines to be changed (added and/or removed) are present in
|
||||||
|
a single section.
|
||||||
|
.El
|
||||||
|
.Pp
|
||||||
|
Comparison options:
|
||||||
|
.Bl -tag -width Ds
|
||||||
|
.It Fl a
|
||||||
|
Treat all files as
|
||||||
|
.Tn ASCII
|
||||||
|
text.
|
||||||
|
Normally
|
||||||
|
.Nm
|
||||||
|
will simply print
|
||||||
|
.Dq Binary files ... differ
|
||||||
|
if files contain binary characters.
|
||||||
|
Use of this option forces
|
||||||
|
.Nm
|
||||||
|
to produce a diff.
|
||||||
|
.It Fl b
|
||||||
|
Causes trailing blanks (spaces and tabs) to be ignored, and other
|
||||||
|
strings of blanks to compare equal.
|
||||||
|
.It Fl d
|
||||||
|
Try very hard to produce a diff as small as possible.
|
||||||
|
This may consume a lot of processing power and memory when processing
|
||||||
|
large files with many changes.
|
||||||
|
.It Fl I Ar pattern
|
||||||
|
Ignores changes, insertions, and deletions whose lines match the
|
||||||
|
extended regular expression
|
||||||
|
.Ar pattern .
|
||||||
|
Multiple
|
||||||
|
.Fl I
|
||||||
|
patterns may be specified.
|
||||||
|
All lines in the change must match some pattern for the change to be
|
||||||
|
ignored.
|
||||||
|
See
|
||||||
|
.Xr re_format 7
|
||||||
|
for more information on regular expression patterns.
|
||||||
|
.It Fl i
|
||||||
|
Ignores the case of letters.
|
||||||
|
E.g.,
|
||||||
|
.Dq A
|
||||||
|
will compare equal to
|
||||||
|
.Dq a .
|
||||||
|
.It Fl L Ar label
|
||||||
|
Print
|
||||||
|
.Ar label
|
||||||
|
instead of the first (and second, if this option is specified twice)
|
||||||
|
file name and time in the context or unified diff header.
|
||||||
|
.It Fl l
|
||||||
|
Long output format; each text file
|
||||||
|
.Nm diff Ns \'d
|
||||||
|
is piped through
|
||||||
|
.Xr pr 1
|
||||||
|
to paginate it;
|
||||||
|
other differences are remembered and summarized
|
||||||
|
after all text file differences are reported.
|
||||||
|
.It Fl p
|
||||||
|
With unified and context diffs, show with each change
|
||||||
|
the first 40 characters of the last line before the context beginning
|
||||||
|
with a letter, an underscore or a dollar sign.
|
||||||
|
For C source code following standard layout conventions, this will
|
||||||
|
show the prototype of the function the change applies to.
|
||||||
|
.It Fl T
|
||||||
|
Print a tab rather than a space before the rest of the line for the
|
||||||
|
normal, context or unified output formats.
|
||||||
|
This makes the alignment of tabs in the line consistent.
|
||||||
|
.It Fl t
|
||||||
|
Will expand tabs in output lines.
|
||||||
|
Normal or
|
||||||
|
.Fl c
|
||||||
|
output adds character(s) to the front of each line which may screw up
|
||||||
|
the indentation of the original source lines and make the output listing
|
||||||
|
difficult to interpret.
|
||||||
|
This option will preserve the original source's indentation.
|
||||||
|
.It Fl w
|
||||||
|
Is similar to
|
||||||
|
.Fl b
|
||||||
|
but causes whitespace (blanks and tabs) to be totally ignored.
|
||||||
|
E.g.,
|
||||||
|
.Dq if (\ \&a == b \&)
|
||||||
|
will compare equal to
|
||||||
|
.Dq if(a==b) .
|
||||||
|
.El
|
||||||
|
.Pp
|
||||||
|
Directory comparison options:
|
||||||
|
.Bl -tag -width Ds
|
||||||
|
.It Fl N
|
||||||
|
If a file is found in only one directory, act as if it was found in the
|
||||||
|
other directory too but was of zero size.
|
||||||
|
.It Fl P
|
||||||
|
If a file is found only in
|
||||||
|
.Ar dir2 ,
|
||||||
|
act as if it was found in
|
||||||
|
.Ar dir1
|
||||||
|
too but was of zero size.
|
||||||
|
.It Fl r
|
||||||
|
Causes application of
|
||||||
|
.Nm
|
||||||
|
recursively to common subdirectories encountered.
|
||||||
|
.It Fl S Ar name
|
||||||
|
Re-starts a directory
|
||||||
|
.Nm
|
||||||
|
in the middle, beginning with file
|
||||||
|
.Ar name .
|
||||||
|
.It Fl s
|
||||||
|
Causes
|
||||||
|
.Nm
|
||||||
|
to report files which are the same, which are otherwise not mentioned.
|
||||||
|
.It Fl X Ar file
|
||||||
|
Exclude files and subdirectories from comparison whose basenames match
|
||||||
|
lines in
|
||||||
|
.Ar file .
|
||||||
|
Multiple
|
||||||
|
.Fl X
|
||||||
|
options may be specified.
|
||||||
|
.It Fl x Ar pattern
|
||||||
|
Exclude files and subdirectories from comparison whose basenames match
|
||||||
|
.Ar pattern .
|
||||||
|
Patterns are matched using shell-style globbing via
|
||||||
|
.Xr fnmatch 3 .
|
||||||
|
Multiple
|
||||||
|
.Fl x
|
||||||
|
options may be specified.
|
||||||
|
.El
|
||||||
|
.Pp
|
||||||
|
If both arguments are directories,
|
||||||
|
.Nm
|
||||||
|
sorts the contents of the directories by name, and then runs the
|
||||||
|
regular file
|
||||||
|
.Nm
|
||||||
|
algorithm, producing a change list,
|
||||||
|
on text files which are different.
|
||||||
|
Binary files which differ,
|
||||||
|
common subdirectories, and files which appear in only one directory
|
||||||
|
are described as such.
|
||||||
|
In directory mode only regular files and directories are compared.
|
||||||
|
If a non-regular file such as a device special file or
|
||||||
|
.Tn FIFO
|
||||||
|
is encountered, a diagnostic message is printed.
|
||||||
|
.Pp
|
||||||
|
If only one of
|
||||||
|
.Ar file1
|
||||||
|
and
|
||||||
|
.Ar file2
|
||||||
|
is a directory,
|
||||||
|
.Nm
|
||||||
|
is applied to the non-directory file and the file contained in
|
||||||
|
the directory file with a filename that is the same as the
|
||||||
|
last component of the non-directory file.
|
||||||
|
.Pp
|
||||||
|
If either
|
||||||
|
.Ar file1
|
||||||
|
or
|
||||||
|
.Ar file2
|
||||||
|
is
|
||||||
|
.Sq Fl ,
|
||||||
|
the standard input is
|
||||||
|
used in its place.
|
||||||
|
.Ss Output Style
|
||||||
|
The default (without
|
||||||
|
.Fl e ,
|
||||||
|
.Fl c ,
|
||||||
|
or
|
||||||
|
.Fl n
|
||||||
|
.\" -C
|
||||||
|
options)
|
||||||
|
output contains lines of these forms, where
|
||||||
|
.Va XX , YY , ZZ , QQ
|
||||||
|
are line numbers respective of file order.
|
||||||
|
.Pp
|
||||||
|
.Bl -tag -width "XX,YYcZZ,QQ" -compact
|
||||||
|
.It Li XX Ns Ic a Ns Li YY
|
||||||
|
At (the end of) line
|
||||||
|
.Va XX
|
||||||
|
of
|
||||||
|
.Ar file1 ,
|
||||||
|
append the contents
|
||||||
|
of line
|
||||||
|
.Va YY
|
||||||
|
of
|
||||||
|
.Ar file2
|
||||||
|
to make them equal.
|
||||||
|
.It Li XX Ns Ic a Ns Li YY,ZZ
|
||||||
|
Same as above, but append the range of lines,
|
||||||
|
.Va YY
|
||||||
|
through
|
||||||
|
.Va ZZ
|
||||||
|
of
|
||||||
|
.Ar file2
|
||||||
|
to line
|
||||||
|
.Va XX
|
||||||
|
of file1.
|
||||||
|
.It Li XX Ns Ic d Ns Li YY
|
||||||
|
At line
|
||||||
|
.Va XX
|
||||||
|
delete
|
||||||
|
the line.
|
||||||
|
The value
|
||||||
|
.Va YY
|
||||||
|
tells to which line the change would bring
|
||||||
|
.Ar file1
|
||||||
|
in line with
|
||||||
|
.Ar file1 .
|
||||||
|
.It Li XX,YY Ns Ic d Ns Li ZZ
|
||||||
|
Delete the range of lines
|
||||||
|
.Va XX
|
||||||
|
through
|
||||||
|
.Va YY
|
||||||
|
in
|
||||||
|
.Ar file1 .
|
||||||
|
.It Li XX Ns Ic c Ns Li YY
|
||||||
|
Change the line
|
||||||
|
.Va XX
|
||||||
|
in
|
||||||
|
.Ar file1
|
||||||
|
to the line
|
||||||
|
.Va YY
|
||||||
|
in
|
||||||
|
.Ar file2 .
|
||||||
|
.It Li XX,YY Ns Ic c Ns Li ZZ
|
||||||
|
Replace the range of specified lines with the line
|
||||||
|
.Va ZZ .
|
||||||
|
.It Li XX,YY Ns Ic c Ns Li ZZ,QQ
|
||||||
|
Replace the range
|
||||||
|
.Va XX , Ns Va YY
|
||||||
|
from
|
||||||
|
.Ar file1
|
||||||
|
with the range
|
||||||
|
.Va ZZ , Ns Va QQ
|
||||||
|
from
|
||||||
|
.Ar file2 .
|
||||||
|
.El
|
||||||
|
.Pp
|
||||||
|
These lines resemble
|
||||||
|
.Xr ed 1
|
||||||
|
subcommands to convert
|
||||||
|
.Ar file1
|
||||||
|
into
|
||||||
|
.Ar file2 .
|
||||||
|
The line numbers before the action letters pertain to
|
||||||
|
.Ar file1 ;
|
||||||
|
those after pertain to
|
||||||
|
.Ar file2 .
|
||||||
|
Thus, by exchanging
|
||||||
|
.Ic a
|
||||||
|
for
|
||||||
|
.Ic d
|
||||||
|
and reading the line in reverse order, one can also
|
||||||
|
determine how to convert
|
||||||
|
.Ar file2
|
||||||
|
into
|
||||||
|
.Ar file1 .
|
||||||
|
As in
|
||||||
|
.Xr ed 1 ,
|
||||||
|
identical
|
||||||
|
pairs (where num1 = num2) are abbreviated as a single
|
||||||
|
number.
|
||||||
|
.Sh ENVIRONMENT
|
||||||
|
.Bl -tag -width TMPDIR
|
||||||
|
.It Ev TMPDIR
|
||||||
|
If the environment variable
|
||||||
|
.Ev TMPDIR
|
||||||
|
exists,
|
||||||
|
.Nm
|
||||||
|
will use the directory specified by
|
||||||
|
.Ev TMPDIR
|
||||||
|
as the temporary directory.
|
||||||
|
.El
|
||||||
|
.Sh FILES
|
||||||
|
.Bl -tag -width /tmp/diff.XXXXXXXX -compact
|
||||||
|
.It Pa /tmp/diff. Ns Ar XXXXXXXX
|
||||||
|
Temporary file used when comparing a device or the standard input.
|
||||||
|
Note that the temporary file is unlinked as soon as it is created
|
||||||
|
so it will not show up in a directory listing.
|
||||||
|
.El
|
||||||
|
.Sh DIAGNOSTICS
|
||||||
|
The
|
||||||
|
.Nm
|
||||||
|
utility exits with one of the following values:
|
||||||
|
.Pp
|
||||||
|
.Bl -tag -width Ds -compact -offset indent
|
||||||
|
.It 0
|
||||||
|
No differences were found.
|
||||||
|
.It 1
|
||||||
|
Differences were found.
|
||||||
|
.It \*(Gt1
|
||||||
|
An error occurred.
|
||||||
|
.El
|
||||||
|
.Sh SEE ALSO
|
||||||
|
.Xr cmp 1 ,
|
||||||
|
.Xr comm 1 ,
|
||||||
|
.Xr diff3 1 ,
|
||||||
|
.Xr ed 1 ,
|
||||||
|
.Xr pr 1 ,
|
||||||
|
.Xr sdiff 1 ,
|
||||||
|
.Xr fnmatch 3 ,
|
||||||
|
.Xr re_format 7
|
||||||
|
.Sh STANDARDS
|
||||||
|
The
|
||||||
|
.Nm
|
||||||
|
utility is compliant with the
|
||||||
|
.St -p1003.1-2008
|
||||||
|
specification.
|
||||||
|
.Pp
|
||||||
|
The flags
|
||||||
|
.Op Fl aDdIiLlNnPpqSsTtwXx
|
||||||
|
are extensions to that specification.
|
||||||
|
.Sh HISTORY
|
||||||
|
A
|
||||||
|
.Nm
|
||||||
|
command appeared in
|
||||||
|
.At v6 .
|
||||||
|
.Sh BUGS
|
||||||
|
When comparing directories with the
|
||||||
|
.Fl b ,
|
||||||
|
.Fl w
|
||||||
|
or
|
||||||
|
.Fl i
|
||||||
|
options specified,
|
||||||
|
.Nm
|
||||||
|
first compares the files ala
|
||||||
|
.Xr cmp 1 ,
|
||||||
|
and then decides to run the
|
||||||
|
.Nm
|
||||||
|
algorithm if they are not equal.
|
||||||
|
This may cause a small amount of spurious output if the files
|
||||||
|
then turn out to be identical because the only differences are
|
||||||
|
insignificant whitespace or case differences.
|
413
commands/diff/diff.c
Normal file
413
commands/diff/diff.c
Normal file
@ -0,0 +1,413 @@
|
|||||||
|
/* $OpenBSD: diff.c,v 1.56 2010/02/21 15:24:01 sobrado Exp $ */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2003 Todd C. Miller <Todd.Miller@courtesan.com>
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*
|
||||||
|
* Sponsored in part by the Defense Advanced Research Projects
|
||||||
|
* Agency (DARPA) and Air Force Research Laboratory, Air Force
|
||||||
|
* Materiel Command, USAF, under agreement number F39502-99-1-0512.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/param.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <err.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <getopt.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include "diff.h"
|
||||||
|
#include "xmalloc.h"
|
||||||
|
|
||||||
|
int lflag, Nflag, Pflag, rflag, sflag, Tflag;
|
||||||
|
int diff_format, diff_context, status;
|
||||||
|
char *start, *ifdefname, *diffargs, *label[2], *ignore_pats;
|
||||||
|
struct stat stb1, stb2;
|
||||||
|
struct excludes *excludes_list;
|
||||||
|
regex_t ignore_re;
|
||||||
|
|
||||||
|
#define OPTIONS "0123456789abC:cdD:efhI:iL:lnNPpqrS:sTtU:uwX:x:"
|
||||||
|
static struct option longopts[] = {
|
||||||
|
{ "text", no_argument, 0, 'a' },
|
||||||
|
{ "ignore-space-change", no_argument, 0, 'b' },
|
||||||
|
{ "context", optional_argument, 0, 'C' },
|
||||||
|
{ "ifdef", required_argument, 0, 'D' },
|
||||||
|
{ "minimal", no_argument, 0, 'd' },
|
||||||
|
{ "ed", no_argument, 0, 'e' },
|
||||||
|
{ "forward-ed", no_argument, 0, 'f' },
|
||||||
|
{ "ignore-matching-lines", required_argument, 0, 'I' },
|
||||||
|
{ "ignore-case", no_argument, 0, 'i' },
|
||||||
|
{ "paginate", no_argument, 0, 'l' },
|
||||||
|
{ "label", required_argument, 0, 'L' },
|
||||||
|
{ "new-file", no_argument, 0, 'N' },
|
||||||
|
{ "rcs", no_argument, 0, 'n' },
|
||||||
|
{ "unidirectional-new-file", no_argument, 0, 'P' },
|
||||||
|
{ "show-c-function", no_argument, 0, 'p' },
|
||||||
|
{ "brief", no_argument, 0, 'q' },
|
||||||
|
{ "recursive", no_argument, 0, 'r' },
|
||||||
|
{ "report-identical-files", no_argument, 0, 's' },
|
||||||
|
{ "starting-file", required_argument, 0, 'S' },
|
||||||
|
{ "expand-tabs", no_argument, 0, 't' },
|
||||||
|
{ "initial-tab", no_argument, 0, 'T' },
|
||||||
|
{ "unified", optional_argument, 0, 'U' },
|
||||||
|
{ "ignore-all-space", no_argument, 0, 'w' },
|
||||||
|
{ "exclude", required_argument, 0, 'x' },
|
||||||
|
{ "exclude-from", required_argument, 0, 'X' },
|
||||||
|
{ NULL, 0, 0, '\0'}
|
||||||
|
};
|
||||||
|
|
||||||
|
__dead void usage(void);
|
||||||
|
void push_excludes(char *);
|
||||||
|
void push_ignore_pats(char *);
|
||||||
|
void read_excludes_file(char *file);
|
||||||
|
void set_argstr(char **, char **);
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
char *ep, **oargv;
|
||||||
|
long l;
|
||||||
|
int ch, dflags, lastch, gotstdin, prevoptind, newarg;
|
||||||
|
|
||||||
|
oargv = argv;
|
||||||
|
gotstdin = 0;
|
||||||
|
dflags = 0;
|
||||||
|
lastch = '\0';
|
||||||
|
prevoptind = 1;
|
||||||
|
newarg = 1;
|
||||||
|
while ((ch = getopt_long(argc, argv, OPTIONS, longopts, NULL)) != -1) {
|
||||||
|
switch (ch) {
|
||||||
|
case '0': case '1': case '2': case '3': case '4':
|
||||||
|
case '5': case '6': case '7': case '8': case '9':
|
||||||
|
if (newarg)
|
||||||
|
usage(); /* disallow -[0-9]+ */
|
||||||
|
else if (lastch == 'c' || lastch == 'u')
|
||||||
|
diff_context = 0;
|
||||||
|
else if (!isdigit(lastch) || diff_context > INT_MAX / 10)
|
||||||
|
usage();
|
||||||
|
diff_context = (diff_context * 10) + (ch - '0');
|
||||||
|
break;
|
||||||
|
case 'a':
|
||||||
|
dflags |= D_FORCEASCII;
|
||||||
|
break;
|
||||||
|
case 'b':
|
||||||
|
dflags |= D_FOLDBLANKS;
|
||||||
|
break;
|
||||||
|
case 'C':
|
||||||
|
case 'c':
|
||||||
|
diff_format = D_CONTEXT;
|
||||||
|
if (optarg != NULL) {
|
||||||
|
l = strtol(optarg, &ep, 10);
|
||||||
|
if (*ep != '\0' || l < 0 || l >= INT_MAX)
|
||||||
|
usage();
|
||||||
|
diff_context = (int)l;
|
||||||
|
} else
|
||||||
|
diff_context = 3;
|
||||||
|
break;
|
||||||
|
case 'd':
|
||||||
|
dflags |= D_MINIMAL;
|
||||||
|
break;
|
||||||
|
case 'D':
|
||||||
|
diff_format = D_IFDEF;
|
||||||
|
ifdefname = optarg;
|
||||||
|
break;
|
||||||
|
case 'e':
|
||||||
|
diff_format = D_EDIT;
|
||||||
|
break;
|
||||||
|
case 'f':
|
||||||
|
diff_format = D_REVERSE;
|
||||||
|
break;
|
||||||
|
case 'h':
|
||||||
|
/* silently ignore for backwards compatibility */
|
||||||
|
break;
|
||||||
|
case 'I':
|
||||||
|
push_ignore_pats(optarg);
|
||||||
|
break;
|
||||||
|
case 'i':
|
||||||
|
dflags |= D_IGNORECASE;
|
||||||
|
break;
|
||||||
|
case 'L':
|
||||||
|
if (label[0] == NULL)
|
||||||
|
label[0] = optarg;
|
||||||
|
else if (label[1] == NULL)
|
||||||
|
label[1] = optarg;
|
||||||
|
else
|
||||||
|
usage();
|
||||||
|
break;
|
||||||
|
case 'l':
|
||||||
|
lflag = 1;
|
||||||
|
signal(SIGPIPE, SIG_IGN);
|
||||||
|
break;
|
||||||
|
case 'N':
|
||||||
|
Nflag = 1;
|
||||||
|
break;
|
||||||
|
case 'n':
|
||||||
|
diff_format = D_NREVERSE;
|
||||||
|
break;
|
||||||
|
case 'p':
|
||||||
|
dflags |= D_PROTOTYPE;
|
||||||
|
break;
|
||||||
|
case 'P':
|
||||||
|
Pflag = 1;
|
||||||
|
break;
|
||||||
|
case 'r':
|
||||||
|
rflag = 1;
|
||||||
|
break;
|
||||||
|
case 'q':
|
||||||
|
diff_format = D_BRIEF;
|
||||||
|
break;
|
||||||
|
case 'S':
|
||||||
|
start = optarg;
|
||||||
|
break;
|
||||||
|
case 's':
|
||||||
|
sflag = 1;
|
||||||
|
break;
|
||||||
|
case 'T':
|
||||||
|
Tflag = 1;
|
||||||
|
break;
|
||||||
|
case 't':
|
||||||
|
dflags |= D_EXPANDTABS;
|
||||||
|
break;
|
||||||
|
case 'U':
|
||||||
|
case 'u':
|
||||||
|
diff_format = D_UNIFIED;
|
||||||
|
if (optarg != NULL) {
|
||||||
|
l = strtol(optarg, &ep, 10);
|
||||||
|
if (*ep != '\0' || l < 0 || l >= INT_MAX)
|
||||||
|
usage();
|
||||||
|
diff_context = (int)l;
|
||||||
|
} else
|
||||||
|
diff_context = 3;
|
||||||
|
break;
|
||||||
|
case 'w':
|
||||||
|
dflags |= D_IGNOREBLANKS;
|
||||||
|
break;
|
||||||
|
case 'X':
|
||||||
|
read_excludes_file(optarg);
|
||||||
|
break;
|
||||||
|
case 'x':
|
||||||
|
push_excludes(optarg);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
usage();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
lastch = ch;
|
||||||
|
newarg = optind != prevoptind;
|
||||||
|
prevoptind = optind;
|
||||||
|
}
|
||||||
|
argc -= optind;
|
||||||
|
argv += optind;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Do sanity checks, fill in stb1 and stb2 and call the appropriate
|
||||||
|
* driver routine. Both drivers use the contents of stb1 and stb2.
|
||||||
|
*/
|
||||||
|
if (argc != 2)
|
||||||
|
usage();
|
||||||
|
if (ignore_pats != NULL) {
|
||||||
|
char buf[BUFSIZ];
|
||||||
|
int error;
|
||||||
|
|
||||||
|
if ((error = regcomp(&ignore_re, ignore_pats,
|
||||||
|
REG_NEWLINE | REG_EXTENDED)) != 0) {
|
||||||
|
regerror(error, &ignore_re, buf, sizeof(buf));
|
||||||
|
if (*ignore_pats != '\0')
|
||||||
|
errx(2, "%s: %s", ignore_pats, buf);
|
||||||
|
else
|
||||||
|
errx(2, "%s", buf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (strcmp(argv[0], "-") == 0) {
|
||||||
|
fstat(STDIN_FILENO, &stb1);
|
||||||
|
gotstdin = 1;
|
||||||
|
} else if (stat(argv[0], &stb1) != 0)
|
||||||
|
err(2, "%s", argv[0]);
|
||||||
|
if (strcmp(argv[1], "-") == 0) {
|
||||||
|
fstat(STDIN_FILENO, &stb2);
|
||||||
|
gotstdin = 1;
|
||||||
|
} else if (stat(argv[1], &stb2) != 0)
|
||||||
|
err(2, "%s", argv[1]);
|
||||||
|
if (gotstdin && (S_ISDIR(stb1.st_mode) || S_ISDIR(stb2.st_mode)))
|
||||||
|
errx(2, "can't compare - to a directory");
|
||||||
|
set_argstr(oargv, argv);
|
||||||
|
if (S_ISDIR(stb1.st_mode) && S_ISDIR(stb2.st_mode)) {
|
||||||
|
if (diff_format == D_IFDEF)
|
||||||
|
errx(2, "-D option not supported with directories");
|
||||||
|
diffdir(argv[0], argv[1], dflags);
|
||||||
|
} else {
|
||||||
|
if (S_ISDIR(stb1.st_mode)) {
|
||||||
|
argv[0] = splice(argv[0], argv[1]);
|
||||||
|
if (stat(argv[0], &stb1) < 0)
|
||||||
|
err(2, "%s", argv[0]);
|
||||||
|
}
|
||||||
|
if (S_ISDIR(stb2.st_mode)) {
|
||||||
|
argv[1] = splice(argv[1], argv[0]);
|
||||||
|
if (stat(argv[1], &stb2) < 0)
|
||||||
|
err(2, "%s", argv[1]);
|
||||||
|
}
|
||||||
|
print_status(diffreg(argv[0], argv[1], dflags), argv[0], argv[1],
|
||||||
|
NULL);
|
||||||
|
}
|
||||||
|
exit(status);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
set_argstr(char **av, char **ave)
|
||||||
|
{
|
||||||
|
size_t argsize;
|
||||||
|
char **ap;
|
||||||
|
|
||||||
|
argsize = 4 + *ave - *av + 1;
|
||||||
|
diffargs = xmalloc(argsize);
|
||||||
|
strlcpy(diffargs, "diff", argsize);
|
||||||
|
for (ap = av + 1; ap < ave; ap++) {
|
||||||
|
if (strcmp(*ap, "--") != 0) {
|
||||||
|
strlcat(diffargs, " ", argsize);
|
||||||
|
strlcat(diffargs, *ap, argsize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Read in an excludes file and push each line.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
read_excludes_file(char *file)
|
||||||
|
{
|
||||||
|
FILE *fp;
|
||||||
|
char *buf, *pattern;
|
||||||
|
size_t len;
|
||||||
|
|
||||||
|
if (strcmp(file, "-") == 0)
|
||||||
|
fp = stdin;
|
||||||
|
else if ((fp = fopen(file, "r")) == NULL)
|
||||||
|
err(2, "%s", file);
|
||||||
|
while ((buf = fgetln(fp, &len)) != NULL) {
|
||||||
|
if (buf[len - 1] == '\n')
|
||||||
|
len--;
|
||||||
|
pattern = xmalloc(len + 1);
|
||||||
|
memcpy(pattern, buf, len);
|
||||||
|
pattern[len] = '\0';
|
||||||
|
push_excludes(pattern);
|
||||||
|
}
|
||||||
|
if (strcmp(file, "-") != 0)
|
||||||
|
fclose(fp);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Push a pattern onto the excludes list.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
push_excludes(char *pattern)
|
||||||
|
{
|
||||||
|
struct excludes *entry;
|
||||||
|
|
||||||
|
entry = xmalloc(sizeof(*entry));
|
||||||
|
entry->pattern = pattern;
|
||||||
|
entry->next = excludes_list;
|
||||||
|
excludes_list = entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
push_ignore_pats(char *pattern)
|
||||||
|
{
|
||||||
|
size_t len;
|
||||||
|
|
||||||
|
if (ignore_pats == NULL)
|
||||||
|
ignore_pats = xstrdup(pattern);
|
||||||
|
else {
|
||||||
|
/* old + "|" + new + NUL */
|
||||||
|
len = strlen(ignore_pats) + strlen(pattern) + 2;
|
||||||
|
ignore_pats = xrealloc(ignore_pats, 1, len);
|
||||||
|
strlcat(ignore_pats, "|", len);
|
||||||
|
strlcat(ignore_pats, pattern, len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
print_only(const char *path, size_t dirlen, const char *entry)
|
||||||
|
{
|
||||||
|
if (dirlen > 1)
|
||||||
|
dirlen--;
|
||||||
|
printf("Only in %.*s: %s\n", (int)dirlen, path, entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
print_status(int val, char *path1, char *path2, char *entry)
|
||||||
|
{
|
||||||
|
switch (val) {
|
||||||
|
case D_ONLY:
|
||||||
|
print_only(path1, strlen(path1), entry);
|
||||||
|
break;
|
||||||
|
case D_COMMON:
|
||||||
|
printf("Common subdirectories: %s%s and %s%s\n",
|
||||||
|
path1, entry ? entry : "", path2, entry ? entry : "");
|
||||||
|
break;
|
||||||
|
case D_BINARY:
|
||||||
|
printf("Binary files %s%s and %s%s differ\n",
|
||||||
|
path1, entry ? entry : "", path2, entry ? entry : "");
|
||||||
|
break;
|
||||||
|
case D_DIFFER:
|
||||||
|
if (diff_format == D_BRIEF)
|
||||||
|
printf("Files %s%s and %s%s differ\n",
|
||||||
|
path1, entry ? entry : "",
|
||||||
|
path2, entry ? entry : "");
|
||||||
|
break;
|
||||||
|
case D_SAME:
|
||||||
|
if (sflag)
|
||||||
|
printf("Files %s%s and %s%s are identical\n",
|
||||||
|
path1, entry ? entry : "",
|
||||||
|
path2, entry ? entry : "");
|
||||||
|
break;
|
||||||
|
case D_MISMATCH1:
|
||||||
|
printf("File %s%s is a directory while file %s%s is a regular file\n",
|
||||||
|
path1, entry ? entry : "", path2, entry ? entry : "");
|
||||||
|
break;
|
||||||
|
case D_MISMATCH2:
|
||||||
|
printf("File %s%s is a regular file while file %s%s is a directory\n",
|
||||||
|
path1, entry ? entry : "", path2, entry ? entry : "");
|
||||||
|
break;
|
||||||
|
case D_SKIPPED1:
|
||||||
|
printf("File %s%s is not a regular file or directory and was skipped\n",
|
||||||
|
path1, entry ? entry : "");
|
||||||
|
break;
|
||||||
|
case D_SKIPPED2:
|
||||||
|
printf("File %s%s is not a regular file or directory and was skipped\n",
|
||||||
|
path2, entry ? entry : "");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
__dead void
|
||||||
|
usage(void)
|
||||||
|
{
|
||||||
|
(void)fprintf(stderr,
|
||||||
|
"usage: diff [-abdilpTtw] [-c | -e | -f | -n | -q | -u] [-I pattern] [-L label]\n"
|
||||||
|
" file1 file2\n"
|
||||||
|
" diff [-abdilpTtw] [-I pattern] [-L label] -C number file1 file2\n"
|
||||||
|
" diff [-abdiltw] [-I pattern] -D string file1 file2\n"
|
||||||
|
" diff [-abdilpTtw] [-I pattern] [-L label] -U number file1 file2\n"
|
||||||
|
" diff [-abdilNPprsTtw] [-c | -e | -f | -n | -q | -u] [-I pattern]\n"
|
||||||
|
" [-L label] [-S name] [-X file] [-x pattern] dir1 dir2\n");
|
||||||
|
|
||||||
|
exit(2);
|
||||||
|
}
|
101
commands/diff/diff.h
Normal file
101
commands/diff/diff.h
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
/* $OpenBSD: diff.h,v 1.32 2009/06/07 08:39:13 ray Exp $ */
|
||||||
|
|
||||||
|
/*-
|
||||||
|
* Copyright (c) 1991, 1993
|
||||||
|
* The Regents of the University of California. All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. Neither the name of the University nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* @(#)diff.h 8.1 (Berkeley) 6/6/93
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <regex.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Output format options
|
||||||
|
*/
|
||||||
|
#define D_NORMAL 0 /* Normal output */
|
||||||
|
#define D_EDIT -1 /* Editor script out */
|
||||||
|
#define D_REVERSE 1 /* Reverse editor script */
|
||||||
|
#define D_CONTEXT 2 /* Diff with context */
|
||||||
|
#define D_UNIFIED 3 /* Unified context diff */
|
||||||
|
#define D_IFDEF 4 /* Diff with merged #ifdef's */
|
||||||
|
#define D_NREVERSE 5 /* Reverse ed script with numbered
|
||||||
|
lines and no trailing . */
|
||||||
|
#define D_BRIEF 6 /* Say if the files differ */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Output flags
|
||||||
|
*/
|
||||||
|
#define D_HEADER 0x001 /* Print a header/footer between files */
|
||||||
|
#define D_EMPTY1 0x002 /* Treat first file as empty (/dev/null) */
|
||||||
|
#define D_EMPTY2 0x004 /* Treat second file as empty (/dev/null) */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Command line flags
|
||||||
|
*/
|
||||||
|
#define D_FORCEASCII 0x008 /* Treat file as ascii regardless of content */
|
||||||
|
#define D_FOLDBLANKS 0x010 /* Treat all white space as equal */
|
||||||
|
#define D_MINIMAL 0x020 /* Make diff as small as possible */
|
||||||
|
#define D_IGNORECASE 0x040 /* Case-insensitive matching */
|
||||||
|
#define D_PROTOTYPE 0x080 /* Display C function prototype */
|
||||||
|
#define D_EXPANDTABS 0x100 /* Expand tabs to spaces */
|
||||||
|
#define D_IGNOREBLANKS 0x200 /* Ignore white space changes */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Status values for print_status() and diffreg() return values
|
||||||
|
*/
|
||||||
|
#define D_SAME 0 /* Files are the same */
|
||||||
|
#define D_DIFFER 1 /* Files are different */
|
||||||
|
#define D_BINARY 2 /* Binary files are different */
|
||||||
|
#define D_COMMON 3 /* Subdirectory common to both dirs */
|
||||||
|
#define D_ONLY 4 /* Only exists in one directory */
|
||||||
|
#define D_MISMATCH1 5 /* path1 was a dir, path2 a file */
|
||||||
|
#define D_MISMATCH2 6 /* path1 was a file, path2 a dir */
|
||||||
|
#define D_ERROR 7 /* An error occurred */
|
||||||
|
#define D_SKIPPED1 8 /* path1 was a special file */
|
||||||
|
#define D_SKIPPED2 9 /* path2 was a special file */
|
||||||
|
|
||||||
|
struct excludes {
|
||||||
|
char *pattern;
|
||||||
|
struct excludes *next;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern int lflag, Nflag, Pflag, rflag, sflag, Tflag;
|
||||||
|
extern int diff_format, diff_context, status;
|
||||||
|
extern char *start, *ifdefname, *diffargs, *label[2], *ignore_pats;
|
||||||
|
extern struct stat stb1, stb2;
|
||||||
|
extern struct excludes *excludes_list;
|
||||||
|
extern regex_t ignore_re;
|
||||||
|
|
||||||
|
char *splice(char *, char *);
|
||||||
|
int diffreg(char *, char *, int);
|
||||||
|
int easprintf(char **, const char *, ...);
|
||||||
|
void *emalloc(size_t);
|
||||||
|
void *erealloc(void *, size_t);
|
||||||
|
void diffdir(char *, char *, int);
|
||||||
|
void print_only(const char *, size_t, const char *);
|
||||||
|
void print_status(int, char *, char *, char *);
|
328
commands/diff/diffdir.c
Normal file
328
commands/diff/diffdir.c
Normal file
@ -0,0 +1,328 @@
|
|||||||
|
/* $OpenBSD: diffdir.c,v 1.35 2009/10/27 23:59:37 deraadt Exp $ */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2003 Todd C. Miller <Todd.Miller@courtesan.com>
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*
|
||||||
|
* Sponsored in part by the Defense Advanced Research Projects
|
||||||
|
* Agency (DARPA) and Air Force Research Laboratory, Air Force
|
||||||
|
* Materiel Command, USAF, under agreement number F39502-99-1-0512.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/param.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
#include <dirent.h>
|
||||||
|
#include <err.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <fnmatch.h>
|
||||||
|
#include <paths.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include "diff.h"
|
||||||
|
#include "xmalloc.h"
|
||||||
|
|
||||||
|
static int dircompare(const void *, const void *);
|
||||||
|
static int excluded(const char *);
|
||||||
|
static struct dirent **slurpdir(char *, char **, int);
|
||||||
|
static void diffit(struct dirent *, char *, size_t, char *, size_t, int);
|
||||||
|
|
||||||
|
#define d_status d_type /* we need to store status for -l */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Diff directory traversal. Will be called recursively if -r was specified.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
diffdir(char *p1, char *p2, int flags)
|
||||||
|
{
|
||||||
|
struct dirent **dirp1, **dirp2, **dp1, **dp2;
|
||||||
|
struct dirent *dent1, *dent2;
|
||||||
|
size_t dirlen1, dirlen2;
|
||||||
|
char path1[MAXPATHLEN], path2[MAXPATHLEN];
|
||||||
|
char *dirbuf1, *dirbuf2;
|
||||||
|
int pos;
|
||||||
|
|
||||||
|
dirlen1 = strlcpy(path1, *p1 ? p1 : ".", sizeof(path1));
|
||||||
|
if (dirlen1 >= sizeof(path1) - 1) {
|
||||||
|
warnx("%s: %s", p1, strerror(ENAMETOOLONG));
|
||||||
|
status = 2;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (path1[dirlen1 - 1] != '/') {
|
||||||
|
path1[dirlen1++] = '/';
|
||||||
|
path1[dirlen1] = '\0';
|
||||||
|
}
|
||||||
|
dirlen2 = strlcpy(path2, *p2 ? p2 : ".", sizeof(path2));
|
||||||
|
if (dirlen2 >= sizeof(path2) - 1) {
|
||||||
|
warnx("%s: %s", p2, strerror(ENAMETOOLONG));
|
||||||
|
status = 2;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (path2[dirlen2 - 1] != '/') {
|
||||||
|
path2[dirlen2++] = '/';
|
||||||
|
path2[dirlen2] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
/* get a list of the entries in each directory */
|
||||||
|
dp1 = dirp1 = slurpdir(path1, &dirbuf1, Nflag + Pflag);
|
||||||
|
dp2 = dirp2 = slurpdir(path2, &dirbuf2, Nflag);
|
||||||
|
if (dirp1 == NULL || dirp2 == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If we were given a starting point, find it.
|
||||||
|
*/
|
||||||
|
if (start != NULL) {
|
||||||
|
while (*dp1 != NULL && strcmp((*dp1)->d_name, start) < 0)
|
||||||
|
dp1++;
|
||||||
|
while (*dp2 != NULL && strcmp((*dp2)->d_name, start) < 0)
|
||||||
|
dp2++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Iterate through the two directory lists, diffing as we go.
|
||||||
|
*/
|
||||||
|
while (*dp1 != NULL || *dp2 != NULL) {
|
||||||
|
dent1 = *dp1;
|
||||||
|
dent2 = *dp2;
|
||||||
|
|
||||||
|
pos = dent1 == NULL ? 1 : dent2 == NULL ? -1 :
|
||||||
|
strcmp(dent1->d_name, dent2->d_name);
|
||||||
|
if (pos == 0) {
|
||||||
|
/* file exists in both dirs, diff it */
|
||||||
|
diffit(dent1, path1, dirlen1, path2, dirlen2, flags);
|
||||||
|
dp1++;
|
||||||
|
dp2++;
|
||||||
|
} else if (pos < 0) {
|
||||||
|
/* file only in first dir, only diff if -N */
|
||||||
|
if (Nflag)
|
||||||
|
diffit(dent1, path1, dirlen1, path2, dirlen2,
|
||||||
|
flags);
|
||||||
|
else if (lflag)
|
||||||
|
dent1->d_status |= D_ONLY;
|
||||||
|
else
|
||||||
|
print_only(path1, dirlen1, dent1->d_name);
|
||||||
|
dp1++;
|
||||||
|
} else {
|
||||||
|
/* file only in second dir, only diff if -N or -P */
|
||||||
|
if (Nflag || Pflag)
|
||||||
|
diffit(dent2, path1, dirlen1, path2, dirlen2,
|
||||||
|
flags);
|
||||||
|
else if (lflag)
|
||||||
|
dent2->d_status |= D_ONLY;
|
||||||
|
else
|
||||||
|
print_only(path2, dirlen2, dent2->d_name);
|
||||||
|
dp2++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (lflag) {
|
||||||
|
path1[dirlen1] = '\0';
|
||||||
|
path2[dirlen2] = '\0';
|
||||||
|
for (dp1 = dirp1; (dent1 = *dp1) != NULL; dp1++) {
|
||||||
|
print_status(dent1->d_status, path1, path2,
|
||||||
|
dent1->d_name);
|
||||||
|
}
|
||||||
|
for (dp2 = dirp2; (dent2 = *dp2) != NULL; dp2++) {
|
||||||
|
if (dent2->d_status == D_ONLY)
|
||||||
|
print_status(dent2->d_status, path2, NULL,
|
||||||
|
dent2->d_name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dirbuf1 != NULL) {
|
||||||
|
xfree(dirp1);
|
||||||
|
xfree(dirbuf1);
|
||||||
|
}
|
||||||
|
if (dirbuf2 != NULL) {
|
||||||
|
xfree(dirp2);
|
||||||
|
xfree(dirbuf2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Read in a whole directory's worth of struct dirents, culling
|
||||||
|
* out the "excluded" ones.
|
||||||
|
* Returns an array of struct dirent *'s that point into the buffer
|
||||||
|
* returned via bufp. Caller is responsible for free()ing both of these.
|
||||||
|
*/
|
||||||
|
static struct dirent **
|
||||||
|
slurpdir(char *path, char **bufp, int enoentok)
|
||||||
|
{
|
||||||
|
char *buf, *ebuf, *cp;
|
||||||
|
size_t bufsize, have, need;
|
||||||
|
long base;
|
||||||
|
int fd, nbytes, entries;
|
||||||
|
struct stat sb;
|
||||||
|
struct dirent **dirlist, *dp;
|
||||||
|
|
||||||
|
*bufp = NULL;
|
||||||
|
if ((fd = open(path, O_RDONLY, 0644)) == -1) {
|
||||||
|
static struct dirent *dummy;
|
||||||
|
|
||||||
|
if (!enoentok || errno != ENOENT) {
|
||||||
|
warn("%s", path);
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
return (&dummy);
|
||||||
|
}
|
||||||
|
if (fstat(fd, &sb) == -1) {
|
||||||
|
warn("%s", path);
|
||||||
|
close(fd);
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
need = roundup(sb.st_blksize, sizeof(struct dirent));
|
||||||
|
have = bufsize = roundup(MAX(sb.st_size, sb.st_blksize),
|
||||||
|
sizeof(struct dirent)) + need;
|
||||||
|
ebuf = buf = xmalloc(bufsize);
|
||||||
|
|
||||||
|
do {
|
||||||
|
if (have < need) {
|
||||||
|
bufsize += need;
|
||||||
|
have += need;
|
||||||
|
cp = xrealloc(buf, 1, bufsize);
|
||||||
|
ebuf = cp + (ebuf - buf);
|
||||||
|
buf = cp;
|
||||||
|
}
|
||||||
|
nbytes = getdirentries(fd, ebuf, have, &base);
|
||||||
|
if (nbytes == -1) {
|
||||||
|
warn("%s", path);
|
||||||
|
xfree(buf);
|
||||||
|
close(fd);
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
ebuf += nbytes;
|
||||||
|
have -= nbytes;
|
||||||
|
} while (nbytes != 0);
|
||||||
|
close(fd);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We now have all the directory entries in our buffer.
|
||||||
|
* However, in order to easily sort them we need to convert
|
||||||
|
* the buffer into an array.
|
||||||
|
*/
|
||||||
|
for (entries = 0, cp = buf; cp < ebuf; ) {
|
||||||
|
dp = (struct dirent *)cp;
|
||||||
|
if (dp->d_fileno != 0)
|
||||||
|
entries++;
|
||||||
|
if (dp->d_reclen <= 0)
|
||||||
|
break;
|
||||||
|
cp += dp->d_reclen;
|
||||||
|
}
|
||||||
|
dirlist = xcalloc(sizeof(*dirlist), entries + 1);
|
||||||
|
for (entries = 0, cp = buf; cp < ebuf; ) {
|
||||||
|
dp = (struct dirent *)cp;
|
||||||
|
if (dp->d_fileno != 0 && !excluded(dp->d_name)) {
|
||||||
|
dp->d_status = 0;
|
||||||
|
dirlist[entries++] = dp;
|
||||||
|
}
|
||||||
|
if (dp->d_reclen <= 0)
|
||||||
|
break;
|
||||||
|
cp += dp->d_reclen;
|
||||||
|
}
|
||||||
|
dirlist[entries] = NULL;
|
||||||
|
|
||||||
|
qsort(dirlist, entries, sizeof(struct dirent *), dircompare);
|
||||||
|
|
||||||
|
*bufp = buf;
|
||||||
|
return (dirlist);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Compare d_name in two dirent structures; for qsort(3).
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
dircompare(const void *vp1, const void *vp2)
|
||||||
|
{
|
||||||
|
struct dirent *dp1 = *((struct dirent **) vp1);
|
||||||
|
struct dirent *dp2 = *((struct dirent **) vp2);
|
||||||
|
|
||||||
|
return (strcmp(dp1->d_name, dp2->d_name));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Do the actual diff by calling either diffreg() or diffdir().
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
diffit(struct dirent *dp, char *path1, size_t plen1, char *path2, size_t plen2,
|
||||||
|
int flags)
|
||||||
|
{
|
||||||
|
flags |= D_HEADER;
|
||||||
|
strlcpy(path1 + plen1, dp->d_name, MAXPATHLEN - plen1);
|
||||||
|
if (stat(path1, &stb1) != 0) {
|
||||||
|
if (!(Nflag || Pflag) || errno != ENOENT) {
|
||||||
|
warn("%s", path1);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
flags |= D_EMPTY1;
|
||||||
|
memset(&stb1, 0, sizeof(stb1));
|
||||||
|
}
|
||||||
|
|
||||||
|
strlcpy(path2 + plen2, dp->d_name, MAXPATHLEN - plen2);
|
||||||
|
if (stat(path2, &stb2) != 0) {
|
||||||
|
if (!Nflag || errno != ENOENT) {
|
||||||
|
warn("%s", path2);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
flags |= D_EMPTY2;
|
||||||
|
memset(&stb2, 0, sizeof(stb2));
|
||||||
|
stb2.st_mode = stb1.st_mode;
|
||||||
|
}
|
||||||
|
if (stb1.st_mode == 0)
|
||||||
|
stb1.st_mode = stb2.st_mode;
|
||||||
|
|
||||||
|
if (S_ISDIR(stb1.st_mode) && S_ISDIR(stb2.st_mode)) {
|
||||||
|
if (rflag)
|
||||||
|
diffdir(path1, path2, flags);
|
||||||
|
else if (lflag)
|
||||||
|
dp->d_status |= D_COMMON;
|
||||||
|
else
|
||||||
|
printf("Common subdirectories: %s and %s\n",
|
||||||
|
path1, path2);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!S_ISREG(stb1.st_mode) && !S_ISDIR(stb1.st_mode))
|
||||||
|
dp->d_status = D_SKIPPED1;
|
||||||
|
else if (!S_ISREG(stb2.st_mode) && !S_ISDIR(stb2.st_mode))
|
||||||
|
dp->d_status = D_SKIPPED2;
|
||||||
|
else
|
||||||
|
dp->d_status = diffreg(path1, path2, flags);
|
||||||
|
if (!lflag)
|
||||||
|
print_status(dp->d_status, path1, path2, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Exclude the given directory entry?
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
excluded(const char *entry)
|
||||||
|
{
|
||||||
|
struct excludes *excl;
|
||||||
|
|
||||||
|
/* always skip "." and ".." */
|
||||||
|
if (entry[0] == '.' &&
|
||||||
|
(entry[1] == '\0' || (entry[1] == '.' && entry[2] == '\0')))
|
||||||
|
return (1);
|
||||||
|
|
||||||
|
/* check excludes list */
|
||||||
|
for (excl = excludes_list; excl != NULL; excl = excl->next)
|
||||||
|
if (fnmatch(excl->pattern, entry, FNM_PATHNAME) == 0)
|
||||||
|
return (1);
|
||||||
|
|
||||||
|
return (0);
|
||||||
|
}
|
1535
commands/diff/diffreg.c
Normal file
1535
commands/diff/diffreg.c
Normal file
File diff suppressed because it is too large
Load Diff
25
commands/diff/pathnames.h
Normal file
25
commands/diff/pathnames.h
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
/* $OpenBSD: pathnames.h,v 1.10 2003/07/09 00:07:44 millert Exp $ */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2003 Todd C. Miller <Todd.Miller@courtesan.com>
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*
|
||||||
|
* Sponsored in part by the Defense Advanced Research Projects
|
||||||
|
* Agency (DARPA) and Air Force Research Laboratory, Air Force
|
||||||
|
* Materiel Command, USAF, under agreement number F39502-99-1-0512.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <paths.h>
|
||||||
|
|
||||||
|
#define _PATH_PR "/usr/bin/pr"
|
107
commands/diff/xmalloc.c
Normal file
107
commands/diff/xmalloc.c
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
/* $OpenBSD: xmalloc.c,v 1.2 2009/06/07 08:39:13 ray Exp $ */
|
||||||
|
/*
|
||||||
|
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||||
|
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||||
|
* All rights reserved
|
||||||
|
* Versions of malloc and friends that check their results, and never return
|
||||||
|
* failure (they call fatal if they encounter an error).
|
||||||
|
*
|
||||||
|
* As far as I am concerned, the code I have written for this software
|
||||||
|
* can be used freely for any purpose. Any derived versions of this
|
||||||
|
* software must be clearly marked as such, and if the derived work is
|
||||||
|
* incompatible with the protocol description in the RFC file, it must be
|
||||||
|
* called by a name other than "ssh" or "Secure Shell".
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <err.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "xmalloc.h"
|
||||||
|
|
||||||
|
void *
|
||||||
|
xmalloc(size_t size)
|
||||||
|
{
|
||||||
|
void *ptr;
|
||||||
|
|
||||||
|
if (size == 0)
|
||||||
|
errx(2, NULL);
|
||||||
|
ptr = malloc(size);
|
||||||
|
if (ptr == NULL)
|
||||||
|
errx(2, NULL);
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *
|
||||||
|
xcalloc(size_t nmemb, size_t size)
|
||||||
|
{
|
||||||
|
void *ptr;
|
||||||
|
|
||||||
|
if (size == 0 || nmemb == 0)
|
||||||
|
errx(1, "xcalloc: zero size");
|
||||||
|
if (SIZE_MAX / nmemb < size)
|
||||||
|
errx(1, "xcalloc: nmemb * size > SIZE_MAX");
|
||||||
|
ptr = calloc(nmemb, size);
|
||||||
|
if (ptr == NULL)
|
||||||
|
errx(1, "xcalloc: out of memory (allocating %lu bytes)",
|
||||||
|
(u_long)(size * nmemb));
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *
|
||||||
|
xrealloc(void *ptr, size_t nmemb, size_t size)
|
||||||
|
{
|
||||||
|
void *new_ptr;
|
||||||
|
size_t new_size = nmemb * size;
|
||||||
|
|
||||||
|
if (new_size == 0)
|
||||||
|
errx(2, NULL);
|
||||||
|
if (SIZE_MAX / nmemb < size)
|
||||||
|
errx(2, NULL);
|
||||||
|
if (ptr == NULL)
|
||||||
|
new_ptr = malloc(new_size);
|
||||||
|
else
|
||||||
|
new_ptr = realloc(ptr, new_size);
|
||||||
|
if (new_ptr == NULL)
|
||||||
|
errx(2, NULL);
|
||||||
|
return new_ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
xfree(void *ptr)
|
||||||
|
{
|
||||||
|
if (ptr == NULL)
|
||||||
|
errx(2, NULL);
|
||||||
|
free(ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
char *
|
||||||
|
xstrdup(const char *str)
|
||||||
|
{
|
||||||
|
size_t len;
|
||||||
|
char *cp;
|
||||||
|
|
||||||
|
len = strlen(str) + 1;
|
||||||
|
cp = xmalloc(len);
|
||||||
|
strlcpy(cp, str, len);
|
||||||
|
return cp;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
xasprintf(char **ret, const char *fmt, ...)
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
va_start(ap, fmt);
|
||||||
|
i = vasprintf(ret, fmt, ap);
|
||||||
|
va_end(ap);
|
||||||
|
|
||||||
|
if (i < 0 || *ret == NULL)
|
||||||
|
errx(2, NULL);
|
||||||
|
|
||||||
|
return (i);
|
||||||
|
}
|
31
commands/diff/xmalloc.h
Normal file
31
commands/diff/xmalloc.h
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
/* $OpenBSD: xmalloc.h,v 1.2 2009/06/07 08:39:13 ray Exp $ */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||||
|
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||||
|
* All rights reserved
|
||||||
|
* Created: Mon Mar 20 22:09:17 1995 ylo
|
||||||
|
*
|
||||||
|
* Versions of malloc and friends that check their results, and never return
|
||||||
|
* failure (they call fatal if they encounter an error).
|
||||||
|
*
|
||||||
|
* As far as I am concerned, the code I have written for this software
|
||||||
|
* can be used freely for any purpose. Any derived versions of this
|
||||||
|
* software must be clearly marked as such, and if the derived work is
|
||||||
|
* incompatible with the protocol description in the RFC file, it must be
|
||||||
|
* called by a name other than "ssh" or "Secure Shell".
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef XMALLOC_H
|
||||||
|
#define XMALLOC_H
|
||||||
|
|
||||||
|
void *xmalloc(size_t);
|
||||||
|
void *xcalloc(size_t, size_t);
|
||||||
|
void *xrealloc(void *, size_t, size_t);
|
||||||
|
void xfree(void *);
|
||||||
|
char *xstrdup(const char *);
|
||||||
|
int xasprintf(char **, const char *, ...)
|
||||||
|
__attribute__((__format__ (printf, 2, 3)))
|
||||||
|
__attribute__((__nonnull__ (2)));
|
||||||
|
|
||||||
|
#endif /* XMALLOC_H */
|
Loading…
x
Reference in New Issue
Block a user