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
|
will probe and set core.fileMode false if appropriate when the
|
||||||
repository is created.
|
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::
|
core.ignorecase::
|
||||||
If true, this option enables various workarounds to enable
|
If true, this option enables various workarounds to enable
|
||||||
Git to work better on filesystems that are not case sensitive,
|
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 += column.h
|
||||||
LIB_H += commit.h
|
LIB_H += commit.h
|
||||||
LIB_H += compat/bswap.h
|
LIB_H += compat/bswap.h
|
||||||
LIB_H += compat/cygwin.h
|
|
||||||
LIB_H += compat/mingw.h
|
LIB_H += compat/mingw.h
|
||||||
LIB_H += compat/obstack.h
|
LIB_H += compat/obstack.h
|
||||||
LIB_H += compat/poll/poll.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
|
# Try commenting this out if you suspect MMAP is more efficient
|
||||||
NO_MMAP = YesPlease
|
NO_MMAP = YesPlease
|
||||||
X = .exe
|
X = .exe
|
||||||
COMPAT_OBJS += compat/cygwin.o
|
|
||||||
UNRELIABLE_FSTAT = UnfortunatelyYes
|
UNRELIABLE_FSTAT = UnfortunatelyYes
|
||||||
SPARSE_FLAGS = -isystem /usr/include/w32api -Wno-one-bit-signed-bitfield
|
SPARSE_FLAGS = -isystem /usr/include/w32api -Wno-one-bit-signed-bitfield
|
||||||
endif
|
endif
|
||||||
|
|
|
||||||
|
|
@ -1957,7 +1957,6 @@ _git_config ()
|
||||||
core.fileMode
|
core.fileMode
|
||||||
core.fsyncobjectfiles
|
core.fsyncobjectfiles
|
||||||
core.gitProxy
|
core.gitProxy
|
||||||
core.ignoreCygwinFSTricks
|
|
||||||
core.ignoreStat
|
core.ignoreStat
|
||||||
core.ignorecase
|
core.ignorecase
|
||||||
core.logAllRefUpdates
|
core.logAllRefUpdates
|
||||||
|
|
|
||||||
|
|
@ -129,8 +129,6 @@
|
||||||
#include <poll.h>
|
#include <poll.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
extern int get_st_mode_bits(const char *path, int *mode);
|
|
||||||
|
|
||||||
#if defined(__MINGW32__)
|
#if defined(__MINGW32__)
|
||||||
/* pull in Windows compatibility stuff */
|
/* pull in Windows compatibility stuff */
|
||||||
#include "compat/mingw.h"
|
#include "compat/mingw.h"
|
||||||
|
|
@ -171,7 +169,6 @@ typedef unsigned long uintptr_t;
|
||||||
#undef _XOPEN_SOURCE
|
#undef _XOPEN_SOURCE
|
||||||
#include <grp.h>
|
#include <grp.h>
|
||||||
#define _XOPEN_SOURCE 600
|
#define _XOPEN_SOURCE 600
|
||||||
#include "compat/cygwin.h"
|
|
||||||
#else
|
#else
|
||||||
#undef _ALL_SOURCE /* AIX 5.3L defines a struct list with _ALL_SOURCE. */
|
#undef _ALL_SOURCE /* AIX 5.3L defines a struct list with _ALL_SOURCE. */
|
||||||
#include <grp.h>
|
#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))
|
!S_ISREG(st.st_mode))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
#if defined(GIT_WINDOWS_NATIVE) || defined(__CYGWIN__)
|
#if defined(GIT_WINDOWS_NATIVE)
|
||||||
#if defined(__CYGWIN__)
|
|
||||||
if ((st.st_mode & S_IXUSR) == 0)
|
|
||||||
#endif
|
|
||||||
{ /* cannot trust the executable bit, peek into the file instead */
|
{ /* cannot trust the executable bit, peek into the file instead */
|
||||||
char buf[3] = { 0 };
|
char buf[3] = { 0 };
|
||||||
int n;
|
int n;
|
||||||
|
|
|
||||||
9
path.c
9
path.c
|
|
@ -5,13 +5,7 @@
|
||||||
#include "strbuf.h"
|
#include "strbuf.h"
|
||||||
#include "string-list.h"
|
#include "string-list.h"
|
||||||
|
|
||||||
#ifndef get_st_mode_bits
|
static int get_st_mode_bits(const char *path, int *mode)
|
||||||
/*
|
|
||||||
* 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)
|
|
||||||
{
|
{
|
||||||
struct stat st;
|
struct stat st;
|
||||||
if (lstat(path, &st) < 0)
|
if (lstat(path, &st) < 0)
|
||||||
|
|
@ -19,7 +13,6 @@ int get_st_mode_bits(const char *path, int *mode)
|
||||||
*mode = st.st_mode;
|
*mode = st.st_mode;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
static char bad_path[] = "/bad-path/";
|
static char bad_path[] = "/bad-path/";
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue