Separate source files, clean up repository
[platform/core/appfw/pkgmgr-info.git] / src / pkgmgrinfo_client.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <dlfcn.h>
4
5 #include <dbus/dbus.h>
6 #include <dbus/dbus-glib-lowlevel.h>
7
8 #include "pkgmgrinfo_type.h"
9 #include "pkgmgrinfo_debug.h"
10 #include "pkgmgrinfo_private.h"
11
12 API pkgmgrinfo_client *pkgmgrinfo_client_new(pkgmgrinfo_client_type ctype)
13 {
14         char *errmsg;
15         void *pc = NULL;
16         void *handle;
17         pkgmgrinfo_client *(*__pkgmgr_client_new)(pkgmgrinfo_client_type ctype) = NULL;
18
19         handle = dlopen("libpkgmgr-client.so.0", RTLD_LAZY | RTLD_GLOBAL);
20         retvm_if(!handle, NULL, "dlopen() failed. [%s]", dlerror());
21
22         __pkgmgr_client_new = dlsym(handle, "pkgmgr_client_new");
23         errmsg = dlerror();
24         trym_if((errmsg != NULL) || (__pkgmgr_client_new == NULL), "dlsym() failed. [%s]", errmsg);
25
26         pc = __pkgmgr_client_new(ctype);
27         trym_if(pc == NULL, "pkgmgr_client_new failed.");
28
29 catch:
30         dlclose(handle);
31         return (pkgmgrinfo_client *) pc;
32 }
33
34 API int pkgmgrinfo_client_set_status_type(pkgmgrinfo_client *pc, int status_type)
35 {
36         int ret;
37         char *errmsg;
38         void *handle;
39         int (*__pkgmgr_client_set_status_type)(pkgmgrinfo_client *pc, int status_type) = NULL;
40
41         handle = dlopen("libpkgmgr-client.so.0", RTLD_LAZY | RTLD_GLOBAL);
42         retvm_if(!handle, PMINFO_R_ERROR, "dlopen() failed. [%s]", dlerror());
43
44         __pkgmgr_client_set_status_type = dlsym(handle, "pkgmgr_client_set_status_type");
45         errmsg = dlerror();
46         tryvm_if((errmsg != NULL) || (__pkgmgr_client_set_status_type == NULL), ret = PMINFO_R_ERROR, "dlsym() failed. [%s]", errmsg);
47
48         ret = __pkgmgr_client_set_status_type(pc, status_type);
49         tryvm_if(ret < 0, ret = PMINFO_R_ERROR, "pkgmgr_client_new failed.");
50
51 catch:
52         /*
53          * Do not close libpkgmgr-client.so.0 to avoid munmap registered callback
54          *
55          * The lib dependency chain like below
56          * amd --> pkgmgr-info -- dlopen --> libpkgmgr-client --> libpkgmgr-installer-client
57          *
58          * And there is a function in libpkgmgr-installer-client named _on_signal_handle_filter()
59          * which will registered to dbus callback in amd though in fact amd doesn't direct depends
60          * on libpkgmgr-installer-client.
61          *
62          * So when the dlcose happen, then libpkgmgr-installer-client been closed too since no one
63          * link to it then.
64          *
65          * However, when the libdbus call into the callback function, it suddenly fond that the
66          * function address is gone (unmapped), then we receive a SIGSEGV.
67          *
68          * I'm not sure why we're using dlopen/dlclose in this case, I think it's much simple and
69          * robust if we just link to the well-known lib.
70          *
71          * See https://bugs.tizen.org/jira/browse/PTREL-591
72         dlclose(handle);
73          */
74         return ret;
75 }
76
77 API int pkgmgrinfo_client_listen_status(pkgmgrinfo_client *pc, pkgmgrinfo_handler event_cb, void *data)
78 {
79         int ret = 0;
80         char *errmsg = NULL;
81         void *handle = NULL;
82         int (*__pkgmgr_client_listen_status)(pkgmgrinfo_client *pc, pkgmgrinfo_handler event_cb, void *data) = NULL;
83
84         handle = dlopen("libpkgmgr-client.so.0", RTLD_LAZY | RTLD_GLOBAL);
85         retvm_if(!handle, PMINFO_R_ERROR, "dlopen() failed. [%s]", dlerror());
86
87         __pkgmgr_client_listen_status = dlsym(handle, "pkgmgr_client_listen_status");
88         errmsg = dlerror();
89         tryvm_if((errmsg != NULL) || (__pkgmgr_client_listen_status == NULL), ret = PMINFO_R_ERROR, "dlsym() failed. [%s]", errmsg);
90
91         ret = __pkgmgr_client_listen_status(pc, event_cb, data);
92         tryvm_if(ret < 0, ret = PMINFO_R_ERROR, "pkgmgr_client_new failed.");
93
94 catch:
95         /* same as pkgmgrinfo_client_new */
96         return ret;
97 }
98
99 API int pkgmgrinfo_client_free(pkgmgrinfo_client *pc)
100 {
101         int ret = 0;
102         char *errmsg = NULL;
103         void *handle = NULL;
104         int (*__pkgmgr_client_free)(pkgmgrinfo_client *pc) = NULL;
105
106         handle = dlopen("libpkgmgr-client.so.0", RTLD_LAZY | RTLD_GLOBAL);
107         retvm_if(!handle, PMINFO_R_ERROR, "dlopen() failed. [%s]", dlerror());
108
109         __pkgmgr_client_free = dlsym(handle, "pkgmgr_client_free");
110         errmsg = dlerror();
111         tryvm_if((errmsg != NULL) || (__pkgmgr_client_free == NULL), ret = PMINFO_R_ERROR, "dlsym() failed. [%s]", errmsg);
112
113         ret = __pkgmgr_client_free(pc);
114         tryvm_if(ret < 0, ret = PMINFO_R_ERROR, "pkgmgr_client_new failed.");
115
116 catch:
117         /* same as pkgmgrinfo_client_new */
118         return ret;
119 }
120
121 static int __get_pkg_location(const char *pkgid)
122 {
123         retvm_if(pkgid == NULL, PMINFO_R_OK, "pkginfo handle is NULL");
124
125         FILE *fp = NULL;
126         char pkg_mmc_path[FILENAME_MAX] = { 0, };
127         snprintf(pkg_mmc_path, FILENAME_MAX, "%s%s", PKG_SD_PATH, pkgid);
128
129         /*check whether application is in external memory or not */
130         fp = fopen(pkg_mmc_path, "r");
131         if (fp != NULL) {
132                 fclose(fp);
133                 fp = NULL;
134                 return PMINFO_EXTERNAL_STORAGE;
135         }
136
137         return PMINFO_INTERNAL_STORAGE;
138 }
139
140 API int pkgmgrinfo_client_request_enable_external_pkg(char *pkgid)
141 {
142         DBusConnection *bus;
143         DBusMessage *message = NULL;
144         DBusMessage *reply = NULL;
145
146         retvm_if(pkgid == NULL, PMINFO_R_EINVAL, "pkgid is NULL\n");
147
148         if(__get_pkg_location(pkgid) != PMINFO_EXTERNAL_STORAGE)
149                 return PMINFO_R_OK;
150
151         bus = dbus_bus_get(DBUS_BUS_SYSTEM, NULL);
152         retvm_if(bus == NULL, PMINFO_R_EINVAL, "dbus_bus_get() failed.");
153
154         message = dbus_message_new_method_call (SERVICE_NAME, PATH_NAME, INTERFACE_NAME, METHOD_NAME);
155         trym_if(message == NULL, "dbus_message_new_method_call() failed.");
156
157         dbus_message_append_args(message, DBUS_TYPE_STRING, &pkgid, DBUS_TYPE_INVALID);
158
159         reply = dbus_connection_send_with_reply_and_block(bus, message, -1, NULL);
160         trym_if(reply == NULL, "connection_send dbus fail");
161
162 catch:
163         dbus_connection_flush(bus);
164         if (message)
165                 dbus_message_unref(message);
166         if (reply)
167                 dbus_message_unref(reply);
168
169         return PMINFO_R_OK;
170 }