Add serialization for syscall args (XCC)
[akaros.git] / tools / compilers / gcc-glibc / glibc-2.19-akaros / sysdeps / akaros / serialize.c
1 /* Copyright (c) 2015 Google Inc., All Rights Reserved.
2  * Kevin Klues <klueska@google.com>
3  * See LICENSE for details. */
4
5 #include <parlib/serialize.h>
6 #include <malloc.h>
7 #include <string.h>
8 #include <stddef.h>
9 #include <stdint.h>
10
11 struct serialized_data* serialize_argv_envp(char* const* argv,
12                                             char* const* envp)
13 {
14         size_t bufsize = 0;
15         size_t argc = 0, envc = 0;
16         struct serialized_data *sd;
17
18         /* Count how many args and environment variables we have. */
19         if(argv) while(argv[argc]) argc++;
20         if(envp) while(envp[envc]) envc++;
21
22         /* Reserve space for argc and envc as well as space for the actual
23          * pointers to our arguments and environment variables in a
24          * to-be-allocated buffer ... */
25         bufsize += sizeof(argc) + sizeof(envc);
26         bufsize += ((argc + envc) * sizeof(uintptr_t));
27
28         /* Reserve space in the buffer for each of our arguments (the +1 comes
29          * from the '\0' character) */
30         int arglens[argc];
31         for (int i = 0; i < argc; i++) {
32                 arglens[i] = strlen(argv[i]) + 1;
33                 bufsize += arglens[i];
34         }
35
36         /* Reserve space in our buffer for each of our environment variables (the
37          * +1 comes from the '\0' character) */
38         int envlens[envc];
39         for (int i = 0; i < envc; i++) {
40                 envlens[i] = strlen(envp[i]) + 1;
41                 bufsize += envlens[i];
42         }
43
44         /* Allocate an sd struct with enough room for all of our
45          * arguments, environment variables, and their pointers. */
46         sd = calloc(1, sizeof(struct serialized_data) + bufsize);
47         if (!sd)
48                 return sd;
49
50         /* Now fill in the buffer!. */
51         size_t *sd_argc = (size_t*)(sd->buf);
52         size_t *sd_envc = (size_t*)(sd->buf + sizeof(size_t));
53         char **ppos = (char**)(sd->buf + 2*sizeof(size_t));
54         char *vpos = (char*)(ppos + argc + envc);
55         char *vpos_base = vpos;
56
57         sd->len = bufsize;
58         *sd_argc = argc;
59         *sd_envc = envc;
60         for (int i = 0; i < argc; i++) {
61                 ppos[i] = vpos - vpos_base;
62                 memcpy(vpos, argv[i], arglens[i]);
63                 vpos += arglens[i];
64         }
65         for(int i = 0; i < envc; i++) {
66                 ppos[argc + i] = vpos - vpos_base;
67                 memcpy(vpos, envp[i], envlens[i]);
68                 vpos += envlens[i];
69         }
70         return sd;
71 }
72
73 void free_serialized_data(struct serialized_data *sd)
74 {
75         free(sd);
76 }
77