зеркало из https://github.com/microsoft/git.git
Merge branch 'sk/mingw-dirent'
* sk/mingw-dirent: Win32 dirent: improve dirent implementation Win32 dirent: clarify #include directives Win32 dirent: change FILENAME_MAX to MAX_PATH Win32 dirent: remove unused dirent.d_reclen member Win32 dirent: remove unused dirent.d_ino member
This commit is contained in:
Коммит
b0bae7f0e4
|
@ -1,96 +1,91 @@
|
||||||
#include "../git-compat-util.h"
|
#include "../../git-compat-util.h"
|
||||||
#include "dirent.h"
|
|
||||||
|
|
||||||
struct DIR {
|
struct DIR {
|
||||||
struct dirent dd_dir; /* includes d_type */
|
struct dirent dd_dir; /* includes d_type */
|
||||||
HANDLE dd_handle; /* FindFirstFile handle */
|
HANDLE dd_handle; /* FindFirstFile handle */
|
||||||
int dd_stat; /* 0-based index */
|
int dd_stat; /* 0-based index */
|
||||||
char dd_name[1]; /* extend struct */
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static inline void finddata2dirent(struct dirent *ent, WIN32_FIND_DATAA *fdata)
|
||||||
|
{
|
||||||
|
/* copy file name from WIN32_FIND_DATA to dirent */
|
||||||
|
memcpy(ent->d_name, fdata->cFileName, sizeof(ent->d_name));
|
||||||
|
|
||||||
|
/* Set file type, based on WIN32_FIND_DATA */
|
||||||
|
if (fdata->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
|
||||||
|
ent->d_type = DT_DIR;
|
||||||
|
else
|
||||||
|
ent->d_type = DT_REG;
|
||||||
|
}
|
||||||
|
|
||||||
DIR *opendir(const char *name)
|
DIR *opendir(const char *name)
|
||||||
{
|
{
|
||||||
DWORD attrs = GetFileAttributesA(name);
|
char pattern[MAX_PATH];
|
||||||
|
WIN32_FIND_DATAA fdata;
|
||||||
|
HANDLE h;
|
||||||
int len;
|
int len;
|
||||||
DIR *p;
|
DIR *dir;
|
||||||
|
|
||||||
/* check for valid path */
|
/* check that name is not NULL */
|
||||||
if (attrs == INVALID_FILE_ATTRIBUTES) {
|
if (!name) {
|
||||||
errno = ENOENT;
|
errno = EINVAL;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* check if it's a directory */
|
|
||||||
if (!(attrs & FILE_ATTRIBUTE_DIRECTORY)) {
|
|
||||||
errno = ENOTDIR;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* check that the pattern won't be too long for FindFirstFileA */
|
/* check that the pattern won't be too long for FindFirstFileA */
|
||||||
len = strlen(name);
|
len = strlen(name);
|
||||||
if (is_dir_sep(name[len - 1]))
|
|
||||||
len--;
|
|
||||||
if (len + 2 >= MAX_PATH) {
|
if (len + 2 >= MAX_PATH) {
|
||||||
errno = ENAMETOOLONG;
|
errno = ENAMETOOLONG;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
/* copy name to temp buffer */
|
||||||
|
memcpy(pattern, name, len + 1);
|
||||||
|
|
||||||
p = malloc(sizeof(DIR) + len + 2);
|
/* append optional '/' and wildcard '*' */
|
||||||
if (!p)
|
if (len && !is_dir_sep(pattern[len - 1]))
|
||||||
|
pattern[len++] = '/';
|
||||||
|
pattern[len++] = '*';
|
||||||
|
pattern[len] = 0;
|
||||||
|
|
||||||
|
/* open find handle */
|
||||||
|
h = FindFirstFileA(pattern, &fdata);
|
||||||
|
if (h == INVALID_HANDLE_VALUE) {
|
||||||
|
DWORD err = GetLastError();
|
||||||
|
errno = (err == ERROR_DIRECTORY) ? ENOTDIR : err_win_to_posix(err);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
memset(p, 0, sizeof(DIR) + len + 2);
|
/* initialize DIR structure and copy first dir entry */
|
||||||
strcpy(p->dd_name, name);
|
dir = xmalloc(sizeof(DIR));
|
||||||
p->dd_name[len] = '/';
|
dir->dd_handle = h;
|
||||||
p->dd_name[len+1] = '*';
|
dir->dd_stat = 0;
|
||||||
|
finddata2dirent(&dir->dd_dir, &fdata);
|
||||||
p->dd_handle = INVALID_HANDLE_VALUE;
|
return dir;
|
||||||
return p;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct dirent *readdir(DIR *dir)
|
struct dirent *readdir(DIR *dir)
|
||||||
{
|
{
|
||||||
WIN32_FIND_DATAA buf;
|
if (!dir) {
|
||||||
HANDLE handle;
|
|
||||||
|
|
||||||
if (!dir || !dir->dd_handle) {
|
|
||||||
errno = EBADF; /* No set_errno for mingw */
|
errno = EBADF; /* No set_errno for mingw */
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dir->dd_handle == INVALID_HANDLE_VALUE && dir->dd_stat == 0) {
|
/* if first entry, dirent has already been set up by opendir */
|
||||||
DWORD lasterr;
|
if (dir->dd_stat) {
|
||||||
handle = FindFirstFileA(dir->dd_name, &buf);
|
/* get next entry and convert from WIN32_FIND_DATA to dirent */
|
||||||
lasterr = GetLastError();
|
WIN32_FIND_DATAA fdata;
|
||||||
dir->dd_handle = handle;
|
if (FindNextFileA(dir->dd_handle, &fdata)) {
|
||||||
if (handle == INVALID_HANDLE_VALUE && (lasterr != ERROR_NO_MORE_FILES)) {
|
finddata2dirent(&dir->dd_dir, &fdata);
|
||||||
errno = err_win_to_posix(lasterr);
|
} else {
|
||||||
|
DWORD lasterr = GetLastError();
|
||||||
|
/* POSIX says you shouldn't set errno when readdir can't
|
||||||
|
find any more files; so, if another error we leave it set. */
|
||||||
|
if (lasterr != ERROR_NO_MORE_FILES)
|
||||||
|
errno = err_win_to_posix(lasterr);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
} else if (dir->dd_handle == INVALID_HANDLE_VALUE) {
|
|
||||||
return NULL;
|
|
||||||
} else if (!FindNextFileA(dir->dd_handle, &buf)) {
|
|
||||||
DWORD lasterr = GetLastError();
|
|
||||||
FindClose(dir->dd_handle);
|
|
||||||
dir->dd_handle = INVALID_HANDLE_VALUE;
|
|
||||||
/* POSIX says you shouldn't set errno when readdir can't
|
|
||||||
find any more files; so, if another error we leave it set. */
|
|
||||||
if (lasterr != ERROR_NO_MORE_FILES)
|
|
||||||
errno = err_win_to_posix(lasterr);
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We get here if `buf' contains valid data. */
|
|
||||||
strcpy(dir->dd_dir.d_name, buf.cFileName);
|
|
||||||
++dir->dd_stat;
|
++dir->dd_stat;
|
||||||
|
|
||||||
/* Set file type, based on WIN32_FIND_DATA */
|
|
||||||
dir->dd_dir.d_type = 0;
|
|
||||||
if (buf.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
|
|
||||||
dir->dd_dir.d_type |= DT_DIR;
|
|
||||||
else
|
|
||||||
dir->dd_dir.d_type |= DT_REG;
|
|
||||||
|
|
||||||
return &dir->dd_dir;
|
return &dir->dd_dir;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -101,8 +96,7 @@ int closedir(DIR *dir)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dir->dd_handle != INVALID_HANDLE_VALUE)
|
FindClose(dir->dd_handle);
|
||||||
FindClose(dir->dd_handle);
|
|
||||||
free(dir);
|
free(dir);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,12 +9,8 @@ typedef struct DIR DIR;
|
||||||
#define DT_LNK 3
|
#define DT_LNK 3
|
||||||
|
|
||||||
struct dirent {
|
struct dirent {
|
||||||
long d_ino; /* Always zero. */
|
unsigned char d_type; /* file type to prevent lstat after readdir */
|
||||||
char d_name[FILENAME_MAX]; /* File name. */
|
char d_name[MAX_PATH]; /* file name */
|
||||||
union {
|
|
||||||
unsigned short d_reclen; /* Always zero. */
|
|
||||||
unsigned char d_type; /* Reimplementation adds this */
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
DIR *opendir(const char *dirname);
|
DIR *opendir(const char *dirname);
|
||||||
|
|
|
@ -354,6 +354,7 @@ ifeq ($(uname_S),Windows)
|
||||||
NO_POSIX_GOODIES = UnfortunatelyYes
|
NO_POSIX_GOODIES = UnfortunatelyYes
|
||||||
NATIVE_CRLF = YesPlease
|
NATIVE_CRLF = YesPlease
|
||||||
DEFAULT_HELP_FORMAT = html
|
DEFAULT_HELP_FORMAT = html
|
||||||
|
NO_D_INO_IN_DIRENT = YesPlease
|
||||||
|
|
||||||
CC = compat/vcbuild/scripts/clink.pl
|
CC = compat/vcbuild/scripts/clink.pl
|
||||||
AR = compat/vcbuild/scripts/lib.pl
|
AR = compat/vcbuild/scripts/lib.pl
|
||||||
|
@ -503,6 +504,7 @@ ifneq (,$(findstring MINGW,$(uname_S)))
|
||||||
NO_INET_NTOP = YesPlease
|
NO_INET_NTOP = YesPlease
|
||||||
NO_POSIX_GOODIES = UnfortunatelyYes
|
NO_POSIX_GOODIES = UnfortunatelyYes
|
||||||
DEFAULT_HELP_FORMAT = html
|
DEFAULT_HELP_FORMAT = html
|
||||||
|
NO_D_INO_IN_DIRENT = YesPlease
|
||||||
COMPAT_CFLAGS += -D__USE_MINGW_ACCESS -D_USE_32BIT_TIME_T -DNOGDI -Icompat -Icompat/win32
|
COMPAT_CFLAGS += -D__USE_MINGW_ACCESS -D_USE_32BIT_TIME_T -DNOGDI -Icompat -Icompat/win32
|
||||||
COMPAT_CFLAGS += -DSTRIP_EXTENSION=\".exe\"
|
COMPAT_CFLAGS += -DSTRIP_EXTENSION=\".exe\"
|
||||||
COMPAT_OBJS += compat/mingw.o compat/winansi.o \
|
COMPAT_OBJS += compat/mingw.o compat/winansi.o \
|
||||||
|
|
Загрузка…
Ссылка в новой задаче