summaryrefslogtreecommitdiff
path: root/src/lib/ecore_file/ecore_file.c
diff options
context:
space:
mode:
authorVincent Torri <vincent.torri@gmail.com>2012-12-02 22:35:45 +0000
committerVincent Torri <vincent.torri@gmail.com>2012-12-02 22:35:45 +0000
commit7d6010b12c47a20e492da808e3192c3f87dab619 (patch)
tree26c6fd189e046a76560c0bc740b85f4d767ae399 /src/lib/ecore_file/ecore_file.c
parent53fc441d5475155965d92da89502fe4634a561b2 (diff)
merge: add escape ecore, fix several bugs
SVN revision: 79995
Diffstat (limited to 'src/lib/ecore_file/ecore_file.c')
-rw-r--r--src/lib/ecore_file/ecore_file.c1137
1 files changed, 1137 insertions, 0 deletions
diff --git a/src/lib/ecore_file/ecore_file.c b/src/lib/ecore_file/ecore_file.c
new file mode 100644
index 0000000000..6876511fc6
--- /dev/null
+++ b/src/lib/ecore_file/ecore_file.c
@@ -0,0 +1,1137 @@
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 @c EINA_TRUE if the @p file exists, @c EINA_FALSE otherwise.
166 *
167 * This function returns @c EINA_TRUE if @p file exists on local filesystem,
168 * @c 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 @c EINA_TRUE if the file exists and is a directory, @c EINA_FALSE
186 * otherwise.
187 *
188 * This function returns @c EINA_TRUE if @p file exists exists and is a
189 * directory on local filesystem, @c 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 @c EINA_TRUE on successful creation, @c 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 @c EINA_TRUE, @c 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 @c EINA_TRUE on success, @c EINA_FALSE otherwise.
346 *
347 * This function deletes @p dir. It returns @c EINA_TRUE on success,
348 * @c 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 @c EINA_TRUE on success, @c EINA_FALSE otherwise.
362 *
363 * This function deletes @p file. It returns @c EINA_TRUE on success,
364 * @c 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 @c EINA_TRUE on success, @c EINA_FALSE otherwise.
378 *
379 * This function removes @p file. It returns @c EINA_TRUE on success,
380 * @c 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 @c EINA_TRUE on success, @c 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 @c EINA_TRUE on success,
397 * @c EINA_FALSE otherwise.
398 */
399EAPI Eina_Bool
400ecore_file_recursive_rm(const char *dir)
401{
402 struct stat st;
403
404#ifdef _WIN32
405 char buf[PATH_MAX];
406
407 if (readlink(dir, buf, sizeof(buf) - 1) > 0)
408 return ecore_file_unlink(dir);
409 if (stat(dir, &st) == -1)
410 return EINA_FALSE;
411#else
412 if (lstat(dir, &st) == -1)
413 return EINA_FALSE;
414#endif
415
416 if (S_ISDIR(st.st_mode))
417 {
418 Eina_File_Direct_Info *info;
419 Eina_Iterator *it;
420 int ret;
421
422 ret = 1;
423 it = eina_file_direct_ls(dir);
424 EINA_ITERATOR_FOREACH(it, info)
425 {
426 if (!ecore_file_recursive_rm(info->path))
427 ret = 0;
428 }
429 eina_iterator_free(it);
430
431 if (!ecore_file_rmdir(dir)) ret = 0;
432 if (ret)
433 return EINA_TRUE;
434 else
435 return EINA_FALSE;
436 }
437 else
438 {
439 return ecore_file_unlink(dir);
440 }
441}
442
443static inline Eina_Bool
444_ecore_file_mkpath_if_not_exists(const char *path)
445{
446 struct stat st;
447
448 /* Windows: path like C: or D: etc are valid, but stat() returns an error */
449#ifdef _WIN32
450 if ((strlen(path) == 2) &&
451 ((path[0] >= 'a' && path[0] <= 'z') ||
452 (path[0] >= 'A' && path[0] <= 'Z')) &&
453 (path[1] == ':'))
454 return EINA_TRUE;
455#endif
456
457 if (stat(path, &st) < 0)
458 return ecore_file_mkdir(path);
459 else if (!S_ISDIR(st.st_mode))
460 return EINA_FALSE;
461 else
462 return EINA_TRUE;
463}
464
465/**
466 * @brief Create a complete path.
467 *
468 * @param path The path to create
469 * @return @c EINA_TRUE on success, @c EINA_FALSE otherwise.
470 *
471 * This function creates @p path and all the subdirectories it
472 * contains. The separator is '/' or '\'. If @p path exists, this
473 * function returns @c EINA_TRUE immediately. It returns @c EINA_TRUE on
474 * success, @c EINA_FALSE otherwise.
475 */
476EAPI Eina_Bool
477ecore_file_mkpath(const char *path)
478{
479 char ss[PATH_MAX];
480 unsigned int i;
481
482 if (ecore_file_is_dir(path))
483 return EINA_TRUE;
484
485 for (i = 0; path[i] != '\0'; ss[i] = path[i], i++)
486 {
487 if (i == sizeof(ss) - 1) return EINA_FALSE;
488 if (((path[i] == '/') || (path[i] == '\\')) && (i > 0))
489 {
490 ss[i] = '\0';
491 if (!_ecore_file_mkpath_if_not_exists(ss))
492 return EINA_FALSE;
493 }
494 }
495 ss[i] = '\0';
496 return _ecore_file_mkpath_if_not_exists(ss);
497}
498
499/**
500 * @brief Create complete paths in a batch.
501 *
502 * @param paths list of paths, null terminated.
503 * @return number of successful paths created, -1 if paths is NULL.
504 *
505 * This function creates all the directories that are in the null
506 * terminated array @p paths. The function loops over the directories
507 * and call ecore_file_mkpath(), hence on Windows, '\' must be
508 * replaced by '/' before calling that function. This function
509 * returns -1 if @p paths is @c NULL. Otherwise if returns the number
510 * of suceesfully created directories.
511 */
512EAPI int
513ecore_file_mkpaths(const char **paths)
514{
515 int i = 0;
516
517 if (!paths) return -1;
518
519 for (; *paths; paths++)
520 if (ecore_file_mkpath(*paths))
521 i++;
522 return i;
523}
524
525/**
526 * @brief Copy the given file to the given destination.
527 *
528 * @param src The name of the source file.
529 * @param dst The name of the destination file.
530 * @return @c EINA_TRUE on success, @c EINA_FALSE otherwise.
531 *
532 * This function copies @p src to @p dst. If the absolute path name of
533 * @p src and @p dst can not be computed, or if they are equal, or if
534 * the copy fails, the function returns @c EINA_FALSE, otherwise it
535 * returns @c EINA_TRUE.
536 */
537EAPI Eina_Bool
538ecore_file_cp(const char *src, const char *dst)
539{
540 FILE *f1, *f2;
541 char buf[16384];
542 char realpath1[PATH_MAX], realpath2[PATH_MAX];
543 size_t num;
544 Eina_Bool ret = EINA_TRUE;
545
546 if (!realpath(src, realpath1)) return EINA_FALSE;
547 if (realpath(dst, realpath2) && !strcmp(realpath1, realpath2)) return EINA_FALSE;
548
549 f1 = fopen(src, "rb");
550 if (!f1) return EINA_FALSE;
551 f2 = fopen(dst, "wb");
552 if (!f2)
553 {
554 fclose(f1);
555 return EINA_FALSE;
556 }
557 while ((num = fread(buf, 1, sizeof(buf), f1)) > 0)
558 {
559 if (fwrite(buf, 1, num, f2) != num) ret = EINA_FALSE;
560 }
561 fclose(f1);
562 fclose(f2);
563 return ret;
564}
565
566/**
567 * @brief Move the given file to the given destination.
568 *
569 * @param src The name of the source file.
570 * @param dst The name of the destination file.
571 * @return @c EINA_TRUE on success, @c EINA_FALSE otherwise.
572 *
573 * This function moves @p src to @p dst. It returns @c EINA_TRUE on
574 * success, @c EINA_FALSE otherwise.
575 */
576EAPI Eina_Bool
577ecore_file_mv(const char *src, const char *dst)
578{
579 char buf[PATH_MAX];
580 int fd;
581
582 if (rename(src, dst))
583 {
584 // File cannot be moved directly because
585 // it resides on a different mount point.
586 if (errno == EXDEV)
587 {
588 struct stat st;
589
590 // Make sure this is a regular file before
591 // we do anything fancy.
592 stat(src, &st);
593 if (S_ISREG(st.st_mode))
594 {
595 char *dir;
596
597 dir = ecore_file_dir_get(dst);
598 // Since we can't directly rename, try to
599 // copy to temp file in the dst directory
600 // and then rename.
601 snprintf(buf, sizeof(buf), "%s/.%s.tmp.XXXXXX",
602 dir, ecore_file_file_get(dst));
603 free(dir);
604 fd = mkstemp(buf);
605 if (fd < 0) goto FAIL;
606 close(fd);
607
608 // Copy to temp file
609 if (!ecore_file_cp(src, buf))
610 goto FAIL;
611
612 // Set file permissions of temp file to match src
613 chmod(buf, st.st_mode);
614
615 // Try to atomically move temp file to dst
616 if (rename(buf, dst))
617 {
618 // If we still cannot atomically move
619 // do a normal copy and hope for the best.
620 if (!ecore_file_cp(buf, dst))
621 goto FAIL;
622 }
623
624 // Delete temporary file and src
625 ecore_file_unlink(buf);
626 ecore_file_unlink(src);
627 goto PASS;
628 }
629 }
630 goto FAIL;
631 }
632
633PASS:
634 return EINA_TRUE;
635
636FAIL:
637 return EINA_FALSE;
638}
639
640/**
641 * @brief Create a symbolic link.
642 *
643 * @param src The name of the file to link.
644 * @param dest The name of link.
645 * @return @c EINA_TRUE on success, @c EINA_FALSE otherwise.
646 *
647 * This function create the symbolic link @p dest of @p src. This
648 * function does not work on Windows. It returns @c EINA_TRUE on success,
649 * @c EINA_FALSE otherwise.
650 */
651EAPI Eina_Bool
652ecore_file_symlink(const char *src, const char *dest)
653{
654 if (!symlink(src, dest)) return EINA_TRUE;
655
656 return EINA_FALSE;
657}
658
659/**
660 * @brief Get the canonicalized absolute path name.
661 *
662 * @param file The file path.
663 * @return The canonicalized absolute pathname or an empty string on
664 * failure.
665 *
666 * This function returns the absolute path name of @p file as a newly
667 * allocated string. If @p file is @c NULL, or on error, this function
668 * returns an empty string. Otherwise, it returns the absolute path
669 * name. When not needed anymore, the returned value must be freed.
670 */
671EAPI char *
672ecore_file_realpath(const char *file)
673{
674 char buf[PATH_MAX];
675
676 /*
677 * Some implementations of realpath do not conform to the SUS.
678 * And as a result we must prevent a null arg from being passed.
679 */
680 if (!file) return strdup("");
681 if (!realpath(file, buf)) return strdup("");
682
683 return strdup(buf);
684}
685
686/**
687 * Get the filename from a given path.
688 *
689 * @param path The complete path.
690 * @return The file name.
691 *
692 * This function returns the file name of @p path. If @p path is
693 * @c NULL, the functions returns @c NULL.
694 */
695EAPI const char *
696ecore_file_file_get(const char *path)
697{
698 char *result = NULL;
699
700 if (!path) return NULL;
701 if ((result = strrchr(path, '/'))) result++;
702 else result = (char *)path;
703 return result;
704}
705
706/**
707 * @brief Get the directory where the given file resides.
708 *
709 * @param file The name of the file.
710 * @return The directory name.
711 *
712 * This function returns the directory where @p file resides as anewly
713 * allocated string. If @p file is @c NULL or on error, this function
714 * returns @c NULL. When not needed anymore, the returned value must
715 * be freed.
716 */
717EAPI char *
718ecore_file_dir_get(const char *file)
719{
720 char *p;
721 char buf[PATH_MAX];
722
723 if (!file) return NULL;
724 strncpy(buf, file, PATH_MAX);
725 buf[PATH_MAX - 1] = 0;
726 p = dirname(buf);
727 return strdup(p);
728}
729
730/**
731 * @brief Check if the given file can be read.
732 *
733 * @param file The name of the file.
734 * @return @c EINA_TRUE if the @p file is readable, @c EINA_FALSE otherwise.
735 *
736 * This function returns @c EINA_TRUE if @p file can be read, @c EINA_FALSE
737 * otherwise.
738 */
739EAPI Eina_Bool
740ecore_file_can_read(const char *file)
741{
742 if (!file) return EINA_FALSE;
743 if (!access(file, R_OK)) return EINA_TRUE;
744 return EINA_FALSE;
745}
746
747/**
748 * @brief Check if the given file can be written.
749 *
750 * @param file The name of the file.
751 * @return @c EINA_TRUE if the @p file is writable, @c EINA_FALSE otherwise.
752 *
753 * This function returns @c EINA_TRUE if @p file can be written, @c EINA_FALSE
754 * otherwise.
755 */
756EAPI Eina_Bool
757ecore_file_can_write(const char *file)
758{
759 if (!file) return EINA_FALSE;
760 if (!access(file, W_OK)) return EINA_TRUE;
761 return EINA_FALSE;
762}
763
764/**
765 * @brief Check if the given file can be executed.
766 *
767 * @param file The name of the file.
768 * @return @c EINA_TRUE if the @p file can be executed, @c EINA_FALSE
769 * otherwise.
770 *
771 * This function returns @c EINA_TRUE if @p file can be executed, @c EINA_FALSE
772 * otherwise.
773 */
774EAPI Eina_Bool
775ecore_file_can_exec(const char *file)
776{
777 if (!file) return EINA_FALSE;
778 if (!access(file, X_OK)) return EINA_TRUE;
779 return EINA_FALSE;
780}
781
782/**
783 * @brief Get the path pointed by the given link.
784 *
785 * @param lnk The name of the link.
786 * @return The path pointed by link or NULL.
787 *
788 * This function returns the path pointed by @p link as a newly
789 * allocated string. This function does not work on Windows. On
790 * failure, the function returns @c NULL. When not needed anymore, the
791 * returned value must be freed.
792 */
793EAPI char *
794ecore_file_readlink(const char *lnk)
795{
796 char buf[PATH_MAX];
797 int count;
798
799 if ((count = readlink(lnk, buf, sizeof(buf) - 1)) < 0) return NULL;
800 buf[count] = 0;
801 return strdup(buf);
802}
803
804/**
805 * @brief Get the list of the files and directories in the given
806 * directory.
807 *
808 * @param dir The name of the directory to list
809 * @return Return an Eina_List containing all the files in the directory;
810 * on failure it returns NULL.
811 *
812 * This function returns a list of allocated strings of all the files
813 * and directories contained in @p dir. The list will be sorted with
814 * strcoll as compare function. That means that you may want to set
815 * the current locale for the category LC_COLLATE with
816 * setlocale(). For more information see the manual pages of strcoll
817 * and setlocale. The list will not contain the directory entries for
818 * '.' and '..'. On failure, @c NULL is returned. When not needed
819 * anymore, the list elements must be freed.
820 */
821EAPI Eina_List *
822ecore_file_ls(const char *dir)
823{
824 Eina_File_Direct_Info *info;
825 Eina_Iterator *ls;
826 Eina_List *list = NULL;
827
828 ls = eina_file_direct_ls(dir);
829 if (!ls) return NULL;
830
831 EINA_ITERATOR_FOREACH(ls, info)
832 {
833 char *f;
834
835 f = strdup(info->path + info->name_start);
836 list = eina_list_append(list, f);
837 }
838 eina_iterator_free(ls);
839
840 list = eina_list_sort(list, eina_list_count(list), EINA_COMPARE_CB(strcoll));
841
842 return list;
843}
844
845/**
846 * @brief Return the executable from the given command.
847 *
848 * @param app The application command, with parameters.
849 * @return The executable from @p app as a newly allocated string. Arguments
850 * are removed and escape characters are handled. If @p app is @c NULL, or
851 * on failure, the function returns @c NULL. When not needed anymore, the
852 * returned value must be freed.
853 */
854EAPI char *
855ecore_file_app_exe_get(const char *app)
856{
857 char *p, *pp, *exe1 = NULL, *exe2 = NULL;
858 char *exe = NULL;
859 int in_quot_dbl = 0, in_quot_sing = 0, restart = 0;
860
861 if (!app) return NULL;
862
863 p = (char *)app;
864restart:
865 while ((*p) && (isspace((unsigned char)*p))) p++;
866 exe1 = p;
867 while (*p)
868 {
869 if (in_quot_sing)
870 {
871 if (*p == '\'')
872 in_quot_sing = 0;
873 }
874 else if (in_quot_dbl)
875 {
876 if (*p == '\"')
877 in_quot_dbl = 0;
878 }
879 else
880 {
881 if (*p == '\'')
882 in_quot_sing = 1;
883 else if (*p == '\"')
884 in_quot_dbl = 1;
885 if ((isspace((unsigned char)*p)) && ((p <= app) || (p[-1] == '\\')))
886 break;
887 }
888 p++;
889 }
890 exe2 = p;
891 if (exe2 == exe1) return NULL;
892 if (*exe1 == '~')
893 {
894 char *homedir;
895 int len;
896
897 /* Skip ~ */
898 exe1++;
899
900 homedir = getenv("HOME");
901 if (!homedir) return NULL;
902 len = strlen(homedir);
903 if (exe) free(exe);
904 exe = malloc(len + exe2 - exe1 + 2);
905 if (!exe) return NULL;
906 pp = exe;
907 if (len)
908 {
909 strcpy(exe, homedir);
910 pp += len;
911 if (*(pp - 1) != '/')
912 {
913 *pp = '/';
914 pp++;
915 }
916 }
917 }
918 else
919 {
920 if (exe) free(exe);
921 exe = malloc(exe2 - exe1 + 1);
922 if (!exe) return NULL;
923 pp = exe;
924 }
925 p = exe1;
926 restart = 0;
927 in_quot_dbl = 0;
928 in_quot_sing = 0;
929 while (*p)
930 {
931 if (in_quot_sing)
932 {
933 if (*p == '\'')
934 in_quot_sing = 0;
935 else
936 {
937 *pp = *p;
938 pp++;
939 }
940 }
941 else if (in_quot_dbl)
942 {
943 if (*p == '\"')
944 in_quot_dbl = 0;
945 else
946 {
947 /* technically this is wrong. double quotes also accept
948 * special chars:
949 *
950 * $, `, \
951 */
952 *pp = *p;
953 pp++;
954 }
955 }
956 else
957 {
958 /* technically we should handle special chars:
959 *
960 * $, `, \, etc.
961 */
962 if ((p > exe1) && (p[-1] == '\\'))
963 {
964 if (*p != '\n')
965 {
966 *pp = *p;
967 pp++;
968 }
969 }
970 else if ((p > exe1) && (*p == '='))
971 {
972 restart = 1;
973 *pp = *p;
974 pp++;
975 }
976 else if (*p == '\'')
977 in_quot_sing = 1;
978 else if (*p == '\"')
979 in_quot_dbl = 1;
980 else if (isspace((unsigned char)*p))
981 {
982 if (restart)
983 goto restart;
984 else
985 break;
986 }
987 else
988 {
989 *pp = *p;
990 pp++;
991 }
992 }
993 p++;
994 }
995 *pp = 0;
996 return exe;
997}
998
999/**
1000 * @brief Add the escape sequence ('\\') to the given file name.
1001 *
1002 * @param filename The file name.
1003 * @return The file name with special characters escaped.
1004 *
1005 * This function adds the escape sequence ('\\') to the given file
1006 * name and returns the result as a newly allocated string. If the
1007 * length of the returned string is longer than PATH_MAX, or on
1008 * failure, @c NULL is returned. When not needed anymore, the returned
1009 * value must be freed.
1010 */
1011EAPI char *
1012ecore_file_escape_name(const char *filename)
1013{
1014 const char *p;
1015 char *q;
1016 char buf[PATH_MAX];
1017
1018 EINA_SAFETY_ON_NULL_RETURN_VAL(filename, NULL);
1019
1020 p = filename;
1021 q = buf;
1022 while (*p)
1023 {
1024 if ((q - buf) > (PATH_MAX - 6)) return NULL;
1025 if (
1026 (*p == ' ') || (*p == '\\') || (*p == '\'') ||
1027 (*p == '\"') || (*p == ';') || (*p == '!') ||
1028 (*p == '#') || (*p == '$') || (*p == '%') ||
1029 (*p == '&') || (*p == '*') || (*p == '(') ||
1030 (*p == ')') || (*p == '[') || (*p == ']') ||
1031 (*p == '{') || (*p == '}') || (*p == '|') ||
1032 (*p == '<') || (*p == '>') || (*p == '?')
1033 )
1034 {
1035 *q = '\\';
1036 q++;
1037 }
1038 else if (*p == '\t')
1039 {
1040 *q = '\\';
1041 q++;
1042 *q = '\\';
1043 q++;
1044 *q = 't';
1045 q++;
1046 p++;
1047 continue;
1048 }
1049 else if (*p == '\n')
1050 {
1051 *q = '\\';
1052 q++;
1053 *q = '\\';
1054 q++;
1055 *q = 'n';
1056 q++;
1057 p++;
1058 continue;
1059 }
1060
1061 *q = *p;
1062 q++;
1063 p++;
1064 }
1065 *q = 0;
1066 return strdup(buf);
1067}
1068
1069/**
1070 * @brief Remove the extension from the given file name.
1071 *
1072 * @param path The name of the file.
1073 * @return A newly allocated string with the extension stripped out or
1074 * @c NULL on errors.
1075 *
1076 * This function removes the extension from @p path and returns the
1077 * result as a newly allocated string. If @p path is @c NULL, or on
1078 * failure, the function returns @c NULL. When not needed anymore, the
1079 * returned value must be freed.
1080 */
1081EAPI char *
1082ecore_file_strip_ext(const char *path)
1083{
1084 char *p, *file = NULL;
1085
1086 if (!path)
1087 return NULL;
1088
1089 p = strrchr(path, '.');
1090 if (!p)
1091 file = strdup(path);
1092 else if (p != path)
1093 {
1094 file = malloc(((p - path) + 1) * sizeof(char));
1095 if (file)
1096 {
1097 memcpy(file, path, (p - path));
1098 file[p - path] = 0;
1099 }
1100 }
1101
1102 return file;
1103}
1104
1105/**
1106 * @brief Check if the given directory is empty.
1107 *
1108 * @param dir The name of the directory to check.
1109 * @return @c 1 if directory is empty, @c 0 if it has at least one file or
1110 * @c -1 in case of errors.
1111 *
1112 * This functions checks if @p dir is empty. The '.' and '..' files
1113 * will be ignored. If @p dir is empty, 1 is returned, if it contains
1114 * at least one file, @c 0 is returned. On failure, @c -1 is returned.
1115 */
1116EAPI int
1117ecore_file_dir_is_empty(const char *dir)
1118{
1119 Eina_File_Direct_Info *info;
1120 Eina_Iterator *it;
1121
1122 it = eina_file_direct_ls(dir);
1123 if (!it) return -1;
1124
1125 EINA_ITERATOR_FOREACH(it, info)
1126 {
1127 eina_iterator_free(it);
1128 return 0;
1129 }
1130
1131 eina_iterator_free(it);
1132 return 1;
1133}
1134
1135/**
1136 * @}
1137 */