1 /*
2 * Copyright (C) 2007 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include <cutils/native_handle.h>
18
19 #include <errno.h>
20 #include <stdint.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <unistd.h>
24
native_handle_init(char * storage,int numFds,int numInts)25 native_handle_t* native_handle_init(char* storage, int numFds, int numInts) {
26 if ((uintptr_t) storage % alignof(native_handle_t)) {
27 errno = EINVAL;
28 return NULL;
29 }
30
31 native_handle_t* handle = (native_handle_t*) storage;
32 handle->version = sizeof(native_handle_t);
33 handle->numFds = numFds;
34 handle->numInts = numInts;
35 return handle;
36 }
37
native_handle_create(int numFds,int numInts)38 native_handle_t* native_handle_create(int numFds, int numInts) {
39 if (numFds < 0 || numInts < 0 || numFds > NATIVE_HANDLE_MAX_FDS ||
40 numInts > NATIVE_HANDLE_MAX_INTS) {
41 errno = EINVAL;
42 return NULL;
43 }
44
45 size_t mallocSize = sizeof(native_handle_t) + (sizeof(int) * (numFds + numInts));
46 native_handle_t* h = malloc(mallocSize);
47 if (h) {
48 h->version = sizeof(native_handle_t);
49 h->numFds = numFds;
50 h->numInts = numInts;
51 }
52 return h;
53 }
54
native_handle_clone(const native_handle_t * handle)55 native_handle_t* native_handle_clone(const native_handle_t* handle) {
56 native_handle_t* clone = native_handle_create(handle->numFds, handle->numInts);
57 if (clone == NULL) return NULL;
58
59 for (int i = 0; i < handle->numFds; i++) {
60 clone->data[i] = dup(handle->data[i]);
61 if (clone->data[i] == -1) {
62 clone->numFds = i;
63 native_handle_close(clone);
64 native_handle_delete(clone);
65 return NULL;
66 }
67 }
68
69 memcpy(&clone->data[handle->numFds], &handle->data[handle->numFds],
70 sizeof(int) * handle->numInts);
71
72 return clone;
73 }
74
native_handle_delete(native_handle_t * h)75 int native_handle_delete(native_handle_t* h) {
76 if (h) {
77 if (h->version != sizeof(native_handle_t)) return -EINVAL;
78 free(h);
79 }
80 return 0;
81 }
82
native_handle_close(const native_handle_t * h)83 int native_handle_close(const native_handle_t* h) {
84 if (h->version != sizeof(native_handle_t)) return -EINVAL;
85
86 int saved_errno = errno;
87 const int numFds = h->numFds;
88 for (int i = 0; i < numFds; ++i) {
89 close(h->data[i]);
90 }
91 errno = saved_errno;
92 return 0;
93 }
94