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