2008-05-25 22:16:34 -07:00
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
# include <config.h>
|
|
|
|
#endif
|
2008-01-25 21:40:53 -08:00
|
|
|
|
2011-12-06 08:09:05 -08:00
|
|
|
#include <stdlib.h>
|
2009-01-31 10:33:39 -08:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <string.h>
|
2010-04-05 01:26:48 -07:00
|
|
|
|
2011-01-07 07:56:54 -08:00
|
|
|
#ifndef _MSC_VER
|
2010-04-05 01:26:48 -07:00
|
|
|
# include <unistd.h>
|
|
|
|
# include <libgen.h>
|
|
|
|
#endif
|
2009-01-31 10:33:39 -08:00
|
|
|
|
2011-11-21 12:20:39 -08:00
|
|
|
#ifdef _WIN32
|
|
|
|
# include <direct.h>
|
|
|
|
#endif
|
|
|
|
|
2008-01-25 21:40:53 -08:00
|
|
|
#ifdef HAVE_FEATURES_H
|
2007-09-09 03:26:37 -07:00
|
|
|
# include <features.h>
|
2007-06-05 14:52:15 -07:00
|
|
|
#endif
|
2005-09-29 17:46:15 -07:00
|
|
|
#include <ctype.h>
|
2007-02-04 05:14:16 -08:00
|
|
|
#include <errno.h>
|
2005-02-20 04:17:07 -08:00
|
|
|
|
2011-11-20 08:52:21 -08:00
|
|
|
#ifdef HAVE_ATFILE_SOURCE
|
|
|
|
# include <dirent.h>
|
|
|
|
#endif
|
|
|
|
|
2008-05-25 22:16:34 -07:00
|
|
|
#include "ecore_file_private.h"
|
2007-09-09 03:26:37 -07:00
|
|
|
|
2009-12-21 09:32:19 -08:00
|
|
|
int _ecore_file_log_dom = -1;
|
2009-10-09 22:28:43 -07:00
|
|
|
static int _ecore_file_init_count = 0;
|
2005-09-07 01:50:25 -07:00
|
|
|
|
2005-02-20 04:17:07 -08:00
|
|
|
/* externally accessible functions */
|
2010-10-23 04:05:36 -07:00
|
|
|
|
|
|
|
/**
|
2011-01-27 12:40:02 -08:00
|
|
|
* @addtogroup Ecore_File_Group Ecore_File - Files and directories convenience functions
|
2010-10-23 04:05:36 -07:00
|
|
|
*
|
|
|
|
* @{
|
|
|
|
*/
|
|
|
|
|
2007-08-10 07:15:14 -07:00
|
|
|
/**
|
2010-10-23 04:05:36 -07:00
|
|
|
* @brief Initialize the Ecore_File library.
|
|
|
|
*
|
|
|
|
* @return 1 or greater on success, 0 on error.
|
|
|
|
*
|
|
|
|
* This function sets up Ecore_File and the services it will use
|
|
|
|
* (monitoring, downloading, PATH related feature). It returns 0 on
|
|
|
|
* failure, otherwise it returns the number of times it has already
|
|
|
|
* been called.
|
|
|
|
*
|
|
|
|
* When Ecore_File is not used anymore, call ecore_file_shutdown()
|
|
|
|
* to shut down the Ecore_File library.
|
2007-08-10 07:15:14 -07:00
|
|
|
*/
|
2006-01-06 10:46:30 -08:00
|
|
|
EAPI int
|
2005-02-20 04:17:07 -08:00
|
|
|
ecore_file_init()
|
|
|
|
{
|
2009-10-09 22:28:43 -07:00
|
|
|
if (++_ecore_file_init_count != 1)
|
|
|
|
return _ecore_file_init_count;
|
2011-06-03 09:06:57 -07:00
|
|
|
|
|
|
|
if (!ecore_init())
|
|
|
|
return --_ecore_file_init_count;
|
|
|
|
|
2010-10-07 15:31:46 -07:00
|
|
|
_ecore_file_log_dom = eina_log_domain_register
|
|
|
|
("ecore_file", ECORE_FILE_DEFAULT_LOG_COLOR);
|
|
|
|
if(_ecore_file_log_dom < 0)
|
2009-12-21 09:32:19 -08:00
|
|
|
{
|
|
|
|
EINA_LOG_ERR("Impossible to create a log domain for the ecore file module.");
|
|
|
|
return --_ecore_file_init_count;
|
|
|
|
}
|
2009-10-09 22:28:43 -07:00
|
|
|
ecore_file_path_init();
|
|
|
|
ecore_file_monitor_init();
|
|
|
|
ecore_file_download_init();
|
|
|
|
|
|
|
|
/* FIXME: were the tests disabled for a good reason ? */
|
|
|
|
|
|
|
|
/*
|
|
|
|
if (!ecore_file_monitor_init())
|
|
|
|
goto shutdown_ecore_file_path;
|
|
|
|
|
|
|
|
if (!ecore_file_download_init())
|
|
|
|
goto shutdown_ecore_file_monitor;
|
|
|
|
*/
|
|
|
|
|
|
|
|
return _ecore_file_init_count;
|
|
|
|
|
|
|
|
/*
|
|
|
|
shutdown_ecore_file_monitor:
|
2005-09-07 01:50:25 -07:00
|
|
|
ecore_file_monitor_shutdown();
|
2009-10-09 22:28:43 -07:00
|
|
|
shutdown_ecore_file_path:
|
2005-09-07 01:50:25 -07:00
|
|
|
ecore_file_path_shutdown();
|
|
|
|
|
2009-10-09 22:28:43 -07:00
|
|
|
return --_ecore_file_init_count;
|
|
|
|
*/
|
2005-02-20 04:17:07 -08:00
|
|
|
}
|
|
|
|
|
2007-08-10 07:15:14 -07:00
|
|
|
/**
|
2010-10-23 04:05:36 -07:00
|
|
|
* @brief Shut down the Ecore_File library.
|
|
|
|
*
|
|
|
|
* @return 0 when the library is completely shut down, 1 or
|
|
|
|
* greater otherwise.
|
|
|
|
*
|
|
|
|
* This function shuts down the Ecore_File library. It returns 0 when it has
|
|
|
|
* been called the same number of times than ecore_file_init(). In that case
|
|
|
|
* it shuts down all the services it uses.
|
2007-08-10 07:15:14 -07:00
|
|
|
*/
|
2006-01-06 10:46:30 -08:00
|
|
|
EAPI int
|
2005-02-20 04:17:07 -08:00
|
|
|
ecore_file_shutdown()
|
|
|
|
{
|
2009-10-09 22:28:43 -07:00
|
|
|
if (--_ecore_file_init_count != 0)
|
|
|
|
return _ecore_file_init_count;
|
2005-09-07 01:50:25 -07:00
|
|
|
|
2009-10-09 22:28:43 -07:00
|
|
|
ecore_file_download_shutdown();
|
2005-09-07 01:50:25 -07:00
|
|
|
ecore_file_monitor_shutdown();
|
|
|
|
ecore_file_path_shutdown();
|
2011-06-03 09:06:57 -07:00
|
|
|
|
2009-12-21 09:32:19 -08:00
|
|
|
eina_log_domain_unregister(_ecore_file_log_dom);
|
|
|
|
_ecore_file_log_dom = -1;
|
2011-06-03 09:06:57 -07:00
|
|
|
|
|
|
|
ecore_shutdown();
|
|
|
|
|
2009-10-09 22:28:43 -07:00
|
|
|
return _ecore_file_init_count;
|
2005-02-20 04:17:07 -08:00
|
|
|
}
|
|
|
|
|
2007-08-10 07:15:14 -07:00
|
|
|
/**
|
2010-10-23 04:05:36 -07:00
|
|
|
* @brief Get the time of the last modification to the given file.
|
|
|
|
*
|
|
|
|
* @param file The name of the file.
|
|
|
|
* @return Return the time of the last data modification, or 0 on
|
|
|
|
* failure.
|
|
|
|
*
|
|
|
|
* This function returns the time of the last modification of
|
|
|
|
* @p file. On failure, it returns 0.
|
2007-08-10 07:15:14 -07:00
|
|
|
*/
|
2007-06-02 09:33:43 -07:00
|
|
|
EAPI long long
|
2005-02-21 08:03:08 -08:00
|
|
|
ecore_file_mod_time(const char *file)
|
2005-02-20 04:17:07 -08:00
|
|
|
{
|
|
|
|
struct stat st;
|
|
|
|
|
|
|
|
if (stat(file, &st) < 0) return 0;
|
|
|
|
return st.st_mtime;
|
|
|
|
}
|
|
|
|
|
2007-08-06 13:00:28 -07:00
|
|
|
/**
|
2010-10-23 04:05:36 -07:00
|
|
|
* @brief Get the size of the given file.
|
|
|
|
*
|
|
|
|
* @param file The name of the file.
|
|
|
|
* @return Return the size of the file in bytes, or 0 on failure.
|
|
|
|
*
|
|
|
|
* This function returns the size of @p file in bytes. On failure, it
|
|
|
|
* returns 0.
|
2007-08-06 13:00:28 -07:00
|
|
|
*/
|
2007-06-02 09:33:43 -07:00
|
|
|
EAPI long long
|
2005-12-08 16:02:21 -08:00
|
|
|
ecore_file_size(const char *file)
|
|
|
|
{
|
|
|
|
struct stat st;
|
|
|
|
|
|
|
|
if (stat(file, &st) < 0) return 0;
|
|
|
|
return st.st_size;
|
|
|
|
}
|
|
|
|
|
2007-08-06 13:00:28 -07:00
|
|
|
/**
|
2010-10-23 04:05:36 -07:00
|
|
|
* @brief Check if the given file exists.
|
|
|
|
*
|
|
|
|
* @param file The name of the file.
|
2012-04-11 20:51:36 -07:00
|
|
|
* @return @c EINA_TRUE if the @p file exists, @c EINA_FALSE otherwise.
|
2010-10-23 04:05:36 -07:00
|
|
|
*
|
2012-04-11 20:51:36 -07:00
|
|
|
* This function returns @c EINA_TRUE if @p file exists on local filesystem,
|
|
|
|
* @c EINA_FALSE otherwise.
|
2007-08-06 13:00:28 -07:00
|
|
|
*/
|
2010-06-10 04:57:12 -07:00
|
|
|
EAPI Eina_Bool
|
2005-02-21 08:03:08 -08:00
|
|
|
ecore_file_exists(const char *file)
|
2005-02-20 04:17:07 -08:00
|
|
|
{
|
|
|
|
struct stat st;
|
2011-03-28 19:28:41 -07:00
|
|
|
if (!file) return EINA_FALSE;
|
2005-02-20 04:17:07 -08:00
|
|
|
|
2005-08-26 21:17:36 -07:00
|
|
|
/*Workaround so that "/" returns a true, otherwise we can't monitor "/" in ecore_file_monitor*/
|
2010-06-10 04:57:12 -07:00
|
|
|
if (stat(file, &st) < 0 && strcmp(file, "/")) return EINA_FALSE;
|
|
|
|
return EINA_TRUE;
|
2005-02-20 04:17:07 -08:00
|
|
|
}
|
|
|
|
|
2007-08-06 13:00:28 -07:00
|
|
|
/**
|
2010-10-23 04:05:36 -07:00
|
|
|
* @brief Check if the given file is a directory.
|
|
|
|
*
|
|
|
|
* @param file The name of the file.
|
2012-04-11 20:51:36 -07:00
|
|
|
* @return @c EINA_TRUE if the file exists and is a directory, @c EINA_FALSE
|
|
|
|
* otherwise.
|
2010-10-23 04:05:36 -07:00
|
|
|
*
|
2012-04-11 20:51:36 -07:00
|
|
|
* This function returns @c EINA_TRUE if @p file exists exists and is a
|
|
|
|
* directory on local filesystem, @c EINA_FALSE otherwise.
|
2007-08-06 13:00:28 -07:00
|
|
|
*/
|
2010-06-10 04:57:12 -07:00
|
|
|
EAPI Eina_Bool
|
2005-02-21 08:03:08 -08:00
|
|
|
ecore_file_is_dir(const char *file)
|
2005-02-20 04:17:07 -08:00
|
|
|
{
|
|
|
|
struct stat st;
|
|
|
|
|
2010-06-10 04:57:12 -07:00
|
|
|
if (stat(file, &st) < 0) return EINA_FALSE;
|
|
|
|
if (S_ISDIR(st.st_mode)) return EINA_TRUE;
|
|
|
|
return EINA_FALSE;
|
2005-02-20 04:17:07 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
static mode_t default_mode = S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
|
2008-05-25 22:16:34 -07:00
|
|
|
|
2007-08-06 13:00:28 -07:00
|
|
|
/**
|
2010-10-23 04:05:36 -07:00
|
|
|
* @brief Create a new directory.
|
|
|
|
*
|
2007-08-06 13:00:28 -07:00
|
|
|
* @param dir The name of the directory to create
|
2012-04-11 20:51:36 -07:00
|
|
|
* @return @c EINA_TRUE on successful creation, @c EINA_FALSE otherwise.
|
2007-08-06 13:00:28 -07:00
|
|
|
*
|
2010-10-23 04:05:36 -07:00
|
|
|
* This function creates the directory @p dir with the mode S_IRUSR |
|
|
|
|
* S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH. On
|
2012-04-11 20:51:36 -07:00
|
|
|
* success, it returns @c EINA_TRUE, @c EINA_FALSE otherwise.
|
2007-08-06 13:00:28 -07:00
|
|
|
*/
|
2010-06-10 04:57:12 -07:00
|
|
|
EAPI Eina_Bool
|
2005-02-21 08:03:08 -08:00
|
|
|
ecore_file_mkdir(const char *dir)
|
2005-02-20 04:17:07 -08:00
|
|
|
{
|
2010-06-10 04:57:12 -07:00
|
|
|
if (mkdir(dir, default_mode) < 0) return EINA_FALSE;
|
|
|
|
return EINA_TRUE;
|
2005-02-20 04:17:07 -08:00
|
|
|
}
|
|
|
|
|
2009-04-10 23:13:02 -07:00
|
|
|
/**
|
2010-10-23 04:05:36 -07:00
|
|
|
* @brief Create complete directory in a batch.
|
2009-04-10 23:13:02 -07:00
|
|
|
*
|
2010-10-23 04:05:36 -07:00
|
|
|
* @param dirs The list of directories, null terminated.
|
|
|
|
* @return The number of successful directories created, -1 if dirs is
|
|
|
|
* @c NULL.
|
2009-04-10 23:13:02 -07:00
|
|
|
*
|
2010-10-23 04:05:36 -07:00
|
|
|
* This function creates all the directories that are in the null
|
|
|
|
* terminated array @p dirs. The function loops over the directories
|
|
|
|
* and call ecore_file_mkdir(). This function returns -1 if @p dirs is
|
|
|
|
* @c NULL, otherwise if returns the number of suceesfully created
|
|
|
|
* directories.
|
2009-04-10 23:13:02 -07:00
|
|
|
*/
|
|
|
|
EAPI int
|
|
|
|
ecore_file_mkdirs(const char **dirs)
|
|
|
|
{
|
|
|
|
int i = 0;
|
2010-01-03 13:50:23 -08:00
|
|
|
|
2010-04-05 01:26:48 -07:00
|
|
|
if (!dirs) return -1;
|
|
|
|
|
2010-08-21 06:52:25 -07:00
|
|
|
for (; *dirs; dirs++)
|
2009-04-10 23:13:02 -07:00
|
|
|
if (ecore_file_mkdir(*dirs))
|
|
|
|
i++;
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
|
2009-04-11 00:10:12 -07:00
|
|
|
/**
|
2010-10-23 04:05:36 -07:00
|
|
|
* @brief Create complete list of sub-directories in a batch (optimized).
|
2009-04-11 00:10:12 -07:00
|
|
|
*
|
2010-10-23 04:05:36 -07:00
|
|
|
* @param base The base directory to act on.
|
|
|
|
* @param subdirs The list of directories, null terminated.
|
|
|
|
* @return number of successful directories created, -1 on failure.
|
2009-04-11 00:10:12 -07:00
|
|
|
*
|
2010-10-23 04:05:36 -07:00
|
|
|
* This function creates all the directories that are in the null
|
|
|
|
* terminated array @p dirs in the @p base directory. If @p base does
|
|
|
|
* not exist, it will be created. The function loops over the directories
|
|
|
|
* and call ecore_file_mkdir(). The whole path of the directories must
|
|
|
|
* exist. So if base/a/b/c wants to be created, @p subdirs must
|
|
|
|
* contain "a", "a/b" and "a/b/c", in that order. This function
|
|
|
|
* returns -1 if @p dirs or @p base are @c NULL, or if @p base is
|
|
|
|
* empty ("\0"). It returns 0 is @p base is not a directory or
|
|
|
|
* invalid, or if it can't be created. Otherwise if returns the number
|
2011-04-20 07:15:33 -07:00
|
|
|
* of suceesfully created directories.
|
2009-04-11 00:10:12 -07:00
|
|
|
*/
|
|
|
|
EAPI int
|
|
|
|
ecore_file_mksubdirs(const char *base, const char **subdirs)
|
|
|
|
{
|
|
|
|
#ifndef HAVE_ATFILE_SOURCE
|
|
|
|
char buf[PATH_MAX];
|
|
|
|
int baselen;
|
|
|
|
#else
|
|
|
|
int fd;
|
|
|
|
DIR *dir;
|
|
|
|
#endif
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if (!subdirs) return -1;
|
|
|
|
if ((!base) || (base[0] == '\0')) return -1;
|
|
|
|
|
|
|
|
if ((!ecore_file_is_dir(base)) && (!ecore_file_mkpath(base)))
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
#ifndef HAVE_ATFILE_SOURCE
|
2010-01-27 12:59:26 -08:00
|
|
|
baselen = eina_strlcpy(buf, base, sizeof(buf));
|
2009-04-11 00:10:12 -07:00
|
|
|
if ((baselen < 1) || (baselen + 1 >= (int)sizeof(buf)))
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (buf[baselen - 1] != '/')
|
|
|
|
{
|
2010-09-30 00:25:06 -07:00
|
|
|
buf[baselen] = '/';
|
|
|
|
baselen++;
|
2009-04-11 00:10:12 -07:00
|
|
|
}
|
|
|
|
#else
|
|
|
|
dir = opendir(base);
|
|
|
|
if (!dir)
|
|
|
|
return 0;
|
|
|
|
fd = dirfd(dir);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
i = 0;
|
2010-08-21 06:52:25 -07:00
|
|
|
for (; *subdirs; subdirs++)
|
2009-04-11 00:10:12 -07:00
|
|
|
{
|
2010-09-30 00:25:06 -07:00
|
|
|
struct stat st;
|
2009-04-11 00:10:12 -07:00
|
|
|
|
|
|
|
#ifndef HAVE_ATFILE_SOURCE
|
2010-09-30 00:25:06 -07:00
|
|
|
eina_strlcpy(buf + baselen, *subdirs, sizeof(buf) - baselen);
|
|
|
|
if (stat(buf, &st) == 0)
|
2009-04-11 00:10:12 -07:00
|
|
|
#else
|
2010-09-30 00:25:06 -07:00
|
|
|
if (fstatat(fd, *subdirs, &st, 0) == 0)
|
2009-04-11 00:10:12 -07:00
|
|
|
#endif
|
2010-09-30 00:25:06 -07:00
|
|
|
{
|
|
|
|
if (S_ISDIR(st.st_mode))
|
|
|
|
{
|
|
|
|
i++;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (errno == ENOENT)
|
|
|
|
{
|
2009-04-11 00:10:12 -07:00
|
|
|
#ifndef HAVE_ATFILE_SOURCE
|
2010-09-30 00:25:06 -07:00
|
|
|
if (mkdir(buf, default_mode) == 0)
|
2009-04-11 00:10:12 -07:00
|
|
|
#else
|
2010-09-30 00:25:06 -07:00
|
|
|
if (mkdirat(fd, *subdirs, default_mode) == 0)
|
2009-04-11 00:10:12 -07:00
|
|
|
#endif
|
2010-09-30 00:25:06 -07:00
|
|
|
{
|
|
|
|
i++;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2009-04-11 00:10:12 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef HAVE_ATFILE_SOURCE
|
|
|
|
closedir(dir);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
|
2007-08-06 13:00:28 -07:00
|
|
|
/**
|
2010-10-23 04:05:36 -07:00
|
|
|
* @brief Delete the given directory.
|
|
|
|
*
|
|
|
|
* @param dir The name of the directory to delete.
|
2012-04-11 20:51:36 -07:00
|
|
|
* @return @c EINA_TRUE on success, @c EINA_FALSE otherwise.
|
2010-10-23 04:05:36 -07:00
|
|
|
*
|
2012-04-11 20:51:36 -07:00
|
|
|
* This function deletes @p dir. It returns @c EINA_TRUE on success,
|
|
|
|
* @c EINA_FALSE otherwise.
|
2007-08-06 13:00:28 -07:00
|
|
|
*/
|
2010-06-10 04:57:12 -07:00
|
|
|
EAPI Eina_Bool
|
2005-04-28 14:53:36 -07:00
|
|
|
ecore_file_rmdir(const char *dir)
|
|
|
|
{
|
2010-06-10 04:57:12 -07:00
|
|
|
if (rmdir(dir) < 0) return EINA_FALSE;
|
|
|
|
return EINA_TRUE;
|
2005-04-28 14:53:36 -07:00
|
|
|
}
|
|
|
|
|
2007-08-06 13:00:28 -07:00
|
|
|
/**
|
2010-10-23 04:05:36 -07:00
|
|
|
* @brief Delete the given file.
|
|
|
|
*
|
|
|
|
* @param file The name of the file to delete.
|
2012-04-11 20:51:36 -07:00
|
|
|
* @return @c EINA_TRUE on success, @c EINA_FALSE otherwise.
|
2010-10-23 04:05:36 -07:00
|
|
|
*
|
2012-04-11 20:51:36 -07:00
|
|
|
* This function deletes @p file. It returns @c EINA_TRUE on success,
|
|
|
|
* @c EINA_FALSE otherwise.
|
2007-08-06 13:00:28 -07:00
|
|
|
*/
|
2010-06-10 04:57:12 -07:00
|
|
|
EAPI Eina_Bool
|
2005-04-28 14:53:36 -07:00
|
|
|
ecore_file_unlink(const char *file)
|
|
|
|
{
|
2010-06-10 04:57:12 -07:00
|
|
|
if (unlink(file) < 0) return EINA_FALSE;
|
|
|
|
return EINA_TRUE;
|
2005-04-28 14:53:36 -07:00
|
|
|
}
|
|
|
|
|
2009-12-19 11:09:37 -08:00
|
|
|
/**
|
2010-10-23 04:05:36 -07:00
|
|
|
* @brief Remove the given file or directory.
|
|
|
|
*
|
|
|
|
* @param file The name of the file or directory to delete.
|
2012-04-11 20:51:36 -07:00
|
|
|
* @return @c EINA_TRUE on success, @c EINA_FALSE otherwise.
|
2010-10-23 04:05:36 -07:00
|
|
|
*
|
2012-04-11 20:51:36 -07:00
|
|
|
* This function removes @p file. It returns @c EINA_TRUE on success,
|
|
|
|
* @c EINA_FALSE otherwise.
|
2009-12-19 11:09:37 -08:00
|
|
|
*/
|
2010-06-10 04:57:12 -07:00
|
|
|
EAPI Eina_Bool
|
2009-12-19 11:09:37 -08:00
|
|
|
ecore_file_remove(const char *file)
|
|
|
|
{
|
2010-06-10 04:57:12 -07:00
|
|
|
if (remove(file) < 0) return EINA_FALSE;
|
|
|
|
return EINA_TRUE;
|
2009-12-19 11:09:37 -08:00
|
|
|
}
|
|
|
|
|
2007-08-06 13:00:28 -07:00
|
|
|
/**
|
2010-10-23 04:05:36 -07:00
|
|
|
* @brief Delete the given directory and all its contents.
|
2007-09-09 03:26:37 -07:00
|
|
|
*
|
2010-10-23 04:05:36 -07:00
|
|
|
* @param dir The name of the directory to delete.
|
2012-04-11 20:51:36 -07:00
|
|
|
* @return @c EINA_TRUE on success, @c EINA_FALSE otherwise.
|
2010-10-23 04:05:36 -07:00
|
|
|
*
|
|
|
|
* This function delete @p dir and all its contents. If @p dir is a
|
2012-04-11 20:51:36 -07:00
|
|
|
* link only the link is removed. It returns @c EINA_TRUE on success,
|
|
|
|
* @c EINA_FALSE otherwise.
|
2007-08-06 13:00:28 -07:00
|
|
|
*/
|
2010-06-10 04:57:12 -07:00
|
|
|
EAPI Eina_Bool
|
2005-10-23 16:21:29 -07:00
|
|
|
ecore_file_recursive_rm(const char *dir)
|
2005-10-24 03:05:35 -07:00
|
|
|
{
|
2011-11-20 07:14:48 -08:00
|
|
|
Eina_Iterator *it;
|
|
|
|
char buf[PATH_MAX];
|
2010-01-03 13:50:23 -08:00
|
|
|
struct stat st;
|
|
|
|
int ret;
|
2005-10-24 03:05:35 -07:00
|
|
|
|
2012-09-07 23:21:42 -07:00
|
|
|
if (readlink(dir, buf, sizeof(buf) - 1) > 0)
|
2010-01-03 13:50:23 -08:00
|
|
|
return ecore_file_unlink(dir);
|
2007-09-09 03:26:37 -07:00
|
|
|
|
2006-10-15 02:32:25 -07:00
|
|
|
ret = stat(dir, &st);
|
|
|
|
if ((ret == 0) && (S_ISDIR(st.st_mode)))
|
2006-08-31 01:53:38 -07:00
|
|
|
{
|
2011-11-20 07:14:48 -08:00
|
|
|
Eina_File_Direct_Info *info;
|
|
|
|
|
2010-09-30 00:25:06 -07:00
|
|
|
ret = 1;
|
2011-11-20 07:14:48 -08:00
|
|
|
if (stat(dir, &st) == -1) return EINA_FALSE; /* WOOT: WHY ARE WE CALLING STAT TWO TIMES ??? */
|
|
|
|
|
|
|
|
it = eina_file_direct_ls(dir);
|
|
|
|
EINA_ITERATOR_FOREACH(it, info)
|
2010-09-30 00:25:06 -07:00
|
|
|
{
|
2011-11-20 07:14:48 -08:00
|
|
|
if (!ecore_file_recursive_rm(info->path))
|
|
|
|
ret = 0;
|
2010-09-30 00:25:06 -07:00
|
|
|
}
|
2011-11-20 07:14:48 -08:00
|
|
|
eina_iterator_free(it);
|
|
|
|
|
2010-09-30 00:25:06 -07:00
|
|
|
if (!ecore_file_rmdir(dir)) ret = 0;
|
2010-06-10 04:57:12 -07:00
|
|
|
if (ret)
|
|
|
|
return EINA_TRUE;
|
|
|
|
else
|
|
|
|
return EINA_FALSE;
|
2006-08-31 01:53:38 -07:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2010-09-30 00:25:06 -07:00
|
|
|
if (ret == -1) return EINA_FALSE;
|
|
|
|
return ecore_file_unlink(dir);
|
2005-10-23 16:21:29 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-06-10 04:57:12 -07:00
|
|
|
static inline Eina_Bool
|
2009-04-10 23:33:00 -07:00
|
|
|
_ecore_file_mkpath_if_not_exists(const char *path)
|
|
|
|
{
|
|
|
|
struct stat st;
|
2010-01-03 13:50:23 -08:00
|
|
|
|
2010-11-26 05:47:51 -08:00
|
|
|
/* Windows: path like C: or D: etc are valid, but stat() returns an error */
|
|
|
|
#ifdef _WIN32
|
|
|
|
if ((strlen(path) == 2) &&
|
|
|
|
((path[0] >= 'a' && path[0] <= 'z') ||
|
|
|
|
(path[0] >= 'A' && path[0] <= 'Z')) &&
|
|
|
|
(path[1] == ':'))
|
|
|
|
return EINA_TRUE;
|
|
|
|
#endif
|
|
|
|
|
2009-04-10 23:33:00 -07:00
|
|
|
if (stat(path, &st) < 0)
|
|
|
|
return ecore_file_mkdir(path);
|
|
|
|
else if (!S_ISDIR(st.st_mode))
|
2010-06-10 04:57:12 -07:00
|
|
|
return EINA_FALSE;
|
2009-04-10 23:33:00 -07:00
|
|
|
else
|
2010-06-10 04:57:12 -07:00
|
|
|
return EINA_TRUE;
|
2009-04-10 23:33:00 -07:00
|
|
|
}
|
|
|
|
|
2007-08-06 13:00:28 -07:00
|
|
|
/**
|
2010-10-23 04:05:36 -07:00
|
|
|
* @brief Create a complete path.
|
|
|
|
*
|
2007-08-06 13:00:28 -07:00
|
|
|
* @param path The path to create
|
2012-04-11 20:51:36 -07:00
|
|
|
* @return @c EINA_TRUE on success, @c EINA_FALSE otherwise.
|
2009-04-10 23:13:02 -07:00
|
|
|
*
|
2011-05-09 04:53:45 -07:00
|
|
|
* This function creates @p path and all the subdirectories it
|
2010-11-26 05:47:51 -08:00
|
|
|
* contains. The separator is '/' or '\'. If @p path exists, this
|
2012-04-11 20:51:36 -07:00
|
|
|
* function returns @c EINA_TRUE immediately. It returns @c EINA_TRUE on
|
|
|
|
* success, @c EINA_FALSE otherwise.
|
2007-08-06 13:00:28 -07:00
|
|
|
*/
|
2010-06-10 04:57:12 -07:00
|
|
|
EAPI Eina_Bool
|
2005-02-21 08:03:08 -08:00
|
|
|
ecore_file_mkpath(const char *path)
|
2005-02-20 04:17:07 -08:00
|
|
|
{
|
|
|
|
char ss[PATH_MAX];
|
2009-04-10 23:33:00 -07:00
|
|
|
unsigned int i;
|
|
|
|
|
|
|
|
if (ecore_file_is_dir(path))
|
2010-06-10 04:57:12 -07:00
|
|
|
return EINA_TRUE;
|
2005-02-20 04:17:07 -08:00
|
|
|
|
2009-04-10 23:33:00 -07:00
|
|
|
for (i = 0; path[i] != '\0'; ss[i] = path[i], i++)
|
2005-02-20 04:17:07 -08:00
|
|
|
{
|
2010-09-30 00:25:06 -07:00
|
|
|
if (i == sizeof(ss) - 1) return EINA_FALSE;
|
2010-11-26 05:47:51 -08:00
|
|
|
if (((path[i] == '/') || (path[i] == '\\')) && (i > 0))
|
2010-09-30 00:25:06 -07:00
|
|
|
{
|
|
|
|
ss[i] = '\0';
|
|
|
|
if (!_ecore_file_mkpath_if_not_exists(ss))
|
|
|
|
return EINA_FALSE;
|
|
|
|
}
|
2005-02-20 04:17:07 -08:00
|
|
|
}
|
2009-04-10 23:33:00 -07:00
|
|
|
ss[i] = '\0';
|
|
|
|
return _ecore_file_mkpath_if_not_exists(ss);
|
2005-02-20 04:17:07 -08:00
|
|
|
}
|
|
|
|
|
2009-04-10 23:13:02 -07:00
|
|
|
/**
|
2010-10-23 04:05:36 -07:00
|
|
|
* @brief Create complete paths in a batch.
|
2009-04-10 23:13:02 -07:00
|
|
|
*
|
|
|
|
* @param paths list of paths, null terminated.
|
2010-09-08 04:23:42 -07:00
|
|
|
* @return number of successful paths created, -1 if paths is NULL.
|
2009-04-10 23:13:02 -07:00
|
|
|
*
|
2010-10-23 04:05:36 -07:00
|
|
|
* This function creates all the directories that are in the null
|
|
|
|
* terminated array @p paths. The function loops over the directories
|
|
|
|
* and call ecore_file_mkpath(), hence on Windows, '\' must be
|
|
|
|
* replaced by '/' before calling that function. This function
|
|
|
|
* returns -1 if @p paths is @c NULL. Otherwise if returns the number
|
2011-04-20 07:15:33 -07:00
|
|
|
* of suceesfully created directories.
|
2009-04-10 23:13:02 -07:00
|
|
|
*/
|
|
|
|
EAPI int
|
|
|
|
ecore_file_mkpaths(const char **paths)
|
|
|
|
{
|
2010-04-05 01:26:48 -07:00
|
|
|
int i = 0;
|
2010-01-03 13:50:23 -08:00
|
|
|
|
2009-04-10 23:13:02 -07:00
|
|
|
if (!paths) return -1;
|
2010-01-03 13:50:23 -08:00
|
|
|
|
2010-08-21 06:52:25 -07:00
|
|
|
for (; *paths; paths++)
|
2009-04-10 23:13:02 -07:00
|
|
|
if (ecore_file_mkpath(*paths))
|
|
|
|
i++;
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
|
2007-08-06 13:00:28 -07:00
|
|
|
/**
|
2010-10-23 04:05:36 -07:00
|
|
|
* @brief Copy the given file to the given destination.
|
|
|
|
*
|
|
|
|
* @param src The name of the source file.
|
|
|
|
* @param dst The name of the destination file.
|
2012-04-11 20:51:36 -07:00
|
|
|
* @return @c EINA_TRUE on success, @c EINA_FALSE otherwise.
|
2010-10-23 04:05:36 -07:00
|
|
|
*
|
|
|
|
* This function copies @p src to @p dst. If the absolute path name of
|
|
|
|
* @p src and @p dst can not be computed, or if they are equal, or if
|
2012-04-11 20:51:36 -07:00
|
|
|
* the copy fails, the function returns @c EINA_FALSE, otherwise it
|
|
|
|
* returns @c EINA_TRUE.
|
2007-08-06 13:00:28 -07:00
|
|
|
*/
|
2010-06-10 04:57:12 -07:00
|
|
|
EAPI Eina_Bool
|
2005-02-21 08:03:08 -08:00
|
|
|
ecore_file_cp(const char *src, const char *dst)
|
2005-02-20 04:17:07 -08:00
|
|
|
{
|
2010-01-03 13:50:23 -08:00
|
|
|
FILE *f1, *f2;
|
|
|
|
char buf[16384];
|
|
|
|
char realpath1[PATH_MAX], realpath2[PATH_MAX];
|
|
|
|
size_t num;
|
2010-06-10 04:57:12 -07:00
|
|
|
Eina_Bool ret = EINA_TRUE;
|
2005-10-24 03:05:35 -07:00
|
|
|
|
2010-06-10 04:57:12 -07:00
|
|
|
if (!realpath(src, realpath1)) return EINA_FALSE;
|
|
|
|
if (realpath(dst, realpath2) && !strcmp(realpath1, realpath2)) return EINA_FALSE;
|
2005-10-10 14:10:04 -07:00
|
|
|
|
2005-02-20 04:17:07 -08:00
|
|
|
f1 = fopen(src, "rb");
|
2010-06-10 04:57:12 -07:00
|
|
|
if (!f1) return EINA_FALSE;
|
2005-02-20 04:17:07 -08:00
|
|
|
f2 = fopen(dst, "wb");
|
|
|
|
if (!f2)
|
|
|
|
{
|
2010-09-30 00:25:06 -07:00
|
|
|
fclose(f1);
|
|
|
|
return EINA_FALSE;
|
2005-02-20 04:17:07 -08:00
|
|
|
}
|
2007-04-22 16:07:48 -07:00
|
|
|
while ((num = fread(buf, 1, sizeof(buf), f1)) > 0)
|
|
|
|
{
|
2010-09-30 00:25:06 -07:00
|
|
|
if (fwrite(buf, 1, num, f2) != num) ret = EINA_FALSE;
|
2007-04-22 16:07:48 -07:00
|
|
|
}
|
2005-02-20 04:17:07 -08:00
|
|
|
fclose(f1);
|
|
|
|
fclose(f2);
|
2007-04-22 16:07:48 -07:00
|
|
|
return ret;
|
2005-02-20 04:17:07 -08:00
|
|
|
}
|
|
|
|
|
2007-08-06 13:00:28 -07:00
|
|
|
/**
|
2010-10-23 04:05:36 -07:00
|
|
|
* @brief Move the given file to the given destination.
|
|
|
|
*
|
|
|
|
* @param src The name of the source file.
|
|
|
|
* @param dst The name of the destination file.
|
2012-04-11 20:51:36 -07:00
|
|
|
* @return @c EINA_TRUE on success, @c EINA_FALSE otherwise.
|
2010-10-23 04:05:36 -07:00
|
|
|
*
|
2012-04-11 20:51:36 -07:00
|
|
|
* This function moves @p src to @p dst. It returns @c EINA_TRUE on
|
|
|
|
* success, @c EINA_FALSE otherwise.
|
2007-08-06 13:00:28 -07:00
|
|
|
*/
|
2010-06-10 04:57:12 -07:00
|
|
|
EAPI Eina_Bool
|
2005-05-11 01:52:27 -07:00
|
|
|
ecore_file_mv(const char *src, const char *dst)
|
|
|
|
{
|
2008-09-01 19:44:47 -07:00
|
|
|
char buf[PATH_MAX];
|
|
|
|
int fd;
|
|
|
|
|
2007-02-04 05:14:16 -08:00
|
|
|
if (rename(src, dst))
|
|
|
|
{
|
2008-09-01 19:44:47 -07:00
|
|
|
// File cannot be moved directly because
|
|
|
|
// it resides on a different mount point.
|
2010-09-30 00:25:06 -07:00
|
|
|
if (errno == EXDEV)
|
|
|
|
{
|
|
|
|
struct stat st;
|
2007-09-09 03:26:37 -07:00
|
|
|
|
2008-09-01 19:44:47 -07:00
|
|
|
// Make sure this is a regular file before
|
|
|
|
// we do anything fancy.
|
2010-09-30 00:25:06 -07:00
|
|
|
stat(src, &st);
|
|
|
|
if (S_ISREG(st.st_mode))
|
|
|
|
{
|
|
|
|
char *dir;
|
|
|
|
|
|
|
|
dir = ecore_file_dir_get(dst);
|
2011-04-20 07:15:33 -07:00
|
|
|
// Since we can't directly rename, try to
|
2010-09-30 00:25:06 -07:00
|
|
|
// copy to temp file in the dst directory
|
|
|
|
// and then rename.
|
2011-04-20 07:15:33 -07:00
|
|
|
snprintf(buf, sizeof(buf), "%s/.%s.tmp.XXXXXX",
|
2010-09-30 00:25:06 -07:00
|
|
|
dir, ecore_file_file_get(dst));
|
|
|
|
free(dir);
|
|
|
|
fd = mkstemp(buf);
|
2011-12-08 08:21:29 -08:00
|
|
|
if (fd < 0) goto FAIL;
|
2010-09-30 00:25:06 -07:00
|
|
|
close(fd);
|
|
|
|
|
|
|
|
// Copy to temp file
|
|
|
|
if (!ecore_file_cp(src, buf))
|
|
|
|
goto FAIL;
|
|
|
|
|
|
|
|
// Set file permissions of temp file to match src
|
|
|
|
chmod(buf, st.st_mode);
|
|
|
|
|
|
|
|
// Try to atomically move temp file to dst
|
|
|
|
if (rename(buf, dst))
|
|
|
|
{
|
|
|
|
// If we still cannot atomically move
|
|
|
|
// do a normal copy and hope for the best.
|
|
|
|
if (!ecore_file_cp(buf, dst))
|
|
|
|
goto FAIL;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Delete temporary file and src
|
|
|
|
ecore_file_unlink(buf);
|
|
|
|
ecore_file_unlink(src);
|
|
|
|
goto PASS;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
goto FAIL;
|
2007-02-04 05:14:16 -08:00
|
|
|
}
|
2008-09-01 19:44:47 -07:00
|
|
|
|
2008-09-01 22:38:46 -07:00
|
|
|
PASS:
|
2010-06-10 04:57:12 -07:00
|
|
|
return EINA_TRUE;
|
2008-09-01 19:44:47 -07:00
|
|
|
|
2008-09-01 22:38:46 -07:00
|
|
|
FAIL:
|
2010-06-10 04:57:12 -07:00
|
|
|
return EINA_FALSE;
|
2005-05-11 01:52:27 -07:00
|
|
|
}
|
|
|
|
|
2007-08-06 13:00:28 -07:00
|
|
|
/**
|
2010-10-23 04:05:36 -07:00
|
|
|
* @brief Create a symbolic link.
|
|
|
|
*
|
|
|
|
* @param src The name of the file to link.
|
|
|
|
* @param dest The name of link.
|
2012-04-11 20:51:36 -07:00
|
|
|
* @return @c EINA_TRUE on success, @c EINA_FALSE otherwise.
|
2010-10-23 04:05:36 -07:00
|
|
|
*
|
|
|
|
* This function create the symbolic link @p dest of @p src. This
|
2012-04-11 20:51:36 -07:00
|
|
|
* function does not work on Windows. It returns @c EINA_TRUE on success,
|
|
|
|
* @c EINA_FALSE otherwise.
|
2007-08-06 13:00:28 -07:00
|
|
|
*/
|
2010-06-10 04:57:12 -07:00
|
|
|
EAPI Eina_Bool
|
2006-01-02 16:18:42 -08:00
|
|
|
ecore_file_symlink(const char *src, const char *dest)
|
|
|
|
{
|
2010-06-10 04:57:12 -07:00
|
|
|
if (!symlink(src, dest)) return EINA_TRUE;
|
2007-09-09 03:26:37 -07:00
|
|
|
|
2010-06-10 04:57:12 -07:00
|
|
|
return EINA_FALSE;
|
2006-01-02 16:18:42 -08:00
|
|
|
}
|
|
|
|
|
2007-08-06 13:00:28 -07:00
|
|
|
/**
|
2010-10-23 04:05:36 -07:00
|
|
|
* @brief Get the canonicalized absolute path name.
|
|
|
|
*
|
|
|
|
* @param file The file path.
|
|
|
|
* @return The canonicalized absolute pathname or an empty string on
|
|
|
|
* failure.
|
|
|
|
*
|
|
|
|
* This function returns the absolute path name of @p file as a newly
|
|
|
|
* allocated string. If @p file is @c NULL, or on error, this function
|
|
|
|
* returns an empty string. Otherwise, it returns the absolute path
|
|
|
|
* name. When not needed anymore, the returned value must be freed.
|
2007-08-06 13:00:28 -07:00
|
|
|
*/
|
2006-01-06 10:46:30 -08:00
|
|
|
EAPI char *
|
2005-02-21 08:03:08 -08:00
|
|
|
ecore_file_realpath(const char *file)
|
2005-02-20 04:17:07 -08:00
|
|
|
{
|
2010-01-03 13:50:23 -08:00
|
|
|
char buf[PATH_MAX];
|
2005-02-20 04:17:07 -08:00
|
|
|
|
2008-04-16 19:04:02 -07:00
|
|
|
/*
|
|
|
|
* Some implementations of realpath do not conform to the SUS.
|
|
|
|
* And as a result we must prevent a null arg from being passed.
|
|
|
|
*/
|
|
|
|
if (!file) return strdup("");
|
2007-03-12 19:28:18 -07:00
|
|
|
if (!realpath(file, buf)) return strdup("");
|
2007-09-09 03:26:37 -07:00
|
|
|
|
2005-02-20 04:17:07 -08:00
|
|
|
return strdup(buf);
|
|
|
|
}
|
|
|
|
|
2007-08-06 13:00:28 -07:00
|
|
|
/**
|
2010-10-23 04:05:36 -07:00
|
|
|
* Get the filename from a given path.
|
|
|
|
*
|
|
|
|
* @param path The complete path.
|
|
|
|
* @return The file name.
|
|
|
|
*
|
|
|
|
* This function returns the file name of @p path. If @p path is
|
|
|
|
* @c NULL, the functions returns @c NULL.
|
2007-08-06 13:00:28 -07:00
|
|
|
*/
|
2006-01-06 10:46:30 -08:00
|
|
|
EAPI const char *
|
2007-07-25 10:01:04 -07:00
|
|
|
ecore_file_file_get(const char *path)
|
2005-02-20 04:17:07 -08:00
|
|
|
{
|
|
|
|
char *result = NULL;
|
|
|
|
|
|
|
|
if (!path) return NULL;
|
|
|
|
if ((result = strrchr(path, '/'))) result++;
|
2006-01-06 10:46:30 -08:00
|
|
|
else result = (char *)path;
|
2005-02-20 04:17:07 -08:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2007-08-06 13:00:28 -07:00
|
|
|
/**
|
2010-10-23 04:05:36 -07:00
|
|
|
* @brief Get the directory where the given file resides.
|
|
|
|
*
|
|
|
|
* @param file The name of the file.
|
|
|
|
* @return The directory name.
|
|
|
|
*
|
|
|
|
* This function returns the directory where @p file resides as anewly
|
|
|
|
* allocated string. If @p file is @c NULL or on error, this function
|
|
|
|
* returns @c NULL. When not needed anymore, the returned value must
|
|
|
|
* be freed.
|
2007-08-06 13:00:28 -07:00
|
|
|
*/
|
2006-01-06 10:46:30 -08:00
|
|
|
EAPI char *
|
2007-07-25 10:01:04 -07:00
|
|
|
ecore_file_dir_get(const char *file)
|
2005-02-20 04:17:07 -08:00
|
|
|
{
|
2010-01-03 13:50:23 -08:00
|
|
|
char *p;
|
|
|
|
char buf[PATH_MAX];
|
2005-02-20 04:17:07 -08:00
|
|
|
|
2010-01-20 04:41:22 -08:00
|
|
|
if (!file) return NULL;
|
2005-02-20 04:17:07 -08:00
|
|
|
strncpy(buf, file, PATH_MAX);
|
2010-01-23 18:23:43 -08:00
|
|
|
buf[PATH_MAX - 1] = 0;
|
2010-01-18 03:05:03 -08:00
|
|
|
p = dirname(buf);
|
|
|
|
return strdup(p);
|
2005-02-20 04:17:07 -08:00
|
|
|
}
|
|
|
|
|
2007-08-06 13:00:28 -07:00
|
|
|
/**
|
2010-10-23 04:05:36 -07:00
|
|
|
* @brief Check if the given file can be read.
|
|
|
|
*
|
|
|
|
* @param file The name of the file.
|
2012-04-11 20:51:36 -07:00
|
|
|
* @return @c EINA_TRUE if the @p file is readable, @c EINA_FALSE otherwise.
|
2010-10-23 04:05:36 -07:00
|
|
|
*
|
2012-04-11 20:51:36 -07:00
|
|
|
* This function returns @c EINA_TRUE if @p file can be read, @c EINA_FALSE
|
2010-10-23 04:05:36 -07:00
|
|
|
* otherwise.
|
2007-08-06 13:00:28 -07:00
|
|
|
*/
|
2010-06-10 04:57:12 -07:00
|
|
|
EAPI Eina_Bool
|
2005-11-30 22:23:58 -08:00
|
|
|
ecore_file_can_read(const char *file)
|
|
|
|
{
|
2010-06-10 04:57:12 -07:00
|
|
|
if (!file) return EINA_FALSE;
|
|
|
|
if (!access(file, R_OK)) return EINA_TRUE;
|
|
|
|
return EINA_FALSE;
|
2005-11-30 22:23:58 -08:00
|
|
|
}
|
|
|
|
|
2007-08-06 13:00:28 -07:00
|
|
|
/**
|
2010-10-23 04:05:36 -07:00
|
|
|
* @brief Check if the given file can be written.
|
|
|
|
*
|
|
|
|
* @param file The name of the file.
|
2012-04-11 20:51:36 -07:00
|
|
|
* @return @c EINA_TRUE if the @p file is writable, @c EINA_FALSE otherwise.
|
2010-10-23 04:05:36 -07:00
|
|
|
*
|
2012-04-11 20:51:36 -07:00
|
|
|
* This function returns @c EINA_TRUE if @p file can be written, @c EINA_FALSE
|
2010-10-23 04:05:36 -07:00
|
|
|
* otherwise.
|
2007-08-06 13:00:28 -07:00
|
|
|
*/
|
2010-06-10 04:57:12 -07:00
|
|
|
EAPI Eina_Bool
|
2005-11-30 22:23:58 -08:00
|
|
|
ecore_file_can_write(const char *file)
|
|
|
|
{
|
2010-06-10 04:57:12 -07:00
|
|
|
if (!file) return EINA_FALSE;
|
|
|
|
if (!access(file, W_OK)) return EINA_TRUE;
|
|
|
|
return EINA_FALSE;
|
2005-11-30 22:23:58 -08:00
|
|
|
}
|
|
|
|
|
2007-08-06 13:00:28 -07:00
|
|
|
/**
|
2012-01-17 03:37:35 -08:00
|
|
|
* @brief Check if the given file can be executed.
|
2010-10-23 04:05:36 -07:00
|
|
|
*
|
|
|
|
* @param file The name of the file.
|
2012-04-11 20:51:36 -07:00
|
|
|
* @return @c EINA_TRUE if the @p file can be executed, @c EINA_FALSE
|
|
|
|
* otherwise.
|
2010-10-23 04:05:36 -07:00
|
|
|
*
|
2012-04-11 20:51:36 -07:00
|
|
|
* This function returns @c EINA_TRUE if @p file can be executed, @c EINA_FALSE
|
2010-10-23 04:05:36 -07:00
|
|
|
* otherwise.
|
2007-08-06 13:00:28 -07:00
|
|
|
*/
|
2010-06-10 04:57:12 -07:00
|
|
|
EAPI Eina_Bool
|
2005-02-21 08:03:08 -08:00
|
|
|
ecore_file_can_exec(const char *file)
|
2005-02-20 04:17:07 -08:00
|
|
|
{
|
2010-06-10 04:57:12 -07:00
|
|
|
if (!file) return EINA_FALSE;
|
|
|
|
if (!access(file, X_OK)) return EINA_TRUE;
|
|
|
|
return EINA_FALSE;
|
2005-02-20 04:17:07 -08:00
|
|
|
}
|
|
|
|
|
2007-08-06 13:00:28 -07:00
|
|
|
/**
|
2010-10-23 04:05:36 -07:00
|
|
|
* @brief Get the path pointed by the given link.
|
|
|
|
*
|
2011-02-09 09:10:00 -08:00
|
|
|
* @param lnk The name of the link.
|
2010-10-23 04:05:36 -07:00
|
|
|
* @return The path pointed by link or NULL.
|
|
|
|
*
|
|
|
|
* This function returns the path pointed by @p link as a newly
|
|
|
|
* allocated string. This function does not work on Windows. On
|
|
|
|
* failure, the function returns @c NULL. When not needed anymore, the
|
|
|
|
* returned value must be freed.
|
2007-08-06 13:00:28 -07:00
|
|
|
*/
|
2006-01-06 10:46:30 -08:00
|
|
|
EAPI char *
|
2011-02-09 09:10:00 -08:00
|
|
|
ecore_file_readlink(const char *lnk)
|
2005-02-20 04:17:07 -08:00
|
|
|
{
|
2010-01-03 13:50:23 -08:00
|
|
|
char buf[PATH_MAX];
|
|
|
|
int count;
|
2005-02-20 04:17:07 -08:00
|
|
|
|
2011-02-09 09:10:00 -08:00
|
|
|
if ((count = readlink(lnk, buf, sizeof(buf) - 1)) < 0) return NULL;
|
2005-02-20 04:17:07 -08:00
|
|
|
buf[count] = 0;
|
|
|
|
return strdup(buf);
|
|
|
|
}
|
|
|
|
|
2007-08-06 13:00:28 -07:00
|
|
|
/**
|
2010-10-23 04:05:36 -07:00
|
|
|
* @brief Get the list of the files and directories in the given
|
|
|
|
* directory.
|
|
|
|
*
|
2007-08-06 13:00:28 -07:00
|
|
|
* @param dir The name of the directory to list
|
* estickies,
* etk,
* PROTO/exalt,
* E-MODULES-EXTRA/diskio,
* E-MODULES-EXTRA/drawer,
* E-MODULES-EXTRA/penguins,
* E-MODULES-EXTRA/slideshow,
* E-MODULES-EXTRA/mail,
* E-MODULES-EXTRA/forecasts,
* E-MODULES-EXTRA/iiirk,
* E-MODULES-EXTRA/places,
* e,
* ewl,
* ecore,
* elitaire,
* entrance,
* e_dbus,
* efreet: Here we go, move from Ecore_List to Eina_List.
NOTE: This patch is huge, I did test it a lot, and I hope nothing is
broken. But if you think something change after this commit, please
contact me ASAP.
SVN revision: 39200
2009-02-25 03:03:47 -08:00
|
|
|
* @return Return an Eina_List containing all the files in the directory;
|
2007-08-10 07:15:14 -07:00
|
|
|
* on failure it returns NULL.
|
2010-10-23 04:05:36 -07:00
|
|
|
*
|
|
|
|
* This function returns a list of allocated strings of all the files
|
|
|
|
* and directories contained in @p dir. The list will be sorted with
|
|
|
|
* strcoll as compare function. That means that you may want to set
|
|
|
|
* the current locale for the category LC_COLLATE with
|
|
|
|
* setlocale(). For more information see the manual pages of strcoll
|
|
|
|
* and setlocale. The list will not contain the directory entries for
|
|
|
|
* '.' and '..'. On failure, @c NULL is returned. When not needed
|
|
|
|
* anymore, the list elements must be freed.
|
2007-08-06 13:00:28 -07:00
|
|
|
*/
|
* estickies,
* etk,
* PROTO/exalt,
* E-MODULES-EXTRA/diskio,
* E-MODULES-EXTRA/drawer,
* E-MODULES-EXTRA/penguins,
* E-MODULES-EXTRA/slideshow,
* E-MODULES-EXTRA/mail,
* E-MODULES-EXTRA/forecasts,
* E-MODULES-EXTRA/iiirk,
* E-MODULES-EXTRA/places,
* e,
* ewl,
* ecore,
* elitaire,
* entrance,
* e_dbus,
* efreet: Here we go, move from Ecore_List to Eina_List.
NOTE: This patch is huge, I did test it a lot, and I hope nothing is
broken. But if you think something change after this commit, please
contact me ASAP.
SVN revision: 39200
2009-02-25 03:03:47 -08:00
|
|
|
EAPI Eina_List *
|
2005-02-21 08:03:08 -08:00
|
|
|
ecore_file_ls(const char *dir)
|
2005-02-20 04:17:07 -08:00
|
|
|
{
|
2011-11-20 07:14:48 -08:00
|
|
|
Eina_File_Direct_Info *info;
|
|
|
|
Eina_Iterator *ls;
|
2010-01-03 13:50:23 -08:00
|
|
|
Eina_List *list = NULL;
|
2005-02-20 04:17:07 -08:00
|
|
|
|
2011-11-20 07:14:48 -08:00
|
|
|
ls = eina_file_direct_ls(dir);
|
2012-02-24 08:53:51 -08:00
|
|
|
if (!ls) return NULL;
|
|
|
|
|
2011-11-20 07:14:48 -08:00
|
|
|
EINA_ITERATOR_FOREACH(ls, info)
|
2005-02-20 04:17:07 -08:00
|
|
|
{
|
2011-11-20 07:14:48 -08:00
|
|
|
char *f;
|
|
|
|
|
|
|
|
f = strdup(info->path + info->name_start);
|
|
|
|
list = eina_list_append(list, f);
|
2005-02-20 04:17:07 -08:00
|
|
|
}
|
2011-11-20 07:14:48 -08:00
|
|
|
eina_iterator_free(ls);
|
2007-09-09 03:26:37 -07:00
|
|
|
|
2010-01-16 05:43:04 -08:00
|
|
|
list = eina_list_sort(list, eina_list_count(list), EINA_COMPARE_CB(strcoll));
|
2005-11-10 06:29:33 -08:00
|
|
|
|
2005-04-14 06:35:50 -07:00
|
|
|
return list;
|
2005-02-20 04:17:07 -08:00
|
|
|
}
|
2005-09-29 17:46:15 -07:00
|
|
|
|
2007-08-10 07:15:14 -07:00
|
|
|
/**
|
2010-10-23 04:05:36 -07:00
|
|
|
* @brief Return the executable from the given command.
|
|
|
|
*
|
|
|
|
* @param app The application command, with parameters.
|
2012-04-05 00:00:42 -07:00
|
|
|
* @return The executable from @p app as a newly allocated string. Arguments
|
|
|
|
* are removed and escape characters are handled. If @p app is @c NULL, or
|
|
|
|
* on failure, the function returns @c NULL. When not needed anymore, the
|
|
|
|
* returned value must be freed.
|
2007-08-10 07:15:14 -07:00
|
|
|
*/
|
2006-01-06 10:46:30 -08:00
|
|
|
EAPI char *
|
2005-09-29 17:46:15 -07:00
|
|
|
ecore_file_app_exe_get(const char *app)
|
|
|
|
{
|
|
|
|
char *p, *pp, *exe1 = NULL, *exe2 = NULL;
|
2005-10-07 10:48:09 -07:00
|
|
|
char *exe = NULL;
|
|
|
|
int in_quot_dbl = 0, in_quot_sing = 0, restart = 0;
|
2005-10-24 03:05:35 -07:00
|
|
|
|
2007-03-25 05:05:48 -07:00
|
|
|
if (!app) return NULL;
|
|
|
|
|
2005-09-29 17:46:15 -07:00
|
|
|
p = (char *)app;
|
2005-10-07 10:48:09 -07:00
|
|
|
restart:
|
2011-12-01 19:33:19 -08:00
|
|
|
while ((*p) && (isspace((unsigned char)*p))) p++;
|
2005-09-29 17:46:15 -07:00
|
|
|
exe1 = p;
|
|
|
|
while (*p)
|
|
|
|
{
|
2010-09-30 00:25:06 -07:00
|
|
|
if (in_quot_sing)
|
|
|
|
{
|
|
|
|
if (*p == '\'')
|
|
|
|
in_quot_sing = 0;
|
|
|
|
}
|
|
|
|
else if (in_quot_dbl)
|
|
|
|
{
|
|
|
|
if (*p == '\"')
|
|
|
|
in_quot_dbl = 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (*p == '\'')
|
|
|
|
in_quot_sing = 1;
|
|
|
|
else if (*p == '\"')
|
|
|
|
in_quot_dbl = 1;
|
2011-12-01 19:33:19 -08:00
|
|
|
if ((isspace((unsigned char)*p)) && ((p <= app) || (p[-1] == '\\')))
|
2010-09-30 00:25:06 -07:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
p++;
|
2005-09-29 17:46:15 -07:00
|
|
|
}
|
|
|
|
exe2 = p;
|
|
|
|
if (exe2 == exe1) return NULL;
|
2005-09-29 17:51:29 -07:00
|
|
|
if (*exe1 == '~')
|
|
|
|
{
|
2010-09-30 00:25:06 -07:00
|
|
|
char *homedir;
|
|
|
|
int len;
|
|
|
|
|
|
|
|
/* Skip ~ */
|
|
|
|
exe1++;
|
|
|
|
|
|
|
|
homedir = getenv("HOME");
|
|
|
|
if (!homedir) return NULL;
|
|
|
|
len = strlen(homedir);
|
|
|
|
if (exe) free(exe);
|
|
|
|
exe = malloc(len + exe2 - exe1 + 2);
|
|
|
|
if (!exe) return NULL;
|
|
|
|
pp = exe;
|
|
|
|
if (len)
|
|
|
|
{
|
|
|
|
strcpy(exe, homedir);
|
|
|
|
pp += len;
|
|
|
|
if (*(pp - 1) != '/')
|
|
|
|
{
|
|
|
|
*pp = '/';
|
|
|
|
pp++;
|
|
|
|
}
|
|
|
|
}
|
2005-09-29 17:51:29 -07:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2010-09-30 00:25:06 -07:00
|
|
|
if (exe) free(exe);
|
|
|
|
exe = malloc(exe2 - exe1 + 1);
|
|
|
|
if (!exe) return NULL;
|
|
|
|
pp = exe;
|
2005-09-29 17:51:29 -07:00
|
|
|
}
|
2005-09-29 17:46:15 -07:00
|
|
|
p = exe1;
|
2005-10-07 10:48:09 -07:00
|
|
|
restart = 0;
|
2005-09-29 17:46:15 -07:00
|
|
|
in_quot_dbl = 0;
|
|
|
|
in_quot_sing = 0;
|
|
|
|
while (*p)
|
|
|
|
{
|
2010-09-30 00:25:06 -07:00
|
|
|
if (in_quot_sing)
|
|
|
|
{
|
|
|
|
if (*p == '\'')
|
|
|
|
in_quot_sing = 0;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
*pp = *p;
|
|
|
|
pp++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (in_quot_dbl)
|
|
|
|
{
|
|
|
|
if (*p == '\"')
|
|
|
|
in_quot_dbl = 0;
|
|
|
|
else
|
|
|
|
{
|
2010-10-23 04:05:36 -07:00
|
|
|
/* technically this is wrong. double quotes also accept
|
2010-09-30 00:25:06 -07:00
|
|
|
* special chars:
|
|
|
|
*
|
|
|
|
* $, `, \
|
|
|
|
*/
|
|
|
|
*pp = *p;
|
|
|
|
pp++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* technically we should handle special chars:
|
|
|
|
*
|
|
|
|
* $, `, \, etc.
|
|
|
|
*/
|
|
|
|
if ((p > exe1) && (p[-1] == '\\'))
|
|
|
|
{
|
|
|
|
if (*p != '\n')
|
|
|
|
{
|
|
|
|
*pp = *p;
|
|
|
|
pp++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if ((p > exe1) && (*p == '='))
|
|
|
|
{
|
|
|
|
restart = 1;
|
|
|
|
*pp = *p;
|
|
|
|
pp++;
|
|
|
|
}
|
|
|
|
else if (*p == '\'')
|
|
|
|
in_quot_sing = 1;
|
|
|
|
else if (*p == '\"')
|
|
|
|
in_quot_dbl = 1;
|
2011-12-01 19:33:19 -08:00
|
|
|
else if (isspace((unsigned char)*p))
|
2010-09-30 00:25:06 -07:00
|
|
|
{
|
|
|
|
if (restart)
|
|
|
|
goto restart;
|
|
|
|
else
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
*pp = *p;
|
|
|
|
pp++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
p++;
|
2005-09-29 17:46:15 -07:00
|
|
|
}
|
|
|
|
*pp = 0;
|
|
|
|
return exe;
|
|
|
|
}
|
2005-10-05 11:38:27 -07:00
|
|
|
|
2007-08-06 13:00:28 -07:00
|
|
|
/**
|
2010-10-23 04:05:36 -07:00
|
|
|
* @brief Add the escape sequence ('\\') to the given file name.
|
|
|
|
*
|
|
|
|
* @param filename The file name.
|
|
|
|
* @return The file name with special characters escaped.
|
|
|
|
*
|
|
|
|
* This function adds the escape sequence ('\\') to the given file
|
|
|
|
* name and returns the result as a newly allocated string. If the
|
|
|
|
* length of the returned string is longer than PATH_MAX, or on
|
|
|
|
* failure, @c NULL is returned. When not needed anymore, the returned
|
|
|
|
* value must be freed.
|
2007-08-06 13:00:28 -07:00
|
|
|
*/
|
2006-10-28 01:48:11 -07:00
|
|
|
EAPI char *
|
|
|
|
ecore_file_escape_name(const char *filename)
|
|
|
|
{
|
|
|
|
const char *p;
|
|
|
|
char *q;
|
2006-10-28 18:08:28 -07:00
|
|
|
char buf[PATH_MAX];
|
2007-09-09 03:26:37 -07:00
|
|
|
|
2006-10-28 01:48:11 -07:00
|
|
|
p = filename;
|
|
|
|
q = buf;
|
|
|
|
while (*p)
|
|
|
|
{
|
2010-09-30 00:25:06 -07:00
|
|
|
if ((q - buf) > (PATH_MAX - 6)) return NULL;
|
|
|
|
if (
|
2012-09-18 04:34:36 -07:00
|
|
|
(*p == ' ') || (*p == '\\') || (*p == '\'') ||
|
|
|
|
(*p == '\"') || (*p == ';') || (*p == '!') ||
|
|
|
|
(*p == '#') || (*p == '$') || (*p == '%') ||
|
|
|
|
(*p == '&') || (*p == '*') || (*p == '(') ||
|
|
|
|
(*p == ')') || (*p == '[') || (*p == ']') ||
|
|
|
|
(*p == '{') || (*p == '}') || (*p == '|') ||
|
|
|
|
(*p == '<') || (*p == '>') || (*p == '?')
|
2010-09-30 00:25:06 -07:00
|
|
|
)
|
|
|
|
{
|
|
|
|
*q = '\\';
|
|
|
|
q++;
|
|
|
|
}
|
2012-09-18 04:34:36 -07:00
|
|
|
else if (*p == '\t')
|
|
|
|
{
|
|
|
|
*q = '\\';
|
|
|
|
q++;
|
|
|
|
*q = '\\';
|
|
|
|
q++;
|
|
|
|
*q = 't';
|
|
|
|
q++;
|
|
|
|
p++;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
else if (*p == '\n')
|
|
|
|
{
|
|
|
|
*q = '\\';
|
|
|
|
q++;
|
|
|
|
*q = '\\';
|
|
|
|
q++;
|
|
|
|
*q = 'n';
|
|
|
|
q++;
|
|
|
|
p++;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2010-09-30 00:25:06 -07:00
|
|
|
*q = *p;
|
|
|
|
q++;
|
|
|
|
p++;
|
2006-10-28 01:48:11 -07:00
|
|
|
}
|
|
|
|
*q = 0;
|
|
|
|
return strdup(buf);
|
|
|
|
}
|
|
|
|
|
2007-08-06 13:00:28 -07:00
|
|
|
/**
|
2012-01-17 03:37:35 -08:00
|
|
|
* @brief Remove the extension from the given file name.
|
2010-10-23 04:05:36 -07:00
|
|
|
*
|
|
|
|
* @param path The name of the file.
|
|
|
|
* @return A newly allocated string with the extension stripped out or
|
2012-04-11 20:51:36 -07:00
|
|
|
* @c NULL on errors.
|
2010-10-23 04:05:36 -07:00
|
|
|
*
|
|
|
|
* This function removes the extension from @p path and returns the
|
|
|
|
* result as a newly allocated string. If @p path is @c NULL, or on
|
|
|
|
* failure, the function returns @c NULL. When not needed anymore, the
|
|
|
|
* returned value must be freed.
|
2007-08-06 13:00:28 -07:00
|
|
|
*/
|
2006-01-06 10:46:30 -08:00
|
|
|
EAPI char *
|
2005-10-05 11:38:27 -07:00
|
|
|
ecore_file_strip_ext(const char *path)
|
|
|
|
{
|
2005-10-07 10:32:31 -07:00
|
|
|
char *p, *file = NULL;
|
2005-10-05 11:38:27 -07:00
|
|
|
|
2010-10-23 04:05:36 -07:00
|
|
|
if (!path)
|
|
|
|
return NULL;
|
|
|
|
|
2005-10-07 10:32:31 -07:00
|
|
|
p = strrchr(path, '.');
|
|
|
|
if (!p)
|
2010-01-03 13:50:23 -08:00
|
|
|
file = strdup(path);
|
2005-10-07 10:32:31 -07:00
|
|
|
else if (p != path)
|
|
|
|
{
|
2010-09-30 00:25:06 -07:00
|
|
|
file = malloc(((p - path) + 1) * sizeof(char));
|
|
|
|
if (file)
|
|
|
|
{
|
|
|
|
memcpy(file, path, (p - path));
|
|
|
|
file[p - path] = 0;
|
|
|
|
}
|
2005-10-07 10:32:31 -07:00
|
|
|
}
|
2005-10-05 11:38:27 -07:00
|
|
|
|
|
|
|
return file;
|
|
|
|
}
|
2008-06-22 08:10:00 -07:00
|
|
|
|
|
|
|
/**
|
2010-10-23 04:05:36 -07:00
|
|
|
* @brief Check if the given directory is empty.
|
|
|
|
*
|
|
|
|
* @param dir The name of the directory to check.
|
2012-04-11 20:51:36 -07:00
|
|
|
* @return @c 1 if directory is empty, @c 0 if it has at least one file or
|
|
|
|
* @c -1 in case of errors.
|
2010-10-23 04:05:36 -07:00
|
|
|
*
|
|
|
|
* This functions checks if @p dir is empty. The '.' and '..' files
|
|
|
|
* will be ignored. If @p dir is empty, 1 is returned, if it contains
|
2012-04-11 20:51:36 -07:00
|
|
|
* at least one file, @c 0 is returned. On failure, @c -1 is returned.
|
2008-06-22 08:10:00 -07:00
|
|
|
*/
|
|
|
|
EAPI int
|
|
|
|
ecore_file_dir_is_empty(const char *dir)
|
|
|
|
{
|
2011-11-20 07:14:48 -08:00
|
|
|
Eina_File_Direct_Info *info;
|
|
|
|
Eina_Iterator *it;
|
2008-06-22 08:10:00 -07:00
|
|
|
|
2011-11-20 07:14:48 -08:00
|
|
|
it = eina_file_direct_ls(dir);
|
|
|
|
if (!it) return -1;
|
2008-06-22 08:10:00 -07:00
|
|
|
|
2011-11-20 07:14:48 -08:00
|
|
|
EINA_ITERATOR_FOREACH(it, info)
|
2008-06-22 08:10:00 -07:00
|
|
|
{
|
2011-11-20 07:14:48 -08:00
|
|
|
eina_iterator_free(it);
|
|
|
|
return 0;
|
2008-06-22 08:10:00 -07:00
|
|
|
}
|
2011-04-20 07:15:33 -07:00
|
|
|
|
2011-11-20 07:14:48 -08:00
|
|
|
eina_iterator_free(it);
|
2008-06-22 08:10:00 -07:00
|
|
|
return 1;
|
|
|
|
}
|
2010-10-23 04:05:36 -07:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @}
|
|
|
|
*/
|