1 /*-
2 * Copyright (c) 2002-2005 MAEKAWA Masahide <maekawa@cvsync.org>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided 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 * 3. Neither the name of the author nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30 #include <sys/types.h>
31
32 #include <pthread.h>
33 #include <string.h>
34
35 #include "compat_stdbool.h"
36 #include "compat_stdint.h"
37 #include "compat_inttypes.h"
38 #include "basedef.h"
39
40 #include "hash.h"
41 #include "logmsg.h"
42 #include "mux.h"
43 #include "rdiff.h"
44
45 uint32_t
rdiff_weak(const uint8_t * addr,size_t size)46 rdiff_weak(const uint8_t *addr, size_t size)
47 {
48 uint16_t l_rv = 0, h_rv = 0;
49 size_t i;
50
51 for (i = 0 ; i < size ; i++) {
52 l_rv += addr[i];
53 h_rv += l_rv;
54 }
55
56 return ((h_rv << 16) | l_rv);
57 }
58
59 uint8_t *
rdiff_search(uint8_t * sp,uint8_t * bp,uint32_t bsize,size_t length,uint32_t weak,uint8_t * strong,const struct hash_args * hashops)60 rdiff_search(uint8_t *sp, uint8_t *bp, uint32_t bsize, size_t length,
61 uint32_t weak, uint8_t *strong, const struct hash_args *hashops)
62 {
63 uint32_t w;
64 uint16_t wl, wh, rwl, rwh;
65 uint8_t hash[HASH_MAXLEN];
66 void *ctx;
67 size_t len;
68
69 if ((len = bp - sp) < length)
70 return (NULL);
71 if (len > bsize)
72 len = bsize;
73 if ((w = rdiff_weak(sp, len)) == weak) {
74 if (!(*hashops->init)(&ctx)) {
75 logmsg_err("rdiff error: hash init");
76 return (NULL);
77 }
78 (*hashops->update)(ctx, sp, len);
79 (*hashops->final)(ctx, hash);
80
81 if (memcmp(hash, strong, hashops->length) == 0)
82 return (sp);
83 }
84 rwl = RDIFF_WEAK_LOW(weak);
85 rwh = RDIFF_WEAK_HIGH(weak);
86
87 wl = RDIFF_WEAK_LOW(w);
88 wh = RDIFF_WEAK_HIGH(w);
89
90 while (sp < bp) {
91 if ((len = bp - sp) < length)
92 return (NULL);
93
94 if (len > bsize) {
95 wl = wl - sp[0] + sp[bsize];
96 wh = wh - bsize * sp[0] + wl;
97 len = bsize;
98 } else {
99 wl = wl - sp[0];
100 wh = wh - len-- * sp[0];
101 }
102
103 if ((rwl == wl) && (rwh == wh)) {
104 if (!(*hashops->init)(&ctx)) {
105 logmsg_err("rdiff error: hash init");
106 return (NULL);
107 }
108 (*hashops->update)(ctx, sp + 1, len);
109 (*hashops->final)(ctx, hash);
110
111 if (memcmp(hash, strong, hashops->length) == 0)
112 return (sp + 1);
113 }
114
115 sp++;
116 }
117
118 return (NULL);
119 }
120
121 bool
rdiff_copy(struct mux * mx,uint8_t chnum,off_t position,size_t length)122 rdiff_copy(struct mux *mx, uint8_t chnum, off_t position, size_t length)
123 {
124 uint8_t cmd[RDIFF_MAXCMDLEN];
125
126 cmd[0] = RDIFF_CMD_COPY;
127 SetDDWord(&cmd[1], position);
128 SetDWord(&cmd[9], length);
129
130 if (!mux_send(mx, chnum, cmd, 13)) {
131 logmsg_err("rdiff(COPY) error: send");
132 return (false);
133 }
134
135 return (true);
136 }
137
138 bool
rdiff_data(struct mux * mx,uint8_t chnum,const void * buffer,size_t bufsize)139 rdiff_data(struct mux *mx, uint8_t chnum, const void *buffer, size_t bufsize)
140 {
141 uint8_t cmd[RDIFF_MAXCMDLEN];
142
143 cmd[0] = RDIFF_CMD_DATA;
144 SetDWord(&cmd[1], bufsize);
145
146 if (!mux_send(mx, chnum, cmd, 5)) {
147 logmsg_err("rdiff(DATA) error: send");
148 return (false);
149 }
150 if (!mux_send(mx, chnum, buffer, bufsize)) {
151 logmsg_err("rdiff(DATA) error: send");
152 return (false);
153 }
154
155 return (true);
156 }
157
158 bool
rdiff_eof(struct mux * mx,uint8_t chnum)159 rdiff_eof(struct mux *mx, uint8_t chnum)
160 {
161 uint8_t cmd[RDIFF_MAXCMDLEN];
162
163 cmd[0] = RDIFF_CMD_EOF;
164
165 if (!mux_send(mx, chnum, cmd, 1)) {
166 logmsg_err("rdiff(EOF) error: send");
167 return (false);
168 }
169
170 return (true);
171 }
172