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.
15 #include <libubox/avl.h>
16 #include <libubox/avl-cmp.h>
20 #include <sys/types.h>
29 __blobmsg_list_init(struct blobmsg_list
*list
, int offset
, int len
, blobmsg_list_cmp cmp
)
31 avl_init(&list
->avl
, avl_strcmp
, false, NULL
);
32 list
->node_offset
= offset
;
38 blobmsg_list_fill(struct blobmsg_list
*list
, void *data
, int len
, bool array
)
40 struct avl_tree
*tree
= &list
->avl
;
41 struct blobmsg_list_node
*node
;
42 struct blob_attr
*cur
;
47 __blob_for_each_attr(cur
, data
, rem
) {
48 if (!blobmsg_check_attr(cur
, !array
))
51 ptr
= calloc(1, list
->node_len
);
55 node
= (void *) ((char *)ptr
+ list
->node_offset
);
57 node
->avl
.key
= blobmsg_data(cur
);
59 node
->avl
.key
= blobmsg_name(cur
);
61 if (avl_insert(tree
, &node
->avl
)) {
73 blobmsg_list_move(struct blobmsg_list
*list
, struct blobmsg_list
*src
)
75 struct blobmsg_list_node
*node
, *tmp
;
78 avl_remove_all_elements(&src
->avl
, node
, avl
, tmp
) {
79 if (avl_insert(&list
->avl
, &node
->avl
)) {
80 ptr
= ((char *) node
- list
->node_offset
);
87 blobmsg_list_free(struct blobmsg_list
*list
)
89 struct blobmsg_list_node
*node
, *tmp
;
92 avl_remove_all_elements(&list
->avl
, node
, avl
, tmp
) {
93 ptr
= ((char *) node
- list
->node_offset
);
99 blobmsg_list_equal(struct blobmsg_list
*l1
, struct blobmsg_list
*l2
)
101 struct blobmsg_list_node
*n1
, *n2
;
102 int count
= l1
->avl
.count
;
104 if (count
!= l2
->avl
.count
)
107 n1
= avl_first_element(&l1
->avl
, n1
, avl
);
108 n2
= avl_first_element(&l2
->avl
, n2
, avl
);
110 while (count
-- > 0) {
113 len
= blob_len(n1
->data
);
114 if (len
!= blob_len(n2
->data
))
117 if (memcmp(n1
->data
, n2
->data
, len
) != 0)
120 if (l1
->cmp
&& !l1
->cmp(n1
, n2
))
126 n1
= avl_next_element(n1
, avl
);
127 n2
= avl_next_element(n2
, avl
);
133 char* get_cmdline_val(const char* name
, char* out
, int len
)
135 char line
[CMDLINE_SIZE
+ 1], *c
, *sptr
;
136 int fd
= open("/proc/cmdline", O_RDONLY
);
137 ssize_t r
= read(fd
, line
, sizeof(line
) - 1);
145 for (c
= strtok_r(line
, " \t\n", &sptr
); c
;
146 c
= strtok_r(NULL
, " \t\n", &sptr
)) {
147 char *sep
= strchr(c
, '=');
148 ssize_t klen
= sep
- c
;
149 if (klen
< 0 || strncmp(name
, c
, klen
) || name
[klen
] != 0)
152 strncpy(out
, &sep
[1], len
);
160 int patch_fd(const char *device
, int fd
, int flags
)
165 device
= "/dev/null";
167 if (*device
!= '/') {
168 dfd
= open("/dev", O_RDONLY
);
173 nfd
= openat(dfd
, device
, flags
);
177 nfd
= open(device
, flags
);
180 if (nfd
< 0 && strcmp(device
, "/dev/null"))
181 nfd
= open("/dev/null", flags
);
188 if (nfd
> STDERR_FILENO
)
191 return (fd
< 0) ? -1 : 0;
194 int patch_stdio(const char *device
)
197 const char *fdname
[3] = { "stdin", "stdout", "stderr" };
199 for (fd
= STDIN_FILENO
; fd
<= STDERR_FILENO
; fd
++) {
200 if (patch_fd(device
, fd
, fd
? O_WRONLY
: O_RDONLY
)) {
201 ERROR("Failed to redirect %s to %s: %d (%s)\n",
202 fdname
[fd
], device
, errno
, strerror(errno
));