version 1.31, 2003/07/09 00:07:44 |
version 1.32, 2003/07/09 00:39:26 |
|
|
static const char rcsid[] = "$OpenBSD$"; |
static const char rcsid[] = "$OpenBSD$"; |
#endif /* not lint */ |
#endif /* not lint */ |
|
|
#include <sys/types.h> |
#include <sys/param.h> |
#include <sys/stat.h> |
#include <sys/stat.h> |
#include <sys/wait.h> |
#include <sys/wait.h> |
|
|
#include <ctype.h> |
#include <ctype.h> |
#include <err.h> |
#include <err.h> |
|
#include <errno.h> |
#include <fcntl.h> |
#include <fcntl.h> |
#include <libgen.h> |
#include <libgen.h> |
#include <signal.h> |
|
#include <stdio.h> |
#include <stdio.h> |
#include <stdlib.h> |
#include <stdlib.h> |
#include <string.h> |
#include <string.h> |
|
|
static struct line *sfile[2]; /* shortened by pruning common prefix/suffix */ |
static struct line *sfile[2]; /* shortened by pruning common prefix/suffix */ |
static u_char *chrtran; /* translation table for case-folding */ |
static u_char *chrtran; /* translation table for case-folding */ |
|
|
|
static FILE *opentemp(const char *); |
static void fetch(long *, int, int, FILE *, char *, int); |
static void fetch(long *, int, int, FILE *, char *, int); |
static void output(char *, FILE *, char *, FILE *); |
static void output(char *, FILE *, char *, FILE *); |
static void check(char *, FILE *, char *, FILE *); |
static void check(char *, FILE *, char *, FILE *); |
|
|
|
|
anychange = 0; |
anychange = 0; |
chrtran = (iflag ? cup2low : clow2low); |
chrtran = (iflag ? cup2low : clow2low); |
|
if (S_ISDIR(stb1.st_mode) != S_ISDIR(stb2.st_mode)) |
|
return (D_MISMATCH); |
if (strcmp(file1, "-") == 0 && strcmp(file2, "-") == 0) |
if (strcmp(file1, "-") == 0 && strcmp(file2, "-") == 0) |
goto notsame; |
goto notsame; |
|
|
/* XXX - only make temp file for stdin if not seekable? (millert) */ |
|
if (flags & D_EMPTY1) |
if (flags & D_EMPTY1) |
f1 = fopen(_PATH_DEVNULL, "r"); |
f1 = fopen(_PATH_DEVNULL, "r"); |
else { |
else { |
if (S_ISDIR(stb1.st_mode)) { |
if (!S_ISREG(stb1.st_mode)) { |
file1 = splice(file1, file2); |
if ((f1 = opentemp(file1)) == NULL || |
if (stat(file1, &stb1) < 0) { |
fstat(fileno(f1), &stb1) < 0) { |
warn("%s", file1); |
warn("%s", file1); |
status |= 2; |
status |= 2; |
goto closem; |
goto closem; |
} |
} |
} else if (!S_ISREG(stb1.st_mode)) { |
} else if (strcmp(file1, "-") == 0) |
file1 = copytemp(file1, 1); |
|
if (file1 == NULL || stat(file1, &stb1) < 0) { |
|
warn("%s", file1); |
|
status |= 2; |
|
goto closem; |
|
} |
|
} |
|
if (strcmp(file1, "-") == 0) |
|
f1 = stdin; |
f1 = stdin; |
else |
else |
f1 = fopen(file1, "r"); |
f1 = fopen(file1, "r"); |
|
|
if (flags & D_EMPTY2) |
if (flags & D_EMPTY2) |
f2 = fopen(_PATH_DEVNULL, "r"); |
f2 = fopen(_PATH_DEVNULL, "r"); |
else { |
else { |
if (S_ISDIR(stb2.st_mode)) { |
if (!S_ISREG(stb2.st_mode)) { |
file2 = splice(file2, file1); |
if ((f2 = opentemp(file2)) == NULL || |
if (stat(file2, &stb2) < 0) { |
fstat(fileno(f2), &stb2) < 0) { |
warn("%s", file2); |
warn("%s", file2); |
status |= 2; |
status |= 2; |
goto closem; |
goto closem; |
} |
} |
} else if (!S_ISREG(stb2.st_mode)) { |
} else if (strcmp(file2, "-") == 0) |
file2 = copytemp(file2, 2); |
|
if (file2 == NULL || stat(file2, &stb2) < 0) { |
|
warn("%s", file2); |
|
status |= 2; |
|
goto closem; |
|
} |
|
} |
|
if (strcmp(file2, "-") == 0) |
|
f2 = stdin; |
f2 = stdin; |
else |
else |
f2 = fopen(file2, "r"); |
f2 = fopen(file2, "r"); |
|
|
fclose(f1); |
fclose(f1); |
if (f2 != NULL) |
if (f2 != NULL) |
fclose(f2); |
fclose(f2); |
if (tempfiles[0] != NULL) { |
if (file1 != ofile1) |
unlink(tempfiles[0]); |
|
free(tempfiles[0]); |
|
tempfiles[0] = NULL; |
|
} else if (file1 != ofile1) |
|
free(file1); |
free(file1); |
if (tempfiles[1] != NULL) { |
if (file2 != ofile2) |
unlink(tempfiles[1]); |
|
free(tempfiles[1]); |
|
tempfiles[1] = NULL; |
|
} else if (file2 != ofile2) |
|
free(file2); |
free(file2); |
return (rval); |
return (rval); |
} |
} |
|
|
} |
} |
} |
} |
|
|
char *tempfiles[2]; |
static FILE * |
|
opentemp(const char *file) |
/* XXX - pass back a FILE * too (millert) */ |
|
char * |
|
copytemp(const char *file, int n) |
|
{ |
{ |
char buf[BUFSIZ], *tempdir, *tempfile; |
char buf[BUFSIZ], *tempdir, tempfile[MAXPATHLEN]; |
int i, ifd, ofd; |
ssize_t nread; |
|
int ifd, ofd; |
|
|
if (n != 1 && n != 2) |
|
return (NULL); |
|
|
|
if (strcmp(file, "-") == 0) |
if (strcmp(file, "-") == 0) |
ifd = STDIN_FILENO; |
ifd = STDIN_FILENO; |
else if ((ifd = open(file, O_RDONLY, 0644)) < 0) |
else if ((ifd = open(file, O_RDONLY, 0644)) < 0) |
|
|
|
|
if ((tempdir = getenv("TMPDIR")) == NULL) |
if ((tempdir = getenv("TMPDIR")) == NULL) |
tempdir = _PATH_TMP; |
tempdir = _PATH_TMP; |
if (asprintf(&tempfile, "%s/diff%d.XXXXXXXX", tempdir, n) == -1) |
if (snprintf(tempfile, sizeof(tempfile), "%s/diff.XXXXXXXX", |
|
tempdir) >= sizeof(tempfile)) { |
|
close(ifd); |
|
errno = ENAMETOOLONG; |
return (NULL); |
return (NULL); |
tempfiles[n - 1] = tempfile; |
} |
|
|
signal(SIGHUP, quit); |
if ((ofd = mkstemp(tempfile)) < 0) |
signal(SIGINT, quit); |
|
signal(SIGPIPE, quit); |
|
signal(SIGTERM, quit); |
|
signal(SIGPIPE, SIG_IGN); |
|
ofd = mkstemp(tempfile); |
|
if (ofd < 0) |
|
return (NULL); |
return (NULL); |
while ((i = read(ifd, buf, BUFSIZ)) > 0) { |
unlink(tempfile); |
if (write(ofd, buf, i) != i) |
while ((nread = read(ifd, buf, BUFSIZ)) > 0) { |
|
if (write(ofd, buf, nread) != nread) { |
|
close(ifd); |
|
close(ofd); |
return (NULL); |
return (NULL); |
|
} |
} |
} |
close(ifd); |
close(ifd); |
close(ofd); |
return (fdopen(ofd, "r")); |
return (tempfile); |
|
} |
} |
|
|
char * |
char * |
|
|
{ |
{ |
char *tail, *buf; |
char *tail, *buf; |
|
|
tail = strrchr(file, '/'); |
if ((tail = strrchr(file, '/')) == NULL) |
if (tail == NULL) |
|
tail = file; |
tail = file; |
else |
else |
tail++; |
tail++; |