1.1 --- a/plover/fileio.c Tue Jun 14 12:39:53 2016 +0100
1.2 +++ b/plover/fileio.c Thu Jun 16 18:00:21 2016 +0100
1.3 @@ -17,6 +17,8 @@
1.4 */
1.5
1.6 #include <stdlib.h>
1.7 +#include <string.h>
1.8 +#include <errno.h>
1.9 #include <razor.h>
1.10 #include <glib.h>
1.11 #include <gio/gio.h>
1.12 @@ -25,6 +27,158 @@
1.13
1.14 static GList *open_razor_files;
1.15
1.16 +static gboolean has_valid_scheme(const char *uri)
1.17 +{
1.18 + /*
1.19 + * RFC 2396 defines valid schemes as:
1.20 + * scheme = alpha *( alpha | digit | "+" | "-" | "." )
1.21 + */
1.22 + const char *s;
1.23 + if (!g_ascii_isalpha(*uri))
1.24 + return FALSE;
1.25 + for(s=uri+1;;s++)
1.26 + if (*s==':')
1.27 + return TRUE;
1.28 + else if (!g_ascii_isalnum(*s) && *s!='+' && *s!='-' && *s!='.')
1.29 + return FALSE;
1.30 +}
1.31 +
1.32 +static GFile *file_for_uri(const char *uri)
1.33 +{
1.34 + GFile *file;
1.35 + if (!has_valid_scheme(uri))
1.36 + {
1.37 + g_warning("%s: Not a valid URI",uri);
1.38 + file=g_file_new_for_path(uri);
1.39 + }
1.40 + else
1.41 + {
1.42 + if (strstr(uri+1,"file:/"))
1.43 + g_warning("%s: Implausible URI",uri);
1.44 + file=g_file_new_for_uri(uri);
1.45 + }
1.46 + return file;
1.47 +}
1.48 +
1.49 +int file_mkdir(const char *uri,mode_t mode,struct razor_error **error)
1.50 +{
1.51 + GFile *file;
1.52 + GFileInfo *info;
1.53 + gchar *path;
1.54 + int retval;
1.55 + GError *err=NULL;
1.56 + g_message("file_mkdir(%s)",uri);
1.57 + file=file_for_uri(uri);
1.58 + path=g_file_get_path(file);
1.59 + if (path)
1.60 + {
1.61 + retval=razor_file_default_mkdir(path,mode,error);
1.62 + g_free(path);
1.63 + }
1.64 + else if (!g_file_make_directory(file,NULL,&err))
1.65 + {
1.66 + retval=-1;
1.67 + if (g_error_matches(err,G_IO_ERROR,G_IO_ERROR_EXISTS))
1.68 + {
1.69 + info=g_file_query_info(file,G_FILE_ATTRIBUTE_STANDARD_TYPE,
1.70 + G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,NULL,NULL);
1.71 + if (info)
1.72 + {
1.73 + g_clear_error(&err);
1.74 + if (g_file_info_get_file_type(info)==G_FILE_TYPE_DIRECTORY)
1.75 + retval=0;
1.76 + else
1.77 + razor_set_error(error,RAZOR_POSIX_ERROR,EEXIST,uri,
1.78 + "Not a directory");
1.79 + g_object_unref(info);
1.80 + }
1.81 + }
1.82 + if (err)
1.83 + plover_propagate_g_error(error,err);
1.84 + }
1.85 + else
1.86 + retval=0;
1.87 + g_object_unref(file);
1.88 + return retval;
1.89 +}
1.90 +
1.91 +int file_unlink(const char *uri,struct razor_error **error)
1.92 +{
1.93 + GFile *file;
1.94 + gchar *path;
1.95 + int retval;
1.96 + GError *err=NULL;
1.97 + g_message("file_unlink(%s)",uri);
1.98 + file=file_for_uri(uri);
1.99 + path=g_file_get_path(file);
1.100 + if (path)
1.101 + {
1.102 + retval=razor_file_default_unlink(path,error);
1.103 + g_free(path);
1.104 + }
1.105 + else if (!g_file_delete(file,NULL,&err))
1.106 + {
1.107 + plover_propagate_g_error(error,err);
1.108 + retval=-1;
1.109 + }
1.110 + else
1.111 + retval=0;
1.112 + g_object_unref(file);
1.113 + return retval;
1.114 +}
1.115 +
1.116 +int file_open(const char *uri,int flags,mode_t mode,struct razor_error **error)
1.117 +{
1.118 + GFile *file;
1.119 + gchar *path;
1.120 + int retval;
1.121 + GError *err=NULL;
1.122 + g_message("file_open(%s)",uri);
1.123 + file=file_for_uri(uri);
1.124 + path=g_file_get_path(file);
1.125 + if (path)
1.126 + {
1.127 + retval=razor_file_default_open(path,flags,mode,error);
1.128 + g_free(path);
1.129 + }
1.130 + else
1.131 + {
1.132 + razor_set_error(error,RAZOR_GENERAL_ERROR,RAZOR_GENERAL_ERROR_FAILED,
1.133 + uri,"File is not local");
1.134 + retval=-1;
1.135 + }
1.136 + g_object_unref(file);
1.137 + return retval;
1.138 +}
1.139 +
1.140 +int file_move(const char *src_uri,const char *dst_uri,
1.141 + struct razor_error **error)
1.142 +{
1.143 + GFile *src,*dst;
1.144 + gchar *src_path,*dst_path;
1.145 + int retval;
1.146 + GError *err=NULL;
1.147 + g_message("file_move(%s,%s)",src_uri,dst_uri);
1.148 + src=file_for_uri(src_uri);
1.149 + dst=file_for_uri(dst_uri);
1.150 + src_path=g_file_get_path(src);
1.151 + dst_path=g_file_get_path(dst);
1.152 + if (src_path && dst_path)
1.153 + retval=razor_file_default_move(src_path,dst_path,error);
1.154 + else if (!g_file_move(src,dst,G_FILE_COPY_OVERWRITE,NULL,NULL,NULL,&err))
1.155 + {
1.156 + plover_propagate_g_error(error,err);
1.157 + retval=-1;
1.158 + }
1.159 + else
1.160 + retval=0;
1.161 + g_free(src_path);
1.162 + g_free(dst_path);
1.163 + g_object_unref(src);
1.164 + g_object_unref(dst);
1.165 + return retval;
1.166 +}
1.167 +
1.168 static void *file_get_contents(const char *uri,size_t *length,int private,
1.169 struct razor_error **error)
1.170 {
1.171 @@ -35,7 +189,7 @@
1.172 gsize len;
1.173 GError *err=NULL;
1.174 g_message("file_get_contents(%s)",uri);
1.175 - file=g_file_new_for_uri(uri);
1.176 + file=file_for_uri(uri);
1.177 path=g_file_get_path(file);
1.178 if (path)
1.179 {
1.180 @@ -80,15 +234,183 @@
1.181 return retval;
1.182 }
1.183
1.184 +int file_is_directory(const char *uri,struct razor_error **error)
1.185 +{
1.186 + GFile *file;
1.187 + GFileInfo *info;
1.188 + gchar *path;
1.189 + int retval;
1.190 + GError *err=NULL;
1.191 + g_message("file_is_directory(%s)",uri);
1.192 + file=file_for_uri(uri);
1.193 + path=g_file_get_path(file);
1.194 + if (path)
1.195 + {
1.196 + retval=razor_file_default_is_directory(path,error);
1.197 + g_free(path);
1.198 + }
1.199 + else
1.200 + {
1.201 + info=g_file_query_info(file,G_FILE_ATTRIBUTE_STANDARD_TYPE,
1.202 + G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,NULL,&err);
1.203 + if (info)
1.204 + {
1.205 + if (g_file_info_get_file_type(info)==G_FILE_TYPE_DIRECTORY)
1.206 + retval=1;
1.207 + else
1.208 + retval=0;
1.209 + g_object_unref(info);
1.210 + }
1.211 + else
1.212 + {
1.213 + retval=-1;
1.214 + plover_propagate_g_error(error,err);
1.215 + }
1.216 + }
1.217 + g_object_unref(file);
1.218 + return retval;
1.219 +}
1.220 +
1.221 +char *file_mkdtemp_near(const char *uri,const char *template,
1.222 + struct razor_error **error)
1.223 +{
1.224 + GFile *file;
1.225 + gchar *path,*tmpuri;
1.226 + char *tmppath,*retval;
1.227 + GError *err=NULL;
1.228 + g_message("file_mkdtemp_near(%s)",uri);
1.229 + file=file_for_uri(uri);
1.230 + path=g_file_get_path(file);
1.231 + g_object_unref(file);
1.232 + if (path)
1.233 + {
1.234 + tmppath=razor_file_default_mkdtemp_near(path,template,error);
1.235 + g_free(path);
1.236 + if (tmppath)
1.237 + {
1.238 + file=g_file_new_for_path(tmppath);
1.239 + tmpuri=g_file_get_uri(file);
1.240 + g_object_unref(file);
1.241 + retval=strdup(tmpuri);
1.242 + g_free(tmpuri);
1.243 + }
1.244 + else
1.245 + retval=NULL;
1.246 + }
1.247 + else
1.248 + {
1.249 + razor_set_error(error,RAZOR_GENERAL_ERROR,RAZOR_GENERAL_ERROR_FAILED,
1.250 + uri,"File is not local");
1.251 + retval=NULL;
1.252 + }
1.253 + return retval;
1.254 +}
1.255 +
1.256 +struct file_dir {
1.257 + void *razor_file_default;
1.258 + GFileEnumerator *enumerator;
1.259 +};
1.260 +
1.261 +void *file_opendir(const char *uri,struct razor_error **error)
1.262 +{
1.263 + GFile *file;
1.264 + gchar *path;
1.265 + struct file_dir *dir;
1.266 + GError *err=NULL;
1.267 + g_message("file_opendir(%s)",uri);
1.268 + dir=g_new0(struct file_dir,1);
1.269 + file=file_for_uri(uri);
1.270 + path=g_file_get_path(file);
1.271 + if (path)
1.272 + {
1.273 + dir->razor_file_default=razor_file_default_opendir(path,error);
1.274 + if (!dir->razor_file_default)
1.275 + {
1.276 + g_free(dir);
1.277 + dir=NULL;
1.278 + }
1.279 + g_free(path);
1.280 + }
1.281 + else
1.282 + {
1.283 + dir->enumerator=g_file_enumerate_children(file,
1.284 + G_FILE_ATTRIBUTE_STANDARD_NAME,G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
1.285 + NULL,&err);
1.286 + if (!dir->enumerator)
1.287 + {
1.288 + g_free(dir);
1.289 + dir=NULL;
1.290 + plover_propagate_g_error(error,err);
1.291 + }
1.292 + }
1.293 + g_object_unref(file);
1.294 + return dir;
1.295 +}
1.296 +
1.297 +char *file_readdir(void *dp,struct razor_error **error)
1.298 +{
1.299 + struct file_dir *dir=dp;
1.300 + char *name;
1.301 + GError *err=NULL;
1.302 + GFileInfo *info;
1.303 + g_message("file_readdir(%p)",dp);
1.304 + if (dir->razor_file_default)
1.305 + name=razor_file_default_readdir(dir->razor_file_default,error);
1.306 + else
1.307 + {
1.308 + info=g_file_enumerator_next_file(dir->enumerator,NULL,&err);
1.309 + if (!info)
1.310 + {
1.311 + name=NULL;
1.312 + plover_propagate_g_error(error,err);
1.313 + }
1.314 + else
1.315 + {
1.316 + name=strdup(g_file_info_get_name(info));
1.317 + g_object_unref(info);
1.318 + }
1.319 + }
1.320 + return name;
1.321 +}
1.322 +
1.323 +int file_closedir(void *dp,struct razor_error **error)
1.324 +{
1.325 + struct file_dir *dir=dp;
1.326 + int retval;
1.327 + GError *err=NULL;
1.328 + g_message("file_closedir(%p)",dp);
1.329 + if (dir->razor_file_default)
1.330 + retval=razor_file_default_closedir(dir->razor_file_default,error);
1.331 + else
1.332 + {
1.333 + retval=g_file_enumerator_close(dir->enumerator,NULL,&err)?0:-1;
1.334 + if (retval)
1.335 + plover_propagate_g_error(error,err);
1.336 + g_object_unref(dir->enumerator);
1.337 + }
1.338 + g_free(dir);
1.339 + return retval;
1.340 +}
1.341 +
1.342 void plover__file_io_init(void)
1.343 {
1.344 static gsize init=0;
1.345 - struct razor_file_vtable file_vtable;
1.346 + struct razor_file_vtable file_vtable={0,};
1.347 g_message("plover__file_io_init()");
1.348 if (g_once_init_enter(&init))
1.349 {
1.350 + file_vtable.structure_size=sizeof(file_vtable);
1.351 + file_vtable.mkdir=file_mkdir;
1.352 + file_vtable.unlink=file_unlink;
1.353 + file_vtable.open=file_open;
1.354 + file_vtable.move=file_move;
1.355 file_vtable.get_contents=file_get_contents;
1.356 file_vtable.free_contents=file_free_contents;
1.357 + file_vtable.is_directory=file_is_directory;
1.358 + file_vtable.mkdtemp_near=file_mkdtemp_near;
1.359 + file_vtable.opendir=file_opendir;
1.360 + file_vtable.readdir=file_readdir;
1.361 + file_vtable.closedir=file_closedir;
1.362 razor_file_set_vtable(&file_vtable);
1.363 g_once_init_leave(&init,1);
1.364 }