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