diff --git a/init/init.c b/init/init.c index 39df0ffae..afa4d44ef 100755 --- a/init/init.c +++ b/init/init.c @@ -625,7 +625,7 @@ static void import_kernel_nv(char *name, int for_emulator) static void export_kernel_boot_props(void) { char tmp[PROP_VALUE_MAX]; - const char *pval; + int ret; unsigned i; struct { const char *src_prop; @@ -639,22 +639,26 @@ static void export_kernel_boot_props(void) }; for (i = 0; i < ARRAY_SIZE(prop_map); i++) { - pval = property_get(prop_map[i].src_prop); - property_set(prop_map[i].dest_prop, pval ?: prop_map[i].def_val); + ret = property_get(prop_map[i].src_prop, tmp); + if (ret > 0) + property_set(prop_map[i].dest_prop, tmp); + else + property_set(prop_map[i].dest_prop, prop_map[i].def_val); } - pval = property_get("ro.boot.console"); - if (pval) - strlcpy(console, pval, sizeof(console)); + ret = property_get("ro.boot.console", tmp); + if (ret) + strlcpy(console, tmp, sizeof(console)); /* save a copy for init's usage during boot */ - strlcpy(bootmode, property_get("ro.bootmode"), sizeof(bootmode)); + property_get("ro.bootmode", tmp); + strlcpy(bootmode, tmp, sizeof(bootmode)); /* if this was given on kernel command line, override what we read * before (e.g. from /proc/cpuinfo), if anything */ - pval = property_get("ro.boot.hardware"); - if (pval) - strlcpy(hardware, pval, sizeof(hardware)); + ret = property_get("ro.boot.hardware", tmp); + if (ret) + strlcpy(hardware, tmp, sizeof(hardware)); property_set("ro.hardware", hardware); snprintf(tmp, PROP_VALUE_MAX, "%d", revision); diff --git a/init/init_parser.c b/init/init_parser.c index 686640ed4..cce109386 100644 --- a/init/init_parser.c +++ b/init/init_parser.c @@ -206,8 +206,9 @@ int expand_props(char *dst, const char *src, int dst_size) while (*src_ptr && left > 0) { char *c; char prop[PROP_NAME_MAX + 1]; - const char *prop_val; + char prop_val[PROP_VALUE_MAX]; int prop_len = 0; + int prop_val_len; c = strchr(src_ptr, '$'); if (!c) { @@ -265,14 +266,14 @@ int expand_props(char *dst, const char *src, int dst_size) goto err; } - prop_val = property_get(prop); - if (!prop_val) { + prop_val_len = property_get(prop, prop_val); + if (!prop_val_len) { ERROR("property '%s' doesn't exist while expanding '%s'\n", prop, src); goto err; } - ret = push_chars(&dst_ptr, &left, prop_val, strlen(prop_val)); + ret = push_chars(&dst_ptr, &left, prop_val, prop_val_len); if (ret < 0) goto err_nospace; src_ptr = c; @@ -543,7 +544,7 @@ void queue_all_property_triggers() const char* equals = strchr(name, '='); if (equals) { char prop_name[PROP_NAME_MAX + 1]; - const char* value; + char value[PROP_VALUE_MAX]; int length = equals - name; if (length > PROP_NAME_MAX) { ERROR("property name too long in trigger %s", act->name); @@ -552,9 +553,8 @@ void queue_all_property_triggers() prop_name[length] = 0; /* does the property exist, and match the trigger value? */ - value = property_get(prop_name); - if (value && (!strcmp(equals + 1, value) || - !strcmp(equals + 1, "*"))) { + property_get(prop_name, value); + if (!strcmp(equals + 1, value) ||!strcmp(equals + 1, "*")) { action_add_queue_tail(act); } } diff --git a/init/keychords.c b/init/keychords.c index aab08195e..d18a6e41c 100644 --- a/init/keychords.c +++ b/init/keychords.c @@ -95,24 +95,23 @@ void keychord_init() void handle_keychord() { struct service *svc; - const char* debuggable; - const char* adb_enabled; + char debuggable[PROP_VALUE_MAX]; + char adb_enabled[PROP_VALUE_MAX]; int ret; __u16 id; // only handle keychords if ro.debuggable is set or adb is enabled. // the logic here is that bugreports should be enabled in userdebug or eng builds // and on user builds for users that are developers. - debuggable = property_get("ro.debuggable"); - adb_enabled = property_get("init.svc.adbd"); + property_get("ro.debuggable", debuggable); + property_get("init.svc.adbd", adb_enabled); ret = read(keychord_fd, &id, sizeof(id)); if (ret != sizeof(id)) { ERROR("could not read keychord id\n"); return; } - if ((debuggable && !strcmp(debuggable, "1")) || - (adb_enabled && !strcmp(adb_enabled, "running"))) { + if (!strcmp(debuggable, "1") || !strcmp(adb_enabled, "running")) { svc = service_find_by_keychord(id); if (svc) { INFO("starting service %s from keychord\n", svc->name); diff --git a/init/property_service.c b/init/property_service.c index 48488be9c..86e35f132 100755 --- a/init/property_service.c +++ b/init/property_service.c @@ -152,23 +152,11 @@ out: return -1; } -/* (8 header words + 247 toc words) = 1020 bytes */ -/* 1024 bytes header and toc + 247 prop_infos @ 128 bytes = 32640 bytes */ - -#define PA_COUNT_MAX 247 -#define PA_INFO_START 1024 -#define PA_SIZE 32768 - static workspace pa_workspace; -static prop_info *pa_info_array; - -extern prop_area *__system_property_area__; static int init_property_area(void) { - prop_area *pa; - - if(pa_info_array) + if (property_area_inited) return -1; if(init_workspace(&pa_workspace, PA_SIZE)) @@ -176,27 +164,12 @@ static int init_property_area(void) fcntl(pa_workspace.fd, F_SETFD, FD_CLOEXEC); - pa_info_array = (void*) (((char*) pa_workspace.data) + PA_INFO_START); + __system_property_area_init(pa_workspace.data); - pa = pa_workspace.data; - memset(pa, 0, PA_SIZE); - pa->magic = PROP_AREA_MAGIC; - pa->version = PROP_AREA_VERSION; - - /* plug into the lib property services */ - __system_property_area__ = pa; property_area_inited = 1; return 0; } -static void update_prop_info(prop_info *pi, const char *value, unsigned len) -{ - pi->serial = pi->serial | 1; - memcpy(pi->value, value, len + 1); - pi->serial = (len << 24) | ((pi->serial + 1) & 0xffffff); - __futex_wake(&pi->serial, INT32_MAX); -} - static int check_mac_perms(const char *name, char *sctx) { if (is_selinux_enabled() <= 0) @@ -292,19 +265,9 @@ static int check_perms(const char *name, unsigned int uid, unsigned int gid, cha return 0; } -const char* property_get(const char *name) +int __property_get(const char *name, char *value) { - prop_info *pi; - - if(strlen(name) >= PROP_NAME_MAX) return 0; - - pi = (prop_info*) __system_property_find(name); - - if(pi != 0) { - return pi->value; - } else { - return 0; - } + return __system_property_get(name, value); } static void write_persistent_property(const char *name, const char *value) @@ -331,8 +294,8 @@ static void write_persistent_property(const char *name, const char *value) int property_set(const char *name, const char *value) { - prop_area *pa; prop_info *pi; + int ret; size_t namelen = strlen(name); size_t valuelen = strlen(value); @@ -347,29 +310,13 @@ int property_set(const char *name, const char *value) /* ro.* properties may NEVER be modified once set */ if(!strncmp(name, "ro.", 3)) return -1; - pa = __system_property_area__; - update_prop_info(pi, value, valuelen); - pa->serial++; - __futex_wake(&pa->serial, INT32_MAX); + __system_property_update(pi, value, valuelen); } else { - pa = __system_property_area__; - if(pa->count == PA_COUNT_MAX) { - ERROR("Failed to set '%s'='%s', property pool is exhausted at %d entries", - name, value, PA_COUNT_MAX); - return -1; + ret = __system_property_add(name, namelen, value, valuelen); + if (ret < 0) { + ERROR("Failed to set '%s'='%s'", name, value); + return ret; } - - pi = pa_info_array + pa->count; - pi->serial = (valuelen << 24); - memcpy(pi->name, name, namelen + 1); - memcpy(pi->value, value, valuelen + 1); - - pa->toc[pa->count] = - (namelen << 24) | (((unsigned) pi) - ((unsigned) pa)); - - pa->count++; - pa->serial++; - __futex_wake(&pa->serial, INT32_MAX); } /* If name starts with "net." treat as a DNS property. */ if (strncmp("net.", name, strlen("net.")) == 0) { @@ -591,8 +538,11 @@ int properties_inited(void) static void load_override_properties() { #ifdef ALLOW_LOCAL_PROP_OVERRIDE - const char *debuggable = property_get("ro.debuggable"); - if (debuggable && (strcmp(debuggable, "1") == 0)) { + char debuggable[PROP_VALUE_MAX]; + int ret; + + ret = property_get("ro.debuggable", debuggable); + if (ret && (strcmp(debuggable, "1") == 0)) { load_properties_from_file(PROP_PATH_LOCAL_OVERRIDE); } #endif /* ALLOW_LOCAL_PROP_OVERRIDE */ diff --git a/init/property_service.h b/init/property_service.h index b9d1bf610..46cbd8ff5 100644 --- a/init/property_service.h +++ b/init/property_service.h @@ -18,6 +18,7 @@ #define _INIT_PROPERTY_H #include +#include extern void handle_property_set_fd(void); extern void property_init(void); @@ -25,9 +26,25 @@ extern void property_load_boot_defaults(void); extern void load_persist_props(void); extern void start_property_service(void); void get_property_workspace(int *fd, int *sz); -extern const char* property_get(const char *name); +extern int __property_get(const char *name, char *value); extern int property_set(const char *name, const char *value); extern int properties_inited(); int get_property_set_fd(void); +extern void __property_get_size_error() + __attribute__((__error__("property_get called with too small buffer"))); + +static inline +__attribute__ ((always_inline)) +__attribute__ ((gnu_inline)) +__attribute__ ((artificial)) +int property_get(const char *name, char *value) +{ + size_t value_len = __builtin_object_size(value, 0); + if (value_len != PROP_VALUE_MAX) + __property_get_size_error(); + + return __property_get(name, value); +} + #endif /* _INIT_PROPERTY_H */ diff --git a/toolbox/watchprops.c b/toolbox/watchprops.c index d3119924b..3418d6293 100644 --- a/toolbox/watchprops.c +++ b/toolbox/watchprops.c @@ -9,9 +9,6 @@ #define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_ #include - -extern prop_area *__system_property_area__; - typedef struct pwatch pwatch; struct pwatch @@ -39,33 +36,35 @@ static void announce(const prop_info *pi) int watchprops_main(int argc, char *argv[]) { - prop_area *pa = __system_property_area__; - unsigned serial = pa->serial; - unsigned count = pa->count; + unsigned serial = 0; + unsigned count; unsigned n; - if(count >= 1024) exit(1); - - for(n = 0; n < count; n++) { + for(n = 0; n < 1024; n++) { watchlist[n].pi = __system_property_find_nth(n); - watchlist[n].serial = watchlist[n].pi->serial; + if (watchlist[n].pi == 0) + break; + watchlist[n].serial = __system_property_serial(watchlist[n].pi); } - for(;;) { - do { - __futex_wait(&pa->serial, serial, 0); - } while(pa->serial == serial); + count = n; + if (count == 1024) + exit(1); - while(count < pa->count){ + for(;;) { + serial = __system_property_wait_any(serial); + while(count < 1024){ watchlist[count].pi = __system_property_find_nth(count); - watchlist[count].serial = watchlist[n].pi->serial; + if (watchlist[count].pi == 0) + break; + watchlist[count].serial = __system_property_serial(watchlist[n].pi); announce(watchlist[count].pi); count++; if(count == 1024) exit(1); } for(n = 0; n < count; n++){ - unsigned tmp = watchlist[n].pi->serial; + unsigned tmp = __system_property_serial(watchlist[n].pi); if(watchlist[n].serial != tmp) { announce(watchlist[n].pi); watchlist[n].serial = tmp;