summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorUlf Lilleengen <lulf@carrot.studby.ntnu.no>2008-08-09 16:14:53 +0200
committerUlf Lilleengen <lulf@carrot.studby.ntnu.no>2008-08-09 16:14:53 +0200
commit64e1a2a9e5cc03d234fa4cf1a3577dcf84e5e22e (patch)
tree914f4fd2e17571a65b66a999331ec2c9be288aa3
parentcfa01e2eded5e91a9272d1578e48540199c8b2d8 (diff)
- Add support for reading a file in /Tracks directory.
- Make use of the generic lookup framework to create functions which open and stat files. - Make getattr a bit generic and use the lookup stuff.
-rw-r--r--include/mp3fs.h16
-rw-r--r--src/mp3_subr.c29
-rwxr-xr-xsrc/mp3_vnops.c135
3 files changed, 151 insertions, 29 deletions
diff --git a/include/mp3fs.h b/include/mp3fs.h
index aac7435..4966aee 100644
--- a/include/mp3fs.h
+++ b/include/mp3fs.h
@@ -17,18 +17,32 @@ void traverse_hierarchy(char *, traverse_fn_t);
traverse_fn_t mp3_scan;
/*
- * Data passed to mp3_lookup.
+ * Data passed to mp3_lookup_list
*/
struct filler_data {
void *buf;
fuse_fill_dir_t filler;
};
+/*
+ * Data passed to mp3_lookup_open
+ */
+struct file_data {
+ int fd;
+ int found;
+};
+
#define LIST_DATATYPE_STRING 1
#define LIST_DATATYPE_INT 2
typedef void lookup_fn_t(void *, const char *);
+/* Lookup function listing each row. */
lookup_fn_t mp3_lookup_list;
+/* Lookup function opening the first file match. */
+lookup_fn_t mp3_lookup_open;
+/* Lookup function stat'ing a file. */
+lookup_fn_t mp3_lookup_stat;
+
struct lookuphandle;
struct lookuphandle *mp3_lookup_start(int, void *, lookup_fn_t *, const char *);
diff --git a/src/mp3_subr.c b/src/mp3_subr.c
index e6a0ba6..814888d 100644
--- a/src/mp3_subr.c
+++ b/src/mp3_subr.c
@@ -496,3 +496,32 @@ mp3_lookup_list(void *data, const char *str)
fd = (struct filler_data *)data;
fd->filler(fd->buf, str, NULL, 0);
}
+
+/*
+ * Lookup a file and open it if found.
+ */
+void
+mp3_lookup_open(void *data, const char *str)
+{
+ struct file_data *fd;
+
+ fd = (struct file_data *)data;
+ if (!fd->found) {
+ fd->fd = open(str, O_RDONLY);
+ fd->found = 1;
+ }
+}
+
+/*
+ * Stat a file.
+ * XXX: watch out for duplicates, we might stat more than once.
+ */
+void
+mp3_lookup_stat(void *data, const char *str)
+{
+ struct stat *st;
+
+ st = (struct stat *)data;
+ if (stat(str, st) < 0)
+ return;
+}
diff --git a/src/mp3_vnops.c b/src/mp3_vnops.c
index fd90883..b532556 100755
--- a/src/mp3_vnops.c
+++ b/src/mp3_vnops.c
@@ -10,6 +10,8 @@
#include <dirent.h>
#include <fuse.h>
#include <sys/param.h>
+#include <sys/uio.h>
+#include <unistd.h>
#include <tag_c.h>
#include <mp3fs.h>
@@ -20,37 +22,52 @@ char *logpath = "/home/lulf/dev/mp3fs/mp3fs.log";
static int mp3_getattr (const char *path, struct stat *stbuf)
{
+ struct lookuphandle *lh;
+ char *title;
int tokens;
+
memset (stbuf, 0, sizeof (struct stat));
if (strcmp (path, "/") == 0) {
stbuf->st_mode = S_IFDIR | 0755;
stbuf->st_nlink = 2;
return 0;
}
- if (strcmp(path, "/Artists") == 0 ||
- strcmp(path, "/Genres") == 0 ||
- strcmp(path, "/Tracks") == 0 ||
- strcmp(path, "/Albums") == 0) {
- stbuf->st_mode = S_IFDIR | 0444;
- stbuf->st_nlink = 1;
- stbuf->st_size = 12;
- return 0;
- }
- tokens = mp3_numtoken(path);
- if (tokens == 2) {
- stbuf->st_mode = S_IFDIR | 0444;
- stbuf->st_nlink = 1;
- stbuf->st_size = 12;
- return 0;
- } else if (tokens == 3) {
- stbuf->st_mode = S_IFDIR | 0444;
- stbuf->st_nlink = 1;
- stbuf->st_size = 12;
- return 0;
- } else if (tokens == 4) {
- stbuf->st_mode = S_IFREG | 0644;
- stbuf->st_nlink = 1;
- stbuf->st_size = 512;
+ if (strncmp(path, "/Artists", 8) == 0 ||
+ strncmp(path, "/Genres", 7) == 0 ||
+ strncmp(path, "/Albums", 7) == 0) {
+ tokens = mp3_numtoken(path);
+ switch (tokens) {
+ case 1:
+ case 2:
+ case 3:
+ stbuf->st_mode = S_IFDIR | 0444;
+ stbuf->st_nlink = 1;
+ stbuf->st_size = 12;
+ return 0;
+ case 4:
+ stbuf->st_mode = S_IFREG | 0644;
+ stbuf->st_nlink = 1;
+ stbuf->st_size = 512;
+ return 0;
+ }
+ } else if (strncmp(path, "/Tracks", 7) == 0) {
+ tokens = mp3_numtoken(path);
+ switch (tokens) {
+ case 1:
+ stbuf->st_mode = S_IFDIR | 0444;
+ stbuf->st_nlink = 1;
+ stbuf->st_size = 12;
+ return 0;
+ case 2:
+ title = mp3_gettoken(path, 2);
+ if (title == NULL)
+ break;
+ lh = mp3_lookup_start(0, stbuf, mp3_lookup_stat,
+ "SELECT filepath FROM song WHERE title LIKE ?");
+ mp3_lookup_insert(lh, title, LIST_DATATYPE_STRING);
+ mp3_lookup_finish(lh);
+ break;
+ }
return 0;
}
return -ENOENT;
@@ -89,7 +106,7 @@ static int mp3_readdir (const char *path, void *buf, fuse_fill_dir_t filler,
return (0);
} else if (strcmp(path, "/Tracks") == 0) {
lh = mp3_lookup_start(0, &fd, mp3_lookup_list,
- "SELECT title FROM song");
+ "SELECT DISTINCT title FROM song");
mp3_lookup_finish(lh);
return (0);
} else if (strcmp(path, "/Albums") == 0) {
@@ -104,8 +121,37 @@ static int mp3_readdir (const char *path, void *buf, fuse_fill_dir_t filler,
static int mp3_open (const char *path, struct fuse_file_info *fi)
{
- if (strcmp (path, "/Tracks") == 0)
- return 0;
+ struct file_data fd;
+ struct lookuphandle *lh;
+ char *title;
+
+ lh = NULL;
+ fd.fd = -1;
+ fd.found = 0;
+ /* Open a specific track. */
+ if (strncmp(path, "/Tracks", 7) == 0) {
+ switch (mp3_numtoken(path)) {
+ case 2:
+ title = mp3_gettoken(path, 2);
+ if (title == NULL)
+ break;
+ lh = mp3_lookup_start(0, &fd, mp3_lookup_open,
+ "SELECT filepath FROM song WHERE title LIKE ?");
+ if (lh == NULL)
+ return (-EIO);
+ mp3_lookup_insert(lh, title, LIST_DATATYPE_STRING);
+ break;
+ default:
+ return (-ENOENT);
+ }
+ mp3_lookup_finish(lh);
+ if (!fd.found)
+ return (-ENOENT);
+ if (fd.fd < 0)
+ return (-EIO);
+ close(fd.fd);
+ return (0);
+ }
/*
* 1. Have a lookup cache for names?.
* Parse Genre, Album, Artist etc.
@@ -120,11 +166,44 @@ static int mp3_open (const char *path, struct fuse_file_info *fi)
static int mp3_read (const char *path, char *buf, size_t size, off_t offset,
struct fuse_file_info *fi)
{
+ struct file_data fd;
+ struct lookuphandle *lh;
+ char *title;
+ size_t bytes;
+
+ lh = NULL;
+ fd.fd = -1;
+ fd.found = 0;
if (strcmp (path, "/Artists") == 0) {
memcpy (buf, "Oh you wish\n", 12);
return 12;
}
-
+ /* Open a specific track. */
+ if (strncmp(path, "/Tracks", 7) == 0) {
+ switch (mp3_numtoken(path)) {
+ case 2:
+ title = mp3_gettoken(path, 2);
+ if (title == NULL)
+ break;
+ lh = mp3_lookup_start(0, &fd, mp3_lookup_open,
+ "SELECT filepath FROM song WHERE title LIKE ?");
+ if (lh == NULL)
+ return (-EIO);
+ mp3_lookup_insert(lh, title, LIST_DATATYPE_STRING);
+ break;
+ default:
+ return (-ENOENT);
+ }
+ mp3_lookup_finish(lh);
+ if (!fd.found)
+ return (-ENOENT);
+ if (fd.fd < 0)
+ return (-EIO);
+ lseek(fd.fd, offset, SEEK_CUR);
+ bytes = read(fd.fd, buf, size);
+ close(fd.fd);
+ return (bytes);
+ }
/*
* 1. Find the mnode given the path. If not in cache, read through mp3
* list to find it.