Coverage Report

Created: 2025-06-13 06:55

/src/glib/gio/glocalvfs.c
Line
Count
Source (jump to first uncovered line)
1
/* GIO - GLib Input, Output and Streaming Library
2
 * 
3
 * Copyright (C) 2006-2007 Red Hat, Inc.
4
 *
5
 * SPDX-License-Identifier: LGPL-2.1-or-later
6
 *
7
 * This library is free software; you can redistribute it and/or
8
 * modify it under the terms of the GNU Lesser General Public
9
 * License as published by the Free Software Foundation; either
10
 * version 2.1 of the License, or (at your option) any later version.
11
 *
12
 * This library is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15
 * Lesser General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU Lesser General
18
 * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
19
 *
20
 * Author: Alexander Larsson <alexl@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 G_OS_UNIX
32
#include "glib-unix.h"
33
#include <pwd.h>
34
#endif
35
#include <string.h>
36
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
0
{
59
  /* must chain up */
60
0
  G_OBJECT_CLASS (g_local_vfs_parent_class)->finalize (object);
61
0
}
62
63
static void
64
g_local_vfs_init (GLocalVfs *vfs)
65
0
{
66
0
}
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
0
{
78
0
  return g_object_new (G_TYPE_LOCAL_VFS, NULL);
79
0
}
80
81
static GFile *
82
g_local_vfs_get_file_for_path (GVfs       *vfs,
83
                               const char *path)
84
0
{
85
0
  if (*path == '\0')
86
0
    return _g_dummy_file_new (path);
87
0
  else
88
0
    return _g_local_file_new (path);
89
0
}
90
91
static GFile *
92
g_local_vfs_get_file_for_uri (GVfs       *vfs,
93
                              const char *uri)
94
0
{
95
0
  char *path;
96
0
  GFile *file;
97
0
  char *stripped_uri, *hash, *question_mark;
98
99
  /* As per https://url.spec.whatwg.org/#file-state, file: URIs can contain
100
   * query and fragment sections. We ignore them in order to get only the file
101
   * path. Compliance to this part of the WhatWG spec doesn’t necessarily mean
102
   * we comply with the entire spec. */
103
0
  if (strchr (uri, '#') != NULL)
104
0
    {
105
0
      stripped_uri = g_strdup (uri);
106
0
      hash = strchr (stripped_uri, '#');
107
0
      *hash = 0;
108
0
    }
109
0
  else if (strchr (uri, '?') != NULL)
110
0
    {
111
0
      stripped_uri = g_strdup (uri);
112
0
      question_mark = strchr (stripped_uri, '?');
113
0
      *question_mark = 0;
114
0
    }
115
0
  else
116
0
    stripped_uri = (char *)uri;
117
      
118
0
  path = g_filename_from_uri (stripped_uri, NULL, NULL);
119
120
0
  if (stripped_uri != uri)
121
0
    g_free (stripped_uri);
122
  
123
0
  if (path != NULL)
124
0
    file = _g_local_file_new (path);
125
0
  else
126
0
    file = _g_dummy_file_new (uri);
127
128
0
  g_free (path);
129
130
0
  return file;
131
0
}
132
133
static const gchar * const *
134
g_local_vfs_get_supported_uri_schemes (GVfs *vfs)
135
0
{
136
0
  static const gchar * uri_schemes[] = { "file", NULL };
137
138
0
  return uri_schemes;
139
0
}
140
141
static GFile *
142
g_local_vfs_parse_name (GVfs       *vfs,
143
                        const char *parse_name)
144
0
{
145
0
  GFile *file;
146
0
  char *filename;
147
0
  char *user_prefix;
148
0
  const char *user_end;
149
0
  char *rest;
150
  
151
0
  g_return_val_if_fail (G_IS_VFS (vfs), NULL);
152
0
  g_return_val_if_fail (parse_name != NULL, NULL);
153
154
0
  if (g_ascii_strncasecmp ("file:", parse_name, 5) == 0)
155
0
    filename = g_filename_from_uri (parse_name, NULL, NULL);
156
0
  else
157
0
    {
158
0
      if (*parse_name == '~')
159
0
  {
160
0
#ifdef G_OS_UNIX
161
0
    const char *user_start;
162
0
    user_start = parse_name + 1;
163
0
#endif
164
0
    parse_name ++;
165
    
166
0
    while (*parse_name != 0 && *parse_name != '/')
167
0
      parse_name++;
168
    
169
0
    user_end = parse_name;
170
171
0
#ifdef G_OS_UNIX
172
0
    if (user_end == user_start)
173
0
      user_prefix = g_strdup (g_get_home_dir ());
174
0
    else
175
0
      {
176
0
              struct passwd *passwd_file_entry;
177
0
              char *user_name;
178
179
0
              user_name = g_strndup (user_start, user_end - user_start);
180
0
              passwd_file_entry = g_unix_get_passwd_entry (user_name, NULL);
181
0
              g_free (user_name);
182
183
0
              if (passwd_file_entry != NULL &&
184
0
                  passwd_file_entry->pw_dir != NULL)
185
0
                user_prefix = g_strdup (passwd_file_entry->pw_dir);
186
0
              else
187
0
                user_prefix = g_strdup (g_get_home_dir ());
188
189
0
              g_free (passwd_file_entry);
190
0
      }
191
#else
192
    user_prefix = g_strdup (g_get_home_dir ());
193
#endif
194
195
0
    rest = NULL;
196
0
    if (*user_end != 0)
197
0
      rest = g_filename_from_utf8 (user_end, -1, NULL, NULL, NULL);
198
    
199
0
    filename = g_build_filename (user_prefix, rest, NULL);
200
0
    g_free (rest);
201
0
    g_free (user_prefix);
202
0
  }
203
0
      else
204
0
  filename = g_filename_from_utf8 (parse_name, -1, NULL, NULL, NULL);
205
0
    }
206
  
207
0
  if (filename == NULL)
208
0
    filename = g_strdup (parse_name);
209
    
210
0
  file = _g_local_file_new (filename);
211
0
  g_free (filename);
212
213
0
  return file;
214
0
}
215
216
static gboolean
217
g_local_vfs_is_active (GVfs *vfs)
218
0
{
219
0
  return TRUE;
220
0
}
221
222
static void
223
g_local_vfs_class_init (GLocalVfsClass *class)
224
0
{
225
0
  GObjectClass *object_class;
226
0
  GVfsClass *vfs_class;
227
  
228
0
  object_class = (GObjectClass *) class;
229
230
0
  object_class->finalize = g_local_vfs_finalize;
231
232
0
  vfs_class = G_VFS_CLASS (class);
233
234
0
  vfs_class->is_active = g_local_vfs_is_active;
235
0
  vfs_class->get_file_for_path = g_local_vfs_get_file_for_path;
236
0
  vfs_class->get_file_for_uri = g_local_vfs_get_file_for_uri;
237
0
  vfs_class->get_supported_uri_schemes = g_local_vfs_get_supported_uri_schemes;
238
0
  vfs_class->parse_name = g_local_vfs_parse_name;
239
0
}