2 * Copyright (C) 2016 J. Ali Harlow <ali@juiblex.co.uk>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
26 #include "plover/plover.h"
28 static GList *open_razor_files;
30 static gboolean has_valid_scheme(const char *uri)
33 * RFC 2396 defines valid schemes as:
34 * scheme = alpha *( alpha | digit | "+" | "-" | "." )
37 if (!g_ascii_isalpha(*uri))
42 else if (!g_ascii_isalnum(*s) && *s!='+' && *s!='-' && *s!='.')
46 static GFile *file_for_uri(const char *uri)
49 if (!has_valid_scheme(uri))
51 g_warning("%s: Not a valid URI",uri);
52 file=g_file_new_for_path(uri);
56 if (strstr(uri+1,"file:/"))
57 g_warning("%s: Implausible URI",uri);
58 file=g_file_new_for_uri(uri);
63 int file_mkdir(const char *uri,mode_t mode,struct razor_error **error)
70 g_message("file_mkdir(%s)",uri);
71 file=file_for_uri(uri);
72 path=g_file_get_path(file);
75 retval=razor_file_default_mkdir(path,mode,error);
78 else if (!g_file_make_directory(file,NULL,&err))
81 if (g_error_matches(err,G_IO_ERROR,G_IO_ERROR_EXISTS))
83 info=g_file_query_info(file,G_FILE_ATTRIBUTE_STANDARD_TYPE,
84 G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,NULL,NULL);
88 if (g_file_info_get_file_type(info)==G_FILE_TYPE_DIRECTORY)
91 razor_set_error(error,RAZOR_POSIX_ERROR,EEXIST,uri,
97 plover_propagate_g_error(error,err);
101 g_object_unref(file);
105 int file_unlink(const char *uri,struct razor_error **error)
111 g_message("file_unlink(%s)",uri);
112 file=file_for_uri(uri);
113 path=g_file_get_path(file);
116 retval=razor_file_default_unlink(path,error);
119 else if (!g_file_delete(file,NULL,&err))
121 plover_propagate_g_error(error,err);
126 g_object_unref(file);
130 int file_open(const char *uri,int flags,mode_t mode,struct razor_error **error)
136 g_message("file_open(%s)",uri);
137 file=file_for_uri(uri);
138 path=g_file_get_path(file);
141 retval=razor_file_default_open(path,flags,mode,error);
146 razor_set_error(error,RAZOR_GENERAL_ERROR,RAZOR_GENERAL_ERROR_FAILED,
147 uri,"File is not local");
150 g_object_unref(file);
154 int file_move(const char *src_uri,const char *dst_uri,
155 struct razor_error **error)
158 gchar *src_path,*dst_path;
161 g_message("file_move(%s,%s)",src_uri,dst_uri);
162 src=file_for_uri(src_uri);
163 dst=file_for_uri(dst_uri);
164 src_path=g_file_get_path(src);
165 dst_path=g_file_get_path(dst);
166 if (src_path && dst_path)
167 retval=razor_file_default_move(src_path,dst_path,error);
168 else if (!g_file_move(src,dst,G_FILE_COPY_OVERWRITE,NULL,NULL,NULL,&err))
170 plover_propagate_g_error(error,err);
182 static void *file_get_contents(const char *uri,size_t *length,int private,
183 struct razor_error **error)
191 g_message("file_get_contents(%s)",uri);
192 file=file_for_uri(uri);
193 path=g_file_get_path(file);
196 g_object_unref(file);
197 addr=razor_file_default_get_contents(path,length,private,error);
199 open_razor_files=g_list_prepend(open_razor_files,addr);
202 else if (!g_file_load_contents(file,NULL,&contents,&len,NULL,&err))
204 plover_propagate_g_error(error,err);
205 g_object_unref(file);
210 g_object_unref(file);
218 static int file_free_contents(void *addr,size_t length)
222 g_message("file_free_contents(%p)",addr);
223 lnk=g_list_find(open_razor_files,addr);
226 open_razor_files=g_list_delete_link(open_razor_files,lnk);
227 retval=razor_file_default_free_contents(addr,length);
237 int file_is_directory(const char *uri,struct razor_error **error)
244 g_message("file_is_directory(%s)",uri);
245 file=file_for_uri(uri);
246 path=g_file_get_path(file);
249 retval=razor_file_default_is_directory(path,error);
254 info=g_file_query_info(file,G_FILE_ATTRIBUTE_STANDARD_TYPE,
255 G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,NULL,&err);
258 if (g_file_info_get_file_type(info)==G_FILE_TYPE_DIRECTORY)
262 g_object_unref(info);
267 plover_propagate_g_error(error,err);
270 g_object_unref(file);
274 char *file_mkdtemp_near(const char *uri,const char *template,
275 struct razor_error **error)
279 char *tmppath,*retval;
281 g_message("file_mkdtemp_near(%s)",uri);
282 file=file_for_uri(uri);
283 path=g_file_get_path(file);
284 g_object_unref(file);
287 tmppath=razor_file_default_mkdtemp_near(path,template,error);
291 file=g_file_new_for_path(tmppath);
292 tmpuri=g_file_get_uri(file);
293 g_object_unref(file);
294 retval=strdup(tmpuri);
302 razor_set_error(error,RAZOR_GENERAL_ERROR,RAZOR_GENERAL_ERROR_FAILED,
303 uri,"File is not local");
310 void *razor_file_default;
311 GFileEnumerator *enumerator;
314 void *file_opendir(const char *uri,struct razor_error **error)
318 struct file_dir *dir;
320 g_message("file_opendir(%s)",uri);
321 dir=g_new0(struct file_dir,1);
322 file=file_for_uri(uri);
323 path=g_file_get_path(file);
326 dir->razor_file_default=razor_file_default_opendir(path,error);
327 if (!dir->razor_file_default)
336 dir->enumerator=g_file_enumerate_children(file,
337 G_FILE_ATTRIBUTE_STANDARD_NAME,G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
339 if (!dir->enumerator)
343 plover_propagate_g_error(error,err);
346 g_object_unref(file);
350 char *file_readdir(void *dp,struct razor_error **error)
352 struct file_dir *dir=dp;
356 g_message("file_readdir(%p)",dp);
357 if (dir->razor_file_default)
358 name=razor_file_default_readdir(dir->razor_file_default,error);
361 info=g_file_enumerator_next_file(dir->enumerator,NULL,&err);
365 plover_propagate_g_error(error,err);
369 name=strdup(g_file_info_get_name(info));
370 g_object_unref(info);
376 int file_closedir(void *dp,struct razor_error **error)
378 struct file_dir *dir=dp;
381 g_message("file_closedir(%p)",dp);
382 if (dir->razor_file_default)
383 retval=razor_file_default_closedir(dir->razor_file_default,error);
386 retval=g_file_enumerator_close(dir->enumerator,NULL,&err)?0:-1;
388 plover_propagate_g_error(error,err);
389 g_object_unref(dir->enumerator);
395 void plover__file_io_init(void)
398 struct razor_file_vtable file_vtable={0,};
399 g_message("plover__file_io_init()");
400 if (g_once_init_enter(&init))
402 file_vtable.structure_size=sizeof(file_vtable);
403 file_vtable.mkdir=file_mkdir;
404 file_vtable.unlink=file_unlink;
405 file_vtable.open=file_open;
406 file_vtable.move=file_move;
407 file_vtable.get_contents=file_get_contents;
408 file_vtable.free_contents=file_free_contents;
409 file_vtable.is_directory=file_is_directory;
410 file_vtable.mkdtemp_near=file_mkdtemp_near;
411 file_vtable.opendir=file_opendir;
412 file_vtable.readdir=file_readdir;
413 file_vtable.closedir=file_closedir;
414 razor_file_set_vtable(&file_vtable);
415 g_once_init_leave(&init,1);