1 /* GIO - GLib Input, Output and Streaming Library 2 * 3 * Copyright (C) 2006-2007 Red Hat, Inc. 4 * 5 * This library is free software; you can redistribute it and/or 6 * modify it under the terms of the GNU Lesser General Public 7 * License as published by the Free Software Foundation; either 8 * version 2 of the License, or (at your option) any later version. 9 * 10 * This library is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 * Lesser General Public License for more details. 14 * 15 * You should have received a copy of the GNU Lesser General 16 * Public License along with this library; if not, write to the 17 * Free Software Foundation, Inc., 59 Temple Place, Suite 330, 18 * Boston, MA 02111-1307, USA. 19 * 20 * Author: Alexander Larsson <alexl (at) redhat.com> 21 */ 22 23 #include "config.h" 24 #include "glocalvfs.h" 25 #include "glocalfile.h" 26 #include "giomodule.h" 27 #include "giomodule-priv.h" 28 #include "gvfs.h" 29 #include <gio/gdummyfile.h> 30 #include <sys/types.h> 31 #ifdef HAVE_PWD_H 32 #include <pwd.h> 33 #endif 34 #include <string.h> 35 36 #include "gioalias.h" 37 38 struct _GLocalVfs 39 { 40 GVfs parent; 41 }; 42 43 struct _GLocalVfsClass 44 { 45 GVfsClass parent_class; 46 47 }; 48 49 #define g_local_vfs_get_type _g_local_vfs_get_type 50 G_DEFINE_TYPE_WITH_CODE (GLocalVfs, g_local_vfs, G_TYPE_VFS, 51 _g_io_modules_ensure_extension_points_registered (); 52 g_io_extension_point_implement (G_VFS_EXTENSION_POINT_NAME, 53 g_define_type_id, 54 "local", 55 0)) 56 static void 57 g_local_vfs_finalize (GObject *object) 58 { 59 /* must chain up */ 60 G_OBJECT_CLASS (g_local_vfs_parent_class)->finalize (object); 61 } 62 63 static void 64 g_local_vfs_init (GLocalVfs *vfs) 65 { 66 } 67 68 /** 69 * g_local_vfs_new: 70 * 71 * Returns a new #GVfs handle for a local vfs. 72 * 73 * Returns: a new #GVfs handle. 74 **/ 75 GVfs * 76 _g_local_vfs_new (void) 77 { 78 return g_object_new (G_TYPE_LOCAL_VFS, NULL); 79 } 80 81 static GFile * 82 g_local_vfs_get_file_for_path (GVfs *vfs, 83 const char *path) 84 { 85 return _g_local_file_new (path); 86 } 87 88 static GFile * 89 g_local_vfs_get_file_for_uri (GVfs *vfs, 90 const char *uri) 91 { 92 char *path; 93 GFile *file; 94 char *stripped_uri, *hash; 95 96 if (strchr (uri, '#') != NULL) 97 { 98 stripped_uri = g_strdup (uri); 99 hash = strchr (stripped_uri, '#'); 100 *hash = 0; 101 } 102 else 103 stripped_uri = (char *)uri; 104 105 path = g_filename_from_uri (stripped_uri, NULL, NULL); 106 107 if (stripped_uri != uri) 108 g_free (stripped_uri); 109 110 if (path != NULL) 111 file = _g_local_file_new (path); 112 else 113 file = _g_dummy_file_new (uri); 114 115 g_free (path); 116 117 return file; 118 } 119 120 static const gchar * const * 121 g_local_vfs_get_supported_uri_schemes (GVfs *vfs) 122 { 123 static const gchar * uri_schemes[] = { "file", NULL }; 124 125 return uri_schemes; 126 } 127 128 static GFile * 129 g_local_vfs_parse_name (GVfs *vfs, 130 const char *parse_name) 131 { 132 GFile *file; 133 char *filename; 134 char *user_prefix; 135 const char *user_start, *user_end; 136 char *rest; 137 138 g_return_val_if_fail (G_IS_VFS (vfs), NULL); 139 g_return_val_if_fail (parse_name != NULL, NULL); 140 141 if (g_ascii_strncasecmp ("file:", parse_name, 5) == 0) 142 filename = g_filename_from_uri (parse_name, NULL, NULL); 143 else 144 { 145 if (*parse_name == '~') 146 { 147 parse_name ++; 148 user_start = parse_name; 149 150 while (*parse_name != 0 && *parse_name != '/') 151 parse_name++; 152 153 user_end = parse_name; 154 155 if (user_end == user_start) 156 user_prefix = g_strdup (g_get_home_dir ()); 157 else 158 { 159 #ifdef HAVE_PWD_H 160 struct passwd *passwd_file_entry; 161 char *user_name; 162 163 user_name = g_strndup (user_start, user_end - user_start); 164 passwd_file_entry = getpwnam (user_name); 165 g_free (user_name); 166 167 if (passwd_file_entry != NULL && 168 passwd_file_entry->pw_dir != NULL) 169 user_prefix = g_strdup (passwd_file_entry->pw_dir); 170 else 171 #endif 172 user_prefix = g_strdup (g_get_home_dir ()); 173 } 174 175 rest = NULL; 176 if (*user_end != 0) 177 rest = g_filename_from_utf8 (user_end, -1, NULL, NULL, NULL); 178 179 filename = g_build_filename (user_prefix, rest, NULL); 180 g_free (rest); 181 g_free (user_prefix); 182 } 183 else 184 filename = g_filename_from_utf8 (parse_name, -1, NULL, NULL, NULL); 185 } 186 187 if (filename == NULL) 188 filename = g_strdup (parse_name); 189 190 file = _g_local_file_new (filename); 191 g_free (filename); 192 193 return file; 194 } 195 196 static gboolean 197 g_local_vfs_is_active (GVfs *vfs) 198 { 199 return TRUE; 200 } 201 202 static void 203 g_local_vfs_class_init (GLocalVfsClass *class) 204 { 205 GObjectClass *object_class; 206 GVfsClass *vfs_class; 207 208 object_class = (GObjectClass *) class; 209 210 object_class->finalize = g_local_vfs_finalize; 211 212 vfs_class = G_VFS_CLASS (class); 213 214 vfs_class->is_active = g_local_vfs_is_active; 215 vfs_class->get_file_for_path = g_local_vfs_get_file_for_path; 216 vfs_class->get_file_for_uri = g_local_vfs_get_file_for_uri; 217 vfs_class->get_supported_uri_schemes = g_local_vfs_get_supported_uri_schemes; 218 vfs_class->parse_name = g_local_vfs_parse_name; 219 } 220