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 #include "config.h"
00034
00035 #define VFS_SIG ('V' | ('F' << 8) | ('S' << 16))
00036
00042 struct _VFSFile {
00043 char * uri;
00044 VFSConstructor * base;
00045 void * handle;
00046 int sig;
00047 };
00048
00049
00050
00051
00052
00053
00054
00055 static VFSConstructor * (* lookup_func) (const char * scheme) = NULL;
00056
00057 EXPORT void vfs_set_lookup_func (VFSConstructor * (* func) (const char * scheme))
00058 {
00059 lookup_func = func;
00060 }
00061
00062 static bool_t verbose = FALSE;
00063
00064 EXPORT void vfs_set_verbose (bool_t set)
00065 {
00066 verbose = set;
00067 }
00068
00069 static void logger (const char * format, ...)
00070 {
00071 static char last[256] = "";
00072 static int repeated = 0;
00073
00074 char buf[256];
00075
00076 va_list args;
00077 va_start (args, format);
00078 vsnprintf (buf, sizeof buf, format, args);
00079 va_end (args);
00080
00081 if (! strcmp (buf, last))
00082 repeated ++;
00083 else
00084 {
00085 if (repeated)
00086 {
00087 printf ("VFS: (last message repeated %d times)\n", repeated);
00088 repeated = 0;
00089 }
00090
00091 fputs (buf, stdout);
00092 strcpy (last, buf);
00093 }
00094 }
00095
00096 EXPORT VFSFile * vfs_new (const char * path, VFSConstructor * vtable, void * handle)
00097 {
00098 VFSFile * file = g_slice_new (VFSFile);
00099 file->uri = str_get (path);
00100 file->base = vtable;
00101 file->handle = handle;
00102 file->sig = VFS_SIG;
00103 return file;
00104 }
00105
00106 EXPORT const char * vfs_get_filename (VFSFile * file)
00107 {
00108 return file->uri;
00109 }
00110
00111 EXPORT void * vfs_get_handle (VFSFile * file)
00112 {
00113 return file->handle;
00114 }
00115
00124 EXPORT VFSFile *
00125 vfs_fopen(const char * path,
00126 const char * mode)
00127 {
00128 g_return_val_if_fail (path && mode, NULL);
00129 g_return_val_if_fail (lookup_func, NULL);
00130
00131 const char * s = strstr (path, "://");
00132 g_return_val_if_fail (s, NULL);
00133 char scheme[s - path + 1];
00134 strncpy (scheme, path, s - path);
00135 scheme[s - path] = 0;
00136
00137 VFSConstructor * vtable = lookup_func (scheme);
00138 if (! vtable)
00139 return NULL;
00140
00141 const gchar * sub;
00142 uri_parse (path, NULL, NULL, & sub, NULL);
00143
00144 gchar buf[sub - path + 1];
00145 memcpy (buf, path, sub - path);
00146 buf[sub - path] = 0;
00147
00148 void * handle = vtable->vfs_fopen_impl (buf, mode);
00149 if (! handle)
00150 return NULL;
00151
00152 VFSFile * file = vfs_new (path, vtable, handle);
00153
00154 if (verbose)
00155 logger ("VFS: <%p> open (mode %s) %s\n", file, mode, path);
00156
00157 return file;
00158 }
00159
00166 EXPORT int
00167 vfs_fclose(VFSFile * file)
00168 {
00169 g_return_val_if_fail (file && file->sig == VFS_SIG, -1);
00170
00171 if (verbose)
00172 logger ("VFS: <%p> close\n", file);
00173
00174 int ret = 0;
00175
00176 if (file->base->vfs_fclose_impl(file) != 0)
00177 ret = -1;
00178
00179 str_unref (file->uri);
00180
00181 memset (file, 0, sizeof (VFSFile));
00182 g_slice_free (VFSFile, file);
00183
00184 return ret;
00185 }
00186
00196 EXPORT int64_t vfs_fread (void * ptr, int64_t size, int64_t nmemb, VFSFile * file)
00197 {
00198 g_return_val_if_fail (file && file->sig == VFS_SIG, 0);
00199
00200 int64_t readed = file->base->vfs_fread_impl (ptr, size, nmemb, file);
00201
00202
00203
00204
00205
00206 return readed;
00207 }
00208
00218 EXPORT int64_t vfs_fwrite (const void * ptr, int64_t size, int64_t nmemb, VFSFile * file)
00219 {
00220 g_return_val_if_fail (file && file->sig == VFS_SIG, 0);
00221
00222 int64_t written = file->base->vfs_fwrite_impl (ptr, size, nmemb, file);
00223
00224 if (verbose)
00225 logger ("VFS: <%p> write %"PRId64" elements of size %"PRId64" = "
00226 "%"PRId64"\n", file, nmemb, size, written);
00227
00228 return written;
00229 }
00230
00237 EXPORT int
00238 vfs_getc(VFSFile *file)
00239 {
00240 g_return_val_if_fail (file && file->sig == VFS_SIG, EOF);
00241
00242 if (verbose)
00243 logger ("VFS: <%p> getc\n", file);
00244
00245 return file->base->vfs_getc_impl(file);
00246 }
00247
00255 EXPORT int
00256 vfs_ungetc(int c, VFSFile *file)
00257 {
00258 g_return_val_if_fail (file && file->sig == VFS_SIG, EOF);
00259
00260 if (verbose)
00261 logger ("VFS: <%p> ungetc\n", file);
00262
00263 return file->base->vfs_ungetc_impl(c, file);
00264 }
00265
00279 EXPORT int
00280 vfs_fseek(VFSFile * file,
00281 int64_t offset,
00282 int whence)
00283 {
00284 g_return_val_if_fail (file && file->sig == VFS_SIG, -1);
00285
00286 if (verbose)
00287 logger ("VFS: <%p> seek to %"PRId64" from %s\n", file, offset, whence ==
00288 SEEK_CUR ? "current" : whence == SEEK_SET ? "beginning" : whence ==
00289 SEEK_END ? "end" : "invalid");
00290
00291 return file->base->vfs_fseek_impl(file, offset, whence);
00292 }
00293
00299 EXPORT void
00300 vfs_rewind(VFSFile * file)
00301 {
00302 g_return_if_fail (file && file->sig == VFS_SIG);
00303
00304 if (verbose)
00305 logger ("VFS: <%p> rewind\n", file);
00306
00307 file->base->vfs_rewind_impl(file);
00308 }
00309
00316 EXPORT int64_t
00317 vfs_ftell(VFSFile * file)
00318 {
00319 g_return_val_if_fail (file && file->sig == VFS_SIG, -1);
00320
00321 int64_t told = file->base->vfs_ftell_impl (file);
00322
00323 if (verbose)
00324 logger ("VFS: <%p> tell = %"PRId64"\n", file, told);
00325
00326 return told;
00327 }
00328
00335 EXPORT bool_t
00336 vfs_feof(VFSFile * file)
00337 {
00338 g_return_val_if_fail (file && file->sig == VFS_SIG, TRUE);
00339
00340 bool_t eof = file->base->vfs_feof_impl (file);
00341
00342 if (verbose)
00343 logger ("VFS: <%p> eof = %s\n", file, eof ? "yes" : "no");
00344
00345 return eof;
00346 }
00347
00355 EXPORT int vfs_ftruncate (VFSFile * file, int64_t length)
00356 {
00357 g_return_val_if_fail (file && file->sig == VFS_SIG, -1);
00358
00359 if (verbose)
00360 logger ("VFS: <%p> truncate to %"PRId64"\n", file, length);
00361
00362 return file->base->vfs_ftruncate_impl(file, length);
00363 }
00364
00371 EXPORT int64_t vfs_fsize (VFSFile * file)
00372 {
00373 g_return_val_if_fail (file && file->sig == VFS_SIG, -1);
00374
00375 int64_t size = file->base->vfs_fsize_impl (file);
00376
00377 if (verbose)
00378 logger ("VFS: <%p> size = %"PRId64"\n", file, size);
00379
00380 return size;
00381 }
00382
00390 EXPORT char *
00391 vfs_get_metadata(VFSFile * file, const char * field)
00392 {
00393 if (file == NULL)
00394 return NULL;
00395
00396 if (file->base->vfs_get_metadata_impl)
00397 return file->base->vfs_get_metadata_impl(file, field);
00398 return NULL;
00399 }
00400
00408 EXPORT bool_t
00409 vfs_file_test(const char * path, int test)
00410 {
00411 if (strncmp (path, "file://", 7))
00412 return FALSE;
00413
00414 char * path2 = uri_to_filename (path);
00415
00416 if (path2 == NULL)
00417 path2 = g_strdup(path);
00418
00419 bool_t ret = g_file_test (path2, test);
00420
00421 g_free(path2);
00422
00423 return ret;
00424 }
00425
00432 EXPORT bool_t
00433 vfs_is_writeable(const char * path)
00434 {
00435 struct stat info;
00436 char * realfn = uri_to_filename (path);
00437
00438 if (stat(realfn, &info) == -1)
00439 return FALSE;
00440
00441 g_free(realfn);
00442
00443 return (info.st_mode & S_IWUSR);
00444 }
00445
00452 EXPORT bool_t vfs_is_remote (const char * path)
00453 {
00454 return strncmp (path, "file://", 7) ? TRUE : FALSE;
00455 }
00456
00463 EXPORT bool_t vfs_is_streaming (VFSFile * file)
00464 {
00465 return (vfs_fsize (file) < 0);
00466 }