Coverage Report

Created: 2025-07-01 06:23

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