📄 devices.c
字号:
/* * Copyright (C) 2007 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */#include <errno.h>#include <stdio.h>#include <stdlib.h>#include <sys/stat.h>#include <sys/types.h>#include <fcntl.h>#include <dirent.h>#include <unistd.h>#include <string.h>#include <sys/socket.h>#include <sys/un.h>#include <linux/netlink.h>#include <private/android_filesystem_config.h>#include <sys/time.h>#include <asm/page.h>#include "init.h"#include "devices.h"#define CMDLINE_PREFIX "/dev"#define SYSFS_PREFIX "/sys"#define FIRMWARE_DIR "/etc/firmware"#define MAX_QEMU_PERM 6struct uevent { const char *action; const char *path; const char *subsystem; const char *firmware; int major; int minor;};static int open_uevent_socket(void){ struct sockaddr_nl addr; int sz = 64*1024; // XXX larger? udev uses 16MB! int s; memset(&addr, 0, sizeof(addr)); addr.nl_family = AF_NETLINK; addr.nl_pid = getpid(); addr.nl_groups = 0xffffffff; s = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT); if(s < 0) return -1; setsockopt(s, SOL_SOCKET, SO_RCVBUFFORCE, &sz, sizeof(sz)); if(bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) { close(s); return -1; } return s;}struct perms_ { char *name; mode_t perm; unsigned int uid; unsigned int gid; unsigned short prefix;};static struct perms_ devperms[] = { { "/dev/null", 0666, AID_ROOT, AID_ROOT, 0 }, { "/dev/zero", 0666, AID_ROOT, AID_ROOT, 0 }, { "/dev/full", 0666, AID_ROOT, AID_ROOT, 0 }, { "/dev/ptmx", 0666, AID_ROOT, AID_ROOT, 0 }, { "/dev/tty", 0666, AID_ROOT, AID_ROOT, 0 }, { "/dev/random", 0666, AID_ROOT, AID_ROOT, 0 }, { "/dev/urandom", 0666, AID_ROOT, AID_ROOT, 0 }, { "/dev/ashmem", 0666, AID_ROOT, AID_ROOT, 0 }, { "/dev/binder", 0666, AID_ROOT, AID_ROOT, 0 }, /* logger should be world writable (for logging) but not readable */ { "/dev/log/", 0662, AID_ROOT, AID_LOG, 1 }, /* these should not be world writable */ { "/dev/android_adb", 0660, AID_ADB, AID_ADB, 0 }, { "/dev/android_adb_enable", 0660, AID_ADB, AID_ADB, 0 }, { "/dev/ttyMSM0", 0660, AID_BLUETOOTH, AID_BLUETOOTH, 0 }, { "/dev/alarm", 0664, AID_SYSTEM, AID_RADIO, 0 }, { "/dev/tty0", 0666, AID_ROOT, AID_SYSTEM, 0 }, { "/dev/graphics/", 0660, AID_ROOT, AID_GRAPHICS, 1 }, { "/dev/hw3d", 0660, AID_SYSTEM, AID_GRAPHICS, 0 }, { "/dev/input/", 0660, AID_ROOT, AID_INPUT, 1 }, { "/dev/eac", 0660, AID_ROOT, AID_AUDIO, 0 }, { "/dev/cam", 0660, AID_ROOT, AID_CAMERA, 0 }, { "/dev/pmem", 0660, AID_SYSTEM, AID_GRAPHICS, 0 }, { "/dev/pmem_gpu", 0660, AID_SYSTEM, AID_GRAPHICS, 1 }, { "/dev/pmem_adsp", 0660, AID_SYSTEM, AID_AUDIO, 1 }, { "/dev/pmem_camera", 0660, AID_SYSTEM, AID_CAMERA, 1 }, { "/dev/oncrpc/", 0660, AID_ROOT, AID_SYSTEM, 1 }, { "/dev/adsp/", 0660, AID_SYSTEM, AID_AUDIO, 1 }, { "/dev/mt9t013", 0660, AID_SYSTEM, AID_SYSTEM, 0 }, { "/dev/akm8976_daemon",0640, AID_COMPASS, AID_SYSTEM, 0 }, { "/dev/akm8976_aot", 0640, AID_COMPASS, AID_SYSTEM, 0 }, { "/dev/akm8976_pffd", 0640, AID_COMPASS, AID_SYSTEM, 0 }, { "/dev/msm_pcm_out", 0660, AID_SYSTEM, AID_AUDIO, 1 }, { "/dev/msm_pcm_in", 0660, AID_SYSTEM, AID_AUDIO, 1 }, { "/dev/msm_pcm_ctl", 0660, AID_SYSTEM, AID_AUDIO, 1 }, { "/dev/msm_mp3", 0660, AID_SYSTEM, AID_AUDIO, 1 }, { "/dev/smd0", 0640, AID_RADIO, AID_RADIO, 0 }, { "/dev/qmi", 0640, AID_RADIO, AID_RADIO, 0 }, { "/dev/qmi0", 0640, AID_RADIO, AID_RADIO, 0 }, { "/dev/qmi1", 0640, AID_RADIO, AID_RADIO, 0 }, { "/dev/qmi2", 0640, AID_RADIO, AID_RADIO, 0 }, { "/dev/htc-acoustic", 0640, AID_RADIO, AID_RADIO, 0 }, { NULL, 0, 0, 0, 0 },};/* devperms_partners list and perm_node are for hardware specific /dev entries */struct perm_node { struct perms_ dp; struct listnode plist;};list_declare(devperms_partners);/* * Permission override when in emulator mode, must be parsed before * system properties is initalized. */static int qemu_perm_count;static struct perms_ qemu_perms[MAX_QEMU_PERM + 1];int add_devperms_partners(const char *name, mode_t perm, unsigned int uid, unsigned int gid, unsigned short prefix) { int size; struct perm_node *node = malloc(sizeof (struct perm_node)); if (!node) return -ENOMEM; size = strlen(name) + 1; if ((node->dp.name = malloc(size)) == NULL) return -ENOMEM; memcpy(node->dp.name, name, size); node->dp.perm = perm; node->dp.uid = uid; node->dp.gid = gid; node->dp.prefix = prefix; list_add_tail(&devperms_partners, &node->plist); return 0;}void qemu_init(void) { qemu_perm_count = 0; memset(&qemu_perms, 0, sizeof(qemu_perms));}static int qemu_perm(const char* name, mode_t perm, unsigned int uid, unsigned int gid, unsigned short prefix){ char *buf; if (qemu_perm_count == MAX_QEMU_PERM) return -ENOSPC; buf = malloc(strlen(name) + 1); if (!buf) return -errno; strlcpy(buf, name, strlen(name) + 1); qemu_perms[qemu_perm_count].name = buf; qemu_perms[qemu_perm_count].perm = perm; qemu_perms[qemu_perm_count].uid = uid; qemu_perms[qemu_perm_count].gid = gid; qemu_perms[qemu_perm_count].prefix = prefix; qemu_perm_count++; return 0;}/* Permission overrides for emulator that are parsed from /proc/cmdline. */void qemu_cmdline(const char* name, const char *value){ char *buf; if (!strcmp(name, "android.ril")) { /* cmd line params currently assume /dev/ prefix */ if (asprintf(&buf, CMDLINE_PREFIX"/%s", value) == -1) { return; } INFO("nani- buf:: %s\n", buf); qemu_perm(buf, 0660, AID_RADIO, AID_ROOT, 0); }}static int get_device_perm_inner(struct perms_ *perms, const char *path, unsigned *uid, unsigned *gid, mode_t *perm){ int i; for(i = 0; perms[i].name; i++) { if(perms[i].prefix) { if(strncmp(path, perms[i].name, strlen(perms[i].name))) continue; } else { if(strcmp(path, perms[i].name)) continue; } *uid = perms[i].uid; *gid = perms[i].gid; *perm = perms[i].perm; return 0; } return -1;}/* First checks for emulator specific permissions specified in /proc/cmdline. */static mode_t get_device_perm(const char *path, unsigned *uid, unsigned *gid){ mode_t perm; if (get_device_perm_inner(qemu_perms, path, uid, gid, &perm) == 0) { return perm; } else if (get_device_perm_inner(devperms, path, uid, gid, &perm) == 0) { return perm; } else { struct listnode *node; struct perm_node *perm_node; struct perms_ *dp; /* Check partners list. */ list_for_each(node, &devperms_partners) { perm_node = node_to_item(node, struct perm_node, plist); dp = &perm_node->dp; if (dp->prefix) { if (strncmp(path, dp->name, strlen(dp->name))) continue; } else { if (strcmp(path, dp->name)) continue; } /* Found perm in partner list. */ *uid = dp->uid; *gid = dp->gid; return dp->perm; } /* Default if nothing found. */ *uid = 0; *gid = 0; return 0600; }}static void make_device(const char *path, int block, int major, int minor){ unsigned uid; unsigned gid; mode_t mode; dev_t dev; if(major > 255 || minor > 255) return; mode = get_device_perm(path, &uid, &gid) | (block ? S_IFBLK : S_IFCHR); dev = (major << 8) | minor; mknod(path, mode, dev); chown(path, uid, gid);}#ifdef LOG_UEVENTSstatic inline suseconds_t get_usecs(void){ struct timeval tv; gettimeofday(&tv, 0); return tv.tv_sec * (suseconds_t) 1000000 + tv.tv_usec;}#define log_event_print(x...) INFO(x)#else#define log_event_print(fmt, args...) do { } while (0)#define get_usecs() 0#endifstatic void parse_event(const char *msg, struct uevent *uevent){ uevent->action = ""; uevent->path = ""; uevent->subsystem = ""; uevent->firmware = ""; uevent->major = -1; uevent->minor = -1; /* currently ignoring SEQNUM */ while(*msg) { if(!strncmp(msg, "ACTION=", 7)) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -