Audacious  $Id:Doxyfile42802007-03-2104:39:00Znenolod$
vfs.c
Go to the documentation of this file.
1 /*
2  * vfs.c
3  * Copyright 2006-2011 William Pitcock, Daniel Barkalow, Ralf Ertzinger,
4  * Yoshiki Yazawa, Matti Hämäläinen, and John Lindgren
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions are met:
8  *
9  * 1. Redistributions of source code must retain the above copyright notice,
10  * this list of conditions, and the following disclaimer.
11  *
12  * 2. Redistributions in binary form must reproduce the above copyright notice,
13  * this list of conditions, and the following disclaimer in the documentation
14  * provided with the distribution.
15  *
16  * This software is provided "as is" and without any warranty, express or
17  * implied. In no event shall the authors be liable for any damages arising from
18  * the use of this software.
19  */
20 
21 #include <glib.h>
22 #include <inttypes.h>
23 
24 #include "vfs.h"
25 #include "audstrings.h"
26 #include <stdio.h>
27 #include <unistd.h>
28 #include <sys/stat.h>
29 #include <sys/types.h>
30 #include <string.h>
31 
32 #define VFS_SIG ('V' | ('F' << 8) | ('S' << 16))
33 
39 struct _VFSFile {
40  char * uri;
42  void * handle;
43  int sig;
44 };
45 
46 /* Audacious core provides us with a function that looks up a VFS transport for
47  * a given URI scheme. Since this function will load plugins as needed, it can
48  * only be called from the main thread. When VFS is used from parallel threads,
49  * vfs_prepare must be called from the main thread to look up any needed
50  * transports beforehand. */
51 
52 static VFSConstructor * (* lookup_func) (const char * scheme) = NULL;
53 
54 EXPORT void vfs_set_lookup_func (VFSConstructor * (* func) (const char * scheme))
55 {
56  lookup_func = func;
57 }
58 
59 static bool_t verbose = FALSE;
60 
61 EXPORT void vfs_set_verbose (bool_t set)
62 {
63  verbose = set;
64 }
65 
66 static void logger (const char * format, ...)
67 {
68  static char last[256] = "";
69  static int repeated = 0;
70 
71  char buf[256];
72 
73  va_list args;
74  va_start (args, format);
75  vsnprintf (buf, sizeof buf, format, args);
76  va_end (args);
77 
78  if (! strcmp (buf, last))
79  repeated ++;
80  else
81  {
82  if (repeated)
83  {
84  printf ("VFS: (last message repeated %d times)\n", repeated);
85  repeated = 0;
86  }
87 
88  fputs (buf, stdout);
89  strcpy (last, buf);
90  }
91 }
92 
93 EXPORT VFSFile * vfs_new (const char * path, VFSConstructor * vtable, void * handle)
94 {
95  VFSFile * file = g_slice_new (VFSFile);
96  file->uri = str_get (path);
97  file->base = vtable;
98  file->handle = handle;
99  file->sig = VFS_SIG;
100  return file;
101 }
102 
103 EXPORT const char * vfs_get_filename (VFSFile * file)
104 {
105  return file->uri;
106 }
107 
108 EXPORT void * vfs_get_handle (VFSFile * file)
109 {
110  return file->handle;
111 }
112 
121 EXPORT VFSFile *
122 vfs_fopen(const char * path,
123  const char * mode)
124 {
125  g_return_val_if_fail (path && mode, NULL);
126  g_return_val_if_fail (lookup_func, NULL);
127 
128  const char * s = strstr (path, "://");
129  g_return_val_if_fail (s, NULL);
130  char scheme[s - path + 1];
131  strncpy (scheme, path, s - path);
132  scheme[s - path] = 0;
133 
134  VFSConstructor * vtable = lookup_func (scheme);
135  if (! vtable)
136  return NULL;
137 
138  const gchar * sub;
139  uri_parse (path, NULL, NULL, & sub, NULL);
140 
141  gchar buf[sub - path + 1];
142  memcpy (buf, path, sub - path);
143  buf[sub - path] = 0;
144 
145  void * handle = vtable->vfs_fopen_impl (buf, mode);
146  if (! handle)
147  return NULL;
148 
149  VFSFile * file = vfs_new (path, vtable, handle);
150 
151  if (verbose)
152  logger ("VFS: <%p> open (mode %s) %s\n", file, mode, path);
153 
154  return file;
155 }
156 
163 EXPORT int
165 {
166  g_return_val_if_fail (file && file->sig == VFS_SIG, -1);
167 
168  if (verbose)
169  logger ("VFS: <%p> close\n", file);
170 
171  int ret = 0;
172 
173  if (file->base->vfs_fclose_impl(file) != 0)
174  ret = -1;
175 
176  str_unref (file->uri);
177 
178  memset (file, 0, sizeof (VFSFile));
179  g_slice_free (VFSFile, file);
180 
181  return ret;
182 }
183 
193 EXPORT int64_t vfs_fread (void * ptr, int64_t size, int64_t nmemb, VFSFile * file)
194 {
195  g_return_val_if_fail (file && file->sig == VFS_SIG, 0);
196 
197  int64_t readed = file->base->vfs_fread_impl (ptr, size, nmemb, file);
198 
199 /* if (verbose)
200  logger ("VFS: <%p> read %"PRId64" elements of size %"PRId64" = "
201  "%"PRId64"\n", file, nmemb, size, readed); */
202 
203  return readed;
204 }
205 
215 EXPORT int64_t vfs_fwrite (const void * ptr, int64_t size, int64_t nmemb, VFSFile * file)
216 {
217  g_return_val_if_fail (file && file->sig == VFS_SIG, 0);
218 
219  int64_t written = file->base->vfs_fwrite_impl (ptr, size, nmemb, file);
220 
221  if (verbose)
222  logger ("VFS: <%p> write %"PRId64" elements of size %"PRId64" = "
223  "%"PRId64"\n", file, nmemb, size, written);
224 
225  return written;
226 }
227 
234 EXPORT int
236 {
237  g_return_val_if_fail (file && file->sig == VFS_SIG, EOF);
238 
239  if (verbose)
240  logger ("VFS: <%p> getc\n", file);
241 
242  return file->base->vfs_getc_impl(file);
243 }
244 
252 EXPORT int
253 vfs_ungetc(int c, VFSFile *file)
254 {
255  g_return_val_if_fail (file && file->sig == VFS_SIG, EOF);
256 
257  if (verbose)
258  logger ("VFS: <%p> ungetc\n", file);
259 
260  return file->base->vfs_ungetc_impl(c, file);
261 }
262 
276 EXPORT int
278  int64_t offset,
279  int whence)
280 {
281  g_return_val_if_fail (file && file->sig == VFS_SIG, -1);
282 
283  if (verbose)
284  logger ("VFS: <%p> seek to %"PRId64" from %s\n", file, offset, whence ==
285  SEEK_CUR ? "current" : whence == SEEK_SET ? "beginning" : whence ==
286  SEEK_END ? "end" : "invalid");
287 
288  return file->base->vfs_fseek_impl(file, offset, whence);
289 }
290 
296 EXPORT void
298 {
299  g_return_if_fail (file && file->sig == VFS_SIG);
300 
301  if (verbose)
302  logger ("VFS: <%p> rewind\n", file);
303 
304  file->base->vfs_rewind_impl(file);
305 }
306 
313 EXPORT int64_t
315 {
316  g_return_val_if_fail (file && file->sig == VFS_SIG, -1);
317 
318  int64_t told = file->base->vfs_ftell_impl (file);
319 
320  if (verbose)
321  logger ("VFS: <%p> tell = %"PRId64"\n", file, told);
322 
323  return told;
324 }
325 
332 EXPORT bool_t
334 {
335  g_return_val_if_fail (file && file->sig == VFS_SIG, TRUE);
336 
337  bool_t eof = file->base->vfs_feof_impl (file);
338 
339  if (verbose)
340  logger ("VFS: <%p> eof = %s\n", file, eof ? "yes" : "no");
341 
342  return eof;
343 }
344 
352 EXPORT int vfs_ftruncate (VFSFile * file, int64_t length)
353 {
354  g_return_val_if_fail (file && file->sig == VFS_SIG, -1);
355 
356  if (verbose)
357  logger ("VFS: <%p> truncate to %"PRId64"\n", file, length);
358 
359  return file->base->vfs_ftruncate_impl(file, length);
360 }
361 
368 EXPORT int64_t vfs_fsize (VFSFile * file)
369 {
370  g_return_val_if_fail (file && file->sig == VFS_SIG, -1);
371 
372  int64_t size = file->base->vfs_fsize_impl (file);
373 
374  if (verbose)
375  logger ("VFS: <%p> size = %"PRId64"\n", file, size);
376 
377  return size;
378 }
379 
387 EXPORT char *
388 vfs_get_metadata(VFSFile * file, const char * field)
389 {
390  if (file == NULL)
391  return NULL;
392 
393  if (file->base->vfs_get_metadata_impl)
394  return file->base->vfs_get_metadata_impl(file, field);
395  return NULL;
396 }
397 
405 EXPORT bool_t
406 vfs_file_test(const char * path, int test)
407 {
408  if (strncmp (path, "file://", 7))
409  return FALSE; /* only local files are handled */
410 
411  char * path2 = uri_to_filename (path);
412  if (! path2)
413  return FALSE;
414 
415 #ifdef S_ISLNK
416  if (test & VFS_IS_SYMLINK)
417  {
418  struct stat st;
419  if (lstat (path2, & st) < 0)
420  return FALSE;
421 
422  if (S_ISLNK (st.st_mode))
423  test &= ~VFS_IS_SYMLINK;
424  }
425 #endif
426 
428  {
429  struct stat st;
430  if (stat (path2, & st) < 0)
431  return FALSE;
432 
433  if (S_ISREG (st.st_mode))
434  test &= ~VFS_IS_REGULAR;
435  if (S_ISDIR (st.st_mode))
436  test &= ~VFS_IS_DIR;
437  if (st.st_mode & S_IXUSR)
438  test &= ~VFS_IS_EXECUTABLE;
439 
440  test &= ~VFS_EXISTS;
441  }
442 
443  g_free (path2);
444 
445  return ! test;
446 }
447 
454 EXPORT bool_t
455 vfs_is_writeable(const char * path)
456 {
457  struct stat info;
458  char * realfn = uri_to_filename (path);
459 
460  if (stat(realfn, &info) == -1)
461  return FALSE;
462 
463  g_free(realfn);
464 
465  return (info.st_mode & S_IWUSR);
466 }
467 
474 EXPORT bool_t vfs_is_remote (const char * path)
475 {
476  return strncmp (path, "file://", 7) ? TRUE : FALSE;
477 }
478 
486 {
487  return (vfs_fsize (file) < 0);
488 }
static VFSConstructor *(* lookup_func)(const char *scheme)
Definition: vfs.c:52
EXPORT int64_t vfs_fwrite(const void *ptr, int64_t size, int64_t nmemb, VFSFile *file)
Writes to a VFS stream.
Definition: vfs.c:215
#define VFS_SIG
Definition: vfs.c:32
EXPORT bool_t vfs_feof(VFSFile *file)
Returns whether or not the VFS stream has reached EOF.
Definition: vfs.c:333
#define VFS_EXISTS
Definition: vfs.h:39
EXPORT int64_t vfs_ftell(VFSFile *file)
Returns the current position in the VFS stream&#39;s buffer.
Definition: vfs.c:314
EXPORT char * uri_to_filename(const char *uri)
Definition: audstrings.c:172
Main API header for accessing Audacious VFS functionality.
EXPORT int vfs_fclose(VFSFile *file)
Closes a VFS stream and destroys a VFSFile object.
Definition: vfs.c:164
EXPORT bool_t vfs_is_streaming(VFSFile *file)
Tests if a file is associated to streaming.
Definition: vfs.c:485
void * handle
Opaque data used by the transport plugins.
Definition: vfs.c:42
EXPORT VFSFile * vfs_new(const char *path, VFSConstructor *vtable, void *handle)
Definition: vfs.c:93
int format
Definition: audio.c:132
char * uri
The URI of the stream.
Definition: vfs.c:40
#define VFS_IS_SYMLINK
Definition: vfs.h:36
EXPORT int vfs_ftruncate(VFSFile *file, int64_t length)
Truncates a VFS stream to a certain size.
Definition: vfs.c:352
#define FALSE
Definition: core.h:37
Index Index bool_t
Definition: playlist-api.h:122
EXPORT const char * vfs_get_filename(VFSFile *file)
Definition: vfs.c:103
EXPORT int vfs_fseek(VFSFile *file, int64_t offset, int whence)
Performs a seek in given VFS stream.
Definition: vfs.c:277
static void logger(const char *format,...)
Definition: vfs.c:66
#define NULL
Definition: core.h:29
int sig
Used to detect invalid or twice-closed objects.
Definition: vfs.c:43
EXPORT int64_t vfs_fread(void *ptr, int64_t size, int64_t nmemb, VFSFile *file)
Reads from a VFS stream.
Definition: vfs.c:193
static bool_t verbose
Definition: vfs.c:59
EXPORT void vfs_set_lookup_func(VFSConstructor *(*func)(const char *scheme))
Definition: vfs.c:54
#define TRUE
Definition: core.h:39
EXPORT void * vfs_get_handle(VFSFile *file)
Definition: vfs.c:108
EXPORT int vfs_ungetc(int c, VFSFile *file)
Pushes a character back to the VFS stream.
Definition: vfs.c:253
func
Definition: plugins-api.h:41
EXPORT bool_t vfs_is_writeable(const char *path)
Tests if a file is writeable.
Definition: vfs.c:455
void str_unref(char *str)
Definition: strpool.c:131
#define VFS_IS_REGULAR
Definition: vfs.h:35
EXPORT VFSFile * vfs_fopen(const char *path, const char *mode)
Opens a stream from a VFS transport using one of the registered VFSConstructor handlers.
Definition: vfs.c:122
EXPORT void uri_parse(const char *uri, const char **base_p, const char **ext_p, const char **sub_p, int *isub_p)
Definition: audstrings.c:223
#define VFS_IS_DIR
Definition: vfs.h:37
EXPORT char * vfs_get_metadata(VFSFile *file, const char *field)
Returns metadata about the stream.
Definition: vfs.c:388
VFSFile objects describe an opened VFS stream, basically being similar in purpose as stdio FILE ...
Definition: vfs.c:39
EXPORT bool_t vfs_is_remote(const char *path)
Tests if a path is remote uri.
Definition: vfs.c:474
EXPORT void vfs_set_verbose(bool_t set)
Definition: vfs.c:61
EXPORT void vfs_rewind(VFSFile *file)
Rewinds a VFS stream.
Definition: vfs.c:297
EXPORT int vfs_getc(VFSFile *file)
Reads a character from a VFS stream.
Definition: vfs.c:235
struct @17::@18::@20 s
char * str_get(const char *str)
Definition: strpool.c:68
VFSConstructor * base
The base vtable used for VFS functions.
Definition: vfs.c:41
EXPORT int64_t vfs_fsize(VFSFile *file)
Returns size of the file.
Definition: vfs.c:368
EXPORT bool_t vfs_file_test(const char *path, int test)
Wrapper for g_file_test().
Definition: vfs.c:406
#define VFS_IS_EXECUTABLE
Definition: vfs.h:38