Welcome to mirror list, hosted at ThFree Co, Russian Federation.

cygwin.com/git/newlib-cygwin.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'winsup/cygwin/times.cc')
-rw-r--r--winsup/cygwin/times.cc540
1 files changed, 540 insertions, 0 deletions
diff --git a/winsup/cygwin/times.cc b/winsup/cygwin/times.cc
new file mode 100644
index 000000000..6ee283b5c
--- /dev/null
+++ b/winsup/cygwin/times.cc
@@ -0,0 +1,540 @@
+/* times.cc
+
+ Copyright 1996, 1997, 1998, 1999, 2000 Cygnus Solutions.
+
+This file is part of Cygwin.
+
+This software is a copyrighted work licensed under the terms of the
+Cygwin license. Please consult the file "CYGWIN_LICENSE" for
+details. */
+
+#include <time.h>
+#include <sys/times.h>
+#include <sys/timeb.h>
+#include <utime.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include "winsup.h"
+
+extern time_t __declspec(dllexport) _timezone;
+extern int __declspec(dllexport) _daylight;
+
+#define FACTOR (0x19db1ded53ea710LL)
+#define NSPERSEC 10000000LL
+
+static void __stdcall timeval_to_filetime (timeval *time, FILETIME *out);
+
+/* Cygwin internal */
+static unsigned long long __stdcall
+__to_clock_t (FILETIME * src, int flag)
+{
+ unsigned long long total = ((unsigned long long) src->dwHighDateTime << 32) + ((unsigned)src->dwLowDateTime);
+ syscall_printf ("dwHighDateTime %u, dwLowDateTime %u", src->dwHighDateTime, src->dwLowDateTime);
+
+ /* Convert into clock ticks - the total is in 10ths of a usec. */
+ if (flag)
+ total -= FACTOR;
+
+ total /= (unsigned long long) (NSPERSEC / CLOCKS_PER_SEC);
+ syscall_printf ("total %08x %08x\n", (unsigned)(total>>32), (unsigned)(total));
+ return total;
+}
+
+/* times: POSIX 4.5.2.1 */
+extern "C" clock_t
+times (struct tms * buf)
+{
+ FILETIME creation_time, exit_time, kernel_time, user_time;
+
+ DWORD ticks = GetTickCount ();
+ /* Ticks is in milliseconds, convert to our ticks. Use long long to prevent
+ overflow. */
+ clock_t tc = (clock_t) ((long long) ticks * CLOCKS_PER_SEC / 1000);
+ if (os_being_run == winNT)
+ {
+ GetProcessTimes (hMainProc, &creation_time, &exit_time,
+ &kernel_time, &user_time);
+
+ syscall_printf ("ticks %d, CLOCKS_PER_SEC %d", ticks, CLOCKS_PER_SEC);
+ syscall_printf ("user_time %d, kernel_time %d, creation_time %d, exit_time %d",
+ user_time, kernel_time, creation_time, exit_time);
+ buf->tms_stime = __to_clock_t (&kernel_time, 0);
+ buf->tms_utime = __to_clock_t (&user_time, 0);
+ timeval_to_filetime (&myself->rusage_children.ru_stime, &kernel_time);
+ buf->tms_cstime = __to_clock_t (&kernel_time, 1);
+ timeval_to_filetime (&myself->rusage_children.ru_utime, &user_time);
+ buf->tms_cutime = __to_clock_t (&user_time, 1);
+ }
+ else
+ /* GetProcessTimes() does not work for non-NT versions of Windows. The
+ return values are undefined, so instead just copy the ticks value
+ into utime so that clock() will work properly on these systems */
+ {
+ buf->tms_utime = tc;
+ buf->tms_stime = 0;
+ buf->tms_cstime = 0;
+ buf->tms_cutime = 0;
+ }
+
+ return tc;
+}
+
+extern "C" clock_t
+_times (struct tms * buf)
+{
+ return times (buf);
+}
+
+/* settimeofday: BSD */
+extern "C" int
+settimeofday (const struct timeval *, const struct timezone *)
+{
+ set_errno (ENOSYS);
+ return -1;
+}
+
+/* timezone: standards? */
+extern "C" char *
+timezone ()
+{
+#ifdef _MT_SAFE
+ char *b=_reent_winsup()->_b;
+#else
+ static NO_COPY char b[20] = {0};
+#endif
+
+ tzset();
+ __small_sprintf (b,"GMT%+d:%02d", (int) (-_timezone / 3600), (int) (abs(_timezone / 60) % 60));
+ return b;
+}
+
+/* Cygwin internal */
+void __stdcall
+totimeval (struct timeval *dst, FILETIME *src, int sub, int flag)
+{
+ long long x = __to_clock_t (src, flag);
+
+ x *= (int) (1e6) / CLOCKS_PER_SEC; /* Turn x into usecs */
+ x -= (long long) sub * (int) (1e6);
+
+ dst->tv_usec = x % (long long) (1e6); /* And split */
+ dst->tv_sec = x / (long long) (1e6);
+}
+
+/* gettimeofday: BSD */
+extern "C" int
+gettimeofday (struct timeval *p, struct timezone *z)
+{
+ int res = 0;
+
+ if (p != NULL)
+ {
+ SYSTEMTIME t;
+ FILETIME f;
+
+ GetSystemTime (&t);
+ if (! SystemTimeToFileTime (&t, &f))
+ res = -1;
+ totimeval (p, &f, 0, 1);
+ }
+
+ if (z != NULL)
+ {
+ tzset();
+ z->tz_minuteswest = _timezone / 60;
+ z->tz_dsttime = _daylight;
+ }
+
+ syscall_printf ("%d = gettimeofday (%x, %x)", res, p, z);
+
+ return res;
+}
+
+extern "C"
+int
+_gettimeofday (struct timeval *p, struct timezone *z)
+{
+ return gettimeofday (p, z);
+}
+
+#if 0
+/* Work out magic constant below */
+genf ()
+{
+ SYSTEMTIME s;
+ FILETIME f;
+ s.wYear = 1970;
+ s.wMonth = 1;
+ s.wDayOfWeek = 5;
+ s.wDay = 1;
+ s.wHour = 0;
+ s.wMinute = 0;
+ s.wSecond = 0;
+ s.wMilliseconds = 1;
+ SystemTimeToFileTime (&s, &f);
+
+ small_printf ("FILE TIME is %08x%08x\n",
+ f.dwHighDateTime,
+ f.dwLowDateTime);
+}
+#endif
+
+/* Cygwin internal */
+void
+time_t_to_filetime (time_t time_in, FILETIME *out)
+{
+ long long x = time_in * NSPERSEC + FACTOR;
+ out->dwHighDateTime = x >> 32;
+ out->dwLowDateTime = x;
+}
+
+/* Cygwin internal */
+static void __stdcall
+timeval_to_filetime (timeval *time_in, FILETIME *out)
+{
+ long long x = time_in->tv_sec * NSPERSEC +
+ time_in->tv_usec * (NSPERSEC/1000000) + FACTOR;
+ out->dwHighDateTime = x >> 32;
+ out->dwLowDateTime = x;
+}
+
+/* Cygwin internal */
+static timeval __stdcall
+time_t_to_timeval (time_t in)
+{
+ timeval res;
+ res.tv_sec = in;
+ res.tv_usec = 0;
+ return res;
+}
+
+/* Cygwin internal */
+/* Convert a Win32 time to "UNIX" format. */
+long __stdcall
+to_time_t (FILETIME *ptr)
+{
+ /* A file time is the number of 100ns since jan 1 1601
+ stuffed into two long words.
+ A time_t is the number of seconds since jan 1 1970. */
+
+ long rem;
+ long long x = ((long long) ptr->dwHighDateTime << 32) + ((unsigned)ptr->dwLowDateTime);
+ x -= FACTOR; /* number of 100ns between 1601 and 1970 */
+ rem = x % ((long long)NSPERSEC);
+ rem += (NSPERSEC / 2);
+ x /= (long long) NSPERSEC; /* number of 100ns in a second */
+ x += (long long) (rem / NSPERSEC);
+ return x;
+}
+
+/* time: POSIX 4.5.1.1, C 4.12.2.4 */
+/* Return number of seconds since 00:00 UTC on jan 1, 1970 */
+extern "C"
+time_t
+time (time_t * ptr)
+{
+ time_t res;
+ SYSTEMTIME systemtime;
+ FILETIME filetime;
+
+ GetSystemTime (&systemtime);
+ SystemTimeToFileTime (&systemtime, &filetime);
+ res = to_time_t (&filetime);
+ if (ptr)
+ *ptr = res;
+
+ syscall_printf ("%d = time (%x)", res, ptr);
+
+ return res;
+}
+
+/*
+ * localtime_r.c
+ * Original Author: Adapted from tzcode maintained by Arthur David Olson.
+ *
+ * Converts the calendar time pointed to by tim_p into a broken-down time
+ * expressed as local time. Returns a pointer to a structure containing the
+ * broken-down time.
+ */
+
+#define SECSPERMIN 60
+#define MINSPERHOUR 60
+#define HOURSPERDAY 24
+#define SECSPERHOUR (SECSPERMIN * MINSPERHOUR)
+#define SECSPERDAY (SECSPERHOUR * HOURSPERDAY)
+#define DAYSPERWEEK 7
+#define MONSPERYEAR 12
+
+#define YEAR_BASE 1900
+#define EPOCH_YEAR 1970
+#define EPOCH_WDAY 4
+
+#define isleap(y) ((((y) % 4) == 0 && ((y) % 100) != 0) || ((y) % 400) == 0)
+
+#if 0 /* POSIX_LOCALTIME */
+
+static _CONST int mon_lengths[2][MONSPERYEAR] = {
+ {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
+ {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
+};
+
+static _CONST int year_lengths[2] = {
+ 365,
+ 366
+};
+
+/*
+ * Convert a time_t into a struct tm *.
+ * Does NO timezone conversion.
+ */
+
+/* Cygwin internal */
+static struct tm * __stdcall
+corelocaltime (const time_t * tim_p)
+{
+ long days, rem;
+ int y;
+ int yleap;
+ _CONST int *ip;
+#ifdef _MT_SAFE
+ struct tm &localtime_buf=_reent_winsup()->_localtime_buf;
+#else
+ static NO_COPY struct tm localtime_buf = {0};
+#endif
+
+ time_t tim = *tim_p;
+ struct tm *res = &localtime_buf;
+
+ days = ((long) tim) / SECSPERDAY;
+ rem = ((long) tim) % SECSPERDAY;
+
+ while (rem < 0)
+ {
+ rem += SECSPERDAY;
+ --days;
+ }
+ while (rem >= SECSPERDAY)
+ {
+ rem -= SECSPERDAY;
+ ++days;
+ }
+
+ /* compute hour, min, and sec */
+ res->tm_hour = (int) (rem / SECSPERHOUR);
+ rem %= SECSPERHOUR;
+ res->tm_min = (int) (rem / SECSPERMIN);
+ res->tm_sec = (int) (rem % SECSPERMIN);
+
+ /* compute day of week */
+ if ((res->tm_wday = ((EPOCH_WDAY + days) % DAYSPERWEEK)) < 0)
+ res->tm_wday += DAYSPERWEEK;
+
+ /* compute year & day of year */
+ y = EPOCH_YEAR;
+ if (days >= 0)
+ {
+ for (;;)
+ {
+ yleap = isleap (y);
+ if (days < year_lengths[yleap])
+ break;
+ y++;
+ days -= year_lengths[yleap];
+ }
+ }
+ else
+ {
+ do
+ {
+ --y;
+ yleap = isleap (y);
+ days += year_lengths[yleap];
+ } while (days < 0);
+ }
+
+ res->tm_year = y - YEAR_BASE;
+ res->tm_yday = days;
+ ip = mon_lengths[yleap];
+ for (res->tm_mon = 0; days >= ip[res->tm_mon]; ++res->tm_mon)
+ days -= ip[res->tm_mon];
+ res->tm_mday = days + 1;
+
+ /* set daylight saving time flag */
+ res->tm_isdst = -1;
+
+ syscall_printf ("%d = corelocaltime (%x)", res, tim_p);
+
+ return (res);
+}
+
+/* localtime: POSIX 8.1.1, C 4.12.3.4 */
+/*
+ * localtime takes a time_t (which is in UTC)
+ * and formats it into a struct tm as a local time.
+ */
+extern "C"
+struct tm *
+localtime (const time_t *tim_p)
+{
+ time_t tim = *tim_p;
+ struct tm *rtm;
+
+ tzset();
+
+ tim -= _timezone;
+
+ rtm = corelocaltime (&tim);
+
+ rtm->tm_isdst = _daylight;
+
+ syscall_printf ("%x = localtime (%x)", rtm, tim_p);
+
+ return rtm;
+}
+
+/* gmtime: C 4.12.3.3 */
+/*
+ * gmtime takes a time_t (which is already in UTC)
+ * and just puts it into a struct tm.
+ */
+extern "C"
+struct tm *
+gmtime (const time_t *tim_p)
+{
+ time_t tim = *tim_p;
+
+ struct tm *rtm = corelocaltime (&tim);
+ /* UTC has no daylight savings time */
+ rtm->tm_isdst = 0;
+
+ syscall_printf ("%x = gmtime (%x)", rtm, tim_p);
+
+ return rtm;
+}
+
+#endif /* POSIX_LOCALTIME */
+
+/* utimes: standards? */
+extern "C"
+int
+utimes (const char *path, struct timeval *tvp)
+{
+ int res = 0;
+ struct timeval tmp[2];
+ path_conv win32 (path);
+
+ if (win32.error)
+ {
+ set_errno (win32.error);
+ syscall_printf ("-1 = utimes (%s, %x)", path, tvp);
+ return -1;
+ }
+
+ /* MSDN suggests using FILE_FLAG_BACKUP_SEMANTICS for accessing
+ the times of directories. FIXME: what about Win95??? */
+ HANDLE h = CreateFileA (win32.get_win32 (),
+ GENERIC_WRITE,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ &sec_none_nih,
+ OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL | FILE_FLAG_BACKUP_SEMANTICS,
+ 0);
+
+ if (h == INVALID_HANDLE_VALUE)
+ {
+ if ((res = GetFileAttributes (win32.get_win32 ())) != -1 &&
+ (res & FILE_ATTRIBUTE_DIRECTORY))
+ {
+ /* What we can do with directories more? */
+ res = 0;
+ }
+ else
+ {
+ res = -1;
+ __seterrno ();
+ }
+ }
+ else
+ {
+ if (tvp == 0)
+ {
+ gettimeofday (&tmp[0], 0);
+ tmp[1] = tmp[0];
+ tvp = tmp;
+ }
+
+ FILETIME lastaccess;
+ FILETIME lastwrite;
+
+ timeval_to_filetime (tvp + 0, &lastaccess);
+ timeval_to_filetime (tvp + 1, &lastwrite);
+
+ debug_printf ("incoming lastaccess %08x %08x",
+ tvp->tv_sec,
+ tvp->tv_usec);
+
+// dump_filetime (lastaccess);
+// dump_filetime (lastwrite);
+
+ /* FIXME: SetFileTime needs a handle with a write lock
+ on the file whose time is being modified. So calls to utime()
+ fail for read only files. */
+
+ if (!SetFileTime (h, 0, &lastaccess, &lastwrite))
+ {
+ __seterrno ();
+ res = -1;
+ }
+ else
+ res = 0;
+ CloseHandle (h);
+ }
+
+ syscall_printf ("%d = utimes (%s, %x); (h%d)",
+ res, path, tvp, h);
+ return res;
+}
+
+/* utime: POSIX 5.6.6.1 */
+extern "C"
+int
+utime (const char *path, struct utimbuf *buf)
+{
+ struct timeval tmp[2];
+
+ if (buf == 0)
+ return utimes (path, 0);
+
+ debug_printf ("incoming utime act %x", buf->actime);
+ tmp[0] = time_t_to_timeval (buf->actime);
+ tmp[1] = time_t_to_timeval (buf->modtime);
+
+ return utimes (path, tmp);
+}
+
+/* ftime: standards? */
+extern "C"
+int
+ftime (struct timeb *tp)
+{
+ struct timeval tv;
+ struct timezone tz;
+
+ if (gettimeofday (&tv, &tz) < 0)
+ return -1;
+
+ tp->time = tv.tv_sec;
+ tp->millitm = tv.tv_usec / 1000;
+ tp->timezone = tz.tz_minuteswest;
+ tp->dstflag = tz.tz_dsttime;
+
+ return 0;
+}
+
+/* obsolete, changed to cygwin_tzset when localtime.c was added - dj */
+extern "C"
+void
+cygwin_tzset ()
+{
+}