4 * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
22 * @desc It's main entry point for handling proc events
23 * @see proc_cgroup_cmd_type
29 #include <sys/types.h>
30 #include <sys/socket.h>
34 #include <sys/xattr.h>
39 #include "proc-main.h"
40 #include "proc-noti.h"
41 #include "proc-process.h"
42 #include "resourced.h"
46 * @desc function receives uint
47 * negative value for error reporting
49 static inline int recv_int(int fd)
53 r = read(fd, &val, sizeof(int));
58 _E("Re-read for error(EINTR)");
61 _E("Read fail for int");
67 static inline char *recv_str(int fd)
73 r = read(fd, &len, sizeof(int));
76 _E("Re-read for error(EINTR)");
79 _E("Read fail for str length");
92 _E("size is over INT_MAX");
96 str = (char *)malloc(len + 1);
98 _E("Not enough memory");
103 r = read(fd, str, len);
105 if (errno == EINTR) {
106 _E("Re-read for error(EINTR)");
109 _E("Read fail for str");
122 * @desc This function read from fd to msg,
123 * it supports multiple argument list given from client
125 * @return 0 on success errno constants in error case
127 static int read_message(int fd, struct resourced_noti *msg)
131 msg->pid = recv_int(fd);
132 ret_value_if(msg->pid < 0, errno);
133 msg->type = recv_int(fd);
134 ret_value_if(msg->type < 0, errno);
135 msg->path = recv_str(fd);
136 msg->argc = recv_int(fd);
137 ret_value_if(msg->argc < 0, errno);
139 for (i = 0; i < msg->argc; ++i)
140 msg->argv[i] = recv_str(fd);
145 static bool _fatal_read_message_error(const int error_code)
147 return error_code == EBADF || error_code == EISDIR;
150 static inline void internal_free(char *str)
156 static inline void free_message(struct resourced_noti *msg)
160 internal_free(msg->path);
162 for (i = 0; i < msg->argc; i++)
163 internal_free(msg->argv[i]);
167 static int process_message(struct resourced_noti *msg)
169 _D("process message caller pid %d\n", msg->pid);
170 return resourced_proc_action(msg->type, msg->argc, msg->argv);
173 static void safe_write_int(int fd, int type, int *value)
175 bool sync = SYNC_OPERATION(type);
178 _D("Response is not needed");
182 ret = write(fd, value, sizeof(int));
184 ETRACE_ERRNO_MSG("Failed to response to client, %d", *value);
187 static Eina_Bool proc_noti_cb(void *data, Ecore_Fd_Handler *fd_handler)
190 struct resourced_noti *msg;
192 struct sockaddr_un client_address;
197 if (!ecore_main_fd_handler_active_get(fd_handler, ECORE_FD_READ)) {
198 _E("ecore_main_fd_handler_active_get error , return\n");
199 return ECORE_CALLBACK_CANCEL;
202 fd = ecore_main_fd_handler_fd_get(fd_handler);
204 msg = malloc(sizeof(struct resourced_noti));
206 _E("proc_noti_cb : Not enough memory");
207 return ECORE_CALLBACK_RENEW;
210 client_len = sizeof(client_address);
212 accept(fd, (struct sockaddr *)&client_address,
213 (socklen_t *)&client_len);
214 if (client_sockfd == -1) {
215 _E("socket accept error");
217 return ECORE_CALLBACK_RENEW;
220 error_code = read_message(client_sockfd, msg);
222 if (error_code && _fatal_read_message_error(error_code)) {
224 close(client_sockfd);
225 return ECORE_CALLBACK_CANCEL;
226 } else if (error_code) { /* It's not fatal */
227 _E("%s : recv error msg, %d", __func__, error_code);
228 safe_write_int(client_sockfd, msg->type, &ret);
229 goto proc_noti_renew;
232 if (msg->argc > NOTI_MAXARG) {
233 _E("%s : error argument", __func__);
234 safe_write_int(client_sockfd, msg->type, &ret);
235 goto proc_noti_renew;
238 ret = process_message(msg);
240 safe_write_int(client_sockfd, msg->type, &ret);
244 close(client_sockfd);
247 return ECORE_CALLBACK_RENEW;
250 static int proc_noti_socket_init(void)
253 struct sockaddr_un serveraddr;
255 if (access(RESOURCED_SOCKET_PATH, F_OK) == 0)
256 unlink(RESOURCED_SOCKET_PATH);
258 fd = socket(AF_UNIX, SOCK_STREAM, 0);
260 _E("%s: socket create failed\n", __func__);
264 if ((fsetxattr(fd, "security.SMACK64IPOUT", "@", 2, 0)) < 0) {
265 _E("%s: Socket SMACK labeling failed\n", __func__);
266 if (errno != EOPNOTSUPP) {
272 if ((fsetxattr(fd, "security.SMACK64IPIN", "*", 2, 0)) < 0) {
273 _E("%s: Socket SMACK labeling failed\n", __func__);
274 if (errno != EOPNOTSUPP) {
280 bzero(&serveraddr, sizeof(struct sockaddr_un));
281 serveraddr.sun_family = AF_UNIX;
282 strncpy(serveraddr.sun_path, RESOURCED_SOCKET_PATH,
283 sizeof(serveraddr.sun_path));
285 if (bind(fd, (struct sockaddr *)&serveraddr, sizeof(struct sockaddr)) <
287 _E("%s: socket bind failed\n", __func__);
292 if (chmod(RESOURCED_SOCKET_PATH, (S_IRWXU | S_IRWXG | S_IRWXO)) < 0)
293 _E("failed to change the socket permission");
295 if (listen(fd, 5) < 0) {
296 _E("%s: socket listen failed\n", __func__);
301 _D("socket create & listen ok\n");
309 fd = proc_noti_socket_init();
310 ecore_main_fd_handler_add(fd, ECORE_FD_READ, (Ecore_Fd_Cb)proc_noti_cb,