1 /* 2 * Copyright (C) 2008 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 <stdarg.h> 18 #include <stdlib.h> 19 #include <stdio.h> 20 #include <string.h> 21 #include <fcntl.h> 22 #include <ctype.h> 23 #include <errno.h> 24 #include <time.h> 25 26 #include <sys/stat.h> 27 #include <sys/types.h> 28 #include <sys/socket.h> 29 #include <sys/un.h> 30 31 /* for ANDROID_SOCKET_* */ 32 #include <cutils/sockets.h> 33 34 #include <private/android_filesystem_config.h> 35 36 #include "log.h" 37 #include "list.h" 38 #include "util.h" 39 40 static int log_fd = -1; 41 /* Inital log level before init.rc is parsed and this this is reset. */ 42 static int log_level = LOG_DEFAULT_LEVEL; 43 44 45 void log_set_level(int level) { 46 log_level = level; 47 } 48 49 void log_init(void) 50 { 51 static const char *name = "/dev/__kmsg__"; 52 if (mknod(name, S_IFCHR | 0600, (1 << 8) | 11) == 0) { 53 log_fd = open(name, O_WRONLY); 54 fcntl(log_fd, F_SETFD, FD_CLOEXEC); 55 unlink(name); 56 } 57 } 58 59 #define LOG_BUF_MAX 512 60 61 void log_write(int level, const char *fmt, ...) 62 { 63 char buf[LOG_BUF_MAX]; 64 va_list ap; 65 66 if (level > log_level) return; 67 if (log_fd < 0) return; 68 69 va_start(ap, fmt); 70 vsnprintf(buf, LOG_BUF_MAX, fmt, ap); 71 buf[LOG_BUF_MAX - 1] = 0; 72 va_end(ap); 73 write(log_fd, buf, strlen(buf)); 74 } 75 76 /* 77 * android_name_to_id - returns the integer uid/gid associated with the given 78 * name, or -1U on error. 79 */ 80 static unsigned int android_name_to_id(const char *name) 81 { 82 struct android_id_info *info = android_ids; 83 unsigned int n; 84 85 for (n = 0; n < android_id_count; n++) { 86 if (!strcmp(info[n].name, name)) 87 return info[n].aid; 88 } 89 90 return -1U; 91 } 92 93 /* 94 * decode_uid - decodes and returns the given string, which can be either the 95 * numeric or name representation, into the integer uid or gid. Returns -1U on 96 * error. 97 */ 98 unsigned int decode_uid(const char *s) 99 { 100 unsigned int v; 101 102 if (!s || *s == '\0') 103 return -1U; 104 if (isalpha(s[0])) 105 return android_name_to_id(s); 106 107 errno = 0; 108 v = (unsigned int) strtoul(s, 0, 0); 109 if (errno) 110 return -1U; 111 return v; 112 } 113 114 /* 115 * create_socket - creates a Unix domain socket in ANDROID_SOCKET_DIR 116 * ("/dev/socket") as dictated in init.rc. This socket is inherited by the 117 * daemon. We communicate the file descriptor's value via the environment 118 * variable ANDROID_SOCKET_ENV_PREFIX<name> ("ANDROID_SOCKET_foo"). 119 */ 120 int create_socket(const char *name, int type, mode_t perm, uid_t uid, gid_t gid) 121 { 122 struct sockaddr_un addr; 123 int fd, ret; 124 125 fd = socket(PF_UNIX, type, 0); 126 if (fd < 0) { 127 ERROR("Failed to open socket '%s': %s\n", name, strerror(errno)); 128 return -1; 129 } 130 131 memset(&addr, 0 , sizeof(addr)); 132 addr.sun_family = AF_UNIX; 133 snprintf(addr.sun_path, sizeof(addr.sun_path), ANDROID_SOCKET_DIR"/%s", 134 name); 135 136 ret = unlink(addr.sun_path); 137 if (ret != 0 && errno != ENOENT) { 138 ERROR("Failed to unlink old socket '%s': %s\n", name, strerror(errno)); 139 goto out_close; 140 } 141 142 ret = bind(fd, (struct sockaddr *) &addr, sizeof (addr)); 143 if (ret) { 144 ERROR("Failed to bind socket '%s': %s\n", name, strerror(errno)); 145 goto out_unlink; 146 } 147 148 chown(addr.sun_path, uid, gid); 149 chmod(addr.sun_path, perm); 150 151 INFO("Created socket '%s' with mode '%o', user '%d', group '%d'\n", 152 addr.sun_path, perm, uid, gid); 153 154 return fd; 155 156 out_unlink: 157 unlink(addr.sun_path); 158 out_close: 159 close(fd); 160 return -1; 161 } 162 163 /* reads a file, making sure it is terminated with \n \0 */ 164 void *read_file(const char *fn, unsigned *_sz) 165 { 166 char *data; 167 int sz; 168 int fd; 169 170 data = 0; 171 fd = open(fn, O_RDONLY); 172 if(fd < 0) return 0; 173 174 sz = lseek(fd, 0, SEEK_END); 175 if(sz < 0) goto oops; 176 177 if(lseek(fd, 0, SEEK_SET) != 0) goto oops; 178 179 data = (char*) malloc(sz + 2); 180 if(data == 0) goto oops; 181 182 if(read(fd, data, sz) != sz) goto oops; 183 close(fd); 184 data[sz] = '\n'; 185 data[sz+1] = 0; 186 if(_sz) *_sz = sz; 187 return data; 188 189 oops: 190 close(fd); 191 if(data != 0) free(data); 192 return 0; 193 } 194 195 void list_init(struct listnode *node) 196 { 197 node->next = node; 198 node->prev = node; 199 } 200 201 void list_add_tail(struct listnode *head, struct listnode *item) 202 { 203 item->next = head; 204 item->prev = head->prev; 205 head->prev->next = item; 206 head->prev = item; 207 } 208 209 void list_remove(struct listnode *item) 210 { 211 item->next->prev = item->prev; 212 item->prev->next = item->next; 213 } 214 215 #define MAX_MTD_PARTITIONS 16 216 217 static struct { 218 char name[16]; 219 int number; 220 } mtd_part_map[MAX_MTD_PARTITIONS]; 221 222 static int mtd_part_count = -1; 223 224 static void find_mtd_partitions(void) 225 { 226 int fd; 227 char buf[1024]; 228 char *pmtdbufp; 229 ssize_t pmtdsize; 230 int r; 231 232 fd = open("/proc/mtd", O_RDONLY); 233 if (fd < 0) 234 return; 235 236 buf[sizeof(buf) - 1] = '\0'; 237 pmtdsize = read(fd, buf, sizeof(buf) - 1); 238 pmtdbufp = buf; 239 while (pmtdsize > 0) { 240 int mtdnum, mtdsize, mtderasesize; 241 char mtdname[16]; 242 mtdname[0] = '\0'; 243 mtdnum = -1; 244 r = sscanf(pmtdbufp, "mtd%d: %x %x %15s", 245 &mtdnum, &mtdsize, &mtderasesize, mtdname); 246 if ((r == 4) && (mtdname[0] == '"')) { 247 char *x = strchr(mtdname + 1, '"'); 248 if (x) { 249 *x = 0; 250 } 251 INFO("mtd partition %d, %s\n", mtdnum, mtdname + 1); 252 if (mtd_part_count < MAX_MTD_PARTITIONS) { 253 strcpy(mtd_part_map[mtd_part_count].name, mtdname + 1); 254 mtd_part_map[mtd_part_count].number = mtdnum; 255 mtd_part_count++; 256 } else { 257 ERROR("too many mtd partitions\n"); 258 } 259 } 260 while (pmtdsize > 0 && *pmtdbufp != '\n') { 261 pmtdbufp++; 262 pmtdsize--; 263 } 264 if (pmtdsize > 0) { 265 pmtdbufp++; 266 pmtdsize--; 267 } 268 } 269 close(fd); 270 } 271 272 int mtd_name_to_number(const char *name) 273 { 274 int n; 275 if (mtd_part_count < 0) { 276 mtd_part_count = 0; 277 find_mtd_partitions(); 278 } 279 for (n = 0; n < mtd_part_count; n++) { 280 if (!strcmp(name, mtd_part_map[n].name)) { 281 return mtd_part_map[n].number; 282 } 283 } 284 return -1; 285 } 286 287 /* 288 * gettime() - returns the time in seconds of the system's monotonic clock or 289 * zero on error. 290 */ 291 time_t gettime(void) 292 { 293 struct timespec ts; 294 int ret; 295 296 ret = clock_gettime(CLOCK_MONOTONIC, &ts); 297 if (ret < 0) { 298 ERROR("clock_gettime(CLOCK_MONOTONIC) failed: %s\n", strerror(errno)); 299 return 0; 300 } 301 302 return ts.tv_sec; 303 } 304 305 int mkdir_recursive(const char *pathname, mode_t mode) 306 { 307 char buf[128]; 308 const char *slash; 309 const char *p = pathname; 310 int width; 311 int ret; 312 struct stat info; 313 314 while ((slash = strchr(p, '/')) != NULL) { 315 width = slash - pathname; 316 p = slash + 1; 317 if (width < 0) 318 break; 319 if (width == 0) 320 continue; 321 if ((unsigned int)width > sizeof(buf) - 1) { 322 ERROR("path too long for mkdir_recursive\n"); 323 return -1; 324 } 325 memcpy(buf, pathname, width); 326 buf[width] = 0; 327 if (stat(buf, &info) != 0) { 328 ret = mkdir(buf, mode); 329 if (ret && errno != EEXIST) 330 return ret; 331 } 332 } 333 ret = mkdir(pathname, mode); 334 if (ret && errno != EEXIST) 335 return ret; 336 return 0; 337 } 338 339 void sanitize(char *s) 340 { 341 if (!s) 342 return; 343 while (isalnum(*s)) 344 s++; 345 *s = 0; 346 } 347 void make_link(const char *oldpath, const char *newpath) 348 { 349 int ret; 350 char buf[256]; 351 char *slash; 352 int width; 353 354 slash = strrchr(newpath, '/'); 355 if (!slash) 356 return; 357 width = slash - newpath; 358 if (width <= 0 || width > (int)sizeof(buf) - 1) 359 return; 360 memcpy(buf, newpath, width); 361 buf[width] = 0; 362 ret = mkdir_recursive(buf, 0755); 363 if (ret) 364 ERROR("Failed to create directory %s: %s (%d)\n", buf, strerror(errno), errno); 365 366 ret = symlink(oldpath, newpath); 367 if (ret && errno != EEXIST) 368 ERROR("Failed to symlink %s to %s: %s (%d)\n", oldpath, newpath, strerror(errno), errno); 369 } 370 371 void remove_link(const char *oldpath, const char *newpath) 372 { 373 char path[256]; 374 ssize_t ret; 375 ret = readlink(newpath, path, sizeof(path) - 1); 376 if (ret <= 0) 377 return; 378 path[ret] = 0; 379 if (!strcmp(path, oldpath)) 380 unlink(newpath); 381 } 382 383 int wait_for_file(const char *filename, int timeout) 384 { 385 struct stat info; 386 time_t timeout_time = gettime() + timeout; 387 int ret = -1; 388 389 while (gettime() < timeout_time && ((ret = stat(filename, &info)) < 0)) 390 usleep(10000); 391 392 return ret; 393 } 394 395 void open_devnull_stdio(void) 396 { 397 int fd; 398 static const char *name = "/dev/__null__"; 399 if (mknod(name, S_IFCHR | 0600, (1 << 8) | 3) == 0) { 400 fd = open(name, O_RDWR); 401 unlink(name); 402 if (fd >= 0) { 403 dup2(fd, 0); 404 dup2(fd, 1); 405 dup2(fd, 2); 406 if (fd > 2) { 407 close(fd); 408 } 409 return; 410 } 411 } 412 413 exit(1); 414 } 415 416 void get_hardware_name(char *hardware, unsigned int *revision) 417 { 418 char data[1024]; 419 int fd, n; 420 char *x, *hw, *rev; 421 422 /* Hardware string was provided on kernel command line */ 423 if (hardware[0]) 424 return; 425 426 fd = open("/proc/cpuinfo", O_RDONLY); 427 if (fd < 0) return; 428 429 n = read(fd, data, 1023); 430 close(fd); 431 if (n < 0) return; 432 433 data[n] = 0; 434 hw = strstr(data, "\nHardware"); 435 rev = strstr(data, "\nRevision"); 436 437 if (hw) { 438 x = strstr(hw, ": "); 439 if (x) { 440 x += 2; 441 n = 0; 442 while (*x && !isspace(*x)) { 443 hardware[n++] = tolower(*x); 444 x++; 445 if (n == 31) break; 446 } 447 hardware[n] = 0; 448 } 449 } 450 451 if (rev) { 452 x = strstr(rev, ": "); 453 if (x) { 454 *revision = strtoul(x + 2, 0, 16); 455 } 456 } 457 } 458