summaryrefslogtreecommitdiff
path: root/src/lib/ecore_file
diff options
context:
space:
mode:
authorVincent Torri <vincent dot torri at gmail dot com>2015-10-01 07:29:11 +0200
committerCedric BAIL <cedric@osg.samsung.com>2015-10-12 17:21:59 -0700
commitb9ed3375f2d9a822d83a383ff3d6691470b1c348 (patch)
tree321e57ebb45e4939842cfb021a484bac89b3f8b0 /src/lib/ecore_file
parentce4ef2cf91144df407614cfe91c113625865922d (diff)
ecore_file: fix ecore_file management function on Windows
On windows, stat() returns -1 if a path is finished with a \ or /, so replace all stat() calls with a function which removes the trailing slash or backslash on Windows At this stage the code duplicate many code path for avoiding potential borkage on Unix system. During 1.17 release cycle, it would be nice to refactor this piece. @fix Signed-off-by: Cedric BAIL <cedric@osg.samsung.com>
Diffstat (limited to 'src/lib/ecore_file')
-rw-r--r--src/lib/ecore_file/ecore_file.c116
1 files changed, 94 insertions, 22 deletions
diff --git a/src/lib/ecore_file/ecore_file.c b/src/lib/ecore_file/ecore_file.c
index 7dba323895..015a9b9675 100644
--- a/src/lib/ecore_file/ecore_file.c
+++ b/src/lib/ecore_file/ecore_file.c
@@ -27,9 +27,61 @@
27 27
28#include "ecore_file_private.h" 28#include "ecore_file_private.h"
29 29
30/*
31 * FIXME: the following functions will certainly not work on Windows:
32 * ecore_file_file_get()
33 * ecore_file_app_exe_get()
34 * ecore_file_escape_name()
35 */
36
30int _ecore_file_log_dom = -1; 37int _ecore_file_log_dom = -1;
31static int _ecore_file_init_count = 0; 38static int _ecore_file_init_count = 0;
32 39
40static Eina_Bool
41_ecore_file_stat(const char *file,
42 long long *mtime,
43 long long *size,
44 mode_t *mode,
45 Eina_Bool *is_dir,
46 Eina_Bool *is_reg)
47{
48 struct stat st;
49#ifdef _WIN32
50 /*
51 * On Windows, stat() returns -1 is file is a path finishing with
52 * a slash or blackslash
53 * see https://msdn.microsoft.com/en-us/library/14h5k7ff.aspx
54 * ("Return Value" section)
55 *
56 * so we ensure that file never finishes with \ or /
57 */
58 char f[MAX_PATH];
59 size_t len;
60
61 len = strlen(file);
62 if ((len + 1) > MAX_PATH)
63 return EINA_FALSE;
64
65 memcpy(f, file, len + 1);
66 if ((f[len - 1] == '/') || (f[len - 1] == '\\'))
67 f[len - 1] = '\0';
68
69 if (stat(f, &st) < 0)
70 return EINA_FALSE;
71#else
72 if (stat(file, &st) < 0)
73 return EINA_FALSE;
74#endif
75
76 if (mtime) *mtime = st.st_mtime;
77 if (size) *size = st.st_size;
78 if (mode) *mode = st.st_mode;
79 if (is_dir) *is_dir = S_ISDIR(st.st_mode);
80 if (is_reg) *is_reg = S_ISREG(st.st_mode);
81
82 return EINA_TRUE;
83}
84
33/* externally accessible functions */ 85/* externally accessible functions */
34 86
35/** 87/**
@@ -134,10 +186,12 @@ ecore_file_shutdown()
134EAPI long long 186EAPI long long
135ecore_file_mod_time(const char *file) 187ecore_file_mod_time(const char *file)
136{ 188{
137 struct stat st; 189 long long time;
190
191 if (!_ecore_file_stat(file, &time, NULL, NULL, NULL, NULL))
192 return 0;
138 193
139 if (stat(file, &st) < 0) return 0; 194 return time;
140 return st.st_mtime;
141} 195}
142 196
143/** 197/**
@@ -152,10 +206,12 @@ ecore_file_mod_time(const char *file)
152EAPI long long 206EAPI long long
153ecore_file_size(const char *file) 207ecore_file_size(const char *file)
154{ 208{
155 struct stat st; 209 long long size;
210
211 if (!_ecore_file_stat(file, NULL, &size, NULL, NULL, NULL))
212 return 0;
156 213
157 if (stat(file, &st) < 0) return 0; 214 return size;
158 return st.st_size;
159} 215}
160 216
161/** 217/**
@@ -170,12 +226,17 @@ ecore_file_size(const char *file)
170EAPI Eina_Bool 226EAPI Eina_Bool
171ecore_file_exists(const char *file) 227ecore_file_exists(const char *file)
172{ 228{
229#ifdef _WIN32
230 /* I prefer not touching the specific UNIX code... */
231 return _ecore_file_stat(file, NULL, NULL, NULL, NULL, NULL);
232#else
173 struct stat st; 233 struct stat st;
174 if (!file) return EINA_FALSE; 234 if (!file) return EINA_FALSE;
175 235
176 /*Workaround so that "/" returns a true, otherwise we can't monitor "/" in ecore_file_monitor*/ 236 /*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; 237 if (stat(file, &st) < 0 && strcmp(file, "/")) return EINA_FALSE;
178 return EINA_TRUE; 238 return EINA_TRUE;
239#endif
179} 240}
180 241
181/** 242/**
@@ -191,11 +252,12 @@ ecore_file_exists(const char *file)
191EAPI Eina_Bool 252EAPI Eina_Bool
192ecore_file_is_dir(const char *file) 253ecore_file_is_dir(const char *file)
193{ 254{
194 struct stat st; 255 Eina_Bool is_dir;
195 256
196 if (stat(file, &st) < 0) return EINA_FALSE; 257 if (!_ecore_file_stat(file, NULL, NULL, NULL, &is_dir, NULL))
197 if (S_ISDIR(st.st_mode)) return EINA_TRUE; 258 return EINA_FALSE;
198 return EINA_FALSE; 259
260 return is_dir;
199} 261}
200 262
201static mode_t default_mode = S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH; 263static mode_t default_mode = S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
@@ -299,16 +361,21 @@ ecore_file_mksubdirs(const char *base, const char **subdirs)
299 i = 0; 361 i = 0;
300 for (; *subdirs; subdirs++) 362 for (; *subdirs; subdirs++)
301 { 363 {
364#ifdef HAVE_ATFILE_SOURCE
302 struct stat st; 365 struct stat st;
366#endif
367 Eina_Bool is_dir;
303 368
304#ifndef HAVE_ATFILE_SOURCE 369#ifndef HAVE_ATFILE_SOURCE
305 eina_strlcpy(buf + baselen, *subdirs, sizeof(buf) - baselen); 370 eina_strlcpy(buf + baselen, *subdirs, sizeof(buf) - baselen);
306 if (stat(buf, &st) == 0) 371 if (_ecore_file_stat(buf, NULL, NULL, NULL, &is_dir, NULL))
372 {
307#else 373#else
308 if (fstatat(fd, *subdirs, &st, 0) == 0) 374 if (fstatat(fd, *subdirs, &st, 0) == 0)
309#endif
310 { 375 {
311 if (S_ISDIR(st.st_mode)) 376 is_dir = S_ISDIR(st.st_mode);
377#endif
378 if (is_dir)
312 { 379 {
313 i++; 380 i++;
314 continue; 381 continue;
@@ -399,21 +466,25 @@ ecore_file_remove(const char *file)
399EAPI Eina_Bool 466EAPI Eina_Bool
400ecore_file_recursive_rm(const char *dir) 467ecore_file_recursive_rm(const char *dir)
401{ 468{
469#ifndef _WIN32
402 struct stat st; 470 struct stat st;
471#endif
472 Eina_Bool is_dir;
403 473
404#ifdef _WIN32 474#ifdef _WIN32
405 char buf[PATH_MAX]; 475 char buf[PATH_MAX];
406 476
407 if (readlink(dir, buf, sizeof(buf) - 1) > 0) 477 if (readlink(dir, buf, sizeof(buf) - 1) > 0)
408 return ecore_file_unlink(dir); 478 return ecore_file_unlink(dir);
409 if (stat(dir, &st) == -1) 479 if (!_ecore_file_stat(buf, NULL, NULL, NULL, &is_dir, NULL))
410 return EINA_FALSE; 480 return EINA_FALSE;
411#else 481#else
412 if (lstat(dir, &st) == -1) 482 if (lstat(dir, &st) == -1)
413 return EINA_FALSE; 483 return EINA_FALSE;
484 is_dir = S_ISDIR(st.st_mode);
414#endif 485#endif
415 486
416 if (S_ISDIR(st.st_mode)) 487 if (is_dir)
417 { 488 {
418 Eina_File_Direct_Info *info; 489 Eina_File_Direct_Info *info;
419 Eina_Iterator *it; 490 Eina_Iterator *it;
@@ -443,7 +514,7 @@ ecore_file_recursive_rm(const char *dir)
443static inline Eina_Bool 514static inline Eina_Bool
444_ecore_file_mkpath_if_not_exists(const char *path) 515_ecore_file_mkpath_if_not_exists(const char *path)
445{ 516{
446 struct stat st; 517 Eina_Bool is_dir;
447 518
448 /* Windows: path like C: or D: etc are valid, but stat() returns an error */ 519 /* Windows: path like C: or D: etc are valid, but stat() returns an error */
449#ifdef _WIN32 520#ifdef _WIN32
@@ -454,9 +525,9 @@ _ecore_file_mkpath_if_not_exists(const char *path)
454 return EINA_TRUE; 525 return EINA_TRUE;
455#endif 526#endif
456 527
457 if (stat(path, &st) < 0) 528 if (!_ecore_file_stat(path, NULL, NULL, NULL, &is_dir, NULL))
458 return ecore_file_mkdir(path); 529 return ecore_file_mkdir(path);
459 else if (!S_ISDIR(st.st_mode)) 530 else if (!is_dir)
460 return EINA_FALSE; 531 return EINA_FALSE;
461 else 532 else
462 return EINA_TRUE; 533 return EINA_TRUE;
@@ -587,13 +658,14 @@ ecore_file_mv(const char *src, const char *dst)
587 // it resides on a different mount point. 658 // it resides on a different mount point.
588 if (errno == EXDEV) 659 if (errno == EXDEV)
589 { 660 {
590 struct stat st; 661 mode_t mode;
662 Eina_Bool is_reg;
591 663
592 // Make sure this is a regular file before 664 // Make sure this is a regular file before
593 // we do anything fancy. 665 // we do anything fancy.
594 if (stat(src, &st) == -1) 666 if (!_ecore_file_stat(src, NULL, NULL, &mode, NULL, &is_reg))
595 goto FAIL; 667 goto FAIL;
596 if (S_ISREG(st.st_mode)) 668 if (is_reg)
597 { 669 {
598 char *dir; 670 char *dir;
599 671
@@ -613,7 +685,7 @@ ecore_file_mv(const char *src, const char *dst)
613 goto FAIL; 685 goto FAIL;
614 686
615 // Set file permissions of temp file to match src 687 // Set file permissions of temp file to match src
616 if (chmod(buf, st.st_mode) == -1) goto FAIL; 688 if (chmod(buf, mode) == -1) goto FAIL;
617 689
618 // Try to atomically move temp file to dst 690 // Try to atomically move temp file to dst
619 if (rename(buf, dst)) 691 if (rename(buf, dst))