LCOV - code coverage report
Current view: top level - glib/gio/tests - live-g-file.c (source / functions) Hit Total Coverage
Test: unnamed Lines: 632 657 96.2 %
Date: 2024-04-23 05:16:05 Functions: 21 21 100.0 %
Branches: 198 266 74.4 %

           Branch data     Line data    Source code
       1                 :            : /* GLib testing framework examples and tests
       2                 :            :  * Copyright (C) 2008 Red Hat, Inc.
       3                 :            :  * Authors: Tomas Bzatek <tbzatek@redhat.com>
       4                 :            :  *
       5                 :            :  * SPDX-License-Identifier: LicenseRef-old-glib-tests
       6                 :            :  *
       7                 :            :  * This work is provided "as is"; redistribution and modification
       8                 :            :  * in whole or in part, in any medium, physical or electronic is
       9                 :            :  * permitted without restriction.
      10                 :            :  *
      11                 :            :  * This work is distributed in the hope that it will be useful,
      12                 :            :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      13                 :            :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
      14                 :            :  *
      15                 :            :  * In no event shall the authors or contributors be liable for any
      16                 :            :  * direct, indirect, incidental, special, exemplary, or consequential
      17                 :            :  * damages (including, but not limited to, procurement of substitute
      18                 :            :  * goods or services; loss of use, data, or profits; or business
      19                 :            :  * interruption) however caused and on any theory of liability, whether
      20                 :            :  * in contract, strict liability, or tort (including negligence or
      21                 :            :  * otherwise) arising in any way out of the use of this software, even
      22                 :            :  * if advised of the possibility of such damage.
      23                 :            :  */
      24                 :            : 
      25                 :            : #include <glib/glib.h>
      26                 :            : #include <gio/gio.h>
      27                 :            : #include <errno.h>
      28                 :            : #include <stdlib.h>
      29                 :            : #include <stdio.h>
      30                 :            : #include <unistd.h>
      31                 :            : #include <sys/types.h>
      32                 :            : #include <string.h>
      33                 :            : #include <sys/stat.h>
      34                 :            : 
      35                 :            : #define DEFAULT_TEST_DIR                "testdir_live-g-file"
      36                 :            : 
      37                 :            : #define PATTERN_FILE_SIZE       0x10000
      38                 :            : #define TEST_HANDLE_SPECIAL     TRUE
      39                 :            : 
      40                 :            : enum StructureExtraFlags
      41                 :            : {
      42                 :            :   TEST_DELETE_NORMAL = 1 << 0,
      43                 :            :   TEST_DELETE_TRASH = 1 << 1,
      44                 :            :   TEST_DELETE_NON_EMPTY = 1 << 2,
      45                 :            :   TEST_DELETE_FAILURE = 1 << 3,
      46                 :            :   TEST_NOT_EXISTS = 1 << 4,
      47                 :            :   TEST_ENUMERATE_FILE = 1 << 5,
      48                 :            :   TEST_NO_ACCESS = 1 << 6,
      49                 :            :   TEST_COPY = 1 << 7,
      50                 :            :   TEST_MOVE = 1 << 8,
      51                 :            :   TEST_COPY_ERROR_RECURSE = 1 << 9,
      52                 :            :   TEST_ALREADY_EXISTS = 1 << 10,
      53                 :            :   TEST_TARGET_IS_FILE = 1 << 11,
      54                 :            :   TEST_CREATE = 1 << 12,
      55                 :            :   TEST_REPLACE = 1 << 13,
      56                 :            :   TEST_APPEND = 1 << 14,
      57                 :            :   TEST_OPEN = 1 << 15,
      58                 :            :   TEST_OVERWRITE = 1 << 16,
      59                 :            :   TEST_INVALID_SYMLINK = 1 << 17,
      60                 :            :   TEST_HIDDEN = 1 << 18,
      61                 :            :   TEST_DOT_HIDDEN = 1 << 19,
      62                 :            : };
      63                 :            : 
      64                 :            : struct StructureItem
      65                 :            : {
      66                 :            :   const char *filename;
      67                 :            :   const char *link_to;
      68                 :            :   GFileType file_type;
      69                 :            :   GFileCreateFlags create_flags;
      70                 :            :   guint32 mode;
      71                 :            :   gboolean handle_special;
      72                 :            :   enum StructureExtraFlags extra_flags;
      73                 :            : };
      74                 :            : 
      75                 :            : #define TEST_DIR_NO_ACCESS              "dir_no-access"
      76                 :            : #define TEST_DIR_NO_WRITE               "dir_no-write"
      77                 :            : #define TEST_DIR_TARGET                 "dir-target"
      78                 :            : #define TEST_NAME_NOT_EXISTS    "not_exists"
      79                 :            : #define TEST_TARGET_FILE                "target-file"
      80                 :            : 
      81                 :            : 
      82                 :            : static const struct StructureItem sample_struct[] = {
      83                 :            : /*       filename                               link    file_type                               create_flags            mode | handle_special | extra_flags              */
      84                 :            :     {"dir1",                          NULL,   G_FILE_TYPE_DIRECTORY,  G_FILE_CREATE_NONE, 0, 0, TEST_DELETE_NORMAL | TEST_DELETE_NON_EMPTY | TEST_REPLACE | TEST_OPEN},
      85                 :            :     {"dir1/subdir",                   NULL,   G_FILE_TYPE_DIRECTORY,  G_FILE_CREATE_NONE, 0, 0, TEST_COPY     | TEST_COPY_ERROR_RECURSE | TEST_APPEND},
      86                 :            :     {"dir2",                          NULL,   G_FILE_TYPE_DIRECTORY,  G_FILE_CREATE_NONE, 0, 0, TEST_DELETE_NORMAL | TEST_MOVE | TEST_CREATE},
      87                 :            :     {TEST_DIR_TARGET,           NULL,   G_FILE_TYPE_DIRECTORY,  G_FILE_CREATE_NONE, 0, 0, TEST_COPY | TEST_COPY_ERROR_RECURSE},
      88                 :            :     {TEST_DIR_NO_ACCESS,        NULL,   G_FILE_TYPE_DIRECTORY,  G_FILE_CREATE_PRIVATE, S_IRUSR + S_IWUSR + S_IRGRP + S_IWGRP + S_IROTH + S_IWOTH, 0, TEST_NO_ACCESS | TEST_OPEN},
      89                 :            :     {TEST_DIR_NO_WRITE,         NULL,   G_FILE_TYPE_DIRECTORY,  G_FILE_CREATE_PRIVATE, S_IRUSR + S_IXUSR + S_IRGRP + S_IXGRP + S_IROTH + S_IXOTH, 0, 0},
      90                 :            :     {TEST_TARGET_FILE,          NULL,   G_FILE_TYPE_REGULAR,    G_FILE_CREATE_NONE, 0, 0, TEST_COPY | TEST_OPEN},
      91                 :            :         {"normal_file",                       NULL,   G_FILE_TYPE_REGULAR,    G_FILE_CREATE_NONE, 0, 0, TEST_ENUMERATE_FILE | TEST_CREATE | TEST_OVERWRITE},
      92                 :            :         {"normal_file-symlink",       "normal_file",        G_FILE_TYPE_SYMBOLIC_LINK, G_FILE_CREATE_NONE, 0, 0, TEST_ENUMERATE_FILE | TEST_COPY | TEST_OPEN},
      93                 :            :     {"executable_file",               NULL,   G_FILE_TYPE_REGULAR,    G_FILE_CREATE_NONE, S_IRWXU + S_IRWXG + S_IRWXO, 0, TEST_DELETE_TRASH | TEST_COPY | TEST_OPEN | TEST_OVERWRITE | TEST_REPLACE},
      94                 :            :     {"private_file",          NULL,   G_FILE_TYPE_REGULAR,    G_FILE_CREATE_PRIVATE, 0, 0, TEST_COPY | TEST_OPEN | TEST_OVERWRITE | TEST_APPEND},
      95                 :            :     {"normal_file2",          NULL,   G_FILE_TYPE_REGULAR,    G_FILE_CREATE_NONE, 0, 0, TEST_COPY | TEST_OVERWRITE | TEST_REPLACE},
      96                 :            :     {"readonly_file",         NULL,   G_FILE_TYPE_REGULAR,    G_FILE_CREATE_NONE, S_IRUSR + S_IRGRP + S_IROTH, 0, TEST_DELETE_NORMAL | TEST_OPEN},
      97                 :            :     {"UTF_pr\xcc\x8ci\xcc\x81lis\xcc\x8c z",
      98                 :            :                                                 NULL,   G_FILE_TYPE_REGULAR,    G_FILE_CREATE_NONE, 0, 0, TEST_COPY | TEST_CREATE | TEST_OPEN | TEST_OVERWRITE},
      99                 :            :     {"dir_pr\xcc\x8ci\xcc\x81lis\xcc\x8c z",
     100                 :            :                                                 NULL,   G_FILE_TYPE_DIRECTORY,  G_FILE_CREATE_NONE, 0, 0, TEST_DELETE_NORMAL | TEST_CREATE},
     101                 :            :     {"pattern_file",          NULL,   G_FILE_TYPE_REGULAR,    G_FILE_CREATE_NONE, 0, TEST_HANDLE_SPECIAL, TEST_COPY | TEST_OPEN | TEST_APPEND},
     102                 :            :     {TEST_NAME_NOT_EXISTS,      NULL,   G_FILE_TYPE_REGULAR,    G_FILE_CREATE_NONE, 0, TEST_HANDLE_SPECIAL, TEST_DELETE_NORMAL | TEST_NOT_EXISTS | TEST_COPY | TEST_OPEN},
     103                 :            :     {TEST_NAME_NOT_EXISTS,      NULL,   G_FILE_TYPE_REGULAR,    G_FILE_CREATE_NONE, 0, TEST_HANDLE_SPECIAL, TEST_DELETE_TRASH | TEST_NOT_EXISTS | TEST_MOVE},
     104                 :            :     {"not_exists2",                   NULL,   G_FILE_TYPE_REGULAR,    G_FILE_CREATE_NONE, 0, TEST_HANDLE_SPECIAL, TEST_NOT_EXISTS | TEST_CREATE},
     105                 :            :     {"not_exists3",                   NULL,   G_FILE_TYPE_REGULAR,    G_FILE_CREATE_NONE, 0, TEST_HANDLE_SPECIAL, TEST_NOT_EXISTS | TEST_REPLACE},
     106                 :            :     {"not_exists4",                   NULL,   G_FILE_TYPE_REGULAR,    G_FILE_CREATE_NONE, 0, TEST_HANDLE_SPECIAL, TEST_NOT_EXISTS | TEST_APPEND},
     107                 :            :     {"dir_no-execute/file",   NULL,   G_FILE_TYPE_REGULAR,    G_FILE_CREATE_NONE, 0, TEST_HANDLE_SPECIAL, TEST_DELETE_NORMAL | TEST_DELETE_FAILURE | TEST_NOT_EXISTS | TEST_OPEN},
     108                 :            :         {"lost_symlink",              "nowhere",    G_FILE_TYPE_SYMBOLIC_LINK, G_FILE_CREATE_NONE, 0, 0, TEST_COPY | TEST_DELETE_NORMAL | TEST_OPEN | TEST_INVALID_SYMLINK},
     109                 :            :     {"dir_hidden",            NULL,   G_FILE_TYPE_DIRECTORY,  G_FILE_CREATE_NONE, 0, 0, 0},
     110                 :            :     {"dir_hidden/.hidden",            NULL,   G_FILE_TYPE_REGULAR,    G_FILE_CREATE_NONE, 0, TEST_HANDLE_SPECIAL, 0},
     111                 :            :     {"dir_hidden/.a-hidden-file",     NULL,   G_FILE_TYPE_REGULAR,    G_FILE_CREATE_NONE, 0, 0, TEST_HIDDEN},
     112                 :            :     {"dir_hidden/file-in-.hidden1",   NULL,   G_FILE_TYPE_REGULAR,    G_FILE_CREATE_NONE, 0, 0, TEST_HIDDEN | TEST_DOT_HIDDEN},
     113                 :            :     {"dir_hidden/file-in-.hidden2",   NULL,   G_FILE_TYPE_REGULAR,    G_FILE_CREATE_NONE, 0, 0, TEST_HIDDEN | TEST_DOT_HIDDEN},
     114                 :            :   };
     115                 :            : 
     116                 :            : static gboolean test_suite;
     117                 :            : static gboolean write_test;
     118                 :            : static gboolean verbose;
     119                 :            : static gboolean posix_compat;
     120                 :            : 
     121                 :            : #ifdef G_OS_UNIX
     122                 :            : /*
     123                 :            :  * check_cap_dac_override:
     124                 :            :  * @tmpdir: A temporary directory in which we can create and delete files
     125                 :            :  *
     126                 :            :  * Check whether the current process can bypass DAC permissions.
     127                 :            :  *
     128                 :            :  * Traditionally, "privileged" processes (those with effective uid 0)
     129                 :            :  * could do this (and bypass many other checks), and "unprivileged"
     130                 :            :  * processes could not.
     131                 :            :  *
     132                 :            :  * In Linux, the special powers of euid 0 are divided into many
     133                 :            :  * capabilities: see `capabilities(7)`. The one we are interested in
     134                 :            :  * here is `CAP_DAC_OVERRIDE`.
     135                 :            :  *
     136                 :            :  * We do this generically instead of actually looking at the capability
     137                 :            :  * bits, so that the right thing will happen on non-Linux Unix
     138                 :            :  * implementations, in particular if they have something equivalent to
     139                 :            :  * but not identical to Linux permissions.
     140                 :            :  *
     141                 :            :  * Returns: %TRUE if we have Linux `CAP_DAC_OVERRIDE` or equivalent
     142                 :            :  *  privileges
     143                 :            :  */
     144                 :            : static gboolean
     145                 :         73 : check_cap_dac_override (const char *tmpdir)
     146                 :            : {
     147                 :            :   gchar *dac_denies_write;
     148                 :            :   gchar *inside;
     149                 :            :   gboolean have_cap;
     150                 :            : 
     151                 :         73 :   dac_denies_write = g_build_filename (tmpdir, "dac-denies-write", NULL);
     152                 :         73 :   inside = g_build_filename (dac_denies_write, "inside", NULL);
     153                 :            : 
     154                 :         73 :   g_assert_no_errno (mkdir (dac_denies_write, S_IRWXU));
     155                 :         73 :   g_assert_no_errno (chmod (dac_denies_write, 0));
     156                 :            : 
     157         [ -  + ]:         73 :   if (mkdir (inside, S_IRWXU) == 0)
     158                 :            :     {
     159                 :          0 :       g_test_message ("Looks like we have CAP_DAC_OVERRIDE or equivalent");
     160                 :          0 :       g_assert_no_errno (rmdir (inside));
     161                 :          0 :       have_cap = TRUE;
     162                 :            :     }
     163                 :            :   else
     164                 :            :     {
     165                 :         73 :       int saved_errno = errno;
     166                 :            : 
     167                 :         73 :       g_test_message ("We do not have CAP_DAC_OVERRIDE or equivalent");
     168                 :         73 :       g_assert_cmpint (saved_errno, ==, EACCES);
     169                 :         73 :       have_cap = FALSE;
     170                 :            :     }
     171                 :            : 
     172                 :         73 :   g_assert_no_errno (chmod (dac_denies_write, S_IRWXU));
     173                 :         73 :   g_assert_no_errno (rmdir (dac_denies_write));
     174                 :         73 :   g_free (dac_denies_write);
     175                 :         73 :   g_free (inside);
     176                 :         73 :   return have_cap;
     177                 :            : }
     178                 :            : #endif
     179                 :            : 
     180                 :            : static GFile *
     181                 :         10 : create_empty_file (GFile * parent, const char *filename,
     182                 :            :                    GFileCreateFlags create_flags)
     183                 :            : {
     184                 :            :   GFile *child;
     185                 :            :   GError *error;
     186                 :            :   GFileOutputStream *outs;
     187                 :            : 
     188                 :         10 :   child = g_file_get_child (parent, filename);
     189                 :         10 :   g_assert_nonnull (child);
     190                 :            : 
     191                 :         10 :   error = NULL;
     192                 :         10 :   outs = g_file_replace (child, NULL, FALSE, create_flags, NULL, &error);
     193                 :         10 :   g_assert_no_error (error);
     194                 :         10 :   g_assert_nonnull (outs);
     195                 :         10 :   error = NULL;
     196                 :         10 :   g_output_stream_close (G_OUTPUT_STREAM (outs), NULL, &error);
     197                 :         10 :   g_object_unref (outs);
     198                 :         10 :   return child;
     199                 :            : }
     200                 :            : 
     201                 :            : static GFile *
     202                 :          8 : create_empty_dir (GFile * parent, const char *filename)
     203                 :            : {
     204                 :            :   GFile *child;
     205                 :            :   gboolean res;
     206                 :            :   GError *error;
     207                 :            : 
     208                 :          8 :   child = g_file_get_child (parent, filename);
     209                 :          8 :   g_assert_nonnull (child);
     210                 :          8 :   error = NULL;
     211                 :          8 :   res = g_file_make_directory (child, NULL, &error);
     212                 :          8 :   g_assert_true (res);
     213                 :          8 :   g_assert_no_error (error);
     214                 :          8 :   return child;
     215                 :            : }
     216                 :            : 
     217                 :            : static GFile *
     218                 :          2 : create_symlink (GFile * parent, const char *filename, const char *points_to)
     219                 :            : {
     220                 :            :   GFile *child;
     221                 :            :   gboolean res;
     222                 :            :   GError *error;
     223                 :            : 
     224                 :          2 :   child = g_file_get_child (parent, filename);
     225                 :          2 :   g_assert_nonnull (child);
     226                 :          2 :   error = NULL;
     227                 :          2 :   res = g_file_make_symbolic_link (child, points_to, NULL, &error);
     228                 :          2 :   g_assert_true (res);
     229                 :          2 :   g_assert_no_error (error);
     230                 :          2 :   return child;
     231                 :            : }
     232                 :            : 
     233                 :            : static void
     234                 :          1 : test_create_structure (gconstpointer test_data)
     235                 :            : {
     236                 :            :   GFile *root;
     237                 :            :   GFile *child;
     238                 :            :   gboolean res;
     239                 :          1 :   GError *error = NULL;
     240                 :            :   GFileOutputStream *outs;
     241                 :            :   GDataOutputStream *outds;
     242                 :            :   guint i;
     243                 :            :   struct StructureItem item;
     244                 :            : 
     245                 :          1 :   g_assert_nonnull (test_data);
     246                 :          1 :   g_test_message ("\n  Going to create testing structure in '%s'...",
     247                 :            :                   (char *) test_data);
     248                 :            : 
     249                 :          1 :   root = g_file_new_for_commandline_arg ((char *) test_data);
     250                 :          1 :   g_assert_nonnull (root);
     251                 :            : 
     252                 :            :   /*  create root directory  */
     253                 :          1 :   g_file_make_directory (root, NULL, &error);
     254                 :          1 :   g_assert_no_error (error);
     255                 :            : 
     256                 :            :   /*  create any other items  */
     257         [ +  + ]:         29 :   for (i = 0; i < G_N_ELEMENTS (sample_struct); i++)
     258                 :            :     {
     259                 :         28 :       item = sample_struct[i];
     260         [ +  + ]:         28 :       if ((item.handle_special)
     261         [ -  + ]:         20 :           || ((!posix_compat)
     262         [ #  # ]:          0 :               && (item.file_type == G_FILE_TYPE_SYMBOLIC_LINK)))
     263                 :          8 :         continue;
     264                 :            : 
     265                 :         20 :       child = NULL;
     266   [ +  +  +  - ]:         20 :       switch (item.file_type)
     267                 :            :         {
     268                 :         10 :         case G_FILE_TYPE_REGULAR:
     269                 :         10 :           g_test_message ("    Creating file '%s'...", item.filename);
     270                 :         10 :           child = create_empty_file (root, item.filename, item.create_flags);
     271                 :         10 :           break;
     272                 :          8 :         case G_FILE_TYPE_DIRECTORY:
     273                 :          8 :           g_test_message ("    Creating directory '%s'...", item.filename);
     274                 :          8 :           child = create_empty_dir (root, item.filename);
     275                 :          8 :           break;
     276                 :          2 :         case G_FILE_TYPE_SYMBOLIC_LINK:
     277                 :          2 :           g_test_message ("    Creating symlink '%s' --> '%s'...", item.filename,
     278                 :            :                           item.link_to);
     279                 :          2 :           child = create_symlink (root, item.filename, item.link_to);
     280                 :          2 :           break;
     281                 :          0 :         case G_FILE_TYPE_UNKNOWN:
     282                 :            :         case G_FILE_TYPE_SPECIAL:
     283                 :            :         case G_FILE_TYPE_SHORTCUT:
     284                 :            :         case G_FILE_TYPE_MOUNTABLE:
     285                 :            :         default:
     286                 :          0 :           break;
     287                 :            :         }
     288                 :         20 :       g_assert_nonnull (child);
     289                 :            : 
     290   [ +  +  +  - ]:         20 :       if ((item.mode > 0) && (posix_compat))
     291                 :            :         {
     292                 :            :           res =
     293                 :          4 :             g_file_set_attribute_uint32 (child, G_FILE_ATTRIBUTE_UNIX_MODE,
     294                 :            :                                          item.mode,
     295                 :            :                                          G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
     296                 :            :                                          NULL, &error);
     297                 :          4 :           g_assert_true (res);
     298                 :          4 :           g_assert_no_error (error);
     299                 :            :         }
     300                 :            : 
     301         [ +  + ]:         20 :       if ((item.extra_flags & TEST_DOT_HIDDEN) == TEST_DOT_HIDDEN)
     302                 :            :         {
     303                 :            :           gchar *dir, *path, *basename;
     304                 :            :           FILE *f;
     305                 :            : 
     306                 :          2 :           dir = g_path_get_dirname (item.filename);
     307                 :          2 :           basename = g_path_get_basename (item.filename);
     308                 :          2 :           path = g_build_filename (test_data, dir, ".hidden", NULL);
     309                 :            : 
     310                 :          2 :           f = fopen (path, "a");
     311                 :          2 :           fprintf (f, "%s\n", basename);
     312                 :          2 :           fclose (f);
     313                 :            : 
     314                 :          2 :           g_free (dir);
     315                 :          2 :           g_free (path);
     316                 :          2 :           g_free (basename);
     317                 :            :         }
     318                 :            : 
     319                 :         20 :       g_object_unref (child);
     320                 :            :     }
     321                 :            : 
     322                 :            :   /*  create a pattern file  */
     323                 :          1 :   g_test_message ("    Creating pattern file...");
     324                 :          1 :   child = g_file_get_child (root, "pattern_file");
     325                 :          1 :   g_assert_nonnull (child);
     326                 :            : 
     327                 :            :   outs =
     328                 :          1 :     g_file_replace (child, NULL, FALSE, G_FILE_CREATE_NONE, NULL, &error);
     329                 :          1 :   g_assert_no_error (error);
     330                 :            : 
     331                 :          1 :   g_assert_nonnull (outs);
     332                 :          1 :   outds = g_data_output_stream_new (G_OUTPUT_STREAM (outs));
     333                 :          1 :   g_assert_nonnull (outds);
     334         [ +  + ]:      65537 :   for (i = 0; i < PATTERN_FILE_SIZE; i++)
     335                 :            :     {
     336                 :      65536 :       g_data_output_stream_put_byte (outds, i % 256, NULL, &error);
     337                 :      65536 :       g_assert_no_error (error);
     338                 :            :     }
     339                 :            : 
     340                 :          1 :   g_output_stream_close (G_OUTPUT_STREAM (outs), NULL, &error);
     341                 :          1 :   g_assert_no_error (error);
     342                 :          1 :   g_object_unref (outds);
     343                 :          1 :   g_object_unref (outs);
     344                 :          1 :   g_object_unref (child);
     345                 :          1 :   g_test_message (" done.");
     346                 :            : 
     347                 :          1 :   g_object_unref (root);
     348                 :          1 : }
     349                 :            : 
     350                 :            : static GFile *
     351                 :         30 : file_exists (GFile * parent, const char *filename, gboolean * result)
     352                 :            : {
     353                 :            :   GFile *child;
     354                 :            :   gboolean res;
     355                 :            : 
     356         [ +  - ]:         30 :   if (result)
     357                 :         30 :     *result = FALSE;
     358                 :            : 
     359                 :         30 :   child = g_file_get_child (parent, filename);
     360                 :         30 :   g_assert_nonnull (child);
     361                 :         30 :   res = g_file_query_exists (child, NULL);
     362         [ +  - ]:         30 :   if (result)
     363                 :         30 :     *result = res;
     364                 :            : 
     365                 :         30 :   return child;
     366                 :            : }
     367                 :            : 
     368                 :            : static void
     369                 :         42 : test_attributes (struct StructureItem item, GFileInfo * info)
     370                 :            : {
     371                 :            :   GFileType ftype;
     372                 :            :   guint32 mode;
     373                 :            :   const char *name, *display_name, *edit_name, *copy_name, *symlink_target;
     374                 :            :   gboolean utf8_valid;
     375                 :            :   gboolean has_attr;
     376                 :            :   gboolean is_symlink;
     377                 :            :   gboolean is_hidden;
     378                 :            :   gboolean can_read, can_write;
     379                 :            : 
     380                 :            :   /*  standard::type  */
     381                 :         42 :   has_attr = g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_STANDARD_TYPE);
     382                 :         42 :   g_assert_true (has_attr);
     383                 :         42 :   ftype = g_file_info_get_file_type (info);
     384                 :         42 :   g_assert_cmpint (ftype, !=, G_FILE_TYPE_UNKNOWN);
     385                 :         42 :   g_assert_cmpint (ftype, ==, item.file_type);
     386                 :            : 
     387                 :            :   /*  unix::mode  */
     388   [ +  +  +  - ]:         42 :   if ((item.mode > 0) && (posix_compat))
     389                 :            :     {
     390                 :          8 :       mode =
     391                 :          8 :         g_file_info_get_attribute_uint32 (info,
     392                 :            :                                           G_FILE_ATTRIBUTE_UNIX_MODE) & 0xFFF;
     393                 :          8 :       g_assert_cmpint (mode, ==, item.mode);
     394                 :            :     }
     395                 :            : 
     396                 :            :   /*  access::can-read  */
     397         [ +  + ]:         42 :   if (item.file_type != G_FILE_TYPE_SYMBOLIC_LINK)
     398                 :            :     {
     399                 :            :       can_read =
     400                 :         38 :         g_file_info_get_attribute_boolean (info,
     401                 :            :                                            G_FILE_ATTRIBUTE_ACCESS_CAN_READ);
     402                 :         38 :       g_assert_true (can_read);
     403                 :            :     }
     404                 :            : 
     405                 :            :   /*  access::can-write  */
     406   [ +  -  +  + ]:         42 :   if ((write_test) && ((item.extra_flags & TEST_OVERWRITE) == TEST_OVERWRITE))
     407                 :            :     {
     408                 :            :       can_write =
     409                 :         10 :         g_file_info_get_attribute_boolean (info,
     410                 :            :                                            G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE);
     411                 :         10 :       g_assert_true (can_write);
     412                 :            :     }
     413                 :            : 
     414                 :            :   /*  standard::name  */
     415                 :         42 :   name = g_file_info_get_name (info);
     416                 :         42 :   g_assert_nonnull (name);
     417                 :            : 
     418                 :            :   /*  standard::display-name  */
     419                 :         42 :   display_name = g_file_info_get_display_name (info);
     420                 :         42 :   g_assert_nonnull (display_name);
     421                 :         42 :   utf8_valid = g_utf8_validate (display_name, -1, NULL);
     422                 :         42 :   g_assert_true (utf8_valid);
     423                 :            : 
     424                 :            :   /*  standard::edit-name  */
     425                 :         42 :   edit_name = g_file_info_get_edit_name (info);
     426         [ +  - ]:         42 :   if (edit_name)
     427                 :            :     {
     428                 :         42 :       utf8_valid = g_utf8_validate (edit_name, -1, NULL);
     429                 :         42 :       g_assert_true (utf8_valid);
     430                 :            :     }
     431                 :            : 
     432                 :            :   /*  standard::copy-name  */
     433                 :            :   copy_name =
     434                 :         42 :     g_file_info_get_attribute_string (info,
     435                 :            :                                       G_FILE_ATTRIBUTE_STANDARD_COPY_NAME);
     436         [ +  - ]:         42 :   if (copy_name)
     437                 :            :     {
     438                 :         42 :       utf8_valid = g_utf8_validate (copy_name, -1, NULL);
     439                 :         42 :       g_assert_true (utf8_valid);
     440                 :            :     }
     441                 :            : 
     442                 :            :   /*  standard::is-symlink  */
     443         [ +  - ]:         42 :   if (posix_compat)
     444                 :            :     {
     445                 :         42 :       is_symlink = g_file_info_get_is_symlink (info);
     446                 :         42 :       g_assert_cmpint (is_symlink, ==,
     447                 :            :                        item.file_type == G_FILE_TYPE_SYMBOLIC_LINK);
     448                 :            :     }
     449                 :            : 
     450                 :            :   /*  standard::symlink-target  */
     451   [ +  +  +  - ]:         42 :   if ((item.file_type == G_FILE_TYPE_SYMBOLIC_LINK) && (posix_compat))
     452                 :            :     {
     453                 :          4 :       symlink_target = g_file_info_get_symlink_target (info);
     454                 :          4 :       g_assert_cmpstr (symlink_target, ==, item.link_to);
     455                 :            :     }
     456                 :            : 
     457                 :            :   /*  standard::is-hidden  */
     458         [ +  + ]:         42 :   if ((item.extra_flags & TEST_HIDDEN) == TEST_HIDDEN)
     459                 :            :     {
     460                 :            :       is_hidden =
     461                 :          6 :         g_file_info_get_attribute_boolean (info,
     462                 :            :                                            G_FILE_ATTRIBUTE_STANDARD_IS_HIDDEN);
     463                 :          6 :       g_assert_true (is_hidden);
     464                 :            :     }
     465                 :            : 
     466                 :            :   /* unix::is-mountpoint */
     467         [ +  - ]:         42 :   if (posix_compat)
     468                 :            :     {
     469                 :            :       gboolean is_mountpoint =
     470                 :         42 :         g_file_info_get_attribute_boolean (info,
     471                 :            :                                       G_FILE_ATTRIBUTE_UNIX_IS_MOUNTPOINT);
     472                 :         42 :       g_assert_false (is_mountpoint);
     473                 :            :     }
     474                 :         42 : }
     475                 :            : 
     476                 :            : static void
     477                 :          1 : test_initial_structure (gconstpointer test_data)
     478                 :            : {
     479                 :            :   GFile *root;
     480                 :            :   GFile *child;
     481                 :            :   gboolean res;
     482                 :            :   GError *error;
     483                 :            :   GFileInputStream *ins;
     484                 :            :   guint i;
     485                 :            :   GFileInfo *info;
     486                 :            :   guint32 size;
     487                 :            :   guchar *buffer;
     488                 :            :   gssize read, total_read;
     489                 :            :   struct StructureItem item;
     490                 :            : 
     491                 :          1 :   g_assert_nonnull (test_data);
     492                 :          1 :   g_test_message ("  Testing sample structure in '%s'...", (char *) test_data);
     493                 :            : 
     494                 :          1 :   root = g_file_new_for_commandline_arg ((char *) test_data);
     495                 :          1 :   g_assert_nonnull (root);
     496                 :          1 :   res = g_file_query_exists (root, NULL);
     497                 :          1 :   g_assert_true (res);
     498                 :            : 
     499                 :            :   /*  test the structure  */
     500         [ +  + ]:         29 :   for (i = 0; i < G_N_ELEMENTS (sample_struct); i++)
     501                 :            :     {
     502                 :         28 :       item = sample_struct[i];
     503   [ -  +  -  - ]:         28 :       if (((!posix_compat) && (item.file_type == G_FILE_TYPE_SYMBOLIC_LINK))
     504         [ +  + ]:         28 :           || (item.handle_special))
     505                 :          8 :         continue;
     506                 :            : 
     507                 :         20 :       g_test_message ("    Testing file '%s'...", item.filename);
     508                 :            : 
     509                 :         20 :       child = file_exists (root, item.filename, &res);
     510                 :         20 :       g_assert_nonnull (child);
     511                 :         20 :       g_assert_true (res);
     512                 :            : 
     513                 :         20 :       error = NULL;
     514                 :            :       info =
     515                 :         20 :         g_file_query_info (child, "*", G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
     516                 :            :                            NULL, &error);
     517                 :         20 :       g_assert_no_error (error);
     518                 :         20 :       g_assert_nonnull (info);
     519                 :            : 
     520                 :         20 :       test_attributes (item, info);
     521                 :            : 
     522                 :         20 :       g_object_unref (child);
     523                 :         20 :       g_object_unref (info);
     524                 :            :     }
     525                 :            : 
     526                 :            :   /*  read and test the pattern file  */
     527                 :          1 :   g_test_message ("    Testing pattern file...");
     528                 :          1 :   child = file_exists (root, "pattern_file", &res);
     529                 :          1 :   g_assert_nonnull (child);
     530                 :          1 :   g_assert_true (res);
     531                 :            : 
     532                 :          1 :   error = NULL;
     533                 :            :   info =
     534                 :          1 :     g_file_query_info (child, "*", G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, NULL,
     535                 :            :                        &error);
     536                 :          1 :   g_assert_no_error (error);
     537                 :          1 :   g_assert_nonnull (info);
     538                 :          1 :   size = g_file_info_get_size (info);
     539                 :          1 :   g_assert_cmpint (size, ==, PATTERN_FILE_SIZE);
     540                 :          1 :   g_object_unref (info);
     541                 :            : 
     542                 :          1 :   error = NULL;
     543                 :          1 :   ins = g_file_read (child, NULL, &error);
     544                 :          1 :   g_assert_nonnull (ins);
     545                 :          1 :   g_assert_no_error (error);
     546                 :            : 
     547                 :          1 :   buffer = g_malloc (PATTERN_FILE_SIZE);
     548                 :          1 :   total_read = 0;
     549                 :            : 
     550         [ +  + ]:          2 :   while (total_read < PATTERN_FILE_SIZE)
     551                 :            :     {
     552                 :          1 :       error = NULL;
     553                 :            :       read =
     554                 :          1 :         g_input_stream_read (G_INPUT_STREAM (ins), buffer + total_read,
     555                 :            :                              PATTERN_FILE_SIZE, NULL, &error);
     556                 :          1 :       g_assert_no_error (error);
     557                 :          1 :       total_read += read;
     558                 :          1 :       g_test_message ("      read %"G_GSSIZE_FORMAT" bytes, total = %"G_GSSIZE_FORMAT" of %d.",
     559                 :            :                       read, total_read, PATTERN_FILE_SIZE);
     560                 :            :     }
     561                 :          1 :   g_assert_cmpint (total_read, ==, PATTERN_FILE_SIZE);
     562                 :            : 
     563                 :          1 :   error = NULL;
     564                 :          1 :   res = g_input_stream_close (G_INPUT_STREAM (ins), NULL, &error);
     565                 :          1 :   g_assert_no_error (error);
     566                 :          1 :   g_assert_true (res);
     567                 :            : 
     568         [ +  + ]:      65537 :   for (i = 0; i < PATTERN_FILE_SIZE; i++)
     569                 :      65536 :     g_assert_cmpint (*(buffer + i), ==, i % 256);
     570                 :            : 
     571                 :          1 :   g_object_unref (ins);
     572                 :          1 :   g_object_unref (child);
     573                 :          1 :   g_free (buffer);
     574                 :          1 :   g_object_unref (root);
     575                 :          1 : }
     576                 :            : 
     577                 :            : static void
     578                 :          9 : traverse_recurse_dirs (GFile * parent, GFile * root)
     579                 :            : {
     580                 :            :   gboolean res;
     581                 :            :   GError *error;
     582                 :            :   GFileEnumerator *enumerator;
     583                 :            :   GFileInfo *info;
     584                 :            :   GFile *descend;
     585                 :            :   char *relative_path;
     586                 :            :   guint i;
     587                 :            :   gboolean found;
     588                 :            : 
     589                 :          9 :   g_assert_nonnull (root);
     590                 :            : 
     591                 :          9 :   error = NULL;
     592                 :            :   enumerator =
     593                 :          9 :     g_file_enumerate_children (parent, "*",
     594                 :            :                                G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, NULL,
     595                 :            :                                &error);
     596                 :          9 :   g_assert_nonnull (enumerator);
     597                 :          9 :   g_assert_no_error (error);
     598                 :            : 
     599                 :          9 :   g_assert_true (g_file_enumerator_get_container (enumerator) == parent);
     600                 :            : 
     601                 :          9 :   error = NULL;
     602                 :          9 :   info = g_file_enumerator_next_file (enumerator, NULL, &error);
     603   [ +  +  +  - ]:         31 :   while ((info) && (!error))
     604                 :            :     {
     605                 :         22 :       descend = g_file_enumerator_get_child (enumerator, info);
     606                 :         22 :       g_assert_nonnull (descend);
     607                 :         22 :       relative_path = g_file_get_relative_path (root, descend);
     608                 :         22 :       g_assert_nonnull (relative_path);
     609                 :            : 
     610                 :         22 :       found = FALSE;
     611         [ +  - ]:        289 :       for (i = 0; i < G_N_ELEMENTS (sample_struct); i++)
     612                 :            :         {
     613         [ +  + ]:        289 :           if (strcmp (sample_struct[i].filename, relative_path) == 0)
     614                 :            :             {
     615                 :            :               /*  test the attributes again  */
     616                 :         22 :               test_attributes (sample_struct[i], info);
     617                 :            : 
     618                 :         22 :               found = TRUE;
     619                 :         22 :               break;
     620                 :            :             }
     621                 :            :         }
     622                 :         22 :       g_assert_true (found);
     623                 :            : 
     624                 :         22 :       g_test_message ("  Found file %s, relative to root: %s",
     625                 :            :                       g_file_info_get_display_name (info), relative_path);
     626                 :            : 
     627         [ +  + ]:         22 :       if (g_file_info_get_file_type (info) == G_FILE_TYPE_DIRECTORY)
     628                 :          8 :         traverse_recurse_dirs (descend, root);
     629                 :            : 
     630                 :         22 :       g_object_unref (descend);
     631                 :         22 :       error = NULL;
     632                 :         22 :       g_object_unref (info);
     633                 :         22 :       g_free (relative_path);
     634                 :            : 
     635                 :         22 :       info = g_file_enumerator_next_file (enumerator, NULL, &error);
     636                 :            :     }
     637                 :          9 :   g_assert_no_error (error);
     638                 :            : 
     639                 :          9 :   error = NULL;
     640                 :          9 :   res = g_file_enumerator_close (enumerator, NULL, &error);
     641                 :          9 :   g_assert_true (res);
     642                 :          9 :   g_assert_no_error (error);
     643                 :          9 :   g_assert_true (g_file_enumerator_is_closed (enumerator));
     644                 :            : 
     645                 :          9 :   g_object_unref (enumerator);
     646                 :          9 : }
     647                 :            : 
     648                 :            : static void
     649                 :          1 : test_traverse_structure (gconstpointer test_data)
     650                 :            : {
     651                 :            :   GFile *root;
     652                 :            :   gboolean res;
     653                 :            : 
     654                 :          1 :   g_assert_nonnull (test_data);
     655                 :          1 :   g_test_message ("  Traversing through the sample structure in '%s'...",
     656                 :            :                   (char *) test_data);
     657                 :            : 
     658                 :          1 :   root = g_file_new_for_commandline_arg ((char *) test_data);
     659                 :          1 :   g_assert_nonnull (root);
     660                 :          1 :   res = g_file_query_exists (root, NULL);
     661                 :          1 :   g_assert_true (res);
     662                 :            : 
     663                 :          1 :   traverse_recurse_dirs (root, root);
     664                 :            : 
     665                 :          1 :   g_object_unref (root);
     666                 :          1 : }
     667                 :            : 
     668                 :            : 
     669                 :            : 
     670                 :            : 
     671                 :            : static void
     672                 :          1 : test_enumerate (gconstpointer test_data)
     673                 :            : {
     674                 :            :   GFile *root, *child;
     675                 :            :   gboolean res;
     676                 :            :   GError *error;
     677                 :            :   GFileEnumerator *enumerator;
     678                 :            :   GFileInfo *info;
     679                 :            :   guint i;
     680                 :            :   struct StructureItem item;
     681                 :            : 
     682                 :            : 
     683                 :          1 :   g_assert_nonnull (test_data);
     684                 :          1 :   g_test_message ("  Test enumerate '%s'...", (char *) test_data);
     685                 :            : 
     686                 :          1 :   root = g_file_new_for_commandline_arg ((char *) test_data);
     687                 :          1 :   g_assert_nonnull (root);
     688                 :          1 :   res = g_file_query_exists (root, NULL);
     689                 :          1 :   g_assert_true (res);
     690                 :            : 
     691                 :            : 
     692         [ +  + ]:         29 :   for (i = 0; i < G_N_ELEMENTS (sample_struct); i++)
     693                 :            :     {
     694                 :         28 :       item = sample_struct[i];
     695   [ -  +  -  - ]:         28 :       if ((!posix_compat) && (item.file_type == G_FILE_TYPE_SYMBOLIC_LINK))
     696                 :          0 :         continue;
     697                 :            : 
     698         [ +  + ]:         28 :       if (((item.extra_flags & TEST_NOT_EXISTS) == TEST_NOT_EXISTS) ||
     699         [ +  + ]:         22 :           (((item.extra_flags & TEST_NO_ACCESS) == TEST_NO_ACCESS)
     700         [ -  + ]:          1 :            && posix_compat)
     701         [ +  + ]:         21 :           || ((item.extra_flags & TEST_ENUMERATE_FILE) ==
     702                 :            :               TEST_ENUMERATE_FILE))
     703                 :            :         {
     704                 :          9 :           g_test_message ("    Testing file '%s'", item.filename);
     705                 :          9 :           child = g_file_get_child (root, item.filename);
     706                 :          9 :           g_assert_nonnull (child);
     707                 :          9 :           error = NULL;
     708                 :            :           enumerator =
     709                 :          9 :             g_file_enumerate_children (child, "*",
     710                 :            :                                        G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
     711                 :            :                                        NULL, &error);
     712                 :            : 
     713         [ +  + ]:          9 :           if ((item.extra_flags & TEST_NOT_EXISTS) == TEST_NOT_EXISTS)
     714                 :            :             {
     715                 :          6 :               g_assert_null (enumerator);
     716                 :          6 :               g_assert_error (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND);
     717                 :            :             }
     718         [ +  + ]:          9 :           if ((item.extra_flags & TEST_ENUMERATE_FILE) == TEST_ENUMERATE_FILE)
     719                 :            :             {
     720                 :          2 :               g_assert_null (enumerator);
     721                 :          2 :               g_assert_error (error, G_IO_ERROR, G_IO_ERROR_NOT_DIRECTORY);
     722                 :            :             }
     723         [ +  + ]:          9 :           if ((item.extra_flags & TEST_NO_ACCESS) == TEST_NO_ACCESS)
     724                 :            :             {
     725                 :          1 :               g_assert_nonnull (enumerator);
     726                 :            : 
     727                 :          1 :               error = NULL;
     728                 :          1 :               info = g_file_enumerator_next_file (enumerator, NULL, &error);
     729                 :          1 :               g_assert_null (info);
     730                 :          1 :               g_assert_no_error (error);
     731                 :            :               /*  no items should be found, no error should be logged  */
     732                 :            :             }
     733                 :            : 
     734         [ +  + ]:          9 :           if (error)
     735                 :          8 :             g_error_free (error);
     736                 :            : 
     737         [ +  + ]:          9 :           if (enumerator)
     738                 :            :             {
     739                 :          1 :               error = NULL;
     740                 :          1 :               res = g_file_enumerator_close (enumerator, NULL, &error);
     741                 :          1 :               g_assert_true (res);
     742                 :          1 :               g_assert_no_error (error);
     743                 :            : 
     744                 :          1 :               g_object_unref (enumerator);
     745                 :            :             }
     746                 :          9 :           g_object_unref (child);
     747                 :            :         }
     748                 :            :     }
     749                 :          1 :   g_object_unref (root);
     750                 :          1 : }
     751                 :            : 
     752                 :            : static void
     753                 :         72 : do_copy_move (GFile * root, struct StructureItem item, const char *target_dir,
     754                 :            :               enum StructureExtraFlags extra_flags)
     755                 :            : {
     756                 :            :   GFile *dst_dir, *src_file, *dst_file;
     757                 :            :   gboolean res;
     758                 :            :   GError *error;
     759                 :            : #ifdef G_OS_UNIX
     760                 :         72 :   gboolean have_cap_dac_override = check_cap_dac_override (g_file_peek_path (root));
     761                 :            : #endif
     762                 :            : 
     763                 :         72 :   g_test_message ("    do_copy_move: '%s' --> '%s'", item.filename, target_dir);
     764                 :            : 
     765                 :         72 :   dst_dir = g_file_get_child (root, target_dir);
     766                 :         72 :   g_assert_nonnull (dst_dir);
     767                 :         72 :   src_file = g_file_get_child (root, item.filename);
     768                 :         72 :   g_assert_nonnull (src_file);
     769                 :         72 :   dst_file = g_file_get_child (dst_dir, item.filename);
     770                 :         72 :   g_assert_nonnull (dst_file);
     771                 :            : 
     772                 :         72 :   error = NULL;
     773         [ +  + ]:         72 :   if ((item.extra_flags & TEST_COPY) == TEST_COPY)
     774                 :            :     res =
     775         [ +  + ]:         70 :       g_file_copy (src_file, dst_file,
     776                 :            :                    G_FILE_COPY_NOFOLLOW_SYMLINKS |
     777                 :            :                    ((extra_flags ==
     778                 :            :                      TEST_OVERWRITE) ? G_FILE_COPY_OVERWRITE :
     779                 :            :                     G_FILE_COPY_NONE), NULL, NULL, NULL, &error);
     780                 :            :   else
     781                 :            :     res =
     782                 :          2 :       g_file_move (src_file, dst_file, G_FILE_COPY_NOFOLLOW_SYMLINKS, NULL,
     783                 :            :                    NULL, NULL, &error);
     784                 :            : 
     785         [ +  + ]:         72 :   if (error)
     786                 :         59 :     g_test_message ("       res = %d, error code %d = %s", res, error->code,
     787                 :         59 :                     error->message);
     788                 :            : 
     789                 :            :   /*  copying file/directory to itself (".")  */
     790   [ +  +  +  + ]:         72 :   if (((item.extra_flags & TEST_NOT_EXISTS) != TEST_NOT_EXISTS) &&
     791                 :            :       (extra_flags == TEST_ALREADY_EXISTS))
     792                 :            :     {
     793                 :         10 :       g_assert_false (res);
     794                 :         10 :       g_assert_error (error, G_IO_ERROR, G_IO_ERROR_EXISTS);
     795                 :            :     }
     796                 :            :   /*  target file is a file, overwrite is not set  */
     797   [ +  +  +  + ]:         62 :   else if (((item.extra_flags & TEST_NOT_EXISTS) != TEST_NOT_EXISTS) &&
     798                 :            :            (extra_flags == TEST_TARGET_IS_FILE))
     799                 :            :     {
     800                 :         10 :       g_assert_false (res);
     801                 :         10 :       g_assert_error (error, G_IO_ERROR, G_IO_ERROR_NOT_DIRECTORY);
     802                 :            :     }
     803                 :            :   /*  source file is directory  */
     804         [ +  + ]:         52 :   else if ((item.extra_flags & TEST_COPY_ERROR_RECURSE) ==
     805                 :            :            TEST_COPY_ERROR_RECURSE)
     806                 :            :     {
     807                 :          8 :       g_assert_false (res);
     808                 :          8 :       g_assert_error (error, G_IO_ERROR, G_IO_ERROR_WOULD_RECURSE);
     809                 :            :     }
     810                 :            :   /*  source or target path doesn't exist  */
     811   [ +  +  +  + ]:         44 :   else if (((item.extra_flags & TEST_NOT_EXISTS) == TEST_NOT_EXISTS) ||
     812                 :            :            (extra_flags == TEST_NOT_EXISTS))
     813                 :            :     {
     814                 :         15 :       g_assert_false (res);
     815                 :         15 :       g_assert_error (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND);
     816                 :            :     }
     817                 :            :   /*  source or target path permission denied  */
     818   [ +  -  +  + ]:         29 :   else if (((item.extra_flags & TEST_NO_ACCESS) == TEST_NO_ACCESS) ||
     819                 :            :            (extra_flags == TEST_NO_ACCESS))
     820                 :            :     {
     821                 :            :       /* This works for root, see bug #552912 */
     822                 :            : #ifdef G_OS_UNIX
     823         [ -  + ]:         16 :       if (have_cap_dac_override)
     824                 :            :         {
     825                 :          0 :           g_test_message ("Unable to exercise g_file_copy() or g_file_move() "
     826                 :            :                           "failing with EACCES: we probably have "
     827                 :            :                           "CAP_DAC_OVERRIDE");
     828                 :          0 :           g_assert_true (res);
     829                 :          0 :           g_assert_no_error (error);
     830                 :            :         }
     831                 :            :       else
     832                 :            : #endif
     833                 :            :         {
     834                 :         16 :           g_assert_false (res);
     835                 :         16 :           g_assert_error (error, G_IO_ERROR, G_IO_ERROR_PERMISSION_DENIED);
     836                 :            :         }
     837                 :            :     }
     838                 :            :   /*  no error should be found, all exceptions defined above  */
     839                 :            :   else
     840                 :            :     {
     841                 :         13 :       g_assert_true (res);
     842                 :         13 :       g_assert_no_error (error);
     843                 :            :     }
     844                 :            : 
     845         [ +  + ]:         72 :   if (error)
     846                 :         59 :     g_error_free (error);
     847                 :            : 
     848                 :            : 
     849                 :         72 :   g_object_unref (dst_dir);
     850                 :         72 :   g_object_unref (src_file);
     851                 :         72 :   g_object_unref (dst_file);
     852                 :         72 : }
     853                 :            : 
     854                 :            : static void
     855                 :          1 : test_copy_move (gconstpointer test_data)
     856                 :            : {
     857                 :            :   GFile *root;
     858                 :            :   gboolean res;
     859                 :            :   guint i;
     860                 :            :   struct StructureItem item;
     861                 :            : 
     862                 :          1 :   g_assert_nonnull (test_data);
     863                 :          1 :   root = g_file_new_for_commandline_arg ((char *) test_data);
     864                 :          1 :   g_assert_nonnull (root);
     865                 :          1 :   res = g_file_query_exists (root, NULL);
     866                 :          1 :   g_assert_true (res);
     867                 :            : 
     868                 :            : 
     869         [ +  + ]:         29 :   for (i = 0; i < G_N_ELEMENTS (sample_struct); i++)
     870                 :            :     {
     871                 :         28 :       item = sample_struct[i];
     872                 :            : 
     873   [ -  +  -  - ]:         28 :       if ((!posix_compat) && (item.file_type == G_FILE_TYPE_SYMBOLIC_LINK))
     874                 :          0 :         continue;
     875                 :            : 
     876         [ +  + ]:         28 :       if (((item.extra_flags & TEST_COPY) == TEST_COPY) ||
     877         [ +  + ]:         17 :           ((item.extra_flags & TEST_MOVE) == TEST_MOVE))
     878                 :            :         {
     879                 :            :           /*  test copy/move to a directory, expecting no errors if source files exist  */
     880                 :         13 :           do_copy_move (root, item, TEST_DIR_TARGET, 0);
     881                 :            : 
     882                 :            :           /*  some files have been already moved so we can't count with them in the tests  */
     883         [ +  + ]:         13 :           if ((item.extra_flags & TEST_COPY) == TEST_COPY)
     884                 :            :             {
     885                 :            :               /*  test overwrite for flagged files  */
     886         [ +  + ]:         11 :               if ((item.extra_flags & TEST_OVERWRITE) == TEST_OVERWRITE)
     887                 :            :                 {
     888                 :          4 :                   do_copy_move (root, item, TEST_DIR_TARGET, TEST_OVERWRITE);
     889                 :            :                 }
     890                 :            :               /*  source = target, should return G_IO_ERROR_EXISTS  */
     891                 :         11 :               do_copy_move (root, item, ".", TEST_ALREADY_EXISTS);
     892                 :            :               /*  target is file  */
     893                 :         11 :               do_copy_move (root, item, TEST_TARGET_FILE,
     894                 :            :                             TEST_TARGET_IS_FILE);
     895                 :            :               /*  target path is invalid  */
     896                 :         11 :               do_copy_move (root, item, TEST_NAME_NOT_EXISTS,
     897                 :            :                             TEST_NOT_EXISTS);
     898                 :            : 
     899                 :            :               /*  tests on POSIX-compatible filesystems  */
     900         [ +  - ]:         11 :               if (posix_compat)
     901                 :            :                 {
     902                 :            :                   /*  target directory is not accessible (no execute flag)  */
     903                 :         11 :                   do_copy_move (root, item, TEST_DIR_NO_ACCESS,
     904                 :            :                                 TEST_NO_ACCESS);
     905                 :            :                   /*  target directory is readonly  */
     906                 :         11 :                   do_copy_move (root, item, TEST_DIR_NO_WRITE,
     907                 :            :                                 TEST_NO_ACCESS);
     908                 :            :                 }
     909                 :            :             }
     910                 :            :         }
     911                 :            :     }
     912                 :          1 :   g_object_unref (root);
     913                 :          1 : }
     914                 :            : 
     915                 :            : /* Test that G_FILE_ATTRIBUTE_UNIX_IS_MOUNTPOINT is TRUE for / and for another
     916                 :            :  * known mountpoint. The FALSE case is tested for many directories and files by
     917                 :            :  * test_initial_structure(), via test_attributes().
     918                 :            :  */
     919                 :            : static void
     920                 :          2 : test_unix_is_mountpoint (gconstpointer data)
     921                 :            : {
     922                 :          2 :   const gchar *path = data;
     923                 :          2 :   GFile *file = g_file_new_for_path (path);
     924                 :            :   GFileInfo *info;
     925                 :            :   gboolean is_mountpoint;
     926                 :          2 :   GError *error = NULL;
     927                 :            : 
     928                 :          2 :   info = g_file_query_info (file, G_FILE_ATTRIBUTE_UNIX_IS_MOUNTPOINT,
     929                 :            :                             G_FILE_QUERY_INFO_NONE, NULL, &error);
     930                 :          2 :   g_assert_no_error (error);
     931                 :          2 :   g_assert_nonnull (info);
     932                 :            : 
     933                 :            :   is_mountpoint =
     934                 :          2 :     g_file_info_get_attribute_boolean (info,
     935                 :            :                                        G_FILE_ATTRIBUTE_UNIX_IS_MOUNTPOINT);
     936                 :          2 :   g_assert_true (is_mountpoint);
     937                 :            : 
     938                 :          2 :   g_clear_object (&info);
     939                 :          2 :   g_clear_object (&file);
     940                 :          2 : }
     941                 :            : 
     942                 :            : static void
     943                 :          1 : test_create (gconstpointer test_data)
     944                 :            : {
     945                 :            :   GFile *root, *child;
     946                 :            :   gboolean res;
     947                 :            :   GError *error;
     948                 :            :   guint i;
     949                 :            :   struct StructureItem item;
     950                 :            :   GFileOutputStream *os;
     951                 :            : 
     952                 :          1 :   g_assert_nonnull (test_data);
     953                 :            : 
     954                 :          1 :   root = g_file_new_for_commandline_arg ((char *) test_data);
     955                 :          1 :   g_assert_nonnull (root);
     956                 :          1 :   res = g_file_query_exists (root, NULL);
     957                 :          1 :   g_assert_true (res);
     958                 :            : 
     959         [ +  + ]:         29 :   for (i = 0; i < G_N_ELEMENTS (sample_struct); i++)
     960                 :            :     {
     961                 :         28 :       item = sample_struct[i];
     962                 :            : 
     963         [ +  + ]:         28 :       if (((item.extra_flags & TEST_CREATE) == TEST_CREATE) ||
     964         [ +  + ]:         23 :           ((item.extra_flags & TEST_REPLACE) == TEST_REPLACE) ||
     965         [ +  + ]:         19 :           ((item.extra_flags & TEST_APPEND) == TEST_APPEND))
     966                 :            :         {
     967                 :         13 :           g_test_message ("  test_create: '%s'", item.filename);
     968                 :            : 
     969                 :         13 :           child = g_file_get_child (root, item.filename);
     970                 :         13 :           g_assert_nonnull (child);
     971                 :         13 :           error = NULL;
     972                 :         13 :           os = NULL;
     973                 :            : 
     974         [ +  + ]:         13 :           if ((item.extra_flags & TEST_CREATE) == TEST_CREATE)
     975                 :          5 :             os = g_file_create (child, item.create_flags, NULL, &error);
     976         [ +  + ]:          8 :           else if ((item.extra_flags & TEST_REPLACE) == TEST_REPLACE)
     977                 :            :             os =
     978                 :          4 :               g_file_replace (child, NULL, TRUE, item.create_flags, NULL,
     979                 :            :                               &error);
     980         [ +  - ]:          4 :           else if ((item.extra_flags & TEST_APPEND) == TEST_APPEND)
     981                 :          4 :             os = g_file_append_to (child, item.create_flags, NULL, &error);
     982                 :            : 
     983                 :            : 
     984         [ +  + ]:         13 :           if (error)
     985                 :          6 :             g_test_message ("       error code %d = %s", error->code, error->message);
     986                 :            : 
     987         [ +  + ]:         13 :           if (((item.extra_flags & TEST_NOT_EXISTS) == 0) &&
     988         [ +  + ]:         10 :               ((item.extra_flags & TEST_CREATE) == TEST_CREATE))
     989                 :            :             {
     990                 :          4 :               g_assert_null (os);
     991                 :          4 :               g_assert_error (error, G_IO_ERROR, G_IO_ERROR_EXISTS);
     992                 :            :             }
     993         [ +  + ]:          9 :           else if (item.file_type == G_FILE_TYPE_DIRECTORY)
     994                 :            :             {
     995                 :          2 :               g_assert_null (os);
     996         [ -  + ]:          2 :               if ((item.extra_flags & TEST_CREATE) == TEST_CREATE)
     997                 :          0 :                 g_assert_error (error, G_IO_ERROR, G_IO_ERROR_EXISTS);
     998                 :            :               else
     999                 :          2 :                 g_assert_error (error, G_IO_ERROR, G_IO_ERROR_IS_DIRECTORY);
    1000                 :            :             }
    1001                 :            :           else
    1002                 :            :             {
    1003                 :          7 :               g_assert_nonnull (os);
    1004                 :          7 :               g_assert_no_error (error);
    1005                 :            :             }
    1006                 :            : 
    1007         [ +  + ]:         13 :           if (error)
    1008                 :          6 :             g_error_free (error);
    1009                 :            : 
    1010         [ +  + ]:         13 :           if (os)
    1011                 :            :             {
    1012                 :          7 :               error = NULL;
    1013                 :            :               res =
    1014                 :          7 :                 g_output_stream_close (G_OUTPUT_STREAM (os), NULL, &error);
    1015         [ -  + ]:          7 :               if (error)
    1016                 :          0 :                 g_test_message ("         g_output_stream_close: error %d = %s",
    1017                 :          0 :                                 error->code, error->message);
    1018                 :          7 :               g_assert_true (res);
    1019                 :          7 :               g_assert_no_error (error);
    1020                 :          7 :               g_object_unref (os);
    1021                 :            :             }
    1022                 :         13 :           g_object_unref (child);
    1023                 :            :         }
    1024                 :            :     }
    1025                 :          1 :   g_object_unref (root);
    1026                 :          1 : }
    1027                 :            : 
    1028                 :            : static void
    1029                 :          1 : test_open (gconstpointer test_data)
    1030                 :            : {
    1031                 :            :   GFile *root, *child;
    1032                 :            :   gboolean res;
    1033                 :            :   GError *error;
    1034                 :            :   guint i;
    1035                 :            :   struct StructureItem item;
    1036                 :            :   GFileInputStream *input_stream;
    1037                 :            : 
    1038                 :          1 :   g_assert_nonnull (test_data);
    1039                 :            : 
    1040                 :          1 :   root = g_file_new_for_commandline_arg ((char *) test_data);
    1041                 :          1 :   g_assert_nonnull (root);
    1042                 :          1 :   res = g_file_query_exists (root, NULL);
    1043                 :          1 :   g_assert_true (res);
    1044                 :            : 
    1045         [ +  + ]:         29 :   for (i = 0; i < G_N_ELEMENTS (sample_struct); i++)
    1046                 :            :     {
    1047                 :         28 :       item = sample_struct[i];
    1048                 :            : 
    1049   [ -  +  -  - ]:         28 :       if ((!posix_compat) && (item.file_type == G_FILE_TYPE_SYMBOLIC_LINK))
    1050                 :          0 :         continue;
    1051                 :            : 
    1052         [ +  + ]:         28 :       if ((item.extra_flags & TEST_OPEN) == TEST_OPEN)
    1053                 :            :         {
    1054                 :         12 :           g_test_message ("  test_open: '%s'", item.filename);
    1055                 :            : 
    1056                 :         12 :           child = g_file_get_child (root, item.filename);
    1057                 :         12 :           g_assert_nonnull (child);
    1058                 :         12 :           error = NULL;
    1059                 :         12 :           input_stream = g_file_read (child, NULL, &error);
    1060                 :            : 
    1061         [ +  + ]:         12 :           if (((item.extra_flags & TEST_NOT_EXISTS) == TEST_NOT_EXISTS) ||
    1062         [ +  + ]:         10 :               ((item.extra_flags & TEST_INVALID_SYMLINK) ==
    1063                 :            :                TEST_INVALID_SYMLINK))
    1064                 :            :             {
    1065                 :          3 :               g_assert_null (input_stream);
    1066                 :          3 :               g_assert_error (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND);
    1067                 :            :             }
    1068         [ +  + ]:          9 :           else if (item.file_type == G_FILE_TYPE_DIRECTORY)
    1069                 :            :             {
    1070                 :          2 :               g_assert_null (input_stream);
    1071                 :          2 :               g_assert_error (error, G_IO_ERROR, G_IO_ERROR_IS_DIRECTORY);
    1072                 :            :             }
    1073                 :            :           else
    1074                 :            :             {
    1075                 :          7 :               g_assert_nonnull (input_stream);
    1076                 :          7 :               g_assert_no_error (error);
    1077                 :            :             }
    1078                 :            : 
    1079         [ +  + ]:         12 :           if (error)
    1080                 :          5 :             g_error_free (error);
    1081                 :            : 
    1082         [ +  + ]:         12 :           if (input_stream)
    1083                 :            :             {
    1084                 :          7 :               error = NULL;
    1085                 :            :               res =
    1086                 :          7 :                 g_input_stream_close (G_INPUT_STREAM (input_stream), NULL,
    1087                 :            :                                       &error);
    1088                 :          7 :               g_assert_true (res);
    1089                 :          7 :               g_assert_no_error (error);
    1090                 :          7 :               g_object_unref (input_stream);
    1091                 :            :             }
    1092                 :         12 :           g_object_unref (child);
    1093                 :            :         }
    1094                 :            :     }
    1095                 :          1 :   g_object_unref (root);
    1096                 :          1 : }
    1097                 :            : 
    1098                 :            : static void
    1099                 :          1 : test_delete (gconstpointer test_data)
    1100                 :            : {
    1101                 :            :   GFile *root;
    1102                 :            :   GFile *child;
    1103                 :            :   gboolean res;
    1104                 :            :   GError *error;
    1105                 :            :   guint i;
    1106                 :            :   struct StructureItem item;
    1107                 :            :   gchar *path;
    1108                 :            : 
    1109                 :          1 :   g_assert_nonnull (test_data);
    1110                 :            : 
    1111                 :          1 :   root = g_file_new_for_commandline_arg ((char *) test_data);
    1112                 :          1 :   g_assert_nonnull (root);
    1113                 :          1 :   res = g_file_query_exists (root, NULL);
    1114                 :          1 :   g_assert_true (res);
    1115                 :            : 
    1116         [ +  + ]:         29 :   for (i = 0; i < G_N_ELEMENTS (sample_struct); i++)
    1117                 :            :     {
    1118                 :         28 :       item = sample_struct[i];
    1119                 :            : 
    1120   [ -  +  -  - ]:         28 :       if ((!posix_compat) && (item.file_type == G_FILE_TYPE_SYMBOLIC_LINK))
    1121                 :          0 :         continue;
    1122                 :            : 
    1123         [ +  + ]:         28 :       if (((item.extra_flags & TEST_DELETE_NORMAL) == TEST_DELETE_NORMAL) ||
    1124         [ +  + ]:         21 :           ((item.extra_flags & TEST_DELETE_TRASH) == TEST_DELETE_TRASH))
    1125                 :            :         {
    1126                 :          9 :           child = file_exists (root, item.filename, &res);
    1127                 :          9 :           g_assert_nonnull (child);
    1128                 :            :           /*  we don't care about result here  */
    1129                 :            : 
    1130                 :          9 :           path = g_file_get_path (child);
    1131                 :          9 :           g_test_message ("  Deleting %s, path = %s", item.filename, path);
    1132                 :          9 :           g_free (path);
    1133                 :            : 
    1134                 :          9 :           error = NULL;
    1135         [ +  + ]:          9 :           if ((item.extra_flags & TEST_DELETE_NORMAL) == TEST_DELETE_NORMAL)
    1136                 :          7 :             res = g_file_delete (child, NULL, &error);
    1137                 :            :           else
    1138                 :          2 :             res = g_file_trash (child, NULL, &error);
    1139                 :            : 
    1140         [ +  + ]:          9 :           if ((item.extra_flags & TEST_DELETE_NON_EMPTY) ==
    1141                 :            :               TEST_DELETE_NON_EMPTY)
    1142                 :            :             {
    1143                 :          1 :               g_assert_false (res);
    1144                 :          1 :               g_assert_error (error, G_IO_ERROR, G_IO_ERROR_NOT_EMPTY);
    1145                 :            :             }
    1146         [ +  + ]:          9 :           if ((item.extra_flags & TEST_DELETE_FAILURE) == TEST_DELETE_FAILURE)
    1147                 :            :             {
    1148                 :          1 :               g_assert_false (res);
    1149                 :          1 :               g_assert_error (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND);
    1150                 :            :             }
    1151         [ +  + ]:          9 :           if ((item.extra_flags & TEST_NOT_EXISTS) == TEST_NOT_EXISTS)
    1152                 :            :             {
    1153                 :          3 :               g_assert_false (res);
    1154                 :          3 :               g_assert_error (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND);
    1155                 :            :             }
    1156                 :            : 
    1157         [ +  + ]:          9 :           if (error)
    1158                 :            :             {
    1159                 :          6 :               g_test_message ("      result = %d, error = %s", res, error->message);
    1160                 :          6 :               g_error_free (error);
    1161                 :            :             }
    1162                 :            : 
    1163                 :          9 :           g_object_unref (child);
    1164                 :            :         }
    1165                 :            :     }
    1166                 :          1 :   g_object_unref (root);
    1167                 :          1 : }
    1168                 :            : 
    1169                 :            : static void
    1170                 :          1 : test_make_directory_with_parents (gconstpointer test_data)
    1171                 :            : {
    1172                 :            :   GFile *root, *child, *grandchild, *greatgrandchild;
    1173                 :            :   gboolean res;
    1174                 :          1 :   GError *error = NULL;
    1175                 :            : #ifdef G_OS_UNIX
    1176                 :          1 :   gboolean have_cap_dac_override = check_cap_dac_override (test_data);
    1177                 :            : #endif
    1178                 :            : 
    1179                 :          1 :   g_assert_nonnull (test_data);
    1180                 :            : 
    1181                 :          1 :   root = g_file_new_for_commandline_arg ((char *) test_data);
    1182                 :          1 :   g_assert_nonnull (root);
    1183                 :          1 :   res = g_file_query_exists (root, NULL);
    1184                 :          1 :   g_assert_true (res);
    1185                 :            : 
    1186                 :          1 :   child = g_file_get_child (root, "a");
    1187                 :          1 :   grandchild = g_file_get_child (child, "b");
    1188                 :          1 :   greatgrandchild = g_file_get_child (grandchild, "c");
    1189                 :            : 
    1190                 :            :   /* Check that we can successfully make directory hierarchies of
    1191                 :            :    * depth 1, 2, or 3
    1192                 :            :    */
    1193                 :          1 :   res = g_file_make_directory_with_parents (child, NULL, &error);
    1194                 :          1 :   g_assert_true (res);
    1195                 :          1 :   g_assert_no_error (error);
    1196                 :          1 :   res = g_file_query_exists (child, NULL);
    1197                 :          1 :   g_assert_true (res);
    1198                 :            : 
    1199                 :          1 :   g_file_delete (child, NULL, NULL);
    1200                 :            : 
    1201                 :          1 :   res = g_file_make_directory_with_parents (grandchild, NULL, &error);
    1202                 :          1 :   g_assert_true (res);
    1203                 :          1 :   g_assert_no_error (error);
    1204                 :          1 :   res = g_file_query_exists (grandchild, NULL);
    1205                 :          1 :   g_assert_true (res);
    1206                 :            : 
    1207                 :          1 :   g_file_delete (grandchild, NULL, NULL);
    1208                 :          1 :   g_file_delete (child, NULL, NULL);
    1209                 :            : 
    1210                 :          1 :   res = g_file_make_directory_with_parents (greatgrandchild, NULL, &error);
    1211                 :          1 :   g_assert_true (res);
    1212                 :          1 :   g_assert_no_error (error);
    1213                 :          1 :   res = g_file_query_exists (greatgrandchild, NULL);
    1214                 :          1 :   g_assert_true (res);
    1215                 :            : 
    1216                 :          1 :   g_file_delete (greatgrandchild, NULL, NULL);
    1217                 :          1 :   g_file_delete (grandchild, NULL, NULL);
    1218                 :          1 :   g_file_delete (child, NULL, NULL);
    1219                 :            : 
    1220                 :            :   /* Now test failure by trying to create a directory hierarchy
    1221                 :            :    * where a ancestor exists but is read-only
    1222                 :            :    */
    1223                 :            : 
    1224                 :            :   /* No obvious way to do this on Windows */
    1225         [ -  + ]:          1 :   if (!posix_compat)
    1226                 :          0 :     goto out;
    1227                 :            : 
    1228                 :            : #ifdef G_OS_UNIX
    1229                 :            :   /* Permissions are ignored if we have CAP_DAC_OVERRIDE or equivalent,
    1230                 :            :    * and in particular if we're root */
    1231         [ -  + ]:          1 :   if (have_cap_dac_override)
    1232                 :            :     {
    1233                 :          0 :       g_test_skip ("Unable to exercise g_file_make_directory_with_parents "
    1234                 :            :                    "failing with EACCES: we probably have "
    1235                 :            :                    "CAP_DAC_OVERRIDE");
    1236                 :          0 :       goto out;
    1237                 :            :     }
    1238                 :            : #endif
    1239                 :            : 
    1240                 :          1 :   g_file_make_directory (child, NULL, NULL);
    1241                 :          1 :   g_assert_true (res);
    1242                 :            : 
    1243                 :          1 :   res = g_file_set_attribute_uint32 (child,
    1244                 :            :                                      G_FILE_ATTRIBUTE_UNIX_MODE,
    1245                 :            :                                      S_IRUSR + S_IXUSR, /* -r-x------ */
    1246                 :            :                                      G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
    1247                 :            :                                      NULL, NULL);
    1248                 :          1 :   g_assert_true (res);
    1249                 :            : 
    1250                 :          1 :   res = g_file_make_directory_with_parents (grandchild, NULL, &error);
    1251                 :          1 :   g_assert_false (res);
    1252                 :          1 :   g_assert_error (error, G_IO_ERROR, G_IO_ERROR_PERMISSION_DENIED);
    1253                 :          1 :   g_clear_error (&error);
    1254                 :            : 
    1255                 :          1 :   res = g_file_make_directory_with_parents (greatgrandchild, NULL, &error);
    1256                 :          1 :   g_assert_false (res);
    1257                 :          1 :   g_assert_error (error, G_IO_ERROR, G_IO_ERROR_PERMISSION_DENIED);
    1258                 :          1 :   g_clear_error (&error);
    1259                 :            : 
    1260                 :          1 : out:
    1261                 :          1 :   g_object_unref (greatgrandchild);
    1262                 :          1 :   g_object_unref (grandchild);
    1263                 :          1 :   g_object_unref (child);
    1264                 :          1 :   g_object_unref (root);
    1265                 :          1 : }
    1266                 :            : 
    1267                 :            : 
    1268                 :            : static void
    1269                 :         10 : cleanup_dir_recurse (GFile *parent, GFile *root)
    1270                 :            : {
    1271                 :            :   gboolean res;
    1272                 :            :   GError *error;
    1273                 :            :   GFileEnumerator *enumerator;
    1274                 :            :   GFileInfo *info;
    1275                 :            :   GFile *descend;
    1276                 :            :   char *relative_path;
    1277                 :            : 
    1278                 :         10 :   g_assert_nonnull (root);
    1279                 :            : 
    1280                 :            :   enumerator =
    1281                 :         10 :     g_file_enumerate_children (parent, "*",
    1282                 :            :                                G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, NULL,
    1283                 :            :                                NULL);
    1284         [ +  + ]:         10 :   if (! enumerator)
    1285                 :          1 :           return;
    1286                 :            : 
    1287                 :          9 :   error = NULL;
    1288                 :          9 :   info = g_file_enumerator_next_file (enumerator, NULL, &error);
    1289   [ +  +  +  - ]:         42 :   while ((info) && (!error))
    1290                 :            :     {
    1291                 :         33 :       descend = g_file_enumerator_get_child (enumerator, info);
    1292                 :         33 :       g_assert_nonnull (descend);
    1293                 :         33 :       relative_path = g_file_get_relative_path (root, descend);
    1294                 :         33 :       g_assert_nonnull (relative_path);
    1295                 :         33 :       g_free (relative_path);
    1296                 :            : 
    1297                 :         33 :       g_test_message ("    deleting '%s'", g_file_info_get_display_name (info));
    1298                 :            : 
    1299         [ +  + ]:         33 :       if (g_file_info_get_file_type (info) == G_FILE_TYPE_DIRECTORY)
    1300                 :          8 :           cleanup_dir_recurse (descend, root);
    1301                 :            :       
    1302                 :         33 :       error = NULL;
    1303                 :         33 :       res = g_file_delete (descend, NULL, &error);
    1304                 :         33 :       g_assert_true (res);
    1305                 :            : 
    1306                 :         33 :       g_object_unref (descend);
    1307                 :         33 :       error = NULL;
    1308                 :         33 :       g_object_unref (info);
    1309                 :            : 
    1310                 :         33 :       info = g_file_enumerator_next_file (enumerator, NULL, &error);
    1311                 :            :     }
    1312                 :          9 :   g_assert_no_error (error);
    1313                 :            : 
    1314                 :          9 :   error = NULL;
    1315                 :          9 :   res = g_file_enumerator_close (enumerator, NULL, &error);
    1316                 :          9 :   g_assert_true (res);
    1317                 :          9 :   g_assert_no_error (error);
    1318                 :            : 
    1319                 :          9 :   g_object_unref (enumerator);
    1320                 :            : }
    1321                 :            : 
    1322                 :            : static void
    1323                 :          2 : prep_clean_structure (gconstpointer test_data)
    1324                 :            : {
    1325                 :            :   GFile *root;
    1326                 :            :   
    1327                 :          2 :   g_assert_nonnull (test_data);
    1328                 :          2 :   g_test_message ("  Cleaning target testing structure in '%s'...",
    1329                 :            :                   (char *) test_data);
    1330                 :            : 
    1331                 :          2 :   root = g_file_new_for_commandline_arg ((char *) test_data);
    1332                 :          2 :   g_assert_nonnull (root);
    1333                 :            :   
    1334                 :          2 :   cleanup_dir_recurse (root, root);
    1335                 :            : 
    1336                 :          2 :   g_file_delete (root, NULL, NULL);
    1337                 :            :   
    1338                 :          2 :   g_object_unref (root);
    1339                 :          2 : }
    1340                 :            : 
    1341                 :            : int
    1342                 :          1 : main (int argc, char *argv[])
    1343                 :            : {
    1344                 :            :   static gboolean only_create_struct;
    1345                 :            :   const char *target_path;
    1346                 :            :   GError *error;
    1347                 :            :   GOptionContext *context;
    1348                 :            : 
    1349                 :            :   static GOptionEntry cmd_entries[] = {
    1350                 :            :     {"read-write", 'w', 0, G_OPTION_ARG_NONE, &write_test,
    1351                 :            :      "Perform write tests (incl. structure creation)", NULL},
    1352                 :            :     {"create-struct", 'c', 0, G_OPTION_ARG_NONE, &only_create_struct,
    1353                 :            :      "Only create testing structure (no tests)", NULL},
    1354                 :            :     {"verbose", 'v', 0, G_OPTION_ARG_NONE, &verbose, "Be verbose", NULL},
    1355                 :            :     {"posix", 'x', 0, G_OPTION_ARG_NONE, &posix_compat,
    1356                 :            :      "Test POSIX-specific features (unix permissions, symlinks)", NULL},
    1357                 :            :     G_OPTION_ENTRY_NULL
    1358                 :            :   };
    1359                 :            : 
    1360                 :          1 :   test_suite = FALSE;
    1361                 :          1 :   verbose = FALSE;
    1362                 :          1 :   write_test = FALSE;
    1363                 :          1 :   only_create_struct = FALSE;
    1364                 :          1 :   target_path = NULL;
    1365                 :          1 :   posix_compat = FALSE;
    1366                 :            : 
    1367                 :            :   /*  strip all gtester-specific args  */
    1368                 :          1 :   g_test_init (&argc, &argv, NULL);
    1369                 :            : 
    1370                 :            :   /*  no extra parameters specified, assume we're executed from glib test suite  */ 
    1371         [ +  - ]:          1 :   if (argc < 2)
    1372                 :            :     {
    1373                 :          1 :           test_suite = TRUE;
    1374                 :          1 :           verbose = TRUE;
    1375                 :          1 :           write_test = TRUE;
    1376                 :          1 :           only_create_struct = FALSE;
    1377                 :          1 :           target_path = DEFAULT_TEST_DIR;
    1378                 :            : #ifdef G_PLATFORM_WIN32
    1379                 :            :           posix_compat = FALSE;
    1380                 :            : #else
    1381                 :          1 :           posix_compat = TRUE;
    1382                 :            : #endif
    1383                 :            :     }
    1384                 :            :   
    1385                 :            :   /*  add trailing args  */
    1386                 :          1 :   error = NULL;
    1387                 :          1 :   context = g_option_context_new ("target_path");
    1388                 :          1 :   g_option_context_add_main_entries (context, cmd_entries, NULL);
    1389         [ -  + ]:          1 :   if (!g_option_context_parse (context, &argc, &argv, &error))
    1390                 :            :     {
    1391                 :          0 :       g_printerr ("option parsing failed: %s\n", error->message);
    1392                 :          0 :       return g_test_run ();
    1393                 :            :     }
    1394                 :            : 
    1395                 :            :   /*  remaining arg should is the target path; we don't care of the extra args here  */ 
    1396         [ -  + ]:          1 :   if (argc >= 2)
    1397                 :          0 :     target_path = strdup (argv[1]);
    1398                 :            :   
    1399         [ -  + ]:          1 :   if (! target_path) 
    1400                 :            :     {
    1401                 :          0 :       g_printerr ("error: target path was not specified\n");
    1402                 :          0 :       g_printerr ("%s", g_option_context_get_help (context, TRUE, NULL));
    1403                 :          0 :       return g_test_run ();
    1404                 :            :     }
    1405                 :            : 
    1406                 :          1 :   g_option_context_free (context);
    1407                 :            : 
    1408                 :            :   /*  Write test - clean target directory first  */
    1409                 :            :   /*    this can be also considered as a test - enumerate + delete  */ 
    1410   [ -  +  -  - ]:          1 :   if (write_test || only_create_struct)
    1411                 :          1 :     g_test_add_data_func ("/live-g-file/prep_clean_structure", target_path,
    1412                 :            :                   prep_clean_structure);
    1413                 :            :   
    1414                 :            :   /*  Write test - create new testing structure  */
    1415   [ -  +  -  - ]:          1 :   if (write_test || only_create_struct)
    1416                 :          1 :     g_test_add_data_func ("/live-g-file/create_structure", target_path,
    1417                 :            :                           test_create_structure);
    1418                 :            : 
    1419                 :            :   /*  Read test - test the sample structure - expect defined attributes to be there  */
    1420         [ +  - ]:          1 :   if (!only_create_struct)
    1421                 :          1 :     g_test_add_data_func ("/live-g-file/test_initial_structure", target_path,
    1422                 :            :                           test_initial_structure);
    1423                 :            : 
    1424                 :            :   /*  Read test - test traverse the structure - no special file should appear  */
    1425         [ +  - ]:          1 :   if (!only_create_struct)
    1426                 :          1 :     g_test_add_data_func ("/live-g-file/test_traverse_structure", target_path,
    1427                 :            :                           test_traverse_structure);
    1428                 :            : 
    1429                 :            :   /*  Read test - enumerate  */
    1430         [ +  - ]:          1 :   if (!only_create_struct)
    1431                 :          1 :     g_test_add_data_func ("/live-g-file/test_enumerate", target_path,
    1432                 :            :                           test_enumerate);
    1433                 :            : 
    1434                 :            :   /*  Read test - open (g_file_read())  */
    1435         [ +  - ]:          1 :   if (!only_create_struct)
    1436                 :          1 :     g_test_add_data_func ("/live-g-file/test_open", target_path, test_open);
    1437                 :            : 
    1438         [ +  - ]:          1 :   if (posix_compat)
    1439                 :            :     {
    1440                 :          1 :       g_test_add_data_func ("/live-g-file/test_unix_is_mountpoint/sysroot",
    1441                 :            :                             "/",
    1442                 :            :                             test_unix_is_mountpoint);
    1443                 :            : #ifdef __linux__
    1444                 :          1 :       g_test_add_data_func ("/live-g-file/test_unix_is_mountpoint/proc",
    1445                 :            :                             "/proc",
    1446                 :            :                             test_unix_is_mountpoint);
    1447                 :            : #endif
    1448                 :            :     }
    1449                 :            : 
    1450                 :            :   /*  Write test - create  */
    1451   [ +  -  +  - ]:          1 :   if (write_test && (!only_create_struct))
    1452                 :          1 :     g_test_add_data_func ("/live-g-file/test_create", target_path,
    1453                 :            :                           test_create);
    1454                 :            : 
    1455                 :            :   /*  Write test - copy, move  */
    1456   [ +  -  +  - ]:          1 :   if (write_test && (!only_create_struct))
    1457                 :          1 :     g_test_add_data_func ("/live-g-file/test_copy_move", target_path,
    1458                 :            :                           test_copy_move);
    1459                 :            : 
    1460                 :            :   /*  Write test - delete, trash  */
    1461   [ +  -  +  - ]:          1 :   if (write_test && (!only_create_struct))
    1462                 :          1 :     g_test_add_data_func ("/live-g-file/test_delete", target_path,
    1463                 :            :                           test_delete);
    1464                 :            : 
    1465                 :            :   /*  Write test - make_directory_with_parents */
    1466   [ +  -  +  - ]:          1 :   if (write_test && (!only_create_struct))
    1467                 :          1 :     g_test_add_data_func ("/live-g-file/test_make_directory_with_parents", target_path,
    1468                 :            :                           test_make_directory_with_parents);
    1469                 :            : 
    1470   [ -  +  -  - ]:          1 :   if (write_test || only_create_struct)
    1471                 :          1 :     g_test_add_data_func ("/live-g-file/final_clean", target_path,
    1472                 :            :                   prep_clean_structure);
    1473                 :            : 
    1474                 :          1 :   return g_test_run ();
    1475                 :            : 
    1476                 :            : }

Generated by: LCOV version 1.14