summaryrefslogtreecommitdiff
path: root/compat
diff options
context:
space:
mode:
Diffstat (limited to 'compat')
-rw-r--r--compat/cygwin.c7
-rw-r--r--compat/fnmatch/fnmatch.c29
-rw-r--r--compat/mingw.c114
-rw-r--r--compat/mingw.h11
-rw-r--r--compat/mkdir.c24
-rw-r--r--compat/nedmalloc/nedmalloc.c5
-rw-r--r--compat/poll/poll.c (renamed from compat/win32/poll.c)14
-rw-r--r--compat/poll/poll.h (renamed from compat/win32/poll.h)0
-rw-r--r--compat/terminal.c129
9 files changed, 258 insertions, 75 deletions
diff --git a/compat/cygwin.c b/compat/cygwin.c
index dfe9b30..5428858 100644
--- a/compat/cygwin.c
+++ b/compat/cygwin.c
@@ -1,6 +1,13 @@
#define WIN32_LEAN_AND_MEAN
+#ifdef CYGWIN_V15_WIN32API
#include "../git-compat-util.h"
#include "win32.h"
+#else
+#include <sys/stat.h>
+#include <sys/errno.h>
+#include "win32.h"
+#include "../git-compat-util.h"
+#endif
#include "../cache.h" /* to read configuration */
static inline void filetime_to_timespec(const FILETIME *ft, struct timespec *ts)
diff --git a/compat/fnmatch/fnmatch.c b/compat/fnmatch/fnmatch.c
index 9473aed..5ef0685 100644
--- a/compat/fnmatch/fnmatch.c
+++ b/compat/fnmatch/fnmatch.c
@@ -55,7 +55,8 @@
program understand `configure --with-gnu-libc' and omit the object files,
it is simpler to just do this in the source for each such file. */
-#if defined _LIBC || !defined __GNU_LIBRARY__
+#if defined NO_FNMATCH || defined NO_FNMATCH_CASEFOLD || \
+ defined _LIBC || !defined __GNU_LIBRARY__
# if defined STDC_HEADERS || !defined isascii
@@ -135,9 +136,9 @@ extern int errno;
# if !defined HAVE___STRCHRNUL && !defined _LIBC
static char *
-__strchrnul (s, c)
- const char *s;
- int c;
+__strchrnul (const char *s, int c)
+
+
{
char *result = strchr (s, c);
if (result == NULL)
@@ -159,11 +160,11 @@ static int internal_fnmatch __P ((const char *pattern, const char *string,
internal_function;
static int
internal_function
-internal_fnmatch (pattern, string, no_leading_period, flags)
- const char *pattern;
- const char *string;
- int no_leading_period;
- int flags;
+internal_fnmatch (const char *pattern, const char *string, int no_leading_period, int flags)
+
+
+
+
{
register const char *p = pattern, *n = string;
register unsigned char c;
@@ -345,7 +346,7 @@ internal_fnmatch (pattern, string, no_leading_period, flags)
for (;;)
{
- if (c1 == CHAR_CLASS_MAX_LENGTH)
+ if (c1 > CHAR_CLASS_MAX_LENGTH)
/* The name is too long and therefore the pattern
is ill-formed. */
return FNM_NOMATCH;
@@ -481,10 +482,10 @@ internal_fnmatch (pattern, string, no_leading_period, flags)
int
-fnmatch (pattern, string, flags)
- const char *pattern;
- const char *string;
- int flags;
+fnmatch (const char *pattern, const char *string, int flags)
+
+
+
{
return internal_fnmatch (pattern, string, flags & FNM_PERIOD, flags);
}
diff --git a/compat/mingw.c b/compat/mingw.c
index afc892d..b673625 100644
--- a/compat/mingw.c
+++ b/compat/mingw.c
@@ -256,6 +256,8 @@ int mingw_rmdir(const char *pathname)
while ((ret = rmdir(pathname)) == -1 && tries < ARRAY_SIZE(delay)) {
if (!is_file_in_use_error(GetLastError()))
+ errno = err_win_to_posix(GetLastError());
+ if (errno != EACCES)
break;
if (!is_dir_empty(pathname)) {
errno = ENOTEMPTY;
@@ -271,7 +273,7 @@ int mingw_rmdir(const char *pathname)
Sleep(delay[tries]);
tries++;
}
- while (ret == -1 && is_file_in_use_error(GetLastError()) &&
+ while (ret == -1 && errno == EACCES && is_file_in_use_error(GetLastError()) &&
ask_yes_no_if_possible("Deletion of directory '%s' failed. "
"Should I try again?", pathname))
ret = rmdir(pathname);
@@ -319,6 +321,31 @@ ssize_t mingw_write(int fd, const void *buf, size_t count)
return write(fd, buf, min(count, 31 * 1024 * 1024));
}
+static BOOL WINAPI ctrl_ignore(DWORD type)
+{
+ return TRUE;
+}
+
+#undef fgetc
+int mingw_fgetc(FILE *stream)
+{
+ int ch;
+ if (!isatty(_fileno(stream)))
+ return fgetc(stream);
+
+ SetConsoleCtrlHandler(ctrl_ignore, TRUE);
+ while (1) {
+ ch = fgetc(stream);
+ if (ch != EOF || GetLastError() != ERROR_OPERATION_ABORTED)
+ break;
+
+ /* Ctrl+C was pressed, simulate SIGINT and retry */
+ mingw_raise(SIGINT);
+ }
+ SetConsoleCtrlHandler(ctrl_ignore, FALSE);
+ return ch;
+}
+
#undef fopen
FILE *mingw_fopen (const char *filename, const char *otype)
{
@@ -335,6 +362,28 @@ FILE *mingw_freopen (const char *filename, const char *otype, FILE *stream)
return freopen(filename, otype, stream);
}
+#undef fflush
+int mingw_fflush(FILE *stream)
+{
+ int ret = fflush(stream);
+
+ /*
+ * write() is used behind the scenes of stdio output functions.
+ * Since git code does not check for errors after each stdio write
+ * operation, it can happen that write() is called by a later
+ * stdio function even if an earlier write() call failed. In the
+ * case of a pipe whose readable end was closed, only the first
+ * call to write() reports EPIPE on Windows. Subsequent write()
+ * calls report EINVAL. It is impossible to notice whether this
+ * fflush invocation triggered such a case, therefore, we have to
+ * catch all EINVAL errors whole-sale.
+ */
+ if (ret && errno == EINVAL)
+ errno = EPIPE;
+
+ return ret;
+}
+
/*
* The unit of FILETIME is 100-nanoseconds since January 1, 1601, UTC.
* Returns the 100-nanoseconds ("hekto nanoseconds") since the epoch.
@@ -1524,7 +1573,7 @@ static HANDLE timer_event;
static HANDLE timer_thread;
static int timer_interval;
static int one_shot;
-static sig_handler_t timer_fn = SIG_DFL;
+static sig_handler_t timer_fn = SIG_DFL, sigint_fn = SIG_DFL;
/* The timer works like this:
* The thread, ticktack(), is a trivial routine that most of the time
@@ -1538,10 +1587,7 @@ static sig_handler_t timer_fn = SIG_DFL;
static unsigned __stdcall ticktack(void *dummy)
{
while (WaitForSingleObject(timer_event, timer_interval) == WAIT_TIMEOUT) {
- if (timer_fn == SIG_DFL)
- die("Alarm");
- if (timer_fn != SIG_IGN)
- timer_fn(SIGALRM);
+ mingw_raise(SIGALRM);
if (one_shot)
break;
}
@@ -1632,12 +1678,49 @@ int sigaction(int sig, struct sigaction *in, struct sigaction *out)
sig_handler_t mingw_signal(int sig, sig_handler_t handler)
{
sig_handler_t old = timer_fn;
- if (sig != SIGALRM)
+
+ switch (sig) {
+ case SIGALRM:
+ timer_fn = handler;
+ break;
+
+ case SIGINT:
+ sigint_fn = handler;
+ break;
+
+ default:
return signal(sig, handler);
- timer_fn = handler;
+ }
+
return old;
}
+#undef raise
+int mingw_raise(int sig)
+{
+ switch (sig) {
+ case SIGALRM:
+ if (timer_fn == SIG_DFL) {
+ if (isatty(STDERR_FILENO))
+ fputs("Alarm clock\n", stderr);
+ exit(128 + SIGALRM);
+ } else if (timer_fn != SIG_IGN)
+ timer_fn(SIGALRM);
+ return 0;
+
+ case SIGINT:
+ if (sigint_fn == SIG_DFL)
+ exit(128 + SIGINT);
+ else if (sigint_fn != SIG_IGN)
+ sigint_fn(SIGINT);
+ return 0;
+
+ default:
+ return raise(sig);
+ }
+}
+
+
static const char *make_backslash_path(const char *path)
{
static char buf[PATH_MAX + 1];
@@ -1699,21 +1782,6 @@ int link(const char *oldpath, const char *newpath)
return 0;
}
-char *getpass(const char *prompt)
-{
- struct strbuf buf = STRBUF_INIT;
-
- fputs(prompt, stderr);
- for (;;) {
- char c = _getch();
- if (c == '\r' || c == '\n')
- break;
- strbuf_addch(&buf, c);
- }
- fputs("\n", stderr);
- return strbuf_detach(&buf, NULL);
-}
-
pid_t waitpid(pid_t pid, int *status, int options)
{
HANDLE h = OpenProcess(SYNCHRONIZE | PROCESS_QUERY_INFORMATION,
diff --git a/compat/mingw.h b/compat/mingw.h
index 61a6521..685cd2c 100644
--- a/compat/mingw.h
+++ b/compat/mingw.h
@@ -55,8 +55,6 @@ struct passwd {
char *pw_dir;
};
-extern char *getpass(const char *prompt);
-
typedef void (__cdecl *sig_handler_t)(int);
struct sigaction {
sig_handler_t sa_handler;
@@ -179,12 +177,18 @@ int mingw_open (const char *filename, int oflags, ...);
ssize_t mingw_write(int fd, const void *buf, size_t count);
#define write mingw_write
+int mingw_fgetc(FILE *stream);
+#define fgetc mingw_fgetc
+
FILE *mingw_fopen (const char *filename, const char *otype);
#define fopen mingw_fopen
FILE *mingw_freopen (const char *filename, const char *otype, FILE *stream);
#define freopen mingw_freopen
+int mingw_fflush(FILE *stream);
+#define fflush mingw_fflush
+
char *mingw_getcwd(char *pointer, int len);
#define getcwd mingw_getcwd
@@ -287,6 +291,9 @@ static inline unsigned int git_ntohl(unsigned int x)
sig_handler_t mingw_signal(int sig, sig_handler_t handler);
#define signal mingw_signal
+int mingw_raise(int sig);
+#define raise mingw_raise
+
/*
* ANSI emulation wrappers
*/
diff --git a/compat/mkdir.c b/compat/mkdir.c
new file mode 100644
index 0000000..9e253fb
--- /dev/null
+++ b/compat/mkdir.c
@@ -0,0 +1,24 @@
+#include "../git-compat-util.h"
+#undef mkdir
+
+/* for platforms that can't deal with a trailing '/' */
+int compat_mkdir_wo_trailing_slash(const char *dir, mode_t mode)
+{
+ int retval;
+ char *tmp_dir = NULL;
+ size_t len = strlen(dir);
+
+ if (len && dir[len-1] == '/') {
+ if ((tmp_dir = strdup(dir)) == NULL)
+ return -1;
+ tmp_dir[len-1] = '\0';
+ }
+ else
+ tmp_dir = (char *)dir;
+
+ retval = mkdir(tmp_dir, mode);
+ if (tmp_dir != dir)
+ free(tmp_dir);
+
+ return retval;
+}
diff --git a/compat/nedmalloc/nedmalloc.c b/compat/nedmalloc/nedmalloc.c
index d9a17a8..91c4e7f 100644
--- a/compat/nedmalloc/nedmalloc.c
+++ b/compat/nedmalloc/nedmalloc.c
@@ -603,7 +603,10 @@ static NOINLINE mstate FindMSpace(nedpool *p, threadcache *tc, int *lastUsed, si
}
/* We really want to make sure this goes into memory now but we
have to be careful of breaking aliasing rules, so write it twice */
- *((volatile struct malloc_state **) &p->m[end])=p->m[end]=temp;
+ {
+ volatile struct malloc_state **_m=(volatile struct malloc_state **) &p->m[end];
+ *_m=(p->m[end]=temp);
+ }
ACQUIRE_LOCK(&p->m[end]->mutex);
/*printf("Created mspace idx %d\n", end);*/
RELEASE_LOCK(&p->mutex);
diff --git a/compat/win32/poll.c b/compat/poll/poll.c
index 403eaa7..7d226ec 100644
--- a/compat/win32/poll.c
+++ b/compat/poll/poll.c
@@ -24,7 +24,9 @@
# pragma GCC diagnostic ignored "-Wtype-limits"
#endif
-#include <malloc.h>
+#if defined(WIN32)
+# include <malloc.h>
+#endif
#include <sys/types.h>
@@ -48,7 +50,9 @@
#else
# include <sys/time.h>
# include <sys/socket.h>
-# include <sys/select.h>
+# ifndef NO_SYS_SELECT_H
+# include <sys/select.h>
+# endif
# include <unistd.h>
#endif
@@ -302,6 +306,10 @@ compute_revents (int fd, int sought, fd_set *rfds, fd_set *wfds, fd_set *efds)
|| socket_errno == ECONNABORTED || socket_errno == ENETRESET)
happened |= POLLHUP;
+ /* some systems can't use recv() on non-socket, including HP NonStop */
+ else if (/* (r == -1) && */ socket_errno == ENOTSOCK)
+ happened |= (POLLIN | POLLRDNORM) & sought;
+
else
happened |= POLLERR;
}
@@ -349,7 +357,7 @@ poll (struct pollfd *pfd, nfds_t nfd, int timeout)
/* EFAULT is not necessary to implement, but let's do it in the
simplest case. */
- if (!pfd)
+ if (!pfd && nfd)
{
errno = EFAULT;
return -1;
diff --git a/compat/win32/poll.h b/compat/poll/poll.h
index b7aa59d..b7aa59d 100644
--- a/compat/win32/poll.h
+++ b/compat/poll/poll.h
diff --git a/compat/terminal.c b/compat/terminal.c
index bbb038d..9b5e3d1 100644
--- a/compat/terminal.c
+++ b/compat/terminal.c
@@ -3,8 +3,22 @@
#include "sigchain.h"
#include "strbuf.h"
+#if defined(HAVE_DEV_TTY) || defined(WIN32)
+
+static void restore_term(void);
+
+static void restore_term_on_signal(int sig)
+{
+ restore_term();
+ sigchain_pop(sig);
+ raise(sig);
+}
+
#ifdef HAVE_DEV_TTY
+#define INPUT_PATH "/dev/tty"
+#define OUTPUT_PATH "/dev/tty"
+
static int term_fd = -1;
static struct termios old_term;
@@ -14,58 +28,109 @@ static void restore_term(void)
return;
tcsetattr(term_fd, TCSAFLUSH, &old_term);
+ close(term_fd);
term_fd = -1;
}
-static void restore_term_on_signal(int sig)
+static int disable_echo(void)
{
- restore_term();
- sigchain_pop(sig);
- raise(sig);
+ struct termios t;
+
+ term_fd = open("/dev/tty", O_RDWR);
+ if (tcgetattr(term_fd, &t) < 0)
+ goto error;
+
+ old_term = t;
+ sigchain_push_common(restore_term_on_signal);
+
+ t.c_lflag &= ~ECHO;
+ if (!tcsetattr(term_fd, TCSAFLUSH, &t))
+ return 0;
+
+error:
+ close(term_fd);
+ term_fd = -1;
+ return -1;
+}
+
+#elif defined(WIN32)
+
+#define INPUT_PATH "CONIN$"
+#define OUTPUT_PATH "CONOUT$"
+#define FORCE_TEXT "t"
+
+static HANDLE hconin = INVALID_HANDLE_VALUE;
+static DWORD cmode;
+
+static void restore_term(void)
+{
+ if (hconin == INVALID_HANDLE_VALUE)
+ return;
+
+ SetConsoleMode(hconin, cmode);
+ CloseHandle(hconin);
+ hconin = INVALID_HANDLE_VALUE;
}
+static int disable_echo(void)
+{
+ hconin = CreateFile("CONIN$", GENERIC_READ | GENERIC_WRITE,
+ FILE_SHARE_READ, NULL, OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL, NULL);
+ if (hconin == INVALID_HANDLE_VALUE)
+ return -1;
+
+ GetConsoleMode(hconin, &cmode);
+ sigchain_push_common(restore_term_on_signal);
+ if (!SetConsoleMode(hconin, cmode & (~ENABLE_ECHO_INPUT))) {
+ CloseHandle(hconin);
+ hconin = INVALID_HANDLE_VALUE;
+ return -1;
+ }
+
+ return 0;
+}
+
+#endif
+
+#ifndef FORCE_TEXT
+#define FORCE_TEXT
+#endif
+
char *git_terminal_prompt(const char *prompt, int echo)
{
static struct strbuf buf = STRBUF_INIT;
int r;
- FILE *fh;
+ FILE *input_fh, *output_fh;
- fh = fopen("/dev/tty", "w+");
- if (!fh)
+ input_fh = fopen(INPUT_PATH, "r" FORCE_TEXT);
+ if (!input_fh)
return NULL;
- if (!echo) {
- struct termios t;
-
- if (tcgetattr(fileno(fh), &t) < 0) {
- fclose(fh);
- return NULL;
- }
-
- old_term = t;
- term_fd = fileno(fh);
- sigchain_push_common(restore_term_on_signal);
-
- t.c_lflag &= ~ECHO;
- if (tcsetattr(fileno(fh), TCSAFLUSH, &t) < 0) {
- term_fd = -1;
- fclose(fh);
- return NULL;
- }
+ output_fh = fopen(OUTPUT_PATH, "w" FORCE_TEXT);
+ if (!output_fh) {
+ fclose(input_fh);
+ return NULL;
+ }
+
+ if (!echo && disable_echo()) {
+ fclose(input_fh);
+ fclose(output_fh);
+ return NULL;
}
- fputs(prompt, fh);
- fflush(fh);
+ fputs(prompt, output_fh);
+ fflush(output_fh);
- r = strbuf_getline(&buf, fh, '\n');
+ r = strbuf_getline(&buf, input_fh, '\n');
if (!echo) {
- fseek(fh, SEEK_CUR, 0);
- putc('\n', fh);
- fflush(fh);
+ putc('\n', output_fh);
+ fflush(output_fh);
}
restore_term();
- fclose(fh);
+ fclose(input_fh);
+ fclose(output_fh);
if (r == EOF)
return NULL;