00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include <glib.h>
00023 #include <inttypes.h>
00024
00025 #include "vfs.h"
00026 #include "audstrings.h"
00027 #include <stdio.h>
00028 #include <unistd.h>
00029 #include <sys/stat.h>
00030 #include <sys/types.h>
00031 #include <string.h>
00032
00033 #define VFS_SIG ('V' | ('F' << 8) | ('S' << 16))
00034
00040 struct _VFSFile {
00041 char * uri;
00042 VFSConstructor * base;
00043 void * handle;
00044 int sig;
00045 };
00046
00047
00048
00049
00050
00051
00052
00053 static VFSConstructor * (* lookup_func) (const char * scheme) = NULL;
00054
00055 void vfs_set_lookup_func (VFSConstructor * (* func) (const char * scheme))
00056 {
00057 lookup_func = func;
00058 }
00059
00060 static bool_t verbose = FALSE;
00061
00062 void vfs_set_verbose (bool_t set)
00063 {
00064 verbose = set;
00065 }
00066
00067 static void logger (const char * format, ...)
00068 {
00069 static char last[256] = "";
00070 static int repeated = 0;
00071
00072 char buf[256];
00073
00074 va_list args;
00075 va_start (args, format);
00076 vsnprintf (buf, sizeof buf, format, args);
00077 va_end (args);
00078
00079 if (! strcmp (buf, last))
00080 repeated ++;
00081 else
00082 {
00083 if (repeated)
00084 {
00085 printf ("VFS: (last message repeated %d times)\n", repeated);
00086 repeated = 0;
00087 }
00088
00089 fputs (buf, stdout);
00090 strcpy (last, buf);
00091 }
00092 }
00093
00094 VFSFile * vfs_new (const char * path, VFSConstructor * vtable, void * handle)
00095 {
00096 VFSFile * file = g_slice_new (VFSFile);
00097 file->uri = str_get (path);
00098 file->base = vtable;
00099 file->handle = handle;
00100 file->sig = VFS_SIG;
00101 return file;
00102 }
00103
00104 const char * vfs_get_filename (VFSFile * file)
00105 {
00106 return file->uri;
00107 }
00108
00109 void * vfs_get_handle (VFSFile * file)
00110 {
00111 return file->handle;
00112 }
00113
00122 VFSFile *
00123 vfs_fopen(const char * path,
00124 const char * mode)
00125 {
00126 g_return_val_if_fail (path && mode, NULL);
00127 g_return_val_if_fail (lookup_func, NULL);
00128
00129 const char * s = strstr (path, "://");
00130 g_return_val_if_fail (s, NULL);
00131 char scheme[s - path + 1];
00132 strncpy (scheme, path, s - path);
00133 scheme[s - path] = 0;
00134
00135 VFSConstructor * vtable = lookup_func (scheme);
00136 if (! vtable)
00137 return NULL;
00138
00139 const gchar * sub;
00140 uri_parse (path, NULL, NULL, & sub, NULL);
00141
00142 gchar buf[sub - path + 1];
00143 memcpy (buf, path, sub - path);
00144 buf[sub - path] = 0;
00145
00146 void * handle = vtable->vfs_fopen_impl (buf, mode);
00147 if (! handle)
00148 return NULL;
00149
00150 VFSFile * file = vfs_new (path, vtable, handle);
00151
00152 if (verbose)
00153 logger ("VFS: <%p> open (mode %s) %s\n", file, mode, path);
00154
00155 return file;
00156 }
00157
00164 int
00165 vfs_fclose(VFSFile * file)
00166 {
00167 g_return_val_if_fail (file && file->sig == VFS_SIG, -1);
00168
00169 if (verbose)
00170 logger ("VFS: <%p> close\n", file);
00171
00172 int ret = 0;
00173
00174 if (file->base->vfs_fclose_impl(file) != 0)
00175 ret = -1;
00176
00177 str_unref (file->uri);
00178
00179 memset (file, 0, sizeof (VFSFile));
00180 g_slice_free (VFSFile, file);
00181
00182 return ret;
00183 }
00184
00194 int64_t vfs_fread (void * ptr, int64_t size, int64_t nmemb, VFSFile * file)
00195 {
00196 g_return_val_if_fail (file && file->sig == VFS_SIG, 0);
00197
00198 int64_t readed = file->base->vfs_fread_impl (ptr, size, nmemb, file);
00199
00200
00201
00202
00203
00204 return readed;
00205 }
00206
00216 int64_t vfs_fwrite (const void * ptr, int64_t size, int64_t nmemb, VFSFile * file)
00217 {
00218 g_return_val_if_fail (file && file->sig == VFS_SIG, 0);
00219
00220 int64_t written = file->base->vfs_fwrite_impl (ptr, size, nmemb, file);
00221
00222 if (verbose)
00223 logger ("VFS: <%p> write %"PRId64" elements of size %"PRId64" = "
00224 "%"PRId64"\n", file, nmemb, size, written);
00225
00226 return written;
00227 }
00228
00235 int
00236 vfs_getc(VFSFile *file)
00237 {
00238 g_return_val_if_fail (file && file->sig == VFS_SIG, EOF);
00239
00240 if (verbose)
00241 logger ("VFS: <%p> getc\n", file);
00242
00243 return file->base->vfs_getc_impl(file);
00244 }
00245
00253 int
00254 vfs_ungetc(int c, VFSFile *file)
00255 {
00256 g_return_val_if_fail (file && file->sig == VFS_SIG, EOF);
00257
00258 if (verbose)
00259 logger ("VFS: <%p> ungetc\n", file);
00260
00261 return file->base->vfs_ungetc_impl(c, file);
00262 }
00263
00277 int
00278 vfs_fseek(VFSFile * file,
00279 int64_t offset,
00280 int whence)
00281 {
00282 g_return_val_if_fail (file && file->sig == VFS_SIG, -1);
00283
00284 if (verbose)
00285 logger ("VFS: <%p> seek to %"PRId64" from %s\n", file, offset, whence ==
00286 SEEK_CUR ? "current" : whence == SEEK_SET ? "beginning" : whence ==
00287 SEEK_END ? "end" : "invalid");
00288
00289 return file->base->vfs_fseek_impl(file, offset, whence);
00290 }
00291
00297 void
00298 vfs_rewind(VFSFile * file)
00299 {
00300 g_return_if_fail (file && file->sig == VFS_SIG);
00301
00302 if (verbose)
00303 logger ("VFS: <%p> rewind\n", file);
00304
00305 file->base->vfs_rewind_impl(file);
00306 }
00307
00314 int64_t
00315 vfs_ftell(VFSFile * file)
00316 {
00317 g_return_val_if_fail (file && file->sig == VFS_SIG, -1);
00318
00319 int64_t told = file->base->vfs_ftell_impl (file);
00320
00321 if (verbose)
00322 logger ("VFS: <%p> tell = %"PRId64"\n", file, told);
00323
00324 return told;
00325 }
00326
00333 bool_t
00334 vfs_feof(VFSFile * file)
00335 {
00336 g_return_val_if_fail (file && file->sig == VFS_SIG, TRUE);
00337
00338 bool_t eof = file->base->vfs_feof_impl (file);
00339
00340 if (verbose)
00341 logger ("VFS: <%p> eof = %s\n", file, eof ? "yes" : "no");
00342
00343 return eof;
00344 }
00345
00353 int vfs_ftruncate (VFSFile * file, int64_t length)
00354 {
00355 g_return_val_if_fail (file && file->sig == VFS_SIG, -1);
00356
00357 if (verbose)
00358 logger ("VFS: <%p> truncate to %"PRId64"\n", file, length);
00359
00360 return file->base->vfs_ftruncate_impl(file, length);
00361 }
00362
00369 int64_t vfs_fsize (VFSFile * file)
00370 {
00371 g_return_val_if_fail (file && file->sig == VFS_SIG, -1);
00372
00373 int64_t size = file->base->vfs_fsize_impl (file);
00374
00375 if (verbose)
00376 logger ("VFS: <%p> size = %"PRId64"\n", file, size);
00377
00378 return size;
00379 }
00380
00388 char *
00389 vfs_get_metadata(VFSFile * file, const char * field)
00390 {
00391 if (file == NULL)
00392 return NULL;
00393
00394 if (file->base->vfs_get_metadata_impl)
00395 return file->base->vfs_get_metadata_impl(file, field);
00396 return NULL;
00397 }
00398
00406 bool_t
00407 vfs_file_test(const char * path, int test)
00408 {
00409 if (strncmp (path, "file://", 7))
00410 return FALSE;
00411
00412 char * path2 = uri_to_filename (path);
00413
00414 if (path2 == NULL)
00415 path2 = g_strdup(path);
00416
00417 bool_t ret = g_file_test (path2, test);
00418
00419 g_free(path2);
00420
00421 return ret;
00422 }
00423
00430 bool_t
00431 vfs_is_writeable(const char * path)
00432 {
00433 struct stat info;
00434 char * realfn = uri_to_filename (path);
00435
00436 if (stat(realfn, &info) == -1)
00437 return FALSE;
00438
00439 g_free(realfn);
00440
00441 return (info.st_mode & S_IWUSR);
00442 }
00443
00450 bool_t vfs_is_remote (const char * path)
00451 {
00452 return strncmp (path, "file://", 7) ? TRUE : FALSE;
00453 }
00454
00461 bool_t vfs_is_streaming (VFSFile * file)
00462 {
00463 return (vfs_fsize (file) < 0);
00464 }