aboutsummaryrefslogtreecommitdiffstats
path: root/compat
diff options
context:
space:
mode:
Diffstat (limited to 'compat')
-rw-r--r--compat/basename.c16
-rw-r--r--compat/compiler.h5
-rw-r--r--compat/disk.h1
-rw-r--r--compat/fsmonitor/fsm-health-darwin.c8
-rw-r--r--compat/fsmonitor/fsm-health-win32.c1
-rw-r--r--compat/fsmonitor/fsm-ipc-darwin.c9
-rw-r--r--compat/fsmonitor/fsm-ipc-win32.c2
-rw-r--r--compat/fsmonitor/fsm-listen-darwin.c11
-rw-r--r--compat/fsmonitor/fsm-listen-win32.c35
-rw-r--r--compat/fsmonitor/fsm-path-utils-win32.c7
-rw-r--r--compat/fsmonitor/fsm-settings-win32.c2
-rw-r--r--compat/mingw.c322
-rw-r--r--compat/mingw.h24
-rw-r--r--compat/nedmalloc/nedmalloc.c2
-rw-r--r--compat/precompose_utf8.c1
-rw-r--r--compat/regex/regcomp.c16
-rw-r--r--compat/regex/regex_internal.c4
-rw-r--r--compat/regex/regexec.c12
-rw-r--r--compat/sha1-chunked.c2
-rw-r--r--compat/simple-ipc/ipc-shared.c8
-rw-r--r--compat/simple-ipc/ipc-unix-socket.c31
-rw-r--r--compat/simple-ipc/ipc-win32.c48
-rw-r--r--compat/stub/procinfo.c2
-rw-r--r--compat/terminal.c2
-rw-r--r--compat/vcbuild/include/unistd.h4
-rw-r--r--compat/win32/headless.c2
-rw-r--r--compat/win32/path-utils.c39
-rw-r--r--compat/win32/path-utils.h4
-rw-r--r--compat/win32/pthread.c2
-rw-r--r--compat/win32/pthread.h4
-rw-r--r--compat/win32/syslog.c2
-rw-r--r--compat/win32/trace2_win32_process_info.c2
-rw-r--r--compat/win32mmap.c2
-rw-r--r--compat/winansi.c4
34 files changed, 506 insertions, 130 deletions
diff --git a/compat/basename.c b/compat/basename.c
index 96bd9533b4..c33579ef61 100644
--- a/compat/basename.c
+++ b/compat/basename.c
@@ -10,7 +10,13 @@ char *gitbasename (char *path)
skip_dos_drive_prefix(&path);
if (!path || !*path)
- return ".";
+ /*
+ * basename(3P) is mis-specified because it returns a
+ * non-constant pointer even though it is specified to return a
+ * pointer to internal memory at times. The cast is a result of
+ * that.
+ */
+ return (char *) ".";
for (base = path; *path; path++) {
if (!is_dir_sep(*path))
@@ -34,7 +40,13 @@ char *gitdirname(char *path)
int dos_drive_prefix;
if (!p)
- return ".";
+ /*
+ * dirname(3P) is mis-specified because it returns a
+ * non-constant pointer even though it is specified to return a
+ * pointer to internal memory at times. The cast is a result of
+ * that.
+ */
+ return (char *) ".";
if ((dos_drive_prefix = skip_dos_drive_prefix(&p)) && !*p)
goto dot;
diff --git a/compat/compiler.h b/compat/compiler.h
index 10dbb65937..e12e426404 100644
--- a/compat/compiler.h
+++ b/compat/compiler.h
@@ -1,7 +1,6 @@
#ifndef COMPILER_H
#define COMPILER_H
-#include "git-compat-util.h"
#include "strbuf.h"
#ifdef __GLIBC__
@@ -10,7 +9,7 @@
static inline void get_compiler_info(struct strbuf *info)
{
- int len = info->len;
+ size_t len = info->len;
#ifdef __clang__
strbuf_addf(info, "clang: %s\n", __clang_version__);
#elif defined(__GNUC__)
@@ -28,7 +27,7 @@ static inline void get_compiler_info(struct strbuf *info)
static inline void get_libc_info(struct strbuf *info)
{
- int len = info->len;
+ size_t len = info->len;
#ifdef __GLIBC__
strbuf_addf(info, "glibc: %s\n", gnu_get_libc_version());
diff --git a/compat/disk.h b/compat/disk.h
index 6c979c27d8..23bc1bef86 100644
--- a/compat/disk.h
+++ b/compat/disk.h
@@ -1,7 +1,6 @@
#ifndef COMPAT_DISK_H
#define COMPAT_DISK_H
-#include "git-compat-util.h"
#include "abspath.h"
#include "gettext.h"
diff --git a/compat/fsmonitor/fsm-health-darwin.c b/compat/fsmonitor/fsm-health-darwin.c
index 5b1709d63f..c2afcbe6c8 100644
--- a/compat/fsmonitor/fsm-health-darwin.c
+++ b/compat/fsmonitor/fsm-health-darwin.c
@@ -4,21 +4,21 @@
#include "fsm-health.h"
#include "fsmonitor--daemon.h"
-int fsm_health__ctor(struct fsmonitor_daemon_state *state)
+int fsm_health__ctor(struct fsmonitor_daemon_state *state UNUSED)
{
return 0;
}
-void fsm_health__dtor(struct fsmonitor_daemon_state *state)
+void fsm_health__dtor(struct fsmonitor_daemon_state *state UNUSED)
{
return;
}
-void fsm_health__loop(struct fsmonitor_daemon_state *state)
+void fsm_health__loop(struct fsmonitor_daemon_state *state UNUSED)
{
return;
}
-void fsm_health__stop_async(struct fsmonitor_daemon_state *state)
+void fsm_health__stop_async(struct fsmonitor_daemon_state *state UNUSED)
{
}
diff --git a/compat/fsmonitor/fsm-health-win32.c b/compat/fsmonitor/fsm-health-win32.c
index 2d4e245beb..2aa8c219ac 100644
--- a/compat/fsmonitor/fsm-health-win32.c
+++ b/compat/fsmonitor/fsm-health-win32.c
@@ -4,6 +4,7 @@
#include "fsm-health.h"
#include "fsmonitor--daemon.h"
#include "gettext.h"
+#include "simple-ipc.h"
/*
* Every minute wake up and test our health.
diff --git a/compat/fsmonitor/fsm-ipc-darwin.c b/compat/fsmonitor/fsm-ipc-darwin.c
index 6f3a95410c..fe149a1b37 100644
--- a/compat/fsmonitor/fsm-ipc-darwin.c
+++ b/compat/fsmonitor/fsm-ipc-darwin.c
@@ -1,3 +1,5 @@
+#define USE_THE_REPOSITORY_VARIABLE
+
#include "git-compat-util.h"
#include "config.h"
#include "gettext.h"
@@ -17,7 +19,7 @@ const char *fsmonitor_ipc__get_path(struct repository *r)
git_SHA_CTX sha1ctx;
char *sock_dir = NULL;
struct strbuf ipc_file = STRBUF_INIT;
- unsigned char hash[GIT_MAX_RAWSZ];
+ unsigned char hash[GIT_SHA1_RAWSZ];
if (!r)
BUG("No repository passed into fsmonitor_ipc__get_path");
@@ -41,9 +43,10 @@ const char *fsmonitor_ipc__get_path(struct repository *r)
/* Create the socket file in either socketDir or $HOME */
if (sock_dir && *sock_dir) {
strbuf_addf(&ipc_file, "%s/.git-fsmonitor-%s",
- sock_dir, hash_to_hex(hash));
+ sock_dir, hash_to_hex_algop(hash, &hash_algos[GIT_HASH_SHA1]));
} else {
- strbuf_addf(&ipc_file, "~/.git-fsmonitor-%s", hash_to_hex(hash));
+ strbuf_addf(&ipc_file, "~/.git-fsmonitor-%s",
+ hash_to_hex_algop(hash, &hash_algos[GIT_HASH_SHA1]));
}
free(sock_dir);
diff --git a/compat/fsmonitor/fsm-ipc-win32.c b/compat/fsmonitor/fsm-ipc-win32.c
index 8928fa93ce..41984ea48e 100644
--- a/compat/fsmonitor/fsm-ipc-win32.c
+++ b/compat/fsmonitor/fsm-ipc-win32.c
@@ -6,6 +6,6 @@
const char *fsmonitor_ipc__get_path(struct repository *r) {
static char *ret;
if (!ret)
- ret = git_pathdup("fsmonitor--daemon.ipc");
+ ret = repo_git_path(r, "fsmonitor--daemon.ipc");
return ret;
}
diff --git a/compat/fsmonitor/fsm-listen-darwin.c b/compat/fsmonitor/fsm-listen-darwin.c
index 36c7e13281..dfa551459d 100644
--- a/compat/fsmonitor/fsm-listen-darwin.c
+++ b/compat/fsmonitor/fsm-listen-darwin.c
@@ -29,6 +29,7 @@
#include "fsmonitor--daemon.h"
#include "fsmonitor-path-utils.h"
#include "gettext.h"
+#include "simple-ipc.h"
#include "string-list.h"
#include "trace.h"
@@ -191,12 +192,12 @@ static void my_add_path(struct fsmonitor_batch *batch, const char *path)
}
-static void fsevent_callback(ConstFSEventStreamRef streamRef,
+static void fsevent_callback(ConstFSEventStreamRef streamRef UNUSED,
void *ctx,
size_t num_of_events,
void *event_paths,
const FSEventStreamEventFlags event_flags[],
- const FSEventStreamEventId event_ids[])
+ const FSEventStreamEventId event_ids[] UNUSED)
{
struct fsmonitor_daemon_state *state = ctx;
struct fsm_listen_data *data = state->listen_data;
@@ -515,6 +516,12 @@ void fsm_listen__loop(struct fsmonitor_daemon_state *state)
}
data->stream_started = 1;
+ /*
+ * Our fs event listener is now running, so it's safe to start
+ * serving client requests.
+ */
+ ipc_server_start_async(state->ipc_server_data);
+
pthread_mutex_lock(&data->dq_lock);
pthread_cond_wait(&data->dq_finished, &data->dq_lock);
pthread_mutex_unlock(&data->dq_lock);
diff --git a/compat/fsmonitor/fsm-listen-win32.c b/compat/fsmonitor/fsm-listen-win32.c
index a361a7db20..9a6efc9bea 100644
--- a/compat/fsmonitor/fsm-listen-win32.c
+++ b/compat/fsmonitor/fsm-listen-win32.c
@@ -4,6 +4,7 @@
#include "fsm-listen.h"
#include "fsmonitor--daemon.h"
#include "gettext.h"
+#include "simple-ipc.h"
#include "trace2.h"
/*
@@ -289,8 +290,7 @@ void fsm_listen__stop_async(struct fsmonitor_daemon_state *state)
SetEvent(state->listen_data->hListener[LISTENER_SHUTDOWN]);
}
-static struct one_watch *create_watch(struct fsmonitor_daemon_state *state,
- const char *path)
+static struct one_watch *create_watch(const char *path)
{
struct one_watch *watch = NULL;
DWORD desired_access = FILE_LIST_DIRECTORY;
@@ -361,8 +361,7 @@ static void destroy_watch(struct one_watch *watch)
free(watch);
}
-static int start_rdcw_watch(struct fsm_listen_data *data,
- struct one_watch *watch)
+static int start_rdcw_watch(struct one_watch *watch)
{
DWORD dwNotifyFilter =
FILE_NOTIFY_CHANGE_FILE_NAME |
@@ -432,9 +431,9 @@ static int recv_rdcw_watch(struct one_watch *watch)
* but I observed ERROR_ACCESS_DENIED (0x05) errors during
* testing.
*
- * Note that we only get notificaiton events for events
+ * Note that we only get notification events for events
* *within* the directory, not *on* the directory itself.
- * (These might be properies of the parent directory, for
+ * (These might be properties of the parent directory, for
* example).
*
* NEEDSWORK: We might try to check for the deleted directory
@@ -735,13 +734,19 @@ void fsm_listen__loop(struct fsmonitor_daemon_state *state)
state->listen_error_code = 0;
- if (start_rdcw_watch(data, data->watch_worktree) == -1)
+ if (start_rdcw_watch(data->watch_worktree) == -1)
goto force_error_stop;
if (data->watch_gitdir &&
- start_rdcw_watch(data, data->watch_gitdir) == -1)
+ start_rdcw_watch(data->watch_gitdir) == -1)
goto force_error_stop;
+ /*
+ * Now that we've established the rdcw watches, we can start
+ * serving clients.
+ */
+ ipc_server_start_async(state->ipc_server_data);
+
for (;;) {
dwWait = WaitForMultipleObjects(data->nr_listener_handles,
data->hListener,
@@ -755,7 +760,7 @@ void fsm_listen__loop(struct fsmonitor_daemon_state *state)
}
if (result == -2) {
/* retryable error */
- if (start_rdcw_watch(data, data->watch_worktree) == -1)
+ if (start_rdcw_watch(data->watch_worktree) == -1)
goto force_error_stop;
continue;
}
@@ -763,7 +768,7 @@ void fsm_listen__loop(struct fsmonitor_daemon_state *state)
/* have data */
if (process_worktree_events(state) == LISTENER_SHUTDOWN)
goto force_shutdown;
- if (start_rdcw_watch(data, data->watch_worktree) == -1)
+ if (start_rdcw_watch(data->watch_worktree) == -1)
goto force_error_stop;
continue;
}
@@ -776,7 +781,7 @@ void fsm_listen__loop(struct fsmonitor_daemon_state *state)
}
if (result == -2) {
/* retryable error */
- if (start_rdcw_watch(data, data->watch_gitdir) == -1)
+ if (start_rdcw_watch(data->watch_gitdir) == -1)
goto force_error_stop;
continue;
}
@@ -784,7 +789,7 @@ void fsm_listen__loop(struct fsmonitor_daemon_state *state)
/* have data */
if (process_gitdir_events(state) == LISTENER_SHUTDOWN)
goto force_shutdown;
- if (start_rdcw_watch(data, data->watch_gitdir) == -1)
+ if (start_rdcw_watch(data->watch_gitdir) == -1)
goto force_error_stop;
continue;
}
@@ -821,16 +826,14 @@ int fsm_listen__ctor(struct fsmonitor_daemon_state *state)
data->hEventShutdown = CreateEvent(NULL, TRUE, FALSE, NULL);
- data->watch_worktree = create_watch(state,
- state->path_worktree_watch.buf);
+ data->watch_worktree = create_watch(state->path_worktree_watch.buf);
if (!data->watch_worktree)
goto failed;
check_for_shortnames(data->watch_worktree);
if (state->nr_paths_watching > 1) {
- data->watch_gitdir = create_watch(state,
- state->path_gitdir_watch.buf);
+ data->watch_gitdir = create_watch(state->path_gitdir_watch.buf);
if (!data->watch_gitdir)
goto failed;
}
diff --git a/compat/fsmonitor/fsm-path-utils-win32.c b/compat/fsmonitor/fsm-path-utils-win32.c
index c8a3e9dcdb..f4f9cc1f33 100644
--- a/compat/fsmonitor/fsm-path-utils-win32.c
+++ b/compat/fsmonitor/fsm-path-utils-win32.c
@@ -132,7 +132,8 @@ int fsmonitor__is_fs_remote(const char *path)
/*
* No-op for now.
*/
-int fsmonitor__get_alias(const char *path, struct alias_info *info)
+int fsmonitor__get_alias(const char *path UNUSED,
+ struct alias_info *info UNUSED)
{
return 0;
}
@@ -140,8 +141,8 @@ int fsmonitor__get_alias(const char *path, struct alias_info *info)
/*
* No-op for now.
*/
-char *fsmonitor__resolve_alias(const char *path,
- const struct alias_info *info)
+char *fsmonitor__resolve_alias(const char *path UNUSED,
+ const struct alias_info *info UNUSED)
{
return NULL;
}
diff --git a/compat/fsmonitor/fsm-settings-win32.c b/compat/fsmonitor/fsm-settings-win32.c
index b6f6744494..0f2aa321f6 100644
--- a/compat/fsmonitor/fsm-settings-win32.c
+++ b/compat/fsmonitor/fsm-settings-win32.c
@@ -25,7 +25,7 @@ static enum fsmonitor_reason check_vfs4git(struct repository *r)
return FSMONITOR_REASON_OK;
}
-enum fsmonitor_reason fsm_os__incompatible(struct repository *r, int ipc)
+enum fsmonitor_reason fsm_os__incompatible(struct repository *r, int ipc UNUSED)
{
enum fsmonitor_reason reason;
diff --git a/compat/mingw.c b/compat/mingw.c
index ec5280da16..63f36c893b 100644
--- a/compat/mingw.c
+++ b/compat/mingw.c
@@ -1,3 +1,5 @@
+#define USE_THE_REPOSITORY_VARIABLE
+
#include "../git-compat-util.h"
#include "win32.h"
#include <aclapi.h>
@@ -26,7 +28,6 @@ static const int delay[] = { 0, 1, 10, 20, 40 };
void open_in_gdb(void)
{
static struct child_process cp = CHILD_PROCESS_INIT;
- extern char *_pgmptr;
strvec_pushl(&cp.args, "mintty", "gdb", NULL);
strvec_pushf(&cp.args, "--pid=%d", getpid());
@@ -244,7 +245,8 @@ static enum hide_dotfiles_type hide_dotfiles = HIDE_DOTFILES_DOTGITONLY;
static char *unset_environment_variables;
int mingw_core_config(const char *var, const char *value,
- const struct config_context *ctx, void *cb)
+ const struct config_context *ctx UNUSED,
+ void *cb UNUSED)
{
if (!strcmp(var, "core.hidedotfiles")) {
if (value && !strcasecmp(value, "dotgitonly"))
@@ -255,6 +257,8 @@ int mingw_core_config(const char *var, const char *value,
}
if (!strcmp(var, "core.unsetenvvars")) {
+ if (!value)
+ return config_error_nonbool(var);
free(unset_environment_variables);
unset_environment_variables = xstrdup(value);
return 0;
@@ -452,7 +456,7 @@ static int set_hidden_flag(const wchar_t *path, int set)
return -1;
}
-int mingw_mkdir(const char *path, int mode)
+int mingw_mkdir(const char *path, int mode UNUSED)
{
int ret;
wchar_t wpath[MAX_PATH];
@@ -498,7 +502,7 @@ static int mingw_open_append(wchar_t const *wfilename, int oflags, ...)
* to append to the file.
*/
handle = CreateFileW(wfilename, FILE_APPEND_DATA,
- FILE_SHARE_WRITE | FILE_SHARE_READ,
+ FILE_SHARE_WRITE | FILE_SHARE_READ | FILE_SHARE_DELETE,
NULL, create, FILE_ATTRIBUTE_NORMAL, NULL);
if (handle == INVALID_HANDLE_VALUE) {
DWORD err = GetLastError();
@@ -529,6 +533,70 @@ static int mingw_open_append(wchar_t const *wfilename, int oflags, ...)
}
/*
+ * Ideally, we'd use `_wopen()` to implement this functionality so that we
+ * don't have to reimplement it, but unfortunately we do not have tight control
+ * over the share mode there. And while `_wsopen()` and friends exist that give
+ * us _some_ control over the share mode, this family of functions doesn't give
+ * us the ability to enable FILE_SHARE_DELETE, either. But this is a strict
+ * requirement for us though so that we can unlink or rename over files that
+ * are held open by another process.
+ *
+ * We are thus forced to implement our own emulation of `open()`. To make our
+ * life simpler we only implement basic support for this, namely opening
+ * existing files for reading and/or writing. This means that newly created
+ * files won't have their sharing mode set up correctly, but for now I couldn't
+ * find any case where this matters. We may have to revisit that in the future
+ * though based on our needs.
+ */
+static int mingw_open_existing(const wchar_t *filename, int oflags, ...)
+{
+ SECURITY_ATTRIBUTES security_attributes = {
+ .nLength = sizeof(security_attributes),
+ .bInheritHandle = !(oflags & O_NOINHERIT),
+ };
+ HANDLE handle;
+ DWORD access;
+ int fd;
+
+ /* We only support basic flags. */
+ if (oflags & ~(O_ACCMODE | O_NOINHERIT)) {
+ errno = ENOSYS;
+ return -1;
+ }
+
+ switch (oflags & O_ACCMODE) {
+ case O_RDWR:
+ access = GENERIC_READ | GENERIC_WRITE;
+ break;
+ case O_WRONLY:
+ access = GENERIC_WRITE;
+ break;
+ default:
+ access = GENERIC_READ;
+ break;
+ }
+
+ handle = CreateFileW(filename, access,
+ FILE_SHARE_WRITE | FILE_SHARE_READ | FILE_SHARE_DELETE,
+ &security_attributes, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+ if (handle == INVALID_HANDLE_VALUE) {
+ DWORD err = GetLastError();
+
+ /* See `mingw_open_append()` for why we have this conversion. */
+ if (err == ERROR_INVALID_PARAMETER)
+ err = ERROR_PATH_NOT_FOUND;
+
+ errno = err_win_to_posix(err);
+ return -1;
+ }
+
+ fd = _open_osfhandle((intptr_t)handle, oflags | O_BINARY);
+ if (fd < 0)
+ CloseHandle(handle);
+ return fd;
+}
+
+/*
* Does the pathname map to the local named pipe filesystem?
* That is, does it have a "//./pipe/" prefix?
*/
@@ -563,6 +631,8 @@ int mingw_open (const char *filename, int oflags, ...)
if ((oflags & O_APPEND) && !is_local_named_pipe_path(filename))
open_fn = mingw_open_append;
+ else if (!(oflags & ~(O_ACCMODE | O_NOINHERIT)))
+ open_fn = mingw_open_existing;
else
open_fn = _wopen;
@@ -596,7 +666,7 @@ int mingw_open (const char *filename, int oflags, ...)
return fd;
}
-static BOOL WINAPI ctrl_ignore(DWORD type)
+static BOOL WINAPI ctrl_ignore(DWORD type UNUSED)
{
return TRUE;
}
@@ -705,13 +775,24 @@ ssize_t mingw_write(int fd, const void *buf, size_t len)
{
ssize_t result = write(fd, buf, len);
- if (result < 0 && errno == EINVAL && buf) {
+ if (result < 0 && (errno == EINVAL || errno == ENOSPC) && buf) {
+ int orig = errno;
+
/* check if fd is a pipe */
HANDLE h = (HANDLE) _get_osfhandle(fd);
- if (GetFileType(h) == FILE_TYPE_PIPE)
+ if (GetFileType(h) != FILE_TYPE_PIPE)
+ errno = orig;
+ else if (orig == EINVAL)
errno = EPIPE;
- else
- errno = EINVAL;
+ else {
+ DWORD buf_size;
+
+ if (!GetNamedPipeInfo(h, NULL, NULL, &buf_size, NULL))
+ buf_size = 4096;
+ if (len > buf_size)
+ return write(fd, buf, buf_size);
+ errno = orig;
+ }
}
return result;
@@ -767,7 +848,7 @@ static inline void filetime_to_timespec(const FILETIME *ft, struct timespec *ts)
*/
static int has_valid_directory_prefix(wchar_t *wfilename)
{
- int n = wcslen(wfilename);
+ size_t n = wcslen(wfilename);
while (n > 0) {
wchar_t c = wfilename[--n];
@@ -876,7 +957,7 @@ static int do_lstat(int follow, const char *file_name, struct stat *buf)
*/
static int do_stat_internal(int follow, const char *file_name, struct stat *buf)
{
- int namelen;
+ size_t namelen;
char alt_name[PATH_MAX];
if (!do_lstat(follow, file_name, buf))
@@ -991,7 +1072,7 @@ int mingw_utime (const char *file_name, const struct utimbuf *times)
osfilehandle = CreateFileW(wfilename,
FILE_WRITE_ATTRIBUTES,
- 0 /*FileShare.None*/,
+ FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
NULL,
OPEN_EXISTING,
(attrs != INVALID_FILE_ATTRIBUTES &&
@@ -1073,7 +1154,7 @@ int mkstemp(char *template)
return git_mkstemp_mode(template, 0600);
}
-int gettimeofday(struct timeval *tv, void *tz)
+int gettimeofday(struct timeval *tv, void *tz UNUSED)
{
FILETIME ft;
long long hnsec;
@@ -1259,7 +1340,8 @@ static const char *parse_interpreter(const char *cmd)
{
static char buf[100];
char *p, *opt;
- int n, fd;
+ ssize_t n; /* read() can return negative values */
+ int fd;
/* don't even try a .exe */
n = strlen(cmd);
@@ -1324,7 +1406,7 @@ static char *path_lookup(const char *cmd, int exe_only)
{
const char *path;
char *prog = NULL;
- int len = strlen(cmd);
+ size_t len = strlen(cmd);
int isexe = len >= 4 && !strcasecmp(cmd+len-4, ".exe");
if (strpbrk(cmd, "/\\"))
@@ -1534,7 +1616,7 @@ static int is_msys2_sh(const char *cmd)
return ret;
}
- if (ends_with(cmd, "\\sh.exe")) {
+ if (ends_with(cmd, "\\sh.exe") || ends_with(cmd, "/sh.exe")) {
static char *sh;
if (!sh)
@@ -1941,7 +2023,7 @@ char *mingw_getenv(const char *name)
#define GETENV_MAX_RETAIN 64
static char *values[GETENV_MAX_RETAIN];
static int value_counter;
- int len_key, len_value;
+ size_t len_key, len_value;
wchar_t *w_key;
char *value;
wchar_t w_value[32768];
@@ -1953,7 +2035,8 @@ char *mingw_getenv(const char *name)
/* We cannot use xcalloc() here because that uses getenv() itself */
w_key = calloc(len_key, sizeof(wchar_t));
if (!w_key)
- die("Out of memory, (tried to allocate %u wchar_t's)", len_key);
+ die("Out of memory, (tried to allocate %"PRIuMAX" wchar_t's)",
+ (uintmax_t)len_key);
xutftowcs(w_key, name, len_key);
/* GetEnvironmentVariableW() only sets the last error upon failure */
SetLastError(ERROR_SUCCESS);
@@ -1968,7 +2051,8 @@ char *mingw_getenv(const char *name)
/* We cannot use xcalloc() here because that uses getenv() itself */
value = calloc(len_value, sizeof(char));
if (!value)
- die("Out of memory, (tried to allocate %u bytes)", len_value);
+ die("Out of memory, (tried to allocate %"PRIuMAX" bytes)",
+ (uintmax_t)len_value);
xwcstoutf(value, w_value, len_value);
/*
@@ -1986,7 +2070,7 @@ char *mingw_getenv(const char *name)
int mingw_putenv(const char *namevalue)
{
- int size;
+ size_t size;
wchar_t *wide, *equal;
BOOL result;
@@ -1996,7 +2080,8 @@ int mingw_putenv(const char *namevalue)
size = strlen(namevalue) * 2 + 1;
wide = calloc(size, sizeof(wchar_t));
if (!wide)
- die("Out of memory, (tried to allocate %u wchar_t's)", size);
+ die("Out of memory, (tried to allocate %" PRIuMAX " wchar_t's)",
+ (uintmax_t)size);
xutftowcs(wide, namevalue, size);
equal = wcschr(wide, L'=');
if (!equal)
@@ -2136,10 +2221,16 @@ int mingw_accept(int sockfd1, struct sockaddr *sa, socklen_t *sz)
#undef rename
int mingw_rename(const char *pold, const char *pnew)
{
+ static int supports_file_rename_info_ex = 1;
DWORD attrs, gle;
int tries = 0;
wchar_t wpold[MAX_PATH], wpnew[MAX_PATH];
- if (xutftowcs_path(wpold, pold) < 0 || xutftowcs_path(wpnew, pnew) < 0)
+ int wpnew_len;
+
+ if (xutftowcs_path(wpold, pold) < 0)
+ return -1;
+ wpnew_len = xutftowcs_path(wpnew, pnew);
+ if (wpnew_len < 0)
return -1;
/*
@@ -2150,11 +2241,84 @@ int mingw_rename(const char *pold, const char *pnew)
return 0;
if (errno != EEXIST)
return -1;
+
repeat:
- if (MoveFileExW(wpold, wpnew, MOVEFILE_REPLACE_EXISTING))
- return 0;
+ if (supports_file_rename_info_ex) {
+ /*
+ * Our minimum required Windows version is still set to Windows
+ * Vista. We thus have to declare required infrastructure for
+ * FileRenameInfoEx ourselves until we bump _WIN32_WINNT to
+ * 0x0A00. Furthermore, we have to handle cases where the
+ * FileRenameInfoEx call isn't supported yet.
+ */
+#define FILE_RENAME_FLAG_REPLACE_IF_EXISTS 0x00000001
+#define FILE_RENAME_FLAG_POSIX_SEMANTICS 0x00000002
+ FILE_INFO_BY_HANDLE_CLASS FileRenameInfoEx = 22;
+ struct {
+ /*
+ * This is usually an unnamed union, but that is not
+ * part of ISO C99. We thus inline the field, as we
+ * really only care for the Flags field anyway.
+ */
+ DWORD Flags;
+ HANDLE RootDirectory;
+ DWORD FileNameLength;
+ /*
+ * The actual structure is defined with a single-character
+ * flex array so that the structure has to be allocated on
+ * the heap. As we declare this structure ourselves though
+ * we can avoid the allocation and define FileName to have
+ * MAX_PATH bytes.
+ */
+ WCHAR FileName[MAX_PATH];
+ } rename_info = { 0 };
+ HANDLE old_handle = INVALID_HANDLE_VALUE;
+ BOOL success;
+
+ old_handle = CreateFileW(wpold, DELETE,
+ FILE_SHARE_WRITE | FILE_SHARE_READ | FILE_SHARE_DELETE,
+ NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+ if (old_handle == INVALID_HANDLE_VALUE) {
+ errno = err_win_to_posix(GetLastError());
+ return -1;
+ }
+
+ rename_info.Flags = FILE_RENAME_FLAG_REPLACE_IF_EXISTS |
+ FILE_RENAME_FLAG_POSIX_SEMANTICS;
+ rename_info.FileNameLength = wpnew_len * sizeof(WCHAR);
+ memcpy(rename_info.FileName, wpnew, wpnew_len * sizeof(WCHAR));
+
+ success = SetFileInformationByHandle(old_handle, FileRenameInfoEx,
+ &rename_info, sizeof(rename_info));
+ gle = GetLastError();
+ CloseHandle(old_handle);
+ if (success)
+ return 0;
+
+ /*
+ * When we see ERROR_INVALID_PARAMETER we can assume that the
+ * current system doesn't support FileRenameInfoEx. Keep us
+ * from using it in future calls and retry.
+ */
+ if (gle == ERROR_INVALID_PARAMETER) {
+ supports_file_rename_info_ex = 0;
+ goto repeat;
+ }
+
+ /*
+ * In theory, we shouldn't get ERROR_ACCESS_DENIED because we
+ * always open files with FILE_SHARE_DELETE But in practice we
+ * cannot assume that Git is the only one accessing files, and
+ * other applications may not set FILE_SHARE_DELETE. So we have
+ * to retry.
+ */
+ } else {
+ if (MoveFileExW(wpold, wpnew, MOVEFILE_REPLACE_EXISTING))
+ return 0;
+ gle = GetLastError();
+ }
+
/* TODO: translate more errors */
- gle = GetLastError();
if (gle == ERROR_ACCESS_DENIED &&
(attrs = GetFileAttributesW(wpnew)) != INVALID_FILE_ATTRIBUTES) {
if (attrs & FILE_ATTRIBUTE_DIRECTORY) {
@@ -2240,7 +2404,7 @@ char *mingw_query_user_email(void)
return get_extended_user_info(NameUserPrincipal);
}
-struct passwd *getpwuid(int uid)
+struct passwd *getpwuid(int uid UNUSED)
{
static unsigned initialized;
static char user_name[100];
@@ -2266,7 +2430,11 @@ struct passwd *getpwuid(int uid)
p->pw_name = user_name;
p->pw_gecos = get_extended_user_info(NameDisplay);
if (!p->pw_gecos)
- p->pw_gecos = "unknown";
+ /*
+ * Data returned by getpwuid(3P) is treated as internal and
+ * must never be written to or freed.
+ */
+ p->pw_gecos = (char *) "unknown";
p->pw_dir = NULL;
initialized = 1;
@@ -2288,7 +2456,7 @@ static sig_handler_t timer_fn = SIG_DFL, sigint_fn = SIG_DFL;
* length to call the signal handler.
*/
-static unsigned __stdcall ticktack(void *dummy)
+static unsigned __stdcall ticktack(void *dummy UNUSED)
{
while (WaitForSingleObject(timer_event, timer_interval) == WAIT_TIMEOUT) {
mingw_raise(SIGALRM);
@@ -2336,7 +2504,7 @@ static inline int is_timeval_eq(const struct timeval *i1, const struct timeval *
return i1->tv_sec == i2->tv_sec && i1->tv_usec == i2->tv_usec;
}
-int setitimer(int type, struct itimerval *in, struct itimerval *out)
+int setitimer(int type UNUSED, struct itimerval *in, struct itimerval *out)
{
static const struct timeval zero;
static int atexit_done;
@@ -2682,6 +2850,30 @@ static PSID get_current_user_sid(void)
return result;
}
+static BOOL user_sid_to_user_name(PSID sid, LPSTR *str)
+{
+ SID_NAME_USE pe_use;
+ DWORD len_user = 0, len_domain = 0;
+ BOOL translate_sid_to_user;
+
+ /*
+ * returns only FALSE, because the string pointers are NULL
+ */
+ LookupAccountSidA(NULL, sid, NULL, &len_user, NULL, &len_domain,
+ &pe_use);
+ /*
+ * Alloc needed space of the strings
+ */
+ ALLOC_ARRAY((*str), (size_t)len_domain + (size_t)len_user);
+ translate_sid_to_user = LookupAccountSidA(NULL, sid,
+ (*str) + len_domain, &len_user, *str, &len_domain, &pe_use);
+ if (!translate_sid_to_user)
+ FREE_AND_NULL(*str);
+ else
+ (*str)[len_domain] = '/';
+ return translate_sid_to_user;
+}
+
static int acls_supported(const char *path)
{
size_t offset = offset_1st_component(path);
@@ -2763,27 +2955,47 @@ int is_path_owned_by_current_sid(const char *path, struct strbuf *report)
strbuf_addf(report, "'%s' is on a file system that does "
"not record ownership\n", path);
} else if (report) {
- LPSTR str1, str2, to_free1 = NULL, to_free2 = NULL;
+ PCSTR str1, str2, str3, str4;
+ LPSTR to_free1 = NULL, to_free3 = NULL,
+ to_local_free2 = NULL, to_local_free4 = NULL;
- if (ConvertSidToStringSidA(sid, &str1))
- to_free1 = str1;
+ if (user_sid_to_user_name(sid, &to_free1))
+ str1 = to_free1;
else
str1 = "(inconvertible)";
-
- if (!current_user_sid)
- str2 = "(none)";
- else if (!IsValidSid(current_user_sid))
- str2 = "(invalid)";
- else if (ConvertSidToStringSidA(current_user_sid, &str2))
- to_free2 = str2;
+ if (ConvertSidToStringSidA(sid, &to_local_free2))
+ str2 = to_local_free2;
else
str2 = "(inconvertible)";
+
+ if (!current_user_sid) {
+ str3 = "(none)";
+ str4 = "(none)";
+ }
+ else if (!IsValidSid(current_user_sid)) {
+ str3 = "(invalid)";
+ str4 = "(invalid)";
+ } else {
+ if (user_sid_to_user_name(current_user_sid,
+ &to_free3))
+ str3 = to_free3;
+ else
+ str3 = "(inconvertible)";
+ if (ConvertSidToStringSidA(current_user_sid,
+ &to_local_free4))
+ str4 = to_local_free4;
+ else
+ str4 = "(inconvertible)";
+ }
strbuf_addf(report,
"'%s' is owned by:\n"
- "\t'%s'\nbut the current user is:\n"
- "\t'%s'\n", path, str1, str2);
- LocalFree(to_free1);
- LocalFree(to_free2);
+ "\t%s (%s)\nbut the current user is:\n"
+ "\t%s (%s)\n",
+ path, str1, str2, str3, str4);
+ free(to_free1);
+ LocalFree(to_local_free2);
+ free(to_free3);
+ LocalFree(to_local_free4);
}
}
@@ -3022,7 +3234,8 @@ static void maybe_redirect_std_handles(void)
*/
int wmain(int argc, const wchar_t **wargv)
{
- int i, maxlen, exit_status;
+ int i, exit_status;
+ size_t maxlen;
char *buffer, **save;
const char **argv;
@@ -3101,3 +3314,24 @@ int uname(struct utsname *buf)
"%u", (v >> 16) & 0x7fff);
return 0;
}
+
+#ifndef NO_UNIX_SOCKETS
+int mingw_have_unix_sockets(void)
+{
+ SC_HANDLE scm, srvc;
+ SERVICE_STATUS_PROCESS status;
+ DWORD bytes;
+ int ret = 0;
+ scm = OpenSCManagerA(NULL, NULL, SC_MANAGER_CONNECT);
+ if (scm) {
+ srvc = OpenServiceA(scm, "afunix", SERVICE_QUERY_STATUS);
+ if (srvc) {
+ if(QueryServiceStatusEx(srvc, SC_STATUS_PROCESS_INFO, (LPBYTE)&status, sizeof(SERVICE_STATUS_PROCESS), &bytes))
+ ret = status.dwCurrentState == SERVICE_RUNNING;
+ CloseServiceHandle(srvc);
+ }
+ CloseServiceHandle(scm);
+ }
+ return ret;
+}
+#endif
diff --git a/compat/mingw.h b/compat/mingw.h
index 6aec50e412..ebfb8ba423 100644
--- a/compat/mingw.h
+++ b/compat/mingw.h
@@ -122,17 +122,17 @@ struct utsname {
* trivial stubs
*/
-static inline int readlink(const char *path, char *buf, size_t bufsiz)
+static inline int readlink(const char *path UNUSED, char *buf UNUSED, size_t bufsiz UNUSED)
{ errno = ENOSYS; return -1; }
-static inline int symlink(const char *oldpath, const char *newpath)
+static inline int symlink(const char *oldpath UNUSED, const char *newpath UNUSED)
{ errno = ENOSYS; return -1; }
-static inline int fchmod(int fildes, mode_t mode)
+static inline int fchmod(int fildes UNUSED, mode_t mode UNUSED)
{ errno = ENOSYS; return -1; }
#ifndef __MINGW64_VERSION_MAJOR
static inline pid_t fork(void)
{ errno = ENOSYS; return -1; }
#endif
-static inline unsigned int alarm(unsigned int seconds)
+static inline unsigned int alarm(unsigned int seconds UNUSED)
{ return 0; }
static inline int fsync(int fd)
{ return _commit(fd); }
@@ -140,9 +140,9 @@ static inline void sync(void)
{}
static inline uid_t getuid(void)
{ return 1; }
-static inline struct passwd *getpwnam(const char *name)
+static inline struct passwd *getpwnam(const char *name UNUSED)
{ return NULL; }
-static inline int fcntl(int fd, int cmd, ...)
+static inline int fcntl(int fd UNUSED, int cmd, ...)
{
if (cmd == F_GETFD || cmd == F_SETFD)
return 0;
@@ -151,17 +151,17 @@ static inline int fcntl(int fd, int cmd, ...)
}
#define sigemptyset(x) (void)0
-static inline int sigaddset(sigset_t *set, int signum)
+static inline int sigaddset(sigset_t *set UNUSED, int signum UNUSED)
{ return 0; }
#define SIG_BLOCK 0
#define SIG_UNBLOCK 0
-static inline int sigprocmask(int how, const sigset_t *set, sigset_t *oldset)
+static inline int sigprocmask(int how UNUSED, const sigset_t *set UNUSED, sigset_t *oldset UNUSED)
{ return 0; }
static inline pid_t getppid(void)
{ return 1; }
static inline pid_t getpgid(pid_t pid)
{ return pid == 0 ? getpid() : pid; }
-static inline pid_t tcgetpgrp(int fd)
+static inline pid_t tcgetpgrp(int fd UNUSED)
{ return getpid(); }
/*
@@ -631,3 +631,9 @@ void open_in_gdb(void);
* Used by Pthread API implementation for Windows
*/
int err_win_to_posix(DWORD winerr);
+
+#ifndef NO_UNIX_SOCKETS
+int mingw_have_unix_sockets(void);
+#undef have_unix_sockets
+#define have_unix_sockets mingw_have_unix_sockets
+#endif
diff --git a/compat/nedmalloc/nedmalloc.c b/compat/nedmalloc/nedmalloc.c
index 2c0ace7075..145255da43 100644
--- a/compat/nedmalloc/nedmalloc.c
+++ b/compat/nedmalloc/nedmalloc.c
@@ -31,6 +31,8 @@ DEALINGS IN THE SOFTWARE.
/*#pragma optimize("a", on)*/
#endif
+#pragma GCC diagnostic ignored "-Wunused-parameter"
+
/*#define FULLSANITYCHECKS*/
#include "nedmalloc.h"
diff --git a/compat/precompose_utf8.c b/compat/precompose_utf8.c
index 0bd5c24250..f7cc7b3be5 100644
--- a/compat/precompose_utf8.c
+++ b/compat/precompose_utf8.c
@@ -4,6 +4,7 @@
*/
#define PRECOMPOSE_UNICODE_C
+#define USE_THE_REPOSITORY_VARIABLE
#include "git-compat-util.h"
#include "config.h"
diff --git a/compat/regex/regcomp.c b/compat/regex/regcomp.c
index d1bc09e49b..8d93a9b93f 100644
--- a/compat/regex/regcomp.c
+++ b/compat/regex/regcomp.c
@@ -17,6 +17,8 @@
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
+#pragma GCC diagnostic ignored "-Wunused-parameter"
+
#if defined __TANDEM
/* This is currently duplicated from git-compat-utils.h */
# ifdef NO_INTPTR_T
@@ -848,7 +850,7 @@ init_dfa (re_dfa_t *dfa, size_t pat_len)
{
unsigned int table_size;
#ifndef _LIBC
- char *codeset_name;
+ const char *codeset_name;
#endif
memset (dfa, '\0', sizeof (re_dfa_t));
@@ -868,7 +870,7 @@ init_dfa (re_dfa_t *dfa, size_t pat_len)
if (table_size > pat_len)
break;
- dfa->state_table = calloc (sizeof (struct re_state_table_entry), table_size);
+ dfa->state_table = calloc (table_size, sizeof (struct re_state_table_entry));
dfa->state_hash_mask = table_size - 1;
dfa->mb_cur_max = MB_CUR_MAX;
@@ -936,7 +938,7 @@ init_dfa (re_dfa_t *dfa, size_t pat_len)
{
int i, j, ch;
- dfa->sb_char = (re_bitset_ptr_t) calloc (sizeof (bitset_t), 1);
+ dfa->sb_char = (re_bitset_ptr_t) calloc (1, sizeof (bitset_t));
if (BE (dfa->sb_char == NULL, 0))
return REG_ESPACE;
@@ -3079,9 +3081,9 @@ parse_bracket_exp (re_string_t *regexp, re_dfa_t *dfa, re_token_t *token,
_NL_COLLATE_SYMB_EXTRAMB);
}
#endif
- sbcset = (re_bitset_ptr_t) calloc (sizeof (bitset_t), 1);
+ sbcset = (re_bitset_ptr_t) calloc (1, sizeof (bitset_t));
#ifdef RE_ENABLE_I18N
- mbcset = (re_charset_t *) calloc (sizeof (re_charset_t), 1);
+ mbcset = (re_charset_t *) calloc (1, sizeof (re_charset_t));
#endif /* RE_ENABLE_I18N */
#ifdef RE_ENABLE_I18N
if (BE (sbcset == NULL || mbcset == NULL, 0))
@@ -3626,9 +3628,9 @@ build_charclass_op (re_dfa_t *dfa, RE_TRANSLATE_TYPE trans,
re_token_t br_token;
bin_tree_t *tree;
- sbcset = (re_bitset_ptr_t) calloc (sizeof (bitset_t), 1);
+ sbcset = (re_bitset_ptr_t) calloc (1, sizeof (bitset_t));
#ifdef RE_ENABLE_I18N
- mbcset = (re_charset_t *) calloc (sizeof (re_charset_t), 1);
+ mbcset = (re_charset_t *) calloc (1, sizeof (re_charset_t));
#endif /* RE_ENABLE_I18N */
#ifdef RE_ENABLE_I18N
diff --git a/compat/regex/regex_internal.c b/compat/regex/regex_internal.c
index ec51cf3446..ec5cc5d2dd 100644
--- a/compat/regex/regex_internal.c
+++ b/compat/regex/regex_internal.c
@@ -1628,7 +1628,7 @@ create_ci_newstate (const re_dfa_t *dfa, const re_node_set *nodes,
reg_errcode_t err;
re_dfastate_t *newstate;
- newstate = (re_dfastate_t *) calloc (sizeof (re_dfastate_t), 1);
+ newstate = (re_dfastate_t *) calloc (1, sizeof (re_dfastate_t));
if (BE (newstate == NULL, 0))
return NULL;
err = re_node_set_init_copy (&newstate->nodes, nodes);
@@ -1678,7 +1678,7 @@ create_cd_newstate (const re_dfa_t *dfa, const re_node_set *nodes,
reg_errcode_t err;
re_dfastate_t *newstate;
- newstate = (re_dfastate_t *) calloc (sizeof (re_dfastate_t), 1);
+ newstate = (re_dfastate_t *) calloc (1, sizeof (re_dfastate_t));
if (BE (newstate == NULL, 0))
return NULL;
err = re_node_set_init_copy (&newstate->nodes, nodes);
diff --git a/compat/regex/regexec.c b/compat/regex/regexec.c
index 49358ae475..2eeec82f40 100644
--- a/compat/regex/regexec.c
+++ b/compat/regex/regexec.c
@@ -292,7 +292,7 @@ compat_symbol (libc, __compat_regexec, regexec, GLIBC_2_0);
concerned.
If REGS is not NULL, and BUFP->no_sub is not set, the offsets of the match
- and all groups is stroed in REGS. (For the "_2" variants, the offsets are
+ and all groups are stored in REGS. (For the "_2" variants, the offsets are
computed relative to the concatenation, not relative to the individual
strings.)
@@ -2796,8 +2796,8 @@ get_subexp (re_match_context_t *mctx, int bkref_node, int bkref_str_idx)
continue; /* No. */
if (sub_top->path == NULL)
{
- sub_top->path = calloc (sizeof (state_array_t),
- sl_str - sub_top->str_idx + 1);
+ sub_top->path = calloc (sl_str - sub_top->str_idx + 1,
+ sizeof (state_array_t));
if (sub_top->path == NULL)
return REG_ESPACE;
}
@@ -3361,7 +3361,7 @@ build_trtable (const re_dfa_t *dfa, re_dfastate_t *state)
if (ndests == 0)
{
state->trtable = (re_dfastate_t **)
- calloc (sizeof (re_dfastate_t *), SBC_MAX);
+ calloc (SBC_MAX, sizeof (re_dfastate_t *));
return 1;
}
return 0;
@@ -3457,7 +3457,7 @@ out_free:
discern by looking at the character code: allocate a
256-entry transition table. */
trtable = state->trtable =
- (re_dfastate_t **) calloc (sizeof (re_dfastate_t *), SBC_MAX);
+ (re_dfastate_t **) calloc (SBC_MAX, sizeof (re_dfastate_t *));
if (BE (trtable == NULL, 0))
goto out_free;
@@ -3488,7 +3488,7 @@ out_free:
transition tables, one starting at trtable[0] and one
starting at trtable[SBC_MAX]. */
trtable = state->word_trtable =
- (re_dfastate_t **) calloc (sizeof (re_dfastate_t *), 2 * SBC_MAX);
+ (re_dfastate_t **) calloc (2 * SBC_MAX, sizeof (re_dfastate_t *));
if (BE (trtable == NULL, 0))
goto out_free;
diff --git a/compat/sha1-chunked.c b/compat/sha1-chunked.c
index a4a6f930d7..0446f9983f 100644
--- a/compat/sha1-chunked.c
+++ b/compat/sha1-chunked.c
@@ -1,5 +1,5 @@
#include "git-compat-util.h"
-#include "hash-ll.h"
+#include "hash.h"
int git_SHA1_Update_Chunked(platform_SHA_CTX *c, const void *data, size_t len)
{
diff --git a/compat/simple-ipc/ipc-shared.c b/compat/simple-ipc/ipc-shared.c
index e5e1dda8cc..d1c21b49bd 100644
--- a/compat/simple-ipc/ipc-shared.c
+++ b/compat/simple-ipc/ipc-shared.c
@@ -1,8 +1,5 @@
#include "git-compat-util.h"
#include "simple-ipc.h"
-#include "strbuf.h"
-#include "pkt-line.h"
-#include "thread-utils.h"
#ifndef SUPPORTS_SIMPLE_IPC
/*
@@ -19,11 +16,12 @@ int ipc_server_run(const char *path, const struct ipc_server_opts *opts,
struct ipc_server_data *server_data = NULL;
int ret;
- ret = ipc_server_run_async(&server_data, path, opts,
- application_cb, application_data);
+ ret = ipc_server_init_async(&server_data, path, opts,
+ application_cb, application_data);
if (ret)
return ret;
+ ipc_server_start_async(server_data);
ret = ipc_server_await(server_data);
ipc_server_free(server_data);
diff --git a/compat/simple-ipc/ipc-unix-socket.c b/compat/simple-ipc/ipc-unix-socket.c
index b2f4f22ce4..7db3b2a897 100644
--- a/compat/simple-ipc/ipc-unix-socket.c
+++ b/compat/simple-ipc/ipc-unix-socket.c
@@ -2,7 +2,6 @@
#include "gettext.h"
#include "simple-ipc.h"
#include "strbuf.h"
-#include "pkt-line.h"
#include "thread-utils.h"
#include "trace2.h"
#include "unix-socket.h"
@@ -329,6 +328,7 @@ struct ipc_server_data {
int back_pos;
int front_pos;
+ int started;
int shutdown_requested;
int is_stopped;
};
@@ -713,7 +713,7 @@ static int accept_thread__wait_for_connection(
* Block SIGPIPE in this thread for the life of the thread. This
* avoids any stray SIGPIPE signals when closing pipe fds under
* extremely heavy loads (such as when the fifo queue is full and we
- * drop incomming connections).
+ * drop incoming connections).
*/
static void *accept_thread_proc(void *_accept_thread_data)
{
@@ -825,10 +825,10 @@ static int setup_listener_socket(
/*
* Start IPC server in a pool of background threads.
*/
-int ipc_server_run_async(struct ipc_server_data **returned_server_data,
- const char *path, const struct ipc_server_opts *opts,
- ipc_server_application_cb *application_cb,
- void *application_data)
+int ipc_server_init_async(struct ipc_server_data **returned_server_data,
+ const char *path, const struct ipc_server_opts *opts,
+ ipc_server_application_cb *application_cb,
+ void *application_data)
{
struct unix_ss_socket *server_socket = NULL;
struct ipc_server_data *server_data;
@@ -889,6 +889,12 @@ int ipc_server_run_async(struct ipc_server_data **returned_server_data,
server_data->accept_thread->fd_send_shutdown = sv[0];
server_data->accept_thread->fd_wait_shutdown = sv[1];
+ /*
+ * Hold work-available mutex so that no work can start until
+ * we unlock it.
+ */
+ pthread_mutex_lock(&server_data->work_available_mutex);
+
if (pthread_create(&server_data->accept_thread->pthread_id, NULL,
accept_thread_proc, server_data->accept_thread))
die_errno(_("could not start accept_thread '%s'"), path);
@@ -919,6 +925,15 @@ int ipc_server_run_async(struct ipc_server_data **returned_server_data,
return 0;
}
+void ipc_server_start_async(struct ipc_server_data *server_data)
+{
+ if (!server_data || server_data->started)
+ return;
+
+ server_data->started = 1;
+ pthread_mutex_unlock(&server_data->work_available_mutex);
+}
+
/*
* Gently tell the IPC server treads to shutdown.
* Can be run on any thread.
@@ -934,7 +949,9 @@ int ipc_server_stop_async(struct ipc_server_data *server_data)
trace2_region_enter("ipc-server", "server-stop-async", NULL);
- pthread_mutex_lock(&server_data->work_available_mutex);
+ /* If we haven't started yet, we are already holding lock. */
+ if (server_data->started)
+ pthread_mutex_lock(&server_data->work_available_mutex);
server_data->shutdown_requested = 1;
diff --git a/compat/simple-ipc/ipc-win32.c b/compat/simple-ipc/ipc-win32.c
index 8bfe51248e..a8fc812adf 100644
--- a/compat/simple-ipc/ipc-win32.c
+++ b/compat/simple-ipc/ipc-win32.c
@@ -371,6 +371,9 @@ struct ipc_server_data {
HANDLE hEventStopRequested;
struct ipc_server_thread_data *thread_list;
int is_stopped;
+
+ pthread_mutex_t startup_barrier;
+ int started;
};
enum connect_result {
@@ -526,6 +529,16 @@ static int use_connection(struct ipc_server_thread_data *server_thread_data)
return ret;
}
+static void wait_for_startup_barrier(struct ipc_server_data *server_data)
+{
+ /*
+ * Temporarily hold the startup_barrier mutex before starting,
+ * which lets us know that it's OK to start serving requests.
+ */
+ pthread_mutex_lock(&server_data->startup_barrier);
+ pthread_mutex_unlock(&server_data->startup_barrier);
+}
+
/*
* Thread proc for an IPC server worker thread. It handles a series of
* connections from clients. It cleans and reuses the hPipe between each
@@ -550,6 +563,8 @@ static void *server_thread_proc(void *_server_thread_data)
memset(&oConnect, 0, sizeof(oConnect));
oConnect.hEvent = hEventConnected;
+ wait_for_startup_barrier(server_thread_data->server_data);
+
for (;;) {
cr = wait_for_connection(server_thread_data, &oConnect);
@@ -752,10 +767,10 @@ static HANDLE create_new_pipe(wchar_t *wpath, int is_first)
return hPipe;
}
-int ipc_server_run_async(struct ipc_server_data **returned_server_data,
- const char *path, const struct ipc_server_opts *opts,
- ipc_server_application_cb *application_cb,
- void *application_data)
+int ipc_server_init_async(struct ipc_server_data **returned_server_data,
+ const char *path, const struct ipc_server_opts *opts,
+ ipc_server_application_cb *application_cb,
+ void *application_data)
{
struct ipc_server_data *server_data;
wchar_t wpath[MAX_PATH];
@@ -787,6 +802,13 @@ int ipc_server_run_async(struct ipc_server_data **returned_server_data,
strbuf_addstr(&server_data->buf_path, path);
wcscpy(server_data->wpath, wpath);
+ /*
+ * Hold the startup_barrier lock so that no threads will progress
+ * until ipc_server_start_async() is called.
+ */
+ pthread_mutex_init(&server_data->startup_barrier, NULL);
+ pthread_mutex_lock(&server_data->startup_barrier);
+
if (nr_threads < 1)
nr_threads = 1;
@@ -837,6 +859,15 @@ int ipc_server_run_async(struct ipc_server_data **returned_server_data,
return 0;
}
+void ipc_server_start_async(struct ipc_server_data *server_data)
+{
+ if (!server_data || server_data->started)
+ return;
+
+ server_data->started = 1;
+ pthread_mutex_unlock(&server_data->startup_barrier);
+}
+
int ipc_server_stop_async(struct ipc_server_data *server_data)
{
if (!server_data)
@@ -850,6 +881,13 @@ int ipc_server_stop_async(struct ipc_server_data *server_data)
* We DO NOT attempt to force them to drop an active connection.
*/
SetEvent(server_data->hEventStopRequested);
+
+ /*
+ * If we haven't yet told the threads they are allowed to run,
+ * do so now, so they can receive the shutdown event.
+ */
+ ipc_server_start_async(server_data);
+
return 0;
}
@@ -900,5 +938,7 @@ void ipc_server_free(struct ipc_server_data *server_data)
free(std);
}
+ pthread_mutex_destroy(&server_data->startup_barrier);
+
free(server_data);
}
diff --git a/compat/stub/procinfo.c b/compat/stub/procinfo.c
index 12c0a23c9e..3168cd5714 100644
--- a/compat/stub/procinfo.c
+++ b/compat/stub/procinfo.c
@@ -6,6 +6,6 @@
* Stub. See sample implementations in compat/linux/procinfo.c and
* compat/win32/trace2_win32_process_info.c.
*/
-void trace2_collect_process_info(enum trace2_process_info_reason reason)
+void trace2_collect_process_info(enum trace2_process_info_reason reason UNUSED)
{
}
diff --git a/compat/terminal.c b/compat/terminal.c
index 0afda730f2..d54efa1c5d 100644
--- a/compat/terminal.c
+++ b/compat/terminal.c
@@ -594,7 +594,7 @@ void restore_term(void)
{
}
-char *git_terminal_prompt(const char *prompt, int echo)
+char *git_terminal_prompt(const char *prompt, int echo UNUSED)
{
return getpass(prompt);
}
diff --git a/compat/vcbuild/include/unistd.h b/compat/vcbuild/include/unistd.h
index 3a959d124c..a261a925b7 100644
--- a/compat/vcbuild/include/unistd.h
+++ b/compat/vcbuild/include/unistd.h
@@ -14,7 +14,11 @@ typedef _mode_t mode_t;
#ifndef _SSIZE_T_
#define _SSIZE_T_
+#ifdef _WIN64
+typedef __int64 _ssize_t;
+#else
typedef long _ssize_t;
+#endif /* _WIN64 */
#ifndef _OFF_T_
#define _OFF_T_
diff --git a/compat/win32/headless.c b/compat/win32/headless.c
index 8b00dfe3bd..11392a0b9a 100644
--- a/compat/win32/headless.c
+++ b/compat/win32/headless.c
@@ -11,6 +11,8 @@
#include <stdlib.h>
#include <wchar.h>
+#pragma GCC diagnostic ignored "-Wunused-parameter"
+
/*
* If `dir` contains the path to a Git exec directory, extend `PATH` to
* include the corresponding `bin/` directory (which is where all those
diff --git a/compat/win32/path-utils.c b/compat/win32/path-utils.c
index ebf2f12eb6..966ef779b9 100644
--- a/compat/win32/path-utils.c
+++ b/compat/win32/path-utils.c
@@ -1,4 +1,7 @@
+#define USE_THE_REPOSITORY_VARIABLE
+
#include "../../git-compat-util.h"
+#include "../../environment.h"
int win32_has_dos_drive_prefix(const char *path)
{
@@ -50,3 +53,39 @@ int win32_offset_1st_component(const char *path)
return pos + is_dir_sep(*pos) - path;
}
+
+int win32_fspathncmp(const char *a, const char *b, size_t count)
+{
+ int diff;
+
+ for (;;) {
+ if (!count--)
+ return 0;
+ if (!*a)
+ return *b ? -1 : 0;
+ if (!*b)
+ return +1;
+
+ if (is_dir_sep(*a)) {
+ if (!is_dir_sep(*b))
+ return -1;
+ a++;
+ b++;
+ continue;
+ } else if (is_dir_sep(*b))
+ return +1;
+
+ diff = ignore_case ?
+ (unsigned char)tolower(*a) - (int)(unsigned char)tolower(*b) :
+ (unsigned char)*a - (int)(unsigned char)*b;
+ if (diff)
+ return diff;
+ a++;
+ b++;
+ }
+}
+
+int win32_fspathcmp(const char *a, const char *b)
+{
+ return win32_fspathncmp(a, b, (size_t)-1);
+}
diff --git a/compat/win32/path-utils.h b/compat/win32/path-utils.h
index 65fa3b9263..a561c700e7 100644
--- a/compat/win32/path-utils.h
+++ b/compat/win32/path-utils.h
@@ -29,5 +29,9 @@ static inline int win32_has_dir_sep(const char *path)
#define has_dir_sep(path) win32_has_dir_sep(path)
int win32_offset_1st_component(const char *path);
#define offset_1st_component win32_offset_1st_component
+int win32_fspathcmp(const char *a, const char *b);
+#define fspathcmp win32_fspathcmp
+int win32_fspathncmp(const char *a, const char *b, size_t count);
+#define fspathncmp win32_fspathncmp
#endif
diff --git a/compat/win32/pthread.c b/compat/win32/pthread.c
index 85f8f7920c..58980a529c 100644
--- a/compat/win32/pthread.c
+++ b/compat/win32/pthread.c
@@ -21,7 +21,7 @@ static unsigned __stdcall win32_start_routine(void *arg)
return 0;
}
-int pthread_create(pthread_t *thread, const void *unused,
+int pthread_create(pthread_t *thread, const void *attr UNUSED,
void *(*start_routine)(void *), void *arg)
{
thread->arg = arg;
diff --git a/compat/win32/pthread.h b/compat/win32/pthread.h
index cc3221cb2c..e2b5c4f64c 100644
--- a/compat/win32/pthread.h
+++ b/compat/win32/pthread.h
@@ -18,7 +18,7 @@
*/
#define pthread_mutex_t CRITICAL_SECTION
-static inline int return_0(int i) {
+static inline int return_0(int i UNUSED) {
return 0;
}
#define pthread_mutex_init(a,b) return_0((InitializeCriticalSection((a)), 0))
@@ -70,7 +70,7 @@ static inline void NORETURN pthread_exit(void *ret)
}
typedef DWORD pthread_key_t;
-static inline int pthread_key_create(pthread_key_t *keyp, void (*destructor)(void *value))
+static inline int pthread_key_create(pthread_key_t *keyp, void (*destructor)(void *value) UNUSED)
{
return (*keyp = TlsAlloc()) == TLS_OUT_OF_INDEXES ? EAGAIN : 0;
}
diff --git a/compat/win32/syslog.c b/compat/win32/syslog.c
index 0af18d8882..4e4794743a 100644
--- a/compat/win32/syslog.c
+++ b/compat/win32/syslog.c
@@ -2,7 +2,7 @@
static HANDLE ms_eventlog;
-void openlog(const char *ident, int logopt, int facility)
+void openlog(const char *ident, int logopt UNUSED, int facility UNUSED)
{
if (ms_eventlog)
return;
diff --git a/compat/win32/trace2_win32_process_info.c b/compat/win32/trace2_win32_process_info.c
index 3ef0936f6f..f147da706a 100644
--- a/compat/win32/trace2_win32_process_info.c
+++ b/compat/win32/trace2_win32_process_info.c
@@ -1,3 +1,5 @@
+#define USE_THE_REPOSITORY_VARIABLE
+
#include "../../git-compat-util.h"
#include "../../json-writer.h"
#include "../../repository.h"
diff --git a/compat/win32mmap.c b/compat/win32mmap.c
index 519d51f2b6..a4ab4cb939 100644
--- a/compat/win32mmap.c
+++ b/compat/win32mmap.c
@@ -40,7 +40,7 @@ void *git_mmap(void *start, size_t length, int prot, int flags, int fd, off_t of
return MAP_FAILED;
}
-int git_munmap(void *start, size_t length)
+int git_munmap(void *start, size_t length UNUSED)
{
return !UnmapViewOfFile(start);
}
diff --git a/compat/winansi.c b/compat/winansi.c
index f83610f684..1b3f916b9f 100644
--- a/compat/winansi.c
+++ b/compat/winansi.c
@@ -139,7 +139,7 @@ static void write_console(unsigned char *str, size_t len)
/* convert utf-8 to utf-16 */
int wlen = xutftowcsn(wbuf, (char*) str, ARRAY_SIZE(wbuf), len);
if (wlen < 0) {
- wchar_t *err = L"[invalid]";
+ const wchar_t *err = L"[invalid]";
WriteConsoleW(console, err, wcslen(err), &dummy, NULL);
return;
}
@@ -340,7 +340,7 @@ enum {
TEXT = 0, ESCAPE = 033, BRACKET = '['
};
-static DWORD WINAPI console_thread(LPVOID unused)
+static DWORD WINAPI console_thread(LPVOID data UNUSED)
{
unsigned char buffer[BUFFER_SIZE];
DWORD bytes;