properties.c 8.3 KB

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