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

Generated by: LCOV version 1.14