cygwin: Remove the Win32 l/stat() implementation
Commitmaintadbc0b6b("cygwin: Use native Win32 API for stat", 30-09-2008) added a Win32 specific implementation of the stat functions. In order to handle absolute paths, cygwin mount points and symbolic links, this implementation may fall back on the standard cygwin l/stat() functions. Also, the choice of cygwin or Win32 functions is made lazily (by the first call(s) to l/stat) based on the state of some config variables. Unfortunately, this "schizophrenic stat" implementation has been the source of many problems ever since. For example, see commits7faee6b8,79748439,452993c2,085479e7,b8a97333,924aaf3e,05bab3eaand0117c2f0. In order to avoid further problems, such as the issue raised by the new reference handling API, remove the Win32 l/stat() implementation. Signed-off-by: Ramsay Jones <ramsay@ramsay1.demon.co.uk> Signed-off-by: Junio C Hamano <gitster@pobox.com>
							parent
							
								
									001b0976af
								
							
						
					
					
						commit
						f66450ae94
					
				|  | @ -213,17 +213,6 @@ The default is true, except linkgit:git-clone[1] or linkgit:git-init[1] | |||
| will probe and set core.fileMode false if appropriate when the | ||||
| repository is created. | ||||
|  | ||||
| core.ignoreCygwinFSTricks:: | ||||
| 	This option is only used by Cygwin implementation of Git. If false, | ||||
| 	the Cygwin stat() and lstat() functions are used. This may be useful | ||||
| 	if your repository consists of a few separate directories joined in | ||||
| 	one hierarchy using Cygwin mount. If true, Git uses native Win32 API | ||||
| 	whenever it is possible and falls back to Cygwin functions only to | ||||
| 	handle symbol links. The native mode is more than twice faster than | ||||
| 	normal Cygwin l/stat() functions. True by default, unless core.filemode | ||||
| 	is true, in which case ignoreCygwinFSTricks is ignored as Cygwin's | ||||
| 	POSIX emulation is required to support core.filemode. | ||||
|  | ||||
| core.ignorecase:: | ||||
| 	If true, this option enables various workarounds to enable | ||||
| 	Git to work better on filesystems that are not case sensitive, | ||||
|  |  | |||
							
								
								
									
										1
									
								
								Makefile
								
								
								
								
							
							
						
						
									
										1
									
								
								Makefile
								
								
								
								
							|  | @ -654,7 +654,6 @@ LIB_H += color.h | |||
| LIB_H += column.h | ||||
| LIB_H += commit.h | ||||
| LIB_H += compat/bswap.h | ||||
| LIB_H += compat/cygwin.h | ||||
| LIB_H += compat/mingw.h | ||||
| LIB_H += compat/obstack.h | ||||
| LIB_H += compat/poll/poll.h | ||||
|  |  | |||
							
								
								
									
										157
									
								
								compat/cygwin.c
								
								
								
								
							
							
						
						
									
										157
									
								
								compat/cygwin.c
								
								
								
								
							|  | @ -1,157 +0,0 @@ | |||
| #define CYGWIN_C | ||||
| #define WIN32_LEAN_AND_MEAN | ||||
| #include <sys/stat.h> | ||||
| #include <sys/errno.h> | ||||
| #include "win32.h" | ||||
| #include "../git-compat-util.h" | ||||
| #include "../cache.h" /* to read configuration */ | ||||
|  | ||||
| /* | ||||
|  * Return POSIX permission bits, regardless of core.ignorecygwinfstricks | ||||
|  */ | ||||
| int cygwin_get_st_mode_bits(const char *path, int *mode) | ||||
| { | ||||
| 	struct stat st; | ||||
| 	if (lstat(path, &st) < 0) | ||||
| 		return -1; | ||||
| 	*mode = st.st_mode; | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| static inline void filetime_to_timespec(const FILETIME *ft, struct timespec *ts) | ||||
| { | ||||
| 	long long winTime = ((long long)ft->dwHighDateTime << 32) + | ||||
| 			ft->dwLowDateTime; | ||||
| 	winTime -= 116444736000000000LL; /* Windows to Unix Epoch conversion */ | ||||
| 	/* convert 100-nsecond interval to seconds and nanoseconds */ | ||||
| 	ts->tv_sec = (time_t)(winTime/10000000); | ||||
| 	ts->tv_nsec = (long)(winTime - ts->tv_sec*10000000LL) * 100; | ||||
| } | ||||
|  | ||||
| #define size_to_blocks(s) (((s)+511)/512) | ||||
|  | ||||
| /* do_stat is a common implementation for cygwin_lstat and cygwin_stat. | ||||
|  * | ||||
|  * To simplify its logic, in the case of cygwin symlinks, this implementation | ||||
|  * falls back to the cygwin version of stat/lstat, which is provided as the | ||||
|  * last argument. | ||||
|  */ | ||||
| static int do_stat(const char *file_name, struct stat *buf, stat_fn_t cygstat) | ||||
| { | ||||
| 	WIN32_FILE_ATTRIBUTE_DATA fdata; | ||||
|  | ||||
| 	if (file_name[0] == '/') | ||||
| 		return cygstat (file_name, buf); | ||||
|  | ||||
| 	if (!(errno = get_file_attr(file_name, &fdata))) { | ||||
| 		/* | ||||
| 		 * If the system attribute is set and it is not a directory then | ||||
| 		 * it could be a symbol link created in the nowinsymlinks mode. | ||||
| 		 * Normally, Cygwin works in the winsymlinks mode, so this situation | ||||
| 		 * is very unlikely. For the sake of simplicity of our code, let's | ||||
| 		 * Cygwin to handle it. | ||||
| 		 */ | ||||
| 		if ((fdata.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM) && | ||||
| 		    !(fdata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) | ||||
| 			return cygstat(file_name, buf); | ||||
|  | ||||
| 		/* fill out the stat structure */ | ||||
| 		buf->st_dev = buf->st_rdev = 0; /* not used by Git */ | ||||
| 		buf->st_ino = 0; | ||||
| 		buf->st_mode = file_attr_to_st_mode(fdata.dwFileAttributes); | ||||
| 		buf->st_nlink = 1; | ||||
| 		buf->st_uid = buf->st_gid = 0; | ||||
| #ifdef __CYGWIN_USE_BIG_TYPES__ | ||||
| 		buf->st_size = ((_off64_t)fdata.nFileSizeHigh << 32) + | ||||
| 			fdata.nFileSizeLow; | ||||
| #else | ||||
| 		buf->st_size = (off_t)fdata.nFileSizeLow; | ||||
| #endif | ||||
| 		buf->st_blocks = size_to_blocks(buf->st_size); | ||||
| 		filetime_to_timespec(&fdata.ftLastAccessTime, &buf->st_atim); | ||||
| 		filetime_to_timespec(&fdata.ftLastWriteTime, &buf->st_mtim); | ||||
| 		filetime_to_timespec(&fdata.ftCreationTime, &buf->st_ctim); | ||||
| 		return 0; | ||||
| 	} else if (errno == ENOENT) { | ||||
| 		/* | ||||
| 		 * In the winsymlinks mode (which is the default), Cygwin | ||||
| 		 * emulates symbol links using Windows shortcut files. These | ||||
| 		 * files are formed by adding .lnk extension. So, if we have | ||||
| 		 * not found the specified file name, it could be that it is | ||||
| 		 * a symbol link. Let's Cygwin to deal with that. | ||||
| 		 */ | ||||
| 		return cygstat(file_name, buf); | ||||
| 	} | ||||
| 	return -1; | ||||
| } | ||||
|  | ||||
| /* We provide our own lstat/stat functions, since the provided Cygwin versions | ||||
|  * of these functions are too slow. These stat functions are tailored for Git's | ||||
|  * usage, and therefore they are not meant to be complete and correct emulation | ||||
|  * of lstat/stat functionality. | ||||
|  */ | ||||
| static int cygwin_lstat(const char *path, struct stat *buf) | ||||
| { | ||||
| 	return do_stat(path, buf, lstat); | ||||
| } | ||||
|  | ||||
| static int cygwin_stat(const char *path, struct stat *buf) | ||||
| { | ||||
| 	return do_stat(path, buf, stat); | ||||
| } | ||||
|  | ||||
|  | ||||
| /* | ||||
|  * At start up, we are trying to determine whether Win32 API or cygwin stat | ||||
|  * functions should be used. The choice is determined by core.ignorecygwinfstricks. | ||||
|  * Reading this option is not always possible immediately as git_dir may | ||||
|  * not be set yet. So until it is set, use cygwin lstat/stat functions. | ||||
|  * However, if core.filemode is set, we must use the Cygwin posix | ||||
|  * stat/lstat as the Windows stat functions do not determine posix filemode. | ||||
|  * | ||||
|  * Note that git_cygwin_config() does NOT call git_default_config() and this | ||||
|  * is deliberate.  Many commands read from config to establish initial | ||||
|  * values in variables and later tweak them from elsewhere (e.g. command line). | ||||
|  * init_stat() is called lazily on demand, typically much late in the program, | ||||
|  * and calling git_default_config() from here would break such variables. | ||||
|  */ | ||||
| static int native_stat = 1; | ||||
| static int core_filemode = 1; /* matches trust_executable_bit default */ | ||||
|  | ||||
| static int git_cygwin_config(const char *var, const char *value, void *cb) | ||||
| { | ||||
| 	if (!strcmp(var, "core.ignorecygwinfstricks")) | ||||
| 		native_stat = git_config_bool(var, value); | ||||
| 	else if (!strcmp(var, "core.filemode")) | ||||
| 		core_filemode = git_config_bool(var, value); | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| static int init_stat(void) | ||||
| { | ||||
| 	if (have_git_dir() && git_config(git_cygwin_config,NULL)) { | ||||
| 		if (!core_filemode && native_stat) { | ||||
| 			cygwin_stat_fn = cygwin_stat; | ||||
| 			cygwin_lstat_fn = cygwin_lstat; | ||||
| 		} else { | ||||
| 			cygwin_stat_fn = stat; | ||||
| 			cygwin_lstat_fn = lstat; | ||||
| 		} | ||||
| 		return 0; | ||||
| 	} | ||||
| 	return 1; | ||||
| } | ||||
|  | ||||
| static int cygwin_stat_stub(const char *file_name, struct stat *buf) | ||||
| { | ||||
| 	return (init_stat() ? stat : *cygwin_stat_fn)(file_name, buf); | ||||
| } | ||||
|  | ||||
| static int cygwin_lstat_stub(const char *file_name, struct stat *buf) | ||||
| { | ||||
| 	return (init_stat() ? lstat : *cygwin_lstat_fn)(file_name, buf); | ||||
| } | ||||
|  | ||||
| stat_fn_t cygwin_stat_fn = cygwin_stat_stub; | ||||
| stat_fn_t cygwin_lstat_fn = cygwin_lstat_stub; | ||||
|  | ||||
|  | @ -1,14 +0,0 @@ | |||
| #include <sys/types.h> | ||||
| #include <sys/stat.h> | ||||
|  | ||||
| typedef int (*stat_fn_t)(const char*, struct stat*); | ||||
| extern stat_fn_t cygwin_stat_fn; | ||||
| extern stat_fn_t cygwin_lstat_fn; | ||||
| int cygwin_get_st_mode_bits(const char *path, int *mode); | ||||
|  | ||||
| #define get_st_mode_bits(p,m) cygwin_get_st_mode_bits((p),(m)) | ||||
| #ifndef CYGWIN_C | ||||
| /* cygwin.c needs the original lstat() */ | ||||
| #define stat(path, buf) (*cygwin_stat_fn)(path, buf) | ||||
| #define lstat(path, buf) (*cygwin_lstat_fn)(path, buf) | ||||
| #endif | ||||
|  | @ -170,7 +170,6 @@ ifeq ($(uname_O),Cygwin) | |||
| 	# Try commenting this out if you suspect MMAP is more efficient | ||||
| 	NO_MMAP = YesPlease | ||||
| 	X = .exe | ||||
| 	COMPAT_OBJS += compat/cygwin.o | ||||
| 	UNRELIABLE_FSTAT = UnfortunatelyYes | ||||
| 	SPARSE_FLAGS = -isystem /usr/include/w32api -Wno-one-bit-signed-bitfield | ||||
| endif | ||||
|  |  | |||
|  | @ -1957,7 +1957,6 @@ _git_config () | |||
| 		core.fileMode | ||||
| 		core.fsyncobjectfiles | ||||
| 		core.gitProxy | ||||
| 		core.ignoreCygwinFSTricks | ||||
| 		core.ignoreStat | ||||
| 		core.ignorecase | ||||
| 		core.logAllRefUpdates | ||||
|  |  | |||
|  | @ -129,8 +129,6 @@ | |||
| #include <poll.h> | ||||
| #endif | ||||
|  | ||||
| extern int get_st_mode_bits(const char *path, int *mode); | ||||
|  | ||||
| #if defined(__MINGW32__) | ||||
| /* pull in Windows compatibility stuff */ | ||||
| #include "compat/mingw.h" | ||||
|  | @ -171,7 +169,6 @@ typedef unsigned long uintptr_t; | |||
| #undef _XOPEN_SOURCE | ||||
| #include <grp.h> | ||||
| #define _XOPEN_SOURCE 600 | ||||
| #include "compat/cygwin.h" | ||||
| #else | ||||
| #undef _ALL_SOURCE /* AIX 5.3L defines a struct list with _ALL_SOURCE. */ | ||||
| #include <grp.h> | ||||
|  |  | |||
							
								
								
									
										5
									
								
								help.c
								
								
								
								
							
							
						
						
									
										5
									
								
								help.c
								
								
								
								
							|  | @ -107,10 +107,7 @@ static int is_executable(const char *name) | |||
| 	    !S_ISREG(st.st_mode)) | ||||
| 		return 0; | ||||
|  | ||||
| #if defined(GIT_WINDOWS_NATIVE) || defined(__CYGWIN__) | ||||
| #if defined(__CYGWIN__) | ||||
| if ((st.st_mode & S_IXUSR) == 0) | ||||
| #endif | ||||
| #if defined(GIT_WINDOWS_NATIVE) | ||||
| {	/* cannot trust the executable bit, peek into the file instead */ | ||||
| 	char buf[3] = { 0 }; | ||||
| 	int n; | ||||
|  |  | |||
							
								
								
									
										9
									
								
								path.c
								
								
								
								
							
							
						
						
									
										9
									
								
								path.c
								
								
								
								
							|  | @ -5,13 +5,7 @@ | |||
| #include "strbuf.h" | ||||
| #include "string-list.h" | ||||
|  | ||||
| #ifndef get_st_mode_bits | ||||
| /* | ||||
|  * The replacement lstat(2) we use on Cygwin is incomplete and | ||||
|  * may return wrong permission bits. Most of the time we do not care, | ||||
|  * but the callsites of this wrapper do care. | ||||
|  */ | ||||
| int get_st_mode_bits(const char *path, int *mode) | ||||
| static int get_st_mode_bits(const char *path, int *mode) | ||||
| { | ||||
| 	struct stat st; | ||||
| 	if (lstat(path, &st) < 0) | ||||
|  | @ -19,7 +13,6 @@ int get_st_mode_bits(const char *path, int *mode) | |||
| 	*mode = st.st_mode; | ||||
| 	return 0; | ||||
| } | ||||
| #endif | ||||
|  | ||||
| static char bad_path[] = "/bad-path/"; | ||||
|  | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	 Ramsay Jones
						Ramsay Jones