00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <inttypes.h>
00021
00022 #include "vfs.h"
00023 #include "audstrings.h"
00024 #include <stdio.h>
00025 #include <unistd.h>
00026 #include <sys/stat.h>
00027 #include <sys/types.h>
00028 #include <string.h>
00029
00030 #include <mowgli.h>
00031
00032
00033
00034
00035
00036
00037
00038 static VFSConstructor * (* lookup_func) (const gchar * scheme) = NULL;
00039
00040 void vfs_set_lookup_func (VFSConstructor * (* func) (const gchar * scheme))
00041 {
00042 lookup_func = func;
00043 }
00044
00045 static gboolean verbose = FALSE;
00046
00047 void vfs_set_verbose (gboolean set)
00048 {
00049 verbose = set;
00050 }
00051
00052 static void logger (const gchar * format, ...)
00053 {
00054 static gchar last[256] = "";
00055 static gint repeated = 0;
00056
00057 gchar buf[256];
00058
00059 va_list args;
00060 va_start (args, format);
00061 vsnprintf (buf, sizeof buf, format, args);
00062 va_end (args);
00063
00064 if (! strcmp (buf, last))
00065 repeated ++;
00066 else
00067 {
00068 if (repeated)
00069 {
00070 printf ("VFS: (last message repeated %d times)\n", repeated);
00071 repeated = 0;
00072 }
00073
00074 fputs (buf, stdout);
00075 strcpy (last, buf);
00076 }
00077 }
00078
00087 VFSFile *
00088 vfs_fopen(const gchar * path,
00089 const gchar * mode)
00090 {
00091 g_return_val_if_fail (path && mode, NULL);
00092 g_return_val_if_fail (lookup_func, NULL);
00093
00094 VFSFile *file;
00095 VFSConstructor *vtable = NULL;
00096
00097 const gchar * s = strstr (path, "://");
00098 g_return_val_if_fail (s, NULL);
00099 gchar scheme[s - path + 1];
00100 strncpy (scheme, path, s - path);
00101 scheme[s - path] = 0;
00102
00103 vtable = lookup_func (scheme);
00104 if (! vtable)
00105 return NULL;
00106
00107 file = vtable->vfs_fopen_impl(path, mode);
00108
00109 if (verbose)
00110 logger ("VFS: <%p> open (mode %s) %s\n", file, mode, path);
00111
00112 if (file == NULL)
00113 return NULL;
00114
00115 file->uri = g_strdup(path);
00116 file->base = vtable;
00117 file->ref = 1;
00118 file->sig = VFS_SIG;
00119
00120 return file;
00121 }
00122
00129 gint
00130 vfs_fclose(VFSFile * file)
00131 {
00132 g_return_val_if_fail (file && file->sig == VFS_SIG, -1);
00133
00134 if (verbose)
00135 printf ("VFS: <%p> close\n", file);
00136
00137 gint ret = 0;
00138
00139 if (--file->ref > 0)
00140 return -1;
00141
00142 if (file->base->vfs_fclose_impl(file) != 0)
00143 ret = -1;
00144
00145 g_free(file->uri);
00146
00147 memset (file, 0, sizeof (VFSFile));
00148 g_free (file);
00149
00150 return ret;
00151 }
00152
00162 gint64 vfs_fread (void * ptr, gint64 size, gint64 nmemb, VFSFile * file)
00163 {
00164 g_return_val_if_fail (file && file->sig == VFS_SIG, 0);
00165
00166 gint64 readed = file->base->vfs_fread_impl (ptr, size, nmemb, file);
00167
00168 if (verbose)
00169 logger ("VFS: <%p> read %"PRId64" elements of size %"PRId64" = "
00170 "%"PRId64"\n", file, nmemb, size, readed);
00171
00172 return readed;
00173 }
00174
00184 gint64 vfs_fwrite (const void * ptr, gint64 size, gint64 nmemb, VFSFile * file)
00185 {
00186 g_return_val_if_fail (file && file->sig == VFS_SIG, 0);
00187
00188 gint64 written = file->base->vfs_fwrite_impl (ptr, size, nmemb, file);
00189
00190 if (verbose)
00191 logger ("VFS: <%p> write %"PRId64" elements of size %"PRId64" = "
00192 "%"PRId64"\n", file, nmemb, size, written);
00193
00194 return written;
00195 }
00196
00203 gint
00204 vfs_getc(VFSFile *file)
00205 {
00206 g_return_val_if_fail (file && file->sig == VFS_SIG, EOF);
00207
00208 if (verbose)
00209 logger ("VFS: <%p> getc\n", file);
00210
00211 return file->base->vfs_getc_impl(file);
00212 }
00213
00221 gint
00222 vfs_ungetc(gint c, VFSFile *file)
00223 {
00224 g_return_val_if_fail (file && file->sig == VFS_SIG, EOF);
00225
00226 if (verbose)
00227 logger ("VFS: <%p> ungetc\n", file);
00228
00229 return file->base->vfs_ungetc_impl(c, file);
00230 }
00231
00245 gint
00246 vfs_fseek(VFSFile * file,
00247 gint64 offset,
00248 gint whence)
00249 {
00250 g_return_val_if_fail (file && file->sig == VFS_SIG, -1);
00251
00252 if (verbose)
00253 logger ("VFS: <%p> seek to %"PRId64" from %s\n", file, offset, whence ==
00254 SEEK_CUR ? "current" : whence == SEEK_SET ? "beginning" : whence ==
00255 SEEK_END ? "end" : "invalid");
00256
00257 return file->base->vfs_fseek_impl(file, offset, whence);
00258 }
00259
00265 void
00266 vfs_rewind(VFSFile * file)
00267 {
00268 g_return_if_fail (file && file->sig == VFS_SIG);
00269
00270 if (verbose)
00271 logger ("VFS: <%p> rewind\n", file);
00272
00273 file->base->vfs_rewind_impl(file);
00274 }
00275
00282 gint64
00283 vfs_ftell(VFSFile * file)
00284 {
00285 g_return_val_if_fail (file && file->sig == VFS_SIG, -1);
00286
00287 gint64 told = file->base->vfs_ftell_impl (file);
00288
00289 if (verbose)
00290 logger ("VFS: <%p> tell = %"PRId64"\n", file, told);
00291
00292 return told;
00293 }
00294
00301 gboolean
00302 vfs_feof(VFSFile * file)
00303 {
00304 g_return_val_if_fail (file && file->sig == VFS_SIG, TRUE);
00305
00306 gboolean eof = file->base->vfs_feof_impl (file);
00307
00308 if (verbose)
00309 logger ("VFS: <%p> eof = %s\n", file, eof ? "yes" : "no");
00310
00311 return eof;
00312 }
00313
00321 gint vfs_ftruncate (VFSFile * file, gint64 length)
00322 {
00323 g_return_val_if_fail (file && file->sig == VFS_SIG, -1);
00324
00325 if (verbose)
00326 logger ("VFS: <%p> truncate to %"PRId64"\n", file, length);
00327
00328 return file->base->vfs_ftruncate_impl(file, length);
00329 }
00330
00337 gint64 vfs_fsize (VFSFile * file)
00338 {
00339 g_return_val_if_fail (file && file->sig == VFS_SIG, -1);
00340
00341 gint64 size = file->base->vfs_fsize_impl (file);
00342
00343 if (verbose)
00344 logger ("VFS: <%p> size = %"PRId64"\n", file, size);
00345
00346 return size;
00347 }
00348
00356 gchar *
00357 vfs_get_metadata(VFSFile * file, const gchar * field)
00358 {
00359 if (file == NULL)
00360 return NULL;
00361
00362 if (file->base->vfs_get_metadata_impl)
00363 return file->base->vfs_get_metadata_impl(file, field);
00364 return NULL;
00365 }
00366
00374 gboolean
00375 vfs_file_test(const gchar * path, GFileTest test)
00376 {
00377 if (strncmp (path, "file://", 7))
00378 return FALSE;
00379
00380 gchar * path2 = uri_to_filename (path);
00381
00382 if (path2 == NULL)
00383 path2 = g_strdup(path);
00384
00385 gboolean ret = g_file_test (path2, test);
00386
00387 g_free(path2);
00388
00389 return ret;
00390 }
00391
00398 gboolean
00399 vfs_is_writeable(const gchar * path)
00400 {
00401 struct stat info;
00402 gchar * realfn = uri_to_filename (path);
00403
00404 if (stat(realfn, &info) == -1)
00405 return FALSE;
00406
00407 g_free(realfn);
00408
00409 return (info.st_mode & S_IWUSR);
00410 }
00411
00421 VFSFile *
00422 vfs_dup(VFSFile *in)
00423 {
00424 g_return_val_if_fail(in != NULL, NULL);
00425
00426 in->ref++;
00427
00428 return in;
00429 }
00430
00437 gboolean
00438 vfs_is_remote(const gchar * path)
00439 {
00440 return strncasecmp (path, "file://", 7) ? TRUE : FALSE;
00441 }
00442
00449 gboolean
00450 vfs_is_streaming(VFSFile *file)
00451 {
00452 off_t size = 0;
00453
00454 if (file == NULL)
00455 return FALSE;
00456
00457 size = file->base->vfs_fsize_impl(file);
00458
00459 if (size == -1)
00460 return TRUE;
00461 else
00462 return FALSE;
00463 }