vfs: Add filo like vfs layer

Signed-off-by: Thomas Heijligen <src@posteo.de>
diff --git a/src/main.c b/src/main.c
index d1939ee..ee3095c 100644
--- a/src/main.c
+++ b/src/main.c
@@ -3,18 +3,7 @@
 #include <getopt.h>
 
 #include "blockdev.h"
-
-struct fsys_entry {
-	char *name;
-	int (*mount_func) (void);
-	int (*read_func) (char *buf, int len); // read from open file
-	int (*dir_func) (char *dirname); // open file
-	int (*close_func) (void);
-} fsys_table[] = {
-	{ "dummy", NULL, NULL, NULL, NULL},
-};
-
-static const size_t fsys_table_length = sizeof(fsys_table) / sizeof(struct fsys_entry);
+#include "vfs.h"
 
 struct program_options {
 	char *devname;
diff --git a/src/vfs.c b/src/vfs.c
new file mode 100644
index 0000000..f73edb2
--- /dev/null
+++ b/src/vfs.c
@@ -0,0 +1,92 @@
+#include <stdio.h>
+#include <string.h>
+
+#include "vfs.h"
+#include "blockdev.h"
+
+struct fsys_entry {
+	char *name;
+	int (*mount_func) (void);
+	int (*read_func) (char *buf, int len);
+	int (*dir_func) (char *dirname);
+	int (*close_func) (void);
+} static const fsys_table[] = {
+	{ "dummy", NULL, NULL, NULL, NULL },
+};
+
+static const size_t fsys_table_length = sizeof(fsys_table) / sizeof(fsys_table[0]);
+
+const struct fsys_entry *fsys = NULL;
+int filemax;
+int filepos;
+
+int mount_fs(char *fs_name)
+{
+	for (size_t i = 0; i < fsys_table_length; i++) {
+		if ((!fs_name || !strcmp(fsys_table[i].name, fs_name)) && fsys_table[i].mount_func()) {
+			fsys = &fsys_table[i];
+			return 1;
+		}
+	}
+
+	if (fs_name)
+		fprintf(stderr, "mount_fs: Faild to mount filesystem: %s.\n", fs_name);
+	else
+		fprintf(stderr, "mount_fs: No matching filesystem found.\n");
+	return 0;
+}
+
+
+
+
+int file_open(const char *filename)
+{
+	if (filename && filename[0] != '/') {
+		fprintf(stderr, "file_open: filename musst start with '/',"
+			"no support for device identifier");
+		return 0;
+	}
+	
+	if (!fsys) {
+		fprintf(stderr, "file_open: no open filesystem.\n");
+		return 0;
+	}
+	char *path = strdup(filename);
+	if (!fsys->dir_func(path)) {
+		fprintf(stderr, "file_open: file not found '%s'.\n", filename);
+		return 0;
+	}
+	filepos = 0;
+	return 1;
+}
+
+int file_read(void *buf, unsigned long len)
+{
+	if (filepos < 0 || filepos > filemax)
+		filepos = filemax;
+
+	if (len < 0 || len > filemax - filepos)
+		len = filemax - filepos;
+	return fsys->read_func(buf, len);
+}
+
+unsigned long file_seek(unsigned long offset)
+{
+	if (offset <= filemax)
+		filepos = offset;
+	else
+		filepos = filemax;
+	return filepos;
+}
+
+unsigned long file_size(void)
+{
+	return filemax;
+}
+
+void file_close(void)
+{
+	// In contrast to filo the device is not closed here
+	// devclose();
+}
+
diff --git a/src/vfs.h b/src/vfs.h
new file mode 100644
index 0000000..865b73b
--- /dev/null
+++ b/src/vfs.h
@@ -0,0 +1,31 @@
+#ifndef VFS_H
+#define VFS_H
+
+/** mount_fs
+ * @param fs_name  Name of filesystem or NULL for auto selection
+ * @return 1 on success, 0 on failure
+ */
+int mount_fs(char *fs_name);
+
+/** file_open
+ * @param filename
+ * @return 1 on success, 0 on failure
+ */
+int file_open(const char *filename);
+
+/** file_read
+ * @param buf
+ * @param len  Size of buffer / bytes to read
+ * @return     Number of bytes read
+ */
+int file_read(void *buf, unsigned long len);
+
+unsigned long file_seek(unsigned long offset);
+/**file_size
+ * @return  Filesize in bytes
+ */
+unsigned long file_size(void);
+
+void file_close(void);
+
+#endif /* VFS_H */