8f14aadc7903d241bb07253b2b02eff808d3f644
2 * Copyright (C) 2013 Felix Fietkau <nbd@openwrt.org>
3 * Copyright (C) 2013 John Crispin <blogic@openwrt.org>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU Lesser General Public License version 2.1
7 * as published by the Free Software Foundation
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
16 #include <libubox/avl.h>
17 #include <libubox/avl-cmp.h>
21 #include <sys/types.h>
30 __blobmsg_list_init(struct blobmsg_list
*list
, int offset
, int len
, blobmsg_list_cmp cmp
)
32 avl_init(&list
->avl
, avl_strcmp
, false, NULL
);
33 list
->node_offset
= offset
;
39 blobmsg_list_fill(struct blobmsg_list
*list
, void *data
, int len
, bool array
)
41 struct avl_tree
*tree
= &list
->avl
;
42 struct blobmsg_list_node
*node
;
43 struct blob_attr
*cur
;
48 __blob_for_each_attr(cur
, data
, rem
) {
49 if (!blobmsg_check_attr(cur
, !array
))
52 ptr
= calloc(1, list
->node_len
);
56 node
= (void *) ((char *)ptr
+ list
->node_offset
);
58 node
->avl
.key
= blobmsg_data(cur
);
60 node
->avl
.key
= blobmsg_name(cur
);
62 if (avl_insert(tree
, &node
->avl
)) {
74 blobmsg_list_move(struct blobmsg_list
*list
, struct blobmsg_list
*src
)
76 struct blobmsg_list_node
*node
, *tmp
;
79 avl_remove_all_elements(&src
->avl
, node
, avl
, tmp
) {
80 if (avl_insert(&list
->avl
, &node
->avl
)) {
81 ptr
= ((char *) node
- list
->node_offset
);
88 blobmsg_list_free(struct blobmsg_list
*list
)
90 struct blobmsg_list_node
*node
, *tmp
;
93 avl_remove_all_elements(&list
->avl
, node
, avl
, tmp
) {
94 ptr
= ((char *) node
- list
->node_offset
);
100 blobmsg_list_equal(struct blobmsg_list
*l1
, struct blobmsg_list
*l2
)
102 struct blobmsg_list_node
*n1
, *n2
;
103 int count
= l1
->avl
.count
;
105 if (count
!= l2
->avl
.count
)
108 n1
= avl_first_element(&l1
->avl
, n1
, avl
);
109 n2
= avl_first_element(&l2
->avl
, n2
, avl
);
111 while (count
-- > 0) {
114 len
= blob_len(n1
->data
);
115 if (len
!= blob_len(n2
->data
))
118 if (memcmp(n1
->data
, n2
->data
, len
) != 0)
121 if (l1
->cmp
&& !l1
->cmp(n1
, n2
))
127 n1
= avl_next_element(n1
, avl
);
128 n2
= avl_next_element(n2
, avl
);
134 char* get_cmdline_val(const char* name
, char* out
, int len
)
136 char line
[CMDLINE_SIZE
+ 1], *c
, *sptr
;
137 int fd
= open("/proc/cmdline", O_RDONLY
);
138 ssize_t r
= read(fd
, line
, sizeof(line
) - 1);
146 for (c
= strtok_r(line
, " \t\n", &sptr
); c
;
147 c
= strtok_r(NULL
, " \t\n", &sptr
)) {
148 char *sep
= strchr(c
, '=');
149 ssize_t klen
= sep
- c
;
150 if (klen
< 0 || strncmp(name
, c
, klen
) || name
[klen
] != 0)
153 strncpy(out
, &sep
[1], len
);
161 int patch_fd(const char *device
, int fd
, int flags
)
166 device
= "/dev/null";
168 if (*device
!= '/') {
169 dfd
= open("/dev", O_PATH
|O_DIRECTORY
);
174 nfd
= openat(dfd
, device
, flags
);
178 nfd
= open(device
, flags
);
181 if (nfd
< 0 && strcmp(device
, "/dev/null"))
182 nfd
= open("/dev/null", flags
);
189 if (nfd
> STDERR_FILENO
)
192 return (fd
< 0) ? -1 : 0;
195 int patch_stdio(const char *device
)
198 const char *fdname
[3] = { "stdin", "stdout", "stderr" };
200 for (fd
= STDIN_FILENO
; fd
<= STDERR_FILENO
; fd
++) {
201 if (patch_fd(device
, fd
, fd
? O_WRONLY
: O_RDONLY
)) {
202 ERROR("Failed to redirect %s to %s: %d (%s)\n",
203 fdname
[fd
], device
, errno
, strerror(errno
));