1 /* 2 * Copyright (C) 2013 Felix Fietkau <nbd@openwrt.org> 3 * Copyright (C) 2013 John Crispin <blogic@openwrt.org> 4 * 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 8 * 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. 13 */ 14 15 #define _GNU_SOURCE 16 #include <libubox/avl.h> 17 #include <libubox/avl-cmp.h> 18 #include "utils.h" 19 #include <regex.h> 20 #include <unistd.h> 21 #include <sys/types.h> 22 #include <sys/stat.h> 23 #include <fcntl.h> 24 #include <string.h> 25 #include <errno.h> 26 27 #include "../log.h" 28 29 #ifndef O_PATH 30 #define O_PATH 010000000 31 #endif 32 33 void 34 __blobmsg_list_init(struct blobmsg_list *list, int offset, int len, blobmsg_list_cmp cmp) 35 { 36 avl_init(&list->avl, avl_strcmp, false, NULL); 37 list->node_offset = offset; 38 list->node_len = len; 39 list->cmp = cmp; 40 } 41 42 int 43 blobmsg_list_fill(struct blobmsg_list *list, void *data, int len, bool array) 44 { 45 struct avl_tree *tree = &list->avl; 46 struct blobmsg_list_node *node; 47 struct blob_attr *cur; 48 void *ptr; 49 int count = 0; 50 int rem = len; 51 52 __blob_for_each_attr(cur, data, rem) { 53 if (!blobmsg_check_attr(cur, !array)) 54 continue; 55 56 ptr = calloc(1, list->node_len); 57 if (!ptr) 58 return -1; 59 60 node = (void *) ((char *)ptr + list->node_offset); 61 if (array) 62 node->avl.key = blobmsg_data(cur); 63 else 64 node->avl.key = blobmsg_name(cur); 65 node->data = cur; 66 if (avl_insert(tree, &node->avl)) { 67 free(ptr); 68 continue; 69 } 70 71 count++; 72 } 73 74 return count; 75 } 76 77 void 78 blobmsg_list_move(struct blobmsg_list *list, struct blobmsg_list *src) 79 { 80 struct blobmsg_list_node *node, *tmp; 81 void *ptr; 82 83 avl_remove_all_elements(&src->avl, node, avl, tmp) { 84 if (avl_insert(&list->avl, &node->avl)) { 85 ptr = ((char *) node - list->node_offset); 86 free(ptr); 87 } 88 } 89 } 90 91 void 92 blobmsg_list_free(struct blobmsg_list *list) 93 { 94 struct blobmsg_list_node *node, *tmp; 95 void *ptr; 96 97 avl_remove_all_elements(&list->avl, node, avl, tmp) { 98 ptr = ((char *) node - list->node_offset); 99 free(ptr); 100 } 101 } 102 103 bool 104 blobmsg_list_equal(struct blobmsg_list *l1, struct blobmsg_list *l2) 105 { 106 struct blobmsg_list_node *n1, *n2; 107 int count = l1->avl.count; 108 109 if (count != l2->avl.count) 110 return false; 111 112 n1 = avl_first_element(&l1->avl, n1, avl); 113 n2 = avl_first_element(&l2->avl, n2, avl); 114 115 while (count-- > 0) { 116 int len; 117 118 len = blob_len(n1->data); 119 if (len != blob_len(n2->data)) 120 return false; 121 122 if (memcmp(n1->data, n2->data, len) != 0) 123 return false; 124 125 if (l1->cmp && !l1->cmp(n1, n2)) 126 return false; 127 128 if (!count) 129 break; 130 131 n1 = avl_next_element(n1, avl); 132 n2 = avl_next_element(n2, avl); 133 } 134 135 return true; 136 } 137 138 char *get_active_console(char *out, int len) 139 { 140 char line[CMDLINE_SIZE + 1]; 141 int fd = open("/sys/class/tty/console/active", O_RDONLY); 142 ssize_t r; 143 144 if (fd < 0) 145 return NULL; 146 147 r = read(fd, line, sizeof(line) - 1); 148 line[CMDLINE_SIZE] = '\0'; 149 150 close(fd); 151 152 if (r <= 0) 153 return NULL; 154 155 /* The active file is terminated by a newline which we need to strip */ 156 char *newline = strtok(line, "\n"); 157 158 if (newline != NULL) { 159 strncpy(out, newline, len); 160 return out; 161 } 162 163 return NULL; 164 } 165 166 char* get_cmdline_val(const char* name, char* out, int len) 167 { 168 char line[CMDLINE_SIZE + 1], *c, *sptr; 169 int fd = open("/proc/cmdline", O_RDONLY); 170 ssize_t r = read(fd, line, sizeof(line) - 1); 171 close(fd); 172 173 if (r <= 0) 174 return NULL; 175 176 line[r] = 0; 177 178 for (c = strtok_r(line, " \t\n", &sptr); c; 179 c = strtok_r(NULL, " \t\n", &sptr)) { 180 char *sep = strchr(c, '='); 181 if (sep == NULL) 182 continue; 183 184 ssize_t klen = sep - c; 185 if (strncmp(name, c, klen) || name[klen] != 0) 186 continue; 187 188 strncpy(out, &sep[1], len); 189 out[len-1] = 0; 190 return out; 191 } 192 193 return NULL; 194 } 195 196 int patch_fd(const char *device, int fd, int flags) 197 { 198 int dfd, nfd; 199 200 if (device == NULL) 201 device = "/dev/null"; 202 203 if (*device != '/') { 204 dfd = open("/dev", O_PATH|O_DIRECTORY); 205 206 if (dfd < 0) 207 return -1; 208 209 nfd = openat(dfd, device, flags); 210 211 close(dfd); 212 } else { 213 nfd = open(device, flags); 214 } 215 216 if (nfd < 0 && strcmp(device, "/dev/null")) 217 nfd = open("/dev/null", flags); 218 219 if (nfd < 0) 220 return -1; 221 222 fd = dup2(nfd, fd); 223 224 if (nfd > STDERR_FILENO) 225 close(nfd); 226 227 return (fd < 0) ? -1 : 0; 228 } 229 230 int patch_stdio(const char *device) 231 { 232 int fd, rv = 0; 233 const char *fdname[3] = { "stdin", "stdout", "stderr" }; 234 235 for (fd = STDIN_FILENO; fd <= STDERR_FILENO; fd++) { 236 if (patch_fd(device, fd, fd ? O_WRONLY : O_RDONLY)) { 237 ERROR("Failed to redirect %s to %s: %m\n", 238 fdname[fd], device); 239 rv = -1; 240 } 241 } 242 243 return rv; 244 } 245
This page was automatically generated by LXR 0.3.1. • OpenWrt