blob: 41cdb41fad2a216d27c65234f113cd4d1b4c354a [file] [log] [blame]
San Mehat3c5a6f02009-05-22 15:36:13 -07001/*
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 Mehatc4a895b2009-06-23 21:10:57 -070017#include <stdlib.h>
18#include <sys/socket.h>
19#include <netinet/in.h>
20#include <arpa/inet.h>
21
San Mehat3c5a6f02009-05-22 15:36:13 -070022#define LOG_TAG "PropertyManager"
23
24#include <cutils/log.h>
25
26#include "PropertyManager.h"
27
28PropertyManager::PropertyManager() {
San Mehatc4a895b2009-06-23 21:10:57 -070029 mNamespaces = new PropertyNamespaceCollection();
San Mehat3c5a6f02009-05-22 15:36:13 -070030 pthread_mutex_init(&mLock, NULL);
31}
32
33PropertyManager::~PropertyManager() {
San Mehatc4a895b2009-06-23 21:10:57 -070034 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 Mehat3c5a6f02009-05-22 15:36:13 -070041}
42
San Mehatc4a895b2009-06-23 21:10:57 -070043PropertyNamespace *PropertyManager::lookupNamespace_UNLOCKED(const char *ns) {
44 PropertyNamespaceCollection::iterator ns_it;
San Mehat3c5a6f02009-05-22 15:36:13 -070045
San Mehatc4a895b2009-06-23 21:10:57 -070046 for (ns_it = mNamespaces->begin(); ns_it != mNamespaces->end(); ++ns_it) {
47 if (!strcasecmp(ns, (*ns_it)->getName()))
48 return (*ns_it);
San Mehat3c5a6f02009-05-22 15:36:13 -070049 }
San Mehatc4a895b2009-06-23 21:10:57 -070050 errno = ENOENT;
51 return NULL;
52}
53
54Property *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
66int PropertyManager::attachProperty(const char *ns_name, Property *p) {
67 PropertyNamespace *ns;
68
Steve Block8d66c492011-12-20 16:07:45 +000069 ALOGD("Attaching property %s to namespace %s", p->getName(), ns_name);
San Mehatc4a895b2009-06-23 21:10:57 -070070 pthread_mutex_lock(&mLock);
71 if (!(ns = lookupNamespace_UNLOCKED(ns_name))) {
Steve Block8d66c492011-12-20 16:07:45 +000072 ALOGD("Creating namespace %s", ns_name);
San Mehatc4a895b2009-06-23 21:10:57 -070073 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);
Steve Block01dda202012-01-06 14:13:42 +000080 ALOGE("Failed to register property %s.%s (%s)",
San Mehatc4a895b2009-06-23 21:10:57 -070081 ns_name, p->getName(), strerror(errno));
82 return -1;
83 }
84
85 ns->getProperties()->push_back(p);
San Mehat3c5a6f02009-05-22 15:36:13 -070086 pthread_mutex_unlock(&mLock);
87 return 0;
88}
89
San Mehatc4a895b2009-06-23 21:10:57 -070090int PropertyManager::detachProperty(const char *ns_name, Property *p) {
91 PropertyNamespace *ns;
San Mehat3c5a6f02009-05-22 15:36:13 -070092
Steve Block8d66c492011-12-20 16:07:45 +000093 ALOGD("Detaching property %s from namespace %s", p->getName(), ns_name);
San Mehat3c5a6f02009-05-22 15:36:13 -070094 pthread_mutex_lock(&mLock);
San Mehatc4a895b2009-06-23 21:10:57 -070095 if (!(ns = lookupNamespace_UNLOCKED(ns_name))) {
96 pthread_mutex_unlock(&mLock);
Steve Block01dda202012-01-06 14:13:42 +000097 ALOGE("Namespace '%s' not found", ns_name);
San Mehatc4a895b2009-06-23 21:10:57 -070098 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 Mehat3c5a6f02009-05-22 15:36:13 -0700106 delete ((*it));
San Mehatc4a895b2009-06-23 21:10:57 -0700107 ns->getProperties()->erase(it);
San Mehat3c5a6f02009-05-22 15:36:13 -0700108 pthread_mutex_unlock(&mLock);
109 return 0;
110 }
111 }
San Mehatc4a895b2009-06-23 21:10:57 -0700112
Steve Block01dda202012-01-06 14:13:42 +0000113 ALOGE("Property %s.%s not found", ns_name, p->getName());
San Mehat3c5a6f02009-05-22 15:36:13 -0700114 pthread_mutex_unlock(&mLock);
115 errno = ENOENT;
116 return -1;
117}
118
San Mehatc4a895b2009-06-23 21:10:57 -0700119int 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) {
Steve Block01dda202012-01-06 14:13:42 +0000133 ALOGE("Failed to convert '%s' to int", value);
San Mehatc4a895b2009-06-23 21:10:57 -0700134 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)) {
Steve Block01dda202012-01-06 14:13:42 +0000141 ALOGE("Failed to convert '%s' to ipv4", value);
San Mehatc4a895b2009-06-23 21:10:57 -0700142 errno = EINVAL;
143 return -1;
144 }
145 return p->set(idx, &tmp);
146 } else {
Steve Block01dda202012-01-06 14:13:42 +0000147 ALOGE("Property '%s' has an unknown type (%d)", p->getName(),
San Mehatc4a895b2009-06-23 21:10:57 -0700148 p->getType());
149 errno = EINVAL;
150 return -1;
151 }
152 errno = ENOENT;
153 return -1;
154}
155
156int 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)) {
Steve Blockae8b56c2012-01-05 22:25:38 +0000160 ALOGW("String property %s get failed (%s)", p->getName(),
San Mehatc4a895b2009-06-23 21:10:57 -0700161 strerror(errno));
162 return -1;
163 }
164 }
165 else if (p->getType() == Property::Type_INTEGER) {
166 int tmp;
167 if (p->get(idx, &tmp)) {
Steve Blockae8b56c2012-01-05 22:25:38 +0000168 ALOGW("Integer property %s get failed (%s)", p->getName(),
San Mehatc4a895b2009-06-23 21:10:57 -0700169 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)) {
Steve Blockae8b56c2012-01-05 22:25:38 +0000176 ALOGW("IPV4 property %s get failed (%s)", p->getName(),
San Mehatc4a895b2009-06-23 21:10:57 -0700177 strerror(errno));
178 return -1;
179 }
180 strncpy(buffer, inet_ntoa(tmp), max);
181 } else {
Steve Block01dda202012-01-06 14:13:42 +0000182 ALOGE("Property '%s' has an unknown type (%d)", p->getName(),
San Mehatc4a895b2009-06-23 21:10:57 -0700183 p->getType());
184 errno = EINVAL;
185 return -1;
186 }
187 return 0;
188}
189
San Mehat3c5a6f02009-05-22 15:36:13 -0700190/*
191 * IPropertyManager methods
192 */
193
194int PropertyManager::set(const char *name, const char *value) {
San Mehat3c5a6f02009-05-22 15:36:13 -0700195
Steve Block8d66c492011-12-20 16:07:45 +0000196 ALOGD("set %s = '%s'", name, value);
San Mehat3c5a6f02009-05-22 15:36:13 -0700197 pthread_mutex_lock(&mLock);
San Mehatc4a895b2009-06-23 21:10:57 -0700198 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 Mehat3c5a6f02009-05-22 15:36:13 -0700215 }
216 }
San Mehatc4a895b2009-06-23 21:10:57 -0700217
Steve Block01dda202012-01-06 14:13:42 +0000218 ALOGE("Property %s not found", name);
San Mehat3c5a6f02009-05-22 15:36:13 -0700219 pthread_mutex_unlock(&mLock);
220 errno = ENOENT;
221 return -1;
222}
223
224const char *PropertyManager::get(const char *name, char *buffer, size_t max) {
San Mehat3c5a6f02009-05-22 15:36:13 -0700225 pthread_mutex_lock(&mLock);
San Mehatc4a895b2009-06-23 21:10:57 -0700226 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 Mehat3c5a6f02009-05-22 15:36:13 -0700245 }
San Mehatc4a895b2009-06-23 21:10:57 -0700246 }
San Mehat3c5a6f02009-05-22 15:36:13 -0700247 }
San Mehatc4a895b2009-06-23 21:10:57 -0700248
Steve Block01dda202012-01-06 14:13:42 +0000249 ALOGE("Property %s not found", name);
San Mehat3c5a6f02009-05-22 15:36:13 -0700250 pthread_mutex_unlock(&mLock);
251 errno = ENOENT;
252 return NULL;
253}
254
San Mehatc4a895b2009-06-23 21:10:57 -0700255android::List<char *> *PropertyManager::createPropertyList(const char *prefix) {
San Mehat3c5a6f02009-05-22 15:36:13 -0700256 android::List<char *> *c = new android::List<char *>();
257
San Mehat3c5a6f02009-05-22 15:36:13 -0700258 pthread_mutex_lock(&mLock);
San Mehatc4a895b2009-06-23 21:10:57 -0700259 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 Mehat3c5a6f02009-05-22 15:36:13 -0700278 pthread_mutex_unlock(&mLock);
279 return c;
280}