(root)/
coreutils-9.4/
lib/
uname.c
       1  /* uname replacement.
       2     Copyright (C) 2009-2023 Free Software Foundation, Inc.
       3  
       4     This file is free software: you can redistribute it and/or modify
       5     it under the terms of the GNU Lesser General Public License as
       6     published by the Free Software Foundation; either version 2.1 of the
       7     License, or (at your option) any later version.
       8  
       9     This file 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 Lesser General Public License for more details.
      13  
      14     You should have received a copy of the GNU Lesser General Public License
      15     along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
      16  
      17  #include <config.h>
      18  
      19  /* Specification.  */
      20  #include <sys/utsname.h>
      21  
      22  /* This file provides an implementation only for the native Windows API.  */
      23  #if defined _WIN32 && ! defined __CYGWIN__
      24  
      25  # include <stdio.h>
      26  # include <stdlib.h>
      27  # include <string.h>
      28  # include <unistd.h>
      29  # include <windows.h>
      30  
      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
      35  
      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
      43  
      44  /* Mingw headers don't have the latest processor codes.  */
      45  # ifndef PROCESSOR_AMD_X8664
      46  #  define PROCESSOR_AMD_X8664 8664
      47  # endif
      48  
      49  /* Don't assume that UNICODE is not defined.  */
      50  # undef OSVERSIONINFO
      51  # define OSVERSIONINFO OSVERSIONINFOA
      52  # undef GetVersionEx
      53  # define GetVersionEx GetVersionExA
      54  
      55  int
      56  uname (struct utsname *buf)
      57  {
      58    OSVERSIONINFO version;
      59    OSVERSIONINFOEX versionex;
      60    BOOL have_versionex; /* indicates whether versionex is filled */
      61    const char *super_version;
      62  
      63    /* Preparation: Fill version and, if possible, also versionex.
      64       But try to call GetVersionEx only once in the common case.  */
      65    versionex.dwOSVersionInfoSize = sizeof (OSVERSIONINFOEX);
      66    have_versionex = GetVersionEx ((OSVERSIONINFO *) &versionex);
      67    if (have_versionex)
      68      {
      69        /* We know that OSVERSIONINFO is a subset of OSVERSIONINFOEX.  */
      70        memcpy (&version, &versionex, sizeof (OSVERSIONINFO));
      71      }
      72    else
      73      {
      74        version.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
      75        if (!GetVersionEx (&version))
      76          abort ();
      77      }
      78  
      79    /* Fill in nodename.  */
      80    if (gethostname (buf->nodename, sizeof (buf->nodename)) < 0)
      81      strcpy (buf->nodename, "localhost");
      82  
      83    /* Determine major-major Windows version.  */
      84    if (version.dwPlatformId == VER_PLATFORM_WIN32_NT)
      85      {
      86        /* Windows NT or newer.  */
      87        super_version = "NT";
      88      }
      89    else if (version.dwPlatformId == VER_PLATFORM_WIN32_CE)
      90      {
      91        /* Windows CE or Embedded CE.  */
      92        super_version = "CE";
      93      }
      94    else if (version.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS)
      95      {
      96        /* Windows 95/98/ME.  */
      97        switch (version.dwMinorVersion)
      98          {
      99          case 0:
     100            super_version = "95";
     101            break;
     102          case 10:
     103            super_version = "98";
     104            break;
     105          case 90:
     106            super_version = "ME";
     107            break;
     108          default:
     109            super_version = "";
     110            break;
     111          }
     112      }
     113    else
     114      super_version = "";
     115  
     116    /* Fill in sysname.  */
     117  # ifdef __MINGW32__
     118    /* Returns a string compatible with the MSYS uname.exe program,
     119       so that no further changes are needed to GNU config.guess.
     120       For example,
     121         $ ./uname.exe -s      => MINGW32_NT-5.1
     122     */
     123    sprintf (buf->sysname, "MINGW32_%s-%u.%u", super_version,
     124             (unsigned int) version.dwMajorVersion,
     125             (unsigned int) version.dwMinorVersion);
     126  # else
     127    sprintf (buf->sysname, "Windows%s", super_version);
     128  # endif
     129  
     130    /* Fill in release, version.  */
     131    /* The MSYS uname.exe programs uses strings from a modified Cygwin runtime:
     132         $ ./uname.exe -r      => 1.0.11(0.46/3/2)
     133         $ ./uname.exe -v      => 2008-08-25 23:40
     134       There is no point in imitating this behaviour.  */
     135    if (version.dwPlatformId == VER_PLATFORM_WIN32_NT)
     136      {
     137        /* Windows NT or newer.  */
     138        struct windows_version
     139          {
     140            int major;
     141            int minor;
     142            unsigned int server_offset;
     143            const char *name;
     144          };
     145  
     146        /* Storing the workstation and server version names in a single
     147           stream does not waste memory when they are the same.  These
     148           macros abstract the representation.  VERSION1 is used if
     149           version.wProductType does not matter, VERSION2 if it does.  */
     150        #define VERSION1(major, minor, name) \
     151          { major, minor, 0, name }
     152        #define VERSION2(major, minor, workstation, server) \
     153          { major, minor, sizeof workstation, workstation "\0" server }
     154        static const struct windows_version versions[] =
     155          {
     156            VERSION2 (3, -1, "Windows NT Workstation", "Windows NT Server"),
     157            VERSION2 (4, -1, "Windows NT Workstation", "Windows NT Server"),
     158            VERSION1 (5, 0, "Windows 2000"),
     159            VERSION1 (5, 1, "Windows XP"),
     160            VERSION1 (5, 2, "Windows Server 2003"),
     161            VERSION2 (6, 0, "Windows Vista", "Windows Server 2008"),
     162            VERSION2 (6, 1, "Windows 7", "Windows Server 2008 R2"),
     163            VERSION2 (-1, -1, "Windows", "Windows Server")
     164          };
     165        const char *base;
     166        const struct windows_version *v = versions;
     167  
     168        /* Find a version that matches ours.  The last element is a
     169           wildcard that always ends the loop.  */
     170        while ((v->major != version.dwMajorVersion && v->major != -1)
     171               || (v->minor != version.dwMinorVersion && v->minor != -1))
     172          v++;
     173  
     174        if (have_versionex && versionex.wProductType != VER_NT_WORKSTATION)
     175          base = v->name + v->server_offset;
     176        else
     177          base = v->name;
     178        if (v->major == -1 || v->minor == -1)
     179          sprintf (buf->release, "%s %u.%u",
     180                   base,
     181                   (unsigned int) version.dwMajorVersion,
     182                   (unsigned int) version.dwMinorVersion);
     183        else
     184          strcpy (buf->release, base);
     185      }
     186    else if (version.dwPlatformId == VER_PLATFORM_WIN32_CE)
     187      {
     188        /* Windows CE or Embedded CE.  */
     189        sprintf (buf->release, "Windows CE %u.%u",
     190                 (unsigned int) version.dwMajorVersion,
     191                 (unsigned int) version.dwMinorVersion);
     192      }
     193    else
     194      {
     195        /* Windows 95/98/ME.  */
     196        sprintf (buf->release, "Windows %s", super_version);
     197      }
     198    strcpy (buf->version, version.szCSDVersion);
     199  
     200    /* Fill in machine.  */
     201    {
     202      SYSTEM_INFO info;
     203  
     204      GetSystemInfo (&info);
     205      /* Check for Windows NT or CE, since the info.wProcessorLevel is
     206         garbage on Windows 95. */
     207      if (version.dwPlatformId == VER_PLATFORM_WIN32_NT
     208          || version.dwPlatformId == VER_PLATFORM_WIN32_CE)
     209        {
     210          /* Windows NT or newer, or Windows CE or Embedded CE.  */
     211          switch (info.wProcessorArchitecture)
     212            {
     213            case PROCESSOR_ARCHITECTURE_AMD64:
     214              strcpy (buf->machine, "x86_64");
     215              break;
     216            case PROCESSOR_ARCHITECTURE_IA64:
     217              strcpy (buf->machine, "ia64");
     218              break;
     219            case PROCESSOR_ARCHITECTURE_INTEL:
     220              strcpy (buf->machine, "i386");
     221              if (info.wProcessorLevel >= 3)
     222                buf->machine[1] =
     223                  '0' + (info.wProcessorLevel <= 6 ? info.wProcessorLevel : 6);
     224              break;
     225            case PROCESSOR_ARCHITECTURE_IA32_ON_WIN64:
     226              strcpy (buf->machine, "i686");
     227              break;
     228            case PROCESSOR_ARCHITECTURE_MIPS:
     229              strcpy (buf->machine, "mips");
     230              break;
     231            case PROCESSOR_ARCHITECTURE_ALPHA:
     232            case PROCESSOR_ARCHITECTURE_ALPHA64:
     233              strcpy (buf->machine, "alpha");
     234              break;
     235            case PROCESSOR_ARCHITECTURE_PPC:
     236              strcpy (buf->machine, "powerpc");
     237              break;
     238            case PROCESSOR_ARCHITECTURE_SHX:
     239              strcpy (buf->machine, "sh");
     240              break;
     241            case PROCESSOR_ARCHITECTURE_ARM:
     242              strcpy (buf->machine, "arm");
     243              break;
     244            default:
     245              strcpy (buf->machine, "unknown");
     246              break;
     247            }
     248        }
     249      else
     250        {
     251          /* Windows 95/98/ME.  */
     252          switch (info.dwProcessorType)
     253            {
     254            case PROCESSOR_AMD_X8664:
     255              strcpy (buf->machine, "x86_64");
     256              break;
     257            case PROCESSOR_INTEL_IA64:
     258              strcpy (buf->machine, "ia64");
     259              break;
     260            default:
     261              if (info.dwProcessorType % 100 == 86)
     262                sprintf (buf->machine, "i%u",
     263                         (unsigned int) info.dwProcessorType);
     264              else
     265                strcpy (buf->machine, "unknown");
     266              break;
     267            }
     268        }
     269    }
     270  
     271    return 0;
     272  }
     273  
     274  #endif