LCOV - code coverage report
Current view: top level - glib/glib - gutils.c (source / functions) Hit Total Coverage
Test: unnamed Lines: 475 642 74.0 %
Date: 2024-04-16 05:15:53 Functions: 47 48 97.9 %
Branches: 206 387 53.2 %

           Branch data     Line data    Source code
       1                 :            : /* GLIB - Library of useful routines for C programming
       2                 :            :  * Copyright (C) 1995-1998  Peter Mattis, Spencer Kimball and Josh MacDonald
       3                 :            :  *
       4                 :            :  * SPDX-License-Identifier: LGPL-2.1-or-later
       5                 :            :  *
       6                 :            :  * This library is free software; you can redistribute it and/or
       7                 :            :  * modify it under the terms of the GNU Lesser General Public
       8                 :            :  * License as published by the Free Software Foundation; either
       9                 :            :  * version 2.1 of the License, or (at your option) any later version.
      10                 :            :  *
      11                 :            :  * This library is distributed in the hope that it will be useful,
      12                 :            :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      13                 :            :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      14                 :            :  * Lesser General Public License for more details.
      15                 :            :  *
      16                 :            :  * You should have received a copy of the GNU Lesser General Public
      17                 :            :  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
      18                 :            :  */
      19                 :            : 
      20                 :            : /*
      21                 :            :  * Modified by the GLib Team and others 1997-2000.  See the AUTHORS
      22                 :            :  * file for a list of people on the GLib Team.  See the ChangeLog
      23                 :            :  * files for a list of changes.  These files are distributed with
      24                 :            :  * GLib at ftp://ftp.gtk.org/pub/gtk/. 
      25                 :            :  */
      26                 :            : 
      27                 :            : /* 
      28                 :            :  * MT safe for the unix part, FIXME: make the win32 part MT safe as well.
      29                 :            :  */
      30                 :            : 
      31                 :            : #include "config.h"
      32                 :            : 
      33                 :            : #include "gutils.h"
      34                 :            : #include "gutilsprivate.h"
      35                 :            : 
      36                 :            : #include <stdarg.h>
      37                 :            : #include <stdlib.h>
      38                 :            : #include <stdio.h>
      39                 :            : #include <locale.h>
      40                 :            : #include <string.h>
      41                 :            : #include <ctype.h>                /* For tolower() */
      42                 :            : #include <errno.h>
      43                 :            : #include <sys/types.h>
      44                 :            : #include <sys/stat.h>
      45                 :            : #ifdef G_OS_UNIX
      46                 :            : #include <pwd.h>
      47                 :            : #include <sys/utsname.h>
      48                 :            : #include <unistd.h>
      49                 :            : #endif
      50                 :            : #include <sys/types.h>
      51                 :            : #ifdef HAVE_SYS_PARAM_H
      52                 :            : #include <sys/param.h>
      53                 :            : #endif
      54                 :            : #ifdef HAVE_CRT_EXTERNS_H 
      55                 :            : #include <crt_externs.h> /* for _NSGetEnviron */
      56                 :            : #endif
      57                 :            : #ifdef HAVE_SYS_AUXV_H
      58                 :            : #include <sys/auxv.h>
      59                 :            : #endif
      60                 :            : 
      61                 :            : #include "glib-init.h"
      62                 :            : #include "glib-private.h"
      63                 :            : #include "genviron.h"
      64                 :            : #include "gfileutils.h"
      65                 :            : #include "ggettext.h"
      66                 :            : #include "ghash.h"
      67                 :            : #include "gthread.h"
      68                 :            : #include "gtestutils.h"
      69                 :            : #include "gunicode.h"
      70                 :            : #include "gstrfuncs.h"
      71                 :            : #include "garray.h"
      72                 :            : #include "glibintl.h"
      73                 :            : #include "gstdio.h"
      74                 :            : #include "gquark.h"
      75                 :            : 
      76                 :            : #ifdef G_PLATFORM_WIN32
      77                 :            : #include "gconvert.h"
      78                 :            : #include "gwin32.h"
      79                 :            : #endif
      80                 :            : 
      81                 :            : 
      82                 :            : #ifdef G_PLATFORM_WIN32
      83                 :            : #  include <windows.h>
      84                 :            : #  ifndef GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS
      85                 :            : #    define GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT 2
      86                 :            : #    define GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS 4
      87                 :            : #  endif
      88                 :            : #  include <lmcons.h>             /* For UNLEN */
      89                 :            : #endif /* G_PLATFORM_WIN32 */
      90                 :            : 
      91                 :            : #ifdef G_OS_WIN32
      92                 :            : #  include <direct.h>
      93                 :            : #  include <shlobj.h>
      94                 :            : #  include <process.h>
      95                 :            : #endif
      96                 :            : 
      97                 :            : #ifdef HAVE_CODESET
      98                 :            : #include <langinfo.h>
      99                 :            : #endif
     100                 :            : 
     101                 :            : /**
     102                 :            :  * g_memmove: 
     103                 :            :  * @dest: the destination address to copy the bytes to.
     104                 :            :  * @src: the source address to copy the bytes from.
     105                 :            :  * @len: the number of bytes to copy.
     106                 :            :  *
     107                 :            :  * Copies a block of memory @len bytes long, from @src to @dest.
     108                 :            :  * The source and destination areas may overlap.
     109                 :            :  *
     110                 :            :  * Deprecated:2.40: Just use memmove().
     111                 :            :  */
     112                 :            : 
     113                 :            : #ifdef G_OS_WIN32
     114                 :            : #undef g_atexit
     115                 :            : #endif
     116                 :            : 
     117                 :            : /**
     118                 :            :  * g_atexit:
     119                 :            :  * @func: (scope async): the function to call on normal program termination.
     120                 :            :  * 
     121                 :            :  * Specifies a function to be called at normal program termination.
     122                 :            :  *
     123                 :            :  * Since GLib 2.8.2, on Windows g_atexit() actually is a preprocessor
     124                 :            :  * macro that maps to a call to the atexit() function in the C
     125                 :            :  * library. This means that in case the code that calls g_atexit(),
     126                 :            :  * i.e. atexit(), is in a DLL, the function will be called when the
     127                 :            :  * DLL is detached from the program. This typically makes more sense
     128                 :            :  * than that the function is called when the GLib DLL is detached,
     129                 :            :  * which happened earlier when g_atexit() was a function in the GLib
     130                 :            :  * DLL.
     131                 :            :  *
     132                 :            :  * The behaviour of atexit() in the context of dynamically loaded
     133                 :            :  * modules is not formally specified and varies wildly.
     134                 :            :  *
     135                 :            :  * On POSIX systems, calling g_atexit() (or atexit()) in a dynamically
     136                 :            :  * loaded module which is unloaded before the program terminates might
     137                 :            :  * well cause a crash at program exit.
     138                 :            :  *
     139                 :            :  * Some POSIX systems implement atexit() like Windows, and have each
     140                 :            :  * dynamically loaded module maintain an own atexit chain that is
     141                 :            :  * called when the module is unloaded.
     142                 :            :  *
     143                 :            :  * On other POSIX systems, before a dynamically loaded module is
     144                 :            :  * unloaded, the registered atexit functions (if any) residing in that
     145                 :            :  * module are called, regardless where the code that registered them
     146                 :            :  * resided. This is presumably the most robust approach.
     147                 :            :  *
     148                 :            :  * As can be seen from the above, for portability it's best to avoid
     149                 :            :  * calling g_atexit() (or atexit()) except in the main executable of a
     150                 :            :  * program.
     151                 :            :  *
     152                 :            :  * Deprecated:2.32: It is best to avoid g_atexit().
     153                 :            :  */
     154                 :            : G_GNUC_BEGIN_IGNORE_DEPRECATIONS
     155                 :            : void
     156                 :          5 : g_atexit (GVoidFunc func)
     157                 :            : {
     158                 :            :   gint result;
     159                 :            :   int errsv;
     160                 :            : 
     161                 :          5 :   result = atexit ((void (*)(void)) func);
     162                 :          5 :   errsv = errno;
     163         [ -  + ]:          5 :   if (result)
     164                 :            :     {
     165                 :          0 :       g_error ("Could not register atexit() function: %s",
     166                 :            :                g_strerror (errsv));
     167                 :            :     }
     168                 :          5 : }
     169                 :            : G_GNUC_END_IGNORE_DEPRECATIONS
     170                 :            : 
     171                 :            : /* Based on execvp() from GNU Libc.
     172                 :            :  * Some of this code is cut-and-pasted into gspawn.c
     173                 :            :  */
     174                 :            : 
     175                 :            : static gchar*
     176                 :       1757 : my_strchrnul (const gchar *str, 
     177                 :            :               gchar        c)
     178                 :            : {
     179                 :       1757 :   gchar *p = (gchar*)str;
     180   [ +  +  +  + ]:      33013 :   while (*p && (*p != c))
     181                 :      31256 :     ++p;
     182                 :            : 
     183                 :       1757 :   return p;
     184                 :            : }
     185                 :            : 
     186                 :            : #ifdef G_OS_WIN32
     187                 :            : 
     188                 :            : static gchar *inner_find_program_in_path (const gchar *program);
     189                 :            : 
     190                 :            : gchar*
     191                 :            : g_find_program_in_path (const gchar *program)
     192                 :            : {
     193                 :            :   const gchar *last_dot = strrchr (program, '.');
     194                 :            : 
     195                 :            :   if (last_dot == NULL ||
     196                 :            :       strchr (last_dot, '\\') != NULL ||
     197                 :            :       strchr (last_dot, '/') != NULL)
     198                 :            :     {
     199                 :            :       const gint program_length = strlen (program);
     200                 :            :       gchar *pathext = g_build_path (";",
     201                 :            :                                      ".exe;.cmd;.bat;.com",
     202                 :            :                                      g_getenv ("PATHEXT"),
     203                 :            :                                      NULL);
     204                 :            :       gchar *p;
     205                 :            :       gchar *decorated_program;
     206                 :            :       gchar *retval;
     207                 :            : 
     208                 :            :       p = pathext;
     209                 :            :       do
     210                 :            :         {
     211                 :            :           gchar *q = my_strchrnul (p, ';');
     212                 :            : 
     213                 :            :           decorated_program = g_malloc (program_length + (q-p) + 1);
     214                 :            :           memcpy (decorated_program, program, program_length);
     215                 :            :           memcpy (decorated_program+program_length, p, q-p);
     216                 :            :           decorated_program [program_length + (q-p)] = '\0';
     217                 :            :           
     218                 :            :           retval = inner_find_program_in_path (decorated_program);
     219                 :            :           g_free (decorated_program);
     220                 :            : 
     221                 :            :           if (retval != NULL)
     222                 :            :             {
     223                 :            :               g_free (pathext);
     224                 :            :               return retval;
     225                 :            :             }
     226                 :            :           p = q;
     227                 :            :         } while (*p++ != '\0');
     228                 :            :       g_free (pathext);
     229                 :            :       return NULL;
     230                 :            :     }
     231                 :            :   else
     232                 :            :     return inner_find_program_in_path (program);
     233                 :            : }
     234                 :            : 
     235                 :            : #endif
     236                 :            : 
     237                 :            : /**
     238                 :            :  * g_find_program_in_path:
     239                 :            :  * @program: (type filename): a program name in the GLib file name encoding
     240                 :            :  * 
     241                 :            :  * Locates the first executable named @program in the user's path, in the
     242                 :            :  * same way that execvp() would locate it. Returns an allocated string
     243                 :            :  * with the absolute path name, or %NULL if the program is not found in
     244                 :            :  * the path. If @program is already an absolute path, returns a copy of
     245                 :            :  * @program if @program exists and is executable, and %NULL otherwise.
     246                 :            :  *  
     247                 :            :  * On Windows, if @program does not have a file type suffix, tries
     248                 :            :  * with the suffixes .exe, .cmd, .bat and .com, and the suffixes in
     249                 :            :  * the `PATHEXT` environment variable. 
     250                 :            :  * 
     251                 :            :  * On Windows, it looks for the file in the same way as CreateProcess() 
     252                 :            :  * would. This means first in the directory where the executing
     253                 :            :  * program was loaded from, then in the current directory, then in the
     254                 :            :  * Windows 32-bit system directory, then in the Windows directory, and
     255                 :            :  * finally in the directories in the `PATH` environment variable. If
     256                 :            :  * the program is found, the return value contains the full name
     257                 :            :  * including the type suffix.
     258                 :            :  *
     259                 :            :  * Returns: (type filename) (transfer full) (nullable): a newly-allocated
     260                 :            :  *   string with the absolute path, or %NULL
     261                 :            :  **/
     262                 :            : #ifdef G_OS_WIN32
     263                 :            : static gchar *
     264                 :            : inner_find_program_in_path (const gchar *program)
     265                 :            : #else
     266                 :            : gchar*
     267                 :        109 : g_find_program_in_path (const gchar *program)
     268                 :            : #endif
     269                 :            : {
     270                 :        109 :   return g_find_program_for_path (program, NULL, NULL);
     271                 :            : }
     272                 :            : 
     273                 :            : /**
     274                 :            :  * g_find_program_for_path:
     275                 :            :  * @program: (type filename): a program name in the GLib file name encoding
     276                 :            :  * @path: (type filename) (nullable): the current dir where to search program
     277                 :            :  * @working_dir: (type filename) (nullable): the working dir where to search
     278                 :            :  *   program
     279                 :            :  *
     280                 :            :  * Locates the first executable named @program in @path, in the
     281                 :            :  * same way that execvp() would locate it. Returns an allocated string
     282                 :            :  * with the absolute path name (taking in account the @working_dir), or
     283                 :            :  * %NULL if the program is not found in @path. If @program is already an
     284                 :            :  * absolute path, returns a copy of @program if @program exists and is
     285                 :            :  * executable, and %NULL otherwise.
     286                 :            :  *
     287                 :            :  * On Windows, if @path is %NULL, it looks for the file in the same way as
     288                 :            :  * CreateProcess()  would. This means first in the directory where the
     289                 :            :  * executing program was loaded from, then in the current directory, then in
     290                 :            :  * the Windows 32-bit system directory, then in the Windows directory, and
     291                 :            :  * finally in the directories in the `PATH` environment variable. If
     292                 :            :  * the program is found, the return value contains the full name
     293                 :            :  * including the type suffix.
     294                 :            :  *
     295                 :            :  * Returns: (type filename) (transfer full) (nullable): a newly-allocated
     296                 :            :  *   string with the absolute path, or %NULL
     297                 :            :  * Since: 2.76
     298                 :            :  **/
     299                 :            : char *
     300                 :        863 : g_find_program_for_path (const char *program,
     301                 :            :                          const char *path,
     302                 :            :                          const char *working_dir)
     303                 :            : {
     304                 :        863 :   const char *original_path = path;
     305                 :        863 :   const char *original_program = program;
     306                 :        863 :   char *program_path = NULL;
     307                 :            :   const gchar *p;
     308                 :            :   gchar *name, *freeme;
     309                 :            : #ifdef G_OS_WIN32
     310                 :            :   const gchar *path_copy;
     311                 :            :   gchar *filename = NULL, *appdir = NULL;
     312                 :            :   gchar *sysdir = NULL, *windir = NULL;
     313                 :            :   int n;
     314                 :            :   wchar_t wfilename[MAXPATHLEN], wsysdir[MAXPATHLEN],
     315                 :            :     wwindir[MAXPATHLEN];
     316                 :            : #endif
     317                 :            :   gsize len;
     318                 :            :   gsize pathlen;
     319                 :            : 
     320                 :        863 :   g_return_val_if_fail (program != NULL, NULL);
     321                 :            : 
     322                 :            :   /* Use the working dir as program path if provided */
     323   [ +  +  +  - ]:        863 :   if (working_dir && !g_path_is_absolute (program))
     324                 :            :     {
     325                 :        218 :       program_path = g_build_filename (working_dir, program, NULL);
     326                 :        218 :       program = program_path;
     327                 :            :     }
     328                 :            : 
     329                 :            :   /* If it is an absolute path, or a relative path including subdirectories,
     330                 :            :    * don't look in PATH.
     331                 :            :    */
     332         [ +  + ]:        863 :   if (g_path_is_absolute (program)
     333         [ +  + ]:        628 :       || strchr (original_program, G_DIR_SEPARATOR) != NULL
     334                 :            : #ifdef G_OS_WIN32
     335                 :            :       || strchr (original_program, '/') != NULL
     336                 :            : #endif
     337                 :            :       )
     338                 :            :     {
     339   [ +  +  +  + ]:        309 :       if (g_file_test (program, G_FILE_TEST_IS_EXECUTABLE) &&
     340                 :         69 :           !g_file_test (program, G_FILE_TEST_IS_DIR))
     341                 :            :         {
     342                 :         64 :           gchar *out = NULL;
     343                 :            : 
     344         [ +  + ]:         64 :           if (g_path_is_absolute (program))
     345                 :            :             {
     346                 :         59 :               out = g_strdup (program);
     347                 :            :             }
     348                 :            :           else
     349                 :            :             {
     350                 :          5 :               char *cwd = g_get_current_dir ();
     351                 :          5 :               out = g_build_filename (cwd, program, NULL);
     352                 :          5 :               g_free (cwd);
     353                 :            :             }
     354                 :            : 
     355                 :         64 :           g_free (program_path);
     356                 :            : 
     357                 :         64 :           return g_steal_pointer (&out);
     358                 :            :         }
     359                 :            :       else
     360                 :            :         {
     361                 :        176 :           g_clear_pointer (&program_path, g_free);
     362                 :            : 
     363         [ +  + ]:        176 :           if (g_path_is_absolute (original_program))
     364                 :         12 :             return NULL;
     365                 :            :         }
     366                 :            :     }
     367                 :            : 
     368                 :        787 :   program = original_program;
     369                 :            : 
     370         [ +  + ]:        787 :   if G_LIKELY (original_path == NULL)
     371                 :        284 :     path = g_getenv ("PATH");
     372                 :            :   else
     373                 :        503 :     path = original_path;
     374                 :            : 
     375                 :            : #if defined(G_OS_UNIX)
     376         [ -  + ]:        787 :   if (path == NULL)
     377                 :            :     {
     378                 :            :       /* There is no 'PATH' in the environment.  The default
     379                 :            :        * search path in GNU libc is the current directory followed by
     380                 :            :        * the path 'confstr' returns for '_CS_PATH'.
     381                 :            :        */
     382                 :            :       
     383                 :            :       /* In GLib we put . last, for security, and don't use the
     384                 :            :        * unportable confstr(); UNIX98 does not actually specify
     385                 :            :        * what to search if PATH is unset. POSIX may, dunno.
     386                 :            :        */
     387                 :            :       
     388                 :          0 :       path = "/bin:/usr/bin:.";
     389                 :            :     }
     390                 :            : #else
     391                 :            :   if G_LIKELY (original_path == NULL)
     392                 :            :     {
     393                 :            :       n = GetModuleFileNameW (NULL, wfilename, MAXPATHLEN);
     394                 :            :       if (n > 0 && n < MAXPATHLEN)
     395                 :            :         filename = g_utf16_to_utf8 (wfilename, -1, NULL, NULL, NULL);
     396                 :            : 
     397                 :            :       n = GetSystemDirectoryW (wsysdir, MAXPATHLEN);
     398                 :            :       if (n > 0 && n < MAXPATHLEN)
     399                 :            :         sysdir = g_utf16_to_utf8 (wsysdir, -1, NULL, NULL, NULL);
     400                 :            : 
     401                 :            :       n = GetWindowsDirectoryW (wwindir, MAXPATHLEN);
     402                 :            :       if (n > 0 && n < MAXPATHLEN)
     403                 :            :         windir = g_utf16_to_utf8 (wwindir, -1, NULL, NULL, NULL);
     404                 :            : 
     405                 :            :       if (filename)
     406                 :            :         {
     407                 :            :           appdir = g_path_get_dirname (filename);
     408                 :            :           g_free (filename);
     409                 :            :         }
     410                 :            : 
     411                 :            :       path = g_strdup (path);
     412                 :            : 
     413                 :            :       if (windir)
     414                 :            :         {
     415                 :            :           const gchar *tem = path;
     416                 :            :           path = g_strconcat (windir, ";", path, NULL);
     417                 :            :           g_free ((gchar *) tem);
     418                 :            :           g_free (windir);
     419                 :            :         }
     420                 :            : 
     421                 :            :       if (sysdir)
     422                 :            :         {
     423                 :            :           const gchar *tem = path;
     424                 :            :           path = g_strconcat (sysdir, ";", path, NULL);
     425                 :            :           g_free ((gchar *) tem);
     426                 :            :           g_free (sysdir);
     427                 :            :         }
     428                 :            : 
     429                 :            :       {
     430                 :            :         const gchar *tem = path;
     431                 :            :         path = g_strconcat (".;", path, NULL);
     432                 :            :         g_free ((gchar *) tem);
     433                 :            :       }
     434                 :            : 
     435                 :            :       if (appdir)
     436                 :            :         {
     437                 :            :           const gchar *tem = path;
     438                 :            :           path = g_strconcat (appdir, ";", path, NULL);
     439                 :            :           g_free ((gchar *) tem);
     440                 :            :           g_free (appdir);
     441                 :            :         }
     442                 :            : 
     443                 :            :       path_copy = path;
     444                 :            :     }
     445                 :            :   else
     446                 :            :     {
     447                 :            :       path_copy = g_strdup (path);
     448                 :            :     }
     449                 :            : 
     450                 :            : #endif
     451                 :            :   
     452                 :        787 :   len = strlen (program) + 1;
     453                 :        787 :   pathlen = strlen (path);
     454                 :        787 :   freeme = name = g_malloc (pathlen + len + 1);
     455                 :            :   
     456                 :            :   /* Copy the file name at the top, including '\0'  */
     457                 :        787 :   memcpy (name + pathlen + 1, program, len);
     458                 :        787 :   name = name + pathlen;
     459                 :            :   /* And add the slash before the filename  */
     460                 :        787 :   *name = G_DIR_SEPARATOR;
     461                 :            :   
     462                 :        787 :   p = path;
     463                 :            :   do
     464                 :            :     {
     465                 :            :       char *startp;
     466                 :       1757 :       char *startp_path = NULL;
     467                 :            : 
     468                 :       1757 :       path = p;
     469                 :       1757 :       p = my_strchrnul (path, G_SEARCHPATH_SEPARATOR);
     470                 :            : 
     471         [ +  + ]:       1757 :       if (p == path)
     472                 :            :         /* Two adjacent colons, or a colon at the beginning or the end
     473                 :            :          * of 'PATH' means to search the current directory.
     474                 :            :          */
     475                 :         40 :         startp = name + 1;
     476                 :            :       else
     477                 :       1717 :         startp = memcpy (name - (p - path), path, p - path);
     478                 :            : 
     479                 :            :       /* Use the working dir as program path if provided */
     480   [ +  +  +  + ]:       1757 :       if (working_dir && !g_path_is_absolute (startp))
     481                 :            :         {
     482                 :         55 :           startp_path = g_build_filename (working_dir, startp, NULL);
     483                 :         55 :           startp = startp_path;
     484                 :            :         }
     485                 :            : 
     486   [ +  +  +  - ]:       2095 :       if (g_file_test (startp, G_FILE_TEST_IS_EXECUTABLE) &&
     487                 :        338 :           !g_file_test (startp, G_FILE_TEST_IS_DIR))
     488                 :            :         {
     489                 :            :           gchar *ret;
     490         [ +  + ]:        338 :           if (g_path_is_absolute (startp)) {
     491                 :        323 :             ret = g_strdup (startp);
     492                 :            :           } else {
     493                 :         15 :             gchar *cwd = NULL;
     494                 :         15 :             cwd = g_get_current_dir ();
     495                 :         15 :             ret = g_build_filename (cwd, startp, NULL);
     496                 :         15 :             g_free (cwd);
     497                 :            :           }
     498                 :            : 
     499                 :        338 :           g_free (program_path);
     500                 :        338 :           g_free (startp_path);
     501                 :        338 :           g_free (freeme);
     502                 :            : #ifdef G_OS_WIN32
     503                 :            :           g_free ((gchar *) path_copy);
     504                 :            : #endif
     505                 :        338 :           return ret;
     506                 :            :         }
     507                 :            : 
     508                 :       1419 :       g_free (startp_path);
     509                 :            :     }
     510         [ +  + ]:       1419 :   while (*p++ != '\0');
     511                 :            : 
     512                 :        449 :   g_free (program_path);
     513                 :        449 :   g_free (freeme);
     514                 :            : #ifdef G_OS_WIN32
     515                 :            :   g_free ((gchar *) path_copy);
     516                 :            : #endif
     517                 :            : 
     518                 :        449 :   return NULL;
     519                 :            : }
     520                 :            : 
     521                 :            : /* The functions below are defined this way for compatibility reasons.
     522                 :            :  * See the note in gutils.h.
     523                 :            :  */
     524                 :            : 
     525                 :            : /**
     526                 :            :  * g_bit_nth_lsf:
     527                 :            :  * @mask: a #gulong containing flags
     528                 :            :  * @nth_bit: the index of the bit to start the search from
     529                 :            :  *
     530                 :            :  * Find the position of the first bit set in @mask, searching
     531                 :            :  * from (but not including) @nth_bit upwards. Bits are numbered
     532                 :            :  * from 0 (least significant) to sizeof(#gulong) * 8 - 1 (31 or 63,
     533                 :            :  * usually). To start searching from the 0th bit, set @nth_bit to -1.
     534                 :            :  *
     535                 :            :  * Returns: the index of the first bit set which is higher than @nth_bit, or -1
     536                 :            :  *    if no higher bits are set
     537                 :            :  */
     538                 :            : gint
     539                 :    1050000 : (g_bit_nth_lsf) (gulong mask,
     540                 :            :                  gint   nth_bit)
     541                 :            : {
     542                 :    1050000 :   return g_bit_nth_lsf_impl (mask, nth_bit);
     543                 :            : }
     544                 :            : 
     545                 :            : /**
     546                 :            :  * g_bit_nth_msf:
     547                 :            :  * @mask: a #gulong containing flags
     548                 :            :  * @nth_bit: the index of the bit to start the search from
     549                 :            :  *
     550                 :            :  * Find the position of the first bit set in @mask, searching
     551                 :            :  * from (but not including) @nth_bit downwards. Bits are numbered
     552                 :            :  * from 0 (least significant) to sizeof(#gulong) * 8 - 1 (31 or 63,
     553                 :            :  * usually). To start searching from the last bit, set @nth_bit to
     554                 :            :  * -1 or GLIB_SIZEOF_LONG * 8.
     555                 :            :  *
     556                 :            :  * Returns: the index of the first bit set which is lower than @nth_bit, or -1
     557                 :            :  *    if no lower bits are set
     558                 :            :  */
     559                 :            : gint
     560                 :    1050000 : (g_bit_nth_msf) (gulong mask,
     561                 :            :                  gint   nth_bit)
     562                 :            : {
     563                 :    1050000 :   return g_bit_nth_msf_impl (mask, nth_bit);
     564                 :            : }
     565                 :            : 
     566                 :            : 
     567                 :            : /**
     568                 :            :  * g_bit_storage:
     569                 :            :  * @number: a #guint
     570                 :            :  *
     571                 :            :  * Gets the number of bits used to hold @number,
     572                 :            :  * e.g. if @number is 4, 3 bits are needed.
     573                 :            :  *
     574                 :            :  * Returns: the number of bits used to hold @number
     575                 :            :  */
     576                 :            : guint
     577                 :      15000 : (g_bit_storage) (gulong number)
     578                 :            : {
     579                 :      15000 :   return g_bit_storage_impl (number);
     580                 :            : }
     581                 :            : 
     582                 :            : G_LOCK_DEFINE_STATIC (g_utils_global);
     583                 :            : 
     584                 :            : typedef struct
     585                 :            : {
     586                 :            :   gchar *user_name;
     587                 :            :   gchar *real_name;
     588                 :            :   gchar *home_dir;
     589                 :            : } UserDatabaseEntry;
     590                 :            : 
     591                 :            : /* These must all be read/written with @g_utils_global held. */
     592                 :            : static  gchar   *g_user_data_dir = NULL;
     593                 :            : static  gchar  **g_system_data_dirs = NULL;
     594                 :            : static  gchar   *g_user_cache_dir = NULL;
     595                 :            : static  gchar   *g_user_config_dir = NULL;
     596                 :            : static  gchar   *g_user_state_dir = NULL;
     597                 :            : static  gchar   *g_user_runtime_dir = NULL;
     598                 :            : static  gchar  **g_system_config_dirs = NULL;
     599                 :            : static  gchar  **g_user_special_dirs = NULL;
     600                 :            : static  gchar   *g_tmp_dir = NULL;
     601                 :            : 
     602                 :            : /* fifteen minutes of fame for everybody */
     603                 :            : #define G_USER_DIRS_EXPIRE      15 * 60
     604                 :            : 
     605                 :            : #ifdef G_OS_WIN32
     606                 :            : 
     607                 :            : static gchar *
     608                 :            : get_special_folder (REFKNOWNFOLDERID known_folder_guid_ptr)
     609                 :            : {
     610                 :            :   wchar_t *wcp = NULL;
     611                 :            :   gchar *result = NULL;
     612                 :            :   HRESULT hr;
     613                 :            : 
     614                 :            :   hr = SHGetKnownFolderPath (known_folder_guid_ptr, 0, NULL, &wcp);
     615                 :            : 
     616                 :            :   if (SUCCEEDED (hr))
     617                 :            :     result = g_utf16_to_utf8 (wcp, -1, NULL, NULL, NULL);
     618                 :            : 
     619                 :            :   CoTaskMemFree (wcp);
     620                 :            : 
     621                 :            :   return result;
     622                 :            : }
     623                 :            : 
     624                 :            : static char *
     625                 :            : get_windows_directory_root (void)
     626                 :            : {
     627                 :            :   wchar_t wwindowsdir[MAX_PATH];
     628                 :            : 
     629                 :            :   if (GetWindowsDirectoryW (wwindowsdir, G_N_ELEMENTS (wwindowsdir)))
     630                 :            :     {
     631                 :            :       /* Usually X:\Windows, but in terminal server environments
     632                 :            :        * might be an UNC path, AFAIK.
     633                 :            :        */
     634                 :            :       char *windowsdir = g_utf16_to_utf8 (wwindowsdir, -1, NULL, NULL, NULL);
     635                 :            :       char *p;
     636                 :            : 
     637                 :            :       if (windowsdir == NULL)
     638                 :            :         return g_strdup ("C:\\");
     639                 :            : 
     640                 :            :       p = (char *) g_path_skip_root (windowsdir);
     641                 :            :       if (G_IS_DIR_SEPARATOR (p[-1]) && p[-2] != ':')
     642                 :            :         p--;
     643                 :            :       *p = '\0';
     644                 :            :       return windowsdir;
     645                 :            :     }
     646                 :            :   else
     647                 :            :     return g_strdup ("C:\\");
     648                 :            : }
     649                 :            : 
     650                 :            : #endif
     651                 :            : 
     652                 :            : /* HOLDS: g_utils_global_lock */
     653                 :            : static UserDatabaseEntry *
     654                 :         12 : g_get_user_database_entry (void)
     655                 :            : {
     656                 :            :   static UserDatabaseEntry *entry;
     657                 :            : 
     658   [ +  +  +  -  :         12 :   if (g_once_init_enter_pointer (&entry))
                   +  + ]
     659                 :            :     {
     660                 :            :       static UserDatabaseEntry e;
     661                 :            : 
     662                 :            : #ifdef G_OS_UNIX
     663                 :            :       {
     664                 :          6 :         struct passwd *pw = NULL;
     665                 :          6 :         gpointer buffer = NULL;
     666                 :            :         gint error;
     667                 :            :         const char *logname;
     668                 :            : 
     669                 :            : #  if defined (HAVE_GETPWUID_R)
     670                 :            :         struct passwd pwd;
     671                 :            : #    ifdef _SC_GETPW_R_SIZE_MAX
     672                 :            :         /* This returns the maximum length */
     673                 :          6 :         glong bufsize = sysconf (_SC_GETPW_R_SIZE_MAX);
     674                 :            : 
     675         [ -  + ]:          6 :         if (bufsize < 0)
     676                 :          0 :           bufsize = 64;
     677                 :            : #    else /* _SC_GETPW_R_SIZE_MAX */
     678                 :            :         glong bufsize = 64;
     679                 :            : #    endif /* _SC_GETPW_R_SIZE_MAX */
     680                 :            : 
     681                 :          6 :         logname = g_getenv ("LOGNAME");
     682                 :            : 
     683                 :            :         do
     684                 :            :           {
     685                 :          6 :             g_free (buffer);
     686                 :            :             /* we allocate 6 extra bytes to work around a bug in
     687                 :            :              * Mac OS < 10.3. See #156446
     688                 :            :              */
     689                 :          6 :             buffer = g_malloc (bufsize + 6);
     690                 :          6 :             errno = 0;
     691                 :            : 
     692         [ -  + ]:          6 :             if (logname) {
     693                 :          0 :               error = getpwnam_r (logname, &pwd, buffer, bufsize, &pw);
     694   [ #  #  #  # ]:          0 :               if (!pw || (pw->pw_uid != getuid ())) {
     695                 :            :                 /* LOGNAME is lying, fall back to looking up the uid */
     696                 :          0 :                 error = getpwuid_r (getuid (), &pwd, buffer, bufsize, &pw);
     697                 :            :               }
     698                 :            :             } else {
     699                 :          6 :               error = getpwuid_r (getuid (), &pwd, buffer, bufsize, &pw);
     700                 :            :             }
     701         [ -  + ]:          6 :             error = error < 0 ? errno : error;
     702                 :            : 
     703         [ -  + ]:          6 :             if (!pw)
     704                 :            :               {
     705                 :            :                 /* we bail out prematurely if the user id can't be found
     706                 :            :                  * (should be pretty rare case actually), or if the buffer
     707                 :            :                  * should be sufficiently big and lookups are still not
     708                 :            :                  * successful.
     709                 :            :                  */
     710   [ #  #  #  # ]:          0 :                 if (error == 0 || error == ENOENT)
     711                 :            :                   {
     712                 :          0 :                     g_warning ("getpwuid_r(): failed due to unknown user id (%lu)",
     713                 :            :                                (gulong) getuid ());
     714                 :          0 :                     break;
     715                 :            :                   }
     716         [ #  # ]:          0 :                 if (bufsize > 32 * 1024)
     717                 :            :                   {
     718                 :          0 :                     g_warning ("getpwuid_r(): failed due to: %s.",
     719                 :            :                                g_strerror (error));
     720                 :          0 :                     break;
     721                 :            :                   }
     722                 :            : 
     723                 :          0 :                 bufsize *= 2;
     724                 :            :               }
     725                 :            :           }
     726         [ -  + ]:          6 :         while (!pw);
     727                 :            : #  endif /* HAVE_GETPWUID_R */
     728                 :            : 
     729         [ -  + ]:          6 :         if (!pw)
     730                 :            :           {
     731                 :          0 :             pw = getpwuid (getuid ());
     732                 :            :           }
     733         [ +  - ]:          6 :         if (pw)
     734                 :            :           {
     735                 :          6 :             e.user_name = g_strdup (pw->pw_name);
     736                 :            : 
     737                 :            : #ifndef __BIONIC__
     738   [ +  -  -  +  :          6 :             if (pw->pw_gecos && *pw->pw_gecos != '\0' && pw->pw_name)
                   -  - ]
     739                 :            :               {
     740                 :            :                 gchar **gecos_fields;
     741                 :            :                 gchar **name_parts;
     742                 :            :                 gchar *uppercase_pw_name;
     743                 :            : 
     744                 :            :                 /* split the gecos field and substitute '&' */
     745                 :          0 :                 gecos_fields = g_strsplit (pw->pw_gecos, ",", 0);
     746                 :          0 :                 name_parts = g_strsplit (gecos_fields[0], "&", 0);
     747                 :          0 :                 uppercase_pw_name = g_strdup (pw->pw_name);
     748                 :          0 :                 uppercase_pw_name[0] = g_ascii_toupper (uppercase_pw_name[0]);
     749                 :          0 :                 e.real_name = g_strjoinv (uppercase_pw_name, name_parts);
     750                 :          0 :                 g_strfreev (gecos_fields);
     751                 :          0 :                 g_strfreev (name_parts);
     752                 :          0 :                 g_free (uppercase_pw_name);
     753                 :            :               }
     754                 :            : #endif
     755                 :            : 
     756         [ +  - ]:          6 :             if (!e.home_dir)
     757                 :         12 :               e.home_dir = g_strdup (pw->pw_dir);
     758                 :            :           }
     759                 :          6 :         g_free (buffer);
     760                 :            :       }
     761                 :            : 
     762                 :            : #endif /* G_OS_UNIX */
     763                 :            : 
     764                 :            : #ifdef G_OS_WIN32
     765                 :            :       {
     766                 :            :         guint len = UNLEN+1;
     767                 :            :         wchar_t buffer[UNLEN+1];
     768                 :            : 
     769                 :            :         if (GetUserNameW (buffer, (LPDWORD) &len))
     770                 :            :           {
     771                 :            :             e.user_name = g_utf16_to_utf8 (buffer, -1, NULL, NULL, NULL);
     772                 :            :             e.real_name = g_strdup (e.user_name);
     773                 :            :           }
     774                 :            :       }
     775                 :            : #endif /* G_OS_WIN32 */
     776                 :            : 
     777         [ +  + ]:          6 :       if (!e.user_name)
     778                 :          1 :         e.user_name = g_strdup ("somebody");
     779         [ +  - ]:          6 :       if (!e.real_name)
     780                 :          6 :         e.real_name = g_strdup ("Unknown");
     781                 :            : 
     782                 :          6 :       g_once_init_leave_pointer (&entry, &e);
     783                 :            :     }
     784                 :            : 
     785                 :         12 :   return entry;
     786                 :            : }
     787                 :            : 
     788                 :            : /**
     789                 :            :  * g_get_user_name:
     790                 :            :  *
     791                 :            :  * Gets the user name of the current user. The encoding of the returned
     792                 :            :  * string is system-defined. On UNIX, it might be the preferred file name
     793                 :            :  * encoding, or something else, and there is no guarantee that it is even
     794                 :            :  * consistent on a machine. On Windows, it is always UTF-8.
     795                 :            :  *
     796                 :            :  * Returns: (type filename) (transfer none): the user name of the current user.
     797                 :            :  */
     798                 :            : const gchar *
     799                 :          6 : g_get_user_name (void)
     800                 :            : {
     801                 :            :   UserDatabaseEntry *entry;
     802                 :            : 
     803                 :          6 :   entry = g_get_user_database_entry ();
     804                 :            : 
     805                 :          6 :   return entry->user_name;
     806                 :            : }
     807                 :            : 
     808                 :            : /**
     809                 :            :  * g_get_real_name:
     810                 :            :  *
     811                 :            :  * Gets the real name of the user. This usually comes from the user's
     812                 :            :  * entry in the `passwd` file. The encoding of the returned string is
     813                 :            :  * system-defined. (On Windows, it is, however, always UTF-8.) If the
     814                 :            :  * real user name cannot be determined, the string "Unknown" is 
     815                 :            :  * returned.
     816                 :            :  *
     817                 :            :  * Returns: (type filename) (transfer none): the user's real name.
     818                 :            :  */
     819                 :            : const gchar *
     820                 :          6 : g_get_real_name (void)
     821                 :            : {
     822                 :            :   UserDatabaseEntry *entry;
     823                 :            : 
     824                 :          6 :   entry = g_get_user_database_entry ();
     825                 :            : 
     826                 :          6 :   return entry->real_name;
     827                 :            : }
     828                 :            : 
     829                 :            : /* Protected by @g_utils_global_lock. */
     830                 :            : static gchar *g_home_dir = NULL;  /* (owned) (nullable before initialised) */
     831                 :            : 
     832                 :            : static gchar *
     833                 :        114 : g_build_home_dir (void)
     834                 :            : {
     835                 :            :   gchar *home_dir;
     836                 :            : 
     837                 :            :   /* We first check HOME and use it if it is set */
     838                 :        114 :   home_dir = g_strdup (g_getenv ("HOME"));
     839                 :            : 
     840                 :            : #ifdef G_OS_WIN32
     841                 :            :   /* Only believe HOME if it is an absolute path and exists.
     842                 :            :    *
     843                 :            :    * We only do this check on Windows for a couple of reasons.
     844                 :            :    * Historically, we only did it there because we used to ignore $HOME
     845                 :            :    * on UNIX.  There are concerns about enabling it now on UNIX because
     846                 :            :    * of things like autofs.  In short, if the user has a bogus value in
     847                 :            :    * $HOME then they get what they pay for...
     848                 :            :    */
     849                 :            :   if (home_dir != NULL)
     850                 :            :     {
     851                 :            :       if (!(g_path_is_absolute (home_dir) &&
     852                 :            :             g_file_test (home_dir, G_FILE_TEST_IS_DIR)))
     853                 :            :         g_clear_pointer (&home_dir, g_free);
     854                 :            :     }
     855                 :            : 
     856                 :            :   /* In case HOME is Unix-style (it happens), convert it to
     857                 :            :    * Windows style.
     858                 :            :    */
     859                 :            :   if (home_dir != NULL)
     860                 :            :     {
     861                 :            :       gchar *p;
     862                 :            :       while ((p = strchr (home_dir, '/')) != NULL)
     863                 :            :         *p = '\\';
     864                 :            :     }
     865                 :            : 
     866                 :            :   if (home_dir == NULL)
     867                 :            :     {
     868                 :            :       /* USERPROFILE is probably the closest equivalent to $HOME? */
     869                 :            :       if (g_getenv ("USERPROFILE") != NULL)
     870                 :            :         home_dir = g_strdup (g_getenv ("USERPROFILE"));
     871                 :            :     }
     872                 :            : 
     873                 :            :   if (home_dir == NULL)
     874                 :            :     home_dir = get_special_folder (&FOLDERID_Profile);
     875                 :            : 
     876                 :            :   if (home_dir == NULL)
     877                 :            :     home_dir = get_windows_directory_root ();
     878                 :            : #endif /* G_OS_WIN32 */
     879                 :            : 
     880         [ -  + ]:        114 :   if (home_dir == NULL)
     881                 :            :     {
     882                 :            :       /* If we didn't get it from any of those methods, we will have
     883                 :            :        * to read the user database entry.
     884                 :            :        */
     885                 :          0 :       UserDatabaseEntry *entry = g_get_user_database_entry ();
     886                 :          0 :       home_dir = g_strdup (entry->home_dir);
     887                 :            :     }
     888                 :            : 
     889                 :            :   /* If we have been denied access to /etc/passwd (for example, by an
     890                 :            :    * overly-zealous LSM), make up a junk value. The return value at this
     891                 :            :    * point is explicitly documented as ‘undefined’. */
     892         [ -  + ]:        114 :   if (home_dir == NULL)
     893                 :            :     {
     894                 :          0 :       g_warning ("Could not find home directory: $HOME is not set, and "
     895                 :            :                  "user database could not be read.");
     896                 :          0 :       home_dir = g_strdup ("/");
     897                 :            :     }
     898                 :            : 
     899                 :        114 :   return g_steal_pointer (&home_dir);
     900                 :            : }
     901                 :            : 
     902                 :            : /**
     903                 :            :  * g_get_home_dir:
     904                 :            :  *
     905                 :            :  * Gets the current user's home directory.
     906                 :            :  *
     907                 :            :  * As with most UNIX tools, this function will return the value of the
     908                 :            :  * `HOME` environment variable if it is set to an existing absolute path
     909                 :            :  * name, falling back to the `passwd` file in the case that it is unset.
     910                 :            :  *
     911                 :            :  * If the path given in `HOME` is non-absolute, does not exist, or is
     912                 :            :  * not a directory, the result is undefined.
     913                 :            :  *
     914                 :            :  * Before version 2.36 this function would ignore the `HOME` environment
     915                 :            :  * variable, taking the value from the `passwd` database instead. This was
     916                 :            :  * changed to increase the compatibility of GLib with other programs (and
     917                 :            :  * the XDG basedir specification) and to increase testability of programs
     918                 :            :  * based on GLib (by making it easier to run them from test frameworks).
     919                 :            :  *
     920                 :            :  * If your program has a strong requirement for either the new or the
     921                 :            :  * old behaviour (and if you don't wish to increase your GLib
     922                 :            :  * dependency to ensure that the new behaviour is in effect) then you
     923                 :            :  * should either directly check the `HOME` environment variable yourself
     924                 :            :  * or unset it before calling any functions in GLib.
     925                 :            :  *
     926                 :            :  * Returns: (type filename) (transfer none): the current user's home directory
     927                 :            :  */
     928                 :            : const gchar *
     929                 :       1071 : g_get_home_dir (void)
     930                 :            : {
     931                 :            :   const gchar *home_dir;
     932                 :            : 
     933                 :       1071 :   G_LOCK (g_utils_global);
     934                 :            : 
     935         [ +  + ]:       1071 :   if (g_home_dir == NULL)
     936                 :         59 :     g_home_dir = g_build_home_dir ();
     937                 :       1071 :   home_dir = g_home_dir;
     938                 :            : 
     939                 :       1071 :   G_UNLOCK (g_utils_global);
     940                 :            : 
     941                 :       1071 :   return home_dir;
     942                 :            : }
     943                 :            : 
     944                 :            : void
     945                 :         58 : _g_unset_cached_tmp_dir (void)
     946                 :            : {
     947                 :         58 :   G_LOCK (g_utils_global);
     948                 :            :   /* We have to leak the old value, as user code could be retaining pointers
     949                 :            :    * to it. */
     950                 :         58 :   g_ignore_leak (g_tmp_dir);
     951                 :         58 :   g_tmp_dir = NULL;
     952                 :         58 :   G_UNLOCK (g_utils_global);
     953                 :         58 : }
     954                 :            : 
     955                 :            : /**
     956                 :            :  * g_get_tmp_dir:
     957                 :            :  *
     958                 :            :  * Gets the directory to use for temporary files.
     959                 :            :  *
     960                 :            :  * On UNIX, this is taken from the `TMPDIR` environment variable.
     961                 :            :  * If the variable is not set, `P_tmpdir` is
     962                 :            :  * used, as defined by the system C library. Failing that, a
     963                 :            :  * hard-coded default of "/tmp" is returned.
     964                 :            :  *
     965                 :            :  * On Windows, the `TEMP` environment variable is used, with the
     966                 :            :  * root directory of the Windows installation (eg: "C:\") used
     967                 :            :  * as a default.
     968                 :            :  *
     969                 :            :  * The encoding of the returned string is system-defined. On Windows,
     970                 :            :  * it is always UTF-8. The return value is never %NULL or the empty
     971                 :            :  * string.
     972                 :            :  *
     973                 :            :  * Returns: (type filename) (transfer none): the directory to use for temporary files.
     974                 :            :  */
     975                 :            : const gchar *
     976                 :        468 : g_get_tmp_dir (void)
     977                 :            : {
     978                 :        468 :   G_LOCK (g_utils_global);
     979                 :            : 
     980         [ +  + ]:        468 :   if (g_tmp_dir == NULL)
     981                 :            :     {
     982                 :            :       gchar *tmp;
     983                 :            : 
     984                 :        126 :       tmp = g_strdup (g_getenv ("G_TEST_TMPDIR"));
     985                 :            : 
     986   [ +  +  -  + ]:        126 :       if (tmp == NULL || *tmp == '\0')
     987                 :            :         {
     988                 :         96 :           g_free (tmp);
     989                 :        192 :           tmp = g_strdup (g_getenv (
     990                 :            : #ifdef G_OS_WIN32
     991                 :            :             "TEMP"
     992                 :            : #else /* G_OS_WIN32 */
     993                 :            :             "TMPDIR"
     994                 :            : #endif /* G_OS_WIN32 */
     995                 :            :           ));
     996                 :            :         }
     997                 :            : 
     998                 :            : #ifdef G_OS_WIN32
     999                 :            :       if (tmp == NULL || *tmp == '\0')
    1000                 :            :         {
    1001                 :            :           g_free (tmp);
    1002                 :            :           tmp = get_windows_directory_root ();
    1003                 :            :         }
    1004                 :            : #else /* G_OS_WIN32 */
    1005                 :            : 
    1006                 :            : #ifdef P_tmpdir
    1007   [ +  +  +  + ]:        126 :       if (tmp == NULL || *tmp == '\0')
    1008                 :            :         {
    1009                 :            :           gsize k;
    1010                 :         96 :           g_free (tmp);
    1011                 :         96 :           tmp = g_strdup (P_tmpdir);
    1012                 :         96 :           k = strlen (tmp);
    1013   [ +  -  -  + ]:         96 :           if (k > 1 && G_IS_DIR_SEPARATOR (tmp[k - 1]))
    1014                 :          0 :             tmp[k - 1] = '\0';
    1015                 :            :         }
    1016                 :            : #endif /* P_tmpdir */
    1017                 :            : 
    1018   [ +  -  -  + ]:        126 :       if (tmp == NULL || *tmp == '\0')
    1019                 :            :         {
    1020                 :          0 :           g_free (tmp);
    1021                 :          0 :           tmp = g_strdup ("/tmp");
    1022                 :            :         }
    1023                 :            : #endif /* !G_OS_WIN32 */
    1024                 :            : 
    1025                 :        126 :       g_tmp_dir = g_steal_pointer (&tmp);
    1026                 :            :     }
    1027                 :            : 
    1028                 :        468 :   G_UNLOCK (g_utils_global);
    1029                 :            : 
    1030                 :        468 :   return g_tmp_dir;
    1031                 :            : }
    1032                 :            : 
    1033                 :            : /**
    1034                 :            :  * g_get_host_name:
    1035                 :            :  *
    1036                 :            :  * Return a name for the machine. 
    1037                 :            :  *
    1038                 :            :  * The returned name is not necessarily a fully-qualified domain name,
    1039                 :            :  * or even present in DNS or some other name service at all. It need
    1040                 :            :  * not even be unique on your local network or site, but usually it
    1041                 :            :  * is. Callers should not rely on the return value having any specific
    1042                 :            :  * properties like uniqueness for security purposes. Even if the name
    1043                 :            :  * of the machine is changed while an application is running, the
    1044                 :            :  * return value from this function does not change. The returned
    1045                 :            :  * string is owned by GLib and should not be modified or freed. If no
    1046                 :            :  * name can be determined, a default fixed string "localhost" is
    1047                 :            :  * returned.
    1048                 :            :  *
    1049                 :            :  * The encoding of the returned string is UTF-8.
    1050                 :            :  *
    1051                 :            :  * Returns: (transfer none): the host name of the machine.
    1052                 :            :  *
    1053                 :            :  * Since: 2.8
    1054                 :            :  */
    1055                 :            : const gchar *
    1056                 :          5 : g_get_host_name (void)
    1057                 :            : {
    1058                 :            :   static gchar *hostname;
    1059                 :            : 
    1060   [ +  -  +  -  :          5 :   if (g_once_init_enter_pointer (&hostname))
                   +  - ]
    1061                 :            :     {
    1062                 :            :       gboolean failed;
    1063                 :          5 :       gchar *utmp = NULL;
    1064                 :            : 
    1065                 :            : #ifndef G_OS_WIN32
    1066                 :            :       gsize size;
    1067                 :            :       /* The number 256 * 256 is taken from the value of _POSIX_HOST_NAME_MAX,
    1068                 :            :        * which is 255. Since we use _POSIX_HOST_NAME_MAX + 1 (= 256) in the
    1069                 :            :        * fallback case, we pick 256 * 256 as the size of the larger buffer here.
    1070                 :            :        * It should be large enough. It doesn't looks reasonable to name a host
    1071                 :            :        * with a string that is longer than 64 KiB.
    1072                 :            :        */
    1073                 :          5 :       const gsize size_large = (gsize) 256 * 256;
    1074                 :            :       gchar *tmp;
    1075                 :            : 
    1076                 :            : #ifdef _SC_HOST_NAME_MAX
    1077                 :            :       {
    1078                 :            :         glong max;
    1079                 :            : 
    1080                 :          5 :         max = sysconf (_SC_HOST_NAME_MAX);
    1081   [ +  -  +  - ]:          5 :         if (max > 0 && (gsize) max <= G_MAXSIZE - 1)
    1082                 :          5 :           size = (gsize) max + 1;
    1083                 :            :         else
    1084                 :            : #ifdef HOST_NAME_MAX
    1085                 :          0 :           size = HOST_NAME_MAX + 1;
    1086                 :            : #else
    1087                 :            :           size = _POSIX_HOST_NAME_MAX + 1;
    1088                 :            : #endif /* HOST_NAME_MAX */
    1089                 :            :       }
    1090                 :            : #else
    1091                 :            :       /* Fallback to some reasonable value */
    1092                 :            :       size = 256;
    1093                 :            : #endif /* _SC_HOST_NAME_MAX */
    1094                 :          5 :       tmp = g_malloc (size);
    1095                 :          5 :       failed = (gethostname (tmp, size) == -1);
    1096   [ -  +  -  - ]:          5 :       if (failed && size < size_large)
    1097                 :            :         {
    1098                 :            :           /* Try again with a larger buffer if 'size' may be too small. */
    1099                 :          0 :           g_free (tmp);
    1100                 :          0 :           tmp = g_malloc (size_large);
    1101                 :          0 :           failed = (gethostname (tmp, size_large) == -1);
    1102                 :            :         }
    1103                 :            : 
    1104         [ -  + ]:          5 :       if (failed)
    1105                 :          0 :         g_clear_pointer (&tmp, g_free);
    1106                 :          5 :       utmp = tmp;
    1107                 :            : #else
    1108                 :            :       wchar_t tmp[MAX_COMPUTERNAME_LENGTH + 1];
    1109                 :            :       DWORD size = sizeof (tmp) / sizeof (tmp[0]);
    1110                 :            :       failed = (!GetComputerNameW (tmp, &size));
    1111                 :            :       if (!failed)
    1112                 :            :         utmp = g_utf16_to_utf8 (tmp, size, NULL, NULL, NULL);
    1113                 :            :       if (utmp == NULL)
    1114                 :            :         failed = TRUE;
    1115                 :            : #endif
    1116                 :            : 
    1117         [ -  + ]:          5 :       g_once_init_leave_pointer (&hostname, failed ? g_strdup ("localhost") : utmp);
    1118                 :            :     }
    1119                 :            : 
    1120                 :          5 :   return hostname;
    1121                 :            : }
    1122                 :            : 
    1123                 :            : static const gchar *g_prgname = NULL; /* always a quark */
    1124                 :            : 
    1125                 :            : /**
    1126                 :            :  * g_get_prgname:
    1127                 :            :  *
    1128                 :            :  * Gets the name of the program. This name should not be localized,
    1129                 :            :  * in contrast to g_get_application_name().
    1130                 :            :  *
    1131                 :            :  * If you are using #GApplication the program name is set in
    1132                 :            :  * g_application_run(). In case of GDK or GTK it is set in
    1133                 :            :  * gdk_init(), which is called by gtk_init() and the
    1134                 :            :  * #GtkApplication::startup handler. The program name is found by
    1135                 :            :  * taking the last component of @argv[0].
    1136                 :            :  *
    1137                 :            :  * Returns: (nullable) (transfer none): the name of the program,
    1138                 :            :  *   or %NULL if it has not been set yet. The returned string belongs
    1139                 :            :  *   to GLib and must not be modified or freed.
    1140                 :            :  */
    1141                 :            : const gchar*
    1142                 :     330522 : g_get_prgname (void)
    1143                 :            : {
    1144                 :     330522 :   return g_atomic_pointer_get (&g_prgname);
    1145                 :            : }
    1146                 :            : 
    1147                 :            : /**
    1148                 :            :  * g_set_prgname:
    1149                 :            :  * @prgname: the name of the program.
    1150                 :            :  *
    1151                 :            :  * Sets the name of the program. This name should not be localized,
    1152                 :            :  * in contrast to g_set_application_name().
    1153                 :            :  *
    1154                 :            :  * If you are using #GApplication the program name is set in
    1155                 :            :  * g_application_run(). In case of GDK or GTK it is set in
    1156                 :            :  * gdk_init(), which is called by gtk_init() and the
    1157                 :            :  * #GtkApplication::startup handler. The program name is found by
    1158                 :            :  * taking the last component of @argv[0].
    1159                 :            :  *
    1160                 :            :  * Since GLib 2.72, this function can be called multiple times
    1161                 :            :  * and is fully thread safe. Prior to GLib 2.72, this function
    1162                 :            :  * could only be called once per process.
    1163                 :            :  */
    1164                 :            : void
    1165                 :         48 : g_set_prgname (const gchar *prgname)
    1166                 :            : {
    1167                 :         48 :   prgname = g_intern_string (prgname);
    1168                 :         48 :   g_atomic_pointer_set (&g_prgname, prgname);
    1169                 :         48 : }
    1170                 :            : 
    1171                 :            : /**
    1172                 :            :  * g_set_prgname_once:
    1173                 :            :  * @prgname: the name of the program.
    1174                 :            :  *
    1175                 :            :  * If g_get_prgname() is not set, this is the same as setting
    1176                 :            :  * the name via g_set_prgname() and %TRUE is returned. Otherwise,
    1177                 :            :  * does nothing and returns %FALSE. This is thread-safe.
    1178                 :            :  *
    1179                 :            :  * Returns: whether g_prgname was initialized by the call.
    1180                 :            :  */
    1181                 :            : gboolean
    1182                 :        806 : g_set_prgname_once (const gchar *prgname)
    1183                 :            : {
    1184                 :            :   /* if @prgname is NULL, then this has the same effect as calling
    1185                 :            :    * (g_get_prgname()==NULL). */
    1186                 :        806 :   prgname = g_intern_string (prgname);
    1187                 :        806 :   return g_atomic_pointer_compare_and_exchange (&g_prgname, NULL, prgname);
    1188                 :            : }
    1189                 :            : 
    1190                 :            : static gchar *g_application_name = NULL;
    1191                 :            : 
    1192                 :            : /**
    1193                 :            :  * g_get_application_name:
    1194                 :            :  * 
    1195                 :            :  * Gets a human-readable name for the application, as set by
    1196                 :            :  * g_set_application_name(). This name should be localized if
    1197                 :            :  * possible, and is intended for display to the user.  Contrast with
    1198                 :            :  * g_get_prgname(), which gets a non-localized name. If
    1199                 :            :  * g_set_application_name() has not been called, returns the result of
    1200                 :            :  * g_get_prgname() (which may be %NULL if g_set_prgname() has also not
    1201                 :            :  * been called).
    1202                 :            :  * 
    1203                 :            :  * Returns: (transfer none) (nullable): human-readable application
    1204                 :            :  *   name. May return %NULL
    1205                 :            :  *
    1206                 :            :  * Since: 2.2
    1207                 :            :  **/
    1208                 :            : const gchar *
    1209                 :         21 : g_get_application_name (void)
    1210                 :            : {
    1211                 :            :   const char *retval;
    1212                 :            : 
    1213                 :         21 :   retval = g_atomic_pointer_get (&g_application_name);
    1214                 :            : 
    1215         [ +  + ]:         21 :   if (retval)
    1216                 :          5 :     return retval;
    1217                 :            : 
    1218                 :         16 :   return g_get_prgname ();
    1219                 :            : }
    1220                 :            : 
    1221                 :            : /**
    1222                 :            :  * g_set_application_name:
    1223                 :            :  * @application_name: localized name of the application
    1224                 :            :  *
    1225                 :            :  * Sets a human-readable name for the application. This name should be
    1226                 :            :  * localized if possible, and is intended for display to the user.
    1227                 :            :  * Contrast with g_set_prgname(), which sets a non-localized name.
    1228                 :            :  * g_set_prgname() will be called automatically by gtk_init(),
    1229                 :            :  * but g_set_application_name() will not.
    1230                 :            :  *
    1231                 :            :  * Note that for thread safety reasons, this function can only
    1232                 :            :  * be called once.
    1233                 :            :  *
    1234                 :            :  * The application name will be used in contexts such as error messages,
    1235                 :            :  * or when displaying an application's name in the task list.
    1236                 :            :  * 
    1237                 :            :  * Since: 2.2
    1238                 :            :  **/
    1239                 :            : void
    1240                 :          5 : g_set_application_name (const gchar *application_name)
    1241                 :            : {
    1242                 :            :   char *name;
    1243                 :            : 
    1244                 :          5 :   g_return_if_fail (application_name);
    1245                 :            : 
    1246                 :          5 :   name = g_strdup (application_name);
    1247                 :            : 
    1248         [ -  + ]:          5 :   if (!g_atomic_pointer_compare_and_exchange (&g_application_name, NULL, name))
    1249                 :            :     {
    1250                 :          0 :       g_warning ("g_set_application_name() called multiple times");
    1251                 :          0 :       g_free (name);
    1252                 :            :     }
    1253                 :            : }
    1254                 :            : 
    1255                 :            : #ifdef G_OS_WIN32
    1256                 :            : /* For the past versions we can just
    1257                 :            :  * hardcode all the names.
    1258                 :            :  */
    1259                 :            : static const struct winver
    1260                 :            : {
    1261                 :            :   gint major;
    1262                 :            :   gint minor;
    1263                 :            :   gint sp;
    1264                 :            :   const char *version;
    1265                 :            :   const char *spversion;
    1266                 :            : } versions[] =
    1267                 :            : {
    1268                 :            :   {6, 2, 0, "8", ""},
    1269                 :            :   {6, 1, 1, "7", " SP1"},
    1270                 :            :   {6, 1, 0, "7", ""},
    1271                 :            :   {6, 0, 2, "Vista", " SP2"},
    1272                 :            :   {6, 0, 1, "Vista", " SP1"},
    1273                 :            :   {6, 0, 0, "Vista", ""},
    1274                 :            :   {5, 1, 3, "XP", " SP3"},
    1275                 :            :   {5, 1, 2, "XP", " SP2"},
    1276                 :            :   {5, 1, 1, "XP", " SP1"},
    1277                 :            :   {5, 1, 0, "XP", ""},
    1278                 :            :   {0, 0, 0, NULL, NULL},
    1279                 :            : };
    1280                 :            : 
    1281                 :            : static gchar *
    1282                 :            : get_registry_str (HKEY root_key, const wchar_t *path, const wchar_t *value_name)
    1283                 :            : {
    1284                 :            :   HKEY key_handle;
    1285                 :            :   DWORD req_value_data_size;
    1286                 :            :   DWORD req_value_data_size2;
    1287                 :            :   LONG status;
    1288                 :            :   DWORD value_type_w;
    1289                 :            :   DWORD value_type_w2;
    1290                 :            :   char *req_value_data;
    1291                 :            :   gchar *result;
    1292                 :            : 
    1293                 :            :   status = RegOpenKeyExW (root_key, path, 0, KEY_READ, &key_handle);
    1294                 :            :   if (status != ERROR_SUCCESS)
    1295                 :            :     return NULL;
    1296                 :            : 
    1297                 :            :   req_value_data_size = 0;
    1298                 :            :   status = RegQueryValueExW (key_handle,
    1299                 :            :                              value_name,
    1300                 :            :                              NULL,
    1301                 :            :                              &value_type_w,
    1302                 :            :                              NULL,
    1303                 :            :                              &req_value_data_size);
    1304                 :            : 
    1305                 :            :   if (status != ERROR_MORE_DATA && status != ERROR_SUCCESS)
    1306                 :            :     {
    1307                 :            :       RegCloseKey (key_handle);
    1308                 :            : 
    1309                 :            :       return NULL;
    1310                 :            :     }
    1311                 :            : 
    1312                 :            :   req_value_data = g_malloc (req_value_data_size);
    1313                 :            :   req_value_data_size2 = req_value_data_size;
    1314                 :            : 
    1315                 :            :   status = RegQueryValueExW (key_handle,
    1316                 :            :                              value_name,
    1317                 :            :                              NULL,
    1318                 :            :                              &value_type_w2,
    1319                 :            :                              (gpointer) req_value_data,
    1320                 :            :                              &req_value_data_size2);
    1321                 :            : 
    1322                 :            :   result = NULL;
    1323                 :            : 
    1324                 :            :   if (status == ERROR_SUCCESS && value_type_w2 == REG_SZ)
    1325                 :            :     result = g_utf16_to_utf8 ((gunichar2 *) req_value_data,
    1326                 :            :                               req_value_data_size / sizeof (gunichar2),
    1327                 :            :                               NULL,
    1328                 :            :                               NULL,
    1329                 :            :                               NULL);
    1330                 :            : 
    1331                 :            :   g_free (req_value_data);
    1332                 :            :   RegCloseKey (key_handle);
    1333                 :            : 
    1334                 :            :   return result;
    1335                 :            : }
    1336                 :            : 
    1337                 :            : /* Windows 8.1 can be either plain or with Update 1,
    1338                 :            :  * depending on its build number (9200 or 9600).
    1339                 :            :  */
    1340                 :            : static gchar *
    1341                 :            : get_windows_8_1_update (void)
    1342                 :            : {
    1343                 :            :   gchar *current_build;
    1344                 :            :   gchar *result = NULL;
    1345                 :            : 
    1346                 :            :   current_build = get_registry_str (HKEY_LOCAL_MACHINE,
    1347                 :            :                                     L"SOFTWARE"
    1348                 :            :                                     L"\\Microsoft"
    1349                 :            :                                     L"\\Windows NT"
    1350                 :            :                                     L"\\CurrentVersion",
    1351                 :            :                                     L"CurrentBuild");
    1352                 :            : 
    1353                 :            :   if (current_build != NULL)
    1354                 :            :     {
    1355                 :            :       wchar_t *end;
    1356                 :            :       long build = wcstol ((const wchar_t *) current_build, &end, 10);
    1357                 :            : 
    1358                 :            :       if (build <= INT_MAX &&
    1359                 :            :           build >= INT_MIN &&
    1360                 :            :           errno == 0 &&
    1361                 :            :           *end == L'\0')
    1362                 :            :         {
    1363                 :            :           if (build >= 9600)
    1364                 :            :             result = g_strdup ("Update 1");
    1365                 :            :         }
    1366                 :            :     }
    1367                 :            : 
    1368                 :            :   g_clear_pointer (&current_build, g_free);
    1369                 :            : 
    1370                 :            :   return result;
    1371                 :            : }
    1372                 :            : 
    1373                 :            : static gchar *
    1374                 :            : get_windows_version (gboolean with_windows)
    1375                 :            : {
    1376                 :            :   GString *version = g_string_new (NULL);
    1377                 :            :   gboolean is_win_server = FALSE;
    1378                 :            : 
    1379                 :            :   if (g_win32_check_windows_version (10, 0, 0, G_WIN32_OS_ANY))
    1380                 :            :     {
    1381                 :            :       gchar *win10_release;
    1382                 :            :       gboolean is_win11 = FALSE;
    1383                 :            :       OSVERSIONINFOEXW osinfo;
    1384                 :            : 
    1385                 :            :       /* Are we on Windows 2016/2019/2022 Server? */
    1386                 :            :       is_win_server = g_win32_check_windows_version (10, 0, 0, G_WIN32_OS_SERVER);
    1387                 :            : 
    1388                 :            :       /*
    1389                 :            :        * This always succeeds if we get here, since the
    1390                 :            :        * g_win32_check_windows_version() already did this!
    1391                 :            :        * We want the OSVERSIONINFOEXW here for more even
    1392                 :            :        * fine-grained versioning items
    1393                 :            :        */
    1394                 :            :       _g_win32_call_rtl_version (&osinfo);
    1395                 :            : 
    1396                 :            :       if (!is_win_server)
    1397                 :            :         {
    1398                 :            :           /*
    1399                 :            :            * Windows 11 is actually Windows 10.0.22000+,
    1400                 :            :            * so look at the build number
    1401                 :            :            */
    1402                 :            :           is_win11 = (osinfo.dwBuildNumber >= 22000);
    1403                 :            :         }
    1404                 :            :       else
    1405                 :            :         {
    1406                 :            :           /*
    1407                 :            :            * Windows 2022 Server is actually Windows 10.0.20348+,
    1408                 :            :            * Windows 2019 Server is actually Windows 10.0.17763+,
    1409                 :            :            * Windows 2016 Server is actually Windows 10.0.14393+,
    1410                 :            :            * so look at the build number
    1411                 :            :            */
    1412                 :            :           g_string_append (version, "Server");
    1413                 :            :           if (osinfo.dwBuildNumber >= 20348)
    1414                 :            :             g_string_append (version, " 2022");
    1415                 :            :           else if (osinfo.dwBuildNumber >= 17763)
    1416                 :            :             g_string_append (version, " 2019");
    1417                 :            :           else
    1418                 :            :             g_string_append (version, " 2016");
    1419                 :            :         }
    1420                 :            : 
    1421                 :            :       if (is_win11)
    1422                 :            :         g_string_append (version, "11");
    1423                 :            :       else if (!is_win_server)
    1424                 :            :         g_string_append (version, "10");
    1425                 :            : 
    1426                 :            :       /* Windows 10/Server 2016+ is identified by its ReleaseId or
    1427                 :            :        * DisplayVersion (since 20H2), such as
    1428                 :            :        * 1511, 1607, 1703, 1709, 1803, 1809 or 1903 etc.
    1429                 :            :        * The first version of Windows 10 has no release number.
    1430                 :            :        */
    1431                 :            :       win10_release = get_registry_str (HKEY_LOCAL_MACHINE,
    1432                 :            :                                         L"SOFTWARE"
    1433                 :            :                                         L"\\Microsoft"
    1434                 :            :                                         L"\\Windows NT"
    1435                 :            :                                         L"\\CurrentVersion",
    1436                 :            :                                         L"ReleaseId");
    1437                 :            : 
    1438                 :            :       if (win10_release != NULL)
    1439                 :            :         {
    1440                 :            :           if (g_strcmp0 (win10_release, "2009") != 0)
    1441                 :            :             g_string_append_printf (version, " %s", win10_release);
    1442                 :            :           else
    1443                 :            :             {
    1444                 :            :               g_free (win10_release);
    1445                 :            : 
    1446                 :            :               win10_release = get_registry_str (HKEY_LOCAL_MACHINE,
    1447                 :            :                                                 L"SOFTWARE"
    1448                 :            :                                                 L"\\Microsoft"
    1449                 :            :                                                 L"\\Windows NT"
    1450                 :            :                                                 L"\\CurrentVersion",
    1451                 :            :                                                 L"DisplayVersion");
    1452                 :            : 
    1453                 :            :               if (win10_release != NULL)
    1454                 :            :                 g_string_append_printf (version, " %s", win10_release);
    1455                 :            :               else
    1456                 :            :                 g_string_append_printf (version, " 2009");
    1457                 :            :             }
    1458                 :            :         }
    1459                 :            : 
    1460                 :            :       g_free (win10_release);
    1461                 :            :     }
    1462                 :            :   else if (g_win32_check_windows_version (6, 3, 0, G_WIN32_OS_ANY))
    1463                 :            :     {
    1464                 :            :       gchar *win81_update;
    1465                 :            : 
    1466                 :            :       if (g_win32_check_windows_version (6, 3, 0, G_WIN32_OS_WORKSTATION))
    1467                 :            :         g_string_append (version, "8.1");
    1468                 :            :       else
    1469                 :            :         g_string_append (version, "Server 2012 R2");
    1470                 :            : 
    1471                 :            :       win81_update = get_windows_8_1_update ();
    1472                 :            : 
    1473                 :            :       if (win81_update != NULL)
    1474                 :            :         g_string_append_printf (version, " %s", win81_update);
    1475                 :            : 
    1476                 :            :       g_free (win81_update);
    1477                 :            :     }
    1478                 :            :   else
    1479                 :            :     {
    1480                 :            :       gint i;
    1481                 :            : 
    1482                 :            :       for (i = 0; versions[i].major > 0; i++)
    1483                 :            :         {
    1484                 :            :           if (!g_win32_check_windows_version (versions[i].major, versions[i].minor, versions[i].sp, G_WIN32_OS_ANY))
    1485                 :            :             continue;
    1486                 :            : 
    1487                 :            :           g_string_append (version, versions[i].version);
    1488                 :            : 
    1489                 :            :           if (g_win32_check_windows_version (versions[i].major, versions[i].minor, versions[i].sp, G_WIN32_OS_SERVER))
    1490                 :            :             {
    1491                 :            :               /*
    1492                 :            :                * This condition should now always hold, since Windows
    1493                 :            :                * 7+/Server 2008 R2+ is now required
    1494                 :            :                */
    1495                 :            :               if (versions[i].major == 6)
    1496                 :            :                 {
    1497                 :            :                   g_string_append (version, "Server");
    1498                 :            :                   if (versions[i].minor == 2)
    1499                 :            :                     g_string_append (version, " 2012");
    1500                 :            :                   else if (versions[i].minor == 1)
    1501                 :            :                     g_string_append (version, " 2008 R2");
    1502                 :            :                   else
    1503                 :            :                     g_string_append (version, " 2008");
    1504                 :            :                 }
    1505                 :            :             }
    1506                 :            : 
    1507                 :            :           g_string_append (version, versions[i].spversion);
    1508                 :            :         }
    1509                 :            :     }
    1510                 :            : 
    1511                 :            :   if (version->len == 0)
    1512                 :            :     {
    1513                 :            :       g_string_free (version, TRUE);
    1514                 :            : 
    1515                 :            :       return NULL;
    1516                 :            :     }
    1517                 :            : 
    1518                 :            :   if (with_windows)
    1519                 :            :     g_string_prepend (version, "Windows ");
    1520                 :            : 
    1521                 :            :   return g_string_free (version, FALSE);
    1522                 :            : }
    1523                 :            : #endif
    1524                 :            : 
    1525                 :            : #if defined (G_OS_UNIX) && !defined (__APPLE__)
    1526                 :            : static gchar *
    1527                 :          5 : get_os_info_from_os_release (const gchar *key_name,
    1528                 :            :                              const gchar *buffer)
    1529                 :            : {
    1530                 :            :   GStrv lines;
    1531                 :            :   gchar *prefix;
    1532                 :            :   size_t i;
    1533                 :          5 :   gchar *result = NULL;
    1534                 :            : 
    1535                 :          5 :   lines = g_strsplit (buffer, "\n", -1);
    1536                 :          5 :   prefix = g_strdup_printf ("%s=", key_name);
    1537         [ +  - ]:          5 :   for (i = 0; lines[i] != NULL; i++)
    1538                 :            :     {
    1539                 :          5 :       const gchar *line = lines[i];
    1540                 :            :       const gchar *value;
    1541                 :            : 
    1542         [ +  - ]:          5 :       if (g_str_has_prefix (line, prefix))
    1543                 :            :         {
    1544                 :          5 :           value = line + strlen (prefix);
    1545                 :          5 :           result = g_shell_unquote (value, NULL);
    1546         [ -  + ]:          5 :           if (result == NULL)
    1547                 :          0 :             result = g_strdup (value);
    1548                 :          5 :           break;
    1549                 :            :         }
    1550                 :            :     }
    1551                 :          5 :   g_strfreev (lines);
    1552                 :          5 :   g_free (prefix);
    1553                 :            : 
    1554                 :            : #ifdef __linux__
    1555                 :            :   /* Default values in spec */
    1556         [ -  + ]:          5 :   if (result == NULL)
    1557                 :            :     {
    1558         [ #  # ]:          0 :       if (g_str_equal (key_name, G_OS_INFO_KEY_NAME))
    1559                 :          0 :         return g_strdup ("Linux");
    1560         [ #  # ]:          0 :       if (g_str_equal (key_name, G_OS_INFO_KEY_ID))
    1561                 :          0 :         return g_strdup ("linux");
    1562         [ #  # ]:          0 :       if (g_str_equal (key_name, G_OS_INFO_KEY_PRETTY_NAME))
    1563                 :          0 :         return g_strdup ("Linux");
    1564                 :            :     }
    1565                 :            : #endif
    1566                 :            : 
    1567                 :          5 :   return g_steal_pointer (&result);
    1568                 :            : }
    1569                 :            : 
    1570                 :            : static gchar *
    1571                 :          0 : get_os_info_from_uname (const gchar *key_name)
    1572                 :            : {
    1573                 :            :   struct utsname info;
    1574                 :            : 
    1575         [ #  # ]:          0 :   if (uname (&info) == -1)
    1576                 :          0 :     return NULL;
    1577                 :            : 
    1578         [ #  # ]:          0 :   if (strcmp (key_name, G_OS_INFO_KEY_NAME) == 0)
    1579                 :          0 :     return g_strdup (info.sysname);
    1580         [ #  # ]:          0 :   else if (strcmp (key_name, G_OS_INFO_KEY_VERSION) == 0)
    1581                 :          0 :     return g_strdup (info.release);
    1582         [ #  # ]:          0 :   else if (strcmp (key_name, G_OS_INFO_KEY_PRETTY_NAME) == 0)
    1583                 :          0 :     return g_strdup_printf ("%s %s", info.sysname, info.release);
    1584         [ #  # ]:          0 :   else if (strcmp (key_name, G_OS_INFO_KEY_ID) == 0)
    1585                 :            :     {
    1586                 :          0 :       gchar *result = g_ascii_strdown (info.sysname, -1);
    1587                 :            : 
    1588                 :          0 :       g_strcanon (result, "abcdefghijklmnopqrstuvwxyz0123456789_-.", '_');
    1589                 :          0 :       return g_steal_pointer (&result);
    1590                 :            :     }
    1591         [ #  # ]:          0 :   else if (strcmp (key_name, G_OS_INFO_KEY_VERSION_ID) == 0)
    1592                 :            :     {
    1593                 :            :       /* We attempt to convert the version string to the format returned by
    1594                 :            :        * config.guess, which is the script used to generate target triplets
    1595                 :            :        * in GNU autotools. There are a lot of rules in the script. We only
    1596                 :            :        * implement a few rules which are easy to understand here.
    1597                 :            :        *
    1598                 :            :        * config.guess can be found at https://savannah.gnu.org/projects/config.
    1599                 :            :        */
    1600                 :            :       gchar *result;
    1601                 :            : 
    1602         [ #  # ]:          0 :       if (strcmp (info.sysname, "NetBSD") == 0)
    1603                 :            :         {
    1604                 :            :           /* sed -e 's,[-_].*,,' */
    1605                 :          0 :           gssize len = G_MAXSSIZE;
    1606                 :            :           const gchar *c;
    1607                 :            : 
    1608         [ #  # ]:          0 :           if ((c = strchr (info.release, '-')) != NULL)
    1609                 :          0 :             len = MIN (len, c - info.release);
    1610         [ #  # ]:          0 :           if ((c = strchr (info.release, '_')) != NULL)
    1611                 :          0 :             len = MIN (len, c - info.release);
    1612         [ #  # ]:          0 :           if (len == G_MAXSSIZE)
    1613                 :          0 :             len = -1;
    1614                 :            : 
    1615                 :          0 :           result = g_ascii_strdown (info.release, len);
    1616                 :            :         }
    1617         [ #  # ]:          0 :       else if (strcmp (info.sysname, "GNU") == 0)
    1618                 :            :         {
    1619                 :            :           /* sed -e 's,/.*$,,' */
    1620                 :          0 :           gssize len = -1;
    1621                 :          0 :           const gchar *c = strchr (info.release, '/');
    1622                 :            : 
    1623         [ #  # ]:          0 :           if (c != NULL)
    1624                 :          0 :             len = c - info.release;
    1625                 :            : 
    1626                 :          0 :           result = g_ascii_strdown (info.release, len);
    1627                 :            :         }
    1628   [ #  #  #  #  :          0 :       else if (g_str_has_prefix (info.sysname, "GNU/") ||
             #  #  #  # ]
    1629         [ #  # ]:          0 :                strcmp (info.sysname, "FreeBSD") == 0 ||
    1630         [ #  # ]:          0 :                strcmp (info.sysname, "DragonFly") == 0)
    1631                 :          0 :         {
    1632                 :            :           /* sed -e 's,[-(].*,,' */
    1633                 :          0 :           gssize len = G_MAXSSIZE;
    1634                 :            :           const gchar *c;
    1635                 :            : 
    1636         [ #  # ]:          0 :           if ((c = strchr (info.release, '-')) != NULL)
    1637                 :          0 :             len = MIN (len, c - info.release);
    1638         [ #  # ]:          0 :           if ((c = strchr (info.release, '(')) != NULL)
    1639                 :          0 :             len = MIN (len, c - info.release);
    1640         [ #  # ]:          0 :           if (len == G_MAXSSIZE)
    1641                 :          0 :             len = -1;
    1642                 :            : 
    1643                 :          0 :           result = g_ascii_strdown (info.release, len);
    1644                 :            :         }
    1645                 :            :       else
    1646                 :          0 :         result = g_ascii_strdown (info.release, -1);
    1647                 :            : 
    1648                 :          0 :       g_strcanon (result, "abcdefghijklmnopqrstuvwxyz0123456789_-.", '_');
    1649                 :          0 :       return g_steal_pointer (&result);
    1650                 :            :     }
    1651                 :            :   else
    1652                 :          0 :     return NULL;
    1653                 :            : }
    1654                 :            : #endif  /* defined (G_OS_UNIX) && !defined (__APPLE__) */
    1655                 :            : 
    1656                 :            : /**
    1657                 :            :  * g_get_os_info:
    1658                 :            :  * @key_name: a key for the OS info being requested, for example %G_OS_INFO_KEY_NAME.
    1659                 :            :  *
    1660                 :            :  * Get information about the operating system.
    1661                 :            :  *
    1662                 :            :  * On Linux this comes from the `/etc/os-release` file. On other systems, it may
    1663                 :            :  * come from a variety of sources. You can either use the standard key names
    1664                 :            :  * like %G_OS_INFO_KEY_NAME or pass any UTF-8 string key name. For example,
    1665                 :            :  * `/etc/os-release` provides a number of other less commonly used values that may
    1666                 :            :  * be useful. No key is guaranteed to be provided, so the caller should always
    1667                 :            :  * check if the result is %NULL.
    1668                 :            :  *
    1669                 :            :  * Returns: (nullable): The associated value for the requested key or %NULL if
    1670                 :            :  *   this information is not provided.
    1671                 :            :  *
    1672                 :            :  * Since: 2.64
    1673                 :            :  **/
    1674                 :            : gchar *
    1675                 :          5 : g_get_os_info (const gchar *key_name)
    1676                 :            : {
    1677                 :            : #if defined (__APPLE__)
    1678                 :            :   if (g_strcmp0 (key_name, G_OS_INFO_KEY_NAME) == 0)
    1679                 :            :     return g_strdup ("macOS");
    1680                 :            :   else
    1681                 :            :     return NULL;
    1682                 :            : #elif defined (G_OS_UNIX)
    1683                 :          5 :   const gchar * const os_release_files[] = { "/etc/os-release", "/usr/lib/os-release" };
    1684                 :            :   gsize i;
    1685                 :          5 :   gchar *buffer = NULL;
    1686                 :          5 :   gchar *result = NULL;
    1687                 :            : 
    1688                 :          5 :   g_return_val_if_fail (key_name != NULL, NULL);
    1689                 :            : 
    1690         [ +  - ]:          5 :   for (i = 0; i < G_N_ELEMENTS (os_release_files); i++)
    1691                 :            :     {
    1692                 :          5 :       GError *error = NULL;
    1693                 :            :       gboolean file_missing;
    1694                 :            : 
    1695         [ +  - ]:          5 :       if (g_file_get_contents (os_release_files[i], &buffer, NULL, &error))
    1696                 :          5 :         break;
    1697                 :            : 
    1698                 :          0 :       file_missing = g_error_matches (error, G_FILE_ERROR, G_FILE_ERROR_NOENT);
    1699                 :          0 :       g_clear_error (&error);
    1700                 :            : 
    1701         [ #  # ]:          0 :       if (!file_missing)
    1702                 :          0 :         return NULL;
    1703                 :            :     }
    1704                 :            : 
    1705         [ +  - ]:          5 :   if (buffer != NULL)
    1706                 :          5 :     result = get_os_info_from_os_release (key_name, buffer);
    1707                 :            :   else
    1708                 :          0 :     result = get_os_info_from_uname (key_name);
    1709                 :            : 
    1710                 :          5 :   g_free (buffer);
    1711                 :          5 :   return g_steal_pointer (&result);
    1712                 :            : #elif defined (G_OS_WIN32)
    1713                 :            :   if (g_strcmp0 (key_name, G_OS_INFO_KEY_NAME) == 0)
    1714                 :            :     return g_strdup ("Windows");
    1715                 :            :   else if (g_strcmp0 (key_name, G_OS_INFO_KEY_ID) == 0)
    1716                 :            :     return g_strdup ("windows");
    1717                 :            :   else if (g_strcmp0 (key_name, G_OS_INFO_KEY_PRETTY_NAME) == 0)
    1718                 :            :     /* Windows XP SP2 or Windows 10 1903 or Windows 7 Server SP1 */
    1719                 :            :     return get_windows_version (TRUE);
    1720                 :            :   else if (g_strcmp0 (key_name, G_OS_INFO_KEY_VERSION) == 0)
    1721                 :            :     /* XP SP2 or 10 1903 or 7 Server SP1 */
    1722                 :            :     return get_windows_version (FALSE);
    1723                 :            :   else if (g_strcmp0 (key_name, G_OS_INFO_KEY_VERSION_ID) == 0)
    1724                 :            :     {
    1725                 :            :       /* xp_sp2 or 10_1903 or 7_server_sp1 */
    1726                 :            :       gchar *result;
    1727                 :            :       gchar *version = get_windows_version (FALSE);
    1728                 :            : 
    1729                 :            :       if (version == NULL)
    1730                 :            :         return NULL;
    1731                 :            : 
    1732                 :            :       result = g_ascii_strdown (version, -1);
    1733                 :            :       g_free (version);
    1734                 :            : 
    1735                 :            :       return g_strcanon (result, "abcdefghijklmnopqrstuvwxyz0123456789_-.", '_');
    1736                 :            :     }
    1737                 :            :   else if (g_strcmp0 (key_name, G_OS_INFO_KEY_HOME_URL) == 0)
    1738                 :            :     return g_strdup ("https://microsoft.com/windows/");
    1739                 :            :   else if (g_strcmp0 (key_name, G_OS_INFO_KEY_DOCUMENTATION_URL) == 0)
    1740                 :            :     return g_strdup ("https://docs.microsoft.com/");
    1741                 :            :   else if (g_strcmp0 (key_name, G_OS_INFO_KEY_SUPPORT_URL) == 0)
    1742                 :            :     return g_strdup ("https://support.microsoft.com/");
    1743                 :            :   else if (g_strcmp0 (key_name, G_OS_INFO_KEY_BUG_REPORT_URL) == 0)
    1744                 :            :     return g_strdup ("https://support.microsoft.com/contactus/");
    1745                 :            :   else if (g_strcmp0 (key_name, G_OS_INFO_KEY_PRIVACY_POLICY_URL) == 0)
    1746                 :            :     return g_strdup ("https://privacy.microsoft.com/");
    1747                 :            :   else
    1748                 :            :     return NULL;
    1749                 :            : #endif
    1750                 :            : }
    1751                 :            : 
    1752                 :            : /* Set @global_str to a copy of @new_value if it’s currently unset or has a
    1753                 :            :  * different value. If its current value matches @new_value, do nothing. If
    1754                 :            :  * replaced, we have to leak the old value as client code could still have
    1755                 :            :  * pointers to it. */
    1756                 :            : static void
    1757                 :       3138 : set_str_if_different (gchar       **global_str,
    1758                 :            :                       const gchar  *type,
    1759                 :            :                       const gchar  *new_value)
    1760                 :            : {
    1761         [ +  + ]:       3138 :   if (*global_str == NULL ||
    1762         [ +  - ]:       2774 :       !g_str_equal (new_value, *global_str))
    1763                 :            :     {
    1764                 :       3138 :       g_debug ("g_set_user_dirs: Setting %s to %s", type, new_value);
    1765                 :            : 
    1766                 :            :       /* We have to leak the old value, as user code could be retaining pointers
    1767                 :            :        * to it. */
    1768                 :       3138 :       g_ignore_leak (*global_str);
    1769                 :       3138 :       *global_str = g_strdup (new_value);
    1770                 :            :     }
    1771                 :       3138 : }
    1772                 :            : 
    1773                 :            : static void
    1774                 :       1046 : set_strv_if_different (gchar                ***global_strv,
    1775                 :            :                        const gchar            *type,
    1776                 :            :                        const gchar  * const   *new_value)
    1777                 :            : {
    1778   [ +  +  +  - ]:       1971 :   if (*global_strv == NULL ||
    1779                 :        925 :       !g_strv_equal (new_value, (const gchar * const *) *global_strv))
    1780                 :            :     {
    1781                 :       1046 :       gchar *new_value_str = g_strjoinv (":", (gchar **) new_value);
    1782                 :       1046 :       g_debug ("g_set_user_dirs: Setting %s to %s", type, new_value_str);
    1783                 :       1046 :       g_free (new_value_str);
    1784                 :            : 
    1785                 :            :       /* We have to leak the old value, as user code could be retaining pointers
    1786                 :            :        * to it. */
    1787                 :       1046 :       g_ignore_strv_leak (*global_strv);
    1788                 :       1046 :       *global_strv = g_strdupv ((gchar **) new_value);
    1789                 :            :     }
    1790                 :       1046 : }
    1791                 :            : 
    1792                 :            : /*
    1793                 :            :  * g_set_user_dirs:
    1794                 :            :  * @first_dir_type: Type of the first directory to set
    1795                 :            :  * @...: Value to set the first directory to, followed by additional type/value
    1796                 :            :  *    pairs, followed by %NULL
    1797                 :            :  *
    1798                 :            :  * Set one or more ‘user’ directories to custom values. This is intended to be
    1799                 :            :  * used by test code (particularly with the %G_TEST_OPTION_ISOLATE_DIRS option)
    1800                 :            :  * to override the values returned by the following functions, so that test
    1801                 :            :  * code can be run without touching an installed system and user data:
    1802                 :            :  *
    1803                 :            :  *  - g_get_home_dir() — use type `HOME`, pass a string
    1804                 :            :  *  - g_get_user_cache_dir() — use type `XDG_CACHE_HOME`, pass a string
    1805                 :            :  *  - g_get_system_config_dirs() — use type `XDG_CONFIG_DIRS`, pass a
    1806                 :            :  *    %NULL-terminated string array
    1807                 :            :  *  - g_get_user_config_dir() — use type `XDG_CONFIG_HOME`, pass a string
    1808                 :            :  *  - g_get_system_data_dirs() — use type `XDG_DATA_DIRS`, pass a
    1809                 :            :  *    %NULL-terminated string array
    1810                 :            :  *  - g_get_user_data_dir() — use type `XDG_DATA_HOME`, pass a string
    1811                 :            :  *  - g_get_user_runtime_dir() — use type `XDG_RUNTIME_DIR`, pass a string
    1812                 :            :  *
    1813                 :            :  * The list must be terminated with a %NULL type. All of the values must be
    1814                 :            :  * non-%NULL — passing %NULL as a value won’t reset a directory. If a reference
    1815                 :            :  * to a directory from the calling environment needs to be kept, copy it before
    1816                 :            :  * the first call to g_set_user_dirs(). g_set_user_dirs() can be called multiple
    1817                 :            :  * times.
    1818                 :            :  *
    1819                 :            :  * Since: 2.60
    1820                 :            :  */
    1821                 :            : /*< private > */
    1822                 :            : void
    1823                 :        523 : g_set_user_dirs (const gchar *first_dir_type,
    1824                 :            :                  ...)
    1825                 :            : {
    1826                 :            :   va_list args;
    1827                 :            :   const gchar *dir_type;
    1828                 :            : 
    1829                 :        523 :   G_LOCK (g_utils_global);
    1830                 :            : 
    1831                 :        523 :   va_start (args, first_dir_type);
    1832                 :            : 
    1833         [ +  + ]:       4707 :   for (dir_type = first_dir_type; dir_type != NULL; dir_type = va_arg (args, const gchar *))
    1834                 :            :     {
    1835                 :       4184 :       gconstpointer dir_value = va_arg (args, gconstpointer);
    1836                 :       4184 :       g_assert (dir_value != NULL);
    1837                 :            : 
    1838         [ +  + ]:       4184 :       if (g_str_equal (dir_type, "HOME"))
    1839                 :        523 :         set_str_if_different (&g_home_dir, dir_type, dir_value);
    1840         [ +  + ]:       3661 :       else if (g_str_equal (dir_type, "XDG_CACHE_HOME"))
    1841                 :        523 :         set_str_if_different (&g_user_cache_dir, dir_type, dir_value);
    1842         [ +  + ]:       3138 :       else if (g_str_equal (dir_type, "XDG_CONFIG_DIRS"))
    1843                 :        523 :         set_strv_if_different (&g_system_config_dirs, dir_type, dir_value);
    1844         [ +  + ]:       2615 :       else if (g_str_equal (dir_type, "XDG_CONFIG_HOME"))
    1845                 :        523 :         set_str_if_different (&g_user_config_dir, dir_type, dir_value);
    1846         [ +  + ]:       2092 :       else if (g_str_equal (dir_type, "XDG_DATA_DIRS"))
    1847                 :        523 :         set_strv_if_different (&g_system_data_dirs, dir_type, dir_value);
    1848         [ +  + ]:       1569 :       else if (g_str_equal (dir_type, "XDG_DATA_HOME"))
    1849                 :        523 :         set_str_if_different (&g_user_data_dir, dir_type, dir_value);
    1850         [ +  + ]:       1046 :       else if (g_str_equal (dir_type, "XDG_STATE_HOME"))
    1851                 :        523 :         set_str_if_different (&g_user_state_dir, dir_type, dir_value);
    1852         [ +  - ]:        523 :       else if (g_str_equal (dir_type, "XDG_RUNTIME_DIR"))
    1853                 :        523 :         set_str_if_different (&g_user_runtime_dir, dir_type, dir_value);
    1854                 :            :       else
    1855                 :            :         g_assert_not_reached ();
    1856                 :            :     }
    1857                 :            : 
    1858                 :        523 :   va_end (args);
    1859                 :            : 
    1860                 :        523 :   G_UNLOCK (g_utils_global);
    1861                 :        523 : }
    1862                 :            : 
    1863                 :            : static gchar *
    1864                 :         61 : g_build_user_data_dir (void)
    1865                 :            : {
    1866                 :         61 :   gchar *data_dir = NULL;
    1867                 :         61 :   const gchar *data_dir_env = g_getenv ("XDG_DATA_HOME");
    1868                 :            : 
    1869   [ +  +  +  - ]:         61 :   if (data_dir_env && data_dir_env[0])
    1870                 :         53 :     data_dir = g_strdup (data_dir_env);
    1871                 :            : #ifdef G_OS_WIN32
    1872                 :            :   else
    1873                 :            :     data_dir = get_special_folder (&FOLDERID_LocalAppData);
    1874                 :            : #endif
    1875   [ +  +  -  + ]:         61 :   if (!data_dir || !data_dir[0])
    1876                 :            :     {
    1877                 :          8 :       gchar *home_dir = g_build_home_dir ();
    1878                 :          8 :       g_free (data_dir);
    1879                 :          8 :       data_dir = g_build_filename (home_dir, ".local", "share", NULL);
    1880                 :          8 :       g_free (home_dir);
    1881                 :            :     }
    1882                 :            : 
    1883                 :         61 :   return g_steal_pointer (&data_dir);
    1884                 :            : }
    1885                 :            : 
    1886                 :            : /**
    1887                 :            :  * g_get_user_data_dir:
    1888                 :            :  * 
    1889                 :            :  * Returns a base directory in which to access application data such
    1890                 :            :  * as icons that is customized for a particular user.  
    1891                 :            :  *
    1892                 :            :  * On UNIX platforms this is determined using the mechanisms described
    1893                 :            :  * in the
    1894                 :            :  * [XDG Base Directory Specification](http://www.freedesktop.org/Standards/basedir-spec).
    1895                 :            :  * In this case the directory retrieved will be `XDG_DATA_HOME`.
    1896                 :            :  *
    1897                 :            :  * On Windows it follows XDG Base Directory Specification if `XDG_DATA_HOME`
    1898                 :            :  * is defined. If `XDG_DATA_HOME` is undefined, the folder to use for local (as
    1899                 :            :  * opposed to roaming) application data is used instead. See the
    1900                 :            :  * [documentation for `FOLDERID_LocalAppData`](https://docs.microsoft.com/en-us/windows/win32/shell/knownfolderid).
    1901                 :            :  * Note that in this case on Windows it will be the same
    1902                 :            :  * as what g_get_user_config_dir() returns.
    1903                 :            :  *
    1904                 :            :  * The return value is cached and modifying it at runtime is not supported, as
    1905                 :            :  * it’s not thread-safe to modify environment variables at runtime.
    1906                 :            :  *
    1907                 :            :  * Returns: (type filename) (transfer none): a string owned by GLib that must
    1908                 :            :  *   not be modified or freed.
    1909                 :            :  *
    1910                 :            :  * Since: 2.6
    1911                 :            :  **/
    1912                 :            : const gchar *
    1913                 :        235 : g_get_user_data_dir (void)
    1914                 :            : {
    1915                 :            :   const gchar *user_data_dir;
    1916                 :            : 
    1917                 :        235 :   G_LOCK (g_utils_global);
    1918                 :            : 
    1919         [ +  + ]:        235 :   if (g_user_data_dir == NULL)
    1920                 :         61 :     g_user_data_dir = g_build_user_data_dir ();
    1921                 :        235 :   user_data_dir = g_user_data_dir;
    1922                 :            : 
    1923                 :        235 :   G_UNLOCK (g_utils_global);
    1924                 :            : 
    1925                 :        235 :   return user_data_dir;
    1926                 :            : }
    1927                 :            : 
    1928                 :            : static gchar *
    1929                 :         70 : g_build_user_config_dir (void)
    1930                 :            : {
    1931                 :         70 :   gchar *config_dir = NULL;
    1932                 :         70 :   const gchar *config_dir_env = g_getenv ("XDG_CONFIG_HOME");
    1933                 :            : 
    1934   [ +  +  +  - ]:         70 :   if (config_dir_env && config_dir_env[0])
    1935                 :         48 :     config_dir = g_strdup (config_dir_env);
    1936                 :            : #ifdef G_OS_WIN32
    1937                 :            :   else
    1938                 :            :     config_dir = get_special_folder (&FOLDERID_LocalAppData);
    1939                 :            : #endif
    1940   [ +  +  -  + ]:         70 :   if (!config_dir || !config_dir[0])
    1941                 :            :     {
    1942                 :         22 :       gchar *home_dir = g_build_home_dir ();
    1943                 :         22 :       config_dir = g_build_filename (home_dir, ".config", NULL);
    1944                 :         22 :       g_free (home_dir);
    1945                 :            :     }
    1946                 :            : 
    1947                 :         70 :   return g_steal_pointer (&config_dir);
    1948                 :            : }
    1949                 :            : 
    1950                 :            : /**
    1951                 :            :  * g_get_user_config_dir:
    1952                 :            :  * 
    1953                 :            :  * Returns a base directory in which to store user-specific application 
    1954                 :            :  * configuration information such as user preferences and settings. 
    1955                 :            :  *
    1956                 :            :  * On UNIX platforms this is determined using the mechanisms described
    1957                 :            :  * in the
    1958                 :            :  * [XDG Base Directory Specification](http://www.freedesktop.org/Standards/basedir-spec).
    1959                 :            :  * In this case the directory retrieved will be `XDG_CONFIG_HOME`.
    1960                 :            :  *
    1961                 :            :  * On Windows it follows XDG Base Directory Specification if `XDG_CONFIG_HOME` is defined.
    1962                 :            :  * If `XDG_CONFIG_HOME` is undefined, the folder to use for local (as opposed
    1963                 :            :  * to roaming) application data is used instead. See the
    1964                 :            :  * [documentation for `FOLDERID_LocalAppData`](https://docs.microsoft.com/en-us/windows/win32/shell/knownfolderid).
    1965                 :            :  * Note that in this case on Windows it will be  the same
    1966                 :            :  * as what g_get_user_data_dir() returns.
    1967                 :            :  *
    1968                 :            :  * The return value is cached and modifying it at runtime is not supported, as
    1969                 :            :  * it’s not thread-safe to modify environment variables at runtime.
    1970                 :            :  *
    1971                 :            :  * Returns: (type filename) (transfer none): a string owned by GLib that
    1972                 :            :  *   must not be modified or freed.
    1973                 :            :  * Since: 2.6
    1974                 :            :  **/
    1975                 :            : const gchar *
    1976                 :        346 : g_get_user_config_dir (void)
    1977                 :            : {
    1978                 :            :   const gchar *user_config_dir;
    1979                 :            : 
    1980                 :        346 :   G_LOCK (g_utils_global);
    1981                 :            : 
    1982         [ +  + ]:        346 :   if (g_user_config_dir == NULL)
    1983                 :         54 :     g_user_config_dir = g_build_user_config_dir ();
    1984                 :        346 :   user_config_dir = g_user_config_dir;
    1985                 :            : 
    1986                 :        346 :   G_UNLOCK (g_utils_global);
    1987                 :            : 
    1988                 :        346 :   return user_config_dir;
    1989                 :            : }
    1990                 :            : 
    1991                 :            : static gchar *
    1992                 :         15 : g_build_user_cache_dir (void)
    1993                 :            : {
    1994                 :         15 :   gchar *cache_dir = NULL;
    1995                 :         15 :   const gchar *cache_dir_env = g_getenv ("XDG_CACHE_HOME");
    1996                 :            : 
    1997   [ +  +  +  - ]:         15 :   if (cache_dir_env && cache_dir_env[0])
    1998                 :          1 :     cache_dir = g_strdup (cache_dir_env);
    1999                 :            : #ifdef G_OS_WIN32
    2000                 :            :   else
    2001                 :            :     cache_dir = get_special_folder (&FOLDERID_InternetCache);
    2002                 :            : #endif
    2003   [ +  +  -  + ]:         15 :   if (!cache_dir || !cache_dir[0])
    2004                 :            :     {
    2005                 :         14 :       gchar *home_dir = g_build_home_dir ();
    2006                 :         14 :       cache_dir = g_build_filename (home_dir, ".cache", NULL);
    2007                 :         14 :       g_free (home_dir);
    2008                 :            :     }
    2009                 :            : 
    2010                 :         15 :   return g_steal_pointer (&cache_dir);
    2011                 :            : }
    2012                 :            : 
    2013                 :            : /**
    2014                 :            :  * g_get_user_cache_dir:
    2015                 :            :  * 
    2016                 :            :  * Returns a base directory in which to store non-essential, cached
    2017                 :            :  * data specific to particular user.
    2018                 :            :  *
    2019                 :            :  * On UNIX platforms this is determined using the mechanisms described
    2020                 :            :  * in the
    2021                 :            :  * [XDG Base Directory Specification](http://www.freedesktop.org/Standards/basedir-spec).
    2022                 :            :  * In this case the directory retrieved will be `XDG_CACHE_HOME`.
    2023                 :            :  *
    2024                 :            :  * On Windows it follows XDG Base Directory Specification if `XDG_CACHE_HOME` is defined.
    2025                 :            :  * If `XDG_CACHE_HOME` is undefined, the directory that serves as a common
    2026                 :            :  * repository for temporary Internet files is used instead. A typical path is
    2027                 :            :  * `C:\Documents and Settings\username\Local Settings\Temporary Internet Files`.
    2028                 :            :  * See the [documentation for `FOLDERID_InternetCache`](https://docs.microsoft.com/en-us/windows/win32/shell/knownfolderid).
    2029                 :            :  *
    2030                 :            :  * The return value is cached and modifying it at runtime is not supported, as
    2031                 :            :  * it’s not thread-safe to modify environment variables at runtime.
    2032                 :            :  *
    2033                 :            :  * Returns: (type filename) (transfer none): a string owned by GLib that
    2034                 :            :  *   must not be modified or freed.
    2035                 :            :  * Since: 2.6
    2036                 :            :  **/
    2037                 :            : const gchar *
    2038                 :       1384 : g_get_user_cache_dir (void)
    2039                 :            : {
    2040                 :            :   const gchar *user_cache_dir;
    2041                 :            : 
    2042                 :       1384 :   G_LOCK (g_utils_global);
    2043                 :            : 
    2044         [ +  + ]:       1384 :   if (g_user_cache_dir == NULL)
    2045                 :          7 :     g_user_cache_dir = g_build_user_cache_dir ();
    2046                 :       1384 :   user_cache_dir = g_user_cache_dir;
    2047                 :            : 
    2048                 :       1384 :   G_UNLOCK (g_utils_global);
    2049                 :            : 
    2050                 :       1384 :   return user_cache_dir;
    2051                 :            : }
    2052                 :            : 
    2053                 :            : static gchar *
    2054                 :          5 : g_build_user_state_dir (void)
    2055                 :            : {
    2056                 :          5 :   gchar *state_dir = NULL;
    2057                 :          5 :   const gchar *state_dir_env = g_getenv ("XDG_STATE_HOME");
    2058                 :            : 
    2059   [ -  +  -  - ]:          5 :   if (state_dir_env && state_dir_env[0])
    2060                 :          0 :     state_dir = g_strdup (state_dir_env);
    2061                 :            : #ifdef G_OS_WIN32
    2062                 :            :   else
    2063                 :            :     state_dir = get_special_folder (&FOLDERID_LocalAppData);
    2064                 :            : #endif
    2065   [ -  +  -  - ]:          5 :   if (!state_dir || !state_dir[0])
    2066                 :            :     {
    2067                 :          5 :       gchar *home_dir = g_build_home_dir ();
    2068                 :          5 :       state_dir = g_build_filename (home_dir, ".local/state", NULL);
    2069                 :          5 :       g_free (home_dir);
    2070                 :            :     }
    2071                 :            : 
    2072                 :          5 :   return g_steal_pointer (&state_dir);
    2073                 :            : }
    2074                 :            : 
    2075                 :            : /**
    2076                 :            :  * g_get_user_state_dir:
    2077                 :            :  *
    2078                 :            :  * Returns a base directory in which to store state files specific to
    2079                 :            :  * particular user.
    2080                 :            :  *
    2081                 :            :  * On UNIX platforms this is determined using the mechanisms described
    2082                 :            :  * in the
    2083                 :            :  * [XDG Base Directory Specification](http://www.freedesktop.org/Standards/basedir-spec).
    2084                 :            :  * In this case the directory retrieved will be `XDG_STATE_HOME`.
    2085                 :            :  *
    2086                 :            :  * On Windows it follows XDG Base Directory Specification if `XDG_STATE_HOME` is defined.
    2087                 :            :  * If `XDG_STATE_HOME` is undefined, the folder to use for local (as opposed
    2088                 :            :  * to roaming) application data is used instead. See the
    2089                 :            :  * [documentation for `FOLDERID_LocalAppData`](https://docs.microsoft.com/en-us/windows/win32/shell/knownfolderid).
    2090                 :            :  * Note that in this case on Windows it will be the same
    2091                 :            :  * as what g_get_user_data_dir() returns.
    2092                 :            :  *
    2093                 :            :  * The return value is cached and modifying it at runtime is not supported, as
    2094                 :            :  * it’s not thread-safe to modify environment variables at runtime.
    2095                 :            :  *
    2096                 :            :  * Returns: (type filename) (transfer none): a string owned by GLib that
    2097                 :            :  *   must not be modified or freed.
    2098                 :            :  *
    2099                 :            :  * Since: 2.72
    2100                 :            :  **/
    2101                 :            : const gchar *
    2102                 :          6 : g_get_user_state_dir (void)
    2103                 :            : {
    2104                 :            :   const gchar *user_state_dir;
    2105                 :            : 
    2106                 :          6 :   G_LOCK (g_utils_global);
    2107                 :            : 
    2108         [ +  + ]:          6 :   if (g_user_state_dir == NULL)
    2109                 :          5 :     g_user_state_dir = g_build_user_state_dir ();
    2110                 :          6 :   user_state_dir = g_user_state_dir;
    2111                 :            : 
    2112                 :          6 :   G_UNLOCK (g_utils_global);
    2113                 :            : 
    2114                 :          6 :   return user_state_dir;
    2115                 :            : }
    2116                 :            : 
    2117                 :            : static gchar *
    2118                 :          9 : g_build_user_runtime_dir (void)
    2119                 :            : {
    2120                 :          9 :   gchar *runtime_dir = NULL;
    2121                 :          9 :   const gchar *runtime_dir_env = g_getenv ("XDG_RUNTIME_DIR");
    2122                 :            : 
    2123   [ +  +  +  - ]:          9 :   if (runtime_dir_env && runtime_dir_env[0])
    2124                 :            :     {
    2125                 :          1 :       runtime_dir = g_strdup (runtime_dir_env);
    2126                 :            : 
    2127                 :            :       /* If the XDG_RUNTIME_DIR environment variable is set, we are being told by
    2128                 :            :        * the OS that this directory exists and is appropriately configured
    2129                 :            :        * already.
    2130                 :            :        */
    2131                 :            :     }
    2132                 :            :   else
    2133                 :            :     {
    2134                 :          8 :       runtime_dir = g_build_user_cache_dir ();
    2135                 :            : 
    2136                 :            :       /* Fallback case: the directory may not yet exist.
    2137                 :            :        *
    2138                 :            :        * The user should be able to rely on the directory existing
    2139                 :            :        * when the function returns.  Probably it already does, but
    2140                 :            :        * let's make sure.  Just do mkdir() directly since it will be
    2141                 :            :        * no more expensive than a stat() in the case that the
    2142                 :            :        * directory already exists and is a lot easier.
    2143                 :            :        *
    2144                 :            :        * $XDG_CACHE_HOME is probably ~/.cache/ so as long as $HOME
    2145                 :            :        * exists this will work.  If the user changed $XDG_CACHE_HOME
    2146                 :            :        * then they can make sure that it exists...
    2147                 :            :        */
    2148                 :          8 :       (void) g_mkdir (runtime_dir, 0700);
    2149                 :            :     }
    2150                 :            : 
    2151                 :          9 :   return g_steal_pointer (&runtime_dir);
    2152                 :            : }
    2153                 :            : 
    2154                 :            : /**
    2155                 :            :  * g_get_user_runtime_dir:
    2156                 :            :  *
    2157                 :            :  * Returns a directory that is unique to the current user on the local
    2158                 :            :  * system.
    2159                 :            :  *
    2160                 :            :  * This is determined using the mechanisms described
    2161                 :            :  * in the 
    2162                 :            :  * [XDG Base Directory Specification](http://www.freedesktop.org/Standards/basedir-spec).
    2163                 :            :  * This is the directory
    2164                 :            :  * specified in the `XDG_RUNTIME_DIR` environment variable.
    2165                 :            :  * In the case that this variable is not set, we return the value of
    2166                 :            :  * g_get_user_cache_dir(), after verifying that it exists.
    2167                 :            :  *
    2168                 :            :  * The return value is cached and modifying it at runtime is not supported, as
    2169                 :            :  * it’s not thread-safe to modify environment variables at runtime.
    2170                 :            :  *
    2171                 :            :  * Returns: (type filename): a string owned by GLib that must not be
    2172                 :            :  *     modified or freed.
    2173                 :            :  *
    2174                 :            :  * Since: 2.28
    2175                 :            :  **/
    2176                 :            : const gchar *
    2177                 :         97 : g_get_user_runtime_dir (void)
    2178                 :            : {
    2179                 :            :   const gchar *user_runtime_dir;
    2180                 :            : 
    2181                 :         97 :   G_LOCK (g_utils_global);
    2182                 :            : 
    2183         [ +  + ]:         97 :   if (g_user_runtime_dir == NULL)
    2184                 :          9 :     g_user_runtime_dir = g_build_user_runtime_dir ();
    2185                 :         97 :   user_runtime_dir = g_user_runtime_dir;
    2186                 :            : 
    2187                 :         97 :   G_UNLOCK (g_utils_global);
    2188                 :            : 
    2189                 :         97 :   return user_runtime_dir;
    2190                 :            : }
    2191                 :            : 
    2192                 :            : #ifdef HAVE_COCOA
    2193                 :            : 
    2194                 :            : /* Implemented in gutils-macos.m */
    2195                 :            : void load_user_special_dirs_macos (gchar **table);
    2196                 :            : 
    2197                 :            : static void
    2198                 :            : load_user_special_dirs (void)
    2199                 :            : {
    2200                 :            :   load_user_special_dirs_macos (g_user_special_dirs);
    2201                 :            : }
    2202                 :            : 
    2203                 :            : #elif defined(G_OS_WIN32)
    2204                 :            : 
    2205                 :            : static void
    2206                 :            : load_user_special_dirs (void)
    2207                 :            : {
    2208                 :            :   g_user_special_dirs[G_USER_DIRECTORY_DESKTOP] = get_special_folder (&FOLDERID_Desktop);
    2209                 :            :   g_user_special_dirs[G_USER_DIRECTORY_DOCUMENTS] = get_special_folder (&FOLDERID_Documents);
    2210                 :            : 
    2211                 :            :   g_user_special_dirs[G_USER_DIRECTORY_DOWNLOAD] = get_special_folder (&FOLDERID_Downloads);
    2212                 :            :   if (g_user_special_dirs[G_USER_DIRECTORY_DOWNLOAD] == NULL)
    2213                 :            :     g_user_special_dirs[G_USER_DIRECTORY_DOWNLOAD] = get_special_folder (&FOLDERID_Desktop);
    2214                 :            : 
    2215                 :            :   g_user_special_dirs[G_USER_DIRECTORY_MUSIC] = get_special_folder (&FOLDERID_Music);
    2216                 :            :   g_user_special_dirs[G_USER_DIRECTORY_PICTURES] = get_special_folder (&FOLDERID_Pictures);
    2217                 :            : 
    2218                 :            :   g_user_special_dirs[G_USER_DIRECTORY_PUBLIC_SHARE] = get_special_folder (&FOLDERID_Public);
    2219                 :            :   if (g_user_special_dirs[G_USER_DIRECTORY_PUBLIC_SHARE] == NULL)
    2220                 :            :     g_user_special_dirs[G_USER_DIRECTORY_PUBLIC_SHARE] = get_special_folder (&FOLDERID_PublicDocuments);
    2221                 :            : 
    2222                 :            :   g_user_special_dirs[G_USER_DIRECTORY_TEMPLATES] = get_special_folder (&FOLDERID_Templates);
    2223                 :            :   g_user_special_dirs[G_USER_DIRECTORY_VIDEOS] = get_special_folder (&FOLDERID_Videos);
    2224                 :            : }
    2225                 :            : 
    2226                 :            : #else /* default is unix */
    2227                 :            : 
    2228                 :            : /* adapted from xdg-user-dir-lookup.c
    2229                 :            :  *
    2230                 :            :  * Copyright (C) 2007 Red Hat Inc.
    2231                 :            :  *
    2232                 :            :  * Permission is hereby granted, free of charge, to any person
    2233                 :            :  * obtaining a copy of this software and associated documentation files
    2234                 :            :  * (the "Software"), to deal in the Software without restriction,
    2235                 :            :  * including without limitation the rights to use, copy, modify, merge,
    2236                 :            :  * publish, distribute, sublicense, and/or sell copies of the Software,
    2237                 :            :  * and to permit persons to whom the Software is furnished to do so,
    2238                 :            :  * subject to the following conditions: 
    2239                 :            :  *
    2240                 :            :  * The above copyright notice and this permission notice shall be
    2241                 :            :  * included in all copies or substantial portions of the Software. 
    2242                 :            :  *
    2243                 :            :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    2244                 :            :  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    2245                 :            :  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
    2246                 :            :  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
    2247                 :            :  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
    2248                 :            :  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
    2249                 :            :  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
    2250                 :            :  * SOFTWARE.
    2251                 :            :  */
    2252                 :            : static void
    2253                 :         16 : load_user_special_dirs (void)
    2254                 :            : {
    2255                 :         16 :   gchar *config_dir = NULL;
    2256                 :            :   gchar *config_file;
    2257                 :            :   gchar *data;
    2258                 :            :   gchar **lines;
    2259                 :            :   gint n_lines, i;
    2260                 :            :   
    2261                 :         16 :   config_dir = g_build_user_config_dir ();
    2262                 :         16 :   config_file = g_build_filename (config_dir,
    2263                 :            :                                   "user-dirs.dirs",
    2264                 :            :                                   NULL);
    2265                 :         16 :   g_free (config_dir);
    2266                 :            : 
    2267         [ +  - ]:         16 :   if (!g_file_get_contents (config_file, &data, NULL, NULL))
    2268                 :            :     {
    2269                 :         16 :       g_free (config_file);
    2270                 :         16 :       return;
    2271                 :            :     }
    2272                 :            : 
    2273                 :          0 :   lines = g_strsplit (data, "\n", -1);
    2274                 :          0 :   n_lines = g_strv_length (lines);
    2275                 :          0 :   g_free (data);
    2276                 :            :   
    2277         [ #  # ]:          0 :   for (i = 0; i < n_lines; i++)
    2278                 :            :     {
    2279                 :          0 :       gchar *buffer = lines[i];
    2280                 :            :       gchar *d, *p;
    2281                 :            :       gint len;
    2282                 :          0 :       gboolean is_relative = FALSE;
    2283                 :            :       GUserDirectory directory;
    2284                 :            : 
    2285                 :            :       /* Remove newline at end */
    2286                 :          0 :       len = strlen (buffer);
    2287   [ #  #  #  # ]:          0 :       if (len > 0 && buffer[len - 1] == '\n')
    2288                 :          0 :         buffer[len - 1] = 0;
    2289                 :            :       
    2290                 :          0 :       p = buffer;
    2291   [ #  #  #  # ]:          0 :       while (*p == ' ' || *p == '\t')
    2292                 :          0 :         p++;
    2293                 :            :       
    2294         [ #  # ]:          0 :       if (strncmp (p, "XDG_DESKTOP_DIR", strlen ("XDG_DESKTOP_DIR")) == 0)
    2295                 :            :         {
    2296                 :          0 :           directory = G_USER_DIRECTORY_DESKTOP;
    2297                 :          0 :           p += strlen ("XDG_DESKTOP_DIR");
    2298                 :            :         }
    2299         [ #  # ]:          0 :       else if (strncmp (p, "XDG_DOCUMENTS_DIR", strlen ("XDG_DOCUMENTS_DIR")) == 0)
    2300                 :            :         {
    2301                 :          0 :           directory = G_USER_DIRECTORY_DOCUMENTS;
    2302                 :          0 :           p += strlen ("XDG_DOCUMENTS_DIR");
    2303                 :            :         }
    2304         [ #  # ]:          0 :       else if (strncmp (p, "XDG_DOWNLOAD_DIR", strlen ("XDG_DOWNLOAD_DIR")) == 0)
    2305                 :            :         {
    2306                 :          0 :           directory = G_USER_DIRECTORY_DOWNLOAD;
    2307                 :          0 :           p += strlen ("XDG_DOWNLOAD_DIR");
    2308                 :            :         }
    2309         [ #  # ]:          0 :       else if (strncmp (p, "XDG_MUSIC_DIR", strlen ("XDG_MUSIC_DIR")) == 0)
    2310                 :            :         {
    2311                 :          0 :           directory = G_USER_DIRECTORY_MUSIC;
    2312                 :          0 :           p += strlen ("XDG_MUSIC_DIR");
    2313                 :            :         }
    2314         [ #  # ]:          0 :       else if (strncmp (p, "XDG_PICTURES_DIR", strlen ("XDG_PICTURES_DIR")) == 0)
    2315                 :            :         {
    2316                 :          0 :           directory = G_USER_DIRECTORY_PICTURES;
    2317                 :          0 :           p += strlen ("XDG_PICTURES_DIR");
    2318                 :            :         }
    2319         [ #  # ]:          0 :       else if (strncmp (p, "XDG_PUBLICSHARE_DIR", strlen ("XDG_PUBLICSHARE_DIR")) == 0)
    2320                 :            :         {
    2321                 :          0 :           directory = G_USER_DIRECTORY_PUBLIC_SHARE;
    2322                 :          0 :           p += strlen ("XDG_PUBLICSHARE_DIR");
    2323                 :            :         }
    2324         [ #  # ]:          0 :       else if (strncmp (p, "XDG_TEMPLATES_DIR", strlen ("XDG_TEMPLATES_DIR")) == 0)
    2325                 :            :         {
    2326                 :          0 :           directory = G_USER_DIRECTORY_TEMPLATES;
    2327                 :          0 :           p += strlen ("XDG_TEMPLATES_DIR");
    2328                 :            :         }
    2329         [ #  # ]:          0 :       else if (strncmp (p, "XDG_VIDEOS_DIR", strlen ("XDG_VIDEOS_DIR")) == 0)
    2330                 :            :         {
    2331                 :          0 :           directory = G_USER_DIRECTORY_VIDEOS;
    2332                 :          0 :           p += strlen ("XDG_VIDEOS_DIR");
    2333                 :            :         }
    2334                 :            :       else
    2335                 :          0 :         continue;
    2336                 :            : 
    2337   [ #  #  #  # ]:          0 :       while (*p == ' ' || *p == '\t')
    2338                 :          0 :         p++;
    2339                 :            : 
    2340         [ #  # ]:          0 :       if (*p != '=')
    2341                 :          0 :         continue;
    2342                 :          0 :       p++;
    2343                 :            : 
    2344   [ #  #  #  # ]:          0 :       while (*p == ' ' || *p == '\t')
    2345                 :          0 :         p++;
    2346                 :            : 
    2347         [ #  # ]:          0 :       if (*p != '"')
    2348                 :          0 :         continue;
    2349                 :          0 :       p++;
    2350                 :            : 
    2351         [ #  # ]:          0 :       if (strncmp (p, "$HOME", 5) == 0)
    2352                 :            :         {
    2353                 :          0 :           p += 5;
    2354                 :          0 :           is_relative = TRUE;
    2355                 :            :         }
    2356         [ #  # ]:          0 :       else if (*p != '/')
    2357                 :          0 :         continue;
    2358                 :            : 
    2359                 :          0 :       d = strrchr (p, '"');
    2360         [ #  # ]:          0 :       if (!d)
    2361                 :          0 :         continue;
    2362                 :          0 :       *d = 0;
    2363                 :            : 
    2364                 :          0 :       d = p;
    2365                 :            :       
    2366                 :            :       /* remove trailing slashes */
    2367                 :          0 :       len = strlen (d);
    2368         [ #  # ]:          0 :       if (d[len - 1] == '/')
    2369                 :          0 :         d[len - 1] = 0;
    2370                 :            :       
    2371         [ #  # ]:          0 :       if (is_relative)
    2372                 :            :         {
    2373                 :          0 :           gchar *home_dir = g_build_home_dir ();
    2374                 :          0 :           g_user_special_dirs[directory] = g_build_filename (home_dir, d, NULL);
    2375                 :          0 :           g_free (home_dir);
    2376                 :            :         }
    2377                 :            :       else
    2378                 :          0 :         g_user_special_dirs[directory] = g_strdup (d);
    2379                 :            :     }
    2380                 :            : 
    2381                 :          0 :   g_strfreev (lines);
    2382                 :          0 :   g_free (config_file);
    2383                 :            : }
    2384                 :            : 
    2385                 :            : #endif /* platform-specific load_user_special_dirs implementations */
    2386                 :            : 
    2387                 :            : 
    2388                 :            : /**
    2389                 :            :  * g_reload_user_special_dirs_cache:
    2390                 :            :  *
    2391                 :            :  * Resets the cache used for g_get_user_special_dir(), so
    2392                 :            :  * that the latest on-disk version is used. Call this only
    2393                 :            :  * if you just changed the data on disk yourself.
    2394                 :            :  *
    2395                 :            :  * Due to thread safety issues this may cause leaking of strings
    2396                 :            :  * that were previously returned from g_get_user_special_dir()
    2397                 :            :  * that can't be freed. We ensure to only leak the data for
    2398                 :            :  * the directories that actually changed value though.
    2399                 :            :  *
    2400                 :            :  * Since: 2.22
    2401                 :            :  */
    2402                 :            : void
    2403                 :         10 : g_reload_user_special_dirs_cache (void)
    2404                 :            : {
    2405                 :            :   int i;
    2406                 :            : 
    2407                 :         10 :   G_LOCK (g_utils_global);
    2408                 :            : 
    2409         [ +  - ]:         10 :   if (g_user_special_dirs != NULL)
    2410                 :            :     {
    2411                 :            :       /* save a copy of the pointer, to check if some memory can be preserved */
    2412                 :         10 :       char **old_g_user_special_dirs = g_user_special_dirs;
    2413                 :            :       char *old_val;
    2414                 :            : 
    2415                 :            :       /* recreate and reload our cache */
    2416                 :         10 :       g_user_special_dirs = g_new0 (gchar *, G_USER_N_DIRECTORIES);
    2417                 :         10 :       load_user_special_dirs ();
    2418                 :            : 
    2419                 :            :       /* only leak changed directories */
    2420         [ +  + ]:         90 :       for (i = 0; i < G_USER_N_DIRECTORIES; i++)
    2421                 :            :         {
    2422                 :         80 :           old_val = old_g_user_special_dirs[i];
    2423         [ +  - ]:         80 :           if (g_user_special_dirs[i] == NULL)
    2424                 :            :             {
    2425                 :         80 :               g_user_special_dirs[i] = old_val;
    2426                 :            :             }
    2427         [ #  # ]:          0 :           else if (g_strcmp0 (old_val, g_user_special_dirs[i]) == 0)
    2428                 :            :             {
    2429                 :            :               /* don't leak */
    2430                 :          0 :               g_free (g_user_special_dirs[i]);
    2431                 :          0 :               g_user_special_dirs[i] = old_val;
    2432                 :            :             }
    2433                 :            :           else
    2434                 :          0 :             g_free (old_val);
    2435                 :            :         }
    2436                 :            : 
    2437                 :            :       /* free the old array */
    2438                 :         10 :       g_free (old_g_user_special_dirs);
    2439                 :            :     }
    2440                 :            : 
    2441                 :         10 :   G_UNLOCK (g_utils_global);
    2442                 :         10 : }
    2443                 :            : 
    2444                 :            : /**
    2445                 :            :  * g_get_user_special_dir:
    2446                 :            :  * @directory: the logical id of special directory
    2447                 :            :  *
    2448                 :            :  * Returns the full path of a special directory using its logical id.
    2449                 :            :  *
    2450                 :            :  * On UNIX this is done using the XDG special user directories.
    2451                 :            :  * For compatibility with existing practise, %G_USER_DIRECTORY_DESKTOP
    2452                 :            :  * falls back to `$HOME/Desktop` when XDG special user directories have
    2453                 :            :  * not been set up. 
    2454                 :            :  *
    2455                 :            :  * Depending on the platform, the user might be able to change the path
    2456                 :            :  * of the special directory without requiring the session to restart; GLib
    2457                 :            :  * will not reflect any change once the special directories are loaded.
    2458                 :            :  *
    2459                 :            :  * Returns: (type filename) (nullable): the path to the specified special
    2460                 :            :  *   directory, or %NULL if the logical id was not found. The returned string is
    2461                 :            :  *   owned by GLib and should not be modified or freed.
    2462                 :            :  *
    2463                 :            :  * Since: 2.14
    2464                 :            :  */
    2465                 :            : const gchar *
    2466                 :       1236 : g_get_user_special_dir (GUserDirectory directory)
    2467                 :            : {
    2468                 :            :   const gchar *user_special_dir;
    2469                 :            : 
    2470                 :       1236 :   g_return_val_if_fail (directory >= G_USER_DIRECTORY_DESKTOP &&
    2471                 :            :                         directory < G_USER_N_DIRECTORIES, NULL);
    2472                 :            : 
    2473                 :       1236 :   G_LOCK (g_utils_global);
    2474                 :            : 
    2475         [ +  + ]:       1236 :   if (G_UNLIKELY (g_user_special_dirs == NULL))
    2476                 :            :     {
    2477                 :          6 :       g_user_special_dirs = g_new0 (gchar *, G_USER_N_DIRECTORIES);
    2478                 :            : 
    2479                 :          6 :       load_user_special_dirs ();
    2480                 :            : 
    2481                 :            :       /* Special-case desktop for historical compatibility */
    2482         [ +  - ]:          6 :       if (g_user_special_dirs[G_USER_DIRECTORY_DESKTOP] == NULL)
    2483                 :            :         {
    2484                 :          6 :           gchar *home_dir = g_build_home_dir ();
    2485                 :          6 :           g_user_special_dirs[G_USER_DIRECTORY_DESKTOP] = g_build_filename (home_dir, "Desktop", NULL);
    2486                 :          6 :           g_free (home_dir);
    2487                 :            :         }
    2488                 :            :     }
    2489                 :       1236 :   user_special_dir = g_user_special_dirs[directory];
    2490                 :            : 
    2491                 :       1236 :   G_UNLOCK (g_utils_global);
    2492                 :            : 
    2493                 :       1236 :   return user_special_dir;
    2494                 :            : }
    2495                 :            : 
    2496                 :            : #ifdef G_OS_WIN32
    2497                 :            : 
    2498                 :            : #undef g_get_system_data_dirs
    2499                 :            : 
    2500                 :            : static HMODULE
    2501                 :            : get_module_for_address (gconstpointer address)
    2502                 :            : {
    2503                 :            :   /* Holds the g_utils_global lock */
    2504                 :            : 
    2505                 :            :   HMODULE hmodule = NULL;
    2506                 :            : 
    2507                 :            :   if (!address)
    2508                 :            :     return NULL;
    2509                 :            : 
    2510                 :            :   if (!GetModuleHandleExW (GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT |
    2511                 :            :                            GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
    2512                 :            :                            address, &hmodule))
    2513                 :            :     {
    2514                 :            :       MEMORY_BASIC_INFORMATION mbi;
    2515                 :            :       VirtualQuery (address, &mbi, sizeof (mbi));
    2516                 :            :       hmodule = (HMODULE) mbi.AllocationBase;
    2517                 :            :     }
    2518                 :            : 
    2519                 :            :   return hmodule;
    2520                 :            : }
    2521                 :            : 
    2522                 :            : static gchar *
    2523                 :            : get_module_share_dir (gconstpointer address)
    2524                 :            : {
    2525                 :            :   HMODULE hmodule;
    2526                 :            :   gchar *filename;
    2527                 :            :   gchar *retval;
    2528                 :            : 
    2529                 :            :   hmodule = get_module_for_address (address);
    2530                 :            :   if (hmodule == NULL)
    2531                 :            :     return NULL;
    2532                 :            : 
    2533                 :            :   filename = g_win32_get_package_installation_directory_of_module (hmodule);
    2534                 :            :   retval = g_build_filename (filename, "share", NULL);
    2535                 :            :   g_free (filename);
    2536                 :            : 
    2537                 :            :   return retval;
    2538                 :            : }
    2539                 :            : 
    2540                 :            : static const gchar * const *
    2541                 :            : g_win32_get_system_data_dirs_for_module_real (void (*address_of_function)(void))
    2542                 :            : {
    2543                 :            :   GArray *data_dirs;
    2544                 :            :   HMODULE hmodule;
    2545                 :            :   static GHashTable *per_module_data_dirs = NULL;
    2546                 :            :   gchar **retval;
    2547                 :            :   gchar *p;
    2548                 :            :   gchar *exe_root;
    2549                 :            : 
    2550                 :            :   hmodule = NULL;
    2551                 :            :   if (address_of_function)
    2552                 :            :     {
    2553                 :            :       G_LOCK (g_utils_global);
    2554                 :            :       hmodule = get_module_for_address (address_of_function);
    2555                 :            :       if (hmodule != NULL)
    2556                 :            :         {
    2557                 :            :           if (per_module_data_dirs == NULL)
    2558                 :            :             per_module_data_dirs = g_hash_table_new (NULL, NULL);
    2559                 :            :           else
    2560                 :            :             {
    2561                 :            :               retval = g_hash_table_lookup (per_module_data_dirs, hmodule);
    2562                 :            :               
    2563                 :            :               if (retval != NULL)
    2564                 :            :                 {
    2565                 :            :                   G_UNLOCK (g_utils_global);
    2566                 :            :                   return (const gchar * const *) retval;
    2567                 :            :                 }
    2568                 :            :             }
    2569                 :            :         }
    2570                 :            :     }
    2571                 :            : 
    2572                 :            :   data_dirs = g_array_new (TRUE, TRUE, sizeof (char *));
    2573                 :            : 
    2574                 :            :   /* Documents and Settings\All Users\Application Data */
    2575                 :            :   p = get_special_folder (&FOLDERID_ProgramData);
    2576                 :            :   if (p)
    2577                 :            :     g_array_append_val (data_dirs, p);
    2578                 :            : 
    2579                 :            :   /* Documents and Settings\All Users\Documents */
    2580                 :            :   p = get_special_folder (&FOLDERID_PublicDocuments);
    2581                 :            :   if (p)
    2582                 :            :     g_array_append_val (data_dirs, p);
    2583                 :            : 
    2584                 :            :   /* Using the above subfolders of Documents and Settings perhaps
    2585                 :            :    * makes sense from a Windows perspective.
    2586                 :            :    *
    2587                 :            :    * But looking at the actual use cases of this function in GTK
    2588                 :            :    * and GNOME software, what we really want is the "share"
    2589                 :            :    * subdirectory of the installation directory for the package
    2590                 :            :    * our caller is a part of.
    2591                 :            :    *
    2592                 :            :    * The address_of_function parameter, if non-NULL, points to a
    2593                 :            :    * function in the calling module. Use that to determine that
    2594                 :            :    * module's installation folder, and use its "share" subfolder.
    2595                 :            :    *
    2596                 :            :    * Additionally, also use the "share" subfolder of the installation
    2597                 :            :    * locations of GLib and the .exe file being run.
    2598                 :            :    *
    2599                 :            :    * To guard against none of the above being what is really wanted,
    2600                 :            :    * callers of this function should have Win32-specific code to look
    2601                 :            :    * up their installation folder themselves, and handle a subfolder
    2602                 :            :    * "share" of it in the same way as the folders returned from this
    2603                 :            :    * function.
    2604                 :            :    */
    2605                 :            : 
    2606                 :            :   p = get_module_share_dir (address_of_function);
    2607                 :            :   if (p)
    2608                 :            :     g_array_append_val (data_dirs, p);
    2609                 :            :     
    2610                 :            :   if (glib_dll != NULL)
    2611                 :            :     {
    2612                 :            :       gchar *glib_root = g_win32_get_package_installation_directory_of_module (glib_dll);
    2613                 :            :       p = g_build_filename (glib_root, "share", NULL);
    2614                 :            :       if (p)
    2615                 :            :         g_array_append_val (data_dirs, p);
    2616                 :            :       g_free (glib_root);
    2617                 :            :     }
    2618                 :            :   
    2619                 :            :   exe_root = g_win32_get_package_installation_directory_of_module (NULL);
    2620                 :            :   p = g_build_filename (exe_root, "share", NULL);
    2621                 :            :   if (p)
    2622                 :            :     g_array_append_val (data_dirs, p);
    2623                 :            :   g_free (exe_root);
    2624                 :            : 
    2625                 :            :   retval = (gchar **) g_array_free (data_dirs, FALSE);
    2626                 :            : 
    2627                 :            :   if (address_of_function)
    2628                 :            :     {
    2629                 :            :       if (hmodule != NULL)
    2630                 :            :         g_hash_table_insert (per_module_data_dirs, hmodule, retval);
    2631                 :            :       G_UNLOCK (g_utils_global);
    2632                 :            :     }
    2633                 :            : 
    2634                 :            :   return (const gchar * const *) retval;
    2635                 :            : }
    2636                 :            : 
    2637                 :            : const gchar * const *
    2638                 :            : g_win32_get_system_data_dirs_for_module (void (*address_of_function)(void))
    2639                 :            : {
    2640                 :            :   gboolean should_call_g_get_system_data_dirs;
    2641                 :            : 
    2642                 :            :   should_call_g_get_system_data_dirs = TRUE;
    2643                 :            :   /* These checks are the same as the ones that g_build_system_data_dirs() does.
    2644                 :            :    * Please keep them in sync.
    2645                 :            :    */
    2646                 :            :   G_LOCK (g_utils_global);
    2647                 :            : 
    2648                 :            :   if (!g_system_data_dirs)
    2649                 :            :     {
    2650                 :            :       const gchar *data_dirs = g_getenv ("XDG_DATA_DIRS");
    2651                 :            : 
    2652                 :            :       if (!data_dirs || !data_dirs[0])
    2653                 :            :         should_call_g_get_system_data_dirs = FALSE;
    2654                 :            :     }
    2655                 :            : 
    2656                 :            :   G_UNLOCK (g_utils_global);
    2657                 :            : 
    2658                 :            :   /* There is a subtle difference between g_win32_get_system_data_dirs_for_module (NULL),
    2659                 :            :    * which is what GLib code can normally call,
    2660                 :            :    * and g_win32_get_system_data_dirs_for_module (&_g_win32_get_system_data_dirs),
    2661                 :            :    * which is what the inline function used by non-GLib code calls.
    2662                 :            :    * The former gets prefix relative to currently-running executable,
    2663                 :            :    * the latter - relative to the module that calls _g_win32_get_system_data_dirs()
    2664                 :            :    * (disguised as g_get_system_data_dirs()), which could be an executable or
    2665                 :            :    * a DLL that is located somewhere else.
    2666                 :            :    * This is why that inline function in gutils.h exists, and why we can't just
    2667                 :            :    * call g_get_system_data_dirs() from there - because we need to get the address
    2668                 :            :    * local to the non-GLib caller-module.
    2669                 :            :    */
    2670                 :            : 
    2671                 :            :   /*
    2672                 :            :    * g_get_system_data_dirs() will fall back to calling
    2673                 :            :    * g_win32_get_system_data_dirs_for_module_real(NULL) if XDG_DATA_DIRS is NULL
    2674                 :            :    * or an empty string. The checks above ensure that we do not call it in such
    2675                 :            :    * cases and use the address_of_function that we've been given by the inline function.
    2676                 :            :    * The reason we're calling g_get_system_data_dirs /at all/ is to give
    2677                 :            :    * XDG_DATA_DIRS precedence (if it is set).
    2678                 :            :    */
    2679                 :            :   if (should_call_g_get_system_data_dirs)
    2680                 :            :     return g_get_system_data_dirs ();
    2681                 :            : 
    2682                 :            :   return g_win32_get_system_data_dirs_for_module_real (address_of_function);
    2683                 :            : }
    2684                 :            : 
    2685                 :            : #endif
    2686                 :            : 
    2687                 :            : static gchar **
    2688                 :         56 : g_build_system_data_dirs (void)
    2689                 :            : {
    2690                 :         56 :   gchar **data_dir_vector = NULL;
    2691                 :         56 :   gchar *data_dirs = (gchar *) g_getenv ("XDG_DATA_DIRS");
    2692                 :            : 
    2693                 :            :   /* These checks are the same as the ones that g_win32_get_system_data_dirs_for_module()
    2694                 :            :    * does. Please keep them in sync.
    2695                 :            :    */
    2696                 :            : #ifndef G_OS_WIN32
    2697   [ +  +  -  + ]:         56 :   if (!data_dirs || !data_dirs[0])
    2698                 :          4 :     data_dirs = "/usr/local/share/:/usr/share/";
    2699                 :            : 
    2700                 :         56 :   data_dir_vector = g_strsplit (data_dirs, G_SEARCHPATH_SEPARATOR_S, 0);
    2701                 :            : #else
    2702                 :            :   if (!data_dirs || !data_dirs[0])
    2703                 :            :     data_dir_vector = g_strdupv ((gchar **) g_win32_get_system_data_dirs_for_module_real (NULL));
    2704                 :            :   else
    2705                 :            :     data_dir_vector = g_strsplit (data_dirs, G_SEARCHPATH_SEPARATOR_S, 0);
    2706                 :            : #endif
    2707                 :            : 
    2708                 :         56 :   return g_steal_pointer (&data_dir_vector);
    2709                 :            : }
    2710                 :            : 
    2711                 :            : /**
    2712                 :            :  * g_get_system_data_dirs:
    2713                 :            :  * 
    2714                 :            :  * Returns an ordered list of base directories in which to access 
    2715                 :            :  * system-wide application data.
    2716                 :            :  *
    2717                 :            :  * On UNIX platforms this is determined using the mechanisms described
    2718                 :            :  * in the
    2719                 :            :  * [XDG Base Directory Specification](http://www.freedesktop.org/Standards/basedir-spec)
    2720                 :            :  * In this case the list of directories retrieved will be `XDG_DATA_DIRS`.
    2721                 :            :  *
    2722                 :            :  * On Windows it follows XDG Base Directory Specification if `XDG_DATA_DIRS` is defined.
    2723                 :            :  * If `XDG_DATA_DIRS` is undefined,
    2724                 :            :  * the first elements in the list are the Application Data
    2725                 :            :  * and Documents folders for All Users. (These can be determined only
    2726                 :            :  * on Windows 2000 or later and are not present in the list on other
    2727                 :            :  * Windows versions.) See documentation for FOLDERID_ProgramData and
    2728                 :            :  * FOLDERID_PublicDocuments.
    2729                 :            :  *
    2730                 :            :  * Then follows the "share" subfolder in the installation folder for
    2731                 :            :  * the package containing the DLL that calls this function, if it can
    2732                 :            :  * be determined.
    2733                 :            :  * 
    2734                 :            :  * Finally the list contains the "share" subfolder in the installation
    2735                 :            :  * folder for GLib, and in the installation folder for the package the
    2736                 :            :  * application's .exe file belongs to.
    2737                 :            :  *
    2738                 :            :  * The installation folders above are determined by looking up the
    2739                 :            :  * folder where the module (DLL or EXE) in question is located. If the
    2740                 :            :  * folder's name is "bin", its parent is used, otherwise the folder
    2741                 :            :  * itself.
    2742                 :            :  *
    2743                 :            :  * Note that on Windows the returned list can vary depending on where
    2744                 :            :  * this function is called.
    2745                 :            :  *
    2746                 :            :  * The return value is cached and modifying it at runtime is not supported, as
    2747                 :            :  * it’s not thread-safe to modify environment variables at runtime.
    2748                 :            :  *
    2749                 :            :  * Returns: (array zero-terminated=1) (element-type filename) (transfer none):
    2750                 :            :  *     a %NULL-terminated array of strings owned by GLib that must not be
    2751                 :            :  *     modified or freed.
    2752                 :            :  * 
    2753                 :            :  * Since: 2.6
    2754                 :            :  **/
    2755                 :            : const gchar * const * 
    2756                 :        117 : g_get_system_data_dirs (void)
    2757                 :            : {
    2758                 :            :   const gchar * const *system_data_dirs;
    2759                 :            : 
    2760                 :        117 :   G_LOCK (g_utils_global);
    2761                 :            : 
    2762         [ +  + ]:        117 :   if (g_system_data_dirs == NULL)
    2763                 :         56 :     g_system_data_dirs = g_build_system_data_dirs ();
    2764                 :        117 :   system_data_dirs = (const gchar * const *) g_system_data_dirs;
    2765                 :            : 
    2766                 :        117 :   G_UNLOCK (g_utils_global);
    2767                 :            : 
    2768                 :        117 :   return system_data_dirs;
    2769                 :            : }
    2770                 :            : 
    2771                 :            : static gchar **
    2772                 :         54 : g_build_system_config_dirs (void)
    2773                 :            : {
    2774                 :         54 :   gchar **conf_dir_vector = NULL;
    2775                 :         54 :   const gchar *conf_dirs = g_getenv ("XDG_CONFIG_DIRS");
    2776                 :            : #ifdef G_OS_WIN32
    2777                 :            :   if (conf_dirs)
    2778                 :            :     {
    2779                 :            :       conf_dir_vector = g_strsplit (conf_dirs, G_SEARCHPATH_SEPARATOR_S, 0);
    2780                 :            :     }
    2781                 :            :   else
    2782                 :            :     {
    2783                 :            :       gchar *special_conf_dirs = get_special_folder (&FOLDERID_ProgramData);
    2784                 :            : 
    2785                 :            :       if (special_conf_dirs)
    2786                 :            :         conf_dir_vector = g_strsplit (special_conf_dirs, G_SEARCHPATH_SEPARATOR_S, 0);
    2787                 :            :       else
    2788                 :            :         /* Return empty list */
    2789                 :            :         conf_dir_vector = g_strsplit ("", G_SEARCHPATH_SEPARATOR_S, 0);
    2790                 :            : 
    2791                 :            :       g_free (special_conf_dirs);
    2792                 :            :     }
    2793                 :            : #else
    2794   [ +  +  -  + ]:         54 :   if (!conf_dirs || !conf_dirs[0])
    2795                 :          6 :     conf_dirs = "/etc/xdg";
    2796                 :            : 
    2797                 :         54 :   conf_dir_vector = g_strsplit (conf_dirs, G_SEARCHPATH_SEPARATOR_S, 0);
    2798                 :            : #endif
    2799                 :            : 
    2800                 :         54 :   return g_steal_pointer (&conf_dir_vector);
    2801                 :            : }
    2802                 :            : 
    2803                 :            : /**
    2804                 :            :  * g_get_system_config_dirs:
    2805                 :            :  * 
    2806                 :            :  * Returns an ordered list of base directories in which to access 
    2807                 :            :  * system-wide configuration information.
    2808                 :            :  *
    2809                 :            :  * On UNIX platforms this is determined using the mechanisms described
    2810                 :            :  * in the
    2811                 :            :  * [XDG Base Directory Specification](http://www.freedesktop.org/Standards/basedir-spec).
    2812                 :            :  * In this case the list of directories retrieved will be `XDG_CONFIG_DIRS`.
    2813                 :            :  *
    2814                 :            :  * On Windows it follows XDG Base Directory Specification if `XDG_CONFIG_DIRS` is defined.
    2815                 :            :  * If `XDG_CONFIG_DIRS` is undefined, the directory that contains application
    2816                 :            :  * data for all users is used instead. A typical path is
    2817                 :            :  * `C:\Documents and Settings\All Users\Application Data`.
    2818                 :            :  * This folder is used for application data
    2819                 :            :  * that is not user specific. For example, an application can store
    2820                 :            :  * a spell-check dictionary, a database of clip art, or a log file in the
    2821                 :            :  * FOLDERID_ProgramData folder. This information will not roam and is available
    2822                 :            :  * to anyone using the computer.
    2823                 :            :  *
    2824                 :            :  * The return value is cached and modifying it at runtime is not supported, as
    2825                 :            :  * it’s not thread-safe to modify environment variables at runtime.
    2826                 :            :  *
    2827                 :            :  * Returns: (array zero-terminated=1) (element-type filename) (transfer none):
    2828                 :            :  *     a %NULL-terminated array of strings owned by GLib that must not be
    2829                 :            :  *     modified or freed.
    2830                 :            :  * 
    2831                 :            :  * Since: 2.6
    2832                 :            :  **/
    2833                 :            : const gchar * const *
    2834                 :        102 : g_get_system_config_dirs (void)
    2835                 :            : {
    2836                 :            :   const gchar * const *system_config_dirs;
    2837                 :            : 
    2838                 :        102 :   G_LOCK (g_utils_global);
    2839                 :            : 
    2840         [ +  + ]:        102 :   if (g_system_config_dirs == NULL)
    2841                 :         54 :     g_system_config_dirs = g_build_system_config_dirs ();
    2842                 :        102 :   system_config_dirs = (const gchar * const *) g_system_config_dirs;
    2843                 :            : 
    2844                 :        102 :   G_UNLOCK (g_utils_global);
    2845                 :            : 
    2846                 :        102 :   return system_config_dirs;
    2847                 :            : }
    2848                 :            : 
    2849                 :            : /**
    2850                 :            :  * g_nullify_pointer:
    2851                 :            :  * @nullify_location: (not nullable): the memory address of the pointer.
    2852                 :            :  *
    2853                 :            :  * Set the pointer at the specified location to %NULL.
    2854                 :            :  **/
    2855                 :            : void
    2856                 :        212 : g_nullify_pointer (gpointer *nullify_location)
    2857                 :            : {
    2858                 :        212 :   g_return_if_fail (nullify_location != NULL);
    2859                 :            : 
    2860                 :        212 :   *nullify_location = NULL;
    2861                 :            : }
    2862                 :            : 
    2863                 :            : #define KILOBYTE_FACTOR (G_GOFFSET_CONSTANT (1000))
    2864                 :            : #define MEGABYTE_FACTOR (KILOBYTE_FACTOR * KILOBYTE_FACTOR)
    2865                 :            : #define GIGABYTE_FACTOR (MEGABYTE_FACTOR * KILOBYTE_FACTOR)
    2866                 :            : #define TERABYTE_FACTOR (GIGABYTE_FACTOR * KILOBYTE_FACTOR)
    2867                 :            : #define PETABYTE_FACTOR (TERABYTE_FACTOR * KILOBYTE_FACTOR)
    2868                 :            : #define EXABYTE_FACTOR  (PETABYTE_FACTOR * KILOBYTE_FACTOR)
    2869                 :            : 
    2870                 :            : #define KIBIBYTE_FACTOR (G_GOFFSET_CONSTANT (1024))
    2871                 :            : #define MEBIBYTE_FACTOR (KIBIBYTE_FACTOR * KIBIBYTE_FACTOR)
    2872                 :            : #define GIBIBYTE_FACTOR (MEBIBYTE_FACTOR * KIBIBYTE_FACTOR)
    2873                 :            : #define TEBIBYTE_FACTOR (GIBIBYTE_FACTOR * KIBIBYTE_FACTOR)
    2874                 :            : #define PEBIBYTE_FACTOR (TEBIBYTE_FACTOR * KIBIBYTE_FACTOR)
    2875                 :            : #define EXBIBYTE_FACTOR (PEBIBYTE_FACTOR * KIBIBYTE_FACTOR)
    2876                 :            : 
    2877                 :            : /**
    2878                 :            :  * g_format_size:
    2879                 :            :  * @size: a size in bytes
    2880                 :            :  *
    2881                 :            :  * Formats a size (for example the size of a file) into a human readable
    2882                 :            :  * string.  Sizes are rounded to the nearest size prefix (kB, MB, GB)
    2883                 :            :  * and are displayed rounded to the nearest tenth. E.g. the file size
    2884                 :            :  * 3292528 bytes will be converted into the string "3.2 MB". The returned string
    2885                 :            :  * is UTF-8, and may use a non-breaking space to separate the number and units,
    2886                 :            :  * to ensure they aren’t separated when line wrapped.
    2887                 :            :  *
    2888                 :            :  * The prefix units base is 1000 (i.e. 1 kB is 1000 bytes).
    2889                 :            :  *
    2890                 :            :  * This string should be freed with g_free() when not needed any longer.
    2891                 :            :  *
    2892                 :            :  * See g_format_size_full() for more options about how the size might be
    2893                 :            :  * formatted.
    2894                 :            :  *
    2895                 :            :  * Returns: (transfer full): a newly-allocated formatted string containing
    2896                 :            :  *   a human readable file size
    2897                 :            :  *
    2898                 :            :  * Since: 2.30
    2899                 :            :  */
    2900                 :            : gchar *
    2901                 :          9 : g_format_size (guint64 size)
    2902                 :            : {
    2903                 :          9 :   return g_format_size_full (size, G_FORMAT_SIZE_DEFAULT);
    2904                 :            : }
    2905                 :            : 
    2906                 :            : /**
    2907                 :            :  * GFormatSizeFlags:
    2908                 :            :  * @G_FORMAT_SIZE_DEFAULT: behave the same as g_format_size()
    2909                 :            :  * @G_FORMAT_SIZE_LONG_FORMAT: include the exact number of bytes as part
    2910                 :            :  *     of the returned string.  For example, "45.6 kB (45,612 bytes)".
    2911                 :            :  * @G_FORMAT_SIZE_IEC_UNITS: use IEC (base 1024) units with "KiB"-style
    2912                 :            :  *     suffixes. IEC units should only be used for reporting things with
    2913                 :            :  *     a strong "power of 2" basis, like RAM sizes or RAID stripe sizes.
    2914                 :            :  *     Network and storage sizes should be reported in the normal SI units.
    2915                 :            :  * @G_FORMAT_SIZE_BITS: set the size as a quantity in bits, rather than
    2916                 :            :  *     bytes, and return units in bits. For example, ‘Mbit’ rather than ‘MB’.
    2917                 :            :  * @G_FORMAT_SIZE_ONLY_VALUE: return only value, without unit; this should
    2918                 :            :  *     not be used together with @G_FORMAT_SIZE_LONG_FORMAT
    2919                 :            :  *     nor @G_FORMAT_SIZE_ONLY_UNIT. Since: 2.74
    2920                 :            :  * @G_FORMAT_SIZE_ONLY_UNIT: return only unit, without value; this should
    2921                 :            :  *     not be used together with @G_FORMAT_SIZE_LONG_FORMAT
    2922                 :            :  *     nor @G_FORMAT_SIZE_ONLY_VALUE. Since: 2.74
    2923                 :            :  *
    2924                 :            :  * Flags to modify the format of the string returned by g_format_size_full().
    2925                 :            :  */
    2926                 :            : 
    2927                 :            : #pragma GCC diagnostic push
    2928                 :            : #pragma GCC diagnostic ignored "-Wformat-nonliteral"
    2929                 :            : 
    2930                 :            : /**
    2931                 :            :  * g_format_size_full:
    2932                 :            :  * @size: a size in bytes
    2933                 :            :  * @flags: #GFormatSizeFlags to modify the output
    2934                 :            :  *
    2935                 :            :  * Formats a size.
    2936                 :            :  *
    2937                 :            :  * This function is similar to g_format_size() but allows for flags
    2938                 :            :  * that modify the output. See #GFormatSizeFlags.
    2939                 :            :  *
    2940                 :            :  * Returns: (transfer full): a newly-allocated formatted string
    2941                 :            :  *   containing a human readable file size
    2942                 :            :  *
    2943                 :            :  * Since: 2.30
    2944                 :            :  */
    2945                 :            : gchar *
    2946                 :         67 : g_format_size_full (guint64          size,
    2947                 :            :                     GFormatSizeFlags flags)
    2948                 :            : {
    2949                 :            :   struct Format
    2950                 :            :   {
    2951                 :            :     guint64 factor;
    2952                 :            :     char string[10];
    2953                 :            :   };
    2954                 :            : 
    2955                 :            :   typedef enum
    2956                 :            :   {
    2957                 :            :     FORMAT_BYTES,
    2958                 :            :     FORMAT_BYTES_IEC,
    2959                 :            :     FORMAT_BITS,
    2960                 :            :     FORMAT_BITS_IEC
    2961                 :            :   } FormatIndex;
    2962                 :            : 
    2963                 :         67 :   const struct Format formats[4][6] = {
    2964                 :            :     {
    2965                 :            :       /* Translators: A unit symbol for size formatting, showing for example: "13.0 kB" */
    2966                 :            :       { KILOBYTE_FACTOR, N_("kB") },
    2967                 :            :       /* Translators: A unit symbol for size formatting, showing for example: "13.0 MB" */
    2968                 :            :       { MEGABYTE_FACTOR, N_("MB") },
    2969                 :            :       /* Translators: A unit symbol for size formatting, showing for example: "13.0 GB" */
    2970                 :            :       { GIGABYTE_FACTOR, N_("GB") },
    2971                 :            :       /* Translators: A unit symbol for size formatting, showing for example: "13.0 TB" */
    2972                 :            :       { TERABYTE_FACTOR, N_("TB") },
    2973                 :            :       /* Translators: A unit symbol for size formatting, showing for example: "13.0 PB" */
    2974                 :            :       { PETABYTE_FACTOR, N_("PB") },
    2975                 :            :       /* Translators: A unit symbol for size formatting, showing for example: "13.0 EB" */
    2976                 :            :       { EXABYTE_FACTOR,  N_("EB") }
    2977                 :            :     },
    2978                 :            :     {
    2979                 :            :       /* Translators: A unit symbol for size formatting, showing for example: "13.0 KiB" */
    2980                 :            :       { KIBIBYTE_FACTOR, N_("KiB") },
    2981                 :            :       /* Translators: A unit symbol for size formatting, showing for example: "13.0 MiB" */
    2982                 :            :       { MEBIBYTE_FACTOR, N_("MiB") },
    2983                 :            :       /* Translators: A unit symbol for size formatting, showing for example: "13.0 GiB" */
    2984                 :            :       { GIBIBYTE_FACTOR, N_("GiB") },
    2985                 :            :       /* Translators: A unit symbol for size formatting, showing for example: "13.0 TiB" */
    2986                 :            :       { TEBIBYTE_FACTOR, N_("TiB") },
    2987                 :            :       /* Translators: A unit symbol for size formatting, showing for example: "13.0 PiB" */
    2988                 :            :       { PEBIBYTE_FACTOR, N_("PiB") },
    2989                 :            :       /* Translators: A unit symbol for size formatting, showing for example: "13.0 EiB" */
    2990                 :            :       { EXBIBYTE_FACTOR, N_("EiB") }
    2991                 :            :     },
    2992                 :            :     {
    2993                 :            :       /* Translators: A unit symbol for size formatting, showing for example: "13.0 kbit" */
    2994                 :            :       { KILOBYTE_FACTOR, N_("kbit") },
    2995                 :            :       /* Translators: A unit symbol for size formatting, showing for example: "13.0 Mbit" */
    2996                 :            :       { MEGABYTE_FACTOR, N_("Mbit") },
    2997                 :            :       /* Translators: A unit symbol for size formatting, showing for example: "13.0 Gbit" */
    2998                 :            :       { GIGABYTE_FACTOR, N_("Gbit") },
    2999                 :            :       /* Translators: A unit symbol for size formatting, showing for example: "13.0 Tbit" */
    3000                 :            :       { TERABYTE_FACTOR, N_("Tbit") },
    3001                 :            :       /* Translators: A unit symbol for size formatting, showing for example: "13.0 Pbit" */
    3002                 :            :       { PETABYTE_FACTOR, N_("Pbit") },
    3003                 :            :       /* Translators: A unit symbol for size formatting, showing for example: "13.0 Ebit" */
    3004                 :            :       { EXABYTE_FACTOR,  N_("Ebit") }
    3005                 :            :     },
    3006                 :            :     {
    3007                 :            :       /* Translators: A unit symbol for size formatting, showing for example: "13.0 Kibit" */
    3008                 :            :       { KIBIBYTE_FACTOR, N_("Kibit") },
    3009                 :            :       /* Translators: A unit symbol for size formatting, showing for example: "13.0 Mibit" */
    3010                 :            :       { MEBIBYTE_FACTOR, N_("Mibit") },
    3011                 :            :       /* Translators: A unit symbol for size formatting, showing for example: "13.0 Gibit" */
    3012                 :            :       { GIBIBYTE_FACTOR, N_("Gibit") },
    3013                 :            :       /* Translators: A unit symbol for size formatting, showing for example: "13.0 Tibit" */
    3014                 :            :       { TEBIBYTE_FACTOR, N_("Tibit") },
    3015                 :            :       /* Translators: A unit symbol for size formatting, showing for example: "13.0 Pibit" */
    3016                 :            :       { PEBIBYTE_FACTOR, N_("Pibit") },
    3017                 :            :       /* Translators: A unit symbol for size formatting, showing for example: "13.0 Eibit" */
    3018                 :            :       { EXBIBYTE_FACTOR, N_("Eibit") }
    3019                 :            :     }
    3020                 :            :   };
    3021                 :            : 
    3022                 :            :   GString *string;
    3023                 :            :   FormatIndex index;
    3024                 :            : 
    3025                 :         67 :   g_return_val_if_fail ((flags & (G_FORMAT_SIZE_LONG_FORMAT | G_FORMAT_SIZE_ONLY_VALUE)) != (G_FORMAT_SIZE_LONG_FORMAT | G_FORMAT_SIZE_ONLY_VALUE), NULL);
    3026                 :         67 :   g_return_val_if_fail ((flags & (G_FORMAT_SIZE_LONG_FORMAT | G_FORMAT_SIZE_ONLY_UNIT)) != (G_FORMAT_SIZE_LONG_FORMAT | G_FORMAT_SIZE_ONLY_UNIT), NULL);
    3027                 :         67 :   g_return_val_if_fail ((flags & (G_FORMAT_SIZE_ONLY_VALUE | G_FORMAT_SIZE_ONLY_UNIT)) != (G_FORMAT_SIZE_ONLY_VALUE | G_FORMAT_SIZE_ONLY_UNIT), NULL);
    3028                 :            : 
    3029                 :         67 :   string = g_string_new (NULL);
    3030                 :            : 
    3031   [ +  +  +  +  :         67 :   switch (flags & ~(G_FORMAT_SIZE_LONG_FORMAT | G_FORMAT_SIZE_ONLY_VALUE | G_FORMAT_SIZE_ONLY_UNIT))
                      - ]
    3032                 :            :     {
    3033                 :         11 :     case G_FORMAT_SIZE_DEFAULT:
    3034                 :         11 :       index = FORMAT_BYTES;
    3035                 :         11 :       break;
    3036                 :         18 :     case (G_FORMAT_SIZE_DEFAULT | G_FORMAT_SIZE_IEC_UNITS):
    3037                 :         18 :       index = FORMAT_BYTES_IEC;
    3038                 :         18 :       break;
    3039                 :         19 :     case G_FORMAT_SIZE_BITS:
    3040                 :         19 :       index = FORMAT_BITS;
    3041                 :         19 :       break;
    3042                 :         19 :     case (G_FORMAT_SIZE_BITS | G_FORMAT_SIZE_IEC_UNITS):
    3043                 :         19 :       index = FORMAT_BITS_IEC;
    3044                 :         19 :       break;
    3045                 :          0 :     default:
    3046                 :            :       g_assert_not_reached ();
    3047                 :            :     }
    3048                 :            : 
    3049                 :            : 
    3050         [ +  + ]:         67 :   if (size < formats[index][0].factor)
    3051                 :            :     {
    3052                 :            :       const char * units;
    3053                 :            : 
    3054   [ +  +  +  + ]:         30 :       if (index == FORMAT_BYTES || index == FORMAT_BYTES_IEC)
    3055                 :            :         {
    3056                 :         12 :           units = g_dngettext (GETTEXT_PACKAGE, "byte", "bytes", (guint) size);
    3057                 :            :         }
    3058                 :            :       else
    3059                 :            :         {
    3060                 :         18 :           units = g_dngettext (GETTEXT_PACKAGE, "bit", "bits", (guint) size);
    3061                 :            :         }
    3062                 :            : 
    3063         [ +  + ]:         30 :       if ((flags & G_FORMAT_SIZE_ONLY_UNIT) != 0)
    3064                 :            :         g_string_append (string, units);
    3065         [ +  + ]:         21 :       else if ((flags & G_FORMAT_SIZE_ONLY_VALUE) != 0)
    3066                 :            :         /* Translators: The "%u" is replaced with the size value, like "13"; it could
    3067                 :            :          * be part of "13 bytes", but only the number is requested this time. */
    3068                 :          9 :         g_string_printf (string, C_("format-size", "%u"), (guint) size);
    3069                 :            :       else
    3070                 :            :         {
    3071                 :            :           /* Translators: The first "%u" is replaced with the value, the "%s" with a unit of the value.
    3072                 :            :            * The order can be changed with "%$2s %$1u". An example: "13 bytes" */
    3073                 :         12 :           g_string_printf (string, C_("format-size", "%u %s"), (guint) size, units);
    3074                 :            :         }
    3075                 :            : 
    3076                 :         30 :       flags &= ~G_FORMAT_SIZE_LONG_FORMAT;
    3077                 :            :     }
    3078                 :            :   else
    3079                 :            :     {
    3080                 :         37 :       const gsize n = G_N_ELEMENTS (formats[index]);
    3081                 :            :       const gchar * units;
    3082                 :            :       gdouble value;
    3083                 :            :       gsize i;
    3084                 :            : 
    3085                 :            :       /*
    3086                 :            :        * Point the last format (the highest unit) by default
    3087                 :            :        * and then then scan all formats, starting with the 2nd one
    3088                 :            :        * because the 1st is already managed by with the plural form
    3089                 :            :        */
    3090                 :         37 :       const struct Format * f = &formats[index][n - 1];
    3091                 :            : 
    3092         [ +  + ]:        110 :       for (i = 1; i < n; i++)
    3093                 :            :         {
    3094         [ +  + ]:        106 :           if (size < formats[index][i].factor)
    3095                 :            :             {
    3096                 :         33 :               f = &formats[index][i - 1];
    3097                 :         33 :               break;
    3098                 :            :             }
    3099                 :            :         }
    3100                 :            : 
    3101                 :         37 :       units = _(f->string);
    3102                 :         37 :       value = (gdouble) size / (gdouble) f->factor;
    3103                 :            : 
    3104         [ +  + ]:         37 :       if ((flags & G_FORMAT_SIZE_ONLY_UNIT) != 0)
    3105                 :            :         g_string_append (string, units);
    3106         [ +  + ]:         34 :       else if ((flags & G_FORMAT_SIZE_ONLY_VALUE) != 0)
    3107                 :            :         /* Translators: The "%.1f" is replaced with the size value, like "13.0"; it could
    3108                 :            :          * be part of "13.0 MB", but only the number is requested this time. */
    3109                 :          3 :         g_string_printf (string, C_("format-size", "%.1f"), value);
    3110                 :            :       else
    3111                 :            :         {
    3112                 :            :           /* Translators: The first "%.1f" is replaced with the value, the "%s" with a unit of the value.
    3113                 :            :            * The order can be changed with "%$2s %$1.1f". Keep the no-break space between the value and
    3114                 :            :            * the unit symbol. An example: "13.0 MB" */
    3115                 :         31 :           g_string_printf (string, C_("format-size", "%.1f %s"), value, units);
    3116                 :            :         }
    3117                 :            :     }
    3118                 :            : 
    3119         [ +  + ]:         67 :   if (flags & G_FORMAT_SIZE_LONG_FORMAT)
    3120                 :            :     {
    3121                 :            :       /* First problem: we need to use the number of bytes to decide on
    3122                 :            :        * the plural form that is used for display, but the number of
    3123                 :            :        * bytes potentially exceeds the size of a guint (which is what
    3124                 :            :        * ngettext() takes).
    3125                 :            :        *
    3126                 :            :        * From a pragmatic standpoint, it seems that all known languages
    3127                 :            :        * base plural forms on one or both of the following:
    3128                 :            :        *
    3129                 :            :        *   - the lowest digits of the number
    3130                 :            :        *
    3131                 :            :        *   - if the number if greater than some small value
    3132                 :            :        *
    3133                 :            :        * Here's how we fake it:  Draw an arbitrary line at one thousand.
    3134                 :            :        * If the number is below that, then fine.  If it is above it,
    3135                 :            :        * then we take the modulus of the number by one thousand (in
    3136                 :            :        * order to keep the lowest digits) and add one thousand to that
    3137                 :            :        * (in order to ensure that 1001 is not treated the same as 1).
    3138                 :            :        */
    3139         [ +  - ]:          3 :       guint plural_form = size < 1000 ? size : size % 1000 + 1000;
    3140                 :            : 
    3141                 :            :       /* Second problem: we need to translate the string "%u byte/bit" and
    3142                 :            :        * "%u bytes/bits" for pluralisation, but the correct number format to
    3143                 :            :        * use for a gsize is different depending on which architecture
    3144                 :            :        * we're on.
    3145                 :            :        *
    3146                 :            :        * Solution: format the number separately and use "%s bytes/bits" on
    3147                 :            :        * all platforms.
    3148                 :            :        */
    3149                 :            :       const gchar *translated_format;
    3150                 :            :       gchar *formatted_number;
    3151                 :            : 
    3152   [ +  +  -  + ]:          3 :       if (index == FORMAT_BYTES || index == FORMAT_BYTES_IEC)
    3153                 :            :         {
    3154                 :            :           /* Translators: the %s in "%s bytes" will always be replaced by a number. */
    3155                 :          1 :           translated_format = g_dngettext (GETTEXT_PACKAGE, "%s byte", "%s bytes", plural_form);
    3156                 :            :         }
    3157                 :            :       else
    3158                 :            :         {
    3159                 :            :           /* Translators: the %s in "%s bits" will always be replaced by a number. */
    3160                 :          2 :           translated_format = g_dngettext (GETTEXT_PACKAGE, "%s bit", "%s bits", plural_form);
    3161                 :            :         }
    3162                 :          3 :       formatted_number = g_strdup_printf ("%'"G_GUINT64_FORMAT, size);
    3163                 :            : 
    3164         [ +  - ]:          3 :       g_string_append (string, " (");
    3165                 :          3 :       g_string_append_printf (string, translated_format, formatted_number);
    3166                 :          3 :       g_free (formatted_number);
    3167         [ +  - ]:          6 :       g_string_append (string, ")");
    3168                 :            :     }
    3169                 :            : 
    3170                 :         67 :   return g_string_free (string, FALSE);
    3171                 :            : }
    3172                 :            : 
    3173                 :            : #pragma GCC diagnostic pop
    3174                 :            : 
    3175                 :            : /**
    3176                 :            :  * g_format_size_for_display:
    3177                 :            :  * @size: a size in bytes
    3178                 :            :  *
    3179                 :            :  * Formats a size (for example the size of a file) into a human
    3180                 :            :  * readable string. Sizes are rounded to the nearest size prefix
    3181                 :            :  * (KB, MB, GB) and are displayed rounded to the nearest tenth.
    3182                 :            :  * E.g. the file size 3292528 bytes will be converted into the
    3183                 :            :  * string "3.1 MB".
    3184                 :            :  *
    3185                 :            :  * The prefix units base is 1024 (i.e. 1 KB is 1024 bytes).
    3186                 :            :  *
    3187                 :            :  * This string should be freed with g_free() when not needed any longer.
    3188                 :            :  *
    3189                 :            :  * Returns: (transfer full): a newly-allocated formatted string
    3190                 :            :  *   containing a human readable file size
    3191                 :            :  *
    3192                 :            :  * Since: 2.16
    3193                 :            :  *
    3194                 :            :  * Deprecated:2.30: This function is broken due to its use of SI
    3195                 :            :  *     suffixes to denote IEC units. Use g_format_size() instead.
    3196                 :            :  */
    3197                 :            : gchar *
    3198                 :          9 : g_format_size_for_display (goffset size)
    3199                 :            : {
    3200         [ +  + ]:          9 :   if (size < (goffset) KIBIBYTE_FACTOR)
    3201                 :          3 :     return g_strdup_printf (g_dngettext(GETTEXT_PACKAGE, "%u byte", "%u bytes",(guint) size), (guint) size);
    3202                 :            :   else
    3203                 :            :     {
    3204                 :            :       gdouble displayed_size;
    3205                 :            : 
    3206         [ +  + ]:          6 :       if (size < (goffset) MEBIBYTE_FACTOR)
    3207                 :            :         {
    3208                 :          1 :           displayed_size = (gdouble) size / (gdouble) KIBIBYTE_FACTOR;
    3209                 :            :           /* Translators: this is from the deprecated function g_format_size_for_display() which uses 'KB' to
    3210                 :            :            * mean 1024 bytes.  I am aware that 'KB' is not correct, but it has been preserved for reasons of
    3211                 :            :            * compatibility.  Users will not see this string unless a program is using this deprecated function.
    3212                 :            :            * Please translate as literally as possible.
    3213                 :            :            */
    3214                 :          1 :           return g_strdup_printf (_("%.1f KB"), displayed_size);
    3215                 :            :         }
    3216         [ +  + ]:          5 :       else if (size < (goffset) GIBIBYTE_FACTOR)
    3217                 :            :         {
    3218                 :          1 :           displayed_size = (gdouble) size / (gdouble) MEBIBYTE_FACTOR;
    3219                 :          1 :           return g_strdup_printf (_("%.1f MB"), displayed_size);
    3220                 :            :         }
    3221         [ +  + ]:          4 :       else if (size < (goffset) TEBIBYTE_FACTOR)
    3222                 :            :         {
    3223                 :          1 :           displayed_size = (gdouble) size / (gdouble) GIBIBYTE_FACTOR;
    3224                 :          1 :           return g_strdup_printf (_("%.1f GB"), displayed_size);
    3225                 :            :         }
    3226         [ +  + ]:          3 :       else if (size < (goffset) PEBIBYTE_FACTOR)
    3227                 :            :         {
    3228                 :          1 :           displayed_size = (gdouble) size / (gdouble) TEBIBYTE_FACTOR;
    3229                 :          1 :           return g_strdup_printf (_("%.1f TB"), displayed_size);
    3230                 :            :         }
    3231         [ +  + ]:          2 :       else if (size < (goffset) EXBIBYTE_FACTOR)
    3232                 :            :         {
    3233                 :          1 :           displayed_size = (gdouble) size / (gdouble) PEBIBYTE_FACTOR;
    3234                 :          1 :           return g_strdup_printf (_("%.1f PB"), displayed_size);
    3235                 :            :         }
    3236                 :            :       else
    3237                 :            :         {
    3238                 :          1 :           displayed_size = (gdouble) size / (gdouble) EXBIBYTE_FACTOR;
    3239                 :          1 :           return g_strdup_printf (_("%.1f EB"), displayed_size);
    3240                 :            :         }
    3241                 :            :     }
    3242                 :            : }
    3243                 :            : 
    3244                 :            : #if defined (G_OS_WIN32) && !defined (_WIN64)
    3245                 :            : 
    3246                 :            : /* Binary compatibility versions. Not for newly compiled code. */
    3247                 :            : 
    3248                 :            : _GLIB_EXTERN const gchar *g_get_user_name_utf8        (void);
    3249                 :            : _GLIB_EXTERN const gchar *g_get_real_name_utf8        (void);
    3250                 :            : _GLIB_EXTERN const gchar *g_get_home_dir_utf8         (void);
    3251                 :            : _GLIB_EXTERN const gchar *g_get_tmp_dir_utf8          (void);
    3252                 :            : _GLIB_EXTERN gchar       *g_find_program_in_path_utf8 (const gchar *program);
    3253                 :            : 
    3254                 :            : gchar *
    3255                 :            : g_find_program_in_path_utf8 (const gchar *program)
    3256                 :            : {
    3257                 :            :   return g_find_program_in_path (program);
    3258                 :            : }
    3259                 :            : 
    3260                 :            : const gchar *g_get_user_name_utf8 (void) { return g_get_user_name (); }
    3261                 :            : const gchar *g_get_real_name_utf8 (void) { return g_get_real_name (); }
    3262                 :            : const gchar *g_get_home_dir_utf8 (void) { return g_get_home_dir (); }
    3263                 :            : const gchar *g_get_tmp_dir_utf8 (void) { return g_get_tmp_dir (); }
    3264                 :            : 
    3265                 :            : #endif
    3266                 :            : 
    3267                 :            : /* Private API:
    3268                 :            :  *
    3269                 :            :  * Returns %TRUE if the current process was executed as setuid
    3270                 :            :  */ 
    3271                 :            : gboolean
    3272                 :       3686 : g_check_setuid (void)
    3273                 :            : {
    3274                 :            : #if defined(HAVE_SYS_AUXV_H) && defined(HAVE_GETAUXVAL) && defined(AT_SECURE)
    3275                 :            :   unsigned long value;
    3276                 :            :   int errsv;
    3277                 :            : 
    3278                 :       3686 :   errno = 0;
    3279                 :       3686 :   value = getauxval (AT_SECURE);
    3280                 :       3686 :   errsv = errno;
    3281         [ -  + ]:       3686 :   if (errsv)
    3282                 :          0 :     g_error ("getauxval () failed: %s", g_strerror (errsv));
    3283                 :       3686 :   return value;
    3284                 :            : #elif defined(HAVE_ISSETUGID) && !defined(__ANDROID__)
    3285                 :            :   /* BSD: http://www.freebsd.org/cgi/man.cgi?query=issetugid&sektion=2 */
    3286                 :            : 
    3287                 :            :   /* Android had it in older versions but the new 64 bit ABI does not
    3288                 :            :    * have it anymore, and some versions of the 32 bit ABI neither.
    3289                 :            :    * https://code.google.com/p/android-developer-preview/issues/detail?id=168
    3290                 :            :    */
    3291                 :            :   return issetugid ();
    3292                 :            : #elif defined(G_OS_UNIX)
    3293                 :            :   uid_t ruid, euid, suid; /* Real, effective and saved user ID's */
    3294                 :            :   gid_t rgid, egid, sgid; /* Real, effective and saved group ID's */
    3295                 :            : 
    3296                 :            :   static gsize check_setuid_initialised;
    3297                 :            :   static gboolean is_setuid;
    3298                 :            : 
    3299                 :            :   if (g_once_init_enter (&check_setuid_initialised))
    3300                 :            :     {
    3301                 :            : #ifdef HAVE_GETRESUID
    3302                 :            :       /* These aren't in the header files, so we prototype them here.
    3303                 :            :        */
    3304                 :            :       int getresuid(uid_t *ruid, uid_t *euid, uid_t *suid);
    3305                 :            :       int getresgid(gid_t *rgid, gid_t *egid, gid_t *sgid);
    3306                 :            :       
    3307                 :            :       if (getresuid (&ruid, &euid, &suid) != 0 ||
    3308                 :            :           getresgid (&rgid, &egid, &sgid) != 0)
    3309                 :            : #endif /* HAVE_GETRESUID */
    3310                 :            :         {
    3311                 :            :           suid = ruid = getuid ();
    3312                 :            :           sgid = rgid = getgid ();
    3313                 :            :           euid = geteuid ();
    3314                 :            :           egid = getegid ();
    3315                 :            :         }
    3316                 :            : 
    3317                 :            :       is_setuid = (ruid != euid || ruid != suid ||
    3318                 :            :                    rgid != egid || rgid != sgid);
    3319                 :            : 
    3320                 :            :       g_once_init_leave (&check_setuid_initialised, 1);
    3321                 :            :     }
    3322                 :            :   return is_setuid;
    3323                 :            : #else
    3324                 :            :   return FALSE;
    3325                 :            : #endif
    3326                 :            : }
    3327                 :            : 
    3328                 :            : #ifdef G_OS_WIN32
    3329                 :            : /**
    3330                 :            :  * g_abort:
    3331                 :            :  *
    3332                 :            :  * A wrapper for the POSIX abort() function.
    3333                 :            :  *
    3334                 :            :  * On Windows it is a function that makes extra effort (including a call
    3335                 :            :  * to abort()) to ensure that a debugger-catchable exception is thrown
    3336                 :            :  * before the program terminates.
    3337                 :            :  *
    3338                 :            :  * See your C library manual for more details about abort().
    3339                 :            :  *
    3340                 :            :  * Since: 2.50
    3341                 :            :  */
    3342                 :            : void
    3343                 :            : g_abort (void)
    3344                 :            : {
    3345                 :            :   /* One call to break the debugger
    3346                 :            :    * We check if a debugger is actually attached to
    3347                 :            :    * avoid a windows error reporting popup window
    3348                 :            :    * when run in a test harness / on CI
    3349                 :            :    */
    3350                 :            :   if (IsDebuggerPresent ())
    3351                 :            :     DebugBreak ();
    3352                 :            :   /* One call in case CRT changes its abort() behaviour */
    3353                 :            :   abort ();
    3354                 :            :   /* And one call to bind them all and terminate the program for sure */
    3355                 :            :   ExitProcess (127);
    3356                 :            : }
    3357                 :            : #endif

Generated by: LCOV version 1.14