diff options
Diffstat (limited to 'compat')
-rw-r--r-- | compat/clipped-write.c | 13 | ||||
-rw-r--r-- | compat/cygwin.c | 17 | ||||
-rw-r--r-- | compat/cygwin.h | 5 | ||||
-rw-r--r-- | compat/fnmatch/fnmatch.c | 32 | ||||
-rw-r--r-- | compat/mingw.c | 124 | ||||
-rw-r--r-- | compat/mingw.h | 22 | ||||
-rw-r--r-- | compat/mkdir.c | 24 | ||||
-rw-r--r-- | compat/msvc.h | 2 | ||||
-rw-r--r-- | compat/nedmalloc/Readme.txt | 2 | ||||
-rw-r--r-- | compat/nedmalloc/malloc.c.h | 12 | ||||
-rw-r--r-- | compat/nedmalloc/nedmalloc.c | 9 | ||||
-rw-r--r-- | compat/obstack.h | 2 | ||||
-rw-r--r-- | compat/poll/poll.c (renamed from compat/win32/poll.c) | 16 | ||||
-rw-r--r-- | compat/poll/poll.h (renamed from compat/win32/poll.h) | 0 | ||||
-rw-r--r-- | compat/precompose_utf8.c | 184 | ||||
-rw-r--r-- | compat/precompose_utf8.h | 45 | ||||
-rw-r--r-- | compat/regex/regcomp.c | 4 | ||||
-rw-r--r-- | compat/regex/regex.c | 2 | ||||
-rw-r--r-- | compat/regex/regex_internal.c | 6 | ||||
-rw-r--r-- | compat/regex/regexec.c | 6 | ||||
-rw-r--r-- | compat/strtok_r.c | 61 | ||||
-rw-r--r-- | compat/terminal.c | 128 | ||||
-rw-r--r-- | compat/unsetenv.c | 1 | ||||
-rw-r--r-- | compat/vcbuild/include/sys/poll.h | 1 | ||||
-rw-r--r-- | compat/vcbuild/include/unistd.h | 3 | ||||
-rw-r--r-- | compat/win32.h | 2 | ||||
-rw-r--r-- | compat/win32/pthread.c | 2 | ||||
-rw-r--r-- | compat/win32mmap.c | 4 |
28 files changed, 562 insertions, 167 deletions
diff --git a/compat/clipped-write.c b/compat/clipped-write.c new file mode 100644 index 0000000000..b8f98ff77f --- /dev/null +++ b/compat/clipped-write.c @@ -0,0 +1,13 @@ +#include "../git-compat-util.h" +#undef write + +/* + * Version of write that will write at most INT_MAX bytes. + * Workaround a xnu bug on Mac OS X + */ +ssize_t clipped_write(int fildes, const void *buf, size_t nbyte) +{ + if (nbyte > INT_MAX) + nbyte = INT_MAX; + return write(fildes, buf, nbyte); +} diff --git a/compat/cygwin.c b/compat/cygwin.c index dfe9b3084f..91ce5d4c7a 100644 --- a/compat/cygwin.c +++ b/compat/cygwin.c @@ -1,8 +1,23 @@ +#define CYGWIN_C #define WIN32_LEAN_AND_MEAN -#include "../git-compat-util.h" +#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) + diff --git a/compat/cygwin.h b/compat/cygwin.h index a3229f5b4f..c04965a2e0 100644 --- a/compat/cygwin.h +++ b/compat/cygwin.h @@ -4,6 +4,11 @@ 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 diff --git a/compat/fnmatch/fnmatch.c b/compat/fnmatch/fnmatch.c index 9473aed2bb..378c467401 100644 --- a/compat/fnmatch/fnmatch.c +++ b/compat/fnmatch/fnmatch.c @@ -25,6 +25,7 @@ # define _GNU_SOURCE 1 #endif +#include <stddef.h> #include <errno.h> #include <fnmatch.h> #include <ctype.h> @@ -55,7 +56,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 @@ -120,7 +122,7 @@ whose names are inconsistent. */ # if !defined _LIBC && !defined getenv -extern char *getenv (); +extern char *getenv (const char *name); # endif # ifndef errno @@ -135,9 +137,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 +161,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 +347,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 +483,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 afc892d6b1..bb92c436f7 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. @@ -792,8 +841,8 @@ struct pinfo_t { struct pinfo_t *next; pid_t pid; HANDLE proc; -} pinfo_t; -struct pinfo_t *pinfo = NULL; +}; +static struct pinfo_t *pinfo = NULL; CRITICAL_SECTION pinfo_cs; static pid_t mingw_spawnve_fd(const char *cmd, const char **argv, char **env, @@ -1204,7 +1253,7 @@ static int WSAAPI getaddrinfo_stub(const char *node, const char *service, else sin->sin_addr.s_addr = INADDR_LOOPBACK; ai->ai_addr = (struct sockaddr *)sin; - ai->ai_next = 0; + ai->ai_next = NULL; return 0; } @@ -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; } @@ -1631,13 +1677,52 @@ int sigaction(int sig, struct sigaction *in, struct sigaction *out) #undef signal sig_handler_t mingw_signal(int sig, sig_handler_t handler) { - sig_handler_t old = timer_fn; - if (sig != SIGALRM) + sig_handler_t old; + + switch (sig) { + case SIGALRM: + old = timer_fn; + timer_fn = handler; + break; + + case SIGINT: + old = sigint_fn; + 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 +1784,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 61a652138a..bd0a88bc1d 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 */ @@ -327,13 +334,20 @@ char **make_augmented_environ(const char *const *vars); void free_environ(char **env); /* + * A critical section used in the implementation of the spawn + * functions (mingw_spawnv[p]e()) and waitpid(). Intialised in + * the replacement main() macro below. + */ +extern CRITICAL_SECTION pinfo_cs; + +/* * A replacement of main() that ensures that argv[0] has a path * and that default fmode and std(in|out|err) are in binary mode */ #define main(c,v) dummy_decl_mingw_main(); \ -static int mingw_main(); \ -int main(int argc, const char **argv) \ +static int mingw_main(c,v); \ +int main(int argc, char **argv) \ { \ extern CRITICAL_SECTION pinfo_cs; \ _fmode = _O_BINARY; \ diff --git a/compat/mkdir.c b/compat/mkdir.c new file mode 100644 index 0000000000..9e253fb72f --- /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/msvc.h b/compat/msvc.h index aa4b56315a..96b6d605da 100644 --- a/compat/msvc.h +++ b/compat/msvc.h @@ -12,6 +12,8 @@ #define __attribute__(x) #define strncasecmp _strnicmp #define ftruncate _chsize +#define strtoull _strtoui64 +#define strtoll _strtoi64 static __inline int strcasecmp (const char *s1, const char *s2) { diff --git a/compat/nedmalloc/Readme.txt b/compat/nedmalloc/Readme.txt index 876365646e..e46d8f112c 100644 --- a/compat/nedmalloc/Readme.txt +++ b/compat/nedmalloc/Readme.txt @@ -100,7 +100,7 @@ v1.04alpha_svn915 7th October 2006: Thanks to Dmitry Chichkov for reporting this. Futher thanks to Aleksey Sanin. * Fixed realloc(0, <size>) segfaulting. Thanks to Dmitry Chichkov for reporting this. - * Made config defines #ifndef so they can be overriden by the build system. + * Made config defines #ifndef so they can be overridden by the build system. Thanks to Aleksey Sanin for suggesting this. * Fixed deadlock in nedprealloc() due to unnecessary locking of preferred thread mspace when mspace_realloc() always uses the original block's mspace diff --git a/compat/nedmalloc/malloc.c.h b/compat/nedmalloc/malloc.c.h index ff7c2c4fd8..5a44dead9d 100644 --- a/compat/nedmalloc/malloc.c.h +++ b/compat/nedmalloc/malloc.c.h @@ -484,6 +484,10 @@ MAX_RELEASE_CHECK_RATE default: 4095 unless not HAVE_MMAP #define DLMALLOC_VERSION 20804 #endif /* DLMALLOC_VERSION */ +#if defined(linux) +#define _GNU_SOURCE 1 +#endif + #ifndef WIN32 #ifdef _WIN32 #define WIN32 1 @@ -1802,7 +1806,7 @@ struct win32_mlock_t static MLOCK_T malloc_global_mutex = { 0, 0, 0}; -static FORCEINLINE long win32_getcurrentthreadid() { +static FORCEINLINE long win32_getcurrentthreadid(void) { #ifdef _MSC_VER #if defined(_M_IX86) long *threadstruct=(long *)__readfsdword(0x18); @@ -4778,7 +4782,7 @@ void* dlmalloc(size_t bytes) { void dlfree(void* mem) { /* - Consolidate freed chunks with preceeding or succeeding bordering + Consolidate freed chunks with preceding or succeeding bordering free chunks, if they exist, and then place in a bin. Intermixed with special cases for top, dv, mmapped chunks, and usage errors. */ @@ -5680,10 +5684,10 @@ History: Wolfram Gloger (Gloger@lrz.uni-muenchen.de). * Use last_remainder in more cases. * Pack bins using idea from colin@nyx10.cs.du.edu - * Use ordered bins instead of best-fit threshhold + * Use ordered bins instead of best-fit threshold * Eliminate block-local decls to simplify tracing and debugging. * Support another case of realloc via move into top - * Fix error occuring when initial sbrk_base not word-aligned. + * Fix error occurring when initial sbrk_base not word-aligned. * Rely on page size for units instead of SBRK_UNIT to avoid surprises about sbrk alignment conventions. * Add mallinfo, mallopt. Thanks to Raymond Nijssen diff --git a/compat/nedmalloc/nedmalloc.c b/compat/nedmalloc/nedmalloc.c index d9a17a8057..609ebba125 100644 --- a/compat/nedmalloc/nedmalloc.c +++ b/compat/nedmalloc/nedmalloc.c @@ -159,8 +159,8 @@ struct mallinfo nedmallinfo(void) THROWSPEC { return nedpmallinfo(0); } #endif int nedmallopt(int parno, int value) THROWSPEC { return nedpmallopt(0, parno, value); } int nedmalloc_trim(size_t pad) THROWSPEC { return nedpmalloc_trim(0, pad); } -void nedmalloc_stats() THROWSPEC { nedpmalloc_stats(0); } -size_t nedmalloc_footprint() THROWSPEC { return nedpmalloc_footprint(0); } +void nedmalloc_stats(void) THROWSPEC { nedpmalloc_stats(0); } +size_t nedmalloc_footprint(void) THROWSPEC { return nedpmalloc_footprint(0); } void **nedindependent_calloc(size_t elemsno, size_t elemsize, void **chunks) THROWSPEC { return nedpindependent_calloc(0, elemsno, elemsize, chunks); } void **nedindependent_comalloc(size_t elems, size_t *sizes, void **chunks) THROWSPEC { return nedpindependent_comalloc(0, elems, sizes, chunks); } @@ -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/obstack.h b/compat/obstack.h index d178bd6716..ceb4bdbcdd 100644 --- a/compat/obstack.h +++ b/compat/obstack.h @@ -128,7 +128,7 @@ extern "C" { #define __BPTR_ALIGN(B, P, A) ((B) + (((P) - (B) + (A)) & ~(A))) -/* Similiar to _BPTR_ALIGN (B, P, A), except optimize the common case +/* Similar to _BPTR_ALIGN (B, P, A), except optimize the common case where pointers can be converted to integers, aligned as integers, and converted back again. If PTR_INT_TYPE is narrower than a pointer (e.g., the AS/400), play it safe and compute the alignment diff --git a/compat/win32/poll.c b/compat/poll/poll.c index 403eaa7a3c..44103103a4 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; @@ -568,7 +576,7 @@ restart: { /* It's a socket. */ WSAEnumNetworkEvents ((SOCKET) h, NULL, &ev); - WSAEventSelect ((SOCKET) h, 0, 0); + WSAEventSelect ((SOCKET) h, NULL, 0); /* If we're lucky, WSAEnumNetworkEvents already provided a way to distinguish FD_READ and FD_ACCEPT; this saves a recv later. */ diff --git a/compat/win32/poll.h b/compat/poll/poll.h index b7aa59d973..b7aa59d973 100644 --- a/compat/win32/poll.h +++ b/compat/poll/poll.h diff --git a/compat/precompose_utf8.c b/compat/precompose_utf8.c new file mode 100644 index 0000000000..7980abd1a7 --- /dev/null +++ b/compat/precompose_utf8.c @@ -0,0 +1,184 @@ +/* + * Converts filenames from decomposed unicode into precomposed unicode. + * Used on MacOS X. + */ + +#define PRECOMPOSE_UNICODE_C + +#include "cache.h" +#include "utf8.h" +#include "precompose_utf8.h" + +typedef char *iconv_ibp; +static const char *repo_encoding = "UTF-8"; +static const char *path_encoding = "UTF-8-MAC"; + +static size_t has_non_ascii(const char *s, size_t maxlen, size_t *strlen_c) +{ + const uint8_t *ptr = (const uint8_t *)s; + size_t strlen_chars = 0; + size_t ret = 0; + + if (!ptr || !*ptr) + return 0; + + while (*ptr && maxlen) { + if (*ptr & 0x80) + ret++; + strlen_chars++; + ptr++; + maxlen--; + } + if (strlen_c) + *strlen_c = strlen_chars; + + return ret; +} + + +void probe_utf8_pathname_composition(char *path, int len) +{ + static const char *auml_nfc = "\xc3\xa4"; + static const char *auml_nfd = "\x61\xcc\x88"; + int output_fd; + if (precomposed_unicode != -1) + return; /* We found it defined in the global config, respect it */ + strcpy(path + len, auml_nfc); + output_fd = open(path, O_CREAT|O_EXCL|O_RDWR, 0600); + if (output_fd >= 0) { + close(output_fd); + strcpy(path + len, auml_nfd); + /* Indicate to the user, that we can configure it to true */ + if (!access(path, R_OK)) + git_config_set("core.precomposeunicode", "false"); + /* To be backward compatible, set precomposed_unicode to 0 */ + precomposed_unicode = 0; + strcpy(path + len, auml_nfc); + if (unlink(path)) + die_errno(_("failed to unlink '%s'"), path); + } +} + + +void precompose_argv(int argc, const char **argv) +{ + int i = 0; + const char *oldarg; + char *newarg; + iconv_t ic_precompose; + + if (precomposed_unicode != 1) + return; + + ic_precompose = iconv_open(repo_encoding, path_encoding); + if (ic_precompose == (iconv_t) -1) + return; + + while (i < argc) { + size_t namelen; + oldarg = argv[i]; + if (has_non_ascii(oldarg, (size_t)-1, &namelen)) { + newarg = reencode_string_iconv(oldarg, namelen, ic_precompose, NULL); + if (newarg) + argv[i] = newarg; + } + i++; + } + iconv_close(ic_precompose); +} + + +PREC_DIR *precompose_utf8_opendir(const char *dirname) +{ + PREC_DIR *prec_dir = xmalloc(sizeof(PREC_DIR)); + prec_dir->dirent_nfc = xmalloc(sizeof(dirent_prec_psx)); + prec_dir->dirent_nfc->max_name_len = sizeof(prec_dir->dirent_nfc->d_name); + + prec_dir->dirp = opendir(dirname); + if (!prec_dir->dirp) { + free(prec_dir->dirent_nfc); + free(prec_dir); + return NULL; + } else { + int ret_errno = errno; + prec_dir->ic_precompose = iconv_open(repo_encoding, path_encoding); + /* if iconv_open() fails, die() in readdir() if needed */ + errno = ret_errno; + } + + return prec_dir; +} + +struct dirent_prec_psx *precompose_utf8_readdir(PREC_DIR *prec_dir) +{ + struct dirent *res; + res = readdir(prec_dir->dirp); + if (res) { + size_t namelenz = strlen(res->d_name) + 1; /* \0 */ + size_t new_maxlen = namelenz; + + int ret_errno = errno; + + if (new_maxlen > prec_dir->dirent_nfc->max_name_len) { + size_t new_len = sizeof(dirent_prec_psx) + new_maxlen - + sizeof(prec_dir->dirent_nfc->d_name); + + prec_dir->dirent_nfc = xrealloc(prec_dir->dirent_nfc, new_len); + prec_dir->dirent_nfc->max_name_len = new_maxlen; + } + + prec_dir->dirent_nfc->d_ino = res->d_ino; + prec_dir->dirent_nfc->d_type = res->d_type; + + if ((precomposed_unicode == 1) && has_non_ascii(res->d_name, (size_t)-1, NULL)) { + if (prec_dir->ic_precompose == (iconv_t)-1) { + die("iconv_open(%s,%s) failed, but needed:\n" + " precomposed unicode is not supported.\n" + " If you want to use decomposed unicode, run\n" + " \"git config core.precomposeunicode false\"\n", + repo_encoding, path_encoding); + } else { + iconv_ibp cp = (iconv_ibp)res->d_name; + size_t inleft = namelenz; + char *outpos = &prec_dir->dirent_nfc->d_name[0]; + size_t outsz = prec_dir->dirent_nfc->max_name_len; + size_t cnt; + errno = 0; + cnt = iconv(prec_dir->ic_precompose, &cp, &inleft, &outpos, &outsz); + if (errno || inleft) { + /* + * iconv() failed and errno could be E2BIG, EILSEQ, EINVAL, EBADF + * MacOS X avoids illegal byte sequemces. + * If they occur on a mounted drive (e.g. NFS) it is not worth to + * die() for that, but rather let the user see the original name + */ + namelenz = 0; /* trigger strlcpy */ + } + } + } else + namelenz = 0; + + if (!namelenz) + strlcpy(prec_dir->dirent_nfc->d_name, res->d_name, + prec_dir->dirent_nfc->max_name_len); + + errno = ret_errno; + return prec_dir->dirent_nfc; + } + return NULL; +} + + +int precompose_utf8_closedir(PREC_DIR *prec_dir) +{ + int ret_value; + int ret_errno; + ret_value = closedir(prec_dir->dirp); + ret_errno = errno; + if (prec_dir->ic_precompose != (iconv_t)-1) + iconv_close(prec_dir->ic_precompose); + free(prec_dir->dirent_nfc); + free(prec_dir); + errno = ret_errno; + return ret_value; +} diff --git a/compat/precompose_utf8.h b/compat/precompose_utf8.h new file mode 100644 index 0000000000..3b73585fc5 --- /dev/null +++ b/compat/precompose_utf8.h @@ -0,0 +1,45 @@ +#ifndef PRECOMPOSE_UNICODE_H +#include <sys/stat.h> +#include <sys/types.h> +#include <dirent.h> +#include <iconv.h> + + +typedef struct dirent_prec_psx { + ino_t d_ino; /* Posix */ + size_t max_name_len; /* See below */ + unsigned char d_type; /* available on all systems git runs on */ + + /* + * See http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/dirent.h.html + * NAME_MAX + 1 should be enough, but some systems have + * NAME_MAX=255 and strlen(d_name) may return 508 or 510 + * Solution: allocate more when needed, see precompose_utf8_readdir() + */ + char d_name[NAME_MAX+1]; +} dirent_prec_psx; + + +typedef struct { + iconv_t ic_precompose; + DIR *dirp; + struct dirent_prec_psx *dirent_nfc; +} PREC_DIR; + +void precompose_argv(int argc, const char **argv); +void probe_utf8_pathname_composition(char *, int); + +PREC_DIR *precompose_utf8_opendir(const char *dirname); +struct dirent_prec_psx *precompose_utf8_readdir(PREC_DIR *dirp); +int precompose_utf8_closedir(PREC_DIR *dirp); + +#ifndef PRECOMPOSE_UNICODE_C +#define dirent dirent_prec_psx +#define opendir(n) precompose_utf8_opendir(n) +#define readdir(d) precompose_utf8_readdir(d) +#define closedir(d) precompose_utf8_closedir(d) +#define DIR PREC_DIR +#endif /* PRECOMPOSE_UNICODE_C */ + +#define PRECOMPOSE_UNICODE_H +#endif /* PRECOMPOSE_UNICODE_H */ diff --git a/compat/regex/regcomp.c b/compat/regex/regcomp.c index 8c96ed942c..d0025bd58d 100644 --- a/compat/regex/regcomp.c +++ b/compat/regex/regcomp.c @@ -2095,7 +2095,7 @@ peek_token_bracket (re_token_t *token, re_string_t *input, reg_syntax_t syntax) /* Entry point of the parser. Parse the regular expression REGEXP and return the structure tree. - If an error is occured, ERR is set by error code, and return NULL. + If an error has occurred, ERR is set by error code, and return NULL. This function build the following tree, from regular expression <reg_exp>: CAT / \ @@ -3715,7 +3715,7 @@ build_charclass_op (re_dfa_t *dfa, RE_TRANSLATE_TYPE trans, /* This is intended for the expressions like "a{1,3}". Fetch a number from `input', and return the number. Return -1, if the number field is empty like "{,1}". - Return -2, If an error is occured. */ + Return -2, if an error has occurred. */ static int fetch_number (re_string_t *input, re_token_t *token, reg_syntax_t syntax) diff --git a/compat/regex/regex.c b/compat/regex/regex.c index 3dd8dfa01f..6aaae00327 100644 --- a/compat/regex/regex.c +++ b/compat/regex/regex.c @@ -22,7 +22,7 @@ #include "config.h" #endif -/* Make sure noone compiles this code with a C++ compiler. */ +/* Make sure no one compiles this code with a C++ compiler. */ #ifdef __cplusplus # error "This is C code, use a C compiler" #endif diff --git a/compat/regex/regex_internal.c b/compat/regex/regex_internal.c index 193854cf5b..d4121f2f4f 100644 --- a/compat/regex/regex_internal.c +++ b/compat/regex/regex_internal.c @@ -1284,7 +1284,7 @@ re_node_set_merge (re_node_set *dest, const re_node_set *src) /* Insert the new element ELEM to the re_node_set* SET. SET should not already have ELEM. - return -1 if an error is occured, return 1 otherwise. */ + return -1 if an error has occurred, return 1 otherwise. */ static int internal_function @@ -1341,7 +1341,7 @@ re_node_set_insert (re_node_set *set, int elem) /* Insert the new element ELEM to the re_node_set* SET. SET should not already have any element greater than or equal to ELEM. - Return -1 if an error is occured, return 1 otherwise. */ + Return -1 if an error has occurred, return 1 otherwise. */ static int internal_function @@ -1416,7 +1416,7 @@ re_node_set_remove_at (re_node_set *set, int idx) /* Add the token TOKEN to dfa->nodes, and return the index of the token. - Or return -1, if an error will be occured. */ + Or return -1, if an error has occurred. */ static int internal_function diff --git a/compat/regex/regexec.c b/compat/regex/regexec.c index 0194965c5d..0cd6e0ef98 100644 --- a/compat/regex/regexec.c +++ b/compat/regex/regexec.c @@ -2313,7 +2313,7 @@ transit_state (reg_errcode_t *err, re_match_context_t *mctx, } /* Update the state_log if we need */ -re_dfastate_t * +static re_dfastate_t * internal_function merge_state_with_log (reg_errcode_t *err, re_match_context_t *mctx, re_dfastate_t *next_state) @@ -2326,7 +2326,7 @@ merge_state_with_log (reg_errcode_t *err, re_match_context_t *mctx, mctx->state_log[cur_idx] = next_state; mctx->state_log_top = cur_idx; } - else if (mctx->state_log[cur_idx] == 0) + else if (mctx->state_log[cur_idx] == NULL) { mctx->state_log[cur_idx] = next_state; } @@ -2392,7 +2392,7 @@ merge_state_with_log (reg_errcode_t *err, re_match_context_t *mctx, /* Skip bytes in the input that correspond to part of a multi-byte match, then look in the log for a state from which to restart matching. */ -re_dfastate_t * +static re_dfastate_t * internal_function find_recover_state (reg_errcode_t *err, re_match_context_t *mctx) { diff --git a/compat/strtok_r.c b/compat/strtok_r.c deleted file mode 100644 index 7b5d568a96..0000000000 --- a/compat/strtok_r.c +++ /dev/null @@ -1,61 +0,0 @@ -/* Reentrant string tokenizer. Generic version. - Copyright (C) 1991,1996-1999,2001,2004 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, write to the Free - Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA - 02111-1307 USA. */ - -#include "../git-compat-util.h" - -/* Parse S into tokens separated by characters in DELIM. - If S is NULL, the saved pointer in SAVE_PTR is used as - the next starting point. For example: - char s[] = "-abc-=-def"; - char *sp; - x = strtok_r(s, "-", &sp); // x = "abc", sp = "=-def" - x = strtok_r(NULL, "-=", &sp); // x = "def", sp = NULL - x = strtok_r(NULL, "=", &sp); // x = NULL - // s = "abc\0-def\0" -*/ -char * -gitstrtok_r (char *s, const char *delim, char **save_ptr) -{ - char *token; - - if (s == NULL) - s = *save_ptr; - - /* Scan leading delimiters. */ - s += strspn (s, delim); - if (*s == '\0') - { - *save_ptr = s; - return NULL; - } - - /* Find the end of the token. */ - token = s; - s = strpbrk (token, delim); - if (s == NULL) - /* This token finishes the string. */ - *save_ptr = token + strlen (token); - else - { - /* Terminate the token and make *SAVE_PTR point past it. */ - *s = '\0'; - *save_ptr = s + 1; - } - return token; -} diff --git a/compat/terminal.c b/compat/terminal.c index 6d16c8fba0..313897d581 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(GIT_WINDOWS_NATIVE) + +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,57 +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(GIT_WINDOWS_NATIVE) + +#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) { - 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; diff --git a/compat/unsetenv.c b/compat/unsetenv.c index eb29f5e084..4ea18569c2 100644 --- a/compat/unsetenv.c +++ b/compat/unsetenv.c @@ -2,7 +2,6 @@ void gitunsetenv (const char *name) { - extern char **environ; int src, dst; size_t nmln; diff --git a/compat/vcbuild/include/sys/poll.h b/compat/vcbuild/include/sys/poll.h deleted file mode 100644 index 0d8552a2c6..0000000000 --- a/compat/vcbuild/include/sys/poll.h +++ /dev/null @@ -1 +0,0 @@ -/* Intentionally empty file to support building git with MSVC */ diff --git a/compat/vcbuild/include/unistd.h b/compat/vcbuild/include/unistd.h index b14fcf94da..c65c2cd566 100644 --- a/compat/vcbuild/include/unistd.h +++ b/compat/vcbuild/include/unistd.h @@ -49,6 +49,9 @@ typedef int64_t off64_t; #define INTMAX_MAX _I64_MAX #define UINTMAX_MAX _UI64_MAX +#define UINT32_MAX 0xffffffff /* 4294967295U */ + +#define STDIN_FILENO 0 #define STDOUT_FILENO 1 #define STDERR_FILENO 2 diff --git a/compat/win32.h b/compat/win32.h index 8ce91048de..a97e880757 100644 --- a/compat/win32.h +++ b/compat/win32.h @@ -2,7 +2,7 @@ #define WIN32_H /* common Win32 functions for MinGW and Cygwin */ -#ifndef WIN32 /* Not defined by Cygwin */ +#ifndef GIT_WINDOWS_NATIVE /* Not defined for Cygwin */ #include <windows.h> #endif diff --git a/compat/win32/pthread.c b/compat/win32/pthread.c index 010e875ec4..e18f5c6e2e 100644 --- a/compat/win32/pthread.c +++ b/compat/win32/pthread.c @@ -52,7 +52,7 @@ int win32_pthread_join(pthread_t *thread, void **value_ptr) pthread_t pthread_self(void) { - pthread_t t = { 0 }; + pthread_t t = { NULL }; t.tid = GetCurrentThreadId(); return t; } diff --git a/compat/win32mmap.c b/compat/win32mmap.c index 61d2ef8e46..80a8c9af4f 100644 --- a/compat/win32mmap.c +++ b/compat/win32mmap.c @@ -21,8 +21,8 @@ void *git_mmap(void *start, size_t length, int prot, int flags, int fd, off_t of if (!(flags & MAP_PRIVATE)) die("Invalid usage of mmap when built with USE_WIN32_MMAP"); - hmap = CreateFileMapping((HANDLE)_get_osfhandle(fd), 0, PAGE_WRITECOPY, - 0, 0, 0); + hmap = CreateFileMapping((HANDLE)_get_osfhandle(fd), NULL, + PAGE_WRITECOPY, 0, 0, NULL); if (!hmap) return MAP_FAILED; |