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 strlcpy(out, newline, len); 160 return out; 161 } 162 163 return NULL; 164 } 165 166 char *get_cmdline_val_offset(const char *name, char *out, int len, int offset) 167 { 168 char line[CMDLINE_SIZE + 1], *c, *sptr; 169 int i, fd = open("/proc/cmdline", O_RDONLY); 170 ssize_t r; 171 172 if (fd < 0) 173 return NULL; 174 175 r = read(fd, line, sizeof(line) - 1); 176 close(fd); 177 178 if (r <= 0) 179 return NULL; 180 181 line[r] = 0; 182 183 for (i = 0, c = strtok_r(line, " \t\n", &sptr); c; 184 c = strtok_r(NULL, " \t\n", &sptr)) { 185 char *sep = strchr(c, '='); 186 if (sep == NULL) 187 continue; 188 189 ssize_t klen = sep - c; 190 if (strncmp(name, c, klen) || name[klen] != 0) 191 continue; 192 193 if (i++ < offset) 194 continue; 195 strlcpy(out, &sep[1], len); 196 return out; 197 } 198 199 return NULL; 200 } 201 202 int patch_fd(const char *device, int fd, int flags) 203 { 204 int dfd, nfd; 205 206 if (device == NULL) 207 device = "/dev/null"; 208 209 if (*device != '/') { 210 dfd = open("/dev", O_PATH|O_DIRECTORY); 211 212 if (dfd < 0) 213 return -1; 214 215 nfd = openat(dfd, device, flags); 216 217 close(dfd); 218 } else { 219 nfd = open(device, flags); 220 } 221 222 if (nfd < 0 && strcmp(device, "/dev/null")) 223 nfd = open("/dev/null", flags); 224 225 if (nfd < 0) 226 return -1; 227 228 fd = dup2(nfd, fd); 229 230 if (nfd > STDERR_FILENO) 231 close(nfd); 232 233 return (fd < 0) ? -1 : 0; 234 } 235 236 int patch_stdio(const char *device) 237 { 238 int fd, rv = 0; 239 const char *fdname[3] = { "stdin", "stdout", "stderr" }; 240 241 for (fd = STDIN_FILENO; fd <= STDERR_FILENO; fd++) { 242 if (patch_fd(device, fd, fd ? O_WRONLY : O_RDONLY)) { 243 ERROR("Failed to redirect %s to %s: %m\n", 244 fdname[fd], device); 245 rv = -1; 246 } 247 } 248 249 return rv; 250 } 251
This page was automatically generated by LXR 0.3.1. • OpenWrt