[CONFIGURATION]

* NEW: Detect the fstatat() system function.

[INTERPRETER]
* OPT: Dir() and RDir() are now 10-30% faster by using fstatat() and assuming that directories with just two hard links have no child directories (each sub-directory having one hard-link to its parent directory through the ".." entry).


git-svn-id: svn://localhost/gambas/trunk@7610 867c0c6c-44f3-4631-809d-bfa615b0a4ec
This commit is contained in:
Benoît Minisini 2016-02-21 15:48:40 +00:00
parent a282de2f75
commit c1eb854159
2 changed files with 73 additions and 35 deletions

View File

@ -199,7 +199,7 @@ AC_DEFUN([GB_INIT],
dnl AC_FUNC_WAIT3
dnl AC_CHECK_FUNCS(getcwd gettimeofday mkdir rmdir select socket strdup strerror strtod strtol sysinfo)
AC_CHECK_FUNCS(setenv unsetenv getdomainname getpt cfmakeraw)
AC_CHECK_FUNCS(setenv unsetenv getdomainname getpt cfmakeraw fstatat)
dnl ---- Checks for libraries

View File

@ -52,6 +52,9 @@
#include "gb_file.h"
#define OPT_NLINK 1
#define OPT_FSTATAT 1
#ifdef PROJECT_EXEC
//FILE_STAT FILE_stat_info = { 0 };
@ -690,6 +693,7 @@ void FILE_dir_first(const char *path, const char *pattern, int attr)
if (attr == (GB_STAT_FILE | GB_STAT_DIRECTORY))
attr = 0;
file_attr = attr;
if (FILE_is_relative(path))
@ -715,6 +719,12 @@ void FILE_dir_first(const char *path, const char *pattern, int attr)
file_path = STRING_new_zero(path);
}
#if OPT_FSTATAT
#else
#ifdef FSTATAT
#undef FSTATAT
#endif
#endif
bool FILE_dir_next(char **path, int *len)
{
@ -722,10 +732,11 @@ bool FILE_dir_next(char **path, int *len)
int len_entry;
bool ret;
char *name;
#ifdef _DIRENT_HAVE_D_TYPE
#else
#ifndef _DIRENT_HAVE_D_TYPE
struct stat info;
char *p = file_buffer;
#ifndef HAVE_FSTATAT
char *p = file_buffer;
#endif
#endif
if (file_dir_arch)
@ -739,16 +750,17 @@ bool FILE_dir_next(char **path, int *len)
if (file_dir == NULL)
return TRUE;
#ifdef _DIRENT_HAVE_D_TYPE
#else
if (file_attr)
{
init_file_buffer(file_path);
p += file_buffer_length;
#ifndef _DIRENT_HAVE_D_TYPE
#ifndef HAVE_FSTATAT
if (file_attr)
{
init_file_buffer(file_path);
p += file_buffer_length;
if (p[-1] != '/' && (file_buffer[1] || file_buffer[0] != '/'))
*p++ = '/';
}
if (p[-1] != '/' && (file_buffer[1] || file_buffer[0] != '/'))
*p++ = '/';
}
#endif
#endif
for(;;)
@ -775,14 +787,18 @@ bool FILE_dir_next(char **path, int *len)
if ((file_attr == GB_STAT_DIRECTORY) ^ (entry->d_type == DT_DIR))
continue;
#else
strcpy(p, name);
if (stat(file_buffer, &info))
{
if (file_attr == GB_STAT_DIRECTORY)
#if HAVE_FSTATAT
if (fstatat(dirfd(file_dir), name, &info, 0))
#else
strcpy(p, name);
if (stat(file_buffer, &info))
#endif
{
if (file_attr == GB_STAT_DIRECTORY)
continue;
}
else if ((file_attr == GB_STAT_DIRECTORY) ^ (S_ISDIR(info.st_mode) != 0))
continue;
}
else if ((file_attr == GB_STAT_DIRECTORY) ^ (S_ISDIR(info.st_mode) != 0))
continue;
#endif
}
@ -818,6 +834,9 @@ void FILE_recursive_dir(const char *dir, void (*found)(const char *), void (*aft
#endif
char *temp;
bool is_dir;
#if OPT_NLINK
bool no_subdir = FALSE;
#endif
if (!dir || *dir == 0)
dir = ".";
@ -828,26 +847,45 @@ void FILE_recursive_dir(const char *dir, void (*found)(const char *), void (*aft
file_rdir_path = STRING_new_zero(dir);
FILE_dir_first(dir, NULL, attr != GB_STAT_DIRECTORY ? 0 : GB_STAT_DIRECTORY);
#if OPT_NLINK
if (file_dir)
{
struct stat dinfo;
fstat(dirfd(file_dir), &dinfo);
no_subdir = dinfo.st_nlink == 2;
}
#endif
while (!FILE_dir_next(&file, &len))
{
temp = STRING_new_temp(file, len);
path = (char *)FILE_cat(file_rdir_path, temp, NULL);
#ifdef _DIRENT_HAVE_D_TYPE
is_dir = _last_is_dir;
#else
if (follow)
is_dir = FILE_is_dir(path);
else
{
FILE_stat(path, &info, FALSE);
is_dir = info.type == GB_STAT_DIRECTORY;
}
#endif
if (is_dir)
push_path(&dir_list, path);
else
push_path(&list, path);
#if OPT_NLINK
if (!no_subdir || follow)
#endif
{
#ifdef _DIRENT_HAVE_D_TYPE
is_dir = _last_is_dir;
#else
if (follow)
is_dir = FILE_is_dir(path);
else
{
FILE_stat(path, &info, FALSE);
is_dir = info.type == GB_STAT_DIRECTORY;
}
#endif
if (is_dir)
{
push_path(&dir_list, path);
continue;
}
}
push_path(&list, path);
}
while (dir_list)