summaryrefslogtreecommitdiff
path: root/compat
diff options
context:
space:
mode:
Diffstat (limited to 'compat')
-rw-r--r--compat/mingw.c23
-rw-r--r--compat/terminal.c29
-rw-r--r--compat/terminal.h8
3 files changed, 50 insertions, 10 deletions
diff --git a/compat/mingw.c b/compat/mingw.c
index 03af369b2b..58f347d6ae 100644
--- a/compat/mingw.c
+++ b/compat/mingw.c
@@ -961,9 +961,11 @@ static inline void time_t_to_filetime(time_t t, FILETIME *ft)
int mingw_utime (const char *file_name, const struct utimbuf *times)
{
FILETIME mft, aft;
- int fh, rc;
+ int rc;
DWORD attrs;
wchar_t wfilename[MAX_PATH];
+ HANDLE osfilehandle;
+
if (xutftowcs_path(wfilename, file_name) < 0)
return -1;
@@ -975,7 +977,17 @@ int mingw_utime (const char *file_name, const struct utimbuf *times)
SetFileAttributesW(wfilename, attrs & ~FILE_ATTRIBUTE_READONLY);
}
- if ((fh = _wopen(wfilename, O_RDWR | O_BINARY)) < 0) {
+ osfilehandle = CreateFileW(wfilename,
+ FILE_WRITE_ATTRIBUTES,
+ 0 /*FileShare.None*/,
+ NULL,
+ OPEN_EXISTING,
+ (attrs != INVALID_FILE_ATTRIBUTES &&
+ (attrs & FILE_ATTRIBUTE_DIRECTORY)) ?
+ FILE_FLAG_BACKUP_SEMANTICS : 0,
+ NULL);
+ if (osfilehandle == INVALID_HANDLE_VALUE) {
+ errno = err_win_to_posix(GetLastError());
rc = -1;
goto revert_attrs;
}
@@ -987,12 +999,15 @@ int mingw_utime (const char *file_name, const struct utimbuf *times)
GetSystemTimeAsFileTime(&mft);
aft = mft;
}
- if (!SetFileTime((HANDLE)_get_osfhandle(fh), NULL, &aft, &mft)) {
+
+ if (!SetFileTime(osfilehandle, NULL, &aft, &mft)) {
errno = EINVAL;
rc = -1;
} else
rc = 0;
- close(fh);
+
+ if (osfilehandle != INVALID_HANDLE_VALUE)
+ CloseHandle(osfilehandle);
revert_attrs:
if (attrs != INVALID_FILE_ATTRIBUTES &&
diff --git a/compat/terminal.c b/compat/terminal.c
index 5b903e7c7e..3620184e79 100644
--- a/compat/terminal.c
+++ b/compat/terminal.c
@@ -11,7 +11,7 @@
static void restore_term_on_signal(int sig)
{
restore_term();
- sigchain_pop(sig);
+ /* restore_term calls sigchain_pop_common */
raise(sig);
}
@@ -31,14 +31,20 @@ void restore_term(void)
tcsetattr(term_fd, TCSAFLUSH, &old_term);
close(term_fd);
term_fd = -1;
+ sigchain_pop_common();
}
int save_term(int full_duplex)
{
if (term_fd < 0)
term_fd = open("/dev/tty", O_RDWR);
+ if (term_fd < 0)
+ return -1;
+ if (tcgetattr(term_fd, &old_term) < 0)
+ return -1;
+ sigchain_push_common(restore_term_on_signal);
- return (term_fd < 0) ? -1 : tcgetattr(term_fd, &old_term);
+ return 0;
}
static int disable_bits(tcflag_t bits)
@@ -49,12 +55,16 @@ static int disable_bits(tcflag_t bits)
goto error;
t = old_term;
- sigchain_push_common(restore_term_on_signal);
t.c_lflag &= ~bits;
+ if (bits & ICANON) {
+ t.c_cc[VMIN] = 1;
+ t.c_cc[VTIME] = 0;
+ }
if (!tcsetattr(term_fd, TCSAFLUSH, &t))
return 0;
+ sigchain_pop_common();
error:
close(term_fd);
term_fd = -1;
@@ -100,6 +110,8 @@ void restore_term(void)
return;
}
+ sigchain_pop_common();
+
if (hconin == INVALID_HANDLE_VALUE)
return;
@@ -134,6 +146,7 @@ int save_term(int full_duplex)
GetConsoleMode(hconin, &cmode_in);
use_stty = 0;
+ sigchain_push_common(restore_term_on_signal);
return 0;
error:
CloseHandle(hconin);
@@ -150,7 +163,11 @@ static int disable_bits(DWORD bits)
if (bits & ENABLE_LINE_INPUT) {
string_list_append(&stty_restore, "icanon");
- strvec_push(&cp.args, "-icanon");
+ /*
+ * POSIX allows VMIN and VTIME to overlap with VEOF and
+ * VEOL - let's hope that is not the case on windows.
+ */
+ strvec_pushl(&cp.args, "-icanon", "min", "1", "time", "0", NULL);
}
if (bits & ENABLE_ECHO_INPUT) {
@@ -177,10 +194,10 @@ static int disable_bits(DWORD bits)
if (save_term(0) < 0)
return -1;
- sigchain_push_common(restore_term_on_signal);
if (!SetConsoleMode(hconin, cmode_in & ~bits)) {
CloseHandle(hconin);
hconin = INVALID_HANDLE_VALUE;
+ sigchain_pop_common();
return -1;
}
@@ -385,7 +402,7 @@ int read_key_without_echo(struct strbuf *buf)
ch = getchar();
if (ch == EOF)
- return 0;
+ break;
strbuf_addch(buf, ch);
}
}
diff --git a/compat/terminal.h b/compat/terminal.h
index e1770c575b..0fb9fa147c 100644
--- a/compat/terminal.h
+++ b/compat/terminal.h
@@ -1,7 +1,15 @@
#ifndef COMPAT_TERMINAL_H
#define COMPAT_TERMINAL_H
+/*
+ * Save the terminal attributes so they can be restored later by a
+ * call to restore_term(). Note that every successful call to
+ * save_term() must be matched by a call to restore_term() even if the
+ * attributes have not been changed. Returns 0 on success, -1 on
+ * failure.
+ */
int save_term(int full_duplex);
+/* Restore the terminal attributes that were saved with save_term() */
void restore_term(void);
char *git_terminal_prompt(const char *prompt, int echo);