sys_stat: Fix 'implicit declaration of function' warning on OS/2 kLIBC.
[gnulib.git] / lib / uname.c
blob54ba27276b27207879f795f166adea484a5a0d98
1 /* uname replacement.
2 Copyright (C) 2009-2019 Free Software Foundation, Inc.
4 This program is free software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 3 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program. If not, see <https://www.gnu.org/licenses/>. */
17 #include <config.h>
19 /* Specification. */
20 #include <sys/utsname.h>
22 /* This file provides an implementation only for the native Windows API. */
23 #if defined _WIN32 && ! defined __CYGWIN__
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <unistd.h>
29 #include <windows.h>
31 /* Mingw headers don't have all the platform codes. */
32 #ifndef VER_PLATFORM_WIN32_CE
33 # define VER_PLATFORM_WIN32_CE 3
34 #endif
36 /* Some headers don't have all the processor architecture codes. */
37 #ifndef PROCESSOR_ARCHITECTURE_AMD64
38 # define PROCESSOR_ARCHITECTURE_AMD64 9
39 #endif
40 #ifndef PROCESSOR_ARCHITECTURE_IA32_ON_WIN64
41 # define PROCESSOR_ARCHITECTURE_IA32_ON_WIN64 10
42 #endif
44 /* Mingw headers don't have the latest processor codes. */
45 #ifndef PROCESSOR_AMD_X8664
46 # define PROCESSOR_AMD_X8664 8664
47 #endif
49 int
50 uname (struct utsname *buf)
52 OSVERSIONINFO version;
53 OSVERSIONINFOEX versionex;
54 BOOL have_versionex; /* indicates whether versionex is filled */
55 const char *super_version;
57 /* Preparation: Fill version and, if possible, also versionex.
58 But try to call GetVersionEx only once in the common case. */
59 versionex.dwOSVersionInfoSize = sizeof (OSVERSIONINFOEX);
60 have_versionex = GetVersionEx ((OSVERSIONINFO *) &versionex);
61 if (have_versionex)
63 /* We know that OSVERSIONINFO is a subset of OSVERSIONINFOEX. */
64 memcpy (&version, &versionex, sizeof (OSVERSIONINFO));
66 else
68 version.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
69 if (!GetVersionEx (&version))
70 abort ();
73 /* Fill in nodename. */
74 if (gethostname (buf->nodename, sizeof (buf->nodename)) < 0)
75 strcpy (buf->nodename, "localhost");
77 /* Determine major-major Windows version. */
78 if (version.dwPlatformId == VER_PLATFORM_WIN32_NT)
80 /* Windows NT or newer. */
81 super_version = "NT";
83 else if (version.dwPlatformId == VER_PLATFORM_WIN32_CE)
85 /* Windows CE or Embedded CE. */
86 super_version = "CE";
88 else if (version.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS)
90 /* Windows 95/98/ME. */
91 switch (version.dwMinorVersion)
93 case 0:
94 super_version = "95";
95 break;
96 case 10:
97 super_version = "98";
98 break;
99 case 90:
100 super_version = "ME";
101 break;
102 default:
103 super_version = "";
104 break;
107 else
108 super_version = "";
110 /* Fill in sysname. */
111 #ifdef __MINGW32__
112 /* Returns a string compatible with the MSYS uname.exe program,
113 so that no further changes are needed to GNU config.guess.
114 For example,
115 $ ./uname.exe -s => MINGW32_NT-5.1
117 sprintf (buf->sysname, "MINGW32_%s-%u.%u", super_version,
118 (unsigned int) version.dwMajorVersion,
119 (unsigned int) version.dwMinorVersion);
120 #else
121 sprintf (buf->sysname, "Windows%s", super_version);
122 #endif
124 /* Fill in release, version. */
125 /* The MSYS uname.exe programs uses strings from a modified Cygwin runtime:
126 $ ./uname.exe -r => 1.0.11(0.46/3/2)
127 $ ./uname.exe -v => 2008-08-25 23:40
128 There is no point in imitating this behaviour. */
129 if (version.dwPlatformId == VER_PLATFORM_WIN32_NT)
131 /* Windows NT or newer. */
132 struct windows_version
134 int major;
135 int minor;
136 unsigned int server_offset;
137 const char *name;
140 /* Storing the workstation and server version names in a single
141 stream does not waste memory when they are the same. These
142 macros abstract the representation. VERSION1 is used if
143 version.wProductType does not matter, VERSION2 if it does. */
144 #define VERSION1(major, minor, name) \
145 { major, minor, 0, name }
146 #define VERSION2(major, minor, workstation, server) \
147 { major, minor, sizeof workstation, workstation "\0" server }
148 static const struct windows_version versions[] =
150 VERSION2 (3, -1, "Windows NT Workstation", "Windows NT Server"),
151 VERSION2 (4, -1, "Windows NT Workstation", "Windows NT Server"),
152 VERSION1 (5, 0, "Windows 2000"),
153 VERSION1 (5, 1, "Windows XP"),
154 VERSION1 (5, 2, "Windows Server 2003"),
155 VERSION2 (6, 0, "Windows Vista", "Windows Server 2008"),
156 VERSION2 (6, 1, "Windows 7", "Windows Server 2008 R2"),
157 VERSION2 (-1, -1, "Windows", "Windows Server")
159 const char *base;
160 const struct windows_version *v = versions;
162 /* Find a version that matches ours. The last element is a
163 wildcard that always ends the loop. */
164 while ((v->major != version.dwMajorVersion && v->major != -1)
165 || (v->minor != version.dwMinorVersion && v->minor != -1))
166 v++;
168 if (have_versionex && versionex.wProductType != VER_NT_WORKSTATION)
169 base = v->name + v->server_offset;
170 else
171 base = v->name;
172 if (v->major == -1 || v->minor == -1)
173 sprintf (buf->release, "%s %u.%u",
174 base,
175 (unsigned int) version.dwMajorVersion,
176 (unsigned int) version.dwMinorVersion);
177 else
178 strcpy (buf->release, base);
180 else if (version.dwPlatformId == VER_PLATFORM_WIN32_CE)
182 /* Windows CE or Embedded CE. */
183 sprintf (buf->release, "Windows CE %u.%u",
184 (unsigned int) version.dwMajorVersion,
185 (unsigned int) version.dwMinorVersion);
187 else
189 /* Windows 95/98/ME. */
190 sprintf (buf->release, "Windows %s", super_version);
192 strcpy (buf->version, version.szCSDVersion);
194 /* Fill in machine. */
196 SYSTEM_INFO info;
198 GetSystemInfo (&info);
199 /* Check for Windows NT or CE, since the info.wProcessorLevel is
200 garbage on Windows 95. */
201 if (version.dwPlatformId == VER_PLATFORM_WIN32_NT
202 || version.dwPlatformId == VER_PLATFORM_WIN32_CE)
204 /* Windows NT or newer, or Windows CE or Embedded CE. */
205 switch (info.wProcessorArchitecture)
207 case PROCESSOR_ARCHITECTURE_AMD64:
208 strcpy (buf->machine, "x86_64");
209 break;
210 case PROCESSOR_ARCHITECTURE_IA64:
211 strcpy (buf->machine, "ia64");
212 break;
213 case PROCESSOR_ARCHITECTURE_INTEL:
214 strcpy (buf->machine, "i386");
215 if (info.wProcessorLevel >= 3)
216 buf->machine[1] =
217 '0' + (info.wProcessorLevel <= 6 ? info.wProcessorLevel : 6);
218 break;
219 case PROCESSOR_ARCHITECTURE_IA32_ON_WIN64:
220 strcpy (buf->machine, "i686");
221 break;
222 case PROCESSOR_ARCHITECTURE_MIPS:
223 strcpy (buf->machine, "mips");
224 break;
225 case PROCESSOR_ARCHITECTURE_ALPHA:
226 case PROCESSOR_ARCHITECTURE_ALPHA64:
227 strcpy (buf->machine, "alpha");
228 break;
229 case PROCESSOR_ARCHITECTURE_PPC:
230 strcpy (buf->machine, "powerpc");
231 break;
232 case PROCESSOR_ARCHITECTURE_SHX:
233 strcpy (buf->machine, "sh");
234 break;
235 case PROCESSOR_ARCHITECTURE_ARM:
236 strcpy (buf->machine, "arm");
237 break;
238 default:
239 strcpy (buf->machine, "unknown");
240 break;
243 else
245 /* Windows 95/98/ME. */
246 switch (info.dwProcessorType)
248 case PROCESSOR_AMD_X8664:
249 strcpy (buf->machine, "x86_64");
250 break;
251 case PROCESSOR_INTEL_IA64:
252 strcpy (buf->machine, "ia64");
253 break;
254 default:
255 if (info.dwProcessorType % 100 == 86)
256 sprintf (buf->machine, "i%u",
257 (unsigned int) info.dwProcessorType);
258 else
259 strcpy (buf->machine, "unknown");
260 break;
265 return 0;
268 #endif