Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


e7d99a9db8e7d2cdc79c3e8f72abc792204b6dca
[palacios.git] / linux_usr / v3_user_keyed_stream_file.c
1 #include <unistd.h>
2 #include <stdlib.h>
3 #include <stdio.h>
4 #include <stdint.h>
5 #include <string.h>
6 #include <sys/select.h>
7 #include <malloc.h>
8 #include <alloca.h>
9 #include <sys/types.h>
10 #include <dirent.h>
11 #include <sys/stat.h>
12 #include <fcntl.h>
13
14 #define sint64_t int64_t
15
16 #include "v3_user_keyed_stream.h"
17
18 void usage()
19 {
20     fprintf(stderr,"v3_user_keyed_stream_file /dev/v3-vm0 user:file:stream\n");
21 }
22
23 char *dir;
24
25 int dir_setup(char *dir)
26 {
27     DIR *d;
28     int created=0;
29     int fd;
30     
31     char buf[strlen(dir)+strlen("/.palacios_keyed_stream_user_file")+1];
32
33
34     strcpy(buf,dir);
35     strcat(buf,"/.palacios_keyed_stream_user_file");
36
37     d=opendir(dir);
38
39     // does the directory exist or can we create it
40     if (d) { 
41         closedir(d);
42     } else {
43         if (mkdir(dir,0700)<0) { 
44             perror("cannot create directory");
45             return -1;
46         } else {
47             created=1;
48         }
49     }
50
51     // can we write to it?
52
53     fd = open(buf,O_RDWR | O_CREAT,0600);
54
55     if (fd<0) { 
56         perror("cannot write directory");
57         if (created) { 
58             rmdir(dir);
59         }
60         return -1;
61     }
62
63     // ok, we are done
64
65     close(fd);
66
67     return 0;
68 }
69     
70
71
72 int handle_open_key(struct palacios_user_keyed_stream_op *req, 
73                     struct palacios_user_keyed_stream_op **resp,
74                     char *dir)
75 {
76     int fd;
77     char fn[strlen(dir)+req->buf_len+1];
78
79     strcpy(fn,dir);
80     strcat(fn,"/");
81     strcat(fn,req->buf);
82
83
84     fd = open(fn,O_RDWR | O_CREAT,0600);
85     
86     (*resp) = malloc(sizeof(struct palacios_user_keyed_stream_op)+0);
87     
88     if (!(*resp)) {
89         return -1;
90     }
91
92     (*resp)->len=sizeof(struct palacios_user_keyed_stream_op);
93     (*resp)->type=req->type;
94     (*resp)->xfer=0;
95     (*resp)->user_key=(void*)(uint64_t)fd;
96     (*resp)->buf_len=0;
97     (*resp)->data_off=0;
98     
99     return 0;
100
101 }
102
103 int handle_close_key(struct palacios_user_keyed_stream_op *req, 
104                      struct palacios_user_keyed_stream_op **resp,
105                      char *dir)
106 {
107     int fd;
108     int rc;
109  
110     fd = (int) (uint64_t) (req->user_key);
111
112     rc = close(fd);
113
114     (*resp) = malloc(sizeof(struct palacios_user_keyed_stream_op)+0);
115     
116     if (!(*resp)) {
117         return -1;
118     }
119
120     (*resp)->len=sizeof(struct palacios_user_keyed_stream_op);
121     (*resp)->type=req->type;
122     (*resp)->xfer=rc;
123     (*resp)->user_key=(void*)(uint64_t)fd;
124     (*resp)->buf_len=0;
125     (*resp)->data_off=0;
126     
127     return 0;
128
129 }
130
131 int read_all(int fd, char *buf, int len)
132 {
133     int xfer;
134     int left;
135
136     left=len;
137
138     while (left>0) { 
139         xfer=read(fd, buf+len-left,left);
140         if (xfer<0) {
141             perror("cannot read file");
142             return -1;
143         } else {
144             left-=xfer;
145         }
146     }
147     return len;
148 }
149
150 int write_all(int fd, char *buf, int len)
151 {
152     int xfer;
153     int left;
154
155     left=len;
156
157     while (left>0) { 
158         xfer=write(fd, buf+len-left,left);
159         if (xfer<0) {
160             perror("cannot write file");
161             return -1;
162         } else {
163             left-=xfer;
164         }
165     }
166     return len;
167 }
168
169
170 int handle_write_key(struct palacios_user_keyed_stream_op *req, 
171                      struct palacios_user_keyed_stream_op **resp,
172                      char *dir)
173 {
174     int fd;
175     int rc;
176     sint64_t taglen = req->data_off;
177     sint64_t datalen = req->buf_len - req->data_off;
178
179     if (datalen != req->xfer) { 
180       fprintf(stderr,"Odd, xfer=%lld but datalen computed is %lld\n",req->xfer,datalen);
181       if (datalen > req->xfer) { 
182         datalen = req->xfer;
183       }
184     }
185  
186     fd = (int) (uint64_t) (req->user_key);
187
188     // Write tag
189     rc = write_all(fd,req->buf,taglen);
190     
191     if (rc!=taglen) { 
192       // failed to write tag, lets report as negative error
193       fprintf(stderr,"Failed to write tag (taglen=%lld, rc=%d)\n",taglen,rc);
194       rc = -1;
195     } else {
196       // Write data
197       rc = write_all(fd,req->buf+taglen,datalen);
198       if (rc!=datalen) {
199         fprintf(stderr,"Failed to write data (datalen=%lld, rc=%d)\n",datalen,rc);
200       }
201     }
202
203     (*resp) = malloc(sizeof(struct palacios_user_keyed_stream_op)+0);
204     
205     if (!(*resp)) {
206         return -1;
207     }
208
209     (*resp)->len=sizeof(struct palacios_user_keyed_stream_op);
210     (*resp)->type=req->type;
211     (*resp)->xfer=rc;
212     (*resp)->user_key=(void*)(uint64_t)fd;
213     (*resp)->buf_len=0;
214     (*resp)->data_off=0;
215     
216
217     return 0;
218
219 }
220
221 int handle_read_key(struct palacios_user_keyed_stream_op *req, 
222                     struct palacios_user_keyed_stream_op **resp,
223                     char *dir)
224 {
225     int fd;
226     int rc;
227     sint64_t taglen = req->data_off;
228     char temptag[taglen];
229  
230     fd = (int) (uint64_t) (req->user_key);
231
232     (*resp) = malloc(sizeof(struct palacios_user_keyed_stream_op)+req->xfer);
233     
234     if (!(*resp)) {
235         return -1;
236     }
237
238     // read key and compare
239     rc = read_all(fd,temptag,taglen);
240     
241     if (rc!=taglen) { 
242       // Error
243       fprintf(stderr,"Failed to read tag (taglen=%lld, rc=%d)\n",taglen,rc);
244       rc = -1;
245     } else {
246       // tag check
247       if (memcmp(temptag,req->buf,taglen)) { 
248         // tag mismatch
249         fprintf(stderr,"Tag mismatch in read tag\n");
250         rc =-1;
251       } else {
252         // OK, do data read
253         rc = read_all(fd,(*resp)->buf,req->xfer);
254       }
255     }
256
257     (*resp)->len=sizeof(struct palacios_user_keyed_stream_op) + (rc>0 ? rc : 0);
258     (*resp)->type=req->type;
259     (*resp)->xfer=rc;
260     (*resp)->user_key=(void*)(uint64_t)fd;
261     (*resp)->buf_len=rc>0 ? rc : 0;
262     (*resp)->data_off = 0;
263
264     return 0;
265
266 }
267
268
269
270
271 int handle_request(struct palacios_user_keyed_stream_op *req, 
272                    struct palacios_user_keyed_stream_op **resp,
273                    char *dir)
274 {
275     uint64_t datasize;
276     
277     switch (req->type) { 
278         case PALACIOS_KSTREAM_OPEN:
279         case PALACIOS_KSTREAM_CLOSE:
280             fprintf(stderr,"unsupported stream open or close\n");
281             return -1;
282             break;
283
284         case PALACIOS_KSTREAM_OPEN_KEY:
285             return handle_open_key(req,resp,dir);
286             break;
287         case PALACIOS_KSTREAM_CLOSE_KEY:
288             return handle_close_key(req,resp,dir);
289             break;
290         case PALACIOS_KSTREAM_READ_KEY:
291             return handle_read_key(req,resp,dir);
292             break;
293         case PALACIOS_KSTREAM_WRITE_KEY:
294             return handle_write_key(req,resp,dir);
295             break;
296         default:
297             fprintf(stderr,"unknown request type\n");
298             return -1;
299             break;
300     }
301
302     return 0;
303 }
304
305
306 int run(int devfd, char *dir) 
307
308     struct palacios_user_keyed_stream_op *req;
309     struct palacios_user_keyed_stream_op *resp;
310     fd_set   readset;
311     int rc;
312     
313     while (1) { 
314         FD_ZERO(&readset);
315         FD_SET(devfd,&readset);
316         
317         rc = select(devfd+1, &readset, 0, 0, 0);  
318         
319         if (rc>0) { 
320             if (FD_ISSET(devfd,&readset)) { 
321
322                 int err;
323
324                 if (v3_user_keyed_stream_pull_request(devfd, &req)) { 
325                     fprintf(stderr, "could not get request\n");
326                     free(req);
327                     return -1;
328                 }
329                 
330                 err=handle_request(req, &resp, dir);
331
332                 if (v3_user_keyed_stream_push_response(devfd, resp)) { 
333                     fprintf(stderr,"could not send response\n");
334                     free(req);
335                     free(resp);
336                     return -1;
337                 }
338
339                 if (err) { 
340                     fprintf(stderr, "request handling resulted in an error, continuing\n");
341                 }
342                 
343                 free(req);
344                 free(resp);
345             }
346         }
347     }
348
349     return 0;
350 }
351
352
353
354 int main(int argc, char *argv[])
355 {
356     int devfd;
357     char *vm, *url;
358     char *dir;
359
360     if (argc!=3) { 
361         usage();
362         exit(-1);
363     }
364     
365     vm=argv[1];
366     url=argv[2];
367
368     if (strncmp(url,"user:file:",10)) { 
369         fprintf(stderr, "Url %s is not a user:file: url\n",url);
370         exit(-1);
371     }
372
373     dir = url+10;
374
375     if (dir_setup(dir)) { 
376         fprintf(stderr,"Unable to open or create directory %s\n",dir);
377         return -1;
378     }
379
380     fprintf(stderr,"Attempting to attach to vm %s as url %s\n", vm, url);
381     
382     if ((devfd = v3_user_keyed_stream_attach(vm,url))<0) { 
383         perror("failed to attach");
384         exit(-1);
385     }
386     
387     fprintf(stderr,"Attached and running\n");
388
389     run(devfd,dir);
390
391     v3_user_keyed_stream_detach(devfd);
392     
393     return 0;
394
395 }
396