2 * Copyright (c) 2012 Carsten Munk <carsten.munk@gmail.com>
3 * 2008 The Android Open Source Project
4 * 2013 Simon Busch <morphis@gravedo.de>
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
26 #include <sys/types.h>
31 #include <sys/socket.h>
33 #include <sys/select.h>
34 #include <sys/types.h>
35 #include <netinet/in.h>
38 #include <hybris/properties/properties.h>
39 #include "properties_p.h"
42 static const char property_service_socket
[] = "/dev/socket/" PROP_SERVICE_NAME
;
43 static int send_prop_msg_no_reply
= 0;
45 /* Get/Set a property from the Android Init property socket */
46 static int send_prop_msg(prop_msg_t
*msg
,
47 void (*propfn
)(const char *, const char *, void *),
50 struct pollfd pollfds
[1];
52 struct sockaddr_un addr
;
53 struct sockaddr addr_g
;
62 /* if we tried to talk to the server in the past and didn't get a reply,
63 * it's fairly safe to say that init is not patched and this is all
64 * hopeless, so we should just quit while we're ahead
66 if (send_prop_msg_no_reply
== 1)
69 s
= socket(AF_LOCAL
, SOCK_STREAM
, 0);
74 memset(&addr
, 0, sizeof(addr
));
75 namelen
= strlen(property_service_socket
);
76 strncpy(addr
.addr
.sun_path
, property_service_socket
,
77 sizeof(addr
.addr
.sun_path
));
78 addr
.addr
.sun_family
= AF_LOCAL
;
79 alen
= namelen
+ offsetof(struct sockaddr_un
, sun_path
) + 1;
81 if (TEMP_FAILURE_RETRY(connect(s
, &addr
.addr_g
, alen
) < 0)) {
86 r
= TEMP_FAILURE_RETRY(send(s
, msg
, sizeof(prop_msg_t
), 0));
88 if (r
== sizeof(prop_msg_t
)) {
90 pollfds
[0].events
= 0;
91 // We successfully wrote to the property server, so use recv
92 // in case we need to get a property. Once the other side is
93 // finished, the socket is closed.
94 while ((r
= recv(s
, msg
, sizeof(prop_msg_t
), 0)) > 0) {
95 if (r
!= sizeof(prop_msg_t
)) {
100 /* If we got a reply, this is a patched init */
105 propfn(msg
->name
, msg
->value
, cookie
);
108 /* We also just get a close in case of setprop */
109 if ((r
>= 0) && (patched_init
||
110 (msg
->cmd
== PROP_MSG_SETPROP
))) {
113 send_prop_msg_no_reply
= 1;
121 int property_list(void (*propfn
)(const char *key
, const char *value
, void *cookie
),
127 memset(&msg
, 0, sizeof(msg
));
128 msg
.cmd
= PROP_MSG_LISTPROP
;
130 err
= send_prop_msg(&msg
, propfn
, cookie
);
138 static int property_get_socket(const char *key
, char *value
, const char *default_value
)
143 memset(&msg
, 0, sizeof(msg
));
144 msg
.cmd
= PROP_MSG_GETPROP
;
147 strncpy(msg
.name
, key
, sizeof(msg
.name
));
148 err
= send_prop_msg(&msg
, NULL
, NULL
);
153 /* In case it's null, just use the default */
154 if ((strlen(msg
.value
) == 0) && (default_value
)) {
155 if (strlen(default_value
) >= PROP_VALUE_MAX
-1) return -1;
156 strcpy(msg
.value
, default_value
);
159 strcpy(value
, msg
.value
);
164 int property_get(const char *key
, char *value
, const char *default_value
)
168 if ((key
) && (strlen(key
) >= PROP_NAME_MAX
-1)) return -1;
169 if (value
== NULL
) return -1;
171 if (property_get_socket(key
, value
, default_value
) == 0)
172 return strlen(value
);
174 /* In case the socket is not available, search the property file cache by hand */
175 ret
= hybris_propcache_find(key
);
180 return strlen(value
);
181 } else if (default_value
!= NULL
) {
182 strcpy(value
, default_value
);
183 return strlen(value
);
191 int property_set(const char *key
, const char *value
)
196 if (key
== 0) return -1;
197 if (value
== 0) value
= "";
198 if (strlen(key
) >= PROP_NAME_MAX
-1) return -1;
199 if (strlen(value
) >= PROP_VALUE_MAX
-1) return -1;
201 memset(&msg
, 0, sizeof(msg
));
202 msg
.cmd
= PROP_MSG_SETPROP
;
203 strncpy(msg
.name
, key
, sizeof(msg
.name
));
204 strncpy(msg
.value
, value
, sizeof(msg
.value
));
206 err
= send_prop_msg(&msg
, NULL
, NULL
);
214 // vim:ts=4:sw=4:noexpandtab