mirror of
https://github.com/git/git.git
synced 2024-11-24 02:17:02 +08:00
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:
commit
b0bae7f0e4
@ -1,96 +1,91 @@
|
||||
#include "../git-compat-util.h"
|
||||
#include "dirent.h"
|
||||
#include "../../git-compat-util.h"
|
||||
|
||||
struct DIR {
|
||||
struct dirent dd_dir; /* includes d_type */
|
||||
HANDLE dd_handle; /* FindFirstFile handle */
|
||||
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)
|
||||
{
|
||||
DWORD attrs = GetFileAttributesA(name);
|
||||
char pattern[MAX_PATH];
|
||||
WIN32_FIND_DATAA fdata;
|
||||
HANDLE h;
|
||||
int len;
|
||||
DIR *p;
|
||||
DIR *dir;
|
||||
|
||||
/* check for valid path */
|
||||
if (attrs == INVALID_FILE_ATTRIBUTES) {
|
||||
errno = ENOENT;
|
||||
/* check that name is not NULL */
|
||||
if (!name) {
|
||||
errno = EINVAL;
|
||||
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 */
|
||||
len = strlen(name);
|
||||
if (is_dir_sep(name[len - 1]))
|
||||
len--;
|
||||
if (len + 2 >= MAX_PATH) {
|
||||
errno = ENAMETOOLONG;
|
||||
return NULL;
|
||||
}
|
||||
/* copy name to temp buffer */
|
||||
memcpy(pattern, name, len + 1);
|
||||
|
||||
p = malloc(sizeof(DIR) + len + 2);
|
||||
if (!p)
|
||||
/* append optional '/' and wildcard '*' */
|
||||
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;
|
||||
}
|
||||
|
||||
memset(p, 0, sizeof(DIR) + len + 2);
|
||||
strcpy(p->dd_name, name);
|
||||
p->dd_name[len] = '/';
|
||||
p->dd_name[len+1] = '*';
|
||||
|
||||
p->dd_handle = INVALID_HANDLE_VALUE;
|
||||
return p;
|
||||
/* initialize DIR structure and copy first dir entry */
|
||||
dir = xmalloc(sizeof(DIR));
|
||||
dir->dd_handle = h;
|
||||
dir->dd_stat = 0;
|
||||
finddata2dirent(&dir->dd_dir, &fdata);
|
||||
return dir;
|
||||
}
|
||||
|
||||
struct dirent *readdir(DIR *dir)
|
||||
{
|
||||
WIN32_FIND_DATAA buf;
|
||||
HANDLE handle;
|
||||
|
||||
if (!dir || !dir->dd_handle) {
|
||||
if (!dir) {
|
||||
errno = EBADF; /* No set_errno for mingw */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (dir->dd_handle == INVALID_HANDLE_VALUE && dir->dd_stat == 0) {
|
||||
DWORD lasterr;
|
||||
handle = FindFirstFileA(dir->dd_name, &buf);
|
||||
lasterr = GetLastError();
|
||||
dir->dd_handle = handle;
|
||||
if (handle == INVALID_HANDLE_VALUE && (lasterr != ERROR_NO_MORE_FILES)) {
|
||||
errno = err_win_to_posix(lasterr);
|
||||
/* if first entry, dirent has already been set up by opendir */
|
||||
if (dir->dd_stat) {
|
||||
/* get next entry and convert from WIN32_FIND_DATA to dirent */
|
||||
WIN32_FIND_DATAA fdata;
|
||||
if (FindNextFileA(dir->dd_handle, &fdata)) {
|
||||
finddata2dirent(&dir->dd_dir, &fdata);
|
||||
} 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;
|
||||
}
|
||||
} 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;
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
@ -101,8 +96,7 @@ int closedir(DIR *dir)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (dir->dd_handle != INVALID_HANDLE_VALUE)
|
||||
FindClose(dir->dd_handle);
|
||||
FindClose(dir->dd_handle);
|
||||
free(dir);
|
||||
return 0;
|
||||
}
|
||||
|
@ -9,12 +9,8 @@ typedef struct DIR DIR;
|
||||
#define DT_LNK 3
|
||||
|
||||
struct dirent {
|
||||
long d_ino; /* Always zero. */
|
||||
char d_name[FILENAME_MAX]; /* File name. */
|
||||
union {
|
||||
unsigned short d_reclen; /* Always zero. */
|
||||
unsigned char d_type; /* Reimplementation adds this */
|
||||
};
|
||||
unsigned char d_type; /* file type to prevent lstat after readdir */
|
||||
char d_name[MAX_PATH]; /* file name */
|
||||
};
|
||||
|
||||
DIR *opendir(const char *dirname);
|
||||
|
@ -354,6 +354,7 @@ ifeq ($(uname_S),Windows)
|
||||
NO_POSIX_GOODIES = UnfortunatelyYes
|
||||
NATIVE_CRLF = YesPlease
|
||||
DEFAULT_HELP_FORMAT = html
|
||||
NO_D_INO_IN_DIRENT = YesPlease
|
||||
|
||||
CC = compat/vcbuild/scripts/clink.pl
|
||||
AR = compat/vcbuild/scripts/lib.pl
|
||||
@ -503,6 +504,7 @@ ifneq (,$(findstring MINGW,$(uname_S)))
|
||||
NO_INET_NTOP = YesPlease
|
||||
NO_POSIX_GOODIES = UnfortunatelyYes
|
||||
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 += -DSTRIP_EXTENSION=\".exe\"
|
||||
COMPAT_OBJS += compat/mingw.o compat/winansi.o \
|
||||
|
Loading…
Reference in New Issue
Block a user