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