1/** \file 2 * \brief inheritance of file descriptors 3 */ 4 5/* 6 * Copyright (c) 2010, 2012, ETH Zurich. 7 * All rights reserved. 8 * 9 * This file is distributed under the terms in the attached LICENSE file. 10 * If you do not find this file, copies can be found by writing to: 11 * ETH Zurich D-INFK, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group. 12 */ 13 14#include <stdio.h> 15#include <stdlib.h> 16#include <string.h> 17#include <sys/socket.h> 18 19#include <unistd.h> 20#include <fcntl.h> 21 22#include <barrelfish/barrelfish.h> 23#include <barrelfish/spawn_client.h> 24 25#include "testdesc.h" 26 27/* Copying the actual handles is hard. 28 * We could try a deep copy, but really we should come up with a serialised 29 * format for each type. It also involves implementing the underlying 30 * resources such that the descriptors can actually be used in the new 31 * dispatcher. 32 */ 33 34static size_t copy_file_fd(void *dest, lpaddr_t offset, struct fd_store *fds) 35{ 36 size_t size = sizeof(void *); 37 38 printf("FILE\n\thandle: %p\n", fds->handle); 39 40 /* This following isn't correct at all - we're just copying the value of 41 * the pointer, which is useless in the new dispatcher */ 42 43 printf("copying %zu bytes from %p to %p\n", size, &fds->handle, dest); 44 memcpy(dest, &fds->handle, size); 45 fds->handle = (void*)(offset); 46 printf("fd %d fixed handle is: %p\n", fds->num, fds->handle); 47 48 return size; 49} 50 51 52static size_t copy_unixsock_fd(void *dest, lpaddr_t offset, 53 struct fd_store *fds) 54{ 55 // shallow copy. doesn't really help us. 56 57 struct _unix_socket *ush; 58 size_t size; 59 60 ush = fds->handle; 61 printf("adding UNIX socket (%p)\n\ttype: %x protocol: %x\n\tpassive: %d " 62 "nonblkng: %d\n", 63 fds->handle, ush->type, ush->protocol, ush->passive, ush->nonblocking); 64 size = sizeof(struct _unix_socket); 65 66 printf("copying %zu bytes from %p to %p\n", size, fds->handle, dest); 67 memcpy(dest, fds->handle, size); 68 fds->handle = (void*)(offset); 69 printf("fd %d fixed handle is: %p\n", fds->num, fds->handle); 70 71 return size; 72} 73 74 75/** 76 * \brief Setup inherited file descriptors 77 * 78 */ 79static errval_t spawn_setup_fds(struct capref *frame) 80{ 81 errval_t err; 82 void *fdspg; 83 84 // Create frame (actually multiple pages) for fds 85 err = frame_alloc(frame, FDS_SIZE, NULL); 86 if (err_is_fail(err)) { 87 return err_push(err, SPAWN_ERR_CREATE_FDSPG); 88 } 89 90 // map it in so we can write to it 91 err = vspace_map_one_frame(&fdspg, FDS_SIZE, *frame, NULL, NULL); 92 if (err_is_fail(err)) { 93 return err_push(err, SPAWN_ERR_MAP_FDSPG_TO_SELF); 94 } 95 96 /* Layout of FD page: 97 * int num_fds 98 * struct fd_store fdtab[num_fds] 99 * uint8_t buf[] // store of actual handle data. entries in fdtab above 100 * // point here (relative offset from the beginning of buf). 101 * TODO: add the actual handle data! 102 */ 103 int *num_fds = (int *)fdspg; 104 *num_fds = 0; 105 struct fd_store *fdtab = (struct fd_store *)(num_fds + 1); 106 107 /* first copy all the fd table entries */ 108 struct fdtab_entry *fde; 109 struct fd_store *fds; 110 int i; 111 for (i = MIN_FD; i < MAX_FD; i++) { 112 fde = fdtab_get(i); 113 if (fde->type != FDTAB_TYPE_AVAILABLE) { 114 fds = &fdtab[*num_fds]; 115 fds->num = i; 116 fds->type = fde->type; 117 fds->handle = fde->handle; 118 printf("added fd %d to fdtabs[%d]: %p as fd_store (%p: num: %d, " 119 "type: %d, (unfixed)handle: %p)\n", 120 i, *num_fds, &fdtab[*num_fds], fds, fds->num, fds->type, 121 fds->handle); 122 (*num_fds)++; 123 } 124 } 125 126 /* then copy all the handle data to the buffer */ 127 char *buf = (char *)&fdtab[*num_fds]; 128 char *dest = buf; 129 genpaddr_t offset; 130 size_t size; 131 for (i = 0; i < *num_fds; i++) { 132 fds = &fdtab[i]; 133 offset = (genpaddr_t)(dest - buf); 134 switch (fds->type) { 135 case FDTAB_TYPE_FILE: 136 size = copy_file_fd(dest, offset, fds); 137 break; 138 case FDTAB_TYPE_UNIX_SOCKET: 139 size = copy_unixsock_fd(dest, offset, fds); 140 break; 141 default: 142 // nothing to copy 143 size = 0; 144 break; 145 } 146 dest += size; 147 } 148 149 // unmap frame 150 err = vspace_unmap(fdspg); 151 152 return err; 153} 154 155 156static errval_t spawn_child(struct capref fdcap) 157 158{ 159 errval_t err; 160 161 char *argv[2] = { "testdesc-child", NULL }; 162 163 struct capref new_domain; 164 165 coreid_t core = 0; 166 167 // allocate inheritcn 168 struct capref inheritcn_cap; 169 err = alloc_inheritcn_with_caps(&inheritcn_cap, fdcap, 170 NULL_CAP, NULL_CAP); 171 172 err = spawn_program_with_caps(core, argv[0], argv, NULL, inheritcn_cap, 173 NULL_CAP, SPAWN_FLAGS_NEW_DOMAIN, &new_domain); 174 175 if (err_is_fail(err)) { 176 DEBUG_ERR(err, "failed spawn on core %d", core); 177 return err; 178 } 179 180 return SYS_ERR_OK; 181 182} 183 184int main(int argc, char *argv[]) 185{ 186 errval_t err; 187 188 printf("Test inheritance of file descriptors\n"); 189 190 // create some file handles 191 int fd = open("test file", O_CREAT); 192 printf("opened a file with fd: %d\n", fd); 193 194 fd = socket(AF_UNIX, SOCK_STREAM, 0); 195 printf("opened a socket with fd: %d\n", fd); 196 197 struct capref fdcap; 198 err = spawn_setup_fds(&fdcap); 199 if (err_is_fail(err)) { 200 DEBUG_ERR(err, "could not setup fds!\n"); 201 return EXIT_FAILURE; 202 } 203 204 err = spawn_child(fdcap); 205 if (err_is_fail(err)) { 206 DEBUG_ERR(err, "could not spawn child!\n"); 207 return EXIT_FAILURE; 208 } 209 210 return EXIT_SUCCESS; 211} 212