| GCC Code Coverage Report | |||||||||||||||||||||
        
  | 
    |||||||||||||||||||||
| Line | Branch | Exec | Source | 
1  | 
    /* $OpenBSD: rcsdiff.c,v 1.84 2015/11/02 16:45:21 nicm Exp $ */  | 
    ||
2  | 
    /*  | 
    ||
3  | 
    * Copyright (c) 2005 Joris Vink <joris@openbsd.org>  | 
    ||
4  | 
    * All rights reserved.  | 
    ||
5  | 
    *  | 
    ||
6  | 
    * Redistribution and use in source and binary forms, with or without  | 
    ||
7  | 
    * modification, are permitted provided that the following conditions  | 
    ||
8  | 
    * are met:  | 
    ||
9  | 
    *  | 
    ||
10  | 
    * 1. Redistributions of source code must retain the above copyright  | 
    ||
11  | 
    * notice, this list of conditions and the following disclaimer.  | 
    ||
12  | 
    * 2. The name of the author may not be used to endorse or promote products  | 
    ||
13  | 
    * derived from this software without specific prior written permission.  | 
    ||
14  | 
    *  | 
    ||
15  | 
    * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,  | 
    ||
16  | 
    * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY  | 
    ||
17  | 
    * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL  | 
    ||
18  | 
    * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,  | 
    ||
19  | 
    * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,  | 
    ||
20  | 
    * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;  | 
    ||
21  | 
    * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,  | 
    ||
22  | 
    * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR  | 
    ||
23  | 
    * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF  | 
    ||
24  | 
    * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.  | 
    ||
25  | 
    */  | 
    ||
26  | 
    |||
27  | 
    #include <sys/stat.h>  | 
    ||
28  | 
    #include <sys/time.h>  | 
    ||
29  | 
    |||
30  | 
    #include <err.h>  | 
    ||
31  | 
    #include <fcntl.h>  | 
    ||
32  | 
    #include <stdio.h>  | 
    ||
33  | 
    #include <stdlib.h>  | 
    ||
34  | 
    #include <string.h>  | 
    ||
35  | 
    #include <unistd.h>  | 
    ||
36  | 
    |||
37  | 
    #include "rcsprog.h"  | 
    ||
38  | 
    #include "diff.h"  | 
    ||
39  | 
    |||
40  | 
    static int rcsdiff_file(RCSFILE *, RCSNUM *, const char *, int);  | 
    ||
41  | 
    static int rcsdiff_rev(RCSFILE *, RCSNUM *, RCSNUM *, int);  | 
    ||
42  | 
    static void push_ignore_pats(char *);  | 
    ||
43  | 
    |||
44  | 
    static int quiet;  | 
    ||
45  | 
    static int kflag = RCS_KWEXP_ERR;  | 
    ||
46  | 
    static char *diff_ignore_pats;  | 
    ||
47  | 
    |||
48  | 
    int  | 
    ||
49  | 
    rcsdiff_main(int argc, char **argv)  | 
    ||
50  | 
    { | 
    ||
51  | 
    int fd, i, ch, dflags, status;  | 
    ||
52  | 
    RCSNUM *rev1, *rev2;  | 
    ||
53  | 
    RCSFILE *file;  | 
    ||
54  | 
    8  | 
    char fpath[PATH_MAX], *rev_str1, *rev_str2;  | 
    |
55  | 
    4  | 
    const char *errstr;  | 
    |
56  | 
    |||
57  | 
    rev1 = rev2 = NULL;  | 
    ||
58  | 
    4  | 
    rev_str1 = rev_str2 = NULL;  | 
    |
59  | 
    status = D_SAME;  | 
    ||
60  | 
    dflags = 0;  | 
    ||
61  | 
    |||
62  | 
    ✗✓ | 4  | 
    if (strlcpy(diffargs, "diff", sizeof(diffargs)) >= sizeof(diffargs))  | 
    
63  | 
    errx(D_ERROR, "diffargs too long");  | 
    ||
64  | 
    |||
65  | 
    ✓✓ | 17  | 
    	while ((ch = rcs_getopt(argc, argv, "abC:cdI:ik:npqr:TtU:uVwx::z::")) != -1) { | 
    
66  | 
    ✓✗✗✗ ✗✗✗✗ ✗✗✗✓ ✓✗✗✓ ✗✗✗✗ ✗  | 
    26  | 
    		switch (ch) { | 
    
67  | 
    case 'a':  | 
    ||
68  | 
    if (strlcat(diffargs, " -a", sizeof(diffargs)) >=  | 
    ||
69  | 
    sizeof(diffargs))  | 
    ||
70  | 
    errx(D_ERROR, "diffargs too long");  | 
    ||
71  | 
    dflags |= D_FORCEASCII;  | 
    ||
72  | 
    break;  | 
    ||
73  | 
    case 'b':  | 
    ||
74  | 
    if (strlcat(diffargs, " -b", sizeof(diffargs)) >=  | 
    ||
75  | 
    sizeof(diffargs))  | 
    ||
76  | 
    errx(D_ERROR, "diffargs too long");  | 
    ||
77  | 
    dflags |= D_FOLDBLANKS;  | 
    ||
78  | 
    break;  | 
    ||
79  | 
    case 'C':  | 
    ||
80  | 
    (void)strlcat(diffargs, " -C", sizeof(diffargs));  | 
    ||
81  | 
    if (strlcat(diffargs, rcs_optarg, sizeof(diffargs)) >=  | 
    ||
82  | 
    sizeof(diffargs))  | 
    ||
83  | 
    errx(D_ERROR, "diffargs too long");  | 
    ||
84  | 
    diff_context = strtonum(rcs_optarg, 0, INT_MAX, &errstr);  | 
    ||
85  | 
    if (errstr)  | 
    ||
86  | 
    errx(D_ERROR, "context is %s: %s",  | 
    ||
87  | 
    errstr, rcs_optarg);  | 
    ||
88  | 
    diff_format = D_CONTEXT;  | 
    ||
89  | 
    break;  | 
    ||
90  | 
    case 'c':  | 
    ||
91  | 
    if (strlcat(diffargs, " -c", sizeof(diffargs)) >=  | 
    ||
92  | 
    sizeof(diffargs))  | 
    ||
93  | 
    errx(D_ERROR, "diffargs too long");  | 
    ||
94  | 
    diff_format = D_CONTEXT;  | 
    ||
95  | 
    break;  | 
    ||
96  | 
    case 'd':  | 
    ||
97  | 
    if (strlcat(diffargs, " -d", sizeof(diffargs)) >=  | 
    ||
98  | 
    sizeof(diffargs))  | 
    ||
99  | 
    errx(D_ERROR, "diffargs too long");  | 
    ||
100  | 
    dflags |= D_MINIMAL;  | 
    ||
101  | 
    break;  | 
    ||
102  | 
    case 'i':  | 
    ||
103  | 
    if (strlcat(diffargs, " -i", sizeof(diffargs)) >=  | 
    ||
104  | 
    sizeof(diffargs))  | 
    ||
105  | 
    errx(D_ERROR, "diffargs too long");  | 
    ||
106  | 
    dflags |= D_IGNORECASE;  | 
    ||
107  | 
    break;  | 
    ||
108  | 
    case 'I':  | 
    ||
109  | 
    (void)strlcat(diffargs, " -I", sizeof(diffargs));  | 
    ||
110  | 
    if (strlcat(diffargs, rcs_optarg, sizeof(diffargs)) >=  | 
    ||
111  | 
    sizeof(diffargs))  | 
    ||
112  | 
    errx(D_ERROR, "diffargs too long");  | 
    ||
113  | 
    push_ignore_pats(rcs_optarg);  | 
    ||
114  | 
    break;  | 
    ||
115  | 
    case 'k':  | 
    ||
116  | 
    kflag = rcs_kflag_get(rcs_optarg);  | 
    ||
117  | 
    			if (RCS_KWEXP_INVAL(kflag)) { | 
    ||
118  | 
    				warnx("invalid RCS keyword substitution mode"); | 
    ||
119  | 
    (usage)();  | 
    ||
120  | 
    }  | 
    ||
121  | 
    break;  | 
    ||
122  | 
    case 'n':  | 
    ||
123  | 
    if (strlcat(diffargs, " -n", sizeof(diffargs)) >=  | 
    ||
124  | 
    sizeof(diffargs))  | 
    ||
125  | 
    errx(D_ERROR, "diffargs too long");  | 
    ||
126  | 
    diff_format = D_RCSDIFF;  | 
    ||
127  | 
    break;  | 
    ||
128  | 
    case 'p':  | 
    ||
129  | 
    if (strlcat(diffargs, " -p", sizeof(diffargs)) >=  | 
    ||
130  | 
    sizeof(diffargs))  | 
    ||
131  | 
    errx(D_ERROR, "diffargs too long");  | 
    ||
132  | 
    dflags |= D_PROTOTYPE;  | 
    ||
133  | 
    break;  | 
    ||
134  | 
    case 'q':  | 
    ||
135  | 
    4  | 
    quiet = 1;  | 
    |
136  | 
    4  | 
    break;  | 
    |
137  | 
    case 'r':  | 
    ||
138  | 
    5  | 
    rcs_setrevstr2(&rev_str1, &rev_str2, rcs_optarg);  | 
    |
139  | 
    5  | 
    break;  | 
    |
140  | 
    case 'T':  | 
    ||
141  | 
    /*  | 
    ||
142  | 
    * kept for compatibility  | 
    ||
143  | 
    */  | 
    ||
144  | 
    break;  | 
    ||
145  | 
    case 't':  | 
    ||
146  | 
    if (strlcat(diffargs, " -t", sizeof(diffargs)) >=  | 
    ||
147  | 
    sizeof(diffargs))  | 
    ||
148  | 
    errx(D_ERROR, "diffargs too long");  | 
    ||
149  | 
    dflags |= D_EXPANDTABS;  | 
    ||
150  | 
    break;  | 
    ||
151  | 
    case 'U':  | 
    ||
152  | 
    (void)strlcat(diffargs, " -U", sizeof(diffargs));  | 
    ||
153  | 
    if (strlcat(diffargs, rcs_optarg, sizeof(diffargs)) >=  | 
    ||
154  | 
    sizeof(diffargs))  | 
    ||
155  | 
    errx(D_ERROR, "diffargs too long");  | 
    ||
156  | 
    diff_context = strtonum(rcs_optarg, 0, INT_MAX, &errstr);  | 
    ||
157  | 
    if (errstr)  | 
    ||
158  | 
    errx(D_ERROR, "context is %s: %s",  | 
    ||
159  | 
    errstr, rcs_optarg);  | 
    ||
160  | 
    diff_format = D_UNIFIED;  | 
    ||
161  | 
    break;  | 
    ||
162  | 
    case 'u':  | 
    ||
163  | 
    ✗✓ | 4  | 
    if (strlcat(diffargs, " -u", sizeof(diffargs)) >=  | 
    
164  | 
    sizeof(diffargs))  | 
    ||
165  | 
    errx(D_ERROR, "diffargs too long");  | 
    ||
166  | 
    4  | 
    diff_format = D_UNIFIED;  | 
    |
167  | 
    4  | 
    break;  | 
    |
168  | 
    case 'V':  | 
    ||
169  | 
    			printf("%s\n", rcs_version); | 
    ||
170  | 
    exit(0);  | 
    ||
171  | 
    case 'w':  | 
    ||
172  | 
    if (strlcat(diffargs, " -w", sizeof(diffargs)) >=  | 
    ||
173  | 
    sizeof(diffargs))  | 
    ||
174  | 
    errx(D_ERROR, "diffargs too long");  | 
    ||
175  | 
    dflags |= D_IGNOREBLANKS;  | 
    ||
176  | 
    break;  | 
    ||
177  | 
    case 'x':  | 
    ||
178  | 
    /* Use blank extension if none given. */  | 
    ||
179  | 
    rcs_suffixes = rcs_optarg ? rcs_optarg : "";  | 
    ||
180  | 
    break;  | 
    ||
181  | 
    case 'z':  | 
    ||
182  | 
    timezone_flag = rcs_optarg;  | 
    ||
183  | 
    break;  | 
    ||
184  | 
    default:  | 
    ||
185  | 
    (usage)();  | 
    ||
186  | 
    }  | 
    ||
187  | 
    }  | 
    ||
188  | 
    |||
189  | 
    4  | 
    argc -= rcs_optind;  | 
    |
190  | 
    4  | 
    argv += rcs_optind;  | 
    |
191  | 
    |||
192  | 
    ✗✓ | 4  | 
    	if (argc == 0) { | 
    
193  | 
    		warnx("no input file"); | 
    ||
194  | 
    (usage)();  | 
    ||
195  | 
    }  | 
    ||
196  | 
    |||
197  | 
    ✗✓ | 4  | 
    	if (diff_ignore_pats != NULL) { | 
    
198  | 
    char buf[BUFSIZ];  | 
    ||
199  | 
    int error;  | 
    ||
200  | 
    |||
201  | 
    diff_ignore_re = xmalloc(sizeof(*diff_ignore_re));  | 
    ||
202  | 
    if ((error = regcomp(diff_ignore_re, diff_ignore_pats,  | 
    ||
203  | 
    		    REG_NEWLINE | REG_EXTENDED)) != 0) { | 
    ||
204  | 
    regerror(error, diff_ignore_re, buf, sizeof(buf));  | 
    ||
205  | 
    if (*diff_ignore_pats != '\0')  | 
    ||
206  | 
    errx(D_ERROR, "%s: %s", diff_ignore_pats, buf);  | 
    ||
207  | 
    else  | 
    ||
208  | 
    errx(D_ERROR, "%s", buf);  | 
    ||
209  | 
    }  | 
    ||
210  | 
    }  | 
    ||
211  | 
    |||
212  | 
    ✓✓ | 16  | 
    	for (i = 0; i < argc; i++) { | 
    
213  | 
    4  | 
    fd = rcs_choosefile(argv[i], fpath, sizeof(fpath));  | 
    |
214  | 
    ✗✓ | 4  | 
    		if (fd < 0) { | 
    
215  | 
    			warn("%s", fpath); | 
    ||
216  | 
    continue;  | 
    ||
217  | 
    }  | 
    ||
218  | 
    |||
219  | 
    ✓✗ | 8  | 
    if ((file = rcs_open(fpath, fd,  | 
    
220  | 
    4  | 
    RCS_READ|RCS_PARSE_FULLY)) == NULL)  | 
    |
221  | 
    continue;  | 
    ||
222  | 
    |||
223  | 
    4  | 
    rcs_kwexp_set(file, kflag);  | 
    |
224  | 
    |||
225  | 
    ✓✓ | 4  | 
    		if (rev_str1 != NULL) { | 
    
226  | 
    ✗✓ | 3  | 
    if ((rev1 = rcs_getrevnum(rev_str1, file)) == NULL)  | 
    
227  | 
    errx(D_ERROR, "bad revision number");  | 
    ||
228  | 
    }  | 
    ||
229  | 
    ✓✓ | 4  | 
    		if (rev_str2 != NULL) { | 
    
230  | 
    ✗✓ | 2  | 
    if ((rev2 = rcs_getrevnum(rev_str2, file)) == NULL)  | 
    
231  | 
    errx(D_ERROR, "bad revision number");  | 
    ||
232  | 
    }  | 
    ||
233  | 
    |||
234  | 
    ✗✓ | 4  | 
    		if (!quiet) { | 
    
235  | 
    fprintf(stderr, "%s\n", RCS_DIFF_DIV);  | 
    ||
236  | 
    fprintf(stderr, "RCS file: %s\n", fpath);  | 
    ||
237  | 
    }  | 
    ||
238  | 
    |||
239  | 
    4  | 
    diff_file = argv[i];  | 
    |
240  | 
    |||
241  | 
    /* No revisions given. */  | 
    ||
242  | 
    ✓✓ | 4  | 
    if (rev_str1 == NULL)  | 
    
243  | 
    1  | 
    status = rcsdiff_file(file, file->rf_head, argv[i],  | 
    |
244  | 
    dflags);  | 
    ||
245  | 
    /* One revision given. */  | 
    ||
246  | 
    ✓✓ | 3  | 
    else if (rev_str2 == NULL)  | 
    
247  | 
    1  | 
    status = rcsdiff_file(file, rev1, argv[i], dflags);  | 
    |
248  | 
    /* Two revisions given. */  | 
    ||
249  | 
    else  | 
    ||
250  | 
    2  | 
    status = rcsdiff_rev(file, rev1, rev2, dflags);  | 
    |
251  | 
    |||
252  | 
    4  | 
    rcs_close(file);  | 
    |
253  | 
    4  | 
    rcsnum_free(rev1);  | 
    |
254  | 
    4  | 
    rcsnum_free(rev2);  | 
    |
255  | 
    rev1 = rev2 = NULL;  | 
    ||
256  | 
    4  | 
    }  | 
    |
257  | 
    |||
258  | 
    4  | 
    return (status);  | 
    |
259  | 
    4  | 
    }  | 
    |
260  | 
    |||
261  | 
    __dead void  | 
    ||
262  | 
    rcsdiff_usage(void)  | 
    ||
263  | 
    { | 
    ||
264  | 
    fprintf(stderr,  | 
    ||
265  | 
    "usage: rcsdiff [-cnquV] [-kmode] [-rrev] [-xsuffixes] [-ztz]\n"  | 
    ||
266  | 
    " [diff_options] file ...\n");  | 
    ||
267  | 
    |||
268  | 
    exit(D_ERROR);  | 
    ||
269  | 
    }  | 
    ||
270  | 
    |||
271  | 
    static int  | 
    ||
272  | 
    rcsdiff_file(RCSFILE *file, RCSNUM *rev, const char *filename, int dflags)  | 
    ||
273  | 
    { | 
    ||
274  | 
    int ret, fd;  | 
    ||
275  | 
    time_t t;  | 
    ||
276  | 
    4  | 
    struct stat st;  | 
    |
277  | 
    2  | 
    char *path1, *path2;  | 
    |
278  | 
    BUF *b1, *b2;  | 
    ||
279  | 
    2  | 
    char rbuf[RCS_REV_BUFSZ];  | 
    |
280  | 
    struct tm *tb;  | 
    ||
281  | 
    2  | 
    struct timeval tv[2], tv2[2];  | 
    |
282  | 
    |||
283  | 
    2  | 
    memset(&tv, 0, sizeof(tv));  | 
    |
284  | 
    2  | 
    memset(&tv2, 0, sizeof(tv2));  | 
    |
285  | 
    |||
286  | 
    ret = D_ERROR;  | 
    ||
287  | 
    b1 = b2 = NULL;  | 
    ||
288  | 
    |||
289  | 
    2  | 
    diff_rev1 = rev;  | 
    |
290  | 
    2  | 
    diff_rev2 = NULL;  | 
    |
291  | 
    2  | 
    path1 = path2 = NULL;  | 
    |
292  | 
    |||
293  | 
    ✗✓ | 2  | 
    	if ((fd = open(filename, O_RDONLY)) == -1) { | 
    
294  | 
    		warn("%s", filename); | 
    ||
295  | 
    goto out;  | 
    ||
296  | 
    }  | 
    ||
297  | 
    |||
298  | 
    2  | 
    rcsnum_tostr(rev, rbuf, sizeof(rbuf));  | 
    |
299  | 
    ✗✓ | 2  | 
    	if (!quiet) { | 
    
300  | 
    fprintf(stderr, "retrieving revision %s\n", rbuf);  | 
    ||
301  | 
    fprintf(stderr, "%s -r%s %s\n", diffargs, rbuf, filename);  | 
    ||
302  | 
    }  | 
    ||
303  | 
    |||
304  | 
    ✗✓ | 2  | 
    	if ((b1 = rcs_getrev(file, rev)) == NULL) { | 
    
305  | 
    		warnx("failed to retrieve revision %s", rbuf); | 
    ||
306  | 
    goto out;  | 
    ||
307  | 
    }  | 
    ||
308  | 
    |||
309  | 
    2  | 
    b1 = rcs_kwexp_buf(b1, file, rev);  | 
    |
310  | 
    2  | 
    tv[0].tv_sec = rcs_rev_getdate(file, rev);  | 
    |
311  | 
    2  | 
    tv[1].tv_sec = tv[0].tv_sec;  | 
    |
312  | 
    |||
313  | 
    ✗✓ | 2  | 
    	if ((b2 = buf_load(filename)) == NULL) { | 
    
314  | 
    		warnx("failed to load file: `%s'", filename); | 
    ||
315  | 
    goto out;  | 
    ||
316  | 
    }  | 
    ||
317  | 
    |||
318  | 
    /* XXX - GNU uses GMT */  | 
    ||
319  | 
    ✗✓ | 2  | 
    if (fstat(fd, &st) == -1)  | 
    
320  | 
    err(D_ERROR, "%s", filename);  | 
    ||
321  | 
    |||
322  | 
    2  | 
    tb = gmtime(&st.st_mtime);  | 
    |
323  | 
    2  | 
    t = mktime(tb);  | 
    |
324  | 
    |||
325  | 
    2  | 
    tv2[0].tv_sec = t;  | 
    |
326  | 
    2  | 
    tv2[1].tv_sec = t;  | 
    |
327  | 
    |||
328  | 
    2  | 
    (void)xasprintf(&path1, "%s/diff1.XXXXXXXXXX", rcs_tmpdir);  | 
    |
329  | 
    2  | 
    buf_write_stmp(b1, path1);  | 
    |
330  | 
    |||
331  | 
    2  | 
    buf_free(b1);  | 
    |
332  | 
    b1 = NULL;  | 
    ||
333  | 
    |||
334  | 
    ✗✓ | 2  | 
    if (utimes(path1, (const struct timeval *)&tv) < 0)  | 
    
335  | 
    		warn("utimes"); | 
    ||
336  | 
    |||
337  | 
    2  | 
    (void)xasprintf(&path2, "%s/diff2.XXXXXXXXXX", rcs_tmpdir);  | 
    |
338  | 
    2  | 
    buf_write_stmp(b2, path2);  | 
    |
339  | 
    |||
340  | 
    2  | 
    buf_free(b2);  | 
    |
341  | 
    b2 = NULL;  | 
    ||
342  | 
    |||
343  | 
    ✗✓ | 2  | 
    if (utimes(path2, (const struct timeval *)&tv2) < 0)  | 
    
344  | 
    		warn("utimes"); | 
    ||
345  | 
    |||
346  | 
    2  | 
    ret = diffreg(path1, path2, NULL, dflags);  | 
    |
347  | 
    |||
348  | 
    out:  | 
    ||
349  | 
    ✓✗ | 2  | 
    if (fd != -1)  | 
    
350  | 
    2  | 
    (void)close(fd);  | 
    |
351  | 
    2  | 
    buf_free(b1);  | 
    |
352  | 
    2  | 
    buf_free(b2);  | 
    |
353  | 
    2  | 
    free(path1);  | 
    |
354  | 
    2  | 
    free(path2);  | 
    |
355  | 
    |||
356  | 
    2  | 
    return (ret);  | 
    |
357  | 
    2  | 
    }  | 
    |
358  | 
    |||
359  | 
    static int  | 
    ||
360  | 
    rcsdiff_rev(RCSFILE *file, RCSNUM *rev1, RCSNUM *rev2, int dflags)  | 
    ||
361  | 
    { | 
    ||
362  | 
    4  | 
    struct timeval tv[2], tv2[2];  | 
    |
363  | 
    BUF *b1, *b2;  | 
    ||
364  | 
    int ret;  | 
    ||
365  | 
    2  | 
    char *path1, *path2, rbuf1[RCS_REV_BUFSZ], rbuf2[RCS_REV_BUFSZ];  | 
    |
366  | 
    |||
367  | 
    ret = D_ERROR;  | 
    ||
368  | 
    b1 = b2 = NULL;  | 
    ||
369  | 
    2  | 
    memset(&tv, 0, sizeof(tv));  | 
    |
370  | 
    2  | 
    memset(&tv2, 0, sizeof(tv2));  | 
    |
371  | 
    |||
372  | 
    2  | 
    diff_rev1 = rev1;  | 
    |
373  | 
    2  | 
    diff_rev2 = rev2;  | 
    |
374  | 
    2  | 
    path1 = path2 = NULL;  | 
    |
375  | 
    |||
376  | 
    2  | 
    rcsnum_tostr(rev1, rbuf1, sizeof(rbuf1));  | 
    |
377  | 
    ✗✓ | 2  | 
    if (!quiet)  | 
    
378  | 
    fprintf(stderr, "retrieving revision %s\n", rbuf1);  | 
    ||
379  | 
    |||
380  | 
    ✗✓ | 2  | 
    	if ((b1 = rcs_getrev(file, rev1)) == NULL) { | 
    
381  | 
    		warnx("failed to retrieve revision %s", rbuf1); | 
    ||
382  | 
    goto out;  | 
    ||
383  | 
    }  | 
    ||
384  | 
    |||
385  | 
    2  | 
    b1 = rcs_kwexp_buf(b1, file, rev1);  | 
    |
386  | 
    2  | 
    tv[0].tv_sec = rcs_rev_getdate(file, rev1);  | 
    |
387  | 
    2  | 
    tv[1].tv_sec = tv[0].tv_sec;  | 
    |
388  | 
    |||
389  | 
    2  | 
    rcsnum_tostr(rev2, rbuf2, sizeof(rbuf2));  | 
    |
390  | 
    ✗✓ | 2  | 
    if (!quiet)  | 
    
391  | 
    fprintf(stderr, "retrieving revision %s\n", rbuf2);  | 
    ||
392  | 
    |||
393  | 
    ✗✓ | 2  | 
    	if ((b2 = rcs_getrev(file, rev2)) == NULL) { | 
    
394  | 
    		warnx("failed to retrieve revision %s", rbuf2); | 
    ||
395  | 
    goto out;  | 
    ||
396  | 
    }  | 
    ||
397  | 
    |||
398  | 
    2  | 
    b2 = rcs_kwexp_buf(b2, file, rev2);  | 
    |
399  | 
    2  | 
    tv2[0].tv_sec = rcs_rev_getdate(file, rev2);  | 
    |
400  | 
    2  | 
    tv2[1].tv_sec = tv2[0].tv_sec;  | 
    |
401  | 
    |||
402  | 
    ✗✓ | 2  | 
    if (!quiet)  | 
    
403  | 
    fprintf(stderr, "%s -r%s -r%s\n", diffargs, rbuf1, rbuf2);  | 
    ||
404  | 
    |||
405  | 
    2  | 
    (void)xasprintf(&path1, "%s/diff1.XXXXXXXXXX", rcs_tmpdir);  | 
    |
406  | 
    2  | 
    buf_write_stmp(b1, path1);  | 
    |
407  | 
    |||
408  | 
    2  | 
    buf_free(b1);  | 
    |
409  | 
    b1 = NULL;  | 
    ||
410  | 
    |||
411  | 
    ✗✓ | 2  | 
    if (utimes(path1, (const struct timeval *)&tv) < 0)  | 
    
412  | 
    		warn("utimes"); | 
    ||
413  | 
    |||
414  | 
    2  | 
    (void)xasprintf(&path2, "%s/diff2.XXXXXXXXXX", rcs_tmpdir);  | 
    |
415  | 
    2  | 
    buf_write_stmp(b2, path2);  | 
    |
416  | 
    |||
417  | 
    2  | 
    buf_free(b2);  | 
    |
418  | 
    b2 = NULL;  | 
    ||
419  | 
    |||
420  | 
    ✗✓ | 2  | 
    if (utimes(path2, (const struct timeval *)&tv2) < 0)  | 
    
421  | 
    		warn("utimes"); | 
    ||
422  | 
    |||
423  | 
    2  | 
    ret = diffreg(path1, path2, NULL, dflags);  | 
    |
424  | 
    |||
425  | 
    out:  | 
    ||
426  | 
    2  | 
    buf_free(b1);  | 
    |
427  | 
    2  | 
    buf_free(b2);  | 
    |
428  | 
    2  | 
    free(path1);  | 
    |
429  | 
    2  | 
    free(path2);  | 
    |
430  | 
    |||
431  | 
    2  | 
    return (ret);  | 
    |
432  | 
    2  | 
    }  | 
    |
433  | 
    |||
434  | 
    static void  | 
    ||
435  | 
    push_ignore_pats(char *pattern)  | 
    ||
436  | 
    { | 
    ||
437  | 
    size_t len;  | 
    ||
438  | 
    |||
439  | 
    	if (diff_ignore_pats == NULL) { | 
    ||
440  | 
    len = strlen(pattern) + 1;  | 
    ||
441  | 
    diff_ignore_pats = xmalloc(len);  | 
    ||
442  | 
    strlcpy(diff_ignore_pats, pattern, len);  | 
    ||
443  | 
    	} else { | 
    ||
444  | 
    /* old + "|" + new + NUL */  | 
    ||
445  | 
    len = strlen(diff_ignore_pats) + strlen(pattern) + 2;  | 
    ||
446  | 
    diff_ignore_pats = xreallocarray(diff_ignore_pats, len, 1);  | 
    ||
447  | 
    strlcat(diff_ignore_pats, "|", len);  | 
    ||
448  | 
    strlcat(diff_ignore_pats, pattern, len);  | 
    ||
449  | 
    }  | 
    ||
450  | 
    }  | 
    
| Generated by: GCOVR (Version 3.3) |