|
|
1.1 root 1: #include "update.h"
2:
3: /*
4: ** Reconstruct a target file from a source file and a delta file.
5: ** The delta file contain block move instructions computed by delta().
6: **
7: ** Written by Kiem-Phong Vo, 5/20/88
8: */
9:
10: /* buffers for delta and target files */
11: static unsigned char *Ddata, *Dnext, *Dend,
12: *Tdata, *Tnext, *Tend;
13: static int Dfd, Tfd;
14:
15: #define delinit(buf,size,fd) (Ddata=Dnext=Dend=buf, Dfd=fd)
16: #define tarinit(buf,size,fd) (Tdata=Tnext=buf, Tend=buf+size, Tfd=fd)
17: #define tarflush() (write(Tfd,Tdata,Tnext-Tdata) >= 0 ? (Tnext=Tdata,0) : -1)
18:
19: /* read a byte from delta file */
20: static int delgetc()
21: {
22: if(Dnext >= Dend)
23: {
24: register int n;
25: if((n = read(Dfd,Ddata,BUFSIZE)) <= 0)
26: return -1;
27: Dnext = Ddata, Dend = Ddata+n;
28: }
29: return (int)(*Dnext++);
30: }
31:
32: /* read a long value from delta file */
33: static long delgetl(n)
34: register int n;
35: {
36: register long lv;
37:
38: lv = 0;
39: for(; n > 0; --n)
40: {
41: register int v;
42: if((v = delgetc()) < 0)
43: return -1;
44: lv = lv*256 + v;
45: }
46: return lv;
47: }
48:
49: /* transfer a number of bytes from a file to the target file */
50: static int filetransfer(fd,n)
51: int fd;
52: long n;
53: {
54: while(n > 0)
55: {
56: register int r;
57:
58: if(Tnext >= Tend)
59: if(tarflush() < 0)
60: return -1;
61: r = n > (Tend-Tnext) ? (Tend-Tnext) : n;
62: if(read(fd,Tnext,r) != r)
63: return -1;
64: Tnext += r;
65: n -= r;
66: }
67: return 0;
68: }
69:
70: /* transfer a number of bytes from a memory area to the target file */
71: static int memtransfer(addr,n)
72: unsigned char *addr;
73: register long n;
74: {
75: while(n > 0)
76: {
77: register int r;
78:
79: if(Tnext >= Tend)
80: if(tarflush() < 0)
81: return -1;
82: r = n > (Tend-Tnext) ? (Tend-Tnext) : n;
83: memcopy(Tnext,addr,r);
84: Tnext += r;
85: addr += r;
86: n -= r;
87: }
88: return 0;
89: }
90:
91: /* transfer a number of bytes from delta to target */
92: static int deltransfer(n)
93: long n;
94: {
95: register int d;
96:
97: /* transfer what's already in core */
98: if((d = Dend-Dnext) > 0)
99: {
100: register int w = n <= d ? n : d;
101:
102: if(w > (Tend-Tnext))
103: if(tarflush() < 0)
104: return -1;
105:
106: /* copy from the delta buffer */
107: memcopy(Tnext,Dnext,w);
108: Dnext += w;
109: Tnext += w;
110: n -= w;
111: }
112:
113: return n > 0 ? filetransfer(Dfd,n) : 0;
114: }
115:
116: update(srcfd,offset,delfd,tarfd)
117: int srcfd;
118: long offset;
119: int delfd;
120: int tarfd;
121: {
122: register int i;
123: register long n_src, n_tar;
124: unsigned char delbuf[BUFSIZE], tarbuf[BUFSIZE];
125: unsigned char *src, *tar, *malloc();
126:
127: /* start buffering system for delta file */
128: delinit(delbuf,BUFSIZE,delfd);
129:
130: /* read the file sizes */
131: if((i = delgetc()) < 0 || (i&DELTA_TYPE) != DELTA_TYPE)
132: return -1;
133: if((n_src = delgetl((i>>3)&07)) < 0 || (n_tar = delgetl(i&07)) < 0)
134: return -1;
135:
136: /* make data area for target file */
137: if(tar = malloc(n_tar)) /* assignment = */
138: tarinit(tar,n_tar,tarfd);
139: else tarinit(tarbuf,BUFSIZE,tarfd);
140:
141: /* read in source file if possible to avoid lseek */
142: if(src = malloc(n_src)) /* assignment = */
143: {
144: lseek(srcfd,offset,0);
145: if(read(srcfd,src,n_src) != n_src)
146: return -1;
147: }
148:
149: while((i = delgetc()) >= 0)
150: {
151: register long size, addr;
152:
153: if((size = delgetl((i>>3)&07)) < 0)
154: return -1;
155: switch(i&DELTA_TYPE)
156: {
157: default :
158: return -1;
159: case DELTA_TYPE :
160: /* sync delta file pointer */
161: if((addr = Dend-Dnext) > 0)
162: lseek(Dfd,-addr,1);
163: /* flush output buffer */
164: if(tarflush() < 0)
165: return -1;
166: /* free space used */
167: if(src)
168: free(src);
169: if(tar)
170: free(tar);
171: return 0;
172: case DELTA_MOVE :
173: if((addr = delgetl(i&07)) < 0)
174: return -1;
175: if(src)
176: {
177: if(memtransfer(src+addr,size) < 0)
178: return -1;
179: }
180: else
181: {
182: if(lseek(srcfd,offset+addr,0) < 0)
183: return -1;
184: if(filetransfer(srcfd,size) < 0)
185: return -1;
186: }
187: break;
188: case DELTA_ADD :
189: if(deltransfer(size) < 0)
190: return -1;
191: break;
192: }
193: }
194:
195: /* should never get here */
196: return -1;
197: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.