• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2006 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 #define LOG_TAG "properties"
18 
19 #include <stdlib.h>
20 #include <string.h>
21 #include <unistd.h>
22 #include <cutils/sockets.h>
23 #include <errno.h>
24 #include <assert.h>
25 
26 #include <cutils/properties.h>
27 #include "loghack.h"
28 
29 #ifdef HAVE_LIBC_SYSTEM_PROPERTIES
30 
31 #define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_
32 #include <sys/_system_properties.h>
33 
property_set(const char * key,const char * value)34 int property_set(const char *key, const char *value)
35 {
36     return __system_property_set(key, value);
37 }
38 
property_get(const char * key,char * value,const char * default_value)39 int property_get(const char *key, char *value, const char *default_value)
40 {
41     int len;
42 
43     len = __system_property_get(key, value);
44     if(len > 0) {
45         return len;
46     }
47 
48     if(default_value) {
49         len = strlen(default_value);
50         memcpy(value, default_value, len + 1);
51     }
52     return len;
53 }
54 
property_list(void (* propfn)(const char * key,const char * value,void * cookie),void * cookie)55 int property_list(void (*propfn)(const char *key, const char *value, void *cookie),
56                   void *cookie)
57 {
58     char name[PROP_NAME_MAX];
59     char value[PROP_VALUE_MAX];
60     const prop_info *pi;
61     unsigned n;
62 
63     for(n = 0; (pi = __system_property_find_nth(n)); n++) {
64         __system_property_read(pi, name, value);
65         propfn(name, value, cookie);
66     }
67     return 0;
68 }
69 
70 #elif defined(HAVE_SYSTEM_PROPERTY_SERVER)
71 
72 /*
73  * The Linux simulator provides a "system property server" that uses IPC
74  * to set/get/list properties.  The file descriptor is shared by all
75  * threads in the process, so we use a mutex to ensure that requests
76  * from multiple threads don't get interleaved.
77  */
78 #include <stdio.h>
79 #include <sys/types.h>
80 #include <sys/socket.h>
81 #include <sys/un.h>
82 #include <pthread.h>
83 
84 static pthread_once_t gInitOnce = PTHREAD_ONCE_INIT;
85 static pthread_mutex_t gPropertyFdLock = PTHREAD_MUTEX_INITIALIZER;
86 static int gPropFd = -1;
87 
88 /*
89  * Connect to the properties server.
90  *
91  * Returns the socket descriptor on success.
92  */
connectToServer(const char * fileName)93 static int connectToServer(const char* fileName)
94 {
95     int sock = -1;
96     int cc;
97 
98     struct sockaddr_un addr;
99 
100     sock = socket(AF_UNIX, SOCK_STREAM, 0);
101     if (sock < 0) {
102         ALOGW("UNIX domain socket create failed (errno=%d)\n", errno);
103         return -1;
104     }
105 
106     /* connect to socket; fails if file doesn't exist */
107     strcpy(addr.sun_path, fileName);    // max 108 bytes
108     addr.sun_family = AF_UNIX;
109     cc = connect(sock, (struct sockaddr*) &addr, SUN_LEN(&addr));
110     if (cc < 0) {
111         // ENOENT means socket file doesn't exist
112         // ECONNREFUSED means socket exists but nobody is listening
113         //ALOGW("AF_UNIX connect failed for '%s': %s\n",
114         //    fileName, strerror(errno));
115         close(sock);
116         return -1;
117     }
118 
119     return sock;
120 }
121 
122 /*
123  * Perform one-time initialization.
124  */
init(void)125 static void init(void)
126 {
127     assert(gPropFd == -1);
128 
129     gPropFd = connectToServer(SYSTEM_PROPERTY_PIPE_NAME);
130     if (gPropFd < 0) {
131         //ALOGW("not connected to system property server\n");
132     } else {
133         //ALOGV("Connected to system property server\n");
134     }
135 }
136 
property_get(const char * key,char * value,const char * default_value)137 int property_get(const char *key, char *value, const char *default_value)
138 {
139     char sendBuf[1+PROPERTY_KEY_MAX];
140     char recvBuf[1+PROPERTY_VALUE_MAX];
141     int len = -1;
142 
143     //ALOGV("PROPERTY GET [%s]\n", key);
144 
145     pthread_once(&gInitOnce, init);
146     if (gPropFd < 0) {
147         /* this mimics the behavior of the device implementation */
148         if (default_value != NULL) {
149             strcpy(value, default_value);
150             len = strlen(value);
151         }
152         return len;
153     }
154 
155     if (strlen(key) >= PROPERTY_KEY_MAX) return -1;
156 
157     memset(sendBuf, 0xdd, sizeof(sendBuf));    // placate valgrind
158 
159     sendBuf[0] = (char) kSystemPropertyGet;
160     strcpy(sendBuf+1, key);
161 
162     pthread_mutex_lock(&gPropertyFdLock);
163     if (write(gPropFd, sendBuf, sizeof(sendBuf)) != sizeof(sendBuf)) {
164         pthread_mutex_unlock(&gPropertyFdLock);
165         return -1;
166     }
167     if (read(gPropFd, recvBuf, sizeof(recvBuf)) != sizeof(recvBuf)) {
168         pthread_mutex_unlock(&gPropertyFdLock);
169         return -1;
170     }
171     pthread_mutex_unlock(&gPropertyFdLock);
172 
173     /* first byte is 0 if value not defined, 1 if found */
174     if (recvBuf[0] == 0) {
175         if (default_value != NULL) {
176             strcpy(value, default_value);
177             len = strlen(value);
178         } else {
179             /*
180              * If the value isn't defined, hand back an empty string and
181              * a zero length, rather than a failure.  This seems wrong,
182              * since you can't tell the difference between "undefined" and
183              * "defined but empty", but it's what the device does.
184              */
185             value[0] = '\0';
186             len = 0;
187         }
188     } else if (recvBuf[0] == 1) {
189         strcpy(value, recvBuf+1);
190         len = strlen(value);
191     } else {
192         ALOGE("Got strange response to property_get request (%d)\n",
193             recvBuf[0]);
194         assert(0);
195         return -1;
196     }
197     //ALOGV("PROP [found=%d def='%s'] (%d) [%s]: [%s]\n",
198     //    recvBuf[0], default_value, len, key, value);
199 
200     return len;
201 }
202 
203 
property_set(const char * key,const char * value)204 int property_set(const char *key, const char *value)
205 {
206     char sendBuf[1+PROPERTY_KEY_MAX+PROPERTY_VALUE_MAX];
207     char recvBuf[1];
208     int result = -1;
209 
210     //ALOGV("PROPERTY SET [%s]: [%s]\n", key, value);
211 
212     pthread_once(&gInitOnce, init);
213     if (gPropFd < 0)
214         return -1;
215 
216     if (strlen(key) >= PROPERTY_KEY_MAX) return -1;
217     if (strlen(value) >= PROPERTY_VALUE_MAX) return -1;
218 
219     memset(sendBuf, 0xdd, sizeof(sendBuf));    // placate valgrind
220 
221     sendBuf[0] = (char) kSystemPropertySet;
222     strcpy(sendBuf+1, key);
223     strcpy(sendBuf+1+PROPERTY_KEY_MAX, value);
224 
225     pthread_mutex_lock(&gPropertyFdLock);
226     if (write(gPropFd, sendBuf, sizeof(sendBuf)) != sizeof(sendBuf)) {
227         pthread_mutex_unlock(&gPropertyFdLock);
228         return -1;
229     }
230     if (read(gPropFd, recvBuf, sizeof(recvBuf)) != sizeof(recvBuf)) {
231         pthread_mutex_unlock(&gPropertyFdLock);
232         return -1;
233     }
234     pthread_mutex_unlock(&gPropertyFdLock);
235 
236     if (recvBuf[0] != 1)
237         return -1;
238     return 0;
239 }
240 
property_list(void (* propfn)(const char * key,const char * value,void * cookie),void * cookie)241 int property_list(void (*propfn)(const char *key, const char *value, void *cookie),
242                   void *cookie)
243 {
244     //ALOGV("PROPERTY LIST\n");
245     pthread_once(&gInitOnce, init);
246     if (gPropFd < 0)
247         return -1;
248 
249     return 0;
250 }
251 
252 #else
253 
254 /* SUPER-cheesy place-holder implementation for Win32 */
255 
256 #include <cutils/threads.h>
257 
258 static mutex_t  env_lock = MUTEX_INITIALIZER;
259 
property_get(const char * key,char * value,const char * default_value)260 int property_get(const char *key, char *value, const char *default_value)
261 {
262     char ename[PROPERTY_KEY_MAX + 6];
263     char *p;
264     int len;
265 
266     len = strlen(key);
267     if(len >= PROPERTY_KEY_MAX) return -1;
268     memcpy(ename, "PROP_", 5);
269     memcpy(ename + 5, key, len + 1);
270 
271     mutex_lock(&env_lock);
272 
273     p = getenv(ename);
274     if(p == 0) p = "";
275     len = strlen(p);
276     if(len >= PROPERTY_VALUE_MAX) {
277         len = PROPERTY_VALUE_MAX - 1;
278     }
279 
280     if((len == 0) && default_value) {
281         len = strlen(default_value);
282         memcpy(value, default_value, len + 1);
283     } else {
284         memcpy(value, p, len);
285         value[len] = 0;
286     }
287 
288     mutex_unlock(&env_lock);
289 
290     return len;
291 }
292 
293 
property_set(const char * key,const char * value)294 int property_set(const char *key, const char *value)
295 {
296     char ename[PROPERTY_KEY_MAX + 6];
297     char *p;
298     int len;
299     int r;
300 
301     if(strlen(value) >= PROPERTY_VALUE_MAX) return -1;
302 
303     len = strlen(key);
304     if(len >= PROPERTY_KEY_MAX) return -1;
305     memcpy(ename, "PROP_", 5);
306     memcpy(ename + 5, key, len + 1);
307 
308     mutex_lock(&env_lock);
309 #ifdef HAVE_MS_C_RUNTIME
310     {
311         char  temp[256];
312         snprintf( temp, sizeof(temp), "%s=%s", ename, value);
313         putenv(temp);
314         r = 0;
315     }
316 #else
317     r = setenv(ename, value, 1);
318 #endif
319     mutex_unlock(&env_lock);
320 
321     return r;
322 }
323 
property_list(void (* propfn)(const char * key,const char * value,void * cookie),void * cookie)324 int property_list(void (*propfn)(const char *key, const char *value, void *cookie),
325                   void *cookie)
326 {
327     return 0;
328 }
329 
330 #endif
331