diff options
author | Ulf Lilleengen <lulf@carrot.studby.ntnu.no> | 2008-08-09 16:14:53 +0200 |
---|---|---|
committer | Ulf Lilleengen <lulf@carrot.studby.ntnu.no> | 2008-08-09 16:14:53 +0200 |
commit | 64e1a2a9e5cc03d234fa4cf1a3577dcf84e5e22e (patch) | |
tree | 914f4fd2e17571a65b66a999331ec2c9be288aa3 | |
parent | cfa01e2eded5e91a9272d1578e48540199c8b2d8 (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.h | 16 | ||||
-rw-r--r-- | src/mp3_subr.c | 29 | ||||
-rwxr-xr-x | src/mp3_vnops.c | 135 |
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. |