(root)/
glib-2.79.0/
gio/
tests/
trash.c
       1  /*
       2   * Copyright (C) 2018 Red Hat, Inc.
       3   *
       4   * SPDX-License-Identifier: LGPL-2.1-or-later
       5   *
       6   * This library is free software; you can redistribute it and/or modify
       7   * it under the terms of the GNU Lesser General Public License as
       8   * published by the Free Software Foundation; either version 2.1 of the
       9   * licence, or (at your option) any later version.
      10   *
      11   * This is distributed in the hope that it will be useful, but WITHOUT
      12   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
      13   * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
      14   * License for more details.
      15   *
      16   * You should have received a copy of the GNU Lesser General Public License
      17   * along with this library; if not, see <http://www.gnu.org/licenses/>.
      18   */
      19  
      20  #include <glib.h>
      21  
      22  #ifndef G_OS_UNIX
      23  #error This is a Unix-specific test
      24  #endif
      25  
      26  #include <glib/gstdio.h>
      27  #include <gio/gio.h>
      28  #include <gio/gunixmounts.h>
      29  
      30  /* Test that g_file_trash() returns G_IO_ERROR_NOT_SUPPORTED for files on system mounts. */
      31  static void
      32  test_trash_not_supported (void)
      33  {
      34    GFile *file;
      35    GFileIOStream *stream;
      36    GUnixMountEntry *mount;
      37    GFileInfo *info;
      38    GError *error = NULL;
      39    gboolean ret;
      40    gchar *parent_dirname;
      41    GStatBuf parent_stat, home_stat;
      42  
      43    g_test_bug ("https://gitlab.gnome.org/GNOME/glib/issues/251");
      44  
      45    /* The test assumes that tmp file is located on system internal mount. */
      46    file = g_file_new_tmp ("test-trashXXXXXX", &stream, &error);
      47    parent_dirname = g_path_get_dirname (g_file_peek_path (file));
      48    g_assert_no_error (error);
      49    g_assert_cmpint (g_stat (parent_dirname, &parent_stat), ==, 0);
      50    g_test_message ("File: %s (parent st_dev: %" G_GUINT64_FORMAT ")",
      51                    g_file_peek_path (file), (guint64) parent_stat.st_dev);
      52  
      53    g_assert_cmpint (g_stat (g_get_home_dir (), &home_stat), ==, 0);
      54    g_test_message ("Home: %s (st_dev: %" G_GUINT64_FORMAT ")",
      55                    g_get_home_dir (), (guint64) home_stat.st_dev);
      56  
      57    if (parent_stat.st_dev == home_stat.st_dev)
      58      {
      59        g_test_skip ("The file has to be on another filesystem than the home trash to run this test");
      60  
      61        g_free (parent_dirname);
      62        g_object_unref (stream);
      63        g_object_unref (file);
      64  
      65        return;
      66      }
      67  
      68    mount = g_unix_mount_for (g_file_peek_path (file), NULL);
      69    g_assert_true (mount == NULL || g_unix_mount_is_system_internal (mount));
      70    g_test_message ("Mount: %s", (mount != NULL) ? g_unix_mount_get_mount_path (mount) : "(null)");
      71    g_clear_pointer (&mount, g_unix_mount_free);
      72  
      73    /* g_file_trash() shouldn't be supported on system internal mounts,
      74     * because those are not monitored by gvfsd-trash.
      75     */
      76    ret = g_file_trash (file, NULL, &error);
      77    g_assert_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED);
      78    g_test_message ("Error: %s", error->message);
      79    g_assert_false (ret);
      80    g_clear_error (&error);
      81  
      82    info = g_file_query_info (file,
      83                              G_FILE_ATTRIBUTE_ACCESS_CAN_TRASH,
      84                              G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
      85                              NULL,
      86                              &error);
      87    g_assert_no_error (error);
      88  
      89    g_assert_false (g_file_info_get_attribute_boolean (info,
      90                                                       G_FILE_ATTRIBUTE_ACCESS_CAN_TRASH));
      91  
      92    g_io_stream_close (G_IO_STREAM (stream), NULL, &error);
      93    g_assert_no_error (error);
      94  
      95    g_free (parent_dirname);
      96    g_object_unref (info);
      97    g_object_unref (stream);
      98    g_object_unref (file);
      99  }
     100  
     101  /* Test that symlinks are properly expaned when looking for topdir (e.g. for trash folder). */
     102  static void
     103  test_trash_symlinks (void)
     104  {
     105    GFile *symlink;
     106    GUnixMountEntry *target_mount, *tmp_mount, *symlink_mount, *target_over_symlink_mount;
     107    gchar *target, *tmp, *target_over_symlink;
     108    GError *error = NULL;
     109  
     110    g_test_bug ("https://gitlab.gnome.org/GNOME/glib/issues/1522");
     111  
     112    target = g_build_filename (g_get_home_dir (), ".local", NULL);
     113  
     114    if (!g_file_test (target, G_FILE_TEST_IS_DIR))
     115      {
     116        g_test_skip_printf ("Directory '%s' does not exist", target);
     117        g_free (target);
     118        return;
     119      }
     120  
     121    target_mount = g_unix_mount_for (target, NULL);
     122  
     123    if (target_mount == NULL)
     124      {
     125        g_test_skip_printf ("Unable to determine mount point for %s", target);
     126        g_free (target);
     127        return;
     128      }
     129  
     130    g_assert_nonnull (target_mount);
     131    g_test_message ("Target: %s (mount: %s)", target, g_unix_mount_get_mount_path (target_mount));
     132  
     133    tmp = g_dir_make_tmp ("test-trashXXXXXX", &error);
     134    g_assert_no_error (error);
     135    g_assert_nonnull (tmp);
     136    tmp_mount = g_unix_mount_for (tmp, NULL);
     137  
     138    if (tmp_mount == NULL)
     139      {
     140        g_test_skip_printf ("Unable to determine mount point for %s", tmp);
     141        g_unix_mount_free (target_mount);
     142        g_free (target);
     143        g_free (tmp);
     144        return;
     145      }
     146  
     147    g_assert_nonnull (tmp_mount);
     148    g_test_message ("Tmp: %s (mount: %s)", tmp, g_unix_mount_get_mount_path (tmp_mount));
     149  
     150    if (g_unix_mount_compare (target_mount, tmp_mount) == 0)
     151      {
     152        g_test_skip ("The tmp has to be on another mount than the home to run this test");
     153  
     154        g_unix_mount_free (tmp_mount);
     155        g_free (tmp);
     156        g_unix_mount_free (target_mount);
     157        g_free (target);
     158  
     159        return;
     160      }
     161  
     162    symlink = g_file_new_build_filename (tmp, "symlink", NULL);
     163    g_file_make_symbolic_link (symlink, g_get_home_dir (), NULL, &error);
     164    g_assert_no_error (error);
     165  
     166    symlink_mount = g_unix_mount_for (g_file_peek_path (symlink), NULL);
     167    g_assert_nonnull (symlink_mount);
     168    g_test_message ("Symlink: %s (mount: %s)", g_file_peek_path (symlink), g_unix_mount_get_mount_path (symlink_mount));
     169  
     170    g_assert_cmpint (g_unix_mount_compare (symlink_mount, tmp_mount), ==, 0);
     171  
     172    target_over_symlink = g_build_filename (g_file_peek_path (symlink),
     173                                            ".local",
     174                                            NULL);
     175    target_over_symlink_mount = g_unix_mount_for (target_over_symlink, NULL);
     176    g_assert_nonnull (symlink_mount);
     177    g_test_message ("Target over symlink: %s (mount: %s)", target_over_symlink, g_unix_mount_get_mount_path (target_over_symlink_mount));
     178  
     179    g_assert_cmpint (g_unix_mount_compare (target_over_symlink_mount, target_mount), ==, 0);
     180  
     181    g_unix_mount_free (target_over_symlink_mount);
     182    g_unix_mount_free (symlink_mount);
     183    g_free (target_over_symlink);
     184    g_object_unref (symlink);
     185    g_unix_mount_free (tmp_mount);
     186    g_free (tmp);
     187    g_unix_mount_free (target_mount);
     188    g_free (target);
     189  }
     190  
     191  int
     192  main (int argc, char *argv[])
     193  {
     194    g_test_init (&argc, &argv, NULL);
     195  
     196    g_test_add_func ("/trash/not-supported", test_trash_not_supported);
     197    g_test_add_func ("/trash/symlinks", test_trash_symlinks);
     198  
     199    return g_test_run ();
     200  }