summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorKjetil Ørbekk <orbekk@pvv.ntnu.no>2008-08-15 21:54:18 +0200
committerKjetil Ørbekk <orbekk@pvv.ntnu.no>2008-08-15 21:54:18 +0200
commitd554386b01ba7edbb4fc8547d6f0bc6dcaec15c3 (patch)
tree2546b1850d80dcf9191552fa7aad0e0201feba3b /src
parentc054405a1e256e9cf41ed2121e7dabeca518b592 (diff)
parentaaccd1929a253e6e687f50a810877bb9eb4ea8df (diff)
Merge branch 'config'
Diffstat (limited to 'src')
-rw-r--r--src/mfs_subr.c166
-rwxr-xr-xsrc/mfs_vnops.c198
2 files changed, 334 insertions, 30 deletions
diff --git a/src/mfs_subr.c b/src/mfs_subr.c
index ab847f7..d3d3c0b 100644
--- a/src/mfs_subr.c
+++ b/src/mfs_subr.c
@@ -38,6 +38,8 @@
#include <sqlite3.h>
#include <debug.h>
+#define MFS_HANDLE ((void*)-1)
+
struct lookuphandle {
sqlite3 *handle;
sqlite3_stmt *st;
@@ -48,21 +50,151 @@ struct lookuphandle {
lookup_fn_t *lookup;
};
+char *db_path;
sqlite3 *handle;
+/*
+ * Returns the path to $HOME[/extra]
+ */
+char *mfs_get_home_path(const char *extra)
+{
+ int hlen, exlen = 0;
+ char *res;
+ const char *home = getenv("HOME");
+
+ hlen = strlen(home);
+ if (extra)
+ exlen = strlen(extra);
+
+ res = malloc(sizeof(char) * (hlen + exlen + 2));
+ strcpy(res, home);
+
+ if (extra) {
+ res[hlen] = '/';
+ strcpy(res + hlen + 1, extra);
+ }
+
+ return (res);
+}
+
+/*
+ * Insert a musicpath into the database.
+ */
int
-mfs_initscan(char *musicpath)
+mfs_insert_path(char *path, sqlite3 *handle)
{
- int error;
+ int res;
+ sqlite3_stmt *st;
+ /* Add path to registered paths in DB */
+ res = sqlite3_prepare_v2(handle,
+ "SELECT path FROM path WHERE path LIKE ?",
+ -1, &st, NULL);
+ if (res != SQLITE_OK) {
+ warnx("Error preparing stamtement: %s\n",
+ sqlite3_errmsg(handle));
+ return (-1);
+ }
+ sqlite3_bind_text(st, 1, path, -1, SQLITE_TRANSIENT);
+ res = sqlite3_step(st);
+ sqlite3_finalize(st);
+
+ if (res == SQLITE_DONE) {
+ DEBUG("Inserting path '%s' to paths\n", path);
+ /* Doesn't exist. Insert it */
+ res = sqlite3_prepare_v2(handle,
+ "INSERT INTO path(path) VALUES(?)",
+ -1, &st, NULL);
+ if (res != SQLITE_OK) {
+ warnx("Error preparing stamtement: %s\n",
+ sqlite3_errmsg(handle));
+ return (-1);
+ }
+ sqlite3_bind_text(st, 1, path, -1, SQLITE_TRANSIENT);
+ res = sqlite3_step(st);
+ sqlite3_finalize(st);
+ if (res != SQLITE_DONE) {
+ warnx("Error inserting into database: %s\n",
+ sqlite3_errmsg(handle));
+ return (-1);
+ }
+ }
+ return (0);
+}
+
+/*
+ * Reload the configuration from $HOME/.mfsrc
+ *
+ */
+int
+mfs_reload_config()
+{
+ int res, len;
+ char *mfsrc = mfs_get_home_path(".mfsrc");
+ char line[4096];
+ struct lookuphandle *lh;
+ sqlite3 *handle;
+ FILE *f = fopen(mfsrc, "r");
+
+ if (f == NULL) {
+ warnx("Couldn't open configuration file %s\n",
+ mfsrc);
+ return (-1);
+ }
+
+ res = sqlite3_open(db_path, &handle);
+ if (res) {
+ warnx("Can't open database: %s\n", sqlite3_errmsg(handle));
+ sqlite3_close(handle);
+ return (-1);
+ }
+
+ /* XXX: Just adding the paths for now. queue.h for the rest*/
+
+ while (fgets(line, 4096, f) != NULL) {
+ len = strlen(line);
+ if (len > 0 && line[0] != '\n' && line[0] != '#') {
+ if (line[len-1] == '\n')
+ line[len-1] = '\0';
+
+ res = mfs_insert_path(line, handle);
+ DEBUG("inserted path %s, returned(%d)\n", line, res);
+ }
+ }
+
+ free (mfsrc);
+ sqlite3_close(handle);
+
+ /* Do the actual loading */
+ lh = mfs_lookup_start(0, MFS_HANDLE, mfs_lookup_load_path,
+ "SELECT path FROM path");
+ mfs_lookup_finish(lh);
+
+ sqlite3_close(handle);
+ return (0);
+}
+
+int
+mfs_initscan()
+{
+ int error;
+ db_path = mfs_get_home_path(".mfs.db");
/* Open database. */
- error = sqlite3_open(DBNAME, &handle);
+ error = sqlite3_open(db_path, &handle);
if (error) {
warnx("Can't open database: %s\n", sqlite3_errmsg(handle));
sqlite3_close(handle);
return (-1);
}
- traverse_hierarchy(musicpath, mfs_scan);
+
+/* error = mfs_insert_path(musicpath, handle); */
+/* if (error != 0) */
+/* return (error); */
+
+ error = mfs_reload_config();
+ if (error != 0)
+ return (error);
+
sqlite3_close(handle);
return (0);
}
@@ -73,8 +205,9 @@ mfs_initscan(char *musicpath)
* sub-directories.
*/
void
-traverse_hierarchy(char *dirpath, traverse_fn_t fileop)
+traverse_hierarchy(const char *dirpath, traverse_fn_t fileop)
{
+ DEBUG("traversing %s\n", dirpath);
DIR *dirp;
struct dirent *dp;
char filepath[MAXPATHLEN];
@@ -304,15 +437,22 @@ mfs_lookup_start(int field, void *data, lookup_fn_t *fn, const char *query)
return (NULL);
lh->field = field;
lh->lookup = fn;
- lh->priv = data;
+
/* Open database. */
- error = sqlite3_open(DBNAME, &lh->handle);
+ error = sqlite3_open(db_path, &lh->handle);
if (error) {
warnx("Can't open database: %s\n", sqlite3_errmsg(lh->handle));
sqlite3_close(lh->handle);
free(lh);
return (NULL);
}
+
+ if (data == MFS_HANDLE)
+ /* Workaround to give access to the handle */
+ lh->priv = lh->handle;
+ else
+ lh->priv = data;
+
ret = sqlite3_prepare_v2(lh->handle, query, -1, &lh->st, NULL);
if (ret != SQLITE_OK) {
free(lh);
@@ -735,6 +875,18 @@ mfs_lookup_stat(void *data, const char *str)
}
/*
+ * Load a path into database
+ */
+int
+mfs_lookup_load_path(void *data, const char *str)
+{
+ handle = (sqlite3 *)data;
+ traverse_hierarchy(str, mfs_scan);
+
+ return (0);
+}
+
+/*
* Guess on a filetype for a path.
*
* Examples:
diff --git a/src/mfs_vnops.c b/src/mfs_vnops.c
index 60c9ad6..bfb4fe1 100755
--- a/src/mfs_vnops.c
+++ b/src/mfs_vnops.c
@@ -28,6 +28,7 @@
#include <err.h>
#include <sys/types.h>
+#include <sys/time.h>
#include <dirent.h>
#include <fuse.h>
#include <sys/param.h>
@@ -38,9 +39,6 @@
#include <musicfs.h>
#include <debug.h>
-char musicpath[MAXPATHLEN]; // = "/home/lulf/dev/musicfs/music";
-char *logpath = "/home/lulf/dev/musicfs/musicfs.log";
-
static int mfs_getattr (const char *path, struct stat *stbuf)
{
struct file_data fd;
@@ -50,12 +48,20 @@ static int mfs_getattr (const char *path, struct stat *stbuf)
int status = 0;
memset (stbuf, 0, sizeof (struct stat));
- if (strcmp (path, "/") == 0) {
+ if (strcmp(path, "/") == 0) {
stbuf->st_mode = S_IFDIR | 0755;
stbuf->st_nlink = 2;
return 0;
}
+ if (strcmp(path, "/.config") == 0) {
+ char *mfsrc = mfs_get_home_path(".mfsrc");
+ int res = stat(mfsrc, stbuf);
+ DEBUG("stat result for %s: %d\n", mfsrc, res);
+ free(mfsrc);
+ return (res);
+ }
+
enum mfs_filetype type = mfs_get_filetype(path);
switch (type) {
case MFS_DIRECTORY:
@@ -102,6 +108,7 @@ static int mfs_readdir (const char *path, void *buf, fuse_fill_dir_t filler,
filler(buf, "Genres", NULL, 0);
filler(buf, "Tracks", NULL, 0);
filler(buf, "Albums", NULL, 0);
+ filler(buf, ".config", NULL, 0);
return (0);
}
@@ -136,6 +143,9 @@ static int mfs_open (const char *path, struct fuse_file_info *fi)
fd.fd = -1;
fd.found = 0;
+ if (strcmp(path, "/.config") == 0)
+ return (0);
+
int status = mfs_file_data_for_path(path, &fd);
if (status != 0)
return (status);
@@ -166,6 +176,18 @@ static int mfs_read (const char *path, char *buf, size_t size, off_t offset,
fd.found = 0;
size_t bytes;
+ DEBUG("read: path(%s) offset(%d) size(%d)\n", path, (int)offset,
+ (int)size);
+ if (strcmp(path, "/.config") == 0) {
+ char *mfsrc = mfs_get_home_path(".mfsrc");
+ int fd = open(mfsrc, O_RDONLY);
+ free(mfsrc);
+ lseek(fd, offset, SEEK_CUR);
+ bytes = read(fd, buf, size);
+ close(fd);
+ return (bytes);
+ }
+
int status = mfs_file_data_for_path(path, &fd);
if (status != 0)
return (status);
@@ -186,24 +208,159 @@ static int mfs_read (const char *path, char *buf, size_t size, off_t offset,
*/
}
+static int mfs_write(const char *path, const char *buf, size_t size,
+ off_t offset, struct fuse_file_info *fi)
+{
+ size_t bytes;
+
+ DEBUG("write: path(%s) offset(%d) size(%d)\n", path, (int)offset,
+ (int)size);
+
+ if (strcmp(path, "/.config") == 0) {
+ char *mfsrc = mfs_get_home_path(".mfsrc");
+ int fd = open(mfsrc, O_WRONLY);
+ free(mfsrc);
+ lseek(fd, offset, SEEK_CUR);
+ bytes = write(fd, buf, size);
+ close(fd);
+ return (bytes);
+ }
+
+ return (-1);
+}
+
+static int mfs_create(const char *path, mode_t mode, struct fuse_file_info *fi)
+{
+ DEBUG("create %s\n", path);
+ return (-1);
+}
+
+static int mfs_mknod(const char *path, mode_t mode, dev_t rdev)
+{
+ DEBUG("mknod %s\n", path);
+ return (-1);
+}
+
+static int mfs_truncate(const char *path, off_t size)
+{
+ char *mfsrc;
+ int res;
+ DEBUG("truncating %s to size %d\n", path, (int)size);
+
+ if (strcmp(path, "/.config") == 0) {
+ mfsrc = mfs_get_home_path(".mfsrc");
+ res = truncate(mfsrc, size);
+ DEBUG("truncated %s with result: %d\n", mfsrc, res)
+ free(mfsrc);
+ return (res);
+ }
+
+ return (-1);
+}
+
+static int mfs_flush(const char *path, struct fuse_file_info *fi)
+{
+ DEBUG("flushing path %s\n", path);
+ if (strcmp(path, "/.config") == 0) {
+ return (0);
+ }
+
+ return (-1);
+}
+
+static int mfs_fsync(const char *path, int datasync,
+ struct fuse_file_info *fi)
+{
+ DEBUG("fsync path %s\n", path);
+ return (0);
+}
+
+static int mfs_release(const char *path, struct fuse_file_info *fi)
+{
+ DEBUG("release %s\n", path);
+
+ if (strcmp(path, "/.config") == 0) {
+ /* Reload configuration file */
+ mfs_reload_config();
+ }
+
+ return (0);
+}
+
+static int mfs_chmod(const char *path, mode_t mode)
+{
+ char *mfsrc;
+ int ret;
+
+ DEBUG("chmod %s, %d\n", path, (int)mode);
+ if (strcmp(path, "/.config") == 0) {
+ mfsrc = mfs_get_home_path(".mfsrc");
+ ret = chmod(mfsrc, mode);
+ free(mfsrc);
+ return (ret);
+ }
+
+ return (-1);
+}
+
+static int mfs_utimens(const char *path, const struct timespec tv[2])
+{
+ char *mfsrc;
+ int ret;
+
+ DEBUG("utime %s\n", path);
+
+ if (strcmp(path, "/.config") == 0) {
+ mfsrc = mfs_get_home_path(".mfsrc");
+ ret = 0; /* utimes(mfsrc, tval); */
+ free(mfsrc);
+ return (ret);
+ }
+
+ return (-1);
+}
+
+static int mfs_access(const char *path, int mask)
+{
+ DEBUG("access called for path %s\n", path);
+ return (0);
+}
+
+static int mfs_setxattr(const char *path, const char *name,
+ const char *val, size_t size, int flags)
+{
+ DEBUG("setxattr on path %s: %s=%s\n", path, name, val);
+ return (0);
+}
+
static struct fuse_operations mfs_ops = {
- .getattr = mfs_getattr,
- .readdir = mfs_readdir,
- .open = mfs_open,
- .read = mfs_read,
+ .getattr = mfs_getattr,
+ .readdir = mfs_readdir,
+ .open = mfs_open,
+ .read = mfs_read,
+ .write = mfs_write,
+ .mknod = mfs_mknod,
+ .create = mfs_create,
+ .truncate = mfs_truncate,
+ .fsync = mfs_fsync,
+ .chmod = mfs_chmod,
+ .release = mfs_release,
+ .utimens = mfs_utimens,
+ .setxattr = mfs_setxattr,
};
static int musicfs_opt_proc (void *data, const char *arg, int key,
struct fuse_args *outargs)
{
- static int musicpath_set = 0;
+ /* Using config now. This is how we added the additional parameter: */
+ /* static int musicpath_set = 0; */
+ /* if (key == FUSE_OPT_KEY_NONOPT && !musicpath_set) { */
+ /* /\* The source directory isn't already set, let's do it *\/ */
+ /* strcpy(musicpath, arg); */
+ /* musicpath_set = 1; */
+ /* return (0); */
+ /* } */
- if (key == FUSE_OPT_KEY_NONOPT && !musicpath_set) {
- /* The source directory isn't already set, let's do it */
- strcpy(musicpath, arg);
- musicpath_set = 1;
- return (0);
- }
return (1);
}
@@ -211,13 +368,9 @@ int
mfs_run(int argc, char **argv)
{
int ret;
- /*
- * XXX: Build index of mp3's.
- */
- /* Update tables. */
- if (argc < 2) {
- fprintf(stderr, "Usage: %s <musicfolder> <mountpoint>\n", argv[0]);
+ if (argc < 1) {
+ fprintf(stderr, "Usage: %s <mountpoint>\n", argv[0]);
return (-1);
}
@@ -226,8 +379,7 @@ mfs_run(int argc, char **argv)
if (fuse_opt_parse(&args, NULL, NULL, musicfs_opt_proc) != 0)
exit (1);
- DEBUG("musicpath: %s\n", musicpath);
- mfs_initscan(musicpath);
+ mfs_initscan();
ret = 0;
ret = fuse_main(args.argc, args.argv, &mfs_ops, NULL);