util.c revision f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98d
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> 24dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 25dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <sys/stat.h> 26dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <sys/types.h> 27dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <sys/socket.h> 28dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <sys/un.h> 29dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 30dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/* for ANDROID_SOCKET_* */ 31dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <cutils/sockets.h> 32dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 33dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <private/android_filesystem_config.h> 34dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 35dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include "init.h" 36dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 37dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic int log_fd = -1; 38dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/* Inital log level before init.rc is parsed and this this is reset. */ 39dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic int log_level = LOG_DEFAULT_LEVEL; 40dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 41dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 42dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid log_set_level(int level) { 43dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project log_level = level; 44dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 45dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 46dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid log_init(void) 47dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 48dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project static const char *name = "/dev/__kmsg__"; 49dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (mknod(name, S_IFCHR | 0600, (1 << 8) | 11) == 0) { 50dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project log_fd = open(name, O_WRONLY); 51dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project fcntl(log_fd, F_SETFD, FD_CLOEXEC); 52dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project unlink(name); 53dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 54dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 55dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 56dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define LOG_BUF_MAX 512 57dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 58dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid log_write(int level, const char *fmt, ...) 59dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 60dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project char buf[LOG_BUF_MAX]; 61dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project va_list ap; 62dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 63dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (level > log_level) return; 64dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (log_fd < 0) return; 65dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 66dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project va_start(ap, fmt); 67dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project vsnprintf(buf, LOG_BUF_MAX, fmt, ap); 68dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project buf[LOG_BUF_MAX - 1] = 0; 69dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project va_end(ap); 70dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project write(log_fd, buf, strlen(buf)); 71dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 72dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 73dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/* 74dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * android_name_to_id - returns the integer uid/gid associated with the given 75dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * name, or -1U on error. 76dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */ 77dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic unsigned int android_name_to_id(const char *name) 78dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 79dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project struct android_id_info *info = android_ids; 80dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project unsigned int n; 81dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 82dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project for (n = 0; n < android_id_count; n++) { 83dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (!strcmp(info[n].name, name)) 84dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return info[n].aid; 85dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 86dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 87dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return -1U; 88dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 89dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 90dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/* 91dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * decode_uid - decodes and returns the given string, which can be either the 92dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * numeric or name representation, into the integer uid or gid. Returns -1U on 93dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * error. 94dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */ 95dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectunsigned int decode_uid(const char *s) 96dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 97dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project unsigned int v; 98dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 99dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (!s || *s == '\0') 100dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return -1U; 101dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (isalpha(s[0])) 102dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return android_name_to_id(s); 103dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 104dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project errno = 0; 105dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project v = (unsigned int) strtoul(s, 0, 0); 106dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (errno) 107dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return -1U; 108dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return v; 109dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 110dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 111dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/* 112dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * create_socket - creates a Unix domain socket in ANDROID_SOCKET_DIR 113dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * ("/dev/socket") as dictated in init.rc. This socket is inherited by the 114dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * daemon. We communicate the file descriptor's value via the environment 115dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * variable ANDROID_SOCKET_ENV_PREFIX<name> ("ANDROID_SOCKET_foo"). 116dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */ 117dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint create_socket(const char *name, int type, mode_t perm, uid_t uid, gid_t gid) 118dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 119dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project struct sockaddr_un addr; 120dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project int fd, ret; 121dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 122dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project fd = socket(PF_UNIX, type, 0); 123dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (fd < 0) { 124dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ERROR("Failed to open socket '%s': %s\n", name, strerror(errno)); 125dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return -1; 126dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 127dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 128dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project memset(&addr, 0 , sizeof(addr)); 129dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project addr.sun_family = AF_UNIX; 130dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project snprintf(addr.sun_path, sizeof(addr.sun_path), ANDROID_SOCKET_DIR"/%s", 131dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project name); 132dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 133dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ret = unlink(addr.sun_path); 134dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (ret != 0 && errno != ENOENT) { 135dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ERROR("Failed to unlink old socket '%s': %s\n", name, strerror(errno)); 136dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project goto out_close; 137dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 138dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 139dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ret = bind(fd, (struct sockaddr *) &addr, sizeof (addr)); 140dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (ret) { 141dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ERROR("Failed to bind socket '%s': %s\n", name, strerror(errno)); 142dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project goto out_unlink; 143dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 144dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 145dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project chown(addr.sun_path, uid, gid); 146dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project chmod(addr.sun_path, perm); 147dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 148dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project INFO("Created socket '%s' with mode '%o', user '%d', group '%d'\n", 149dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project addr.sun_path, perm, uid, gid); 150dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 151dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return fd; 152dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 153dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectout_unlink: 154dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project unlink(addr.sun_path); 155dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectout_close: 156dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project close(fd); 157dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return -1; 158dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 159dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 160dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/* reads a file, making sure it is terminated with \n \0 */ 161dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid *read_file(const char *fn, unsigned *_sz) 162dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 163dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project char *data; 164dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project int sz; 165dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project int fd; 166dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 167dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project data = 0; 168dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project fd = open(fn, O_RDONLY); 169dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(fd < 0) return 0; 170dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 171dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project sz = lseek(fd, 0, SEEK_END); 172dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(sz < 0) goto oops; 173dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 174dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(lseek(fd, 0, SEEK_SET) != 0) goto oops; 175dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 176dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project data = (char*) malloc(sz + 2); 177dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(data == 0) goto oops; 178dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 179dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(read(fd, data, sz) != sz) goto oops; 180dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project close(fd); 181dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project data[sz] = '\n'; 182dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project data[sz+1] = 0; 183dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(_sz) *_sz = sz; 184dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return data; 185dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 186dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectoops: 187dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project close(fd); 188dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(data != 0) free(data); 189dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return 0; 190dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 191dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 192dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid list_init(struct listnode *node) 193dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 194dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project node->next = node; 195dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project node->prev = node; 196dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 197dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 198dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid list_add_tail(struct listnode *head, struct listnode *item) 199dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 200dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project item->next = head; 201dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project item->prev = head->prev; 202dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project head->prev->next = item; 203dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project head->prev = item; 204dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 205dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 206dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid list_remove(struct listnode *item) 207dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 208dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project item->next->prev = item->prev; 209dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project item->prev->next = item->next; 210dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 211dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 212f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross#define MAX_MTD_PARTITIONS 16 213f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross 214f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Crossstatic struct { 215f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross char name[16]; 216f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross int number; 217f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross} mtd_part_map[MAX_MTD_PARTITIONS]; 218f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross 219f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Crossstatic int mtd_part_count = -1; 220f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross 221f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Crossstatic void find_mtd_partitions(void) 222f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross{ 223f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross int fd; 224f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross char buf[1024]; 225f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross char *pmtdbufp; 226f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross ssize_t pmtdsize; 227f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross int r; 228f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross 229f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross fd = open("/proc/mtd", O_RDONLY); 230f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross if (fd < 0) 231f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross return; 232f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross 233f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross buf[sizeof(buf) - 1] = '\0'; 234f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross pmtdsize = read(fd, buf, sizeof(buf) - 1); 235f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross pmtdbufp = buf; 236f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross while (pmtdsize > 0) { 237f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross int mtdnum, mtdsize, mtderasesize; 238f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross char mtdname[16]; 239f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross mtdname[0] = '\0'; 240f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross mtdnum = -1; 241f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross r = sscanf(pmtdbufp, "mtd%d: %x %x %15s", 242f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross &mtdnum, &mtdsize, &mtderasesize, mtdname); 243f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross if ((r == 4) && (mtdname[0] == '"')) { 244f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross char *x = strchr(mtdname + 1, '"'); 245f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross if (x) { 246f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross *x = 0; 247f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross } 248f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross INFO("mtd partition %d, %s\n", mtdnum, mtdname + 1); 249f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross if (mtd_part_count < MAX_MTD_PARTITIONS) { 250f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross strcpy(mtd_part_map[mtd_part_count].name, mtdname + 1); 251f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross mtd_part_map[mtd_part_count].number = mtdnum; 252f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross mtd_part_count++; 253f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross } else { 254f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross ERROR("too many mtd partitions\n"); 255f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross } 256f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross } 257f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross while (pmtdsize > 0 && *pmtdbufp != '\n') { 258f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross pmtdbufp++; 259f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross pmtdsize--; 260f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross } 261f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross if (pmtdsize > 0) { 262f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross pmtdbufp++; 263f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross pmtdsize--; 264f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross } 265f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross } 266f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross close(fd); 267f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross} 268f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross 269f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Crossint mtd_name_to_number(const char *name) 270f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross{ 271f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross int n; 272f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross if (mtd_part_count < 0) { 273f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross mtd_part_count = 0; 274f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross find_mtd_partitions(); 275f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross } 276f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross for (n = 0; n < mtd_part_count; n++) { 277f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross if (!strcmp(name, mtd_part_map[n].name)) { 278f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross return mtd_part_map[n].number; 279f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross } 280f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross } 281f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross return -1; 282f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross} 283