]> git.ipfire.org Git - thirdparty/git.git/blame - receive-pack.c
Start of "git-send-pack", the local part of sending off a pack
[thirdparty/git.git] / receive-pack.c
CommitLineData
575f4974
LT
1#include "cache.h"
2#include <sys/wait.h>
3
4static const char receive_pack_usage[] = "git-receive-pack [--unpack=executable] <git-dir> [heads]";
5
6static const char *unpacker = "git-unpack-objects";
7
8static int path_match(const char *path, int nr, char **match)
9{
10 int i;
11 int pathlen = strlen(path);
12
13 for (i = 0; i < nr; i++) {
14 char *s = match[i];
15 int len = strlen(s);
16
17 if (!len || len > pathlen)
18 continue;
19 if (memcmp(path + pathlen - len, s, len))
20 continue;
21 if (pathlen > len && path[pathlen - len - 1] != '/')
22 continue;
23 *s = 0;
24 return 1;
25 }
26 return 0;
27}
28
29static void safe_write(int fd, const void *buf, unsigned n)
30{
31 while (n) {
32 int ret = write(fd, buf, n);
33 if (ret > 0) {
34 buf += ret;
35 n -= ret;
36 continue;
37 }
38 if (!ret)
39 die("write error (disk full?)");
40 if (errno == EAGAIN || errno == EINTR)
41 continue;
42 die("write error (%s)", strerror(errno));
43 }
44}
45
46/*
47 * If we buffered things up above (we don't, but we should),
48 * we'd flush it here
49 */
50static void flush_safe(int fd)
51{
52}
53
54/*
55 * Write a packetized stream, where each line is preceded by
56 * its length (including the header) as a 4-byte hex number.
57 * A length of 'zero' means end of stream (and a length of 1-3
58 * would be an error).
59 */
60#define hex(a) (hexchar[(a) & 15])
61static void packet_write(const char *fmt, ...)
62{
63 static char buffer[1000];
64 static char hexchar[] = "0123456789abcdef";
65 va_list args;
66 unsigned n;
67
68 va_start(args, fmt);
69 n = vsnprintf(buffer + 4, sizeof(buffer) - 4, fmt, args);
70 va_end(args);
71 if (n >= sizeof(buffer)-4)
72 die("protocol error: impossibly long line");
73 n += 4;
74 buffer[0] = hex(n >> 12);
75 buffer[1] = hex(n >> 8);
76 buffer[2] = hex(n >> 4);
77 buffer[3] = hex(n);
78 safe_write(1, buffer, n);
79}
80
81static void show_ref(const char *path, unsigned char *sha1)
82{
83 packet_write("%s %s\n", sha1_to_hex(sha1), path);
84}
85
86static int read_ref(const char *path, unsigned char *sha1)
87{
88 int ret = -1;
89 int fd = open(path, O_RDONLY);
90
91 if (fd >= 0) {
92 char buffer[60];
93 if (read(fd, buffer, sizeof(buffer)) >= 40)
94 ret = get_sha1_hex(buffer, sha1);
95 close(fd);
96 }
97 return ret;
98}
99
100static void write_head_info(const char *base, int nr, char **match)
101{
102 DIR *dir = opendir(base);
103
104 if (dir) {
105 struct dirent *de;
106 int baselen = strlen(base);
107 char *path = xmalloc(baselen + 257);
108 memcpy(path, base, baselen);
109
110 while ((de = readdir(dir)) != NULL) {
111 char sha1[20];
112 struct stat st;
113 int namelen;
114
115 if (de->d_name[0] == '.')
116 continue;
117 namelen = strlen(de->d_name);
118 if (namelen > 255)
119 continue;
120 memcpy(path + baselen, de->d_name, namelen+1);
121 if (lstat(path, &st) < 0)
122 continue;
123 if (S_ISDIR(st.st_mode)) {
124 path[baselen + namelen] = '/';
125 path[baselen + namelen + 1] = 0;
126 write_head_info(path, nr, match);
127 continue;
128 }
129 if (read_ref(path, sha1) < 0)
130 continue;
131 if (nr && !path_match(path, nr, match))
132 continue;
133 show_ref(path, sha1);
134 }
135 free(path);
136 closedir(dir);
137 }
138}
139
140/*
141 * This is all pretty stupid, but we use this packetized line
142 * format to make a streaming format possible without ever
143 * over-running the read buffers. That way we'll never read
144 * into what might be the pack data (which should go to another
145 * process entirely).
146 *
147 * The writing side could use stdio, but since the reading
148 * side can't, we stay with pure read/write interfaces.
149 */
150static void safe_read(int fd, void *buffer, unsigned size)
151{
152 int n = 0;
153
154 while (n < size) {
155 int ret = read(0, buffer + n, size - n);
156 if (ret < 0) {
157 if (errno == EINTR || errno == EAGAIN)
158 continue;
159 die("read error (%s)", strerror(errno));
160 }
161 if (!ret)
162 die("unexpected EOF");
163 n += ret;
164 }
165}
166
167static int safe_read_line(char *buffer, unsigned size)
168{
169 int n, len;
170
171 safe_read(0, buffer, 4);
172
173 len = 0;
174 for (n = 0; n < 4; n++) {
175 unsigned char c = buffer[n];
176 len <<= 4;
177 if (c >= '0' && c <= '9') {
178 len += c - '0';
179 continue;
180 }
181 if (c >= 'a' && c <= 'f') {
182 len += c - 'a' + 10;
183 continue;
184 }
185 if (c >= 'A' && c <= 'F') {
186 len += c - 'A' + 10;
187 continue;
188 }
189 die("protocol error: bad line length character");
190 }
191 if (!len)
192 return 0;
193 if (len < 4 || len >= size)
194 die("protocol error: bad line length %d", len);
195 safe_read(0, buffer + 4, len - 4);
196 buffer[len] = 0;
197 return len;
198}
199
200struct line {
201 struct line *next;
202 char data[0];
203};
204
205struct line *commands = NULL;
206
207/*
208 * This gets called after(if) we've successfully
209 * unpacked the data payload.
210 */
211static void execute_commands(void)
212{
213 struct line *line = commands;
214
215 while (line) {
216 printf("%s", line->data);
217 line = line->next;
218 }
219}
220
221static void read_head_info(void)
222{
223 struct line **p = &commands;
224 for (;;) {
225 static char line[1000];
226 int len = safe_read_line(line, sizeof(line));
227 struct line *n;
228 if (!len)
229 break;
230 n = xmalloc(sizeof(struct line) + len);
231 n->next = NULL;
232 memcpy(n->data, line + 4, len - 3);
233 *p = n;
234 p = &n->next;
235 }
236}
237
238static void unpack(void)
239{
240 pid_t pid = fork();
241
242 if (pid < 0)
243 die("unpack fork failed");
244 if (!pid) {
245 char *const envp[] = { "GIT_DIR=.", NULL };
246 execle(unpacker, unpacker, NULL, envp);
247 die("unpack execute failed");
248 }
249
250 for (;;) {
251 int status, code;
252 int retval = waitpid(pid, &status, 0);
253
254 if (retval < 0) {
255 if (errno == EINTR)
256 continue;
257 die("waitpid failed (%s)", strerror(retval));
258 }
259 if (retval != pid)
260 die("waitpid is confused");
261 if (WIFSIGNALED(status))
262 die("%s died of signal %d", unpacker, WTERMSIG(status));
263 if (!WIFEXITED(status))
264 die("%s died out of really strange complications", unpacker);
265 code = WEXITSTATUS(status);
266 if (code)
267 die("%s exited with error code %d", unpacker, code);
268 return;
269 }
270}
271
272int main(int argc, char **argv)
273{
274 int i, nr_heads = 0;
275 const char *dir = NULL;
276 char **heads = NULL;
277
278 argv++;
279 for (i = 1; i < argc; i++) {
280 const char *arg = *argv++;
281
282 if (*arg == '-') {
283 if (!strncmp(arg, "--unpack=", 9)) {
284 unpacker = arg+9;
285 continue;
286 }
287 /* Do flag handling here */
288 usage(receive_pack_usage);
289 }
290 dir = arg;
291 heads = argv;
292 nr_heads = argc - i - 1;
293 break;
294 }
295 if (!dir)
296 usage(receive_pack_usage);
297
298 /* chdir to the directory. If that fails, try appending ".git" */
299 if (chdir(dir) < 0) {
300 static char path[PATH_MAX];
301 snprintf(path, sizeof(path), "%s.git", dir);
302 if (chdir(path) < 0)
303 die("unable to cd to %s", dir);
304 }
305
306 /* If we have a ".git" directory, chdir to it */
307 chdir(".git");
308
309 if (access("objects", X_OK) < 0 || access("refs/heads", X_OK) < 0)
310 die("%s doesn't appear to be a git directory", dir);
311 write_head_info("refs/", nr_heads, heads);
312
313 /* EOF */
314 safe_write(1, "0000", 4);
315 flush_safe(1);
316
317 read_head_info();
318 unpack();
319 execute_commands();
320 return 0;
321}