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>
25ae76f6dbcf3dfd6eda223911f91f4a1316433771Nick Kralevich#include <ftw.h>
26dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
27e46f9d510db9351682cf17c49115110870147335Stephen Smalley#include <selinux/label.h>
28dbd37f2e1da5b27ef1ad6d0cc9580e6893560f5fStephen Smalley#include <selinux/android.h>
29e46f9d510db9351682cf17c49115110870147335Stephen Smalley
30dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <sys/stat.h>
31dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <sys/types.h>
32dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <sys/socket.h>
33dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <sys/un.h>
34dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
35dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/* for ANDROID_SOCKET_* */
36dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <cutils/sockets.h>
37dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
38dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <private/android_filesystem_config.h>
39dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
40e46f9d510db9351682cf17c49115110870147335Stephen Smalley#include "init.h"
41ed8a7d84428ec945c48b6b53dc5a3a18fabaf683Colin Cross#include "log.h"
42f83d0b9af5cbe4440cc41ceaa8a7806a13c86282Colin Cross#include "util.h"
43dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
44dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/*
45dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * android_name_to_id - returns the integer uid/gid associated with the given
46dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * name, or -1U on error.
47dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */
48dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic unsigned int android_name_to_id(const char *name)
49dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
50de7f1ad86f532e79ea2a9f77b0147406a9ad971bEdwin Vane    const struct android_id_info *info = android_ids;
51dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    unsigned int n;
52dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
53dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    for (n = 0; n < android_id_count; n++) {
54dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (!strcmp(info[n].name, name))
55dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            return info[n].aid;
56dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
57dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
58dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return -1U;
59dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
60dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
61dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/*
62dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * decode_uid - decodes and returns the given string, which can be either the
63dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * numeric or name representation, into the integer uid or gid. Returns -1U on
64dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * error.
65dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */
66dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectunsigned int decode_uid(const char *s)
67dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
68dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    unsigned int v;
69dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
70dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (!s || *s == '\0')
71dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return -1U;
72dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (isalpha(s[0]))
73dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return android_name_to_id(s);
74dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
75dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    errno = 0;
76dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    v = (unsigned int) strtoul(s, 0, 0);
77dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (errno)
78dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return -1U;
79dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return v;
80dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
81dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
82dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/*
83dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * create_socket - creates a Unix domain socket in ANDROID_SOCKET_DIR
84dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * ("/dev/socket") as dictated in init.rc. This socket is inherited by the
85dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * daemon. We communicate the file descriptor's value via the environment
86dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * variable ANDROID_SOCKET_ENV_PREFIX<name> ("ANDROID_SOCKET_foo").
87dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */
888348d279c7ce1a2453965ba7f05a7b818d58886cStephen Smalleyint create_socket(const char *name, int type, mode_t perm, uid_t uid,
898348d279c7ce1a2453965ba7f05a7b818d58886cStephen Smalley                  gid_t gid, const char *socketcon)
90dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
91dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    struct sockaddr_un addr;
92dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int fd, ret;
938348d279c7ce1a2453965ba7f05a7b818d58886cStephen Smalley    char *filecon;
948348d279c7ce1a2453965ba7f05a7b818d58886cStephen Smalley
958348d279c7ce1a2453965ba7f05a7b818d58886cStephen Smalley    if (socketcon)
968348d279c7ce1a2453965ba7f05a7b818d58886cStephen Smalley        setsockcreatecon(socketcon);
97dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
98dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fd = socket(PF_UNIX, type, 0);
99dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (fd < 0) {
100dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        ERROR("Failed to open socket '%s': %s\n", name, strerror(errno));
101dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return -1;
102dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
103dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
1048348d279c7ce1a2453965ba7f05a7b818d58886cStephen Smalley    if (socketcon)
1058348d279c7ce1a2453965ba7f05a7b818d58886cStephen Smalley        setsockcreatecon(NULL);
1068348d279c7ce1a2453965ba7f05a7b818d58886cStephen Smalley
107dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    memset(&addr, 0 , sizeof(addr));
108dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    addr.sun_family = AF_UNIX;
109dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    snprintf(addr.sun_path, sizeof(addr.sun_path), ANDROID_SOCKET_DIR"/%s",
110dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project             name);
111dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
112dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    ret = unlink(addr.sun_path);
113dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (ret != 0 && errno != ENOENT) {
114dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        ERROR("Failed to unlink old socket '%s': %s\n", name, strerror(errno));
115dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        goto out_close;
116dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
117dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
1188348d279c7ce1a2453965ba7f05a7b818d58886cStephen Smalley    filecon = NULL;
119e46f9d510db9351682cf17c49115110870147335Stephen Smalley    if (sehandle) {
1208348d279c7ce1a2453965ba7f05a7b818d58886cStephen Smalley        ret = selabel_lookup(sehandle, &filecon, addr.sun_path, S_IFSOCK);
121e46f9d510db9351682cf17c49115110870147335Stephen Smalley        if (ret == 0)
1228348d279c7ce1a2453965ba7f05a7b818d58886cStephen Smalley            setfscreatecon(filecon);
123e46f9d510db9351682cf17c49115110870147335Stephen Smalley    }
124e46f9d510db9351682cf17c49115110870147335Stephen Smalley
125dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    ret = bind(fd, (struct sockaddr *) &addr, sizeof (addr));
126dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (ret) {
127dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        ERROR("Failed to bind socket '%s': %s\n", name, strerror(errno));
128dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        goto out_unlink;
129dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
130dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
131e46f9d510db9351682cf17c49115110870147335Stephen Smalley    setfscreatecon(NULL);
1328348d279c7ce1a2453965ba7f05a7b818d58886cStephen Smalley    freecon(filecon);
133e46f9d510db9351682cf17c49115110870147335Stephen Smalley
134dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    chown(addr.sun_path, uid, gid);
135dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    chmod(addr.sun_path, perm);
136dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
137dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    INFO("Created socket '%s' with mode '%o', user '%d', group '%d'\n",
138dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project         addr.sun_path, perm, uid, gid);
139dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
140dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return fd;
141dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
142dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectout_unlink:
143dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    unlink(addr.sun_path);
144dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectout_close:
145dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    close(fd);
146dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return -1;
147dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
148dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
149dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/* reads a file, making sure it is terminated with \n \0 */
150dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid *read_file(const char *fn, unsigned *_sz)
151dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
152dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    char *data;
153dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int sz;
154dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int fd;
15538f368c1b3bac76d342189b6412691a217421178Nick Kralevich    struct stat sb;
156dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
157dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    data = 0;
158dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fd = open(fn, O_RDONLY);
159dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(fd < 0) return 0;
160dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
16138f368c1b3bac76d342189b6412691a217421178Nick Kralevich    // for security reasons, disallow world-writable
16238f368c1b3bac76d342189b6412691a217421178Nick Kralevich    // or group-writable files
16338f368c1b3bac76d342189b6412691a217421178Nick Kralevich    if (fstat(fd, &sb) < 0) {
16438f368c1b3bac76d342189b6412691a217421178Nick Kralevich        ERROR("fstat failed for '%s'\n", fn);
16538f368c1b3bac76d342189b6412691a217421178Nick Kralevich        goto oops;
16638f368c1b3bac76d342189b6412691a217421178Nick Kralevich    }
16738f368c1b3bac76d342189b6412691a217421178Nick Kralevich    if ((sb.st_mode & (S_IWGRP | S_IWOTH)) != 0) {
16838f368c1b3bac76d342189b6412691a217421178Nick Kralevich        ERROR("skipping insecure file '%s'\n", fn);
16938f368c1b3bac76d342189b6412691a217421178Nick Kralevich        goto oops;
17038f368c1b3bac76d342189b6412691a217421178Nick Kralevich    }
17138f368c1b3bac76d342189b6412691a217421178Nick Kralevich
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
193f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross#define MAX_MTD_PARTITIONS 16
194f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross
195f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Crossstatic struct {
196f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross    char name[16];
197f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross    int number;
198f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross} mtd_part_map[MAX_MTD_PARTITIONS];
199f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross
200f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Crossstatic int mtd_part_count = -1;
201f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross
202f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Crossstatic void find_mtd_partitions(void)
203f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross{
204f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross    int fd;
205f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross    char buf[1024];
206f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross    char *pmtdbufp;
207f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross    ssize_t pmtdsize;
208f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross    int r;
209f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross
210f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross    fd = open("/proc/mtd", O_RDONLY);
211f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross    if (fd < 0)
212f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross        return;
213f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross
214f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross    buf[sizeof(buf) - 1] = '\0';
215f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross    pmtdsize = read(fd, buf, sizeof(buf) - 1);
216f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross    pmtdbufp = buf;
217f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross    while (pmtdsize > 0) {
218f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross        int mtdnum, mtdsize, mtderasesize;
219f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross        char mtdname[16];
220f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross        mtdname[0] = '\0';
221f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross        mtdnum = -1;
222f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross        r = sscanf(pmtdbufp, "mtd%d: %x %x %15s",
223f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross                   &mtdnum, &mtdsize, &mtderasesize, mtdname);
224f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross        if ((r == 4) && (mtdname[0] == '"')) {
225f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross            char *x = strchr(mtdname + 1, '"');
226f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross            if (x) {
227f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross                *x = 0;
228f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross            }
229f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross            INFO("mtd partition %d, %s\n", mtdnum, mtdname + 1);
230f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross            if (mtd_part_count < MAX_MTD_PARTITIONS) {
231f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross                strcpy(mtd_part_map[mtd_part_count].name, mtdname + 1);
232f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross                mtd_part_map[mtd_part_count].number = mtdnum;
233f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross                mtd_part_count++;
234f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross            } else {
235f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross                ERROR("too many mtd partitions\n");
236f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross            }
237f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross        }
238f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross        while (pmtdsize > 0 && *pmtdbufp != '\n') {
239f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross            pmtdbufp++;
240f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross            pmtdsize--;
241f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross        }
242f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross        if (pmtdsize > 0) {
243f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross            pmtdbufp++;
244f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross            pmtdsize--;
245f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross        }
246f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross    }
247f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross    close(fd);
248f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross}
249f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross
250f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Crossint mtd_name_to_number(const char *name)
251f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross{
252f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross    int n;
253f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross    if (mtd_part_count < 0) {
254f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross        mtd_part_count = 0;
255f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross        find_mtd_partitions();
256f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross    }
257f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross    for (n = 0; n < mtd_part_count; n++) {
258f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross        if (!strcmp(name, mtd_part_map[n].name)) {
259f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross            return mtd_part_map[n].number;
260f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross        }
261f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross    }
262f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross    return -1;
263f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross}
264504bc5175a8fe5a2f2552903afee761a86283cf4Colin Cross
265504bc5175a8fe5a2f2552903afee761a86283cf4Colin Cross/*
266504bc5175a8fe5a2f2552903afee761a86283cf4Colin Cross * gettime() - returns the time in seconds of the system's monotonic clock or
267504bc5175a8fe5a2f2552903afee761a86283cf4Colin Cross * zero on error.
268504bc5175a8fe5a2f2552903afee761a86283cf4Colin Cross */
269504bc5175a8fe5a2f2552903afee761a86283cf4Colin Crosstime_t gettime(void)
270504bc5175a8fe5a2f2552903afee761a86283cf4Colin Cross{
271504bc5175a8fe5a2f2552903afee761a86283cf4Colin Cross    struct timespec ts;
272504bc5175a8fe5a2f2552903afee761a86283cf4Colin Cross    int ret;
273504bc5175a8fe5a2f2552903afee761a86283cf4Colin Cross
274504bc5175a8fe5a2f2552903afee761a86283cf4Colin Cross    ret = clock_gettime(CLOCK_MONOTONIC, &ts);
275504bc5175a8fe5a2f2552903afee761a86283cf4Colin Cross    if (ret < 0) {
276504bc5175a8fe5a2f2552903afee761a86283cf4Colin Cross        ERROR("clock_gettime(CLOCK_MONOTONIC) failed: %s\n", strerror(errno));
277504bc5175a8fe5a2f2552903afee761a86283cf4Colin Cross        return 0;
278504bc5175a8fe5a2f2552903afee761a86283cf4Colin Cross    }
279504bc5175a8fe5a2f2552903afee761a86283cf4Colin Cross
280504bc5175a8fe5a2f2552903afee761a86283cf4Colin Cross    return ts.tv_sec;
281504bc5175a8fe5a2f2552903afee761a86283cf4Colin Cross}
282b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross
283b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Crossint mkdir_recursive(const char *pathname, mode_t mode)
284b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross{
285b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross    char buf[128];
286b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross    const char *slash;
287b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross    const char *p = pathname;
288b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross    int width;
289b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross    int ret;
290b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross    struct stat info;
291b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross
292b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross    while ((slash = strchr(p, '/')) != NULL) {
293b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross        width = slash - pathname;
294b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross        p = slash + 1;
295b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross        if (width < 0)
296b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross            break;
297b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross        if (width == 0)
298b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross            continue;
299b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross        if ((unsigned int)width > sizeof(buf) - 1) {
300b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross            ERROR("path too long for mkdir_recursive\n");
301b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross            return -1;
302b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross        }
303b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross        memcpy(buf, pathname, width);
304b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross        buf[width] = 0;
305b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross        if (stat(buf, &info) != 0) {
306e096e36e50b4b66638ebc4d3c09c2ee35f538dfaStephen Smalley            ret = make_dir(buf, mode);
307b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross            if (ret && errno != EEXIST)
308b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross                return ret;
309b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross        }
310b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross    }
311e096e36e50b4b66638ebc4d3c09c2ee35f538dfaStephen Smalley    ret = make_dir(pathname, mode);
312b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross    if (ret && errno != EEXIST)
313b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross        return ret;
314b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross    return 0;
315b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross}
316b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross
31793ca79b44535ee24ece08001e1948070db6ab6edJohan Redestig/*
31893ca79b44535ee24ece08001e1948070db6ab6edJohan Redestig * replaces any unacceptable characters with '_', the
31993ca79b44535ee24ece08001e1948070db6ab6edJohan Redestig * length of the resulting string is equal to the input string
32093ca79b44535ee24ece08001e1948070db6ab6edJohan Redestig */
321b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Crossvoid sanitize(char *s)
322b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross{
32393ca79b44535ee24ece08001e1948070db6ab6edJohan Redestig    const char* accept =
32493ca79b44535ee24ece08001e1948070db6ab6edJohan Redestig            "abcdefghijklmnopqrstuvwxyz"
32593ca79b44535ee24ece08001e1948070db6ab6edJohan Redestig            "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
32693ca79b44535ee24ece08001e1948070db6ab6edJohan Redestig            "0123456789"
32793ca79b44535ee24ece08001e1948070db6ab6edJohan Redestig            "_-.";
32893ca79b44535ee24ece08001e1948070db6ab6edJohan Redestig
329b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross    if (!s)
330b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross        return;
33193ca79b44535ee24ece08001e1948070db6ab6edJohan Redestig
332ba95be58c596aa7b5034b1bce8f3fde97ae08780Christopher R. Palmer    while (*s) {
33393ca79b44535ee24ece08001e1948070db6ab6edJohan Redestig        s += strspn(s, accept);
334ba95be58c596aa7b5034b1bce8f3fde97ae08780Christopher R. Palmer        if (*s) *s++ = '_';
33593ca79b44535ee24ece08001e1948070db6ab6edJohan Redestig    }
336b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross}
33793ca79b44535ee24ece08001e1948070db6ab6edJohan Redestig
3385b3aa21bc70d42b3fcb1764a1be04ab8db5ebfb9Chris Friesvoid make_link_init(const char *oldpath, const char *newpath)
339b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross{
340b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross    int ret;
341b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross    char buf[256];
342b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross    char *slash;
343b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross    int width;
344b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross
345b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross    slash = strrchr(newpath, '/');
346b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross    if (!slash)
347b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross        return;
348b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross    width = slash - newpath;
349b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross    if (width <= 0 || width > (int)sizeof(buf) - 1)
350b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross        return;
351b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross    memcpy(buf, newpath, width);
352b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross    buf[width] = 0;
353b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross    ret = mkdir_recursive(buf, 0755);
354b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross    if (ret)
355b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross        ERROR("Failed to create directory %s: %s (%d)\n", buf, strerror(errno), errno);
356b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross
357b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross    ret = symlink(oldpath, newpath);
358b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross    if (ret && errno != EEXIST)
359b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross        ERROR("Failed to symlink %s to %s: %s (%d)\n", oldpath, newpath, strerror(errno), errno);
360b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross}
361b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross
362b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Crossvoid remove_link(const char *oldpath, const char *newpath)
363b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross{
364b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross    char path[256];
365b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross    ssize_t ret;
366b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross    ret = readlink(newpath, path, sizeof(path) - 1);
367b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross    if (ret <= 0)
368b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross        return;
369b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross    path[ret] = 0;
370b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross    if (!strcmp(path, oldpath))
371b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross        unlink(newpath);
372b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross}
373cd0f173e2790ee068fd2a20bcfc6c20468e97e51Colin Cross
374cd0f173e2790ee068fd2a20bcfc6c20468e97e51Colin Crossint wait_for_file(const char *filename, int timeout)
375cd0f173e2790ee068fd2a20bcfc6c20468e97e51Colin Cross{
376cd0f173e2790ee068fd2a20bcfc6c20468e97e51Colin Cross    struct stat info;
377cd0f173e2790ee068fd2a20bcfc6c20468e97e51Colin Cross    time_t timeout_time = gettime() + timeout;
378cd0f173e2790ee068fd2a20bcfc6c20468e97e51Colin Cross    int ret = -1;
379cd0f173e2790ee068fd2a20bcfc6c20468e97e51Colin Cross
380cd0f173e2790ee068fd2a20bcfc6c20468e97e51Colin Cross    while (gettime() < timeout_time && ((ret = stat(filename, &info)) < 0))
381cd0f173e2790ee068fd2a20bcfc6c20468e97e51Colin Cross        usleep(10000);
382cd0f173e2790ee068fd2a20bcfc6c20468e97e51Colin Cross
383cd0f173e2790ee068fd2a20bcfc6c20468e97e51Colin Cross    return ret;
384cd0f173e2790ee068fd2a20bcfc6c20468e97e51Colin Cross}
385f83d0b9af5cbe4440cc41ceaa8a7806a13c86282Colin Cross
386f83d0b9af5cbe4440cc41ceaa8a7806a13c86282Colin Crossvoid open_devnull_stdio(void)
387f83d0b9af5cbe4440cc41ceaa8a7806a13c86282Colin Cross{
388f83d0b9af5cbe4440cc41ceaa8a7806a13c86282Colin Cross    int fd;
389f83d0b9af5cbe4440cc41ceaa8a7806a13c86282Colin Cross    static const char *name = "/dev/__null__";
390f83d0b9af5cbe4440cc41ceaa8a7806a13c86282Colin Cross    if (mknod(name, S_IFCHR | 0600, (1 << 8) | 3) == 0) {
391f83d0b9af5cbe4440cc41ceaa8a7806a13c86282Colin Cross        fd = open(name, O_RDWR);
392f83d0b9af5cbe4440cc41ceaa8a7806a13c86282Colin Cross        unlink(name);
393f83d0b9af5cbe4440cc41ceaa8a7806a13c86282Colin Cross        if (fd >= 0) {
394f83d0b9af5cbe4440cc41ceaa8a7806a13c86282Colin Cross            dup2(fd, 0);
395f83d0b9af5cbe4440cc41ceaa8a7806a13c86282Colin Cross            dup2(fd, 1);
396f83d0b9af5cbe4440cc41ceaa8a7806a13c86282Colin Cross            dup2(fd, 2);
397f83d0b9af5cbe4440cc41ceaa8a7806a13c86282Colin Cross            if (fd > 2) {
398f83d0b9af5cbe4440cc41ceaa8a7806a13c86282Colin Cross                close(fd);
399f83d0b9af5cbe4440cc41ceaa8a7806a13c86282Colin Cross            }
400f83d0b9af5cbe4440cc41ceaa8a7806a13c86282Colin Cross            return;
401f83d0b9af5cbe4440cc41ceaa8a7806a13c86282Colin Cross        }
402f83d0b9af5cbe4440cc41ceaa8a7806a13c86282Colin Cross    }
403f83d0b9af5cbe4440cc41ceaa8a7806a13c86282Colin Cross
404f83d0b9af5cbe4440cc41ceaa8a7806a13c86282Colin Cross    exit(1);
405f83d0b9af5cbe4440cc41ceaa8a7806a13c86282Colin Cross}
406f83d0b9af5cbe4440cc41ceaa8a7806a13c86282Colin Cross
407f83d0b9af5cbe4440cc41ceaa8a7806a13c86282Colin Crossvoid get_hardware_name(char *hardware, unsigned int *revision)
408f83d0b9af5cbe4440cc41ceaa8a7806a13c86282Colin Cross{
409229dc35f699f144e5e3ccd8062bba8f6e650cfdcJon Medhurst    const char *cpuinfo = "/proc/cpuinfo";
410229dc35f699f144e5e3ccd8062bba8f6e650cfdcJon Medhurst    char *data = NULL;
411229dc35f699f144e5e3ccd8062bba8f6e650cfdcJon Medhurst    size_t len = 0, limit = 1024;
412f83d0b9af5cbe4440cc41ceaa8a7806a13c86282Colin Cross    int fd, n;
413f83d0b9af5cbe4440cc41ceaa8a7806a13c86282Colin Cross    char *x, *hw, *rev;
414f83d0b9af5cbe4440cc41ceaa8a7806a13c86282Colin Cross
415f83d0b9af5cbe4440cc41ceaa8a7806a13c86282Colin Cross    /* Hardware string was provided on kernel command line */
416f83d0b9af5cbe4440cc41ceaa8a7806a13c86282Colin Cross    if (hardware[0])
417f83d0b9af5cbe4440cc41ceaa8a7806a13c86282Colin Cross        return;
418f83d0b9af5cbe4440cc41ceaa8a7806a13c86282Colin Cross
419229dc35f699f144e5e3ccd8062bba8f6e650cfdcJon Medhurst    fd = open(cpuinfo, O_RDONLY);
420f83d0b9af5cbe4440cc41ceaa8a7806a13c86282Colin Cross    if (fd < 0) return;
421f83d0b9af5cbe4440cc41ceaa8a7806a13c86282Colin Cross
422229dc35f699f144e5e3ccd8062bba8f6e650cfdcJon Medhurst    for (;;) {
423229dc35f699f144e5e3ccd8062bba8f6e650cfdcJon Medhurst        x = realloc(data, limit);
424229dc35f699f144e5e3ccd8062bba8f6e650cfdcJon Medhurst        if (!x) {
425229dc35f699f144e5e3ccd8062bba8f6e650cfdcJon Medhurst            ERROR("Failed to allocate memory to read %s\n", cpuinfo);
426229dc35f699f144e5e3ccd8062bba8f6e650cfdcJon Medhurst            goto done;
427229dc35f699f144e5e3ccd8062bba8f6e650cfdcJon Medhurst        }
428229dc35f699f144e5e3ccd8062bba8f6e650cfdcJon Medhurst        data = x;
429229dc35f699f144e5e3ccd8062bba8f6e650cfdcJon Medhurst
430229dc35f699f144e5e3ccd8062bba8f6e650cfdcJon Medhurst        n = read(fd, data + len, limit - len);
431229dc35f699f144e5e3ccd8062bba8f6e650cfdcJon Medhurst        if (n < 0) {
432229dc35f699f144e5e3ccd8062bba8f6e650cfdcJon Medhurst            ERROR("Failed reading %s: %s (%d)\n", cpuinfo, strerror(errno), errno);
433229dc35f699f144e5e3ccd8062bba8f6e650cfdcJon Medhurst            goto done;
434229dc35f699f144e5e3ccd8062bba8f6e650cfdcJon Medhurst        }
435229dc35f699f144e5e3ccd8062bba8f6e650cfdcJon Medhurst        len += n;
436229dc35f699f144e5e3ccd8062bba8f6e650cfdcJon Medhurst
437229dc35f699f144e5e3ccd8062bba8f6e650cfdcJon Medhurst        if (len < limit)
438229dc35f699f144e5e3ccd8062bba8f6e650cfdcJon Medhurst            break;
439229dc35f699f144e5e3ccd8062bba8f6e650cfdcJon Medhurst
440229dc35f699f144e5e3ccd8062bba8f6e650cfdcJon Medhurst        /* We filled the buffer, so increase size and loop to read more */
441229dc35f699f144e5e3ccd8062bba8f6e650cfdcJon Medhurst        limit *= 2;
442229dc35f699f144e5e3ccd8062bba8f6e650cfdcJon Medhurst    }
443f83d0b9af5cbe4440cc41ceaa8a7806a13c86282Colin Cross
444229dc35f699f144e5e3ccd8062bba8f6e650cfdcJon Medhurst    data[len] = 0;
445f83d0b9af5cbe4440cc41ceaa8a7806a13c86282Colin Cross    hw = strstr(data, "\nHardware");
446f83d0b9af5cbe4440cc41ceaa8a7806a13c86282Colin Cross    rev = strstr(data, "\nRevision");
447f83d0b9af5cbe4440cc41ceaa8a7806a13c86282Colin Cross
448f83d0b9af5cbe4440cc41ceaa8a7806a13c86282Colin Cross    if (hw) {
449f83d0b9af5cbe4440cc41ceaa8a7806a13c86282Colin Cross        x = strstr(hw, ": ");
450f83d0b9af5cbe4440cc41ceaa8a7806a13c86282Colin Cross        if (x) {
451f83d0b9af5cbe4440cc41ceaa8a7806a13c86282Colin Cross            x += 2;
452f83d0b9af5cbe4440cc41ceaa8a7806a13c86282Colin Cross            n = 0;
453742150c031756da1393bf4223b2468b17cb79326The Android Open Source Project            while (*x && *x != '\n') {
454742150c031756da1393bf4223b2468b17cb79326The Android Open Source Project                if (!isspace(*x))
455742150c031756da1393bf4223b2468b17cb79326The Android Open Source Project                    hardware[n++] = tolower(*x);
456f83d0b9af5cbe4440cc41ceaa8a7806a13c86282Colin Cross                x++;
457f83d0b9af5cbe4440cc41ceaa8a7806a13c86282Colin Cross                if (n == 31) break;
458f83d0b9af5cbe4440cc41ceaa8a7806a13c86282Colin Cross            }
459f83d0b9af5cbe4440cc41ceaa8a7806a13c86282Colin Cross            hardware[n] = 0;
460f83d0b9af5cbe4440cc41ceaa8a7806a13c86282Colin Cross        }
461f83d0b9af5cbe4440cc41ceaa8a7806a13c86282Colin Cross    }
462f83d0b9af5cbe4440cc41ceaa8a7806a13c86282Colin Cross
463f83d0b9af5cbe4440cc41ceaa8a7806a13c86282Colin Cross    if (rev) {
464f83d0b9af5cbe4440cc41ceaa8a7806a13c86282Colin Cross        x = strstr(rev, ": ");
465f83d0b9af5cbe4440cc41ceaa8a7806a13c86282Colin Cross        if (x) {
466f83d0b9af5cbe4440cc41ceaa8a7806a13c86282Colin Cross            *revision = strtoul(x + 2, 0, 16);
467f83d0b9af5cbe4440cc41ceaa8a7806a13c86282Colin Cross        }
468f83d0b9af5cbe4440cc41ceaa8a7806a13c86282Colin Cross    }
469229dc35f699f144e5e3ccd8062bba8f6e650cfdcJon Medhurst
470229dc35f699f144e5e3ccd8062bba8f6e650cfdcJon Medhurstdone:
471229dc35f699f144e5e3ccd8062bba8f6e650cfdcJon Medhurst    close(fd);
472229dc35f699f144e5e3ccd8062bba8f6e650cfdcJon Medhurst    free(data);
473f83d0b9af5cbe4440cc41ceaa8a7806a13c86282Colin Cross}
4742b99543cef1b8b0aa8cca39544939910035117b0Vladimir Chtchetkine
4752b99543cef1b8b0aa8cca39544939910035117b0Vladimir Chtchetkinevoid import_kernel_cmdline(int in_qemu,
4762b99543cef1b8b0aa8cca39544939910035117b0Vladimir Chtchetkine                           void (*import_kernel_nv)(char *name, int in_qemu))
4772b99543cef1b8b0aa8cca39544939910035117b0Vladimir Chtchetkine{
4782e63e71f3116f0330b3bf61dde7deca235dd40acAndrew Boie    char cmdline[2048];
4792b99543cef1b8b0aa8cca39544939910035117b0Vladimir Chtchetkine    char *ptr;
4802b99543cef1b8b0aa8cca39544939910035117b0Vladimir Chtchetkine    int fd;
4812b99543cef1b8b0aa8cca39544939910035117b0Vladimir Chtchetkine
4822b99543cef1b8b0aa8cca39544939910035117b0Vladimir Chtchetkine    fd = open("/proc/cmdline", O_RDONLY);
4832b99543cef1b8b0aa8cca39544939910035117b0Vladimir Chtchetkine    if (fd >= 0) {
4842e63e71f3116f0330b3bf61dde7deca235dd40acAndrew Boie        int n = read(fd, cmdline, sizeof(cmdline) - 1);
4852b99543cef1b8b0aa8cca39544939910035117b0Vladimir Chtchetkine        if (n < 0) n = 0;
4862b99543cef1b8b0aa8cca39544939910035117b0Vladimir Chtchetkine
4872b99543cef1b8b0aa8cca39544939910035117b0Vladimir Chtchetkine        /* get rid of trailing newline, it happens */
4882b99543cef1b8b0aa8cca39544939910035117b0Vladimir Chtchetkine        if (n > 0 && cmdline[n-1] == '\n') n--;
4892b99543cef1b8b0aa8cca39544939910035117b0Vladimir Chtchetkine
4902b99543cef1b8b0aa8cca39544939910035117b0Vladimir Chtchetkine        cmdline[n] = 0;
4912b99543cef1b8b0aa8cca39544939910035117b0Vladimir Chtchetkine        close(fd);
4922b99543cef1b8b0aa8cca39544939910035117b0Vladimir Chtchetkine    } else {
4932b99543cef1b8b0aa8cca39544939910035117b0Vladimir Chtchetkine        cmdline[0] = 0;
4942b99543cef1b8b0aa8cca39544939910035117b0Vladimir Chtchetkine    }
4952b99543cef1b8b0aa8cca39544939910035117b0Vladimir Chtchetkine
4962b99543cef1b8b0aa8cca39544939910035117b0Vladimir Chtchetkine    ptr = cmdline;
4972b99543cef1b8b0aa8cca39544939910035117b0Vladimir Chtchetkine    while (ptr && *ptr) {
4982b99543cef1b8b0aa8cca39544939910035117b0Vladimir Chtchetkine        char *x = strchr(ptr, ' ');
4992b99543cef1b8b0aa8cca39544939910035117b0Vladimir Chtchetkine        if (x != 0) *x++ = 0;
5002b99543cef1b8b0aa8cca39544939910035117b0Vladimir Chtchetkine        import_kernel_nv(ptr, in_qemu);
5012b99543cef1b8b0aa8cca39544939910035117b0Vladimir Chtchetkine        ptr = x;
5022b99543cef1b8b0aa8cca39544939910035117b0Vladimir Chtchetkine    }
5032b99543cef1b8b0aa8cca39544939910035117b0Vladimir Chtchetkine}
504e096e36e50b4b66638ebc4d3c09c2ee35f538dfaStephen Smalley
505e096e36e50b4b66638ebc4d3c09c2ee35f538dfaStephen Smalleyint make_dir(const char *path, mode_t mode)
506e096e36e50b4b66638ebc4d3c09c2ee35f538dfaStephen Smalley{
507e096e36e50b4b66638ebc4d3c09c2ee35f538dfaStephen Smalley    int rc;
508e096e36e50b4b66638ebc4d3c09c2ee35f538dfaStephen Smalley
509e096e36e50b4b66638ebc4d3c09c2ee35f538dfaStephen Smalley    char *secontext = NULL;
510e096e36e50b4b66638ebc4d3c09c2ee35f538dfaStephen Smalley
511e096e36e50b4b66638ebc4d3c09c2ee35f538dfaStephen Smalley    if (sehandle) {
512e096e36e50b4b66638ebc4d3c09c2ee35f538dfaStephen Smalley        selabel_lookup(sehandle, &secontext, path, mode);
513e096e36e50b4b66638ebc4d3c09c2ee35f538dfaStephen Smalley        setfscreatecon(secontext);
514e096e36e50b4b66638ebc4d3c09c2ee35f538dfaStephen Smalley    }
515e096e36e50b4b66638ebc4d3c09c2ee35f538dfaStephen Smalley
516e096e36e50b4b66638ebc4d3c09c2ee35f538dfaStephen Smalley    rc = mkdir(path, mode);
517e096e36e50b4b66638ebc4d3c09c2ee35f538dfaStephen Smalley
518e096e36e50b4b66638ebc4d3c09c2ee35f538dfaStephen Smalley    if (secontext) {
519e096e36e50b4b66638ebc4d3c09c2ee35f538dfaStephen Smalley        int save_errno = errno;
520e096e36e50b4b66638ebc4d3c09c2ee35f538dfaStephen Smalley        freecon(secontext);
521e096e36e50b4b66638ebc4d3c09c2ee35f538dfaStephen Smalley        setfscreatecon(NULL);
522e096e36e50b4b66638ebc4d3c09c2ee35f538dfaStephen Smalley        errno = save_errno;
523e096e36e50b4b66638ebc4d3c09c2ee35f538dfaStephen Smalley    }
524b5982bf7c65b30be981ecfe1847437b05e32b2bbKenny Root
525e096e36e50b4b66638ebc4d3c09c2ee35f538dfaStephen Smalley    return rc;
526e096e36e50b4b66638ebc4d3c09c2ee35f538dfaStephen Smalley}
527e096e36e50b4b66638ebc4d3c09c2ee35f538dfaStephen Smalley
528dbd37f2e1da5b27ef1ad6d0cc9580e6893560f5fStephen Smalleyint restorecon(const char* pathname)
529e096e36e50b4b66638ebc4d3c09c2ee35f538dfaStephen Smalley{
53027a93650c0df02e4cd3c48bbec8acee8b817a012Stephen Smalley    return selinux_android_restorecon(pathname, 0);
531ae76f6dbcf3dfd6eda223911f91f4a1316433771Nick Kralevich}
532ae76f6dbcf3dfd6eda223911f91f4a1316433771Nick Kralevich
533ae76f6dbcf3dfd6eda223911f91f4a1316433771Nick Kralevichint restorecon_recursive(const char* pathname)
534ae76f6dbcf3dfd6eda223911f91f4a1316433771Nick Kralevich{
53527a93650c0df02e4cd3c48bbec8acee8b817a012Stephen Smalley    return selinux_android_restorecon(pathname, SELINUX_ANDROID_RESTORECON_RECURSE);
536ae76f6dbcf3dfd6eda223911f91f4a1316433771Nick Kralevich}
537