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:
		@ -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 {
 | 
				
			||||||
			return NULL;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	} else if (dir->dd_handle == INVALID_HANDLE_VALUE) {
 | 
					 | 
				
			||||||
		return NULL;
 | 
					 | 
				
			||||||
	} else if (!FindNextFileA(dir->dd_handle, &buf)) {
 | 
					 | 
				
			||||||
			DWORD lasterr = GetLastError();
 | 
								DWORD lasterr = GetLastError();
 | 
				
			||||||
		FindClose(dir->dd_handle);
 | 
					 | 
				
			||||||
		dir->dd_handle = INVALID_HANDLE_VALUE;
 | 
					 | 
				
			||||||
			/* POSIX says you shouldn't set errno when readdir can't
 | 
								/* POSIX says you shouldn't set errno when readdir can't
 | 
				
			||||||
			   find any more files; so, if another error we leave it set. */
 | 
								   find any more files; so, if another error we leave it set. */
 | 
				
			||||||
			if (lasterr != ERROR_NO_MORE_FILES)
 | 
								if (lasterr != ERROR_NO_MORE_FILES)
 | 
				
			||||||
				errno = err_win_to_posix(lasterr);
 | 
									errno = err_win_to_posix(lasterr);
 | 
				
			||||||
			return NULL;
 | 
								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,7 +96,6 @@ 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 \
 | 
				
			||||||
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user