San Mehat | 3c5a6f0 | 2009-05-22 15:36:13 -0700 | [diff] [blame] | 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 | |
San Mehat | c4a895b | 2009-06-23 21:10:57 -0700 | [diff] [blame] | 17 | #include <stdlib.h> |
| 18 | #include <sys/socket.h> |
| 19 | #include <netinet/in.h> |
| 20 | #include <arpa/inet.h> |
| 21 | |
San Mehat | 3c5a6f0 | 2009-05-22 15:36:13 -0700 | [diff] [blame] | 22 | #define LOG_TAG "PropertyManager" |
| 23 | |
| 24 | #include <cutils/log.h> |
| 25 | |
| 26 | #include "PropertyManager.h" |
| 27 | |
| 28 | PropertyManager::PropertyManager() { |
San Mehat | c4a895b | 2009-06-23 21:10:57 -0700 | [diff] [blame] | 29 | mNamespaces = new PropertyNamespaceCollection(); |
San Mehat | 3c5a6f0 | 2009-05-22 15:36:13 -0700 | [diff] [blame] | 30 | pthread_mutex_init(&mLock, NULL); |
| 31 | } |
| 32 | |
| 33 | PropertyManager::~PropertyManager() { |
San Mehat | c4a895b | 2009-06-23 21:10:57 -0700 | [diff] [blame] | 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; |
San Mehat | 3c5a6f0 | 2009-05-22 15:36:13 -0700 | [diff] [blame] | 41 | } |
| 42 | |
San Mehat | c4a895b | 2009-06-23 21:10:57 -0700 | [diff] [blame] | 43 | PropertyNamespace *PropertyManager::lookupNamespace_UNLOCKED(const char *ns) { |
| 44 | PropertyNamespaceCollection::iterator ns_it; |
San Mehat | 3c5a6f0 | 2009-05-22 15:36:13 -0700 | [diff] [blame] | 45 | |
San Mehat | c4a895b | 2009-06-23 21:10:57 -0700 | [diff] [blame] | 46 | for (ns_it = mNamespaces->begin(); ns_it != mNamespaces->end(); ++ns_it) { |
| 47 | if (!strcasecmp(ns, (*ns_it)->getName())) |
| 48 | return (*ns_it); |
San Mehat | 3c5a6f0 | 2009-05-22 15:36:13 -0700 | [diff] [blame] | 49 | } |
San Mehat | c4a895b | 2009-06-23 21:10:57 -0700 | [diff] [blame] | 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); |
San Mehat | 3c5a6f0 | 2009-05-22 15:36:13 -0700 | [diff] [blame] | 86 | pthread_mutex_unlock(&mLock); |
| 87 | return 0; |
| 88 | } |
| 89 | |
San Mehat | c4a895b | 2009-06-23 21:10:57 -0700 | [diff] [blame] | 90 | int PropertyManager::detachProperty(const char *ns_name, Property *p) { |
| 91 | PropertyNamespace *ns; |
San Mehat | 3c5a6f0 | 2009-05-22 15:36:13 -0700 | [diff] [blame] | 92 | |
San Mehat | c4a895b | 2009-06-23 21:10:57 -0700 | [diff] [blame] | 93 | LOGD("Detaching property %s from namespace %s", p->getName(), ns_name); |
San Mehat | 3c5a6f0 | 2009-05-22 15:36:13 -0700 | [diff] [blame] | 94 | pthread_mutex_lock(&mLock); |
San Mehat | c4a895b | 2009-06-23 21:10:57 -0700 | [diff] [blame] | 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())) { |
San Mehat | 3c5a6f0 | 2009-05-22 15:36:13 -0700 | [diff] [blame] | 106 | delete ((*it)); |
San Mehat | c4a895b | 2009-06-23 21:10:57 -0700 | [diff] [blame] | 107 | ns->getProperties()->erase(it); |
San Mehat | 3c5a6f0 | 2009-05-22 15:36:13 -0700 | [diff] [blame] | 108 | pthread_mutex_unlock(&mLock); |
| 109 | return 0; |
| 110 | } |
| 111 | } |
San Mehat | c4a895b | 2009-06-23 21:10:57 -0700 | [diff] [blame] | 112 | |
| 113 | LOGE("Property %s.%s not found", ns_name, p->getName()); |
San Mehat | 3c5a6f0 | 2009-05-22 15:36:13 -0700 | [diff] [blame] | 114 | pthread_mutex_unlock(&mLock); |
| 115 | errno = ENOENT; |
| 116 | return -1; |
| 117 | } |
| 118 | |
San Mehat | c4a895b | 2009-06-23 21:10:57 -0700 | [diff] [blame] | 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 | |
San Mehat | 3c5a6f0 | 2009-05-22 15:36:13 -0700 | [diff] [blame] | 190 | /* |
| 191 | * IPropertyManager methods |
| 192 | */ |
| 193 | |
| 194 | int PropertyManager::set(const char *name, const char *value) { |
San Mehat | 3c5a6f0 | 2009-05-22 15:36:13 -0700 | [diff] [blame] | 195 | |
San Mehat | c4a895b | 2009-06-23 21:10:57 -0700 | [diff] [blame] | 196 | LOGD("set %s = '%s'", name, value); |
San Mehat | 3c5a6f0 | 2009-05-22 15:36:13 -0700 | [diff] [blame] | 197 | pthread_mutex_lock(&mLock); |
San Mehat | c4a895b | 2009-06-23 21:10:57 -0700 | [diff] [blame] | 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 | } |
San Mehat | 3c5a6f0 | 2009-05-22 15:36:13 -0700 | [diff] [blame] | 215 | } |
| 216 | } |
San Mehat | c4a895b | 2009-06-23 21:10:57 -0700 | [diff] [blame] | 217 | |
| 218 | LOGE("Property %s not found", name); |
San Mehat | 3c5a6f0 | 2009-05-22 15:36:13 -0700 | [diff] [blame] | 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) { |
San Mehat | 3c5a6f0 | 2009-05-22 15:36:13 -0700 | [diff] [blame] | 225 | pthread_mutex_lock(&mLock); |
San Mehat | c4a895b | 2009-06-23 21:10:57 -0700 | [diff] [blame] | 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 | } |
San Mehat | 3c5a6f0 | 2009-05-22 15:36:13 -0700 | [diff] [blame] | 245 | } |
San Mehat | c4a895b | 2009-06-23 21:10:57 -0700 | [diff] [blame] | 246 | } |
San Mehat | 3c5a6f0 | 2009-05-22 15:36:13 -0700 | [diff] [blame] | 247 | } |
San Mehat | c4a895b | 2009-06-23 21:10:57 -0700 | [diff] [blame] | 248 | |
| 249 | LOGE("Property %s not found", name); |
San Mehat | 3c5a6f0 | 2009-05-22 15:36:13 -0700 | [diff] [blame] | 250 | pthread_mutex_unlock(&mLock); |
| 251 | errno = ENOENT; |
| 252 | return NULL; |
| 253 | } |
| 254 | |
San Mehat | c4a895b | 2009-06-23 21:10:57 -0700 | [diff] [blame] | 255 | android::List<char *> *PropertyManager::createPropertyList(const char *prefix) { |
San Mehat | 3c5a6f0 | 2009-05-22 15:36:13 -0700 | [diff] [blame] | 256 | android::List<char *> *c = new android::List<char *>(); |
| 257 | |
San Mehat | 3c5a6f0 | 2009-05-22 15:36:13 -0700 | [diff] [blame] | 258 | pthread_mutex_lock(&mLock); |
San Mehat | c4a895b | 2009-06-23 21:10:57 -0700 | [diff] [blame] | 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 | } |
San Mehat | 3c5a6f0 | 2009-05-22 15:36:13 -0700 | [diff] [blame] | 278 | pthread_mutex_unlock(&mLock); |
| 279 | return c; |
| 280 | } |