From d63c2da552bc89c6748c31af651699b77fc1efe6 Mon Sep 17 00:00:00 2001 From: Corinna Vinschen Date: Fri, 14 Mar 2008 20:43:28 +0000 Subject: [PATCH] * fcntl.cc (fcntl_worker): Protect with a 'myfault'. * path.cc (normalize_posix_path): Treat X:/ as Win32 path, too. * smallprint.cc (__wrn): New static function. (__small_vswprintf): New function to generate WCHAR strings. (__small_swprintf): Ditto. * winsup.h (__small_swprintf): Declare. (__small_vswprintf): Declare. --- winsup/cygwin/ChangeLog | 12 +++ winsup/cygwin/fcntl.cc | 5 + winsup/cygwin/path.cc | 2 +- winsup/cygwin/smallprint.cc | 193 ++++++++++++++++++++++++++++++++++++ winsup/cygwin/winsup.h | 2 + 5 files changed, 213 insertions(+), 1 deletion(-) diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index 01408f2f5..37c6a7db0 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,15 @@ +2008-03-14 Corinna Vinschen + + * fcntl.cc (fcntl_worker): Protect with a 'myfault'. + + * path.cc (normalize_posix_path): Treat X:/ as Win32 path, too. + + * smallprint.cc (__wrn): New static function. + (__small_vswprintf): New function to generate WCHAR strings. + (__small_swprintf): Ditto. + * winsup.h (__small_swprintf): Declare. + (__small_vswprintf): Declare. + 2008-03-13 Corinna Vinschen * path.sgml: Remove documentation for old path API. Add documentation diff --git a/winsup/cygwin/fcntl.cc b/winsup/cygwin/fcntl.cc index b1f0d9972..f9a023ec4 100644 --- a/winsup/cygwin/fcntl.cc +++ b/winsup/cygwin/fcntl.cc @@ -18,12 +18,17 @@ details. */ #include "dtable.h" #include "cygheap.h" #include "thread.h" +#include "cygtls.h" int fcntl_worker (int fd, int cmd, void *arg) { int res; + myfault efault; + if (efault.faulted (EFAULT)) + return -1; + cygheap_fdget cfd (fd, true); if (cfd < 0) { diff --git a/winsup/cygwin/path.cc b/winsup/cygwin/path.cc index aa390bcd2..84490f287 100644 --- a/winsup/cygwin/path.cc +++ b/winsup/cygwin/path.cc @@ -253,7 +253,7 @@ normalize_posix_path (const char *src, char *dst, char *&tail) char *dst_start = dst; syscall_printf ("src %s", src); - if ((isdrive (src) && src[2] == '\\') || *src == '\\') + if ((isdrive (src) && isdirsep (src[2])) || *src == '\\') goto win32_path; tail = dst; diff --git a/winsup/cygwin/smallprint.cc b/winsup/cygwin/smallprint.cc index 2a7810c50..eead3716f 100644 --- a/winsup/cygwin/smallprint.cc +++ b/winsup/cygwin/smallprint.cc @@ -14,6 +14,8 @@ details. */ #include #include #include +#include +#include #include #define LLMASK (0xffffffffffffffffULL) @@ -286,3 +288,194 @@ console_printf (const char *fmt, ...) FlushFileBuffers (console_handle); } #endif + +#define wrnarg(dst, base, dosign, len, pad) __wrn ((dst), (base), (dosign), va_arg (ap, long), len, pad, LMASK) +#define wrnargLL(dst, base, dosign, len, pad) __wrn ((dst), (base), (dosign), va_arg (ap, unsigned long long), len, pad, LLMASK) + +static PWCHAR __fastcall +__wrn (PWCHAR dst, int base, int dosign, long long val, int len, int pad, unsigned long long mask) +{ + /* longest number is ULLONG_MAX, 18446744073709551615, 20 digits */ + unsigned long long uval = 0; + WCHAR res[20]; + static const WCHAR str[] = L"0123456789ABCDEF"; + int l = 0; + + if (dosign && val < 0) + { + *dst++ = L'-'; + uval = -val; + } + else if (dosign > 0 && val > 0) + { + *dst++ = L'+'; + uval = val; + } + else + uval = val; + + uval &= mask; + + do + { + res[l++] = str[uval % base]; + uval /= base; + } + while (uval); + + while (len-- > l) + *dst++ = pad; + + while (l > 0) + *dst++ = res[--l]; + + return dst; +} + +extern "C" int +__small_vswprintf (PWCHAR dst, const WCHAR *fmt, va_list ap) +{ + WCHAR tmp[NT_MAX_PATH]; + PWCHAR orig = dst; + const char *s; + PWCHAR w; + UNICODE_STRING uw, *us; + + DWORD err = GetLastError (); + + while (*fmt) + { + unsigned int n = 0x7fff; + if (*fmt != L'%') + *dst++ = *fmt++; + else + { + int len = 0; + WCHAR pad = L' '; + int addsign = -1; + + switch (*++fmt) + { + case L'+': + addsign = 1; + fmt++; + break; + case L'%': + *dst++ = *fmt++; + continue; + } + + for (;;) + { + char c = *fmt++; + switch (c) + { + case L'0': + if (len == 0) + { + pad = L'0'; + continue; + } + case L'1' ... L'9': + len = len * 10 + (c - L'0'); + continue; + case L'l': + continue; + case L'c': + case L'C': + { + unsigned int c = va_arg (ap, unsigned int); + if (c > L' ' && c <= 127) + *dst++ = c; + else + { + *dst++ = L'0'; + *dst++ = L'x'; + dst = __wrn (dst, 16, 0, c, len, pad, LMASK); + } + } + break; + case L'E': + wcscpy (dst, L"Win32 error "); + dst = __wrn (dst + sizeof ("Win32 error"), 10, 0, err, len, pad, LMASK); + break; + case L'd': + dst = wrnarg (dst, 10, addsign, len, pad); + break; + case L'D': + dst = wrnargLL (dst, 10, addsign, len, pad); + break; + case L'u': + dst = wrnarg (dst, 10, 0, len, pad); + break; + case L'U': + dst = wrnargLL (dst, 10, 0, len, pad); + break; + case L'o': + dst = wrnarg (dst, 8, 0, len, pad); + break; + case L'p': + *dst++ = L'0'; + *dst++ = L'x'; + /* fall through */ + case L'x': + dst = wrnarg (dst, 16, 0, len, pad); + break; + case L'X': + dst = wrnargLL (dst, 16, 0, len, pad); + break; + case L'P': + if (!GetModuleFileNameW (NULL, tmp, NT_MAX_PATH)) + RtlInitUnicodeString (us = &uw, L"cygwin program"); + else + RtlInitUnicodeString (us = &uw, tmp); + goto fillin; + case L'.': + n = wcstoul (fmt, (wchar_t **) &fmt, 10); + if (*fmt++ != L's') + goto endfor; + case L's': + s = va_arg (ap, char *); + if (s == NULL) + s = "(null)"; + sys_mbstowcs (tmp, NT_MAX_PATH, s, n); + RtlInitUnicodeString (us = &uw, tmp); + goto fillin; + break; + case L'W': + w = va_arg (ap, PWCHAR); + RtlInitUnicodeString (us = &uw, w); + goto fillin; + case L'S': + us = va_arg (ap, PUNICODE_STRING); + fillin: + if (us->Length / sizeof (WCHAR) < n) + n = us->Length / sizeof (WCHAR); + + for (unsigned int i = 0; i < n; i++) + *dst++ = *w++; + break; + default: + *dst++ = L'?'; + *dst++ = fmt[-1]; + } + endfor: + break; + } + } + } + *dst = L'\0'; + SetLastError (err); + return dst - orig; +} + +extern "C" int +__small_swprintf (PWCHAR dst, const WCHAR *fmt, ...) +{ + int r; + va_list ap; + va_start (ap, fmt); + r = __small_vswprintf (dst, fmt, ap); + va_end (ap); + return r; +} diff --git a/winsup/cygwin/winsup.h b/winsup/cygwin/winsup.h index 7981e5469..5d9af096c 100644 --- a/winsup/cygwin/winsup.h +++ b/winsup/cygwin/winsup.h @@ -310,6 +310,8 @@ extern bool wsock_started; extern "C" void __api_fatal (const char *, ...) __attribute__ ((noreturn)); extern "C" int __small_sprintf (char *dst, const char *fmt, ...) /*__attribute__ ((regparm (2)))*/; extern "C" int __small_vsprintf (char *dst, const char *fmt, va_list ap) /*__attribute__ ((regparm (3)))*/; +extern "C" int __small_swprintf (PWCHAR dst, const WCHAR *fmt, ...) /*__attribute__ ((regparm (2)))*/; +extern "C" int __small_vswprintf (PWCHAR dst, const WCHAR *fmt, va_list ap) /*__attribute__ ((regparm (3)))*/; extern void multiple_cygwin_problem (const char *, unsigned, unsigned); extern "C" void vklog (int priority, const char *message, va_list ap);