| 1222 | } |
| 1223 | |
| 1224 | int |
| 1225 | exec_copyin_data_fds(struct thread *td, struct image_args *args, |
| 1226 | const void *data, size_t datalen, const int *fds, size_t fdslen) |
| 1227 | { |
| 1228 | struct filedesc *ofdp; |
| 1229 | const char *p; |
| 1230 | int *kfds; |
| 1231 | int error; |
| 1232 | |
| 1233 | memset(args, '\0', sizeof(*args)); |
| 1234 | ofdp = td->td_proc->p_fd; |
| 1235 | if (datalen >= ARG_MAX || fdslen >= ofdp->fd_nfiles) |
| 1236 | return (E2BIG); |
| 1237 | error = exec_alloc_args(args); |
| 1238 | if (error != 0) |
| 1239 | return (error); |
| 1240 | |
| 1241 | args->begin_argv = args->buf; |
| 1242 | args->stringspace = ARG_MAX; |
| 1243 | |
| 1244 | if (datalen > 0) { |
| 1245 | /* |
| 1246 | * Argument buffer has been provided. Copy it into the |
| 1247 | * kernel as a single string and add a terminating null |
| 1248 | * byte. |
| 1249 | */ |
| 1250 | error = copyin(data, args->begin_argv, datalen); |
| 1251 | if (error != 0) |
| 1252 | goto err_exit; |
| 1253 | args->begin_argv[datalen] = '\0'; |
| 1254 | args->endp = args->begin_argv + datalen + 1; |
| 1255 | args->stringspace -= datalen + 1; |
| 1256 | |
| 1257 | /* |
| 1258 | * Traditional argument counting. Count the number of |
| 1259 | * null bytes. |
| 1260 | */ |
| 1261 | for (p = args->begin_argv; p < args->endp; ++p) |
| 1262 | if (*p == '\0') |
| 1263 | ++args->argc; |
| 1264 | } else { |
| 1265 | /* No argument buffer provided. */ |
| 1266 | args->endp = args->begin_argv; |
| 1267 | } |
| 1268 | |
| 1269 | /* Create new file descriptor table. */ |
| 1270 | kfds = malloc(fdslen * sizeof(int), M_TEMP, M_WAITOK); |
| 1271 | error = copyin(fds, kfds, fdslen * sizeof(int)); |
| 1272 | if (error != 0) { |
| 1273 | free(kfds, M_TEMP); |
| 1274 | goto err_exit; |
| 1275 | } |
| 1276 | error = fdcopy_remapped(ofdp, kfds, fdslen, &args->fdp); |
| 1277 | free(kfds, M_TEMP); |
| 1278 | if (error != 0) |
| 1279 | goto err_exit; |
| 1280 | |
| 1281 | return (0); |
nothing calls this directly
no test coverage detected