Blob


1 /* $OpenBSD: rcsutil.c,v 1.46 2017/08/29 16:47:33 otto Exp $ */
2 /*
3 * Copyright (c) 2005, 2006 Joris Vink <joris@openbsd.org>
4 * Copyright (c) 2006 Xavier Santolaria <xsa@openbsd.org>
5 * Copyright (c) 2006 Niall O'Higgins <niallo@openbsd.org>
6 * Copyright (c) 2006 Ray Lai <ray@openbsd.org>
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 *
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
19 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
20 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
21 * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
24 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
26 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
27 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
30 #include <sys/queue.h>
32 #include <ctype.h>
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include <unistd.h>
38 #include "got_compat.h"
40 #include "buf.h"
41 #include "rcsutil.h"
43 /*
44 * Split the contents of a file into a list of lines.
45 */
46 struct rcs_lines *
47 rcs_splitlines(u_char *data, size_t len)
48 {
49 u_char *c, *p;
50 struct rcs_lines *lines;
51 struct rcs_line *lp;
52 size_t i, tlen;
54 lines = calloc(1, sizeof(*lines));
55 if (lines == NULL)
56 return NULL;
57 TAILQ_INIT(&(lines->l_lines));
59 lp = calloc(1, sizeof(*lp));
60 if (lp == NULL) {
61 free(lines);
62 return NULL;
63 }
64 TAILQ_INSERT_TAIL(&(lines->l_lines), lp, l_list);
66 p = c = data;
67 for (i = 0; i < len; i++) {
68 if (*p == '\n' || (i == len - 1)) {
69 tlen = p - c + 1;
70 lp = malloc(sizeof(*lp));
71 if (lp == NULL) {
72 rcs_freelines(lines);
73 return NULL;
74 }
75 lp->l_line = c;
76 lp->l_len = tlen;
77 lp->l_lineno = ++(lines->l_nblines);
78 TAILQ_INSERT_TAIL(&(lines->l_lines), lp, l_list);
79 c = p + 1;
80 }
81 p++;
82 }
84 return (lines);
85 }
87 void
88 rcs_freelines(struct rcs_lines *lines)
89 {
90 struct rcs_line *lp;
92 while ((lp = TAILQ_FIRST(&(lines->l_lines))) != NULL) {
93 TAILQ_REMOVE(&(lines->l_lines), lp, l_list);
94 free(lp);
95 }
97 free(lines);
98 }
100 BUF *
101 rcs_patchfile(u_char *data, size_t dlen, u_char *patch, size_t plen,
102 int (*p)(struct rcs_lines *, struct rcs_lines *))
104 const struct got_error *err = NULL;
105 struct rcs_lines *dlines, *plines;
106 struct rcs_line *lp;
107 BUF *res;
108 size_t newlen;
110 dlines = rcs_splitlines(data, dlen);
111 plines = rcs_splitlines(patch, plen);
113 if (p(dlines, plines) < 0) {
114 rcs_freelines(dlines);
115 rcs_freelines(plines);
116 return (NULL);
119 err = buf_alloc(&res, 1024);
120 if (err)
121 return NULL;
122 TAILQ_FOREACH(lp, &dlines->l_lines, l_list) {
123 if (lp->l_line == NULL)
124 continue;
125 buf_append(&newlen, res, lp->l_line, lp->l_len);
128 rcs_freelines(dlines);
129 rcs_freelines(plines);
130 return (res);