2008-08-06 11:15:24 -07:00
|
|
|
/* EINA - EFL data type library
|
2008-09-01 05:51:50 -07:00
|
|
|
* Copyright (C) 2007-2008 Jorge Luis Zapata Muga, Vincent Torri
|
2011-09-15 08:37:28 -07:00
|
|
|
* Copyright (C) 2010-2011 Cedric Bail
|
2008-08-06 11:15:24 -07:00
|
|
|
*
|
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
|
|
* License as published by the Free Software Foundation; either
|
|
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This library is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* Lesser General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
|
|
* License along with this library;
|
|
|
|
* if not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
|
2008-08-28 00:46:42 -07:00
|
|
|
#ifdef HAVE_CONFIG_H
|
2009-09-06 21:32:49 -07:00
|
|
|
# include "config.h"
|
2008-08-28 00:46:42 -07:00
|
|
|
#endif
|
|
|
|
|
2011-12-06 13:33:39 -08:00
|
|
|
#include <stdlib.h>
|
2009-08-23 02:18:14 -07:00
|
|
|
#include <string.h>
|
2010-10-28 02:59:27 -07:00
|
|
|
#include <stddef.h>
|
2012-05-08 03:31:12 -07:00
|
|
|
#include <stdint.h>
|
2011-12-05 05:57:10 -08:00
|
|
|
#ifdef HAVE_DIRENT_H
|
|
|
|
# include <dirent.h>
|
|
|
|
#endif
|
2010-11-06 14:00:58 -07:00
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/stat.h>
|
|
|
|
#include <unistd.h>
|
2011-12-05 06:25:25 -08:00
|
|
|
#ifdef HAVE_SYS_MMAN_H
|
2011-12-05 05:57:10 -08:00
|
|
|
# include <sys/mman.h>
|
|
|
|
#endif
|
2011-04-13 09:15:30 -07:00
|
|
|
#include <fcntl.h>
|
2009-08-23 02:18:14 -07:00
|
|
|
|
2010-11-06 14:00:58 -07:00
|
|
|
#define PATH_DELIM '/'
|
2008-07-30 06:35:49 -07:00
|
|
|
|
2009-08-28 05:03:34 -07:00
|
|
|
#include "eina_config.h"
|
2008-07-30 05:46:55 -07:00
|
|
|
#include "eina_private.h"
|
2013-01-03 07:10:34 -08:00
|
|
|
#include "eina_alloca.h"
|
2009-09-06 15:21:56 -07:00
|
|
|
|
|
|
|
/* undefs EINA_ARG_NONULL() so NULL checks are not compiled out! */
|
2008-12-26 10:31:14 -08:00
|
|
|
#include "eina_safety_checks.h"
|
2014-05-30 01:25:05 -07:00
|
|
|
#include "eina_cpu.h"
|
2009-08-28 05:03:34 -07:00
|
|
|
#include "eina_file.h"
|
2010-07-02 10:23:05 -07:00
|
|
|
#include "eina_stringshare.h"
|
2011-04-13 09:15:30 -07:00
|
|
|
#include "eina_hash.h"
|
|
|
|
#include "eina_list.h"
|
2011-06-06 10:08:06 -07:00
|
|
|
#include "eina_lock.h"
|
2011-07-04 02:29:59 -07:00
|
|
|
#include "eina_mmap.h"
|
2011-12-05 05:57:10 -08:00
|
|
|
#include "eina_log.h"
|
2012-01-03 07:24:15 -08:00
|
|
|
#include "eina_xattr.h"
|
2013-03-14 04:49:45 -07:00
|
|
|
#include "eina_file_common.h"
|
2010-07-02 10:23:05 -07:00
|
|
|
|
2012-07-21 09:50:26 -07:00
|
|
|
#ifdef HAVE_ESCAPE
|
2011-11-05 10:49:30 -07:00
|
|
|
# include <Escape.h>
|
|
|
|
#endif
|
|
|
|
|
2010-11-06 00:37:52 -07:00
|
|
|
/*============================================================================*
|
|
|
|
* Local *
|
|
|
|
*============================================================================*/
|
|
|
|
|
2011-04-13 10:03:24 -07:00
|
|
|
/**
|
|
|
|
* @cond LOCAL
|
|
|
|
*/
|
|
|
|
|
2013-11-10 00:26:12 -08:00
|
|
|
#define EINA_SMALL_PAGE eina_cpu_page_size()
|
2017-09-14 23:56:17 -07:00
|
|
|
|
|
|
|
// FIXME: This assumes HugeTLB size of 2Mb. How to get this information at runtime?
|
|
|
|
#define EINA_HUGE_PAGE (2 * 1024 * 1024)
|
|
|
|
#define EINA_HUGE_PAGE_MIN (8 * EINA_HUGE_PAGE)
|
2011-05-13 03:44:29 -07:00
|
|
|
|
2011-12-05 05:57:10 -08:00
|
|
|
#ifdef HAVE_DIRENT_H
|
2010-07-02 10:23:05 -07:00
|
|
|
typedef struct _Eina_File_Iterator Eina_File_Iterator;
|
|
|
|
struct _Eina_File_Iterator
|
|
|
|
{
|
|
|
|
Eina_Iterator iterator;
|
|
|
|
|
|
|
|
DIR *dirp;
|
|
|
|
int length;
|
|
|
|
|
|
|
|
char dir[1];
|
|
|
|
};
|
2011-12-05 05:57:10 -08:00
|
|
|
#endif
|
2010-07-02 10:23:05 -07:00
|
|
|
|
2013-03-15 00:05:05 -07:00
|
|
|
int _eina_file_log_dom = -1;
|
2011-04-13 09:15:30 -07:00
|
|
|
|
2010-11-03 03:19:55 -07:00
|
|
|
/*
|
|
|
|
* This complex piece of code is needed due to possible race condition.
|
|
|
|
* The code and description of the issue can be found at :
|
|
|
|
* http://womble.decadent.org.uk/readdir_r-advisory.html
|
|
|
|
*/
|
2011-12-05 05:57:10 -08:00
|
|
|
#ifdef HAVE_DIRENT_H
|
2011-09-18 14:56:54 -07:00
|
|
|
static long
|
2018-11-06 08:53:24 -08:00
|
|
|
_eina_name_max(DIR *dirp EINA_UNUSED)
|
2010-11-03 03:19:55 -07:00
|
|
|
{
|
|
|
|
long name_max;
|
|
|
|
|
|
|
|
#if defined(HAVE_FPATHCONF) && defined(HAVE_DIRFD) && defined(_PC_NAME_MAX)
|
|
|
|
name_max = fpathconf(dirfd(dirp), _PC_NAME_MAX);
|
|
|
|
|
|
|
|
if (name_max == -1)
|
|
|
|
{
|
|
|
|
# if defined(NAME_MAX)
|
|
|
|
name_max = (NAME_MAX > 255) ? NAME_MAX : 255;
|
|
|
|
# else
|
2010-11-03 10:32:07 -07:00
|
|
|
name_max = PATH_MAX;
|
2010-11-03 03:19:55 -07:00
|
|
|
# endif
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
# if defined(NAME_MAX)
|
|
|
|
name_max = (NAME_MAX > 255) ? NAME_MAX : 255;
|
|
|
|
# else
|
|
|
|
# ifdef _PC_NAME_MAX
|
|
|
|
# warning "buffer size for readdir_r cannot be determined safely, best effort, but racy"
|
|
|
|
name_max = pathconf(dirp, _PC_NAME_MAX);
|
|
|
|
# else
|
|
|
|
# error "buffer size for readdir_r cannot be determined safely"
|
2010-11-06 00:37:52 -07:00
|
|
|
# endif
|
2010-11-03 03:19:55 -07:00
|
|
|
# endif
|
|
|
|
#endif
|
2011-09-18 14:56:54 -07:00
|
|
|
|
|
|
|
return name_max;
|
|
|
|
}
|
|
|
|
|
2010-07-02 10:23:05 -07:00
|
|
|
static Eina_Bool
|
|
|
|
_eina_file_ls_iterator_next(Eina_File_Iterator *it, void **data)
|
|
|
|
{
|
|
|
|
struct dirent *dp;
|
|
|
|
char *name;
|
|
|
|
size_t length;
|
|
|
|
|
|
|
|
do
|
|
|
|
{
|
2016-08-25 15:20:19 -07:00
|
|
|
dp = readdir(it->dirp);
|
2010-10-28 02:59:27 -07:00
|
|
|
if (dp == NULL)
|
|
|
|
return EINA_FALSE;
|
2010-07-02 10:23:05 -07:00
|
|
|
}
|
2010-07-06 08:45:12 -07:00
|
|
|
while ((dp->d_name[0] == '.') &&
|
2010-07-27 19:37:05 -07:00
|
|
|
((dp->d_name[1] == '\0') ||
|
|
|
|
((dp->d_name[1] == '.') && (dp->d_name[2] == '\0'))));
|
2010-07-02 10:23:05 -07:00
|
|
|
|
2010-11-02 08:11:05 -07:00
|
|
|
#ifdef _DIRENT_HAVE_D_NAMLEN
|
2010-10-29 22:48:07 -07:00
|
|
|
length = dp->d_namlen;
|
|
|
|
#else
|
2010-07-02 10:23:05 -07:00
|
|
|
length = strlen(dp->d_name);
|
2010-11-02 08:11:05 -07:00
|
|
|
#endif
|
2010-07-02 10:23:05 -07:00
|
|
|
name = alloca(length + 2 + it->length);
|
|
|
|
|
2010-07-27 19:37:05 -07:00
|
|
|
memcpy(name, it->dir, it->length);
|
|
|
|
memcpy(name + it->length, "/", 1);
|
2010-07-02 10:23:05 -07:00
|
|
|
memcpy(name + it->length + 1, dp->d_name, length + 1);
|
|
|
|
|
2010-07-27 19:37:05 -07:00
|
|
|
*data = (char *)eina_stringshare_add(name);
|
2010-07-02 10:23:05 -07:00
|
|
|
return EINA_TRUE;
|
|
|
|
}
|
|
|
|
|
2010-10-25 05:25:24 -07:00
|
|
|
static DIR *
|
2010-07-02 10:23:05 -07:00
|
|
|
_eina_file_ls_iterator_container(Eina_File_Iterator *it)
|
|
|
|
{
|
2010-10-25 05:25:24 -07:00
|
|
|
return it->dirp;
|
2010-07-02 10:23:05 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_eina_file_ls_iterator_free(Eina_File_Iterator *it)
|
|
|
|
{
|
|
|
|
closedir(it->dirp);
|
|
|
|
|
|
|
|
EINA_MAGIC_SET(&it->iterator, 0);
|
|
|
|
free(it);
|
|
|
|
}
|
2008-08-08 22:47:15 -07:00
|
|
|
|
2010-07-06 08:45:12 -07:00
|
|
|
typedef struct _Eina_File_Direct_Iterator Eina_File_Direct_Iterator;
|
|
|
|
struct _Eina_File_Direct_Iterator
|
|
|
|
{
|
|
|
|
Eina_Iterator iterator;
|
|
|
|
|
|
|
|
DIR *dirp;
|
|
|
|
int length;
|
|
|
|
|
|
|
|
Eina_File_Direct_Info info;
|
|
|
|
|
|
|
|
char dir[1];
|
|
|
|
};
|
|
|
|
|
|
|
|
static Eina_Bool
|
|
|
|
_eina_file_direct_ls_iterator_next(Eina_File_Direct_Iterator *it, void **data)
|
|
|
|
{
|
|
|
|
struct dirent *dp;
|
|
|
|
size_t length;
|
2010-11-02 10:07:04 -07:00
|
|
|
|
2010-07-06 08:45:12 -07:00
|
|
|
do
|
|
|
|
{
|
2016-08-25 15:20:19 -07:00
|
|
|
dp = readdir(it->dirp);
|
|
|
|
if (dp == NULL)
|
|
|
|
return EINA_FALSE;
|
2010-07-06 08:45:12 -07:00
|
|
|
|
2010-11-02 08:11:05 -07:00
|
|
|
#ifdef _DIRENT_HAVE_D_NAMLEN
|
2010-10-29 22:48:07 -07:00
|
|
|
length = dp->d_namlen;
|
|
|
|
#else
|
2010-07-27 19:37:05 -07:00
|
|
|
length = strlen(dp->d_name);
|
2010-11-02 08:11:05 -07:00
|
|
|
#endif
|
2010-12-09 02:14:11 -08:00
|
|
|
if (it->info.name_start + length + 1 >= EINA_PATH_MAX)
|
2010-07-27 19:37:05 -07:00
|
|
|
continue;
|
2010-07-06 08:45:12 -07:00
|
|
|
}
|
|
|
|
while ((dp->d_name[0] == '.') &&
|
2010-07-27 19:37:05 -07:00
|
|
|
((dp->d_name[1] == '\0') ||
|
|
|
|
((dp->d_name[1] == '.') && (dp->d_name[2] == '\0'))));
|
2010-07-06 08:45:12 -07:00
|
|
|
|
|
|
|
memcpy(it->info.path + it->info.name_start, dp->d_name, length);
|
|
|
|
it->info.name_length = length;
|
|
|
|
it->info.path_length = it->info.name_start + length;
|
|
|
|
it->info.path[it->info.path_length] = '\0';
|
2010-11-02 08:11:05 -07:00
|
|
|
|
2010-10-29 22:48:07 -07:00
|
|
|
#ifdef _DIRENT_HAVE_D_TYPE
|
|
|
|
switch (dp->d_type)
|
|
|
|
{
|
|
|
|
case DT_FIFO:
|
|
|
|
it->info.type = EINA_FILE_FIFO;
|
|
|
|
break;
|
|
|
|
case DT_CHR:
|
|
|
|
it->info.type = EINA_FILE_CHR;
|
|
|
|
break;
|
|
|
|
case DT_DIR:
|
|
|
|
it->info.type = EINA_FILE_DIR;
|
|
|
|
break;
|
|
|
|
case DT_BLK:
|
|
|
|
it->info.type = EINA_FILE_BLK;
|
|
|
|
break;
|
|
|
|
case DT_REG:
|
|
|
|
it->info.type = EINA_FILE_REG;
|
|
|
|
break;
|
|
|
|
case DT_LNK:
|
|
|
|
it->info.type = EINA_FILE_LNK;
|
|
|
|
break;
|
|
|
|
case DT_SOCK:
|
|
|
|
it->info.type = EINA_FILE_SOCK;
|
|
|
|
break;
|
|
|
|
case DT_WHT:
|
|
|
|
it->info.type = EINA_FILE_WHT;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
it->info.type = EINA_FILE_UNKNOWN;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
#else
|
2010-11-02 10:07:04 -07:00
|
|
|
it->info.type = EINA_FILE_UNKNOWN;
|
2010-10-29 22:48:07 -07:00
|
|
|
#endif
|
2010-11-02 10:07:04 -07:00
|
|
|
|
2010-07-06 08:45:12 -07:00
|
|
|
*data = &it->info;
|
|
|
|
return EINA_TRUE;
|
|
|
|
}
|
|
|
|
|
2010-10-25 05:25:24 -07:00
|
|
|
static DIR *
|
2010-07-06 08:45:12 -07:00
|
|
|
_eina_file_direct_ls_iterator_container(Eina_File_Direct_Iterator *it)
|
|
|
|
{
|
2010-10-25 05:25:24 -07:00
|
|
|
return it->dirp;
|
2010-07-06 08:45:12 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_eina_file_direct_ls_iterator_free(Eina_File_Direct_Iterator *it)
|
|
|
|
{
|
|
|
|
closedir(it->dirp);
|
|
|
|
|
|
|
|
EINA_MAGIC_SET(&it->iterator, 0);
|
|
|
|
free(it);
|
|
|
|
}
|
|
|
|
|
2010-11-02 10:07:04 -07:00
|
|
|
static Eina_Bool
|
|
|
|
_eina_file_stat_ls_iterator_next(Eina_File_Direct_Iterator *it, void **data)
|
|
|
|
{
|
2012-02-23 03:45:25 -08:00
|
|
|
Eina_Stat st;
|
2010-11-02 10:07:04 -07:00
|
|
|
|
|
|
|
if (!_eina_file_direct_ls_iterator_next(it, data))
|
|
|
|
return EINA_FALSE;
|
|
|
|
|
|
|
|
if (it->info.type == EINA_FILE_UNKNOWN)
|
|
|
|
{
|
2012-02-23 03:45:25 -08:00
|
|
|
if (eina_file_statat(it->dirp, &it->info, &st) != 0)
|
2010-11-02 10:07:04 -07:00
|
|
|
it->info.type = EINA_FILE_UNKNOWN;
|
|
|
|
}
|
|
|
|
|
|
|
|
return EINA_TRUE;
|
|
|
|
}
|
2011-12-05 05:57:10 -08:00
|
|
|
#endif
|
2010-11-02 10:07:04 -07:00
|
|
|
|
2013-03-14 04:49:45 -07:00
|
|
|
void
|
|
|
|
eina_file_real_close(Eina_File *file)
|
2011-04-13 09:15:30 -07:00
|
|
|
{
|
2013-07-31 01:16:20 -07:00
|
|
|
Eina_File_Map *map;
|
|
|
|
|
|
|
|
EINA_LIST_FREE(file->dead_map, map)
|
|
|
|
{
|
|
|
|
munmap(map->map, map->length);
|
|
|
|
free(map);
|
|
|
|
}
|
|
|
|
|
2017-08-02 12:37:10 -07:00
|
|
|
if (file->fd != -1)
|
|
|
|
{
|
2017-11-30 05:57:25 -08:00
|
|
|
if (!file->copied && file->global_map != MAP_FAILED)
|
2017-08-02 12:37:10 -07:00
|
|
|
munmap(file->global_map, file->length);
|
|
|
|
close(file->fd);
|
|
|
|
}
|
2011-04-13 09:15:30 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_eina_file_map_close(Eina_File_Map *map)
|
|
|
|
{
|
|
|
|
munmap(map->map, map->length);
|
|
|
|
free(map);
|
|
|
|
}
|
|
|
|
|
2011-05-13 03:44:29 -07:00
|
|
|
#ifndef MAP_POPULATE
|
2011-11-14 14:08:02 -08:00
|
|
|
static unsigned int
|
2016-09-20 05:57:47 -07:00
|
|
|
_eina_file_map_populate(char *map, unsigned long int size, Eina_Bool hugetlb)
|
2011-05-13 03:44:29 -07:00
|
|
|
{
|
2011-11-14 14:08:02 -08:00
|
|
|
unsigned int r = 0xDEADBEEF;
|
2016-09-20 05:57:47 -07:00
|
|
|
unsigned long int i;
|
2011-11-14 14:08:02 -08:00
|
|
|
unsigned int s;
|
2011-05-13 03:44:29 -07:00
|
|
|
|
2016-09-19 14:02:43 -07:00
|
|
|
if (size == 0) return 0;
|
|
|
|
|
2011-10-19 09:09:14 -07:00
|
|
|
s = hugetlb ? EINA_HUGE_PAGE : EINA_SMALL_PAGE;
|
2011-05-13 03:44:29 -07:00
|
|
|
|
|
|
|
for (i = 0; i < size; i += s)
|
|
|
|
r ^= map[i];
|
|
|
|
|
2016-09-19 14:02:43 -07:00
|
|
|
r ^= map[size - 1];
|
2011-05-13 03:44:29 -07:00
|
|
|
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2017-09-14 23:56:17 -07:00
|
|
|
static char *
|
|
|
|
_page_aligned_address(const char *map, unsigned long int offset, Eina_Bool hugetlb)
|
|
|
|
{
|
|
|
|
const uintptr_t align = hugetlb ? EINA_HUGE_PAGE : EINA_SMALL_PAGE;
|
|
|
|
uintptr_t pmap = (uintptr_t) map;
|
|
|
|
|
|
|
|
pmap = (pmap + offset) - ((pmap + offset) & (align - 1));
|
|
|
|
|
|
|
|
return (char *) pmap;
|
|
|
|
}
|
|
|
|
|
2011-05-13 03:44:29 -07:00
|
|
|
static int
|
2017-09-14 23:56:17 -07:00
|
|
|
_eina_file_map_rule_apply(Eina_File_Populate rule, const void *map, unsigned long int offset,
|
|
|
|
unsigned long int size, unsigned long long maplen, Eina_Bool hugetlb)
|
2011-04-13 09:15:30 -07:00
|
|
|
{
|
2011-05-13 03:44:29 -07:00
|
|
|
int tmp = 42;
|
|
|
|
int flag = MADV_RANDOM;
|
2017-09-14 23:56:17 -07:00
|
|
|
char *addr;
|
2011-04-13 09:15:30 -07:00
|
|
|
|
|
|
|
switch (rule)
|
|
|
|
{
|
|
|
|
case EINA_FILE_RANDOM: flag = MADV_RANDOM; break;
|
|
|
|
case EINA_FILE_SEQUENTIAL: flag = MADV_SEQUENTIAL; break;
|
2011-05-13 03:44:29 -07:00
|
|
|
case EINA_FILE_POPULATE: flag = MADV_WILLNEED; break;
|
|
|
|
case EINA_FILE_WILLNEED: flag = MADV_WILLNEED; break;
|
2013-07-06 06:01:23 -07:00
|
|
|
case EINA_FILE_DONTNEED: flag = MADV_DONTNEED; break;
|
2013-08-06 00:13:03 -07:00
|
|
|
#ifdef MADV_REMOVE
|
2013-07-06 06:01:23 -07:00
|
|
|
case EINA_FILE_REMOVE: flag = MADV_REMOVE; break;
|
2013-08-06 00:13:03 -07:00
|
|
|
#elif defined (MADV_FREE)
|
|
|
|
case EINA_FILE_REMOVE: flag = MADV_FREE; break;
|
|
|
|
#else
|
|
|
|
# warning "EINA_FILE_REMOVE does not have system support"
|
|
|
|
#endif
|
2013-07-06 06:01:23 -07:00
|
|
|
default: return tmp; break;
|
2011-04-13 09:15:30 -07:00
|
|
|
}
|
|
|
|
|
2017-09-14 23:56:17 -07:00
|
|
|
if (offset >= maplen) return tmp;
|
|
|
|
|
|
|
|
// Align address, clamp size
|
|
|
|
addr = _page_aligned_address(map, offset, hugetlb);
|
|
|
|
if (size > 0)
|
|
|
|
{
|
|
|
|
size += ((char *) map + offset) - addr;
|
|
|
|
offset -= ((char *) map + offset) - addr;
|
|
|
|
if ((offset + size) > maplen)
|
|
|
|
{
|
|
|
|
if (offset > maplen) return tmp;
|
|
|
|
size = maplen - offset;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-04-13 09:15:30 -07:00
|
|
|
madvise(addr, size, flag);
|
2011-05-13 03:44:29 -07:00
|
|
|
|
|
|
|
#ifndef MAP_POPULATE
|
|
|
|
if (rule == EINA_FILE_POPULATE)
|
2011-10-19 09:09:14 -07:00
|
|
|
tmp ^= _eina_file_map_populate(addr, size, hugetlb);
|
|
|
|
#else
|
|
|
|
(void) hugetlb;
|
2011-05-13 03:44:29 -07:00
|
|
|
#endif
|
|
|
|
|
|
|
|
return tmp;
|
2011-04-13 09:15:30 -07:00
|
|
|
}
|
|
|
|
|
2011-10-03 19:04:40 -07:00
|
|
|
static Eina_Bool
|
|
|
|
_eina_file_timestamp_compare(Eina_File *f, struct stat *st)
|
|
|
|
{
|
|
|
|
if (f->mtime != st->st_mtime) return EINA_FALSE;
|
|
|
|
if (f->length != (unsigned long long) st->st_size) return EINA_FALSE;
|
|
|
|
if (f->inode != st->st_ino) return EINA_FALSE;
|
|
|
|
#ifdef _STAT_VER_LINUX
|
|
|
|
# if (defined __USE_MISC && defined st_mtime)
|
|
|
|
if (f->mtime_nsec != (unsigned long int)st->st_mtim.tv_nsec)
|
|
|
|
return EINA_FALSE;
|
|
|
|
# else
|
|
|
|
if (f->mtime_nsec != (unsigned long int)st->st_mtimensec)
|
|
|
|
return EINA_FALSE;
|
|
|
|
# endif
|
|
|
|
#endif
|
|
|
|
return EINA_TRUE;
|
|
|
|
}
|
|
|
|
|
2011-10-03 19:33:45 -07:00
|
|
|
static void
|
|
|
|
slprintf(char *str, size_t size, const char *format, ...)
|
|
|
|
{
|
|
|
|
va_list ap;
|
|
|
|
|
|
|
|
va_start(ap, format);
|
|
|
|
|
|
|
|
vsnprintf(str, size, format, ap);
|
|
|
|
str[size - 1] = 0;
|
|
|
|
|
|
|
|
va_end(ap);
|
|
|
|
}
|
|
|
|
|
2012-01-21 00:23:23 -08:00
|
|
|
/**
|
|
|
|
* @endcond
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*============================================================================*
|
|
|
|
* Global *
|
|
|
|
*============================================================================*/
|
|
|
|
|
2013-07-31 01:16:20 -07:00
|
|
|
static Eina_Bool
|
|
|
|
_eina_file_mmap_faulty_one(void *addr, long page_size,
|
|
|
|
Eina_File_Map *m)
|
|
|
|
{
|
|
|
|
if ((unsigned char *) addr < (((unsigned char *)m->map) + m->length) &&
|
|
|
|
(((unsigned char *) addr) + page_size) >= (unsigned char *) m->map)
|
|
|
|
{
|
|
|
|
m->faulty = EINA_TRUE;
|
|
|
|
return EINA_TRUE;
|
|
|
|
}
|
|
|
|
return EINA_FALSE;
|
|
|
|
}
|
|
|
|
|
2017-08-29 20:03:41 -07:00
|
|
|
Eina_Bool
|
2012-03-07 00:58:55 -08:00
|
|
|
eina_file_mmap_faulty(void *addr, long page_size)
|
|
|
|
{
|
|
|
|
Eina_File_Map *m;
|
|
|
|
Eina_File *f;
|
|
|
|
Eina_Iterator *itf;
|
|
|
|
Eina_Iterator *itm;
|
2017-08-29 20:03:41 -07:00
|
|
|
Eina_Bool faulty = EINA_FALSE;
|
2012-03-07 00:58:55 -08:00
|
|
|
|
|
|
|
eina_lock_take(&_eina_file_lock_cache);
|
|
|
|
|
|
|
|
itf = eina_hash_iterator_data_new(_eina_file_cache);
|
|
|
|
EINA_ITERATOR_FOREACH(itf, f)
|
|
|
|
{
|
|
|
|
eina_lock_take(&f->lock);
|
|
|
|
|
2013-08-22 05:13:38 -07:00
|
|
|
if (f->global_map != MAP_FAILED)
|
2012-03-07 00:58:55 -08:00
|
|
|
{
|
2017-08-29 20:03:41 -07:00
|
|
|
if ((unsigned char *)addr <
|
|
|
|
(((unsigned char *)f->global_map) + f->length) &&
|
|
|
|
(((unsigned char *)addr) + page_size) >=
|
|
|
|
(unsigned char *)f->global_map)
|
2012-03-07 00:58:55 -08:00
|
|
|
{
|
|
|
|
f->global_faulty = EINA_TRUE;
|
|
|
|
faulty = EINA_TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!faulty)
|
|
|
|
{
|
|
|
|
itm = eina_hash_iterator_data_new(f->map);
|
|
|
|
EINA_ITERATOR_FOREACH(itm, m)
|
|
|
|
{
|
2013-07-31 01:16:20 -07:00
|
|
|
faulty = _eina_file_mmap_faulty_one(addr, page_size, m);
|
|
|
|
if (faulty) break;
|
2012-03-07 00:58:55 -08:00
|
|
|
}
|
|
|
|
eina_iterator_free(itm);
|
|
|
|
}
|
|
|
|
|
2013-07-31 01:16:20 -07:00
|
|
|
if (!faulty)
|
|
|
|
{
|
|
|
|
Eina_List *l;
|
|
|
|
|
|
|
|
EINA_LIST_FOREACH(f->dead_map, l, m)
|
|
|
|
{
|
|
|
|
faulty = _eina_file_mmap_faulty_one(addr, page_size, m);
|
|
|
|
if (faulty) break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-03-07 00:58:55 -08:00
|
|
|
eina_lock_release(&f->lock);
|
|
|
|
|
|
|
|
if (faulty) break;
|
|
|
|
}
|
|
|
|
eina_iterator_free(itf);
|
|
|
|
|
|
|
|
eina_lock_release(&_eina_file_lock_cache);
|
2017-08-29 20:03:41 -07:00
|
|
|
return faulty;
|
2012-03-07 00:58:55 -08:00
|
|
|
}
|
|
|
|
|
2013-03-14 04:49:45 -07:00
|
|
|
/* ================================================================ *
|
|
|
|
* Simplified logic for portability layer with eina_file_common *
|
|
|
|
* ================================================================ */
|
2008-08-08 22:47:15 -07:00
|
|
|
|
2013-03-14 04:49:45 -07:00
|
|
|
Eina_Bool
|
|
|
|
eina_file_path_relative(const char *path)
|
2011-10-03 19:33:45 -07:00
|
|
|
{
|
2013-03-14 04:49:45 -07:00
|
|
|
if (*path != '/') return EINA_TRUE;
|
|
|
|
return EINA_FALSE;
|
|
|
|
}
|
2011-10-03 19:33:45 -07:00
|
|
|
|
2013-03-14 04:49:45 -07:00
|
|
|
Eina_Tmpstr *
|
|
|
|
eina_file_current_directory_get(const char *path, size_t len)
|
|
|
|
{
|
|
|
|
char cwd[PATH_MAX];
|
|
|
|
char *tmp = NULL;
|
2011-10-03 19:33:45 -07:00
|
|
|
|
2013-03-14 04:49:45 -07:00
|
|
|
tmp = getcwd(cwd, PATH_MAX);
|
|
|
|
if (!tmp) return NULL;
|
2011-10-03 19:33:45 -07:00
|
|
|
|
2013-03-14 04:49:45 -07:00
|
|
|
len += strlen(cwd) + 2;
|
|
|
|
tmp = alloca(sizeof (char) * len);
|
2011-10-03 19:33:45 -07:00
|
|
|
|
2013-03-14 04:49:45 -07:00
|
|
|
slprintf(tmp, len, "%s/%s", cwd, path);
|
2011-10-03 19:33:45 -07:00
|
|
|
|
2013-03-14 04:49:45 -07:00
|
|
|
return eina_tmpstr_add_length(tmp, len);
|
|
|
|
}
|
2011-10-03 19:33:45 -07:00
|
|
|
|
2013-03-14 04:49:45 -07:00
|
|
|
char *
|
|
|
|
eina_file_cleanup(Eina_Tmpstr *path)
|
|
|
|
{
|
|
|
|
char *result;
|
2011-10-03 19:33:45 -07:00
|
|
|
|
2013-03-14 04:49:45 -07:00
|
|
|
result = strdup(path ? path : "");
|
|
|
|
eina_tmpstr_del(path);
|
2011-10-03 19:33:45 -07:00
|
|
|
|
2013-03-14 04:49:45 -07:00
|
|
|
return result;
|
2011-10-03 19:33:45 -07:00
|
|
|
}
|
|
|
|
|
2013-03-14 04:49:45 -07:00
|
|
|
/*============================================================================*
|
|
|
|
* API *
|
|
|
|
*============================================================================*/
|
|
|
|
|
|
|
|
|
|
|
|
|
2008-08-18 01:18:16 -07:00
|
|
|
EAPI Eina_Bool
|
2010-07-27 19:37:05 -07:00
|
|
|
eina_file_dir_list(const char *dir,
|
|
|
|
Eina_Bool recursive,
|
|
|
|
Eina_File_Dir_List_Cb cb,
|
|
|
|
void *data)
|
2008-07-30 05:46:55 -07:00
|
|
|
{
|
2011-03-22 09:33:34 -07:00
|
|
|
Eina_File_Direct_Info *info;
|
|
|
|
Eina_Iterator *it;
|
2010-11-06 00:37:52 -07:00
|
|
|
|
2010-07-27 19:37:05 -07:00
|
|
|
EINA_SAFETY_ON_NULL_RETURN_VAL(cb, EINA_FALSE);
|
|
|
|
EINA_SAFETY_ON_NULL_RETURN_VAL(dir, EINA_FALSE);
|
|
|
|
EINA_SAFETY_ON_TRUE_RETURN_VAL(dir[0] == '\0', EINA_FALSE);
|
2009-01-23 08:43:14 -08:00
|
|
|
|
2011-03-22 09:33:34 -07:00
|
|
|
it = eina_file_stat_ls(dir);
|
|
|
|
if (!it)
|
2010-07-27 19:37:05 -07:00
|
|
|
return EINA_FALSE;
|
2008-07-30 05:46:55 -07:00
|
|
|
|
2011-03-22 09:33:34 -07:00
|
|
|
EINA_ITERATOR_FOREACH(it, info)
|
2010-07-27 19:37:05 -07:00
|
|
|
{
|
2011-03-22 09:33:34 -07:00
|
|
|
cb(info->path + info->name_start, dir, data);
|
2008-08-18 01:18:16 -07:00
|
|
|
|
2011-03-22 09:33:34 -07:00
|
|
|
if (recursive == EINA_TRUE && info->type == EINA_FILE_DIR)
|
2010-07-27 19:37:05 -07:00
|
|
|
{
|
2011-03-22 09:33:34 -07:00
|
|
|
eina_file_dir_list(info->path, recursive, cb, data);
|
2010-07-27 19:37:05 -07:00
|
|
|
}
|
|
|
|
}
|
2008-08-18 01:18:16 -07:00
|
|
|
|
2011-03-22 09:33:34 -07:00
|
|
|
eina_iterator_free(it);
|
2008-07-30 05:46:55 -07:00
|
|
|
|
2010-07-27 19:37:05 -07:00
|
|
|
return EINA_TRUE;
|
2008-08-18 01:18:16 -07:00
|
|
|
}
|
2008-09-01 05:51:50 -07:00
|
|
|
|
2008-09-03 07:40:12 -07:00
|
|
|
EAPI Eina_Array *
|
|
|
|
eina_file_split(char *path)
|
2008-09-01 05:51:50 -07:00
|
|
|
{
|
2010-07-27 19:37:05 -07:00
|
|
|
Eina_Array *ea;
|
|
|
|
char *current;
|
|
|
|
size_t length;
|
2008-09-03 07:40:12 -07:00
|
|
|
|
2010-07-27 19:37:05 -07:00
|
|
|
EINA_SAFETY_ON_NULL_RETURN_VAL(path, NULL);
|
2008-09-03 07:40:12 -07:00
|
|
|
|
2010-07-27 19:37:05 -07:00
|
|
|
ea = eina_array_new(16);
|
2008-09-03 07:40:12 -07:00
|
|
|
|
2010-07-27 19:37:05 -07:00
|
|
|
if (!ea)
|
|
|
|
return NULL;
|
2008-09-01 05:51:50 -07:00
|
|
|
|
2010-07-27 19:37:05 -07:00
|
|
|
for (current = strchr(path, PATH_DELIM);
|
2010-08-21 06:52:25 -07:00
|
|
|
current;
|
2010-07-27 19:37:05 -07:00
|
|
|
path = current + 1, current = strchr(path, PATH_DELIM))
|
|
|
|
{
|
|
|
|
length = current - path;
|
2008-09-01 05:51:50 -07:00
|
|
|
|
2017-10-09 16:37:47 -07:00
|
|
|
if (length == 0)
|
2010-07-27 19:37:05 -07:00
|
|
|
continue;
|
2008-09-03 07:40:12 -07:00
|
|
|
|
2010-07-27 19:37:05 -07:00
|
|
|
eina_array_push(ea, path);
|
|
|
|
*current = '\0';
|
|
|
|
}
|
2008-09-01 05:51:50 -07:00
|
|
|
|
2010-07-27 19:37:05 -07:00
|
|
|
if (*path != '\0')
|
|
|
|
eina_array_push(ea, path);
|
2008-09-03 07:40:12 -07:00
|
|
|
|
2010-07-27 19:37:05 -07:00
|
|
|
return ea;
|
2008-09-03 07:40:12 -07:00
|
|
|
}
|
2008-09-18 22:22:43 -07:00
|
|
|
|
2010-07-02 10:23:05 -07:00
|
|
|
EAPI Eina_Iterator *
|
|
|
|
eina_file_ls(const char *dir)
|
|
|
|
{
|
2011-12-05 05:57:10 -08:00
|
|
|
#ifdef HAVE_DIRENT_H
|
2010-07-02 10:23:05 -07:00
|
|
|
Eina_File_Iterator *it;
|
|
|
|
size_t length;
|
2012-10-19 02:03:14 -07:00
|
|
|
DIR *dirp;
|
2010-07-02 10:23:05 -07:00
|
|
|
|
2011-09-15 06:57:27 -07:00
|
|
|
EINA_SAFETY_ON_NULL_RETURN_VAL(dir, NULL);
|
2010-07-02 10:23:05 -07:00
|
|
|
|
|
|
|
length = strlen(dir);
|
2010-07-27 19:37:05 -07:00
|
|
|
if (length < 1)
|
|
|
|
return NULL;
|
2010-07-02 10:23:05 -07:00
|
|
|
|
2012-10-19 02:03:14 -07:00
|
|
|
dirp = opendir(dir);
|
|
|
|
if (!dirp)
|
2010-07-27 19:37:05 -07:00
|
|
|
return NULL;
|
2010-07-02 10:23:05 -07:00
|
|
|
|
2012-10-19 02:03:14 -07:00
|
|
|
it = calloc(1, sizeof (Eina_File_Iterator) + length);
|
|
|
|
if (EINA_UNLIKELY(!it))
|
2010-07-02 10:23:05 -07:00
|
|
|
{
|
2012-10-19 02:03:14 -07:00
|
|
|
closedir(dirp);
|
2010-07-27 19:37:05 -07:00
|
|
|
return NULL;
|
2010-07-02 10:23:05 -07:00
|
|
|
}
|
|
|
|
|
2012-10-19 02:03:14 -07:00
|
|
|
EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR);
|
|
|
|
|
|
|
|
it->dirp = dirp;
|
|
|
|
|
2010-07-02 10:23:05 -07:00
|
|
|
memcpy(it->dir, dir, length + 1);
|
2010-07-06 08:45:12 -07:00
|
|
|
if (dir[length - 1] != '/')
|
2010-07-27 19:37:05 -07:00
|
|
|
it->length = length;
|
2010-07-06 08:45:12 -07:00
|
|
|
else
|
2010-07-27 19:37:05 -07:00
|
|
|
it->length = length - 1;
|
2010-07-02 10:23:05 -07:00
|
|
|
|
2010-08-19 05:02:28 -07:00
|
|
|
it->iterator.version = EINA_ITERATOR_VERSION;
|
2010-07-02 10:23:05 -07:00
|
|
|
it->iterator.next = FUNC_ITERATOR_NEXT(_eina_file_ls_iterator_next);
|
2010-07-27 19:37:05 -07:00
|
|
|
it->iterator.get_container = FUNC_ITERATOR_GET_CONTAINER(
|
|
|
|
_eina_file_ls_iterator_container);
|
2010-07-02 10:23:05 -07:00
|
|
|
it->iterator.free = FUNC_ITERATOR_FREE(_eina_file_ls_iterator_free);
|
|
|
|
|
|
|
|
return &it->iterator;
|
2011-12-05 05:57:10 -08:00
|
|
|
#else
|
|
|
|
(void) dir;
|
|
|
|
return NULL;
|
|
|
|
#endif
|
2010-07-02 10:23:05 -07:00
|
|
|
}
|
|
|
|
|
2010-07-06 08:45:12 -07:00
|
|
|
EAPI Eina_Iterator *
|
|
|
|
eina_file_direct_ls(const char *dir)
|
|
|
|
{
|
2011-12-05 05:57:10 -08:00
|
|
|
#ifdef HAVE_DIRENT_H
|
2010-07-06 08:45:12 -07:00
|
|
|
Eina_File_Direct_Iterator *it;
|
|
|
|
size_t length;
|
2012-10-19 02:03:14 -07:00
|
|
|
DIR *dirp;
|
2010-07-06 08:45:12 -07:00
|
|
|
|
2011-09-15 06:57:27 -07:00
|
|
|
EINA_SAFETY_ON_NULL_RETURN_VAL(dir, NULL);
|
2010-07-06 08:45:12 -07:00
|
|
|
|
|
|
|
length = strlen(dir);
|
2010-07-27 19:37:05 -07:00
|
|
|
if (length < 1)
|
|
|
|
return NULL;
|
|
|
|
|
2012-10-19 02:03:14 -07:00
|
|
|
dirp = opendir(dir);
|
|
|
|
if (!dirp)
|
2010-07-27 19:37:05 -07:00
|
|
|
return NULL;
|
2010-07-06 08:45:12 -07:00
|
|
|
|
2012-10-19 02:03:14 -07:00
|
|
|
it = calloc(1, sizeof(Eina_File_Direct_Iterator) + length);
|
|
|
|
if (EINA_UNLIKELY(!it))
|
2010-07-06 08:45:12 -07:00
|
|
|
{
|
2012-10-19 02:03:14 -07:00
|
|
|
closedir(dirp);
|
2010-07-27 19:37:05 -07:00
|
|
|
return NULL;
|
2010-07-06 08:45:12 -07:00
|
|
|
}
|
|
|
|
|
2012-10-19 02:03:14 -07:00
|
|
|
EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR);
|
|
|
|
|
|
|
|
it->dirp = dirp;
|
|
|
|
|
2011-09-18 14:56:54 -07:00
|
|
|
if (length + _eina_name_max(it->dirp) + 2 >= EINA_PATH_MAX)
|
|
|
|
{
|
|
|
|
_eina_file_direct_ls_iterator_free(it);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2010-07-27 19:37:05 -07:00
|
|
|
memcpy(it->dir, dir, length + 1);
|
2010-07-06 08:45:12 -07:00
|
|
|
it->length = length;
|
|
|
|
|
|
|
|
memcpy(it->info.path, dir, length);
|
|
|
|
if (dir[length - 1] == '/')
|
2010-07-27 19:37:05 -07:00
|
|
|
it->info.name_start = length;
|
2010-07-06 08:45:12 -07:00
|
|
|
else
|
|
|
|
{
|
2010-07-27 19:37:05 -07:00
|
|
|
it->info.path[length] = '/';
|
|
|
|
it->info.name_start = length + 1;
|
2010-07-06 08:45:12 -07:00
|
|
|
}
|
|
|
|
|
2010-08-19 05:02:28 -07:00
|
|
|
it->iterator.version = EINA_ITERATOR_VERSION;
|
2010-07-06 08:45:12 -07:00
|
|
|
it->iterator.next = FUNC_ITERATOR_NEXT(_eina_file_direct_ls_iterator_next);
|
2010-07-27 19:37:05 -07:00
|
|
|
it->iterator.get_container = FUNC_ITERATOR_GET_CONTAINER(
|
|
|
|
_eina_file_direct_ls_iterator_container);
|
2010-07-06 08:45:12 -07:00
|
|
|
it->iterator.free = FUNC_ITERATOR_FREE(_eina_file_direct_ls_iterator_free);
|
|
|
|
|
|
|
|
return &it->iterator;
|
2011-12-05 05:57:10 -08:00
|
|
|
#else
|
|
|
|
(void) dir;
|
|
|
|
return NULL;
|
|
|
|
#endif
|
2010-07-06 08:45:12 -07:00
|
|
|
}
|
|
|
|
|
2010-11-02 10:07:04 -07:00
|
|
|
EAPI Eina_Iterator *
|
|
|
|
eina_file_stat_ls(const char *dir)
|
|
|
|
{
|
2011-12-05 05:57:10 -08:00
|
|
|
#ifdef HAVE_DIRENT_H
|
2010-11-02 10:07:04 -07:00
|
|
|
Eina_File_Direct_Iterator *it;
|
|
|
|
size_t length;
|
2012-10-18 02:12:14 -07:00
|
|
|
DIR *dirp;
|
2010-11-02 10:07:04 -07:00
|
|
|
|
2011-09-15 06:57:27 -07:00
|
|
|
EINA_SAFETY_ON_NULL_RETURN_VAL(dir, NULL);
|
2010-11-02 10:07:04 -07:00
|
|
|
|
|
|
|
length = strlen(dir);
|
|
|
|
if (length < 1)
|
|
|
|
return NULL;
|
|
|
|
|
2012-10-18 02:12:14 -07:00
|
|
|
dirp = opendir(dir);
|
|
|
|
if (!dirp)
|
|
|
|
return NULL;
|
|
|
|
|
2010-11-02 10:07:04 -07:00
|
|
|
it = calloc(1, sizeof(Eina_File_Direct_Iterator) + length);
|
2012-10-19 02:03:14 -07:00
|
|
|
if (EINA_UNLIKELY(!it))
|
2012-10-19 01:18:59 -07:00
|
|
|
{
|
|
|
|
closedir(dirp);
|
|
|
|
return NULL;
|
|
|
|
}
|
2010-11-02 10:07:04 -07:00
|
|
|
|
|
|
|
EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR);
|
|
|
|
|
2012-10-18 02:12:14 -07:00
|
|
|
it->dirp = dirp;
|
2010-11-02 10:07:04 -07:00
|
|
|
|
2011-09-18 14:56:54 -07:00
|
|
|
if (length + _eina_name_max(it->dirp) + 2 >= EINA_PATH_MAX)
|
|
|
|
{
|
|
|
|
_eina_file_direct_ls_iterator_free(it);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2010-11-02 10:07:04 -07:00
|
|
|
memcpy(it->dir, dir, length + 1);
|
|
|
|
it->length = length;
|
|
|
|
|
|
|
|
memcpy(it->info.path, dir, length);
|
|
|
|
if (dir[length - 1] == '/')
|
|
|
|
it->info.name_start = length;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
it->info.path[length] = '/';
|
|
|
|
it->info.name_start = length + 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
it->iterator.version = EINA_ITERATOR_VERSION;
|
|
|
|
it->iterator.next = FUNC_ITERATOR_NEXT(_eina_file_stat_ls_iterator_next);
|
|
|
|
it->iterator.get_container = FUNC_ITERATOR_GET_CONTAINER(
|
|
|
|
_eina_file_direct_ls_iterator_container);
|
|
|
|
it->iterator.free = FUNC_ITERATOR_FREE(_eina_file_direct_ls_iterator_free);
|
|
|
|
|
|
|
|
return &it->iterator;
|
2011-12-05 05:57:10 -08:00
|
|
|
#else
|
|
|
|
(void) dir;
|
|
|
|
return NULL;
|
|
|
|
#endif
|
2010-11-02 10:07:04 -07:00
|
|
|
}
|
2011-04-13 09:15:30 -07:00
|
|
|
|
|
|
|
EAPI Eina_File *
|
2011-10-03 19:33:45 -07:00
|
|
|
eina_file_open(const char *path, Eina_Bool shared)
|
2011-04-13 09:15:30 -07:00
|
|
|
{
|
|
|
|
Eina_File *file;
|
|
|
|
Eina_File *n;
|
2017-10-17 16:14:26 -07:00
|
|
|
Eina_Stringshare *filename;
|
2011-04-13 09:15:30 -07:00
|
|
|
struct stat file_stat;
|
2011-10-03 19:33:45 -07:00
|
|
|
int fd = -1;
|
2011-04-13 09:15:30 -07:00
|
|
|
|
2011-10-03 19:33:45 -07:00
|
|
|
EINA_SAFETY_ON_NULL_RETURN_VAL(path, NULL);
|
2011-09-15 06:57:27 -07:00
|
|
|
|
2017-10-17 16:14:26 -07:00
|
|
|
filename = eina_file_sanitize(path);
|
2011-10-03 19:33:45 -07:00
|
|
|
if (!filename) return NULL;
|
2011-04-13 09:15:30 -07:00
|
|
|
|
|
|
|
if (shared)
|
2012-03-25 04:12:32 -07:00
|
|
|
#ifdef HAVE_SHM_OPEN
|
2011-04-13 22:52:24 -07:00
|
|
|
fd = shm_open(filename, O_RDONLY, S_IRWXU | S_IRWXG | S_IRWXO);
|
2011-07-13 01:51:19 -07:00
|
|
|
#else
|
2011-10-03 19:33:45 -07:00
|
|
|
goto on_error;
|
2011-07-13 01:51:19 -07:00
|
|
|
#endif
|
2011-04-13 09:15:30 -07:00
|
|
|
else
|
2011-04-13 22:52:24 -07:00
|
|
|
fd = open(filename, O_RDONLY, S_IRWXU | S_IRWXG | S_IRWXO);
|
2011-04-13 09:15:30 -07:00
|
|
|
|
2011-10-03 19:33:45 -07:00
|
|
|
if (fd < 0) goto on_error;
|
2011-04-13 09:15:30 -07:00
|
|
|
|
2017-04-18 16:54:03 -07:00
|
|
|
if (!eina_file_close_on_exec(fd, EINA_TRUE))
|
2011-04-13 22:52:24 -07:00
|
|
|
goto on_error;
|
|
|
|
|
2011-04-13 09:15:30 -07:00
|
|
|
if (fstat(fd, &file_stat))
|
2011-04-13 22:52:24 -07:00
|
|
|
goto on_error;
|
2011-04-13 09:15:30 -07:00
|
|
|
|
2011-06-06 10:08:06 -07:00
|
|
|
eina_lock_take(&_eina_file_lock_cache);
|
|
|
|
|
2011-04-13 09:15:30 -07:00
|
|
|
file = eina_hash_find(_eina_file_cache, filename);
|
2012-03-07 02:40:49 -08:00
|
|
|
if ((file) && !_eina_file_timestamp_compare(file, &file_stat))
|
2011-04-13 09:15:30 -07:00
|
|
|
{
|
2011-06-22 05:47:12 -07:00
|
|
|
file->delete_me = EINA_TRUE;
|
|
|
|
eina_hash_del(_eina_file_cache, file->filename, file);
|
|
|
|
file = NULL;
|
2011-04-13 09:15:30 -07:00
|
|
|
}
|
|
|
|
|
2011-06-22 05:47:12 -07:00
|
|
|
if (!file)
|
2011-04-13 09:15:30 -07:00
|
|
|
{
|
2017-10-17 16:14:26 -07:00
|
|
|
n = malloc(sizeof(Eina_File));
|
2011-10-03 18:55:41 -07:00
|
|
|
if (!n)
|
|
|
|
{
|
|
|
|
eina_lock_release(&_eina_file_lock_cache);
|
|
|
|
goto on_error;
|
|
|
|
}
|
2011-04-13 09:15:30 -07:00
|
|
|
|
2012-05-22 21:26:24 -07:00
|
|
|
memset(n, 0, sizeof(Eina_File));
|
2017-10-17 16:14:26 -07:00
|
|
|
n->filename = filename;
|
2013-07-30 19:51:51 -07:00
|
|
|
n->map = eina_hash_new(EINA_KEY_LENGTH(eina_file_map_key_length),
|
|
|
|
EINA_KEY_CMP(eina_file_map_key_cmp),
|
|
|
|
EINA_KEY_HASH(eina_file_map_key_hash),
|
2011-04-13 09:15:30 -07:00
|
|
|
EINA_FREE_CB(_eina_file_map_close),
|
|
|
|
3);
|
|
|
|
n->rmap = eina_hash_pointer_new(NULL);
|
|
|
|
n->global_map = MAP_FAILED;
|
|
|
|
n->length = file_stat.st_size;
|
|
|
|
n->mtime = file_stat.st_mtime;
|
2011-10-05 13:00:29 -07:00
|
|
|
#ifdef _STAT_VER_LINUX
|
|
|
|
# if (defined __USE_MISC && defined st_mtime)
|
|
|
|
n->mtime_nsec = (unsigned long int)file_stat.st_mtim.tv_nsec;
|
|
|
|
# else
|
|
|
|
n->mtime_nsec = (unsigned long int)file_stat.st_mtimensec;
|
|
|
|
# endif
|
|
|
|
#endif
|
2011-05-17 09:17:28 -07:00
|
|
|
n->inode = file_stat.st_ino;
|
2011-04-13 09:15:30 -07:00
|
|
|
n->fd = fd;
|
|
|
|
n->shared = shared;
|
2011-06-06 10:08:06 -07:00
|
|
|
eina_lock_new(&n->lock);
|
2011-05-17 09:17:28 -07:00
|
|
|
eina_hash_direct_add(_eina_file_cache, n->filename, n);
|
2013-11-20 03:06:50 -08:00
|
|
|
|
|
|
|
EINA_MAGIC_SET(n, EINA_FILE_MAGIC);
|
2011-04-13 09:15:30 -07:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
close(fd);
|
|
|
|
n = file;
|
|
|
|
}
|
2011-06-06 10:08:06 -07:00
|
|
|
eina_lock_take(&n->lock);
|
2011-04-13 09:15:30 -07:00
|
|
|
n->refcount++;
|
2011-06-06 10:08:06 -07:00
|
|
|
eina_lock_release(&n->lock);
|
|
|
|
|
|
|
|
eina_lock_release(&_eina_file_lock_cache);
|
2011-04-13 09:15:30 -07:00
|
|
|
|
|
|
|
return n;
|
|
|
|
|
|
|
|
on_error:
|
2014-02-21 23:37:15 -08:00
|
|
|
WRN("Could not open file [%s].", filename);
|
2017-10-17 16:14:26 -07:00
|
|
|
eina_stringshare_del(filename);
|
2014-02-21 00:13:09 -08:00
|
|
|
|
2011-10-03 19:33:45 -07:00
|
|
|
if (fd >= 0) close(fd);
|
2011-04-13 09:15:30 -07:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2013-07-31 01:16:20 -07:00
|
|
|
EAPI Eina_Bool
|
|
|
|
eina_file_refresh(Eina_File *file)
|
|
|
|
{
|
|
|
|
struct stat file_stat;
|
|
|
|
Eina_Bool r = EINA_FALSE;
|
|
|
|
|
|
|
|
EINA_SAFETY_ON_NULL_RETURN_VAL(file, EINA_FALSE);
|
|
|
|
|
|
|
|
if (file->virtual) return EINA_FALSE;
|
|
|
|
|
|
|
|
if (fstat(file->fd, &file_stat))
|
|
|
|
return EINA_FALSE;
|
|
|
|
|
|
|
|
if (file->length != (unsigned long int) file_stat.st_size)
|
|
|
|
{
|
|
|
|
eina_file_flush(file, file_stat.st_size);
|
|
|
|
r = EINA_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
file->length = file_stat.st_size;
|
|
|
|
file->mtime = file_stat.st_mtime;
|
|
|
|
#ifdef _STAT_VER_LINUX
|
|
|
|
# if (defined __USE_MISC && defined st_mtime)
|
|
|
|
file->mtime_nsec = (unsigned long int)file_stat.st_mtim.tv_nsec;
|
|
|
|
# else
|
|
|
|
file->mtime_nsec = (unsigned long int)file_stat.st_mtimensec;
|
|
|
|
# endif
|
|
|
|
#endif
|
|
|
|
file->inode = file_stat.st_ino;
|
|
|
|
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
eina_file: add eina_file_unlink
Test Plan: split D4423 - unlink
Reviewers: raster, vtorri, an.kroitor, jpeg, reutskiy.v.v, NikaWhite, cedric
Reviewed By: cedric
Subscribers: artem.popov, cedric, vtorri, jpeg
Tags: #windows, #efl
Differential Revision: https://phab.enlightenment.org/D4485
Signed-off-by: Cedric BAIL <cedric@osg.samsung.com>
2017-02-07 14:50:32 -08:00
|
|
|
EAPI Eina_Bool
|
|
|
|
eina_file_unlink(const char *pathname)
|
|
|
|
{
|
|
|
|
if ( unlink(pathname) < 0)
|
|
|
|
{
|
|
|
|
return EINA_FALSE;
|
|
|
|
}
|
|
|
|
return EINA_TRUE;
|
|
|
|
}
|
|
|
|
|
2011-04-13 09:15:30 -07:00
|
|
|
EAPI void *
|
|
|
|
eina_file_map_all(Eina_File *file, Eina_File_Populate rule)
|
|
|
|
{
|
|
|
|
int flags = MAP_SHARED;
|
2011-06-06 10:08:06 -07:00
|
|
|
void *ret = NULL;
|
2011-04-13 09:15:30 -07:00
|
|
|
|
2011-09-15 06:57:27 -07:00
|
|
|
EINA_SAFETY_ON_NULL_RETURN_VAL(file, NULL);
|
|
|
|
|
2013-07-30 19:51:51 -07:00
|
|
|
if (file->virtual) return eina_file_virtual_map_all(file);
|
|
|
|
|
|
|
|
// bsd people will lack this feature
|
2011-05-13 03:44:29 -07:00
|
|
|
#ifdef MAP_POPULATE
|
2011-04-13 09:15:30 -07:00
|
|
|
if (rule == EINA_FILE_POPULATE) flags |= MAP_POPULATE;
|
2011-04-21 04:54:16 -07:00
|
|
|
#endif
|
2011-05-13 03:44:29 -07:00
|
|
|
#ifdef MAP_HUGETLB
|
2017-09-14 23:56:17 -07:00
|
|
|
if (file->length >= EINA_HUGE_PAGE_MIN) flags |= MAP_HUGETLB;
|
2011-05-13 03:44:29 -07:00
|
|
|
#endif
|
|
|
|
|
2011-07-04 02:29:59 -07:00
|
|
|
eina_mmap_safety_enabled_set(EINA_TRUE);
|
2011-06-06 10:08:06 -07:00
|
|
|
eina_lock_take(&file->lock);
|
2011-04-13 09:15:30 -07:00
|
|
|
if (file->global_map == MAP_FAILED)
|
|
|
|
file->global_map = mmap(NULL, file->length, PROT_READ, flags, file->fd, 0);
|
2011-10-19 09:09:14 -07:00
|
|
|
#ifdef MAP_HUGETLB
|
|
|
|
if ((file->global_map == MAP_FAILED) && (flags & MAP_HUGETLB))
|
|
|
|
{
|
|
|
|
flags &= ~MAP_HUGETLB;
|
|
|
|
file->global_map = mmap(NULL, file->length, PROT_READ, flags, file->fd, 0);
|
|
|
|
}
|
|
|
|
#endif
|
2011-04-13 09:15:30 -07:00
|
|
|
|
|
|
|
if (file->global_map != MAP_FAILED)
|
|
|
|
{
|
2011-10-19 09:09:14 -07:00
|
|
|
Eina_Bool hugetlb = EINA_FALSE;
|
|
|
|
|
|
|
|
#ifdef MAP_HUGETLB
|
|
|
|
hugetlb = !!(flags & MAP_HUGETLB);
|
|
|
|
#endif
|
2017-09-14 22:38:29 -07:00
|
|
|
if (!file->global_refcount)
|
|
|
|
file->global_hugetlb = hugetlb;
|
|
|
|
else
|
|
|
|
hugetlb = file->global_hugetlb;
|
|
|
|
|
2017-09-14 23:56:17 -07:00
|
|
|
_eina_file_map_rule_apply(rule, file->global_map, 0, file->length, file->length, hugetlb);
|
2011-04-13 09:15:30 -07:00
|
|
|
file->global_refcount++;
|
2011-06-06 10:08:06 -07:00
|
|
|
ret = file->global_map;
|
2011-04-13 09:15:30 -07:00
|
|
|
}
|
2011-06-06 10:08:06 -07:00
|
|
|
|
|
|
|
eina_lock_release(&file->lock);
|
|
|
|
return ret;
|
2011-04-13 09:15:30 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
EAPI void *
|
|
|
|
eina_file_map_new(Eina_File *file, Eina_File_Populate rule,
|
|
|
|
unsigned long int offset, unsigned long int length)
|
|
|
|
{
|
|
|
|
Eina_File_Map *map;
|
|
|
|
unsigned long int key[2];
|
|
|
|
|
2011-08-10 15:42:27 -07:00
|
|
|
EINA_SAFETY_ON_NULL_RETURN_VAL(file, NULL);
|
|
|
|
|
2011-04-13 09:15:30 -07:00
|
|
|
if (offset > file->length)
|
|
|
|
return NULL;
|
|
|
|
if (offset + length > file->length)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
if (offset == 0 && length == file->length)
|
|
|
|
return eina_file_map_all(file, rule);
|
|
|
|
|
2013-07-30 19:51:51 -07:00
|
|
|
if (file->virtual)
|
|
|
|
return eina_file_virtual_map_new(file, offset, length);
|
|
|
|
|
2011-04-13 09:15:30 -07:00
|
|
|
key[0] = offset;
|
|
|
|
key[1] = length;
|
|
|
|
|
2011-07-04 02:29:59 -07:00
|
|
|
eina_mmap_safety_enabled_set(EINA_TRUE);
|
2011-06-06 10:08:06 -07:00
|
|
|
eina_lock_take(&file->lock);
|
|
|
|
|
2011-04-13 09:15:30 -07:00
|
|
|
map = eina_hash_find(file->map, &key);
|
|
|
|
if (!map)
|
|
|
|
{
|
|
|
|
int flags = MAP_SHARED;
|
|
|
|
|
2011-04-21 04:54:16 -07:00
|
|
|
// bsd people will lack this feature
|
2011-05-13 03:44:29 -07:00
|
|
|
#ifdef MAP_POPULATE
|
2011-04-13 09:15:30 -07:00
|
|
|
if (rule == EINA_FILE_POPULATE) flags |= MAP_POPULATE;
|
2011-04-21 04:54:16 -07:00
|
|
|
#endif
|
2011-05-13 03:44:29 -07:00
|
|
|
#ifdef MAP_HUGETLB
|
2017-09-14 23:56:17 -07:00
|
|
|
if (length >= EINA_HUGE_PAGE_MIN) flags |= MAP_HUGETLB;
|
2011-05-13 03:44:29 -07:00
|
|
|
#endif
|
|
|
|
|
2011-04-13 09:15:30 -07:00
|
|
|
map = malloc(sizeof (Eina_File_Map));
|
2011-06-06 10:08:06 -07:00
|
|
|
if (!map) goto on_error;
|
2011-04-13 09:15:30 -07:00
|
|
|
|
|
|
|
map->map = mmap(NULL, length, PROT_READ, flags, file->fd, offset);
|
2011-10-19 09:09:14 -07:00
|
|
|
#ifdef MAP_HUGETLB
|
|
|
|
if (map->map == MAP_FAILED && (flags & MAP_HUGETLB))
|
|
|
|
{
|
|
|
|
flags &= ~MAP_HUGETLB;
|
|
|
|
map->map = mmap(NULL, length, PROT_READ, flags, file->fd, offset);
|
|
|
|
}
|
|
|
|
|
|
|
|
map->hugetlb = !!(flags & MAP_HUGETLB);
|
|
|
|
#else
|
|
|
|
map->hugetlb = EINA_FALSE;
|
|
|
|
#endif
|
2011-04-13 09:15:30 -07:00
|
|
|
map->offset = offset;
|
|
|
|
map->length = length;
|
|
|
|
map->refcount = 0;
|
|
|
|
|
2011-06-06 10:08:06 -07:00
|
|
|
if (map->map == MAP_FAILED) goto on_error;
|
2011-04-13 09:15:30 -07:00
|
|
|
|
|
|
|
eina_hash_add(file->map, &key, map);
|
2013-02-06 01:28:00 -08:00
|
|
|
eina_hash_direct_add(file->rmap, &map->map, map);
|
2011-04-13 09:15:30 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
map->refcount++;
|
|
|
|
|
2017-09-14 23:56:17 -07:00
|
|
|
_eina_file_map_rule_apply(rule, map->map, 0, length, map->length, map->hugetlb);
|
2011-04-13 09:15:30 -07:00
|
|
|
|
2011-06-06 10:08:06 -07:00
|
|
|
eina_lock_release(&file->lock);
|
|
|
|
|
2011-04-13 09:15:30 -07:00
|
|
|
return map->map;
|
2011-06-06 10:08:06 -07:00
|
|
|
|
|
|
|
on_error:
|
|
|
|
free(map);
|
|
|
|
eina_lock_release(&file->lock);
|
|
|
|
|
|
|
|
return NULL;
|
2011-04-13 09:15:30 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
EAPI void
|
|
|
|
eina_file_map_free(Eina_File *file, void *map)
|
|
|
|
{
|
2011-09-15 06:57:27 -07:00
|
|
|
EINA_SAFETY_ON_NULL_RETURN(file);
|
|
|
|
|
2013-07-30 19:51:51 -07:00
|
|
|
if (file->virtual)
|
2014-07-13 03:44:34 -07:00
|
|
|
{
|
|
|
|
eina_file_virtual_map_free(file, map);
|
|
|
|
return;
|
|
|
|
}
|
2013-07-30 19:51:51 -07:00
|
|
|
|
2011-06-06 10:08:06 -07:00
|
|
|
eina_lock_take(&file->lock);
|
|
|
|
|
2011-04-13 09:15:30 -07:00
|
|
|
if (file->global_map == map)
|
|
|
|
{
|
|
|
|
file->global_refcount--;
|
|
|
|
|
2011-06-06 10:08:06 -07:00
|
|
|
if (file->global_refcount > 0) goto on_exit;
|
2011-04-13 09:15:30 -07:00
|
|
|
|
|
|
|
munmap(file->global_map, file->length);
|
|
|
|
file->global_map = MAP_FAILED;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2013-07-31 01:16:20 -07:00
|
|
|
eina_file_common_map_free(file, map, _eina_file_map_close);
|
2011-04-13 09:15:30 -07:00
|
|
|
}
|
2011-06-06 10:08:06 -07:00
|
|
|
|
|
|
|
on_exit:
|
|
|
|
eina_lock_release(&file->lock);
|
2011-04-13 09:15:30 -07:00
|
|
|
}
|
|
|
|
|
2013-07-06 06:01:23 -07:00
|
|
|
EAPI void
|
2013-10-28 02:26:10 -07:00
|
|
|
eina_file_map_populate(Eina_File *file, Eina_File_Populate rule, const void *map,
|
2013-07-06 06:01:23 -07:00
|
|
|
unsigned long int offset, unsigned long int length)
|
|
|
|
{
|
2017-09-14 23:56:17 -07:00
|
|
|
Eina_File_Map *em;
|
|
|
|
|
2013-07-06 06:01:23 -07:00
|
|
|
EINA_SAFETY_ON_NULL_RETURN(file);
|
|
|
|
eina_lock_take(&file->lock);
|
2017-09-14 22:38:29 -07:00
|
|
|
if (map == file->global_map)
|
2017-09-14 23:56:17 -07:00
|
|
|
_eina_file_map_rule_apply(rule, map, offset, length, file->length, file->global_hugetlb);
|
|
|
|
else if ((em = eina_hash_find(file->rmap, &map)) != NULL)
|
|
|
|
_eina_file_map_rule_apply(rule, map, offset, length, em->length, em->hugetlb);
|
2013-07-06 06:01:23 -07:00
|
|
|
eina_lock_release(&file->lock);
|
|
|
|
}
|
|
|
|
|
2012-01-03 06:59:07 -08:00
|
|
|
EAPI Eina_Bool
|
|
|
|
eina_file_map_faulted(Eina_File *file, void *map)
|
|
|
|
{
|
2012-03-14 08:35:12 -07:00
|
|
|
Eina_Bool r = EINA_FALSE;
|
2012-01-03 06:59:07 -08:00
|
|
|
|
|
|
|
EINA_SAFETY_ON_NULL_RETURN_VAL(file, EINA_FALSE);
|
|
|
|
|
2013-07-30 19:51:51 -07:00
|
|
|
if (file->virtual) return EINA_FALSE;
|
|
|
|
|
2012-01-03 06:59:07 -08:00
|
|
|
eina_lock_take(&file->lock);
|
|
|
|
|
2012-03-14 08:35:12 -07:00
|
|
|
if (file->global_map == map)
|
|
|
|
{
|
|
|
|
r = file->global_faulty;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2013-07-31 01:16:20 -07:00
|
|
|
Eina_File_Map *em;
|
|
|
|
|
2012-03-14 08:35:12 -07:00
|
|
|
em = eina_hash_find(file->rmap, &map);
|
2013-07-31 01:16:20 -07:00
|
|
|
if (em)
|
|
|
|
{
|
|
|
|
r = em->faulty;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Eina_List *l;
|
|
|
|
|
|
|
|
EINA_LIST_FOREACH(file->dead_map, l, em)
|
|
|
|
if (em->map == map)
|
|
|
|
{
|
|
|
|
r = em->faulty;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2012-03-14 08:35:12 -07:00
|
|
|
}
|
2012-01-03 06:59:07 -08:00
|
|
|
|
2012-03-14 08:35:12 -07:00
|
|
|
eina_lock_release(&file->lock);
|
2012-01-03 06:59:07 -08:00
|
|
|
|
2012-03-14 08:35:12 -07:00
|
|
|
return r;
|
2012-01-03 06:59:07 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
EAPI Eina_Iterator *
|
|
|
|
eina_file_xattr_get(Eina_File *file)
|
|
|
|
{
|
|
|
|
EINA_SAFETY_ON_NULL_RETURN_VAL(file, NULL);
|
|
|
|
|
2013-07-30 19:51:51 -07:00
|
|
|
if (file->virtual) return NULL;
|
|
|
|
|
2012-01-03 06:59:07 -08:00
|
|
|
return eina_xattr_fd_ls(file->fd);
|
|
|
|
}
|
|
|
|
|
|
|
|
EAPI Eina_Iterator *
|
|
|
|
eina_file_xattr_value_get(Eina_File *file)
|
|
|
|
{
|
|
|
|
EINA_SAFETY_ON_NULL_RETURN_VAL(file, NULL);
|
|
|
|
|
2013-07-30 19:51:51 -07:00
|
|
|
if (file->virtual) return NULL;
|
|
|
|
|
2012-01-03 06:59:07 -08:00
|
|
|
return eina_xattr_value_fd_ls(file->fd);
|
|
|
|
}
|
|
|
|
|
2012-02-22 02:24:11 -08:00
|
|
|
EAPI int
|
2012-02-23 03:45:25 -08:00
|
|
|
eina_file_statat(void *container, Eina_File_Direct_Info *info, Eina_Stat *st)
|
2012-02-22 02:24:11 -08:00
|
|
|
{
|
2012-02-23 03:45:25 -08:00
|
|
|
struct stat buf;
|
2012-12-06 13:15:30 -08:00
|
|
|
#ifdef HAVE_ATFILE_SOURCE
|
2012-02-22 02:24:11 -08:00
|
|
|
int fd;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
EINA_SAFETY_ON_NULL_RETURN_VAL(info, -1);
|
2012-02-23 03:45:25 -08:00
|
|
|
EINA_SAFETY_ON_NULL_RETURN_VAL(st, -1);
|
2012-02-22 02:24:11 -08:00
|
|
|
|
2012-12-06 13:15:30 -08:00
|
|
|
#ifdef HAVE_ATFILE_SOURCE
|
2012-03-13 04:25:56 -07:00
|
|
|
fd = dirfd((DIR*) container);
|
2012-02-23 03:45:25 -08:00
|
|
|
if (fstatat(fd, info->path + info->name_start, &buf, 0))
|
2012-02-22 02:24:11 -08:00
|
|
|
#else
|
2012-03-07 11:52:21 -08:00
|
|
|
(void)container;
|
2012-02-23 03:45:25 -08:00
|
|
|
if (stat(info->path, &buf))
|
2012-02-22 02:24:11 -08:00
|
|
|
#endif
|
2012-02-22 03:50:29 -08:00
|
|
|
{
|
|
|
|
if (info->type != EINA_FILE_LNK)
|
|
|
|
info->type = EINA_FILE_UNKNOWN;
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (info->type == EINA_FILE_UNKNOWN)
|
|
|
|
{
|
2012-02-23 03:45:25 -08:00
|
|
|
if (S_ISREG(buf.st_mode))
|
2012-02-22 03:50:29 -08:00
|
|
|
info->type = EINA_FILE_REG;
|
2012-02-23 03:45:25 -08:00
|
|
|
else if (S_ISDIR(buf.st_mode))
|
2012-02-22 03:50:29 -08:00
|
|
|
info->type = EINA_FILE_DIR;
|
2012-02-23 03:45:25 -08:00
|
|
|
else if (S_ISCHR(buf.st_mode))
|
2012-02-22 03:50:29 -08:00
|
|
|
info->type = EINA_FILE_CHR;
|
2012-02-23 03:45:25 -08:00
|
|
|
else if (S_ISBLK(buf.st_mode))
|
2012-02-22 03:50:29 -08:00
|
|
|
info->type = EINA_FILE_BLK;
|
2012-02-23 03:45:25 -08:00
|
|
|
else if (S_ISFIFO(buf.st_mode))
|
2012-02-22 03:50:29 -08:00
|
|
|
info->type = EINA_FILE_FIFO;
|
2012-02-23 03:45:25 -08:00
|
|
|
else if (S_ISLNK(buf.st_mode))
|
2012-02-22 03:50:29 -08:00
|
|
|
info->type = EINA_FILE_LNK;
|
2012-02-23 03:45:25 -08:00
|
|
|
else if (S_ISSOCK(buf.st_mode))
|
2012-02-22 03:50:29 -08:00
|
|
|
info->type = EINA_FILE_SOCK;
|
|
|
|
else
|
|
|
|
info->type = EINA_FILE_UNKNOWN;
|
|
|
|
}
|
|
|
|
|
2012-02-23 03:45:25 -08:00
|
|
|
st->dev = buf.st_dev;
|
|
|
|
st->ino = buf.st_ino;
|
|
|
|
st->mode = buf.st_mode;
|
|
|
|
st->nlink = buf.st_nlink;
|
|
|
|
st->uid = buf.st_uid;
|
|
|
|
st->gid = buf.st_gid;
|
|
|
|
st->rdev = buf.st_rdev;
|
|
|
|
st->size = buf.st_size;
|
|
|
|
st->blksize = buf.st_blksize;
|
|
|
|
st->blocks = buf.st_blocks;
|
|
|
|
st->atime = buf.st_atime;
|
|
|
|
st->mtime = buf.st_mtime;
|
|
|
|
st->ctime = buf.st_ctime;
|
|
|
|
#ifdef _STAT_VER_LINUX
|
|
|
|
# if (defined __USE_MISC && defined st_mtime)
|
|
|
|
st->atimensec = buf.st_atim.tv_nsec;
|
|
|
|
st->mtimensec = buf.st_mtim.tv_nsec;
|
|
|
|
st->ctimensec = buf.st_ctim.tv_nsec;
|
|
|
|
# else
|
|
|
|
st->atimensec = buf.st_atimensec;
|
|
|
|
st->mtimensec = buf.st_mtimensec;
|
|
|
|
st->ctimensec = buf.st_ctimensec;
|
|
|
|
# endif
|
|
|
|
#else
|
|
|
|
st->atimensec = 0;
|
|
|
|
st->mtimensec = 0;
|
|
|
|
st->ctimensec = 0;
|
|
|
|
#endif
|
2012-02-22 03:50:29 -08:00
|
|
|
return 0;
|
2012-02-22 02:24:11 -08:00
|
|
|
}
|
2012-12-31 15:17:18 -08:00
|
|
|
|