Permalink
Browse files

o add documentation

o add a tagging interface to make things more type-robust.
  • Loading branch information...
1 parent 73093dc commit e9c07dd6928b7499ebc3b493bdbb772016c41013 @hzeller committed Sep 9, 2012
Showing with 166 additions and 11 deletions.
  1. +4 −3 Makefile
  2. +104 −0 convolver.cc
  3. +43 −0 filter-interface.h
  4. +15 −8 fuse-convolve.c
View
@@ -1,8 +1,9 @@
CFLAGS=-D_FILE_OFFSET_BITS=64 -Wall
+CXXFLAGS=-Wall
LDFLAGS=-lfuse
-fuse-convolve: fuse-convolve.c
- gcc $(CFLAGS) $< -o $@ $(LDFLAGS)
+fuse-convolve: fuse-convolve.o convolver.o
+ g++ $(CXXFLAGS) $^ -o $@ $(LDFLAGS)
clean:
- rm fuse-convolve
+ rm fuse-convolve *.o
View
@@ -0,0 +1,104 @@
+// Copyright (C) 2012 Henner Zeller <h.zeller@acm.org>
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <strings.h>
+#include <unistd.h>
+
+#include "filter-interface.h"
+
+namespace {
+class FileFilter : public filter_interface_t {
+public:
+ // Returns bytes read or a negative value indicating a negative errno.
+ virtual int Read(char *buf, size_t size, off_t offset) = 0;
+ virtual int Close() = 0;
+ virtual ~FileFilter() {}
+};
+
+// Very simple filter that just passes the original file through.
+class PassThroughFilter : public FileFilter {
+public:
+ PassThroughFilter(int filedes, const char *path) : filedes_(filedes) {
+ fprintf(stderr, "Creating PassThrough filter for '%s'\n", path);
+ }
+
+ virtual int Read(char *buf, size_t size, off_t offset) {
+ const int result = pread(filedes_, buf, size, offset);
+ return result == -1 ? -errno : result;
+ }
+
+ virtual int Close() {
+ return close(filedes_) == -1 ? -errno : 0;
+ }
+
+private:
+ const int filedes_;
+};
+
+class WavFilter : public FileFilter {
+public:
+ WavFilter(int filedes, const char *path) : filedes_(filedes) {
+ fprintf(stderr, "Creating Wav filter for '%s'\n", path);
+ }
+
+ virtual int Read(char *buf, size_t size, off_t offset) {
+ const int result = pread(filedes_, buf, size, offset);
+ return result == -1 ? -errno : result;
+ }
+
+ virtual int Close() {
+ return close(filedes_) == -1 ? -errno : 0;
+ }
+
+private:
+ const int filedes_;
+};
+} // namespace
+
+// We do a very simple decision which filter to apply by looking at the suffix.
+bool HasSuffixString (const char *str, const char *suffix) {
+ if (!str || !suffix)
+ return false;
+ size_t str_len = strlen(str);
+ size_t suffix_len = strlen(suffix);
+ if (suffix_len > str_len)
+ return false;
+ return strncasecmp(str + str_len - suffix_len, suffix, suffix_len) == 0;
+}
+
+// Implementation of the C functions in filter-interface.h
+struct filter_interface_t *create_filter(int filedes, const char *path) {
+ if (HasSuffixString(path, ".wav")) {
+ return new WavFilter(filedes, path);
+ }
+
+ // Everything other file is just passed through as is.
+ return new PassThroughFilter(filedes, path);
+}
+
+int read_from_filter(struct filter_interface_t *filter,
+ char *buf, size_t size, off_t offset) {
+ return reinterpret_cast<FileFilter*>(filter)->Read(buf, size, offset);
+}
+
+int close_filter(struct filter_interface_t *filter) {
+ FileFilter *file_filter = reinterpret_cast<FileFilter*>(filter);
+ int result = file_filter->Close();
+ delete file_filter;
+ return result;
+}
View
@@ -0,0 +1,43 @@
+// Copyright (C) 2012 Henner Zeller <h.zeller@acm.org>
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+// Simple interface to hook the (pure C) fuse-convolve code into some
+// implementation of the filter (which we choose to do with C++).
+
+#include <unistd.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct filter_interface_t {};
+
+// Create a new filter given the open filedescriptor and the path. Returns
+// that filter in an opaque FilterInterface*
+struct filter_interface_t *create_filter(int filedes, const char *path);
+
+// Read from the given filter at the file-offset "offset, up to "size" bytes
+// into "buffer". Returns number of bytes read or a negative errno value.
+int read_from_filter(struct filter_interface_t *filter,
+ char *buffer, size_t size, off_t offset);
+
+// At the end of the operation, close filter. Return 0 on success or negative
+// errno value on failure.
+int close_filter(struct filter_interface_t *filter);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
View
@@ -13,6 +13,9 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
+// This is a pure C implementation, providing basic file operations and passing
+// actual reading to a filter aquired using the functions in filter-interface.h
+
// Use latest version.
#define FUSE_USE_VERSION 26
@@ -28,6 +31,8 @@
#include <limits.h>
#include <stdlib.h>
+#include "filter-interface.h"
+
// Configuration for fuse convolver filesystem.
static struct {
const char *config_dir;
@@ -92,30 +97,32 @@ static int fuseconv_readlink(const char *path, char *buf, size_t size) {
static int fuseconv_open(const char *path, struct fuse_file_info *fi) {
fprintf(stderr, "HZ ===== open('%s')\n", path);
char path_buf[PATH_MAX];
- const int result = open(assemble_orig_path(path_buf, path), fi->flags);
+ const int fd = open(assemble_orig_path(path_buf, path), fi->flags);
// We want to return partial reads. That way, we can separate reading the
// ID3-tags from the stream.
// In order to return partical content, we need to set the direct_io.
fi->direct_io = 1;
- if (result == -1)
+ if (fd == -1)
return -errno;
- fi->fh = result;
+
+ // The file-handle has the neat property to be 64 bit - so we can actually
+ // store a pointer in there :) (Yay, someone was thinking while developing
+ // that API).
+ fi->fh = (uint64_t) create_filter(fd, path);
return 0;
}
static int fuseconv_read(const char *path, char *buf, size_t size, off_t offset,
struct fuse_file_info *fi) {
- const int result = pread(fi->fh, buf, size, offset);
- if (result == -1)
- return -errno;
- return result;
+ return read_from_filter((struct filter_interface_t*)fi->fh,
+ buf, size, offset);
}
static int fuseconv_release(const char *path, struct fuse_file_info *fi) {
fprintf(stderr, "HZ ===== close('%s')\n", path);
- return close(fi->fh) == -1 ? -errno : 0;
+ return close_filter((struct filter_interface_t*) fi->fh);
}
static struct fuse_operations fuseconv_operations = {

0 comments on commit e9c07dd

Please sign in to comment.