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