util.c revision b0ab94b7d5a888f0b6920b156e5c6a075fa0741a
1dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/* 2dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Copyright (C) 2008 The Android Open Source Project 3dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * 4dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 5dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * you may not use this file except in compliance with the License. 6dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * You may obtain a copy of the License at 7dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * 8dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 9dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * 10dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 11dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 12dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * See the License for the specific language governing permissions and 14dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * limitations under the License. 15dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */ 16dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 17dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <stdarg.h> 18dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <stdlib.h> 19dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <stdio.h> 20dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <string.h> 21dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <fcntl.h> 22dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <ctype.h> 23dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <errno.h> 24504bc5175a8fe5a2f2552903afee761a86283cf4Colin Cross#include <time.h> 25dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 26dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <sys/stat.h> 27dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <sys/types.h> 28dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <sys/socket.h> 29dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <sys/un.h> 30dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 31dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/* for ANDROID_SOCKET_* */ 32dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <cutils/sockets.h> 33dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 34dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <private/android_filesystem_config.h> 35dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 36dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include "init.h" 37dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 38dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic int log_fd = -1; 39dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/* Inital log level before init.rc is parsed and this this is reset. */ 40dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic int log_level = LOG_DEFAULT_LEVEL; 41dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 42dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 43dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid log_set_level(int level) { 44dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project log_level = level; 45dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 46dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 47dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid log_init(void) 48dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 49dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project static const char *name = "/dev/__kmsg__"; 50dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (mknod(name, S_IFCHR | 0600, (1 << 8) | 11) == 0) { 51dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project log_fd = open(name, O_WRONLY); 52dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project fcntl(log_fd, F_SETFD, FD_CLOEXEC); 53dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project unlink(name); 54dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 55dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 56dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 57dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define LOG_BUF_MAX 512 58dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 59dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid log_write(int level, const char *fmt, ...) 60dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 61dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project char buf[LOG_BUF_MAX]; 62dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project va_list ap; 63dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 64dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (level > log_level) return; 65dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (log_fd < 0) return; 66dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 67dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project va_start(ap, fmt); 68dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project vsnprintf(buf, LOG_BUF_MAX, fmt, ap); 69dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project buf[LOG_BUF_MAX - 1] = 0; 70dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project va_end(ap); 71dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project write(log_fd, buf, strlen(buf)); 72dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 73dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 74dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/* 75dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * android_name_to_id - returns the integer uid/gid associated with the given 76dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * name, or -1U on error. 77dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */ 78dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic unsigned int android_name_to_id(const char *name) 79dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 80dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project struct android_id_info *info = android_ids; 81dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project unsigned int n; 82dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 83dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project for (n = 0; n < android_id_count; n++) { 84dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (!strcmp(info[n].name, name)) 85dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return info[n].aid; 86dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 87dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 88dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return -1U; 89dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 90dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 91dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/* 92dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * decode_uid - decodes and returns the given string, which can be either the 93dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * numeric or name representation, into the integer uid or gid. Returns -1U on 94dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * error. 95dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */ 96dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectunsigned int decode_uid(const char *s) 97dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 98dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project unsigned int v; 99dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 100dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (!s || *s == '\0') 101dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return -1U; 102dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (isalpha(s[0])) 103dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return android_name_to_id(s); 104dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 105dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project errno = 0; 106dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project v = (unsigned int) strtoul(s, 0, 0); 107dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (errno) 108dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return -1U; 109dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return v; 110dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 111dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 112dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/* 113dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * create_socket - creates a Unix domain socket in ANDROID_SOCKET_DIR 114dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * ("/dev/socket") as dictated in init.rc. This socket is inherited by the 115dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * daemon. We communicate the file descriptor's value via the environment 116dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * variable ANDROID_SOCKET_ENV_PREFIX<name> ("ANDROID_SOCKET_foo"). 117dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */ 118dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint create_socket(const char *name, int type, mode_t perm, uid_t uid, gid_t gid) 119dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 120dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project struct sockaddr_un addr; 121dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project int fd, ret; 122dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 123dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project fd = socket(PF_UNIX, type, 0); 124dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (fd < 0) { 125dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ERROR("Failed to open socket '%s': %s\n", name, strerror(errno)); 126dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return -1; 127dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 128dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 129dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project memset(&addr, 0 , sizeof(addr)); 130dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project addr.sun_family = AF_UNIX; 131dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project snprintf(addr.sun_path, sizeof(addr.sun_path), ANDROID_SOCKET_DIR"/%s", 132dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project name); 133dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 134dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ret = unlink(addr.sun_path); 135dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (ret != 0 && errno != ENOENT) { 136dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ERROR("Failed to unlink old socket '%s': %s\n", name, strerror(errno)); 137dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project goto out_close; 138dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 139dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 140dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ret = bind(fd, (struct sockaddr *) &addr, sizeof (addr)); 141dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (ret) { 142dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ERROR("Failed to bind socket '%s': %s\n", name, strerror(errno)); 143dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project goto out_unlink; 144dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 145dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 146dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project chown(addr.sun_path, uid, gid); 147dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project chmod(addr.sun_path, perm); 148dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 149dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project INFO("Created socket '%s' with mode '%o', user '%d', group '%d'\n", 150dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project addr.sun_path, perm, uid, gid); 151dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 152dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return fd; 153dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 154dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectout_unlink: 155dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project unlink(addr.sun_path); 156dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectout_close: 157dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project close(fd); 158dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return -1; 159dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 160dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 161dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/* reads a file, making sure it is terminated with \n \0 */ 162dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid *read_file(const char *fn, unsigned *_sz) 163dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 164dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project char *data; 165dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project int sz; 166dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project int fd; 167dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 168dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project data = 0; 169dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project fd = open(fn, O_RDONLY); 170dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(fd < 0) return 0; 171dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 172dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project sz = lseek(fd, 0, SEEK_END); 173dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(sz < 0) goto oops; 174dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 175dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(lseek(fd, 0, SEEK_SET) != 0) goto oops; 176dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 177dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project data = (char*) malloc(sz + 2); 178dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(data == 0) goto oops; 179dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 180dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(read(fd, data, sz) != sz) goto oops; 181dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project close(fd); 182dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project data[sz] = '\n'; 183dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project data[sz+1] = 0; 184dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(_sz) *_sz = sz; 185dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return data; 186dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 187dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectoops: 188dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project close(fd); 189dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(data != 0) free(data); 190dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return 0; 191dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 192dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 193dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid list_init(struct listnode *node) 194dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 195dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project node->next = node; 196dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project node->prev = node; 197dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 198dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 199dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid list_add_tail(struct listnode *head, struct listnode *item) 200dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 201dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project item->next = head; 202dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project item->prev = head->prev; 203dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project head->prev->next = item; 204dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project head->prev = item; 205dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 206dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 207dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid list_remove(struct listnode *item) 208dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 209dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project item->next->prev = item->prev; 210dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project item->prev->next = item->next; 211dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 212dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 213f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross#define MAX_MTD_PARTITIONS 16 214f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross 215f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Crossstatic struct { 216f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross char name[16]; 217f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross int number; 218f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross} mtd_part_map[MAX_MTD_PARTITIONS]; 219f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross 220f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Crossstatic int mtd_part_count = -1; 221f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross 222f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Crossstatic void find_mtd_partitions(void) 223f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross{ 224f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross int fd; 225f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross char buf[1024]; 226f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross char *pmtdbufp; 227f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross ssize_t pmtdsize; 228f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross int r; 229f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross 230f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross fd = open("/proc/mtd", O_RDONLY); 231f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross if (fd < 0) 232f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross return; 233f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross 234f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross buf[sizeof(buf) - 1] = '\0'; 235f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross pmtdsize = read(fd, buf, sizeof(buf) - 1); 236f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross pmtdbufp = buf; 237f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross while (pmtdsize > 0) { 238f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross int mtdnum, mtdsize, mtderasesize; 239f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross char mtdname[16]; 240f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross mtdname[0] = '\0'; 241f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross mtdnum = -1; 242f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross r = sscanf(pmtdbufp, "mtd%d: %x %x %15s", 243f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross &mtdnum, &mtdsize, &mtderasesize, mtdname); 244f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross if ((r == 4) && (mtdname[0] == '"')) { 245f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross char *x = strchr(mtdname + 1, '"'); 246f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross if (x) { 247f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross *x = 0; 248f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross } 249f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross INFO("mtd partition %d, %s\n", mtdnum, mtdname + 1); 250f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross if (mtd_part_count < MAX_MTD_PARTITIONS) { 251f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross strcpy(mtd_part_map[mtd_part_count].name, mtdname + 1); 252f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross mtd_part_map[mtd_part_count].number = mtdnum; 253f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross mtd_part_count++; 254f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross } else { 255f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross ERROR("too many mtd partitions\n"); 256f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross } 257f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross } 258f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross while (pmtdsize > 0 && *pmtdbufp != '\n') { 259f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross pmtdbufp++; 260f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross pmtdsize--; 261f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross } 262f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross if (pmtdsize > 0) { 263f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross pmtdbufp++; 264f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross pmtdsize--; 265f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross } 266f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross } 267f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross close(fd); 268f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross} 269f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross 270f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Crossint mtd_name_to_number(const char *name) 271f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross{ 272f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross int n; 273f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross if (mtd_part_count < 0) { 274f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross mtd_part_count = 0; 275f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross find_mtd_partitions(); 276f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross } 277f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross for (n = 0; n < mtd_part_count; n++) { 278f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross if (!strcmp(name, mtd_part_map[n].name)) { 279f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross return mtd_part_map[n].number; 280f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross } 281f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross } 282f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross return -1; 283f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross} 284504bc5175a8fe5a2f2552903afee761a86283cf4Colin Cross 285504bc5175a8fe5a2f2552903afee761a86283cf4Colin Cross/* 286504bc5175a8fe5a2f2552903afee761a86283cf4Colin Cross * gettime() - returns the time in seconds of the system's monotonic clock or 287504bc5175a8fe5a2f2552903afee761a86283cf4Colin Cross * zero on error. 288504bc5175a8fe5a2f2552903afee761a86283cf4Colin Cross */ 289504bc5175a8fe5a2f2552903afee761a86283cf4Colin Crosstime_t gettime(void) 290504bc5175a8fe5a2f2552903afee761a86283cf4Colin Cross{ 291504bc5175a8fe5a2f2552903afee761a86283cf4Colin Cross struct timespec ts; 292504bc5175a8fe5a2f2552903afee761a86283cf4Colin Cross int ret; 293504bc5175a8fe5a2f2552903afee761a86283cf4Colin Cross 294504bc5175a8fe5a2f2552903afee761a86283cf4Colin Cross ret = clock_gettime(CLOCK_MONOTONIC, &ts); 295504bc5175a8fe5a2f2552903afee761a86283cf4Colin Cross if (ret < 0) { 296504bc5175a8fe5a2f2552903afee761a86283cf4Colin Cross ERROR("clock_gettime(CLOCK_MONOTONIC) failed: %s\n", strerror(errno)); 297504bc5175a8fe5a2f2552903afee761a86283cf4Colin Cross return 0; 298504bc5175a8fe5a2f2552903afee761a86283cf4Colin Cross } 299504bc5175a8fe5a2f2552903afee761a86283cf4Colin Cross 300504bc5175a8fe5a2f2552903afee761a86283cf4Colin Cross return ts.tv_sec; 301504bc5175a8fe5a2f2552903afee761a86283cf4Colin Cross} 302b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross 303b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Crossint mkdir_recursive(const char *pathname, mode_t mode) 304b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross{ 305b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross char buf[128]; 306b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross const char *slash; 307b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross const char *p = pathname; 308b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross int width; 309b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross int ret; 310b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross struct stat info; 311b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross 312b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross while ((slash = strchr(p, '/')) != NULL) { 313b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross width = slash - pathname; 314b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross p = slash + 1; 315b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross if (width < 0) 316b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross break; 317b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross if (width == 0) 318b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross continue; 319b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross if ((unsigned int)width > sizeof(buf) - 1) { 320b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross ERROR("path too long for mkdir_recursive\n"); 321b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross return -1; 322b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross } 323b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross memcpy(buf, pathname, width); 324b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross buf[width] = 0; 325b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross if (stat(buf, &info) != 0) { 326b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross ret = mkdir(buf, mode); 327b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross if (ret && errno != EEXIST) 328b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross return ret; 329b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross } 330b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross } 331b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross ret = mkdir(pathname, mode); 332b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross if (ret && errno != EEXIST) 333b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross return ret; 334b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross return 0; 335b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross} 336b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross 337b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Crossvoid sanitize(char *s) 338b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross{ 339b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross if (!s) 340b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross return; 341b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross while (isalnum(*s)) 342b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross s++; 343b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross *s = 0; 344b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross} 345b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Crossvoid make_link(const char *oldpath, const char *newpath) 346b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross{ 347b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross int ret; 348b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross char buf[256]; 349b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross char *slash; 350b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross int width; 351b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross 352b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross slash = strrchr(newpath, '/'); 353b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross if (!slash) 354b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross return; 355b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross width = slash - newpath; 356b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross if (width <= 0 || width > (int)sizeof(buf) - 1) 357b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross return; 358b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross memcpy(buf, newpath, width); 359b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross buf[width] = 0; 360b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross ret = mkdir_recursive(buf, 0755); 361b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross if (ret) 362b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross ERROR("Failed to create directory %s: %s (%d)\n", buf, strerror(errno), errno); 363b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross 364b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross ret = symlink(oldpath, newpath); 365b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross if (ret && errno != EEXIST) 366b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross ERROR("Failed to symlink %s to %s: %s (%d)\n", oldpath, newpath, strerror(errno), errno); 367b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross} 368b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross 369b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Crossvoid remove_link(const char *oldpath, const char *newpath) 370b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross{ 371b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross char path[256]; 372b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross ssize_t ret; 373b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross ret = readlink(newpath, path, sizeof(path) - 1); 374b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross if (ret <= 0) 375b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross return; 376b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross path[ret] = 0; 377b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross if (!strcmp(path, oldpath)) 378b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross unlink(newpath); 379b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross} 380