source: build-files/freebsd-update/src/findstamps.c @ 635dc54

9.2-releasereleng/10.0releng/10.0.1
Last change on this file since 635dc54 was 635dc54, checked in by Kris Moore <kris@…>, 10 months ago

Add our freebsd-update code to GIT

This will become a dumping ground for mods we may make to the freebsd-update
build process, as well as the specific patches we have going into a release

  • Property mode set to 100644
File size: 7.5 KB
Line 
1/*-
2 * Copyright 2006 Colin Percival
3 * All rights reserved
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted providing that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
18 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
22 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
23 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
24 * POSSIBILITY OF SUCH DAMAGE.
25 */
26
27#include <sys/cdefs.h>
28__FBSDID("$FreeBSD: user/cperciva/freebsd-update-build/src/findstamps.c 247826 2013-03-05 00:52:14Z cperciva $");
29
30#include <sys/types.h>
31
32#include <err.h>
33#include <stdint.h>
34#include <stdio.h>
35#include <stdlib.h>
36#include <string.h>
37
38static void usage(void);
39static void findstamps_text(FILE * F0, FILE * F1);
40static void findstamps_binary(FILE * F0, FILE * F1);
41
42static void
43usage(void)
44{
45        fprintf(stderr, "usage: findstamps [-t] file0 file1\n");
46        exit(1);
47        /* NOTREACHED */
48}
49
50/*
51 * A text buildstamp consists of a line of line of text (immediately
52 * preceded by a '\n' character, and ending with a '\n' character)
53 * which differs between the two files.  It is notated by the number
54 * of '\n' characters preceding it (i.e., files start at line zero).
55 */
56static void
57findstamps_text(FILE * F0, FILE * F1)
58{
59        int ch0, ch1;                   /* Characters read from F0, F1 */
60        off_t stampendpos;              /* Offset in F0 of end of stamp */
61        off_t linestartpos = 0;         /* Offset in F0 of start of line */
62        int linenum = 0;                /* Line number being examined */
63
64        do {
65                /* Read a character from each file */
66                ch0 = getc(F0);
67                ch1 = getc(F1);
68
69                /* Check for errors */
70                if (ferror(F0) || ferror(F1))
71                        err(1, "getc");
72
73                /* Have we reached the EOF of both files? */
74                if (feof(F0) && feof(F1))
75                        return;
76
77                /* Have we reached EOL in both files? */
78                if ((ch0 == '\n') && (ch1 == '\n')) {
79                        linestartpos = ftello(F0);
80                        linenum++;
81                }
82
83                /* If the characters are equal, keep on going */
84                if (ch0 == ch1)
85                        continue;
86
87                /*
88                 * We've found a difference between the two files.  Scan
89                 * forward in each line until we find a '\n'.  If we run
90                 * into EOF, exit with an error, since this means that
91                 * either the files have a different number of lines, or
92                 * the last line isn't EOL-terminated.
93                 */
94                printf("%d\n", linenum);
95                while (ch0 != '\n') {
96                        if (feof(F0))
97                                errx(1, "EOF encountered within stamp!");
98                        ch0 = getc(F0);
99                        if (ferror(F0))
100                                err(1, "getc");
101                }
102                while (ch1 != '\n') {
103                        if (feof(F1))
104                                errx(1, "EOF encountered within stamp!");
105                        ch1 = getc(F1);
106                        if (ferror(F1))
107                                err(1, "getc");
108                }
109
110                /* Go back and print out the stamp value */
111                stampendpos = ftello(F0);
112                if (fseeko(F0, linestartpos, SEEK_SET))
113                        err(1, "fseeko");
114                do {
115                        ch0 = getc(F0);
116                        if (ferror(F0))
117                                err(1, "getc");
118                        fprintf(stderr, "%c", ch0);
119                } while (ch0 != '\n');
120
121                /* We have reached EOL in both files */
122                linestartpos = ftello(F0);
123                linenum++;
124        } while (1);
125}
126
127/*
128 * A binary buildstamp consists of a series of "string" characters
129 * characters (immediately preceded by a non-string character),
130 * plus zero or more following NUL characters, which is different
131 * between the two files; a "string" character is something which
132 * isprint(3) agrees with, or an EOL character after a difference
133 * has already been seen.  Buildstamps are notated by the offset
134 * of the first character and the number of characters.
135 */
136/*-
137 * We find the stamps using a finite state machine; states 0, 1, and 2
138 * mean "between stamps", "inside a stamp", and "inside the trailing
139 * NUL characters of a stamp" respectively.
140 *
141 * State  Characters  New state  startpos  Output
142 * 0      non-string  0          pos + 1
143 * 1      non-string  0          pos + 1   yes
144 * 2      non-string  0          pos + 1   yes
145 * 0      string      0
146 * 1      string      1
147 * 2      string      0          pos       yes
148 * 0      mismatch    1
149 * 1      mismatch    1
150 * 2      mismatch    1          pos       yes
151 * 0      NUL         0          pos + 1
152 * 1      NUL         2
153 * 2      NUL         2
154 * 0      EOF         -1
155 * 1      EOF         -1                   yes
156 * 2      EOF         -1                   yes
157 */
158
159static void
160findstamps_binary(FILE * F0, FILE * F1)
161{
162        int ch0, ch1;                   /* Characters read from F0, F1 */
163        int state = 0;                  /* FSM state */
164        off_t pos = 0, spos = 0, newspos = 0;
165        int output = 0;
166
167        for (pos = 0; state != -1; pos++) {
168                /* Read a character from each file */
169                ch0 = getc(F0);
170                ch1 = getc(F1);
171
172                /* Check for errors */
173                if (ferror(F0) || ferror(F1))
174                        err(1, "getc");
175
176                if (ch0 != ch1) {               /* Non-matching characters */
177                        /* Check for EOF of either file */
178                        if (feof(F0) || feof(F1))
179                                errx(1, "Files have different lengths!");
180
181                        if (state == 2) {
182                                newspos = pos;
183                                output = 1;
184                        }
185                        state = 1;
186                } else if (ch0 == 0) {          /* Matching NUL characters */
187                        if (state == 0)
188                                newspos = pos + 1;
189                        else
190                                state = 2;
191                } else if (ch0 == EOF) {        /* EOF of both files */
192                        if (state != 0)
193                                output = 1;
194                        state = -1;
195                } else if (isprint(ch0) || (ch0 == '\n')) {
196                                        /* Matching string characters */
197                        if ((state == 0) && (ch0 == '\n')) {
198                                /* ok, actually not a string character */
199                                newspos = pos + 1;
200                        } else if (state == 2) {
201                                state = 0;
202                                newspos = pos;
203                                output = 1;
204                        }
205                } else {                /* Matching non-string characters */
206                        if (state != 0)
207                                output = 1;
208                        state = 0;
209                        newspos = pos + 1;
210                }
211
212                /* Output, if needed */
213                if (output) {
214                        printf("%ju|%ju\n", (uintmax_t)(spos),
215                            (uintmax_t)(pos - spos));
216
217                        /* Seek to start of buildstamp */
218                        if (fseeko(F0, spos, SEEK_SET))
219                                err(1, "fseeko");
220
221                        /* Print out buildstamp */
222                        for (; spos < pos; spos++) {
223                                /* Read a character */
224                                ch0 = getc(F0);
225                                if (ferror(F0))
226                                        err(1, "getc");
227
228                                /* Stop printing the stamp if we hit a NUL */
229                                if (ch0 == 0)
230                                        break;
231
232                                /* Print the character */
233                                fprintf(stderr, "%c", ch0);
234                                ch1 = ch0;
235                        }
236
237                        /* If we didn't end with a \n, print one now */
238                        if (ch1 != '\n')
239                                fprintf(stderr, "\n");
240
241                        /* Seek back to where we were before */
242                        if (fseeko(F0, pos + 1, SEEK_SET))
243                                err(1, "fseeko");
244                        output = 0;
245                }
246
247                /* Update spos */
248                spos = newspos;
249        }
250}
251
252int
253main(int argc, char *argv[])
254{
255        FILE * F0, * F1;
256        int tflag = 0;
257
258        /* Are we examining text files? */
259        if (argc < 2)
260                usage();
261        if (strcmp(argv[1], "-t") == 0) {
262                tflag = 1;
263                argc--;
264                argv++;
265        }
266
267        /* Open the files */
268        if (argc != 3)
269                usage();
270        if ((F0 = fopen(argv[1], "r")) == NULL)
271                err(1, "fopen(%s)", argv[1]);
272        if ((F1 = fopen(argv[2], "r")) == NULL)
273                err(1, "fopen(%s)", argv[2]);
274
275        /* Find the stamps */
276        if (tflag)
277                findstamps_text(F0, F1);
278        else
279                findstamps_binary(F0, F1);
280
281        /* Close the files */
282        if (fclose(F0))
283                err(1, "fclose(%s)", argv[1]);
284        if (fclose(F1))
285                err(1, "fclose(%s)", argv[2]);
286
287        return 0;
288}
Note: See TracBrowser for help on using the repository browser.