forked from enlightenment/efl
eina: improve portability of Eina_File.
This commit is contained in:
parent
81f739da84
commit
c002d113f1
|
@ -107,6 +107,8 @@ lib/eina/eina_counter.c \
|
||||||
lib/eina/eina_cow.c \
|
lib/eina/eina_cow.c \
|
||||||
lib/eina/eina_cpu.c \
|
lib/eina/eina_cpu.c \
|
||||||
lib/eina/eina_error.c \
|
lib/eina/eina_error.c \
|
||||||
|
lib/eina/eina_file_common.h \
|
||||||
|
lib/eina/eina_file_common.c \
|
||||||
lib/eina/eina_fp.c \
|
lib/eina/eina_fp.c \
|
||||||
lib/eina/eina_hamster.c \
|
lib/eina/eina_hamster.c \
|
||||||
lib/eina/eina_hash.c \
|
lib/eina/eina_hash.c \
|
||||||
|
|
|
@ -53,6 +53,7 @@
|
||||||
#include "eina_mmap.h"
|
#include "eina_mmap.h"
|
||||||
#include "eina_log.h"
|
#include "eina_log.h"
|
||||||
#include "eina_xattr.h"
|
#include "eina_xattr.h"
|
||||||
|
#include "eina_file_common.h"
|
||||||
|
|
||||||
#ifdef HAVE_ESCAPE
|
#ifdef HAVE_ESCAPE
|
||||||
# include <Escape.h>
|
# include <Escape.h>
|
||||||
|
@ -106,50 +107,6 @@ struct _Eina_File_Iterator
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct _Eina_File
|
|
||||||
{
|
|
||||||
const char *filename;
|
|
||||||
|
|
||||||
Eina_Hash *map;
|
|
||||||
Eina_Hash *rmap;
|
|
||||||
void *global_map;
|
|
||||||
|
|
||||||
Eina_Lock lock;
|
|
||||||
|
|
||||||
unsigned long long length;
|
|
||||||
time_t mtime;
|
|
||||||
ino_t inode;
|
|
||||||
#ifdef _STAT_VER_LINUX
|
|
||||||
unsigned long int mtime_nsec;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
int refcount;
|
|
||||||
int global_refcount;
|
|
||||||
|
|
||||||
int fd;
|
|
||||||
|
|
||||||
Eina_Bool shared : 1;
|
|
||||||
Eina_Bool delete_me : 1;
|
|
||||||
Eina_Bool global_faulty : 1;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct _Eina_File_Map Eina_File_Map;
|
|
||||||
struct _Eina_File_Map
|
|
||||||
{
|
|
||||||
void *map;
|
|
||||||
|
|
||||||
unsigned long int offset;
|
|
||||||
unsigned long int length;
|
|
||||||
|
|
||||||
int refcount;
|
|
||||||
|
|
||||||
Eina_Bool hugetlb : 1;
|
|
||||||
Eina_Bool faulty : 1;
|
|
||||||
};
|
|
||||||
|
|
||||||
static Eina_Hash *_eina_file_cache = NULL;
|
|
||||||
static Eina_Lock _eina_file_lock_cache;
|
|
||||||
|
|
||||||
static int _eina_file_log_dom = -1;
|
static int _eina_file_log_dom = -1;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -368,8 +325,8 @@ _eina_file_stat_ls_iterator_next(Eina_File_Direct_Iterator *it, void **data)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static void
|
void
|
||||||
_eina_file_real_close(Eina_File *file)
|
eina_file_real_close(Eina_File *file)
|
||||||
{
|
{
|
||||||
if (file->refcount != 0) return;
|
if (file->refcount != 0) return;
|
||||||
|
|
||||||
|
@ -488,90 +445,6 @@ slprintf(char *str, size_t size, const char *format, ...)
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *
|
|
||||||
_eina_file_escape(const char *path, int *length)
|
|
||||||
{
|
|
||||||
char *result;
|
|
||||||
char *p;
|
|
||||||
char *q;
|
|
||||||
size_t len;
|
|
||||||
|
|
||||||
result = strdup(path ? path : "");
|
|
||||||
p = result;
|
|
||||||
q = result;
|
|
||||||
|
|
||||||
if (!result)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
if (length) len = *length;
|
|
||||||
else len = strlen(result);
|
|
||||||
|
|
||||||
while ((p = strchr(p, '/')))
|
|
||||||
{
|
|
||||||
// remove double `/'
|
|
||||||
if (p[1] == '/')
|
|
||||||
{
|
|
||||||
memmove(p, p + 1, --len - (p - result));
|
|
||||||
result[len] = '\0';
|
|
||||||
}
|
|
||||||
else
|
|
||||||
if (p[1] == '.'
|
|
||||||
&& p[2] == '.')
|
|
||||||
{
|
|
||||||
// remove `/../'
|
|
||||||
if (p[3] == '/')
|
|
||||||
{
|
|
||||||
char tmp;
|
|
||||||
|
|
||||||
len -= p + 3 - q;
|
|
||||||
memmove(q, p + 3, len - (q - result));
|
|
||||||
result[len] = '\0';
|
|
||||||
p = q;
|
|
||||||
|
|
||||||
/* Update q correctly. */
|
|
||||||
tmp = *p;
|
|
||||||
*p = '\0';
|
|
||||||
q = strrchr(result, '/');
|
|
||||||
if (!q) q = result;
|
|
||||||
*p = tmp;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
// remove '/..$'
|
|
||||||
if (p[3] == '\0')
|
|
||||||
{
|
|
||||||
len -= p + 2 - q;
|
|
||||||
result[len] = '\0';
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
q = p;
|
|
||||||
++p;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
if (p[1] == '.'
|
|
||||||
&& p[2] == '/')
|
|
||||||
{
|
|
||||||
// remove '/./'
|
|
||||||
len -= 2;
|
|
||||||
memmove(p, p + 2, len - (p - result));
|
|
||||||
result[len] = '\0';
|
|
||||||
q = p;
|
|
||||||
++p;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
q = p;
|
|
||||||
++p;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (length)
|
|
||||||
*length = len;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @endcond
|
* @endcond
|
||||||
*/
|
*/
|
||||||
|
@ -683,38 +556,50 @@ eina_file_mmap_faulty(void *addr, long page_size)
|
||||||
eina_lock_release(&_eina_file_lock_cache);
|
eina_lock_release(&_eina_file_lock_cache);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ================================================================ *
|
||||||
|
* Simplified logic for portability layer with eina_file_common *
|
||||||
|
* ================================================================ */
|
||||||
|
|
||||||
|
Eina_Bool
|
||||||
|
eina_file_path_relative(const char *path)
|
||||||
|
{
|
||||||
|
if (*path != '/') return EINA_TRUE;
|
||||||
|
return EINA_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
Eina_Tmpstr *
|
||||||
|
eina_file_current_directory_get(const char *path, size_t len)
|
||||||
|
{
|
||||||
|
char cwd[PATH_MAX];
|
||||||
|
char *tmp = NULL;
|
||||||
|
|
||||||
|
tmp = getcwd(cwd, PATH_MAX);
|
||||||
|
if (!tmp) return NULL;
|
||||||
|
|
||||||
|
len += strlen(cwd) + 2;
|
||||||
|
tmp = alloca(sizeof (char) * len);
|
||||||
|
|
||||||
|
slprintf(tmp, len, "%s/%s", cwd, path);
|
||||||
|
|
||||||
|
return eina_tmpstr_add_length(tmp, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
char *
|
||||||
|
eina_file_cleanup(Eina_Tmpstr *path)
|
||||||
|
{
|
||||||
|
char *result;
|
||||||
|
|
||||||
|
result = strdup(path ? path : "");
|
||||||
|
eina_tmpstr_del(path);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
/*============================================================================*
|
/*============================================================================*
|
||||||
* API *
|
* API *
|
||||||
*============================================================================*/
|
*============================================================================*/
|
||||||
|
|
||||||
EAPI char *
|
|
||||||
eina_file_path_sanitize(const char *path)
|
|
||||||
{
|
|
||||||
char *result = NULL;
|
|
||||||
int len;
|
|
||||||
|
|
||||||
if (!path) return NULL;
|
|
||||||
|
|
||||||
len = strlen(path);
|
|
||||||
|
|
||||||
if (*path != '/')
|
|
||||||
{
|
|
||||||
char cwd[PATH_MAX];
|
|
||||||
char *tmp = NULL;
|
|
||||||
|
|
||||||
tmp = getcwd(cwd, PATH_MAX);
|
|
||||||
if (!tmp) return NULL;
|
|
||||||
|
|
||||||
len += strlen(cwd) + 2;
|
|
||||||
tmp = alloca(sizeof (char) * len);
|
|
||||||
|
|
||||||
slprintf(tmp, len, "%s/%s", cwd, path);
|
|
||||||
|
|
||||||
result = tmp;
|
|
||||||
}
|
|
||||||
|
|
||||||
return _eina_file_escape(result ? result : path, &len);
|
|
||||||
}
|
|
||||||
|
|
||||||
EAPI Eina_Bool
|
EAPI Eina_Bool
|
||||||
eina_file_dir_list(const char *dir,
|
eina_file_dir_list(const char *dir,
|
||||||
|
@ -997,7 +882,7 @@ eina_file_open(const char *path, Eina_Bool shared)
|
||||||
{
|
{
|
||||||
file->delete_me = EINA_TRUE;
|
file->delete_me = EINA_TRUE;
|
||||||
eina_hash_del(_eina_file_cache, file->filename, file);
|
eina_hash_del(_eina_file_cache, file->filename, file);
|
||||||
_eina_file_real_close(file);
|
eina_file_real_close(file);
|
||||||
file = NULL;
|
file = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1056,45 +941,6 @@ eina_file_open(const char *path, Eina_Bool shared)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
EAPI void
|
|
||||||
eina_file_close(Eina_File *file)
|
|
||||||
{
|
|
||||||
EINA_SAFETY_ON_NULL_RETURN(file);
|
|
||||||
|
|
||||||
eina_lock_take(&file->lock);
|
|
||||||
file->refcount--;
|
|
||||||
eina_lock_release(&file->lock);
|
|
||||||
|
|
||||||
if (file->refcount != 0) return;
|
|
||||||
eina_lock_take(&_eina_file_lock_cache);
|
|
||||||
|
|
||||||
eina_hash_del(_eina_file_cache, file->filename, file);
|
|
||||||
_eina_file_real_close(file);
|
|
||||||
|
|
||||||
eina_lock_release(&_eina_file_lock_cache);
|
|
||||||
}
|
|
||||||
|
|
||||||
EAPI size_t
|
|
||||||
eina_file_size_get(Eina_File *file)
|
|
||||||
{
|
|
||||||
EINA_SAFETY_ON_NULL_RETURN_VAL(file, 0);
|
|
||||||
return file->length;
|
|
||||||
}
|
|
||||||
|
|
||||||
EAPI time_t
|
|
||||||
eina_file_mtime_get(Eina_File *file)
|
|
||||||
{
|
|
||||||
EINA_SAFETY_ON_NULL_RETURN_VAL(file, 0);
|
|
||||||
return file->mtime;
|
|
||||||
}
|
|
||||||
|
|
||||||
EAPI const char *
|
|
||||||
eina_file_filename_get(Eina_File *file)
|
|
||||||
{
|
|
||||||
EINA_SAFETY_ON_NULL_RETURN_VAL(file, NULL);
|
|
||||||
return file->filename;
|
|
||||||
}
|
|
||||||
|
|
||||||
EAPI void *
|
EAPI void *
|
||||||
eina_file_map_all(Eina_File *file, Eina_File_Populate rule)
|
eina_file_map_all(Eina_File *file, Eina_File_Populate rule)
|
||||||
{
|
{
|
||||||
|
@ -1139,145 +985,6 @@ eina_file_map_all(Eina_File *file, Eina_File_Populate rule)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef struct _Eina_Lines_Iterator Eina_Lines_Iterator;
|
|
||||||
struct _Eina_Lines_Iterator
|
|
||||||
{
|
|
||||||
Eina_Iterator iterator;
|
|
||||||
|
|
||||||
Eina_File *fp;
|
|
||||||
const char *map;
|
|
||||||
const char *end;
|
|
||||||
|
|
||||||
int boundary;
|
|
||||||
|
|
||||||
Eina_File_Line current;
|
|
||||||
};
|
|
||||||
|
|
||||||
/* search '\r' and '\n' by preserving cache locality and page locality
|
|
||||||
in doing a search inside 4K boundary.
|
|
||||||
*/
|
|
||||||
static inline const char *
|
|
||||||
_eina_fine_eol(const char *start, int boundary, const char *end)
|
|
||||||
{
|
|
||||||
const char *cr;
|
|
||||||
const char *lf;
|
|
||||||
unsigned long long chunk;
|
|
||||||
|
|
||||||
while (start < end)
|
|
||||||
{
|
|
||||||
chunk = start + boundary < end ? boundary : end - start;
|
|
||||||
cr = memchr(start, '\r', chunk);
|
|
||||||
lf = memchr(start, '\n', chunk);
|
|
||||||
if (cr)
|
|
||||||
{
|
|
||||||
if (lf && lf < cr)
|
|
||||||
return lf + 1;
|
|
||||||
return cr + 1;
|
|
||||||
}
|
|
||||||
else if (lf)
|
|
||||||
return lf + 1;
|
|
||||||
|
|
||||||
start += chunk;
|
|
||||||
boundary = 4096;
|
|
||||||
}
|
|
||||||
|
|
||||||
return end;
|
|
||||||
}
|
|
||||||
|
|
||||||
static Eina_Bool
|
|
||||||
_eina_file_map_lines_iterator_next(Eina_Lines_Iterator *it, void **data)
|
|
||||||
{
|
|
||||||
const char *eol;
|
|
||||||
unsigned char match;
|
|
||||||
|
|
||||||
if (it->current.end >= it->end)
|
|
||||||
return EINA_FALSE;
|
|
||||||
|
|
||||||
match = *it->current.end;
|
|
||||||
while ((*it->current.end == '\n' || *it->current.end == '\r')
|
|
||||||
&& it->current.end < it->end)
|
|
||||||
{
|
|
||||||
if (match == *it->current.end)
|
|
||||||
it->current.index++;
|
|
||||||
it->current.end++;
|
|
||||||
}
|
|
||||||
it->current.index++;
|
|
||||||
|
|
||||||
if (it->current.end == it->end)
|
|
||||||
return EINA_FALSE;
|
|
||||||
|
|
||||||
eol = _eina_fine_eol(it->current.end,
|
|
||||||
it->boundary,
|
|
||||||
it->end);
|
|
||||||
it->boundary = (uintptr_t) eol & 0x3FF;
|
|
||||||
if (it->boundary == 0) it->boundary = 4096;
|
|
||||||
|
|
||||||
it->current.start = it->current.end;
|
|
||||||
|
|
||||||
it->current.end = eol;
|
|
||||||
it->current.length = eol - it->current.start - 1;
|
|
||||||
|
|
||||||
*data = &it->current;
|
|
||||||
return EINA_TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static Eina_File *
|
|
||||||
_eina_file_map_lines_iterator_container(Eina_Lines_Iterator *it)
|
|
||||||
{
|
|
||||||
return it->fp;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
_eina_file_map_lines_iterator_free(Eina_Lines_Iterator *it)
|
|
||||||
{
|
|
||||||
eina_file_map_free(it->fp, (void*) it->map);
|
|
||||||
eina_file_close(it->fp);
|
|
||||||
|
|
||||||
EINA_MAGIC_SET(&it->iterator, 0);
|
|
||||||
free(it);
|
|
||||||
}
|
|
||||||
|
|
||||||
EAPI Eina_Iterator *
|
|
||||||
eina_file_map_lines(Eina_File *file)
|
|
||||||
{
|
|
||||||
Eina_Lines_Iterator *it;
|
|
||||||
|
|
||||||
EINA_SAFETY_ON_NULL_RETURN_VAL(file, NULL);
|
|
||||||
|
|
||||||
if (file->length == 0) return NULL;
|
|
||||||
|
|
||||||
it = calloc(1, sizeof (Eina_Lines_Iterator));
|
|
||||||
if (!it) return NULL;
|
|
||||||
|
|
||||||
EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR);
|
|
||||||
|
|
||||||
it->map = eina_file_map_all(file, EINA_FILE_SEQUENTIAL);
|
|
||||||
if (!it->map)
|
|
||||||
{
|
|
||||||
free(it);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
eina_lock_take(&file->lock);
|
|
||||||
file->refcount++;
|
|
||||||
eina_lock_release(&file->lock);
|
|
||||||
|
|
||||||
it->fp = file;
|
|
||||||
it->boundary = 4096;
|
|
||||||
it->current.start = it->map;
|
|
||||||
it->current.end = it->current.start;
|
|
||||||
it->current.index = 0;
|
|
||||||
it->current.length = 0;
|
|
||||||
it->end = it->map + it->fp->length;
|
|
||||||
|
|
||||||
it->iterator.version = EINA_ITERATOR_VERSION;
|
|
||||||
it->iterator.next = FUNC_ITERATOR_NEXT(_eina_file_map_lines_iterator_next);
|
|
||||||
it->iterator.get_container = FUNC_ITERATOR_GET_CONTAINER(_eina_file_map_lines_iterator_container);
|
|
||||||
it->iterator.free = FUNC_ITERATOR_FREE(_eina_file_map_lines_iterator_free);
|
|
||||||
|
|
||||||
return &it->iterator;
|
|
||||||
}
|
|
||||||
|
|
||||||
EAPI void *
|
EAPI void *
|
||||||
eina_file_map_new(Eina_File *file, Eina_File_Populate rule,
|
eina_file_map_new(Eina_File *file, Eina_File_Populate rule,
|
||||||
unsigned long int offset, unsigned long int length)
|
unsigned long int offset, unsigned long int length)
|
||||||
|
|
|
@ -0,0 +1,303 @@
|
||||||
|
/* EINA - EFL data type library
|
||||||
|
* Copyright (C) 2013 Cedric Bail
|
||||||
|
*
|
||||||
|
* 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
# include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#define COPY_BLOCKSIZE (4 * 1024 * 1024)
|
||||||
|
|
||||||
|
#include "eina_config.h"
|
||||||
|
#include "eina_private.h"
|
||||||
|
|
||||||
|
#include "eina_hash.h"
|
||||||
|
#include "eina_safety_checks.h"
|
||||||
|
#include "eina_file_common.h"
|
||||||
|
|
||||||
|
#ifdef HAVE_ESCAPE
|
||||||
|
# include <Escape.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
Eina_Hash *_eina_file_cache = NULL;
|
||||||
|
Eina_Lock _eina_file_lock_cache;
|
||||||
|
|
||||||
|
static char *
|
||||||
|
_eina_file_escape(char *path, size_t len)
|
||||||
|
{
|
||||||
|
char *result;
|
||||||
|
char *p;
|
||||||
|
char *q;
|
||||||
|
|
||||||
|
result = path;
|
||||||
|
p = result;
|
||||||
|
q = result;
|
||||||
|
|
||||||
|
if (!result)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
while ((p = strchr(p, '/')))
|
||||||
|
{
|
||||||
|
// remove double `/'
|
||||||
|
if (p[1] == '/')
|
||||||
|
{
|
||||||
|
memmove(p, p + 1, --len - (p - result));
|
||||||
|
result[len] = '\0';
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if (p[1] == '.'
|
||||||
|
&& p[2] == '.')
|
||||||
|
{
|
||||||
|
// remove `/../'
|
||||||
|
if (p[3] == '/')
|
||||||
|
{
|
||||||
|
char tmp;
|
||||||
|
|
||||||
|
len -= p + 3 - q;
|
||||||
|
memmove(q, p + 3, len - (q - result));
|
||||||
|
result[len] = '\0';
|
||||||
|
p = q;
|
||||||
|
|
||||||
|
/* Update q correctly. */
|
||||||
|
tmp = *p;
|
||||||
|
*p = '\0';
|
||||||
|
q = strrchr(result, '/');
|
||||||
|
if (!q) q = result;
|
||||||
|
*p = tmp;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
// remove '/..$'
|
||||||
|
if (p[3] == '\0')
|
||||||
|
{
|
||||||
|
len -= p + 2 - q;
|
||||||
|
result[len] = '\0';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
q = p;
|
||||||
|
++p;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if (p[1] == '.'
|
||||||
|
&& p[2] == '/')
|
||||||
|
{
|
||||||
|
// remove '/./'
|
||||||
|
len -= 2;
|
||||||
|
memmove(p, p + 2, len - (p - result));
|
||||||
|
result[len] = '\0';
|
||||||
|
q = p;
|
||||||
|
++p;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
q = p;
|
||||||
|
++p;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Global API
|
||||||
|
|
||||||
|
EAPI char *
|
||||||
|
eina_file_path_sanitize(const char *path)
|
||||||
|
{
|
||||||
|
Eina_Tmpstr *result = NULL;
|
||||||
|
size_t len;
|
||||||
|
|
||||||
|
if (!path) return NULL;
|
||||||
|
|
||||||
|
len = strlen(path);
|
||||||
|
|
||||||
|
if (eina_file_path_relative(path))
|
||||||
|
result = eina_file_current_directory_get(path, len);
|
||||||
|
else
|
||||||
|
result = path;
|
||||||
|
|
||||||
|
return _eina_file_escape(eina_file_cleanup(result),
|
||||||
|
eina_tmpstr_strlen(result));
|
||||||
|
}
|
||||||
|
|
||||||
|
EAPI void
|
||||||
|
eina_file_close(Eina_File *file)
|
||||||
|
{
|
||||||
|
EINA_SAFETY_ON_NULL_RETURN(file);
|
||||||
|
|
||||||
|
eina_lock_take(&file->lock);
|
||||||
|
file->refcount--;
|
||||||
|
eina_lock_release(&file->lock);
|
||||||
|
if (file->refcount != 0) return ;
|
||||||
|
|
||||||
|
eina_lock_take(&_eina_file_lock_cache);
|
||||||
|
|
||||||
|
eina_hash_del(_eina_file_cache, file->filename, file);
|
||||||
|
eina_file_real_close(file);
|
||||||
|
|
||||||
|
eina_lock_release(&_eina_file_lock_cache);
|
||||||
|
}
|
||||||
|
|
||||||
|
EAPI size_t
|
||||||
|
eina_file_size_get(Eina_File *file)
|
||||||
|
{
|
||||||
|
EINA_SAFETY_ON_NULL_RETURN_VAL(file, 0);
|
||||||
|
return file->length;
|
||||||
|
}
|
||||||
|
|
||||||
|
EAPI time_t
|
||||||
|
eina_file_mtime_get(Eina_File *file)
|
||||||
|
{
|
||||||
|
EINA_SAFETY_ON_NULL_RETURN_VAL(file, 0);
|
||||||
|
return file->mtime;
|
||||||
|
}
|
||||||
|
|
||||||
|
EAPI const char *
|
||||||
|
eina_file_filename_get(Eina_File *file)
|
||||||
|
{
|
||||||
|
EINA_SAFETY_ON_NULL_RETURN_VAL(file, NULL);
|
||||||
|
return file->filename;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* search '\r' and '\n' by preserving cache locality and page locality
|
||||||
|
in doing a search inside 4K boundary.
|
||||||
|
*/
|
||||||
|
static inline const char *
|
||||||
|
_eina_fine_eol(const char *start, int boundary, const char *end)
|
||||||
|
{
|
||||||
|
const char *cr;
|
||||||
|
const char *lf;
|
||||||
|
unsigned long long chunk;
|
||||||
|
|
||||||
|
while (start < end)
|
||||||
|
{
|
||||||
|
chunk = start + boundary < end ? boundary : end - start;
|
||||||
|
cr = memchr(start, '\r', chunk);
|
||||||
|
lf = memchr(start, '\n', chunk);
|
||||||
|
if (cr)
|
||||||
|
{
|
||||||
|
if (lf && lf < cr)
|
||||||
|
return lf + 1;
|
||||||
|
return cr + 1;
|
||||||
|
}
|
||||||
|
else if (lf)
|
||||||
|
return lf + 1;
|
||||||
|
|
||||||
|
start += chunk;
|
||||||
|
boundary = 4096;
|
||||||
|
}
|
||||||
|
|
||||||
|
return end;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Eina_Bool
|
||||||
|
_eina_file_map_lines_iterator_next(Eina_Lines_Iterator *it, void **data)
|
||||||
|
{
|
||||||
|
const char *eol;
|
||||||
|
unsigned char match;
|
||||||
|
|
||||||
|
if (it->current.end >= it->end)
|
||||||
|
return EINA_FALSE;
|
||||||
|
|
||||||
|
match = *it->current.end;
|
||||||
|
while ((*it->current.end == '\n' || *it->current.end == '\r')
|
||||||
|
&& it->current.end < it->end)
|
||||||
|
{
|
||||||
|
if (match == *it->current.end)
|
||||||
|
it->current.index++;
|
||||||
|
it->current.end++;
|
||||||
|
}
|
||||||
|
it->current.index++;
|
||||||
|
|
||||||
|
if (it->current.end == it->end)
|
||||||
|
return EINA_FALSE;
|
||||||
|
|
||||||
|
eol = _eina_fine_eol(it->current.end,
|
||||||
|
it->boundary,
|
||||||
|
it->end);
|
||||||
|
it->boundary = (uintptr_t) eol & 0x3FF;
|
||||||
|
if (it->boundary == 0) it->boundary = 4096;
|
||||||
|
|
||||||
|
it->current.start = it->current.end;
|
||||||
|
|
||||||
|
it->current.end = eol;
|
||||||
|
it->current.length = eol - it->current.start - 1;
|
||||||
|
|
||||||
|
*data = &it->current;
|
||||||
|
return EINA_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Eina_File *
|
||||||
|
_eina_file_map_lines_iterator_container(Eina_Lines_Iterator *it)
|
||||||
|
{
|
||||||
|
return it->fp;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_eina_file_map_lines_iterator_free(Eina_Lines_Iterator *it)
|
||||||
|
{
|
||||||
|
eina_file_map_free(it->fp, (void*) it->map);
|
||||||
|
eina_file_close(it->fp);
|
||||||
|
|
||||||
|
EINA_MAGIC_SET(&it->iterator, 0);
|
||||||
|
free(it);
|
||||||
|
}
|
||||||
|
|
||||||
|
EAPI Eina_Iterator *
|
||||||
|
eina_file_map_lines(Eina_File *file)
|
||||||
|
{
|
||||||
|
Eina_Lines_Iterator *it;
|
||||||
|
|
||||||
|
EINA_SAFETY_ON_NULL_RETURN_VAL(file, NULL);
|
||||||
|
|
||||||
|
if (file->length == 0) return NULL;
|
||||||
|
|
||||||
|
it = calloc(1, sizeof (Eina_Lines_Iterator));
|
||||||
|
if (!it) return NULL;
|
||||||
|
|
||||||
|
EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR);
|
||||||
|
|
||||||
|
it->map = eina_file_map_all(file, EINA_FILE_SEQUENTIAL);
|
||||||
|
if (!it->map)
|
||||||
|
{
|
||||||
|
free(it);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
eina_lock_take(&file->lock);
|
||||||
|
file->refcount++;
|
||||||
|
eina_lock_release(&file->lock);
|
||||||
|
|
||||||
|
it->fp = file;
|
||||||
|
it->boundary = 4096;
|
||||||
|
it->current.start = it->map;
|
||||||
|
it->current.end = it->current.start;
|
||||||
|
it->current.index = 0;
|
||||||
|
it->current.length = 0;
|
||||||
|
it->end = it->map + it->fp->length;
|
||||||
|
|
||||||
|
it->iterator.version = EINA_ITERATOR_VERSION;
|
||||||
|
it->iterator.next = FUNC_ITERATOR_NEXT(_eina_file_map_lines_iterator_next);
|
||||||
|
it->iterator.get_container = FUNC_ITERATOR_GET_CONTAINER(_eina_file_map_lines_iterator_container);
|
||||||
|
it->iterator.free = FUNC_ITERATOR_FREE(_eina_file_map_lines_iterator_free);
|
||||||
|
|
||||||
|
return &it->iterator;
|
||||||
|
}
|
|
@ -0,0 +1,100 @@
|
||||||
|
/* EINA - EFL data type library
|
||||||
|
* Copyright (C) 2013 Cedric Bail
|
||||||
|
*
|
||||||
|
* 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef EINA_FILE_COMMON_H_
|
||||||
|
# define EINA_FILE_COMMON_H_
|
||||||
|
|
||||||
|
#include "eina_file.h"
|
||||||
|
#include "eina_tmpstr.h"
|
||||||
|
#include "eina_lock.h"
|
||||||
|
|
||||||
|
typedef struct _Eina_File_Map Eina_File_Map;
|
||||||
|
typedef struct _Eina_Lines_Iterator Eina_Lines_Iterator;
|
||||||
|
|
||||||
|
struct _Eina_File
|
||||||
|
{
|
||||||
|
const char *filename;
|
||||||
|
|
||||||
|
Eina_Hash *map;
|
||||||
|
Eina_Hash *rmap;
|
||||||
|
void *global_map;
|
||||||
|
|
||||||
|
Eina_Lock lock;
|
||||||
|
|
||||||
|
#ifndef _WIN32
|
||||||
|
unsigned long long length;
|
||||||
|
time_t mtime;
|
||||||
|
ino_t inode;
|
||||||
|
#ifdef _STAT_VER_LINUX
|
||||||
|
unsigned long int mtime_nsec;
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
ULONGLONG length;
|
||||||
|
ULONGLONG mtime;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int refcount;
|
||||||
|
int global_refcount;
|
||||||
|
|
||||||
|
#ifndef _WIN32
|
||||||
|
int fd;
|
||||||
|
#else
|
||||||
|
HANDLE handle;
|
||||||
|
HANDLE fm;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
Eina_Bool shared : 1;
|
||||||
|
Eina_Bool delete_me : 1;
|
||||||
|
Eina_Bool global_faulty : 1;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _Eina_File_Map
|
||||||
|
{
|
||||||
|
void *map;
|
||||||
|
|
||||||
|
unsigned long int offset;
|
||||||
|
unsigned long int length;
|
||||||
|
|
||||||
|
int refcount;
|
||||||
|
|
||||||
|
Eina_Bool hugetlb : 1;
|
||||||
|
Eina_Bool faulty : 1;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _Eina_Lines_Iterator
|
||||||
|
{
|
||||||
|
Eina_Iterator iterator;
|
||||||
|
|
||||||
|
Eina_File *fp;
|
||||||
|
const char *map;
|
||||||
|
const char *end;
|
||||||
|
|
||||||
|
int boundary;
|
||||||
|
|
||||||
|
Eina_File_Line current;
|
||||||
|
};
|
||||||
|
|
||||||
|
Eina_Bool eina_file_path_relative(const char *path);
|
||||||
|
Eina_Tmpstr *eina_file_current_directory_get(const char *path, size_t len);
|
||||||
|
char *eina_file_cleanup(Eina_Tmpstr *path);
|
||||||
|
void eina_file_real_close(Eina_File *file);
|
||||||
|
|
||||||
|
extern Eina_Hash *_eina_file_cache;
|
||||||
|
extern Eina_Lock _eina_file_lock_cache;
|
||||||
|
|
||||||
|
#endif /* EINA_FILE_COMMON_H_ */
|
|
@ -41,6 +41,7 @@
|
||||||
#include "eina_list.h"
|
#include "eina_list.h"
|
||||||
#include "eina_lock.h"
|
#include "eina_lock.h"
|
||||||
#include "eina_log.h"
|
#include "eina_log.h"
|
||||||
|
#include "eina_file_common.h"
|
||||||
|
|
||||||
/*============================================================================*
|
/*============================================================================*
|
||||||
* Local *
|
* Local *
|
||||||
|
@ -118,42 +119,6 @@ struct _Eina_File_Direct_Iterator
|
||||||
char dir[1];
|
char dir[1];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _Eina_File
|
|
||||||
{
|
|
||||||
const char *filename;
|
|
||||||
|
|
||||||
Eina_Hash *map;
|
|
||||||
Eina_Hash *rmap;
|
|
||||||
void *global_map;
|
|
||||||
|
|
||||||
Eina_Lock lock;
|
|
||||||
|
|
||||||
ULONGLONG length;
|
|
||||||
ULONGLONG mtime;
|
|
||||||
|
|
||||||
int refcount;
|
|
||||||
int global_refcount;
|
|
||||||
|
|
||||||
HANDLE handle;
|
|
||||||
HANDLE fm;
|
|
||||||
|
|
||||||
Eina_Bool shared : 1;
|
|
||||||
Eina_Bool delete_me : 1;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct _Eina_File_Map
|
|
||||||
{
|
|
||||||
void *map;
|
|
||||||
|
|
||||||
unsigned long int offset;
|
|
||||||
unsigned long int length;
|
|
||||||
|
|
||||||
int refcount;
|
|
||||||
};
|
|
||||||
|
|
||||||
static Eina_Hash *_eina_file_cache = NULL;
|
|
||||||
static Eina_Lock _eina_file_lock_cache;
|
|
||||||
|
|
||||||
static int _eina_file_log_dom = -1;
|
static int _eina_file_log_dom = -1;
|
||||||
|
|
||||||
static Eina_Bool
|
static Eina_Bool
|
||||||
|
@ -429,8 +394,8 @@ _eina_file_win32_direct_ls_iterator_free(Eina_File_Direct_Iterator *it)
|
||||||
free(it);
|
free(it);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
void
|
||||||
_eina_file_real_close(Eina_File *file)
|
eina_file_real_close(Eina_File *file)
|
||||||
{
|
{
|
||||||
eina_hash_free(file->rmap);
|
eina_hash_free(file->rmap);
|
||||||
eina_hash_free(file->map);
|
eina_hash_free(file->map);
|
||||||
|
@ -473,175 +438,6 @@ _eina_file_map_key_hash(const unsigned long int *key, int key_length EINA_UNUSED
|
||||||
^ eina_hash_int64(&key[1], sizeof (unsigned long int));
|
^ eina_hash_int64(&key[1], sizeof (unsigned long int));
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *
|
|
||||||
_eina_file_win32_escape(const char *path, size_t *length)
|
|
||||||
{
|
|
||||||
char *result;
|
|
||||||
char *p;
|
|
||||||
char *q;
|
|
||||||
size_t len;
|
|
||||||
|
|
||||||
result = strdup(path ? path : "");
|
|
||||||
if (!result)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
p = result;
|
|
||||||
while (*p)
|
|
||||||
{
|
|
||||||
if (*p == '\\') *p = '/';
|
|
||||||
p++;
|
|
||||||
}
|
|
||||||
p = result;
|
|
||||||
q = result;
|
|
||||||
|
|
||||||
if (!result)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
if (length) len = *length;
|
|
||||||
else len = strlen(result);
|
|
||||||
|
|
||||||
while ((p = strchr(p, '/')))
|
|
||||||
{
|
|
||||||
// remove double `/'
|
|
||||||
if (p[1] == '/')
|
|
||||||
{
|
|
||||||
memmove(p, p + 1, --len - (p - result));
|
|
||||||
result[len] = '\0';
|
|
||||||
}
|
|
||||||
else
|
|
||||||
if (p[1] == '.'
|
|
||||||
&& p[2] == '.')
|
|
||||||
{
|
|
||||||
// remove `/../'
|
|
||||||
if (p[3] == '/')
|
|
||||||
{
|
|
||||||
char tmp;
|
|
||||||
|
|
||||||
len -= p + 3 - q;
|
|
||||||
memmove(q, p + 3, len - (q - result));
|
|
||||||
result[len] = '\0';
|
|
||||||
p = q;
|
|
||||||
|
|
||||||
/* Update q correctly. */
|
|
||||||
tmp = *p;
|
|
||||||
*p = '\0';
|
|
||||||
q = strrchr(result, '/');
|
|
||||||
if (!q) q = result;
|
|
||||||
*p = tmp;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
// remove '/..$'
|
|
||||||
if (p[3] == '\0')
|
|
||||||
{
|
|
||||||
len -= p + 2 - q;
|
|
||||||
result[len] = '\0';
|
|
||||||
q = p;
|
|
||||||
++p;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
q = p;
|
|
||||||
++p;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
q = p;
|
|
||||||
++p;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (length)
|
|
||||||
*length = len;
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* search '\r' and '\n' by preserving cache locality and page locality
|
|
||||||
in doing a search inside 4K boundary.
|
|
||||||
*/
|
|
||||||
static inline const char *
|
|
||||||
_eina_fine_eol(const char *start, int boundary, const char *end)
|
|
||||||
{
|
|
||||||
const char *cr;
|
|
||||||
const char *lf;
|
|
||||||
unsigned long long chunk;
|
|
||||||
|
|
||||||
while (start < end)
|
|
||||||
{
|
|
||||||
chunk = start + boundary < end ? boundary : end - start;
|
|
||||||
cr = memchr(start, '\r', chunk);
|
|
||||||
lf = memchr(start, '\n', chunk);
|
|
||||||
if (cr)
|
|
||||||
{
|
|
||||||
if (lf && lf < cr)
|
|
||||||
return lf + 1;
|
|
||||||
return cr + 1;
|
|
||||||
}
|
|
||||||
else if (lf)
|
|
||||||
return lf + 1;
|
|
||||||
|
|
||||||
start += chunk;
|
|
||||||
boundary = 4096;
|
|
||||||
}
|
|
||||||
|
|
||||||
return end;
|
|
||||||
}
|
|
||||||
|
|
||||||
static Eina_Bool
|
|
||||||
_eina_file_map_lines_iterator_next(Eina_Lines_Iterator *it, void **data)
|
|
||||||
{
|
|
||||||
const char *eol;
|
|
||||||
unsigned char match;
|
|
||||||
|
|
||||||
if (it->current.end >= it->end)
|
|
||||||
return EINA_FALSE;
|
|
||||||
|
|
||||||
match = *it->current.end;
|
|
||||||
while ((*it->current.end == '\n' || *it->current.end == '\r')
|
|
||||||
&& it->current.end < it->end)
|
|
||||||
{
|
|
||||||
if (match == *it->current.end)
|
|
||||||
it->current.index++;
|
|
||||||
it->current.end++;
|
|
||||||
}
|
|
||||||
it->current.index++;
|
|
||||||
|
|
||||||
if (it->current.end == it->end)
|
|
||||||
return EINA_FALSE;
|
|
||||||
|
|
||||||
eol = _eina_fine_eol(it->current.end,
|
|
||||||
it->boundary,
|
|
||||||
it->end);
|
|
||||||
it->boundary = (uintptr_t) eol & 0x3FF;
|
|
||||||
if (it->boundary == 0) it->boundary = 4096;
|
|
||||||
|
|
||||||
it->current.start = it->current.end;
|
|
||||||
|
|
||||||
it->current.end = eol;
|
|
||||||
it->current.length = eol - it->current.start - 1;
|
|
||||||
|
|
||||||
*data = &it->current;
|
|
||||||
return EINA_TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static Eina_File *
|
|
||||||
_eina_file_map_lines_iterator_container(Eina_Lines_Iterator *it)
|
|
||||||
{
|
|
||||||
return it->fp;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
_eina_file_map_lines_iterator_free(Eina_Lines_Iterator *it)
|
|
||||||
{
|
|
||||||
eina_file_map_free(it->fp, (void*) it->map);
|
|
||||||
eina_file_close(it->fp);
|
|
||||||
|
|
||||||
EINA_MAGIC_SET(&it->iterator, 0);
|
|
||||||
free(it);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @endcond
|
* @endcond
|
||||||
*/
|
*/
|
||||||
|
@ -698,44 +494,64 @@ eina_file_shutdown(void)
|
||||||
return EINA_TRUE;
|
return EINA_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* ================================================================ *
|
||||||
|
* Simplified logic for portability layer with eina_file_common *
|
||||||
|
* ================================================================ */
|
||||||
|
|
||||||
|
Eina_Bool
|
||||||
|
eina_file_path_relative(const char *path)
|
||||||
|
{
|
||||||
|
if (!evil_path_is_absolute(path)) return EINA_TRUE;
|
||||||
|
return EINA_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
Eina_Tmpstr *
|
||||||
|
eina_file_current_directory_get(const char *path, size_t len)
|
||||||
|
{
|
||||||
|
char *cwd;
|
||||||
|
char *tmp;
|
||||||
|
DWORD l;
|
||||||
|
|
||||||
|
l = GetCurrentDirectory(0, NULL);
|
||||||
|
if (l <= 0) return NULL;
|
||||||
|
|
||||||
|
cwd = alloca(sizeof(char) * (l + 1));
|
||||||
|
GetCurrentDirectory(l + 1, cwd);
|
||||||
|
len += l + 2;
|
||||||
|
tmp = alloca(sizeof (char) * len);
|
||||||
|
snprintf(tmp, len, "%s\\%s", cwd, path);
|
||||||
|
tmp[len - 1] = '\0';
|
||||||
|
|
||||||
|
return eina_tmpstr_add_length(tmp, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
char *
|
||||||
|
eina_file_cleanup(Eina_Tmpstr *path)
|
||||||
|
{
|
||||||
|
char *result;
|
||||||
|
char *p;
|
||||||
|
|
||||||
|
result = strdup(path ? path : "");
|
||||||
|
eina_tmpstr_del(path);
|
||||||
|
|
||||||
|
if (!result)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
p = result;
|
||||||
|
while (*p)
|
||||||
|
{
|
||||||
|
if (*p == '\\') *p = '/';
|
||||||
|
p++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
/*============================================================================*
|
/*============================================================================*
|
||||||
* API *
|
* API *
|
||||||
*============================================================================*/
|
*============================================================================*/
|
||||||
|
|
||||||
|
|
||||||
EAPI char *
|
|
||||||
eina_file_path_sanitize(const char *path)
|
|
||||||
{
|
|
||||||
char *result = NULL;
|
|
||||||
size_t len;
|
|
||||||
|
|
||||||
if (!path) return NULL;
|
|
||||||
|
|
||||||
len = strlen(path);
|
|
||||||
|
|
||||||
if (!evil_path_is_absolute(path))
|
|
||||||
{
|
|
||||||
DWORD l;
|
|
||||||
|
|
||||||
l = GetCurrentDirectory(0, NULL);
|
|
||||||
if (l > 0)
|
|
||||||
{
|
|
||||||
char *cwd;
|
|
||||||
char *tmp;
|
|
||||||
|
|
||||||
cwd = alloca(sizeof(char) * (l + 1));
|
|
||||||
GetCurrentDirectory(l + 1, cwd);
|
|
||||||
len += l + 2;
|
|
||||||
tmp = alloca(sizeof (char) * len);
|
|
||||||
snprintf(tmp, len, "%s\\%s", cwd, path);
|
|
||||||
tmp[len - 1] = '\0';
|
|
||||||
result = tmp;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return _eina_file_win32_escape(result ? result : path, &len);
|
|
||||||
}
|
|
||||||
|
|
||||||
EAPI Eina_Bool
|
EAPI Eina_Bool
|
||||||
eina_file_dir_list(const char *dir,
|
eina_file_dir_list(const char *dir,
|
||||||
Eina_Bool recursive,
|
Eina_Bool recursive,
|
||||||
|
@ -1011,7 +827,7 @@ eina_file_open(const char *path, Eina_Bool shared)
|
||||||
{
|
{
|
||||||
file->delete_me = EINA_TRUE;
|
file->delete_me = EINA_TRUE;
|
||||||
eina_hash_del(_eina_file_cache, file->filename, file);
|
eina_hash_del(_eina_file_cache, file->filename, file);
|
||||||
_eina_file_real_close(file);
|
eina_file_real_close(file);
|
||||||
file = NULL;
|
file = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1067,45 +883,6 @@ eina_file_open(const char *path, Eina_Bool shared)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
EAPI void
|
|
||||||
eina_file_close(Eina_File *file)
|
|
||||||
{
|
|
||||||
EINA_SAFETY_ON_NULL_RETURN(file);
|
|
||||||
|
|
||||||
eina_lock_take(&file->lock);
|
|
||||||
file->refcount--;
|
|
||||||
eina_lock_release(&file->lock);
|
|
||||||
|
|
||||||
if (file->refcount != 0) return ;
|
|
||||||
eina_lock_take(&_eina_file_lock_cache);
|
|
||||||
|
|
||||||
eina_hash_del(_eina_file_cache, file->filename, file);
|
|
||||||
_eina_file_real_close(file);
|
|
||||||
|
|
||||||
eina_lock_release(&_eina_file_lock_cache);
|
|
||||||
}
|
|
||||||
|
|
||||||
EAPI size_t
|
|
||||||
eina_file_size_get(Eina_File *file)
|
|
||||||
{
|
|
||||||
EINA_SAFETY_ON_NULL_RETURN_VAL(file, 0);
|
|
||||||
return file->length;
|
|
||||||
}
|
|
||||||
|
|
||||||
EAPI time_t
|
|
||||||
eina_file_mtime_get(Eina_File *file)
|
|
||||||
{
|
|
||||||
EINA_SAFETY_ON_NULL_RETURN_VAL(file, 0);
|
|
||||||
return file->mtime;
|
|
||||||
}
|
|
||||||
|
|
||||||
EAPI const char *
|
|
||||||
eina_file_filename_get(Eina_File *file)
|
|
||||||
{
|
|
||||||
EINA_SAFETY_ON_NULL_RETURN_VAL(file, NULL);
|
|
||||||
return file->filename;
|
|
||||||
}
|
|
||||||
|
|
||||||
EAPI Eina_Iterator *eina_file_xattr_get(Eina_File *file EINA_UNUSED)
|
EAPI Eina_Iterator *eina_file_xattr_get(Eina_File *file EINA_UNUSED)
|
||||||
{
|
{
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -1144,47 +921,6 @@ eina_file_map_all(Eina_File *file, Eina_File_Populate rule EINA_UNUSED)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
EAPI Eina_Iterator *
|
|
||||||
eina_file_map_lines(Eina_File *file)
|
|
||||||
{
|
|
||||||
Eina_Lines_Iterator *it;
|
|
||||||
|
|
||||||
EINA_SAFETY_ON_NULL_RETURN_VAL(file, NULL);
|
|
||||||
|
|
||||||
if (file->length == 0) return NULL;
|
|
||||||
|
|
||||||
it = calloc(1, sizeof (Eina_Lines_Iterator));
|
|
||||||
if (!it) return NULL;
|
|
||||||
|
|
||||||
EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR);
|
|
||||||
|
|
||||||
it->map = eina_file_map_all(file, EINA_FILE_SEQUENTIAL);
|
|
||||||
if (!it->map)
|
|
||||||
{
|
|
||||||
free(it);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
eina_lock_take(&file->lock);
|
|
||||||
file->refcount++;
|
|
||||||
eina_lock_release(&file->lock);
|
|
||||||
|
|
||||||
it->fp = file;
|
|
||||||
it->boundary = 4096;
|
|
||||||
it->current.start = it->map;
|
|
||||||
it->current.end = it->current.start;
|
|
||||||
it->current.index = 0;
|
|
||||||
it->current.length = 0;
|
|
||||||
it->end = it->map + it->fp->length;
|
|
||||||
|
|
||||||
it->iterator.version = EINA_ITERATOR_VERSION;
|
|
||||||
it->iterator.next = FUNC_ITERATOR_NEXT(_eina_file_map_lines_iterator_next);
|
|
||||||
it->iterator.get_container = FUNC_ITERATOR_GET_CONTAINER(_eina_file_map_lines_iterator_container);
|
|
||||||
it->iterator.free = FUNC_ITERATOR_FREE(_eina_file_map_lines_iterator_free);
|
|
||||||
|
|
||||||
return &it->iterator;
|
|
||||||
}
|
|
||||||
|
|
||||||
EAPI void *
|
EAPI void *
|
||||||
eina_file_map_new(Eina_File *file, Eina_File_Populate rule,
|
eina_file_map_new(Eina_File *file, Eina_File_Populate rule,
|
||||||
unsigned long int offset, unsigned long int length)
|
unsigned long int offset, unsigned long int length)
|
||||||
|
|
Loading…
Reference in New Issue