13781343738de4abddf56982325a77bd70a98cd26Alexander Larsson/* GIO - GLib Input, Output and Streaming Library 23781343738de4abddf56982325a77bd70a98cd26Alexander Larsson * 33781343738de4abddf56982325a77bd70a98cd26Alexander Larsson * Copyright (C) 2006-2007 Red Hat, Inc. 43781343738de4abddf56982325a77bd70a98cd26Alexander Larsson * 53781343738de4abddf56982325a77bd70a98cd26Alexander Larsson * This library is free software; you can redistribute it and/or 63781343738de4abddf56982325a77bd70a98cd26Alexander Larsson * modify it under the terms of the GNU Lesser General Public 73781343738de4abddf56982325a77bd70a98cd26Alexander Larsson * License as published by the Free Software Foundation; either 83781343738de4abddf56982325a77bd70a98cd26Alexander Larsson * version 2 of the License, or (at your option) any later version. 93781343738de4abddf56982325a77bd70a98cd26Alexander Larsson * 103781343738de4abddf56982325a77bd70a98cd26Alexander Larsson * This library is distributed in the hope that it will be useful, 113781343738de4abddf56982325a77bd70a98cd26Alexander Larsson * but WITHOUT ANY WARRANTY; without even the implied warranty of 123781343738de4abddf56982325a77bd70a98cd26Alexander Larsson * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 133781343738de4abddf56982325a77bd70a98cd26Alexander Larsson * Lesser General Public License for more details. 143781343738de4abddf56982325a77bd70a98cd26Alexander Larsson * 153781343738de4abddf56982325a77bd70a98cd26Alexander Larsson * You should have received a copy of the GNU Lesser General 163781343738de4abddf56982325a77bd70a98cd26Alexander Larsson * Public License along with this library; if not, write to the 173781343738de4abddf56982325a77bd70a98cd26Alexander Larsson * Free Software Foundation, Inc., 59 Temple Place, Suite 330, 183781343738de4abddf56982325a77bd70a98cd26Alexander Larsson * Boston, MA 02111-1307, USA. 193781343738de4abddf56982325a77bd70a98cd26Alexander Larsson * 203781343738de4abddf56982325a77bd70a98cd26Alexander Larsson * Author: Alexander Larsson <alexl@redhat.com> 213781343738de4abddf56982325a77bd70a98cd26Alexander Larsson */ 223781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 23761424465aaad736916b029383483b6ac419d831Johan Dahlin#include "config.h" 243781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 253781343738de4abddf56982325a77bd70a98cd26Alexander Larsson#include <sys/types.h> 263781343738de4abddf56982325a77bd70a98cd26Alexander Larsson#include <sys/stat.h> 273781343738de4abddf56982325a77bd70a98cd26Alexander Larsson#include <string.h> 283781343738de4abddf56982325a77bd70a98cd26Alexander Larsson#include <errno.h> 293781343738de4abddf56982325a77bd70a98cd26Alexander Larsson#include <fcntl.h> 30a33f8a7564cc649daf0dca0d67daac8430808cf9Hans Breuer#ifdef HAVE_UNISTD_H 313781343738de4abddf56982325a77bd70a98cd26Alexander Larsson#include <unistd.h> 32a33f8a7564cc649daf0dca0d67daac8430808cf9Hans Breuer#endif 333781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 343781343738de4abddf56982325a77bd70a98cd26Alexander Larsson#if HAVE_SYS_STATFS_H 353781343738de4abddf56982325a77bd70a98cd26Alexander Larsson#include <sys/statfs.h> 363781343738de4abddf56982325a77bd70a98cd26Alexander Larsson#endif 373781343738de4abddf56982325a77bd70a98cd26Alexander Larsson#if HAVE_SYS_STATVFS_H 383781343738de4abddf56982325a77bd70a98cd26Alexander Larsson#include <sys/statvfs.h> 393781343738de4abddf56982325a77bd70a98cd26Alexander Larsson#endif 403781343738de4abddf56982325a77bd70a98cd26Alexander Larsson#if HAVE_SYS_VFS_H 413781343738de4abddf56982325a77bd70a98cd26Alexander Larsson#include <sys/vfs.h> 423781343738de4abddf56982325a77bd70a98cd26Alexander Larsson#elif HAVE_SYS_MOUNT_H 433781343738de4abddf56982325a77bd70a98cd26Alexander Larsson#if HAVE_SYS_PARAM_H 443781343738de4abddf56982325a77bd70a98cd26Alexander Larsson#include <sys/param.h> 453781343738de4abddf56982325a77bd70a98cd26Alexander Larsson#endif 463781343738de4abddf56982325a77bd70a98cd26Alexander Larsson#include <sys/mount.h> 473781343738de4abddf56982325a77bd70a98cd26Alexander Larsson#endif 483781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 49b221d1b36d0ed5ce22f21a986a352f6a92345c30Alexander Larsson#ifndef O_BINARY 50b221d1b36d0ed5ce22f21a986a352f6a92345c30Alexander Larsson#define O_BINARY 0 51b221d1b36d0ed5ce22f21a986a352f6a92345c30Alexander Larsson#endif 52b221d1b36d0ed5ce22f21a986a352f6a92345c30Alexander Larsson 533781343738de4abddf56982325a77bd70a98cd26Alexander Larsson#if defined(HAVE_STATFS) && defined(HAVE_STATVFS) 543781343738de4abddf56982325a77bd70a98cd26Alexander Larsson/* Some systems have both statfs and statvfs, pick the 553781343738de4abddf56982325a77bd70a98cd26Alexander Larsson most "native" for these */ 56563eb127486d337cf5aef58637328220a5c9fcc8Matthias Clasen# if !defined(HAVE_STRUCT_STATFS_F_BAVAIL) 57563eb127486d337cf5aef58637328220a5c9fcc8Matthias Clasen /* on solaris and irix, statfs doesn't even have the 583781343738de4abddf56982325a77bd70a98cd26Alexander Larsson f_bavail field */ 593781343738de4abddf56982325a77bd70a98cd26Alexander Larsson# define USE_STATVFS 603781343738de4abddf56982325a77bd70a98cd26Alexander Larsson# else 613781343738de4abddf56982325a77bd70a98cd26Alexander Larsson /* at least on linux, statfs is the actual syscall */ 623781343738de4abddf56982325a77bd70a98cd26Alexander Larsson# define USE_STATFS 633781343738de4abddf56982325a77bd70a98cd26Alexander Larsson# endif 643781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 653781343738de4abddf56982325a77bd70a98cd26Alexander Larsson#elif defined(HAVE_STATFS) 663781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 673781343738de4abddf56982325a77bd70a98cd26Alexander Larsson# define USE_STATFS 683781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 693781343738de4abddf56982325a77bd70a98cd26Alexander Larsson#elif defined(HAVE_STATVFS) 703781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 713781343738de4abddf56982325a77bd70a98cd26Alexander Larsson# define USE_STATVFS 723781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 733781343738de4abddf56982325a77bd70a98cd26Alexander Larsson#endif 743781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 753d93bf6968884d75dd2706ef85e2014305eb92f2Cody Russell#include "gfileattribute.h" 763781343738de4abddf56982325a77bd70a98cd26Alexander Larsson#include "glocalfile.h" 773781343738de4abddf56982325a77bd70a98cd26Alexander Larsson#include "glocalfileinfo.h" 783781343738de4abddf56982325a77bd70a98cd26Alexander Larsson#include "glocalfileenumerator.h" 793781343738de4abddf56982325a77bd70a98cd26Alexander Larsson#include "glocalfileinputstream.h" 803781343738de4abddf56982325a77bd70a98cd26Alexander Larsson#include "glocalfileoutputstream.h" 813781343738de4abddf56982325a77bd70a98cd26Alexander Larsson#include "glocaldirectorymonitor.h" 823781343738de4abddf56982325a77bd70a98cd26Alexander Larsson#include "glocalfilemonitor.h" 833ca9fd4dbb134088bf70f2f6584f14a559e6820aDavid Zeuthen#include "gmountprivate.h" 843d93bf6968884d75dd2706ef85e2014305eb92f2Cody Russell#include "gunixmounts.h" 853d93bf6968884d75dd2706ef85e2014305eb92f2Cody Russell#include "gioerror.h" 863781343738de4abddf56982325a77bd70a98cd26Alexander Larsson#include <glib/gstdio.h> 873781343738de4abddf56982325a77bd70a98cd26Alexander Larsson#include "glibintl.h" 883781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 89a33f8a7564cc649daf0dca0d67daac8430808cf9Hans Breuer#ifdef G_OS_WIN32 901d568f35d13d7cf0206439a7a94b7fd3abd92fa3Alexander Larsson#define _WIN32_WINNT 0x0500 91a33f8a7564cc649daf0dca0d67daac8430808cf9Hans Breuer#include <windows.h> 92a33f8a7564cc649daf0dca0d67daac8430808cf9Hans Breuer#include <io.h> 93a33f8a7564cc649daf0dca0d67daac8430808cf9Hans Breuer#include <direct.h> 94a33f8a7564cc649daf0dca0d67daac8430808cf9Hans Breuer 9593bd705e78a4b224e0862e42a2384b5dad4f31a6Tor Lillqvist#ifndef FILE_READ_ONLY_VOLUME 9693bd705e78a4b224e0862e42a2384b5dad4f31a6Tor Lillqvist#define FILE_READ_ONLY_VOLUME 0x00080000 9793bd705e78a4b224e0862e42a2384b5dad4f31a6Tor Lillqvist#endif 9893bd705e78a4b224e0862e42a2384b5dad4f31a6Tor Lillqvist 99a33f8a7564cc649daf0dca0d67daac8430808cf9Hans Breuer#ifndef S_ISDIR 100a33f8a7564cc649daf0dca0d67daac8430808cf9Hans Breuer#define S_ISDIR(m) (((m) & _S_IFMT) == _S_IFDIR) 101a33f8a7564cc649daf0dca0d67daac8430808cf9Hans Breuer#endif 102a33f8a7564cc649daf0dca0d67daac8430808cf9Hans Breuer#ifndef S_ISLNK 103a33f8a7564cc649daf0dca0d67daac8430808cf9Hans Breuer#define S_ISLNK(m) (0) 104a33f8a7564cc649daf0dca0d67daac8430808cf9Hans Breuer#endif 105a33f8a7564cc649daf0dca0d67daac8430808cf9Hans Breuer#endif 106a33f8a7564cc649daf0dca0d67daac8430808cf9Hans Breuer 1077f3280230bc9448a5750fc17a6eabef691ba25f4Alexander Larsson#include "gioalias.h" 1087f3280230bc9448a5750fc17a6eabef691ba25f4Alexander Larsson 10954300dde6d77867aa53e60a2bdfd69cb9e644315Matthias Clasenstatic void g_local_file_file_iface_init (GFileIface *iface); 1103781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 1113781343738de4abddf56982325a77bd70a98cd26Alexander Larssonstatic GFileAttributeInfoList *local_writable_attributes = NULL; 1123781343738de4abddf56982325a77bd70a98cd26Alexander Larssonstatic GFileAttributeInfoList *local_writable_namespaces = NULL; 1133781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 1143781343738de4abddf56982325a77bd70a98cd26Alexander Larssonstruct _GLocalFile 1153781343738de4abddf56982325a77bd70a98cd26Alexander Larsson{ 1163781343738de4abddf56982325a77bd70a98cd26Alexander Larsson GObject parent_instance; 1173781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 1183781343738de4abddf56982325a77bd70a98cd26Alexander Larsson char *filename; 1193781343738de4abddf56982325a77bd70a98cd26Alexander Larsson}; 1203781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 121d9594f5709313d6e7a8a4f3e5f3b23fc72017417Alexander Larsson#define g_local_file_get_type _g_local_file_get_type 1223781343738de4abddf56982325a77bd70a98cd26Alexander LarssonG_DEFINE_TYPE_WITH_CODE (GLocalFile, g_local_file, G_TYPE_OBJECT, 1233781343738de4abddf56982325a77bd70a98cd26Alexander Larsson G_IMPLEMENT_INTERFACE (G_TYPE_FILE, 1243781343738de4abddf56982325a77bd70a98cd26Alexander Larsson g_local_file_file_iface_init)) 1253781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 12654300dde6d77867aa53e60a2bdfd69cb9e644315Matthias Clasenstatic char *find_mountpoint_for (const char *file, dev_t dev); 1273781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 1283781343738de4abddf56982325a77bd70a98cd26Alexander Larssonstatic void 1293781343738de4abddf56982325a77bd70a98cd26Alexander Larssong_local_file_finalize (GObject *object) 1303781343738de4abddf56982325a77bd70a98cd26Alexander Larsson{ 1313781343738de4abddf56982325a77bd70a98cd26Alexander Larsson GLocalFile *local; 1323781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 1333781343738de4abddf56982325a77bd70a98cd26Alexander Larsson local = G_LOCAL_FILE (object); 1343781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 1353781343738de4abddf56982325a77bd70a98cd26Alexander Larsson g_free (local->filename); 136a4427bfff5d31499dc0b46fa3f734bc92f7d0dd5Michael Natterer 137a4427bfff5d31499dc0b46fa3f734bc92f7d0dd5Michael Natterer G_OBJECT_CLASS (g_local_file_parent_class)->finalize (object); 1383781343738de4abddf56982325a77bd70a98cd26Alexander Larsson} 1393781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 1403781343738de4abddf56982325a77bd70a98cd26Alexander Larssonstatic void 1413781343738de4abddf56982325a77bd70a98cd26Alexander Larssong_local_file_class_init (GLocalFileClass *klass) 1423781343738de4abddf56982325a77bd70a98cd26Alexander Larsson{ 1433781343738de4abddf56982325a77bd70a98cd26Alexander Larsson GObjectClass *gobject_class = G_OBJECT_CLASS (klass); 1443781343738de4abddf56982325a77bd70a98cd26Alexander Larsson GFileAttributeInfoList *list; 1453781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 1463781343738de4abddf56982325a77bd70a98cd26Alexander Larsson gobject_class->finalize = g_local_file_finalize; 1473781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 1483781343738de4abddf56982325a77bd70a98cd26Alexander Larsson /* Set up attribute lists */ 1493781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 1503781343738de4abddf56982325a77bd70a98cd26Alexander Larsson /* Writable attributes: */ 1513781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 1523781343738de4abddf56982325a77bd70a98cd26Alexander Larsson list = g_file_attribute_info_list_new (); 1533781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 1543781343738de4abddf56982325a77bd70a98cd26Alexander Larsson g_file_attribute_info_list_add (list, 1553781343738de4abddf56982325a77bd70a98cd26Alexander Larsson G_FILE_ATTRIBUTE_UNIX_MODE, 1563781343738de4abddf56982325a77bd70a98cd26Alexander Larsson G_FILE_ATTRIBUTE_TYPE_UINT32, 1578a9c5b6d3c25bbe2eddb815a1c95af3cc1d927dbAlexander Larsson G_FILE_ATTRIBUTE_INFO_COPY_WITH_FILE | 1584cb6eab803662aebb2a81fe97832dd7576391331Alexander Larsson G_FILE_ATTRIBUTE_INFO_COPY_WHEN_MOVED); 1593781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 1603781343738de4abddf56982325a77bd70a98cd26Alexander Larsson#ifdef HAVE_CHOWN 1613781343738de4abddf56982325a77bd70a98cd26Alexander Larsson g_file_attribute_info_list_add (list, 1623781343738de4abddf56982325a77bd70a98cd26Alexander Larsson G_FILE_ATTRIBUTE_UNIX_UID, 1633781343738de4abddf56982325a77bd70a98cd26Alexander Larsson G_FILE_ATTRIBUTE_TYPE_UINT32, 1644cb6eab803662aebb2a81fe97832dd7576391331Alexander Larsson G_FILE_ATTRIBUTE_INFO_COPY_WHEN_MOVED); 1653781343738de4abddf56982325a77bd70a98cd26Alexander Larsson g_file_attribute_info_list_add (list, 1663781343738de4abddf56982325a77bd70a98cd26Alexander Larsson G_FILE_ATTRIBUTE_UNIX_GID, 1673781343738de4abddf56982325a77bd70a98cd26Alexander Larsson G_FILE_ATTRIBUTE_TYPE_UINT32, 1684cb6eab803662aebb2a81fe97832dd7576391331Alexander Larsson G_FILE_ATTRIBUTE_INFO_COPY_WHEN_MOVED); 1693781343738de4abddf56982325a77bd70a98cd26Alexander Larsson#endif 1703781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 1713781343738de4abddf56982325a77bd70a98cd26Alexander Larsson#ifdef HAVE_SYMLINK 1723781343738de4abddf56982325a77bd70a98cd26Alexander Larsson g_file_attribute_info_list_add (list, 17371768c8426f0d6c580368f6c1d3fc339d2041be0Alexander Larsson G_FILE_ATTRIBUTE_STANDARD_SYMLINK_TARGET, 1743781343738de4abddf56982325a77bd70a98cd26Alexander Larsson G_FILE_ATTRIBUTE_TYPE_BYTE_STRING, 1753781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 0); 1763781343738de4abddf56982325a77bd70a98cd26Alexander Larsson#endif 1773781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 1783781343738de4abddf56982325a77bd70a98cd26Alexander Larsson#ifdef HAVE_UTIMES 1793781343738de4abddf56982325a77bd70a98cd26Alexander Larsson g_file_attribute_info_list_add (list, 1803781343738de4abddf56982325a77bd70a98cd26Alexander Larsson G_FILE_ATTRIBUTE_TIME_MODIFIED, 1813781343738de4abddf56982325a77bd70a98cd26Alexander Larsson G_FILE_ATTRIBUTE_TYPE_UINT64, 18239b3b4148456e596fa0ada24d47bcc76c1984172Alexander Larsson G_FILE_ATTRIBUTE_INFO_COPY_WITH_FILE | 1834cb6eab803662aebb2a81fe97832dd7576391331Alexander Larsson G_FILE_ATTRIBUTE_INFO_COPY_WHEN_MOVED); 1843781343738de4abddf56982325a77bd70a98cd26Alexander Larsson g_file_attribute_info_list_add (list, 1853781343738de4abddf56982325a77bd70a98cd26Alexander Larsson G_FILE_ATTRIBUTE_TIME_MODIFIED_USEC, 1863781343738de4abddf56982325a77bd70a98cd26Alexander Larsson G_FILE_ATTRIBUTE_TYPE_UINT32, 18739b3b4148456e596fa0ada24d47bcc76c1984172Alexander Larsson G_FILE_ATTRIBUTE_INFO_COPY_WITH_FILE | 1884cb6eab803662aebb2a81fe97832dd7576391331Alexander Larsson G_FILE_ATTRIBUTE_INFO_COPY_WHEN_MOVED); 18939b3b4148456e596fa0ada24d47bcc76c1984172Alexander Larsson /* When copying, the target file is accessed. Replicating 19039b3b4148456e596fa0ada24d47bcc76c1984172Alexander Larsson * the source access time does not make sense in this case. 19139b3b4148456e596fa0ada24d47bcc76c1984172Alexander Larsson */ 1923781343738de4abddf56982325a77bd70a98cd26Alexander Larsson g_file_attribute_info_list_add (list, 1933781343738de4abddf56982325a77bd70a98cd26Alexander Larsson G_FILE_ATTRIBUTE_TIME_ACCESS, 1943781343738de4abddf56982325a77bd70a98cd26Alexander Larsson G_FILE_ATTRIBUTE_TYPE_UINT64, 1954cb6eab803662aebb2a81fe97832dd7576391331Alexander Larsson G_FILE_ATTRIBUTE_INFO_COPY_WHEN_MOVED); 1963781343738de4abddf56982325a77bd70a98cd26Alexander Larsson g_file_attribute_info_list_add (list, 1973781343738de4abddf56982325a77bd70a98cd26Alexander Larsson G_FILE_ATTRIBUTE_TIME_ACCESS_USEC, 1983781343738de4abddf56982325a77bd70a98cd26Alexander Larsson G_FILE_ATTRIBUTE_TYPE_UINT32, 1994cb6eab803662aebb2a81fe97832dd7576391331Alexander Larsson G_FILE_ATTRIBUTE_INFO_COPY_WHEN_MOVED); 2003781343738de4abddf56982325a77bd70a98cd26Alexander Larsson#endif 2013781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 2023781343738de4abddf56982325a77bd70a98cd26Alexander Larsson local_writable_attributes = list; 2033781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 2043781343738de4abddf56982325a77bd70a98cd26Alexander Larsson /* Writable namespaces: */ 2053781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 2063781343738de4abddf56982325a77bd70a98cd26Alexander Larsson list = g_file_attribute_info_list_new (); 2073781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 2083781343738de4abddf56982325a77bd70a98cd26Alexander Larsson#ifdef HAVE_XATTR 2093781343738de4abddf56982325a77bd70a98cd26Alexander Larsson g_file_attribute_info_list_add (list, 2103781343738de4abddf56982325a77bd70a98cd26Alexander Larsson "xattr", 2113781343738de4abddf56982325a77bd70a98cd26Alexander Larsson G_FILE_ATTRIBUTE_TYPE_STRING, 2124cb6eab803662aebb2a81fe97832dd7576391331Alexander Larsson G_FILE_ATTRIBUTE_INFO_COPY_WITH_FILE | 2134cb6eab803662aebb2a81fe97832dd7576391331Alexander Larsson G_FILE_ATTRIBUTE_INFO_COPY_WHEN_MOVED); 2143781343738de4abddf56982325a77bd70a98cd26Alexander Larsson g_file_attribute_info_list_add (list, 2151c57670f19012ac6ed8f4b0a0380ec0c304dd542Alexander Larsson "xattr-sys", 2163781343738de4abddf56982325a77bd70a98cd26Alexander Larsson G_FILE_ATTRIBUTE_TYPE_STRING, 2174cb6eab803662aebb2a81fe97832dd7576391331Alexander Larsson G_FILE_ATTRIBUTE_INFO_COPY_WHEN_MOVED); 2183781343738de4abddf56982325a77bd70a98cd26Alexander Larsson#endif 2193781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 2203781343738de4abddf56982325a77bd70a98cd26Alexander Larsson local_writable_namespaces = list; 2213781343738de4abddf56982325a77bd70a98cd26Alexander Larsson} 2223781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 2233781343738de4abddf56982325a77bd70a98cd26Alexander Larssonstatic void 2243781343738de4abddf56982325a77bd70a98cd26Alexander Larssong_local_file_init (GLocalFile *local) 2253781343738de4abddf56982325a77bd70a98cd26Alexander Larsson{ 2263781343738de4abddf56982325a77bd70a98cd26Alexander Larsson} 2273781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 2283781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 2293781343738de4abddf56982325a77bd70a98cd26Alexander Larssonstatic char * 2303781343738de4abddf56982325a77bd70a98cd26Alexander Larssoncanonicalize_filename (const char *filename) 2313781343738de4abddf56982325a77bd70a98cd26Alexander Larsson{ 2323781343738de4abddf56982325a77bd70a98cd26Alexander Larsson char *canon, *start, *p, *q; 2333781343738de4abddf56982325a77bd70a98cd26Alexander Larsson char *cwd; 2342544ae3cd69668ea578ac7c19a23dc7c2dcad396Alexander Larsson int i; 2353781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 2363781343738de4abddf56982325a77bd70a98cd26Alexander Larsson if (!g_path_is_absolute (filename)) 2373781343738de4abddf56982325a77bd70a98cd26Alexander Larsson { 2383781343738de4abddf56982325a77bd70a98cd26Alexander Larsson cwd = g_get_current_dir (); 2393781343738de4abddf56982325a77bd70a98cd26Alexander Larsson canon = g_build_filename (cwd, filename, NULL); 2403781343738de4abddf56982325a77bd70a98cd26Alexander Larsson g_free (cwd); 2413781343738de4abddf56982325a77bd70a98cd26Alexander Larsson } 2423781343738de4abddf56982325a77bd70a98cd26Alexander Larsson else 2433781343738de4abddf56982325a77bd70a98cd26Alexander Larsson canon = g_strdup (filename); 2443781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 2453781343738de4abddf56982325a77bd70a98cd26Alexander Larsson start = (char *)g_path_skip_root (canon); 2463781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 24770a276eca32744525f06edc09e77aed07276abcaAlexander Larsson if (start == NULL) 24870a276eca32744525f06edc09e77aed07276abcaAlexander Larsson { 24970a276eca32744525f06edc09e77aed07276abcaAlexander Larsson /* This shouldn't really happen, as g_get_current_dir() should 25070a276eca32744525f06edc09e77aed07276abcaAlexander Larsson return an absolute pathname, but bug 573843 shows this is 25170a276eca32744525f06edc09e77aed07276abcaAlexander Larsson not always happening */ 25270a276eca32744525f06edc09e77aed07276abcaAlexander Larsson g_free (canon); 25370a276eca32744525f06edc09e77aed07276abcaAlexander Larsson return g_build_filename (G_DIR_SEPARATOR_S, filename, NULL); 25470a276eca32744525f06edc09e77aed07276abcaAlexander Larsson } 25570a276eca32744525f06edc09e77aed07276abcaAlexander Larsson 2562544ae3cd69668ea578ac7c19a23dc7c2dcad396Alexander Larsson /* POSIX allows double slashes at the start to 2572544ae3cd69668ea578ac7c19a23dc7c2dcad396Alexander Larsson * mean something special (as does windows too). 2582544ae3cd69668ea578ac7c19a23dc7c2dcad396Alexander Larsson * So, "//" != "/", but more than two slashes 2592544ae3cd69668ea578ac7c19a23dc7c2dcad396Alexander Larsson * is treated as "/". 2602544ae3cd69668ea578ac7c19a23dc7c2dcad396Alexander Larsson */ 2612544ae3cd69668ea578ac7c19a23dc7c2dcad396Alexander Larsson i = 0; 2622544ae3cd69668ea578ac7c19a23dc7c2dcad396Alexander Larsson for (p = start - 1; 2632544ae3cd69668ea578ac7c19a23dc7c2dcad396Alexander Larsson (p >= canon) && 2642544ae3cd69668ea578ac7c19a23dc7c2dcad396Alexander Larsson G_IS_DIR_SEPARATOR (*p); 2652544ae3cd69668ea578ac7c19a23dc7c2dcad396Alexander Larsson p--) 2662544ae3cd69668ea578ac7c19a23dc7c2dcad396Alexander Larsson i++; 2672544ae3cd69668ea578ac7c19a23dc7c2dcad396Alexander Larsson if (i > 2) 2682544ae3cd69668ea578ac7c19a23dc7c2dcad396Alexander Larsson { 2692544ae3cd69668ea578ac7c19a23dc7c2dcad396Alexander Larsson i -= 1; 2702544ae3cd69668ea578ac7c19a23dc7c2dcad396Alexander Larsson start -= i; 2712544ae3cd69668ea578ac7c19a23dc7c2dcad396Alexander Larsson memmove (start, start+i, strlen (start+i)+1); 2722544ae3cd69668ea578ac7c19a23dc7c2dcad396Alexander Larsson } 2732544ae3cd69668ea578ac7c19a23dc7c2dcad396Alexander Larsson 2743781343738de4abddf56982325a77bd70a98cd26Alexander Larsson p = start; 2753781343738de4abddf56982325a77bd70a98cd26Alexander Larsson while (*p != 0) 2763781343738de4abddf56982325a77bd70a98cd26Alexander Larsson { 2773781343738de4abddf56982325a77bd70a98cd26Alexander Larsson if (p[0] == '.' && (p[1] == 0 || G_IS_DIR_SEPARATOR (p[1]))) 2783781343738de4abddf56982325a77bd70a98cd26Alexander Larsson { 2793781343738de4abddf56982325a77bd70a98cd26Alexander Larsson memmove (p, p+1, strlen (p+1)+1); 2803781343738de4abddf56982325a77bd70a98cd26Alexander Larsson } 2813781343738de4abddf56982325a77bd70a98cd26Alexander Larsson else if (p[0] == '.' && p[1] == '.' && (p[2] == 0 || G_IS_DIR_SEPARATOR (p[2]))) 2823781343738de4abddf56982325a77bd70a98cd26Alexander Larsson { 2833781343738de4abddf56982325a77bd70a98cd26Alexander Larsson q = p + 2; 2843781343738de4abddf56982325a77bd70a98cd26Alexander Larsson /* Skip previous separator */ 2853781343738de4abddf56982325a77bd70a98cd26Alexander Larsson p = p - 2; 2863781343738de4abddf56982325a77bd70a98cd26Alexander Larsson if (p < start) 2873781343738de4abddf56982325a77bd70a98cd26Alexander Larsson p = start; 2883781343738de4abddf56982325a77bd70a98cd26Alexander Larsson while (p > start && !G_IS_DIR_SEPARATOR (*p)) 2893781343738de4abddf56982325a77bd70a98cd26Alexander Larsson p--; 2903781343738de4abddf56982325a77bd70a98cd26Alexander Larsson if (G_IS_DIR_SEPARATOR (*p)) 2913781343738de4abddf56982325a77bd70a98cd26Alexander Larsson *p++ = G_DIR_SEPARATOR; 2923781343738de4abddf56982325a77bd70a98cd26Alexander Larsson memmove (p, q, strlen (q)+1); 2933781343738de4abddf56982325a77bd70a98cd26Alexander Larsson } 2943781343738de4abddf56982325a77bd70a98cd26Alexander Larsson else 2953781343738de4abddf56982325a77bd70a98cd26Alexander Larsson { 2963781343738de4abddf56982325a77bd70a98cd26Alexander Larsson /* Skip until next separator */ 2973781343738de4abddf56982325a77bd70a98cd26Alexander Larsson while (*p != 0 && !G_IS_DIR_SEPARATOR (*p)) 2983781343738de4abddf56982325a77bd70a98cd26Alexander Larsson p++; 2993781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 3003781343738de4abddf56982325a77bd70a98cd26Alexander Larsson if (*p != 0) 3013781343738de4abddf56982325a77bd70a98cd26Alexander Larsson { 3023781343738de4abddf56982325a77bd70a98cd26Alexander Larsson /* Canonicalize one separator */ 3033781343738de4abddf56982325a77bd70a98cd26Alexander Larsson *p++ = G_DIR_SEPARATOR; 3043781343738de4abddf56982325a77bd70a98cd26Alexander Larsson } 3053781343738de4abddf56982325a77bd70a98cd26Alexander Larsson } 3063781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 3073781343738de4abddf56982325a77bd70a98cd26Alexander Larsson /* Remove additional separators */ 3083781343738de4abddf56982325a77bd70a98cd26Alexander Larsson q = p; 3093781343738de4abddf56982325a77bd70a98cd26Alexander Larsson while (*q && G_IS_DIR_SEPARATOR (*q)) 3103781343738de4abddf56982325a77bd70a98cd26Alexander Larsson q++; 3113781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 3123781343738de4abddf56982325a77bd70a98cd26Alexander Larsson if (p != q) 3133781343738de4abddf56982325a77bd70a98cd26Alexander Larsson memmove (p, q, strlen (q)+1); 3143781343738de4abddf56982325a77bd70a98cd26Alexander Larsson } 3153781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 3163781343738de4abddf56982325a77bd70a98cd26Alexander Larsson /* Remove trailing slashes */ 3173781343738de4abddf56982325a77bd70a98cd26Alexander Larsson if (p > start && G_IS_DIR_SEPARATOR (*(p-1))) 3183781343738de4abddf56982325a77bd70a98cd26Alexander Larsson *(p-1) = 0; 3193781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 3203781343738de4abddf56982325a77bd70a98cd26Alexander Larsson return canon; 3213781343738de4abddf56982325a77bd70a98cd26Alexander Larsson} 3223781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 3233781343738de4abddf56982325a77bd70a98cd26Alexander Larsson/** 324d9594f5709313d6e7a8a4f3e5f3b23fc72017417Alexander Larsson * _g_local_file_new: 3253781343738de4abddf56982325a77bd70a98cd26Alexander Larsson * @filename: filename of the file to create. 3263781343738de4abddf56982325a77bd70a98cd26Alexander Larsson * 3273781343738de4abddf56982325a77bd70a98cd26Alexander Larsson * Returns: new local #GFile. 3283781343738de4abddf56982325a77bd70a98cd26Alexander Larsson **/ 3293781343738de4abddf56982325a77bd70a98cd26Alexander LarssonGFile * 330d9594f5709313d6e7a8a4f3e5f3b23fc72017417Alexander Larsson_g_local_file_new (const char *filename) 3313781343738de4abddf56982325a77bd70a98cd26Alexander Larsson{ 3323781343738de4abddf56982325a77bd70a98cd26Alexander Larsson GLocalFile *local; 3333781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 3343781343738de4abddf56982325a77bd70a98cd26Alexander Larsson local = g_object_new (G_TYPE_LOCAL_FILE, NULL); 3353781343738de4abddf56982325a77bd70a98cd26Alexander Larsson local->filename = canonicalize_filename (filename); 3363781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 3373781343738de4abddf56982325a77bd70a98cd26Alexander Larsson return G_FILE (local); 3383781343738de4abddf56982325a77bd70a98cd26Alexander Larsson} 3393781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 3403781343738de4abddf56982325a77bd70a98cd26Alexander Larssonstatic gboolean 3413781343738de4abddf56982325a77bd70a98cd26Alexander Larssong_local_file_is_native (GFile *file) 3423781343738de4abddf56982325a77bd70a98cd26Alexander Larsson{ 3433781343738de4abddf56982325a77bd70a98cd26Alexander Larsson return TRUE; 3443781343738de4abddf56982325a77bd70a98cd26Alexander Larsson} 3453781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 3463781343738de4abddf56982325a77bd70a98cd26Alexander Larssonstatic gboolean 347a2ca589703273fca80cb126430a8b058aba3eb52Matthias Claseng_local_file_has_uri_scheme (GFile *file, 3483781343738de4abddf56982325a77bd70a98cd26Alexander Larsson const char *uri_scheme) 3493781343738de4abddf56982325a77bd70a98cd26Alexander Larsson{ 3503781343738de4abddf56982325a77bd70a98cd26Alexander Larsson return g_ascii_strcasecmp (uri_scheme, "file") == 0; 3513781343738de4abddf56982325a77bd70a98cd26Alexander Larsson} 3523781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 3533781343738de4abddf56982325a77bd70a98cd26Alexander Larssonstatic char * 3543781343738de4abddf56982325a77bd70a98cd26Alexander Larssong_local_file_get_uri_scheme (GFile *file) 3553781343738de4abddf56982325a77bd70a98cd26Alexander Larsson{ 3563781343738de4abddf56982325a77bd70a98cd26Alexander Larsson return g_strdup ("file"); 3573781343738de4abddf56982325a77bd70a98cd26Alexander Larsson} 3583781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 3593781343738de4abddf56982325a77bd70a98cd26Alexander Larssonstatic char * 3603781343738de4abddf56982325a77bd70a98cd26Alexander Larssong_local_file_get_basename (GFile *file) 3613781343738de4abddf56982325a77bd70a98cd26Alexander Larsson{ 3623781343738de4abddf56982325a77bd70a98cd26Alexander Larsson return g_path_get_basename (G_LOCAL_FILE (file)->filename); 3633781343738de4abddf56982325a77bd70a98cd26Alexander Larsson} 3643781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 3653781343738de4abddf56982325a77bd70a98cd26Alexander Larssonstatic char * 3663781343738de4abddf56982325a77bd70a98cd26Alexander Larssong_local_file_get_path (GFile *file) 3673781343738de4abddf56982325a77bd70a98cd26Alexander Larsson{ 3683781343738de4abddf56982325a77bd70a98cd26Alexander Larsson return g_strdup (G_LOCAL_FILE (file)->filename); 3693781343738de4abddf56982325a77bd70a98cd26Alexander Larsson} 3703781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 3713781343738de4abddf56982325a77bd70a98cd26Alexander Larssonstatic char * 3723781343738de4abddf56982325a77bd70a98cd26Alexander Larssong_local_file_get_uri (GFile *file) 3733781343738de4abddf56982325a77bd70a98cd26Alexander Larsson{ 3743781343738de4abddf56982325a77bd70a98cd26Alexander Larsson return g_filename_to_uri (G_LOCAL_FILE (file)->filename, NULL, NULL); 3753781343738de4abddf56982325a77bd70a98cd26Alexander Larsson} 3763781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 3773781343738de4abddf56982325a77bd70a98cd26Alexander Larssonstatic gboolean 3783781343738de4abddf56982325a77bd70a98cd26Alexander Larssonget_filename_charset (const gchar **filename_charset) 3793781343738de4abddf56982325a77bd70a98cd26Alexander Larsson{ 3803781343738de4abddf56982325a77bd70a98cd26Alexander Larsson const gchar **charsets; 3813781343738de4abddf56982325a77bd70a98cd26Alexander Larsson gboolean is_utf8; 3823781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 3833781343738de4abddf56982325a77bd70a98cd26Alexander Larsson is_utf8 = g_get_filename_charsets (&charsets); 3843781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 3853781343738de4abddf56982325a77bd70a98cd26Alexander Larsson if (filename_charset) 3863781343738de4abddf56982325a77bd70a98cd26Alexander Larsson *filename_charset = charsets[0]; 3873781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 3883781343738de4abddf56982325a77bd70a98cd26Alexander Larsson return is_utf8; 3893781343738de4abddf56982325a77bd70a98cd26Alexander Larsson} 3903781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 3913781343738de4abddf56982325a77bd70a98cd26Alexander Larssonstatic gboolean 3923781343738de4abddf56982325a77bd70a98cd26Alexander Larssonname_is_valid_for_display (const char *string, 393a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen gboolean is_valid_utf8) 3943781343738de4abddf56982325a77bd70a98cd26Alexander Larsson{ 3953781343738de4abddf56982325a77bd70a98cd26Alexander Larsson char c; 396b784923e9cb3e639616113cb43edffed7e63e3b6Alexander Larsson 3973781343738de4abddf56982325a77bd70a98cd26Alexander Larsson if (!is_valid_utf8 && 3983781343738de4abddf56982325a77bd70a98cd26Alexander Larsson !g_utf8_validate (string, -1, NULL)) 3993781343738de4abddf56982325a77bd70a98cd26Alexander Larsson return FALSE; 4003781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 4013781343738de4abddf56982325a77bd70a98cd26Alexander Larsson while ((c = *string++) != 0) 4023781343738de4abddf56982325a77bd70a98cd26Alexander Larsson { 40354300dde6d77867aa53e60a2bdfd69cb9e644315Matthias Clasen if (g_ascii_iscntrl (c)) 4043781343738de4abddf56982325a77bd70a98cd26Alexander Larsson return FALSE; 4053781343738de4abddf56982325a77bd70a98cd26Alexander Larsson } 4063781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 4073781343738de4abddf56982325a77bd70a98cd26Alexander Larsson return TRUE; 4083781343738de4abddf56982325a77bd70a98cd26Alexander Larsson} 4093781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 4103781343738de4abddf56982325a77bd70a98cd26Alexander Larssonstatic char * 4113781343738de4abddf56982325a77bd70a98cd26Alexander Larssong_local_file_get_parse_name (GFile *file) 4123781343738de4abddf56982325a77bd70a98cd26Alexander Larsson{ 4133781343738de4abddf56982325a77bd70a98cd26Alexander Larsson const char *filename; 4143781343738de4abddf56982325a77bd70a98cd26Alexander Larsson char *parse_name; 4153781343738de4abddf56982325a77bd70a98cd26Alexander Larsson const gchar *charset; 4163781343738de4abddf56982325a77bd70a98cd26Alexander Larsson char *utf8_filename; 4173781343738de4abddf56982325a77bd70a98cd26Alexander Larsson char *roundtripped_filename; 4183781343738de4abddf56982325a77bd70a98cd26Alexander Larsson gboolean free_utf8_filename; 4193781343738de4abddf56982325a77bd70a98cd26Alexander Larsson gboolean is_valid_utf8; 420b784923e9cb3e639616113cb43edffed7e63e3b6Alexander Larsson char *escaped_path; 421b784923e9cb3e639616113cb43edffed7e63e3b6Alexander Larsson 4223781343738de4abddf56982325a77bd70a98cd26Alexander Larsson filename = G_LOCAL_FILE (file)->filename; 4233781343738de4abddf56982325a77bd70a98cd26Alexander Larsson if (get_filename_charset (&charset)) 4243781343738de4abddf56982325a77bd70a98cd26Alexander Larsson { 4253781343738de4abddf56982325a77bd70a98cd26Alexander Larsson utf8_filename = (char *)filename; 4263781343738de4abddf56982325a77bd70a98cd26Alexander Larsson free_utf8_filename = FALSE; 4273781343738de4abddf56982325a77bd70a98cd26Alexander Larsson is_valid_utf8 = FALSE; /* Can't guarantee this */ 4283781343738de4abddf56982325a77bd70a98cd26Alexander Larsson } 4293781343738de4abddf56982325a77bd70a98cd26Alexander Larsson else 4303781343738de4abddf56982325a77bd70a98cd26Alexander Larsson { 4313781343738de4abddf56982325a77bd70a98cd26Alexander Larsson utf8_filename = g_convert (filename, -1, 4323781343738de4abddf56982325a77bd70a98cd26Alexander Larsson "UTF-8", charset, NULL, NULL, NULL); 4333781343738de4abddf56982325a77bd70a98cd26Alexander Larsson free_utf8_filename = TRUE; 4343781343738de4abddf56982325a77bd70a98cd26Alexander Larsson is_valid_utf8 = TRUE; 4353781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 4363781343738de4abddf56982325a77bd70a98cd26Alexander Larsson if (utf8_filename != NULL) 4373781343738de4abddf56982325a77bd70a98cd26Alexander Larsson { 4383781343738de4abddf56982325a77bd70a98cd26Alexander Larsson /* Make sure we can roundtrip: */ 4393781343738de4abddf56982325a77bd70a98cd26Alexander Larsson roundtripped_filename = g_convert (utf8_filename, -1, 4403781343738de4abddf56982325a77bd70a98cd26Alexander Larsson charset, "UTF-8", NULL, NULL, NULL); 4413781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 4423781343738de4abddf56982325a77bd70a98cd26Alexander Larsson if (roundtripped_filename == NULL || 4433781343738de4abddf56982325a77bd70a98cd26Alexander Larsson strcmp (utf8_filename, roundtripped_filename) != 0) 4443781343738de4abddf56982325a77bd70a98cd26Alexander Larsson { 4453781343738de4abddf56982325a77bd70a98cd26Alexander Larsson g_free (utf8_filename); 4463781343738de4abddf56982325a77bd70a98cd26Alexander Larsson utf8_filename = NULL; 4473781343738de4abddf56982325a77bd70a98cd26Alexander Larsson } 4487b46b2a43bee252846d271483fdec6a55f59dea4Federico Mena Quintero 4497b46b2a43bee252846d271483fdec6a55f59dea4Federico Mena Quintero g_free (roundtripped_filename); 4503781343738de4abddf56982325a77bd70a98cd26Alexander Larsson } 4513781343738de4abddf56982325a77bd70a98cd26Alexander Larsson } 4523781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 4533781343738de4abddf56982325a77bd70a98cd26Alexander Larsson if (utf8_filename != NULL && 4543781343738de4abddf56982325a77bd70a98cd26Alexander Larsson name_is_valid_for_display (utf8_filename, is_valid_utf8)) 4553781343738de4abddf56982325a77bd70a98cd26Alexander Larsson { 4563781343738de4abddf56982325a77bd70a98cd26Alexander Larsson if (free_utf8_filename) 4573781343738de4abddf56982325a77bd70a98cd26Alexander Larsson parse_name = utf8_filename; 4583781343738de4abddf56982325a77bd70a98cd26Alexander Larsson else 4593781343738de4abddf56982325a77bd70a98cd26Alexander Larsson parse_name = g_strdup (utf8_filename); 4603781343738de4abddf56982325a77bd70a98cd26Alexander Larsson } 4613781343738de4abddf56982325a77bd70a98cd26Alexander Larsson else 4623781343738de4abddf56982325a77bd70a98cd26Alexander Larsson { 463b784923e9cb3e639616113cb43edffed7e63e3b6Alexander Larsson escaped_path = g_uri_escape_string (filename, 464b784923e9cb3e639616113cb43edffed7e63e3b6Alexander Larsson G_URI_RESERVED_CHARS_ALLOWED_IN_PATH_ELEMENT "/", 465b784923e9cb3e639616113cb43edffed7e63e3b6Alexander Larsson TRUE); 466b784923e9cb3e639616113cb43edffed7e63e3b6Alexander Larsson parse_name = g_strconcat ("file://", 467b784923e9cb3e639616113cb43edffed7e63e3b6Alexander Larsson (*escaped_path != '/') ? "/" : "", 468b784923e9cb3e639616113cb43edffed7e63e3b6Alexander Larsson escaped_path, 469b784923e9cb3e639616113cb43edffed7e63e3b6Alexander Larsson NULL); 470b784923e9cb3e639616113cb43edffed7e63e3b6Alexander Larsson 471b784923e9cb3e639616113cb43edffed7e63e3b6Alexander Larsson g_free (escaped_path); 472b784923e9cb3e639616113cb43edffed7e63e3b6Alexander Larsson 4733781343738de4abddf56982325a77bd70a98cd26Alexander Larsson if (free_utf8_filename) 4743781343738de4abddf56982325a77bd70a98cd26Alexander Larsson g_free (utf8_filename); 4753781343738de4abddf56982325a77bd70a98cd26Alexander Larsson } 4763781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 4773781343738de4abddf56982325a77bd70a98cd26Alexander Larsson return parse_name; 4783781343738de4abddf56982325a77bd70a98cd26Alexander Larsson} 4793781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 4803781343738de4abddf56982325a77bd70a98cd26Alexander Larssonstatic GFile * 4813781343738de4abddf56982325a77bd70a98cd26Alexander Larssong_local_file_get_parent (GFile *file) 4823781343738de4abddf56982325a77bd70a98cd26Alexander Larsson{ 4833781343738de4abddf56982325a77bd70a98cd26Alexander Larsson GLocalFile *local = G_LOCAL_FILE (file); 4843781343738de4abddf56982325a77bd70a98cd26Alexander Larsson const char *non_root; 4853781343738de4abddf56982325a77bd70a98cd26Alexander Larsson char *dirname; 4863781343738de4abddf56982325a77bd70a98cd26Alexander Larsson GFile *parent; 4873781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 4883781343738de4abddf56982325a77bd70a98cd26Alexander Larsson /* Check for root */ 4893781343738de4abddf56982325a77bd70a98cd26Alexander Larsson non_root = g_path_skip_root (local->filename); 4903781343738de4abddf56982325a77bd70a98cd26Alexander Larsson if (*non_root == 0) 4913781343738de4abddf56982325a77bd70a98cd26Alexander Larsson return NULL; 4923781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 4933781343738de4abddf56982325a77bd70a98cd26Alexander Larsson dirname = g_path_get_dirname (local->filename); 494d9594f5709313d6e7a8a4f3e5f3b23fc72017417Alexander Larsson parent = _g_local_file_new (dirname); 4953781343738de4abddf56982325a77bd70a98cd26Alexander Larsson g_free (dirname); 4963781343738de4abddf56982325a77bd70a98cd26Alexander Larsson return parent; 4973781343738de4abddf56982325a77bd70a98cd26Alexander Larsson} 4983781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 4993781343738de4abddf56982325a77bd70a98cd26Alexander Larssonstatic GFile * 5003781343738de4abddf56982325a77bd70a98cd26Alexander Larssong_local_file_dup (GFile *file) 5013781343738de4abddf56982325a77bd70a98cd26Alexander Larsson{ 5023781343738de4abddf56982325a77bd70a98cd26Alexander Larsson GLocalFile *local = G_LOCAL_FILE (file); 5033781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 504d9594f5709313d6e7a8a4f3e5f3b23fc72017417Alexander Larsson return _g_local_file_new (local->filename); 5053781343738de4abddf56982325a77bd70a98cd26Alexander Larsson} 5063781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 5073781343738de4abddf56982325a77bd70a98cd26Alexander Larssonstatic guint 5083781343738de4abddf56982325a77bd70a98cd26Alexander Larssong_local_file_hash (GFile *file) 5093781343738de4abddf56982325a77bd70a98cd26Alexander Larsson{ 5103781343738de4abddf56982325a77bd70a98cd26Alexander Larsson GLocalFile *local = G_LOCAL_FILE (file); 5113781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 5123781343738de4abddf56982325a77bd70a98cd26Alexander Larsson return g_str_hash (local->filename); 5133781343738de4abddf56982325a77bd70a98cd26Alexander Larsson} 5143781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 5153781343738de4abddf56982325a77bd70a98cd26Alexander Larssonstatic gboolean 5163781343738de4abddf56982325a77bd70a98cd26Alexander Larssong_local_file_equal (GFile *file1, 5173781343738de4abddf56982325a77bd70a98cd26Alexander Larsson GFile *file2) 5183781343738de4abddf56982325a77bd70a98cd26Alexander Larsson{ 5193781343738de4abddf56982325a77bd70a98cd26Alexander Larsson GLocalFile *local1 = G_LOCAL_FILE (file1); 5203781343738de4abddf56982325a77bd70a98cd26Alexander Larsson GLocalFile *local2 = G_LOCAL_FILE (file2); 5213781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 5223781343738de4abddf56982325a77bd70a98cd26Alexander Larsson return g_str_equal (local1->filename, local2->filename); 5233781343738de4abddf56982325a77bd70a98cd26Alexander Larsson} 5243781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 5253781343738de4abddf56982325a77bd70a98cd26Alexander Larssonstatic const char * 526a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasenmatch_prefix (const char *path, 527a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen const char *prefix) 5283781343738de4abddf56982325a77bd70a98cd26Alexander Larsson{ 5293781343738de4abddf56982325a77bd70a98cd26Alexander Larsson int prefix_len; 5303781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 5313781343738de4abddf56982325a77bd70a98cd26Alexander Larsson prefix_len = strlen (prefix); 5323781343738de4abddf56982325a77bd70a98cd26Alexander Larsson if (strncmp (path, prefix, prefix_len) != 0) 5333781343738de4abddf56982325a77bd70a98cd26Alexander Larsson return NULL; 534a80b1120f1fa19cfb036e371313af8e73eaea049Alexander Larsson 535a80b1120f1fa19cfb036e371313af8e73eaea049Alexander Larsson /* Handle the case where prefix is the root, so that 536a80b1120f1fa19cfb036e371313af8e73eaea049Alexander Larsson * the IS_DIR_SEPRARATOR check below works */ 537a80b1120f1fa19cfb036e371313af8e73eaea049Alexander Larsson if (prefix_len > 0 && 538a80b1120f1fa19cfb036e371313af8e73eaea049Alexander Larsson G_IS_DIR_SEPARATOR (prefix[prefix_len-1])) 539a80b1120f1fa19cfb036e371313af8e73eaea049Alexander Larsson prefix_len--; 540a80b1120f1fa19cfb036e371313af8e73eaea049Alexander Larsson 5413781343738de4abddf56982325a77bd70a98cd26Alexander Larsson return path + prefix_len; 5423781343738de4abddf56982325a77bd70a98cd26Alexander Larsson} 5433781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 5443781343738de4abddf56982325a77bd70a98cd26Alexander Larssonstatic gboolean 5456dc9b7ee0050c03e069d026c2c83136547a7d343Alexander Larssong_local_file_prefix_matches (GFile *parent, 5466dc9b7ee0050c03e069d026c2c83136547a7d343Alexander Larsson GFile *descendant) 5473781343738de4abddf56982325a77bd70a98cd26Alexander Larsson{ 5483781343738de4abddf56982325a77bd70a98cd26Alexander Larsson GLocalFile *parent_local = G_LOCAL_FILE (parent); 5493781343738de4abddf56982325a77bd70a98cd26Alexander Larsson GLocalFile *descendant_local = G_LOCAL_FILE (descendant); 5503781343738de4abddf56982325a77bd70a98cd26Alexander Larsson const char *remainder; 5513781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 5523781343738de4abddf56982325a77bd70a98cd26Alexander Larsson remainder = match_prefix (descendant_local->filename, parent_local->filename); 5533781343738de4abddf56982325a77bd70a98cd26Alexander Larsson if (remainder != NULL && G_IS_DIR_SEPARATOR (*remainder)) 5543781343738de4abddf56982325a77bd70a98cd26Alexander Larsson return TRUE; 5553781343738de4abddf56982325a77bd70a98cd26Alexander Larsson return FALSE; 5563781343738de4abddf56982325a77bd70a98cd26Alexander Larsson} 5573781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 5583781343738de4abddf56982325a77bd70a98cd26Alexander Larssonstatic char * 5593781343738de4abddf56982325a77bd70a98cd26Alexander Larssong_local_file_get_relative_path (GFile *parent, 5603781343738de4abddf56982325a77bd70a98cd26Alexander Larsson GFile *descendant) 5613781343738de4abddf56982325a77bd70a98cd26Alexander Larsson{ 5623781343738de4abddf56982325a77bd70a98cd26Alexander Larsson GLocalFile *parent_local = G_LOCAL_FILE (parent); 5633781343738de4abddf56982325a77bd70a98cd26Alexander Larsson GLocalFile *descendant_local = G_LOCAL_FILE (descendant); 5643781343738de4abddf56982325a77bd70a98cd26Alexander Larsson const char *remainder; 5653781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 5663781343738de4abddf56982325a77bd70a98cd26Alexander Larsson remainder = match_prefix (descendant_local->filename, parent_local->filename); 5673781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 5683781343738de4abddf56982325a77bd70a98cd26Alexander Larsson if (remainder != NULL && G_IS_DIR_SEPARATOR (*remainder)) 5693781343738de4abddf56982325a77bd70a98cd26Alexander Larsson return g_strdup (remainder + 1); 5703781343738de4abddf56982325a77bd70a98cd26Alexander Larsson return NULL; 5713781343738de4abddf56982325a77bd70a98cd26Alexander Larsson} 5723781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 5733781343738de4abddf56982325a77bd70a98cd26Alexander Larssonstatic GFile * 574a2ca589703273fca80cb126430a8b058aba3eb52Matthias Claseng_local_file_resolve_relative_path (GFile *file, 5753781343738de4abddf56982325a77bd70a98cd26Alexander Larsson const char *relative_path) 5763781343738de4abddf56982325a77bd70a98cd26Alexander Larsson{ 5773781343738de4abddf56982325a77bd70a98cd26Alexander Larsson GLocalFile *local = G_LOCAL_FILE (file); 5783781343738de4abddf56982325a77bd70a98cd26Alexander Larsson char *filename; 5793781343738de4abddf56982325a77bd70a98cd26Alexander Larsson GFile *child; 5803781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 5813781343738de4abddf56982325a77bd70a98cd26Alexander Larsson if (g_path_is_absolute (relative_path)) 582d9594f5709313d6e7a8a4f3e5f3b23fc72017417Alexander Larsson return _g_local_file_new (relative_path); 5833781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 5843781343738de4abddf56982325a77bd70a98cd26Alexander Larsson filename = g_build_filename (local->filename, relative_path, NULL); 585d9594f5709313d6e7a8a4f3e5f3b23fc72017417Alexander Larsson child = _g_local_file_new (filename); 5863781343738de4abddf56982325a77bd70a98cd26Alexander Larsson g_free (filename); 5873781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 5883781343738de4abddf56982325a77bd70a98cd26Alexander Larsson return child; 5893781343738de4abddf56982325a77bd70a98cd26Alexander Larsson} 5903781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 5913781343738de4abddf56982325a77bd70a98cd26Alexander Larssonstatic GFileEnumerator * 592a2ca589703273fca80cb126430a8b058aba3eb52Matthias Claseng_local_file_enumerate_children (GFile *file, 593a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen const char *attributes, 594a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen GFileQueryInfoFlags flags, 595a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen GCancellable *cancellable, 596a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen GError **error) 5973781343738de4abddf56982325a77bd70a98cd26Alexander Larsson{ 5983781343738de4abddf56982325a77bd70a98cd26Alexander Larsson GLocalFile *local = G_LOCAL_FILE (file); 5993480685d4e5a022530a07464fc20d10b45b3b358Ross Burton return _g_local_file_enumerator_new (local, 600d9594f5709313d6e7a8a4f3e5f3b23fc72017417Alexander Larsson attributes, flags, 601d9594f5709313d6e7a8a4f3e5f3b23fc72017417Alexander Larsson cancellable, error); 6023781343738de4abddf56982325a77bd70a98cd26Alexander Larsson} 6033781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 6043781343738de4abddf56982325a77bd70a98cd26Alexander Larssonstatic GFile * 6053781343738de4abddf56982325a77bd70a98cd26Alexander Larssong_local_file_get_child_for_display_name (GFile *file, 6063781343738de4abddf56982325a77bd70a98cd26Alexander Larsson const char *display_name, 6073781343738de4abddf56982325a77bd70a98cd26Alexander Larsson GError **error) 6083781343738de4abddf56982325a77bd70a98cd26Alexander Larsson{ 609df719f749c9fa1f3966643eeba96eb5dd022b2caGrahame Bowland GFile *new_file; 6103781343738de4abddf56982325a77bd70a98cd26Alexander Larsson char *basename; 6113781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 6123781343738de4abddf56982325a77bd70a98cd26Alexander Larsson basename = g_filename_from_utf8 (display_name, -1, NULL, NULL, NULL); 6133781343738de4abddf56982325a77bd70a98cd26Alexander Larsson if (basename == NULL) 6143781343738de4abddf56982325a77bd70a98cd26Alexander Larsson { 6153781343738de4abddf56982325a77bd70a98cd26Alexander Larsson g_set_error (error, G_IO_ERROR, 6163781343738de4abddf56982325a77bd70a98cd26Alexander Larsson G_IO_ERROR_INVALID_FILENAME, 6173781343738de4abddf56982325a77bd70a98cd26Alexander Larsson _("Invalid filename %s"), display_name); 6183781343738de4abddf56982325a77bd70a98cd26Alexander Larsson return NULL; 6193781343738de4abddf56982325a77bd70a98cd26Alexander Larsson } 6203781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 6213781343738de4abddf56982325a77bd70a98cd26Alexander Larsson new_file = g_file_get_child (file, basename); 6223781343738de4abddf56982325a77bd70a98cd26Alexander Larsson g_free (basename); 6233781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 6243781343738de4abddf56982325a77bd70a98cd26Alexander Larsson return new_file; 6253781343738de4abddf56982325a77bd70a98cd26Alexander Larsson} 6263781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 6273781343738de4abddf56982325a77bd70a98cd26Alexander Larsson#ifdef USE_STATFS 6283781343738de4abddf56982325a77bd70a98cd26Alexander Larssonstatic const char * 6293781343738de4abddf56982325a77bd70a98cd26Alexander Larssonget_fs_type (long f_type) 6303781343738de4abddf56982325a77bd70a98cd26Alexander Larsson{ 6313781343738de4abddf56982325a77bd70a98cd26Alexander Larsson /* filesystem ids taken from linux manpage */ 632a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen switch (f_type) 633a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen { 634a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen case 0xadf5: 635a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen return "adfs"; 636a0c45852e1618b86ef6681b05333bb716febec56Matthias Clasen case 0x5346414f: 637a0c45852e1618b86ef6681b05333bb716febec56Matthias Clasen return "afs"; 638a0c45852e1618b86ef6681b05333bb716febec56Matthias Clasen case 0x0187: 639a0c45852e1618b86ef6681b05333bb716febec56Matthias Clasen return "autofs"; 640a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen case 0xADFF: 641a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen return "affs"; 642a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen case 0x42465331: 643a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen return "befs"; 644a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen case 0x1BADFACE: 645a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen return "bfs"; 646f5483302757a9c03c43e25c86cea4a7bd5aaaf3fMatthias Clasen case 0x9123683E: 647f5483302757a9c03c43e25c86cea4a7bd5aaaf3fMatthias Clasen return "btrfs"; 648a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen case 0xFF534D42: 649a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen return "cifs"; 650a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen case 0x73757245: 651a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen return "coda"; 652a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen case 0x012FF7B7: 653a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen return "coh"; 654a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen case 0x28cd3d45: 655a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen return "cramfs"; 656a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen case 0x1373: 657a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen return "devfs"; 658a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen case 0x00414A53: 659a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen return "efs"; 660a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen case 0x137D: 661a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen return "ext"; 662a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen case 0xEF51: 663a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen return "ext2"; 664a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen case 0xEF53: 66525ff8ee7486c7bdf1612d3554fc1d7d91daedfa6Matthias Clasen return "ext3/ext4"; 666a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen case 0x4244: 667a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen return "hfs"; 668a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen case 0xF995E849: 669a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen return "hpfs"; 670a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen case 0x958458f6: 671a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen return "hugetlbfs"; 672a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen case 0x9660: 673a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen return "isofs"; 674a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen case 0x72b6: 675a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen return "jffs2"; 676a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen case 0x3153464a: 677a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen return "jfs"; 678a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen case 0x137F: 679a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen return "minix"; 680a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen case 0x138F: 681a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen return "minix2"; 682a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen case 0x2468: 683a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen return "minix2"; 684a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen case 0x2478: 685a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen return "minix22"; 686a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen case 0x4d44: 687a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen return "msdos"; 688a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen case 0x564c: 689a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen return "ncp"; 690a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen case 0x6969: 691a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen return "nfs"; 692a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen case 0x5346544e: 693a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen return "ntfs"; 694a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen case 0x9fa1: 695a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen return "openprom"; 696a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen case 0x9fa0: 697a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen return "proc"; 698a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen case 0x002f: 699a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen return "qnx4"; 700a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen case 0x52654973: 701a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen return "reiserfs"; 702a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen case 0x7275: 703a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen return "romfs"; 704a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen case 0x517B: 705a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen return "smb"; 706f5483302757a9c03c43e25c86cea4a7bd5aaaf3fMatthias Clasen case 0x73717368: 707f5483302757a9c03c43e25c86cea4a7bd5aaaf3fMatthias Clasen return "squashfs"; 708a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen case 0x012FF7B6: 709a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen return "sysv2"; 710a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen case 0x012FF7B5: 711a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen return "sysv4"; 712a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen case 0x01021994: 713a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen return "tmpfs"; 714a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen case 0x15013346: 715a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen return "udf"; 716a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen case 0x00011954: 717a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen return "ufs"; 718a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen case 0x9fa2: 719a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen return "usbdevice"; 720a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen case 0xa501FCF5: 721a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen return "vxfs"; 722a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen case 0x012FF7B4: 723a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen return "xenix"; 724a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen case 0x58465342: 725a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen return "xfs"; 726a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen case 0x012FD16D: 727a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen return "xiafs"; 728a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen default: 729a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen return NULL; 730a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen } 7313781343738de4abddf56982325a77bd70a98cd26Alexander Larsson} 7323781343738de4abddf56982325a77bd70a98cd26Alexander Larsson#endif 7333781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 73483445755b3b2d315feadf94cefbb74afc8f142bdTor Lillqvist#ifndef G_OS_WIN32 73583445755b3b2d315feadf94cefbb74afc8f142bdTor Lillqvist 7363781343738de4abddf56982325a77bd70a98cd26Alexander LarssonG_LOCK_DEFINE_STATIC(mount_info_hash); 7373781343738de4abddf56982325a77bd70a98cd26Alexander Larssonstatic GHashTable *mount_info_hash = NULL; 73883445755b3b2d315feadf94cefbb74afc8f142bdTor Lillqviststatic guint64 mount_info_hash_cache_time = 0; 7393781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 7403781343738de4abddf56982325a77bd70a98cd26Alexander Larssontypedef enum { 7413781343738de4abddf56982325a77bd70a98cd26Alexander Larsson MOUNT_INFO_READONLY = 1<<0 7423781343738de4abddf56982325a77bd70a98cd26Alexander Larsson} MountInfo; 7433781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 7443781343738de4abddf56982325a77bd70a98cd26Alexander Larssonstatic gboolean 7453781343738de4abddf56982325a77bd70a98cd26Alexander Larssondevice_equal (gconstpointer v1, 746a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen gconstpointer v2) 7473781343738de4abddf56982325a77bd70a98cd26Alexander Larsson{ 74854300dde6d77867aa53e60a2bdfd69cb9e644315Matthias Clasen return *(dev_t *)v1 == *(dev_t *)v2; 7493781343738de4abddf56982325a77bd70a98cd26Alexander Larsson} 7503781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 7513781343738de4abddf56982325a77bd70a98cd26Alexander Larssonstatic guint 752a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasendevice_hash (gconstpointer v) 7533781343738de4abddf56982325a77bd70a98cd26Alexander Larsson{ 7543781343738de4abddf56982325a77bd70a98cd26Alexander Larsson return (guint) *(dev_t *)v; 7553781343738de4abddf56982325a77bd70a98cd26Alexander Larsson} 7563781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 7573781343738de4abddf56982325a77bd70a98cd26Alexander Larssonstatic void 758a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasenget_mount_info (GFileInfo *fs_info, 759a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen const char *path, 7603781343738de4abddf56982325a77bd70a98cd26Alexander Larsson GFileAttributeMatcher *matcher) 7613781343738de4abddf56982325a77bd70a98cd26Alexander Larsson{ 7623781343738de4abddf56982325a77bd70a98cd26Alexander Larsson struct stat buf; 7633781343738de4abddf56982325a77bd70a98cd26Alexander Larsson gboolean got_info; 7643781343738de4abddf56982325a77bd70a98cd26Alexander Larsson gpointer info_as_ptr; 7653781343738de4abddf56982325a77bd70a98cd26Alexander Larsson guint mount_info; 7663781343738de4abddf56982325a77bd70a98cd26Alexander Larsson char *mountpoint; 7673781343738de4abddf56982325a77bd70a98cd26Alexander Larsson dev_t *dev; 7683ca9fd4dbb134088bf70f2f6584f14a559e6820aDavid Zeuthen GUnixMountEntry *mount; 7693781343738de4abddf56982325a77bd70a98cd26Alexander Larsson guint64 cache_time; 7703781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 771a33f8a7564cc649daf0dca0d67daac8430808cf9Hans Breuer if (g_lstat (path, &buf) != 0) 7723781343738de4abddf56982325a77bd70a98cd26Alexander Larsson return; 7733781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 7743781343738de4abddf56982325a77bd70a98cd26Alexander Larsson G_LOCK (mount_info_hash); 7753781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 7763781343738de4abddf56982325a77bd70a98cd26Alexander Larsson if (mount_info_hash == NULL) 7773781343738de4abddf56982325a77bd70a98cd26Alexander Larsson mount_info_hash = g_hash_table_new_full (device_hash, device_equal, 7783781343738de4abddf56982325a77bd70a98cd26Alexander Larsson g_free, NULL); 7793781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 7803781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 7813781343738de4abddf56982325a77bd70a98cd26Alexander Larsson if (g_unix_mounts_changed_since (mount_info_hash_cache_time)) 7823781343738de4abddf56982325a77bd70a98cd26Alexander Larsson g_hash_table_remove_all (mount_info_hash); 7833781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 7843781343738de4abddf56982325a77bd70a98cd26Alexander Larsson got_info = g_hash_table_lookup_extended (mount_info_hash, 7853781343738de4abddf56982325a77bd70a98cd26Alexander Larsson &buf.st_dev, 7863781343738de4abddf56982325a77bd70a98cd26Alexander Larsson NULL, 7873781343738de4abddf56982325a77bd70a98cd26Alexander Larsson &info_as_ptr); 7883781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 7893781343738de4abddf56982325a77bd70a98cd26Alexander Larsson G_UNLOCK (mount_info_hash); 7903781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 7913781343738de4abddf56982325a77bd70a98cd26Alexander Larsson mount_info = GPOINTER_TO_UINT (info_as_ptr); 7923781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 7933781343738de4abddf56982325a77bd70a98cd26Alexander Larsson if (!got_info) 7943781343738de4abddf56982325a77bd70a98cd26Alexander Larsson { 7953781343738de4abddf56982325a77bd70a98cd26Alexander Larsson mount_info = 0; 7963781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 7973781343738de4abddf56982325a77bd70a98cd26Alexander Larsson mountpoint = find_mountpoint_for (path, buf.st_dev); 7983781343738de4abddf56982325a77bd70a98cd26Alexander Larsson if (mountpoint == NULL) 799d20bf1076b25fb436791e4ea9d656a8756d1cf61Cosimo Cecchi mountpoint = g_strdup ("/"); 8003781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 801feb5258cf9ca9c3b3d9a58a98b1c6c75c822855aMatthias Clasen mount = g_unix_mount_at (mountpoint, &cache_time); 8023781343738de4abddf56982325a77bd70a98cd26Alexander Larsson if (mount) 8033781343738de4abddf56982325a77bd70a98cd26Alexander Larsson { 8043781343738de4abddf56982325a77bd70a98cd26Alexander Larsson if (g_unix_mount_is_readonly (mount)) 8053781343738de4abddf56982325a77bd70a98cd26Alexander Larsson mount_info |= MOUNT_INFO_READONLY; 8063781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 8073781343738de4abddf56982325a77bd70a98cd26Alexander Larsson g_unix_mount_free (mount); 8083781343738de4abddf56982325a77bd70a98cd26Alexander Larsson } 8093781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 810d20bf1076b25fb436791e4ea9d656a8756d1cf61Cosimo Cecchi g_free (mountpoint); 811d20bf1076b25fb436791e4ea9d656a8756d1cf61Cosimo Cecchi 8123781343738de4abddf56982325a77bd70a98cd26Alexander Larsson dev = g_new0 (dev_t, 1); 8133781343738de4abddf56982325a77bd70a98cd26Alexander Larsson *dev = buf.st_dev; 8143781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 8153781343738de4abddf56982325a77bd70a98cd26Alexander Larsson G_LOCK (mount_info_hash); 8163781343738de4abddf56982325a77bd70a98cd26Alexander Larsson mount_info_hash_cache_time = cache_time; 8173781343738de4abddf56982325a77bd70a98cd26Alexander Larsson g_hash_table_insert (mount_info_hash, dev, GUINT_TO_POINTER (mount_info)); 8183781343738de4abddf56982325a77bd70a98cd26Alexander Larsson G_UNLOCK (mount_info_hash); 8193781343738de4abddf56982325a77bd70a98cd26Alexander Larsson } 8203781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 8213781343738de4abddf56982325a77bd70a98cd26Alexander Larsson if (mount_info & MOUNT_INFO_READONLY) 82271768c8426f0d6c580368f6c1d3fc339d2041be0Alexander Larsson g_file_info_set_attribute_boolean (fs_info, G_FILE_ATTRIBUTE_FILESYSTEM_READONLY, TRUE); 8233781343738de4abddf56982325a77bd70a98cd26Alexander Larsson} 8243781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 82583445755b3b2d315feadf94cefbb74afc8f142bdTor Lillqvist#endif 82683445755b3b2d315feadf94cefbb74afc8f142bdTor Lillqvist 8271d568f35d13d7cf0206439a7a94b7fd3abd92fa3Alexander Larsson#ifdef G_OS_WIN32 8281d568f35d13d7cf0206439a7a94b7fd3abd92fa3Alexander Larsson 8291d568f35d13d7cf0206439a7a94b7fd3abd92fa3Alexander Larssonstatic gboolean 8301d568f35d13d7cf0206439a7a94b7fd3abd92fa3Alexander Larssonis_xp_or_later (void) 8311d568f35d13d7cf0206439a7a94b7fd3abd92fa3Alexander Larsson{ 8321d568f35d13d7cf0206439a7a94b7fd3abd92fa3Alexander Larsson static int result = -1; 8331d568f35d13d7cf0206439a7a94b7fd3abd92fa3Alexander Larsson 8341d568f35d13d7cf0206439a7a94b7fd3abd92fa3Alexander Larsson if (result == -1) 8351d568f35d13d7cf0206439a7a94b7fd3abd92fa3Alexander Larsson { 836cc8adfaeb84d666aeb8afadb7501498a0c8970feTor Lillqvist#ifndef _MSC_VER 8371d568f35d13d7cf0206439a7a94b7fd3abd92fa3Alexander Larsson OSVERSIONINFOEX ver_info = {0}; 8381d568f35d13d7cf0206439a7a94b7fd3abd92fa3Alexander Larsson DWORDLONG cond_mask = 0; 8391d568f35d13d7cf0206439a7a94b7fd3abd92fa3Alexander Larsson int op = VER_GREATER_EQUAL; 8401d568f35d13d7cf0206439a7a94b7fd3abd92fa3Alexander Larsson 8411d568f35d13d7cf0206439a7a94b7fd3abd92fa3Alexander Larsson ver_info.dwOSVersionInfoSize = sizeof ver_info; 8421d568f35d13d7cf0206439a7a94b7fd3abd92fa3Alexander Larsson ver_info.dwMajorVersion = 5; 8431d568f35d13d7cf0206439a7a94b7fd3abd92fa3Alexander Larsson ver_info.dwMinorVersion = 1; 8441d568f35d13d7cf0206439a7a94b7fd3abd92fa3Alexander Larsson 8451d568f35d13d7cf0206439a7a94b7fd3abd92fa3Alexander Larsson VER_SET_CONDITION (cond_mask, VER_MAJORVERSION, op); 8461d568f35d13d7cf0206439a7a94b7fd3abd92fa3Alexander Larsson VER_SET_CONDITION (cond_mask, VER_MINORVERSION, op); 8471d568f35d13d7cf0206439a7a94b7fd3abd92fa3Alexander Larsson 8481d568f35d13d7cf0206439a7a94b7fd3abd92fa3Alexander Larsson result = VerifyVersionInfo (&ver_info, 8491d568f35d13d7cf0206439a7a94b7fd3abd92fa3Alexander Larsson VER_MAJORVERSION | VER_MINORVERSION, 8501d568f35d13d7cf0206439a7a94b7fd3abd92fa3Alexander Larsson cond_mask) != 0; 851cc8adfaeb84d666aeb8afadb7501498a0c8970feTor Lillqvist#else 852cc8adfaeb84d666aeb8afadb7501498a0c8970feTor Lillqvist result = ((DWORD)(LOBYTE (LOWORD (GetVersion ())))) >= 5; 853cc8adfaeb84d666aeb8afadb7501498a0c8970feTor Lillqvist#endif 8541d568f35d13d7cf0206439a7a94b7fd3abd92fa3Alexander Larsson } 8551d568f35d13d7cf0206439a7a94b7fd3abd92fa3Alexander Larsson 8561d568f35d13d7cf0206439a7a94b7fd3abd92fa3Alexander Larsson return result; 8571d568f35d13d7cf0206439a7a94b7fd3abd92fa3Alexander Larsson} 8581d568f35d13d7cf0206439a7a94b7fd3abd92fa3Alexander Larsson 8591d568f35d13d7cf0206439a7a94b7fd3abd92fa3Alexander Larssonstatic wchar_t * 8601d568f35d13d7cf0206439a7a94b7fd3abd92fa3Alexander Larssonget_volume_for_path (const char *path) 8611d568f35d13d7cf0206439a7a94b7fd3abd92fa3Alexander Larsson{ 8621d568f35d13d7cf0206439a7a94b7fd3abd92fa3Alexander Larsson long len; 8631d568f35d13d7cf0206439a7a94b7fd3abd92fa3Alexander Larsson wchar_t *wpath; 8641d568f35d13d7cf0206439a7a94b7fd3abd92fa3Alexander Larsson wchar_t *result; 8651d568f35d13d7cf0206439a7a94b7fd3abd92fa3Alexander Larsson 866801da1dfc1cf8f41be8a9e101c28b335af974f93Tor Lillqvist wpath = g_utf8_to_utf16 (path, -1, NULL, NULL, NULL); 867801da1dfc1cf8f41be8a9e101c28b335af974f93Tor Lillqvist result = g_new (wchar_t, MAX_PATH); 8681d568f35d13d7cf0206439a7a94b7fd3abd92fa3Alexander Larsson 869801da1dfc1cf8f41be8a9e101c28b335af974f93Tor Lillqvist if (!GetVolumePathNameW (wpath, result, MAX_PATH)) 8701d568f35d13d7cf0206439a7a94b7fd3abd92fa3Alexander Larsson { 8711d568f35d13d7cf0206439a7a94b7fd3abd92fa3Alexander Larsson char *msg = g_win32_error_message (GetLastError ()); 8721d568f35d13d7cf0206439a7a94b7fd3abd92fa3Alexander Larsson g_critical ("GetVolumePathName failed: %s", msg); 8731d568f35d13d7cf0206439a7a94b7fd3abd92fa3Alexander Larsson g_free (msg); 8741d568f35d13d7cf0206439a7a94b7fd3abd92fa3Alexander Larsson g_free (result); 8751d568f35d13d7cf0206439a7a94b7fd3abd92fa3Alexander Larsson g_free (wpath); 8761d568f35d13d7cf0206439a7a94b7fd3abd92fa3Alexander Larsson return NULL; 8771d568f35d13d7cf0206439a7a94b7fd3abd92fa3Alexander Larsson } 8781d568f35d13d7cf0206439a7a94b7fd3abd92fa3Alexander Larsson 8791d568f35d13d7cf0206439a7a94b7fd3abd92fa3Alexander Larsson len = wcslen (result); 8801d568f35d13d7cf0206439a7a94b7fd3abd92fa3Alexander Larsson if (len > 0 && result[len-1] != L'\\') 8811d568f35d13d7cf0206439a7a94b7fd3abd92fa3Alexander Larsson { 8821d568f35d13d7cf0206439a7a94b7fd3abd92fa3Alexander Larsson result = g_renew (wchar_t, result, len + 2); 8831d568f35d13d7cf0206439a7a94b7fd3abd92fa3Alexander Larsson result[len] = L'\\'; 8841d568f35d13d7cf0206439a7a94b7fd3abd92fa3Alexander Larsson result[len + 1] = 0; 8851d568f35d13d7cf0206439a7a94b7fd3abd92fa3Alexander Larsson } 8861d568f35d13d7cf0206439a7a94b7fd3abd92fa3Alexander Larsson 8871d568f35d13d7cf0206439a7a94b7fd3abd92fa3Alexander Larsson g_free (wpath); 8881d568f35d13d7cf0206439a7a94b7fd3abd92fa3Alexander Larsson return result; 8891d568f35d13d7cf0206439a7a94b7fd3abd92fa3Alexander Larsson} 8901d568f35d13d7cf0206439a7a94b7fd3abd92fa3Alexander Larsson 8911d568f35d13d7cf0206439a7a94b7fd3abd92fa3Alexander Larssonstatic char * 8921d568f35d13d7cf0206439a7a94b7fd3abd92fa3Alexander Larssonfind_mountpoint_for (const char *file, dev_t dev) 8931d568f35d13d7cf0206439a7a94b7fd3abd92fa3Alexander Larsson{ 8941d568f35d13d7cf0206439a7a94b7fd3abd92fa3Alexander Larsson wchar_t *wpath; 8951d568f35d13d7cf0206439a7a94b7fd3abd92fa3Alexander Larsson char *utf8_path; 8961d568f35d13d7cf0206439a7a94b7fd3abd92fa3Alexander Larsson 8971d568f35d13d7cf0206439a7a94b7fd3abd92fa3Alexander Larsson wpath = get_volume_for_path (file); 8981d568f35d13d7cf0206439a7a94b7fd3abd92fa3Alexander Larsson if (!wpath) 8991d568f35d13d7cf0206439a7a94b7fd3abd92fa3Alexander Larsson return NULL; 9001d568f35d13d7cf0206439a7a94b7fd3abd92fa3Alexander Larsson 9011d568f35d13d7cf0206439a7a94b7fd3abd92fa3Alexander Larsson utf8_path = g_utf16_to_utf8 (wpath, -1, NULL, NULL, NULL); 9021d568f35d13d7cf0206439a7a94b7fd3abd92fa3Alexander Larsson 9031d568f35d13d7cf0206439a7a94b7fd3abd92fa3Alexander Larsson g_free (wpath); 9041d568f35d13d7cf0206439a7a94b7fd3abd92fa3Alexander Larsson return utf8_path; 9051d568f35d13d7cf0206439a7a94b7fd3abd92fa3Alexander Larsson} 9061d568f35d13d7cf0206439a7a94b7fd3abd92fa3Alexander Larsson 9071d568f35d13d7cf0206439a7a94b7fd3abd92fa3Alexander Larssonstatic void 9081d568f35d13d7cf0206439a7a94b7fd3abd92fa3Alexander Larssonget_filesystem_readonly (GFileInfo *info, 9091d568f35d13d7cf0206439a7a94b7fd3abd92fa3Alexander Larsson const char *path) 9101d568f35d13d7cf0206439a7a94b7fd3abd92fa3Alexander Larsson{ 9111d568f35d13d7cf0206439a7a94b7fd3abd92fa3Alexander Larsson wchar_t *rootdir; 9121d568f35d13d7cf0206439a7a94b7fd3abd92fa3Alexander Larsson 9131d568f35d13d7cf0206439a7a94b7fd3abd92fa3Alexander Larsson rootdir = get_volume_for_path (path); 9141d568f35d13d7cf0206439a7a94b7fd3abd92fa3Alexander Larsson 9151d568f35d13d7cf0206439a7a94b7fd3abd92fa3Alexander Larsson if (rootdir) 9161d568f35d13d7cf0206439a7a94b7fd3abd92fa3Alexander Larsson { 9171d568f35d13d7cf0206439a7a94b7fd3abd92fa3Alexander Larsson if (is_xp_or_later ()) 9181d568f35d13d7cf0206439a7a94b7fd3abd92fa3Alexander Larsson { 9191d568f35d13d7cf0206439a7a94b7fd3abd92fa3Alexander Larsson DWORD flags; 9201d568f35d13d7cf0206439a7a94b7fd3abd92fa3Alexander Larsson if (GetVolumeInformationW (rootdir, NULL, 0, NULL, NULL, &flags, NULL, 0)) 9211d568f35d13d7cf0206439a7a94b7fd3abd92fa3Alexander Larsson g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_FILESYSTEM_READONLY, 9221d568f35d13d7cf0206439a7a94b7fd3abd92fa3Alexander Larsson (flags & FILE_READ_ONLY_VOLUME) != 0); 9231d568f35d13d7cf0206439a7a94b7fd3abd92fa3Alexander Larsson } 9241d568f35d13d7cf0206439a7a94b7fd3abd92fa3Alexander Larsson else 9251d568f35d13d7cf0206439a7a94b7fd3abd92fa3Alexander Larsson { 9261d568f35d13d7cf0206439a7a94b7fd3abd92fa3Alexander Larsson if (GetDriveTypeW (rootdir) == DRIVE_CDROM) 9271d568f35d13d7cf0206439a7a94b7fd3abd92fa3Alexander Larsson g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_FILESYSTEM_READONLY, TRUE); 9281d568f35d13d7cf0206439a7a94b7fd3abd92fa3Alexander Larsson } 9291d568f35d13d7cf0206439a7a94b7fd3abd92fa3Alexander Larsson } 9301d568f35d13d7cf0206439a7a94b7fd3abd92fa3Alexander Larsson 9311d568f35d13d7cf0206439a7a94b7fd3abd92fa3Alexander Larsson g_free (rootdir); 9321d568f35d13d7cf0206439a7a94b7fd3abd92fa3Alexander Larsson} 9331d568f35d13d7cf0206439a7a94b7fd3abd92fa3Alexander Larsson 9341d568f35d13d7cf0206439a7a94b7fd3abd92fa3Alexander Larsson#endif /* G_OS_WIN32 */ 9351d568f35d13d7cf0206439a7a94b7fd3abd92fa3Alexander Larsson 9363781343738de4abddf56982325a77bd70a98cd26Alexander Larssonstatic GFileInfo * 937a2ca589703273fca80cb126430a8b058aba3eb52Matthias Claseng_local_file_query_filesystem_info (GFile *file, 938a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen const char *attributes, 939a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen GCancellable *cancellable, 940a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen GError **error) 9413781343738de4abddf56982325a77bd70a98cd26Alexander Larsson{ 9423781343738de4abddf56982325a77bd70a98cd26Alexander Larsson GLocalFile *local = G_LOCAL_FILE (file); 9433781343738de4abddf56982325a77bd70a98cd26Alexander Larsson GFileInfo *info; 944cc8adfaeb84d666aeb8afadb7501498a0c8970feTor Lillqvist int statfs_result = 0; 9453781343738de4abddf56982325a77bd70a98cd26Alexander Larsson gboolean no_size; 94683445755b3b2d315feadf94cefbb74afc8f142bdTor Lillqvist#ifndef G_OS_WIN32 9473781343738de4abddf56982325a77bd70a98cd26Alexander Larsson guint64 block_size; 94858e4b463431520d76ea750d31e14e38f8440c42esimon.zheng const char *fstype; 9493781343738de4abddf56982325a77bd70a98cd26Alexander Larsson#ifdef USE_STATFS 9503781343738de4abddf56982325a77bd70a98cd26Alexander Larsson struct statfs statfs_buffer; 9513781343738de4abddf56982325a77bd70a98cd26Alexander Larsson#elif defined(USE_STATVFS) 9523781343738de4abddf56982325a77bd70a98cd26Alexander Larsson struct statvfs statfs_buffer; 9533781343738de4abddf56982325a77bd70a98cd26Alexander Larsson#endif 95483445755b3b2d315feadf94cefbb74afc8f142bdTor Lillqvist#endif 9553781343738de4abddf56982325a77bd70a98cd26Alexander Larsson GFileAttributeMatcher *attribute_matcher; 9563781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 9573781343738de4abddf56982325a77bd70a98cd26Alexander Larsson no_size = FALSE; 9583781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 9593781343738de4abddf56982325a77bd70a98cd26Alexander Larsson#ifdef USE_STATFS 9603781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 9613781343738de4abddf56982325a77bd70a98cd26Alexander Larsson#if STATFS_ARGS == 2 9623781343738de4abddf56982325a77bd70a98cd26Alexander Larsson statfs_result = statfs (local->filename, &statfs_buffer); 9633781343738de4abddf56982325a77bd70a98cd26Alexander Larsson#elif STATFS_ARGS == 4 9643781343738de4abddf56982325a77bd70a98cd26Alexander Larsson statfs_result = statfs (local->filename, &statfs_buffer, 9653781343738de4abddf56982325a77bd70a98cd26Alexander Larsson sizeof (statfs_buffer), 0); 9663781343738de4abddf56982325a77bd70a98cd26Alexander Larsson#endif 9673781343738de4abddf56982325a77bd70a98cd26Alexander Larsson block_size = statfs_buffer.f_bsize; 9683781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 9690b9f24c1e15254da8e105c88290b4d53976e6d0eAlexander Larsson /* Many backends can't report free size (for instance the gvfs fuse 9700b9f24c1e15254da8e105c88290b4d53976e6d0eAlexander Larsson backend for backend not supporting this), and set f_bfree to 0, 9710b9f24c1e15254da8e105c88290b4d53976e6d0eAlexander Larsson but it can be 0 for real too. We treat the availible == 0 and 9720b9f24c1e15254da8e105c88290b4d53976e6d0eAlexander Larsson free == 0 case as "both of these are invalid". 9733781343738de4abddf56982325a77bd70a98cd26Alexander Larsson */ 9740b9f24c1e15254da8e105c88290b4d53976e6d0eAlexander Larsson#ifndef G_OS_WIN32 9750b9f24c1e15254da8e105c88290b4d53976e6d0eAlexander Larsson if (statfs_buffer.f_bavail == 0 && statfs_buffer.f_bfree == 0) 9763781343738de4abddf56982325a77bd70a98cd26Alexander Larsson no_size = TRUE; 9773781343738de4abddf56982325a77bd70a98cd26Alexander Larsson#endif 9783781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 9793781343738de4abddf56982325a77bd70a98cd26Alexander Larsson#elif defined(USE_STATVFS) 9803781343738de4abddf56982325a77bd70a98cd26Alexander Larsson statfs_result = statvfs (local->filename, &statfs_buffer); 9813781343738de4abddf56982325a77bd70a98cd26Alexander Larsson block_size = statfs_buffer.f_frsize; 9823781343738de4abddf56982325a77bd70a98cd26Alexander Larsson#endif 9833781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 9843781343738de4abddf56982325a77bd70a98cd26Alexander Larsson if (statfs_result == -1) 9853781343738de4abddf56982325a77bd70a98cd26Alexander Larsson { 98637ac644bd18168330f43f4d52be7e3cbb3415415Christian Persch int errsv = errno; 98737ac644bd18168330f43f4d52be7e3cbb3415415Christian Persch 9883781343738de4abddf56982325a77bd70a98cd26Alexander Larsson g_set_error (error, G_IO_ERROR, 98937ac644bd18168330f43f4d52be7e3cbb3415415Christian Persch g_io_error_from_errno (errsv), 9903781343738de4abddf56982325a77bd70a98cd26Alexander Larsson _("Error getting filesystem info: %s"), 99137ac644bd18168330f43f4d52be7e3cbb3415415Christian Persch g_strerror (errsv)); 9923781343738de4abddf56982325a77bd70a98cd26Alexander Larsson return NULL; 9933781343738de4abddf56982325a77bd70a98cd26Alexander Larsson } 9943781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 9953781343738de4abddf56982325a77bd70a98cd26Alexander Larsson info = g_file_info_new (); 9963781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 9973781343738de4abddf56982325a77bd70a98cd26Alexander Larsson attribute_matcher = g_file_attribute_matcher_new (attributes); 9983781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 999a30f8df3c8bbfa877ec607a82b9057b4a3dd11b8Matthias Clasen if (!no_size && 1000a30f8df3c8bbfa877ec607a82b9057b4a3dd11b8Matthias Clasen g_file_attribute_matcher_matches (attribute_matcher, 100171768c8426f0d6c580368f6c1d3fc339d2041be0Alexander Larsson G_FILE_ATTRIBUTE_FILESYSTEM_FREE)) 1002a33f8a7564cc649daf0dca0d67daac8430808cf9Hans Breuer { 1003a33f8a7564cc649daf0dca0d67daac8430808cf9Hans Breuer#ifdef G_OS_WIN32 1004a33f8a7564cc649daf0dca0d67daac8430808cf9Hans Breuer gchar *localdir = g_path_get_dirname (local->filename); 1005a33f8a7564cc649daf0dca0d67daac8430808cf9Hans Breuer wchar_t *wdirname = g_utf8_to_utf16 (localdir, -1, NULL, NULL, NULL); 1006a33f8a7564cc649daf0dca0d67daac8430808cf9Hans Breuer ULARGE_INTEGER li; 1007a33f8a7564cc649daf0dca0d67daac8430808cf9Hans Breuer 1008a33f8a7564cc649daf0dca0d67daac8430808cf9Hans Breuer g_free (localdir); 1009a33f8a7564cc649daf0dca0d67daac8430808cf9Hans Breuer if (GetDiskFreeSpaceExW (wdirname, &li, NULL, NULL)) 101071768c8426f0d6c580368f6c1d3fc339d2041be0Alexander Larsson g_file_info_set_attribute_uint64 (info, G_FILE_ATTRIBUTE_FILESYSTEM_FREE, (guint64)li.QuadPart); 1011a33f8a7564cc649daf0dca0d67daac8430808cf9Hans Breuer g_free (wdirname); 1012a33f8a7564cc649daf0dca0d67daac8430808cf9Hans Breuer#else 101371768c8426f0d6c580368f6c1d3fc339d2041be0Alexander Larsson g_file_info_set_attribute_uint64 (info, G_FILE_ATTRIBUTE_FILESYSTEM_FREE, block_size * statfs_buffer.f_bavail); 1014a33f8a7564cc649daf0dca0d67daac8430808cf9Hans Breuer#endif 1015a33f8a7564cc649daf0dca0d67daac8430808cf9Hans Breuer } 1016a30f8df3c8bbfa877ec607a82b9057b4a3dd11b8Matthias Clasen if (!no_size && 1017a30f8df3c8bbfa877ec607a82b9057b4a3dd11b8Matthias Clasen g_file_attribute_matcher_matches (attribute_matcher, 101871768c8426f0d6c580368f6c1d3fc339d2041be0Alexander Larsson G_FILE_ATTRIBUTE_FILESYSTEM_SIZE)) 1019a33f8a7564cc649daf0dca0d67daac8430808cf9Hans Breuer { 1020a33f8a7564cc649daf0dca0d67daac8430808cf9Hans Breuer#ifdef G_OS_WIN32 1021a33f8a7564cc649daf0dca0d67daac8430808cf9Hans Breuer gchar *localdir = g_path_get_dirname (local->filename); 1022a33f8a7564cc649daf0dca0d67daac8430808cf9Hans Breuer wchar_t *wdirname = g_utf8_to_utf16 (localdir, -1, NULL, NULL, NULL); 1023a33f8a7564cc649daf0dca0d67daac8430808cf9Hans Breuer ULARGE_INTEGER li; 1024a33f8a7564cc649daf0dca0d67daac8430808cf9Hans Breuer 1025a33f8a7564cc649daf0dca0d67daac8430808cf9Hans Breuer g_free (localdir); 1026a33f8a7564cc649daf0dca0d67daac8430808cf9Hans Breuer if (GetDiskFreeSpaceExW (wdirname, NULL, &li, NULL)) 102771768c8426f0d6c580368f6c1d3fc339d2041be0Alexander Larsson g_file_info_set_attribute_uint64 (info, G_FILE_ATTRIBUTE_FILESYSTEM_SIZE, (guint64)li.QuadPart); 1028a33f8a7564cc649daf0dca0d67daac8430808cf9Hans Breuer g_free (wdirname); 1029a33f8a7564cc649daf0dca0d67daac8430808cf9Hans Breuer#else 103071768c8426f0d6c580368f6c1d3fc339d2041be0Alexander Larsson g_file_info_set_attribute_uint64 (info, G_FILE_ATTRIBUTE_FILESYSTEM_SIZE, block_size * statfs_buffer.f_blocks); 1031a33f8a7564cc649daf0dca0d67daac8430808cf9Hans Breuer#endif 1032a33f8a7564cc649daf0dca0d67daac8430808cf9Hans Breuer } 10333781343738de4abddf56982325a77bd70a98cd26Alexander Larsson#ifdef USE_STATFS 10347437486b3613a6bdf7f73334a4c4ceaf4539d8f8Alexander Larsson#if defined(HAVE_STRUCT_STATFS_F_FSTYPENAME) 10353cacbe8178316e0c98c12231b18e032818178497Alexander Larsson fstype = g_strdup(statfs_buffer.f_fstypename); 10363cacbe8178316e0c98c12231b18e032818178497Alexander Larsson#else 10373781343738de4abddf56982325a77bd70a98cd26Alexander Larsson fstype = get_fs_type (statfs_buffer.f_type); 10383cacbe8178316e0c98c12231b18e032818178497Alexander Larsson#endif 103958e4b463431520d76ea750d31e14e38f8440c42esimon.zheng 104058e4b463431520d76ea750d31e14e38f8440c42esimon.zheng#elif defined(USE_STATVFS) && defined(HAVE_STRUCT_STATVFS_F_BASETYPE) 104158e4b463431520d76ea750d31e14e38f8440c42esimon.zheng fstype = g_strdup(statfs_buffer.f_basetype); 104258e4b463431520d76ea750d31e14e38f8440c42esimon.zheng#endif 104358e4b463431520d76ea750d31e14e38f8440c42esimon.zheng 104458e4b463431520d76ea750d31e14e38f8440c42esimon.zheng#ifndef G_OS_WIN32 10453781343738de4abddf56982325a77bd70a98cd26Alexander Larsson if (fstype && 10463781343738de4abddf56982325a77bd70a98cd26Alexander Larsson g_file_attribute_matcher_matches (attribute_matcher, 104771768c8426f0d6c580368f6c1d3fc339d2041be0Alexander Larsson G_FILE_ATTRIBUTE_FILESYSTEM_TYPE)) 104871768c8426f0d6c580368f6c1d3fc339d2041be0Alexander Larsson g_file_info_set_attribute_string (info, G_FILE_ATTRIBUTE_FILESYSTEM_TYPE, fstype); 10493781343738de4abddf56982325a77bd70a98cd26Alexander Larsson#endif 10503781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 10513781343738de4abddf56982325a77bd70a98cd26Alexander Larsson if (g_file_attribute_matcher_matches (attribute_matcher, 105271768c8426f0d6c580368f6c1d3fc339d2041be0Alexander Larsson G_FILE_ATTRIBUTE_FILESYSTEM_READONLY)) 10533781343738de4abddf56982325a77bd70a98cd26Alexander Larsson { 1054a33f8a7564cc649daf0dca0d67daac8430808cf9Hans Breuer#ifdef G_OS_WIN32 10551d568f35d13d7cf0206439a7a94b7fd3abd92fa3Alexander Larsson get_filesystem_readonly (info, local->filename); 1056a33f8a7564cc649daf0dca0d67daac8430808cf9Hans Breuer#else 10573781343738de4abddf56982325a77bd70a98cd26Alexander Larsson get_mount_info (info, local->filename, attribute_matcher); 1058a33f8a7564cc649daf0dca0d67daac8430808cf9Hans Breuer#endif 10593781343738de4abddf56982325a77bd70a98cd26Alexander Larsson } 10603781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 10613781343738de4abddf56982325a77bd70a98cd26Alexander Larsson g_file_attribute_matcher_unref (attribute_matcher); 10623781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 10633781343738de4abddf56982325a77bd70a98cd26Alexander Larsson return info; 10643781343738de4abddf56982325a77bd70a98cd26Alexander Larsson} 10653781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 10663ca9fd4dbb134088bf70f2f6584f14a559e6820aDavid Zeuthenstatic GMount * 10673ca9fd4dbb134088bf70f2f6584f14a559e6820aDavid Zeutheng_local_file_find_enclosing_mount (GFile *file, 10683ca9fd4dbb134088bf70f2f6584f14a559e6820aDavid Zeuthen GCancellable *cancellable, 10693ca9fd4dbb134088bf70f2f6584f14a559e6820aDavid Zeuthen GError **error) 10703781343738de4abddf56982325a77bd70a98cd26Alexander Larsson{ 10713781343738de4abddf56982325a77bd70a98cd26Alexander Larsson GLocalFile *local = G_LOCAL_FILE (file); 10723781343738de4abddf56982325a77bd70a98cd26Alexander Larsson struct stat buf; 10733781343738de4abddf56982325a77bd70a98cd26Alexander Larsson char *mountpoint; 10743ca9fd4dbb134088bf70f2f6584f14a559e6820aDavid Zeuthen GMount *mount; 10753781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 1076a33f8a7564cc649daf0dca0d67daac8430808cf9Hans Breuer if (g_lstat (local->filename, &buf) != 0) 10773781343738de4abddf56982325a77bd70a98cd26Alexander Larsson { 10789c17697b56501d11b4c653432cc9e290347aa03eChristian Persch g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND, 10798b294f1f9d4588f6ad68a61546d0e7391b3f09cfWouter Bolsterlee /* Translators: This is an error message when trying to 10808b294f1f9d4588f6ad68a61546d0e7391b3f09cfWouter Bolsterlee * find the enclosing (user visible) mount of a file, but 10818b294f1f9d4588f6ad68a61546d0e7391b3f09cfWouter Bolsterlee * none exists. */ 10828b294f1f9d4588f6ad68a61546d0e7391b3f09cfWouter Bolsterlee _("Containing mount does not exist")); 10833781343738de4abddf56982325a77bd70a98cd26Alexander Larsson return NULL; 10843781343738de4abddf56982325a77bd70a98cd26Alexander Larsson } 10853781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 10863781343738de4abddf56982325a77bd70a98cd26Alexander Larsson mountpoint = find_mountpoint_for (local->filename, buf.st_dev); 10873781343738de4abddf56982325a77bd70a98cd26Alexander Larsson if (mountpoint == NULL) 10883781343738de4abddf56982325a77bd70a98cd26Alexander Larsson { 10899c17697b56501d11b4c653432cc9e290347aa03eChristian Persch g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND, 10908b294f1f9d4588f6ad68a61546d0e7391b3f09cfWouter Bolsterlee /* Translators: This is an error message when trying to 10918b294f1f9d4588f6ad68a61546d0e7391b3f09cfWouter Bolsterlee * find the enclosing (user visible) mount of a file, but 10928b294f1f9d4588f6ad68a61546d0e7391b3f09cfWouter Bolsterlee * none exists. */ 10938b294f1f9d4588f6ad68a61546d0e7391b3f09cfWouter Bolsterlee _("Containing mount does not exist")); 10943781343738de4abddf56982325a77bd70a98cd26Alexander Larsson return NULL; 10953781343738de4abddf56982325a77bd70a98cd26Alexander Larsson } 10963781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 1097c4e3cfbf4070d9bf255d08e23591e8a8dc476d72Alexander Larsson mount = _g_mount_get_for_mount_path (mountpoint, cancellable); 10983781343738de4abddf56982325a77bd70a98cd26Alexander Larsson g_free (mountpoint); 10993ca9fd4dbb134088bf70f2f6584f14a559e6820aDavid Zeuthen if (mount) 11003ca9fd4dbb134088bf70f2f6584f14a559e6820aDavid Zeuthen return mount; 11013781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 11029c17697b56501d11b4c653432cc9e290347aa03eChristian Persch g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND, 11038b294f1f9d4588f6ad68a61546d0e7391b3f09cfWouter Bolsterlee /* Translators: This is an error message when trying to find 11048b294f1f9d4588f6ad68a61546d0e7391b3f09cfWouter Bolsterlee * the enclosing (user visible) mount of a file, but none 11058b294f1f9d4588f6ad68a61546d0e7391b3f09cfWouter Bolsterlee * exists. */ 11068b294f1f9d4588f6ad68a61546d0e7391b3f09cfWouter Bolsterlee _("Containing mount does not exist")); 11073781343738de4abddf56982325a77bd70a98cd26Alexander Larsson return NULL; 11083781343738de4abddf56982325a77bd70a98cd26Alexander Larsson} 11093781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 11103781343738de4abddf56982325a77bd70a98cd26Alexander Larssonstatic GFile * 1111a2ca589703273fca80cb126430a8b058aba3eb52Matthias Claseng_local_file_set_display_name (GFile *file, 1112a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen const char *display_name, 1113a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen GCancellable *cancellable, 1114a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen GError **error) 11153781343738de4abddf56982325a77bd70a98cd26Alexander Larsson{ 11163781343738de4abddf56982325a77bd70a98cd26Alexander Larsson GLocalFile *local, *new_local; 11173781343738de4abddf56982325a77bd70a98cd26Alexander Larsson GFile *new_file, *parent; 11183781343738de4abddf56982325a77bd70a98cd26Alexander Larsson struct stat statbuf; 11193781343738de4abddf56982325a77bd70a98cd26Alexander Larsson int errsv; 11203781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 11213781343738de4abddf56982325a77bd70a98cd26Alexander Larsson parent = g_file_get_parent (file); 11223781343738de4abddf56982325a77bd70a98cd26Alexander Larsson if (parent == NULL) 11233781343738de4abddf56982325a77bd70a98cd26Alexander Larsson { 11249c17697b56501d11b4c653432cc9e290347aa03eChristian Persch g_set_error_literal (error, G_IO_ERROR, 11259c17697b56501d11b4c653432cc9e290347aa03eChristian Persch G_IO_ERROR_FAILED, 11269c17697b56501d11b4c653432cc9e290347aa03eChristian Persch _("Can't rename root directory")); 11273781343738de4abddf56982325a77bd70a98cd26Alexander Larsson return NULL; 11283781343738de4abddf56982325a77bd70a98cd26Alexander Larsson } 11293781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 113054300dde6d77867aa53e60a2bdfd69cb9e644315Matthias Clasen new_file = g_file_get_child_for_display_name (parent, display_name, error); 11313781343738de4abddf56982325a77bd70a98cd26Alexander Larsson g_object_unref (parent); 11323781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 11333781343738de4abddf56982325a77bd70a98cd26Alexander Larsson if (new_file == NULL) 11343781343738de4abddf56982325a77bd70a98cd26Alexander Larsson return NULL; 11353781343738de4abddf56982325a77bd70a98cd26Alexander Larsson local = G_LOCAL_FILE (file); 11363781343738de4abddf56982325a77bd70a98cd26Alexander Larsson new_local = G_LOCAL_FILE (new_file); 11373781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 1138d4d876846e62b613a1e5b80519e4a9a49eb905dcMatthias Clasen if (g_lstat (new_local->filename, &statbuf) == -1) 1139d4d876846e62b613a1e5b80519e4a9a49eb905dcMatthias Clasen { 1140d4d876846e62b613a1e5b80519e4a9a49eb905dcMatthias Clasen errsv = errno; 1141d4d876846e62b613a1e5b80519e4a9a49eb905dcMatthias Clasen 1142d4d876846e62b613a1e5b80519e4a9a49eb905dcMatthias Clasen if (errsv != ENOENT) 1143d4d876846e62b613a1e5b80519e4a9a49eb905dcMatthias Clasen { 1144d4d876846e62b613a1e5b80519e4a9a49eb905dcMatthias Clasen g_set_error (error, G_IO_ERROR, 1145d4d876846e62b613a1e5b80519e4a9a49eb905dcMatthias Clasen g_io_error_from_errno (errsv), 1146d4d876846e62b613a1e5b80519e4a9a49eb905dcMatthias Clasen _("Error renaming file: %s"), 1147d4d876846e62b613a1e5b80519e4a9a49eb905dcMatthias Clasen g_strerror (errsv)); 1148d4d876846e62b613a1e5b80519e4a9a49eb905dcMatthias Clasen return NULL; 1149d4d876846e62b613a1e5b80519e4a9a49eb905dcMatthias Clasen } 1150d4d876846e62b613a1e5b80519e4a9a49eb905dcMatthias Clasen } 1151d4d876846e62b613a1e5b80519e4a9a49eb905dcMatthias Clasen else 11523781343738de4abddf56982325a77bd70a98cd26Alexander Larsson { 11539c17697b56501d11b4c653432cc9e290347aa03eChristian Persch g_set_error_literal (error, G_IO_ERROR, 11549c17697b56501d11b4c653432cc9e290347aa03eChristian Persch G_IO_ERROR_EXISTS, 11559c17697b56501d11b4c653432cc9e290347aa03eChristian Persch _("Can't rename file, filename already exist")); 11563781343738de4abddf56982325a77bd70a98cd26Alexander Larsson return NULL; 11573781343738de4abddf56982325a77bd70a98cd26Alexander Larsson } 11583781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 11593b1b6a9722f40495762fbb115a43b39d495c3170Alexander Larsson if (g_rename (local->filename, new_local->filename) == -1) 11603781343738de4abddf56982325a77bd70a98cd26Alexander Larsson { 11613781343738de4abddf56982325a77bd70a98cd26Alexander Larsson errsv = errno; 11623781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 11633781343738de4abddf56982325a77bd70a98cd26Alexander Larsson if (errsv == EINVAL) 11643781343738de4abddf56982325a77bd70a98cd26Alexander Larsson /* We can't get a rename file into itself error herer, 11653781343738de4abddf56982325a77bd70a98cd26Alexander Larsson so this must be an invalid filename, on e.g. FAT */ 11669c17697b56501d11b4c653432cc9e290347aa03eChristian Persch g_set_error_literal (error, G_IO_ERROR, 11679c17697b56501d11b4c653432cc9e290347aa03eChristian Persch G_IO_ERROR_INVALID_FILENAME, 11689c17697b56501d11b4c653432cc9e290347aa03eChristian Persch _("Invalid filename")); 11693781343738de4abddf56982325a77bd70a98cd26Alexander Larsson else 11703781343738de4abddf56982325a77bd70a98cd26Alexander Larsson g_set_error (error, G_IO_ERROR, 11713781343738de4abddf56982325a77bd70a98cd26Alexander Larsson g_io_error_from_errno (errsv), 11723781343738de4abddf56982325a77bd70a98cd26Alexander Larsson _("Error renaming file: %s"), 11733781343738de4abddf56982325a77bd70a98cd26Alexander Larsson g_strerror (errsv)); 11743781343738de4abddf56982325a77bd70a98cd26Alexander Larsson g_object_unref (new_file); 11753781343738de4abddf56982325a77bd70a98cd26Alexander Larsson return NULL; 11763781343738de4abddf56982325a77bd70a98cd26Alexander Larsson } 11773781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 11783781343738de4abddf56982325a77bd70a98cd26Alexander Larsson return new_file; 11793781343738de4abddf56982325a77bd70a98cd26Alexander Larsson} 11803781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 11813781343738de4abddf56982325a77bd70a98cd26Alexander Larssonstatic GFileInfo * 11823781343738de4abddf56982325a77bd70a98cd26Alexander Larssong_local_file_query_info (GFile *file, 11833781343738de4abddf56982325a77bd70a98cd26Alexander Larsson const char *attributes, 11843781343738de4abddf56982325a77bd70a98cd26Alexander Larsson GFileQueryInfoFlags flags, 11853781343738de4abddf56982325a77bd70a98cd26Alexander Larsson GCancellable *cancellable, 11863781343738de4abddf56982325a77bd70a98cd26Alexander Larsson GError **error) 11873781343738de4abddf56982325a77bd70a98cd26Alexander Larsson{ 11883781343738de4abddf56982325a77bd70a98cd26Alexander Larsson GLocalFile *local = G_LOCAL_FILE (file); 11893781343738de4abddf56982325a77bd70a98cd26Alexander Larsson GFileInfo *info; 11903781343738de4abddf56982325a77bd70a98cd26Alexander Larsson GFileAttributeMatcher *matcher; 11913781343738de4abddf56982325a77bd70a98cd26Alexander Larsson char *basename, *dirname; 11923781343738de4abddf56982325a77bd70a98cd26Alexander Larsson GLocalParentFileInfo parent_info; 11933781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 11943781343738de4abddf56982325a77bd70a98cd26Alexander Larsson matcher = g_file_attribute_matcher_new (attributes); 11953781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 11963781343738de4abddf56982325a77bd70a98cd26Alexander Larsson basename = g_path_get_basename (local->filename); 11973781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 11983781343738de4abddf56982325a77bd70a98cd26Alexander Larsson dirname = g_path_get_dirname (local->filename); 11993781343738de4abddf56982325a77bd70a98cd26Alexander Larsson _g_local_file_info_get_parent_info (dirname, matcher, &parent_info); 12003781343738de4abddf56982325a77bd70a98cd26Alexander Larsson g_free (dirname); 12013781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 12023781343738de4abddf56982325a77bd70a98cd26Alexander Larsson info = _g_local_file_info_get (basename, local->filename, 12033781343738de4abddf56982325a77bd70a98cd26Alexander Larsson matcher, flags, &parent_info, 12043781343738de4abddf56982325a77bd70a98cd26Alexander Larsson error); 12053781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 12063781343738de4abddf56982325a77bd70a98cd26Alexander Larsson g_free (basename); 12073781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 12083781343738de4abddf56982325a77bd70a98cd26Alexander Larsson g_file_attribute_matcher_unref (matcher); 12093781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 12103781343738de4abddf56982325a77bd70a98cd26Alexander Larsson return info; 12113781343738de4abddf56982325a77bd70a98cd26Alexander Larsson} 12123781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 12133781343738de4abddf56982325a77bd70a98cd26Alexander Larssonstatic GFileAttributeInfoList * 1214a2ca589703273fca80cb126430a8b058aba3eb52Matthias Claseng_local_file_query_settable_attributes (GFile *file, 1215a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen GCancellable *cancellable, 1216a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen GError **error) 12173781343738de4abddf56982325a77bd70a98cd26Alexander Larsson{ 12183781343738de4abddf56982325a77bd70a98cd26Alexander Larsson return g_file_attribute_info_list_ref (local_writable_attributes); 12193781343738de4abddf56982325a77bd70a98cd26Alexander Larsson} 12203781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 12213781343738de4abddf56982325a77bd70a98cd26Alexander Larssonstatic GFileAttributeInfoList * 1222a2ca589703273fca80cb126430a8b058aba3eb52Matthias Claseng_local_file_query_writable_namespaces (GFile *file, 1223a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen GCancellable *cancellable, 1224a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen GError **error) 12253781343738de4abddf56982325a77bd70a98cd26Alexander Larsson{ 12263781343738de4abddf56982325a77bd70a98cd26Alexander Larsson return g_file_attribute_info_list_ref (local_writable_namespaces); 12273781343738de4abddf56982325a77bd70a98cd26Alexander Larsson} 12283781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 12293781343738de4abddf56982325a77bd70a98cd26Alexander Larssonstatic gboolean 123054300dde6d77867aa53e60a2bdfd69cb9e644315Matthias Claseng_local_file_set_attribute (GFile *file, 123154300dde6d77867aa53e60a2bdfd69cb9e644315Matthias Clasen const char *attribute, 123254300dde6d77867aa53e60a2bdfd69cb9e644315Matthias Clasen GFileAttributeType type, 123354300dde6d77867aa53e60a2bdfd69cb9e644315Matthias Clasen gpointer value_p, 123454300dde6d77867aa53e60a2bdfd69cb9e644315Matthias Clasen GFileQueryInfoFlags flags, 123554300dde6d77867aa53e60a2bdfd69cb9e644315Matthias Clasen GCancellable *cancellable, 123654300dde6d77867aa53e60a2bdfd69cb9e644315Matthias Clasen GError **error) 12373781343738de4abddf56982325a77bd70a98cd26Alexander Larsson{ 12383781343738de4abddf56982325a77bd70a98cd26Alexander Larsson GLocalFile *local = G_LOCAL_FILE (file); 12393781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 12403781343738de4abddf56982325a77bd70a98cd26Alexander Larsson return _g_local_file_info_set_attribute (local->filename, 12413781343738de4abddf56982325a77bd70a98cd26Alexander Larsson attribute, 1242f5063650794c987868830241a630993e624eabd9Alexander Larsson type, 1243f5063650794c987868830241a630993e624eabd9Alexander Larsson value_p, 12443781343738de4abddf56982325a77bd70a98cd26Alexander Larsson flags, 12453781343738de4abddf56982325a77bd70a98cd26Alexander Larsson cancellable, 12463781343738de4abddf56982325a77bd70a98cd26Alexander Larsson error); 12473781343738de4abddf56982325a77bd70a98cd26Alexander Larsson} 12483781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 12493781343738de4abddf56982325a77bd70a98cd26Alexander Larssonstatic gboolean 1250a2ca589703273fca80cb126430a8b058aba3eb52Matthias Claseng_local_file_set_attributes_from_info (GFile *file, 1251a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen GFileInfo *info, 1252a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen GFileQueryInfoFlags flags, 1253a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen GCancellable *cancellable, 1254a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen GError **error) 12553781343738de4abddf56982325a77bd70a98cd26Alexander Larsson{ 12563781343738de4abddf56982325a77bd70a98cd26Alexander Larsson GLocalFile *local = G_LOCAL_FILE (file); 12573781343738de4abddf56982325a77bd70a98cd26Alexander Larsson int res, chained_res; 125854300dde6d77867aa53e60a2bdfd69cb9e644315Matthias Clasen GFileIface *default_iface; 12593781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 12603781343738de4abddf56982325a77bd70a98cd26Alexander Larsson res = _g_local_file_info_set_attributes (local->filename, 12613781343738de4abddf56982325a77bd70a98cd26Alexander Larsson info, flags, 12623781343738de4abddf56982325a77bd70a98cd26Alexander Larsson cancellable, 12633781343738de4abddf56982325a77bd70a98cd26Alexander Larsson error); 12643781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 12653781343738de4abddf56982325a77bd70a98cd26Alexander Larsson if (!res) 12663781343738de4abddf56982325a77bd70a98cd26Alexander Larsson error = NULL; /* Don't write over error if further errors */ 12673781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 12683781343738de4abddf56982325a77bd70a98cd26Alexander Larsson default_iface = g_type_default_interface_peek (G_TYPE_FILE); 12693781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 12703781343738de4abddf56982325a77bd70a98cd26Alexander Larsson chained_res = (default_iface->set_attributes_from_info) (file, info, flags, cancellable, error); 12713781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 12723781343738de4abddf56982325a77bd70a98cd26Alexander Larsson return res && chained_res; 12733781343738de4abddf56982325a77bd70a98cd26Alexander Larsson} 12743781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 12753781343738de4abddf56982325a77bd70a98cd26Alexander Larssonstatic GFileInputStream * 1276a2ca589703273fca80cb126430a8b058aba3eb52Matthias Claseng_local_file_read (GFile *file, 1277a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen GCancellable *cancellable, 1278a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen GError **error) 12793781343738de4abddf56982325a77bd70a98cd26Alexander Larsson{ 12803781343738de4abddf56982325a77bd70a98cd26Alexander Larsson GLocalFile *local = G_LOCAL_FILE (file); 12813781343738de4abddf56982325a77bd70a98cd26Alexander Larsson int fd; 12823781343738de4abddf56982325a77bd70a98cd26Alexander Larsson struct stat buf; 12833781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 1284b221d1b36d0ed5ce22f21a986a352f6a92345c30Alexander Larsson fd = g_open (local->filename, O_RDONLY|O_BINARY, 0); 12853781343738de4abddf56982325a77bd70a98cd26Alexander Larsson if (fd == -1) 12863781343738de4abddf56982325a77bd70a98cd26Alexander Larsson { 128737ac644bd18168330f43f4d52be7e3cbb3415415Christian Persch int errsv = errno; 128837ac644bd18168330f43f4d52be7e3cbb3415415Christian Persch 12893781343738de4abddf56982325a77bd70a98cd26Alexander Larsson g_set_error (error, G_IO_ERROR, 129037ac644bd18168330f43f4d52be7e3cbb3415415Christian Persch g_io_error_from_errno (errsv), 12913781343738de4abddf56982325a77bd70a98cd26Alexander Larsson _("Error opening file: %s"), 129237ac644bd18168330f43f4d52be7e3cbb3415415Christian Persch g_strerror (errsv)); 12933781343738de4abddf56982325a77bd70a98cd26Alexander Larsson return NULL; 12943781343738de4abddf56982325a77bd70a98cd26Alexander Larsson } 12953781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 12963781343738de4abddf56982325a77bd70a98cd26Alexander Larsson if (fstat(fd, &buf) == 0 && S_ISDIR (buf.st_mode)) 12973781343738de4abddf56982325a77bd70a98cd26Alexander Larsson { 12983781343738de4abddf56982325a77bd70a98cd26Alexander Larsson close (fd); 12999c17697b56501d11b4c653432cc9e290347aa03eChristian Persch g_set_error_literal (error, G_IO_ERROR, 13009c17697b56501d11b4c653432cc9e290347aa03eChristian Persch G_IO_ERROR_IS_DIRECTORY, 13019c17697b56501d11b4c653432cc9e290347aa03eChristian Persch _("Can't open directory")); 13023781343738de4abddf56982325a77bd70a98cd26Alexander Larsson return NULL; 13033781343738de4abddf56982325a77bd70a98cd26Alexander Larsson } 13043781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 1305d9594f5709313d6e7a8a4f3e5f3b23fc72017417Alexander Larsson return _g_local_file_input_stream_new (fd); 13063781343738de4abddf56982325a77bd70a98cd26Alexander Larsson} 13073781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 13083781343738de4abddf56982325a77bd70a98cd26Alexander Larssonstatic GFileOutputStream * 1309a2ca589703273fca80cb126430a8b058aba3eb52Matthias Claseng_local_file_append_to (GFile *file, 1310a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen GFileCreateFlags flags, 1311a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen GCancellable *cancellable, 1312a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen GError **error) 13133781343738de4abddf56982325a77bd70a98cd26Alexander Larsson{ 1314d9594f5709313d6e7a8a4f3e5f3b23fc72017417Alexander Larsson return _g_local_file_output_stream_append (G_LOCAL_FILE (file)->filename, 1315d9594f5709313d6e7a8a4f3e5f3b23fc72017417Alexander Larsson flags, cancellable, error); 13163781343738de4abddf56982325a77bd70a98cd26Alexander Larsson} 13173781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 13183781343738de4abddf56982325a77bd70a98cd26Alexander Larssonstatic GFileOutputStream * 1319a2ca589703273fca80cb126430a8b058aba3eb52Matthias Claseng_local_file_create (GFile *file, 1320a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen GFileCreateFlags flags, 1321a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen GCancellable *cancellable, 1322a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen GError **error) 13233781343738de4abddf56982325a77bd70a98cd26Alexander Larsson{ 1324d9594f5709313d6e7a8a4f3e5f3b23fc72017417Alexander Larsson return _g_local_file_output_stream_create (G_LOCAL_FILE (file)->filename, 1325d9594f5709313d6e7a8a4f3e5f3b23fc72017417Alexander Larsson flags, cancellable, error); 13263781343738de4abddf56982325a77bd70a98cd26Alexander Larsson} 13273781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 13283781343738de4abddf56982325a77bd70a98cd26Alexander Larssonstatic GFileOutputStream * 1329a2ca589703273fca80cb126430a8b058aba3eb52Matthias Claseng_local_file_replace (GFile *file, 1330a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen const char *etag, 1331a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen gboolean make_backup, 1332a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen GFileCreateFlags flags, 1333a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen GCancellable *cancellable, 1334a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen GError **error) 13353781343738de4abddf56982325a77bd70a98cd26Alexander Larsson{ 1336d9594f5709313d6e7a8a4f3e5f3b23fc72017417Alexander Larsson return _g_local_file_output_stream_replace (G_LOCAL_FILE (file)->filename, 1337d9594f5709313d6e7a8a4f3e5f3b23fc72017417Alexander Larsson etag, make_backup, flags, 1338d9594f5709313d6e7a8a4f3e5f3b23fc72017417Alexander Larsson cancellable, error); 13393781343738de4abddf56982325a77bd70a98cd26Alexander Larsson} 13403781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 13413781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 13423781343738de4abddf56982325a77bd70a98cd26Alexander Larssonstatic gboolean 1343a2ca589703273fca80cb126430a8b058aba3eb52Matthias Claseng_local_file_delete (GFile *file, 1344a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen GCancellable *cancellable, 1345a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen GError **error) 13463781343738de4abddf56982325a77bd70a98cd26Alexander Larsson{ 13473781343738de4abddf56982325a77bd70a98cd26Alexander Larsson GLocalFile *local = G_LOCAL_FILE (file); 13483781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 13493781343738de4abddf56982325a77bd70a98cd26Alexander Larsson if (g_remove (local->filename) == -1) 13503781343738de4abddf56982325a77bd70a98cd26Alexander Larsson { 135137ac644bd18168330f43f4d52be7e3cbb3415415Christian Persch int errsv = errno; 135237ac644bd18168330f43f4d52be7e3cbb3415415Christian Persch 1353f0e54fd3280ab55f6226c4baba07047494db5885Alexander Larsson /* Posix allows EEXIST too, but the more sane error 1354f5483302757a9c03c43e25c86cea4a7bd5aaaf3fMatthias Clasen is G_IO_ERROR_NOT_FOUND, and it's what nautilus 1355f0e54fd3280ab55f6226c4baba07047494db5885Alexander Larsson expects */ 1356f0e54fd3280ab55f6226c4baba07047494db5885Alexander Larsson if (errsv == EEXIST) 1357f0e54fd3280ab55f6226c4baba07047494db5885Alexander Larsson errsv = ENOTEMPTY; 1358f0e54fd3280ab55f6226c4baba07047494db5885Alexander Larsson 13593781343738de4abddf56982325a77bd70a98cd26Alexander Larsson g_set_error (error, G_IO_ERROR, 136037ac644bd18168330f43f4d52be7e3cbb3415415Christian Persch g_io_error_from_errno (errsv), 13613781343738de4abddf56982325a77bd70a98cd26Alexander Larsson _("Error removing file: %s"), 136237ac644bd18168330f43f4d52be7e3cbb3415415Christian Persch g_strerror (errsv)); 13633781343738de4abddf56982325a77bd70a98cd26Alexander Larsson return FALSE; 13643781343738de4abddf56982325a77bd70a98cd26Alexander Larsson } 13653781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 13663781343738de4abddf56982325a77bd70a98cd26Alexander Larsson return TRUE; 13673781343738de4abddf56982325a77bd70a98cd26Alexander Larsson} 13683781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 13693781343738de4abddf56982325a77bd70a98cd26Alexander Larssonstatic char * 13703781343738de4abddf56982325a77bd70a98cd26Alexander Larssonstrip_trailing_slashes (const char *path) 13713781343738de4abddf56982325a77bd70a98cd26Alexander Larsson{ 13723781343738de4abddf56982325a77bd70a98cd26Alexander Larsson char *path_copy; 13733781343738de4abddf56982325a77bd70a98cd26Alexander Larsson int len; 13743781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 13753781343738de4abddf56982325a77bd70a98cd26Alexander Larsson path_copy = g_strdup (path); 13763781343738de4abddf56982325a77bd70a98cd26Alexander Larsson len = strlen (path_copy); 13773781343738de4abddf56982325a77bd70a98cd26Alexander Larsson while (len > 1 && path_copy[len-1] == '/') 13783781343738de4abddf56982325a77bd70a98cd26Alexander Larsson path_copy[--len] = 0; 13793781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 13803781343738de4abddf56982325a77bd70a98cd26Alexander Larsson return path_copy; 13813781343738de4abddf56982325a77bd70a98cd26Alexander Larsson } 13823781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 13833781343738de4abddf56982325a77bd70a98cd26Alexander Larssonstatic char * 13843781343738de4abddf56982325a77bd70a98cd26Alexander Larssonexpand_symlink (const char *link) 13853781343738de4abddf56982325a77bd70a98cd26Alexander Larsson{ 13863781343738de4abddf56982325a77bd70a98cd26Alexander Larsson char *resolved, *canonical, *parent, *link2; 13873781343738de4abddf56982325a77bd70a98cd26Alexander Larsson char symlink_value[4096]; 1388a33f8a7564cc649daf0dca0d67daac8430808cf9Hans Breuer#ifdef G_OS_WIN32 1389a33f8a7564cc649daf0dca0d67daac8430808cf9Hans Breuer#else 13903781343738de4abddf56982325a77bd70a98cd26Alexander Larsson ssize_t res; 1391a33f8a7564cc649daf0dca0d67daac8430808cf9Hans Breuer#endif 13923781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 1393a33f8a7564cc649daf0dca0d67daac8430808cf9Hans Breuer#ifdef G_OS_WIN32 1394a33f8a7564cc649daf0dca0d67daac8430808cf9Hans Breuer#else 13953781343738de4abddf56982325a77bd70a98cd26Alexander Larsson res = readlink (link, symlink_value, sizeof (symlink_value) - 1); 1396a33f8a7564cc649daf0dca0d67daac8430808cf9Hans Breuer 13973781343738de4abddf56982325a77bd70a98cd26Alexander Larsson if (res == -1) 13983781343738de4abddf56982325a77bd70a98cd26Alexander Larsson return g_strdup (link); 13993781343738de4abddf56982325a77bd70a98cd26Alexander Larsson symlink_value[res] = 0; 1400a33f8a7564cc649daf0dca0d67daac8430808cf9Hans Breuer#endif 14013781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 14023781343738de4abddf56982325a77bd70a98cd26Alexander Larsson if (g_path_is_absolute (symlink_value)) 14033781343738de4abddf56982325a77bd70a98cd26Alexander Larsson return canonicalize_filename (symlink_value); 14043781343738de4abddf56982325a77bd70a98cd26Alexander Larsson else 14053781343738de4abddf56982325a77bd70a98cd26Alexander Larsson { 14063781343738de4abddf56982325a77bd70a98cd26Alexander Larsson link2 = strip_trailing_slashes (link); 14073781343738de4abddf56982325a77bd70a98cd26Alexander Larsson parent = g_path_get_dirname (link2); 14083781343738de4abddf56982325a77bd70a98cd26Alexander Larsson g_free (link2); 14093781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 14103781343738de4abddf56982325a77bd70a98cd26Alexander Larsson resolved = g_build_filename (parent, symlink_value, NULL); 14113781343738de4abddf56982325a77bd70a98cd26Alexander Larsson g_free (parent); 14123781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 14133781343738de4abddf56982325a77bd70a98cd26Alexander Larsson canonical = canonicalize_filename (resolved); 14143781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 14153781343738de4abddf56982325a77bd70a98cd26Alexander Larsson g_free (resolved); 14163781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 14173781343738de4abddf56982325a77bd70a98cd26Alexander Larsson return canonical; 14183781343738de4abddf56982325a77bd70a98cd26Alexander Larsson } 14193781343738de4abddf56982325a77bd70a98cd26Alexander Larsson} 14203781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 14213781343738de4abddf56982325a77bd70a98cd26Alexander Larssonstatic char * 1422a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasenget_parent (const char *path, 1423a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen dev_t *parent_dev) 14243781343738de4abddf56982325a77bd70a98cd26Alexander Larsson{ 14253781343738de4abddf56982325a77bd70a98cd26Alexander Larsson char *parent, *tmp; 14263781343738de4abddf56982325a77bd70a98cd26Alexander Larsson struct stat parent_stat; 14273781343738de4abddf56982325a77bd70a98cd26Alexander Larsson int num_recursions; 14283781343738de4abddf56982325a77bd70a98cd26Alexander Larsson char *path_copy; 14293781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 14303781343738de4abddf56982325a77bd70a98cd26Alexander Larsson path_copy = strip_trailing_slashes (path); 14313781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 14323781343738de4abddf56982325a77bd70a98cd26Alexander Larsson parent = g_path_get_dirname (path_copy); 14333781343738de4abddf56982325a77bd70a98cd26Alexander Larsson if (strcmp (parent, ".") == 0 || 14343781343738de4abddf56982325a77bd70a98cd26Alexander Larsson strcmp (parent, path_copy) == 0) 14353781343738de4abddf56982325a77bd70a98cd26Alexander Larsson { 1436fe68fc74964a8bc79db8406a2f5efb823daaf25eAlexander Larsson g_free (parent); 14373781343738de4abddf56982325a77bd70a98cd26Alexander Larsson g_free (path_copy); 14383781343738de4abddf56982325a77bd70a98cd26Alexander Larsson return NULL; 14393781343738de4abddf56982325a77bd70a98cd26Alexander Larsson } 14403781343738de4abddf56982325a77bd70a98cd26Alexander Larsson g_free (path_copy); 14413781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 14423781343738de4abddf56982325a77bd70a98cd26Alexander Larsson num_recursions = 0; 14433781343738de4abddf56982325a77bd70a98cd26Alexander Larsson do { 14443781343738de4abddf56982325a77bd70a98cd26Alexander Larsson if (g_lstat (parent, &parent_stat) != 0) 14453781343738de4abddf56982325a77bd70a98cd26Alexander Larsson { 14463781343738de4abddf56982325a77bd70a98cd26Alexander Larsson g_free (parent); 14473781343738de4abddf56982325a77bd70a98cd26Alexander Larsson return NULL; 14483781343738de4abddf56982325a77bd70a98cd26Alexander Larsson } 14493781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 14503781343738de4abddf56982325a77bd70a98cd26Alexander Larsson if (S_ISLNK (parent_stat.st_mode)) 14513781343738de4abddf56982325a77bd70a98cd26Alexander Larsson { 14523781343738de4abddf56982325a77bd70a98cd26Alexander Larsson tmp = parent; 14533781343738de4abddf56982325a77bd70a98cd26Alexander Larsson parent = expand_symlink (parent); 14543781343738de4abddf56982325a77bd70a98cd26Alexander Larsson g_free (tmp); 14553781343738de4abddf56982325a77bd70a98cd26Alexander Larsson } 14563781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 14573781343738de4abddf56982325a77bd70a98cd26Alexander Larsson num_recursions++; 14583781343738de4abddf56982325a77bd70a98cd26Alexander Larsson if (num_recursions > 12) 14593781343738de4abddf56982325a77bd70a98cd26Alexander Larsson { 14603781343738de4abddf56982325a77bd70a98cd26Alexander Larsson g_free (parent); 14613781343738de4abddf56982325a77bd70a98cd26Alexander Larsson return NULL; 14623781343738de4abddf56982325a77bd70a98cd26Alexander Larsson } 14633781343738de4abddf56982325a77bd70a98cd26Alexander Larsson } while (S_ISLNK (parent_stat.st_mode)); 14643781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 14653781343738de4abddf56982325a77bd70a98cd26Alexander Larsson *parent_dev = parent_stat.st_dev; 14663781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 14673781343738de4abddf56982325a77bd70a98cd26Alexander Larsson return parent; 14683781343738de4abddf56982325a77bd70a98cd26Alexander Larsson} 14693781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 14703781343738de4abddf56982325a77bd70a98cd26Alexander Larssonstatic char * 14713781343738de4abddf56982325a77bd70a98cd26Alexander Larssonexpand_all_symlinks (const char *path) 14723781343738de4abddf56982325a77bd70a98cd26Alexander Larsson{ 14733781343738de4abddf56982325a77bd70a98cd26Alexander Larsson char *parent, *parent_expanded; 14743781343738de4abddf56982325a77bd70a98cd26Alexander Larsson char *basename, *res; 14753781343738de4abddf56982325a77bd70a98cd26Alexander Larsson dev_t parent_dev; 14763781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 14773781343738de4abddf56982325a77bd70a98cd26Alexander Larsson parent = get_parent (path, &parent_dev); 14783781343738de4abddf56982325a77bd70a98cd26Alexander Larsson if (parent) 14793781343738de4abddf56982325a77bd70a98cd26Alexander Larsson { 14803781343738de4abddf56982325a77bd70a98cd26Alexander Larsson parent_expanded = expand_all_symlinks (parent); 14813781343738de4abddf56982325a77bd70a98cd26Alexander Larsson g_free (parent); 14823781343738de4abddf56982325a77bd70a98cd26Alexander Larsson basename = g_path_get_basename (path); 14833781343738de4abddf56982325a77bd70a98cd26Alexander Larsson res = g_build_filename (parent_expanded, basename, NULL); 14843781343738de4abddf56982325a77bd70a98cd26Alexander Larsson g_free (basename); 14853781343738de4abddf56982325a77bd70a98cd26Alexander Larsson g_free (parent_expanded); 14863781343738de4abddf56982325a77bd70a98cd26Alexander Larsson } 14873781343738de4abddf56982325a77bd70a98cd26Alexander Larsson else 14883781343738de4abddf56982325a77bd70a98cd26Alexander Larsson res = g_strdup (path); 14893781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 14903781343738de4abddf56982325a77bd70a98cd26Alexander Larsson return res; 14913781343738de4abddf56982325a77bd70a98cd26Alexander Larsson} 14923781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 14931d568f35d13d7cf0206439a7a94b7fd3abd92fa3Alexander Larsson#ifndef G_OS_WIN32 14941d568f35d13d7cf0206439a7a94b7fd3abd92fa3Alexander Larsson 14953781343738de4abddf56982325a77bd70a98cd26Alexander Larssonstatic char * 1496a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasenfind_mountpoint_for (const char *file, 1497a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen dev_t dev) 14983781343738de4abddf56982325a77bd70a98cd26Alexander Larsson{ 14993781343738de4abddf56982325a77bd70a98cd26Alexander Larsson char *dir, *parent; 15003781343738de4abddf56982325a77bd70a98cd26Alexander Larsson dev_t dir_dev, parent_dev; 15013781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 15023781343738de4abddf56982325a77bd70a98cd26Alexander Larsson dir = g_strdup (file); 15033781343738de4abddf56982325a77bd70a98cd26Alexander Larsson dir_dev = dev; 15043781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 1505a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen while (1) 1506a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen { 1507a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen parent = get_parent (dir, &parent_dev); 1508a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen if (parent == NULL) 1509a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen return dir; 15103781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 1511a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen if (parent_dev != dir_dev) 1512a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen { 1513a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen g_free (parent); 1514a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen return dir; 1515a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen } 15163781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 1517a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen g_free (dir); 1518a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen dir = parent; 1519a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen } 15203781343738de4abddf56982325a77bd70a98cd26Alexander Larsson} 15213781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 15223781343738de4abddf56982325a77bd70a98cd26Alexander Larssonstatic char * 15233781343738de4abddf56982325a77bd70a98cd26Alexander Larssonfind_topdir_for (const char *file) 15243781343738de4abddf56982325a77bd70a98cd26Alexander Larsson{ 15253781343738de4abddf56982325a77bd70a98cd26Alexander Larsson char *dir; 15263781343738de4abddf56982325a77bd70a98cd26Alexander Larsson dev_t dir_dev; 15273781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 15283781343738de4abddf56982325a77bd70a98cd26Alexander Larsson dir = get_parent (file, &dir_dev); 15293781343738de4abddf56982325a77bd70a98cd26Alexander Larsson if (dir == NULL) 15303781343738de4abddf56982325a77bd70a98cd26Alexander Larsson return NULL; 15313781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 15323781343738de4abddf56982325a77bd70a98cd26Alexander Larsson return find_mountpoint_for (dir, dir_dev); 15333781343738de4abddf56982325a77bd70a98cd26Alexander Larsson} 15343781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 15353781343738de4abddf56982325a77bd70a98cd26Alexander Larssonstatic char * 1536a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasenget_unique_filename (const char *basename, 1537a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen int id) 15383781343738de4abddf56982325a77bd70a98cd26Alexander Larsson{ 15393781343738de4abddf56982325a77bd70a98cd26Alexander Larsson const char *dot; 15403781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 15413781343738de4abddf56982325a77bd70a98cd26Alexander Larsson if (id == 1) 15423781343738de4abddf56982325a77bd70a98cd26Alexander Larsson return g_strdup (basename); 15433781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 15443781343738de4abddf56982325a77bd70a98cd26Alexander Larsson dot = strchr (basename, '.'); 15453781343738de4abddf56982325a77bd70a98cd26Alexander Larsson if (dot) 1546e4d018f1ddac53ac6f6161c8bb20bddf2c0f220fDan Winship return g_strdup_printf ("%.*s.%d%s", (int)(dot - basename), basename, id, dot); 15473781343738de4abddf56982325a77bd70a98cd26Alexander Larsson else 15483781343738de4abddf56982325a77bd70a98cd26Alexander Larsson return g_strdup_printf ("%s.%d", basename, id); 15493781343738de4abddf56982325a77bd70a98cd26Alexander Larsson} 15503781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 15513781343738de4abddf56982325a77bd70a98cd26Alexander Larssonstatic gboolean 1552a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasenpath_has_prefix (const char *path, 1553a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen const char *prefix) 15543781343738de4abddf56982325a77bd70a98cd26Alexander Larsson{ 15553781343738de4abddf56982325a77bd70a98cd26Alexander Larsson int prefix_len; 15563781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 15573781343738de4abddf56982325a77bd70a98cd26Alexander Larsson if (prefix == NULL) 15583781343738de4abddf56982325a77bd70a98cd26Alexander Larsson return TRUE; 15593781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 15603781343738de4abddf56982325a77bd70a98cd26Alexander Larsson prefix_len = strlen (prefix); 15613781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 15623781343738de4abddf56982325a77bd70a98cd26Alexander Larsson if (strncmp (path, prefix, prefix_len) == 0 && 15633781343738de4abddf56982325a77bd70a98cd26Alexander Larsson (prefix_len == 0 || /* empty prefix always matches */ 15643781343738de4abddf56982325a77bd70a98cd26Alexander Larsson prefix[prefix_len - 1] == '/' || /* last char in prefix was a /, so it must be in path too */ 15653781343738de4abddf56982325a77bd70a98cd26Alexander Larsson path[prefix_len] == 0 || 15663781343738de4abddf56982325a77bd70a98cd26Alexander Larsson path[prefix_len] == '/')) 15673781343738de4abddf56982325a77bd70a98cd26Alexander Larsson return TRUE; 15683781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 15693781343738de4abddf56982325a77bd70a98cd26Alexander Larsson return FALSE; 15703781343738de4abddf56982325a77bd70a98cd26Alexander Larsson} 15713781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 15723781343738de4abddf56982325a77bd70a98cd26Alexander Larssonstatic char * 1573a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasentry_make_relative (const char *path, 1574a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen const char *base) 15753781343738de4abddf56982325a77bd70a98cd26Alexander Larsson{ 15763781343738de4abddf56982325a77bd70a98cd26Alexander Larsson char *path2, *base2; 15773781343738de4abddf56982325a77bd70a98cd26Alexander Larsson char *relative; 15783781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 15793781343738de4abddf56982325a77bd70a98cd26Alexander Larsson path2 = expand_all_symlinks (path); 15803781343738de4abddf56982325a77bd70a98cd26Alexander Larsson base2 = expand_all_symlinks (base); 15813781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 15823781343738de4abddf56982325a77bd70a98cd26Alexander Larsson relative = NULL; 15833781343738de4abddf56982325a77bd70a98cd26Alexander Larsson if (path_has_prefix (path2, base2)) 15843781343738de4abddf56982325a77bd70a98cd26Alexander Larsson { 15853781343738de4abddf56982325a77bd70a98cd26Alexander Larsson relative = path2 + strlen (base2); 15863781343738de4abddf56982325a77bd70a98cd26Alexander Larsson while (*relative == '/') 15873781343738de4abddf56982325a77bd70a98cd26Alexander Larsson relative ++; 15883781343738de4abddf56982325a77bd70a98cd26Alexander Larsson relative = g_strdup (relative); 15893781343738de4abddf56982325a77bd70a98cd26Alexander Larsson } 15903781343738de4abddf56982325a77bd70a98cd26Alexander Larsson g_free (path2); 15913781343738de4abddf56982325a77bd70a98cd26Alexander Larsson g_free (base2); 15923781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 15933781343738de4abddf56982325a77bd70a98cd26Alexander Larsson if (relative) 15943781343738de4abddf56982325a77bd70a98cd26Alexander Larsson return relative; 15953781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 15963781343738de4abddf56982325a77bd70a98cd26Alexander Larsson /* Failed, use abs path */ 15973781343738de4abddf56982325a77bd70a98cd26Alexander Larsson return g_strdup (path); 15983781343738de4abddf56982325a77bd70a98cd26Alexander Larsson} 15993781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 16003781343738de4abddf56982325a77bd70a98cd26Alexander Larssonstatic char * 16013781343738de4abddf56982325a77bd70a98cd26Alexander Larssonescape_trash_name (char *name) 16023781343738de4abddf56982325a77bd70a98cd26Alexander Larsson{ 16033781343738de4abddf56982325a77bd70a98cd26Alexander Larsson GString *str; 16043781343738de4abddf56982325a77bd70a98cd26Alexander Larsson const gchar hex[16] = "0123456789ABCDEF"; 16053781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 16063781343738de4abddf56982325a77bd70a98cd26Alexander Larsson str = g_string_new (""); 16073781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 16083781343738de4abddf56982325a77bd70a98cd26Alexander Larsson while (*name != 0) 16093781343738de4abddf56982325a77bd70a98cd26Alexander Larsson { 16103781343738de4abddf56982325a77bd70a98cd26Alexander Larsson char c; 16113781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 16123781343738de4abddf56982325a77bd70a98cd26Alexander Larsson c = *name++; 16133781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 16143781343738de4abddf56982325a77bd70a98cd26Alexander Larsson if (g_ascii_isprint (c)) 16153781343738de4abddf56982325a77bd70a98cd26Alexander Larsson g_string_append_c (str, c); 16163781343738de4abddf56982325a77bd70a98cd26Alexander Larsson else 16173781343738de4abddf56982325a77bd70a98cd26Alexander Larsson { 16183781343738de4abddf56982325a77bd70a98cd26Alexander Larsson g_string_append_c (str, '%'); 16193781343738de4abddf56982325a77bd70a98cd26Alexander Larsson g_string_append_c (str, hex[((guchar)c) >> 4]); 16203781343738de4abddf56982325a77bd70a98cd26Alexander Larsson g_string_append_c (str, hex[((guchar)c) & 0xf]); 16213781343738de4abddf56982325a77bd70a98cd26Alexander Larsson } 16223781343738de4abddf56982325a77bd70a98cd26Alexander Larsson } 16233781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 16243781343738de4abddf56982325a77bd70a98cd26Alexander Larsson return g_string_free (str, FALSE); 16253781343738de4abddf56982325a77bd70a98cd26Alexander Larsson} 16263781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 1627c5a10d2650e11b9a700b605640a41275a4ee1a5dAlexander Larssongboolean 1628c5a10d2650e11b9a700b605640a41275a4ee1a5dAlexander Larsson_g_local_file_has_trash_dir (const char *dirname, dev_t dir_dev) 1629c5a10d2650e11b9a700b605640a41275a4ee1a5dAlexander Larsson{ 163067b2f9a99b3c6c060914633bff3e494d94d2a0f6Matthias Clasen static gsize home_dev_set = 0; 163167b2f9a99b3c6c060914633bff3e494d94d2a0f6Matthias Clasen static dev_t home_dev; 1632c5a10d2650e11b9a700b605640a41275a4ee1a5dAlexander Larsson char *topdir, *globaldir, *trashdir, *tmpname; 1633c5a10d2650e11b9a700b605640a41275a4ee1a5dAlexander Larsson uid_t uid; 1634c5a10d2650e11b9a700b605640a41275a4ee1a5dAlexander Larsson char uid_str[32]; 1635c5a10d2650e11b9a700b605640a41275a4ee1a5dAlexander Larsson struct stat global_stat, trash_stat; 1636c5a10d2650e11b9a700b605640a41275a4ee1a5dAlexander Larsson gboolean res; 1637c5a10d2650e11b9a700b605640a41275a4ee1a5dAlexander Larsson int statres; 1638c5a10d2650e11b9a700b605640a41275a4ee1a5dAlexander Larsson 163967b2f9a99b3c6c060914633bff3e494d94d2a0f6Matthias Clasen if (g_once_init_enter (&home_dev_set)) 1640c5a10d2650e11b9a700b605640a41275a4ee1a5dAlexander Larsson { 1641c5a10d2650e11b9a700b605640a41275a4ee1a5dAlexander Larsson struct stat home_stat; 1642c5a10d2650e11b9a700b605640a41275a4ee1a5dAlexander Larsson 1643c5a10d2650e11b9a700b605640a41275a4ee1a5dAlexander Larsson g_stat (g_get_home_dir (), &home_stat); 164467b2f9a99b3c6c060914633bff3e494d94d2a0f6Matthias Clasen home_dev = home_stat.st_dev; 164567b2f9a99b3c6c060914633bff3e494d94d2a0f6Matthias Clasen g_once_init_leave (&home_dev_set, 1); 1646c5a10d2650e11b9a700b605640a41275a4ee1a5dAlexander Larsson } 1647c5a10d2650e11b9a700b605640a41275a4ee1a5dAlexander Larsson 1648c5a10d2650e11b9a700b605640a41275a4ee1a5dAlexander Larsson /* Assume we can trash to the home */ 164967b2f9a99b3c6c060914633bff3e494d94d2a0f6Matthias Clasen if (dir_dev == home_dev) 1650c5a10d2650e11b9a700b605640a41275a4ee1a5dAlexander Larsson return TRUE; 1651c5a10d2650e11b9a700b605640a41275a4ee1a5dAlexander Larsson 1652c5a10d2650e11b9a700b605640a41275a4ee1a5dAlexander Larsson topdir = find_mountpoint_for (dirname, dir_dev); 1653c5a10d2650e11b9a700b605640a41275a4ee1a5dAlexander Larsson if (topdir == NULL) 1654c5a10d2650e11b9a700b605640a41275a4ee1a5dAlexander Larsson return FALSE; 1655c5a10d2650e11b9a700b605640a41275a4ee1a5dAlexander Larsson 1656c5a10d2650e11b9a700b605640a41275a4ee1a5dAlexander Larsson globaldir = g_build_filename (topdir, ".Trash", NULL); 1657c5a10d2650e11b9a700b605640a41275a4ee1a5dAlexander Larsson statres = g_lstat (globaldir, &global_stat); 1658c5a10d2650e11b9a700b605640a41275a4ee1a5dAlexander Larsson if (g_lstat (globaldir, &global_stat) == 0 && 1659c5a10d2650e11b9a700b605640a41275a4ee1a5dAlexander Larsson S_ISDIR (global_stat.st_mode) && 1660c5a10d2650e11b9a700b605640a41275a4ee1a5dAlexander Larsson (global_stat.st_mode & S_ISVTX) != 0) 1661c5a10d2650e11b9a700b605640a41275a4ee1a5dAlexander Larsson { 1662c5a10d2650e11b9a700b605640a41275a4ee1a5dAlexander Larsson /* got a toplevel sysadmin created dir, assume we 1663c5a10d2650e11b9a700b605640a41275a4ee1a5dAlexander Larsson * can trash to it (we should be able to create a dir) 1664c5a10d2650e11b9a700b605640a41275a4ee1a5dAlexander Larsson * This fails for the FAT case where the ownership of 1665c5a10d2650e11b9a700b605640a41275a4ee1a5dAlexander Larsson * that dir would be wrong though.. 1666c5a10d2650e11b9a700b605640a41275a4ee1a5dAlexander Larsson */ 1667c5a10d2650e11b9a700b605640a41275a4ee1a5dAlexander Larsson g_free (globaldir); 1668c5a10d2650e11b9a700b605640a41275a4ee1a5dAlexander Larsson g_free (topdir); 1669c5a10d2650e11b9a700b605640a41275a4ee1a5dAlexander Larsson return TRUE; 1670c5a10d2650e11b9a700b605640a41275a4ee1a5dAlexander Larsson } 1671c5a10d2650e11b9a700b605640a41275a4ee1a5dAlexander Larsson g_free (globaldir); 1672c5a10d2650e11b9a700b605640a41275a4ee1a5dAlexander Larsson 1673c5a10d2650e11b9a700b605640a41275a4ee1a5dAlexander Larsson /* No global trash dir, or it failed the tests, fall back to $topdir/.Trash-$uid */ 1674c5a10d2650e11b9a700b605640a41275a4ee1a5dAlexander Larsson uid = geteuid (); 1675c5a10d2650e11b9a700b605640a41275a4ee1a5dAlexander Larsson g_snprintf (uid_str, sizeof (uid_str), "%lu", (unsigned long) uid); 1676c5a10d2650e11b9a700b605640a41275a4ee1a5dAlexander Larsson 1677c5a10d2650e11b9a700b605640a41275a4ee1a5dAlexander Larsson tmpname = g_strdup_printf (".Trash-%s", uid_str); 1678c5a10d2650e11b9a700b605640a41275a4ee1a5dAlexander Larsson trashdir = g_build_filename (topdir, tmpname, NULL); 1679c5a10d2650e11b9a700b605640a41275a4ee1a5dAlexander Larsson g_free (tmpname); 1680c5a10d2650e11b9a700b605640a41275a4ee1a5dAlexander Larsson 1681c5a10d2650e11b9a700b605640a41275a4ee1a5dAlexander Larsson if (g_lstat (trashdir, &trash_stat) == 0) 1682c5a10d2650e11b9a700b605640a41275a4ee1a5dAlexander Larsson { 1683c5a10d2650e11b9a700b605640a41275a4ee1a5dAlexander Larsson g_free (topdir); 1684c5a10d2650e11b9a700b605640a41275a4ee1a5dAlexander Larsson g_free (trashdir); 1685c5a10d2650e11b9a700b605640a41275a4ee1a5dAlexander Larsson return 1686c5a10d2650e11b9a700b605640a41275a4ee1a5dAlexander Larsson S_ISDIR (trash_stat.st_mode) && 1687c5a10d2650e11b9a700b605640a41275a4ee1a5dAlexander Larsson trash_stat.st_uid == uid; 1688c5a10d2650e11b9a700b605640a41275a4ee1a5dAlexander Larsson } 1689c5a10d2650e11b9a700b605640a41275a4ee1a5dAlexander Larsson g_free (trashdir); 1690c5a10d2650e11b9a700b605640a41275a4ee1a5dAlexander Larsson 1691c5a10d2650e11b9a700b605640a41275a4ee1a5dAlexander Larsson /* User specific trash didn't exist, can we create it? */ 1692c5a10d2650e11b9a700b605640a41275a4ee1a5dAlexander Larsson res = g_access (topdir, W_OK) == 0; 1693c5a10d2650e11b9a700b605640a41275a4ee1a5dAlexander Larsson 1694c5a10d2650e11b9a700b605640a41275a4ee1a5dAlexander Larsson g_free (topdir); 1695c5a10d2650e11b9a700b605640a41275a4ee1a5dAlexander Larsson 1696c5a10d2650e11b9a700b605640a41275a4ee1a5dAlexander Larsson return res; 1697c5a10d2650e11b9a700b605640a41275a4ee1a5dAlexander Larsson} 1698c5a10d2650e11b9a700b605640a41275a4ee1a5dAlexander Larsson 1699c5a10d2650e11b9a700b605640a41275a4ee1a5dAlexander Larsson 17003781343738de4abddf56982325a77bd70a98cd26Alexander Larssonstatic gboolean 1701a2ca589703273fca80cb126430a8b058aba3eb52Matthias Claseng_local_file_trash (GFile *file, 1702a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen GCancellable *cancellable, 1703a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen GError **error) 17043781343738de4abddf56982325a77bd70a98cd26Alexander Larsson{ 17053781343738de4abddf56982325a77bd70a98cd26Alexander Larsson GLocalFile *local = G_LOCAL_FILE (file); 170683445755b3b2d315feadf94cefbb74afc8f142bdTor Lillqvist struct stat file_stat, home_stat; 17073781343738de4abddf56982325a77bd70a98cd26Alexander Larsson const char *homedir; 170883445755b3b2d315feadf94cefbb74afc8f142bdTor Lillqvist char *trashdir, *topdir, *infodir, *filesdir; 17093781343738de4abddf56982325a77bd70a98cd26Alexander Larsson char *basename, *trashname, *trashfile, *infoname, *infofile; 17103781343738de4abddf56982325a77bd70a98cd26Alexander Larsson char *original_name, *original_name_escaped; 17113781343738de4abddf56982325a77bd70a98cd26Alexander Larsson int i; 17123781343738de4abddf56982325a77bd70a98cd26Alexander Larsson char *data; 17133781343738de4abddf56982325a77bd70a98cd26Alexander Larsson gboolean is_homedir_trash; 17143781343738de4abddf56982325a77bd70a98cd26Alexander Larsson char delete_time[32]; 17153781343738de4abddf56982325a77bd70a98cd26Alexander Larsson int fd; 171683445755b3b2d315feadf94cefbb74afc8f142bdTor Lillqvist struct stat trash_stat, global_stat; 171783445755b3b2d315feadf94cefbb74afc8f142bdTor Lillqvist char *dirname, *globaldir; 17183781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 17193781343738de4abddf56982325a77bd70a98cd26Alexander Larsson if (g_lstat (local->filename, &file_stat) != 0) 17203781343738de4abddf56982325a77bd70a98cd26Alexander Larsson { 172137ac644bd18168330f43f4d52be7e3cbb3415415Christian Persch int errsv = errno; 172237ac644bd18168330f43f4d52be7e3cbb3415415Christian Persch 17233781343738de4abddf56982325a77bd70a98cd26Alexander Larsson g_set_error (error, G_IO_ERROR, 172437ac644bd18168330f43f4d52be7e3cbb3415415Christian Persch g_io_error_from_errno (errsv), 17253781343738de4abddf56982325a77bd70a98cd26Alexander Larsson _("Error trashing file: %s"), 172637ac644bd18168330f43f4d52be7e3cbb3415415Christian Persch g_strerror (errsv)); 17273781343738de4abddf56982325a77bd70a98cd26Alexander Larsson return FALSE; 17283781343738de4abddf56982325a77bd70a98cd26Alexander Larsson } 17293781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 17303781343738de4abddf56982325a77bd70a98cd26Alexander Larsson homedir = g_get_home_dir (); 17313781343738de4abddf56982325a77bd70a98cd26Alexander Larsson g_stat (homedir, &home_stat); 17323781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 17333781343738de4abddf56982325a77bd70a98cd26Alexander Larsson is_homedir_trash = FALSE; 17343781343738de4abddf56982325a77bd70a98cd26Alexander Larsson trashdir = NULL; 17353781343738de4abddf56982325a77bd70a98cd26Alexander Larsson if (file_stat.st_dev == home_stat.st_dev) 17363781343738de4abddf56982325a77bd70a98cd26Alexander Larsson { 17373781343738de4abddf56982325a77bd70a98cd26Alexander Larsson is_homedir_trash = TRUE; 17383781343738de4abddf56982325a77bd70a98cd26Alexander Larsson errno = 0; 17393781343738de4abddf56982325a77bd70a98cd26Alexander Larsson trashdir = g_build_filename (g_get_user_data_dir (), "Trash", NULL); 17403781343738de4abddf56982325a77bd70a98cd26Alexander Larsson if (g_mkdir_with_parents (trashdir, 0700) < 0) 17413781343738de4abddf56982325a77bd70a98cd26Alexander Larsson { 17423781343738de4abddf56982325a77bd70a98cd26Alexander Larsson char *display_name; 174337ac644bd18168330f43f4d52be7e3cbb3415415Christian Persch int errsv = errno; 17443781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 17453781343738de4abddf56982325a77bd70a98cd26Alexander Larsson display_name = g_filename_display_name (trashdir); 17463781343738de4abddf56982325a77bd70a98cd26Alexander Larsson g_set_error (error, G_IO_ERROR, 174737ac644bd18168330f43f4d52be7e3cbb3415415Christian Persch g_io_error_from_errno (errsv), 17483781343738de4abddf56982325a77bd70a98cd26Alexander Larsson _("Unable to create trash dir %s: %s"), 174937ac644bd18168330f43f4d52be7e3cbb3415415Christian Persch display_name, g_strerror (errsv)); 17503781343738de4abddf56982325a77bd70a98cd26Alexander Larsson g_free (display_name); 17513781343738de4abddf56982325a77bd70a98cd26Alexander Larsson g_free (trashdir); 17523781343738de4abddf56982325a77bd70a98cd26Alexander Larsson return FALSE; 17533781343738de4abddf56982325a77bd70a98cd26Alexander Larsson } 17543781343738de4abddf56982325a77bd70a98cd26Alexander Larsson topdir = g_strdup (g_get_user_data_dir ()); 17553781343738de4abddf56982325a77bd70a98cd26Alexander Larsson } 17563781343738de4abddf56982325a77bd70a98cd26Alexander Larsson else 17573781343738de4abddf56982325a77bd70a98cd26Alexander Larsson { 1758a33f8a7564cc649daf0dca0d67daac8430808cf9Hans Breuer uid_t uid; 1759a33f8a7564cc649daf0dca0d67daac8430808cf9Hans Breuer char uid_str[32]; 1760a33f8a7564cc649daf0dca0d67daac8430808cf9Hans Breuer 17613781343738de4abddf56982325a77bd70a98cd26Alexander Larsson uid = geteuid (); 17623781343738de4abddf56982325a77bd70a98cd26Alexander Larsson g_snprintf (uid_str, sizeof (uid_str), "%lu", (unsigned long)uid); 17633781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 17643781343738de4abddf56982325a77bd70a98cd26Alexander Larsson topdir = find_topdir_for (local->filename); 17653781343738de4abddf56982325a77bd70a98cd26Alexander Larsson if (topdir == NULL) 17663781343738de4abddf56982325a77bd70a98cd26Alexander Larsson { 17679c17697b56501d11b4c653432cc9e290347aa03eChristian Persch g_set_error_literal (error, G_IO_ERROR, 17689c17697b56501d11b4c653432cc9e290347aa03eChristian Persch G_IO_ERROR_NOT_SUPPORTED, 17699c17697b56501d11b4c653432cc9e290347aa03eChristian Persch _("Unable to find toplevel directory for trash")); 17703781343738de4abddf56982325a77bd70a98cd26Alexander Larsson return FALSE; 17713781343738de4abddf56982325a77bd70a98cd26Alexander Larsson } 17723781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 17733781343738de4abddf56982325a77bd70a98cd26Alexander Larsson /* Try looking for global trash dir $topdir/.Trash/$uid */ 17743781343738de4abddf56982325a77bd70a98cd26Alexander Larsson globaldir = g_build_filename (topdir, ".Trash", NULL); 17753781343738de4abddf56982325a77bd70a98cd26Alexander Larsson if (g_lstat (globaldir, &global_stat) == 0 && 17763781343738de4abddf56982325a77bd70a98cd26Alexander Larsson S_ISDIR (global_stat.st_mode) && 17773781343738de4abddf56982325a77bd70a98cd26Alexander Larsson (global_stat.st_mode & S_ISVTX) != 0) 17783781343738de4abddf56982325a77bd70a98cd26Alexander Larsson { 17793781343738de4abddf56982325a77bd70a98cd26Alexander Larsson trashdir = g_build_filename (globaldir, uid_str, NULL); 17803781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 17813781343738de4abddf56982325a77bd70a98cd26Alexander Larsson if (g_lstat (trashdir, &trash_stat) == 0) 17823781343738de4abddf56982325a77bd70a98cd26Alexander Larsson { 17833781343738de4abddf56982325a77bd70a98cd26Alexander Larsson if (!S_ISDIR (trash_stat.st_mode) || 17843781343738de4abddf56982325a77bd70a98cd26Alexander Larsson trash_stat.st_uid != uid) 17853781343738de4abddf56982325a77bd70a98cd26Alexander Larsson { 17863781343738de4abddf56982325a77bd70a98cd26Alexander Larsson /* Not a directory or not owned by user, ignore */ 17873781343738de4abddf56982325a77bd70a98cd26Alexander Larsson g_free (trashdir); 17883781343738de4abddf56982325a77bd70a98cd26Alexander Larsson trashdir = NULL; 17893781343738de4abddf56982325a77bd70a98cd26Alexander Larsson } 17903781343738de4abddf56982325a77bd70a98cd26Alexander Larsson } 17913781343738de4abddf56982325a77bd70a98cd26Alexander Larsson else if (g_mkdir (trashdir, 0700) == -1) 17923781343738de4abddf56982325a77bd70a98cd26Alexander Larsson { 17933781343738de4abddf56982325a77bd70a98cd26Alexander Larsson g_free (trashdir); 17943781343738de4abddf56982325a77bd70a98cd26Alexander Larsson trashdir = NULL; 17953781343738de4abddf56982325a77bd70a98cd26Alexander Larsson } 17963781343738de4abddf56982325a77bd70a98cd26Alexander Larsson } 17973781343738de4abddf56982325a77bd70a98cd26Alexander Larsson g_free (globaldir); 17983781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 17993781343738de4abddf56982325a77bd70a98cd26Alexander Larsson if (trashdir == NULL) 18003781343738de4abddf56982325a77bd70a98cd26Alexander Larsson { 1801218573323514fc0d69929fa0d92a523c254a474eAlexander Larsson gboolean tried_create; 1802218573323514fc0d69929fa0d92a523c254a474eAlexander Larsson 18033781343738de4abddf56982325a77bd70a98cd26Alexander Larsson /* No global trash dir, or it failed the tests, fall back to $topdir/.Trash-$uid */ 18043781343738de4abddf56982325a77bd70a98cd26Alexander Larsson dirname = g_strdup_printf (".Trash-%s", uid_str); 18053781343738de4abddf56982325a77bd70a98cd26Alexander Larsson trashdir = g_build_filename (topdir, dirname, NULL); 18063781343738de4abddf56982325a77bd70a98cd26Alexander Larsson g_free (dirname); 1807218573323514fc0d69929fa0d92a523c254a474eAlexander Larsson 1808218573323514fc0d69929fa0d92a523c254a474eAlexander Larsson tried_create = FALSE; 1809218573323514fc0d69929fa0d92a523c254a474eAlexander Larsson 1810218573323514fc0d69929fa0d92a523c254a474eAlexander Larsson retry: 18113781343738de4abddf56982325a77bd70a98cd26Alexander Larsson if (g_lstat (trashdir, &trash_stat) == 0) 18123781343738de4abddf56982325a77bd70a98cd26Alexander Larsson { 18133781343738de4abddf56982325a77bd70a98cd26Alexander Larsson if (!S_ISDIR (trash_stat.st_mode) || 18143781343738de4abddf56982325a77bd70a98cd26Alexander Larsson trash_stat.st_uid != uid) 18153781343738de4abddf56982325a77bd70a98cd26Alexander Larsson { 1816218573323514fc0d69929fa0d92a523c254a474eAlexander Larsson /* Remove the failed directory */ 1817218573323514fc0d69929fa0d92a523c254a474eAlexander Larsson if (tried_create) 1818218573323514fc0d69929fa0d92a523c254a474eAlexander Larsson g_remove (trashdir); 1819218573323514fc0d69929fa0d92a523c254a474eAlexander Larsson 18203781343738de4abddf56982325a77bd70a98cd26Alexander Larsson /* Not a directory or not owned by user, ignore */ 18213781343738de4abddf56982325a77bd70a98cd26Alexander Larsson g_free (trashdir); 18223781343738de4abddf56982325a77bd70a98cd26Alexander Larsson trashdir = NULL; 18233781343738de4abddf56982325a77bd70a98cd26Alexander Larsson } 18243781343738de4abddf56982325a77bd70a98cd26Alexander Larsson } 1825218573323514fc0d69929fa0d92a523c254a474eAlexander Larsson else 18263781343738de4abddf56982325a77bd70a98cd26Alexander Larsson { 1827218573323514fc0d69929fa0d92a523c254a474eAlexander Larsson if (!tried_create && 1828218573323514fc0d69929fa0d92a523c254a474eAlexander Larsson g_mkdir (trashdir, 0700) != -1) 1829218573323514fc0d69929fa0d92a523c254a474eAlexander Larsson { 1830218573323514fc0d69929fa0d92a523c254a474eAlexander Larsson /* Ensure that the created dir has the right uid etc. 1831218573323514fc0d69929fa0d92a523c254a474eAlexander Larsson This might fail on e.g. a FAT dir */ 1832218573323514fc0d69929fa0d92a523c254a474eAlexander Larsson tried_create = TRUE; 1833218573323514fc0d69929fa0d92a523c254a474eAlexander Larsson goto retry; 1834218573323514fc0d69929fa0d92a523c254a474eAlexander Larsson } 1835218573323514fc0d69929fa0d92a523c254a474eAlexander Larsson else 1836218573323514fc0d69929fa0d92a523c254a474eAlexander Larsson { 1837218573323514fc0d69929fa0d92a523c254a474eAlexander Larsson g_free (trashdir); 1838218573323514fc0d69929fa0d92a523c254a474eAlexander Larsson trashdir = NULL; 1839218573323514fc0d69929fa0d92a523c254a474eAlexander Larsson } 18403781343738de4abddf56982325a77bd70a98cd26Alexander Larsson } 18413781343738de4abddf56982325a77bd70a98cd26Alexander Larsson } 18423781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 18433781343738de4abddf56982325a77bd70a98cd26Alexander Larsson if (trashdir == NULL) 18443781343738de4abddf56982325a77bd70a98cd26Alexander Larsson { 18453781343738de4abddf56982325a77bd70a98cd26Alexander Larsson g_free (topdir); 18469c17697b56501d11b4c653432cc9e290347aa03eChristian Persch g_set_error_literal (error, G_IO_ERROR, 18479c17697b56501d11b4c653432cc9e290347aa03eChristian Persch G_IO_ERROR_NOT_SUPPORTED, 18489c17697b56501d11b4c653432cc9e290347aa03eChristian Persch _("Unable to find or create trash directory")); 18493781343738de4abddf56982325a77bd70a98cd26Alexander Larsson return FALSE; 18503781343738de4abddf56982325a77bd70a98cd26Alexander Larsson } 18513781343738de4abddf56982325a77bd70a98cd26Alexander Larsson } 18523781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 18533781343738de4abddf56982325a77bd70a98cd26Alexander Larsson /* Trashdir points to the trash dir with the "info" and "files" subdirectories */ 18543781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 18553781343738de4abddf56982325a77bd70a98cd26Alexander Larsson infodir = g_build_filename (trashdir, "info", NULL); 18563781343738de4abddf56982325a77bd70a98cd26Alexander Larsson filesdir = g_build_filename (trashdir, "files", NULL); 18573781343738de4abddf56982325a77bd70a98cd26Alexander Larsson g_free (trashdir); 18583781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 18593781343738de4abddf56982325a77bd70a98cd26Alexander Larsson /* Make sure we have the subdirectories */ 18603781343738de4abddf56982325a77bd70a98cd26Alexander Larsson if ((g_mkdir (infodir, 0700) == -1 && errno != EEXIST) || 18613781343738de4abddf56982325a77bd70a98cd26Alexander Larsson (g_mkdir (filesdir, 0700) == -1 && errno != EEXIST)) 18623781343738de4abddf56982325a77bd70a98cd26Alexander Larsson { 18633781343738de4abddf56982325a77bd70a98cd26Alexander Larsson g_free (topdir); 18643781343738de4abddf56982325a77bd70a98cd26Alexander Larsson g_free (infodir); 18653781343738de4abddf56982325a77bd70a98cd26Alexander Larsson g_free (filesdir); 18669c17697b56501d11b4c653432cc9e290347aa03eChristian Persch g_set_error_literal (error, G_IO_ERROR, 18679c17697b56501d11b4c653432cc9e290347aa03eChristian Persch G_IO_ERROR_NOT_SUPPORTED, 18689c17697b56501d11b4c653432cc9e290347aa03eChristian Persch _("Unable to find or create trash directory")); 18693781343738de4abddf56982325a77bd70a98cd26Alexander Larsson return FALSE; 18703781343738de4abddf56982325a77bd70a98cd26Alexander Larsson } 18713781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 18723781343738de4abddf56982325a77bd70a98cd26Alexander Larsson basename = g_path_get_basename (local->filename); 18733781343738de4abddf56982325a77bd70a98cd26Alexander Larsson i = 1; 18743781343738de4abddf56982325a77bd70a98cd26Alexander Larsson trashname = NULL; 18753781343738de4abddf56982325a77bd70a98cd26Alexander Larsson infofile = NULL; 18763781343738de4abddf56982325a77bd70a98cd26Alexander Larsson do { 18773781343738de4abddf56982325a77bd70a98cd26Alexander Larsson g_free (trashname); 18783781343738de4abddf56982325a77bd70a98cd26Alexander Larsson g_free (infofile); 18793781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 18803781343738de4abddf56982325a77bd70a98cd26Alexander Larsson trashname = get_unique_filename (basename, i++); 18813781343738de4abddf56982325a77bd70a98cd26Alexander Larsson infoname = g_strconcat (trashname, ".trashinfo", NULL); 18823781343738de4abddf56982325a77bd70a98cd26Alexander Larsson infofile = g_build_filename (infodir, infoname, NULL); 18833781343738de4abddf56982325a77bd70a98cd26Alexander Larsson g_free (infoname); 18843781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 18853781343738de4abddf56982325a77bd70a98cd26Alexander Larsson fd = open (infofile, O_CREAT | O_EXCL, 0666); 18863781343738de4abddf56982325a77bd70a98cd26Alexander Larsson } while (fd == -1 && errno == EEXIST); 18873781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 18883781343738de4abddf56982325a77bd70a98cd26Alexander Larsson g_free (basename); 18893781343738de4abddf56982325a77bd70a98cd26Alexander Larsson g_free (infodir); 18903781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 18913781343738de4abddf56982325a77bd70a98cd26Alexander Larsson if (fd == -1) 18923781343738de4abddf56982325a77bd70a98cd26Alexander Larsson { 189337ac644bd18168330f43f4d52be7e3cbb3415415Christian Persch int errsv = errno; 189437ac644bd18168330f43f4d52be7e3cbb3415415Christian Persch 18953781343738de4abddf56982325a77bd70a98cd26Alexander Larsson g_free (filesdir); 18963781343738de4abddf56982325a77bd70a98cd26Alexander Larsson g_free (topdir); 18973781343738de4abddf56982325a77bd70a98cd26Alexander Larsson g_free (trashname); 18983781343738de4abddf56982325a77bd70a98cd26Alexander Larsson g_free (infofile); 18993781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 19003781343738de4abddf56982325a77bd70a98cd26Alexander Larsson g_set_error (error, G_IO_ERROR, 190137ac644bd18168330f43f4d52be7e3cbb3415415Christian Persch g_io_error_from_errno (errsv), 1902af7645a49815d6427242d858ca779ce6bd5bb377Matthias Clasen _("Unable to create trashing info file: %s"), 190337ac644bd18168330f43f4d52be7e3cbb3415415Christian Persch g_strerror (errsv)); 19043781343738de4abddf56982325a77bd70a98cd26Alexander Larsson return FALSE; 19053781343738de4abddf56982325a77bd70a98cd26Alexander Larsson } 19063781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 19073781343738de4abddf56982325a77bd70a98cd26Alexander Larsson close (fd); 19083781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 19093781343738de4abddf56982325a77bd70a98cd26Alexander Larsson /* TODO: Maybe we should verify that you can delete the file from the trash 19103781343738de4abddf56982325a77bd70a98cd26Alexander Larsson before moving it? OTOH, that is hard, as it needs a recursive scan */ 19113781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 19123781343738de4abddf56982325a77bd70a98cd26Alexander Larsson trashfile = g_build_filename (filesdir, trashname, NULL); 19133781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 19143781343738de4abddf56982325a77bd70a98cd26Alexander Larsson g_free (filesdir); 19153781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 19163781343738de4abddf56982325a77bd70a98cd26Alexander Larsson if (g_rename (local->filename, trashfile) == -1) 19173781343738de4abddf56982325a77bd70a98cd26Alexander Larsson { 191837ac644bd18168330f43f4d52be7e3cbb3415415Christian Persch int errsv = errno; 191937ac644bd18168330f43f4d52be7e3cbb3415415Christian Persch 19203781343738de4abddf56982325a77bd70a98cd26Alexander Larsson g_free (topdir); 19213781343738de4abddf56982325a77bd70a98cd26Alexander Larsson g_free (trashname); 19223781343738de4abddf56982325a77bd70a98cd26Alexander Larsson g_free (infofile); 19233781343738de4abddf56982325a77bd70a98cd26Alexander Larsson g_free (trashfile); 19241ce74b0dd34222b201369e5aff53b27182db7b66Alexander Larsson 19251ce74b0dd34222b201369e5aff53b27182db7b66Alexander Larsson if (errsv == EXDEV) 19261ce74b0dd34222b201369e5aff53b27182db7b66Alexander Larsson /* The trash dir was actually on another fs anyway!? 19271ce74b0dd34222b201369e5aff53b27182db7b66Alexander Larsson This can happen when the same device is mounted multiple 19281ce74b0dd34222b201369e5aff53b27182db7b66Alexander Larsson times, or with bind mounts of the same fs. */ 19291ce74b0dd34222b201369e5aff53b27182db7b66Alexander Larsson g_set_error (error, G_IO_ERROR, 19301ce74b0dd34222b201369e5aff53b27182db7b66Alexander Larsson G_IO_ERROR_NOT_SUPPORTED, 19311ce74b0dd34222b201369e5aff53b27182db7b66Alexander Larsson _("Unable to trash file: %s"), 19321ce74b0dd34222b201369e5aff53b27182db7b66Alexander Larsson g_strerror (errsv)); 19331ce74b0dd34222b201369e5aff53b27182db7b66Alexander Larsson else 19341ce74b0dd34222b201369e5aff53b27182db7b66Alexander Larsson g_set_error (error, G_IO_ERROR, 19351ce74b0dd34222b201369e5aff53b27182db7b66Alexander Larsson g_io_error_from_errno (errsv), 19361ce74b0dd34222b201369e5aff53b27182db7b66Alexander Larsson _("Unable to trash file: %s"), 19371ce74b0dd34222b201369e5aff53b27182db7b66Alexander Larsson g_strerror (errsv)); 19383781343738de4abddf56982325a77bd70a98cd26Alexander Larsson return FALSE; 19393781343738de4abddf56982325a77bd70a98cd26Alexander Larsson } 19403781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 19413781343738de4abddf56982325a77bd70a98cd26Alexander Larsson g_free (trashfile); 19423781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 19433781343738de4abddf56982325a77bd70a98cd26Alexander Larsson /* TODO: Do we need to update mtime/atime here after the move? */ 19443781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 19453781343738de4abddf56982325a77bd70a98cd26Alexander Larsson /* Use absolute names for homedir */ 19463781343738de4abddf56982325a77bd70a98cd26Alexander Larsson if (is_homedir_trash) 19473781343738de4abddf56982325a77bd70a98cd26Alexander Larsson original_name = g_strdup (local->filename); 19483781343738de4abddf56982325a77bd70a98cd26Alexander Larsson else 19493781343738de4abddf56982325a77bd70a98cd26Alexander Larsson original_name = try_make_relative (local->filename, topdir); 19503781343738de4abddf56982325a77bd70a98cd26Alexander Larsson original_name_escaped = escape_trash_name (original_name); 19513781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 19523781343738de4abddf56982325a77bd70a98cd26Alexander Larsson g_free (original_name); 19533781343738de4abddf56982325a77bd70a98cd26Alexander Larsson g_free (topdir); 19543781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 1955a33f8a7564cc649daf0dca0d67daac8430808cf9Hans Breuer { 1956a33f8a7564cc649daf0dca0d67daac8430808cf9Hans Breuer time_t t; 1957a33f8a7564cc649daf0dca0d67daac8430808cf9Hans Breuer struct tm now; 1958a33f8a7564cc649daf0dca0d67daac8430808cf9Hans Breuer t = time (NULL); 1959a33f8a7564cc649daf0dca0d67daac8430808cf9Hans Breuer localtime_r (&t, &now); 1960a33f8a7564cc649daf0dca0d67daac8430808cf9Hans Breuer delete_time[0] = 0; 1961a33f8a7564cc649daf0dca0d67daac8430808cf9Hans Breuer strftime(delete_time, sizeof (delete_time), "%Y-%m-%dT%H:%M:%S", &now); 1962a33f8a7564cc649daf0dca0d67daac8430808cf9Hans Breuer } 19633781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 19643781343738de4abddf56982325a77bd70a98cd26Alexander Larsson data = g_strdup_printf ("[Trash Info]\nPath=%s\nDeletionDate=%s\n", 19653781343738de4abddf56982325a77bd70a98cd26Alexander Larsson original_name_escaped, delete_time); 19663781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 19673781343738de4abddf56982325a77bd70a98cd26Alexander Larsson g_file_set_contents (infofile, data, -1, NULL); 19683781343738de4abddf56982325a77bd70a98cd26Alexander Larsson g_free (infofile); 19693781343738de4abddf56982325a77bd70a98cd26Alexander Larsson g_free (data); 19703781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 19713781343738de4abddf56982325a77bd70a98cd26Alexander Larsson g_free (original_name_escaped); 19723781343738de4abddf56982325a77bd70a98cd26Alexander Larsson g_free (trashname); 19733781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 19743781343738de4abddf56982325a77bd70a98cd26Alexander Larsson return TRUE; 19753781343738de4abddf56982325a77bd70a98cd26Alexander Larsson} 19761d568f35d13d7cf0206439a7a94b7fd3abd92fa3Alexander Larsson#else /* G_OS_WIN32 */ 19775fe2e21960a2005ff0347266d4bd7aebf277456eTor Lillqvistgboolean 19785fe2e21960a2005ff0347266d4bd7aebf277456eTor Lillqvist_g_local_file_has_trash_dir (const char *dirname, dev_t dir_dev) 19795fe2e21960a2005ff0347266d4bd7aebf277456eTor Lillqvist{ 19805fe2e21960a2005ff0347266d4bd7aebf277456eTor Lillqvist return FALSE; /* XXX ??? */ 19815fe2e21960a2005ff0347266d4bd7aebf277456eTor Lillqvist} 19825fe2e21960a2005ff0347266d4bd7aebf277456eTor Lillqvist 19831d568f35d13d7cf0206439a7a94b7fd3abd92fa3Alexander Larssonstatic gboolean 19841d568f35d13d7cf0206439a7a94b7fd3abd92fa3Alexander Larssong_local_file_trash (GFile *file, 19851d568f35d13d7cf0206439a7a94b7fd3abd92fa3Alexander Larsson GCancellable *cancellable, 19861d568f35d13d7cf0206439a7a94b7fd3abd92fa3Alexander Larsson GError **error) 19871d568f35d13d7cf0206439a7a94b7fd3abd92fa3Alexander Larsson{ 19881d568f35d13d7cf0206439a7a94b7fd3abd92fa3Alexander Larsson GLocalFile *local = G_LOCAL_FILE (file); 19891d568f35d13d7cf0206439a7a94b7fd3abd92fa3Alexander Larsson SHFILEOPSTRUCTW op = {0}; 19901d568f35d13d7cf0206439a7a94b7fd3abd92fa3Alexander Larsson gboolean success; 19911d568f35d13d7cf0206439a7a94b7fd3abd92fa3Alexander Larsson wchar_t *wfilename; 19921d568f35d13d7cf0206439a7a94b7fd3abd92fa3Alexander Larsson long len; 19931d568f35d13d7cf0206439a7a94b7fd3abd92fa3Alexander Larsson 19941d568f35d13d7cf0206439a7a94b7fd3abd92fa3Alexander Larsson wfilename = g_utf8_to_utf16 (local->filename, -1, NULL, &len, NULL); 19951d568f35d13d7cf0206439a7a94b7fd3abd92fa3Alexander Larsson /* SHFILEOPSTRUCT.pFrom is double-zero-terminated */ 19961d568f35d13d7cf0206439a7a94b7fd3abd92fa3Alexander Larsson wfilename = g_renew (wchar_t, wfilename, len + 2); 19971d568f35d13d7cf0206439a7a94b7fd3abd92fa3Alexander Larsson wfilename[len + 1] = 0; 19981d568f35d13d7cf0206439a7a94b7fd3abd92fa3Alexander Larsson 19991d568f35d13d7cf0206439a7a94b7fd3abd92fa3Alexander Larsson op.wFunc = FO_DELETE; 20001d568f35d13d7cf0206439a7a94b7fd3abd92fa3Alexander Larsson op.pFrom = wfilename; 20011d568f35d13d7cf0206439a7a94b7fd3abd92fa3Alexander Larsson op.fFlags = FOF_ALLOWUNDO; 20021d568f35d13d7cf0206439a7a94b7fd3abd92fa3Alexander Larsson 20031d568f35d13d7cf0206439a7a94b7fd3abd92fa3Alexander Larsson success = SHFileOperationW (&op) == 0; 20041d568f35d13d7cf0206439a7a94b7fd3abd92fa3Alexander Larsson 20051d568f35d13d7cf0206439a7a94b7fd3abd92fa3Alexander Larsson if (success && op.fAnyOperationsAborted) 20061d568f35d13d7cf0206439a7a94b7fd3abd92fa3Alexander Larsson { 20071d568f35d13d7cf0206439a7a94b7fd3abd92fa3Alexander Larsson if (cancellable && !g_cancellable_is_cancelled (cancellable)) 20081d568f35d13d7cf0206439a7a94b7fd3abd92fa3Alexander Larsson g_cancellable_cancel (cancellable); 20091d568f35d13d7cf0206439a7a94b7fd3abd92fa3Alexander Larsson g_set_error (error, G_IO_ERROR, 20101d568f35d13d7cf0206439a7a94b7fd3abd92fa3Alexander Larsson G_IO_ERROR_CANCELLED, 20111d568f35d13d7cf0206439a7a94b7fd3abd92fa3Alexander Larsson _("Unable to trash file: %s"), 2012493cbfa6077850d2e134e3ac3dbe4cbf85a36e9bAlexander Larsson _("Operation was cancelled")); 20131d568f35d13d7cf0206439a7a94b7fd3abd92fa3Alexander Larsson success = FALSE; 20141d568f35d13d7cf0206439a7a94b7fd3abd92fa3Alexander Larsson } 20151d568f35d13d7cf0206439a7a94b7fd3abd92fa3Alexander Larsson else if (!success) 20161d568f35d13d7cf0206439a7a94b7fd3abd92fa3Alexander Larsson g_set_error (error, G_IO_ERROR, 20171d568f35d13d7cf0206439a7a94b7fd3abd92fa3Alexander Larsson G_IO_ERROR_FAILED, 20181d568f35d13d7cf0206439a7a94b7fd3abd92fa3Alexander Larsson _("Unable to trash file: %s"), 2019493cbfa6077850d2e134e3ac3dbe4cbf85a36e9bAlexander Larsson _("internal error")); 20201d568f35d13d7cf0206439a7a94b7fd3abd92fa3Alexander Larsson 20211d568f35d13d7cf0206439a7a94b7fd3abd92fa3Alexander Larsson g_free (wfilename); 20221d568f35d13d7cf0206439a7a94b7fd3abd92fa3Alexander Larsson return success; 20231d568f35d13d7cf0206439a7a94b7fd3abd92fa3Alexander Larsson} 20241d568f35d13d7cf0206439a7a94b7fd3abd92fa3Alexander Larsson#endif /* G_OS_WIN32 */ 20253781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 20263781343738de4abddf56982325a77bd70a98cd26Alexander Larssonstatic gboolean 2027a2ca589703273fca80cb126430a8b058aba3eb52Matthias Claseng_local_file_make_directory (GFile *file, 2028a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen GCancellable *cancellable, 2029a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen GError **error) 20303781343738de4abddf56982325a77bd70a98cd26Alexander Larsson{ 20313781343738de4abddf56982325a77bd70a98cd26Alexander Larsson GLocalFile *local = G_LOCAL_FILE (file); 20323781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 203383e4fb4f9b548ffb1eaf0eaeb5306c1aef06cd3cLoïc Minier if (g_mkdir (local->filename, 0777) == -1) 20343781343738de4abddf56982325a77bd70a98cd26Alexander Larsson { 20353781343738de4abddf56982325a77bd70a98cd26Alexander Larsson int errsv = errno; 20363781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 20373781343738de4abddf56982325a77bd70a98cd26Alexander Larsson if (errsv == EINVAL) 20383781343738de4abddf56982325a77bd70a98cd26Alexander Larsson /* This must be an invalid filename, on e.g. FAT */ 20399c17697b56501d11b4c653432cc9e290347aa03eChristian Persch g_set_error_literal (error, G_IO_ERROR, 20409c17697b56501d11b4c653432cc9e290347aa03eChristian Persch G_IO_ERROR_INVALID_FILENAME, 20419c17697b56501d11b4c653432cc9e290347aa03eChristian Persch _("Invalid filename")); 20423781343738de4abddf56982325a77bd70a98cd26Alexander Larsson else 20433781343738de4abddf56982325a77bd70a98cd26Alexander Larsson g_set_error (error, G_IO_ERROR, 20443781343738de4abddf56982325a77bd70a98cd26Alexander Larsson g_io_error_from_errno (errsv), 20458b6fdb362f6b16016e556876b174e7f3d74a10d3Ross Burton _("Error creating directory: %s"), 20463781343738de4abddf56982325a77bd70a98cd26Alexander Larsson g_strerror (errsv)); 20473781343738de4abddf56982325a77bd70a98cd26Alexander Larsson return FALSE; 20483781343738de4abddf56982325a77bd70a98cd26Alexander Larsson } 20493781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 20503781343738de4abddf56982325a77bd70a98cd26Alexander Larsson return TRUE; 20513781343738de4abddf56982325a77bd70a98cd26Alexander Larsson} 20523781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 20533781343738de4abddf56982325a77bd70a98cd26Alexander Larssonstatic gboolean 2054a2ca589703273fca80cb126430a8b058aba3eb52Matthias Claseng_local_file_make_symbolic_link (GFile *file, 2055a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen const char *symlink_value, 2056a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen GCancellable *cancellable, 2057a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen GError **error) 20583781343738de4abddf56982325a77bd70a98cd26Alexander Larsson{ 20593781343738de4abddf56982325a77bd70a98cd26Alexander Larsson#ifdef HAVE_SYMLINK 20603781343738de4abddf56982325a77bd70a98cd26Alexander Larsson GLocalFile *local = G_LOCAL_FILE (file); 20613781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 20623781343738de4abddf56982325a77bd70a98cd26Alexander Larsson if (symlink (symlink_value, local->filename) == -1) 20633781343738de4abddf56982325a77bd70a98cd26Alexander Larsson { 20643781343738de4abddf56982325a77bd70a98cd26Alexander Larsson int errsv = errno; 20653781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 20663781343738de4abddf56982325a77bd70a98cd26Alexander Larsson if (errsv == EINVAL) 20673781343738de4abddf56982325a77bd70a98cd26Alexander Larsson /* This must be an invalid filename, on e.g. FAT */ 20689c17697b56501d11b4c653432cc9e290347aa03eChristian Persch g_set_error_literal (error, G_IO_ERROR, 20699c17697b56501d11b4c653432cc9e290347aa03eChristian Persch G_IO_ERROR_INVALID_FILENAME, 20709c17697b56501d11b4c653432cc9e290347aa03eChristian Persch _("Invalid filename")); 20713781343738de4abddf56982325a77bd70a98cd26Alexander Larsson else 20723781343738de4abddf56982325a77bd70a98cd26Alexander Larsson g_set_error (error, G_IO_ERROR, 20733781343738de4abddf56982325a77bd70a98cd26Alexander Larsson g_io_error_from_errno (errsv), 20743781343738de4abddf56982325a77bd70a98cd26Alexander Larsson _("Error making symbolic link: %s"), 20753781343738de4abddf56982325a77bd70a98cd26Alexander Larsson g_strerror (errsv)); 20763781343738de4abddf56982325a77bd70a98cd26Alexander Larsson return FALSE; 20773781343738de4abddf56982325a77bd70a98cd26Alexander Larsson } 20783781343738de4abddf56982325a77bd70a98cd26Alexander Larsson return TRUE; 20793781343738de4abddf56982325a77bd70a98cd26Alexander Larsson#else 20809c17697b56501d11b4c653432cc9e290347aa03eChristian Persch g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, "Symlinks not supported"); 20813781343738de4abddf56982325a77bd70a98cd26Alexander Larsson return FALSE; 20823781343738de4abddf56982325a77bd70a98cd26Alexander Larsson#endif 20833781343738de4abddf56982325a77bd70a98cd26Alexander Larsson} 20843781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 20853781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 20863781343738de4abddf56982325a77bd70a98cd26Alexander Larssonstatic gboolean 2087a2ca589703273fca80cb126430a8b058aba3eb52Matthias Claseng_local_file_copy (GFile *source, 2088a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen GFile *destination, 2089a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen GFileCopyFlags flags, 2090a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen GCancellable *cancellable, 2091a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen GFileProgressCallback progress_callback, 2092a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen gpointer progress_callback_data, 2093a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen GError **error) 20943781343738de4abddf56982325a77bd70a98cd26Alexander Larsson{ 20953781343738de4abddf56982325a77bd70a98cd26Alexander Larsson /* Fall back to default copy */ 20969c17697b56501d11b4c653432cc9e290347aa03eChristian Persch g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, "Copy not supported"); 20973781343738de4abddf56982325a77bd70a98cd26Alexander Larsson return FALSE; 20983781343738de4abddf56982325a77bd70a98cd26Alexander Larsson} 20993781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 21003781343738de4abddf56982325a77bd70a98cd26Alexander Larssonstatic gboolean 2101a2ca589703273fca80cb126430a8b058aba3eb52Matthias Claseng_local_file_move (GFile *source, 2102a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen GFile *destination, 2103a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen GFileCopyFlags flags, 2104a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen GCancellable *cancellable, 2105a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen GFileProgressCallback progress_callback, 2106a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen gpointer progress_callback_data, 2107a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen GError **error) 21083781343738de4abddf56982325a77bd70a98cd26Alexander Larsson{ 2109c6af0efb11b510806110f422d2aca5ee735d21a8Alexander Larsson GLocalFile *local_source, *local_destination; 21103781343738de4abddf56982325a77bd70a98cd26Alexander Larsson struct stat statbuf; 21113781343738de4abddf56982325a77bd70a98cd26Alexander Larsson gboolean destination_exist, source_is_dir; 21123781343738de4abddf56982325a77bd70a98cd26Alexander Larsson char *backup_name; 21133781343738de4abddf56982325a77bd70a98cd26Alexander Larsson int res; 21140026537f3711dc843075702345f748a21a45345eAlexander Larsson off_t source_size; 21150026537f3711dc843075702345f748a21a45345eAlexander Larsson 21160026537f3711dc843075702345f748a21a45345eAlexander Larsson if (!G_IS_LOCAL_FILE (source) || 21170026537f3711dc843075702345f748a21a45345eAlexander Larsson !G_IS_LOCAL_FILE (destination)) 21180026537f3711dc843075702345f748a21a45345eAlexander Larsson { 21190026537f3711dc843075702345f748a21a45345eAlexander Larsson /* Fall back to default move */ 21209c17697b56501d11b4c653432cc9e290347aa03eChristian Persch g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, "Move not supported"); 21210026537f3711dc843075702345f748a21a45345eAlexander Larsson return FALSE; 21220026537f3711dc843075702345f748a21a45345eAlexander Larsson } 21230026537f3711dc843075702345f748a21a45345eAlexander Larsson 21240026537f3711dc843075702345f748a21a45345eAlexander Larsson local_source = G_LOCAL_FILE (source); 2125c6af0efb11b510806110f422d2aca5ee735d21a8Alexander Larsson local_destination = G_LOCAL_FILE (destination); 21260026537f3711dc843075702345f748a21a45345eAlexander Larsson 21273781343738de4abddf56982325a77bd70a98cd26Alexander Larsson res = g_lstat (local_source->filename, &statbuf); 21283781343738de4abddf56982325a77bd70a98cd26Alexander Larsson if (res == -1) 21293781343738de4abddf56982325a77bd70a98cd26Alexander Larsson { 213037ac644bd18168330f43f4d52be7e3cbb3415415Christian Persch int errsv = errno; 213137ac644bd18168330f43f4d52be7e3cbb3415415Christian Persch 21323781343738de4abddf56982325a77bd70a98cd26Alexander Larsson g_set_error (error, G_IO_ERROR, 213337ac644bd18168330f43f4d52be7e3cbb3415415Christian Persch g_io_error_from_errno (errsv), 21343781343738de4abddf56982325a77bd70a98cd26Alexander Larsson _("Error moving file: %s"), 213537ac644bd18168330f43f4d52be7e3cbb3415415Christian Persch g_strerror (errsv)); 21363781343738de4abddf56982325a77bd70a98cd26Alexander Larsson return FALSE; 21373781343738de4abddf56982325a77bd70a98cd26Alexander Larsson } 21380026537f3711dc843075702345f748a21a45345eAlexander Larsson 21399dfce3a26a37c46cb00d323230ed0885c43b55f1Alexander Larsson source_is_dir = S_ISDIR (statbuf.st_mode); 21400026537f3711dc843075702345f748a21a45345eAlexander Larsson source_size = statbuf.st_size; 21413781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 21423781343738de4abddf56982325a77bd70a98cd26Alexander Larsson destination_exist = FALSE; 21433781343738de4abddf56982325a77bd70a98cd26Alexander Larsson res = g_lstat (local_destination->filename, &statbuf); 21443781343738de4abddf56982325a77bd70a98cd26Alexander Larsson if (res == 0) 21453781343738de4abddf56982325a77bd70a98cd26Alexander Larsson { 21463781343738de4abddf56982325a77bd70a98cd26Alexander Larsson destination_exist = TRUE; /* Target file exists */ 21473781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 21483781343738de4abddf56982325a77bd70a98cd26Alexander Larsson if (flags & G_FILE_COPY_OVERWRITE) 21493781343738de4abddf56982325a77bd70a98cd26Alexander Larsson { 21503781343738de4abddf56982325a77bd70a98cd26Alexander Larsson /* Always fail on dirs, even with overwrite */ 21513781343738de4abddf56982325a77bd70a98cd26Alexander Larsson if (S_ISDIR (statbuf.st_mode)) 21523781343738de4abddf56982325a77bd70a98cd26Alexander Larsson { 21539dfce3a26a37c46cb00d323230ed0885c43b55f1Alexander Larsson if (source_is_dir) 21549c17697b56501d11b4c653432cc9e290347aa03eChristian Persch g_set_error_literal (error, 21559c17697b56501d11b4c653432cc9e290347aa03eChristian Persch G_IO_ERROR, 21569c17697b56501d11b4c653432cc9e290347aa03eChristian Persch G_IO_ERROR_WOULD_MERGE, 21579c17697b56501d11b4c653432cc9e290347aa03eChristian Persch _("Can't move directory over directory")); 21589dfce3a26a37c46cb00d323230ed0885c43b55f1Alexander Larsson else 21599c17697b56501d11b4c653432cc9e290347aa03eChristian Persch g_set_error_literal (error, 21609c17697b56501d11b4c653432cc9e290347aa03eChristian Persch G_IO_ERROR, 21619c17697b56501d11b4c653432cc9e290347aa03eChristian Persch G_IO_ERROR_IS_DIRECTORY, 21629c17697b56501d11b4c653432cc9e290347aa03eChristian Persch _("Can't copy over directory")); 21633781343738de4abddf56982325a77bd70a98cd26Alexander Larsson return FALSE; 21643781343738de4abddf56982325a77bd70a98cd26Alexander Larsson } 21653781343738de4abddf56982325a77bd70a98cd26Alexander Larsson } 21663781343738de4abddf56982325a77bd70a98cd26Alexander Larsson else 21673781343738de4abddf56982325a77bd70a98cd26Alexander Larsson { 21689c17697b56501d11b4c653432cc9e290347aa03eChristian Persch g_set_error_literal (error, 21699c17697b56501d11b4c653432cc9e290347aa03eChristian Persch G_IO_ERROR, 21709c17697b56501d11b4c653432cc9e290347aa03eChristian Persch G_IO_ERROR_EXISTS, 21719c17697b56501d11b4c653432cc9e290347aa03eChristian Persch _("Target file exists")); 21723781343738de4abddf56982325a77bd70a98cd26Alexander Larsson return FALSE; 21733781343738de4abddf56982325a77bd70a98cd26Alexander Larsson } 21743781343738de4abddf56982325a77bd70a98cd26Alexander Larsson } 21753781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 21763781343738de4abddf56982325a77bd70a98cd26Alexander Larsson if (flags & G_FILE_COPY_BACKUP && destination_exist) 21773781343738de4abddf56982325a77bd70a98cd26Alexander Larsson { 21783781343738de4abddf56982325a77bd70a98cd26Alexander Larsson backup_name = g_strconcat (local_destination->filename, "~", NULL); 21793b1b6a9722f40495762fbb115a43b39d495c3170Alexander Larsson if (g_rename (local_destination->filename, backup_name) == -1) 21803781343738de4abddf56982325a77bd70a98cd26Alexander Larsson { 21819c17697b56501d11b4c653432cc9e290347aa03eChristian Persch g_set_error_literal (error, 21829c17697b56501d11b4c653432cc9e290347aa03eChristian Persch G_IO_ERROR, 21839c17697b56501d11b4c653432cc9e290347aa03eChristian Persch G_IO_ERROR_CANT_CREATE_BACKUP, 21849c17697b56501d11b4c653432cc9e290347aa03eChristian Persch _("Backup file creation failed")); 21853781343738de4abddf56982325a77bd70a98cd26Alexander Larsson g_free (backup_name); 21863781343738de4abddf56982325a77bd70a98cd26Alexander Larsson return FALSE; 21873781343738de4abddf56982325a77bd70a98cd26Alexander Larsson } 21883781343738de4abddf56982325a77bd70a98cd26Alexander Larsson g_free (backup_name); 21893781343738de4abddf56982325a77bd70a98cd26Alexander Larsson destination_exist = FALSE; /* It did, but no more */ 21903781343738de4abddf56982325a77bd70a98cd26Alexander Larsson } 21913781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 21923781343738de4abddf56982325a77bd70a98cd26Alexander Larsson if (source_is_dir && destination_exist && (flags & G_FILE_COPY_OVERWRITE)) 21933781343738de4abddf56982325a77bd70a98cd26Alexander Larsson { 21943781343738de4abddf56982325a77bd70a98cd26Alexander Larsson /* Source is a dir, destination exists (and is not a dir, because that would have failed 21953781343738de4abddf56982325a77bd70a98cd26Alexander Larsson earlier), and we're overwriting. Manually remove the target so we can do the rename. */ 21963b1b6a9722f40495762fbb115a43b39d495c3170Alexander Larsson res = g_unlink (local_destination->filename); 21973781343738de4abddf56982325a77bd70a98cd26Alexander Larsson if (res == -1) 21983781343738de4abddf56982325a77bd70a98cd26Alexander Larsson { 219937ac644bd18168330f43f4d52be7e3cbb3415415Christian Persch int errsv = errno; 220037ac644bd18168330f43f4d52be7e3cbb3415415Christian Persch 22013781343738de4abddf56982325a77bd70a98cd26Alexander Larsson g_set_error (error, G_IO_ERROR, 220237ac644bd18168330f43f4d52be7e3cbb3415415Christian Persch g_io_error_from_errno (errsv), 22033781343738de4abddf56982325a77bd70a98cd26Alexander Larsson _("Error removing target file: %s"), 220437ac644bd18168330f43f4d52be7e3cbb3415415Christian Persch g_strerror (errsv)); 22053781343738de4abddf56982325a77bd70a98cd26Alexander Larsson return FALSE; 22063781343738de4abddf56982325a77bd70a98cd26Alexander Larsson } 22073781343738de4abddf56982325a77bd70a98cd26Alexander Larsson } 22083781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 22093b1b6a9722f40495762fbb115a43b39d495c3170Alexander Larsson if (g_rename (local_source->filename, local_destination->filename) == -1) 22103781343738de4abddf56982325a77bd70a98cd26Alexander Larsson { 22113781343738de4abddf56982325a77bd70a98cd26Alexander Larsson int errsv = errno; 22123781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 22136394ae6fdb445f71ca0c4ba0be6b942bbf097832Alexander Larsson if (errsv == EXDEV) 22146394ae6fdb445f71ca0c4ba0be6b942bbf097832Alexander Larsson /* This will cause the fallback code to run */ 22159c17697b56501d11b4c653432cc9e290347aa03eChristian Persch g_set_error_literal (error, G_IO_ERROR, 22169c17697b56501d11b4c653432cc9e290347aa03eChristian Persch G_IO_ERROR_NOT_SUPPORTED, 22179c17697b56501d11b4c653432cc9e290347aa03eChristian Persch _("Move between mounts not supported")); 22186394ae6fdb445f71ca0c4ba0be6b942bbf097832Alexander Larsson else if (errsv == EINVAL) 22193781343738de4abddf56982325a77bd70a98cd26Alexander Larsson /* This must be an invalid filename, on e.g. FAT, or 22203781343738de4abddf56982325a77bd70a98cd26Alexander Larsson we're trying to move the file into itself... 22213781343738de4abddf56982325a77bd70a98cd26Alexander Larsson We return invalid filename for both... */ 22229c17697b56501d11b4c653432cc9e290347aa03eChristian Persch g_set_error_literal (error, G_IO_ERROR, 22239c17697b56501d11b4c653432cc9e290347aa03eChristian Persch G_IO_ERROR_INVALID_FILENAME, 22249c17697b56501d11b4c653432cc9e290347aa03eChristian Persch _("Invalid filename")); 22253781343738de4abddf56982325a77bd70a98cd26Alexander Larsson else 22263781343738de4abddf56982325a77bd70a98cd26Alexander Larsson g_set_error (error, G_IO_ERROR, 22273781343738de4abddf56982325a77bd70a98cd26Alexander Larsson g_io_error_from_errno (errsv), 22283781343738de4abddf56982325a77bd70a98cd26Alexander Larsson _("Error moving file: %s"), 22293781343738de4abddf56982325a77bd70a98cd26Alexander Larsson g_strerror (errsv)); 22303781343738de4abddf56982325a77bd70a98cd26Alexander Larsson return FALSE; 22313781343738de4abddf56982325a77bd70a98cd26Alexander Larsson } 22320026537f3711dc843075702345f748a21a45345eAlexander Larsson 22330026537f3711dc843075702345f748a21a45345eAlexander Larsson /* Make sure we send full copied size */ 22340026537f3711dc843075702345f748a21a45345eAlexander Larsson if (progress_callback) 22350026537f3711dc843075702345f748a21a45345eAlexander Larsson progress_callback (source_size, source_size, progress_callback_data); 22360026537f3711dc843075702345f748a21a45345eAlexander Larsson 22373781343738de4abddf56982325a77bd70a98cd26Alexander Larsson return TRUE; 22383781343738de4abddf56982325a77bd70a98cd26Alexander Larsson} 22393781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 2240e23140cbb43c111fe9010b7f6c3a404db1aa152bAlexander Larssonstatic GFileMonitor* 2241a2ca589703273fca80cb126430a8b058aba3eb52Matthias Claseng_local_file_monitor_dir (GFile *file, 2242a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen GFileMonitorFlags flags, 22433690cb75a67377a169264e226655d8fa3a5d003aAlexander Larsson GCancellable *cancellable, 22443690cb75a67377a169264e226655d8fa3a5d003aAlexander Larsson GError **error) 22453781343738de4abddf56982325a77bd70a98cd26Alexander Larsson{ 22463781343738de4abddf56982325a77bd70a98cd26Alexander Larsson GLocalFile* local_file = G_LOCAL_FILE(file); 22473690cb75a67377a169264e226655d8fa3a5d003aAlexander Larsson return _g_local_directory_monitor_new (local_file->filename, flags, error); 22483781343738de4abddf56982325a77bd70a98cd26Alexander Larsson} 22493781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 22503781343738de4abddf56982325a77bd70a98cd26Alexander Larssonstatic GFileMonitor* 2251a2ca589703273fca80cb126430a8b058aba3eb52Matthias Claseng_local_file_monitor_file (GFile *file, 2252a2ca589703273fca80cb126430a8b058aba3eb52Matthias Clasen GFileMonitorFlags flags, 22533690cb75a67377a169264e226655d8fa3a5d003aAlexander Larsson GCancellable *cancellable, 22543690cb75a67377a169264e226655d8fa3a5d003aAlexander Larsson GError **error) 22553781343738de4abddf56982325a77bd70a98cd26Alexander Larsson{ 22563781343738de4abddf56982325a77bd70a98cd26Alexander Larsson GLocalFile* local_file = G_LOCAL_FILE(file); 22573690cb75a67377a169264e226655d8fa3a5d003aAlexander Larsson return _g_local_file_monitor_new (local_file->filename, flags, error); 22583781343738de4abddf56982325a77bd70a98cd26Alexander Larsson} 22593781343738de4abddf56982325a77bd70a98cd26Alexander Larsson 22603781343738de4abddf56982325a77bd70a98cd26Alexander Larssonstatic void 22613781343738de4abddf56982325a77bd70a98cd26Alexander Larssong_local_file_file_iface_init (GFileIface *iface) 22623781343738de4abddf56982325a77bd70a98cd26Alexander Larsson{ 22633781343738de4abddf56982325a77bd70a98cd26Alexander Larsson iface->dup = g_local_file_dup; 22643781343738de4abddf56982325a77bd70a98cd26Alexander Larsson iface->hash = g_local_file_hash; 22653781343738de4abddf56982325a77bd70a98cd26Alexander Larsson iface->equal = g_local_file_equal; 22663781343738de4abddf56982325a77bd70a98cd26Alexander Larsson iface->is_native = g_local_file_is_native; 22673781343738de4abddf56982325a77bd70a98cd26Alexander Larsson iface->has_uri_scheme = g_local_file_has_uri_scheme; 22683781343738de4abddf56982325a77bd70a98cd26Alexander Larsson iface->get_uri_scheme = g_local_file_get_uri_scheme; 22693781343738de4abddf56982325a77bd70a98cd26Alexander Larsson iface->get_basename = g_local_file_get_basename; 22703781343738de4abddf56982325a77bd70a98cd26Alexander Larsson iface->get_path = g_local_file_get_path; 22713781343738de4abddf56982325a77bd70a98cd26Alexander Larsson iface->get_uri = g_local_file_get_uri; 22723781343738de4abddf56982325a77bd70a98cd26Alexander Larsson iface->get_parse_name = g_local_file_get_parse_name; 22733781343738de4abddf56982325a77bd70a98cd26Alexander Larsson iface->get_parent = g_local_file_get_parent; 22746dc9b7ee0050c03e069d026c2c83136547a7d343Alexander Larsson iface->prefix_matches = g_local_file_prefix_matches; 22753781343738de4abddf56982325a77bd70a98cd26Alexander Larsson iface->get_relative_path = g_local_file_get_relative_path; 22763781343738de4abddf56982325a77bd70a98cd26Alexander Larsson iface->resolve_relative_path = g_local_file_resolve_relative_path; 22773781343738de4abddf56982325a77bd70a98cd26Alexander Larsson iface->get_child_for_display_name = g_local_file_get_child_for_display_name; 22783781343738de4abddf56982325a77bd70a98cd26Alexander Larsson iface->set_display_name = g_local_file_set_display_name; 22793781343738de4abddf56982325a77bd70a98cd26Alexander Larsson iface->enumerate_children = g_local_file_enumerate_children; 22803781343738de4abddf56982325a77bd70a98cd26Alexander Larsson iface->query_info = g_local_file_query_info; 22813781343738de4abddf56982325a77bd70a98cd26Alexander Larsson iface->query_filesystem_info = g_local_file_query_filesystem_info; 22823ca9fd4dbb134088bf70f2f6584f14a559e6820aDavid Zeuthen iface->find_enclosing_mount = g_local_file_find_enclosing_mount; 22833781343738de4abddf56982325a77bd70a98cd26Alexander Larsson iface->query_settable_attributes = g_local_file_query_settable_attributes; 22843781343738de4abddf56982325a77bd70a98cd26Alexander Larsson iface->query_writable_namespaces = g_local_file_query_writable_namespaces; 22853781343738de4abddf56982325a77bd70a98cd26Alexander Larsson iface->set_attribute = g_local_file_set_attribute; 22863781343738de4abddf56982325a77bd70a98cd26Alexander Larsson iface->set_attributes_from_info = g_local_file_set_attributes_from_info; 22872c362b7f9eb7cc81f37970e24c5b5dcdc56ea6d5Alexander Larsson iface->read_fn = g_local_file_read; 22883781343738de4abddf56982325a77bd70a98cd26Alexander Larsson iface->append_to = g_local_file_append_to; 22893781343738de4abddf56982325a77bd70a98cd26Alexander Larsson iface->create = g_local_file_create; 22903781343738de4abddf56982325a77bd70a98cd26Alexander Larsson iface->replace = g_local_file_replace; 22913781343738de4abddf56982325a77bd70a98cd26Alexander Larsson iface->delete_file = g_local_file_delete; 22923781343738de4abddf56982325a77bd70a98cd26Alexander Larsson iface->trash = g_local_file_trash; 22933781343738de4abddf56982325a77bd70a98cd26Alexander Larsson iface->make_directory = g_local_file_make_directory; 22943781343738de4abddf56982325a77bd70a98cd26Alexander Larsson iface->make_symbolic_link = g_local_file_make_symbolic_link; 22953781343738de4abddf56982325a77bd70a98cd26Alexander Larsson iface->copy = g_local_file_copy; 22963781343738de4abddf56982325a77bd70a98cd26Alexander Larsson iface->move = g_local_file_move; 22973781343738de4abddf56982325a77bd70a98cd26Alexander Larsson iface->monitor_dir = g_local_file_monitor_dir; 22983781343738de4abddf56982325a77bd70a98cd26Alexander Larsson iface->monitor_file = g_local_file_monitor_file; 22993781343738de4abddf56982325a77bd70a98cd26Alexander Larsson} 2300