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.1 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, see <http://www.gnu.org/licenses/>. |
17 | * |
18 | * Author: Alexander Larsson <alexl@redhat.com> |
19 | */ |
20 | |
21 | #include "config.h" |
22 | #include "glocalvfs.h" |
23 | #include "glocalfile.h" |
24 | #include "giomodule.h" |
25 | #include "giomodule-priv.h" |
26 | #include "gvfs.h" |
27 | #include <gio/gdummyfile.h> |
28 | #include <sys/types.h> |
29 | #ifdef G_OS_UNIX |
30 | #include "glib-unix.h" |
31 | #include <pwd.h> |
32 | #endif |
33 | #include <string.h> |
34 | |
35 | |
36 | struct _GLocalVfs |
37 | { |
38 | GVfs parent; |
39 | }; |
40 | |
41 | struct _GLocalVfsClass |
42 | { |
43 | GVfsClass parent_class; |
44 | |
45 | }; |
46 | |
47 | #define g_local_vfs_get_type _g_local_vfs_get_type |
48 | G_DEFINE_TYPE_WITH_CODE (GLocalVfs, g_local_vfs, G_TYPE_VFS, |
49 | _g_io_modules_ensure_extension_points_registered (); |
50 | g_io_extension_point_implement (G_VFS_EXTENSION_POINT_NAME, |
51 | g_define_type_id, |
52 | "local" , |
53 | 0)) |
54 | static void |
55 | g_local_vfs_finalize (GObject *object) |
56 | { |
57 | /* must chain up */ |
58 | G_OBJECT_CLASS (g_local_vfs_parent_class)->finalize (object); |
59 | } |
60 | |
61 | static void |
62 | g_local_vfs_init (GLocalVfs *vfs) |
63 | { |
64 | } |
65 | |
66 | /** |
67 | * g_local_vfs_new: |
68 | * |
69 | * Returns a new #GVfs handle for a local vfs. |
70 | * |
71 | * Returns: a new #GVfs handle. |
72 | **/ |
73 | GVfs * |
74 | _g_local_vfs_new (void) |
75 | { |
76 | return g_object_new (G_TYPE_LOCAL_VFS, NULL); |
77 | } |
78 | |
79 | static GFile * |
80 | g_local_vfs_get_file_for_path (GVfs *vfs, |
81 | const char *path) |
82 | { |
83 | if (*path == '\0') |
84 | return _g_dummy_file_new (uri: path); |
85 | else |
86 | return _g_local_file_new (filename: path); |
87 | } |
88 | |
89 | static GFile * |
90 | g_local_vfs_get_file_for_uri (GVfs *vfs, |
91 | const char *uri) |
92 | { |
93 | char *path; |
94 | GFile *file; |
95 | char *stripped_uri, *hash; |
96 | |
97 | if (strchr (s: uri, c: '#') != NULL) |
98 | { |
99 | stripped_uri = g_strdup (str: uri); |
100 | hash = strchr (s: stripped_uri, c: '#'); |
101 | *hash = 0; |
102 | } |
103 | else |
104 | stripped_uri = (char *)uri; |
105 | |
106 | path = g_filename_from_uri (uri: stripped_uri, NULL, NULL); |
107 | |
108 | if (stripped_uri != uri) |
109 | g_free (mem: stripped_uri); |
110 | |
111 | if (path != NULL) |
112 | file = _g_local_file_new (filename: path); |
113 | else |
114 | file = _g_dummy_file_new (uri); |
115 | |
116 | g_free (mem: path); |
117 | |
118 | return file; |
119 | } |
120 | |
121 | static const gchar * const * |
122 | g_local_vfs_get_supported_uri_schemes (GVfs *vfs) |
123 | { |
124 | static const gchar * uri_schemes[] = { "file" , NULL }; |
125 | |
126 | return uri_schemes; |
127 | } |
128 | |
129 | static GFile * |
130 | g_local_vfs_parse_name (GVfs *vfs, |
131 | const char *parse_name) |
132 | { |
133 | GFile *file; |
134 | char *filename; |
135 | char *user_prefix; |
136 | const char *user_end; |
137 | char *rest; |
138 | |
139 | g_return_val_if_fail (G_IS_VFS (vfs), NULL); |
140 | g_return_val_if_fail (parse_name != NULL, NULL); |
141 | |
142 | if (g_ascii_strncasecmp (s1: "file:" , s2: parse_name, n: 5) == 0) |
143 | filename = g_filename_from_uri (uri: parse_name, NULL, NULL); |
144 | else |
145 | { |
146 | if (*parse_name == '~') |
147 | { |
148 | #ifdef G_OS_UNIX |
149 | const char *user_start; |
150 | user_start = parse_name + 1; |
151 | #endif |
152 | parse_name ++; |
153 | |
154 | while (*parse_name != 0 && *parse_name != '/') |
155 | parse_name++; |
156 | |
157 | user_end = parse_name; |
158 | |
159 | #ifdef G_OS_UNIX |
160 | if (user_end == user_start) |
161 | user_prefix = g_strdup (str: g_get_home_dir ()); |
162 | else |
163 | { |
164 | struct passwd *passwd_file_entry; |
165 | char *user_name; |
166 | |
167 | user_name = g_strndup (str: user_start, n: user_end - user_start); |
168 | passwd_file_entry = g_unix_get_passwd_entry (user_name, NULL); |
169 | g_free (mem: user_name); |
170 | |
171 | if (passwd_file_entry != NULL && |
172 | passwd_file_entry->pw_dir != NULL) |
173 | user_prefix = g_strdup (str: passwd_file_entry->pw_dir); |
174 | else |
175 | user_prefix = g_strdup (str: g_get_home_dir ()); |
176 | |
177 | g_free (mem: passwd_file_entry); |
178 | } |
179 | #else |
180 | user_prefix = g_strdup (g_get_home_dir ()); |
181 | #endif |
182 | |
183 | rest = NULL; |
184 | if (*user_end != 0) |
185 | rest = g_filename_from_utf8 (utf8string: user_end, len: -1, NULL, NULL, NULL); |
186 | |
187 | filename = g_build_filename (first_element: user_prefix, rest, NULL); |
188 | g_free (mem: rest); |
189 | g_free (mem: user_prefix); |
190 | } |
191 | else |
192 | filename = g_filename_from_utf8 (utf8string: parse_name, len: -1, NULL, NULL, NULL); |
193 | } |
194 | |
195 | if (filename == NULL) |
196 | filename = g_strdup (str: parse_name); |
197 | |
198 | file = _g_local_file_new (filename); |
199 | g_free (mem: filename); |
200 | |
201 | return file; |
202 | } |
203 | |
204 | static gboolean |
205 | g_local_vfs_is_active (GVfs *vfs) |
206 | { |
207 | return TRUE; |
208 | } |
209 | |
210 | static void |
211 | g_local_vfs_class_init (GLocalVfsClass *class) |
212 | { |
213 | GObjectClass *object_class; |
214 | GVfsClass *vfs_class; |
215 | |
216 | object_class = (GObjectClass *) class; |
217 | |
218 | object_class->finalize = g_local_vfs_finalize; |
219 | |
220 | vfs_class = G_VFS_CLASS (class); |
221 | |
222 | vfs_class->is_active = g_local_vfs_is_active; |
223 | vfs_class->get_file_for_path = g_local_vfs_get_file_for_path; |
224 | vfs_class->get_file_for_uri = g_local_vfs_get_file_for_uri; |
225 | vfs_class->get_supported_uri_schemes = g_local_vfs_get_supported_uri_schemes; |
226 | vfs_class->parse_name = g_local_vfs_parse_name; |
227 | } |
228 | |