aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/libraries/ecore/src/lib/ecore_file/ecore_file.c
diff options
context:
space:
mode:
Diffstat (limited to 'libraries/ecore/src/lib/ecore_file/ecore_file.c')
-rw-r--r--libraries/ecore/src/lib/ecore_file/ecore_file.c1110
1 files changed, 1110 insertions, 0 deletions
diff --git a/libraries/ecore/src/lib/ecore_file/ecore_file.c b/libraries/ecore/src/lib/ecore_file/ecore_file.c
new file mode 100644
index 0000000..2546f2f
--- /dev/null
+++ b/libraries/ecore/src/lib/ecore_file/ecore_file.c
@@ -0,0 +1,1110 @@
1#ifdef HAVE_CONFIG_H
2# include <config.h>
3#endif
4
5#include <stdio.h>
6#include <string.h>
7
8#ifndef _MSC_VER
9# include <unistd.h>
10# include <libgen.h>
11#endif
12
13#ifdef _WIN32
14# include <direct.h>
15#endif
16
17#ifdef HAVE_FEATURES_H
18# include <features.h>
19#endif
20#include <ctype.h>
21#include <errno.h>
22
23#ifdef HAVE_ATFILE_SOURCE
24# include <dirent.h>
25#endif
26
27#include "ecore_file_private.h"
28
29int _ecore_file_log_dom = -1;
30static int _ecore_file_init_count = 0;
31
32/* externally accessible functions */
33
34/**
35 * @addtogroup Ecore_File_Group Ecore_File - Files and directories convenience functions
36 *
37 * @{
38 */
39
40/**
41 * @brief Initialize the Ecore_File library.
42 *
43 * @return 1 or greater on success, 0 on error.
44 *
45 * This function sets up Ecore_File and the services it will use
46 * (monitoring, downloading, PATH related feature). It returns 0 on
47 * failure, otherwise it returns the number of times it has already
48 * been called.
49 *
50 * When Ecore_File is not used anymore, call ecore_file_shutdown()
51 * to shut down the Ecore_File library.
52 */
53EAPI int
54ecore_file_init()
55{
56 if (++_ecore_file_init_count != 1)
57 return _ecore_file_init_count;
58
59 if (!ecore_init())
60 return --_ecore_file_init_count;
61
62 _ecore_file_log_dom = eina_log_domain_register
63 ("ecore_file", ECORE_FILE_DEFAULT_LOG_COLOR);
64 if(_ecore_file_log_dom < 0)
65 {
66 EINA_LOG_ERR("Impossible to create a log domain for the ecore file module.");
67 return --_ecore_file_init_count;
68 }
69 ecore_file_path_init();
70 ecore_file_monitor_init();
71 ecore_file_download_init();
72
73 /* FIXME: were the tests disabled for a good reason ? */
74
75 /*
76 if (!ecore_file_monitor_init())
77 goto shutdown_ecore_file_path;
78
79 if (!ecore_file_download_init())
80 goto shutdown_ecore_file_monitor;
81 */
82
83 return _ecore_file_init_count;
84
85 /*
86 shutdown_ecore_file_monitor:
87 ecore_file_monitor_shutdown();
88 shutdown_ecore_file_path:
89 ecore_file_path_shutdown();
90
91 return --_ecore_file_init_count;
92 */
93}
94
95/**
96 * @brief Shut down the Ecore_File library.
97 *
98 * @return 0 when the library is completely shut down, 1 or
99 * greater otherwise.
100 *
101 * This function shuts down the Ecore_File library. It returns 0 when it has
102 * been called the same number of times than ecore_file_init(). In that case
103 * it shuts down all the services it uses.
104 */
105EAPI int
106ecore_file_shutdown()
107{
108 if (--_ecore_file_init_count != 0)
109 return _ecore_file_init_count;
110
111 ecore_file_download_shutdown();
112 ecore_file_monitor_shutdown();
113 ecore_file_path_shutdown();
114
115 eina_log_domain_unregister(_ecore_file_log_dom);
116 _ecore_file_log_dom = -1;
117
118 ecore_shutdown();
119
120 return _ecore_file_init_count;
121}
122
123/**
124 * @brief Get the time of the last modification to the given file.
125 *
126 * @param file The name of the file.
127 * @return Return the time of the last data modification, or 0 on
128 * failure.
129 *
130 * This function returns the time of the last modification of
131 * @p file. On failure, it returns 0.
132 */
133EAPI long long
134ecore_file_mod_time(const char *file)
135{
136 struct stat st;
137
138 if (stat(file, &st) < 0) return 0;
139 return st.st_mtime;
140}
141
142/**
143 * @brief Get the size of the given file.
144 *
145 * @param file The name of the file.
146 * @return Return the size of the file in bytes, or 0 on failure.
147 *
148 * This function returns the size of @p file in bytes. On failure, it
149 * returns 0.
150 */
151EAPI long long
152ecore_file_size(const char *file)
153{
154 struct stat st;
155
156 if (stat(file, &st) < 0) return 0;
157 return st.st_size;
158}
159
160/**
161 * @brief Check if the given file exists.
162 *
163 * @param file The name of the file.
164 * @return Return EINA_TRUE if the file exists, EINA_FALSE otherwise.
165 *
166 * This function returns EINA_TRUE if @p file exists on local filesystem,
167 * EINA_FALSE otherwise.
168 */
169EAPI Eina_Bool
170ecore_file_exists(const char *file)
171{
172 struct stat st;
173 if (!file) return EINA_FALSE;
174
175 /*Workaround so that "/" returns a true, otherwise we can't monitor "/" in ecore_file_monitor*/
176 if (stat(file, &st) < 0 && strcmp(file, "/")) return EINA_FALSE;
177 return EINA_TRUE;
178}
179
180/**
181 * @brief Check if the given file is a directory.
182 *
183 * @param file The name of the file.
184 * @return Return EINA_TRUE if the file exists and is a directory,
185 * EINA_FALSE otherwise.
186 *
187 * This function returns EINA_TRUE if @p file exists exists and is a
188 * directory on local filesystem, EINA_FALSE otherwise.
189 */
190EAPI Eina_Bool
191ecore_file_is_dir(const char *file)
192{
193 struct stat st;
194
195 if (stat(file, &st) < 0) return EINA_FALSE;
196 if (S_ISDIR(st.st_mode)) return EINA_TRUE;
197 return EINA_FALSE;
198}
199
200static mode_t default_mode = S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
201
202/**
203 * @brief Create a new directory.
204 *
205 * @param dir The name of the directory to create
206 * @return EINA_TRUE on successful creation, EINA_FALSE otherwise.
207 *
208 * This function creates the directory @p dir with the mode S_IRUSR |
209 * S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH. On
210 * success, it returns EINA_TRUE, EINA_FALSE otherwise.
211 */
212EAPI Eina_Bool
213ecore_file_mkdir(const char *dir)
214{
215 if (mkdir(dir, default_mode) < 0) return EINA_FALSE;
216 return EINA_TRUE;
217}
218
219/**
220 * @brief Create complete directory in a batch.
221 *
222 * @param dirs The list of directories, null terminated.
223 * @return The number of successful directories created, -1 if dirs is
224 * @c NULL.
225 *
226 * This function creates all the directories that are in the null
227 * terminated array @p dirs. The function loops over the directories
228 * and call ecore_file_mkdir(). This function returns -1 if @p dirs is
229 * @c NULL, otherwise if returns the number of suceesfully created
230 * directories.
231 */
232EAPI int
233ecore_file_mkdirs(const char **dirs)
234{
235 int i = 0;
236
237 if (!dirs) return -1;
238
239 for (; *dirs; dirs++)
240 if (ecore_file_mkdir(*dirs))
241 i++;
242 return i;
243}
244
245/**
246 * @brief Create complete list of sub-directories in a batch (optimized).
247 *
248 * @param base The base directory to act on.
249 * @param subdirs The list of directories, null terminated.
250 * @return number of successful directories created, -1 on failure.
251 *
252 * This function creates all the directories that are in the null
253 * terminated array @p dirs in the @p base directory. If @p base does
254 * not exist, it will be created. The function loops over the directories
255 * and call ecore_file_mkdir(). The whole path of the directories must
256 * exist. So if base/a/b/c wants to be created, @p subdirs must
257 * contain "a", "a/b" and "a/b/c", in that order. This function
258 * returns -1 if @p dirs or @p base are @c NULL, or if @p base is
259 * empty ("\0"). It returns 0 is @p base is not a directory or
260 * invalid, or if it can't be created. Otherwise if returns the number
261 * of suceesfully created directories.
262 */
263EAPI int
264ecore_file_mksubdirs(const char *base, const char **subdirs)
265{
266#ifndef HAVE_ATFILE_SOURCE
267 char buf[PATH_MAX];
268 int baselen;
269#else
270 int fd;
271 DIR *dir;
272#endif
273 int i;
274
275 if (!subdirs) return -1;
276 if ((!base) || (base[0] == '\0')) return -1;
277
278 if ((!ecore_file_is_dir(base)) && (!ecore_file_mkpath(base)))
279 return 0;
280
281#ifndef HAVE_ATFILE_SOURCE
282 baselen = eina_strlcpy(buf, base, sizeof(buf));
283 if ((baselen < 1) || (baselen + 1 >= (int)sizeof(buf)))
284 return 0;
285
286 if (buf[baselen - 1] != '/')
287 {
288 buf[baselen] = '/';
289 baselen++;
290 }
291#else
292 dir = opendir(base);
293 if (!dir)
294 return 0;
295 fd = dirfd(dir);
296#endif
297
298 i = 0;
299 for (; *subdirs; subdirs++)
300 {
301 struct stat st;
302
303#ifndef HAVE_ATFILE_SOURCE
304 eina_strlcpy(buf + baselen, *subdirs, sizeof(buf) - baselen);
305 if (stat(buf, &st) == 0)
306#else
307 if (fstatat(fd, *subdirs, &st, 0) == 0)
308#endif
309 {
310 if (S_ISDIR(st.st_mode))
311 {
312 i++;
313 continue;
314 }
315 }
316 else
317 {
318 if (errno == ENOENT)
319 {
320#ifndef HAVE_ATFILE_SOURCE
321 if (mkdir(buf, default_mode) == 0)
322#else
323 if (mkdirat(fd, *subdirs, default_mode) == 0)
324#endif
325 {
326 i++;
327 continue;
328 }
329 }
330 }
331 }
332
333#ifdef HAVE_ATFILE_SOURCE
334 closedir(dir);
335#endif
336
337 return i;
338}
339
340/**
341 * @brief Delete the given directory.
342 *
343 * @param dir The name of the directory to delete.
344 * @return EINA_TRUE on success, EINA_FALSE otherwise.
345 *
346 * This function deletes @p dir. It returns EINA_TRUE on success,
347 * EINA_FALSE otherwise.
348 */
349EAPI Eina_Bool
350ecore_file_rmdir(const char *dir)
351{
352 if (rmdir(dir) < 0) return EINA_FALSE;
353 return EINA_TRUE;
354}
355
356/**
357 * @brief Delete the given file.
358 *
359 * @param file The name of the file to delete.
360 * @return EINA_TRUE on success, EINA_FALSE otherwise.
361 *
362 * This function deletes @p file. It returns EINA_TRUE on success,
363 * EINA_FALSE otherwise.
364 */
365EAPI Eina_Bool
366ecore_file_unlink(const char *file)
367{
368 if (unlink(file) < 0) return EINA_FALSE;
369 return EINA_TRUE;
370}
371
372/**
373 * @brief Remove the given file or directory.
374 *
375 * @param file The name of the file or directory to delete.
376 * @return EINA_TRUE on success, EINA_FALSE otherwise.
377 *
378 * This function removes @p file. It returns EINA_TRUE on success,
379 * EINA_FALSE otherwise.
380 */
381EAPI Eina_Bool
382ecore_file_remove(const char *file)
383{
384 if (remove(file) < 0) return EINA_FALSE;
385 return EINA_TRUE;
386}
387
388/**
389 * @brief Delete the given directory and all its contents.
390 *
391 * @param dir The name of the directory to delete.
392 * @return EINA_TRUE on success, EINA_FALSE otherwise.
393 *
394 * This function delete @p dir and all its contents. If @p dir is a
395 * link only the link is removed. It returns EINA_TRUE on success,
396 * EINA_FALSE otherwise.
397 */
398EAPI Eina_Bool
399ecore_file_recursive_rm(const char *dir)
400{
401 Eina_Iterator *it;
402 char buf[PATH_MAX];
403 struct stat st;
404 int ret;
405
406 if (readlink(dir, buf, sizeof(buf)) > 0)
407 return ecore_file_unlink(dir);
408
409 ret = stat(dir, &st);
410 if ((ret == 0) && (S_ISDIR(st.st_mode)))
411 {
412 Eina_File_Direct_Info *info;
413
414 ret = 1;
415 if (stat(dir, &st) == -1) return EINA_FALSE; /* WOOT: WHY ARE WE CALLING STAT TWO TIMES ??? */
416
417 it = eina_file_direct_ls(dir);
418 EINA_ITERATOR_FOREACH(it, info)
419 {
420 if (!ecore_file_recursive_rm(info->path))
421 ret = 0;
422 }
423 eina_iterator_free(it);
424
425 if (!ecore_file_rmdir(dir)) ret = 0;
426 if (ret)
427 return EINA_TRUE;
428 else
429 return EINA_FALSE;
430 }
431 else
432 {
433 if (ret == -1) return EINA_FALSE;
434 return ecore_file_unlink(dir);
435 }
436}
437
438static inline Eina_Bool
439_ecore_file_mkpath_if_not_exists(const char *path)
440{
441 struct stat st;
442
443 /* Windows: path like C: or D: etc are valid, but stat() returns an error */
444#ifdef _WIN32
445 if ((strlen(path) == 2) &&
446 ((path[0] >= 'a' && path[0] <= 'z') ||
447 (path[0] >= 'A' && path[0] <= 'Z')) &&
448 (path[1] == ':'))
449 return EINA_TRUE;
450#endif
451
452 if (stat(path, &st) < 0)
453 return ecore_file_mkdir(path);
454 else if (!S_ISDIR(st.st_mode))
455 return EINA_FALSE;
456 else
457 return EINA_TRUE;
458}
459
460/**
461 * @brief Create a complete path.
462 *
463 * @param path The path to create
464 * @return EINA_TRUE on success, EINA_FALSE otherwise.
465 *
466 * This function creates @p path and all the subdirectories it
467 * contains. The separator is '/' or '\'. If @p path exists, this
468 * function returns EINA_TRUE immediately. It returns EINA_TRUE on
469 * success, EINA_FALSE otherwise.
470 */
471EAPI Eina_Bool
472ecore_file_mkpath(const char *path)
473{
474 char ss[PATH_MAX];
475 unsigned int i;
476
477 if (ecore_file_is_dir(path))
478 return EINA_TRUE;
479
480 for (i = 0; path[i] != '\0'; ss[i] = path[i], i++)
481 {
482 if (i == sizeof(ss) - 1) return EINA_FALSE;
483 if (((path[i] == '/') || (path[i] == '\\')) && (i > 0))
484 {
485 ss[i] = '\0';
486 if (!_ecore_file_mkpath_if_not_exists(ss))
487 return EINA_FALSE;
488 }
489 }
490 ss[i] = '\0';
491 return _ecore_file_mkpath_if_not_exists(ss);
492}
493
494/**
495 * @brief Create complete paths in a batch.
496 *
497 * @param paths list of paths, null terminated.
498 * @return number of successful paths created, -1 if paths is NULL.
499 *
500 * This function creates all the directories that are in the null
501 * terminated array @p paths. The function loops over the directories
502 * and call ecore_file_mkpath(), hence on Windows, '\' must be
503 * replaced by '/' before calling that function. This function
504 * returns -1 if @p paths is @c NULL. Otherwise if returns the number
505 * of suceesfully created directories.
506 */
507EAPI int
508ecore_file_mkpaths(const char **paths)
509{
510 int i = 0;
511
512 if (!paths) return -1;
513
514 for (; *paths; paths++)
515 if (ecore_file_mkpath(*paths))
516 i++;
517 return i;
518}
519
520/**
521 * @brief Copy the given file to the given destination.
522 *
523 * @param src The name of the source file.
524 * @param dst The name of the destination file.
525 * @return EINA_TRUE on success, EINA_FALSE otherwise.
526 *
527 * This function copies @p src to @p dst. If the absolute path name of
528 * @p src and @p dst can not be computed, or if they are equal, or if
529 * the copy fails, the function returns EINA_FALSE, otherwise it
530 * returns EINA_TRUE.
531 */
532EAPI Eina_Bool
533ecore_file_cp(const char *src, const char *dst)
534{
535 FILE *f1, *f2;
536 char buf[16384];
537 char realpath1[PATH_MAX], realpath2[PATH_MAX];
538 size_t num;
539 Eina_Bool ret = EINA_TRUE;
540
541 if (!realpath(src, realpath1)) return EINA_FALSE;
542 if (realpath(dst, realpath2) && !strcmp(realpath1, realpath2)) return EINA_FALSE;
543
544 f1 = fopen(src, "rb");
545 if (!f1) return EINA_FALSE;
546 f2 = fopen(dst, "wb");
547 if (!f2)
548 {
549 fclose(f1);
550 return EINA_FALSE;
551 }
552 while ((num = fread(buf, 1, sizeof(buf), f1)) > 0)
553 {
554 if (fwrite(buf, 1, num, f2) != num) ret = EINA_FALSE;
555 }
556 fclose(f1);
557 fclose(f2);
558 return ret;
559}
560
561/**
562 * @brief Move the given file to the given destination.
563 *
564 * @param src The name of the source file.
565 * @param dst The name of the destination file.
566 * @return EINA_TRUE on success, EINA_FALSE otherwise.
567 *
568 * This function moves @p src to @p dst. It returns EINA_TRUE on
569 * success, EINA_FALSE otherwise.
570 */
571EAPI Eina_Bool
572ecore_file_mv(const char *src, const char *dst)
573{
574 char buf[PATH_MAX];
575 int fd;
576
577 if (rename(src, dst))
578 {
579 // File cannot be moved directly because
580 // it resides on a different mount point.
581 if (errno == EXDEV)
582 {
583 struct stat st;
584
585 // Make sure this is a regular file before
586 // we do anything fancy.
587 stat(src, &st);
588 if (S_ISREG(st.st_mode))
589 {
590 char *dir;
591
592 dir = ecore_file_dir_get(dst);
593 // Since we can't directly rename, try to
594 // copy to temp file in the dst directory
595 // and then rename.
596 snprintf(buf, sizeof(buf), "%s/.%s.tmp.XXXXXX",
597 dir, ecore_file_file_get(dst));
598 free(dir);
599 fd = mkstemp(buf);
600 if (fd < 0)
601 {
602 perror("mkstemp");
603 goto FAIL;
604 }
605 close(fd);
606
607 // Copy to temp file
608 if (!ecore_file_cp(src, buf))
609 goto FAIL;
610
611 // Set file permissions of temp file to match src
612 chmod(buf, st.st_mode);
613
614 // Try to atomically move temp file to dst
615 if (rename(buf, dst))
616 {
617 // If we still cannot atomically move
618 // do a normal copy and hope for the best.
619 if (!ecore_file_cp(buf, dst))
620 goto FAIL;
621 }
622
623 // Delete temporary file and src
624 ecore_file_unlink(buf);
625 ecore_file_unlink(src);
626 goto PASS;
627 }
628 }
629 goto FAIL;
630 }
631
632PASS:
633 return EINA_TRUE;
634
635FAIL:
636 return EINA_FALSE;
637}
638
639/**
640 * @brief Create a symbolic link.
641 *
642 * @param src The name of the file to link.
643 * @param dest The name of link.
644 * @return EINA_TRUE on success, EINA_FALSE otherwise.
645 *
646 * This function create the symbolic link @p dest of @p src. This
647 * function does not work on Windows. It returns EINA_TRUE on success,
648 * EINA_FALSE otherwise.
649 */
650EAPI Eina_Bool
651ecore_file_symlink(const char *src, const char *dest)
652{
653 if (!symlink(src, dest)) return EINA_TRUE;
654
655 return EINA_FALSE;
656}
657
658/**
659 * @brief Get the canonicalized absolute path name.
660 *
661 * @param file The file path.
662 * @return The canonicalized absolute pathname or an empty string on
663 * failure.
664 *
665 * This function returns the absolute path name of @p file as a newly
666 * allocated string. If @p file is @c NULL, or on error, this function
667 * returns an empty string. Otherwise, it returns the absolute path
668 * name. When not needed anymore, the returned value must be freed.
669 */
670EAPI char *
671ecore_file_realpath(const char *file)
672{
673 char buf[PATH_MAX];
674
675 /*
676 * Some implementations of realpath do not conform to the SUS.
677 * And as a result we must prevent a null arg from being passed.
678 */
679 if (!file) return strdup("");
680 if (!realpath(file, buf)) return strdup("");
681
682 return strdup(buf);
683}
684
685/**
686 * Get the filename from a given path.
687 *
688 * @param path The complete path.
689 * @return The file name.
690 *
691 * This function returns the file name of @p path. If @p path is
692 * @c NULL, the functions returns @c NULL.
693 */
694EAPI const char *
695ecore_file_file_get(const char *path)
696{
697 char *result = NULL;
698
699 if (!path) return NULL;
700 if ((result = strrchr(path, '/'))) result++;
701 else result = (char *)path;
702 return result;
703}
704
705/**
706 * @brief Get the directory where the given file resides.
707 *
708 * @param file The name of the file.
709 * @return The directory name.
710 *
711 * This function returns the directory where @p file resides as anewly
712 * allocated string. If @p file is @c NULL or on error, this function
713 * returns @c NULL. When not needed anymore, the returned value must
714 * be freed.
715 */
716EAPI char *
717ecore_file_dir_get(const char *file)
718{
719 char *p;
720 char buf[PATH_MAX];
721
722 if (!file) return NULL;
723 strncpy(buf, file, PATH_MAX);
724 buf[PATH_MAX - 1] = 0;
725 p = dirname(buf);
726 return strdup(p);
727}
728
729/**
730 * @brief Check if the given file can be read.
731 *
732 * @param file The name of the file.
733 * @return EINA_TRUE if the file is readable, EINA_FALSE otherwise.
734 *
735 * This function returns EINA_TRUE if @p file can be read, EINA_FALSE
736 * otherwise.
737 */
738EAPI Eina_Bool
739ecore_file_can_read(const char *file)
740{
741 if (!file) return EINA_FALSE;
742 if (!access(file, R_OK)) return EINA_TRUE;
743 return EINA_FALSE;
744}
745
746/**
747 * @brief Check if the given file can be written.
748 *
749 * @param file The name of the file.
750 * @return EINA_TRUE if the file is writable, EINA_FALSE otherwise.
751 *
752 * This function returns EINA_TRUE if @p file can be written, EINA_FALSE
753 * otherwise.
754 */
755EAPI Eina_Bool
756ecore_file_can_write(const char *file)
757{
758 if (!file) return EINA_FALSE;
759 if (!access(file, W_OK)) return EINA_TRUE;
760 return EINA_FALSE;
761}
762
763/**
764 * @bbrief Check if the given file can be executed.
765 *
766 * @param file The name of the file.
767 * @return EINA_TRUE if the file can be executed, EINA_FALSE otherwise.
768 *
769 * This function returns EINA_TRUE if @p file can be executed, EINA_FALSE
770 * otherwise.
771 */
772EAPI Eina_Bool
773ecore_file_can_exec(const char *file)
774{
775 if (!file) return EINA_FALSE;
776 if (!access(file, X_OK)) return EINA_TRUE;
777 return EINA_FALSE;
778}
779
780/**
781 * @brief Get the path pointed by the given link.
782 *
783 * @param lnk The name of the link.
784 * @return The path pointed by link or NULL.
785 *
786 * This function returns the path pointed by @p link as a newly
787 * allocated string. This function does not work on Windows. On
788 * failure, the function returns @c NULL. When not needed anymore, the
789 * returned value must be freed.
790 */
791EAPI char *
792ecore_file_readlink(const char *lnk)
793{
794 char buf[PATH_MAX];
795 int count;
796
797 if ((count = readlink(lnk, buf, sizeof(buf) - 1)) < 0) return NULL;
798 buf[count] = 0;
799 return strdup(buf);
800}
801
802/**
803 * @brief Get the list of the files and directories in the given
804 * directory.
805 *
806 * @param dir The name of the directory to list
807 * @return Return an Eina_List containing all the files in the directory;
808 * on failure it returns NULL.
809 *
810 * This function returns a list of allocated strings of all the files
811 * and directories contained in @p dir. The list will be sorted with
812 * strcoll as compare function. That means that you may want to set
813 * the current locale for the category LC_COLLATE with
814 * setlocale(). For more information see the manual pages of strcoll
815 * and setlocale. The list will not contain the directory entries for
816 * '.' and '..'. On failure, @c NULL is returned. When not needed
817 * anymore, the list elements must be freed.
818 */
819EAPI Eina_List *
820ecore_file_ls(const char *dir)
821{
822 Eina_File_Direct_Info *info;
823 Eina_Iterator *ls;
824 Eina_List *list = NULL;
825
826 ls = eina_file_direct_ls(dir);
827 EINA_ITERATOR_FOREACH(ls, info)
828 {
829 char *f;
830
831 f = strdup(info->path + info->name_start);
832 list = eina_list_append(list, f);
833 }
834 eina_iterator_free(ls);
835
836 list = eina_list_sort(list, eina_list_count(list), EINA_COMPARE_CB(strcoll));
837
838 return list;
839}
840
841/**
842 * @brief Return the executable from the given command.
843 *
844 * @param app The application command, with parameters.
845 *
846 * This function returns the executable from @p app as a newly
847 * allocated string. Arguments are removed and escae characters are
848 * handled. If @p app is @c NULL, or on failure, the function returns
849 * @c NULL. When not needed anymore, the returned value must be freed.
850 */
851EAPI char *
852ecore_file_app_exe_get(const char *app)
853{
854 char *p, *pp, *exe1 = NULL, *exe2 = NULL;
855 char *exe = NULL;
856 int in_quot_dbl = 0, in_quot_sing = 0, restart = 0;
857
858 if (!app) return NULL;
859
860 p = (char *)app;
861restart:
862 while ((*p) && (isspace(*p))) p++;
863 exe1 = p;
864 while (*p)
865 {
866 if (in_quot_sing)
867 {
868 if (*p == '\'')
869 in_quot_sing = 0;
870 }
871 else if (in_quot_dbl)
872 {
873 if (*p == '\"')
874 in_quot_dbl = 0;
875 }
876 else
877 {
878 if (*p == '\'')
879 in_quot_sing = 1;
880 else if (*p == '\"')
881 in_quot_dbl = 1;
882 if ((isspace(*p)) && (!((p > app) && (p[-1] != '\\'))))
883 break;
884 }
885 p++;
886 }
887 exe2 = p;
888 if (exe2 == exe1) return NULL;
889 if (*exe1 == '~')
890 {
891 char *homedir;
892 int len;
893
894 /* Skip ~ */
895 exe1++;
896
897 homedir = getenv("HOME");
898 if (!homedir) return NULL;
899 len = strlen(homedir);
900 if (exe) free(exe);
901 exe = malloc(len + exe2 - exe1 + 2);
902 if (!exe) return NULL;
903 pp = exe;
904 if (len)
905 {
906 strcpy(exe, homedir);
907 pp += len;
908 if (*(pp - 1) != '/')
909 {
910 *pp = '/';
911 pp++;
912 }
913 }
914 }
915 else
916 {
917 if (exe) free(exe);
918 exe = malloc(exe2 - exe1 + 1);
919 if (!exe) return NULL;
920 pp = exe;
921 }
922 p = exe1;
923 restart = 0;
924 in_quot_dbl = 0;
925 in_quot_sing = 0;
926 while (*p)
927 {
928 if (in_quot_sing)
929 {
930 if (*p == '\'')
931 in_quot_sing = 0;
932 else
933 {
934 *pp = *p;
935 pp++;
936 }
937 }
938 else if (in_quot_dbl)
939 {
940 if (*p == '\"')
941 in_quot_dbl = 0;
942 else
943 {
944 /* technically this is wrong. double quotes also accept
945 * special chars:
946 *
947 * $, `, \
948 */
949 *pp = *p;
950 pp++;
951 }
952 }
953 else
954 {
955 /* technically we should handle special chars:
956 *
957 * $, `, \, etc.
958 */
959 if ((p > exe1) && (p[-1] == '\\'))
960 {
961 if (*p != '\n')
962 {
963 *pp = *p;
964 pp++;
965 }
966 }
967 else if ((p > exe1) && (*p == '='))
968 {
969 restart = 1;
970 *pp = *p;
971 pp++;
972 }
973 else if (*p == '\'')
974 in_quot_sing = 1;
975 else if (*p == '\"')
976 in_quot_dbl = 1;
977 else if (isspace(*p))
978 {
979 if (restart)
980 goto restart;
981 else
982 break;
983 }
984 else
985 {
986 *pp = *p;
987 pp++;
988 }
989 }
990 p++;
991 }
992 *pp = 0;
993 return exe;
994}
995
996/**
997 * @brief Add the escape sequence ('\\') to the given file name.
998 *
999 * @param filename The file name.
1000 * @return The file name with special characters escaped.
1001 *
1002 * This function adds the escape sequence ('\\') to the given file
1003 * name and returns the result as a newly allocated string. If the
1004 * length of the returned string is longer than PATH_MAX, or on
1005 * failure, @c NULL is returned. When not needed anymore, the returned
1006 * value must be freed.
1007 */
1008EAPI char *
1009ecore_file_escape_name(const char *filename)
1010{
1011 const char *p;
1012 char *q;
1013 char buf[PATH_MAX];
1014
1015 p = filename;
1016 q = buf;
1017 while (*p)
1018 {
1019 if ((q - buf) > (PATH_MAX - 6)) return NULL;
1020 if (
1021 (*p == ' ') || (*p == '\t') || (*p == '\n') ||
1022 (*p == '\\') || (*p == '\'') || (*p == '\"') ||
1023 (*p == ';') || (*p == '!') || (*p == '#') ||
1024 (*p == '$') || (*p == '%') || (*p == '&') ||
1025 (*p == '*') || (*p == '(') || (*p == ')') ||
1026 (*p == '[') || (*p == ']') || (*p == '{') ||
1027 (*p == '}') || (*p == '|') || (*p == '<') ||
1028 (*p == '>') || (*p == '?')
1029 )
1030 {
1031 *q = '\\';
1032 q++;
1033 }
1034 *q = *p;
1035 q++;
1036 p++;
1037 }
1038 *q = 0;
1039 return strdup(buf);
1040}
1041
1042/**
1043 * @bried Remove the extension from the given file name.
1044 *
1045 * @param path The name of the file.
1046 * @return A newly allocated string with the extension stripped out or
1047 * NULL on errors.
1048 *
1049 * This function removes the extension from @p path and returns the
1050 * result as a newly allocated string. If @p path is @c NULL, or on
1051 * failure, the function returns @c NULL. When not needed anymore, the
1052 * returned value must be freed.
1053 */
1054EAPI char *
1055ecore_file_strip_ext(const char *path)
1056{
1057 char *p, *file = NULL;
1058
1059 if (!path)
1060 return NULL;
1061
1062 p = strrchr(path, '.');
1063 if (!p)
1064 file = strdup(path);
1065 else if (p != path)
1066 {
1067 file = malloc(((p - path) + 1) * sizeof(char));
1068 if (file)
1069 {
1070 memcpy(file, path, (p - path));
1071 file[p - path] = 0;
1072 }
1073 }
1074
1075 return file;
1076}
1077
1078/**
1079 * @brief Check if the given directory is empty.
1080 *
1081 * @param dir The name of the directory to check.
1082 * @return 1 if directory is empty, 0 if it has at least one file or
1083 * -1 in case of errors.
1084 *
1085 * This functions checks if @p dir is empty. The '.' and '..' files
1086 * will be ignored. If @p dir is empty, 1 is returned, if it contains
1087 * at least 1 file, 0 is returned. On failure, -1 is returned.
1088 */
1089EAPI int
1090ecore_file_dir_is_empty(const char *dir)
1091{
1092 Eina_File_Direct_Info *info;
1093 Eina_Iterator *it;
1094
1095 it = eina_file_direct_ls(dir);
1096 if (!it) return -1;
1097
1098 EINA_ITERATOR_FOREACH(it, info)
1099 {
1100 eina_iterator_free(it);
1101 return 0;
1102 }
1103
1104 eina_iterator_free(it);
1105 return 1;
1106}
1107
1108/**
1109 * @}
1110 */