Release version 0.15.20
[platform/core/appfw/launchpad.git] / src / launchpad-process-pool / src / launchpad_io_channel.c
1 /*
2  * Copyright (c) 2020 Samsung Electronics Co., Ltd All Rights Reserved
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 _GNU_SOURCE
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <glib.h>
21 #include <gio/gio.h>
22
23 #include "launchpad_io_channel.h"
24 #include "log_private.h"
25
26 #define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
27
28 struct io_channel_s {
29         GIOChannel *io;
30         guint tag;
31         bool do_close;
32         int fd;
33         io_channel_event_cb callback;
34         void *user_data;
35 };
36
37 struct io_condition_s {
38         io_condition_e io_cond;
39         GIOCondition g_io_cond;
40 };
41
42 static struct io_condition_s __cond_map[] = {
43         {
44                 .io_cond = IO_IN,
45                 .g_io_cond = G_IO_IN
46         },
47         {
48                 .io_cond = IO_OUT,
49                 .g_io_cond = G_IO_OUT
50         },
51         {
52                 .io_cond = IO_PRI,
53                 .g_io_cond = G_IO_PRI
54         },
55         {
56                 .io_cond = IO_ERR,
57                 .g_io_cond = G_IO_ERR
58         },
59         {
60                 .io_cond = IO_HUP,
61                 .g_io_cond = G_IO_HUP
62         },
63         {
64                 .io_cond = IO_NVAL,
65                 .g_io_cond = G_IO_NVAL,
66         }
67 };
68
69 static io_condition_e __convert_g_io_condition(GIOCondition cond)
70 {
71         io_condition_e condition = 0;
72         int i;
73
74         for (i = 0; i < ARRAY_SIZE(__cond_map); i++) {
75                 if (__cond_map[i].g_io_cond & cond)
76                         condition |= __cond_map[i].io_cond;
77         }
78
79         return condition;
80 }
81
82 static GIOCondition __convert_io_condition(io_condition_e cond)
83 {
84         GIOCondition condition = 0;
85         int i;
86
87         for (i = 0; i < ARRAY_SIZE(__cond_map); i++) {
88                 if (__cond_map[i].io_cond & cond)
89                         condition |= __cond_map[i].g_io_cond;
90         }
91
92         return condition;
93 }
94
95 static gboolean __io_event_cb(GIOChannel *source, GIOCondition condition,
96                 gpointer data)
97 {
98         io_channel_h channel = (io_channel_h)data;
99         io_condition_e cond = __convert_g_io_condition(condition);
100         int fd = g_io_channel_unix_get_fd(source);
101
102         if (!channel->callback(fd, cond, channel->user_data))
103                 return G_SOURCE_REMOVE;
104
105         return G_SOURCE_CONTINUE;
106 }
107
108 io_channel_h _io_channel_create(int fd, io_condition_e cond,
109                 io_channel_event_cb callback, void *user_data)
110 {
111         struct io_channel_s *channel;
112
113         if (fd < 3 || !callback) {
114                 _E("Invalid parameter");
115                 return NULL;
116         }
117
118         channel = calloc(1, sizeof(struct io_channel_s));
119         if (!channel) {
120                 _E("Out of memory");
121                 return NULL;
122         }
123
124         channel->io = g_io_channel_unix_new(fd);
125         if (!channel->io) {
126                 _E("Failed to create GIOChannel");
127                 _io_channel_destroy(channel);
128                 return NULL;
129         }
130
131         channel->tag = g_io_add_watch(channel->io, __convert_io_condition(cond),
132                         __io_event_cb, channel);
133         if (!channel->tag) {
134                 _E("Failed to add GIO watch");
135                 _io_channel_destroy(channel);
136                 return NULL;
137         }
138
139         channel->do_close = true;
140         channel->fd = fd;
141         channel->callback = callback;
142         channel->user_data = user_data;
143
144         return channel;
145 }
146
147 void _io_channel_destroy(io_channel_h channel)
148 {
149         if (!channel)
150                 return;
151
152         if (channel->tag)
153                 g_source_remove(channel->tag);
154
155         if (channel->io)
156                 g_io_channel_unref(channel->io);
157
158         if (channel->do_close && channel->fd > 0)
159                 close(channel->fd);
160
161         free(channel);
162 }
163
164 int _io_channel_set_close_on_destroy(io_channel_h channel, bool do_close)
165 {
166         if (!channel) {
167                 _E("Invalid parameter");
168                 return -EINVAL;
169         }
170
171         channel->do_close = do_close;
172
173         return 0;
174 }