2 * gstfs - a gstreamer filesystem
16 #define min(a,b) ((a)<(b)?(a):(b))
17 #define max(a,b) ((a)>(b)?(a):(b))
19 static GHashTable
*file_cache
;
20 static char *get_source_path(const char *filename
);
22 char *source_mount
= "ogg";
23 char *src_ext
= "ogg", *dest_ext
= "mp3";
25 // This stuff is stored into a hash table blah blah
28 char *filename
; /* hash key */
29 char *source_filename
; /* filename in other mount */
30 size_t len
; /* size of file */
31 size_t alloc_len
; /* allocated size of buf */
32 char *buf
; /* completely converted file */
35 struct file_info
*new_file_info(const char *filename
)
39 fi
= calloc(1, sizeof(struct file_info
));
40 fi
->filename
= strdup(filename
);
41 fi
->source_filename
= get_source_path(filename
);
45 char *replace_ext(char *filename
, char *search
, char *replace
)
47 char *ext
= strrchr(filename
, '.');
48 if (ext
&& strcmp(ext
+1, search
) == 0)
51 filename
= g_strconcat(filename
, replace
, NULL
);
56 int is_target_type(const char *filename
)
58 char *ext
= strrchr(filename
, '.');
59 return (ext
&& strcmp(ext
+1, dest_ext
) == 0);
63 * If the path represents a file in the mirror filesystem, then
64 * look for it in the cache. If not, create a new file info.
66 * If it isn't a mirror file, return NULL.
68 static struct file_info
*gstfs_lookup(const char *path
)
70 struct file_info
*ret
;
72 if (!is_target_type(path
))
75 ret
= g_hash_table_lookup(file_cache
, path
);
78 ret
= new_file_info(path
);
82 g_hash_table_replace(file_cache
, ret
->filename
, ret
);
88 static char *get_source_path(const char *filename
)
92 printf("filename: %s\n", filename
);
94 source
= g_strdup_printf("%s%s", source_mount
, filename
);
95 source
= replace_ext(source
, dest_ext
, src_ext
);
96 printf("-> source filename: %s\n", source
);
100 int gstfs_statfs(const char *path
, struct statvfs
*buf
)
104 source_path
= get_source_path(path
);
105 if (statvfs(path
, buf
))
112 int gstfs_getattr(const char *path
, struct stat
*stbuf
)
116 struct file_info
*converted
;
118 source_path
= get_source_path(path
);
120 printf("in gettattr, foo\n");
121 if (stat(source_path
, stbuf
))
123 else if ((converted
= gstfs_lookup(path
)))
125 stbuf
->st_size
= converted
->len
;
132 static int read_cb(char *buf
, size_t size
, void *data
)
134 struct file_info
*info
= (struct file_info
*) data
;
136 size_t newsz
= info
->len
+ size
;
138 if (info
->alloc_len
< newsz
)
140 info
->alloc_len
= max(info
->alloc_len
* 2, newsz
);
141 info
->buf
= realloc(info
->buf
, info
->alloc_len
);
146 memcpy(&info
->buf
[info
->len
], buf
, size
);
151 int gstfs_read(const char *path
, char *buf
, size_t size
, off_t offset
,
152 struct fuse_file_info
*fi
)
154 struct file_info
*info
= gstfs_lookup(path
);
161 transcode(info
->source_filename
, read_cb
, info
);
163 if (info
->len
<= offset
)
166 count
= min(info
->len
- offset
, size
);
168 memcpy(buf
, &info
->buf
[offset
], count
);
172 int gstfs_open(const char *path
, struct fuse_file_info
*fi
)
174 struct file_info
*info
= gstfs_lookup(path
);
182 * readdir - copy all entries from source mount
184 int gstfs_readdir(const char *path
, void *buf
, fuse_fill_dir_t filler
,
185 off_t offset
, struct fuse_file_info
*fi
)
187 struct dirent
*dirent
;
191 source_path
= get_source_path(path
);
192 dir
= opendir(source_path
);
197 while ((dirent
= readdir(dir
)))
199 char *s
= g_strdup(dirent
->d_name
);
200 s
= replace_ext(s
, src_ext
, dest_ext
);
201 filler(buf
, s
, NULL
, 0);
210 static struct fuse_operations gstfs_ops
= {
211 .readdir
= gstfs_readdir
,
212 .statfs
= gstfs_statfs
,
213 .getattr
= gstfs_getattr
,
218 int main(int argc
, char *argv
[])
220 gst_init (&argc
, &argv
);
221 file_cache
= g_hash_table_new(g_str_hash
, g_str_equal
);
223 return fuse_main(argc
, argv
, &gstfs_ops
, NULL
);