• R/O
  • HTTP
  • SSH
  • HTTPS

提交

標籤
無標籤

Frequently used words (click to add to your profile)

javac++androidlinuxc#objective-cqt誰得cocoawindowspythonrubyphpgameguibathyscaphec翻訳omegat計画中(planning stage)frameworktwittertestdombtronvb.netdirectxarduinopreviewerゲームエンジン

Test programs to compare behaviour of MSVCRT.DLL time dependent functions.


Commit MetaInfo

修訂373ddfbf05122b381083f8e2ca6e139e2ce14f1f (tree)
時間2016-01-07 04:55:12
作者Keith Marshall <keithmarshall@user...>
CommiterKeith Marshall

Log Message

Add "chkfind", "chkstat", and autoconfiscated build system.

Change Summary

差異

--- /dev/null
+++ b/Makefile.in
@@ -0,0 +1,113 @@
1+# @configure_input@
2+# $Id$
3+#
4+# Makefile template for MSVCRT.DLL time_t behavioural test suite.
5+
6+PACKAGE = @PACKAGE_TARNAME@
7+VERSION = @PACKAGE_VERSION@
8+
9+# Written by Keith Marshall <keithmarshall@users.sourceforge.net>
10+# Copyright (C) 2016, MinGW.org Project
11+#
12+#
13+# Permission is hereby granted, free of charge, to any person obtaining a
14+# copy of this software and associated documentation files (the "Software"),
15+# to deal in the Software without restriction, including without limitation
16+# the rights to use, copy, modify, merge, publish, distribute, sublicense,
17+# and/or sell copies of the Software, and to permit persons to whom the
18+# Software is furnished to do so, subject to the following conditions:
19+#
20+# The above copyright notice and this permission notice (including the next
21+# paragraph) shall be included in all copies or substantial portions of the
22+# Software.
23+#
24+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
25+# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
26+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
27+# AUTHORS OR THE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
28+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
29+# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
30+# DEALINGS IN THE SOFTWARE.
31+
32+
33+# The default target is "all"; declare it early, to avoid any possible
34+# inadvertent override from any included file.
35+#
36+all:
37+
38+# The gamut of program files to be built by default.
39+#
40+EXEFILES = chktime$(EXEEXT) chkfind$(EXEEXT) chkstat$(EXEEXT)
41+
42+# Build time path, for location of source files.
43+#
44+vpath % @srcdir@
45+
46+# Command and option specifications for running the C compiler.
47+#
48+CC := @CC@
49+CFLAGS := @CFLAGS@
50+CPPFLAGS := @CPPFLAGS@
51+LDFLAGS := @LDFLAGS@
52+OBJEXT := @OBJEXT@
53+EXEEXT := @EXEEXT@
54+
55+# Actual payload specification for the default build target,
56+# and how to build the deliverable components.
57+#
58+all: $(EXEFILES)
59+%$(EXEEXT): %.c
60+ $(CC) $(CFLAGS) $(CPPFLAGS) -o $@ $^ $(LDFLAGS) $(LIBS)
61+
62+# Additional object file prerequisites for the deliverables.
63+#
64+ADDITIONAL_OBJECTS := tmpfile.$(OBJEXT) hexdump.$(OBJEXT)
65+chkfind$(EXEEXT) chkstat$(EXEEXT): $(ADDITIONAL_OBJECTS)
66+
67+
68+# Distribution.
69+#
70+DISTNAME := $(PACKAGE:mingw32-%=%)-$(VERSION)-mingw32
71+
72+dist: srcdist bindist
73+srcdist: $(DISTNAME)-src.tar.xz
74+bindist: $(DISTNAME)-bin.tar.xz
75+
76+MKDIR_P := @MKDIR_P@
77+LN_S := @LN_S@
78+
79+$(DISTNAME)-%.tar.xz:
80+ mkdir -p $(PACKAGE)-$(VERSION)
81+ $(RM) -r $(PACKAGE)-$(VERSION)/*
82+ cd $(PACKAGE)-$(VERSION); $(LN_S) $(^:%=../%) .
83+ tar chf - $(PACKAGE)-$(VERSION) | xz -c > $@
84+ $(RM) -r $(PACKAGE)-$(VERSION)
85+
86+# Specification of the payload for a source distribution.
87+#
88+$(DISTNAME)-src.tar.xz: $(EXEFILES:$(EXEEXT)=.c)
89+$(DISTNAME)-src.tar.xz: $(ADDITIONAL_OBJECTS:.$(OBJEXT)=.c)
90+$(DISTNAME)-src.tar.xz: configure.ac Makefile.in
91+$(DISTNAME)-src.tar.xz: configure install-sh
92+
93+# Specification of the payload for a binary distribution.
94+#
95+$(DISTNAME)-bin.tar.xz: $(EXEFILES)
96+
97+
98+# Clean-up rules.
99+#
100+clean mostlyclean:
101+ $(RM) *.$(OBJEXT) $(EXEFILES)
102+
103+distclean realclean: clean
104+ $(RM) -r Makefile autom4te.cache config.*
105+
106+maintainer-clean: maintainer-clean-notification distclean
107+ $(RM) configure
108+
109+maintainer-clean-notification:
110+ @echo "WARNING: this command is intended for use by project maintainers;"
111+ @echo "it deletes files which may require special tools to rebuild."
112+#
113+# $RCSfile$: end of file
--- a/chkfind.c
+++ b/chkfind.c
@@ -1,17 +1,50 @@
11 /*
2- * chktim.c
2+ * chkfind.c
33 *
44 * Program to test the hypothesis that MSVCRT.DLL retains the 32-bit
5- * format for _finddata_t, irrespective of MSDN documentation which
6- * suggests that it might have become an alias for _finddata64_t.
5+ * time_t format, (equivalent to __time32_t), for its representation
6+ * of file system time stamps within any instance of the _finddata_t
7+ * structure, irrespective of MSDN documentation which suggests that
8+ * _finddata_t may now be equivalent to _finddata64_t, in which the
9+ * time stamps are represented as 64-bit __time64_t.
710 *
11+ * $Id$
812 *
9- * All MinGW headers assume that _mingw.h is included; we want to avoid
13+ * Written by Keith Marshall <keithmarshall@users.sourceforge.net>
14+ * Copyright (C) 2014-2016, MinGW.org Project
15+ *
16+ *
17+ * Permission is hereby granted, free of charge, to any person obtaining a
18+ * copy of this software and associated documentation files (the "Software"),
19+ * to deal in the Software without restriction, including without limitation
20+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
21+ * and/or sell copies of the Software, and to permit persons to whom the
22+ * Software is furnished to do so, subject to the following conditions:
23+ *
24+ * The above copyright notice, this permission notice, and the following
25+ * disclaimer shall be included in all copies or substantial portions of
26+ * the Software.
27+ *
28+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
29+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
30+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
31+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
32+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
33+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OF OR OTHER
34+ * DEALINGS IN THE SOFTWARE.
35+ *
36+ *
37+ * All MinGW headers assume that <_mingw.h> is included; we want to avoid
1038 * possible conflicts with typedefs from standard headers, where we want
11- * a customized variant; thus we include _mingw.h directly, and copy any
12- * fragments from other headers, as appropriate.
39+ * a customized variant; thus, we avoid including as many of the standard
40+ * system headers as practicible. However, we do need <dlfcn.h>, to get
41+ * the inline implementation for dlsym(); we know that it doesn't create
42+ * any unwanted conflicts, so we go ahead and include it, allowing it to
43+ * include <_mingw.h> for us, while we copy any required fragments from
44+ * other system headers, as appropriate.
45+ *
1346 */
14-#include <_mingw.h>
47+#include <dlfcn.h>
1548
1649 /* The two possible internal representations of time_t, effectively as
1750 * defined by time.h; we want only these from time.h, while excluding any
@@ -28,146 +61,186 @@ typedef __int64 __time64_t;
2861 */
2962 #define FILENAME_MAX (260)
3063
31-struct _finddata32_t
32-{
33- /* This is the MSVCR80.DLL and later representation, equivalent to
34- * the all 32-bit member _finddata_t of earlier runtime versions...
35- */
36- unsigned attrib;
37- __time32_t time_create;
38- __time32_t time_access;
39- __time32_t time_write;
40- __int32 size;
41- char name[FILENAME_MAX];
42-};
43-
44-struct _finddata64_t
45-{
46- /* ...while this is the all 64-bit member alternative, which is used
47- * by those function variants which explicitly require 64-bit members;
48- * (it is NOT equivalent to _finddata_t, when that implicitly adopts
49- * the 64-bit time_t representation, for that retains a 32-bit file
50- * size member, and thus the equivalent is _finddata64i32_t).
51- */
52- unsigned attrib;
53- __time64_t time_create;
54- __time64_t time_access;
55- __time64_t time_write;
56- __int64 size;
57- char name[FILENAME_MAX];
58-};
59-
6064 struct _finddata_t
61-{
62- /* Not the way it's defined in the headers, but this custom variant
65+{ /* Not the way it's defined in the headers, but this custom variant
6366 * allows it to represent the equivalent of either of the above.
6467 */
65- union { struct _finddata32_t _32_bit; struct _finddata64_t _64_bit; };
68+ union
69+ { struct _finddata32_t
70+ { /* This is the MSVCR80.DLL and later representation, equivalent to
71+ * the all 32-bit member _finddata_t of earlier runtime versions...
72+ */
73+ unsigned attrib;
74+ __time32_t time_create;
75+ __time32_t time_access;
76+ __time32_t time_write;
77+ __int32 size;
78+ char name[FILENAME_MAX];
79+ } _32bit;
80+
81+ struct _finddata64_t
82+ { /* ...while this is the all 64-bit member alternative, which is used
83+ * by those function variants which explicitly require 64-bit members;
84+ * (it is NOT equivalent to _finddata_t, when that implicitly adopts
85+ * the 64-bit time_t representation, for that retains a 32-bit file
86+ * size member, and thus the equivalent is _finddata64i32_t).
87+ */
88+ unsigned attrib;
89+ __time64_t time_create;
90+ __time64_t time_access;
91+ __time64_t time_write;
92+ __int64 size;
93+ char name[FILENAME_MAX];
94+ } _64bit;
95+ };
6696 };
6797
68-/* To determine the default equivalence assumed by the runtime DLL,
69- * we evaluate variants of the _findfirst() function; which specific
70- * variant may be specified on the compiling command line, but if it
71- * is not...
72- */
73-#ifndef EVALUATE
74-/*
75- * ...then choose the _findfirst() function itself.
76- */
77-#define EVALUATE _findfirst
78-#endif
79-
8098 /* All variants of _findfirst() require a typedef for intptr_t; this
8199 * is normally provided in stdint.h, but we prefer not to include it,
82100 * and anyway, it's just as convenient to typedef it here.
83101 */
84102 typedef __int32 intptr_t;
85103
86-/* The _findfirst() variant prototypes are nominally declared in io.h,
87- * which we MUST NOT include here; thus, we must declare these locally.
88- */
89-_CRTIMP intptr_t __cdecl __MINGW_NOTHROW _findfirst (const char*, struct _finddata_t*);
90-_CRTIMP intptr_t __cdecl __MINGW_NOTHROW _findfirst32 (const char*, struct _finddata32_t*);
91-_CRTIMP intptr_t __cdecl __MINGW_NOTHROW _findfirst64 (const char*, struct _finddata64_t*);
92-
93-/* Normally prototyped in io.h, which we want to avoid including, declare
94- * the prototypes for the functions we will use to save our test results to
95- * a file, for subsequent inspection using the od command.
96- */
97-_CRTIMP int __cdecl __MINGW_NOTHROW open (const char*, int, ...);
98-_CRTIMP int __cdecl __MINGW_NOTHROW write (int, const void*, unsigned int);
99-_CRTIMP int __cdecl __MINGW_NOTHROW close (int);
100-
101-/* When opening the results file, we must specify a combination of the
102- * following attributes, which are normally defined in either of fctrl.h
103- * or sys/stat.h; once again, we define them locally, to avoid including
104- * either of these header files.
105- */
106-#define O_RDONLY 0
107-#define O_RDONLY 0
108-#define O_WRONLY 1
109-#define O_RDWR 2
110-
111-#define O_CREAT 0x0100 /* Create the file if it does not exist. */
112-#define O_BINARY 0x8000 /* Input and output is not translated. */
113-
114-/* The preceding are from fctrl.h, the following from sys/stat.h
115- */
116-#define S_IRUSR 0x0100
117-#define S_IWUSR 0x0080
118-#define S_IXUSR 0x0040
119-#define S_IRWXU (S_IRUSR | S_IWUSR | S_IXUSR)
120-
121-/* Before opening the results file, we want to ensure that it is
122- * created anew, and that its directory entry is committed before
123- * we attempt to invoke _findfirst() on it; to achieve this we will
124- * first unlink any existing old file, and the immediately close a
125- * duplicate file descriptor for the newly opened file. For this,
126- * we use the following pair of functions, for which we provide
127- * prototypes here, to avoid including io.h
128- */
129-_CRTIMP int __cdecl __MINGW_NOTHROW unlink (const char*);
130-_CRTIMP int __cdecl __MINGW_NOTHROW dup (int);
131-
132104 /* To aid identification of regions of the result buffer which may
133105 * not be updated when _findfirst() is called, we will initially fill
134106 * the data space with a recurring recognizable pattern; for this we
135107 * will use memset(), normally prototyped in string.h, which also
136108 * requires the definition of size_t from sys/types.h; to avoid
137109 * including these headers, we may conveniently reproduce the
138- * requisite typedef and prototype here.
110+ * requisite typedef and prototype here...
139111 */
140112 typedef unsigned __int32 size_t;
141113 _CRTIMP void* __cdecl __MINGW_NOTHROW memset (void *, int, size_t);
142114
143-int main()
115+/* ...together with these, to avoid including <stdio.h>.
116+ */
117+_CRTIMP int __cdecl __MINGW_NOTHROW printf (const char *, ...);
118+_CRTIMP int __cdecl __MINGW_NOTHROW close (int);
119+
120+/* This pair are local to this test suite, but are implemented in
121+ * their own separate translation units.
122+ */
123+int __cdecl __MINGW_NOTHROW tmpfile_create (char *);
124+const void* __cdecl __MINGW_NOTHROW hexdump (void *, size_t);
125+
126+static void timdump( const char *fmt, struct _finddata_t *refdata )
127+# define TIMESTAMP_VALUES(CLASS) refdata->_32bit.CLASS, refdata->_64bit.CLASS
128+{
129+ /* Print the analysis of the timestamp fields, within the
130+ * returned data buffer.
131+ */
132+ printf( fmt, "Creation time", TIMESTAMP_VALUES( time_create ) );
133+ printf( fmt, "Last access time", TIMESTAMP_VALUES( time_access ) );
134+ printf( fmt, "Last write time", TIMESTAMP_VALUES( time_write ) );
135+}
136+
137+static int chkfind( const char *fname, const char *refname )
144138 {
145- /* Begin by creating, and opening, a new file in which to store
146- * the resultant data image; (unlink initially, to ensure that no
147- * pre-existing file of the same name creates confusion).
139+ /* Evaluate the data returned by a single member of the _findfirst()
140+ * family of functions, treating all as generically similar.
148141 */
149- int fd; const char *fname;
150- unlink( fname = "./chkfind.dat" );
151- if( (fd = open( fname, O_RDWR | O_CREAT | O_BINARY, S_IRWXU )) >= 0 )
142+ intptr_t (*fn)( const char *, struct _finddata_t * );
143+
144+ /* Define a generic underlining string, which may be used by the
145+ * ULINE macro, (defined below), to underline table column headings
146+ * with a maximum width of 23 characters.
147+ */
148+ char underline[24];
149+# define ULINE(LEN) underline + sizeof(underline) - LEN - 1
150+ memset( underline, '-', sizeof(underline) );
151+ underline[sizeof(underline)-1] = '\0';
152+
153+ /* First check that the function of interest is actually present,
154+ * in the current runtime environment...
155+ */
156+ printf( "\nChecking for %s()... ", fname );
157+ if( (fn = dlsym( RTLD_DEFAULT, fname )) == (void *)(0) )
152158 {
153- /* File opened successfully; proceed to perform a _findfirst()
154- * look-up on it, having first closed a duplicate file handle to
155- * ensure that the directory entry has been committed, and also
156- * filling the return buffer with a recognizable 0xaa pattern,
157- * before refilling with the actual _findfirst() result.
159+ /* ...bailing out, if not.
158160 */
159- intptr_t lookup; struct _finddata_t ref; close( dup( fd ) );
160- lookup = EVALUATE( fname, memset( &ref, 0xaa, sizeof( ref ) ));
161+ printf( "no\n%s() is not available in the current run time environment\n\n",
162+ fname
163+ );
164+ return 0;
165+ }
166+ else
167+ { /* Next, check that the specified function actually works, with
168+ * the return buffer initialized with a predefined pattern...
169+ */
170+ struct _finddata_t refdata;
171+ printf( "yes\nAnalysing behaviour of function %s()...", fname );
172+ if( fn( refname, memset( &refdata, 0xaa, sizeof( refdata ) )) == -1 )
173+ /*
174+ * ...again, bailing out if not.
175+ */
176+ printf( " failed\n\n" );
177+
178+ else
179+ { /* Print a hexdump of the data returned by the working function...
180+ */
181+ printf( "\n\nContent of returned[*] file data structure is:--\n\n" );
182+ hexdump( &refdata, sizeof( refdata ) );
183+
184+ /* ...followed by a field-by-field analysis, with respect to each
185+ * of the potentially applicable structural layouts, of the time
186+ * valued fields within the returned data.
187+ */
188+ printf( "\nInterpreting as respectively _finddata32_t and _finddata64_t,"
189+ "\nthe embedded file system time stamp values are represented as:--"
190+ "\n\n%32s%22s\n%32s%22s\n", "_finddata32_t", "_finddata64_t",
191+ ULINE(13), ULINE(20)
192+ );
193+ timdump( "%17s: 0x%08I32x 0x%016I64x\n", &refdata );
194+ printf( "%17s%15s%22s\n"
195+ "\nWhen expressed as elapsed seconds since the beginning of "
196+ "\nthe unix epoch, these timestamp values represent:--"
197+ "\n\n%32s%22s\n%32s%22s\n", ULINE(17), ULINE(13), ULINE(20),
198+ "_finddata32_t", "_finddata64_t", ULINE(13), ULINE(20)
199+ );
200+ timdump( "%17s:%+14I32d%+22I64d\n", &refdata );
201+ printf( "%17s%15s%22s\n\n", ULINE(17), ULINE(13), ULINE(20) );
202+
203+ /* Returning non-zero indicates that the specified function did
204+ * exist, and appeared to work as advertised.
205+ */
206+ return 1;
207+ }
208+ }
209+}
161210
162- /* Write an image of the _findfirst() result to file, where we
163- * may subsequently inspect it using od, noting that any 0xaa
164- * remnants in the result were likely untouched by returned
165- * data from the _findfirst() call.
211+int main()
212+{ /* Begin by creating, and opening, a new file on which to execute
213+ * the _findfirst() function tests.
214+ */
215+ int fd;
216+ char fname[] = "./chkfind.XXXXXX";
217+ if( (fd = tmpfile_create( fname )) >= 0 )
218+ {
219+ /* Evaluate each of the potentially available functions, in turn...
220+ */
221+ if( chkfind( "_findfirst", fname )
222+ | chkfind( "_findfirst32", fname )
223+ | chkfind( "_findfirst64", fname )
224+ ) printf(
225+ /*
226+ * ...adding a footnote to the resultant output, when at least
227+ * one of them appears to work as advertised.
228+ */
229+ "[*] In each case, the return data structure is filled with a\n"
230+ " repeating pattern of 0xaa bytes, before invoking the function\n"
231+ " which is to be analysed. Any byte sequences which continue to\n"
232+ " exhibit this pattern, after the function has returned, may be\n"
233+ " assumed to have remained untouched during the function call.\n"
234+ );
235+
236+ /* Closing the temporary file, when we are done with it, causes the
237+ * system to delete it automatically.
166238 */
167- write( fd, &ref, sizeof( ref ) );
168239 close( fd );
169240 }
170241 /* Always terminate indicating successful completion.
171242 */
172243 return 0;
173244 }
245+
246+/* $RCSfile$: end of file */
--- /dev/null
+++ b/chkstat.c
@@ -0,0 +1,342 @@
1+/*
2+ * chkstat.c
3+ *
4+ * Program to test the hypothesis that MSVCRT.DLL retains the 32-bit
5+ * time_t format, (equivalent to __time32_t), for its representation
6+ * of file system time stamps within any instance of the _stat family
7+ * of structures, (other than those which explicitly declare their
8+ * timestamp fields to be of type __time64_t), irrespective of MSDN
9+ * documentation which suggests that __time64_t becomes the default
10+ * unless _USE_32BIT_TIME_T is defined.
11+ *
12+ * $Id$
13+ *
14+ * Written by Keith Marshall <keithmarshall@users.sourceforge.net>
15+ * Copyright (C) 2016, MinGW.org Project
16+ *
17+ *
18+ * Permission is hereby granted, free of charge, to any person obtaining a
19+ * copy of this software and associated documentation files (the "Software"),
20+ * to deal in the Software without restriction, including without limitation
21+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
22+ * and/or sell copies of the Software, and to permit persons to whom the
23+ * Software is furnished to do so, subject to the following conditions:
24+ *
25+ * The above copyright notice, this permission notice, and the following
26+ * disclaimer shall be included in all copies or substantial portions of
27+ * the Software.
28+ *
29+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
30+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
31+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
32+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
33+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
34+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OF OR OTHER
35+ * DEALINGS IN THE SOFTWARE.
36+ *
37+ *
38+ * All MinGW headers assume that <_mingw.h> is included; we want to avoid
39+ * possible conflicts with typedefs from standard headers, where we want
40+ * a customized variant; thus, we avoid including as many of the standard
41+ * system headers as practicible. However, we do need <dlfcn.h>, to get
42+ * the inline implementation for dlsym(); we know that it doesn't create
43+ * any unwanted conflicts, so we go ahead and include it, allowing it to
44+ * include <_mingw.h> for us, while we copy any required fragments from
45+ * other system headers, as appropriate.
46+ *
47+ */
48+#include <dlfcn.h>
49+
50+/* The two possible internal representations of time_t, effectively as
51+ * defined by time.h; we want only these from time.h, while excluding any
52+ * possible ambiguity in mapping to time_t itself, so just typedef them
53+ * locally, rather than include the header file.
54+ */
55+typedef __int32 __time32_t;
56+typedef __int64 __time64_t;
57+
58+/* Similarly, the following three normally come from <sys/types.h>, but
59+ * it is safer for us to just define them here.
60+ */
61+typedef unsigned int _dev_t;
62+typedef unsigned short _mode_t;
63+typedef short _ino_t;
64+
65+/* Here, we definitely want to avoid <sys/stat.h>, to define our own
66+ * custom variant of the stat structure...
67+ */
68+struct _stat
69+{ union
70+ { /* ...making it a union of the normal structure definitions, with
71+ * totally unambiguous declarations for the sizes of the time and
72+ * file size fields, in each case.
73+ */
74+ struct __stat32
75+ { _dev_t st_dev;
76+ _ino_t st_ino;
77+ _mode_t st_mode;
78+ short st_nlink;
79+ short st_uid;
80+ short st_gid;
81+ _dev_t st_rdev;
82+ __int32 st_size;
83+ __time32_t st_atime;
84+ __time32_t st_mtime;
85+ __time32_t st_ctime;
86+ } stat32i32;
87+
88+ struct _stat32i64
89+ { _dev_t st_dev;
90+ _ino_t st_ino;
91+ _mode_t st_mode;
92+ short st_nlink;
93+ short st_uid;
94+ short st_gid;
95+ _dev_t st_rdev;
96+ __int64 st_size;
97+ __time32_t st_atime;
98+ __time32_t st_mtime;
99+ __time32_t st_ctime;
100+ } stat32i64;
101+
102+ struct _stat64i32
103+ { _dev_t st_dev;
104+ _ino_t st_ino;
105+ _mode_t st_mode;
106+ short st_nlink;
107+ short st_uid;
108+ short st_gid;
109+ _dev_t st_rdev;
110+ __int32 st_size;
111+ __time64_t st_atime;
112+ __time64_t st_mtime;
113+ __time64_t st_ctime;
114+ } stat64i32;
115+
116+ struct __stat64
117+ { _dev_t st_dev;
118+ _ino_t st_ino;
119+ _mode_t st_mode;
120+ short st_nlink;
121+ short st_uid;
122+ short st_gid;
123+ _dev_t st_rdev;
124+ __int64 st_size;
125+ __time64_t st_atime;
126+ __time64_t st_mtime;
127+ __time64_t st_ctime;
128+ } stat64i64;
129+ };
130+};
131+
132+/* To aid identification of regions of the result buffer which may
133+ * not be updated when _stat(), (or any of its variants), is called,
134+ * we will initially fill the data space with a recurring recognizable
135+ * pattern; for this we will use memset(), which is normally prototyped
136+ * in <string.h>, and which also requires the definition of size_t from
137+ * <stddef.h>; to avoid including these headers, we may conveniently
138+ * reproduce the requisite typedef and prototype here...
139+ */
140+typedef unsigned __int32 size_t;
141+_CRTIMP void* __cdecl __MINGW_NOTHROW memset (void *, int, size_t);
142+
143+/* ...together with these, to avoid including <stdio.h>.
144+ */
145+_CRTIMP int __cdecl __MINGW_NOTHROW printf (const char *, ...);
146+_CRTIMP int __cdecl __MINGW_NOTHROW close (int);
147+
148+/* This pair are local to this test suite, but are implemented in their
149+ * own separate translation units.
150+ */
151+int __cdecl __MINGW_NOTHROW tmpfile_create (char *);
152+const void* __cdecl __MINGW_NOTHROW hexdump (void *, size_t);
153+
154+/* A macro to facilitate underlining of column headings; we initialize
155+ * the content of its static buffer in our main() function.
156+ */
157+static char underline[32];
158+#define ULINE(LEN) underline + sizeof(underline) - LEN - 1
159+
160+static void first_header( const char *first, const char *second )
161+{
162+ /* Print the table header for the first section of analytical results
163+ * in each single function test...
164+ */
165+ printf(
166+ "\nInterpreting as respectively %s, and %s return data,"
167+ "\nthe embedded file sizes and time stamp values are represented as:--"
168+ "\n\n%43s%26s\n%43s%26s\n", first, second, first, second,
169+ ULINE(24), ULINE(24)
170+ );
171+}
172+/* ...and the footer line, used to separate each analytical section
173+ * from the next.
174+ */
175+static void table_footer( void )
176+{ printf( "%17s%26s%26s\n", ULINE(17), ULINE(24), ULINE(24) ); }
177+
178+/* Macros to specify the format for each table row...
179+ */
180+#define DECFMT "%17s:%+25I64d%+26I64d\n"
181+#define HEXFMT "%17s: 0x%016I64x 0x%016I64x\n"
182+/*
183+ * ...and to identify the specific content for each row.
184+ */
185+#define ATIME(CLASS) (__time64_t)(refdata.CLASS.st_atime)
186+#define CTIME(CLASS) (__time64_t)(refdata.CLASS.st_ctime)
187+#define MTIME(CLASS) (__time64_t)(refdata.CLASS.st_mtime)
188+
189+#define FSIZE(CLASS) (__int64)(refdata.CLASS.st_size)
190+
191+static void epoch_header( const char *first, const char *second )
192+{
193+ /* Print the separator between the first tabulated data section,
194+ * and the following interpretation of time stamp values.
195+ */
196+ table_footer();
197+ printf(
198+ "\nWhen expressed as elapsed seconds since the beginning of "
199+ "\nthe unix epoch, the above timestamp values represent:--"
200+ "\n\n%43s%26s\n%43s%26s\n", first, second,
201+ ULINE(24), ULINE(24)
202+ );
203+}
204+
205+static void fsize_header( const char *first, const char *second )
206+{
207+ /* Print the final table separator, introducing the analysis of
208+ * file size data as decimal values.
209+ */
210+ table_footer();
211+ printf(
212+ "\nThe decimal value equivalents for the above file sizes are:--"
213+ "\n\n%43s%26s\n%43s%26s\n", first, second,
214+ ULINE(24), ULINE(24)
215+ );
216+}
217+
218+static int chkstat( const char *fname, const char *refname )
219+{
220+ /* Evaluate the data returned by a single member of the _stat()
221+ * family of functions, treating all as generically similar.
222+ */
223+ int (*fn)( const char *, struct _stat * );
224+
225+ /* First check that the function of interest is actually present,
226+ * in the current runtime environment...
227+ */
228+ printf( "\nChecking for %s()... ", fname );
229+ if( (fn = dlsym( RTLD_DEFAULT, fname )) == (void *)(0) )
230+ {
231+ /* ...bailing out, if not.
232+ */
233+ printf( "no\n%s() is not available in the current run time environment\n\n",
234+ fname
235+ );
236+ return 0;
237+ }
238+ else
239+ { /* Next, check that the specified function actually works, with
240+ * the return buffer initialized with a predefined pattern...
241+ */
242+ struct _stat refdata;
243+ printf( "yes\nAnalysing behaviour of function %s()...", fname );
244+ if( fn( refname, memset( &refdata, 0xaa, sizeof( refdata ) )) == -1 )
245+ /*
246+ * ...again, bailing out if not.
247+ */
248+ printf( " failed\n\n" );
249+
250+ else
251+ { /* Print a hexdump of the data returned by the working function...
252+ */
253+ printf( "\n\nContent of returned[*] stat data structure is:--\n\n" );
254+ hexdump( &refdata, sizeof( refdata ) );
255+
256+ /* ...followed by a field-by-field analysis, with respect to each
257+ * of the potentially applicable structural layouts.
258+ */
259+ first_header( "_stat", "_stat32i64" );
260+ printf( HEXFMT, "Creation time", CTIME(stat32i32), CTIME(stat32i64) );
261+ printf( HEXFMT, "Last access time", ATIME(stat32i32), ATIME(stat32i64) );
262+ printf( HEXFMT, "Last write time", MTIME(stat32i32), MTIME(stat32i64) );
263+ printf( HEXFMT, "File size", FSIZE(stat32i32), FSIZE(stat32i64) );
264+
265+ epoch_header( "_stat (__time32_t)", "_stat32i64 (__time32_t)" );
266+ printf( DECFMT, "Creation time", CTIME(stat32i32), CTIME(stat32i64) );
267+ printf( DECFMT, "Last access time", ATIME(stat32i32), ATIME(stat32i64) );
268+ printf( DECFMT, "Last write time", MTIME(stat32i32), MTIME(stat32i64) );
269+
270+ fsize_header( "_stat (int32_t)", "_stat32i64 (int64_t)" );
271+ printf( DECFMT, "File size", FSIZE(stat32i32), FSIZE(stat32i64) );
272+ table_footer();
273+
274+ first_header( "_stat64i32", "_stat64" );
275+ printf( HEXFMT, "Creation time", CTIME(stat64i32), CTIME(stat64i64) );
276+ printf( HEXFMT, "Last access time", ATIME(stat64i32), ATIME(stat64i64) );
277+ printf( HEXFMT, "Last write time", MTIME(stat64i32), MTIME(stat64i64) );
278+ printf( HEXFMT, "File size", FSIZE(stat64i32), FSIZE(stat64i64) );
279+
280+ epoch_header( "_stat64i32 (__time64_t)", "_stat64 (__time64_t)" );
281+ printf( DECFMT, "Creation time", CTIME(stat64i32), CTIME(stat64i64) );
282+ printf( DECFMT, "Last access time", ATIME(stat64i32), ATIME(stat64i64) );
283+ printf( DECFMT, "Last write time", MTIME(stat64i32), MTIME(stat64i64) );
284+
285+ fsize_header( "_stat64i32 (int32_t)", "_stat64 (int64_t)" );
286+ printf( DECFMT, "File size", FSIZE(stat64i32), FSIZE(stat64i64) );
287+ table_footer();
288+
289+ /* Returning non-zero indicates that the specified function did
290+ * exist, and appeared to work as advertised.
291+ */
292+ return 1;
293+ }
294+ }
295+}
296+
297+int main()
298+{ /* Begin by creating, and opening, a new file on which to execute
299+ * the stat() function tests.
300+ */
301+ int fd;
302+ char fname[] = "./chkfind.XXXXXX";
303+ if( (fd = tmpfile_create( fname )) >= 0 )
304+ {
305+ /* Define a generic underlining string, which may be used by the
306+ * ULINE macro, (defined above), to underline table column headings
307+ * with a maximum width of 23 characters.
308+ */
309+ memset( underline, '-', sizeof(underline) );
310+ underline[sizeof(underline)-1] = '\0';
311+
312+ /* Evaluate each of the potentially available functions, in turn...
313+ */
314+ if( chkstat( "_stat", fname )
315+ | chkstat( "_stat32", fname )
316+ | chkstat( "_stat64", fname )
317+ | chkstat( "_stat32i64", fname )
318+ | chkstat( "_stat64i32", fname )
319+ | chkstat( "_stati64", fname )
320+ ) printf( "\n\n"
321+ /*
322+ * ...adding a footnote to the resultant output, when at least
323+ * one of them appears to work as advertised.
324+ */
325+ "[*] In each case, the return data structure is filled with a\n"
326+ " repeating pattern of 0xaa bytes, before invoking the function\n"
327+ " which is to be analysed. Any byte sequences which continue to\n"
328+ " exhibit this pattern, after the function has returned, may be\n"
329+ " assumed to have remained untouched during the function call.\n"
330+ );
331+
332+ /* Closing the temporary file, when we are done with it, causes the
333+ * system to delete it automatically.
334+ */
335+ close( fd );
336+ }
337+ /* Always terminate indicating successful completion.
338+ */
339+ return 0;
340+}
341+
342+/* $RCSfile$: end of file */
--- a/chktime.c
+++ b/chktime.c
@@ -6,14 +6,43 @@
66 * MSVCR80.DLL and later, where time_t becomes equivalent to __time64_t,
77 * unless the user defines the _USE_32BIT_TIME_T macro.
88 *
9+ * $Id$
910 *
10- * All MinGW headers assume that _mingw.h is included; we want to avoid
11+ * Written by Keith Marshall <keithmarshall@users.sourceforge.net>
12+ * Copyright (C) 2014-2016, MinGW.org Project
13+ *
14+ *
15+ * Permission is hereby granted, free of charge, to any person obtaining a
16+ * copy of this software and associated documentation files (the "Software"),
17+ * to deal in the Software without restriction, including without limitation
18+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
19+ * and/or sell copies of the Software, and to permit persons to whom the
20+ * Software is furnished to do so, subject to the following conditions:
21+ *
22+ * The above copyright notice, this permission notice, and the following
23+ * disclaimer shall be included in all copies or substantial portions of
24+ * the Software.
25+ *
26+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
27+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
28+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
29+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
30+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
31+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OF OR OTHER
32+ * DEALINGS IN THE SOFTWARE.
33+ *
34+ *
35+ * All MinGW headers assume that <_mingw.h> is included; we want to avoid
1136 * possible conflicts with typedefs from standard headers, where we want
12- * a customized variant; thus we include _mingw.h directly, and copy any
13- * required fragments from other headers, as appropriate.
37+ * a customized variant; thus, we avoid including as many of the standard
38+ * system headers as practicible. However, we do need <dlfcn.h>, to get
39+ * the inline implementation for dlsym(); we know that it doesn't create
40+ * any unwanted conflicts, so we go ahead and include it, allowing it to
41+ * include <_mingw.h> for us, while we copy any required fragments from
42+ * other system headers, as appropriate.
1443 *
1544 */
16-#include <_mingw.h>
45+#include <dlfcn.h>
1746
1847 /* The two possible internal representations of time_t, effectively as
1948 * defined by time.h; we want only these from time.h, while excluding any
@@ -28,75 +57,91 @@ typedef __int64 __time64_t;
2857 */
2958 typedef union { __time32_t _32bit; __time64_t _64bit; } time_t;
3059
31-/* Declare protototypes for the functions we plan to evaluate; (note that
32- * _time32() isn't expected to be present in MSVCRT.DLL, but we declare
33- * its prototype anyway).
60+/* We reproduce the definition of size_t from sys/types.h, the prototype
61+ * for memset() from string.h, and the prototype for printf() from stdio.h,
62+ * to avoid including any of these.
3463 */
35-_CRTIMP time_t __cdecl __MINGW_NOTHROW _time32 (time_t *);
36-_CRTIMP time_t __cdecl __MINGW_NOTHROW _time64 (time_t *);
37-_CRTIMP time_t __cdecl __MINGW_NOTHROW time (time_t *);
64+typedef unsigned __int32 size_t;
65+_CRTIMP void* __cdecl __MINGW_NOTHROW memset( void *, int, size_t );
66+_CRTIMP int __cdecl __MINGW_NOTHROW printf( const char *, ... );
3867
39-#ifndef EVALUATE
40-/*
41- * In the event that no evaluation method was specified on the compiling
42- * command line, delegate the test to the time() function.
68+/* Program implementation begins with this...
4369 */
44-#define EVALUATE time
45-#endif
70+static void eval( const char *fname )
71+{
72+ /* ...helper function to lookup the entry point for the specified
73+ * time() function within the program's (DLL) address space, and to
74+ * invoke it according to a generic time() function template.
75+ */
76+ time_t (*fp)( time_t * );
77+ if( (fp = dlsym( RTLD_DEFAULT, fname )) == (void *)(0) )
78+ /*
79+ * The specified function is not supported in the current
80+ * program runtime environment; simply add a line record to
81+ * the results table, reporting this, instead of attempting
82+ * to invoke a non-existent API function.
83+ */
84+ printf( "%8s():%47s\n", fname, "*** function not supported ***" );
4685
47-/* Normally prototyped in io.h, which we want to avoid including, declare
48- * the prototypes for the functions we will use to save our test results to
49- * a file, for subsequent inspection using the od command.
50- */
51-_CRTIMP int __cdecl __MINGW_NOTHROW open (const char *, int, ...);
52-_CRTIMP int __cdecl __MINGW_NOTHROW write (int, const void *, unsigned int);
53-_CRTIMP int __cdecl __MINGW_NOTHROW close (int);
86+ else
87+ { /* The specified function is available; we set aside a buffer
88+ * in which to capture its return state, initialize that with
89+ * a recognizable bit pattern, (recurring 0xaa bytes), so that
90+ * we can easily see what is subsequently changed as we invoke
91+ * the specified function...
92+ */
93+ time_t now;
94+ fp( memset( &now, 0xaa, sizeof( time_t ) ));
5495
55-/* When opening the results file, we must specify a combination of the
56- * following attributes, which are normally defined in either of fctrl.h
57- * or sys/stat.h; once again, we define them locally, to avoid including
58- * either of these header files.
59- */
60-#define O_RDONLY 0
61-#define O_WRONLY 1
62-#define O_RDWR 2
96+ /* ...and tabulate the return state, as a single line record
97+ * in our results table.
98+ */
99+ printf( "%8s(): 0x%016I64x%+22I32d%+22I64d\n", fname,
100+ now._64bit, now._32bit, now._64bit
101+ );
102+ }
103+}
63104
64-#define O_CREAT 0x0100 /* Create the file if it does not exist. */
65-#define O_BINARY 0x8000 /* Input and output is not translated. */
105+int main()
106+{ /* Define a generic underlining string, which may be used by the
107+ * ULINE macro, (defined below), to underline table column headings
108+ * with a maximum width of 23 characters.
109+ */
110+ char underline[24];
111+ memset( underline, '-', sizeof(underline) );
112+ underline[sizeof(underline)-1] = '\0';
66113
67-/* The preceding are from fctrl.h, the following from sys/stat.h
68- */
69-#define S_IRUSR 0x0100
70-#define S_IWUSR 0x0080
71-#define S_IXUSR 0x0040
72-#define S_IRWXU (S_IRUSR | S_IWUSR | S_IXUSR)
114+ /* Print a table heading.
115+ */
116+# define ULINE(LEN) underline + sizeof(underline) - LEN - 1
117+ printf( "Seconds elapsed since the beginning of the unix epoch,\n"
118+ "as reported by MSVCRT.DLL time functions with time_t interpreted as:--\n"
119+ "\n%30s %-22s%s\n%30s%22s%22s\n", "Uninterpreted [*]",
120+ "32-bit (__time32_t)", "64-bit (__time64_t)",
121+ ULINE(18), ULINE(20), ULINE(20)
122+ );
73123
74-/* Similarly, we reproduce the definition of size_t from sys/types.h, and
75- * the prototype for memset() from string.h, to avoid including these.
76- */
77-typedef unsigned __int32 size_t;
78-_CRTIMP void* __cdecl __MINGW_NOTHROW memset (void *, int, size_t);
124+ /* Evaluate and tabulate the effect of calling each of the possible
125+ * MSVCRT.DLL implementations of the time() function.
126+ */
127+ eval( "time" );
128+ eval( "_time32" );
129+ eval( "_time64" );
79130
80-int main()
81-{
82- /* Begin by initializing the results file; if successful...
131+ /* Close the results table, and print a footnote.
83132 */
84- int fd = open( "./chktime.dat", O_RDWR | O_CREAT | O_BINARY, S_IRWXU );
85- if( fd >= 0 )
86- {
87- /* ...create a results buffer, fill it with a recognizable bit
88- * pattern, then reassign as many initial bytes as required by
89- * the function which is to be evaluated...
90- */
91- time_t now;
92- EVALUATE( memset( &now, 0xaa, sizeof( time_t ) ));
93- /*
94- * ...before committing it to the results file.
95- */
96- write( fd, &now, sizeof( time_t ) );
97- close( fd );
98- }
133+ printf( "%10s%20s%22s%22s\n\n"
134+ "[*] This is a hexadecimal representation of the content of the 64-bit\n"
135+ " results buffer, AFTER the function call; note that this was filled\n"
136+ " with 0xaa bytes BEFORE the function call, and that any bytes which\n"
137+ " retain this value after the call may be assumed to have remained\n"
138+ " untouched, when calling the specified function.\n",
139+ ULINE(9), ULINE(18), ULINE(20), ULINE(20)
140+ );
141+
99142 /* Always terminate as if successful.
100143 */
101144 return 0;
102145 }
146+
147+/* $RCSfile$: end of file */
--- /dev/null
+++ b/configure.ac
@@ -0,0 +1,45 @@
1+# configure.ac
2+#
3+# Configuration script for MinGW time_t behavioural evaluation
4+# for various functions exported by MSVCRT.DLL
5+#
6+ AC_INIT([mingw32-chktime],[1.0.0])
7+#
8+# $Id$
9+#
10+# Written by Keith Marshall <keithmarshall@users.sourceforge.net>
11+# Copyright (C) 2016, MinGW.org Project
12+#
13+#
14+# Permission is hereby granted, free of charge, to any person obtaining a
15+# copy of this software and associated documentation files (the "Software"),
16+# to deal in the Software without restriction, including without limitation
17+# the rights to use, copy, modify, merge, publish, distribute, sublicense,
18+# and/or sell copies of the Software, and to permit persons to whom the
19+# Software is furnished to do so, subject to the following conditions:
20+#
21+# The above copyright notice and this permission notice (including the next
22+# paragraph) shall be included in all copies or substantial portions of the
23+# Software.
24+#
25+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
26+# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
27+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
28+# AUTHORS OR THE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
29+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
30+# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
31+# DEALINGS IN THE SOFTWARE.
32+#
33+#
34+# Tests for build support tools.
35+#
36+ AC_PROG_CC
37+ AC_PROG_MKDIR_P
38+ AC_PROG_LN_S
39+#
40+# Makefile generation.
41+#
42+ AC_CONFIG_FILES([Makefile])
43+ AC_OUTPUT
44+#
45+# $RCSfile$: end of file
--- /dev/null
+++ b/hexdump.c
@@ -0,0 +1,112 @@
1+/*
2+ * hexdump.c
3+ *
4+ * Utility functions to display the content of any memory region, in a
5+ * similar style to the hexadecimal output from the unix od command.
6+ *
7+ * $Id$
8+ *
9+ * Written by Keith Marshall <keithmarshall@users.sourceforge.net>
10+ * Copyright (C) 2014, 2016, MinGW.org Project
11+ *
12+ *
13+ * Permission is hereby granted, free of charge, to any person obtaining a
14+ * copy of this software and associated documentation files (the "Software"),
15+ * to deal in the Software without restriction, including without limitation
16+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
17+ * and/or sell copies of the Software, and to permit persons to whom the
18+ * Software is furnished to do so, subject to the following conditions:
19+ *
20+ * The above copyright notice, this permission notice, and the following
21+ * disclaimer shall be included in all copies or substantial portions of
22+ * the Software.
23+ *
24+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
25+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
26+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
27+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
28+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
29+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OF OR OTHER
30+ * DEALINGS IN THE SOFTWARE.
31+ *
32+ */
33+#include <ctype.h>
34+#include <stdio.h>
35+
36+#define HEXDUMP_INLINE static __inline__ __attribute__((__always_inline__))
37+
38+#ifndef HEXDUMP_OFFSET_FORMAT
39+#define HEXDUMP_OFFSET_FORMAT "%04x"
40+#endif
41+
42+HEXDUMP_INLINE const unsigned char
43+*show_bytes( const unsigned char *dp, int count )
44+{
45+ /* Internal helper function: prints a sequence of up to sixteen
46+ * byte values, as stored contiguously in memory, into a display
47+ * field of fifty character positions; this allows for a display
48+ * of two hexadecimal digits per byte value, with a single space
49+ * separating each value from its predecessor, and two further
50+ * padding spaces, before appending a textual representation
51+ * of the printable bytes within the sequence.
52+ *
53+ * Returns the memory address of the byte immediately following
54+ * the last byte in the displayed sequence.
55+ */
56+ int fw;
57+ for( fw = 50; count-- > 0; fw -= printf( " %02x", *dp++ ) );
58+ while( fw-- > 0 ) putchar( 0x20 );
59+ return dp;
60+}
61+
62+HEXDUMP_INLINE const unsigned char
63+*show_text( const unsigned char *dp, int count )
64+{
65+ /* Internal helper function: prints the textual representation of
66+ * a sequence of up to sixteen contiguous bytes in memory; those
67+ * bytes which represent a printable character are displayed as
68+ * such; all others are replaced by a single '.' for display.
69+ *
70+ * Returns the memory address of the byte immediately following
71+ * the last byte in the displayed sequence.
72+ */
73+ unsigned int c;
74+ while( count-- > 0 ) putchar( isprint( c = *dp++ ) ? c : '.' );
75+ return dp;
76+}
77+
78+HEXDUMP_INLINE const unsigned char
79+*show_hexdump( unsigned offset, const unsigned char *dp, int count )
80+{
81+ /* Internal helper function: combines the effects of show_bytes()
82+ * and show_text() above, to format a single hexdump record for a
83+ * contiguous sequence of up to sixteen bytes in memory; each such
84+ * record is prefixed by a caller specified offset, which is taken
85+ * to represent the offset of the current sequence from the start
86+ * of the data buffer being dumped.
87+ *
88+ * Returns the memory address of the byte immediately following
89+ * the last byte in the displayed sequence.
90+ */
91+ printf( HEXDUMP_OFFSET_FORMAT " ", offset );
92+ dp = show_text( dp, show_bytes( dp, ((count > 16) ? 16 : count) ) - dp );
93+ putchar( '\n' );
94+ return dp;
95+}
96+
97+const void *hexdump( void *data, size_t len )
98+{
99+ /* Entry point for a general purpose hexdump display function.
100+ * Displays the content of a memory buffer of arbitrary length,
101+ * formatting it as a sequence of records of up to sixteen bytes
102+ * each, in conventional hexdump style.
103+ *
104+ * Returns the memory address of the byte immediately following
105+ * the last byte in the specified data buffer region.
106+ */
107+ const void *dp = data, *ep = data + len;
108+ while( dp < ep ) dp = show_hexdump( dp - data, dp, ep - dp );
109+ return dp;
110+}
111+
112+/* $RCSfile$: end of file */
--- /dev/null
+++ b/tmpfile.c
@@ -0,0 +1,61 @@
1+/*
2+ * tmpfile.c
3+ *
4+ * Utility function to create a temporary file, which will be automatically
5+ * deleted when it is closed.
6+ *
7+ * $Id$
8+ *
9+ * Written by Keith Marshall <keithmarshall@users.sourceforge.net>
10+ * Copyright (C) 2014, 2016, MinGW.org Project
11+ *
12+ *
13+ * Permission is hereby granted, free of charge, to any person obtaining a
14+ * copy of this software and associated documentation files (the "Software"),
15+ * to deal in the Software without restriction, including without limitation
16+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
17+ * and/or sell copies of the Software, and to permit persons to whom the
18+ * Software is furnished to do so, subject to the following conditions:
19+ *
20+ * The above copyright notice, this permission notice, and the following
21+ * disclaimer shall be included in all copies or substantial portions of
22+ * the Software.
23+ *
24+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
25+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
26+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
27+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
28+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
29+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OF OR OTHER
30+ * DEALINGS IN THE SOFTWARE.
31+ *
32+ */
33+#include <fcntl.h>
34+#include <stdlib.h>
35+#include <string.h>
36+#include <unistd.h>
37+
38+int tmpfile_create( char *template )
39+{
40+ int fd;
41+
42+ /* Create and open a temporary file, scheduling it for
43+ * automatic deletion on final closure.
44+ */
45+ _MKSTEMP_SETMODE( _O_TEMPORARY );
46+ if( (fd = mkstemp( template )) >= 0 )
47+ {
48+ /* Close a duplicate handle on the opened temporary file,
49+ * to ensure that its directory entry is committed, while
50+ * keeping the original handle open to prevent immediate
51+ * deletion of the file itself.
52+ */
53+ close( dup( fd ));
54+ }
55+ /* Return the handle for the open temporary file, leaving
56+ * the caller to use it as required, and finally close it.
57+ */
58+ return fd;
59+}
60+
61+/* $RCSfile$: end of file */