Fix build error : gettimeofday
[platform/core/connectivity/mtp-responder.git] / src / mtp_util.c
1 /*
2  * Copyright (c) 2012, 2013 Samsung Electronics Co., Ltd.
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
18 #include <unistd.h>
19 #include <sys/types.h>
20 #include <fcntl.h>
21 #include <time.h>
22 #include <pthread.h>
23 #include <tapi_common.h>
24 #include <ITapiModem.h>
25 #include <system_info.h>
26 #include <vconf.h>
27 #include <gcrypt.h>
28 #include <storage/storage.h>
29 #include <sys/stat.h>
30 #include <systemd/sd-login.h>
31 #include <sys/types.h>
32 //#include <grp.h>
33 #include <media_content_internal.h>
34 #include <pwd.h>
35 #include <poll.h>
36 #include "mtp_util.h"
37 #include "mtp_util_support.h"
38 #include "mtp_util_fs.h"
39 #include <sys/time.h>
40 /* time to wait for user session creation, in ms */
41 #define WAIT_FOR_USER_TIMEOUT 10000
42
43 static phone_state_t g_ph_status = { 0 };
44
45
46 /* LCOV_EXCL_START */
47 void _util_print_error()
48 {
49         /*In glibc-2.7, the longest error message string is 50 characters
50           ("Invalid or incomplete multibyte or wide character"). */
51         mtp_char buff[100] = {0};
52
53         strerror_r(errno, buff, sizeof(buff));
54         ERR("Error: [%d]:[%s]\n", errno, buff);
55 }
56 /* LCOV_EXCL_STOP */
57
58 mtp_int32 _util_get_battery_level(void)
59 {
60         mtp_int32 result = 0;
61         mtp_int32 battery_level = 100;
62
63         result = vconf_get_int(VCONFKEY_SYSMAN_BATTERY_CAPACITY,
64                         &battery_level);
65         if (result != 0)
66                 ERR("VCONFKEY_SYSMAN_BATTERY_CAPACITY Fail!");
67
68         return battery_level;
69 }
70
71 mtp_bool _util_get_serial(mtp_char *serial, mtp_uint32 len)
72 {
73         TapiHandle *handle = NULL;
74         mtp_char *imei_no = NULL;
75         mtp_char *serial_no = NULL;
76         mtp_uint16 i = 0;
77         char hash_value[MD5_HASH_LEN] = { 0 };
78
79         if (serial == NULL || len <= MD5_HASH_LEN * 2) {
80                 ERR("serial is null or length is less than (MD5_HASH_LEN * 2)");
81                 return FALSE;
82         }
83
84         serial_no = vconf_get_str(VCONFKEY_MTP_SERIAL_NUMBER_STR);
85         if (serial_no == NULL) {
86                 ERR("vconf_get Fail for %s\n",
87                                 VCONFKEY_MTP_SERIAL_NUMBER_STR);
88                 return FALSE;
89         }
90
91         if (strlen(serial_no) > 0) {
92                 g_strlcpy(serial, serial_no, len);
93                 g_free(serial_no);
94                 return TRUE;
95         }
96 /* LCOV_EXCL_START */
97         g_free(serial_no);
98
99         handle = tel_init(NULL);
100         if (!handle) {
101                 ERR("tel_init Fail");
102                 return FALSE;
103         }
104
105         imei_no = tel_get_misc_me_imei_sync(handle);
106         if (!imei_no) {
107                 ERR("tel_get_misc_me_imei_sync Fail");
108                 tel_deinit(handle);
109                 return FALSE;
110         }
111
112         tel_deinit(handle);
113
114         gcry_md_hash_buffer(GCRY_MD_MD5, hash_value, imei_no, strlen(imei_no));
115
116         for (i = 0; i < MD5_HASH_LEN; i++)
117                 g_snprintf(&serial[i*2], 3, "%02X", hash_value[i]);
118
119         if (vconf_set_str(VCONFKEY_MTP_SERIAL_NUMBER_STR, serial) == -1) {
120                 ERR("vconf_set Fail for %s\n",
121                                 VCONFKEY_MTP_SERIAL_NUMBER_STR);
122                 g_free(imei_no);
123                 return TRUE;
124         }
125
126         g_free(imei_no);
127         return TRUE;
128 }
129 /* LCOV_EXCL_STOP */
130
131 void _util_get_vendor_ext_desc(mtp_char *vendor_ext_desc, mtp_uint32 len)
132 {
133         mtp_int32 ret = SYSTEM_INFO_ERROR_NONE;
134         mtp_char *version = NULL;
135
136         ret_if(len == 0);
137         ret_if(vendor_ext_desc == NULL);
138
139         ret = system_info_get_platform_string(
140                 "http://tizen.org/feature/platform.version", &version);
141
142         if (ret != SYSTEM_INFO_ERROR_NONE) {
143                 ERR("system_info_get_value_string Fail : 0x%X\n", ret); //      LCOV_EXCL_LINE
144                 g_strlcpy(vendor_ext_desc, MTP_VENDOR_EXTENSIONDESC_CHAR, len); //      LCOV_EXCL_LINE
145                 return; //      LCOV_EXCL_LINE
146         }
147         g_snprintf(vendor_ext_desc, len, "%stizen.org:%s; ",
148                         MTP_VENDOR_EXTENSIONDESC_CHAR, version);
149         g_free(version);
150         return;
151 }
152
153 void _util_get_model_name(mtp_char *model_name, mtp_uint32 len)
154 {
155         mtp_int32 ret = SYSTEM_INFO_ERROR_NONE;
156         mtp_char *model = NULL;
157
158         ret_if(len == 0);
159         ret_if(model_name == NULL);
160
161         ret = system_info_get_platform_string(
162                 "http://tizen.org/system/model_name", &model);
163
164         if (ret != SYSTEM_INFO_ERROR_NONE) {
165                 ERR("system_info_get_value_string Fail : 0x%X\n", ret); //      LCOV_EXCL_LINE
166                 g_strlcpy(model_name, MTP_DEFAULT_MODEL_NAME, len);     //      LCOV_EXCL_LINE
167                 return; //      LCOV_EXCL_LINE
168         }
169         g_strlcpy(model_name, model, len);
170         g_free(model);
171         return;
172 }
173
174 void _util_get_device_version(mtp_char *device_version, mtp_uint32 len)
175 {
176         mtp_int32 ret = SYSTEM_INFO_ERROR_NONE;
177         mtp_char *version = NULL;
178         mtp_char *build_info = NULL;
179
180         ret_if(len == 0);
181         ret_if(device_version == NULL);
182
183         ret = system_info_get_platform_string(
184                 "http://tizen.org/feature/platform.version", &version);
185
186         if (ret != SYSTEM_INFO_ERROR_NONE) {
187                 ERR("system_info_get_value_string Fail : 0x%X\n", ret); //      LCOV_EXCL_LINE
188                 g_strlcpy(device_version, MTP_DEFAULT_DEVICE_VERSION, len);     //      LCOV_EXCL_LINE
189                 return; //      LCOV_EXCL_LINE
190         }
191
192         ret = system_info_get_platform_string(
193                 "http://tizen.org/system/build.string", &build_info);
194
195         if (ret != SYSTEM_INFO_ERROR_NONE) {
196                 ERR("system_info_get_value_string Fail : 0x%X\n", ret); //      LCOV_EXCL_LINE
197                 g_strlcpy(device_version, MTP_DEFAULT_DEVICE_VERSION, len);     //      LCOV_EXCL_LINE
198                 g_free(version);        //      LCOV_EXCL_LINE
199                 return;
200         }
201         g_snprintf(device_version, len, "TIZEN %s (%s)", version, build_info);
202         g_free(version);
203         g_free(build_info);
204         return;
205 }
206
207 /* LCOV_EXCL_START */
208 void _util_gen_alt_serial(mtp_char *serial, mtp_uint32 len)
209 {
210         struct timeval st;
211         mtp_char model_name[MTP_MODEL_NAME_LEN_MAX + 1] = { 0 };
212
213         ret_if(len == 0);
214         ret_if(serial == NULL);
215
216         if (gettimeofday(&st, NULL) < 0) {
217                 ERR("gettimeofday Fail");
218                 _util_print_error();
219                 return;
220         }
221         _util_get_model_name(model_name, sizeof(model_name));
222         g_snprintf(serial, len, "%s-%010ld-%011ld", model_name,
223                         st.tv_sec, st.tv_usec);
224
225         if (vconf_set_str(VCONFKEY_MTP_SERIAL_NUMBER_STR, serial) == -1)
226                 ERR("vconf_set Fail %s\n", VCONFKEY_MTP_SERIAL_NUMBER_STR);
227
228         return;
229 }
230
231 void _util_get_usb_status(phone_status_t *val)
232 {
233         mtp_int32 ret = 0;
234         mtp_int32 state = 0;
235
236         ret = vconf_get_int(VCONFKEY_SYSMAN_USB_STATUS, &state);
237         if (ret == -1 || state == VCONFKEY_SYSMAN_USB_DISCONNECTED) {
238                 *val = MTP_PHONE_USB_DISCONNECTED;
239                 return;
240         }
241
242         *val = MTP_PHONE_USB_CONNECTED;
243         return;
244 }
245
246 phone_status_t _util_get_local_usb_status(void)
247 {
248         return g_ph_status.usb_state;
249 }
250
251 void _util_set_local_usb_status(const phone_status_t val)
252 {
253         g_ph_status.usb_state = val;
254         return;
255 }
256
257 void _util_get_mmc_status(phone_status_t *val)
258 {
259         mtp_int32 ret = 0;
260         mtp_int32 state = 0;
261
262         ret = vconf_get_int(VCONFKEY_SYSMAN_MMC_STATUS, &state);
263         if (ret == -1 || state !=
264                         VCONFKEY_SYSMAN_MMC_MOUNTED) {
265                 *val = MTP_PHONE_MMC_NONE;
266                 return;
267         }
268
269         *val = MTP_PHONE_MMC_INSERTED;
270         return;
271 }
272 /* LCOV_EXCL_STOP */
273
274 phone_status_t _util_get_local_mmc_status(void)
275 {
276         return g_ph_status.mmc_state;
277 }
278
279 /* LCOV_EXCL_START */
280 void _util_set_local_mmc_status(const phone_status_t val)
281 {
282         g_ph_status.mmc_state = val;
283         return;
284 }
285
286 void _util_get_usbmode_status(phone_status_t *val)
287 {
288         mtp_int32 ret = 0;
289         mtp_int32 state = 0;
290
291         ret = vconf_get_int(VCONFKEY_USB_CUR_MODE,
292                         &state);
293         if (ret < 0) {
294                 *val = MTP_PHONE_USB_MODE_OTHER;
295                 return;
296         }
297
298         if (state == SET_USB_NONE)
299                 *val = MTP_PHONE_USB_DISCONNECTED;
300         else
301                 *val = MTP_PHONE_USB_CONNECTED;
302         return;
303 }
304
305 phone_status_t _util_get_local_usbmode_status(void)
306 {
307         return g_ph_status.usb_mode_state;
308 }
309
310 void _util_set_local_usbmode_status(const phone_status_t val)
311 {
312         g_ph_status.usb_mode_state = val;
313         return;
314 }
315
316 void _util_get_lock_status(phone_status_t *val)
317 {
318         mtp_int32 state = 0;
319
320         vconf_get_int(VCONFKEY_IDLE_LOCK_STATE_READ_ONLY,
321                         &state);
322
323         if (state)
324                 *val = MTP_PHONE_LOCK_ON;
325         else
326                 *val = MTP_PHONE_LOCK_OFF;
327         return;
328 }
329 /* LCOV_EXCL_STOP */
330
331 phone_status_t _util_get_local_lock_status(void)
332 {
333         return g_ph_status.lock_state;
334 }
335
336 /* LCOV_EXCL_START */
337 void _util_set_local_lock_status(const phone_status_t val)
338 {
339         g_ph_status.lock_state = val;
340         return;
341 }
342
343 static bool _util_device_external_supported_cb(int storage_id, storage_type_e type,
344         storage_state_e state, const char *path, void *user_data)
345 {
346         char *storage_path = (char *)user_data;
347
348         //DBG("storage id: %d, path: %s", storage_id, path);
349
350         if (type == STORAGE_TYPE_EXTERNAL && path != NULL) {
351                 strncpy(storage_path, path, MTP_MAX_PATHNAME_SIZE);
352                 storage_path[MTP_MAX_PATHNAME_SIZE] = 0;
353                 //DBG("external storage path : %s", storage_path);
354         }
355
356         return TRUE;
357 }
358 /* LCOV_EXCL_STOP */
359
360 void _util_get_external_path(char *external_path)
361 {
362         int error = STORAGE_ERROR_NONE;
363
364         error = storage_foreach_device_supported(_util_device_external_supported_cb, external_path);
365
366         if (error != STORAGE_ERROR_NONE) {
367 /* LCOV_EXCL_START */
368                 ERR("get external storage path Fail");
369                 if (external_path != NULL) {
370                         strncpy(external_path, MTP_EXTERNAL_PATH_CHAR, MTP_MAX_PATHNAME_SIZE);
371                         external_path[sizeof(MTP_EXTERNAL_PATH_CHAR) - 1] = 0;
372                 }
373         }
374 }
375
376 int _util_wait_for_user()
377 {
378         __attribute__((cleanup(sd_login_monitor_unrefp))) sd_login_monitor *monitor = NULL;
379         int ret;
380         struct pollfd fds;
381
382         ret = sd_login_monitor_new("uid", &monitor);
383         if (ret < 0) {
384                 char buf[256] = {0,};
385                 strerror_r(-ret, buf, sizeof(buf));
386                 ERR("Failed to allocate login monitor object: [%d]:[%s]", ret, buf);
387                 return ret;
388         }
389
390         fds.fd = sd_login_monitor_get_fd(monitor);
391         fds.events = sd_login_monitor_get_events(monitor);
392
393         ret = poll(&fds, 1, WAIT_FOR_USER_TIMEOUT);
394         if (ret < 0) {
395                 ERR("Error polling: %m");
396                 return -1;
397         }
398
399         return 0;
400 }
401 /* LCOV_EXCL_STOP */
402
403 uid_t _util_get_active_user()
404 {
405         uid_t *active_user_list = NULL;
406         uid_t active_user = 0;
407         int user_cnt = 0;
408         int ret;
409
410         user_cnt = sd_get_uids(&active_user_list);
411         if (user_cnt <= 0) {
412                 /* LCOV_EXCL_START */
413                 ret = _util_wait_for_user();
414                 if (ret < 0)
415                         return -1;
416
417                 user_cnt = sd_get_uids(&active_user_list);
418                 /* LCOV_EXCL_STOP */
419         }
420
421         if (user_cnt <= 0) {
422                 /* LCOV_EXCL_START */
423                 ERR("Active user not exists : %d", user_cnt);
424
425                 if (active_user_list != NULL)
426                         free(active_user_list);
427
428                 return -1;
429                 /* LCOV_EXCL_STOP */
430         }
431
432         if (active_user_list == NULL) {
433                 ERR("active_user_list is NULL");
434                 return -1;
435         }
436
437         active_user = active_user_list[0];
438
439         DBG("Active UID : %d", active_user);
440
441         free(active_user_list);
442
443         if (active_user <= 0) {
444                 ERR("UID is not proper value : %d", active_user);
445                 return -1;
446         }
447
448         return active_user;
449 }
450
451 void _util_get_internal_path(char *internal_path)
452 {
453         struct passwd *pwd;
454         uid_t active_user = 0;
455         char *active_name = NULL;
456
457         active_user = _util_get_active_user();
458         pwd = getpwuid(active_user);
459         active_name = pwd->pw_name;
460
461         if (active_name == NULL) {
462                 /* LCOV_EXCL_START */
463                 ERR("active_name is NULL");
464                 strncpy(internal_path, MTP_USER_DIRECTORY, MTP_MAX_PATHNAME_SIZE);
465                 internal_path[sizeof(MTP_USER_DIRECTORY) - 1] = 0;
466                 return;
467                 /* LCOV_EXCL_STOP */
468         }
469
470         if (internal_path != NULL) {
471                 strncpy(internal_path, MTP_INTERNAL_PATH_CHAR, MTP_MAX_PATHNAME_SIZE);
472                 strncat(internal_path, active_name, MTP_MAX_PATHNAME_SIZE - sizeof(MTP_INTERNAL_PATH_CHAR));
473                 strncat(internal_path, "/media", 7);
474                 internal_path[strlen(internal_path)] = 0;
475         }
476
477         ERR("internal path is %s", internal_path);
478 }
479
480 /* LCOV_EXCL_START */
481 mtp_bool _util_media_content_connect()
482 {
483         mtp_int32 ret = 0;
484         uid_t active_user = 0;
485
486         active_user = _util_get_active_user();
487
488         ret = media_content_connect_with_uid(active_user);
489         if (ret != MEDIA_CONTENT_ERROR_NONE) {
490                 ERR("media_content_connect() failed : %d", ret);
491                 return FALSE;
492         }
493
494         return TRUE;
495 }
496
497 void _util_media_content_disconnect()
498 {
499         media_content_disconnect();
500 }
501 /* LCOV_EXCL_STOP */