Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
att
GitHub Repository: att/ast
Path: blob/master/src/lib/libodelta/update.c
1808 views
1
/***********************************************************************
2
* *
3
* This software is part of the ast package *
4
* Copyright (c) 1989-2011 AT&T Intellectual Property *
5
* and is licensed under the *
6
* Eclipse Public License, Version 1.0 *
7
* by AT&T Intellectual Property *
8
* *
9
* A copy of the License is available at *
10
* http://www.eclipse.org/org/documents/epl-v10.html *
11
* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
12
* *
13
* Information and Software Systems Research *
14
* AT&T Research *
15
* Florham Park NJ *
16
* *
17
* Phong Vo <[email protected]> *
18
* *
19
***********************************************************************/
20
#pragma prototyped
21
#include "update.h"
22
23
/*
24
** Reconstruct a target file from a source file and a delta file.
25
** The delta file contain block move instructions computed by delta().
26
**
27
** Written by Kiem-Phong Vo, 5/20/88
28
*/
29
30
/* buffers for delta and target files */
31
static unsigned char *Ddata, *Dnext, *Dend,
32
*Tdata, *Tnext, *Tend;
33
static int Dfd, Tfd;
34
35
#define delinit(buf,size,fd) (Ddata=Dnext=Dend=buf, Dfd=fd)
36
#define tarinit(buf,size,fd) (Tdata=Tnext=buf, Tend=buf+size, Tfd=fd)
37
#define tarflush() (write(Tfd,(char*)Tdata,Tnext-Tdata) >= 0 ? (Tnext=Tdata,0) : -1)
38
39
/* read a byte from delta file */
40
static int delgetc(void)
41
{
42
if(Dnext >= Dend)
43
{
44
register int n;
45
if((n = read(Dfd,(char*)Ddata,BUFSIZE)) <= 0)
46
return -1;
47
Dnext = Ddata, Dend = Ddata+n;
48
}
49
return (int)(*Dnext++);
50
}
51
52
/* read a long value from delta file */
53
static long delgetl(register int n)
54
{
55
register long lv;
56
57
lv = 0;
58
for(; n > 0; --n)
59
{
60
register int v;
61
if((v = delgetc()) < 0)
62
return -1;
63
lv = lv*256 + v;
64
}
65
return lv;
66
}
67
68
/* transfer a number of bytes from a file to the target file */
69
static int filetransfer(int fd, long n)
70
{
71
while(n > 0)
72
{
73
register int r;
74
75
if(Tnext >= Tend)
76
if(tarflush() < 0)
77
return -1;
78
r = n > (Tend-Tnext) ? (Tend-Tnext) : n;
79
if(read(fd,(char*)Tnext,r) != r)
80
return -1;
81
Tnext += r;
82
n -= r;
83
}
84
return 0;
85
}
86
87
/* transfer a number of bytes from a memory area to the target file */
88
static int memtransfer(unsigned char* addr, register long n)
89
{
90
while(n > 0)
91
{
92
register int r;
93
94
if(Tnext >= Tend)
95
if(tarflush() < 0)
96
return -1;
97
r = n > (Tend-Tnext) ? (Tend-Tnext) : n;
98
memcpy(Tnext,addr,r);
99
Tnext += r;
100
addr += r;
101
n -= r;
102
}
103
return 0;
104
}
105
106
/* transfer a number of bytes from delta to target */
107
static int deltransfer(long n)
108
{
109
register int d;
110
111
/* transfer what's already in core */
112
if((d = Dend-Dnext) > 0)
113
{
114
register int w = n <= d ? n : d;
115
116
if(w > (Tend-Tnext))
117
if(tarflush() < 0)
118
return -1;
119
120
/* copy from the delta buffer */
121
memcpy(Tnext,Dnext,w);
122
Dnext += w;
123
Tnext += w;
124
n -= w;
125
}
126
127
return n > 0 ? filetransfer(Dfd,n) : 0;
128
}
129
130
int
131
update(int srcfd, long offset, int delfd, int tarfd)
132
{
133
register int i;
134
register long n_src, n_tar;
135
unsigned char delbuf[BUFSIZE], tarbuf[BUFSIZE];
136
unsigned char *src, *tar;
137
138
/* start buffering system for delta file */
139
delinit(delbuf,BUFSIZE,delfd);
140
141
/* read the file sizes */
142
if((i = delgetc()) < 0 || (i&DELTA_TYPE) != DELTA_TYPE)
143
return -1;
144
if((n_src = delgetl((i>>3)&07)) < 0 || (n_tar = delgetl(i&07)) < 0)
145
return -1;
146
147
/* make data area for target file */
148
if(tar = (unsigned char*)malloc(n_tar)) /* assignment = */
149
tarinit(tar,n_tar,tarfd);
150
else tarinit(tarbuf,BUFSIZE,tarfd);
151
152
/* read in source file if possible to avoid lseek */
153
if(src = (unsigned char*)malloc(n_src)) /* assignment = */
154
{
155
lseek(srcfd,offset,0);
156
if(read(srcfd,(char*)src,n_src) != n_src)
157
return -1;
158
}
159
160
while((i = delgetc()) >= 0)
161
{
162
register long size, addr;
163
164
if((size = delgetl((i>>3)&07)) < 0)
165
return -1;
166
switch(i&DELTA_TYPE)
167
{
168
default :
169
return -1;
170
case DELTA_TYPE :
171
/* sync delta file pointer */
172
if((addr = Dend-Dnext) > 0)
173
lseek(Dfd,-addr,1);
174
/* flush output buffer */
175
if(tarflush() < 0)
176
return -1;
177
/* free space used */
178
if(src)
179
free(src);
180
if(tar)
181
free(tar);
182
return 0;
183
case DELTA_MOVE :
184
if((addr = delgetl(i&07)) < 0)
185
return -1;
186
if(src)
187
{
188
if(memtransfer(src+addr,size) < 0)
189
return -1;
190
}
191
else
192
{
193
if(lseek(srcfd,offset+addr,0) < 0)
194
return -1;
195
if(filetransfer(srcfd,size) < 0)
196
return -1;
197
}
198
break;
199
case DELTA_ADD :
200
if(deltransfer(size) < 0)
201
return -1;
202
break;
203
}
204
}
205
206
/* should never get here */
207
return -1;
208
}
209
210