LCOV - code coverage report
Current view: top level - glib/glib/tests - fileutils.c (source / functions) Hit Total Coverage
Test: unnamed Lines: 1127 1206 93.4 %
Date: 2024-04-16 05:15:53 Functions: 32 35 91.4 %
Branches: 85 146 58.2 %

           Branch data     Line data    Source code
       1                 :            : /* Unit tests for gfileutils
       2                 :            :  * Copyright (C) 1995-1997  Peter Mattis, Spencer Kimball and Josh MacDonald
       3                 :            :  *
       4                 :            :  * SPDX-License-Identifier: LicenseRef-old-glib-tests
       5                 :            :  *
       6                 :            :  * This work is provided "as is"; redistribution and modification
       7                 :            :  * in whole or in part, in any medium, physical or electronic is
       8                 :            :  * permitted without restriction.
       9                 :            :  *
      10                 :            :  * This work is distributed in the hope that it will be useful,
      11                 :            :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      12                 :            :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
      13                 :            :  *
      14                 :            :  * In no event shall the authors or contributors be liable for any
      15                 :            :  * direct, indirect, incidental, special, exemplary, or consequential
      16                 :            :  * damages (including, but not limited to, procurement of substitute
      17                 :            :  * goods or services; loss of use, data, or profits; or business
      18                 :            :  * interruption) however caused and on any theory of liability, whether
      19                 :            :  * in contract, strict liability, or tort (including negligence or
      20                 :            :  * otherwise) arising in any way out of the use of this software, even
      21                 :            :  * if advised of the possibility of such damage.
      22                 :            :  */
      23                 :            : 
      24                 :            : #include "config.h"
      25                 :            : #include <string.h>
      26                 :            : #include <errno.h>
      27                 :            : 
      28                 :            : /* We are testing some deprecated APIs here */
      29                 :            : #ifndef GLIB_DISABLE_DEPRECATION_WARNINGS
      30                 :            : #define GLIB_DISABLE_DEPRECATION_WARNINGS
      31                 :            : #endif
      32                 :            : 
      33                 :            : #include <glib.h>
      34                 :            : 
      35                 :            : /* Test our stdio wrappers here; this disables redefining (e.g.) g_open() to open() */
      36                 :            : #define G_STDIO_WRAP_ON_UNIX
      37                 :            : #include <glib/gstdio.h>
      38                 :            : #include "glib-private.h"
      39                 :            : 
      40                 :            : #ifdef G_OS_UNIX
      41                 :            : #include <unistd.h>
      42                 :            : #include <sys/types.h>
      43                 :            : #include <sys/stat.h>
      44                 :            : #include <utime.h>
      45                 :            : 
      46                 :            : #define G_TEST_DIR_MODE 0555
      47                 :            : #endif
      48                 :            : #include <fcntl.h>
      49                 :            : #ifdef G_OS_WIN32
      50                 :            : #include <windows.h>
      51                 :            : #include <sys/utime.h>
      52                 :            : #include <io.h>
      53                 :            : #ifndef S_ISDIR
      54                 :            : #define S_ISDIR(m) (((m) & _S_IFMT) == _S_IFDIR)
      55                 :            : #endif
      56                 :            : #ifndef F_OK
      57                 :            : #define F_OK 0
      58                 :            : #endif
      59                 :            : 
      60                 :            : #define G_TEST_DIR_MODE (S_IWRITE | S_IREAD)
      61                 :            : #endif
      62                 :            : 
      63                 :            : #include "testutils.h"
      64                 :            : 
      65                 :            : #define S G_DIR_SEPARATOR_S
      66                 :            : 
      67                 :            : static void
      68                 :        228 : check_string (gchar *str, const gchar *expected)
      69                 :            : {
      70                 :        228 :   g_assert_nonnull (str);
      71                 :        228 :   g_assert_cmpstr (str, ==, expected);
      72                 :        228 :   g_free (str);
      73                 :        228 : }
      74                 :            : 
      75                 :            : static void
      76                 :          1 : test_paths (void)
      77                 :            : {
      78                 :            :   struct
      79                 :            :   {
      80                 :            :     gchar *filename;
      81                 :            :     gchar *dirname;
      82                 :          1 :   } dirname_checks[] = {
      83                 :            :     { "/", "/" },
      84                 :            :     { "////", "/" },
      85                 :            :     { ".////", "." },
      86                 :            :     { "../", ".." },
      87                 :            :     { "..////", ".." },
      88                 :            :     { "a/b", "a" },
      89                 :            :     { "a/b/", "a/b" },
      90                 :            :     { "c///", "c" },
      91                 :            : #ifdef G_OS_WIN32
      92                 :            :     { "\\", "\\" },
      93                 :            :     { ".\\\\\\\\", "." },
      94                 :            :     { "..\\", ".." },
      95                 :            :     { "..\\\\\\\\", ".." },
      96                 :            :     { "a\\b", "a" },
      97                 :            :     { "a\\b/", "a\\b" },
      98                 :            :     { "a/b\\", "a/b" },
      99                 :            :     { "c\\\\/", "c" },
     100                 :            :     { "//\\", "/" },
     101                 :            : #endif
     102                 :            : #ifdef G_WITH_CYGWIN
     103                 :            :     { "//server/share///x", "//server/share" },
     104                 :            : #endif
     105                 :            :     { ".", "." },
     106                 :            :     { "..", "." },
     107                 :            :     { "", "." },
     108                 :            :   };
     109                 :          1 :   const guint n_dirname_checks = G_N_ELEMENTS (dirname_checks);
     110                 :            :   struct
     111                 :            :   {
     112                 :            :     gchar *filename;
     113                 :            :     gchar *without_root;
     114                 :          1 :   } skip_root_checks[] = {
     115                 :            :     { "/", "" },
     116                 :            :     { "//", "" },
     117                 :            :     { "/foo", "foo" },
     118                 :            :     { "//foo", "foo" },
     119                 :            :     { "a/b", NULL },
     120                 :            : #ifdef G_OS_WIN32
     121                 :            :     { "\\", "" },
     122                 :            :     { "\\foo", "foo" },
     123                 :            :     { "\\\\server\\foo", "" },
     124                 :            :     { "\\\\server\\foo\\bar", "bar" },
     125                 :            :     { "a\\b", NULL },
     126                 :            : #endif
     127                 :            : #ifdef G_WITH_CYGWIN
     128                 :            :     { "//server/share///x", "//x" },
     129                 :            : #endif
     130                 :            :     { ".", NULL },
     131                 :            :     { "", NULL },
     132                 :            :   };
     133                 :          1 :   const guint n_skip_root_checks = G_N_ELEMENTS (skip_root_checks);
     134                 :            :   struct
     135                 :            :   {
     136                 :            :     gchar *cwd;
     137                 :            :     gchar *relative_path;
     138                 :            :     gchar *canonical_path;
     139                 :          1 :   } canonicalize_filename_checks[] = {
     140                 :            : #ifndef G_OS_WIN32
     141                 :            :     { "/etc", "../usr/share", "/usr/share" },
     142                 :            :     { "/", "/foo/bar", "/foo/bar" },
     143                 :            :     { "/usr/bin", "../../foo/bar", "/foo/bar" },
     144                 :            :     { "/", "../../foo/bar", "/foo/bar" },
     145                 :            :     { "/double//dash", "../../foo/bar", "/foo/bar" },
     146                 :            :     { "/usr/share/foo", ".././././bar", "/usr/share/bar" },
     147                 :            :     { "/foo/bar", "../bar/./.././bar", "/foo/bar" },
     148                 :            :     { "/test///dir", "../../././foo/bar", "/foo/bar" },
     149                 :            :     { "/test///dir", "../../././/foo///bar", "/foo/bar" },
     150                 :            :     { "/etc", "///triple/slash", "/triple/slash" },
     151                 :            :     { "/etc", "//double/slash", "//double/slash" },
     152                 :            :     { "///triple/slash", ".", "/triple/slash" },
     153                 :            :     { "//double/slash", ".", "//double/slash" },
     154                 :            :     { "/cwd/../with/./complexities/", "./hello", "/with/complexities/hello" },
     155                 :            :     { "/", ".dot-dir", "/.dot-dir" },
     156                 :            :     { "/cwd", "..", "/" },
     157                 :            :     { "/etc", "hello/..", "/etc" },
     158                 :            :     { "/etc", "hello/../", "/etc" },
     159                 :            :     { "/", "..", "/" },
     160                 :            :     { "/", "../", "/" },
     161                 :            :     { "/", "/..", "/" },
     162                 :            :     { "/", "/../", "/" },
     163                 :            :     { "/", ".", "/" },
     164                 :            :     { "/", "./", "/" },
     165                 :            :     { "/", "/.", "/" },
     166                 :            :     { "/", "/./", "/" },
     167                 :            :     { "/", "///usr/../usr", "/usr" },
     168                 :            : #else
     169                 :            :     { "/etc", "../usr/share", "\\usr\\share" },
     170                 :            :     { "/", "/foo/bar", "\\foo\\bar" },
     171                 :            :     { "/usr/bin", "../../foo/bar", "\\foo\\bar" },
     172                 :            :     { "/", "../../foo/bar", "\\foo\\bar" },
     173                 :            :     { "/double//dash", "../../foo/bar", "\\foo\\bar" },
     174                 :            :     { "/usr/share/foo", ".././././bar", "\\usr\\share\\bar" },
     175                 :            :     { "/foo/bar", "../bar/./.././bar", "\\foo\\bar" },
     176                 :            :     { "/test///dir", "../../././foo/bar", "\\foo\\bar" },
     177                 :            :     { "/test///dir", "../../././/foo///bar", "\\foo\\bar" },
     178                 :            :     { "/etc", "///triple/slash", "\\triple\\slash" },
     179                 :            :     { "/etc", "//double/slash", "//double/slash" },
     180                 :            :     { "///triple/slash", ".", "\\triple\\slash" },
     181                 :            :     { "//double/slash", ".", "//double/slash\\" },
     182                 :            :     { "/cwd/../with/./complexities/", "./hello", "\\with\\complexities\\hello" },
     183                 :            :     { "/", ".dot-dir", "\\.dot-dir" },
     184                 :            :     { "/cwd", "..", "\\" },
     185                 :            :     { "/etc", "hello/..", "\\etc" },
     186                 :            :     { "/etc", "hello/../", "\\etc" },
     187                 :            :     { "/", "..", "\\" },
     188                 :            :     { "/", "../", "\\" },
     189                 :            :     { "/", "/..", "\\" },
     190                 :            :     { "/", "/../", "\\" },
     191                 :            :     { "/", ".", "\\" },
     192                 :            :     { "/", "./", "\\" },
     193                 :            :     { "/", "/.", "\\" },
     194                 :            :     { "/", "/./", "\\" },
     195                 :            :     { "/", "///usr/../usr", "\\usr" },
     196                 :            : 
     197                 :            :     { "\\etc", "..\\usr\\share", "\\usr\\share" },
     198                 :            :     { "\\", "\\foo\\bar", "\\foo\\bar" },
     199                 :            :     { "\\usr\\bin", "..\\..\\foo\\bar", "\\foo\\bar" },
     200                 :            :     { "\\", "..\\..\\foo\\bar", "\\foo\\bar" },
     201                 :            :     { "\\double\\\\dash", "..\\..\\foo\\bar", "\\foo\\bar" },
     202                 :            :     { "\\usr\\share\\foo", "..\\.\\.\\.\\bar", "\\usr\\share\\bar" },
     203                 :            :     { "\\foo\\bar", "..\\bar\\.\\..\\.\\bar", "\\foo\\bar" },
     204                 :            :     { "\\test\\\\\\dir", "..\\..\\.\\.\\foo\\bar", "\\foo\\bar" },
     205                 :            :     { "\\test\\\\\\dir", "..\\..\\.\\.\\\\foo\\\\\\bar", "\\foo\\bar" },
     206                 :            :     { "\\etc", "\\\\\\triple\\slash", "\\triple\\slash" },
     207                 :            :     { "\\etc", "\\\\double\\slash", "\\\\double\\slash" },
     208                 :            :     { "\\\\\\triple\\slash", ".", "\\triple\\slash" },
     209                 :            :     { "\\\\double\\slash", ".", "\\\\double\\slash\\" },
     210                 :            :     { "\\cwd\\..\\with\\.\\complexities\\", ".\\hello", "\\with\\complexities\\hello" },
     211                 :            :     { "\\", ".dot-dir", "\\.dot-dir" },
     212                 :            :     { "\\cwd", "..", "\\" },
     213                 :            :     { "\\etc", "hello\\..", "\\etc" },
     214                 :            :     { "\\etc", "hello\\..\\", "\\etc" },
     215                 :            :     { "\\", "..", "\\" },
     216                 :            :     { "\\", "..\\", "\\" },
     217                 :            :     { "\\", "\\..", "\\" },
     218                 :            :     { "\\", "\\..\\", "\\" },
     219                 :            :     { "\\", ".", "\\" },
     220                 :            :     { "\\", ".\\", "\\" },
     221                 :            :     { "\\", "\\.", "\\" },
     222                 :            :     { "\\", "\\.\\", "\\" },
     223                 :            :     { "\\", "\\\\\\usr\\..\\usr", "\\usr" },
     224                 :            : #endif
     225                 :            :   };
     226                 :          1 :   const guint n_canonicalize_filename_checks = G_N_ELEMENTS (canonicalize_filename_checks);
     227                 :            :   gchar *string;
     228                 :            :   guint i;
     229                 :            : 
     230                 :          1 :   string = g_path_get_basename (G_DIR_SEPARATOR_S "foo" G_DIR_SEPARATOR_S "dir" G_DIR_SEPARATOR_S);
     231                 :          1 :   g_assert_cmpstr (string, ==, "dir");
     232                 :          1 :   g_free (string);
     233                 :          1 :   string = g_path_get_basename (G_DIR_SEPARATOR_S "foo" G_DIR_SEPARATOR_S "file");
     234                 :          1 :   g_assert_cmpstr (string, ==, "file");
     235                 :          1 :   g_free (string);
     236                 :            : 
     237                 :            : #ifdef G_OS_WIN32
     238                 :            :   string = g_path_get_basename ("/foo/dir/");
     239                 :            :   g_assert_cmpstr (string, ==, "dir");
     240                 :            :   g_free (string);
     241                 :            :   string = g_path_get_basename ("/foo/file");
     242                 :            :   g_assert_cmpstr (string, ==, "file");
     243                 :            :   g_free (string);
     244                 :            : #endif
     245                 :            : 
     246         [ +  + ]:         12 :   for (i = 0; i < n_dirname_checks; i++)
     247                 :            :     {
     248                 :         11 :       gchar *dirname = g_path_get_dirname (dirname_checks[i].filename);
     249                 :         11 :       g_assert_cmpstr (dirname, ==, dirname_checks[i].dirname);
     250                 :         11 :       g_free (dirname);
     251                 :            :     }
     252                 :            : 
     253         [ +  + ]:          8 :   for (i = 0; i < n_skip_root_checks; i++)
     254                 :            :     {
     255                 :          7 :       const gchar *skipped = g_path_skip_root (skip_root_checks[i].filename);
     256   [ +  +  +  -  :          7 :       if ((skipped && !skip_root_checks[i].without_root) ||
                   +  + ]
     257   [ +  -  +  + ]:          7 :           (!skipped && skip_root_checks[i].without_root) ||
     258         [ +  - ]:          4 :           ((skipped && skip_root_checks[i].without_root) &&
     259         [ -  + ]:          4 :            strcmp (skipped, skip_root_checks[i].without_root)))
     260                 :            :         {
     261   [ #  #  #  # ]:          0 :           g_error ("failed for \"%s\"==\"%s\" (returned: \"%s\")",
     262                 :            :                    skip_root_checks[i].filename,
     263                 :            :                    (skip_root_checks[i].without_root ? skip_root_checks[i].without_root : "<NULL>"),
     264                 :            :                    (skipped ? skipped : "<NULL>"));
     265                 :            :         }
     266                 :            :     }
     267                 :            : 
     268         [ +  + ]:         28 :   for (i = 0; i < n_canonicalize_filename_checks; i++)
     269                 :            :     {
     270                 :            :       gchar *canonical_path =
     271                 :         27 :           g_canonicalize_filename (canonicalize_filename_checks[i].relative_path,
     272                 :         27 :                                    canonicalize_filename_checks[i].cwd);
     273                 :         27 :       g_assert_cmpstr (canonical_path, ==,
     274                 :            :                        canonicalize_filename_checks[i].canonical_path);
     275                 :         27 :       g_free (canonical_path);
     276                 :            :     }
     277                 :            : 
     278                 :            :   {
     279                 :          1 :     const gchar *relative_path = "./";
     280                 :          1 :     gchar *canonical_path = g_canonicalize_filename (relative_path, NULL);
     281                 :          1 :     gchar *cwd = g_get_current_dir ();
     282                 :          1 :     g_assert_cmpstr (canonical_path, ==, cwd);
     283                 :          1 :     g_free (cwd);
     284                 :          1 :     g_free (canonical_path);
     285                 :            :   }
     286                 :          1 : }
     287                 :            : 
     288                 :            : static void
     289                 :          1 : test_build_path (void)
     290                 :            : {
     291         [ +  - ]:          1 :   if (g_test_undefined ())
     292                 :            :     {
     293                 :          1 :       g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
     294                 :            :                              "*assertion*!= NULL*");
     295                 :          1 :       g_assert_null (g_build_path (NULL, "x", "y", NULL));
     296                 :          1 :       g_test_assert_expected_messages ();
     297                 :            :     }
     298                 :            : 
     299                 :            : /*  check_string (g_build_path ("", NULL), "");*/
     300                 :          1 :   check_string (g_build_path ("", "", NULL), "");
     301                 :          1 :   check_string (g_build_path ("", "x", NULL), "x");
     302                 :          1 :   check_string (g_build_path ("", "x", "y",  NULL), "xy");
     303                 :          1 :   check_string (g_build_path ("", "x", "y", "z", NULL), "xyz");
     304                 :            : 
     305                 :            : /*  check_string (g_build_path (":", NULL), "");*/
     306                 :          1 :   check_string (g_build_path (":", ":", NULL), ":");
     307                 :          1 :   check_string (g_build_path (":", ":x", NULL), ":x");
     308                 :          1 :   check_string (g_build_path (":", "x:", NULL), "x:");
     309                 :          1 :   check_string (g_build_path (":", "", "x", NULL), "x");
     310                 :          1 :   check_string (g_build_path (":", "", ":x", NULL), ":x");
     311                 :          1 :   check_string (g_build_path (":", ":", "x", NULL), ":x");
     312                 :          1 :   check_string (g_build_path (":", "::", "x", NULL), "::x");
     313                 :          1 :   check_string (g_build_path (":", "x", "", NULL), "x");
     314                 :          1 :   check_string (g_build_path (":", "x:", "", NULL), "x:");
     315                 :          1 :   check_string (g_build_path (":", "x", ":", NULL), "x:");
     316                 :          1 :   check_string (g_build_path (":", "x", "::", NULL), "x::");
     317                 :          1 :   check_string (g_build_path (":", "x", "y",  NULL), "x:y");
     318                 :          1 :   check_string (g_build_path (":", ":x", "y", NULL), ":x:y");
     319                 :          1 :   check_string (g_build_path (":", "x", "y:", NULL), "x:y:");
     320                 :          1 :   check_string (g_build_path (":", ":x:", ":y:", NULL), ":x:y:");
     321                 :          1 :   check_string (g_build_path (":", ":x::", "::y:", NULL), ":x:y:");
     322                 :          1 :   check_string (g_build_path (":", "x", "","y",  NULL), "x:y");
     323                 :          1 :   check_string (g_build_path (":", "x", ":", "y",  NULL), "x:y");
     324                 :          1 :   check_string (g_build_path (":", "x", "::", "y",  NULL), "x:y");
     325                 :          1 :   check_string (g_build_path (":", "x", "y", "z", NULL), "x:y:z");
     326                 :          1 :   check_string (g_build_path (":", ":x:", ":y:", ":z:", NULL), ":x:y:z:");
     327                 :          1 :   check_string (g_build_path (":", "::x::", "::y::", "::z::", NULL), "::x:y:z::");
     328                 :            : 
     329                 :            : /*  check_string (g_build_path ("::", NULL), "");*/
     330                 :          1 :   check_string (g_build_path ("::", "::", NULL), "::");
     331                 :          1 :   check_string (g_build_path ("::", ":::", NULL), ":::");
     332                 :          1 :   check_string (g_build_path ("::", "::x", NULL), "::x");
     333                 :          1 :   check_string (g_build_path ("::", "x::", NULL), "x::");
     334                 :          1 :   check_string (g_build_path ("::", "", "x", NULL), "x");
     335                 :          1 :   check_string (g_build_path ("::", "", "::x", NULL), "::x");
     336                 :          1 :   check_string (g_build_path ("::", "::", "x", NULL), "::x");
     337                 :          1 :   check_string (g_build_path ("::", "::::", "x", NULL), "::::x");
     338                 :          1 :   check_string (g_build_path ("::", "x", "", NULL), "x");
     339                 :          1 :   check_string (g_build_path ("::", "x::", "", NULL), "x::");
     340                 :          1 :   check_string (g_build_path ("::", "x", "::", NULL), "x::");
     341                 :            : 
     342                 :            :   /* This following is weird, but keeps the definition simple */
     343                 :          1 :   check_string (g_build_path ("::", "x", ":::", NULL), "x:::::");
     344                 :          1 :   check_string (g_build_path ("::", "x", "::::", NULL), "x::::");
     345                 :          1 :   check_string (g_build_path ("::", "x", "y",  NULL), "x::y");
     346                 :          1 :   check_string (g_build_path ("::", "::x", "y", NULL), "::x::y");
     347                 :          1 :   check_string (g_build_path ("::", "x", "y::", NULL), "x::y::");
     348                 :          1 :   check_string (g_build_path ("::", "::x::", "::y::", NULL), "::x::y::");
     349                 :          1 :   check_string (g_build_path ("::", "::x:::", ":::y::", NULL), "::x::::y::");
     350                 :          1 :   check_string (g_build_path ("::", "::x::::", "::::y::", NULL), "::x::y::");
     351                 :          1 :   check_string (g_build_path ("::", "x", "", "y",  NULL), "x::y");
     352                 :          1 :   check_string (g_build_path ("::", "x", "::", "y",  NULL), "x::y");
     353                 :          1 :   check_string (g_build_path ("::", "x", "::::", "y",  NULL), "x::y");
     354                 :          1 :   check_string (g_build_path ("::", "x", "y", "z", NULL), "x::y::z");
     355                 :          1 :   check_string (g_build_path ("::", "::x::", "::y::", "::z::", NULL), "::x::y::z::");
     356                 :          1 :   check_string (g_build_path ("::", ":::x:::", ":::y:::", ":::z:::", NULL), ":::x::::y::::z:::");
     357                 :          1 :   check_string (g_build_path ("::", "::::x::::", "::::y::::", "::::z::::", NULL), "::::x::y::z::::");
     358                 :          1 : }
     359                 :            : 
     360                 :            : static void
     361                 :          1 : test_build_pathv (void)
     362                 :            : {
     363                 :            :   gchar *args[10];
     364                 :            : 
     365                 :          1 :   g_assert_null (g_build_pathv ("", NULL));
     366                 :          1 :   args[0] = NULL;
     367                 :          1 :   check_string (g_build_pathv ("", args), "");
     368                 :          1 :   args[0] = ""; args[1] = NULL;
     369                 :          1 :   check_string (g_build_pathv ("", args), "");
     370                 :          1 :   args[0] = "x"; args[1] = NULL;
     371                 :          1 :   check_string (g_build_pathv ("", args), "x");
     372                 :          1 :   args[0] = "x"; args[1] = "y"; args[2] = NULL;
     373                 :          1 :   check_string (g_build_pathv ("", args), "xy");
     374                 :          1 :   args[0] = "x"; args[1] = "y"; args[2] = "z", args[3] = NULL;
     375                 :          1 :   check_string (g_build_pathv ("", args), "xyz");
     376                 :            : 
     377                 :          1 :   args[0] = NULL;
     378                 :          1 :   check_string (g_build_pathv (":", args), "");
     379                 :          1 :   args[0] = ":"; args[1] = NULL;
     380                 :          1 :   check_string (g_build_pathv (":", args), ":");
     381                 :          1 :   args[0] = ":x"; args[1] = NULL;
     382                 :          1 :   check_string (g_build_pathv (":", args), ":x");
     383                 :          1 :   args[0] = "x:"; args[1] = NULL;
     384                 :          1 :   check_string (g_build_pathv (":", args), "x:");
     385                 :          1 :   args[0] = ""; args[1] = "x"; args[2] = NULL;
     386                 :          1 :   check_string (g_build_pathv (":", args), "x");
     387                 :          1 :   args[0] = ""; args[1] = ":x"; args[2] = NULL;
     388                 :          1 :   check_string (g_build_pathv (":", args), ":x");
     389                 :          1 :   args[0] = ":"; args[1] = "x"; args[2] = NULL;
     390                 :          1 :   check_string (g_build_pathv (":", args), ":x");
     391                 :          1 :   args[0] = "::"; args[1] = "x"; args[2] = NULL;
     392                 :          1 :   check_string (g_build_pathv (":", args), "::x");
     393                 :          1 :   args[0] = "x"; args[1] = ""; args[2] = NULL;
     394                 :          1 :   check_string (g_build_pathv (":", args), "x");
     395                 :          1 :   args[0] = "x:"; args[1] = ""; args[2] = NULL;
     396                 :          1 :   check_string (g_build_pathv (":", args), "x:");
     397                 :          1 :   args[0] = "x"; args[1] = ":"; args[2] = NULL;
     398                 :          1 :   check_string (g_build_pathv (":", args), "x:");
     399                 :          1 :   args[0] = "x"; args[1] = "::"; args[2] = NULL;
     400                 :          1 :   check_string (g_build_pathv (":", args), "x::");
     401                 :          1 :   args[0] = "x"; args[1] = "y"; args[2] = NULL;
     402                 :          1 :   check_string (g_build_pathv (":", args), "x:y");
     403                 :          1 :   args[0] = ":x"; args[1] = "y"; args[2] = NULL;
     404                 :          1 :   check_string (g_build_pathv (":", args), ":x:y");
     405                 :          1 :   args[0] = "x"; args[1] = "y:"; args[2] = NULL;
     406                 :          1 :   check_string (g_build_pathv (":", args), "x:y:");
     407                 :          1 :   args[0] = ":x:"; args[1] = ":y:"; args[2] = NULL;
     408                 :          1 :   check_string (g_build_pathv (":", args), ":x:y:");
     409                 :          1 :   args[0] = ":x::"; args[1] = "::y:"; args[2] = NULL;
     410                 :          1 :   check_string (g_build_pathv (":", args), ":x:y:");
     411                 :          1 :   args[0] = "x"; args[1] = ""; args[2] = "y"; args[3] = NULL;
     412                 :          1 :   check_string (g_build_pathv (":", args), "x:y");
     413                 :          1 :   args[0] = "x"; args[1] = ":"; args[2] = "y"; args[3] = NULL;
     414                 :          1 :   check_string (g_build_pathv (":", args), "x:y");
     415                 :          1 :   args[0] = "x"; args[1] = "::"; args[2] = "y"; args[3] = NULL;
     416                 :          1 :   check_string (g_build_pathv (":", args), "x:y");
     417                 :          1 :   args[0] = "x"; args[1] = "y"; args[2] = "z"; args[3] = NULL;
     418                 :          1 :   check_string (g_build_pathv (":", args), "x:y:z");
     419                 :          1 :   args[0] = ":x:"; args[1] = ":y:"; args[2] = ":z:"; args[3] = NULL;
     420                 :          1 :   check_string (g_build_pathv (":", args), ":x:y:z:");
     421                 :          1 :   args[0] = "::x::"; args[1] = "::y::"; args[2] = "::z::"; args[3] = NULL;
     422                 :          1 :   check_string (g_build_pathv (":", args), "::x:y:z::");
     423                 :            : 
     424                 :          1 :   args[0] = NULL;
     425                 :          1 :   check_string (g_build_pathv ("::", args), "");
     426                 :          1 :   args[0] = "::"; args[1] = NULL;
     427                 :          1 :   check_string (g_build_pathv ("::", args), "::");
     428                 :          1 :   args[0] = ":::"; args[1] = NULL;
     429                 :          1 :   check_string (g_build_pathv ("::", args), ":::");
     430                 :          1 :   args[0] = "::x"; args[1] = NULL;
     431                 :          1 :   check_string (g_build_pathv ("::", args), "::x");
     432                 :          1 :   args[0] = "x::"; args[1] = NULL;
     433                 :          1 :   check_string (g_build_pathv ("::", args), "x::");
     434                 :          1 :   args[0] = ""; args[1] = "x"; args[2] = NULL;
     435                 :          1 :   check_string (g_build_pathv ("::", args), "x");
     436                 :          1 :   args[0] = ""; args[1] = "::x"; args[2] = NULL;
     437                 :          1 :   check_string (g_build_pathv ("::", args), "::x");
     438                 :          1 :   args[0] = "::"; args[1] = "x"; args[2] = NULL;
     439                 :          1 :   check_string (g_build_pathv ("::", args), "::x");
     440                 :          1 :   args[0] = "::::"; args[1] = "x"; args[2] = NULL;
     441                 :          1 :   check_string (g_build_pathv ("::", args), "::::x");
     442                 :          1 :   args[0] = "x"; args[1] = ""; args[2] = NULL;
     443                 :          1 :   check_string (g_build_pathv ("::", args), "x");
     444                 :          1 :   args[0] = "x::"; args[1] = ""; args[2] = NULL;
     445                 :          1 :   check_string (g_build_pathv ("::", args), "x::");
     446                 :          1 :   args[0] = "x"; args[1] = "::"; args[2] = NULL;
     447                 :          1 :   check_string (g_build_pathv ("::", args), "x::");
     448                 :            :   /* This following is weird, but keeps the definition simple */
     449                 :          1 :   args[0] = "x"; args[1] = ":::"; args[2] = NULL;
     450                 :          1 :   check_string (g_build_pathv ("::", args), "x:::::");
     451                 :          1 :   args[0] = "x"; args[1] = "::::"; args[2] = NULL;
     452                 :          1 :   check_string (g_build_pathv ("::", args), "x::::");
     453                 :          1 :   args[0] = "x"; args[1] = "y"; args[2] = NULL;
     454                 :          1 :   check_string (g_build_pathv ("::", args), "x::y");
     455                 :          1 :   args[0] = "::x"; args[1] = "y"; args[2] = NULL;
     456                 :          1 :   check_string (g_build_pathv ("::", args), "::x::y");
     457                 :          1 :   args[0] = "x"; args[1] = "y::"; args[2] = NULL;
     458                 :          1 :   check_string (g_build_pathv ("::", args), "x::y::");
     459                 :          1 :   args[0] = "::x::"; args[1] = "::y::"; args[2] = NULL;
     460                 :          1 :   check_string (g_build_pathv ("::", args), "::x::y::");
     461                 :          1 :   args[0] = "::x:::"; args[1] = ":::y::"; args[2] = NULL;
     462                 :          1 :   check_string (g_build_pathv ("::", args), "::x::::y::");
     463                 :          1 :   args[0] = "::x::::"; args[1] = "::::y::"; args[2] = NULL;
     464                 :          1 :   check_string (g_build_pathv ("::", args), "::x::y::");
     465                 :          1 :   args[0] = "x"; args[1] = ""; args[2] = "y"; args[3] = NULL;
     466                 :          1 :   check_string (g_build_pathv ("::", args), "x::y");
     467                 :          1 :   args[0] = "x"; args[1] = "::"; args[2] = "y"; args[3] = NULL;
     468                 :          1 :   check_string (g_build_pathv ("::", args), "x::y");
     469                 :          1 :   args[0] = "x"; args[1] = "::::"; args[2] = "y"; args[3] = NULL;
     470                 :          1 :   check_string (g_build_pathv ("::", args), "x::y");
     471                 :          1 :   args[0] = "x"; args[1] = "y"; args[2] = "z"; args[3] = NULL;
     472                 :          1 :   check_string (g_build_pathv ("::", args), "x::y::z");
     473                 :          1 :   args[0] = "::x::"; args[1] = "::y::"; args[2] = "::z::"; args[3] = NULL;
     474                 :          1 :   check_string (g_build_pathv ("::", args), "::x::y::z::");
     475                 :          1 :   args[0] = ":::x:::"; args[1] = ":::y:::"; args[2] = ":::z:::"; args[3] = NULL;
     476                 :          1 :   check_string (g_build_pathv ("::", args), ":::x::::y::::z:::");
     477                 :          1 :   args[0] = "::::x::::"; args[1] = "::::y::::"; args[2] = "::::z::::"; args[3] = NULL;
     478                 :          1 :   check_string (g_build_pathv ("::", args), "::::x::y::z::::");
     479                 :          1 : }
     480                 :            : 
     481                 :            : static void
     482                 :          1 : test_build_filename (void)
     483                 :            : {
     484                 :          1 :   check_string (g_build_filename (S, NULL), S);
     485                 :          1 :   check_string (g_build_filename (S"x", NULL), S"x");
     486                 :          1 :   check_string (g_build_filename ("x"S, NULL), "x"S);
     487                 :          1 :   check_string (g_build_filename ("", "x", NULL), "x");
     488                 :          1 :   check_string (g_build_filename ("", S"x", NULL), S"x");
     489                 :          1 :   check_string (g_build_filename (S, "x", NULL), S"x");
     490                 :          1 :   check_string (g_build_filename (S S, "x", NULL), S S"x");
     491                 :          1 :   check_string (g_build_filename ("x", "", NULL), "x");
     492                 :          1 :   check_string (g_build_filename ("x"S, "", NULL), "x"S);
     493                 :          1 :   check_string (g_build_filename ("x", S, NULL), "x"S);
     494                 :          1 :   check_string (g_build_filename ("x", S S, NULL), "x"S S);
     495                 :          1 :   check_string (g_build_filename ("x", "y",  NULL), "x"S"y");
     496                 :          1 :   check_string (g_build_filename (S"x", "y", NULL), S"x"S"y");
     497                 :          1 :   check_string (g_build_filename ("x", "y"S, NULL), "x"S"y"S);
     498                 :          1 :   check_string (g_build_filename (S"x"S, S"y"S, NULL), S"x"S"y"S);
     499                 :          1 :   check_string (g_build_filename (S"x"S S, S S"y"S, NULL), S"x"S"y"S);
     500                 :          1 :   check_string (g_build_filename ("x", "", "y",  NULL), "x"S"y");
     501                 :          1 :   check_string (g_build_filename ("x", S, "y",  NULL), "x"S"y");
     502                 :          1 :   check_string (g_build_filename ("x", S S, "y",  NULL), "x"S"y");
     503                 :          1 :   check_string (g_build_filename ("x", "y", "z", NULL), "x"S"y"S"z");
     504                 :          1 :   check_string (g_build_filename (S"x"S, S"y"S, S"z"S, NULL), S"x"S"y"S"z"S);
     505                 :          1 :   check_string (g_build_filename (S S"x"S S, S S"y"S S, S S"z"S S, NULL), S S"x"S"y"S"z"S S);
     506                 :            : 
     507                 :            : #ifdef G_OS_WIN32
     508                 :            : 
     509                 :            :   /* Test also using the slash as file name separator */
     510                 :            : #define Z "/"
     511                 :            :   /* check_string (g_build_filename (NULL), ""); */
     512                 :            :   check_string (g_build_filename (Z, NULL), Z);
     513                 :            :   check_string (g_build_filename (Z"x", NULL), Z"x");
     514                 :            :   check_string (g_build_filename ("x"Z, NULL), "x"Z);
     515                 :            :   check_string (g_build_filename ("", Z"x", NULL), Z"x");
     516                 :            :   check_string (g_build_filename ("", Z"x", NULL), Z"x");
     517                 :            :   check_string (g_build_filename (Z, "x", NULL), Z"x");
     518                 :            :   check_string (g_build_filename (Z Z, "x", NULL), Z Z"x");
     519                 :            :   check_string (g_build_filename (Z S, "x", NULL), Z S"x");
     520                 :            :   check_string (g_build_filename ("x"Z, "", NULL), "x"Z);
     521                 :            :   check_string (g_build_filename ("x"S"y", "z"Z"a", NULL), "x"S"y"S"z"Z"a");
     522                 :            :   check_string (g_build_filename ("x", Z, NULL), "x"Z);
     523                 :            :   check_string (g_build_filename ("x", Z Z, NULL), "x"Z Z);
     524                 :            :   check_string (g_build_filename ("x", S Z, NULL), "x"S Z);
     525                 :            :   check_string (g_build_filename (Z"x", "y", NULL), Z"x"Z"y");
     526                 :            :   check_string (g_build_filename ("x", "y"Z, NULL), "x"Z"y"Z);
     527                 :            :   check_string (g_build_filename (Z"x"Z, Z"y"Z, NULL), Z"x"Z"y"Z);
     528                 :            :   check_string (g_build_filename (Z"x"Z Z, Z Z"y"Z, NULL), Z"x"Z"y"Z);
     529                 :            :   check_string (g_build_filename ("x", Z, "y",  NULL), "x"Z"y");
     530                 :            :   check_string (g_build_filename ("x", Z Z, "y",  NULL), "x"Z"y");
     531                 :            :   check_string (g_build_filename ("x", Z S, "y",  NULL), "x"S"y");
     532                 :            :   check_string (g_build_filename ("x", S Z, "y",  NULL), "x"Z"y");
     533                 :            :   check_string (g_build_filename ("x", Z "y", "z", NULL), "x"Z"y"Z"z");
     534                 :            :   check_string (g_build_filename ("x", S "y", "z", NULL), "x"S"y"S"z");
     535                 :            :   check_string (g_build_filename ("x", S "y", "z", Z, "a", "b", NULL), "x"S"y"S"z"Z"a"Z"b");
     536                 :            :   check_string (g_build_filename (Z"x"Z, Z"y"Z, Z"z"Z, NULL), Z"x"Z"y"Z"z"Z);
     537                 :            :   check_string (g_build_filename (Z Z"x"Z Z, Z Z"y"Z Z, Z Z"z"Z Z, NULL), Z Z"x"Z"y"Z"z"Z Z);
     538                 :            : 
     539                 :            : #undef Z
     540                 :            : 
     541                 :            : #endif /* G_OS_WIN32 */
     542                 :            : 
     543                 :          1 : }
     544                 :            : 
     545                 :            : static void
     546                 :          1 : test_build_filenamev (void)
     547                 :            : {
     548                 :            :   gchar *args[10];
     549                 :            : 
     550                 :          1 :   args[0] = NULL;
     551                 :          1 :   check_string (g_build_filenamev (args), "");
     552                 :          1 :   args[0] = S; args[1] = NULL;
     553                 :          1 :   check_string (g_build_filenamev (args), S);
     554                 :          1 :   args[0] = S"x"; args[1] = NULL;
     555                 :          1 :   check_string (g_build_filenamev (args), S"x");
     556                 :          1 :   args[0] = "x"S; args[1] = NULL;
     557                 :          1 :   check_string (g_build_filenamev (args), "x"S);
     558                 :          1 :   args[0] = ""; args[1] = "x"; args[2] = NULL;
     559                 :          1 :   check_string (g_build_filenamev (args), "x");
     560                 :          1 :   args[0] = ""; args[1] = S"x"; args[2] = NULL;
     561                 :          1 :   check_string (g_build_filenamev (args), S"x");
     562                 :          1 :   args[0] = S; args[1] = "x"; args[2] = NULL;
     563                 :          1 :   check_string (g_build_filenamev (args), S"x");
     564                 :          1 :   args[0] = S S; args[1] = "x"; args[2] = NULL;
     565                 :          1 :   check_string (g_build_filenamev (args), S S"x");
     566                 :          1 :   args[0] = "x"; args[1] = ""; args[2] = NULL;
     567                 :          1 :   check_string (g_build_filenamev (args), "x");
     568                 :          1 :   args[0] = "x"S; args[1] = ""; args[2] = NULL;
     569                 :          1 :   check_string (g_build_filenamev (args), "x"S);
     570                 :          1 :   args[0] = "x"; args[1] = S; args[2] = NULL;
     571                 :          1 :   check_string (g_build_filenamev (args), "x"S);
     572                 :          1 :   args[0] = "x"; args[1] = S S; args[2] = NULL;
     573                 :          1 :   check_string (g_build_filenamev (args), "x"S S);
     574                 :          1 :   args[0] = "x"; args[1] = "y"; args[2] = NULL;
     575                 :          1 :   check_string (g_build_filenamev (args), "x"S"y");
     576                 :          1 :   args[0] = S"x"; args[1] = "y"; args[2] = NULL;
     577                 :          1 :   check_string (g_build_filenamev (args), S"x"S"y");
     578                 :          1 :   args[0] = "x"; args[1] = "y"S; args[2] = NULL;
     579                 :          1 :   check_string (g_build_filenamev (args), "x"S"y"S);
     580                 :          1 :   args[0] = S"x"S; args[1] = S"y"S; args[2] = NULL;
     581                 :          1 :   check_string (g_build_filenamev (args), S"x"S"y"S);
     582                 :          1 :   args[0] = S"x"S S; args[1] = S S"y"S; args[2] = NULL;
     583                 :          1 :   check_string (g_build_filenamev (args), S"x"S"y"S);
     584                 :          1 :   args[0] = "x"; args[1] = ""; args[2] = "y"; args[3] = NULL;
     585                 :          1 :   check_string (g_build_filenamev (args), "x"S"y");
     586                 :          1 :   args[0] = "x"; args[1] = S; args[2] = "y"; args[3] = NULL;
     587                 :          1 :   check_string (g_build_filenamev (args), "x"S"y");
     588                 :          1 :   args[0] = "x"; args[1] = S S; args[2] = "y"; args[3] = NULL;
     589                 :          1 :   check_string (g_build_filenamev (args), "x"S"y");
     590                 :          1 :   args[0] = "x"; args[1] = "y"; args[2] = "z"; args[3] = NULL;
     591                 :          1 :   check_string (g_build_filenamev (args), "x"S"y"S"z");
     592                 :          1 :   args[0] = S"x"S; args[1] = S"y"S; args[2] = S"z"S; args[3] = NULL;
     593                 :          1 :   check_string (g_build_filenamev (args), S"x"S"y"S"z"S);
     594                 :          1 :   args[0] = S S"x"S S; args[1] = S S"y"S S; args[2] = S S"z"S S; args[3] = NULL;
     595                 :          1 :   check_string (g_build_filenamev (args), S S"x"S"y"S"z"S S);
     596                 :            : 
     597                 :            : #ifdef G_OS_WIN32
     598                 :            : 
     599                 :            :   /* Test also using the slash as file name separator */
     600                 :            : #define Z "/"
     601                 :            :   args[0] = NULL;
     602                 :            :   check_string (g_build_filenamev (args), "");
     603                 :            :   args[0] = Z; args[1] = NULL;
     604                 :            :   check_string (g_build_filenamev (args), Z);
     605                 :            :   args[0] = Z"x"; args[1] = NULL;
     606                 :            :   check_string (g_build_filenamev (args), Z"x");
     607                 :            :   args[0] = "x"Z; args[1] = NULL;
     608                 :            :   check_string (g_build_filenamev (args), "x"Z);
     609                 :            :   args[0] = ""; args[1] = Z"x"; args[2] = NULL;
     610                 :            :   check_string (g_build_filenamev (args), Z"x");
     611                 :            :   args[0] = ""; args[1] = Z"x"; args[2] = NULL;
     612                 :            :   check_string (g_build_filenamev (args), Z"x");
     613                 :            :   args[0] = Z; args[1] = "x"; args[2] = NULL;
     614                 :            :   check_string (g_build_filenamev (args), Z"x");
     615                 :            :   args[0] = Z Z; args[1] = "x"; args[2] = NULL;
     616                 :            :   check_string (g_build_filenamev (args), Z Z"x");
     617                 :            :   args[0] = Z S; args[1] = "x"; args[2] = NULL;
     618                 :            :   check_string (g_build_filenamev (args), Z S"x");
     619                 :            :   args[0] = "x"Z; args[1] = ""; args[2] = NULL;
     620                 :            :   check_string (g_build_filenamev (args), "x"Z);
     621                 :            :   args[0] = "x"S"y"; args[1] = "z"Z"a"; args[2] = NULL;
     622                 :            :   check_string (g_build_filenamev (args), "x"S"y"S"z"Z"a");
     623                 :            :   args[0] = "x"; args[1] = Z; args[2] = NULL;
     624                 :            :   check_string (g_build_filenamev (args), "x"Z);
     625                 :            :   args[0] = "x"; args[1] = Z Z; args[2] = NULL;
     626                 :            :   check_string (g_build_filenamev (args), "x"Z Z);
     627                 :            :   args[0] = "x"; args[1] = S Z; args[2] = NULL;
     628                 :            :   check_string (g_build_filenamev (args), "x"S Z);
     629                 :            :   args[0] = Z"x"; args[1] = "y"; args[2] = NULL;
     630                 :            :   check_string (g_build_filenamev (args), Z"x"Z"y");
     631                 :            :   args[0] = "x"; args[1] = "y"Z; args[2] = NULL;
     632                 :            :   check_string (g_build_filenamev (args), "x"Z"y"Z);
     633                 :            :   args[0] = Z"x"Z; args[1] = Z"y"Z; args[2] = NULL;
     634                 :            :   check_string (g_build_filenamev (args), Z"x"Z"y"Z);
     635                 :            :   args[0] = Z"x"Z Z; args[1] = Z Z"y"Z; args[2] = NULL;
     636                 :            :   check_string (g_build_filenamev (args), Z"x"Z"y"Z);
     637                 :            :   args[0] = "x"; args[1] = Z; args[2] = "y", args[3] = NULL;
     638                 :            :   check_string (g_build_filenamev (args), "x"Z"y");
     639                 :            :   args[0] = "x"; args[1] = Z Z; args[2] = "y", args[3] = NULL;
     640                 :            :   check_string (g_build_filenamev (args), "x"Z"y");
     641                 :            :   args[0] = "x"; args[1] = Z S; args[2] = "y", args[3] = NULL;
     642                 :            :   check_string (g_build_filenamev (args), "x"S"y");
     643                 :            :   args[0] = "x"; args[1] = S Z; args[2] = "y", args[3] = NULL;
     644                 :            :   check_string (g_build_filenamev (args), "x"Z"y");
     645                 :            :   args[0] = "x"; args[1] = Z "y"; args[2] = "z", args[3] = NULL;
     646                 :            :   check_string (g_build_filenamev (args), "x"Z"y"Z"z");
     647                 :            :   args[0] = "x"; args[1] = S "y"; args[2] = "z", args[3] = NULL;
     648                 :            :   check_string (g_build_filenamev (args), "x"S"y"S"z");
     649                 :            :   args[0] = "x"; args[1] = S "y"; args[2] = "z", args[3] = Z;
     650                 :            :   args[4] = "a"; args[5] = "b"; args[6] = NULL;
     651                 :            :   check_string (g_build_filenamev (args), "x"S"y"S"z"Z"a"Z"b");
     652                 :            :   args[0] = Z"x"Z; args[1] = Z"y"Z; args[2] = Z"z"Z, args[3] = NULL;
     653                 :            :   check_string (g_build_filenamev (args), Z"x"Z"y"Z"z"Z);
     654                 :            :   args[0] = Z Z"x"Z Z; args[1] = Z Z"y"Z Z; args[2] = Z Z"z"Z Z, args[3] = NULL;
     655                 :            :   check_string (g_build_filenamev (args), Z Z"x"Z"y"Z"z"Z Z);
     656                 :            : 
     657                 :            : #undef Z
     658                 :            : 
     659                 :            : #endif /* G_OS_WIN32 */
     660                 :          1 : }
     661                 :            : 
     662                 :            : #undef S
     663                 :            : 
     664                 :            : static void
     665                 :          3 : test_mkdir_with_parents_1 (const gchar *base)
     666                 :            : {
     667                 :          3 :   char *p0 = g_build_filename (base, "fum", NULL);
     668                 :          3 :   char *p1 = g_build_filename (p0, "tem", NULL);
     669                 :          3 :   char *p2 = g_build_filename (p1, "zap", NULL);
     670                 :            :   FILE *f;
     671                 :            : 
     672                 :          3 :   g_remove (p2);
     673                 :          3 :   g_remove (p1);
     674                 :          3 :   g_remove (p0);
     675                 :            : 
     676         [ -  + ]:          3 :   if (g_file_test (p0, G_FILE_TEST_EXISTS))
     677                 :          0 :     g_error ("failed, %s exists, cannot test g_mkdir_with_parents", p0);
     678                 :            : 
     679         [ -  + ]:          3 :   if (g_file_test (p1, G_FILE_TEST_EXISTS))
     680                 :          0 :     g_error ("failed, %s exists, cannot test g_mkdir_with_parents", p1);
     681                 :            : 
     682         [ -  + ]:          3 :   if (g_file_test (p2, G_FILE_TEST_EXISTS))
     683                 :          0 :     g_error ("failed, %s exists, cannot test g_mkdir_with_parents", p2);
     684                 :            : 
     685         [ -  + ]:          3 :   if (g_mkdir_with_parents (p2, 0777) == -1)
     686                 :            :     {
     687                 :          0 :       int errsv = errno;
     688                 :          0 :       g_error ("failed, g_mkdir_with_parents(%s) failed: %s", p2, g_strerror (errsv));
     689                 :            :     }
     690                 :            : 
     691         [ -  + ]:          3 :   if (!g_file_test (p2, G_FILE_TEST_IS_DIR))
     692                 :          0 :     g_error ("failed, g_mkdir_with_parents(%s) succeeded, but %s is not a directory", p2, p2);
     693                 :            : 
     694         [ -  + ]:          3 :   if (!g_file_test (p1, G_FILE_TEST_IS_DIR))
     695                 :          0 :     g_error ("failed, g_mkdir_with_parents(%s) succeeded, but %s is not a directory", p2, p1);
     696                 :            : 
     697         [ -  + ]:          3 :   if (!g_file_test (p0, G_FILE_TEST_IS_DIR))
     698                 :          0 :     g_error ("failed, g_mkdir_with_parents(%s) succeeded, but %s is not a directory", p2, p0);
     699                 :            : 
     700                 :          3 :   g_rmdir (p2);
     701         [ -  + ]:          3 :   if (g_file_test (p2, G_FILE_TEST_EXISTS))
     702                 :          0 :     g_error ("failed, did g_rmdir(%s), but %s is still there", p2, p2);
     703                 :            : 
     704                 :          3 :   g_rmdir (p1);
     705         [ -  + ]:          3 :   if (g_file_test (p1, G_FILE_TEST_EXISTS))
     706                 :          0 :     g_error ("failed, did g_rmdir(%s), but %s is still there", p1, p1);
     707                 :            : 
     708                 :          3 :   f = g_fopen (p1, "w");
     709         [ -  + ]:          3 :   if (f == NULL)
     710                 :          0 :     g_error ("failed, couldn't create file %s", p1);
     711                 :          3 :   fclose (f);
     712                 :            : 
     713         [ -  + ]:          3 :   if (g_mkdir_with_parents (p1, 0666) == 0)
     714                 :          0 :     g_error ("failed, g_mkdir_with_parents(%s) succeeded, even if %s is a file", p1, p1);
     715                 :            : 
     716         [ -  + ]:          3 :   if (g_mkdir_with_parents (p2, 0666) == 0)
     717                 :          0 :     g_error("failed, g_mkdir_with_parents(%s) succeeded, even if %s is a file", p2, p1);
     718                 :            : 
     719                 :          3 :   g_remove (p2);
     720                 :          3 :   g_remove (p1);
     721                 :          3 :   g_remove (p0);
     722                 :            : 
     723                 :          3 :   g_free (p2);
     724                 :          3 :   g_free (p1);
     725                 :          3 :   g_free (p0);
     726                 :          3 : }
     727                 :            : 
     728                 :            : /*
     729                 :            :  * check_cap_dac_override:
     730                 :            :  * @tmpdir: (nullable): A temporary directory in which we can create
     731                 :            :  *  and delete files. If %NULL, use the g_get_tmp_dir(), safely.
     732                 :            :  *
     733                 :            :  * Check whether the current process can bypass DAC permissions.
     734                 :            :  *
     735                 :            :  * Traditionally, "privileged" processes (those with effective uid 0)
     736                 :            :  * could do this (and bypass many other checks), and "unprivileged"
     737                 :            :  * processes could not.
     738                 :            :  *
     739                 :            :  * In Linux, the special powers of euid 0 are divided into many
     740                 :            :  * capabilities: see `capabilities(7)`. The one we are interested in
     741                 :            :  * here is `CAP_DAC_OVERRIDE`.
     742                 :            :  *
     743                 :            :  * We do this generically instead of actually looking at the capability
     744                 :            :  * bits, so that the right thing will happen on non-Linux Unix
     745                 :            :  * implementations, in particular if they have something equivalent to
     746                 :            :  * but not identical to Linux permissions.
     747                 :            :  *
     748                 :            :  * Returns: %TRUE if we have Linux `CAP_DAC_OVERRIDE` or equivalent
     749                 :            :  *  privileges
     750                 :            :  */
     751                 :            : static gboolean
     752                 :         11 : check_cap_dac_override (const char *tmpdir)
     753                 :            : {
     754                 :            : #ifdef G_OS_UNIX
     755                 :         11 :   gchar *safe_tmpdir = NULL;
     756                 :            :   gchar *dac_denies_write;
     757                 :            :   gchar *inside;
     758                 :            :   gboolean have_cap;
     759                 :            : 
     760         [ +  + ]:         11 :   if (tmpdir == NULL)
     761                 :            :     {
     762                 :            :       /* It's unsafe to write predictable filenames into g_get_tmp_dir(),
     763                 :            :        * because it's usually a shared directory that can be subject to
     764                 :            :        * symlink attacks, so use a subdirectory for this check. */
     765                 :          2 :       GError *error = NULL;
     766                 :            : 
     767                 :          2 :       safe_tmpdir = g_dir_make_tmp (NULL, &error);
     768                 :          2 :       g_assert_no_error (error);
     769                 :          2 :       g_clear_error (&error);
     770                 :            : 
     771         [ -  + ]:          2 :       if (safe_tmpdir == NULL)
     772                 :          0 :         return FALSE;
     773                 :            : 
     774                 :          2 :       tmpdir = safe_tmpdir;
     775                 :            :     }
     776                 :            : 
     777                 :         11 :   dac_denies_write = g_build_filename (tmpdir, "dac-denies-write", NULL);
     778                 :         11 :   inside = g_build_filename (dac_denies_write, "inside", NULL);
     779                 :            : 
     780                 :         11 :   g_assert_no_errno (mkdir (dac_denies_write, S_IRWXU));
     781                 :         11 :   g_assert_no_errno (g_chmod (dac_denies_write, 0));
     782                 :            : 
     783         [ -  + ]:         11 :   if (mkdir (inside, S_IRWXU) == 0)
     784                 :            :     {
     785                 :          0 :       g_test_message ("Looks like we have CAP_DAC_OVERRIDE or equivalent");
     786                 :          0 :       g_assert_no_errno (rmdir (inside));
     787                 :          0 :       have_cap = TRUE;
     788                 :            :     }
     789                 :            :   else
     790                 :            :     {
     791                 :         11 :       int saved_errno = errno;
     792                 :            : 
     793                 :         11 :       g_test_message ("We do not have CAP_DAC_OVERRIDE or equivalent");
     794                 :         11 :       g_assert_cmpint (saved_errno, ==, EACCES);
     795                 :         11 :       have_cap = FALSE;
     796                 :            :     }
     797                 :            : 
     798                 :         11 :   g_assert_no_errno (g_chmod (dac_denies_write, S_IRWXU));
     799                 :         11 :   g_assert_no_errno (rmdir (dac_denies_write));
     800                 :            : 
     801         [ +  + ]:         11 :   if (safe_tmpdir != NULL)
     802                 :          2 :     g_assert_no_errno (rmdir (safe_tmpdir));
     803                 :            : 
     804                 :         11 :   g_free (dac_denies_write);
     805                 :         11 :   g_free (inside);
     806                 :         11 :   g_free (safe_tmpdir);
     807                 :         11 :   return have_cap;
     808                 :            : #else
     809                 :            :   return FALSE;
     810                 :            : #endif
     811                 :            : }
     812                 :            : 
     813                 :            : static void
     814                 :          1 : test_mkdir_with_parents (void)
     815                 :            : {
     816                 :            :   gchar *cwd, *new_path;
     817                 :            : #ifndef G_OS_WIN32
     818                 :          1 :   gboolean can_override_dac = check_cap_dac_override (NULL);
     819                 :            : #endif
     820         [ -  + ]:          1 :   if (g_test_verbose())
     821                 :          0 :     g_printerr ("checking g_mkdir_with_parents() in subdir ./hum/");
     822                 :          1 :   test_mkdir_with_parents_1 ("hum");
     823                 :          1 :   g_remove ("hum");
     824         [ -  + ]:          1 :   if (g_test_verbose())
     825                 :          0 :     g_printerr ("checking g_mkdir_with_parents() in subdir ./hii///haa/hee/");
     826                 :          1 :   test_mkdir_with_parents_1 ("./hii///haa/hee///");
     827                 :          1 :   g_remove ("hii/haa/hee");
     828                 :          1 :   g_remove ("hii/haa");
     829                 :          1 :   g_remove ("hii");
     830                 :          1 :   cwd = g_get_current_dir ();
     831         [ -  + ]:          1 :   if (g_test_verbose())
     832                 :          0 :     g_printerr ("checking g_mkdir_with_parents() in cwd: %s", cwd);
     833                 :          1 :   test_mkdir_with_parents_1 (cwd);
     834                 :            : 
     835                 :          1 :   new_path = g_build_filename (cwd, "new", NULL);
     836                 :          1 :   g_assert_cmpint (g_mkdir_with_parents (new_path, 0), ==, 0);
     837                 :          1 :   g_assert_cmpint (g_rmdir (new_path), ==, 0);
     838                 :          1 :   g_free (new_path);
     839                 :          1 :   g_free (cwd);
     840                 :            : 
     841                 :          1 :   g_assert_cmpint (g_mkdir_with_parents ("./test", 0), ==, 0);
     842                 :          1 :   g_assert_cmpint (g_mkdir_with_parents ("./test", 0), ==, 0);
     843                 :          1 :   g_remove ("./test");
     844                 :            : 
     845                 :            : #ifndef G_OS_WIN32
     846         [ -  + ]:          1 :   if (can_override_dac)
     847                 :            :     {
     848                 :          0 :       g_assert_cmpint (g_mkdir_with_parents ("/usr/b/c", 0), ==, 0);
     849                 :          0 :       g_remove ("/usr/b/c");
     850                 :          0 :       g_remove ("/usr/b");
     851                 :            :     }
     852                 :            :   else
     853                 :            :     {
     854                 :          1 :       g_assert_cmpint (g_mkdir_with_parents ("/usr/b/c", 0), ==, -1);
     855                 :            :       /* EPERM or EROFS may be returned if the filesystem as a whole is read-only */
     856   [ +  -  +  - ]:          1 :       if (errno != EPERM && errno != EROFS)
     857                 :          1 :         g_assert_cmpint (errno, ==, EACCES);
     858                 :            :     }
     859                 :            : 
     860                 :            : #endif
     861                 :            : 
     862                 :          1 :   g_assert_cmpint (g_mkdir_with_parents (NULL, 0), ==, -1);
     863                 :          1 :   g_assert_cmpint (errno, ==, EINVAL);
     864                 :          1 : }
     865                 :            : 
     866                 :            : /* Reproducer for https://gitlab.gnome.org/GNOME/glib/issues/1852 */
     867                 :            : static void
     868                 :          1 : test_mkdir_with_parents_permission (void)
     869                 :            : {
     870                 :            : #ifdef G_OS_UNIX
     871                 :            :   gchar *tmpdir;
     872                 :            :   gchar *subdir;
     873                 :            :   gchar *subdir2;
     874                 :            :   gchar *subdir3;
     875                 :          1 :   GError *error = NULL;
     876                 :            :   int result;
     877                 :            :   int saved_errno;
     878                 :            :   gboolean have_cap_dac_override;
     879                 :            : 
     880                 :          1 :   tmpdir = g_dir_make_tmp ("test-fileutils.XXXXXX", &error);
     881                 :          1 :   g_assert_no_error (error);
     882                 :          1 :   g_assert_nonnull (tmpdir);
     883                 :            : 
     884                 :          1 :   have_cap_dac_override = check_cap_dac_override (tmpdir);
     885                 :            : 
     886                 :          1 :   subdir = g_build_filename (tmpdir, "sub", NULL);
     887                 :          1 :   subdir2 = g_build_filename (subdir, "sub2", NULL);
     888                 :          1 :   subdir3 = g_build_filename (subdir2, "sub3", NULL);
     889                 :          1 :   g_assert_no_errno (g_mkdir (subdir, 0700));
     890                 :          1 :   g_assert_no_errno (g_chmod (subdir, 0));
     891                 :            : 
     892         [ -  + ]:          1 :   if (have_cap_dac_override)
     893                 :            :     {
     894                 :          0 :       g_test_skip ("have CAP_DAC_OVERRIDE or equivalent, cannot test");
     895                 :            :     }
     896                 :            :   else
     897                 :            :     {
     898                 :          1 :       result = g_mkdir_with_parents (subdir2, 0700);
     899                 :          1 :       saved_errno = errno;
     900                 :          1 :       g_assert_cmpint (result, ==, -1);
     901                 :          1 :       g_assert_cmpint (saved_errno, ==, EACCES);
     902                 :            : 
     903                 :          1 :       result = g_mkdir_with_parents (subdir3, 0700);
     904                 :          1 :       saved_errno = errno;
     905                 :          1 :       g_assert_cmpint (result, ==, -1);
     906                 :          1 :       g_assert_cmpint (saved_errno, ==, EACCES);
     907                 :            : 
     908                 :          1 :       g_assert_no_errno (g_chmod (subdir, 0700));
     909                 :            :     }
     910                 :            : 
     911                 :          1 :   g_assert_no_errno (g_remove (subdir));
     912                 :          1 :   g_assert_no_errno (g_remove (tmpdir));
     913                 :          1 :   g_free (subdir3);
     914                 :          1 :   g_free (subdir2);
     915                 :          1 :   g_free (subdir);
     916                 :          1 :   g_free (tmpdir);
     917                 :            : #else
     918                 :            :   g_test_skip ("cannot test without Unix-style permissions");
     919                 :            : #endif
     920                 :          1 : }
     921                 :            : 
     922                 :            : static void
     923                 :          1 : test_format_size_for_display (void)
     924                 :            : {
     925                 :            : #ifdef G_OS_WIN32
     926                 :            :   SetThreadLocale (MAKELCID (MAKELANGID (LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT));
     927                 :            : #endif
     928                 :            :   /* nobody called setlocale(), so we should get "C" behaviour... */
     929                 :          1 :   check_string (g_format_size_for_display (0), "0 bytes");
     930                 :          1 :   check_string (g_format_size_for_display (1), "1 byte");
     931                 :          1 :   check_string (g_format_size_for_display (2), "2 bytes");
     932                 :          1 :   check_string (g_format_size_for_display (1024), "1.0 KB");
     933                 :          1 :   check_string (g_format_size_for_display (1024 * 1024), "1.0 MB");
     934                 :          1 :   check_string (g_format_size_for_display (1024 * 1024 * 1024), "1.0 GB");
     935                 :          1 :   check_string (g_format_size_for_display (1024ULL * 1024 * 1024 * 1024), "1.0 TB");
     936                 :          1 :   check_string (g_format_size_for_display (1024ULL * 1024 * 1024 * 1024 * 1024), "1.0 PB");
     937                 :          1 :   check_string (g_format_size_for_display (1024ULL * 1024 * 1024 * 1024 * 1024 * 1024), "1.0 EB");
     938                 :            : 
     939                 :          1 :   check_string (g_format_size (0), "0 bytes");
     940                 :          1 :   check_string (g_format_size (1), "1 byte");
     941                 :          1 :   check_string (g_format_size (2), "2 bytes");
     942                 :            :   /* '\302\240' is a no-break space, to keep quantity and unit symbol together at line breaks*/
     943                 :          1 :   check_string (g_format_size (1000ULL), "1.0\302\240kB");
     944                 :          1 :   check_string (g_format_size (1000ULL * 1000), "1.0\302\240MB");
     945                 :          1 :   check_string (g_format_size (1000ULL * 1000 * 1000), "1.0\302\240GB");
     946                 :          1 :   check_string (g_format_size (1000ULL * 1000 * 1000 * 1000), "1.0\302\240TB");
     947                 :          1 :   check_string (g_format_size (1000ULL * 1000 * 1000 * 1000 * 1000), "1.0\302\240PB");
     948                 :          1 :   check_string (g_format_size (1000ULL * 1000 * 1000 * 1000 * 1000 * 1000), "1.0\302\240EB");
     949                 :            : 
     950                 :          1 :   check_string (g_format_size_full (0, G_FORMAT_SIZE_IEC_UNITS), "0 bytes");
     951                 :          1 :   check_string (g_format_size_full (0, G_FORMAT_SIZE_IEC_UNITS | G_FORMAT_SIZE_ONLY_VALUE), "0");
     952                 :          1 :   check_string (g_format_size_full (0, G_FORMAT_SIZE_IEC_UNITS | G_FORMAT_SIZE_ONLY_UNIT), "bytes");
     953                 :          1 :   check_string (g_format_size_full (1, G_FORMAT_SIZE_IEC_UNITS), "1 byte");
     954                 :          1 :   check_string (g_format_size_full (1, G_FORMAT_SIZE_IEC_UNITS | G_FORMAT_SIZE_ONLY_VALUE), "1");
     955                 :          1 :   check_string (g_format_size_full (1, G_FORMAT_SIZE_IEC_UNITS | G_FORMAT_SIZE_ONLY_UNIT), "byte");
     956                 :          1 :   check_string (g_format_size_full (2, G_FORMAT_SIZE_IEC_UNITS), "2 bytes");
     957                 :          1 :   check_string (g_format_size_full (2, G_FORMAT_SIZE_IEC_UNITS | G_FORMAT_SIZE_ONLY_VALUE), "2");
     958                 :          1 :   check_string (g_format_size_full (2, G_FORMAT_SIZE_IEC_UNITS | G_FORMAT_SIZE_ONLY_UNIT), "bytes");
     959                 :            : 
     960                 :          1 :   check_string (g_format_size_full (2048ULL, G_FORMAT_SIZE_IEC_UNITS), "2.0\302\240KiB");
     961                 :          1 :   check_string (g_format_size_full (2048ULL * 1024, G_FORMAT_SIZE_IEC_UNITS), "2.0\302\240MiB");
     962                 :          1 :   check_string (g_format_size_full (2048ULL * 1024 * 1024, G_FORMAT_SIZE_IEC_UNITS), "2.0\302\240GiB");
     963                 :          1 :   check_string (g_format_size_full (2048ULL * 1024 * 1024 * 1024, G_FORMAT_SIZE_IEC_UNITS), "2.0\302\240TiB");
     964                 :          1 :   check_string (g_format_size_full (2048ULL * 1024 * 1024 * 1024 * 1024, G_FORMAT_SIZE_IEC_UNITS), "2.0\302\240PiB");
     965                 :          1 :   check_string (g_format_size_full (2048ULL * 1024 * 1024 * 1024 * 1024 * 1024, G_FORMAT_SIZE_IEC_UNITS), "2.0\302\240EiB");
     966                 :            : 
     967                 :          1 :   check_string (g_format_size_full (238472938, G_FORMAT_SIZE_IEC_UNITS), "227.4\302\240MiB");
     968                 :          1 :   check_string (g_format_size_full (238472938, G_FORMAT_SIZE_DEFAULT), "238.5\302\240MB");
     969                 :          1 :   check_string (g_format_size_full (238472938, G_FORMAT_SIZE_LONG_FORMAT), "238.5\302\240MB (238472938 bytes)");
     970                 :          1 :   check_string (g_format_size_full (238472938, G_FORMAT_SIZE_IEC_UNITS | G_FORMAT_SIZE_ONLY_VALUE), "227.4");
     971                 :          1 :   check_string (g_format_size_full (238472938, G_FORMAT_SIZE_IEC_UNITS | G_FORMAT_SIZE_ONLY_UNIT), "MiB");
     972                 :            : 
     973                 :            : 
     974                 :          1 :   check_string (g_format_size_full (0, G_FORMAT_SIZE_BITS), "0 bits");
     975                 :          1 :   check_string (g_format_size_full (0, G_FORMAT_SIZE_BITS | G_FORMAT_SIZE_ONLY_VALUE), "0");
     976                 :          1 :   check_string (g_format_size_full (0, G_FORMAT_SIZE_BITS | G_FORMAT_SIZE_ONLY_UNIT), "bits");
     977                 :          1 :   check_string (g_format_size_full (1, G_FORMAT_SIZE_BITS), "1 bit");
     978                 :          1 :   check_string (g_format_size_full (1, G_FORMAT_SIZE_BITS | G_FORMAT_SIZE_ONLY_VALUE), "1");
     979                 :          1 :   check_string (g_format_size_full (1, G_FORMAT_SIZE_BITS | G_FORMAT_SIZE_ONLY_UNIT), "bit");
     980                 :          1 :   check_string (g_format_size_full (2, G_FORMAT_SIZE_BITS), "2 bits");
     981                 :          1 :   check_string (g_format_size_full (2, G_FORMAT_SIZE_BITS | G_FORMAT_SIZE_ONLY_VALUE), "2");
     982                 :          1 :   check_string (g_format_size_full (2, G_FORMAT_SIZE_BITS | G_FORMAT_SIZE_ONLY_UNIT), "bits");
     983                 :            : 
     984                 :          1 :   check_string (g_format_size_full (2000ULL, G_FORMAT_SIZE_BITS), "2.0\302\240kbit");
     985                 :          1 :   check_string (g_format_size_full (2000ULL * 1000, G_FORMAT_SIZE_BITS), "2.0\302\240Mbit");
     986                 :          1 :   check_string (g_format_size_full (2000ULL * 1000 * 1000, G_FORMAT_SIZE_BITS), "2.0\302\240Gbit");
     987                 :          1 :   check_string (g_format_size_full (2000ULL * 1000 * 1000 * 1000, G_FORMAT_SIZE_BITS), "2.0\302\240Tbit");
     988                 :          1 :   check_string (g_format_size_full (2000ULL * 1000 * 1000 * 1000 * 1000, G_FORMAT_SIZE_BITS), "2.0\302\240Pbit");
     989                 :          1 :   check_string (g_format_size_full (2000ULL * 1000 * 1000 * 1000 * 1000 * 1000, G_FORMAT_SIZE_BITS), "2.0\302\240Ebit");
     990                 :            : 
     991                 :          1 :   check_string (g_format_size_full (238472938, G_FORMAT_SIZE_BITS), "238.5\302\240Mbit");
     992                 :          1 :   check_string (g_format_size_full (238472938, G_FORMAT_SIZE_BITS | G_FORMAT_SIZE_LONG_FORMAT), "238.5\302\240Mbit (238472938 bits)");
     993                 :          1 :   check_string (g_format_size_full (238472938, G_FORMAT_SIZE_BITS | G_FORMAT_SIZE_ONLY_VALUE), "238.5");
     994                 :          1 :   check_string (g_format_size_full (238472938, G_FORMAT_SIZE_BITS | G_FORMAT_SIZE_ONLY_UNIT), "Mbit");
     995                 :            : 
     996                 :            : 
     997                 :          1 :   check_string (g_format_size_full (0, G_FORMAT_SIZE_BITS | G_FORMAT_SIZE_IEC_UNITS), "0 bits");
     998                 :          1 :   check_string (g_format_size_full (0, G_FORMAT_SIZE_BITS | G_FORMAT_SIZE_IEC_UNITS | G_FORMAT_SIZE_ONLY_VALUE), "0");
     999                 :          1 :   check_string (g_format_size_full (0, G_FORMAT_SIZE_BITS | G_FORMAT_SIZE_IEC_UNITS | G_FORMAT_SIZE_ONLY_UNIT), "bits");
    1000                 :          1 :   check_string (g_format_size_full (1, G_FORMAT_SIZE_BITS | G_FORMAT_SIZE_IEC_UNITS), "1 bit");
    1001                 :          1 :   check_string (g_format_size_full (1, G_FORMAT_SIZE_BITS | G_FORMAT_SIZE_IEC_UNITS | G_FORMAT_SIZE_ONLY_VALUE), "1");
    1002                 :          1 :   check_string (g_format_size_full (1, G_FORMAT_SIZE_BITS | G_FORMAT_SIZE_IEC_UNITS | G_FORMAT_SIZE_ONLY_UNIT), "bit");
    1003                 :          1 :   check_string (g_format_size_full (2, G_FORMAT_SIZE_BITS | G_FORMAT_SIZE_IEC_UNITS), "2 bits");
    1004                 :          1 :   check_string (g_format_size_full (2, G_FORMAT_SIZE_BITS | G_FORMAT_SIZE_IEC_UNITS | G_FORMAT_SIZE_ONLY_VALUE), "2");
    1005                 :          1 :   check_string (g_format_size_full (2, G_FORMAT_SIZE_BITS | G_FORMAT_SIZE_IEC_UNITS | G_FORMAT_SIZE_ONLY_UNIT), "bits");
    1006                 :            : 
    1007                 :          1 :   check_string (g_format_size_full (2048ULL, G_FORMAT_SIZE_BITS | G_FORMAT_SIZE_IEC_UNITS), "2.0\302\240Kibit");
    1008                 :          1 :   check_string (g_format_size_full (2048ULL * 1024, G_FORMAT_SIZE_BITS | G_FORMAT_SIZE_IEC_UNITS), "2.0\302\240Mibit");
    1009                 :          1 :   check_string (g_format_size_full (2048ULL * 1024 * 1024, G_FORMAT_SIZE_BITS | G_FORMAT_SIZE_IEC_UNITS), "2.0\302\240Gibit");
    1010                 :          1 :   check_string (g_format_size_full (2048ULL * 1024 * 1024 * 1024, G_FORMAT_SIZE_BITS | G_FORMAT_SIZE_IEC_UNITS), "2.0\302\240Tibit");
    1011                 :          1 :   check_string (g_format_size_full (2048ULL * 1024 * 1024 * 1024 * 1024, G_FORMAT_SIZE_BITS | G_FORMAT_SIZE_IEC_UNITS), "2.0\302\240Pibit");
    1012                 :          1 :   check_string (g_format_size_full (2048ULL * 1024 * 1024 * 1024 * 1024 * 1024, G_FORMAT_SIZE_BITS | G_FORMAT_SIZE_IEC_UNITS), "2.0\302\240Eibit");
    1013                 :            : 
    1014                 :          1 :   check_string (g_format_size_full (238472938, G_FORMAT_SIZE_BITS | G_FORMAT_SIZE_IEC_UNITS), "227.4\302\240Mibit");
    1015                 :          1 :   check_string (g_format_size_full (238472938, G_FORMAT_SIZE_BITS | G_FORMAT_SIZE_IEC_UNITS | G_FORMAT_SIZE_LONG_FORMAT), "227.4\302\240Mibit (238472938 bits)");
    1016                 :          1 :   check_string (g_format_size_full (238472938, G_FORMAT_SIZE_BITS | G_FORMAT_SIZE_IEC_UNITS | G_FORMAT_SIZE_ONLY_VALUE), "227.4");
    1017                 :          1 :   check_string (g_format_size_full (238472938, G_FORMAT_SIZE_BITS | G_FORMAT_SIZE_IEC_UNITS | G_FORMAT_SIZE_ONLY_UNIT), "Mibit");
    1018                 :          1 : }
    1019                 :            : 
    1020                 :            : static void
    1021                 :          1 : test_file_errors (void)
    1022                 :            : {
    1023                 :          1 :   g_assert_cmpint (g_file_error_from_errno (-1), ==, G_FILE_ERROR_FAILED);
    1024                 :            : 
    1025                 :            : #ifdef EEXIST
    1026                 :          1 :   g_assert_cmpint (g_file_error_from_errno (EEXIST), ==, G_FILE_ERROR_EXIST);
    1027                 :            : #endif
    1028                 :            : #ifdef EISDIR
    1029                 :          1 :   g_assert_cmpint (g_file_error_from_errno (EISDIR), ==, G_FILE_ERROR_ISDIR);
    1030                 :            : #endif
    1031                 :            : #ifdef EACCES
    1032                 :          1 :   g_assert_cmpint (g_file_error_from_errno (EACCES), ==, G_FILE_ERROR_ACCES);
    1033                 :            : #endif
    1034                 :            : #ifdef ENAMETOOLONG
    1035                 :          1 :   g_assert_cmpint (g_file_error_from_errno (ENAMETOOLONG), ==, G_FILE_ERROR_NAMETOOLONG);
    1036                 :            : #endif
    1037                 :            : #ifdef ENOENT
    1038                 :          1 :   g_assert_cmpint (g_file_error_from_errno (ENOENT), ==, G_FILE_ERROR_NOENT);
    1039                 :            : #endif
    1040                 :            : #ifdef ENOTDIR
    1041                 :          1 :   g_assert_cmpint (g_file_error_from_errno (ENOTDIR), ==, G_FILE_ERROR_NOTDIR);
    1042                 :            : #endif
    1043                 :            : #ifdef ENXIO
    1044                 :          1 :   g_assert_cmpint (g_file_error_from_errno (ENXIO), ==, G_FILE_ERROR_NXIO);
    1045                 :            : #endif
    1046                 :            : #ifdef ENODEV
    1047                 :          1 :   g_assert_cmpint (g_file_error_from_errno (ENODEV), ==, G_FILE_ERROR_NODEV);
    1048                 :            : #endif
    1049                 :            : #ifdef EROFS
    1050                 :          1 :   g_assert_cmpint (g_file_error_from_errno (EROFS), ==, G_FILE_ERROR_ROFS);
    1051                 :            : #endif
    1052                 :            : #ifdef ETXTBSY
    1053                 :          1 :   g_assert_cmpint (g_file_error_from_errno (ETXTBSY), ==, G_FILE_ERROR_TXTBSY);
    1054                 :            : #endif
    1055                 :            : #ifdef EFAULT
    1056                 :          1 :   g_assert_cmpint (g_file_error_from_errno (EFAULT), ==, G_FILE_ERROR_FAULT);
    1057                 :            : #endif
    1058                 :            : #ifdef ELOOP
    1059                 :          1 :   g_assert_cmpint (g_file_error_from_errno (ELOOP), ==, G_FILE_ERROR_LOOP);
    1060                 :            : #endif
    1061                 :            : #ifdef ENOSPC
    1062                 :          1 :   g_assert_cmpint (g_file_error_from_errno (ENOSPC), ==, G_FILE_ERROR_NOSPC);
    1063                 :            : #endif
    1064                 :            : #ifdef ENOMEM
    1065                 :          1 :   g_assert_cmpint (g_file_error_from_errno (ENOMEM), ==, G_FILE_ERROR_NOMEM);
    1066                 :            : #endif
    1067                 :            : #ifdef EMFILE
    1068                 :          1 :   g_assert_cmpint (g_file_error_from_errno (EMFILE), ==, G_FILE_ERROR_MFILE);
    1069                 :            : #endif
    1070                 :            : #ifdef ENFILE
    1071                 :          1 :   g_assert_cmpint (g_file_error_from_errno (ENFILE), ==, G_FILE_ERROR_NFILE);
    1072                 :            : #endif
    1073                 :            : #ifdef EBADF
    1074                 :          1 :   g_assert_cmpint (g_file_error_from_errno (EBADF), ==, G_FILE_ERROR_BADF);
    1075                 :            : #endif
    1076                 :            : #ifdef EINVAL
    1077                 :          1 :   g_assert_cmpint (g_file_error_from_errno (EINVAL), ==, G_FILE_ERROR_INVAL);
    1078                 :            : #endif
    1079                 :            : #ifdef EPIPE
    1080                 :          1 :   g_assert_cmpint (g_file_error_from_errno (EPIPE), ==, G_FILE_ERROR_PIPE);
    1081                 :            : #endif
    1082                 :            : #ifdef EAGAIN
    1083                 :          1 :   g_assert_cmpint (g_file_error_from_errno (EAGAIN), ==, G_FILE_ERROR_AGAIN);
    1084                 :            : #endif
    1085                 :            : #ifdef EINTR
    1086                 :          1 :   g_assert_cmpint (g_file_error_from_errno (EINTR), ==, G_FILE_ERROR_INTR);
    1087                 :            : #endif
    1088                 :            : #ifdef EIO
    1089                 :          1 :   g_assert_cmpint (g_file_error_from_errno (EIO), ==, G_FILE_ERROR_IO);
    1090                 :            : #endif
    1091                 :            : #ifdef EPERM
    1092                 :          1 :   g_assert_cmpint (g_file_error_from_errno (EPERM), ==, G_FILE_ERROR_PERM);
    1093                 :            : #endif
    1094                 :            : #ifdef ENOSYS
    1095                 :          1 :   g_assert_cmpint (g_file_error_from_errno (ENOSYS), ==, G_FILE_ERROR_NOSYS);
    1096                 :            : #endif
    1097                 :          1 : }
    1098                 :            : 
    1099                 :            : static void
    1100                 :          1 : test_basename (void)
    1101                 :            : {
    1102                 :          1 :   const gchar *path = "/path/to/a/file/deep/down.sh";
    1103                 :            :   const gchar *b;
    1104                 :            : 
    1105         [ +  - ]:          1 :   if (g_test_undefined ())
    1106                 :            :     {
    1107                 :          1 :       g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
    1108                 :            :                              "*assertion*!= NULL*");
    1109                 :          1 :       g_assert_null (g_basename (NULL));
    1110                 :          1 :       g_test_assert_expected_messages ();
    1111                 :            :     }
    1112                 :            : 
    1113                 :          1 :   b = g_basename (path);
    1114                 :            : 
    1115                 :          1 :   g_assert_cmpstr (b, ==, "down.sh");
    1116                 :          1 : }
    1117                 :            : 
    1118                 :            : static void
    1119                 :          1 : test_get_basename (void)
    1120                 :            : {
    1121                 :            :   gchar *b;
    1122                 :            : 
    1123         [ +  - ]:          1 :   if (g_test_undefined ())
    1124                 :            :     {
    1125                 :          1 :       g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
    1126                 :            :                              "*assertion*!= NULL*");
    1127                 :          1 :       g_assert_null (g_path_get_basename (NULL));
    1128                 :          1 :       g_test_assert_expected_messages ();
    1129                 :            :     }
    1130                 :            : 
    1131                 :          1 :   b = g_path_get_basename ("");
    1132                 :          1 :   g_assert_cmpstr (b, ==, ".");
    1133                 :          1 :   g_free (b);
    1134                 :            : 
    1135                 :          1 :   b = g_path_get_basename ("///");
    1136                 :          1 :   g_assert_cmpstr (b, ==, G_DIR_SEPARATOR_S);
    1137                 :          1 :   g_free (b);
    1138                 :            : 
    1139                 :          1 :   b = g_path_get_basename ("/a/b/c/d");
    1140                 :          1 :   g_assert_cmpstr (b, ==, "d");
    1141                 :          1 :   g_free (b);
    1142                 :          1 : }
    1143                 :            : 
    1144                 :            : static void
    1145                 :          1 : test_dirname (void)
    1146                 :            : {
    1147                 :            :   gsize i;
    1148                 :            :   struct {
    1149                 :            :     const gchar *filename;
    1150                 :            :     const gchar *dirname;
    1151                 :          1 :   } dirname_checks[] = {
    1152                 :            :     { "/", "/" },
    1153                 :            :     { "////", "/" },
    1154                 :            :     { ".////", "." },
    1155                 :            :     { ".", "." },
    1156                 :            :     { "..", "." },
    1157                 :            :     { "../", ".." },
    1158                 :            :     { "..////", ".." },
    1159                 :            :     { "", "." },
    1160                 :            :     { "a/b", "a" },
    1161                 :            :     { "a/b/", "a/b" },
    1162                 :            :     { "c///", "c" },
    1163                 :            :     { "/a/b", "/a" },
    1164                 :            :     { "/a/b/", "/a/b" },
    1165                 :            : #ifdef G_OS_WIN32
    1166                 :            :     { "\\", "\\" },
    1167                 :            :     { ".\\\\\\\\", "." },
    1168                 :            :     { ".\\/\\/", "." },
    1169                 :            :     { ".", "." },
    1170                 :            :     { "..", "." },
    1171                 :            :     { "..\\", ".." },
    1172                 :            :     { "..\\\\\\\\", ".." },
    1173                 :            :     { "..\\//\\", ".." },
    1174                 :            :     { "", "." },
    1175                 :            :     { "a\\b", "a" },
    1176                 :            :     { "a\\b\\", "a\\b" },
    1177                 :            :     { "\\a\\b", "\\a" },
    1178                 :            :     { "\\a\\b\\", "\\a\\b" },
    1179                 :            :     { "c\\\\\\", "c" },
    1180                 :            :     { "c/\\\\", "c" },
    1181                 :            :     { "a:", "a:." },
    1182                 :            :     { "a:foo", "a:." },
    1183                 :            :     { "a:foo\\bar", "a:foo" },
    1184                 :            :     { "a:/foo", "a:/" },
    1185                 :            :     { "a:/foo/bar", "a:/foo" },
    1186                 :            :     { "a:/", "a:/" },
    1187                 :            :     { "a://", "a:/" },
    1188                 :            :     { "a:\\foo", "a:\\" },
    1189                 :            :     { "a:\\", "a:\\" },
    1190                 :            :     { "a:\\\\", "a:\\" },
    1191                 :            :     { "a:\\/", "a:\\" },
    1192                 :            : #endif
    1193                 :            :   };
    1194                 :            : 
    1195         [ +  - ]:          1 :   if (g_test_undefined ())
    1196                 :            :     {
    1197                 :          1 :       g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
    1198                 :            :                              "*assertion*!= NULL*");
    1199                 :          1 :       g_assert_null (g_path_get_dirname (NULL));
    1200                 :          1 :       g_test_assert_expected_messages ();
    1201                 :            :     }
    1202                 :            : 
    1203         [ +  + ]:         14 :   for (i = 0; i < G_N_ELEMENTS (dirname_checks); i++)
    1204                 :            :     {
    1205                 :            :       gchar *dirname;
    1206                 :            : 
    1207                 :         13 :       dirname = g_path_get_dirname (dirname_checks[i].filename);
    1208                 :         13 :       g_assert_cmpstr (dirname, ==, dirname_checks[i].dirname);
    1209                 :         13 :       g_free (dirname);
    1210                 :            :     }
    1211                 :          1 : }
    1212                 :            : 
    1213                 :            : static void
    1214                 :          1 : test_dir_make_tmp (void)
    1215                 :            : {
    1216                 :            :   gchar *name;
    1217                 :          1 :   GError *error = NULL;
    1218                 :            :   gint ret;
    1219                 :            : 
    1220                 :          1 :   name = g_dir_make_tmp ("testXXXXXXtest", &error);
    1221                 :          1 :   g_assert_no_error (error);
    1222                 :          1 :   g_assert_true (g_file_test (name, G_FILE_TEST_IS_DIR));
    1223                 :          1 :   g_assert_true (g_str_has_prefix (name, g_getenv ("G_TEST_TMPDIR")));
    1224                 :          1 :   ret = g_rmdir (name);
    1225                 :          1 :   g_assert_cmpint (ret, ==, 0);
    1226                 :          1 :   g_free (name);
    1227                 :            : 
    1228                 :          1 :   name = g_dir_make_tmp (NULL, &error);
    1229                 :          1 :   g_assert_no_error (error);
    1230                 :          1 :   g_assert_true (g_file_test (name, G_FILE_TEST_IS_DIR));
    1231                 :          1 :   g_assert_true (g_str_has_prefix (name, g_getenv ("G_TEST_TMPDIR")));
    1232                 :          1 :   ret = g_rmdir (name);
    1233                 :          1 :   g_assert_cmpint (ret, ==, 0);
    1234                 :          1 :   g_free (name);
    1235                 :            : 
    1236                 :          1 :   name = g_dir_make_tmp ("test/XXXXXX", &error);
    1237                 :          1 :   g_assert_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED);
    1238                 :          1 :   g_clear_error (&error);
    1239                 :          1 :   g_assert_null (name);
    1240                 :            : 
    1241                 :          1 :   name = g_dir_make_tmp ("XXXXxX", &error);
    1242                 :          1 :   g_assert_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED);
    1243                 :          1 :   g_clear_error (&error);
    1244                 :          1 :   g_assert_null (name);
    1245                 :          1 : }
    1246                 :            : 
    1247                 :            : static void
    1248                 :          1 : test_file_open_tmp (void)
    1249                 :            : {
    1250                 :          1 :   gchar *name = NULL;
    1251                 :          1 :   GError *error = NULL;
    1252                 :            :   gint fd;
    1253                 :            : 
    1254                 :          1 :   fd = g_file_open_tmp ("testXXXXXXtest", &name, &error);
    1255                 :          1 :   g_assert_cmpint (fd, !=, -1);
    1256                 :          1 :   g_assert_no_error (error);
    1257                 :          1 :   g_assert_nonnull (name);
    1258                 :          1 :   g_assert_true (g_str_has_prefix (name, g_getenv ("G_TEST_TMPDIR")));
    1259                 :          1 :   unlink (name);
    1260                 :          1 :   g_free (name);
    1261                 :          1 :   close (fd);
    1262                 :            : 
    1263                 :          1 :   fd = g_file_open_tmp (NULL, &name, &error);
    1264                 :          1 :   g_assert_cmpint (fd, !=, -1);
    1265                 :          1 :   g_assert_no_error (error);
    1266                 :          1 :   g_assert_nonnull (name);
    1267                 :          1 :   g_assert_true (g_str_has_prefix (name, g_getenv ("G_TEST_TMPDIR")));
    1268                 :          1 :   g_unlink (name);
    1269                 :          1 :   g_free (name);
    1270                 :          1 :   close (fd);
    1271                 :            : 
    1272                 :          1 :   name = NULL;
    1273                 :          1 :   fd = g_file_open_tmp ("test/XXXXXX", &name, &error);
    1274                 :          1 :   g_assert_cmpint (fd, ==, -1);
    1275                 :          1 :   g_assert_null (name);
    1276                 :          1 :   g_assert_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED);
    1277                 :          1 :   g_clear_error (&error);
    1278                 :            : 
    1279                 :          1 :   fd = g_file_open_tmp ("XXXXxX", &name, &error);
    1280                 :          1 :   g_assert_cmpint (fd, ==, -1);
    1281                 :          1 :   g_assert_null (name);
    1282                 :          1 :   g_assert_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED);
    1283                 :          1 :   g_clear_error (&error);
    1284                 :            : 
    1285                 :          1 :   error = NULL;
    1286                 :          1 :   name = NULL;
    1287                 :          1 :   fd = g_file_open_tmp ("zap" G_DIR_SEPARATOR_S "barXXXXXX", &name, &error);
    1288                 :          1 :   g_assert_cmpint (fd, ==, -1);
    1289                 :            : 
    1290                 :          1 :   g_clear_error (&error);
    1291                 :          1 :   g_free (name);
    1292                 :            : 
    1293                 :            : #ifdef G_OS_WIN32
    1294                 :            :   name = NULL;
    1295                 :            :   fd = g_file_open_tmp ("zap/barXXXXXX", &name, &error);
    1296                 :            :   g_assert_cmpint (fd, ==, -1);
    1297                 :            : 
    1298                 :            :   g_clear_error (&error);
    1299                 :            :   g_free (name);
    1300                 :            : #endif
    1301                 :            : 
    1302                 :          1 :   name = NULL;
    1303                 :          1 :   fd = g_file_open_tmp ("zapXXXXXX", &name, &error);
    1304                 :          1 :   g_assert_cmpint (fd, !=, -1);
    1305                 :            : 
    1306                 :          1 :   close (fd);
    1307                 :          1 :   g_clear_error (&error);
    1308                 :          1 :   remove (name);
    1309                 :          1 :   g_free (name);
    1310                 :            : 
    1311                 :          1 :   name = NULL;
    1312                 :          1 :   fd = g_file_open_tmp (NULL, &name, &error);
    1313                 :          1 :   g_assert_cmpint (fd, !=, -1);
    1314                 :            : 
    1315                 :          1 :   close (fd);
    1316                 :          1 :   g_clear_error (&error);
    1317                 :          1 :   remove (name);
    1318                 :          1 :   g_free (name);
    1319                 :          1 : }
    1320                 :            : 
    1321                 :            : static void
    1322                 :          1 : test_mkstemp (void)
    1323                 :            : {
    1324                 :            :   gint fd;
    1325                 :            :   gint result;
    1326                 :            :   gchar *name;
    1327                 :            :   char chars[62];
    1328                 :            :   char template[32];
    1329                 :          1 :   const char hello[] = "Hello, World";
    1330                 :          1 :   const gsize hellolen = sizeof (hello) - 1;
    1331                 :            : 
    1332         [ +  - ]:          1 :   if (g_test_undefined ())
    1333                 :            :     {
    1334                 :          1 :       g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
    1335                 :            :                              "*assertion*!= NULL*");
    1336                 :          1 :       g_assert_cmpint (g_mkstemp (NULL), ==, -1);
    1337                 :          1 :       g_test_assert_expected_messages ();
    1338                 :            :     }
    1339                 :            : 
    1340                 :            :   /* Expect to fail if no 'XXXXXX' is given */
    1341                 :          1 :   name = g_strdup ("test");
    1342                 :          1 :   g_assert_cmpint (g_mkstemp (name), ==, -1);
    1343                 :          1 :   g_free (name);
    1344                 :            : 
    1345                 :            :   /* Test normal case */
    1346                 :          1 :   name = g_strdup ("testXXXXXXtest"),
    1347                 :          1 :   fd = g_mkstemp (name);
    1348                 :          1 :   g_assert_cmpint (fd, !=, -1);
    1349                 :          1 :   g_assert_null (strstr (name, "XXXXXX"));
    1350                 :          1 :   unlink (name);
    1351                 :          1 :   close (fd);
    1352                 :          1 :   g_free (name);
    1353                 :            : 
    1354                 :            :   /* g_mkstemp() must not work if template doesn't contain XXXXXX */
    1355                 :          1 :   strcpy (template, "foobar");
    1356                 :          1 :   g_assert_cmpint (g_mkstemp (template), ==, -1);
    1357                 :            : 
    1358                 :            :   /* g_mkstemp() must not work if template doesn't contain six X */
    1359                 :          1 :   strcpy (template, "foobarXXX");
    1360                 :          1 :   g_assert_cmpint (g_mkstemp (template), ==, -1);
    1361                 :            : 
    1362                 :          1 :   strcpy (template, "fooXXXXXX");
    1363                 :          1 :   fd = g_mkstemp (template);
    1364                 :          1 :   g_assert_cmpint (fd, !=, -1);
    1365                 :          1 :   result = write (fd, hello, hellolen);
    1366                 :          1 :   g_assert_cmpint (result, !=, -1);
    1367                 :          1 :   g_assert_cmpint (result, ==, hellolen);
    1368                 :            : 
    1369                 :          1 :   lseek (fd, 0, 0);
    1370                 :          1 :   result = read (fd, chars, sizeof (chars));
    1371                 :          1 :   g_assert_cmpint (result, !=, -1);
    1372                 :          1 :   g_assert_cmpint (result, ==, hellolen);
    1373                 :            : 
    1374                 :          1 :   chars[result] = '\0';
    1375                 :          1 :   g_assert_cmpstr (chars, ==, hello);
    1376                 :            : 
    1377                 :          1 :   close (fd);
    1378                 :          1 :   remove (template);
    1379                 :            : 
    1380                 :            :   /* Check that is does not work for "fooXXXXXX.pdf" */
    1381                 :          1 :   strcpy (template, "fooXXXXXX.pdf");
    1382                 :          1 :   fd = g_mkstemp (template);
    1383                 :          1 :   g_assert_cmpint (fd, !=, -1);
    1384                 :            : 
    1385                 :          1 :   close (fd);
    1386                 :          1 :   remove (template);
    1387                 :          1 : }
    1388                 :            : 
    1389                 :            : static void
    1390                 :          1 : test_mkdtemp (void)
    1391                 :            : {
    1392                 :            :   gint fd;
    1393                 :            :   gchar *ret;
    1394                 :            :   gchar *name;
    1395                 :            :   char template[32];
    1396                 :            : 
    1397                 :          1 :   name = g_strdup ("testXXXXXXtest"),
    1398                 :          1 :   ret = g_mkdtemp (name);
    1399                 :          1 :   g_assert (ret == name);
    1400                 :          1 :   g_assert_null (strstr (name, "XXXXXX"));
    1401                 :          1 :   g_rmdir (name);
    1402                 :          1 :   g_free (name);
    1403                 :            : 
    1404                 :          1 :   name = g_strdup ("testYYYYYYtest"),
    1405                 :          1 :   ret = g_mkdtemp (name);
    1406                 :          1 :   g_assert_null (ret);
    1407                 :          1 :   g_free (name);
    1408                 :            : 
    1409                 :          1 :   strcpy (template, "foodir");
    1410                 :          1 :   g_assert_null (g_mkdtemp (template));
    1411                 :            : 
    1412                 :          1 :   strcpy (template, "foodir");
    1413                 :          1 :   g_assert_null (g_mkdtemp (template));
    1414                 :            : 
    1415                 :          1 :   strcpy (template, "fooXXXXXX");
    1416                 :          1 :   ret = g_mkdtemp (template);
    1417                 :          1 :   g_assert_nonnull (ret);
    1418                 :          1 :   g_assert_true (ret == template);
    1419                 :          1 :   g_assert_false (g_file_test (template, G_FILE_TEST_IS_REGULAR));
    1420                 :          1 :   g_assert_true (g_file_test (template, G_FILE_TEST_IS_DIR));
    1421                 :            : 
    1422                 :          1 :   strcat (template, "/abc");
    1423                 :          1 :   fd = g_open (template, O_WRONLY | O_CREAT, 0600);
    1424                 :          1 :   g_assert_cmpint (fd, !=, -1);
    1425                 :          1 :   close (fd);
    1426                 :          1 :   g_assert_true (g_file_test (template, G_FILE_TEST_IS_REGULAR));
    1427                 :          1 :   g_assert_cmpint (g_unlink (template), !=, -1);
    1428                 :            : 
    1429                 :          1 :   template[9] = '\0';
    1430                 :          1 :   g_assert_cmpint (g_rmdir (template), !=, -1);
    1431                 :            : 
    1432                 :          1 :   strcpy (template, "fooXXXXXX.dir");
    1433                 :          1 :   g_assert_nonnull (g_mkdtemp (template));
    1434                 :          1 :   g_assert_true (g_file_test (template, G_FILE_TEST_IS_DIR));
    1435                 :          1 :   g_rmdir (template);
    1436                 :          1 : }
    1437                 :            : 
    1438                 :            : static void
    1439                 :          1 : test_get_contents (void)
    1440                 :            : {
    1441                 :            :   FILE *f;
    1442                 :            :   gsize len;
    1443                 :            :   gchar *contents;
    1444                 :          1 :   GError *error = NULL;
    1445                 :          1 :   const gchar *text = "abcdefghijklmnopqrstuvwxyz";
    1446                 :          1 :   const gchar *filename = "file-test-get-contents";
    1447                 :            :   gsize bytes_written;
    1448                 :            : 
    1449                 :          1 :   f = g_fopen (filename, "w");
    1450                 :          1 :   bytes_written = fwrite (text, 1, strlen (text), f);
    1451                 :          1 :   g_assert_cmpint (bytes_written, ==, strlen (text));
    1452                 :          1 :   fclose (f);
    1453                 :            : 
    1454         [ +  - ]:          1 :   if (g_test_undefined ())
    1455                 :            :     {
    1456                 :          1 :       g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
    1457                 :            :                              "*assertion*!= NULL*");
    1458                 :          1 :       g_assert_false (g_file_get_contents (NULL, &contents, &len, &error));
    1459                 :          1 :       g_test_assert_expected_messages ();
    1460                 :            : 
    1461                 :          1 :       g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
    1462                 :            :                              "*assertion*!= NULL*");
    1463                 :          1 :       g_assert_false (g_file_get_contents (filename, NULL, &len, &error));
    1464                 :          1 :       g_test_assert_expected_messages ();
    1465                 :            :     }
    1466                 :            : 
    1467                 :          1 :   g_assert_true (g_file_test (filename, G_FILE_TEST_IS_REGULAR));
    1468                 :            : 
    1469                 :          1 :   g_assert_true (g_file_get_contents (filename, &contents, &len, &error));
    1470                 :          1 :   g_assert_cmpstr (text, ==, contents);
    1471                 :          1 :   g_assert_no_error (error);
    1472                 :            : 
    1473                 :          1 :   g_free (contents);
    1474                 :          1 :   g_remove (filename);
    1475                 :          1 : }
    1476                 :            : 
    1477                 :            : static gboolean
    1478                 :          0 : resize_file (const gchar *filename,
    1479                 :            :              gint64       size)
    1480                 :            : {
    1481                 :            :   int fd;
    1482                 :            :   int retval;
    1483                 :            : 
    1484                 :          0 :   fd = g_open (filename, O_CREAT | O_RDWR | O_TRUNC, 0666);
    1485                 :          0 :   g_assert_cmpint (fd, >=, 0);
    1486                 :            : 
    1487                 :            : #ifdef G_OS_WIN32
    1488                 :            :   retval = _chsize_s (fd, size);
    1489                 :            : #elif HAVE_FTRUNCATE64
    1490                 :          0 :   retval = ftruncate64 (fd, size);
    1491                 :            : #else
    1492                 :            :   errno = ENOSYS;
    1493                 :            :   retval = -1;
    1494                 :            : #endif
    1495         [ #  # ]:          0 :   if (retval != 0)
    1496                 :            :     {
    1497                 :          0 :       g_test_message ("Error trying to resize file (%s)", strerror (errno));
    1498                 :          0 :       close (fd);
    1499                 :          0 :       return FALSE;
    1500                 :            :     }
    1501                 :            : 
    1502                 :          0 :   close (fd);
    1503                 :          0 :   return TRUE;
    1504                 :            : }
    1505                 :            : 
    1506                 :            : static gboolean
    1507                 :          0 : is_error_in_list (GFileError       error_code,
    1508                 :            :                   const GFileError ok_list[],
    1509                 :            :                   size_t           ok_count)
    1510                 :            : {
    1511         [ #  # ]:          0 :   for (size_t i = 0; i < ok_count; i++)
    1512                 :            :     {
    1513         [ #  # ]:          0 :       if (ok_list[i] == error_code)
    1514                 :          0 :         return TRUE;
    1515                 :            :     }
    1516                 :          0 :   return FALSE;
    1517                 :            : }
    1518                 :            : 
    1519                 :            : static void
    1520                 :          0 : get_largefile_check_len (const gchar      *filename,
    1521                 :            :                          gint64            large_len,
    1522                 :            :                          const GFileError  ok_list[],
    1523                 :            :                          size_t            ok_count)
    1524                 :            : {
    1525                 :            :   gboolean get_ok;
    1526                 :            :   gsize len;
    1527                 :            :   gchar *contents;
    1528                 :          0 :   GError *error = NULL;
    1529                 :            : 
    1530                 :          0 :   get_ok = g_file_get_contents (filename, &contents, &len, &error);
    1531         [ #  # ]:          0 :   if (get_ok)
    1532                 :            :     {
    1533                 :          0 :       g_assert_cmpint ((gint64) len, ==, large_len);
    1534                 :          0 :       g_free (contents);
    1535                 :            :     }
    1536                 :            :   else
    1537                 :            :     {
    1538                 :          0 :       g_assert_cmpint (error->domain, ==, G_FILE_ERROR);
    1539         [ #  # ]:          0 :       if (is_error_in_list ((GFileError)error->code, ok_list, ok_count))
    1540                 :            :         {
    1541                 :          0 :           g_test_message ("Error reading file of size 0x%" G_GINT64_MODIFIER "x, but with acceptable error type (%s)", large_len, error->message);
    1542                 :            :         }
    1543                 :            :       else
    1544                 :            :         {
    1545                 :            :           /* fail for other errors */
    1546                 :          0 :           g_assert_no_error (error);
    1547                 :            :         }
    1548                 :          0 :       g_clear_error (&error);
    1549                 :            :     }
    1550                 :          0 : }
    1551                 :            : 
    1552                 :            : static void
    1553                 :          1 : test_get_contents_largefile (void)
    1554                 :            : {
    1555         [ +  - ]:          1 :   if (!g_test_slow ())
    1556                 :            :     {
    1557                 :          1 :       g_test_skip ("Skipping slow largefile test");
    1558                 :          1 :       return;
    1559                 :            :     }
    1560                 :            : 
    1561                 :          0 :   const gchar *filename = "file-test-get-contents-large";
    1562                 :            :   gint64 large_len;
    1563                 :            : 
    1564                 :            :   /* error OK if couldn't allocate large buffer, or if file is too large */
    1565                 :          0 :   const GFileError too_large_errors[] = { G_FILE_ERROR_NOMEM, G_FILE_ERROR_FAILED };
    1566                 :            :   /* error OK if couldn't allocate large buffer */
    1567                 :          0 :   const GFileError nomem_errors[] = { G_FILE_ERROR_NOMEM };
    1568                 :            : 
    1569                 :            :   /* OK to fail to read this, but don't silently under-read */
    1570                 :          0 :   large_len = (G_GINT64_CONSTANT (1) << 32) + 16;
    1571         [ #  # ]:          0 :   if (!resize_file (filename, large_len))
    1572                 :          0 :     goto failed_resize;
    1573                 :          0 :   get_largefile_check_len (filename, large_len, too_large_errors, G_N_ELEMENTS (too_large_errors));
    1574                 :            : 
    1575                 :            :   /* OK to fail to read this size, but don't silently under-read */
    1576                 :          0 :   large_len = (G_GINT64_CONSTANT (1) << 32) - 1;
    1577         [ #  # ]:          0 :   if (!resize_file (filename, large_len))
    1578                 :          0 :     goto failed_resize;
    1579                 :          0 :   get_largefile_check_len (filename, large_len, too_large_errors, G_N_ELEMENTS (too_large_errors));
    1580                 :            : 
    1581                 :            :   /* OK to fail memory allocation, but don't otherwise fail this size */
    1582                 :          0 :   large_len = (G_GINT64_CONSTANT (1) << 31) - 1;
    1583         [ #  # ]:          0 :   if (!resize_file (filename, large_len))
    1584                 :          0 :     goto failed_resize;
    1585                 :          0 :   get_largefile_check_len (filename, large_len, nomem_errors, G_N_ELEMENTS (nomem_errors));
    1586                 :            : 
    1587                 :          0 :   g_remove (filename);
    1588                 :          0 :   return;
    1589                 :            : 
    1590                 :          0 : failed_resize:
    1591                 :          0 :   g_test_incomplete ("Failed to resize large file, unable to complete large file tests.");
    1592                 :          0 :   g_remove (filename);
    1593                 :            : }
    1594                 :            : 
    1595                 :            : static void
    1596                 :          1 : test_file_test (void)
    1597                 :            : {
    1598                 :          1 :   GError *error = NULL;
    1599                 :            :   gboolean result;
    1600                 :            :   gchar *name;
    1601                 :            :   gint fd;
    1602                 :            : 
    1603         [ +  - ]:          1 :   if (g_test_undefined ())
    1604                 :            :     {
    1605                 :          1 :       g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
    1606                 :            :                              "*assertion*!= NULL*");
    1607                 :          1 :       result = g_file_test (NULL, G_FILE_TEST_EXISTS);
    1608                 :          1 :       g_assert_false (result);
    1609                 :          1 :       g_test_assert_expected_messages ();
    1610                 :            :     }
    1611                 :            : 
    1612                 :          1 :   fd = g_file_open_tmp (NULL, &name, &error);
    1613                 :          1 :   g_assert_no_error (error);
    1614                 :          1 :   g_assert_cmpint (write (fd, "a", 1), ==, 1);
    1615                 :          1 :   g_assert_cmpint (g_fsync (fd), ==, 0);
    1616                 :          1 :   close (fd);
    1617                 :            : 
    1618                 :            : #ifndef G_OS_WIN32
    1619                 :          1 :   result = g_file_test (name, G_FILE_TEST_IS_SYMLINK);
    1620                 :          1 :   g_assert_false (result);
    1621                 :            : 
    1622                 :          1 :   g_assert_no_errno (symlink (name, "symlink"));
    1623                 :          1 :   result = g_file_test ("symlink", G_FILE_TEST_IS_SYMLINK);
    1624                 :          1 :   g_assert_true (result);
    1625                 :          1 :   unlink ("symlink");
    1626                 :            : #endif
    1627                 :            : 
    1628                 :            :   /* Cleaning */
    1629                 :          1 :   g_remove (name);
    1630                 :          1 :   g_free (name);
    1631                 :          1 : }
    1632                 :            : 
    1633                 :            : static void
    1634                 :          1 : test_set_contents (void)
    1635                 :            : {
    1636                 :          1 :   GError *error = NULL;
    1637                 :            :   gint fd;
    1638                 :            :   gchar *name;
    1639                 :            :   gchar *buf;
    1640                 :            :   gsize len;
    1641                 :            :   gboolean ret;
    1642                 :            : 
    1643                 :          1 :   fd = g_file_open_tmp (NULL, &name, &error);
    1644                 :          1 :   g_assert_no_error (error);
    1645                 :          1 :   g_assert_cmpint (write (fd, "a", 1), ==, 1);
    1646                 :          1 :   g_assert_cmpint (g_fsync (fd), ==, 0);
    1647                 :          1 :   close (fd);
    1648                 :            : 
    1649                 :          1 :   ret = g_file_get_contents (name, &buf, &len, &error);
    1650                 :          1 :   g_assert_true (ret);
    1651                 :          1 :   g_assert_no_error (error);
    1652                 :          1 :   g_assert_cmpstr (buf, ==, "a");
    1653                 :          1 :   g_free (buf);
    1654                 :            : 
    1655                 :          1 :   ret = g_file_set_contents (name, "b", 1, &error);
    1656                 :          1 :   g_assert_true (ret);
    1657                 :          1 :   g_assert_no_error (error);
    1658                 :            : 
    1659                 :          1 :   ret = g_file_get_contents (name, &buf, &len, &error);
    1660                 :          1 :   g_assert_true (ret);
    1661                 :          1 :   g_assert_no_error (error);
    1662                 :          1 :   g_assert_cmpstr (buf, ==, "b");
    1663                 :          1 :   g_free (buf);
    1664                 :            : 
    1665                 :          1 :   g_remove (name);
    1666                 :          1 :   g_free (name);
    1667                 :          1 : }
    1668                 :            : 
    1669                 :            : static void
    1670                 :          1 : test_set_contents_full (void)
    1671                 :            : {
    1672                 :          1 :   GFileSetContentsFlags flags_mask =
    1673                 :            :       G_FILE_SET_CONTENTS_ONLY_EXISTING |
    1674                 :            :       G_FILE_SET_CONTENTS_DURABLE |
    1675                 :            :       G_FILE_SET_CONTENTS_CONSISTENT;
    1676                 :            :   gint flags;
    1677                 :            :   const struct
    1678                 :            :     {
    1679                 :            :       enum
    1680                 :            :         {
    1681                 :            :           EXISTING_FILE_NONE,
    1682                 :            :           EXISTING_FILE_REGULAR,
    1683                 :            : #ifndef G_OS_WIN32
    1684                 :            :           EXISTING_FILE_SYMLINK,
    1685                 :            : #endif
    1686                 :            :           EXISTING_FILE_DIRECTORY,
    1687                 :            :         }
    1688                 :            :       existing_file;
    1689                 :            :       int new_mode;  /* only relevant if @existing_file is %EXISTING_FILE_NONE */
    1690                 :            :       gboolean use_strlen;
    1691                 :            : 
    1692                 :            :       gboolean expected_success;
    1693                 :            :       gint expected_error;
    1694                 :            :     }
    1695                 :          1 :   tests[] =
    1696                 :            :     {
    1697                 :            :       { EXISTING_FILE_NONE, 0644, FALSE, TRUE, 0 },
    1698                 :            :       { EXISTING_FILE_NONE, 0644, TRUE, TRUE, 0 },
    1699                 :            :       { EXISTING_FILE_NONE, 0600, FALSE, TRUE, 0 },
    1700                 :            :       { EXISTING_FILE_REGULAR, 0644, FALSE, TRUE, 0 },
    1701                 :            : #ifndef G_OS_WIN32
    1702                 :            :       { EXISTING_FILE_SYMLINK, 0644, FALSE, TRUE, 0 },
    1703                 :            :       { EXISTING_FILE_DIRECTORY, 0644, FALSE, FALSE, G_FILE_ERROR_ISDIR },
    1704                 :            : #else
    1705                 :            :       /* on win32, _wopen returns EACCES if path is a directory */
    1706                 :            :       { EXISTING_FILE_DIRECTORY, 0644, FALSE, FALSE, G_FILE_ERROR_ACCES },
    1707                 :            : #endif
    1708                 :            :     };
    1709                 :            :   gsize i;
    1710                 :            : 
    1711                 :          1 :   g_test_summary ("Test g_file_set_contents_full() with various flags");
    1712                 :            : 
    1713         [ +  + ]:          8 :   for (flags = 0; flags < (gint) flags_mask; flags++)
    1714                 :            :     {
    1715         [ +  + ]:         49 :       for (i = 0; i < G_N_ELEMENTS (tests); i++)
    1716                 :            :         {
    1717                 :         42 :           GError *error = NULL;
    1718                 :         42 :           gchar *file_name = NULL, *link_name = NULL, *dir_name = NULL;
    1719                 :            :           const gchar *set_contents_name;
    1720                 :         42 :           gchar *buf = NULL;
    1721                 :            :           gsize len;
    1722                 :            :           gboolean ret;
    1723                 :            :           GStatBuf statbuf;
    1724                 :         42 :           const gchar *original_contents = "a string which is longer than what will be overwritten on it";
    1725                 :         42 :           size_t original_contents_len = strlen (original_contents);
    1726                 :            : 
    1727                 :         42 :           g_test_message ("Flags %d and test %" G_GSIZE_FORMAT, flags, i);
    1728                 :            : 
    1729   [ +  +  +  - ]:         42 :           switch (tests[i].existing_file)
    1730                 :            :             {
    1731                 :         14 :             case EXISTING_FILE_REGULAR:
    1732                 :            : #ifndef G_OS_WIN32
    1733                 :            :             case EXISTING_FILE_SYMLINK:
    1734                 :            : #endif
    1735                 :            :               {
    1736                 :            :                 gint fd;
    1737                 :            : 
    1738                 :         14 :                 fd = g_file_open_tmp (NULL, &file_name, &error);
    1739                 :         14 :                 g_assert_no_error (error);
    1740                 :         14 :                 g_assert_cmpint (write (fd, original_contents, original_contents_len), ==, original_contents_len);
    1741                 :         14 :                 g_assert_no_errno (g_fsync (fd));
    1742                 :         14 :                 close (fd);
    1743                 :            : 
    1744                 :            : #ifndef G_OS_WIN32
    1745                 :            :                 /* Pass an existing symlink to g_file_set_contents_full() to see
    1746                 :            :                  * what it does. */
    1747         [ +  + ]:         14 :                 if (tests[i].existing_file == EXISTING_FILE_SYMLINK)
    1748                 :            :                   {
    1749                 :          7 :                     link_name = g_strconcat (file_name, ".link", NULL);
    1750                 :          7 :                     g_assert_no_errno (symlink (file_name, link_name));
    1751                 :            : 
    1752                 :          7 :                     set_contents_name = link_name;
    1753                 :            :                   }
    1754                 :            :                 else
    1755                 :            : #endif  /* !G_OS_WIN32 */
    1756                 :            :                   {
    1757                 :          7 :                     set_contents_name = file_name;
    1758                 :            :                   }
    1759                 :         14 :                 break;
    1760                 :            :               }
    1761                 :          7 :             case EXISTING_FILE_DIRECTORY:
    1762                 :            :               {
    1763                 :          7 :                 dir_name = g_dir_make_tmp ("glib-fileutils-set-contents-full-XXXXXX", &error);
    1764                 :          7 :                 g_assert_no_error (error);
    1765                 :            : 
    1766                 :          7 :                 set_contents_name = dir_name;
    1767                 :          7 :                 break;
    1768                 :            :               }
    1769                 :         21 :             case EXISTING_FILE_NONE:
    1770                 :            :               {
    1771                 :         21 :                 file_name = g_build_filename (g_get_tmp_dir (), "glib-file-set-contents-full-test", NULL);
    1772                 :         21 :                 g_remove (file_name);
    1773                 :         21 :                 g_assert_false (g_file_test (file_name, G_FILE_TEST_EXISTS));
    1774                 :            : 
    1775                 :         21 :                 set_contents_name = file_name;
    1776                 :         21 :                 break;
    1777                 :            :               }
    1778                 :          0 :             default:
    1779                 :            :               {
    1780                 :            :                 g_assert_not_reached ();
    1781                 :            :               }
    1782                 :            :             }
    1783                 :            : 
    1784                 :            :           /* Set the file contents */
    1785                 :         42 :           ret = g_file_set_contents_full (set_contents_name, "b",
    1786                 :         42 :                                           tests[i].use_strlen ? -1 : 1,
    1787         [ +  + ]:         42 :                                           flags, tests[i].new_mode, &error);
    1788                 :            : 
    1789         [ +  + ]:         42 :           if (!tests[i].expected_success)
    1790                 :            :             {
    1791                 :          7 :               g_assert_error (error, G_FILE_ERROR, tests[i].expected_error);
    1792                 :          7 :               g_assert_false (ret);
    1793                 :          7 :               g_clear_error (&error);
    1794                 :            :             }
    1795                 :            :           else
    1796                 :            :             {
    1797                 :         35 :               g_assert_no_error (error);
    1798                 :         35 :               g_assert_true (ret);
    1799                 :            : 
    1800                 :            :               /* Check the contents and mode were set correctly. The mode isn’t
    1801                 :            :                * changed on existing files. */
    1802                 :         35 :               ret = g_file_get_contents (set_contents_name, &buf, &len, &error);
    1803                 :         35 :               g_assert_no_error (error);
    1804                 :         35 :               g_assert_true (ret);
    1805                 :         35 :               g_assert_cmpstr (buf, ==, "b");
    1806                 :         35 :               g_assert_cmpuint (len, ==, 1);
    1807                 :         35 :               g_free (buf);
    1808                 :            : 
    1809                 :         35 :               g_assert_no_errno (g_lstat (set_contents_name, &statbuf));
    1810                 :            : 
    1811         [ +  + ]:         35 :               if (tests[i].existing_file == EXISTING_FILE_NONE)
    1812                 :            :                 {
    1813                 :         21 :                   int mode = statbuf.st_mode & ~S_IFMT;
    1814                 :         21 :                   int new_mode = tests[i].new_mode;
    1815                 :            : #ifdef G_OS_WIN32
    1816                 :            :                   /* on windows, group and others perms handling is different */
    1817                 :            :                   /* only check the rwx user permissions */
    1818                 :            :                   mode &= (_S_IREAD|_S_IWRITE|_S_IEXEC);
    1819                 :            :                   new_mode &= (_S_IREAD|_S_IWRITE|_S_IEXEC);
    1820                 :            : #endif
    1821                 :         21 :                   g_assert_cmpint (mode, ==, new_mode);
    1822                 :            :                 }
    1823                 :            : 
    1824                 :            : #ifndef G_OS_WIN32
    1825         [ +  + ]:         35 :               if (tests[i].existing_file == EXISTING_FILE_SYMLINK)
    1826                 :            :                 {
    1827                 :          7 :                   gchar *target_contents = NULL;
    1828                 :            : 
    1829                 :            :                   /* If the @set_contents_name was a symlink, it should now be a
    1830                 :            :                    * regular file, and the file it pointed to should not have
    1831                 :            :                    * changed. */
    1832                 :          7 :                   g_assert_cmpint (statbuf.st_mode & S_IFMT, ==, S_IFREG);
    1833                 :            : 
    1834                 :          7 :                   g_file_get_contents (file_name, &target_contents, NULL, &error);
    1835                 :          7 :                   g_assert_no_error (error);
    1836                 :          7 :                   g_assert_cmpstr (target_contents, ==, original_contents);
    1837                 :            : 
    1838                 :          7 :                   g_free (target_contents);
    1839                 :            :                 }
    1840                 :            : #endif  /* !G_OS_WIN32 */
    1841                 :            :             }
    1842                 :            : 
    1843         [ +  + ]:         42 :           if (dir_name != NULL)
    1844                 :          7 :             g_rmdir (dir_name);
    1845         [ +  + ]:         42 :           if (link_name != NULL)
    1846                 :          7 :             g_remove (link_name);
    1847         [ +  + ]:         42 :           if (file_name != NULL)
    1848                 :         35 :             g_remove (file_name);
    1849                 :            : 
    1850                 :         42 :           g_free (dir_name);
    1851                 :         42 :           g_free (link_name);
    1852                 :         42 :           g_free (file_name);
    1853                 :            :         }
    1854                 :            :     }
    1855                 :          1 : }
    1856                 :            : 
    1857                 :            : static void
    1858                 :          1 : test_set_contents_full_read_only_file (void)
    1859                 :            : {
    1860                 :            :   gint fd;
    1861                 :          1 :   GError *error = NULL;
    1862                 :          1 :   gchar *file_name = NULL;
    1863                 :            :   gboolean ret;
    1864                 :          1 :   gboolean can_override_dac = check_cap_dac_override (NULL);
    1865                 :            : 
    1866                 :          1 :   g_test_summary ("Test g_file_set_contents_full() on a read-only file");
    1867                 :            : 
    1868                 :            :   /* Can’t test this with different #GFileSetContentsFlags as they all have
    1869                 :            :    * different behaviours wrt replacing the file while noticing/ignoring the
    1870                 :            :    * existing file permissions. */
    1871                 :          1 :   fd = g_file_open_tmp (NULL, &file_name, &error);
    1872                 :          1 :   g_assert_no_error (error);
    1873                 :          1 :   g_assert_cmpint (write (fd, "a", 1), ==, 1);
    1874                 :          1 :   g_assert_no_errno (g_fsync (fd));
    1875                 :          1 :   close (fd);
    1876                 :          1 :   g_assert_no_errno (g_chmod (file_name, 0400)); /* S_IREAD */
    1877                 :            : 
    1878         [ +  - ]:          1 :   if (g_test_undefined ())
    1879                 :            :     {
    1880                 :          1 :       g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
    1881                 :            :                              "*assertion*!= NULL*");
    1882                 :          1 :       ret = g_file_set_contents_full (NULL, "b", 1,
    1883                 :            :                                       G_FILE_SET_CONTENTS_NONE, 0644, &error);
    1884                 :          1 :       g_assert_false (ret);
    1885                 :          1 :       g_test_assert_expected_messages ();
    1886                 :            : 
    1887                 :          1 :       g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
    1888                 :            :                              "*assertion*!= NULL*");
    1889                 :          1 :       ret = g_file_set_contents_full (file_name, NULL, 1,
    1890                 :            :                                       G_FILE_SET_CONTENTS_NONE, 0644, &error);
    1891                 :          1 :       g_assert_false (ret);
    1892                 :          1 :       g_test_assert_expected_messages ();
    1893                 :            :     }
    1894                 :            : 
    1895                 :            :   /* Set the file contents */
    1896                 :          1 :   ret = g_file_set_contents_full (file_name, "b", 1, G_FILE_SET_CONTENTS_NONE, 0644, &error);
    1897                 :            : 
    1898         [ -  + ]:          1 :   if (can_override_dac)
    1899                 :            :     {
    1900                 :          0 :       g_assert_no_error (error);
    1901                 :          0 :       g_assert_true (ret);
    1902                 :            :     }
    1903                 :            :   else
    1904                 :            :     {
    1905                 :          1 :       g_assert_error (error, G_FILE_ERROR, G_FILE_ERROR_ACCES);
    1906                 :          1 :       g_assert_false (ret);
    1907                 :            :     }
    1908                 :            : 
    1909                 :          1 :   g_clear_error (&error);
    1910                 :            : 
    1911                 :          1 :   g_remove (file_name);
    1912                 :            : 
    1913                 :          1 :   g_free (file_name);
    1914                 :          1 : }
    1915                 :            : 
    1916                 :            : static void
    1917                 :          1 : test_set_contents_full_read_only_directory (void)
    1918                 :            : {
    1919                 :            : #ifndef G_OS_WIN32
    1920                 :            : /* windows mostly ignores read-only flagged directories, chmod doesn't work */
    1921                 :          1 :   GFileSetContentsFlags flags_mask =
    1922                 :            :       G_FILE_SET_CONTENTS_ONLY_EXISTING |
    1923                 :            :       G_FILE_SET_CONTENTS_DURABLE |
    1924                 :            :       G_FILE_SET_CONTENTS_CONSISTENT;
    1925                 :            :   gint flags;
    1926                 :            : 
    1927                 :          1 :   g_test_summary ("Test g_file_set_contents_full() on a file in a read-only directory");
    1928                 :            : 
    1929         [ +  + ]:          8 :   for (flags = 0; flags < (gint) flags_mask; flags++)
    1930                 :            :     {
    1931                 :            :       gint fd;
    1932                 :          7 :       GError *error = NULL;
    1933                 :          7 :       gchar *dir_name = NULL;
    1934                 :          7 :       gchar *file_name = NULL;
    1935                 :            :       gboolean ret;
    1936                 :            :       gboolean can_override_dac;
    1937                 :            : 
    1938                 :          7 :       g_test_message ("Flags %d", flags);
    1939                 :            : 
    1940                 :          7 :       dir_name = g_dir_make_tmp ("glib-file-set-contents-full-rodir-XXXXXX", &error);
    1941                 :          7 :       g_assert_no_error (error);
    1942                 :          7 :       can_override_dac = check_cap_dac_override (dir_name);
    1943                 :            : 
    1944                 :          7 :       file_name = g_build_filename (dir_name, "file", NULL);
    1945                 :          7 :       fd = g_open (file_name, O_CREAT | O_RDWR, 0644);
    1946                 :          7 :       g_assert_cmpint (fd, >=, 0);
    1947                 :          7 :       g_assert_cmpint (write (fd, "a", 1), ==, 1);
    1948                 :          7 :       g_assert_no_errno (g_fsync (fd));
    1949                 :          7 :       close (fd);
    1950                 :            : 
    1951                 :          7 :       g_assert_no_errno (g_chmod (dir_name, 0));
    1952                 :            : 
    1953                 :            :       /* Set the file contents */
    1954                 :          7 :       ret = g_file_set_contents_full (file_name, "b", 1, flags, 0644, &error);
    1955                 :            : 
    1956         [ -  + ]:          7 :       if (can_override_dac)
    1957                 :            :         {
    1958                 :          0 :           g_assert_no_error (error);
    1959                 :          0 :           g_assert_true (ret);
    1960                 :            :         }
    1961                 :            :       else
    1962                 :            :         {
    1963                 :          7 :           g_assert_error (error, G_FILE_ERROR, G_FILE_ERROR_ACCES);
    1964                 :          7 :           g_assert_false (ret);
    1965                 :            :         }
    1966                 :            : 
    1967                 :          7 :       g_clear_error (&error);
    1968                 :          7 :       g_remove (file_name);
    1969                 :          7 :       g_unlink (dir_name);
    1970                 :            : 
    1971                 :          7 :       g_free (file_name);
    1972                 :          7 :       g_free (dir_name);
    1973                 :            :     }
    1974                 :            : #else
    1975                 :            :   g_test_skip ("Windows doesn’t support read-only directories in the same way as Unix");
    1976                 :            : #endif
    1977                 :          1 : }
    1978                 :            : 
    1979                 :            : static void
    1980                 :          1 : test_read_link (void)
    1981                 :            : {
    1982                 :            : #ifdef HAVE_READLINK
    1983                 :            : #ifdef G_OS_UNIX
    1984                 :            :   int ret;
    1985                 :            :   FILE *file;
    1986                 :            :   gchar *cwd;
    1987                 :            :   gchar *data;
    1988                 :            :   gchar *newpath;
    1989                 :            :   gchar *badpath;
    1990                 :            :   gchar *path;
    1991                 :          1 :   GError *error = NULL;
    1992                 :            :   const gchar *oldpath;
    1993                 :          1 :   const gchar *filename = "file-test-data";
    1994                 :          1 :   const gchar *link1 = "file-test-link1";
    1995                 :          1 :   const gchar *link2 = "file-test-link2";
    1996                 :          1 :   const gchar *link3 = "file-test-link3";
    1997                 :            : 
    1998         [ +  - ]:          1 :   if (g_test_undefined ())
    1999                 :            :     {
    2000                 :          1 :       g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
    2001                 :            :                              "*assertion*!= NULL*");
    2002                 :          1 :       newpath = g_file_read_link (NULL, &error);
    2003                 :          1 :       g_assert_null (newpath);
    2004                 :          1 :       g_test_assert_expected_messages ();
    2005                 :            :     }
    2006                 :            : 
    2007                 :          1 :   cwd = g_get_current_dir ();
    2008                 :            : 
    2009                 :          1 :   oldpath = g_test_get_filename (G_TEST_DIST, "4096-random-bytes", NULL);
    2010                 :          1 :   newpath = g_build_filename (cwd, "page-of-junk", NULL);
    2011                 :          1 :   badpath = g_build_filename (cwd, "4097-random-bytes", NULL);
    2012                 :          1 :   remove (newpath);
    2013                 :          1 :   ret = symlink (oldpath, newpath);
    2014                 :          1 :   g_assert_cmpint (ret, ==, 0);
    2015                 :          1 :   path = g_file_read_link (newpath, &error);
    2016                 :          1 :   g_assert_no_error (error);
    2017                 :          1 :   g_assert_cmpstr (path, ==, oldpath);
    2018                 :          1 :   g_free (path);
    2019                 :            : 
    2020                 :          1 :   remove (newpath);
    2021                 :          1 :   ret = symlink (badpath, newpath);
    2022                 :          1 :   g_assert_cmpint (ret, ==, 0);
    2023                 :          1 :   path = g_file_read_link (newpath, &error);
    2024                 :          1 :   g_assert_no_error (error);
    2025                 :          1 :   g_assert_cmpstr (path, ==, badpath);
    2026                 :          1 :   g_free (path);
    2027                 :            : 
    2028                 :          1 :   path = g_file_read_link (oldpath, &error);
    2029                 :          1 :   g_assert_error (error, G_FILE_ERROR, G_FILE_ERROR_INVAL);
    2030                 :          1 :   g_assert_null (path);
    2031                 :          1 :   g_error_free (error);
    2032                 :            : 
    2033                 :          1 :   remove (newpath);
    2034                 :          1 :   g_free (cwd);
    2035                 :          1 :   g_free (newpath);
    2036                 :          1 :   g_free (badpath);
    2037                 :            : 
    2038                 :          1 :   file = fopen (filename, "w");
    2039                 :          1 :   g_assert_nonnull (file);
    2040                 :          1 :   fclose (file);
    2041                 :            : 
    2042                 :          1 :   g_assert_no_errno (symlink (filename, link1));
    2043                 :          1 :   g_assert_no_errno (symlink (link1, link2));
    2044                 :            : 
    2045                 :          1 :   error = NULL;
    2046                 :          1 :   data = g_file_read_link (link1, &error);
    2047                 :          1 :   g_assert_nonnull (data);
    2048                 :          1 :   g_assert_cmpstr (data, ==, filename);
    2049                 :          1 :   g_assert_no_error (error);
    2050                 :          1 :   g_free (data);
    2051                 :            : 
    2052                 :          1 :   error = NULL;
    2053                 :          1 :   data = g_file_read_link (link2, &error);
    2054                 :          1 :   g_assert_nonnull (data);
    2055                 :          1 :   g_assert_cmpstr (data, ==, link1);
    2056                 :          1 :   g_assert_no_error (error);
    2057                 :          1 :   g_free (data);
    2058                 :            : 
    2059                 :          1 :   error = NULL;
    2060                 :          1 :   data = g_file_read_link (link3, &error);
    2061                 :          1 :   g_assert_null (data);
    2062                 :          1 :   g_assert_error (error, G_FILE_ERROR, G_FILE_ERROR_NOENT);
    2063                 :          1 :   g_error_free (error);
    2064                 :            : 
    2065                 :          1 :   error = NULL;
    2066                 :          1 :   data = g_file_read_link (filename, &error);
    2067                 :          1 :   g_assert_null (data);
    2068                 :          1 :   g_assert_error (error, G_FILE_ERROR, G_FILE_ERROR_INVAL);
    2069                 :          1 :   g_error_free (error);
    2070                 :            : 
    2071                 :          1 :   remove (filename);
    2072                 :          1 :   remove (link1);
    2073                 :          1 :   remove (link2);
    2074                 :            : #endif
    2075                 :            : #else
    2076                 :            :   g_test_skip ("Symbolic links not supported");
    2077                 :            : #endif
    2078                 :          1 : }
    2079                 :            : 
    2080                 :            : static void
    2081                 :          1 : test_stdio_wrappers (void)
    2082                 :            : {
    2083                 :            :   GStatBuf buf;
    2084                 :            :   gchar *cwd, *path;
    2085                 :            :   gint ret;
    2086                 :            :   struct utimbuf ut;
    2087                 :          1 :   GError *error = NULL;
    2088                 :            :   GStatBuf path_statbuf, cwd_statbuf;
    2089                 :            :   time_t now;
    2090                 :            : #ifdef G_OS_UNIX
    2091                 :            :   gboolean have_cap_dac_override;
    2092                 :            : #endif
    2093                 :            : 
    2094                 :          1 :   g_remove ("mkdir-test/test-create");
    2095                 :          1 :   ret = g_rmdir ("mkdir-test");
    2096                 :          1 :   g_assert (ret == 0 || errno == ENOENT);
    2097                 :            : 
    2098                 :          1 :   ret = g_stat ("mkdir-test", &buf);
    2099                 :          1 :   g_assert_cmpint (ret, ==, -1);
    2100                 :          1 :   ret = g_mkdir ("mkdir-test", 0666);
    2101                 :          1 :   g_assert_cmpint (ret, ==, 0);
    2102                 :          1 :   ret = g_stat ("mkdir-test", &buf);
    2103                 :          1 :   g_assert_cmpint (ret, ==, 0);
    2104                 :          1 :   g_assert_cmpint (S_ISDIR (buf.st_mode), !=, 0);
    2105                 :            : 
    2106                 :          1 :   cwd = g_get_current_dir ();
    2107                 :          1 :   path = g_build_filename (cwd, "mkdir-test", NULL);
    2108                 :            : #ifdef G_OS_UNIX
    2109                 :          1 :   have_cap_dac_override = check_cap_dac_override (cwd);
    2110                 :            : #endif
    2111                 :          1 :   g_free (cwd);
    2112                 :            : 
    2113                 :            :   /* 0666 on directories means nothing to Windows, it only obeys ACLs.
    2114                 :            :    * It doesn't necessarily mean anything on Unix either: if we have
    2115                 :            :    * Linux CAP_DAC_OVERRIDE or equivalent (in particular if we're root),
    2116                 :            :    * then we ignore filesystem permissions. */
    2117                 :            : #ifdef G_OS_UNIX
    2118         [ -  + ]:          1 :   if (have_cap_dac_override)
    2119                 :            :     {
    2120                 :          0 :       g_test_message ("Cannot test g_chdir() failing with EACCES: we "
    2121                 :            :                       "probably have CAP_DAC_OVERRIDE or equivalent");
    2122                 :            :     }
    2123                 :            :   else
    2124                 :            :     {
    2125                 :          1 :       ret = g_chdir (path);
    2126                 :          1 :       g_assert_cmpint (ret == 0 ? 0 : errno, ==, EACCES);
    2127                 :          1 :       g_assert_cmpint (ret, ==, -1);
    2128                 :            :     }
    2129                 :            : #else
    2130                 :            :   g_test_message ("Cannot test g_chdir() failing with EACCES: "
    2131                 :            :                   "it's Unix-specific behaviour");
    2132                 :            : #endif
    2133                 :            : 
    2134                 :          1 :   ret = g_chmod (path, 0777);
    2135                 :          1 :   g_assert_cmpint (ret, ==, 0);
    2136                 :          1 :   ret = g_chdir (path);
    2137                 :          1 :   g_assert_cmpint (ret, ==, 0);
    2138                 :          1 :   cwd = g_get_current_dir ();
    2139                 :            :   /* We essentially want to check that cwd == path, but we can’t compare the
    2140                 :            :    * paths directly since the tests might be running under a symlink (for
    2141                 :            :    * example, /tmp is sometimes a symlink). Compare the inode numbers instead. */
    2142                 :          1 :   g_assert_cmpint (g_stat (cwd, &cwd_statbuf), ==, 0);
    2143                 :          1 :   g_assert_cmpint (g_stat (path, &path_statbuf), ==, 0);
    2144                 :          1 :   g_assert_true (cwd_statbuf.st_dev == path_statbuf.st_dev &&
    2145                 :            :                  cwd_statbuf.st_ino == path_statbuf.st_ino);
    2146                 :          1 :   g_free (cwd);
    2147                 :          1 :   g_free (path);
    2148                 :            : 
    2149                 :          1 :   ret = g_creat ("test-creat", G_TEST_DIR_MODE);
    2150                 :          1 :   g_close (ret, &error);
    2151                 :          1 :   g_assert_no_error (error);
    2152                 :            : 
    2153                 :          1 :   ret = g_access ("test-creat", F_OK);
    2154                 :          1 :   g_assert_cmpint (ret, ==, 0);
    2155                 :            : 
    2156                 :          1 :   ret = g_rename ("test-creat", "test-create");
    2157                 :          1 :   g_assert_cmpint (ret, ==, 0);
    2158                 :            : 
    2159                 :          1 :   ret = g_open ("test-create", O_RDONLY, 0666);
    2160                 :          1 :   g_close (ret, &error);
    2161                 :          1 :   g_assert_no_error (error);
    2162                 :            : 
    2163                 :            : #ifdef G_OS_WIN32
    2164                 :            :   /* On Windows the 5 permission bit results in a read-only file
    2165                 :            :    * that cannot be modified in any way (attribute changes included).
    2166                 :            :    * Remove the read-only attribute via chmod().
    2167                 :            :    */
    2168                 :            :   ret = g_chmod ("test-create", 0666);
    2169                 :            :   g_assert_cmpint (ret, ==, 0);
    2170                 :            : #endif
    2171                 :            : 
    2172                 :          1 :   now = time (NULL);
    2173                 :            : 
    2174                 :          1 :   ut.actime = ut.modtime = now;
    2175                 :          1 :   ret = g_utime ("test-create", &ut);
    2176                 :          1 :   g_assert_cmpint (ret, ==, 0);
    2177                 :            : 
    2178                 :          1 :   ret = g_lstat ("test-create", &buf);
    2179                 :          1 :   g_assert_cmpint (ret, ==, 0);
    2180                 :          1 :   g_assert_cmpint (buf.st_atime, ==, now);
    2181                 :          1 :   g_assert_cmpint (buf.st_mtime, ==, now);
    2182                 :            : 
    2183                 :          1 :   g_chdir ("..");
    2184                 :          1 :   g_remove ("mkdir-test/test-create");
    2185                 :          1 :   g_rmdir ("mkdir-test");
    2186                 :          1 : }
    2187                 :            : 
    2188                 :            : /* Win32 does not support "wb+", but g_fopen() should automatically
    2189                 :            :  * translate this mode to its alias "w+b".
    2190                 :            :  * Also check various other file open modes for correct support across
    2191                 :            :  * platforms.
    2192                 :            :  * See: https://gitlab.gnome.org/GNOME/glib/merge_requests/119
    2193                 :            :  */
    2194                 :            : static void
    2195                 :          1 : test_fopen_modes (void)
    2196                 :            : {
    2197                 :          1 :   char        *path = g_build_filename ("temp-fopen", NULL);
    2198                 :            :   gsize        i;
    2199                 :          1 :   const gchar *modes[] =
    2200                 :            :     {
    2201                 :            :       "w",
    2202                 :            :       "r",
    2203                 :            :       "a",
    2204                 :            :       "w+",
    2205                 :            :       "r+",
    2206                 :            :       "a+",
    2207                 :            :       "wb",
    2208                 :            :       "rb",
    2209                 :            :       "ab",
    2210                 :            :       "w+b",
    2211                 :            :       "r+b",
    2212                 :            :       "a+b",
    2213                 :            :       "wb+",
    2214                 :            :       "rb+",
    2215                 :            :       "ab+"
    2216                 :            :     };
    2217                 :            : 
    2218                 :          1 :   g_test_bug ("https://gitlab.gnome.org/GNOME/glib/merge_requests/119");
    2219                 :            : 
    2220         [ -  + ]:          1 :   if (g_file_test (path, G_FILE_TEST_EXISTS))
    2221                 :          0 :     g_error ("failed, %s exists, cannot test g_fopen()", path);
    2222                 :            : 
    2223         [ +  + ]:         16 :   for (i = 0; i < G_N_ELEMENTS (modes); i++)
    2224                 :            :     {
    2225                 :            :       FILE *f;
    2226                 :            : 
    2227                 :         15 :       g_test_message ("Testing fopen() mode '%s'", modes[i]);
    2228                 :            : 
    2229                 :         15 :       f = g_fopen (path, modes[i]);
    2230                 :         15 :       g_assert_nonnull (f);
    2231                 :         15 :       fclose (f);
    2232                 :            :     }
    2233                 :            : 
    2234                 :          1 :   g_remove (path);
    2235                 :          1 :   g_free (path);
    2236                 :          1 : }
    2237                 :            : 
    2238                 :            : #ifdef G_OS_WIN32
    2239                 :            : #include "../gstdio-private.c"
    2240                 :            : 
    2241                 :            : static int
    2242                 :            : g_wcscmp0 (const gunichar2 *str1,
    2243                 :            :            const gunichar2 *str2)
    2244                 :            : {
    2245                 :            :   if (!str1)
    2246                 :            :     return -(str1 != str2);
    2247                 :            :   if (!str2)
    2248                 :            :     return str1 != str2;
    2249                 :            :   return wcscmp (str1, str2);
    2250                 :            : }
    2251                 :            : 
    2252                 :            : #define g_assert_cmpwcs(s1, cmp, s2, s1u8, s2u8) \
    2253                 :            : G_STMT_START { \
    2254                 :            :   const gunichar2 *__s1 = (s1), *__s2 = (s2); \
    2255                 :            :   if (g_wcscmp0 (__s1, __s2) cmp 0) ; else \
    2256                 :            :     g_assertion_message_cmpstr (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, \
    2257                 :            :                                 #s1u8 " " #cmp " " #s2u8, s1u8, #cmp, s2u8); \
    2258                 :            : } G_STMT_END
    2259                 :            : 
    2260                 :            : static void
    2261                 :            : test_win32_pathstrip (void)
    2262                 :            : {
    2263                 :            :   gunichar2 *buf;
    2264                 :            :   gsize i;
    2265                 :            : #define IDENTITY_TEST(x) { x, x, FALSE }
    2266                 :            :   struct
    2267                 :            :   {
    2268                 :            :     gunichar2 *in;
    2269                 :            :     gunichar2 *out;
    2270                 :            :     gboolean   result;
    2271                 :            :   } testcases[] = {
    2272                 :            :     IDENTITY_TEST (L"\\\\?\\V"),
    2273                 :            :     IDENTITY_TEST (L"\\\\?\\Vo"),
    2274                 :            :     IDENTITY_TEST (L"\\\\?\\Volume{0700f3d3-6d24-11e3-8b2f-806e6f6e6963}\\"),
    2275                 :            :     IDENTITY_TEST (L"\\??\\V"),
    2276                 :            :     IDENTITY_TEST (L"\\??\\Vo"),
    2277                 :            :     IDENTITY_TEST (L"\\??\\Volume{0700f3d3-6d24-11e3-8b2f-806e6f6e6963}\\"),
    2278                 :            :     IDENTITY_TEST (L"\\\\?\\\x0441:\\"),
    2279                 :            :     IDENTITY_TEST (L"\\??\\\x0441:\\"),
    2280                 :            :     IDENTITY_TEST (L"a:\\"),
    2281                 :            :     IDENTITY_TEST (L"a:\\b\\c"),
    2282                 :            :     IDENTITY_TEST (L"x"),
    2283                 :            : #undef IDENTITY_TEST
    2284                 :            :     {
    2285                 :            :       L"\\\\?\\c:\\",
    2286                 :            :              L"c:\\",
    2287                 :            :       TRUE,
    2288                 :            :     },
    2289                 :            :     {
    2290                 :            :       L"\\\\?\\C:\\",
    2291                 :            :              L"C:\\",
    2292                 :            :       TRUE,
    2293                 :            :     },
    2294                 :            :     {
    2295                 :            :       L"\\\\?\\c:\\",
    2296                 :            :              L"c:\\",
    2297                 :            :       TRUE,
    2298                 :            :     },
    2299                 :            :     {
    2300                 :            :       L"\\\\?\\C:\\",
    2301                 :            :              L"C:\\",
    2302                 :            :       TRUE,
    2303                 :            :     },
    2304                 :            :     {
    2305                 :            :       L"\\\\?\\C:\\",
    2306                 :            :              L"C:\\",
    2307                 :            :       TRUE,
    2308                 :            :     },
    2309                 :            :     { 0, }
    2310                 :            :   };
    2311                 :            : 
    2312                 :            :   for (i = 0; testcases[i].in; i++)
    2313                 :            :     {
    2314                 :            :       gsize str_len = wcslen (testcases[i].in) + 1;
    2315                 :            :       gchar *in_u8 = g_utf16_to_utf8 (testcases[i].in, -1, NULL, NULL, NULL);
    2316                 :            :       gchar *out_u8 = g_utf16_to_utf8 (testcases[i].out, -1, NULL, NULL, NULL);
    2317                 :            : 
    2318                 :            :       g_assert_nonnull (in_u8);
    2319                 :            :       g_assert_nonnull (out_u8);
    2320                 :            : 
    2321                 :            :       buf = g_new0 (gunichar2, str_len);
    2322                 :            :       memcpy (buf, testcases[i].in, str_len * sizeof (gunichar2));
    2323                 :            :       _g_win32_strip_extended_ntobjm_prefix (buf, &str_len);
    2324                 :            :       g_assert_cmpwcs (buf, ==, testcases[i].out, in_u8, out_u8);
    2325                 :            :       g_free (buf);
    2326                 :            :       g_free (in_u8);
    2327                 :            :       g_free (out_u8);
    2328                 :            :     }
    2329                 :            :   /* Check for correct behaviour on non-NUL-terminated strings */
    2330                 :            :   for (i = 0; testcases[i].in; i++)
    2331                 :            :     {
    2332                 :            :       gsize str_len = wcslen (testcases[i].in) + 1;
    2333                 :            :       wchar_t old_endchar;
    2334                 :            :       gchar *in_u8 = g_utf16_to_utf8 (testcases[i].in, -1, NULL, NULL, NULL);
    2335                 :            :       gchar *out_u8 = g_utf16_to_utf8 (testcases[i].out, -1, NULL, NULL, NULL);
    2336                 :            : 
    2337                 :            :       g_assert_nonnull (in_u8);
    2338                 :            :       g_assert_nonnull (out_u8);
    2339                 :            : 
    2340                 :            :       buf = g_new0 (gunichar2, str_len);
    2341                 :            :       memcpy (buf, testcases[i].in, (str_len) * sizeof (gunichar2));
    2342                 :            : 
    2343                 :            :       old_endchar = buf[wcslen (testcases[i].out)];
    2344                 :            :       str_len -= 1;
    2345                 :            : 
    2346                 :            :       if (testcases[i].result)
    2347                 :            :         {
    2348                 :            :           /* Given "\\\\?\\C:\\" (len 7, unterminated),
    2349                 :            :            * we should get "C:\\" (len 3, unterminated).
    2350                 :            :            * Put a character different from "\\" (4-th character of the buffer)
    2351                 :            :            * at the end of the unterminated source buffer, into a position
    2352                 :            :            * where NUL-terminator would normally be. Then later test that 4-th character
    2353                 :            :            * in the buffer is still the old "\\".
    2354                 :            :            * After that terminate the string and use normal g_wcscmp0().
    2355                 :            :            */
    2356                 :            :           buf[str_len] = old_endchar - 1;
    2357                 :            :         }
    2358                 :            : 
    2359                 :            :       _g_win32_strip_extended_ntobjm_prefix (buf, &str_len);
    2360                 :            :       g_assert_cmpuint (old_endchar, ==, buf[wcslen (testcases[i].out)]);
    2361                 :            :       buf[str_len] = L'\0';
    2362                 :            :       g_assert_cmpwcs (buf, ==, testcases[i].out, in_u8, out_u8);
    2363                 :            :       g_free (buf);
    2364                 :            :       g_free (in_u8);
    2365                 :            :       g_free (out_u8);
    2366                 :            :     }
    2367                 :            : }
    2368                 :            : 
    2369                 :            : #define g_assert_memcmp(m1, cmp, m2, memlen, m1hex, m2hex, testcase_num) \
    2370                 :            : G_STMT_START { \
    2371                 :            :   if (memcmp (m1, m2, memlen) cmp 0); else \
    2372                 :            :     g_assertion_message_cmpstr (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, \
    2373                 :            :                                 #m1hex " " #cmp " " #m2hex, m1hex, #cmp, m2hex); \
    2374                 :            : } G_STMT_END
    2375                 :            : 
    2376                 :            : static gchar *
    2377                 :            : to_hex (const guchar *buf,
    2378                 :            :         gsize        len)
    2379                 :            : {
    2380                 :            :   gsize i;
    2381                 :            :   GString *s = g_string_new (NULL);
    2382                 :            :   if (len > 0)
    2383                 :            :     g_string_append_printf (s, "%02x", buf[0]);
    2384                 :            :   for (i = 1; i < len; i++)
    2385                 :            :     g_string_append_printf (s, " %02x", buf[i]);
    2386                 :            :   return g_string_free (s, FALSE);
    2387                 :            : }
    2388                 :            : 
    2389                 :            : static void
    2390                 :            : test_win32_zero_terminate_symlink (void)
    2391                 :            : {
    2392                 :            :   gsize i;
    2393                 :            : #define TESTCASE(data, len_mod, use_buf, buf_size, terminate, reported_len, returned_string) \
    2394                 :            :  { (const guchar *) data, wcslen (data) * 2 + len_mod, use_buf, buf_size, terminate, reported_len, (guchar *) returned_string},
    2395                 :            : 
    2396                 :            :   struct
    2397                 :            :   {
    2398                 :            :     const guchar *data;
    2399                 :            :     gsize         data_size;
    2400                 :            :     gboolean      use_buf;
    2401                 :            :     gsize         buf_size;
    2402                 :            :     gboolean      terminate;
    2403                 :            :     int           reported_len;
    2404                 :            :     const guchar *returned_string;
    2405                 :            :   } testcases[] = {
    2406                 :            :     TESTCASE (L"foobar", +2, TRUE, 12 + 4, FALSE, 12 + 2, "f\0o\0o\0b\0a\0r\0\0\0")
    2407                 :            :     TESTCASE (L"foobar", +2, TRUE, 12 + 3, FALSE, 12 + 2, "f\0o\0o\0b\0a\0r\0\0\0")
    2408                 :            :     TESTCASE (L"foobar", +2, TRUE, 12 + 2, FALSE, 12 + 2, "f\0o\0o\0b\0a\0r\0\0\0")
    2409                 :            :     TESTCASE (L"foobar", +2, TRUE, 12 + 1, FALSE, 12 + 1, "f\0o\0o\0b\0a\0r\0\0")
    2410                 :            :     TESTCASE (L"foobar", +2, TRUE, 12 + 0, FALSE, 12 + 0, "f\0o\0o\0b\0a\0r\0")
    2411                 :            :     TESTCASE (L"foobar", +2, TRUE, 12 - 1, FALSE, 12 - 1, "f\0o\0o\0b\0a\0r")
    2412                 :            :     TESTCASE (L"foobar", +2, TRUE, 12 - 2, FALSE, 12 - 2, "f\0o\0o\0b\0a\0")
    2413                 :            :     TESTCASE (L"foobar", +2, TRUE, 12 - 3, FALSE, 12 - 3, "f\0o\0o\0b\0a")
    2414                 :            :     TESTCASE (L"foobar", +1, TRUE, 12 + 4, FALSE, 12 + 1, "f\0o\0o\0b\0a\0r\0\0")
    2415                 :            :     TESTCASE (L"foobar", +1, TRUE, 12 + 3, FALSE, 12 + 1, "f\0o\0o\0b\0a\0r\0\0")
    2416                 :            :     TESTCASE (L"foobar", +1, TRUE, 12 + 2, FALSE, 12 + 1, "f\0o\0o\0b\0a\0r\0\0")
    2417                 :            :     TESTCASE (L"foobar", +1, TRUE, 12 + 1, FALSE, 12 + 1, "f\0o\0o\0b\0a\0r\0\0")
    2418                 :            :     TESTCASE (L"foobar", +1, TRUE, 12 + 0, FALSE, 12 + 0, "f\0o\0o\0b\0a\0r\0")
    2419                 :            :     TESTCASE (L"foobar", +1, TRUE, 12 - 1, FALSE, 12 - 1, "f\0o\0o\0b\0a\0r")
    2420                 :            :     TESTCASE (L"foobar", +1, TRUE, 12 - 2, FALSE, 12 - 2, "f\0o\0o\0b\0a\0")
    2421                 :            :     TESTCASE (L"foobar", +1, TRUE, 12 - 3, FALSE, 12 - 3, "f\0o\0o\0b\0a")
    2422                 :            :     TESTCASE (L"foobar", +0, TRUE, 12 + 4, FALSE, 12 + 0, "f\0o\0o\0b\0a\0r\0")
    2423                 :            :     TESTCASE (L"foobar", +0, TRUE, 12 + 3, FALSE, 12 + 0, "f\0o\0o\0b\0a\0r\0")
    2424                 :            :     TESTCASE (L"foobar", +0, TRUE, 12 + 2, FALSE, 12 + 0, "f\0o\0o\0b\0a\0r\0")
    2425                 :            :     TESTCASE (L"foobar", +0, TRUE, 12 + 1, FALSE, 12 + 0, "f\0o\0o\0b\0a\0r\0")
    2426                 :            :     TESTCASE (L"foobar", +0, TRUE, 12 + 0, FALSE, 12 + 0, "f\0o\0o\0b\0a\0r\0")
    2427                 :            :     TESTCASE (L"foobar", +0, TRUE, 12 - 1, FALSE, 12 - 1, "f\0o\0o\0b\0a\0r")
    2428                 :            :     TESTCASE (L"foobar", +0, TRUE, 12 - 2, FALSE, 12 - 2, "f\0o\0o\0b\0a\0")
    2429                 :            :     TESTCASE (L"foobar", +0, TRUE, 12 - 3, FALSE, 12 - 3, "f\0o\0o\0b\0a")
    2430                 :            :     TESTCASE (L"foobar", -1, TRUE, 12 + 3, FALSE, 12 - 1, "f\0o\0o\0b\0a\0r")
    2431                 :            :     TESTCASE (L"foobar", -1, TRUE, 12 + 2, FALSE, 12 - 1, "f\0o\0o\0b\0a\0r")
    2432                 :            :     TESTCASE (L"foobar", -1, TRUE, 12 + 1, FALSE, 12 - 1, "f\0o\0o\0b\0a\0r")
    2433                 :            :     TESTCASE (L"foobar", -1, TRUE, 12 + 0, FALSE, 12 - 1, "f\0o\0o\0b\0a\0r")
    2434                 :            :     TESTCASE (L"foobar", -1, TRUE, 12 - 1, FALSE, 12 - 1, "f\0o\0o\0b\0a\0r")
    2435                 :            :     TESTCASE (L"foobar", -1, TRUE, 12 - 2, FALSE, 12 - 2, "f\0o\0o\0b\0a\0")
    2436                 :            :     TESTCASE (L"foobar", -1, TRUE, 12 - 3, FALSE, 12 - 3, "f\0o\0o\0b\0a")
    2437                 :            :     TESTCASE (L"foobar", -1, TRUE, 12 - 4, FALSE, 12 - 4, "f\0o\0o\0b\0")
    2438                 :            :     TESTCASE (L"foobar", -2, TRUE, 12 + 2, FALSE, 12 - 2, "f\0o\0o\0b\0a\0")
    2439                 :            :     TESTCASE (L"foobar", -2, TRUE, 12 + 1, FALSE, 12 - 2, "f\0o\0o\0b\0a\0")
    2440                 :            :     TESTCASE (L"foobar", -2, TRUE, 12 + 0, FALSE, 12 - 2, "f\0o\0o\0b\0a\0")
    2441                 :            :     TESTCASE (L"foobar", -2, TRUE, 12 - 1, FALSE, 12 - 2, "f\0o\0o\0b\0a\0")
    2442                 :            :     TESTCASE (L"foobar", -2, TRUE, 12 - 2, FALSE, 12 - 2, "f\0o\0o\0b\0a\0")
    2443                 :            :     TESTCASE (L"foobar", -2, TRUE, 12 - 3, FALSE, 12 - 3, "f\0o\0o\0b\0a")
    2444                 :            :     TESTCASE (L"foobar", -2, TRUE, 12 - 4, FALSE, 12 - 4, "f\0o\0o\0b\0")
    2445                 :            :     TESTCASE (L"foobar", -2, TRUE, 12 - 5, FALSE, 12 - 5, "f\0o\0o\0b")
    2446                 :            :     TESTCASE (L"foobar", +2, TRUE, 12 + 4, TRUE, 12 + 2, "f\0o\0o\0b\0a\0r\0\0\0")
    2447                 :            :     TESTCASE (L"foobar", +2, TRUE, 12 + 3, TRUE, 12 + 2, "f\0o\0o\0b\0a\0r\0\0\0")
    2448                 :            :     TESTCASE (L"foobar", +2, TRUE, 12 + 2, TRUE, 12 + 2, "f\0o\0o\0b\0a\0r\0\0\0")
    2449                 :            :     TESTCASE (L"foobar", +2, TRUE, 12 + 1, TRUE, 12 + 1, "f\0o\0o\0b\0a\0r\0\0")
    2450                 :            :     TESTCASE (L"foobar", +2, TRUE, 12 + 0, TRUE, 12 + 0, "f\0o\0o\0b\0a\0\0\0")
    2451                 :            :     TESTCASE (L"foobar", +2, TRUE, 12 - 1, TRUE, 12 - 1, "f\0o\0o\0b\0a\0\0")
    2452                 :            :     TESTCASE (L"foobar", +2, TRUE, 12 - 2, TRUE, 12 - 2, "f\0o\0o\0b\0\0\0")
    2453                 :            :     TESTCASE (L"foobar", +2, TRUE, 12 - 3, TRUE, 12 - 3, "f\0o\0o\0b\0\0")
    2454                 :            :     TESTCASE (L"foobar", +1, TRUE, 12 + 4, TRUE, 12 + 1, "f\0o\0o\0b\0a\0r\0\0")
    2455                 :            :     TESTCASE (L"foobar", +1, TRUE, 12 + 3, TRUE, 12 + 1, "f\0o\0o\0b\0a\0r\0\0")
    2456                 :            :     TESTCASE (L"foobar", +1, TRUE, 12 + 2, TRUE, 12 + 1, "f\0o\0o\0b\0a\0r\0\0")
    2457                 :            :     TESTCASE (L"foobar", +1, TRUE, 12 + 1, TRUE, 12 + 1, "f\0o\0o\0b\0a\0r\0\0")
    2458                 :            :     TESTCASE (L"foobar", +1, TRUE, 12 + 0, TRUE, 12 + 0, "f\0o\0o\0b\0a\0\0\0")
    2459                 :            :     TESTCASE (L"foobar", +1, TRUE, 12 - 1, TRUE, 12 - 1, "f\0o\0o\0b\0a\0\0")
    2460                 :            :     TESTCASE (L"foobar", +1, TRUE, 12 - 2, TRUE, 12 - 2, "f\0o\0o\0b\0\0\0")
    2461                 :            :     TESTCASE (L"foobar", +1, TRUE, 12 - 3, TRUE, 12 - 3, "f\0o\0o\0b\0\0")
    2462                 :            :     TESTCASE (L"foobar", +0, TRUE, 12 + 4, TRUE, 12 + 1, "f\0o\0o\0b\0a\0r\0\0")
    2463                 :            :     TESTCASE (L"foobar", +0, TRUE, 12 + 3, TRUE, 12 + 1, "f\0o\0o\0b\0a\0r\0\0")
    2464                 :            :     TESTCASE (L"foobar", +0, TRUE, 12 + 2, TRUE, 12 + 1, "f\0o\0o\0b\0a\0r\0\0")
    2465                 :            :     TESTCASE (L"foobar", +0, TRUE, 12 + 1, TRUE, 12 + 1, "f\0o\0o\0b\0a\0r\0\0")
    2466                 :            :     TESTCASE (L"foobar", +0, TRUE, 12 + 0, TRUE, 12 + 0, "f\0o\0o\0b\0a\0\0\0")
    2467                 :            :     TESTCASE (L"foobar", +0, TRUE, 12 - 1, TRUE, 12 - 1, "f\0o\0o\0b\0a\0\0")
    2468                 :            :     TESTCASE (L"foobar", +0, TRUE, 12 - 2, TRUE, 12 - 2, "f\0o\0o\0b\0\0\0")
    2469                 :            :     TESTCASE (L"foobar", +0, TRUE, 12 - 3, TRUE, 12 - 3, "f\0o\0o\0b\0\0")
    2470                 :            :     TESTCASE (L"foobar", -1, TRUE, 12 + 3, TRUE, 12 + 1, "f\0o\0o\0b\0a\0r\0\0")
    2471                 :            :     TESTCASE (L"foobar", -1, TRUE, 12 + 2, TRUE, 12 + 1, "f\0o\0o\0b\0a\0r\0\0")
    2472                 :            :     TESTCASE (L"foobar", -1, TRUE, 12 + 1, TRUE, 12 + 1, "f\0o\0o\0b\0a\0r\0\0")
    2473                 :            :     TESTCASE (L"foobar", -1, TRUE, 12 + 0, TRUE, 12 + 0, "f\0o\0o\0b\0a\0\0\0")
    2474                 :            :     TESTCASE (L"foobar", -1, TRUE, 12 - 1, TRUE, 12 - 1, "f\0o\0o\0b\0a\0\0")
    2475                 :            :     TESTCASE (L"foobar", -1, TRUE, 12 - 2, TRUE, 12 - 2, "f\0o\0o\0b\0\0\0")
    2476                 :            :     TESTCASE (L"foobar", -1, TRUE, 12 - 3, TRUE, 12 - 3, "f\0o\0o\0b\0\0")
    2477                 :            :     TESTCASE (L"foobar", -1, TRUE, 12 - 4, TRUE, 12 - 4, "f\0o\0o\0\0\0")
    2478                 :            :     TESTCASE (L"foobar", -2, TRUE, 12 + 2, TRUE, 12 - 1, "f\0o\0o\0b\0a\0\0")
    2479                 :            :     TESTCASE (L"foobar", -2, TRUE, 12 + 1, TRUE, 12 - 1, "f\0o\0o\0b\0a\0\0")
    2480                 :            :     TESTCASE (L"foobar", -2, TRUE, 12 + 0, TRUE, 12 - 1, "f\0o\0o\0b\0a\0\0")
    2481                 :            :     TESTCASE (L"foobar", -2, TRUE, 12 - 1, TRUE, 12 - 1, "f\0o\0o\0b\0a\0\0")
    2482                 :            :     TESTCASE (L"foobar", -2, TRUE, 12 - 2, TRUE, 12 - 2, "f\0o\0o\0b\0\0\0")
    2483                 :            :     TESTCASE (L"foobar", -2, TRUE, 12 - 3, TRUE, 12 - 3, "f\0o\0o\0b\0\0")
    2484                 :            :     TESTCASE (L"foobar", -2, TRUE, 12 - 4, TRUE, 12 - 4, "f\0o\0o\0\0\0")
    2485                 :            :     TESTCASE (L"foobar", -2, TRUE, 12 - 5, TRUE, 12 - 5, "f\0o\0o\0\0")
    2486                 :            :     TESTCASE (L"foobar", +2, FALSE, 0, FALSE, 12 + 2, "f\0o\0o\0b\0a\0r\0\0\0")
    2487                 :            :     TESTCASE (L"foobar", +1, FALSE, 0, FALSE, 12 + 1, "f\0o\0o\0b\0a\0r\0\0")
    2488                 :            :     TESTCASE (L"foobar", +0, FALSE, 0, FALSE, 12 + 0, "f\0o\0o\0b\0a\0r\0")
    2489                 :            :     TESTCASE (L"foobar", -1, FALSE, 0, FALSE, 12 - 1, "f\0o\0o\0b\0a\0r")
    2490                 :            :     TESTCASE (L"foobar", -2, FALSE, 0, FALSE, 12 - 2, "f\0o\0o\0b\0a\0")
    2491                 :            :     TESTCASE (L"foobar", +2, FALSE, 0, TRUE, 12 + 2, "f\0o\0o\0b\0a\0r\0\0\0")
    2492                 :            :     TESTCASE (L"foobar", +1, FALSE, 0, TRUE, 12 + 1, "f\0o\0o\0b\0a\0r\0\0")
    2493                 :            :     TESTCASE (L"foobar", +0, FALSE, 0, TRUE, 12 + 1, "f\0o\0o\0b\0a\0r\0\0")
    2494                 :            :     TESTCASE (L"foobar", -1, FALSE, 0, TRUE, 12 + 1, "f\0o\0o\0b\0a\0r\0\0")
    2495                 :            :     TESTCASE (L"foobar", -2, FALSE, 0, TRUE, 12 - 1, "f\0o\0o\0b\0a\0\0")
    2496                 :            :     TESTCASE (L"x", +2, TRUE, 2 + 4, FALSE, 2 + 2, "x\0\0\0")
    2497                 :            :     TESTCASE (L"x", +2, TRUE, 2 + 3, FALSE, 2 + 2, "x\0\0\0")
    2498                 :            :     TESTCASE (L"x", +2, TRUE, 2 + 2, FALSE, 2 + 2, "x\0\0\0")
    2499                 :            :     TESTCASE (L"x", +2, TRUE, 2 + 1, FALSE, 2 + 1, "x\0\0")
    2500                 :            :     TESTCASE (L"x", +2, TRUE, 2 + 0, FALSE, 2 + 0, "x\0")
    2501                 :            :     TESTCASE (L"x", +2, TRUE, 2 - 1, FALSE, 2 - 1, "x")
    2502                 :            :     TESTCASE (L"x", +2, TRUE, 2 - 2, FALSE, 2 - 2, "")
    2503                 :            :     TESTCASE (L"x", +1, TRUE, 2 + 3, FALSE, 2 + 1, "x\0\0")
    2504                 :            :     TESTCASE (L"x", +1, TRUE, 2 + 2, FALSE, 2 + 1, "x\0\0")
    2505                 :            :     TESTCASE (L"x", +1, TRUE, 2 + 1, FALSE, 2 + 1, "x\0\0")
    2506                 :            :     TESTCASE (L"x", +1, TRUE, 2 + 0, FALSE, 2 + 0, "x\0")
    2507                 :            :     TESTCASE (L"x", +1, TRUE, 2 - 1, FALSE, 2 - 1, "x")
    2508                 :            :     TESTCASE (L"x", +1, TRUE, 2 - 2, FALSE, 2 - 2, "")
    2509                 :            :     TESTCASE (L"x", +0, TRUE, 2 + 2, FALSE, 2 + 0, "x\0")
    2510                 :            :     TESTCASE (L"x", +0, TRUE, 2 + 1, FALSE, 2 + 0, "x\0")
    2511                 :            :     TESTCASE (L"x", +0, TRUE, 2 + 0, FALSE, 2 + 0, "x\0")
    2512                 :            :     TESTCASE (L"x", +0, TRUE, 2 - 1, FALSE, 2 - 1, "x")
    2513                 :            :     TESTCASE (L"x", +0, TRUE, 2 - 2, FALSE, 2 - 2, "")
    2514                 :            :     TESTCASE (L"x", -1, TRUE, 2 + 1, FALSE, 2 - 1, "x")
    2515                 :            :     TESTCASE (L"x", -1, TRUE, 2 + 0, FALSE, 2 - 1, "x")
    2516                 :            :     TESTCASE (L"x", -1, TRUE, 2 - 1, FALSE, 2 - 1, "x")
    2517                 :            :     TESTCASE (L"x", -1, TRUE, 2 - 2, FALSE, 2 - 2, "")
    2518                 :            :     TESTCASE (L"x", -2, TRUE, 2 + 0, FALSE, 2 - 2, "")
    2519                 :            :     TESTCASE (L"x", -2, TRUE, 2 - 1, FALSE, 2 - 2, "")
    2520                 :            :     TESTCASE (L"x", -2, TRUE, 2 - 2, FALSE, 2 - 2, "")
    2521                 :            :     TESTCASE (L"x", +2, TRUE, 2 + 4, TRUE, 2 + 2, "x\0\0\0")
    2522                 :            :     TESTCASE (L"x", +2, TRUE, 2 + 3, TRUE, 2 + 2, "x\0\0\0")
    2523                 :            :     TESTCASE (L"x", +2, TRUE, 2 + 2, TRUE, 2 + 2, "x\0\0\0")
    2524                 :            :     TESTCASE (L"x", +2, TRUE, 2 + 1, TRUE, 2 + 1, "x\0\0")
    2525                 :            :     TESTCASE (L"x", +2, TRUE, 2 + 0, TRUE, 2 + 0, "\0\0")
    2526                 :            :     TESTCASE (L"x", +2, TRUE, 2 - 1, TRUE, 2 - 1, "\0")
    2527                 :            :     TESTCASE (L"x", +2, TRUE, 2 - 2, TRUE, 2 - 2, "")
    2528                 :            :     TESTCASE (L"x", +1, TRUE, 2 + 3, TRUE, 2 + 1, "x\0\0")
    2529                 :            :     TESTCASE (L"x", +1, TRUE, 2 + 2, TRUE, 2 + 1, "x\0\0")
    2530                 :            :     TESTCASE (L"x", +1, TRUE, 2 + 1, TRUE, 2 + 1, "x\0\0")
    2531                 :            :     TESTCASE (L"x", +1, TRUE, 2 + 0, TRUE, 2 + 0, "\0\0")
    2532                 :            :     TESTCASE (L"x", +1, TRUE, 2 - 1, TRUE, 2 - 1, "\0")
    2533                 :            :     TESTCASE (L"x", +1, TRUE, 2 - 2, TRUE, 2 - 2, "")
    2534                 :            :     TESTCASE (L"x", +0, TRUE, 2 + 2, TRUE, 2 + 1, "x\0\0")
    2535                 :            :     TESTCASE (L"x", +0, TRUE, 2 + 1, TRUE, 2 + 1, "x\0\0")
    2536                 :            :     TESTCASE (L"x", +0, TRUE, 2 + 0, TRUE, 2 + 0, "\0\0")
    2537                 :            :     TESTCASE (L"x", +0, TRUE, 2 - 1, TRUE, 2 - 1, "\0")
    2538                 :            :     TESTCASE (L"x", +0, TRUE, 2 - 2, TRUE, 2 - 2, "")
    2539                 :            :     TESTCASE (L"x", -1, TRUE, 2 + 1, TRUE, 2 + 1, "x\0\0")
    2540                 :            :     TESTCASE (L"x", -1, TRUE, 2 + 0, TRUE, 2 + 0, "\0\0")
    2541                 :            :     TESTCASE (L"x", -1, TRUE, 2 - 1, TRUE, 2 - 1, "\0")
    2542                 :            :     TESTCASE (L"x", -1, TRUE, 2 - 2, TRUE, 2 - 2, "")
    2543                 :            :     TESTCASE (L"x", -2, TRUE, 2 + 0, TRUE, 2 - 2, "")
    2544                 :            :     TESTCASE (L"x", -2, TRUE, 2 - 1, TRUE, 2 - 2, "")
    2545                 :            :     TESTCASE (L"x", -2, TRUE, 2 - 2, TRUE, 2 - 2, "")
    2546                 :            :     TESTCASE (L"x", +2, FALSE, 0, FALSE, 2 + 2, "x\0\0\0")
    2547                 :            :     TESTCASE (L"x", +1, FALSE, 0, FALSE, 2 + 1, "x\0\0")
    2548                 :            :     TESTCASE (L"x", +0, FALSE, 0, FALSE, 2 + 0, "x\0")
    2549                 :            :     TESTCASE (L"x", -1, FALSE, 0, FALSE, 2 - 1, "x")
    2550                 :            :     TESTCASE (L"x", -2, FALSE, 0, FALSE, 2 - 2, "")
    2551                 :            :     TESTCASE (L"x", +2, FALSE, 0, TRUE, 2 + 2, "x\0\0\0")
    2552                 :            :     TESTCASE (L"x", +1, FALSE, 0, TRUE, 2 + 1, "x\0\0")
    2553                 :            :     TESTCASE (L"x", +0, FALSE, 0, TRUE, 2 + 1, "x\0\0")
    2554                 :            :     TESTCASE (L"x", -1, FALSE, 0, TRUE, 2 + 1, "x\0\0")
    2555                 :            :     TESTCASE (L"x", -2, FALSE, 0, TRUE, 2 - 2, "")
    2556                 :            :     { 0, },
    2557                 :            :   };
    2558                 :            : #undef TESTCASE
    2559                 :            : 
    2560                 :            :   for (i = 0; testcases[i].data != NULL; i++)
    2561                 :            :     {
    2562                 :            :       gunichar2 *buf;
    2563                 :            :       int result;
    2564                 :            :       gchar *buf_hex, *expected_hex;
    2565                 :            :       if (testcases[i].use_buf)
    2566                 :            :         buf = g_malloc0 (testcases[i].buf_size + 1); /* +1 to ensure it succeeds with buf_size == 0 */
    2567                 :            :       else
    2568                 :            :         buf = NULL;
    2569                 :            :       result = _g_win32_copy_and_maybe_terminate (testcases[i].data,
    2570                 :            :                                                   testcases[i].data_size,
    2571                 :            :                                                   testcases[i].use_buf ? buf : NULL,
    2572                 :            :                                                   testcases[i].buf_size,
    2573                 :            :                                                   testcases[i].use_buf ? NULL : &buf,
    2574                 :            :                                                   testcases[i].terminate);
    2575                 :            :       if (testcases[i].reported_len != result)
    2576                 :            :         g_error ("Test %" G_GSIZE_FORMAT " failed, result %d != %d", i, result, testcases[i].reported_len);
    2577                 :            :       if (buf == NULL && testcases[i].buf_size != 0)
    2578                 :            :         g_error ("Test %" G_GSIZE_FORMAT " failed, buf == NULL", i);
    2579                 :            :       g_assert_cmpint (testcases[i].reported_len, ==, result);
    2580                 :            :       if ((testcases[i].use_buf && testcases[i].buf_size != 0) ||
    2581                 :            :           (!testcases[i].use_buf && testcases[i].reported_len != 0))
    2582                 :            :         {
    2583                 :            :           g_assert_nonnull (buf);
    2584                 :            :           buf_hex = to_hex ((const guchar *) buf, result);
    2585                 :            :           expected_hex = to_hex (testcases[i].returned_string, testcases[i].reported_len);
    2586                 :            :           if (memcmp (buf, testcases[i].returned_string, result) != 0)
    2587                 :            :             g_error ("Test %" G_GSIZE_FORMAT " failed:\n%s !=\n%s", i, buf_hex, expected_hex);
    2588                 :            :           g_assert_memcmp (buf, ==, testcases[i].returned_string, testcases[i].reported_len, buf_hex, expected_hex, testcases[i].line);
    2589                 :            :           g_free (buf_hex);
    2590                 :            :           g_free (expected_hex);
    2591                 :            :         }
    2592                 :            :       g_free (buf);
    2593                 :            :     }
    2594                 :            : }
    2595                 :            : 
    2596                 :            : #endif
    2597                 :            : 
    2598                 :            : static void
    2599                 :          1 : test_clear_fd_ebadf (void)
    2600                 :            : {
    2601                 :          1 :   char *name = NULL;
    2602                 :          1 :   GError *error = NULL;
    2603                 :            :   int fd;
    2604                 :            :   int copy_of_fd;
    2605                 :            :   int errsv;
    2606                 :            :   gboolean ret;
    2607                 :            :   GWin32InvalidParameterHandler handler;
    2608                 :            : 
    2609                 :            :   /* We're going to trigger a programming error: attmpting to close a
    2610                 :            :    * fd that was already closed. Make criticals non-fatal. */
    2611                 :          1 :   g_assert_true (g_test_undefined ());
    2612                 :          1 :   g_log_set_always_fatal (G_LOG_FATAL_MASK);
    2613                 :          1 :   g_log_set_fatal_mask ("GLib", G_LOG_FATAL_MASK);
    2614                 :          1 :   GLIB_PRIVATE_CALL (g_win32_push_empty_invalid_parameter_handler) (&handler);
    2615                 :            : 
    2616                 :          1 :   fd = g_file_open_tmp (NULL, &name, &error);
    2617                 :          1 :   g_assert_cmpint (fd, !=, -1);
    2618                 :          1 :   g_assert_no_error (error);
    2619                 :          1 :   g_assert_nonnull (name);
    2620                 :          1 :   ret = g_close (fd, &error);
    2621                 :          1 :   g_assert_no_error (error);
    2622                 :          1 :   assert_fd_was_closed (fd);
    2623                 :          1 :   g_assert_true (ret);
    2624                 :          1 :   g_unlink (name);
    2625                 :          1 :   g_free (name);
    2626                 :            : 
    2627                 :            :   /* Try to close it again with g_close() */
    2628                 :          1 :   ret = g_close (fd, NULL);
    2629                 :          1 :   errsv = errno;
    2630                 :          1 :   g_assert_cmpint (errsv, ==, EBADF);
    2631                 :          1 :   assert_fd_was_closed (fd);
    2632                 :          1 :   g_assert_false (ret);
    2633                 :            : 
    2634                 :            :   /* Try to close it again with g_clear_fd() */
    2635                 :          1 :   copy_of_fd = fd;
    2636                 :          1 :   errno = EILSEQ;
    2637                 :          1 :   ret = g_clear_fd (&copy_of_fd, NULL);
    2638                 :          1 :   errsv = errno;
    2639                 :          1 :   g_assert_cmpint (errsv, ==, EBADF);
    2640                 :          1 :   assert_fd_was_closed (fd);
    2641                 :          1 :   g_assert_false (ret);
    2642                 :            : 
    2643                 :            : #ifdef g_autofree
    2644                 :            :     {
    2645                 :          2 :       g_autofd int close_me = fd;
    2646                 :            : 
    2647                 :            :       /* This avoids clang warnings about the variables being unused */
    2648                 :          1 :       g_test_message ("Invalid fd will be closed by autocleanup: %d",
    2649                 :            :                       close_me);
    2650                 :          1 :       errno = EILSEQ;
    2651                 :            :     }
    2652                 :            : 
    2653                 :          1 :   errsv = errno;
    2654                 :          1 :   g_assert_cmpint (errsv, ==, EILSEQ);
    2655                 :            : #endif
    2656                 :            : 
    2657                 :          1 :   GLIB_PRIVATE_CALL (g_win32_pop_invalid_parameter_handler) (&handler);
    2658                 :          1 : }
    2659                 :            : 
    2660                 :            : static void
    2661                 :          1 : test_clear_fd (void)
    2662                 :            : {
    2663                 :          1 :   char *name = NULL;
    2664                 :          1 :   GError *error = NULL;
    2665                 :            :   int fd;
    2666                 :            :   int copy_of_fd;
    2667                 :            :   int errsv;
    2668                 :            : 
    2669                 :            : #ifdef g_autofree
    2670                 :          1 :   g_test_summary ("Test g_clear_fd() and g_autofd");
    2671                 :            : #else
    2672                 :            :   g_test_summary ("Test g_clear_fd() (g_autofd unsupported by this compiler)");
    2673                 :            : #endif
    2674                 :            : 
    2675                 :            :   /* g_clear_fd() normalizes any negative number to -1 */
    2676                 :          1 :   fd = -23;
    2677                 :          1 :   g_clear_fd (&fd, &error);
    2678                 :          1 :   g_assert_cmpint (fd, ==, -1);
    2679                 :          1 :   g_assert_no_error (error);
    2680                 :            : 
    2681                 :            :   /* Nothing special about g_file_open_tmp, it's just a convenient way
    2682                 :            :    * to get an open fd */
    2683                 :          1 :   fd = g_file_open_tmp (NULL, &name, &error);
    2684                 :          1 :   g_assert_cmpint (fd, !=, -1);
    2685                 :          1 :   g_assert_no_error (error);
    2686                 :          1 :   g_assert_nonnull (name);
    2687                 :          1 :   copy_of_fd = fd;
    2688                 :          1 :   g_clear_fd (&fd, &error);
    2689                 :          1 :   g_assert_cmpint (fd, ==, -1);
    2690                 :          1 :   g_assert_no_error (error);
    2691                 :          1 :   assert_fd_was_closed (copy_of_fd);
    2692                 :          1 :   g_unlink (name);
    2693                 :          1 :   g_free (name);
    2694                 :            : 
    2695                 :            :   /* g_clear_fd() is idempotent */
    2696                 :          1 :   g_clear_fd (&fd, &error);
    2697                 :          1 :   g_assert_cmpint (fd, ==, -1);
    2698                 :          1 :   g_assert_no_error (error);
    2699                 :            : 
    2700                 :            : #ifdef g_autofree
    2701                 :          1 :   fd = g_file_open_tmp (NULL, &name, &error);
    2702                 :          1 :   g_assert_cmpint (fd, !=, -1);
    2703                 :          1 :   g_assert_no_error (error);
    2704                 :          1 :   g_assert_nonnull (name);
    2705                 :            : 
    2706                 :            :     {
    2707                 :          1 :       g_autofd int close_me = fd;
    2708                 :          2 :       g_autofd int was_never_set = -42;
    2709                 :            : 
    2710                 :            :       /* This avoids clang warnings about the variables being unused */
    2711                 :          1 :       g_test_message ("Will be closed by autocleanup: %d, %d",
    2712                 :            :                       close_me, was_never_set);
    2713                 :            :       /* This is one of the few errno values guaranteed by Standard C.
    2714                 :            :        * We set it here to check that a successful g_autofd close doesn't
    2715                 :            :        * alter errno. */
    2716                 :          1 :       errno = EILSEQ;
    2717                 :            :     }
    2718                 :            : 
    2719                 :          1 :   errsv = errno;
    2720                 :          1 :   g_assert_cmpint (errsv, ==, EILSEQ);
    2721                 :          1 :   assert_fd_was_closed (fd);
    2722                 :          1 :   g_unlink (name);
    2723                 :          1 :   g_free (name);
    2724                 :            : #endif
    2725                 :            : 
    2726         [ +  - ]:          1 :   if (g_test_undefined ())
    2727                 :            :     {
    2728                 :          1 :       g_test_message ("Testing error handling");
    2729                 :          1 :       g_test_trap_subprocess ("/fileutils/clear-fd/subprocess/ebadf",
    2730                 :            :                               0, G_TEST_SUBPROCESS_DEFAULT);
    2731                 :            : #ifdef g_autofree
    2732                 :          1 :       g_test_trap_assert_stderr ("*failed with EBADF*failed with EBADF*failed with EBADF*");
    2733                 :            : #else
    2734                 :            :       g_test_trap_assert_stderr ("*failed with EBADF*failed with EBADF*");
    2735                 :            : #endif
    2736                 :          1 :       g_test_trap_assert_passed ();
    2737                 :            :     }
    2738                 :          1 : }
    2739                 :            : 
    2740                 :            : int
    2741                 :          2 : main (int   argc,
    2742                 :            :       char *argv[])
    2743                 :            : {
    2744                 :          2 :   g_setenv ("LC_ALL", "C", TRUE);
    2745                 :          2 :   g_test_init (&argc, &argv, G_TEST_OPTION_ISOLATE_DIRS, NULL);
    2746                 :            : 
    2747                 :            : #ifdef G_OS_WIN32
    2748                 :            :   g_test_add_func ("/fileutils/stdio-win32-pathstrip", test_win32_pathstrip);
    2749                 :            :   g_test_add_func ("/fileutils/stdio-win32-zero-terminate-symlink", test_win32_zero_terminate_symlink);
    2750                 :            : #endif
    2751                 :          2 :   g_test_add_func ("/fileutils/paths", test_paths);
    2752                 :          2 :   g_test_add_func ("/fileutils/build-path", test_build_path);
    2753                 :          2 :   g_test_add_func ("/fileutils/build-pathv", test_build_pathv);
    2754                 :          2 :   g_test_add_func ("/fileutils/build-filename", test_build_filename);
    2755                 :          2 :   g_test_add_func ("/fileutils/build-filenamev", test_build_filenamev);
    2756                 :          2 :   g_test_add_func ("/fileutils/mkdir-with-parents", test_mkdir_with_parents);
    2757                 :          2 :   g_test_add_func ("/fileutils/mkdir-with-parents-permission", test_mkdir_with_parents_permission);
    2758                 :          2 :   g_test_add_func ("/fileutils/format-size-for-display", test_format_size_for_display);
    2759                 :          2 :   g_test_add_func ("/fileutils/errors", test_file_errors);
    2760                 :          2 :   g_test_add_func ("/fileutils/basename", test_basename);
    2761                 :          2 :   g_test_add_func ("/fileutils/get-basename", test_get_basename);
    2762                 :          2 :   g_test_add_func ("/fileutils/dirname", test_dirname);
    2763                 :          2 :   g_test_add_func ("/fileutils/dir-make-tmp", test_dir_make_tmp);
    2764                 :          2 :   g_test_add_func ("/fileutils/file-open-tmp", test_file_open_tmp);
    2765                 :          2 :   g_test_add_func ("/fileutils/file-test", test_file_test);
    2766                 :          2 :   g_test_add_func ("/fileutils/mkstemp", test_mkstemp);
    2767                 :          2 :   g_test_add_func ("/fileutils/mkdtemp", test_mkdtemp);
    2768                 :          2 :   g_test_add_func ("/fileutils/get-contents", test_get_contents);
    2769                 :          2 :   g_test_add_func ("/fileutils/get-contents-large-file", test_get_contents_largefile);
    2770                 :          2 :   g_test_add_func ("/fileutils/set-contents", test_set_contents);
    2771                 :          2 :   g_test_add_func ("/fileutils/set-contents-full", test_set_contents_full);
    2772                 :          2 :   g_test_add_func ("/fileutils/set-contents-full/read-only-file", test_set_contents_full_read_only_file);
    2773                 :          2 :   g_test_add_func ("/fileutils/set-contents-full/read-only-directory", test_set_contents_full_read_only_directory);
    2774                 :          2 :   g_test_add_func ("/fileutils/read-link", test_read_link);
    2775                 :          2 :   g_test_add_func ("/fileutils/stdio-wrappers", test_stdio_wrappers);
    2776                 :          2 :   g_test_add_func ("/fileutils/fopen-modes", test_fopen_modes);
    2777                 :          2 :   g_test_add_func ("/fileutils/clear-fd", test_clear_fd);
    2778                 :          2 :   g_test_add_func ("/fileutils/clear-fd/subprocess/ebadf", test_clear_fd_ebadf);
    2779                 :            : 
    2780                 :          2 :   return g_test_run ();
    2781                 :            : }

Generated by: LCOV version 1.14