LCOV - code coverage report
Current view: top level - gio/tests - g-file-info.c (source / functions) Coverage Total Hit
Test: unnamed Lines: 96.5 % 655 632
Test Date: 2026-10-06 05:12:46 Functions: 100.0 % 11 11
Branches: - 0 0

             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 "config.h"
      26                 :             : 
      27                 :             : #include <glib/glib.h>
      28                 :             : #include <gio/gio.h>
      29                 :             : #include <stdlib.h>
      30                 :             : #include <string.h>
      31                 :             : #ifdef G_OS_WIN32
      32                 :             : #include <stdio.h>
      33                 :             : #include <glib/gstdio.h>
      34                 :             : #include <windows.h>
      35                 :             : #include <shlobj.h>
      36                 :             : #include <io.h> /* for _get_osfhandle */
      37                 :             : #endif
      38                 :             : 
      39                 :             : #define TEST_NAME                       "Prilis zlutoucky kun"
      40                 :             : #define TEST_DISPLAY_NAME               "UTF-8 p\xc5\x99\xc3\xadli\xc5\xa1 \xc5\xbelu\xc5\xa5ou\xc4\x8dk\xc3\xbd k\xc5\xaf\xc5\x88"
      41                 :             : #define TEST_SIZE                       0xFFFFFFF0
      42                 :             : 
      43                 :             : static void
      44                 :           6 : test_assigned_values (GFileInfo *info)
      45                 :             : {
      46                 :             :   const char *name, *name_filepath, *display_name, *mistake;
      47                 :             :   guint64 size;
      48                 :             :   GFileType type;
      49                 :             :   
      50                 :             :   /*  Test for attributes presence */
      51                 :           6 :   g_assert_true (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_STANDARD_NAME));
      52                 :           6 :   g_assert_true (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME));
      53                 :           6 :   g_assert_true (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_STANDARD_SIZE));
      54                 :           6 :   g_assert_false (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_STANDARD_COPY_NAME));
      55                 :             :         
      56                 :             :   /*  Retrieve data back and compare */
      57                 :             :   
      58                 :           6 :   name = g_file_info_get_attribute_byte_string (info, G_FILE_ATTRIBUTE_STANDARD_NAME);
      59                 :           6 :   name_filepath = g_file_info_get_attribute_file_path (info, G_FILE_ATTRIBUTE_STANDARD_NAME);
      60                 :           6 :   display_name = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME);
      61                 :           6 :   mistake = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_STANDARD_COPY_NAME);
      62                 :           6 :   size = g_file_info_get_attribute_uint64 (info, G_FILE_ATTRIBUTE_STANDARD_SIZE);
      63                 :           6 :   type = g_file_info_get_file_type (info);
      64                 :             :   
      65                 :           6 :   g_assert_cmpstr (name, ==, TEST_NAME);
      66                 :           6 :   g_assert_cmpstr (name_filepath, ==, name);
      67                 :           6 :   g_assert_cmpstr (display_name, ==, TEST_DISPLAY_NAME);
      68                 :           6 :   g_assert_null (mistake);
      69                 :           6 :   g_assert_cmpint (size, ==, TEST_SIZE);
      70                 :           6 :   g_assert_cmpstr (name, ==, g_file_info_get_name (info));
      71                 :           6 :   g_assert_cmpstr (display_name, ==, g_file_info_get_display_name (info));
      72                 :           6 :   g_assert_cmpint (size, ==, g_file_info_get_size (info)        );
      73                 :           6 :   g_assert_cmpint (type, ==, G_FILE_TYPE_DIRECTORY);
      74                 :           6 : }
      75                 :             : 
      76                 :             : 
      77                 :             : 
      78                 :             : static void
      79                 :           2 : test_g_file_info (void)
      80                 :             : {
      81                 :             :   GFileInfo *info;
      82                 :             :   GFileInfo *info_dup;
      83                 :             :   GFileInfo *info_copy;
      84                 :             :   char **attr_list;
      85                 :             :   GFileAttributeMatcher *matcher;
      86                 :             :   
      87                 :           2 :   info = g_file_info_new ();
      88                 :             :   
      89                 :             :   /*  Test for empty instance */
      90                 :           2 :   attr_list = g_file_info_list_attributes (info, NULL);
      91                 :           2 :   g_assert_nonnull (attr_list);
      92                 :           2 :   g_assert_null (*attr_list);
      93                 :           2 :   g_strfreev (attr_list);
      94                 :             : 
      95                 :           2 :   g_file_info_set_attribute_byte_string (info, G_FILE_ATTRIBUTE_STANDARD_NAME, TEST_NAME);
      96                 :           2 :   g_file_info_set_attribute_string (info, G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME, TEST_DISPLAY_NAME);
      97                 :           2 :   g_file_info_set_attribute_uint64 (info, G_FILE_ATTRIBUTE_STANDARD_SIZE, TEST_SIZE);
      98                 :           2 :   g_file_info_set_file_type (info, G_FILE_TYPE_DIRECTORY);
      99                 :             :         
     100                 :             :   /*  The attr list should not be empty now */
     101                 :           2 :   attr_list = g_file_info_list_attributes (info, NULL);
     102                 :           2 :   g_assert_nonnull (attr_list);
     103                 :           2 :   g_assert_nonnull (*attr_list);
     104                 :           2 :   g_strfreev (attr_list);
     105                 :             : 
     106                 :           2 :   test_assigned_values (info);
     107                 :             : 
     108                 :             :   /* Test the file path encoding functions */
     109                 :           2 :   g_file_info_set_attribute_file_path (info, G_FILE_ATTRIBUTE_STANDARD_NAME, "something different");
     110                 :           2 :   g_assert_cmpstr (g_file_info_get_attribute_file_path (info, G_FILE_ATTRIBUTE_STANDARD_NAME), ==, "something different");
     111                 :           2 :   g_file_info_set_attribute_file_path (info, G_FILE_ATTRIBUTE_STANDARD_NAME, TEST_NAME);
     112                 :             : 
     113                 :             :   /*  Test dups */
     114                 :           2 :   info_dup = g_file_info_dup (info);
     115                 :           2 :   g_assert_nonnull (info_dup);
     116                 :           2 :   test_assigned_values (info_dup);
     117                 :             :   
     118                 :           2 :   info_copy = g_file_info_new ();
     119                 :           2 :   g_file_info_copy_into (info_dup, info_copy);
     120                 :           2 :   g_assert_nonnull (info_copy);
     121                 :           2 :   test_assigned_values (info_copy);
     122                 :             : 
     123                 :             :   /*  Test remove attribute */
     124                 :           2 :   g_assert_false (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_STANDARD_SORT_ORDER));
     125                 :           2 :   g_file_info_set_attribute_int32 (info, G_FILE_ATTRIBUTE_STANDARD_SORT_ORDER, 10);
     126                 :           2 :   g_assert_true (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_STANDARD_SORT_ORDER));
     127                 :             : 
     128                 :           2 :   g_assert_cmpint (g_file_info_get_attribute_type (info, G_FILE_ATTRIBUTE_STANDARD_SORT_ORDER), ==, G_FILE_ATTRIBUTE_TYPE_INT32);
     129                 :           2 :   g_assert_cmpint (g_file_info_get_attribute_status (info, G_FILE_ATTRIBUTE_STANDARD_SORT_ORDER), !=, G_FILE_ATTRIBUTE_STATUS_ERROR_SETTING);
     130                 :             : 
     131                 :           2 :   g_file_info_remove_attribute (info, G_FILE_ATTRIBUTE_STANDARD_SORT_ORDER);
     132                 :           2 :   g_assert_false (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_STANDARD_SORT_ORDER));
     133                 :           2 :   g_assert_cmpint (g_file_info_get_attribute_type (info, G_FILE_ATTRIBUTE_STANDARD_SORT_ORDER), ==, G_FILE_ATTRIBUTE_TYPE_INVALID);
     134                 :             : 
     135                 :           2 :   matcher = g_file_attribute_matcher_new (G_FILE_ATTRIBUTE_STANDARD_NAME ","
     136                 :             :                                           G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME);
     137                 :             : 
     138                 :           2 :   g_assert_true (g_file_attribute_matcher_matches (matcher, G_FILE_ATTRIBUTE_STANDARD_NAME));
     139                 :           2 :   g_assert_false (g_file_attribute_matcher_matches_only (matcher, G_FILE_ATTRIBUTE_STANDARD_NAME));
     140                 :           2 :   g_assert_false (g_file_attribute_matcher_matches (matcher, G_FILE_ATTRIBUTE_STANDARD_SIZE));
     141                 :             : 
     142                 :           2 :   g_file_info_set_attribute_mask (info, matcher);
     143                 :           2 :   g_file_attribute_matcher_unref (matcher);
     144                 :             : 
     145                 :           2 :   g_assert_false (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_STANDARD_SIZE));
     146                 :           2 :   g_assert_true (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_STANDARD_NAME));
     147                 :             : 
     148                 :           2 :   g_object_unref (info);
     149                 :           2 :   g_object_unref (info_dup);
     150                 :           2 :   g_object_unref (info_copy);
     151                 :           2 : }
     152                 :             : 
     153                 :             : static void
     154                 :           2 : test_g_file_info_modification_time (void)
     155                 :             : {
     156                 :           2 :   GFile *file = NULL;
     157                 :           2 :   GFileIOStream *io_stream = NULL;
     158                 :           2 :   GFileInfo *info = NULL;
     159                 :           2 :   GDateTime *dt = NULL, *dt_usecs = NULL, *dt_new = NULL, *dt_new_usecs = NULL;
     160                 :             :   GTimeSpan ts;
     161                 :             :   gboolean nsecs_supported;
     162                 :             :   gint usecs;
     163                 :             :   guint32 nsecs;
     164                 :           2 :   GError *error = NULL;
     165                 :             : 
     166                 :           2 :   g_test_summary ("Test that getting the modification time of a file works.");
     167                 :             : 
     168                 :           2 :   file = g_file_new_tmp ("g-file-info-test-XXXXXX", &io_stream, &error);
     169                 :           2 :   g_assert_no_error (error);
     170                 :             : 
     171                 :           2 :   info = g_file_query_info (file,
     172                 :             :                             G_FILE_ATTRIBUTE_TIME_MODIFIED,
     173                 :             :                             G_FILE_QUERY_INFO_NONE,
     174                 :             :                             NULL, &error);
     175                 :           2 :   g_assert_no_error (error);
     176                 :             : 
     177                 :             :   /* Check the modification time is retrievable. */
     178                 :           2 :   dt = g_file_info_get_modification_date_time (info);
     179                 :           2 :   g_assert_nonnull (dt);
     180                 :             : 
     181                 :             :   /* Try again with microsecond precision. */
     182                 :           2 :   g_clear_object (&info);
     183                 :           2 :   info = g_file_query_info (file,
     184                 :             :                             G_FILE_ATTRIBUTE_TIME_MODIFIED "," G_FILE_ATTRIBUTE_TIME_MODIFIED_USEC,
     185                 :             :                             G_FILE_QUERY_INFO_NONE,
     186                 :             :                             NULL, &error);
     187                 :           2 :   g_assert_no_error (error);
     188                 :             : 
     189                 :           2 :   dt_usecs = g_file_info_get_modification_date_time (info);
     190                 :           2 :   g_assert_nonnull (dt_usecs);
     191                 :             : 
     192                 :           2 :   ts = g_date_time_difference (dt_usecs, dt);
     193                 :           2 :   g_assert_cmpint (ts, >=, 0);
     194                 :           2 :   g_assert_cmpint (ts, <, G_USEC_PER_SEC);
     195                 :             : 
     196                 :             :   /* Try again with nanosecond precision. */
     197                 :           2 :   g_clear_object (&info);
     198                 :           2 :   info = g_file_query_info (file,
     199                 :             :                             G_FILE_ATTRIBUTE_TIME_MODIFIED "," G_FILE_ATTRIBUTE_TIME_MODIFIED_USEC "," G_FILE_ATTRIBUTE_TIME_MODIFIED_NSEC,
     200                 :             :                             G_FILE_QUERY_INFO_NONE,
     201                 :             :                             NULL, &error);
     202                 :           2 :   g_assert_no_error (error);
     203                 :             : 
     204                 :           2 :   nsecs_supported = g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_TIME_MODIFIED_NSEC);
     205                 :           2 :   if (nsecs_supported)
     206                 :             :     {
     207                 :           2 :       usecs = g_date_time_get_microsecond (dt_usecs);
     208                 :           2 :       nsecs = g_file_info_get_attribute_uint32 (info, G_FILE_ATTRIBUTE_TIME_MODIFIED_NSEC);
     209                 :             : 
     210                 :           2 :       g_assert_cmpuint (nsecs, >=, usecs * 1000);
     211                 :           2 :       g_assert_cmpuint (nsecs, <, (usecs + 1) * 1000);
     212                 :           1 :     }
     213                 :             : 
     214                 :             :   /* Try round-tripping the modification time. */
     215                 :           2 :   dt_new = g_date_time_add (dt_usecs, G_USEC_PER_SEC + 50);
     216                 :           2 :   g_file_info_set_modification_date_time (info, dt_new);
     217                 :             : 
     218                 :           2 :   dt_new_usecs = g_file_info_get_modification_date_time (info);
     219                 :           2 :   ts = g_date_time_difference (dt_new_usecs, dt_new);
     220                 :           2 :   g_assert_cmpint (ts, ==, 0);
     221                 :             : 
     222                 :             :   /* Setting the modification time with usec-precision should have cleared nsecs. */
     223                 :           2 :   g_assert_cmpuint (g_file_info_get_attribute_uint32 (info, G_FILE_ATTRIBUTE_TIME_MODIFIED_NSEC), ==, 0);
     224                 :             : 
     225                 :             :   /* Try setting the modification time with nsec-precision and it should set the
     226                 :             :    * usecs too. */
     227                 :           2 :   if (nsecs_supported)
     228                 :             :     {
     229                 :             :       gint new_usecs;
     230                 :             :       guint32 new_nsecs;
     231                 :           2 :       GDateTime *new_dt_usecs = NULL;
     232                 :             : 
     233                 :           2 :       g_file_set_attribute_uint32 (file, G_FILE_ATTRIBUTE_TIME_MODIFIED_NSEC, nsecs + 100,
     234                 :             :                                    G_FILE_QUERY_INFO_NONE, NULL, &error);
     235                 :           2 :       g_assert_no_error (error);
     236                 :             : 
     237                 :           2 :       g_clear_object (&info);
     238                 :           2 :       info = g_file_query_info (file,
     239                 :             :                                 G_FILE_ATTRIBUTE_TIME_MODIFIED "," G_FILE_ATTRIBUTE_TIME_MODIFIED_USEC "," G_FILE_ATTRIBUTE_TIME_MODIFIED_NSEC,
     240                 :             :                                 G_FILE_QUERY_INFO_NONE,
     241                 :             :                                 NULL, &error);
     242                 :           2 :       g_assert_no_error (error);
     243                 :             : 
     244                 :           2 :       new_dt_usecs = g_file_info_get_modification_date_time (info);
     245                 :           2 :       g_assert_nonnull (new_dt_usecs);
     246                 :             : 
     247                 :           2 :       new_usecs = g_date_time_get_microsecond (new_dt_usecs);
     248                 :           2 :       new_nsecs = g_file_info_get_attribute_uint32 (info, G_FILE_ATTRIBUTE_TIME_MODIFIED_NSEC);
     249                 :             : 
     250                 :           2 :       g_assert_cmpuint (new_nsecs, ==, nsecs + 100);
     251                 :           2 :       g_assert_cmpuint (new_nsecs, >=, new_usecs * 1000);
     252                 :           2 :       g_assert_cmpuint (new_nsecs, <, (new_usecs + 1) * 1000);
     253                 :             : 
     254                 :           2 :       g_date_time_unref (new_dt_usecs);
     255                 :           1 :     }
     256                 :             : 
     257                 :             :   /* Clean up. */
     258                 :           2 :   g_clear_object (&io_stream);
     259                 :           2 :   g_file_delete (file, NULL, NULL);
     260                 :           2 :   g_clear_object (&file);
     261                 :             : 
     262                 :           2 :   g_clear_object (&info);
     263                 :           2 :   g_date_time_unref (dt);
     264                 :           2 :   g_date_time_unref (dt_usecs);
     265                 :           2 :   g_date_time_unref (dt_new);
     266                 :           2 :   g_date_time_unref (dt_new_usecs);
     267                 :           2 : }
     268                 :             : 
     269                 :             : static void
     270                 :           2 : test_g_file_info_access_time (void)
     271                 :             : {
     272                 :           2 :   GFile *file = NULL;
     273                 :           2 :   GFileIOStream *io_stream = NULL;
     274                 :           2 :   GFileInfo *info = NULL;
     275                 :           2 :   GDateTime *dt = NULL, *dt_usecs = NULL, *dt_new = NULL, *dt_new_usecs = NULL,
     276                 :           2 :             *dt_before_epoch = NULL, *dt_before_epoch_returned = NULL;
     277                 :             :   GTimeSpan ts;
     278                 :             :   gboolean nsecs_supported;
     279                 :             :   gint usecs;
     280                 :             :   guint32 nsecs;
     281                 :           2 :   GError *error = NULL;
     282                 :             : 
     283                 :           2 :   g_test_summary ("Test that getting the access time of a file works.");
     284                 :             : 
     285                 :           2 :   file = g_file_new_tmp ("g-file-info-test-XXXXXX", &io_stream, &error);
     286                 :           2 :   g_assert_no_error (error);
     287                 :             : 
     288                 :           2 :   info = g_file_query_info (file,
     289                 :             :                             G_FILE_ATTRIBUTE_TIME_ACCESS,
     290                 :             :                             G_FILE_QUERY_INFO_NONE,
     291                 :             :                             NULL, &error);
     292                 :           2 :   g_assert_no_error (error);
     293                 :             : 
     294                 :           2 :   if (!g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_TIME_ACCESS))
     295                 :             :     {
     296                 :           0 :       g_test_skip ("Skipping testing access time as it’s not supported by the kernel");
     297                 :           0 :       g_file_delete (file, NULL, NULL);
     298                 :           0 :       g_clear_object (&file);
     299                 :           0 :       g_clear_object (&info);
     300                 :           0 :       return;
     301                 :             :     }
     302                 :             : 
     303                 :             :   /* Check the access time is retrievable. */
     304                 :           2 :   dt = g_file_info_get_access_date_time (info);
     305                 :           2 :   g_assert_nonnull (dt);
     306                 :             : 
     307                 :             :   /* Try again with microsecond precision. */
     308                 :           2 :   g_clear_object (&info);
     309                 :           2 :   info = g_file_query_info (file,
     310                 :             :                             G_FILE_ATTRIBUTE_TIME_ACCESS "," G_FILE_ATTRIBUTE_TIME_ACCESS_USEC,
     311                 :             :                             G_FILE_QUERY_INFO_NONE,
     312                 :             :                             NULL, &error);
     313                 :           2 :   g_assert_no_error (error);
     314                 :             : 
     315                 :           2 :   dt_usecs = g_file_info_get_access_date_time (info);
     316                 :           2 :   g_assert_nonnull (dt_usecs);
     317                 :             : 
     318                 :           2 :   ts = g_date_time_difference (dt_usecs, dt);
     319                 :           2 :   g_assert_cmpint (ts, >=, 0);
     320                 :           2 :   g_assert_cmpint (ts, <, G_USEC_PER_SEC);
     321                 :             : 
     322                 :             :   /* Try again with nanosecond precision. */
     323                 :           2 :   g_clear_object (&info);
     324                 :           2 :   info = g_file_query_info (file,
     325                 :             :                             G_FILE_ATTRIBUTE_TIME_ACCESS "," G_FILE_ATTRIBUTE_TIME_ACCESS_USEC "," G_FILE_ATTRIBUTE_TIME_ACCESS_NSEC,
     326                 :             :                             G_FILE_QUERY_INFO_NONE,
     327                 :             :                             NULL, &error);
     328                 :           2 :   g_assert_no_error (error);
     329                 :             : 
     330                 :           2 :   nsecs_supported = g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_TIME_ACCESS_NSEC);
     331                 :           2 :   if (nsecs_supported)
     332                 :             :     {
     333                 :           2 :       usecs = g_date_time_get_microsecond (dt_usecs);
     334                 :           2 :       nsecs = g_file_info_get_attribute_uint32 (info, G_FILE_ATTRIBUTE_TIME_ACCESS_NSEC);
     335                 :             : 
     336                 :           2 :       g_assert_cmpuint (nsecs, >=, usecs * 1000);
     337                 :           2 :       g_assert_cmpuint (nsecs, <, (usecs + 1) * 1000);
     338                 :           1 :     }
     339                 :             : 
     340                 :             :   /* Try round-tripping the access time. */
     341                 :           2 :   dt_new = g_date_time_add (dt_usecs, G_USEC_PER_SEC + 50);
     342                 :           2 :   g_file_info_set_access_date_time (info, dt_new);
     343                 :             : 
     344                 :           2 :   dt_new_usecs = g_file_info_get_access_date_time (info);
     345                 :           2 :   ts = g_date_time_difference (dt_new_usecs, dt_new);
     346                 :           2 :   g_assert_cmpint (ts, ==, 0);
     347                 :             : 
     348                 :             :   // try with a negative timestamp
     349                 :           2 :   dt_before_epoch = g_date_time_new_from_unix_utc (-10000);
     350                 :           2 :   g_file_info_set_access_date_time (info, dt_before_epoch);
     351                 :           2 :   dt_before_epoch_returned = g_file_info_get_access_date_time (info);
     352                 :           2 :   ts = g_date_time_difference (dt_before_epoch, dt_before_epoch_returned);
     353                 :           2 :   g_assert_cmpint (ts, ==, 0);
     354                 :             : 
     355                 :             :   /* Setting the access time with usec-precision should have cleared nsecs. */
     356                 :           2 :   g_assert_cmpuint (g_file_info_get_attribute_uint32 (info, G_FILE_ATTRIBUTE_TIME_ACCESS_NSEC), ==, 0);
     357                 :             : 
     358                 :             :   /* Try setting the access time with nsec-precision and it should set the
     359                 :             :    * usecs too. */
     360                 :           2 :   if (nsecs_supported)
     361                 :             :     {
     362                 :             :       gint new_usecs;
     363                 :             :       guint32 new_nsecs;
     364                 :           2 :       GDateTime *new_dt_usecs = NULL;
     365                 :             : 
     366                 :           2 :       g_file_set_attribute_uint32 (file, G_FILE_ATTRIBUTE_TIME_ACCESS_NSEC, nsecs + 100,
     367                 :             :                                    G_FILE_QUERY_INFO_NONE, NULL, &error);
     368                 :           2 :       g_assert_no_error (error);
     369                 :             : 
     370                 :           2 :       g_clear_object (&info);
     371                 :           2 :       info = g_file_query_info (file,
     372                 :             :                                 G_FILE_ATTRIBUTE_TIME_ACCESS "," G_FILE_ATTRIBUTE_TIME_ACCESS_USEC "," G_FILE_ATTRIBUTE_TIME_ACCESS_NSEC,
     373                 :             :                                 G_FILE_QUERY_INFO_NONE,
     374                 :             :                                 NULL, &error);
     375                 :           2 :       g_assert_no_error (error);
     376                 :             : 
     377                 :           2 :       new_dt_usecs = g_file_info_get_access_date_time (info);
     378                 :           2 :       g_assert_nonnull (new_dt_usecs);
     379                 :             : 
     380                 :           2 :       new_usecs = g_date_time_get_microsecond (new_dt_usecs);
     381                 :           2 :       new_nsecs = g_file_info_get_attribute_uint32 (info, G_FILE_ATTRIBUTE_TIME_ACCESS_NSEC);
     382                 :             : 
     383                 :           2 :       g_assert_cmpuint (new_nsecs, ==, nsecs + 100);
     384                 :           2 :       g_assert_cmpuint (new_nsecs, >=, new_usecs * 1000);
     385                 :           2 :       g_assert_cmpuint (new_nsecs, <, (new_usecs + 1) * 1000);
     386                 :             : 
     387                 :           2 :       g_date_time_unref (new_dt_usecs);
     388                 :           1 :     }
     389                 :             : 
     390                 :             :   /* Clean up. */
     391                 :           2 :   g_clear_object (&io_stream);
     392                 :           2 :   g_file_delete (file, NULL, NULL);
     393                 :           2 :   g_clear_object (&file);
     394                 :             : 
     395                 :           2 :   g_clear_object (&info);
     396                 :           2 :   g_date_time_unref (dt);
     397                 :           2 :   g_date_time_unref (dt_usecs);
     398                 :           2 :   g_date_time_unref (dt_new);
     399                 :           2 :   g_date_time_unref (dt_new_usecs);
     400                 :           2 :   g_date_time_unref (dt_before_epoch);
     401                 :           2 :   g_date_time_unref (dt_before_epoch_returned);
     402                 :           1 : }
     403                 :             : 
     404                 :             : static void
     405                 :           2 : test_g_file_info_creation_time (void)
     406                 :             : {
     407                 :           2 :   GFile *file = NULL;
     408                 :           2 :   GFileIOStream *io_stream = NULL;
     409                 :           2 :   GFileInfo *info = NULL;
     410                 :           2 :   GDateTime *dt = NULL, *dt_usecs = NULL, *dt_new = NULL, *dt_new_usecs = NULL,
     411                 :           2 :             *dt_before_epoch = NULL, *dt_before_epoch_returned = NULL;
     412                 :             :   GTimeSpan ts;
     413                 :             :   gboolean nsecs_supported;
     414                 :             :   gint usecs;
     415                 :             :   guint32 nsecs;
     416                 :           2 :   GError *error = NULL;
     417                 :             : 
     418                 :           2 :   g_test_summary ("Test that getting the creation time of a file works.");
     419                 :             : 
     420                 :           2 :   file = g_file_new_tmp ("g-file-info-test-XXXXXX", &io_stream, &error);
     421                 :           2 :   g_assert_no_error (error);
     422                 :             : 
     423                 :           2 :   info = g_file_query_info (file,
     424                 :             :                             G_FILE_ATTRIBUTE_TIME_CREATED,
     425                 :             :                             G_FILE_QUERY_INFO_NONE,
     426                 :             :                             NULL, &error);
     427                 :           2 :   g_assert_no_error (error);
     428                 :             : 
     429                 :           2 :   if (!g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_TIME_CREATED))
     430                 :             :     {
     431                 :           0 :       g_test_skip ("Skipping testing creation time as it’s not supported by the kernel");
     432                 :           0 :       g_clear_object (&io_stream);
     433                 :           0 :       g_file_delete (file, NULL, NULL);
     434                 :           0 :       g_clear_object (&file);
     435                 :           0 :       g_clear_object (&info);
     436                 :           0 :       return;
     437                 :             :     }
     438                 :             : 
     439                 :             :   /* Check the creation time is retrievable. */
     440                 :           2 :   dt = g_file_info_get_creation_date_time (info);
     441                 :             : 
     442                 :             :   /* Try again with microsecond precision. */
     443                 :           2 :   g_clear_object (&info);
     444                 :           2 :   info = g_file_query_info (file,
     445                 :             :                             G_FILE_ATTRIBUTE_TIME_CREATED "," G_FILE_ATTRIBUTE_TIME_CREATED_USEC,
     446                 :             :                             G_FILE_QUERY_INFO_NONE,
     447                 :             :                             NULL, &error);
     448                 :           2 :   g_assert_no_error (error);
     449                 :             : 
     450                 :           2 :   dt_usecs = g_file_info_get_creation_date_time (info);
     451                 :           2 :   g_assert_nonnull (dt_usecs);
     452                 :             : 
     453                 :           2 :   ts = g_date_time_difference (dt_usecs, dt);
     454                 :           2 :   g_assert_cmpint (ts, >=, 0);
     455                 :           2 :   g_assert_cmpint (ts, <, G_USEC_PER_SEC);
     456                 :             : 
     457                 :             :   /* Try again with nanosecond precision. */
     458                 :           2 :   g_clear_object (&info);
     459                 :           2 :   info = g_file_query_info (file,
     460                 :             :                             G_FILE_ATTRIBUTE_TIME_CREATED "," G_FILE_ATTRIBUTE_TIME_CREATED_USEC "," G_FILE_ATTRIBUTE_TIME_CREATED_NSEC,
     461                 :             :                             G_FILE_QUERY_INFO_NONE,
     462                 :             :                             NULL, &error);
     463                 :           2 :   g_assert_no_error (error);
     464                 :             : 
     465                 :           2 :   nsecs_supported = g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_TIME_CREATED_NSEC);
     466                 :           2 :   if (nsecs_supported)
     467                 :             :     {
     468                 :           2 :       usecs = g_date_time_get_microsecond (dt_usecs);
     469                 :           2 :       nsecs = g_file_info_get_attribute_uint32 (info, G_FILE_ATTRIBUTE_TIME_CREATED_NSEC);
     470                 :             : 
     471                 :           2 :       g_assert_cmpuint (nsecs, >=, usecs * 1000);
     472                 :           2 :       g_assert_cmpuint (nsecs, <, (usecs + 1) * 1000);
     473                 :           1 :     }
     474                 :             : 
     475                 :             :   /* Try round-tripping the creation time. */
     476                 :           2 :   dt_new = g_date_time_add (dt_usecs, G_USEC_PER_SEC + 50);
     477                 :           2 :   g_file_info_set_creation_date_time (info, dt_new);
     478                 :             : 
     479                 :           2 :   dt_new_usecs = g_file_info_get_creation_date_time (info);
     480                 :           2 :   ts = g_date_time_difference (dt_new_usecs, dt_new);
     481                 :           2 :   g_assert_cmpint (ts, ==, 0);
     482                 :             : 
     483                 :             :   // try with a negative timestamp
     484                 :           2 :   dt_before_epoch = g_date_time_new_from_unix_utc (-10000);
     485                 :           2 :   g_file_info_set_creation_date_time (info, dt_before_epoch);
     486                 :           2 :   dt_before_epoch_returned = g_file_info_get_creation_date_time (info);
     487                 :           2 :   ts = g_date_time_difference (dt_before_epoch, dt_before_epoch_returned);
     488                 :           2 :   g_assert_cmpint (ts, ==, 0);
     489                 :             : 
     490                 :             :   /* Setting the creation time with usec-precision should have cleared nsecs. */
     491                 :           2 :   g_assert_cmpuint (g_file_info_get_attribute_uint32 (info, G_FILE_ATTRIBUTE_TIME_CREATED_NSEC), ==, 0);
     492                 :             : 
     493                 :             :   /* Try setting the creation time with nsec-precision and it should set the
     494                 :             :    * usecs too. */
     495                 :           2 :   if (nsecs_supported)
     496                 :             :     {
     497                 :             :       gint new_usecs;
     498                 :             :       guint32 new_nsecs;
     499                 :           2 :       GDateTime *new_dt_usecs = NULL;
     500                 :             : 
     501                 :             :       /* This can fail on some platforms, even if reading CREATED_NSEC works */
     502                 :           2 :       g_file_set_attribute_uint32 (file, G_FILE_ATTRIBUTE_TIME_CREATED_NSEC, nsecs + 100,
     503                 :             :                                    G_FILE_QUERY_INFO_NONE, NULL, &error);
     504                 :           2 :       if (error == NULL)
     505                 :             :         {
     506                 :           0 :           g_clear_object (&info);
     507                 :           0 :           info = g_file_query_info (file,
     508                 :             :                                     G_FILE_ATTRIBUTE_TIME_CREATED "," G_FILE_ATTRIBUTE_TIME_CREATED_USEC "," G_FILE_ATTRIBUTE_TIME_CREATED_NSEC,
     509                 :             :                                     G_FILE_QUERY_INFO_NONE,
     510                 :             :                                     NULL, &error);
     511                 :           0 :           g_assert_no_error (error);
     512                 :             : 
     513                 :           0 :           new_dt_usecs = g_file_info_get_creation_date_time (info);
     514                 :           0 :           g_assert_nonnull (new_dt_usecs);
     515                 :             : 
     516                 :           0 :           new_usecs = g_date_time_get_microsecond (new_dt_usecs);
     517                 :           0 :           new_nsecs = g_file_info_get_attribute_uint32 (info, G_FILE_ATTRIBUTE_TIME_CREATED_NSEC);
     518                 :             : 
     519                 :           0 :           g_assert_cmpuint (new_nsecs, ==, nsecs + 100);
     520                 :           0 :           g_assert_cmpuint (new_nsecs, >=, new_usecs * 1000);
     521                 :           0 :           g_assert_cmpuint (new_nsecs, <, (new_usecs + 1) * 1000);
     522                 :             : 
     523                 :           0 :           g_date_time_unref (new_dt_usecs);
     524                 :           0 :         }
     525                 :             :       else
     526                 :             :         {
     527                 :           2 :           if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED))
     528                 :           2 :             g_clear_error (&error);
     529                 :           2 :           g_assert_no_error (error);
     530                 :             :         }
     531                 :           1 :     }
     532                 :             : 
     533                 :             :   /* Clean up. */
     534                 :           2 :   g_clear_object (&io_stream);
     535                 :           2 :   g_file_delete (file, NULL, NULL);
     536                 :           2 :   g_clear_object (&file);
     537                 :             : 
     538                 :           2 :   g_clear_object (&info);
     539                 :           2 :   g_date_time_unref (dt);
     540                 :           2 :   g_date_time_unref (dt_usecs);
     541                 :           2 :   g_date_time_unref (dt_new);
     542                 :           2 :   g_date_time_unref (dt_new_usecs);
     543                 :           2 :   g_date_time_unref (dt_before_epoch);
     544                 :           2 :   g_date_time_unref (dt_before_epoch_returned);
     545                 :           1 : }
     546                 :             : 
     547                 :             : static void
     548                 :           2 : test_g_file_info_icons (void)
     549                 :             : {
     550                 :           2 :   GFile *file = NULL;
     551                 :           2 :   GFileIOStream *io_stream = NULL;
     552                 :           2 :   GError *error = NULL;
     553                 :             :   GFileInfo *info, *fast_info;
     554                 :             :   GIcon *icon, *symbolic_icon;
     555                 :             :   GIcon *fast_icon, *fast_symbolic_icon;
     556                 :             : 
     557                 :           2 :   g_test_summary ("Test fetching icons for a file.");
     558                 :             : 
     559                 :           2 :   file = g_file_new_tmp ("g-file-info-test-XXXXXX", &io_stream, &error);
     560                 :           2 :   g_assert_no_error (error);
     561                 :             : 
     562                 :           2 :   info = g_file_query_info (file,
     563                 :             :                             G_FILE_ATTRIBUTE_STANDARD_NAME ","
     564                 :             :                             G_FILE_ATTRIBUTE_STANDARD_ICON ","
     565                 :             :                             G_FILE_ATTRIBUTE_STANDARD_SYMBOLIC_ICON,
     566                 :             :                             G_FILE_QUERY_INFO_NONE,
     567                 :             :                             NULL, &error);
     568                 :           2 :   g_assert_no_error (error);
     569                 :             : 
     570                 :           2 :   g_assert_true (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_STANDARD_ICON));
     571                 :           2 :   g_assert_true (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_STANDARD_SYMBOLIC_ICON));
     572                 :             : 
     573                 :           2 :   icon = g_file_info_get_icon (info);
     574                 :           2 :   symbolic_icon = g_file_info_get_symbolic_icon (info);
     575                 :             : 
     576                 :           2 :   g_assert_nonnull (icon);
     577                 :           2 :   g_assert_nonnull (symbolic_icon);
     578                 :             : 
     579                 :             :   /* Query icons with fast content type to skip implicit normal content type */
     580                 :           2 :   fast_info = g_file_query_info (file,
     581                 :             :                                  G_FILE_ATTRIBUTE_STANDARD_FAST_CONTENT_TYPE ","
     582                 :             :                                  G_FILE_ATTRIBUTE_STANDARD_NAME ","
     583                 :             :                                  G_FILE_ATTRIBUTE_STANDARD_ICON ","
     584                 :             :                                  G_FILE_ATTRIBUTE_STANDARD_SYMBOLIC_ICON,
     585                 :             :                                  G_FILE_QUERY_INFO_NONE,
     586                 :             :                                  NULL, &error);
     587                 :           2 :   g_assert_no_error (error);
     588                 :             : 
     589                 :           2 :   g_assert_false (g_file_info_has_attribute (fast_info, G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE));
     590                 :           2 :   g_assert_true (g_file_info_has_attribute (fast_info, G_FILE_ATTRIBUTE_STANDARD_FAST_CONTENT_TYPE));
     591                 :           2 :   g_assert_true (g_file_info_has_attribute (fast_info, G_FILE_ATTRIBUTE_STANDARD_ICON));
     592                 :           2 :   g_assert_true (g_file_info_has_attribute (fast_info, G_FILE_ATTRIBUTE_STANDARD_SYMBOLIC_ICON));
     593                 :             : 
     594                 :           2 :   fast_icon = g_file_info_get_icon (fast_info);
     595                 :           2 :   fast_symbolic_icon = g_file_info_get_symbolic_icon (fast_info);
     596                 :             : 
     597                 :           2 :   g_assert_nonnull (fast_icon);
     598                 :           2 :   g_assert_nonnull (fast_symbolic_icon);
     599                 :             : 
     600                 :             :   /* Clean up. */
     601                 :           2 :   g_clear_object (&io_stream);
     602                 :           2 :   g_file_delete (file, NULL, NULL);
     603                 :           2 :   g_clear_object (&file);
     604                 :           2 :   g_clear_object (&info);
     605                 :           2 :   g_clear_object (&fast_info);
     606                 :           2 : }
     607                 :             : 
     608                 :             : #ifdef G_OS_WIN32
     609                 :             : static void
     610                 :           1 : test_internal_enhanced_stdio (void)
     611                 :             : {
     612                 :             :   char *p0, *p1, *ps;
     613                 :             :   gboolean try_sparse;
     614                 :             :   gchar *tmp_dir_root;
     615                 :             :   wchar_t *tmp_dir_root_w;
     616                 :             :   gchar *c;
     617                 :             :   DWORD fsflags;
     618                 :             :   FILE *f;
     619                 :             :   SYSTEMTIME st;
     620                 :             :   FILETIME ft;
     621                 :             :   HANDLE h;
     622                 :             :   GStatBuf statbuf_p0, statbuf_p1, statbuf_ps;
     623                 :             :   GFile *gf_p0, *gf_p1, *gf_ps;
     624                 :             :   GFileInfo *fi_p0, *fi_p1, *fi_ps;
     625                 :             :   guint64 size_p0, alsize_p0, size_ps, alsize_ps;
     626                 :             :   const gchar *id_p0;
     627                 :             :   const gchar *id_p1;
     628                 :             :   guint64 time_p0;
     629                 :             :   gchar *tmp_dir;
     630                 :             :   wchar_t *programdata_dir_w;
     631                 :             :   wchar_t *users_dir_w;
     632                 :             :   static const GUID folder_id_programdata = 
     633                 :             :     { 0x62AB5D82, 0xFDC1, 0x4DC3, { 0xA9, 0xDD, 0x07, 0x0D, 0x1D, 0x49, 0x5D, 0x97 } };
     634                 :             :   static const GUID folder_id_users = 
     635                 :             :     { 0x0762D272, 0xC50A, 0x4BB0, { 0xA3, 0x82, 0x69, 0x7D, 0xCD, 0x72, 0x9B, 0x80 } };
     636                 :           1 :   GDateTime *dt = NULL, *dt2 = NULL;
     637                 :             :   GTimeSpan ts;
     638                 :             :   /* Just before SYSTEMTIME limit (Jan 1 30827) */
     639                 :           1 :   const gint64 one_sec_before_systemtime_limit = 910670515199;
     640                 :             :   gboolean retval;
     641                 :           1 :   GError *local_error = NULL;
     642                 :             : 
     643                 :             : 
     644                 :           1 :   programdata_dir_w = NULL;
     645                 :           1 :   SHGetKnownFolderPath (&folder_id_programdata, 0, NULL, &programdata_dir_w);
     646                 :             : 
     647                 :           1 :   users_dir_w = NULL;
     648                 :           1 :   SHGetKnownFolderPath (&folder_id_users, 0, NULL, &users_dir_w);
     649                 :             : 
     650                 :           1 :   if (programdata_dir_w != NULL && users_dir_w != NULL)
     651                 :             :     {
     652                 :             :       gchar *programdata;
     653                 :             :       gchar *users_dir;
     654                 :             :       gchar *allusers;
     655                 :             :       gchar *commondata;
     656                 :             :       GFile *gf_programdata, *gf_allusers, *gf_commondata;
     657                 :             :       GFileInfo *fi_programdata, *fi_allusers, *fi_allusers_target, *fi_commondata, *fi_commondata_target;
     658                 :             :       GFileType ft_allusers;
     659                 :             :       GFileType ft_allusers_target;
     660                 :             :       GFileType ft_programdata;
     661                 :             :       GFileType ft_commondata;
     662                 :             :       gboolean allusers_is_symlink;
     663                 :             :       gboolean commondata_is_symlink;
     664                 :             :       gboolean commondata_is_mount_point;
     665                 :             :       guint32 allusers_reparse_tag;
     666                 :             :       guint32 commondata_reparse_tag;
     667                 :             :       const gchar *id_allusers;
     668                 :             :       const gchar *id_allusers_target;
     669                 :             :       const gchar *id_commondata_target;
     670                 :             :       const gchar *id_programdata;
     671                 :             :       const gchar *allusers_target;
     672                 :             :       const gchar *commondata_target;
     673                 :             : 
     674                 :             :       /* C:/ProgramData */
     675                 :           1 :       programdata = g_utf16_to_utf8 (programdata_dir_w, -1, NULL, NULL, NULL);
     676                 :           1 :       g_assert_nonnull (programdata);
     677                 :             :       /* C:/Users */
     678                 :           1 :       users_dir = g_utf16_to_utf8 (users_dir_w, -1, NULL, NULL, NULL);
     679                 :           1 :       g_assert_nonnull (users_dir);
     680                 :             :       /* "C:/Users/All Users" is a known directory symlink
     681                 :             :        * for "C:/ProgramData".
     682                 :             :        */
     683                 :           1 :       allusers = g_build_filename (users_dir, "All Users", NULL);
     684                 :             : 
     685                 :             :       /* "C:/Users/All Users/Application Data" is a known
     686                 :             :        * junction for "C:/ProgramData"
     687                 :             :        */
     688                 :           1 :       commondata = g_build_filename (allusers, "Application Data", NULL);
     689                 :             : 
     690                 :             :       /* We don't test g_stat() and g_lstat() on these directories,
     691                 :             :        * because it is pointless - there's no way to tell that these
     692                 :             :        * functions behave correctly in this case
     693                 :             :        * (st_ino is useless, so we can't tell apart g_stat() and g_lstat()
     694                 :             :        *  results; st_mode is also useless as it does not support S_ISLNK;
     695                 :             :        *  and these directories have no interesting properties other
     696                 :             :        *  than [not] being symlinks).
     697                 :             :        */
     698                 :           1 :       gf_programdata = g_file_new_for_path (programdata);
     699                 :           1 :       gf_allusers = g_file_new_for_path (allusers);
     700                 :           1 :       gf_commondata = g_file_new_for_path (commondata);
     701                 :             : 
     702                 :           1 :       fi_programdata = g_file_query_info (gf_programdata,
     703                 :             :                                           G_FILE_ATTRIBUTE_ID_FILE ","
     704                 :             :                                           G_FILE_ATTRIBUTE_STANDARD_TYPE,
     705                 :             :                                           G_FILE_QUERY_INFO_NONE,
     706                 :             :                                           NULL, NULL);
     707                 :             : 
     708                 :           1 :       fi_allusers_target = g_file_query_info (gf_allusers,
     709                 :             :                                               G_FILE_ATTRIBUTE_ID_FILE ","
     710                 :             :                                               G_FILE_ATTRIBUTE_STANDARD_TYPE,
     711                 :             :                                               G_FILE_QUERY_INFO_NONE,
     712                 :             :                                               NULL, NULL);
     713                 :             : 
     714                 :           1 :       fi_allusers = g_file_query_info (gf_allusers,
     715                 :             :                                        G_FILE_ATTRIBUTE_STANDARD_SYMLINK_TARGET ","
     716                 :             :                                        G_FILE_ATTRIBUTE_STANDARD_IS_SYMLINK ","
     717                 :             :                                        G_FILE_ATTRIBUTE_DOS_REPARSE_POINT_TAG ","
     718                 :             :                                        G_FILE_ATTRIBUTE_ID_FILE ","
     719                 :             :                                        G_FILE_ATTRIBUTE_STANDARD_TYPE,
     720                 :             :                                        G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
     721                 :             :                                        NULL, NULL);
     722                 :             : 
     723                 :           1 :       fi_commondata = g_file_query_info (gf_commondata,
     724                 :             :                                          G_FILE_ATTRIBUTE_STANDARD_SYMLINK_TARGET ","
     725                 :             :                                          G_FILE_ATTRIBUTE_STANDARD_IS_SYMLINK ","
     726                 :             :                                          G_FILE_ATTRIBUTE_DOS_IS_MOUNTPOINT ","
     727                 :             :                                          G_FILE_ATTRIBUTE_DOS_REPARSE_POINT_TAG ","
     728                 :             :                                          G_FILE_ATTRIBUTE_ID_FILE ","
     729                 :             :                                          G_FILE_ATTRIBUTE_STANDARD_TYPE,
     730                 :             :                                          G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
     731                 :             :                                          NULL, NULL);
     732                 :             : 
     733                 :           1 :       fi_commondata_target = g_file_query_info (gf_commondata,
     734                 :             :                                                 G_FILE_ATTRIBUTE_ID_FILE ","
     735                 :             :                                                 G_FILE_ATTRIBUTE_STANDARD_TYPE,
     736                 :             :                                                 G_FILE_QUERY_INFO_NONE,
     737                 :             :                                                 NULL, NULL);
     738                 :             : 
     739                 :           1 :       g_assert_true (g_file_info_has_attribute (fi_programdata, G_FILE_ATTRIBUTE_ID_FILE));
     740                 :           1 :       g_assert_true (g_file_info_has_attribute (fi_programdata, G_FILE_ATTRIBUTE_STANDARD_TYPE));
     741                 :             : 
     742                 :           1 :       g_assert_true (g_file_info_has_attribute (fi_allusers_target, G_FILE_ATTRIBUTE_ID_FILE));
     743                 :           1 :       g_assert_true (g_file_info_has_attribute (fi_allusers_target, G_FILE_ATTRIBUTE_STANDARD_TYPE));
     744                 :           1 :       g_assert_true (g_file_info_has_attribute (fi_commondata_target, G_FILE_ATTRIBUTE_ID_FILE));
     745                 :           1 :       g_assert_true (g_file_info_has_attribute (fi_commondata_target, G_FILE_ATTRIBUTE_STANDARD_TYPE));
     746                 :             : 
     747                 :           1 :       g_assert_true (g_file_info_has_attribute (fi_allusers, G_FILE_ATTRIBUTE_ID_FILE));
     748                 :           1 :       g_assert_true (g_file_info_has_attribute (fi_allusers, G_FILE_ATTRIBUTE_STANDARD_TYPE));
     749                 :           1 :       g_assert_true (g_file_info_has_attribute (fi_allusers, G_FILE_ATTRIBUTE_STANDARD_IS_SYMLINK));
     750                 :           1 :       g_assert_true (g_file_info_has_attribute (fi_allusers, G_FILE_ATTRIBUTE_DOS_REPARSE_POINT_TAG));
     751                 :           1 :       g_assert_true (g_file_info_has_attribute (fi_allusers, G_FILE_ATTRIBUTE_STANDARD_SYMLINK_TARGET));
     752                 :             : 
     753                 :           1 :       g_assert_true (g_file_info_has_attribute (fi_commondata, G_FILE_ATTRIBUTE_ID_FILE));
     754                 :           1 :       g_assert_true (g_file_info_has_attribute (fi_commondata, G_FILE_ATTRIBUTE_STANDARD_TYPE));
     755                 :           1 :       g_assert_true (g_file_info_has_attribute (fi_commondata, G_FILE_ATTRIBUTE_STANDARD_IS_SYMLINK));
     756                 :           1 :       g_assert_true (g_file_info_has_attribute (fi_commondata, G_FILE_ATTRIBUTE_DOS_IS_MOUNTPOINT));
     757                 :           1 :       g_assert_true (g_file_info_has_attribute (fi_commondata, G_FILE_ATTRIBUTE_DOS_REPARSE_POINT_TAG));
     758                 :           1 :       g_assert_true (g_file_info_has_attribute (fi_commondata, G_FILE_ATTRIBUTE_STANDARD_SYMLINK_TARGET));
     759                 :             : 
     760                 :           1 :       ft_allusers = g_file_info_get_file_type (fi_allusers);
     761                 :           1 :       ft_allusers_target = g_file_info_get_file_type (fi_allusers_target);
     762                 :           1 :       ft_programdata = g_file_info_get_file_type (fi_programdata);
     763                 :           1 :       ft_commondata = g_file_info_get_file_type (fi_commondata);
     764                 :             : 
     765                 :           1 :       g_assert_cmpint (ft_allusers, ==, G_FILE_TYPE_DIRECTORY);
     766                 :           1 :       g_assert_cmpint (ft_allusers_target, ==, G_FILE_TYPE_DIRECTORY);
     767                 :           1 :       g_assert_cmpint (ft_programdata, ==, G_FILE_TYPE_DIRECTORY);
     768                 :           1 :       g_assert_cmpint (ft_commondata, ==, G_FILE_TYPE_DIRECTORY);
     769                 :             : 
     770                 :           1 :       allusers_is_symlink = g_file_info_get_attribute_boolean (fi_allusers, G_FILE_ATTRIBUTE_STANDARD_IS_SYMLINK);
     771                 :           1 :       allusers_reparse_tag = g_file_info_get_attribute_uint32 (fi_allusers, G_FILE_ATTRIBUTE_DOS_REPARSE_POINT_TAG);
     772                 :           1 :       commondata_is_symlink = g_file_info_get_attribute_boolean (fi_commondata, G_FILE_ATTRIBUTE_STANDARD_IS_SYMLINK);
     773                 :           1 :       commondata_is_mount_point = g_file_info_get_attribute_boolean (fi_commondata, G_FILE_ATTRIBUTE_DOS_IS_MOUNTPOINT);
     774                 :           1 :       commondata_reparse_tag = g_file_info_get_attribute_uint32 (fi_commondata, G_FILE_ATTRIBUTE_DOS_REPARSE_POINT_TAG);
     775                 :             : 
     776                 :           1 :       g_assert_true (allusers_is_symlink);
     777                 :           1 :       g_assert_cmpuint (allusers_reparse_tag, ==, IO_REPARSE_TAG_SYMLINK);
     778                 :           1 :       g_assert_true (commondata_is_symlink);
     779                 :           1 :       g_assert_true (commondata_is_mount_point);
     780                 :           1 :       g_assert_cmpuint (commondata_reparse_tag, ==, IO_REPARSE_TAG_MOUNT_POINT);
     781                 :             : 
     782                 :           1 :       id_allusers = g_file_info_get_attribute_string (fi_allusers, G_FILE_ATTRIBUTE_ID_FILE);
     783                 :           1 :       id_allusers_target = g_file_info_get_attribute_string (fi_allusers_target, G_FILE_ATTRIBUTE_ID_FILE);
     784                 :           1 :       id_commondata_target = g_file_info_get_attribute_string (fi_commondata_target, G_FILE_ATTRIBUTE_ID_FILE);
     785                 :           1 :       id_programdata = g_file_info_get_attribute_string (fi_programdata, G_FILE_ATTRIBUTE_ID_FILE);
     786                 :             : 
     787                 :           1 :       g_assert_cmpstr (id_allusers_target, ==, id_programdata);
     788                 :           1 :       g_assert_cmpstr (id_commondata_target, ==, id_programdata);
     789                 :           1 :       g_assert_cmpstr (id_allusers, !=, id_programdata);
     790                 :             : 
     791                 :           1 :       allusers_target = g_file_info_get_symlink_target (fi_allusers);
     792                 :             : 
     793                 :           2 :       g_assert_true (g_str_has_suffix (allusers_target, "ProgramData"));
     794                 :             : 
     795                 :           1 :       commondata_target = g_file_info_get_symlink_target (fi_commondata);
     796                 :             : 
     797                 :           2 :       g_assert_true (g_str_has_suffix (commondata_target, "ProgramData"));
     798                 :             : 
     799                 :           1 :       g_object_unref (fi_allusers);
     800                 :           1 :       g_object_unref (fi_allusers_target);
     801                 :           1 :       g_object_unref (fi_commondata);
     802                 :           1 :       g_object_unref (fi_commondata_target);
     803                 :           1 :       g_object_unref (fi_programdata);
     804                 :           1 :       g_object_unref (gf_allusers);
     805                 :           1 :       g_object_unref (gf_commondata);
     806                 :           1 :       g_object_unref (gf_programdata);
     807                 :             : 
     808                 :           1 :       g_free (allusers);
     809                 :           1 :       g_free (commondata);
     810                 :           1 :       g_free (users_dir);
     811                 :           1 :       g_free (programdata);
     812                 :           1 :     }
     813                 :             : 
     814                 :           1 :   if (programdata_dir_w)
     815                 :           1 :     CoTaskMemFree (programdata_dir_w);
     816                 :             : 
     817                 :           1 :   if (users_dir_w)
     818                 :           1 :     CoTaskMemFree (users_dir_w);
     819                 :             : 
     820                 :           1 :   tmp_dir = g_dir_make_tmp ("glib_stdio_testXXXXXX", NULL);
     821                 :           1 :   g_assert_nonnull (tmp_dir);
     822                 :             : 
     823                 :             :   /* Technically, this isn't necessary - we already assume NTFS, because of
     824                 :             :    * symlink support, and NTFS also supports sparse files. Still, given
     825                 :             :    * the amount of unusual I/O APIs called in this test, checking for
     826                 :             :    * sparse file support of the filesystem where temp directory is
     827                 :             :    * doesn't seem to be out of place.
     828                 :             :    */
     829                 :           1 :   try_sparse = FALSE;
     830                 :           1 :   tmp_dir_root = g_strdup (tmp_dir);
     831                 :             :   /* We need "C:\\" or "C:/", with a trailing [back]slash */
     832                 :           2 :   for (c = tmp_dir_root; c && c[0] && c[1]; c++)
     833                 :           2 :     if (c[0] == ':')
     834                 :             :       {
     835                 :           1 :         c[2] = '\0';
     836                 :           1 :         break;
     837                 :             :       }
     838                 :           1 :   tmp_dir_root_w = g_utf8_to_utf16 (tmp_dir_root, -1, NULL, NULL, NULL);
     839                 :           1 :   g_assert_nonnull (tmp_dir_root_w);
     840                 :           1 :   g_free (tmp_dir_root);
     841                 :           1 :   g_assert_true (GetVolumeInformationW (tmp_dir_root_w, NULL, 0, NULL, NULL, &fsflags, NULL, 0));
     842                 :           1 :   g_free (tmp_dir_root_w);
     843                 :           1 :   try_sparse = (fsflags & FILE_SUPPORTS_SPARSE_FILES) == FILE_SUPPORTS_SPARSE_FILES;
     844                 :             : 
     845                 :           1 :   p0 = g_build_filename (tmp_dir, "zool", NULL);
     846                 :           1 :   p1 = g_build_filename (tmp_dir, "looz", NULL);
     847                 :           1 :   ps = g_build_filename (tmp_dir, "sparse", NULL);
     848                 :             : 
     849                 :           1 :   if (try_sparse)
     850                 :             :     {
     851                 :             :       FILE_SET_SPARSE_BUFFER ssb;
     852                 :             :       FILE_ZERO_DATA_INFORMATION zdi;
     853                 :             : 
     854                 :           1 :       g_remove (ps);
     855                 :             : 
     856                 :           1 :       f = g_fopen (ps, "wbe");
     857                 :           1 :       g_assert_nonnull (f);
     858                 :             : 
     859                 :           1 :       h = (HANDLE) _get_osfhandle (fileno (f));
     860                 :           1 :       g_assert_cmpuint ((guintptr) h, !=, (guintptr) INVALID_HANDLE_VALUE);
     861                 :             : 
     862                 :           1 :       ssb.SetSparse = TRUE;
     863                 :           1 :       g_assert_true (DeviceIoControl (h,
     864                 :             :                      FSCTL_SET_SPARSE,
     865                 :             :                      &ssb, sizeof (ssb),
     866                 :             :                      NULL, 0, NULL, NULL));
     867                 :             : 
     868                 :             :       /* Make it a sparse file that starts with 4GBs of zeros */
     869                 :           1 :       zdi.FileOffset.QuadPart = 0;
     870                 :           1 :       zdi.BeyondFinalZero.QuadPart = 0xFFFFFFFFULL + 1;
     871                 :           1 :       g_assert_true (DeviceIoControl (h,
     872                 :             :                      FSCTL_SET_ZERO_DATA,
     873                 :             :                      &zdi, sizeof (zdi),
     874                 :             :                      NULL, 0, NULL, NULL));
     875                 :             : 
     876                 :             :       /* Let's not keep this seemingly 4GB monster around
     877                 :             :        * longer than we absolutely need to. Do all operations
     878                 :             :        * without assertions, then remove the file immediately.
     879                 :             :        */
     880                 :           1 :       _fseeki64 (f, 0xFFFFFFFFULL, SEEK_SET);
     881                 :           1 :       fprintf (f, "Hello 4GB World!");
     882                 :           1 :       fflush (f);
     883                 :           1 :       fclose (f);
     884                 :             : 
     885                 :           1 :       memset (&statbuf_ps, 0, sizeof (statbuf_ps));
     886                 :             : 
     887                 :           1 :       g_stat (ps, &statbuf_ps);
     888                 :             : 
     889                 :           1 :       gf_ps = g_file_new_for_path (ps);
     890                 :             : 
     891                 :           1 :       fi_ps = g_file_query_info (gf_ps,
     892                 :             :                                  G_FILE_ATTRIBUTE_STANDARD_SIZE ","
     893                 :             :                                  G_FILE_ATTRIBUTE_STANDARD_ALLOCATED_SIZE,
     894                 :             :                                  G_FILE_QUERY_INFO_NONE,
     895                 :             :                                  NULL, NULL);
     896                 :             : 
     897                 :           1 :       g_remove (ps);
     898                 :             : 
     899                 :           1 :       g_assert_true (g_file_info_has_attribute (fi_ps, G_FILE_ATTRIBUTE_STANDARD_SIZE));
     900                 :           1 :       g_assert_true (g_file_info_has_attribute (fi_ps, G_FILE_ATTRIBUTE_STANDARD_ALLOCATED_SIZE));
     901                 :             : 
     902                 :           1 :       size_ps = g_file_info_get_attribute_uint64 (fi_ps, G_FILE_ATTRIBUTE_STANDARD_SIZE);
     903                 :           1 :       alsize_ps = g_file_info_get_attribute_uint64 (fi_ps, G_FILE_ATTRIBUTE_STANDARD_ALLOCATED_SIZE);
     904                 :             : 
     905                 :             :       /* allocated size should small (usually - size of the FS cluster,
     906                 :             :        * let's assume it's less than 1 gigabyte),
     907                 :             :        * size should be more than 4 gigabytes,
     908                 :             :        * st_size should not exceed its 0xFFFFFFFF 32-bit limit,
     909                 :             :        * and should be nonzero (this also detects a failed g_stat() earlier).
     910                 :             :        */
     911                 :           1 :       g_assert_cmpuint (alsize_ps, <, 0x40000000);
     912                 :           1 :       g_assert_cmpuint (size_ps, >, G_GUINT64_CONSTANT (0xFFFFFFFF));
     913                 :           1 :       g_assert_cmpuint (statbuf_ps.st_size, >, 0);
     914                 :             : #if defined(_WIN64)
     915                 :           1 :       g_assert_cmpuint (statbuf_ps.st_size, ==, G_GUINT64_CONSTANT (0x10000000f));
     916                 :             : #else
     917                 :             :       g_assert_cmpuint (statbuf_ps.st_size, <=, 0xFFFFFFFF);
     918                 :             : #endif
     919                 :             : 
     920                 :           1 :       g_object_unref (fi_ps);
     921                 :           1 :       g_object_unref (gf_ps);
     922                 :           1 :     }
     923                 :             : 
     924                 :             :   /* Wa-a-ay past 02/07/2106 @ 6:28am (UTC),
     925                 :             :    * which is the date corresponding to 0xFFFFFFFF + 1.
     926                 :             :    * This is easier to check than Y2038 (0x80000000 + 1),
     927                 :             :    * since there's no need to worry about signedness this way.
     928                 :             :    */
     929                 :           1 :   st.wYear = 2106;
     930                 :           1 :   st.wMonth = 2;
     931                 :           1 :   st.wDay = 9;
     932                 :           1 :   st.wHour = 0;
     933                 :           1 :   st.wMinute = 0;
     934                 :           1 :   st.wSecond = 0;
     935                 :           1 :   st.wMilliseconds = 0;
     936                 :             : 
     937                 :           1 :   g_assert_true (SystemTimeToFileTime (&st, &ft));
     938                 :             : 
     939                 :           1 :   f = g_fopen (p0, "we");
     940                 :           1 :   g_assert_nonnull (f);
     941                 :             : 
     942                 :           1 :   h = (HANDLE) _get_osfhandle (fileno (f));
     943                 :           1 :   g_assert_cmpuint ((guintptr) h, !=, (guintptr) INVALID_HANDLE_VALUE);
     944                 :             : 
     945                 :           1 :   fprintf (f, "1");
     946                 :           1 :   fflush (f);
     947                 :             : 
     948                 :           1 :   g_assert_true (SetFileTime (h, &ft, &ft, &ft));
     949                 :             : 
     950                 :           1 :   fclose (f);
     951                 :             : 
     952                 :           1 :   f = g_fopen (p1, "we");
     953                 :           1 :   g_assert_nonnull (f);
     954                 :             : 
     955                 :           1 :   fclose (f);
     956                 :             : 
     957                 :           1 :   memset (&statbuf_p0, 0, sizeof (statbuf_p0));
     958                 :           1 :   memset (&statbuf_p1, 0, sizeof (statbuf_p1));
     959                 :             : 
     960                 :           1 :   g_assert_cmpint (g_stat (p0, &statbuf_p0), ==, 0);
     961                 :           1 :   g_assert_cmpint (g_stat (p1, &statbuf_p1), ==, 0);
     962                 :             : 
     963                 :           1 :   gf_p0 = g_file_new_for_path (p0);
     964                 :           1 :   gf_p1 = g_file_new_for_path (p1);
     965                 :             : 
     966                 :           1 :   fi_p0 = g_file_query_info (gf_p0,
     967                 :             :                              G_FILE_ATTRIBUTE_STANDARD_SIZE ","
     968                 :             :                              G_FILE_ATTRIBUTE_STANDARD_ALLOCATED_SIZE ","
     969                 :             :                              G_FILE_ATTRIBUTE_ID_FILE ","
     970                 :             :                              G_FILE_ATTRIBUTE_TIME_MODIFIED ","
     971                 :             :                              G_FILE_ATTRIBUTE_TIME_MODIFIED_USEC ","
     972                 :             :                              G_FILE_ATTRIBUTE_TIME_MODIFIED_NSEC,
     973                 :             :                              G_FILE_QUERY_INFO_NONE,
     974                 :             :                              NULL, NULL);
     975                 :             : 
     976                 :           1 :   fi_p1 = g_file_query_info (gf_p1,
     977                 :             :                              G_FILE_ATTRIBUTE_STANDARD_SIZE ","
     978                 :             :                              G_FILE_ATTRIBUTE_STANDARD_ALLOCATED_SIZE ","
     979                 :             :                              G_FILE_ATTRIBUTE_ID_FILE ","
     980                 :             :                              G_FILE_ATTRIBUTE_TIME_MODIFIED ","
     981                 :             :                              G_FILE_ATTRIBUTE_TIME_MODIFIED_USEC ","
     982                 :             :                              G_FILE_ATTRIBUTE_TIME_MODIFIED_NSEC,
     983                 :             :                              G_FILE_QUERY_INFO_NONE,
     984                 :             :                              NULL, NULL);
     985                 :             : 
     986                 :           1 :   g_assert_true (g_file_info_has_attribute (fi_p0, G_FILE_ATTRIBUTE_STANDARD_SIZE));
     987                 :           1 :   g_assert_true (g_file_info_has_attribute (fi_p0, G_FILE_ATTRIBUTE_STANDARD_ALLOCATED_SIZE));
     988                 :           1 :   g_assert_true (g_file_info_has_attribute (fi_p0, G_FILE_ATTRIBUTE_ID_FILE));
     989                 :           1 :   g_assert_true (g_file_info_has_attribute (fi_p0, G_FILE_ATTRIBUTE_TIME_MODIFIED));
     990                 :           1 :   g_assert_true (g_file_info_has_attribute (fi_p0, G_FILE_ATTRIBUTE_TIME_MODIFIED_USEC));
     991                 :           1 :   g_assert_true (g_file_info_has_attribute (fi_p0, G_FILE_ATTRIBUTE_TIME_MODIFIED_NSEC));
     992                 :             : 
     993                 :           1 :   g_assert_true (g_file_info_has_attribute (fi_p1, G_FILE_ATTRIBUTE_STANDARD_SIZE));
     994                 :           1 :   g_assert_true (g_file_info_has_attribute (fi_p1, G_FILE_ATTRIBUTE_STANDARD_ALLOCATED_SIZE));
     995                 :           1 :   g_assert_true (g_file_info_has_attribute (fi_p1, G_FILE_ATTRIBUTE_ID_FILE));
     996                 :           1 :   g_assert_true (g_file_info_has_attribute (fi_p1, G_FILE_ATTRIBUTE_TIME_MODIFIED));
     997                 :           1 :   g_assert_true (g_file_info_has_attribute (fi_p1, G_FILE_ATTRIBUTE_TIME_MODIFIED_USEC));
     998                 :           1 :   g_assert_true (g_file_info_has_attribute (fi_p1, G_FILE_ATTRIBUTE_TIME_MODIFIED_NSEC));
     999                 :             : 
    1000                 :           1 :   size_p0 = g_file_info_get_attribute_uint64 (fi_p0, G_FILE_ATTRIBUTE_STANDARD_SIZE);
    1001                 :           1 :   alsize_p0 = g_file_info_get_attribute_uint64 (fi_p0, G_FILE_ATTRIBUTE_STANDARD_ALLOCATED_SIZE);
    1002                 :             : 
    1003                 :             :   /* size should be 1, allocated size should be something else
    1004                 :             :    * (could be 0 or the size of the FS cluster, but never 1).
    1005                 :             :    */
    1006                 :           1 :   g_assert_cmpuint (size_p0, ==, statbuf_p0.st_size);
    1007                 :           1 :   g_assert_cmpuint (size_p0, ==, 1);
    1008                 :           1 :   g_assert_cmpuint (alsize_p0, !=, size_p0);
    1009                 :             : 
    1010                 :           1 :   id_p0 = g_file_info_get_attribute_string (fi_p0, G_FILE_ATTRIBUTE_ID_FILE);
    1011                 :           1 :   id_p1 = g_file_info_get_attribute_string (fi_p1, G_FILE_ATTRIBUTE_ID_FILE);
    1012                 :             : 
    1013                 :             :   /* st_ino from W32 stat() is useless for file identification.
    1014                 :             :    * It will be either 0, or it will be the same for both files.
    1015                 :             :    */
    1016                 :           1 :   g_assert_cmpint (statbuf_p0.st_ino, ==, statbuf_p1.st_ino);
    1017                 :           1 :   g_assert_cmpstr (id_p0, !=, id_p1);
    1018                 :             : 
    1019                 :           1 :   time_p0 = g_file_info_get_attribute_uint64 (fi_p0, G_FILE_ATTRIBUTE_TIME_MODIFIED);
    1020                 :             : 
    1021                 :             :   /* Check that GFileInfo doesn't suffer from Y2106 problem.
    1022                 :             :    * Don't check stat(), as its contents may vary depending on
    1023                 :             :    * the host platform architecture
    1024                 :             :    * (time fields are 32-bit on 32-bit Windows,
    1025                 :             :    *  and 64-bit on 64-bit Windows, usually),
    1026                 :             :    * so it *can* pass this test in some cases.
    1027                 :             :    */
    1028                 :           1 :   g_assert_cmpuint (time_p0, >, G_GUINT64_CONSTANT (0xFFFFFFFF));
    1029                 :             : 
    1030                 :           1 :   dt = g_file_info_get_modification_date_time (fi_p0);
    1031                 :           1 :   g_assert_nonnull (dt);
    1032                 :           1 :   dt2 = g_date_time_add (dt, G_USEC_PER_SEC / 100 * 200);
    1033                 :           1 :   g_object_unref (fi_p0);
    1034                 :           1 :   fi_p0 = g_file_info_new ();
    1035                 :           1 :   g_file_info_set_modification_date_time (fi_p0, dt2);
    1036                 :             : 
    1037                 :           1 :   g_assert_true (g_file_set_attributes_from_info (gf_p0,
    1038                 :           1 :                                                   fi_p0,
    1039                 :             :                                                   G_FILE_QUERY_INFO_NONE,
    1040                 :             :                                                   NULL,
    1041                 :             :                                                   NULL));
    1042                 :           1 :   g_date_time_unref (dt2);
    1043                 :           1 :   g_object_unref (fi_p0);
    1044                 :           1 :   fi_p0 = g_file_query_info (gf_p0,
    1045                 :             :                              G_FILE_ATTRIBUTE_TIME_MODIFIED ","
    1046                 :             :                              G_FILE_ATTRIBUTE_TIME_MODIFIED_USEC ","
    1047                 :             :                              G_FILE_ATTRIBUTE_TIME_MODIFIED_NSEC,
    1048                 :             :                              G_FILE_QUERY_INFO_NONE,
    1049                 :             :                              NULL, NULL);
    1050                 :           1 :   dt2 = g_file_info_get_modification_date_time (fi_p0);
    1051                 :           1 :   ts = g_date_time_difference (dt2, dt);
    1052                 :           1 :   g_assert_cmpint (ts, >, 0);
    1053                 :           1 :   g_assert_cmpint (ts, <, G_USEC_PER_SEC / 100 * 300);
    1054                 :             : 
    1055                 :           1 :   g_date_time_unref (dt);
    1056                 :           1 :   g_date_time_unref (dt2);
    1057                 :             : 
    1058                 :           1 :   g_file_info_set_attribute_uint64 (fi_p0,
    1059                 :             :                                     G_FILE_ATTRIBUTE_TIME_MODIFIED,
    1060                 :             :                                     one_sec_before_systemtime_limit);
    1061                 :           1 :   g_file_info_set_attribute_uint32 (fi_p0, G_FILE_ATTRIBUTE_TIME_MODIFIED_USEC, 0);
    1062                 :           1 :   g_assert_true (g_file_set_attributes_from_info (gf_p0,
    1063                 :           1 :                                                   fi_p0,
    1064                 :             :                                                   G_FILE_QUERY_INFO_NONE,
    1065                 :             :                                                   NULL,
    1066                 :             :                                                   NULL));
    1067                 :             : 
    1068                 :           1 :   g_file_info_set_attribute_uint64 (fi_p0,
    1069                 :             :                                    G_FILE_ATTRIBUTE_TIME_MODIFIED,
    1070                 :             :                                    one_sec_before_systemtime_limit + G_USEC_PER_SEC * 2);
    1071                 :           1 :   g_file_info_set_attribute_uint32 (fi_p0, G_FILE_ATTRIBUTE_TIME_MODIFIED_USEC, 0);
    1072                 :           2 :   retval = g_file_set_attributes_from_info (gf_p0,
    1073                 :           1 :                                             fi_p0,
    1074                 :             :                                             G_FILE_QUERY_INFO_NONE,
    1075                 :             :                                             NULL,
    1076                 :             :                                             &local_error);
    1077                 :           1 :   g_assert_error (local_error, G_IO_ERROR, G_IO_ERROR_INVALID_DATA);
    1078                 :           1 :   g_assert_false (retval);
    1079                 :           1 :   g_clear_error (&local_error);
    1080                 :             : 
    1081                 :           1 :   g_object_unref (fi_p0);
    1082                 :           1 :   g_object_unref (fi_p1);
    1083                 :           1 :   g_object_unref (gf_p0);
    1084                 :           1 :   g_object_unref (gf_p1);
    1085                 :           1 :   g_remove (p0);
    1086                 :           1 :   g_remove (p1);
    1087                 :           1 :   g_free (p0);
    1088                 :           1 :   g_free (p1);
    1089                 :           1 :   g_rmdir (tmp_dir);
    1090                 :           1 : }
    1091                 :             : #endif
    1092                 :             : 
    1093                 :             : static void
    1094                 :           2 : test_xattrs (void)
    1095                 :             : {
    1096                 :           2 :   GFile *file = NULL;
    1097                 :           2 :   GFileIOStream *stream = NULL;
    1098                 :           2 :   GFileInfo *file_info0 = NULL, *file_info1 = NULL, *file_info2 = NULL;
    1099                 :           2 :   GError *local_error = NULL;
    1100                 :             : 
    1101                 :           2 :   g_test_summary ("Test setting and getting escaped xattrs");
    1102                 :             : 
    1103                 :             :   /* Create a temporary file; no need to write anything to it. */
    1104                 :           2 :   file = g_file_new_tmp ("g-file-info-test-xattrs-XXXXXX", &stream, &local_error);
    1105                 :           2 :   g_assert_no_error (local_error);
    1106                 :           2 :   g_assert_nonnull (file);
    1107                 :             : 
    1108                 :           2 :   g_io_stream_close (G_IO_STREAM (stream), NULL, NULL);
    1109                 :           2 :   g_object_unref (stream);
    1110                 :             : 
    1111                 :             :   /* Check the existing xattrs. */
    1112                 :           2 :   file_info0 = g_file_query_info (file, "xattr::*", G_FILE_QUERY_INFO_NONE, NULL, &local_error);
    1113                 :           2 :   g_assert_no_error (local_error);
    1114                 :           2 :   g_assert_nonnull (file_info0);
    1115                 :             : 
    1116                 :             :   /* Set some new xattrs, with escaping and some embedded nuls. */
    1117                 :           2 :   g_file_info_set_attribute_string (file_info0, "xattr::escaped", "hello\\x82\\x80\\xbd");
    1118                 :           2 :   g_file_info_set_attribute_string (file_info0, "xattr::string", "hi there");
    1119                 :           2 :   g_file_info_set_attribute_string (file_info0, "xattr::embedded-nul", "hi\\x00there");
    1120                 :           2 :   g_file_info_set_attribute_string (file_info0, "xattr::deleteme", "this attribute will be deleted");
    1121                 :             : 
    1122                 :           2 :   g_file_set_attributes_from_info (file, file_info0, G_FILE_QUERY_INFO_NONE, NULL, &local_error);
    1123                 :             : 
    1124                 :           2 :   g_object_unref (file_info0);
    1125                 :             : 
    1126                 :           2 :   if (g_error_matches (local_error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED))
    1127                 :             :     {
    1128                 :           1 :       g_test_skip ("xattrs not supported on this file system");
    1129                 :           1 :       g_clear_error (&local_error);
    1130                 :           1 :     }
    1131                 :             :   else
    1132                 :             :     {
    1133                 :           1 :       g_assert_no_error (local_error);
    1134                 :             : 
    1135                 :             :       /* Check they were set properly. */
    1136                 :           1 :       file_info1 = g_file_query_info (file, "xattr::*", G_FILE_QUERY_INFO_NONE, NULL, &local_error);
    1137                 :           1 :       g_assert_no_error (local_error);
    1138                 :           1 :       g_assert_nonnull (file_info1);
    1139                 :             : 
    1140                 :           1 :       g_assert_true (g_file_info_has_namespace (file_info1, "xattr"));
    1141                 :             : 
    1142                 :           1 :       g_assert_cmpstr (g_file_info_get_attribute_string (file_info1, "xattr::escaped"), ==, "hello\\x82\\x80\\xbd");
    1143                 :           1 :       g_assert_cmpstr (g_file_info_get_attribute_string (file_info1, "xattr::string"), ==, "hi there");
    1144                 :           1 :       g_assert_cmpstr (g_file_info_get_attribute_string (file_info1, "xattr::embedded-nul"), ==, "hi\\x00there");
    1145                 :           1 :       g_assert_cmpstr (g_file_info_get_attribute_string (file_info1, "xattr::deleteme"), ==, "this attribute will be deleted");
    1146                 :             : 
    1147                 :           1 :       g_object_unref (file_info1);
    1148                 :             : 
    1149                 :             :       /* Check whether removing extended attributes works. */
    1150                 :           1 :       g_file_set_attribute (file, "xattr::deleteme", G_FILE_ATTRIBUTE_TYPE_INVALID, NULL, G_FILE_QUERY_INFO_NONE, NULL, &local_error);
    1151                 :           1 :       g_assert_no_error (local_error);
    1152                 :           1 :       file_info2 = g_file_query_info (file, "xattr::deleteme", G_FILE_QUERY_INFO_NONE, NULL, &local_error);
    1153                 :           1 :       g_assert_no_error (local_error);
    1154                 :           1 :       g_assert_nonnull (file_info2);
    1155                 :           1 :       g_assert_cmpstr (g_file_info_get_attribute_string (file_info2, "xattr::deleteme"), ==, NULL);
    1156                 :             : 
    1157                 :           1 :       g_object_unref (file_info2);
    1158                 :             :     }
    1159                 :             : 
    1160                 :             :   /* Tidy up. */
    1161                 :           2 :   g_file_delete (file, NULL, NULL);
    1162                 :             : 
    1163                 :           2 :   g_object_unref (file);
    1164                 :           2 : }
    1165                 :             : 
    1166                 :             : static void
    1167                 :           2 : test_set_modified_date_time_precision (void)
    1168                 :             : {
    1169                 :           2 :   GDateTime *modified = NULL;
    1170                 :           2 :   GFile *file = NULL;
    1171                 :           2 :   GFileIOStream *stream = NULL;
    1172                 :           2 :   GFileInfo *info = NULL;
    1173                 :           2 :   GError *local_error = NULL;
    1174                 :             : 
    1175                 :             : 
    1176                 :           2 :   g_test_summary ("Test that g_file_info_set_modified_date_time() preserves microseconds");
    1177                 :           2 :   g_test_bug ("https://gitlab.gnome.org/GNOME/glib/-/issues/3116");
    1178                 :             : 
    1179                 :           2 :   file = g_file_new_tmp ("g-file-info-test-set-modified-date-time-precision-XXXXXX", &stream, &local_error);
    1180                 :           2 :   g_assert_no_error (local_error);
    1181                 :             : 
    1182                 :           2 :   modified = g_date_time_new_from_iso8601 ("2000-01-01T00:00:00.123456Z", NULL);
    1183                 :             : 
    1184                 :           2 :   info = g_file_query_info (file,
    1185                 :             :   G_FILE_ATTRIBUTE_TIME_MODIFIED ","
    1186                 :             :         G_FILE_ATTRIBUTE_TIME_MODIFIED_USEC ","
    1187                 :             :         G_FILE_ATTRIBUTE_TIME_MODIFIED_NSEC, G_FILE_QUERY_INFO_NONE, NULL, &local_error);
    1188                 :           2 :   g_assert_no_error (local_error);
    1189                 :             : 
    1190                 :           2 :   g_file_info_set_modification_date_time (info, modified);
    1191                 :           2 :   g_assert_true (g_file_set_attributes_from_info (file, info, G_FILE_QUERY_INFO_NONE, NULL, &local_error));
    1192                 :           2 :   g_assert_no_error (local_error);
    1193                 :             : 
    1194                 :           2 :   g_clear_object (&info);
    1195                 :           2 :   g_clear_pointer (&modified, g_date_time_unref);
    1196                 :             : 
    1197                 :           2 :   info = g_file_query_info (file,
    1198                 :             :   G_FILE_ATTRIBUTE_TIME_MODIFIED ","
    1199                 :             :         G_FILE_ATTRIBUTE_TIME_MODIFIED_USEC ","
    1200                 :             :         G_FILE_ATTRIBUTE_TIME_MODIFIED_NSEC, G_FILE_QUERY_INFO_NONE, NULL, &local_error);
    1201                 :           2 :   g_assert_no_error (local_error);
    1202                 :             : 
    1203                 :           2 :   g_assert_cmpuint (g_file_info_get_attribute_uint32 (info, G_FILE_ATTRIBUTE_TIME_MODIFIED_USEC), ==, 123456);
    1204                 :             : 
    1205                 :           2 :   g_clear_object (&stream);
    1206                 :           2 :   g_clear_object (&info);
    1207                 :           2 :   g_clear_object (&file);
    1208                 :           2 : }
    1209                 :             : 
    1210                 :             : static void
    1211                 :           2 : test_set_symlink_target (void)
    1212                 :             : {
    1213                 :           2 :   GFile *file = NULL;
    1214                 :           2 :   GFileIOStream *stream = NULL;
    1215                 :           2 :   GFileInfo *info = NULL;
    1216                 :           2 :   GError *local_error = NULL;
    1217                 :             : 
    1218                 :           2 :   g_test_summary ("Test that g_file_info_set_symlink_target() sets symlink target correctly");
    1219                 :           2 :   g_test_bug ("https://gitlab.gnome.org/GNOME/glib/-/issues/3897");
    1220                 :             : 
    1221                 :             :   /* Create a temp file to reserve a unique filename for the test */
    1222                 :           2 :   file = g_file_new_tmp ("g-file-info-test-set-symlink-XXXXXX", &stream, &local_error);
    1223                 :           2 :   g_assert_no_error (local_error);
    1224                 :             : 
    1225                 :             :   /* Remove the file and recreate it as a symlink */
    1226                 :           2 :   g_file_delete (file, NULL, NULL);
    1227                 :             : 
    1228                 :           2 :   if (!g_file_make_symbolic_link (file, "initial-target", NULL, &local_error) &&
    1229                 :           1 :       g_error_matches (local_error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED))
    1230                 :             :     {
    1231                 :           1 :       g_clear_error (&local_error);
    1232                 :           1 :       g_test_skip ("Skipping testing symbolic links as they’re not supported on this system");
    1233                 :           1 :       return;
    1234                 :             :     }
    1235                 :             : 
    1236                 :           1 :   g_assert_no_error (local_error);
    1237                 :             : 
    1238                 :           1 :   info = g_file_query_info (file, G_FILE_ATTRIBUTE_STANDARD_SYMLINK_TARGET,
    1239                 :             :                             G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, NULL, &local_error);
    1240                 :           1 :   g_assert_no_error (local_error);
    1241                 :             : 
    1242                 :             :   /* Try setting the symlink target when there isn’t one already set via GIO */
    1243                 :           1 :   g_file_info_set_symlink_target (info, "symlink-target");
    1244                 :           1 :   g_file_set_attributes_from_info (file, info, G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, NULL, &local_error);
    1245                 :           1 :   g_assert_no_error (local_error);
    1246                 :             : 
    1247                 :           1 :   g_clear_object (&info);
    1248                 :             : 
    1249                 :           1 :   info = g_file_query_info (file, G_FILE_ATTRIBUTE_STANDARD_SYMLINK_TARGET,
    1250                 :             :                             G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, NULL, &local_error);
    1251                 :           1 :   g_assert_no_error (local_error);
    1252                 :             : 
    1253                 :           1 :   g_assert_cmpstr (g_file_info_get_symlink_target (info), ==, "symlink-target");
    1254                 :             : 
    1255                 :             :   /* Now try setting it again when there is one already */
    1256                 :           1 :   g_file_info_set_symlink_target (info, "symlink-target2");
    1257                 :           1 :   g_file_set_attributes_from_info (file, info, G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, NULL, &local_error);
    1258                 :           1 :   g_assert_no_error (local_error);
    1259                 :             : 
    1260                 :           1 :   g_clear_object (&info);
    1261                 :             : 
    1262                 :           1 :   info = g_file_query_info (file, G_FILE_ATTRIBUTE_STANDARD_SYMLINK_TARGET,
    1263                 :             :                             G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, NULL, &local_error);
    1264                 :           1 :   g_assert_no_error (local_error);
    1265                 :             : 
    1266                 :           1 :   g_assert_cmpstr (g_file_info_get_symlink_target (info), ==, "symlink-target2");
    1267                 :             : 
    1268                 :             :   /* Clean up */
    1269                 :           1 :   g_file_delete (file, NULL, NULL);
    1270                 :             : 
    1271                 :           1 :   g_clear_object (&stream);
    1272                 :           1 :   g_clear_object (&info);
    1273                 :           1 :   g_clear_object (&file);
    1274                 :           1 : }
    1275                 :             : 
    1276                 :             : int
    1277                 :           2 : main (int   argc,
    1278                 :             :       char *argv[])
    1279                 :             : {
    1280                 :           2 :   g_test_init (&argc, &argv, NULL);
    1281                 :             : 
    1282                 :           2 :   g_test_add_func ("/g-file-info/test_g_file_info", test_g_file_info);
    1283                 :           2 :   g_test_add_func ("/g-file-info/test_g_file_info/modification-time", test_g_file_info_modification_time);
    1284                 :           2 :   g_test_add_func ("/g-file-info/test_g_file_info/access-time", test_g_file_info_access_time);
    1285                 :           2 :   g_test_add_func ("/g-file-info/test_g_file_info/creation-time", test_g_file_info_creation_time);
    1286                 :           2 :   g_test_add_func ("/g-file-info/test_g_file_info/icons", test_g_file_info_icons);
    1287                 :             : #ifdef G_OS_WIN32
    1288                 :           1 :   g_test_add_func ("/g-file-info/internal-enhanced-stdio", test_internal_enhanced_stdio);
    1289                 :             : #endif
    1290                 :           2 :   g_test_add_func ("/g-file-info/xattrs", test_xattrs);
    1291                 :           2 :   g_test_add_func ("/g-file-info/set-modified-date-time-precision", test_set_modified_date_time_precision);
    1292                 :           2 :   g_test_add_func ("/g-file-info/set-symlink-target", test_set_symlink_target);
    1293                 :             :   
    1294                 :           2 :   return g_test_run();
    1295                 :             : }
        

Generated by: LCOV version 2.0-1