aboutsummaryrefslogtreecommitdiffstats
path: root/src/lib/ecore_file/ecore_file.c
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/ecore_file.c
parentecore_exe: close handles only if they are valid (diff)
downloadefl-b9ed3375f2d9a822d83a383ff3d6691470b1c348.tar.gz
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 '')
-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 @@
#include "ecore_file_private.h"
+/*
+ * FIXME: the following functions will certainly not work on Windows:
+ * ecore_file_file_get()
+ * ecore_file_app_exe_get()
+ * ecore_file_escape_name()
+ */
+
int _ecore_file_log_dom = -1;
static int _ecore_file_init_count = 0;
+static Eina_Bool
+_ecore_file_stat(const char *file,
+ long long *mtime,
+ long long *size,
+ mode_t *mode,
+ Eina_Bool *is_dir,
+ Eina_Bool *is_reg)
+{
+ struct stat st;
+#ifdef _WIN32
+ /*
+ * On Windows, stat() returns -1 is file is a path finishing with
+ * a slash or blackslash
+ * see https://msdn.microsoft.com/en-us/library/14h5k7ff.aspx
+ * ("Return Value" section)
+ *
+ * so we ensure that file never finishes with \ or /
+ */
+ char f[MAX_PATH];
+ size_t len;
+
+ len = strlen(file);
+ if ((len + 1) > MAX_PATH)
+ return EINA_FALSE;
+
+ memcpy(f, file, len + 1);
+ if ((f[len - 1] == '/') || (f[len - 1] == '\\'))
+ f[len - 1] = '\0';
+
+ if (stat(f, &st) < 0)
+ return EINA_FALSE;
+#else
+ if (stat(file, &st) < 0)
+ return EINA_FALSE;
+#endif
+
+ if (mtime) *mtime = st.st_mtime;
+ if (size) *size = st.st_size;
+ if (mode) *mode = st.st_mode;
+ if (is_dir) *is_dir = S_ISDIR(st.st_mode);
+ if (is_reg) *is_reg = S_ISREG(st.st_mode);
+
+ return EINA_TRUE;
+}
+
/* externally accessible functions */
/**
@@ -134,10 +186,12 @@ ecore_file_shutdown()
EAPI long long
ecore_file_mod_time(const char *file)
{
- struct stat st;
+ long long time;
+
+ if (!_ecore_file_stat(file, &time, NULL, NULL, NULL, NULL))
+ return 0;
- if (stat(file, &st) < 0) return 0;
- return st.st_mtime;
+ return time;
}
/**
@@ -152,10 +206,12 @@ ecore_file_mod_time(const char *file)
EAPI long long
ecore_file_size(const char *file)
{
- struct stat st;
+ long long size;
+
+ if (!_ecore_file_stat(file, NULL, &size, NULL, NULL, NULL))
+ return 0;
- if (stat(file, &st) < 0) return 0;
- return st.st_size;
+ return size;
}
/**
@@ -170,12 +226,17 @@ ecore_file_size(const char *file)
EAPI Eina_Bool
ecore_file_exists(const char *file)
{
+#ifdef _WIN32
+ /* I prefer not touching the specific UNIX code... */
+ return _ecore_file_stat(file, NULL, NULL, NULL, NULL, NULL);
+#else
struct stat st;
if (!file) return EINA_FALSE;
/*Workaround so that "/" returns a true, otherwise we can't monitor "/" in ecore_file_monitor*/
if (stat(file, &st) < 0 && strcmp(file, "/")) return EINA_FALSE;
return EINA_TRUE;
+#endif
}
/**
@@ -191,11 +252,12 @@ ecore_file_exists(const char *file)
EAPI Eina_Bool
ecore_file_is_dir(const char *file)
{
- struct stat st;
+ Eina_Bool is_dir;
- if (stat(file, &st) < 0) return EINA_FALSE;
- if (S_ISDIR(st.st_mode)) return EINA_TRUE;
- return EINA_FALSE;
+ if (!_ecore_file_stat(file, NULL, NULL, NULL, &is_dir, NULL))
+ return EINA_FALSE;
+
+ return is_dir;
}
static 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)
i = 0;
for (; *subdirs; subdirs++)
{
+#ifdef HAVE_ATFILE_SOURCE
struct stat st;
+#endif
+ Eina_Bool is_dir;
#ifndef HAVE_ATFILE_SOURCE
eina_strlcpy(buf + baselen, *subdirs, sizeof(buf) - baselen);
- if (stat(buf, &st) == 0)
+ if (_ecore_file_stat(buf, NULL, NULL, NULL, &is_dir, NULL))
+ {
#else
if (fstatat(fd, *subdirs, &st, 0) == 0)
-#endif
{
- if (S_ISDIR(st.st_mode))
+ is_dir = S_ISDIR(st.st_mode);
+#endif
+ if (is_dir)
{
i++;
continue;
@@ -399,21 +466,25 @@ ecore_file_remove(const char *file)
EAPI Eina_Bool
ecore_file_recursive_rm(const char *dir)
{
+#ifndef _WIN32
struct stat st;
+#endif
+ Eina_Bool is_dir;
#ifdef _WIN32
char buf[PATH_MAX];
if (readlink(dir, buf, sizeof(buf) - 1) > 0)
return ecore_file_unlink(dir);
- if (stat(dir, &st) == -1)
+ if (!_ecore_file_stat(buf, NULL, NULL, NULL, &is_dir, NULL))
return EINA_FALSE;
#else
if (lstat(dir, &st) == -1)
return EINA_FALSE;
+ is_dir = S_ISDIR(st.st_mode);
#endif
- if (S_ISDIR(st.st_mode))
+ if (is_dir)
{
Eina_File_Direct_Info *info;
Eina_Iterator *it;
@@ -443,7 +514,7 @@ ecore_file_recursive_rm(const char *dir)
static inline Eina_Bool
_ecore_file_mkpath_if_not_exists(const char *path)
{
- struct stat st;
+ Eina_Bool is_dir;
/* Windows: path like C: or D: etc are valid, but stat() returns an error */
#ifdef _WIN32
@@ -454,9 +525,9 @@ _ecore_file_mkpath_if_not_exists(const char *path)
return EINA_TRUE;
#endif
- if (stat(path, &st) < 0)
+ if (!_ecore_file_stat(path, NULL, NULL, NULL, &is_dir, NULL))
return ecore_file_mkdir(path);
- else if (!S_ISDIR(st.st_mode))
+ else if (!is_dir)
return EINA_FALSE;
else
return EINA_TRUE;
@@ -587,13 +658,14 @@ ecore_file_mv(const char *src, const char *dst)
// it resides on a different mount point.
if (errno == EXDEV)
{
- struct stat st;
+ mode_t mode;
+ Eina_Bool is_reg;
// Make sure this is a regular file before
// we do anything fancy.
- if (stat(src, &st) == -1)
+ if (!_ecore_file_stat(src, NULL, NULL, &mode, NULL, &is_reg))
goto FAIL;
- if (S_ISREG(st.st_mode))
+ if (is_reg)
{
char *dir;
@@ -613,7 +685,7 @@ ecore_file_mv(const char *src, const char *dst)
goto FAIL;
// Set file permissions of temp file to match src
- if (chmod(buf, st.st_mode) == -1) goto FAIL;
+ if (chmod(buf, mode) == -1) goto FAIL;
// Try to atomically move temp file to dst
if (rename(buf, dst))