fixed filenames returned by flist
[reposerve] / server / src / client.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <ctype.h>
5 #include <unistd.h>
6 #include "client.h"
7 #include "proto.h"
8 #include "repo.h"
9
10 static int proc_request(struct client *c);
11 static void print_invalid(const char *s);
12 static int proc_flist(struct client *c, char *data, int datasz);
13 static int proc_push(struct client *c, char *data, int datasz);
14 static int proc_pull(struct client *c, char *data, int datasz);
15
16 const char *repo_path;
17
18 int handle_client(struct client *c)
19 {
20         char buf[512];
21         int sz, left;
22
23         while((sz = read(c->s, buf, sizeof buf)) > 0) {
24                 left = sizeof c->buf - c->bsz;
25                 if(sz > left) sz = left;
26                 memcpy(c->buf + c->bsz, buf, sz);
27                 c->bsz += sz;
28         }
29
30         if(proc_request(c) == -1) {
31                 return -1;
32         }
33
34         if(sz == 0) return -1;
35         return 0;
36 }
37
38 static int proc_request(struct client *c)
39 {
40         char *endp = c->buf;
41         char *reqdata;
42         int reqdata_len;
43
44         while(endp < c->buf + c->bsz) {
45                 if(*endp == '\r' && endp[1] == '\n') {
46                         *endp++ = 0;
47                         break;
48                 }
49                 if(*endp == '\n') break;
50                 endp++;
51         }
52         if(endp >= c->buf + c->bsz) {
53                 return 0;
54         }
55         *endp = 0;
56
57         reqdata = endp + 1;
58         reqdata_len = c->bsz - (reqdata - c->buf);
59
60         c->bsz = 0;
61
62         if(strcmp(c->buf, "flist") == 0) {
63                 return proc_flist(c, reqdata, reqdata_len);
64         } else if(strcmp(c->buf, "push") == 0) {
65                 return proc_push(c, reqdata, reqdata_len);
66         } else if(strcmp(c->buf, "pull") == 0) {
67                 return proc_pull(c, reqdata, reqdata_len);
68         } else if(strcmp(c->buf, "dos") == 0) {
69                 c->flags |= CLIENT_DOS;
70                 send_ok(c, 0);
71                 return 0;
72         }
73
74         print_invalid(c->buf);
75         send_err(c);
76         return 0;
77 }
78
79 static void print_invalid(const char *s)
80 {
81         int i;
82         printf("Recv invalid request: \"");
83         for(i=0; i<60; i++) {
84                 if(!*s) break;
85                 if(isprint(*s)) {
86                         putchar(*s);
87                 } else {
88                         printf("\\x%x", (unsigned int)*s);
89                 }
90                 s++;
91         }
92         puts("\"");
93 }
94
95 void send_string(struct client *c, const char *s)
96 {
97         write(c->s, s, strlen(s));
98 }
99
100 void send_ok(struct client *c, int resp_sz)
101 {
102         char buf[32];
103         sprintf(buf, "OK %d\n", resp_sz < 0 ? 0 : resp_sz);
104         send_string(c, buf);
105 }
106
107 void send_err(struct client *c)
108 {
109         send_string(c, "ERR\n");
110 }
111
112 static struct flist *gen_flist(int contents)
113 {
114         int i, count, len;
115         struct flist *flist;
116         char *pathbuf = 0;
117         int pathbuf_sz = 0;
118
119         if(!(flist = flist_create())) {
120                 return 0;
121         }
122
123         if(repo_init(repo_path) == -1) {
124                 return 0;
125         }
126         count = repo_num_files();
127
128         for(i=0; i<count; i++) {
129                 len = strlen(repo_path) + strlen(repo_file(i)->path) + 1;
130                 if(len > pathbuf_sz) {
131                         free(pathbuf);
132                         if(!(pathbuf = malloc(len + 1))) {
133                                 fprintf(stderr, "gen_flist: failed to allocate path buffer (%d bytes)\n", len + 1);
134                                 repo_cleanup();
135                                 flist_destroy(flist);
136                                 return 0;
137                         }
138                 }
139                 sprintf(pathbuf, "%s/%s", repo_path, repo_file(i)->path);
140                 flist_add(flist, repo_file(i)->path, pathbuf, contents);
141         }
142         repo_cleanup();
143
144         free(pathbuf);
145         return flist;
146 }
147
148 static int proc_flist(struct client *c, char *data, int datasz)
149 {
150         struct flist *flist;
151
152         if(!(flist = gen_flist(0))) {
153                 send_err(c);
154                 return -1;
155         }
156         flist_finalize(flist);
157
158         send_ok(c, flist->final_size);
159         write(c->s, flist->flist, flist->final_size);
160
161         flist_destroy(flist);
162         return 0;
163 }
164
165 static int proc_push(struct client *c, char *data, int datasz)
166 {
167         send_err(c);
168         return 0;
169 }
170
171 static int proc_pull(struct client *c, char *data, int datasz)
172 {
173         send_err(c);
174         return 0;
175 }