]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/hgfs/patch.c
hgfs: add wip debug command
[plan9front.git] / sys / src / cmd / hgfs / patch.c
1 #include <u.h>
2 #include <libc.h>
3 #include <thread.h>
4 #include "dat.h"
5 #include "fns.h"
6
7 int
8 fcopy(int dfd, int sfd, vlong len)
9 {
10         uchar buf[BUFSZ];
11         int n;
12
13         while(len > 0){
14                 if((n = BUFSZ) > len)
15                         n = len;
16                 if((n = read(sfd, buf, n)) < 0)
17                         return -1;
18                 if(write(dfd, buf, n) != n)
19                         return -1;
20                 len -= n;
21         }
22         return 0;
23 }
24
25 static uchar patchmark[12] = {
26         0xff, 0xff, 0xff, 0xff,
27         0xff, 0xff, 0xff, 0xff,
28         0xff, 0xff, 0xff, 0xff,
29 };
30
31 int
32 fpatchmark(int pfd, char *)
33 {
34         if(write(pfd, patchmark, 12) != 12)
35                 return -1;
36         return 0;
37 }
38
39 typedef struct Frag Frag;
40 struct Frag
41 {
42         Frag    *next;
43         int     fd;
44         vlong   len;
45         vlong   off;
46 };
47
48 int
49 fpatch(int ofd, int bfd, int pfd)
50 {
51         vlong off, fstart, fend, start, end, len;
52         int err, front, back;
53         Frag *h, *f, *p;
54         uchar buf[12];
55
56         h = nil;
57         err = -1;
58
59         if(bfd >= 0){
60                 h = malloc(sizeof(Frag));
61                 h->next = nil;
62                 h->off = 0;
63                 h->fd = bfd;
64                 h->len = seek(h->fd, 0, 2);
65                 if(h->len < 0)
66                         goto errout;
67         }
68
69         off = 0;
70         while(pfd >= 0){
71                 if(readn(pfd, buf, 12) != 12)
72                         break;
73
74                 if(memcmp(buf, patchmark, 12) == 0){
75                         off = 0;
76                         continue;
77                 }
78
79                 start = buf[0]<<24 | buf[1]<<16 | buf[2]<<8 | buf[3];
80                 end = buf[4]<<24 | buf[5]<<16 | buf[6]<<8 | buf[7];
81                 len = buf[8]<<24 | buf[9]<<16 | buf[10]<<8 | buf[11];
82
83                 if(start > end){
84                         werrstr("bad patch: start > end");
85                         goto errout;
86                 }
87
88                 start += off;
89                 end += off;
90                 off += start + len - end;
91
92                 fstart = 0;
93                 for(f = h; f; f = f->next, fstart = fend){
94                         fend = fstart + f->len;
95                         if(fend <= start)
96                                 continue;
97                         if(fstart >= end)
98                                 break;
99
100                         front = start > fstart;
101                         back = end < fend;
102                         if(front && back){
103                                 p = malloc(sizeof(Frag));
104                                 *p = *f;
105                                 f->next = p;
106                                 f->len = start - fstart;
107                                 p->off += end - fstart;
108                                 p->len -= end - fstart;
109                                 break;
110                         } else if(back){
111                                 f->off += end - fstart;
112                                 f->len -= end - fstart;
113                                 break;
114                         } else if(front){
115                                 f->len = start - fstart;
116                         } else {
117                                 f->len = 0;
118                         }
119                 }
120
121                 fstart = 0;
122                 for(p = nil, f = h; f && fstart < start; p = f, f = f->next)
123                         fstart += f->len;
124
125                 f = malloc(sizeof(Frag));
126                 f->fd = pfd;
127                 f->len = len;
128                 f->off = seek(f->fd, 0, 1);
129
130                 if(p){
131                         f->next = p->next;
132                         p->next = f;
133                 } else {
134                         f->next = h;
135                         h = f;
136                 }
137
138                 if(f->off < 0)
139                         goto errout;
140                 if(seek(pfd, f->len, 1) < 0)
141                         goto errout;
142         }
143
144         for(f = h; f; f = f->next){
145                 if(seek(f->fd, f->off, 0) < 0)
146                         goto errout;
147                 if(fcopy(ofd, f->fd, f->len) < 0)
148                         goto errout;
149         }
150         err = 0;
151
152 errout:
153         while(f = h){
154                 h = f->next;
155                 free(f);
156         }
157
158         return err;
159 }