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