Page MenuHomeFreeBSD

D28402.1789700267.diff
No OneTemporary

Size
5 KB
Referenced Files
None
Subscribers
None

D28402.1789700267.diff

Index: usr.bin/diff/diffreg.c
===================================================================
--- usr.bin/diff/diffreg.c
+++ usr.bin/diff/diffreg.c
@@ -71,6 +71,7 @@
#include <sys/capsicum.h>
#include <sys/stat.h>
+#include <sys/mman.h>
#include <capsicum_helpers.h>
#include <ctype.h>
@@ -190,7 +191,7 @@
static void uni_range(int, int);
static void dump_context_vec(FILE *, FILE *, int);
static void dump_unified_vec(FILE *, FILE *, int);
-static bool prepare(int, FILE *, size_t, int);
+static bool prepare(int, const uint8_t *, size_t, int);
static void prune(void);
static void equiv(struct line *, int, struct line *, int, int *);
static void unravel(int);
@@ -208,8 +209,8 @@
static int skipline(FILE *);
static int isqrt(int);
static int stone(int *, int, int *, int *, int);
-static enum readhash readhash(FILE *, int, unsigned *);
-static int files_differ(FILE *, FILE *, int);
+static enum readhash readhash(const uint8_t **, const uint8_t *, int, unsigned *);
+static int files_differ(const uint8_t *, const uint8_t *, int);
static char *match_function(const long *, int, FILE *);
static char *preadline(int, size_t, off_t);
@@ -258,11 +259,13 @@
diffreg(char *file1, char *file2, int flags, int capsicum)
{
FILE *f1, *f2;
+ uint8_t *filemmap1, *filemmap2;
int i, rval;
struct pr *pr = NULL;
cap_rights_t rights_ro;
f1 = f2 = NULL;
+ filemmap1 = filemmap2 = NULL;
rval = D_SAME;
anychange = 0;
lastline = 0;
@@ -343,7 +346,8 @@
pr = start_pr(file1, file2);
if (capsicum) {
- cap_rights_init(&rights_ro, CAP_READ, CAP_FSTAT, CAP_SEEK);
+ cap_rights_init(&rights_ro, CAP_READ, CAP_FSTAT, CAP_SEEK,
+ CAP_MMAP);
if (caph_rights_limit(fileno(f1), &rights_ro) < 0)
err(2, "unable to limit rights on: %s", file1);
if (caph_rights_limit(fileno(f2), &rights_ro) < 0)
@@ -362,18 +366,15 @@
if (caph_enter() < 0)
err(2, "unable to enter capability mode");
}
-
- switch (files_differ(f1, f2, flags)) {
- case 0:
+ filemmap1 = mmap(NULL, stb1.st_size, PROT_READ, MAP_SHARED, fileno(f1), 0);
+ if (filemmap1 == NULL)
+ err(2, "unable to mmap");
+ filemmap2 = mmap(NULL, stb2.st_size, PROT_READ, MAP_SHARED, fileno(f2), 0);
+ if (filemmap2 == NULL)
+ err(2, "unable to mmap");
+
+ if (files_differ(filemmap2, filemmap2, flags) == 0)
goto closem;
- case 1:
- break;
- default:
- /* error */
- rval = D_ERROR;
- status |= 2;
- goto closem;
- }
if (diff_format == D_BRIEF && ignore_pats == NULL &&
(flags & (D_FOLDBLANKS|D_IGNOREBLANKS|D_IGNORECASE|D_STRIPCR)) == 0)
@@ -383,11 +384,11 @@
goto closem;
}
if ((flags & D_FORCEASCII) != 0) {
- (void)prepare(0, f1, stb1.st_size, flags);
- (void)prepare(1, f2, stb2.st_size, flags);
+ (void)prepare(0, filemmap1, stb1.st_size, flags);
+ (void)prepare(1, filemmap2, stb2.st_size, flags);
} else if (!asciifile(f1) || !asciifile(f2) ||
- !prepare(0, f1, stb1.st_size, flags) ||
- !prepare(1, f2, stb2.st_size, flags)) {
+ !prepare(0, filemmap1, stb1.st_size, flags) ||
+ !prepare(1, filemmap2, stb2.st_size, flags)) {
rval = D_BINARY;
status |= 1;
goto closem;
@@ -431,6 +432,10 @@
if (rval == D_SAME)
rval = D_DIFFER;
}
+ if (filemmap1 != NULL)
+ munmap(filemmap1, stb1.st_size);
+ if (filemmap2 != NULL)
+ munmap(filemmap2, stb2.st_size);
if (f1 != NULL)
fclose(f1);
if (f2 != NULL)
@@ -441,30 +446,16 @@
/*
* Check to see if the given files differ.
- * Returns 0 if they are the same, 1 if different, and -1 on error.
- * XXX - could use code from cmp(1) [faster]
+ * Returns 0 if they are the same, 1 if different.
*/
static int
-files_differ(FILE *f1, FILE *f2, int flags)
+files_differ(const uint8_t *filemmap1, const uint8_t *filemmap2, int flags)
{
- char buf1[BUFSIZ], buf2[BUFSIZ];
- size_t i, j;
-
if ((flags & (D_EMPTY1|D_EMPTY2)) || stb1.st_size != stb2.st_size ||
(stb1.st_mode & S_IFMT) != (stb2.st_mode & S_IFMT))
return (1);
- for (;;) {
- i = fread(buf1, 1, sizeof(buf1), f1);
- j = fread(buf2, 1, sizeof(buf2), f2);
- if ((!i && ferror(f1)) || (!j && ferror(f2)))
- return (-1);
- if (i != j)
- return (1);
- if (i == 0)
- return (0);
- if (memcmp(buf1, buf2, i) != 0)
- return (1);
- }
+
+ return (memcmp(filemmap1, filemmap2, stb1.st_size) != 0);
}
static FILE *
@@ -516,21 +507,20 @@
}
static bool
-prepare(int i, FILE *fd, size_t filesize, int flags)
+prepare(int i, const uint8_t *walk, size_t filesize, int flags)
{
struct line *p;
unsigned h;
size_t sz, j = 0;
enum readhash r;
-
- rewind(fd);
+ const uint8_t *end = buf + filesize;
sz = MIN(filesize, SIZE_MAX) / 25;
if (sz < 100)
sz = 100;
p = xcalloc(sz + 3, sizeof(*p));
- while ((r = readhash(fd, flags, &h)) != RH_EOF)
+ while ((r = readhash(&walk, end, flags, &h)) != RH_EOF)
switch (r) {
case RH_EOF: /* otherwise clang complains */
case RH_BINARY:
@@ -1364,24 +1354,25 @@
* Hash function taken from Robert Sedgewick, Algorithms in C, 3d ed., p 578.
*/
static enum readhash
-readhash(FILE *f, int flags, unsigned *hash)
+readhash(const uint8_t **buf, const uint8_t *end, int flags, unsigned *hash)
{
- int i, t, space;
+ int t, space;
unsigned sum;
+ const uint8_t *walk = *buf;
sum = 1;
space = 0;
- for (i = 0;;) {
- switch (t = getc(f)) {
+ if (walk == end)
+ return (RH_EOF);
+ for (; walk < end; walk++) {
+ switch (t = *walk) {
case '\0':
if ((flags & D_FORCEASCII) == 0)
return (RH_BINARY);
case '\r':
- if (flags & D_STRIPCR) {
- t = getc(f);
- if (t == '\n')
- break;
- ungetc(t, f);
+ if (flags & D_STRIPCR && walk + 1 != end && walk[1] == '\n') {
+ walk += 2;
+ break;
}
/* FALLTHROUGH */
case '\t':
@@ -1395,21 +1386,18 @@
/* FALLTHROUGH */
default:
if (space && (flags & D_IGNOREBLANKS) == 0) {
- i++;
space = 0;
}
sum = sum * 127 + chrtran(t);
- i++;
continue;
- case EOF:
- if (i == 0)
- return (RH_EOF);
/* FALLTHROUGH */
case '\n':
+ walk++;
break;
}
break;
}
+ *buf = walk;
*hash = sum;
return (RH_OK);
}

File Metadata

Mime Type
text/plain
Expires
Fri, Sep 18, 2:57 AM (11 h, 33 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
29719495
Default Alt Text
D28402.1789700267.diff (5 KB)

Event Timeline