Home | History | Annotate | Download | only in nexus
      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 <stdlib.h>
     18 #include <sys/socket.h>
     19 #include <netinet/in.h>
     20 #include <arpa/inet.h>
     21 
     22 #define LOG_TAG "PropertyManager"
     23 
     24 #include <cutils/log.h>
     25 
     26 #include "PropertyManager.h"
     27 
     28 PropertyManager::PropertyManager() {
     29     mNamespaces = new PropertyNamespaceCollection();
     30     pthread_mutex_init(&mLock, NULL);
     31 }
     32 
     33 PropertyManager::~PropertyManager() {
     34     PropertyNamespaceCollection::iterator it;
     35 
     36     for (it = mNamespaces->begin(); it != mNamespaces->end();) {
     37         delete (*it);
     38         it = mNamespaces->erase(it);
     39     }
     40     delete mNamespaces;
     41 }
     42 
     43 PropertyNamespace *PropertyManager::lookupNamespace_UNLOCKED(const char *ns) {
     44     PropertyNamespaceCollection::iterator ns_it;
     45 
     46     for (ns_it = mNamespaces->begin(); ns_it != mNamespaces->end(); ++ns_it) {
     47         if (!strcasecmp(ns, (*ns_it)->getName()))
     48             return (*ns_it);
     49     }
     50     errno = ENOENT;
     51     return NULL;
     52 }
     53 
     54 Property *PropertyManager::lookupProperty_UNLOCKED(PropertyNamespace *ns, const char *name) {
     55     PropertyCollection::iterator it;
     56 
     57     for (it = ns->getProperties()->begin();
     58          it != ns->getProperties()->end(); ++it) {
     59         if (!strcasecmp(name, (*it)->getName()))
     60             return (*it);
     61     }
     62     errno = ENOENT;
     63     return NULL;
     64 }
     65 
     66 int PropertyManager::attachProperty(const char *ns_name, Property *p) {
     67     PropertyNamespace *ns;
     68 
     69     LOGD("Attaching property %s to namespace %s", p->getName(), ns_name);
     70     pthread_mutex_lock(&mLock);
     71     if (!(ns = lookupNamespace_UNLOCKED(ns_name))) {
     72         LOGD("Creating namespace %s", ns_name);
     73         ns = new PropertyNamespace(ns_name);
     74         mNamespaces->push_back(ns);
     75     }
     76 
     77     if (lookupProperty_UNLOCKED(ns, p->getName())) {
     78         errno = EADDRINUSE;
     79         pthread_mutex_unlock(&mLock);
     80         LOGE("Failed to register property %s.%s (%s)",
     81             ns_name, p->getName(), strerror(errno));
     82         return -1;
     83     }
     84 
     85     ns->getProperties()->push_back(p);
     86     pthread_mutex_unlock(&mLock);
     87     return 0;
     88 }
     89 
     90 int PropertyManager::detachProperty(const char *ns_name, Property *p) {
     91     PropertyNamespace *ns;
     92 
     93     LOGD("Detaching property %s from namespace %s", p->getName(), ns_name);
     94     pthread_mutex_lock(&mLock);
     95     if (!(ns = lookupNamespace_UNLOCKED(ns_name))) {
     96         pthread_mutex_unlock(&mLock);
     97         LOGE("Namespace '%s' not found", ns_name);
     98         return -1;
     99     }
    100 
    101     PropertyCollection::iterator it;
    102 
    103     for (it = ns->getProperties()->begin();
    104          it != ns->getProperties()->end(); ++it) {
    105         if (!strcasecmp(p->getName(), (*it)->getName())) {
    106             delete ((*it));
    107             ns->getProperties()->erase(it);
    108             pthread_mutex_unlock(&mLock);
    109             return 0;
    110         }
    111     }
    112 
    113     LOGE("Property %s.%s not found", ns_name, p->getName());
    114     pthread_mutex_unlock(&mLock);
    115     errno = ENOENT;
    116     return -1;
    117 }
    118 
    119 int PropertyManager::doSet(Property *p, int idx, const char *value) {
    120 
    121     if (p->getReadOnly()) {
    122         errno = EROFS;
    123         return -1;
    124     }
    125 
    126     if (p->getType() == Property::Type_STRING) {
    127         return p->set(idx, value);
    128     } else if (p->getType() == Property::Type_INTEGER) {
    129         int tmp;
    130         errno = 0;
    131         tmp = strtol(value, (char **) NULL, 10);
    132         if (errno) {
    133             LOGE("Failed to convert '%s' to int", value);
    134             errno = EINVAL;
    135             return -1;
    136         }
    137         return p->set(idx, tmp);
    138     } else if (p->getType() == Property::Type_IPV4) {
    139         struct in_addr tmp;
    140         if (!inet_aton(value, &tmp)) {
    141             LOGE("Failed to convert '%s' to ipv4", value);
    142             errno = EINVAL;
    143             return -1;
    144         }
    145         return p->set(idx, &tmp);
    146     } else {
    147         LOGE("Property '%s' has an unknown type (%d)", p->getName(),
    148              p->getType());
    149         errno = EINVAL;
    150         return -1;
    151     }
    152     errno = ENOENT;
    153     return -1;
    154 }
    155 
    156 int PropertyManager::doGet(Property *p, int idx, char *buffer, size_t max) {
    157 
    158     if (p->getType() == Property::Type_STRING) {
    159         if (p->get(idx, buffer, max)) {
    160             LOGW("String property %s get failed (%s)", p->getName(),
    161                  strerror(errno));
    162             return -1;
    163         }
    164     }
    165     else if (p->getType() == Property::Type_INTEGER) {
    166         int tmp;
    167         if (p->get(idx, &tmp)) {
    168             LOGW("Integer property %s get failed (%s)", p->getName(),
    169                  strerror(errno));
    170             return -1;
    171         }
    172         snprintf(buffer, max, "%d", tmp);
    173     } else if (p->getType() == Property::Type_IPV4) {
    174         struct in_addr tmp;
    175         if (p->get(idx, &tmp)) {
    176             LOGW("IPV4 property %s get failed (%s)", p->getName(),
    177                  strerror(errno));
    178             return -1;
    179         }
    180         strncpy(buffer, inet_ntoa(tmp), max);
    181     } else {
    182         LOGE("Property '%s' has an unknown type (%d)", p->getName(),
    183              p->getType());
    184         errno = EINVAL;
    185         return -1;
    186     }
    187     return 0;
    188 }
    189 
    190 /*
    191  * IPropertyManager methods
    192  */
    193 
    194 int PropertyManager::set(const char *name, const char *value) {
    195 
    196     LOGD("set %s = '%s'", name, value);
    197     pthread_mutex_lock(&mLock);
    198     PropertyNamespaceCollection::iterator ns_it;
    199     for (ns_it = mNamespaces->begin(); ns_it != mNamespaces->end(); ++ns_it) {
    200         PropertyCollection::iterator p_it;
    201         for (p_it = (*ns_it)->getProperties()->begin();
    202              p_it != (*ns_it)->getProperties()->end(); ++p_it) {
    203             for (int i = 0; i < (*p_it)->getNumElements(); i++) {
    204                 char fqn[255];
    205                 char tmp[8];
    206                 sprintf(tmp, "_%d", i);
    207                 snprintf(fqn, sizeof(fqn), "%s.%s%s",
    208                          (*ns_it)->getName(), (*p_it)->getName(),
    209                          ((*p_it)->getNumElements() > 1 ? tmp : ""));
    210                 if (!strcasecmp(name, fqn)) {
    211                     pthread_mutex_unlock(&mLock);
    212                     return doSet((*p_it), i, value);
    213                 }
    214             }
    215         }
    216     }
    217 
    218     LOGE("Property %s not found", name);
    219     pthread_mutex_unlock(&mLock);
    220     errno = ENOENT;
    221     return -1;
    222 }
    223 
    224 const char *PropertyManager::get(const char *name, char *buffer, size_t max) {
    225     pthread_mutex_lock(&mLock);
    226     PropertyNamespaceCollection::iterator ns_it;
    227     for (ns_it = mNamespaces->begin(); ns_it != mNamespaces->end(); ++ns_it) {
    228         PropertyCollection::iterator p_it;
    229         for (p_it = (*ns_it)->getProperties()->begin();
    230              p_it != (*ns_it)->getProperties()->end(); ++p_it) {
    231 
    232             for (int i = 0; i < (*p_it)->getNumElements(); i++) {
    233                 char fqn[255];
    234                 char tmp[8];
    235                 sprintf(tmp, "_%d", i);
    236                 snprintf(fqn, sizeof(fqn), "%s.%s%s",
    237                          (*ns_it)->getName(), (*p_it)->getName(),
    238                          ((*p_it)->getNumElements() > 1 ? tmp : ""));
    239                 if (!strcasecmp(name, fqn)) {
    240                     pthread_mutex_unlock(&mLock);
    241                     if (doGet((*p_it), i, buffer, max))
    242                         return NULL;
    243                     return buffer;
    244                 }
    245             }
    246         }
    247     }
    248 
    249     LOGE("Property %s not found", name);
    250     pthread_mutex_unlock(&mLock);
    251     errno = ENOENT;
    252     return NULL;
    253 }
    254 
    255 android::List<char *> *PropertyManager::createPropertyList(const char *prefix) {
    256     android::List<char *> *c = new android::List<char *>();
    257 
    258     pthread_mutex_lock(&mLock);
    259     PropertyNamespaceCollection::iterator ns_it;
    260     for (ns_it = mNamespaces->begin(); ns_it != mNamespaces->end(); ++ns_it) {
    261         PropertyCollection::iterator p_it;
    262         for (p_it = (*ns_it)->getProperties()->begin();
    263              p_it != (*ns_it)->getProperties()->end(); ++p_it) {
    264             for (int i = 0; i < (*p_it)->getNumElements(); i++) {
    265                 char fqn[255];
    266                 char tmp[8];
    267                 sprintf(tmp, "_%d", i);
    268                 snprintf(fqn, sizeof(fqn), "%s.%s%s",
    269                          (*ns_it)->getName(), (*p_it)->getName(),
    270                          ((*p_it)->getNumElements() > 1 ? tmp : ""));
    271                 if (!prefix ||
    272                     (prefix && !strncasecmp(fqn, prefix, strlen(prefix)))) {
    273                     c->push_back(strdup(fqn));
    274                 }
    275             }
    276         }
    277     }
    278     pthread_mutex_unlock(&mLock);
    279     return c;
    280 }
    281