Change LGPL-2.1+ to LGPL-2.1-or-later
[platform/upstream/glib.git] / glib / gutils.c
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 /**
83  * SECTION:misc_utils
84  * @title: Miscellaneous Utility Functions
85  * @short_description: a selection of portable utility functions
86  *
87  * These are portable utility functions.
88  */
89
90 #ifdef G_PLATFORM_WIN32
91 #  include <windows.h>
92 #  ifndef GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS
93 #    define GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT 2
94 #    define GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS 4
95 #  endif
96 #  include <lmcons.h>           /* For UNLEN */
97 #endif /* G_PLATFORM_WIN32 */
98
99 #ifdef G_OS_WIN32
100 #  include <direct.h>
101 #  include <shlobj.h>
102 #  include <process.h>
103 #endif
104
105 #ifdef HAVE_CODESET
106 #include <langinfo.h>
107 #endif
108
109 /**
110  * g_memmove: 
111  * @dest: the destination address to copy the bytes to.
112  * @src: the source address to copy the bytes from.
113  * @len: the number of bytes to copy.
114  *
115  * Copies a block of memory @len bytes long, from @src to @dest.
116  * The source and destination areas may overlap.
117  *
118  * Deprecated:2.40: Just use memmove().
119  */
120
121 #ifdef G_OS_WIN32
122 #undef g_atexit
123 #endif
124
125 /**
126  * g_atexit:
127  * @func: (scope async): the function to call on normal program termination.
128  * 
129  * Specifies a function to be called at normal program termination.
130  *
131  * Since GLib 2.8.2, on Windows g_atexit() actually is a preprocessor
132  * macro that maps to a call to the atexit() function in the C
133  * library. This means that in case the code that calls g_atexit(),
134  * i.e. atexit(), is in a DLL, the function will be called when the
135  * DLL is detached from the program. This typically makes more sense
136  * than that the function is called when the GLib DLL is detached,
137  * which happened earlier when g_atexit() was a function in the GLib
138  * DLL.
139  *
140  * The behaviour of atexit() in the context of dynamically loaded
141  * modules is not formally specified and varies wildly.
142  *
143  * On POSIX systems, calling g_atexit() (or atexit()) in a dynamically
144  * loaded module which is unloaded before the program terminates might
145  * well cause a crash at program exit.
146  *
147  * Some POSIX systems implement atexit() like Windows, and have each
148  * dynamically loaded module maintain an own atexit chain that is
149  * called when the module is unloaded.
150  *
151  * On other POSIX systems, before a dynamically loaded module is
152  * unloaded, the registered atexit functions (if any) residing in that
153  * module are called, regardless where the code that registered them
154  * resided. This is presumably the most robust approach.
155  *
156  * As can be seen from the above, for portability it's best to avoid
157  * calling g_atexit() (or atexit()) except in the main executable of a
158  * program.
159  *
160  * Deprecated:2.32: It is best to avoid g_atexit().
161  */
162 G_GNUC_BEGIN_IGNORE_DEPRECATIONS
163 void
164 g_atexit (GVoidFunc func)
165 {
166   gint result;
167   int errsv;
168
169   result = atexit ((void (*)(void)) func);
170   errsv = errno;
171   if (result)
172     {
173       g_error ("Could not register atexit() function: %s",
174                g_strerror (errsv));
175     }
176 }
177 G_GNUC_END_IGNORE_DEPRECATIONS
178
179 /* Based on execvp() from GNU Libc.
180  * Some of this code is cut-and-pasted into gspawn.c
181  */
182
183 static gchar*
184 my_strchrnul (const gchar *str, 
185               gchar        c)
186 {
187   gchar *p = (gchar*)str;
188   while (*p && (*p != c))
189     ++p;
190
191   return p;
192 }
193
194 #ifdef G_OS_WIN32
195
196 static gchar *inner_find_program_in_path (const gchar *program);
197
198 gchar*
199 g_find_program_in_path (const gchar *program)
200 {
201   const gchar *last_dot = strrchr (program, '.');
202
203   if (last_dot == NULL ||
204       strchr (last_dot, '\\') != NULL ||
205       strchr (last_dot, '/') != NULL)
206     {
207       const gint program_length = strlen (program);
208       gchar *pathext = g_build_path (";",
209                                      ".exe;.cmd;.bat;.com",
210                                      g_getenv ("PATHEXT"),
211                                      NULL);
212       gchar *p;
213       gchar *decorated_program;
214       gchar *retval;
215
216       p = pathext;
217       do
218         {
219           gchar *q = my_strchrnul (p, ';');
220
221           decorated_program = g_malloc (program_length + (q-p) + 1);
222           memcpy (decorated_program, program, program_length);
223           memcpy (decorated_program+program_length, p, q-p);
224           decorated_program [program_length + (q-p)] = '\0';
225           
226           retval = inner_find_program_in_path (decorated_program);
227           g_free (decorated_program);
228
229           if (retval != NULL)
230             {
231               g_free (pathext);
232               return retval;
233             }
234           p = q;
235         } while (*p++ != '\0');
236       g_free (pathext);
237       return NULL;
238     }
239   else
240     return inner_find_program_in_path (program);
241 }
242
243 #endif
244
245 /**
246  * g_find_program_in_path:
247  * @program: (type filename): a program name in the GLib file name encoding
248  * 
249  * Locates the first executable named @program in the user's path, in the
250  * same way that execvp() would locate it. Returns an allocated string
251  * with the absolute path name, or %NULL if the program is not found in
252  * the path. If @program is already an absolute path, returns a copy of
253  * @program if @program exists and is executable, and %NULL otherwise.
254  *  
255  * On Windows, if @program does not have a file type suffix, tries
256  * with the suffixes .exe, .cmd, .bat and .com, and the suffixes in
257  * the `PATHEXT` environment variable. 
258  * 
259  * On Windows, it looks for the file in the same way as CreateProcess() 
260  * would. This means first in the directory where the executing
261  * program was loaded from, then in the current directory, then in the
262  * Windows 32-bit system directory, then in the Windows directory, and
263  * finally in the directories in the `PATH` environment variable. If
264  * the program is found, the return value contains the full name
265  * including the type suffix.
266  *
267  * Returns: (type filename) (transfer full) (nullable): a newly-allocated
268  *   string with the absolute path, or %NULL
269  **/
270 #ifdef G_OS_WIN32
271 static gchar *
272 inner_find_program_in_path (const gchar *program)
273 #else
274 gchar*
275 g_find_program_in_path (const gchar *program)
276 #endif
277 {
278   return g_find_program_for_path (program, NULL, NULL);
279 }
280
281 /**
282  * g_find_program_for_path:
283  * @program: (type filename): a program name in the GLib file name encoding
284  * @path: (type filename) (nullable): the current dir where to search program
285  * @working_dir: (type filename) (nullable): the working dir where to search
286  *   program
287  *
288  * Locates the first executable named @program in @path, in the
289  * same way that execvp() would locate it. Returns an allocated string
290  * with the absolute path name (taking in account the @working_dir), or
291  * %NULL if the program is not found in @path. If @program is already an
292  * absolute path, returns a copy of @program if @program exists and is
293  * executable, and %NULL otherwise.
294  *
295  * On Windows, if @path is %NULL, it looks for the file in the same way as
296  * CreateProcess()  would. This means first in the directory where the
297  * executing program was loaded from, then in the current directory, then in
298  * the Windows 32-bit system directory, then in the Windows directory, and
299  * finally in the directories in the `PATH` environment variable. If
300  * the program is found, the return value contains the full name
301  * including the type suffix.
302  *
303  * Returns: (type filename) (transfer full) (nullable): a newly-allocated
304  *   string with the absolute path, or %NULL
305  * Since: 2.76
306  **/
307 char *
308 g_find_program_for_path (const char *program,
309                          const char *path,
310                          const char *working_dir)
311 {
312   const char *original_path = path;
313   const char *original_program = program;
314   char *program_path = NULL;
315   const gchar *p;
316   gchar *name, *freeme;
317 #ifdef G_OS_WIN32
318   const gchar *path_copy;
319   gchar *filename = NULL, *appdir = NULL;
320   gchar *sysdir = NULL, *windir = NULL;
321   int n;
322   wchar_t wfilename[MAXPATHLEN], wsysdir[MAXPATHLEN],
323     wwindir[MAXPATHLEN];
324 #endif
325   gsize len;
326   gsize pathlen;
327
328   g_return_val_if_fail (program != NULL, NULL);
329
330   /* Use the working dir as program path if provided */
331   if (working_dir && !g_path_is_absolute (program))
332     {
333       program_path = g_build_filename (working_dir, program, NULL);
334       program = program_path;
335     }
336
337   /* If it is an absolute path, or a relative path including subdirectories,
338    * don't look in PATH.
339    */
340   if (g_path_is_absolute (program)
341       || strchr (original_program, G_DIR_SEPARATOR) != NULL
342 #ifdef G_OS_WIN32
343       || strchr (original_program, '/') != NULL
344 #endif
345       )
346     {
347       if (g_file_test (program, G_FILE_TEST_IS_EXECUTABLE) &&
348           !g_file_test (program, G_FILE_TEST_IS_DIR))
349         {
350           gchar *out = NULL;
351
352           if (g_path_is_absolute (program))
353             {
354               out = g_strdup (program);
355             }
356           else
357             {
358               char *cwd = g_get_current_dir ();
359               out = g_build_filename (cwd, program, NULL);
360               g_free (cwd);
361             }
362
363           g_free (program_path);
364
365           return g_steal_pointer (&out);
366         }
367       else
368         {
369           g_clear_pointer (&program_path, g_free);
370
371           if (g_path_is_absolute (original_program))
372             return NULL;
373         }
374     }
375
376   program = original_program;
377
378   if G_LIKELY (original_path == NULL)
379     path = g_getenv ("PATH");
380   else
381     path = original_path;
382
383 #if defined(G_OS_UNIX)
384   if (path == NULL)
385     {
386       /* There is no 'PATH' in the environment.  The default
387        * search path in GNU libc is the current directory followed by
388        * the path 'confstr' returns for '_CS_PATH'.
389        */
390       
391       /* In GLib we put . last, for security, and don't use the
392        * unportable confstr(); UNIX98 does not actually specify
393        * what to search if PATH is unset. POSIX may, dunno.
394        */
395       
396       path = "/bin:/usr/bin:.";
397     }
398 #else
399   if G_LIKELY (original_path == NULL)
400     {
401       n = GetModuleFileNameW (NULL, wfilename, MAXPATHLEN);
402       if (n > 0 && n < MAXPATHLEN)
403         filename = g_utf16_to_utf8 (wfilename, -1, NULL, NULL, NULL);
404
405       n = GetSystemDirectoryW (wsysdir, MAXPATHLEN);
406       if (n > 0 && n < MAXPATHLEN)
407         sysdir = g_utf16_to_utf8 (wsysdir, -1, NULL, NULL, NULL);
408
409       n = GetWindowsDirectoryW (wwindir, MAXPATHLEN);
410       if (n > 0 && n < MAXPATHLEN)
411         windir = g_utf16_to_utf8 (wwindir, -1, NULL, NULL, NULL);
412
413       if (filename)
414         {
415           appdir = g_path_get_dirname (filename);
416           g_free (filename);
417         }
418
419       path = g_strdup (path);
420
421       if (windir)
422         {
423           const gchar *tem = path;
424           path = g_strconcat (windir, ";", path, NULL);
425           g_free ((gchar *) tem);
426           g_free (windir);
427         }
428
429       if (sysdir)
430         {
431           const gchar *tem = path;
432           path = g_strconcat (sysdir, ";", path, NULL);
433           g_free ((gchar *) tem);
434           g_free (sysdir);
435         }
436
437       {
438         const gchar *tem = path;
439         path = g_strconcat (".;", path, NULL);
440         g_free ((gchar *) tem);
441       }
442
443       if (appdir)
444         {
445           const gchar *tem = path;
446           path = g_strconcat (appdir, ";", path, NULL);
447           g_free ((gchar *) tem);
448           g_free (appdir);
449         }
450
451       path_copy = path;
452     }
453   else
454     {
455       path_copy = g_strdup (path);
456     }
457
458 #endif
459   
460   len = strlen (program) + 1;
461   pathlen = strlen (path);
462   freeme = name = g_malloc (pathlen + len + 1);
463   
464   /* Copy the file name at the top, including '\0'  */
465   memcpy (name + pathlen + 1, program, len);
466   name = name + pathlen;
467   /* And add the slash before the filename  */
468   *name = G_DIR_SEPARATOR;
469   
470   p = path;
471   do
472     {
473       char *startp;
474       char *startp_path = NULL;
475
476       path = p;
477       p = my_strchrnul (path, G_SEARCHPATH_SEPARATOR);
478
479       if (p == path)
480         /* Two adjacent colons, or a colon at the beginning or the end
481          * of 'PATH' means to search the current directory.
482          */
483         startp = name + 1;
484       else
485         startp = memcpy (name - (p - path), path, p - path);
486
487       /* Use the working dir as program path if provided */
488       if (working_dir && !g_path_is_absolute (startp))
489         {
490           startp_path = g_build_filename (working_dir, startp, NULL);
491           startp = startp_path;
492         }
493
494       if (g_file_test (startp, G_FILE_TEST_IS_EXECUTABLE) &&
495           !g_file_test (startp, G_FILE_TEST_IS_DIR))
496         {
497           gchar *ret;
498           if (g_path_is_absolute (startp)) {
499             ret = g_strdup (startp);
500           } else {
501             gchar *cwd = NULL;
502             cwd = g_get_current_dir ();
503             ret = g_build_filename (cwd, startp, NULL);
504             g_free (cwd);
505           }
506
507           g_free (program_path);
508           g_free (startp_path);
509           g_free (freeme);
510 #ifdef G_OS_WIN32
511           g_free ((gchar *) path_copy);
512 #endif
513           return ret;
514         }
515
516       g_free (startp_path);
517     }
518   while (*p++ != '\0');
519
520   g_free (program_path);
521   g_free (freeme);
522 #ifdef G_OS_WIN32
523   g_free ((gchar *) path_copy);
524 #endif
525
526   return NULL;
527 }
528
529 /* The functions below are defined this way for compatibility reasons.
530  * See the note in gutils.h.
531  */
532
533 /**
534  * g_bit_nth_lsf:
535  * @mask: a #gulong containing flags
536  * @nth_bit: the index of the bit to start the search from
537  *
538  * Find the position of the first bit set in @mask, searching
539  * from (but not including) @nth_bit upwards. Bits are numbered
540  * from 0 (least significant) to sizeof(#gulong) * 8 - 1 (31 or 63,
541  * usually). To start searching from the 0th bit, set @nth_bit to -1.
542  *
543  * Returns: the index of the first bit set which is higher than @nth_bit, or -1
544  *    if no higher bits are set
545  */
546 gint
547 (g_bit_nth_lsf) (gulong mask,
548                  gint   nth_bit)
549 {
550   return g_bit_nth_lsf_impl (mask, nth_bit);
551 }
552
553 /**
554  * g_bit_nth_msf:
555  * @mask: a #gulong containing flags
556  * @nth_bit: the index of the bit to start the search from
557  *
558  * Find the position of the first bit set in @mask, searching
559  * from (but not including) @nth_bit downwards. Bits are numbered
560  * from 0 (least significant) to sizeof(#gulong) * 8 - 1 (31 or 63,
561  * usually). To start searching from the last bit, set @nth_bit to
562  * -1 or GLIB_SIZEOF_LONG * 8.
563  *
564  * Returns: the index of the first bit set which is lower than @nth_bit, or -1
565  *    if no lower bits are set
566  */
567 gint
568 (g_bit_nth_msf) (gulong mask,
569                  gint   nth_bit)
570 {
571   return g_bit_nth_msf_impl (mask, nth_bit);
572 }
573
574
575 /**
576  * g_bit_storage:
577  * @number: a #guint
578  *
579  * Gets the number of bits used to hold @number,
580  * e.g. if @number is 4, 3 bits are needed.
581  *
582  * Returns: the number of bits used to hold @number
583  */
584 guint
585 (g_bit_storage) (gulong number)
586 {
587   return g_bit_storage_impl (number);
588 }
589
590 G_LOCK_DEFINE_STATIC (g_utils_global);
591
592 typedef struct
593 {
594   gchar *user_name;
595   gchar *real_name;
596   gchar *home_dir;
597 } UserDatabaseEntry;
598
599 /* These must all be read/written with @g_utils_global held. */
600 static  gchar   *g_user_data_dir = NULL;
601 static  gchar  **g_system_data_dirs = NULL;
602 static  gchar   *g_user_cache_dir = NULL;
603 static  gchar   *g_user_config_dir = NULL;
604 static  gchar   *g_user_state_dir = NULL;
605 static  gchar   *g_user_runtime_dir = NULL;
606 static  gchar  **g_system_config_dirs = NULL;
607 static  gchar  **g_user_special_dirs = NULL;
608 static  gchar   *g_tmp_dir = NULL;
609
610 /* fifteen minutes of fame for everybody */
611 #define G_USER_DIRS_EXPIRE      15 * 60
612
613 #ifdef G_OS_WIN32
614
615 static gchar *
616 get_special_folder (REFKNOWNFOLDERID known_folder_guid_ptr)
617 {
618   wchar_t *wcp = NULL;
619   gchar *result = NULL;
620   HRESULT hr;
621
622   hr = SHGetKnownFolderPath (known_folder_guid_ptr, 0, NULL, &wcp);
623
624   if (SUCCEEDED (hr))
625     result = g_utf16_to_utf8 (wcp, -1, NULL, NULL, NULL);
626
627   CoTaskMemFree (wcp);
628
629   return result;
630 }
631
632 static char *
633 get_windows_directory_root (void)
634 {
635   wchar_t wwindowsdir[MAX_PATH];
636
637   if (GetWindowsDirectoryW (wwindowsdir, G_N_ELEMENTS (wwindowsdir)))
638     {
639       /* Usually X:\Windows, but in terminal server environments
640        * might be an UNC path, AFAIK.
641        */
642       char *windowsdir = g_utf16_to_utf8 (wwindowsdir, -1, NULL, NULL, NULL);
643       char *p;
644
645       if (windowsdir == NULL)
646         return g_strdup ("C:\\");
647
648       p = (char *) g_path_skip_root (windowsdir);
649       if (G_IS_DIR_SEPARATOR (p[-1]) && p[-2] != ':')
650         p--;
651       *p = '\0';
652       return windowsdir;
653     }
654   else
655     return g_strdup ("C:\\");
656 }
657
658 #endif
659
660 /* HOLDS: g_utils_global_lock */
661 static UserDatabaseEntry *
662 g_get_user_database_entry (void)
663 {
664   static UserDatabaseEntry *entry;
665
666   if (g_once_init_enter (&entry))
667     {
668       static UserDatabaseEntry e;
669
670 #ifdef G_OS_UNIX
671       {
672         struct passwd *pw = NULL;
673         gpointer buffer = NULL;
674         gint error;
675         gchar *logname;
676
677 #  if defined (HAVE_GETPWUID_R)
678         struct passwd pwd;
679 #    ifdef _SC_GETPW_R_SIZE_MAX
680         /* This reurns the maximum length */
681         glong bufsize = sysconf (_SC_GETPW_R_SIZE_MAX);
682
683         if (bufsize < 0)
684           bufsize = 64;
685 #    else /* _SC_GETPW_R_SIZE_MAX */
686         glong bufsize = 64;
687 #    endif /* _SC_GETPW_R_SIZE_MAX */
688
689         logname = (gchar *) g_getenv ("LOGNAME");
690
691         do
692           {
693             g_free (buffer);
694             /* we allocate 6 extra bytes to work around a bug in
695              * Mac OS < 10.3. See #156446
696              */
697             buffer = g_malloc (bufsize + 6);
698             errno = 0;
699
700             if (logname) {
701               error = getpwnam_r (logname, &pwd, buffer, bufsize, &pw);
702               if (!pw || (pw->pw_uid != getuid ())) {
703                 /* LOGNAME is lying, fall back to looking up the uid */
704                 error = getpwuid_r (getuid (), &pwd, buffer, bufsize, &pw);
705               }
706             } else {
707               error = getpwuid_r (getuid (), &pwd, buffer, bufsize, &pw);
708             }
709             error = error < 0 ? errno : error;
710
711             if (!pw)
712               {
713                 /* we bail out prematurely if the user id can't be found
714                  * (should be pretty rare case actually), or if the buffer
715                  * should be sufficiently big and lookups are still not
716                  * successful.
717                  */
718                 if (error == 0 || error == ENOENT)
719                   {
720                     g_warning ("getpwuid_r(): failed due to unknown user id (%lu)",
721                                (gulong) getuid ());
722                     break;
723                   }
724                 if (bufsize > 32 * 1024)
725                   {
726                     g_warning ("getpwuid_r(): failed due to: %s.",
727                                g_strerror (error));
728                     break;
729                   }
730
731                 bufsize *= 2;
732               }
733           }
734         while (!pw);
735 #  endif /* HAVE_GETPWUID_R */
736
737         if (!pw)
738           {
739             pw = getpwuid (getuid ());
740           }
741         if (pw)
742           {
743             e.user_name = g_strdup (pw->pw_name);
744
745 #ifndef __BIONIC__
746             if (pw->pw_gecos && *pw->pw_gecos != '\0' && pw->pw_name)
747               {
748                 gchar **gecos_fields;
749                 gchar **name_parts;
750                 gchar *uppercase_pw_name;
751
752                 /* split the gecos field and substitute '&' */
753                 gecos_fields = g_strsplit (pw->pw_gecos, ",", 0);
754                 name_parts = g_strsplit (gecos_fields[0], "&", 0);
755                 uppercase_pw_name = g_strdup (pw->pw_name);
756                 uppercase_pw_name[0] = g_ascii_toupper (uppercase_pw_name[0]);
757                 e.real_name = g_strjoinv (uppercase_pw_name, name_parts);
758                 g_strfreev (gecos_fields);
759                 g_strfreev (name_parts);
760                 g_free (uppercase_pw_name);
761               }
762 #endif
763
764             if (!e.home_dir)
765               e.home_dir = g_strdup (pw->pw_dir);
766           }
767         g_free (buffer);
768       }
769
770 #endif /* G_OS_UNIX */
771
772 #ifdef G_OS_WIN32
773       {
774         guint len = UNLEN+1;
775         wchar_t buffer[UNLEN+1];
776
777         if (GetUserNameW (buffer, (LPDWORD) &len))
778           {
779             e.user_name = g_utf16_to_utf8 (buffer, -1, NULL, NULL, NULL);
780             e.real_name = g_strdup (e.user_name);
781           }
782       }
783 #endif /* G_OS_WIN32 */
784
785       if (!e.user_name)
786         e.user_name = g_strdup ("somebody");
787       if (!e.real_name)
788         e.real_name = g_strdup ("Unknown");
789
790       g_once_init_leave (&entry, &e);
791     }
792
793   return entry;
794 }
795
796 /**
797  * g_get_user_name:
798  *
799  * Gets the user name of the current user. The encoding of the returned
800  * string is system-defined. On UNIX, it might be the preferred file name
801  * encoding, or something else, and there is no guarantee that it is even
802  * consistent on a machine. On Windows, it is always UTF-8.
803  *
804  * Returns: (type filename) (transfer none): the user name of the current user.
805  */
806 const gchar *
807 g_get_user_name (void)
808 {
809   UserDatabaseEntry *entry;
810
811   entry = g_get_user_database_entry ();
812
813   return entry->user_name;
814 }
815
816 /**
817  * g_get_real_name:
818  *
819  * Gets the real name of the user. This usually comes from the user's
820  * entry in the `passwd` file. The encoding of the returned string is
821  * system-defined. (On Windows, it is, however, always UTF-8.) If the
822  * real user name cannot be determined, the string "Unknown" is 
823  * returned.
824  *
825  * Returns: (type filename) (transfer none): the user's real name.
826  */
827 const gchar *
828 g_get_real_name (void)
829 {
830   UserDatabaseEntry *entry;
831
832   entry = g_get_user_database_entry ();
833
834   return entry->real_name;
835 }
836
837 /* Protected by @g_utils_global_lock. */
838 static gchar *g_home_dir = NULL;  /* (owned) (nullable before initialised) */
839
840 static gchar *
841 g_build_home_dir (void)
842 {
843   gchar *home_dir;
844
845   /* We first check HOME and use it if it is set */
846   home_dir = g_strdup (g_getenv ("HOME"));
847
848 #ifdef G_OS_WIN32
849   /* Only believe HOME if it is an absolute path and exists.
850    *
851    * We only do this check on Windows for a couple of reasons.
852    * Historically, we only did it there because we used to ignore $HOME
853    * on UNIX.  There are concerns about enabling it now on UNIX because
854    * of things like autofs.  In short, if the user has a bogus value in
855    * $HOME then they get what they pay for...
856    */
857   if (home_dir != NULL)
858     {
859       if (!(g_path_is_absolute (home_dir) &&
860             g_file_test (home_dir, G_FILE_TEST_IS_DIR)))
861         g_clear_pointer (&home_dir, g_free);
862     }
863
864   /* In case HOME is Unix-style (it happens), convert it to
865    * Windows style.
866    */
867   if (home_dir != NULL)
868     {
869       gchar *p;
870       while ((p = strchr (home_dir, '/')) != NULL)
871         *p = '\\';
872     }
873
874   if (home_dir == NULL)
875     {
876       /* USERPROFILE is probably the closest equivalent to $HOME? */
877       if (g_getenv ("USERPROFILE") != NULL)
878         home_dir = g_strdup (g_getenv ("USERPROFILE"));
879     }
880
881   if (home_dir == NULL)
882     home_dir = get_special_folder (&FOLDERID_Profile);
883
884   if (home_dir == NULL)
885     home_dir = get_windows_directory_root ();
886 #endif /* G_OS_WIN32 */
887
888   if (home_dir == NULL)
889     {
890       /* If we didn't get it from any of those methods, we will have
891        * to read the user database entry.
892        */
893       UserDatabaseEntry *entry = g_get_user_database_entry ();
894       home_dir = g_strdup (entry->home_dir);
895     }
896
897   /* If we have been denied access to /etc/passwd (for example, by an
898    * overly-zealous LSM), make up a junk value. The return value at this
899    * point is explicitly documented as ‘undefined’. */
900   if (home_dir == NULL)
901     {
902       g_warning ("Could not find home directory: $HOME is not set, and "
903                  "user database could not be read.");
904       home_dir = g_strdup ("/");
905     }
906
907   return g_steal_pointer (&home_dir);
908 }
909
910 /**
911  * g_get_home_dir:
912  *
913  * Gets the current user's home directory.
914  *
915  * As with most UNIX tools, this function will return the value of the
916  * `HOME` environment variable if it is set to an existing absolute path
917  * name, falling back to the `passwd` file in the case that it is unset.
918  *
919  * If the path given in `HOME` is non-absolute, does not exist, or is
920  * not a directory, the result is undefined.
921  *
922  * Before version 2.36 this function would ignore the `HOME` environment
923  * variable, taking the value from the `passwd` database instead. This was
924  * changed to increase the compatibility of GLib with other programs (and
925  * the XDG basedir specification) and to increase testability of programs
926  * based on GLib (by making it easier to run them from test frameworks).
927  *
928  * If your program has a strong requirement for either the new or the
929  * old behaviour (and if you don't wish to increase your GLib
930  * dependency to ensure that the new behaviour is in effect) then you
931  * should either directly check the `HOME` environment variable yourself
932  * or unset it before calling any functions in GLib.
933  *
934  * Returns: (type filename) (transfer none): the current user's home directory
935  */
936 const gchar *
937 g_get_home_dir (void)
938 {
939   const gchar *home_dir;
940
941   G_LOCK (g_utils_global);
942
943   if (g_home_dir == NULL)
944     g_home_dir = g_build_home_dir ();
945   home_dir = g_home_dir;
946
947   G_UNLOCK (g_utils_global);
948
949   return home_dir;
950 }
951
952 void
953 _g_unset_cached_tmp_dir (void)
954 {
955   G_LOCK (g_utils_global);
956   /* We have to leak the old value, as user code could be retaining pointers
957    * to it. */
958   g_ignore_leak (g_tmp_dir);
959   g_tmp_dir = NULL;
960   G_UNLOCK (g_utils_global);
961 }
962
963 /**
964  * g_get_tmp_dir:
965  *
966  * Gets the directory to use for temporary files.
967  *
968  * On UNIX, this is taken from the `TMPDIR` environment variable.
969  * If the variable is not set, `P_tmpdir` is
970  * used, as defined by the system C library. Failing that, a
971  * hard-coded default of "/tmp" is returned.
972  *
973  * On Windows, the `TEMP` environment variable is used, with the
974  * root directory of the Windows installation (eg: "C:\") used
975  * as a default.
976  *
977  * The encoding of the returned string is system-defined. On Windows,
978  * it is always UTF-8. The return value is never %NULL or the empty
979  * string.
980  *
981  * Returns: (type filename) (transfer none): the directory to use for temporary files.
982  */
983 const gchar *
984 g_get_tmp_dir (void)
985 {
986   G_LOCK (g_utils_global);
987
988   if (g_tmp_dir == NULL)
989     {
990       gchar *tmp;
991
992       tmp = g_strdup (g_getenv ("G_TEST_TMPDIR"));
993
994       if (tmp == NULL || *tmp == '\0')
995         {
996           g_free (tmp);
997           tmp = g_strdup (g_getenv (
998 #ifdef G_OS_WIN32
999             "TEMP"
1000 #else /* G_OS_WIN32 */
1001             "TMPDIR"
1002 #endif /* G_OS_WIN32 */
1003           ));
1004         }
1005
1006 #ifdef G_OS_WIN32
1007       if (tmp == NULL || *tmp == '\0')
1008         {
1009           g_free (tmp);
1010           tmp = get_windows_directory_root ();
1011         }
1012 #else /* G_OS_WIN32 */
1013
1014 #ifdef P_tmpdir
1015       if (tmp == NULL || *tmp == '\0')
1016         {
1017           gsize k;
1018           g_free (tmp);
1019           tmp = g_strdup (P_tmpdir);
1020           k = strlen (tmp);
1021           if (k > 1 && G_IS_DIR_SEPARATOR (tmp[k - 1]))
1022             tmp[k - 1] = '\0';
1023         }
1024 #endif /* P_tmpdir */
1025
1026       if (tmp == NULL || *tmp == '\0')
1027         {
1028           g_free (tmp);
1029           tmp = g_strdup ("/tmp");
1030         }
1031 #endif /* !G_OS_WIN32 */
1032
1033       g_tmp_dir = g_steal_pointer (&tmp);
1034     }
1035
1036   G_UNLOCK (g_utils_global);
1037
1038   return g_tmp_dir;
1039 }
1040
1041 /**
1042  * g_get_host_name:
1043  *
1044  * Return a name for the machine. 
1045  *
1046  * The returned name is not necessarily a fully-qualified domain name,
1047  * or even present in DNS or some other name service at all. It need
1048  * not even be unique on your local network or site, but usually it
1049  * is. Callers should not rely on the return value having any specific
1050  * properties like uniqueness for security purposes. Even if the name
1051  * of the machine is changed while an application is running, the
1052  * return value from this function does not change. The returned
1053  * string is owned by GLib and should not be modified or freed. If no
1054  * name can be determined, a default fixed string "localhost" is
1055  * returned.
1056  *
1057  * The encoding of the returned string is UTF-8.
1058  *
1059  * Returns: (transfer none): the host name of the machine.
1060  *
1061  * Since: 2.8
1062  */
1063 const gchar *
1064 g_get_host_name (void)
1065 {
1066   static gchar *hostname;
1067
1068   if (g_once_init_enter (&hostname))
1069     {
1070       gboolean failed;
1071       gchar *utmp = NULL;
1072
1073 #ifndef G_OS_WIN32
1074       gsize size;
1075       /* The number 256 * 256 is taken from the value of _POSIX_HOST_NAME_MAX,
1076        * which is 255. Since we use _POSIX_HOST_NAME_MAX + 1 (= 256) in the
1077        * fallback case, we pick 256 * 256 as the size of the larger buffer here.
1078        * It should be large enough. It doesn't looks reasonable to name a host
1079        * with a string that is longer than 64 KiB.
1080        */
1081       const gsize size_large = (gsize) 256 * 256;
1082       gchar *tmp;
1083
1084 #ifdef _SC_HOST_NAME_MAX
1085       {
1086         glong max;
1087
1088         max = sysconf (_SC_HOST_NAME_MAX);
1089         if (max > 0 && (gsize) max <= G_MAXSIZE - 1)
1090           size = (gsize) max + 1;
1091         else
1092 #ifdef HOST_NAME_MAX
1093           size = HOST_NAME_MAX + 1;
1094 #else
1095           size = _POSIX_HOST_NAME_MAX + 1;
1096 #endif /* HOST_NAME_MAX */
1097       }
1098 #else
1099       /* Fallback to some reasonable value */
1100       size = 256;
1101 #endif /* _SC_HOST_NAME_MAX */
1102       tmp = g_malloc (size);
1103       failed = (gethostname (tmp, size) == -1);
1104       if (failed && size < size_large)
1105         {
1106           /* Try again with a larger buffer if 'size' may be too small. */
1107           g_free (tmp);
1108           tmp = g_malloc (size_large);
1109           failed = (gethostname (tmp, size_large) == -1);
1110         }
1111
1112       if (failed)
1113         g_clear_pointer (&tmp, g_free);
1114       utmp = tmp;
1115 #else
1116       wchar_t tmp[MAX_COMPUTERNAME_LENGTH + 1];
1117       DWORD size = sizeof (tmp) / sizeof (tmp[0]);
1118       failed = (!GetComputerNameW (tmp, &size));
1119       if (!failed)
1120         utmp = g_utf16_to_utf8 (tmp, size, NULL, NULL, NULL);
1121       if (utmp == NULL)
1122         failed = TRUE;
1123 #endif
1124
1125       g_once_init_leave (&hostname, failed ? g_strdup ("localhost") : utmp);
1126     }
1127
1128   return hostname;
1129 }
1130
1131 G_LOCK_DEFINE_STATIC (g_prgname);
1132 static const gchar *g_prgname = NULL; /* always a quark */
1133
1134 /**
1135  * g_get_prgname:
1136  *
1137  * Gets the name of the program. This name should not be localized,
1138  * in contrast to g_get_application_name().
1139  *
1140  * If you are using #GApplication the program name is set in
1141  * g_application_run(). In case of GDK or GTK it is set in
1142  * gdk_init(), which is called by gtk_init() and the
1143  * #GtkApplication::startup handler. The program name is found by
1144  * taking the last component of @argv[0].
1145  *
1146  * Returns: (nullable) (transfer none): the name of the program,
1147  *   or %NULL if it has not been set yet. The returned string belongs
1148  *   to GLib and must not be modified or freed.
1149  */
1150 const gchar*
1151 g_get_prgname (void)
1152 {
1153   const gchar* retval;
1154
1155   G_LOCK (g_prgname);
1156   retval = g_prgname;
1157   G_UNLOCK (g_prgname);
1158
1159   return retval;
1160 }
1161
1162 /**
1163  * g_set_prgname:
1164  * @prgname: the name of the program.
1165  *
1166  * Sets the name of the program. This name should not be localized,
1167  * in contrast to g_set_application_name().
1168  *
1169  * If you are using #GApplication the program name is set in
1170  * g_application_run(). In case of GDK or GTK it is set in
1171  * gdk_init(), which is called by gtk_init() and the
1172  * #GtkApplication::startup handler. The program name is found by
1173  * taking the last component of @argv[0].
1174  *
1175  * Since GLib 2.72, this function can be called multiple times
1176  * and is fully thread safe. Prior to GLib 2.72, this function
1177  * could only be called once per process.
1178  */
1179 void
1180 g_set_prgname (const gchar *prgname)
1181 {
1182   GQuark qprgname = g_quark_from_string (prgname);
1183   G_LOCK (g_prgname);
1184   g_prgname = g_quark_to_string (qprgname);
1185   G_UNLOCK (g_prgname);
1186 }
1187
1188 G_LOCK_DEFINE_STATIC (g_application_name);
1189 static gchar *g_application_name = NULL;
1190
1191 /**
1192  * g_get_application_name:
1193  * 
1194  * Gets a human-readable name for the application, as set by
1195  * g_set_application_name(). This name should be localized if
1196  * possible, and is intended for display to the user.  Contrast with
1197  * g_get_prgname(), which gets a non-localized name. If
1198  * g_set_application_name() has not been called, returns the result of
1199  * g_get_prgname() (which may be %NULL if g_set_prgname() has also not
1200  * been called).
1201  * 
1202  * Returns: (transfer none) (nullable): human-readable application
1203  *   name. May return %NULL
1204  *
1205  * Since: 2.2
1206  **/
1207 const gchar *
1208 g_get_application_name (void)
1209 {
1210   gchar* retval;
1211
1212   G_LOCK (g_application_name);
1213   retval = g_application_name;
1214   G_UNLOCK (g_application_name);
1215
1216   if (retval == NULL)
1217     return g_get_prgname ();
1218   
1219   return retval;
1220 }
1221
1222 /**
1223  * g_set_application_name:
1224  * @application_name: localized name of the application
1225  *
1226  * Sets a human-readable name for the application. This name should be
1227  * localized if possible, and is intended for display to the user.
1228  * Contrast with g_set_prgname(), which sets a non-localized name.
1229  * g_set_prgname() will be called automatically by gtk_init(),
1230  * but g_set_application_name() will not.
1231  *
1232  * Note that for thread safety reasons, this function can only
1233  * be called once.
1234  *
1235  * The application name will be used in contexts such as error messages,
1236  * or when displaying an application's name in the task list.
1237  * 
1238  * Since: 2.2
1239  **/
1240 void
1241 g_set_application_name (const gchar *application_name)
1242 {
1243   gboolean already_set = FALSE;
1244         
1245   G_LOCK (g_application_name);
1246   if (g_application_name)
1247     already_set = TRUE;
1248   else
1249     g_application_name = g_strdup (application_name);
1250   G_UNLOCK (g_application_name);
1251
1252   if (already_set)
1253     g_warning ("g_set_application_name() called multiple times");
1254 }
1255
1256 #ifdef G_OS_WIN32
1257 /* For the past versions we can just
1258  * hardcode all the names.
1259  */
1260 static const struct winver
1261 {
1262   gint major;
1263   gint minor;
1264   gint sp;
1265   const char *version;
1266   const char *spversion;
1267 } versions[] =
1268 {
1269   {6, 2, 0, "8", ""},
1270   {6, 1, 1, "7", " SP1"},
1271   {6, 1, 0, "7", ""},
1272   {6, 0, 2, "Vista", " SP2"},
1273   {6, 0, 1, "Vista", " SP1"},
1274   {6, 0, 0, "Vista", ""},
1275   {5, 1, 3, "XP", " SP3"},
1276   {5, 1, 2, "XP", " SP2"},
1277   {5, 1, 1, "XP", " SP1"},
1278   {5, 1, 0, "XP", ""},
1279   {0, 0, 0, NULL, NULL},
1280 };
1281
1282 static gchar *
1283 get_registry_str (HKEY root_key, const wchar_t *path, const wchar_t *value_name)
1284 {
1285   HKEY key_handle;
1286   DWORD req_value_data_size;
1287   DWORD req_value_data_size2;
1288   LONG status;
1289   DWORD value_type_w;
1290   DWORD value_type_w2;
1291   char *req_value_data;
1292   gchar *result;
1293
1294   status = RegOpenKeyExW (root_key, path, 0, KEY_READ, &key_handle);
1295   if (status != ERROR_SUCCESS)
1296     return NULL;
1297
1298   req_value_data_size = 0;
1299   status = RegQueryValueExW (key_handle,
1300                              value_name,
1301                              NULL,
1302                              &value_type_w,
1303                              NULL,
1304                              &req_value_data_size);
1305
1306   if (status != ERROR_MORE_DATA && status != ERROR_SUCCESS)
1307     {
1308       RegCloseKey (key_handle);
1309
1310       return NULL;
1311     }
1312
1313   req_value_data = g_malloc (req_value_data_size);
1314   req_value_data_size2 = req_value_data_size;
1315
1316   status = RegQueryValueExW (key_handle,
1317                              value_name,
1318                              NULL,
1319                              &value_type_w2,
1320                              (gpointer) req_value_data,
1321                              &req_value_data_size2);
1322
1323   result = NULL;
1324
1325   if (status == ERROR_SUCCESS && value_type_w2 == REG_SZ)
1326     result = g_utf16_to_utf8 ((gunichar2 *) req_value_data,
1327                               req_value_data_size / sizeof (gunichar2),
1328                               NULL,
1329                               NULL,
1330                               NULL);
1331
1332   g_free (req_value_data);
1333   RegCloseKey (key_handle);
1334
1335   return result;
1336 }
1337
1338 /* Windows 8.1 can be either plain or with Update 1,
1339  * depending on its build number (9200 or 9600).
1340  */
1341 static gchar *
1342 get_windows_8_1_update (void)
1343 {
1344   gchar *current_build;
1345   gchar *result = NULL;
1346
1347   current_build = get_registry_str (HKEY_LOCAL_MACHINE,
1348                                     L"SOFTWARE"
1349                                     L"\\Microsoft"
1350                                     L"\\Windows NT"
1351                                     L"\\CurrentVersion",
1352                                     L"CurrentBuild");
1353
1354   if (current_build != NULL)
1355     {
1356       wchar_t *end;
1357       long build = wcstol ((const wchar_t *) current_build, &end, 10);
1358
1359       if (build <= INT_MAX &&
1360           build >= INT_MIN &&
1361           errno == 0 &&
1362           *end == L'\0')
1363         {
1364           if (build >= 9600)
1365             result = g_strdup ("Update 1");
1366         }
1367     }
1368
1369   g_clear_pointer (&current_build, g_free);
1370
1371   return result;
1372 }
1373
1374 static gchar *
1375 get_windows_version (gboolean with_windows)
1376 {
1377   GString *version = g_string_new (NULL);
1378   gboolean is_win_server = FALSE;
1379
1380   if (g_win32_check_windows_version (10, 0, 0, G_WIN32_OS_ANY))
1381     {
1382       gchar *win10_release;
1383       gboolean is_win11 = FALSE;
1384       OSVERSIONINFOEXW osinfo;
1385
1386       /* Are we on Windows 2016/2019/2022 Server? */
1387       is_win_server = g_win32_check_windows_version (10, 0, 0, G_WIN32_OS_SERVER);
1388
1389       /*
1390        * This always succeeds if we get here, since the
1391        * g_win32_check_windows_version() already did this!
1392        * We want the OSVERSIONINFOEXW here for more even
1393        * fine-grained versioning items
1394        */
1395       _g_win32_call_rtl_version (&osinfo);
1396
1397       if (!is_win_server)
1398         {
1399           /*
1400            * Windows 11 is actually Windows 10.0.22000+,
1401            * so look at the build number
1402            */
1403           is_win11 = (osinfo.dwBuildNumber >= 22000);
1404         }
1405       else
1406         {
1407           /*
1408            * Windows 2022 Server is actually Windows 10.0.20348+,
1409            * Windows 2019 Server is actually Windows 10.0.17763+,
1410            * Windows 2016 Server is actually Windows 10.0.14393+,
1411            * so look at the build number
1412            */
1413           g_string_append (version, "Server");
1414           if (osinfo.dwBuildNumber >= 20348)
1415             g_string_append (version, " 2022");
1416           else if (osinfo.dwBuildNumber >= 17763)
1417             g_string_append (version, " 2019");
1418           else
1419             g_string_append (version, " 2016");
1420         }
1421
1422       if (is_win11)
1423         g_string_append (version, "11");
1424       else if (!is_win_server)
1425         g_string_append (version, "10");
1426
1427       /* Windows 10/Server 2016+ is identified by its ReleaseId or
1428        * DisplayVersion (since 20H2), such as
1429        * 1511, 1607, 1703, 1709, 1803, 1809 or 1903 etc.
1430        * The first version of Windows 10 has no release number.
1431        */
1432       win10_release = get_registry_str (HKEY_LOCAL_MACHINE,
1433                                         L"SOFTWARE"
1434                                         L"\\Microsoft"
1435                                         L"\\Windows NT"
1436                                         L"\\CurrentVersion",
1437                                         L"ReleaseId");
1438
1439       if (win10_release != NULL)
1440         {
1441           if (g_strcmp0 (win10_release, "2009") != 0)
1442             g_string_append_printf (version, " %s", win10_release);
1443           else
1444             {
1445               g_free (win10_release);
1446
1447               win10_release = get_registry_str (HKEY_LOCAL_MACHINE,
1448                                                 L"SOFTWARE"
1449                                                 L"\\Microsoft"
1450                                                 L"\\Windows NT"
1451                                                 L"\\CurrentVersion",
1452                                                 L"DisplayVersion");
1453
1454               if (win10_release != NULL)
1455                 g_string_append_printf (version, " %s", win10_release);
1456               else
1457                 g_string_append_printf (version, " 2009");
1458             }
1459         }
1460
1461       g_free (win10_release);
1462     }
1463   else if (g_win32_check_windows_version (6, 3, 0, G_WIN32_OS_ANY))
1464     {
1465       gchar *win81_update;
1466
1467       if (g_win32_check_windows_version (6, 3, 0, G_WIN32_OS_WORKSTATION))
1468         g_string_append (version, "8.1");
1469       else
1470         g_string_append (version, "Server 2012 R2");
1471
1472       win81_update = get_windows_8_1_update ();
1473
1474       if (win81_update != NULL)
1475         g_string_append_printf (version, " %s", win81_update);
1476
1477       g_free (win81_update);
1478     }
1479   else
1480     {
1481       gint i;
1482
1483       for (i = 0; versions[i].major > 0; i++)
1484         {
1485           if (!g_win32_check_windows_version (versions[i].major, versions[i].minor, versions[i].sp, G_WIN32_OS_ANY))
1486             continue;
1487
1488           g_string_append (version, versions[i].version);
1489
1490           if (g_win32_check_windows_version (versions[i].major, versions[i].minor, versions[i].sp, G_WIN32_OS_SERVER))
1491             {
1492               /*
1493                * This condition should now always hold, since Windows
1494                * 7+/Server 2008 R2+ is now required
1495                */
1496               if (versions[i].major == 6)
1497                 {
1498                   g_string_append (version, "Server");
1499                   if (versions[i].minor == 2)
1500                     g_string_append (version, " 2012");
1501                   else if (versions[i].minor == 1)
1502                     g_string_append (version, " 2008 R2");
1503                   else
1504                     g_string_append (version, " 2008");
1505                 }
1506             }
1507
1508           g_string_append (version, versions[i].spversion);
1509         }
1510     }
1511
1512   if (version->len == 0)
1513     {
1514       g_string_free (version, TRUE);
1515
1516       return NULL;
1517     }
1518
1519   if (with_windows)
1520     g_string_prepend (version, "Windows ");
1521
1522   return g_string_free (version, FALSE);
1523 }
1524 #endif
1525
1526 #if defined (G_OS_UNIX) && !defined (__APPLE__)
1527 static gchar *
1528 get_os_info_from_os_release (const gchar *key_name,
1529                              const gchar *buffer)
1530 {
1531   GStrv lines;
1532   gchar *prefix;
1533   size_t i;
1534   gchar *result = NULL;
1535
1536   lines = g_strsplit (buffer, "\n", -1);
1537   prefix = g_strdup_printf ("%s=", key_name);
1538   for (i = 0; lines[i] != NULL; i++)
1539     {
1540       const gchar *line = lines[i];
1541       const gchar *value;
1542
1543       if (g_str_has_prefix (line, prefix))
1544         {
1545           value = line + strlen (prefix);
1546           result = g_shell_unquote (value, NULL);
1547           if (result == NULL)
1548             result = g_strdup (value);
1549           break;
1550         }
1551     }
1552   g_strfreev (lines);
1553   g_free (prefix);
1554
1555 #ifdef __linux__
1556   /* Default values in spec */
1557   if (result == NULL)
1558     {
1559       if (g_str_equal (key_name, G_OS_INFO_KEY_NAME))
1560         return g_strdup ("Linux");
1561       if (g_str_equal (key_name, G_OS_INFO_KEY_ID))
1562         return g_strdup ("linux");
1563       if (g_str_equal (key_name, G_OS_INFO_KEY_PRETTY_NAME))
1564         return g_strdup ("Linux");
1565     }
1566 #endif
1567
1568   return g_steal_pointer (&result);
1569 }
1570
1571 static gchar *
1572 get_os_info_from_uname (const gchar *key_name)
1573 {
1574   struct utsname info;
1575
1576   if (uname (&info) == -1)
1577     return NULL;
1578
1579   if (strcmp (key_name, G_OS_INFO_KEY_NAME) == 0)
1580     return g_strdup (info.sysname);
1581   else if (strcmp (key_name, G_OS_INFO_KEY_VERSION) == 0)
1582     return g_strdup (info.release);
1583   else if (strcmp (key_name, G_OS_INFO_KEY_PRETTY_NAME) == 0)
1584     return g_strdup_printf ("%s %s", info.sysname, info.release);
1585   else if (strcmp (key_name, G_OS_INFO_KEY_ID) == 0)
1586     {
1587       gchar *result = g_ascii_strdown (info.sysname, -1);
1588
1589       g_strcanon (result, "abcdefghijklmnopqrstuvwxyz0123456789_-.", '_');
1590       return g_steal_pointer (&result);
1591     }
1592   else if (strcmp (key_name, G_OS_INFO_KEY_VERSION_ID) == 0)
1593     {
1594       /* We attempt to convert the version string to the format returned by
1595        * config.guess, which is the script used to generate target triplets
1596        * in GNU autotools. There are a lot of rules in the script. We only
1597        * implement a few rules which are easy to understand here.
1598        *
1599        * config.guess can be found at https://savannah.gnu.org/projects/config.
1600        */
1601       gchar *result;
1602
1603       if (strcmp (info.sysname, "NetBSD") == 0)
1604         {
1605           /* sed -e 's,[-_].*,,' */
1606           gssize len = G_MAXSSIZE;
1607           const gchar *c;
1608
1609           if ((c = strchr (info.release, '-')) != NULL)
1610             len = MIN (len, c - info.release);
1611           if ((c = strchr (info.release, '_')) != NULL)
1612             len = MIN (len, c - info.release);
1613           if (len == G_MAXSSIZE)
1614             len = -1;
1615
1616           result = g_ascii_strdown (info.release, len);
1617         }
1618       else if (strcmp (info.sysname, "GNU") == 0)
1619         {
1620           /* sed -e 's,/.*$,,' */
1621           gssize len = -1;
1622           const gchar *c = strchr (info.release, '/');
1623
1624           if (c != NULL)
1625             len = c - info.release;
1626
1627           result = g_ascii_strdown (info.release, len);
1628         }
1629       else if (g_str_has_prefix (info.sysname, "GNU/") ||
1630                strcmp (info.sysname, "FreeBSD") == 0 ||
1631                strcmp (info.sysname, "DragonFly") == 0)
1632         {
1633           /* sed -e 's,[-(].*,,' */
1634           gssize len = G_MAXSSIZE;
1635           const gchar *c;
1636
1637           if ((c = strchr (info.release, '-')) != NULL)
1638             len = MIN (len, c - info.release);
1639           if ((c = strchr (info.release, '(')) != NULL)
1640             len = MIN (len, c - info.release);
1641           if (len == G_MAXSSIZE)
1642             len = -1;
1643
1644           result = g_ascii_strdown (info.release, len);
1645         }
1646       else
1647         result = g_ascii_strdown (info.release, -1);
1648
1649       g_strcanon (result, "abcdefghijklmnopqrstuvwxyz0123456789_-.", '_');
1650       return g_steal_pointer (&result);
1651     }
1652   else
1653     return NULL;
1654 }
1655 #endif  /* defined (G_OS_UNIX) && !defined (__APPLE__) */
1656
1657 /**
1658  * g_get_os_info:
1659  * @key_name: a key for the OS info being requested, for example %G_OS_INFO_KEY_NAME.
1660  *
1661  * Get information about the operating system.
1662  *
1663  * On Linux this comes from the `/etc/os-release` file. On other systems, it may
1664  * come from a variety of sources. You can either use the standard key names
1665  * like %G_OS_INFO_KEY_NAME or pass any UTF-8 string key name. For example,
1666  * `/etc/os-release` provides a number of other less commonly used values that may
1667  * be useful. No key is guaranteed to be provided, so the caller should always
1668  * check if the result is %NULL.
1669  *
1670  * Returns: (nullable): The associated value for the requested key or %NULL if
1671  *   this information is not provided.
1672  *
1673  * Since: 2.64
1674  **/
1675 gchar *
1676 g_get_os_info (const gchar *key_name)
1677 {
1678 #if defined (__APPLE__)
1679   if (g_strcmp0 (key_name, G_OS_INFO_KEY_NAME) == 0)
1680     return g_strdup ("macOS");
1681   else
1682     return NULL;
1683 #elif defined (G_OS_UNIX)
1684   const gchar * const os_release_files[] = { "/etc/os-release", "/usr/lib/os-release" };
1685   gsize i;
1686   gchar *buffer = NULL;
1687   gchar *result = NULL;
1688
1689   g_return_val_if_fail (key_name != NULL, NULL);
1690
1691   for (i = 0; i < G_N_ELEMENTS (os_release_files); i++)
1692     {
1693       GError *error = NULL;
1694       gboolean file_missing;
1695
1696       if (g_file_get_contents (os_release_files[i], &buffer, NULL, &error))
1697         break;
1698
1699       file_missing = g_error_matches (error, G_FILE_ERROR, G_FILE_ERROR_NOENT);
1700       g_clear_error (&error);
1701
1702       if (!file_missing)
1703         return NULL;
1704     }
1705
1706   if (buffer != NULL)
1707     result = get_os_info_from_os_release (key_name, buffer);
1708   else
1709     result = get_os_info_from_uname (key_name);
1710
1711   g_free (buffer);
1712   return g_steal_pointer (&result);
1713 #elif defined (G_OS_WIN32)
1714   if (g_strcmp0 (key_name, G_OS_INFO_KEY_NAME) == 0)
1715     return g_strdup ("Windows");
1716   else if (g_strcmp0 (key_name, G_OS_INFO_KEY_ID) == 0)
1717     return g_strdup ("windows");
1718   else if (g_strcmp0 (key_name, G_OS_INFO_KEY_PRETTY_NAME) == 0)
1719     /* Windows XP SP2 or Windows 10 1903 or Windows 7 Server SP1 */
1720     return get_windows_version (TRUE);
1721   else if (g_strcmp0 (key_name, G_OS_INFO_KEY_VERSION) == 0)
1722     /* XP SP2 or 10 1903 or 7 Server SP1 */
1723     return get_windows_version (FALSE);
1724   else if (g_strcmp0 (key_name, G_OS_INFO_KEY_VERSION_ID) == 0)
1725     {
1726       /* xp_sp2 or 10_1903 or 7_server_sp1 */
1727       gchar *result;
1728       gchar *version = get_windows_version (FALSE);
1729
1730       if (version == NULL)
1731         return NULL;
1732
1733       result = g_ascii_strdown (version, -1);
1734       g_free (version);
1735
1736       return g_strcanon (result, "abcdefghijklmnopqrstuvwxyz0123456789_-.", '_');
1737     }
1738   else if (g_strcmp0 (key_name, G_OS_INFO_KEY_HOME_URL) == 0)
1739     return g_strdup ("https://microsoft.com/windows/");
1740   else if (g_strcmp0 (key_name, G_OS_INFO_KEY_DOCUMENTATION_URL) == 0)
1741     return g_strdup ("https://docs.microsoft.com/");
1742   else if (g_strcmp0 (key_name, G_OS_INFO_KEY_SUPPORT_URL) == 0)
1743     return g_strdup ("https://support.microsoft.com/");
1744   else if (g_strcmp0 (key_name, G_OS_INFO_KEY_BUG_REPORT_URL) == 0)
1745     return g_strdup ("https://support.microsoft.com/contactus/");
1746   else if (g_strcmp0 (key_name, G_OS_INFO_KEY_PRIVACY_POLICY_URL) == 0)
1747     return g_strdup ("https://privacy.microsoft.com/");
1748   else
1749     return NULL;
1750 #endif
1751 }
1752
1753 /* Set @global_str to a copy of @new_value if it’s currently unset or has a
1754  * different value. If its current value matches @new_value, do nothing. If
1755  * replaced, we have to leak the old value as client code could still have
1756  * pointers to it. */
1757 static void
1758 set_str_if_different (gchar       **global_str,
1759                       const gchar  *type,
1760                       const gchar  *new_value)
1761 {
1762   if (*global_str == NULL ||
1763       !g_str_equal (new_value, *global_str))
1764     {
1765       g_debug ("g_set_user_dirs: Setting %s to %s", type, new_value);
1766
1767       /* We have to leak the old value, as user code could be retaining pointers
1768        * to it. */
1769       g_ignore_leak (*global_str);
1770       *global_str = g_strdup (new_value);
1771     }
1772 }
1773
1774 static void
1775 set_strv_if_different (gchar                ***global_strv,
1776                        const gchar            *type,
1777                        const gchar  * const   *new_value)
1778 {
1779   if (*global_strv == NULL ||
1780       !g_strv_equal (new_value, (const gchar * const *) *global_strv))
1781     {
1782       gchar *new_value_str = g_strjoinv (":", (gchar **) new_value);
1783       g_debug ("g_set_user_dirs: Setting %s to %s", type, new_value_str);
1784       g_free (new_value_str);
1785
1786       /* We have to leak the old value, as user code could be retaining pointers
1787        * to it. */
1788       g_ignore_strv_leak (*global_strv);
1789       *global_strv = g_strdupv ((gchar **) new_value);
1790     }
1791 }
1792
1793 /*
1794  * g_set_user_dirs:
1795  * @first_dir_type: Type of the first directory to set
1796  * @...: Value to set the first directory to, followed by additional type/value
1797  *    pairs, followed by %NULL
1798  *
1799  * Set one or more ‘user’ directories to custom values. This is intended to be
1800  * used by test code (particularly with the %G_TEST_OPTION_ISOLATE_DIRS option)
1801  * to override the values returned by the following functions, so that test
1802  * code can be run without touching an installed system and user data:
1803  *
1804  *  - g_get_home_dir() — use type `HOME`, pass a string
1805  *  - g_get_user_cache_dir() — use type `XDG_CACHE_HOME`, pass a string
1806  *  - g_get_system_config_dirs() — use type `XDG_CONFIG_DIRS`, pass a
1807  *    %NULL-terminated string array
1808  *  - g_get_user_config_dir() — use type `XDG_CONFIG_HOME`, pass a string
1809  *  - g_get_system_data_dirs() — use type `XDG_DATA_DIRS`, pass a
1810  *    %NULL-terminated string array
1811  *  - g_get_user_data_dir() — use type `XDG_DATA_HOME`, pass a string
1812  *  - g_get_user_runtime_dir() — use type `XDG_RUNTIME_DIR`, pass a string
1813  *
1814  * The list must be terminated with a %NULL type. All of the values must be
1815  * non-%NULL — passing %NULL as a value won’t reset a directory. If a reference
1816  * to a directory from the calling environment needs to be kept, copy it before
1817  * the first call to g_set_user_dirs(). g_set_user_dirs() can be called multiple
1818  * times.
1819  *
1820  * Since: 2.60
1821  */
1822 /*< private > */
1823 void
1824 g_set_user_dirs (const gchar *first_dir_type,
1825                  ...)
1826 {
1827   va_list args;
1828   const gchar *dir_type;
1829
1830   G_LOCK (g_utils_global);
1831
1832   va_start (args, first_dir_type);
1833
1834   for (dir_type = first_dir_type; dir_type != NULL; dir_type = va_arg (args, const gchar *))
1835     {
1836       gconstpointer dir_value = va_arg (args, gconstpointer);
1837       g_assert (dir_value != NULL);
1838
1839       if (g_str_equal (dir_type, "HOME"))
1840         set_str_if_different (&g_home_dir, dir_type, dir_value);
1841       else if (g_str_equal (dir_type, "XDG_CACHE_HOME"))
1842         set_str_if_different (&g_user_cache_dir, dir_type, dir_value);
1843       else if (g_str_equal (dir_type, "XDG_CONFIG_DIRS"))
1844         set_strv_if_different (&g_system_config_dirs, dir_type, dir_value);
1845       else if (g_str_equal (dir_type, "XDG_CONFIG_HOME"))
1846         set_str_if_different (&g_user_config_dir, dir_type, dir_value);
1847       else if (g_str_equal (dir_type, "XDG_DATA_DIRS"))
1848         set_strv_if_different (&g_system_data_dirs, dir_type, dir_value);
1849       else if (g_str_equal (dir_type, "XDG_DATA_HOME"))
1850         set_str_if_different (&g_user_data_dir, dir_type, dir_value);
1851       else if (g_str_equal (dir_type, "XDG_STATE_HOME"))
1852         set_str_if_different (&g_user_state_dir, dir_type, dir_value);
1853       else if (g_str_equal (dir_type, "XDG_RUNTIME_DIR"))
1854         set_str_if_different (&g_user_runtime_dir, dir_type, dir_value);
1855       else
1856         g_assert_not_reached ();
1857     }
1858
1859   va_end (args);
1860
1861   G_UNLOCK (g_utils_global);
1862 }
1863
1864 static gchar *
1865 g_build_user_data_dir (void)
1866 {
1867   gchar *data_dir = NULL;
1868   const gchar *data_dir_env = g_getenv ("XDG_DATA_HOME");
1869
1870   if (data_dir_env && data_dir_env[0])
1871     data_dir = g_strdup (data_dir_env);
1872 #ifdef G_OS_WIN32
1873   else
1874     data_dir = get_special_folder (&FOLDERID_LocalAppData);
1875 #endif
1876   if (!data_dir || !data_dir[0])
1877     {
1878       gchar *home_dir = g_build_home_dir ();
1879       data_dir = g_build_filename (home_dir, ".local", "share", NULL);
1880       g_free (home_dir);
1881     }
1882
1883   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 g_get_user_data_dir (void)
1914 {
1915   const gchar *user_data_dir;
1916
1917   G_LOCK (g_utils_global);
1918
1919   if (g_user_data_dir == NULL)
1920     g_user_data_dir = g_build_user_data_dir ();
1921   user_data_dir = g_user_data_dir;
1922
1923   G_UNLOCK (g_utils_global);
1924
1925   return user_data_dir;
1926 }
1927
1928 static gchar *
1929 g_build_user_config_dir (void)
1930 {
1931   gchar *config_dir = NULL;
1932   const gchar *config_dir_env = g_getenv ("XDG_CONFIG_HOME");
1933
1934   if (config_dir_env && config_dir_env[0])
1935     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   if (!config_dir || !config_dir[0])
1941     {
1942       gchar *home_dir = g_build_home_dir ();
1943       config_dir = g_build_filename (home_dir, ".config", NULL);
1944       g_free (home_dir);
1945     }
1946
1947   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 g_get_user_config_dir (void)
1977 {
1978   const gchar *user_config_dir;
1979
1980   G_LOCK (g_utils_global);
1981
1982   if (g_user_config_dir == NULL)
1983     g_user_config_dir = g_build_user_config_dir ();
1984   user_config_dir = g_user_config_dir;
1985
1986   G_UNLOCK (g_utils_global);
1987
1988   return user_config_dir;
1989 }
1990
1991 static gchar *
1992 g_build_user_cache_dir (void)
1993 {
1994   gchar *cache_dir = NULL;
1995   const gchar *cache_dir_env = g_getenv ("XDG_CACHE_HOME");
1996
1997   if (cache_dir_env && cache_dir_env[0])
1998     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   if (!cache_dir || !cache_dir[0])
2004     {
2005       gchar *home_dir = g_build_home_dir ();
2006       cache_dir = g_build_filename (home_dir, ".cache", NULL);
2007       g_free (home_dir);
2008     }
2009
2010   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 g_get_user_cache_dir (void)
2039 {
2040   const gchar *user_cache_dir;
2041
2042   G_LOCK (g_utils_global);
2043
2044   if (g_user_cache_dir == NULL)
2045     g_user_cache_dir = g_build_user_cache_dir ();
2046   user_cache_dir = g_user_cache_dir;
2047
2048   G_UNLOCK (g_utils_global);
2049
2050   return user_cache_dir;
2051 }
2052
2053 static gchar *
2054 g_build_user_state_dir (void)
2055 {
2056   gchar *state_dir = NULL;
2057   const gchar *state_dir_env = g_getenv ("XDG_STATE_HOME");
2058
2059   if (state_dir_env && state_dir_env[0])
2060     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   if (!state_dir || !state_dir[0])
2066     {
2067       gchar *home_dir = g_build_home_dir ();
2068       state_dir = g_build_filename (home_dir, ".local/state", NULL);
2069       g_free (home_dir);
2070     }
2071
2072   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 g_get_user_state_dir (void)
2103 {
2104   const gchar *user_state_dir;
2105
2106   G_LOCK (g_utils_global);
2107
2108   if (g_user_state_dir == NULL)
2109     g_user_state_dir = g_build_user_state_dir ();
2110   user_state_dir = g_user_state_dir;
2111
2112   G_UNLOCK (g_utils_global);
2113
2114   return user_state_dir;
2115 }
2116
2117 static gchar *
2118 g_build_user_runtime_dir (void)
2119 {
2120   gchar *runtime_dir = NULL;
2121   const gchar *runtime_dir_env = g_getenv ("XDG_RUNTIME_DIR");
2122
2123   if (runtime_dir_env && runtime_dir_env[0])
2124     {
2125       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       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       (void) g_mkdir (runtime_dir, 0700);
2149     }
2150
2151   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 g_get_user_runtime_dir (void)
2178 {
2179   const gchar *user_runtime_dir;
2180
2181   G_LOCK (g_utils_global);
2182
2183   if (g_user_runtime_dir == NULL)
2184     g_user_runtime_dir = g_build_user_runtime_dir ();
2185   user_runtime_dir = g_user_runtime_dir;
2186
2187   G_UNLOCK (g_utils_global);
2188
2189   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 load_user_special_dirs (void)
2254 {
2255   gchar *config_dir = NULL;
2256   gchar *config_file;
2257   gchar *data;
2258   gchar **lines;
2259   gint n_lines, i;
2260   
2261   config_dir = g_build_user_config_dir ();
2262   config_file = g_build_filename (config_dir,
2263                                   "user-dirs.dirs",
2264                                   NULL);
2265   g_free (config_dir);
2266
2267   if (!g_file_get_contents (config_file, &data, NULL, NULL))
2268     {
2269       g_free (config_file);
2270       return;
2271     }
2272
2273   lines = g_strsplit (data, "\n", -1);
2274   n_lines = g_strv_length (lines);
2275   g_free (data);
2276   
2277   for (i = 0; i < n_lines; i++)
2278     {
2279       gchar *buffer = lines[i];
2280       gchar *d, *p;
2281       gint len;
2282       gboolean is_relative = FALSE;
2283       GUserDirectory directory;
2284
2285       /* Remove newline at end */
2286       len = strlen (buffer);
2287       if (len > 0 && buffer[len - 1] == '\n')
2288         buffer[len - 1] = 0;
2289       
2290       p = buffer;
2291       while (*p == ' ' || *p == '\t')
2292         p++;
2293       
2294       if (strncmp (p, "XDG_DESKTOP_DIR", strlen ("XDG_DESKTOP_DIR")) == 0)
2295         {
2296           directory = G_USER_DIRECTORY_DESKTOP;
2297           p += strlen ("XDG_DESKTOP_DIR");
2298         }
2299       else if (strncmp (p, "XDG_DOCUMENTS_DIR", strlen ("XDG_DOCUMENTS_DIR")) == 0)
2300         {
2301           directory = G_USER_DIRECTORY_DOCUMENTS;
2302           p += strlen ("XDG_DOCUMENTS_DIR");
2303         }
2304       else if (strncmp (p, "XDG_DOWNLOAD_DIR", strlen ("XDG_DOWNLOAD_DIR")) == 0)
2305         {
2306           directory = G_USER_DIRECTORY_DOWNLOAD;
2307           p += strlen ("XDG_DOWNLOAD_DIR");
2308         }
2309       else if (strncmp (p, "XDG_MUSIC_DIR", strlen ("XDG_MUSIC_DIR")) == 0)
2310         {
2311           directory = G_USER_DIRECTORY_MUSIC;
2312           p += strlen ("XDG_MUSIC_DIR");
2313         }
2314       else if (strncmp (p, "XDG_PICTURES_DIR", strlen ("XDG_PICTURES_DIR")) == 0)
2315         {
2316           directory = G_USER_DIRECTORY_PICTURES;
2317           p += strlen ("XDG_PICTURES_DIR");
2318         }
2319       else if (strncmp (p, "XDG_PUBLICSHARE_DIR", strlen ("XDG_PUBLICSHARE_DIR")) == 0)
2320         {
2321           directory = G_USER_DIRECTORY_PUBLIC_SHARE;
2322           p += strlen ("XDG_PUBLICSHARE_DIR");
2323         }
2324       else if (strncmp (p, "XDG_TEMPLATES_DIR", strlen ("XDG_TEMPLATES_DIR")) == 0)
2325         {
2326           directory = G_USER_DIRECTORY_TEMPLATES;
2327           p += strlen ("XDG_TEMPLATES_DIR");
2328         }
2329       else if (strncmp (p, "XDG_VIDEOS_DIR", strlen ("XDG_VIDEOS_DIR")) == 0)
2330         {
2331           directory = G_USER_DIRECTORY_VIDEOS;
2332           p += strlen ("XDG_VIDEOS_DIR");
2333         }
2334       else
2335         continue;
2336
2337       while (*p == ' ' || *p == '\t')
2338         p++;
2339
2340       if (*p != '=')
2341         continue;
2342       p++;
2343
2344       while (*p == ' ' || *p == '\t')
2345         p++;
2346
2347       if (*p != '"')
2348         continue;
2349       p++;
2350
2351       if (strncmp (p, "$HOME", 5) == 0)
2352         {
2353           p += 5;
2354           is_relative = TRUE;
2355         }
2356       else if (*p != '/')
2357         continue;
2358
2359       d = strrchr (p, '"');
2360       if (!d)
2361         continue;
2362       *d = 0;
2363
2364       d = p;
2365       
2366       /* remove trailing slashes */
2367       len = strlen (d);
2368       if (d[len - 1] == '/')
2369         d[len - 1] = 0;
2370       
2371       if (is_relative)
2372         {
2373           gchar *home_dir = g_build_home_dir ();
2374           g_user_special_dirs[directory] = g_build_filename (home_dir, d, NULL);
2375           g_free (home_dir);
2376         }
2377       else
2378         g_user_special_dirs[directory] = g_strdup (d);
2379     }
2380
2381   g_strfreev (lines);
2382   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 g_reload_user_special_dirs_cache (void)
2404 {
2405   int i;
2406
2407   G_LOCK (g_utils_global);
2408
2409   if (g_user_special_dirs != NULL)
2410     {
2411       /* save a copy of the pointer, to check if some memory can be preserved */
2412       char **old_g_user_special_dirs = g_user_special_dirs;
2413       char *old_val;
2414
2415       /* recreate and reload our cache */
2416       g_user_special_dirs = g_new0 (gchar *, G_USER_N_DIRECTORIES);
2417       load_user_special_dirs ();
2418
2419       /* only leak changed directories */
2420       for (i = 0; i < G_USER_N_DIRECTORIES; i++)
2421         {
2422           old_val = old_g_user_special_dirs[i];
2423           if (g_user_special_dirs[i] == NULL)
2424             {
2425               g_user_special_dirs[i] = old_val;
2426             }
2427           else if (g_strcmp0 (old_val, g_user_special_dirs[i]) == 0)
2428             {
2429               /* don't leak */
2430               g_free (g_user_special_dirs[i]);
2431               g_user_special_dirs[i] = old_val;
2432             }
2433           else
2434             g_free (old_val);
2435         }
2436
2437       /* free the old array */
2438       g_free (old_g_user_special_dirs);
2439     }
2440
2441   G_UNLOCK (g_utils_global);
2442 }
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 g_get_user_special_dir (GUserDirectory directory)
2467 {
2468   const gchar *user_special_dir;
2469
2470   g_return_val_if_fail (directory >= G_USER_DIRECTORY_DESKTOP &&
2471                         directory < G_USER_N_DIRECTORIES, NULL);
2472
2473   G_LOCK (g_utils_global);
2474
2475   if (G_UNLIKELY (g_user_special_dirs == NULL))
2476     {
2477       g_user_special_dirs = g_new0 (gchar *, G_USER_N_DIRECTORIES);
2478
2479       load_user_special_dirs ();
2480
2481       /* Special-case desktop for historical compatibility */
2482       if (g_user_special_dirs[G_USER_DIRECTORY_DESKTOP] == NULL)
2483         {
2484           gchar *home_dir = g_build_home_dir ();
2485           g_user_special_dirs[G_USER_DIRECTORY_DESKTOP] = g_build_filename (home_dir, "Desktop", NULL);
2486           g_free (home_dir);
2487         }
2488     }
2489   user_special_dir = g_user_special_dirs[directory];
2490
2491   G_UNLOCK (g_utils_global);
2492
2493   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 g_build_system_data_dirs (void)
2689 {
2690   gchar **data_dir_vector = NULL;
2691   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   if (!data_dirs || !data_dirs[0])
2698     data_dirs = "/usr/local/share/:/usr/share/";
2699
2700   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   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 g_get_system_data_dirs (void)
2757 {
2758   const gchar * const *system_data_dirs;
2759
2760   G_LOCK (g_utils_global);
2761
2762   if (g_system_data_dirs == NULL)
2763     g_system_data_dirs = g_build_system_data_dirs ();
2764   system_data_dirs = (const gchar * const *) g_system_data_dirs;
2765
2766   G_UNLOCK (g_utils_global);
2767
2768   return system_data_dirs;
2769 }
2770
2771 static gchar **
2772 g_build_system_config_dirs (void)
2773 {
2774   gchar **conf_dir_vector = NULL;
2775   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   if (!conf_dirs || !conf_dirs[0])
2795     conf_dirs = "/etc/xdg";
2796
2797   conf_dir_vector = g_strsplit (conf_dirs, G_SEARCHPATH_SEPARATOR_S, 0);
2798 #endif
2799
2800   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 g_get_system_config_dirs (void)
2835 {
2836   const gchar * const *system_config_dirs;
2837
2838   G_LOCK (g_utils_global);
2839
2840   if (g_system_config_dirs == NULL)
2841     g_system_config_dirs = g_build_system_config_dirs ();
2842   system_config_dirs = (const gchar * const *) g_system_config_dirs;
2843
2844   G_UNLOCK (g_utils_global);
2845
2846   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 g_nullify_pointer (gpointer *nullify_location)
2857 {
2858   g_return_if_fail (nullify_location != NULL);
2859
2860   *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 g_format_size (guint64 size)
2902 {
2903   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, ‘Mb’ 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 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   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 kb" */
2994       { KILOBYTE_FACTOR, N_("kb") },
2995       /* Translators: A unit symbol for size formatting, showing for example: "13.0 Mb" */
2996       { MEGABYTE_FACTOR, N_("Mb") },
2997       /* Translators: A unit symbol for size formatting, showing for example: "13.0 Gb" */
2998       { GIGABYTE_FACTOR, N_("Gb") },
2999       /* Translators: A unit symbol for size formatting, showing for example: "13.0 Tb" */
3000       { TERABYTE_FACTOR, N_("Tb") },
3001       /* Translators: A unit symbol for size formatting, showing for example: "13.0 Pb" */
3002       { PETABYTE_FACTOR, N_("Pb") },
3003       /* Translators: A unit symbol for size formatting, showing for example: "13.0 Eb" */
3004       { EXABYTE_FACTOR,  N_("Eb") }
3005     },
3006     {
3007       /* Translators: A unit symbol for size formatting, showing for example: "13.0 Kib" */
3008       { KIBIBYTE_FACTOR, N_("Kib") },
3009       /* Translators: A unit symbol for size formatting, showing for example: "13.0 Mib" */
3010       { MEBIBYTE_FACTOR, N_("Mib") },
3011       /* Translators: A unit symbol for size formatting, showing for example: "13.0 Gib" */
3012       { GIBIBYTE_FACTOR, N_("Gib") },
3013       /* Translators: A unit symbol for size formatting, showing for example: "13.0 Tib" */
3014       { TEBIBYTE_FACTOR, N_("Tib") },
3015       /* Translators: A unit symbol for size formatting, showing for example: "13.0 Pib" */
3016       { PEBIBYTE_FACTOR, N_("Pib") },
3017       /* Translators: A unit symbol for size formatting, showing for example: "13.0 Eib" */
3018       { EXBIBYTE_FACTOR, N_("Eib") }
3019     }
3020   };
3021
3022   GString *string;
3023   FormatIndex index;
3024
3025   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   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   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   string = g_string_new (NULL);
3030
3031   switch (flags & ~(G_FORMAT_SIZE_LONG_FORMAT | G_FORMAT_SIZE_ONLY_VALUE | G_FORMAT_SIZE_ONLY_UNIT))
3032     {
3033     case G_FORMAT_SIZE_DEFAULT:
3034       index = FORMAT_BYTES;
3035       break;
3036     case (G_FORMAT_SIZE_DEFAULT | G_FORMAT_SIZE_IEC_UNITS):
3037       index = FORMAT_BYTES_IEC;
3038       break;
3039     case G_FORMAT_SIZE_BITS:
3040       index = FORMAT_BITS;
3041       break;
3042     case (G_FORMAT_SIZE_BITS | G_FORMAT_SIZE_IEC_UNITS):
3043       index = FORMAT_BITS_IEC;
3044       break;
3045     default:
3046       g_assert_not_reached ();
3047     }
3048
3049
3050   if (size < formats[index][0].factor)
3051     {
3052       const char * units;
3053
3054       if (index == FORMAT_BYTES || index == FORMAT_BYTES_IEC)
3055         {
3056           units = g_dngettext (GETTEXT_PACKAGE, "byte", "bytes", (guint) size);
3057         }
3058       else
3059         {
3060           units = g_dngettext (GETTEXT_PACKAGE, "bit", "bits", (guint) size);
3061         }
3062
3063       if ((flags & G_FORMAT_SIZE_ONLY_UNIT) != 0)
3064         g_string_append (string, units);
3065       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         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           g_string_printf (string, C_("format-size", "%u %s"), (guint) size, units);
3074         }
3075
3076       flags &= ~G_FORMAT_SIZE_LONG_FORMAT;
3077     }
3078   else
3079     {
3080       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       const struct Format * f = &formats[index][n - 1];
3091
3092       for (i = 1; i < n; i++)
3093         {
3094           if (size < formats[index][i].factor)
3095             {
3096               f = &formats[index][i - 1];
3097               break;
3098             }
3099         }
3100
3101       units = _(f->string);
3102       value = (gdouble) size / (gdouble) f->factor;
3103
3104       if ((flags & G_FORMAT_SIZE_ONLY_UNIT) != 0)
3105         g_string_append (string, units);
3106       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         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           g_string_printf (string, C_("format-size", "%.1f %s"), value, units);
3116         }
3117     }
3118
3119   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       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       if (index == FORMAT_BYTES || index == FORMAT_BYTES_IEC)
3153         {
3154           /* Translators: the %s in "%s bytes" will always be replaced by a number. */
3155           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           translated_format = g_dngettext (GETTEXT_PACKAGE, "%s bit", "%s bits", plural_form);
3161         }
3162       formatted_number = g_strdup_printf ("%'"G_GUINT64_FORMAT, size);
3163
3164       g_string_append (string, " (");
3165       g_string_append_printf (string, translated_format, formatted_number);
3166       g_free (formatted_number);
3167       g_string_append (string, ")");
3168     }
3169
3170   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 g_format_size_for_display (goffset size)
3199 {
3200   if (size < (goffset) KIBIBYTE_FACTOR)
3201     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       if (size < (goffset) MEBIBYTE_FACTOR)
3207         {
3208           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           return g_strdup_printf (_("%.1f KB"), displayed_size);
3215         }
3216       else if (size < (goffset) GIBIBYTE_FACTOR)
3217         {
3218           displayed_size = (gdouble) size / (gdouble) MEBIBYTE_FACTOR;
3219           return g_strdup_printf (_("%.1f MB"), displayed_size);
3220         }
3221       else if (size < (goffset) TEBIBYTE_FACTOR)
3222         {
3223           displayed_size = (gdouble) size / (gdouble) GIBIBYTE_FACTOR;
3224           return g_strdup_printf (_("%.1f GB"), displayed_size);
3225         }
3226       else if (size < (goffset) PEBIBYTE_FACTOR)
3227         {
3228           displayed_size = (gdouble) size / (gdouble) TEBIBYTE_FACTOR;
3229           return g_strdup_printf (_("%.1f TB"), displayed_size);
3230         }
3231       else if (size < (goffset) EXBIBYTE_FACTOR)
3232         {
3233           displayed_size = (gdouble) size / (gdouble) PEBIBYTE_FACTOR;
3234           return g_strdup_printf (_("%.1f PB"), displayed_size);
3235         }
3236       else
3237         {
3238           displayed_size = (gdouble) size / (gdouble) EXBIBYTE_FACTOR;
3239           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 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   errno = 0;
3279   value = getauxval (AT_SECURE);
3280   errsv = errno;
3281   if (errsv)
3282     g_error ("getauxval () failed: %s", g_strerror (errsv));
3283   return value;
3284 #elif defined(HAVE_ISSETUGID) && !defined(__BIONIC__)
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