13c5ca93a7ea4ab35473d055d7806d7fa5b8dbfe
[apps/livebox/data-provider-master.git] / src / util.c
1 /*
2  * Copyright 2012  Samsung Electronics Co., Ltd
3  *
4  * Licensed under the Flora License, Version 1.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.tizenopensource.org/license
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 #include <stdio.h>
18 #include <sys/time.h>
19 #include <string.h>
20 #include <errno.h>
21 #include <unistd.h>
22 #include <stdlib.h>
23 #include <sys/statvfs.h>
24 #include <sys/types.h>
25 #include <dirent.h>
26
27 #include <dlog.h>
28 #include <Eina.h>
29 #include <Ecore.h>
30
31 #include "util.h"
32 #include "debug.h"
33 #include "conf.h"
34
35 int errno;
36
37 HAPI unsigned long util_string_hash(const char *str)
38 {
39         unsigned long ret = 0;
40
41         while (*str)
42                 ret += (unsigned long)(*str++);
43
44         ret %= 371773;
45         return ret;
46 }
47
48 HAPI double util_timestamp(void)
49 {
50         struct timeval tv;
51
52         if (gettimeofday(&tv, NULL) < 0) {
53                 static unsigned long internal_count = 0;
54                 ErrPrint("failed to get time of day: %s\n", strerror(errno));
55                 tv.tv_sec = internal_count++;
56                 tv.tv_usec = 0;
57         }
58
59         return (double)tv.tv_sec + (double)tv.tv_usec / 1000000.0f;
60 }
61
62 HAPI int util_check_ext(const char *filename, const char *check_ptr)
63 {
64         int name_len;
65
66         name_len = strlen(filename);
67         while (--name_len >= 0 && *check_ptr) {
68                 if (filename[name_len] != *check_ptr)
69                         return -EINVAL;
70
71                 check_ptr ++;
72         }
73
74         return 0;
75 }
76
77 static inline int check_native_livebox(const char *pkgname)
78 {
79         int len;
80         char *path;
81
82         len = strlen(pkgname) * 2;
83         len += strlen(ROOT_PATH);
84         len += strlen("%s/libexec/liblive-%s.so");
85
86         path = malloc(len + 1);
87         if (!path) {
88                 ErrPrint("Heap: %s\n", strerror(errno));
89                 return -ENOMEM;
90         }
91
92         snprintf(path, len, "%s%s/libexec/liblive-%s.so", ROOT_PATH, pkgname, pkgname);
93         if (access(path, F_OK | R_OK) != 0) {
94                 ErrPrint("%s is not a valid package\n", pkgname);
95                 DbgFree(path);
96                 return -EINVAL;
97         }
98
99         DbgFree(path);
100         return 0;
101 }
102
103 static inline int check_web_livebox(const char *pkgname)
104 {
105         int len;
106         char *path;
107
108         len = strlen(pkgname) * 2;
109         len += strlen("/opt/usr/apps/%s/res/wgt/livebox/index.html");
110
111         path = malloc(len + 1);
112         if (!path) {
113                 ErrPrint("Heap: %s\n", strerror(errno));
114                 return -ENOMEM;
115         }
116
117         snprintf(path, len, "/opt/usr/apps/%s/res/wgt/livebox/index.html", pkgname);
118         if (access(path, F_OK | R_OK) != 0) {
119                 ErrPrint("%s is not a valid package\n", pkgname);
120                 DbgFree(path);
121                 return -EINVAL;
122         }
123
124         DbgFree(path);
125         return 0;
126 }
127
128 HAPI int util_validate_livebox_package(const char *pkgname)
129 {
130         if (!pkgname) {
131                 ErrPrint("Invalid argument\n");
132                 return -EINVAL;
133         }
134
135         if (!check_native_livebox(pkgname) || !check_web_livebox(pkgname))
136                 return 0;
137
138         return -EINVAL;
139 }
140
141 HAPI int util_unlink(const char *filename)
142 {
143         char *descfile;
144         int desclen;
145         int ret;
146
147         desclen = strlen(filename) + 6; /* .desc */
148         descfile = malloc(desclen);
149         if (!descfile) {
150                 ErrPrint("Heap: %s\n", strerror(errno));
151                 return -ENOMEM;
152         }
153
154         ret = snprintf(descfile, desclen, "%s.desc", filename);
155         if (ret < 0) {
156                 ErrPrint("Error: %s\n", strerror(errno));
157                 DbgFree(descfile);
158                 return -EFAULT;
159         }
160
161         (void)unlink(descfile);
162         DbgFree(descfile);
163         (void)unlink(filename);
164
165         return 0;
166 }
167
168 HAPI char *util_slavename(void)
169 {
170         char slavename[BUFSIZ];
171         static unsigned long idx = 0;
172
173         snprintf(slavename, sizeof(slavename), "%lu_%lf", idx++, util_timestamp());
174         return strdup(slavename);
175 }
176
177 HAPI const char *util_basename(const char *name)
178 {
179         int length;
180         length = name ? strlen(name) : 0;
181         if (!length)
182                 return ".";
183
184         while (--length > 0 && name[length] != '/');
185
186         return length <= 0 ? name : (name + length + (name[length] == '/'));
187 }
188
189 HAPI unsigned long util_free_space(const char *path)
190 {
191         struct statvfs st;
192         unsigned long space;
193
194         if (statvfs(path, &st) < 0) {
195                 ErrPrint("statvfs: %s\n", strerror(errno));
196                 return 0lu;
197         }
198
199         space = st.f_bsize * st.f_bfree;
200         /*!
201          * \note
202          * Must have to check the overflow
203          */
204         return space;
205 }
206
207 static inline char *extend_heap(char *buffer, int *sz, int incsz)
208 {
209         char *tmp;
210
211         *sz += incsz;
212         tmp = realloc(buffer, *sz);
213         if (!tmp) {
214                 ErrPrint("Heap: %s\n", strerror(errno));
215                 return NULL;
216         }
217
218         return tmp;
219 }
220
221 HAPI char *util_replace_string(const char *src, const char *pattern, const char *replace)
222 {
223         char *ret;
224         int src_idx;
225         int pattern_idx;
226         int src_rollback_idx;
227         int ret_rollback_idx;
228         int ret_idx;
229         int target_idx;
230         int bufsz;
231         int incsz;
232         int matched;
233
234         bufsz = strlen(src);
235         incsz = bufsz;
236         ret = malloc(bufsz + 1);
237         if (!ret) {
238                 ErrPrint("Heap: %s\n", strerror(errno));
239                 return NULL;
240         }
241
242         pattern_idx = 0;
243         ret_idx = 0;
244         matched = 0;
245         for (src_idx = 0; src[src_idx]; src_idx++) {
246                 if (!pattern[pattern_idx]) {
247                         while (replace[target_idx]) {
248                                 ret[ret_idx] = replace[target_idx];
249                                 ret_idx++;
250                                 target_idx++;
251
252                                 if (ret_idx >= bufsz) {
253                                         char *tmp;
254
255                                         tmp = extend_heap(ret, &bufsz, incsz);
256                                         if (!tmp) {
257                                                 ErrPrint("Heap: %s\n", strerror(errno));
258                                                 DbgFree(ret);
259                                                 return NULL;
260                                         }
261                                         ret = tmp;
262                                 }
263                         }
264
265                         pattern_idx = 0;
266                         src--;
267                         matched++;
268                         continue;
269                 } else if (src[src_idx] == pattern[pattern_idx]) {
270                         if (pattern_idx == 0) {
271                                 src_rollback_idx = src_idx;
272                                 ret_rollback_idx = ret_idx;
273                                 target_idx = 0;
274                         }
275
276                         if (replace[target_idx]) {
277                                 ret[ret_idx] = replace[target_idx];
278                                 ret_idx++;
279                                 target_idx++;
280                                 if (ret_idx >= bufsz) {
281                                         char *tmp;
282
283                                         tmp = extend_heap(ret, &bufsz, incsz);
284                                         if (!tmp) {
285                                                 ErrPrint("Heap: %s\n", strerror(errno));
286                                                 DbgFree(ret);
287                                                 return NULL;
288                                         }
289                                         ret = tmp;
290                                 }
291                         }
292
293                         pattern_idx++;
294                         continue;
295                 } else if (pattern_idx > 0) {
296                         src_idx = src_rollback_idx;
297                         ret_idx = ret_rollback_idx;
298                         pattern_idx = 0;
299                 }
300
301                 ret[ret_idx] = src[src_idx];
302                 ret_idx++;
303                 if (ret_idx >= bufsz) {
304                         char *tmp;
305
306                         tmp = extend_heap(ret, &bufsz, incsz);
307                         if (!tmp) {
308                                 ErrPrint("Heap: %s\n", strerror(errno));
309                                 DbgFree(ret);
310                                 return NULL;
311                         }
312                         ret = tmp;
313                 }
314         }
315         if (matched) {
316                 ret[ret_idx] = '\0';
317         } else {
318                 DbgFree(ret);
319                 ret = NULL;
320         }
321         return ret;
322 }
323
324 HAPI const char *util_uri_to_path(const char *uri)
325 {
326         int len;
327
328         len = strlen(SCHEMA_FILE);
329         if (strncasecmp(uri, SCHEMA_FILE, len))
330                 return NULL;
331
332         return uri + len;
333 }
334
335 static inline void compensate_timer(Ecore_Timer *timer)
336 {
337         struct timeval tv;
338         struct timeval compensator;
339         double delay;
340         double pending;
341
342         if (ecore_timer_interval_get(timer) <= 1.0f) {
343                 DbgPrint("Doesn't need to sync the timer to start from ZERO sec\n");
344                 return;
345         }
346
347         if (gettimeofday(&tv, NULL) < 0) {
348                 ErrPrint("Error: %s\n", strerror(errno));
349                 return;
350         }
351
352         compensator.tv_sec = tv.tv_sec % 60;
353         if (compensator.tv_sec == 0)
354                 compensator.tv_sec = 59;
355
356         delay = 60.0f - ((double)compensator.tv_sec + ((double)tv.tv_usec / 1000000.0f));
357         pending = ecore_timer_pending_get(timer);
358         ecore_timer_delay(timer, delay - pending);
359         DbgPrint("COMPENSATED: %lf\n", delay);
360 }
361
362 HAPI void *util_timer_add(double interval, Eina_Bool (*cb)(void *data), void *data)
363 {
364         Ecore_Timer *timer;
365
366         timer = ecore_timer_add(interval, cb, data);
367         if (!timer)
368                 return NULL;
369
370         compensate_timer(timer);
371         return timer;
372 }
373
374 HAPI void util_timer_interval_set(void *timer, double interval)
375 {
376         ecore_timer_interval_set(timer, interval);
377         compensate_timer(timer);
378 }
379
380 HAPI char *util_get_file_kept_in_safe(const char *id)
381 {
382         const char *path;
383         char *new_path;
384         int len;
385         int base_idx;
386
387         path = util_uri_to_path(id);
388         if (!path) {
389                 ErrPrint("Invalid URI(%s)\n", id);
390                 return NULL;
391         }
392
393         /*!
394          * TODO: Remove me
395          */
396         if (OVERWRITE_CONTENT)
397                 return strdup(path);
398
399         len = strlen(path);
400         base_idx = len - 1;
401
402         while (base_idx > 0 && path[base_idx] != '/') base_idx--;
403         base_idx += (path[base_idx] == '/');
404
405         new_path = malloc(len + 10);
406         if (!new_path) {
407                 ErrPrint("Heap: %s\n", strerror(errno));
408                 return NULL;
409         }
410
411         strncpy(new_path, path, base_idx);
412         snprintf(new_path + base_idx, len + 10 - base_idx, "reader/%s", path + base_idx);
413         return new_path;
414 }
415
416 HAPI int util_unlink_files(const char *folder)
417 {
418         struct stat info;
419         DIR *handle;
420         struct dirent *entry;
421         char *abspath;
422         int len;
423
424         if (lstat(folder, &info) < 0) {
425                 ErrPrint("Error: %s\n", strerror(errno));
426                 return -EIO;
427         }
428
429         if (!S_ISDIR(info.st_mode)) {
430                 ErrPrint("Error: %s is not a folder", folder);
431                 return -EINVAL;
432         }
433
434         handle = opendir(folder);
435         if (!handle) {
436                 ErrPrint("Error: %s\n", strerror(errno));
437                 return -EIO;
438         }
439
440         while ((entry = readdir(handle))) {
441                 if (!strcmp(entry->d_name, "."))
442                         continue;
443
444                 if (!strcmp(entry->d_name, ".."))
445                         continue;
446
447                 len = strlen(folder) + strlen(entry->d_name) + 3;
448                 abspath = calloc(1, len);
449                 if (!abspath) {
450                         ErrPrint("Heap: %s\n", strerror(errno));
451                         continue;
452                 }
453                 snprintf(abspath, len - 1, "%s/%s", folder, entry->d_name);
454
455                 if (unlink(abspath) < 0)
456                         DbgPrint("unlink: %s - %s\n", abspath, strerror(errno));
457
458                 free(abspath);
459         }
460
461         closedir(handle);
462         return 0;
463 }
464
465 /* End of a file */