Permalink
Browse files

Move filesystem operations to separate file

  • Loading branch information...
1 parent 6279717 commit 14dd802a52a0a3c73efc4dccb3d98325fc236171 @khenriks committed Dec 22, 2011
Showing with 362 additions and 338 deletions.
  1. +1 −1 src/Makefile.am
  2. +353 −0 src/fuseops.c
  3. +0 −333 src/mp3fs.c
  4. +0 −2 src/transcode.c
  5. +8 −2 src/transcode.h
View
2 src/Makefile.am
@@ -1,4 +1,4 @@
AM_CFLAGS = $(fuse_CFLAGS) $(id3tag_CFLAGS) $(flac_CFLAGS) -Wall
bin_PROGRAMS = mp3fs
-mp3fs_SOURCES = mp3fs.c transcode.c transcode.h
+mp3fs_SOURCES = mp3fs.c fuseops.c transcode.c transcode.h
mp3fs_LDADD = $(fuse_LIBS) $(id3tag_LIBS) $(flac_LIBS)
View
353 src/fuseops.c
@@ -0,0 +1,353 @@
+/*
+ * MP3FS: A read-only FUSE filesystem which transcodes audio formats
+ * (currently FLAC) to MP3 on the fly when opened and read. See README
+ * for more details.
+ *
+ * Copyright (C) 2006-2008 David Collett
+ * Copyright (C) 2008-2011 Kristofer Henriksson
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <dirent.h>
+#include <limits.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include "transcode.h"
+
+/*
+ * Translate file names from FUSE to the original absolute path. A buffer
+ * is allocated using malloc for the translated path. It is the caller's
+ * responsibility to free it.
+ */
+char* translate_path(const char* path) {
+ char* result;
+ /*
+ * Allocate buffer. The +2 is for the terminating '\0' and to
+ * accomodate possibly translating .mp3 to .flac later.
+ */
+ result = malloc(strlen(params.basepath) + strlen(path) + 2);
+
+ if (result) {
+ strcpy(result, params.basepath);
+ strcat(result, path);
+ }
+
+ return result;
+}
+
+/* Convert file extension between mp3 and flac. */
+void convert_path(char* path, int toflac) {
+ char* ptr;
+ ptr = strrchr(path, '.');
+ if (toflac) {
+ if (ptr && strcmp(ptr, ".mp3") == 0) {
+ strcpy(ptr, ".flac");
+ }
+ } else {
+ if (ptr && strcmp(ptr, ".flac") == 0) {
+ strcpy(ptr, ".mp3");
+ }
+ }
+}
+
+static int mp3fs_readlink(const char *path, char *buf, size_t size) {
+ char* origpath;
+ ssize_t len;
+
+ mp3fs_debug("readlink %s", path);
+
+ errno = 0;
+
+ origpath = translate_path(path);
+ if (!origpath) {
+ goto translate_fail;
+ }
+
+ convert_path(origpath, 1);
+
+ len = readlink(origpath, buf, size - 2);
+ if (len == -1) {
+ goto readlink_fail;
+ }
+
+ buf[len] = '\0';
+
+ convert_path(buf, 0);
+
+readlink_fail:
+ free(origpath);
+translate_fail:
+ return -errno;
+}
+
+static int mp3fs_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
+ off_t offset, struct fuse_file_info *fi) {
+ char* origpath;
+ char* origfile;
+ DIR *dp;
+ struct dirent *de;
+
+ mp3fs_debug("readdir %s", path);
+
+ errno = 0;
+
+ origpath = translate_path(path);
+ if (!origpath) {
+ goto translate_fail;
+ }
+
+ /* 2 for directory separator and NULL byte */
+ origfile = malloc(strlen(origpath) + NAME_MAX + 2);
+ if (!origfile) {
+ goto origfile_fail;
+ }
+
+ dp = opendir(origpath);
+ if (!dp) {
+ goto opendir_fail;
+ }
+
+ while ((de = readdir(dp))) {
+ struct stat st;
+
+ snprintf(origfile, strlen(origpath) + NAME_MAX + 2, "%s/%s", origpath,
+ de->d_name);
+
+ if (lstat(origfile, &st) == -1) {
+ goto stat_fail;
+ } else {
+ if (S_ISREG(st.st_mode) || S_ISLNK(st.st_mode)) {
+ convert_path(de->d_name, 0);
+ }
+ }
+
+ if (filler(buf, de->d_name, &st, 0)) break;
+ }
+
+stat_fail:
+ closedir(dp);
+opendir_fail:
+ free(origfile);
+origfile_fail:
+ free(origpath);
+translate_fail:
+ return -errno;
+}
+
+static int mp3fs_getattr(const char *path, struct stat *stbuf) {
+ char* origpath;
+ struct transcoder* trans;
+
+ mp3fs_debug("getattr %s", path);
+
+ errno = 0;
+
+ origpath = translate_path(path);
+ if (!origpath) {
+ goto translate_fail;
+ }
+
+ /* pass-through for regular files */
+ if (lstat(origpath, stbuf) == 0) {
+ goto passthrough;
+ } else {
+ /* Not really an error. */
+ errno = 0;
+ }
+
+ convert_path(origpath, 1);
+
+ if (lstat(origpath, stbuf) == -1) {
+ goto stat_fail;
+ }
+
+ /*
+ * Get size for resulting mp3 from regular file, otherwise it's a
+ * symbolic link. */
+ if (S_ISREG(stbuf->st_mode)) {
+ trans = transcoder_new(origpath);
+ if (!trans) {
+ goto transcoder_fail;
+ }
+
+ stbuf->st_size = trans->totalsize;
+ stbuf->st_blocks = (stbuf->st_size + 512 - 1) / 512;
+
+ transcoder_finish(trans);
+ transcoder_delete(trans);
+ }
+
+transcoder_fail:
+stat_fail:
+passthrough:
+ free(origpath);
+translate_fail:
+ return -errno;
+}
+
+static int mp3fs_open(const char *path, struct fuse_file_info *fi) {
+ char* origpath;
+ struct transcoder* trans;
+ int fd;
+
+ mp3fs_debug("open %s", path);
+
+ errno = 0;
+
+ origpath = translate_path(path);
+ if (!origpath) {
+ goto translate_fail;
+ }
+
+ fd = open(origpath, fi->flags);
+
+ /* File does exist, but can't be opened. */
+ if (fd == -1 && errno != ENOENT) {
+ goto open_fail;
+ } else {
+ /* Not really an error. */
+ errno = 0;
+ }
+
+ /* File is real and can be opened. */
+ if (fd != -1) {
+ close(fd);
+ goto passthrough;
+ }
+
+ convert_path(origpath, 1);
+
+ trans = transcoder_new(origpath);
+ if (!trans) {
+ goto transcoder_fail;
+ }
+
+ /* Store transcoder in the fuse_file_info structure. */
+ fi->fh = (uint64_t)trans;
+
+transcoder_fail:
+passthrough:
+open_fail:
+ free(origpath);
+translate_fail:
+ return -errno;
+}
+
+static int mp3fs_read(const char *path, char *buf, size_t size, off_t offset,
+ struct fuse_file_info *fi) {
+ char* origpath;
+ int fd;
+ int read = 0;
+ struct transcoder* trans;
+
+ mp3fs_debug("read %s: %zu bytes from %jd", path, size, (intmax_t)offset);
+
+ errno = 0;
+
+ origpath = translate_path(path);
+ if (!origpath) {
+ goto translate_fail;
+ }
+
+ /* If this is a real file, pass the call through. */
+ fd = open(origpath, O_RDONLY);
+ if (fd != -1) {
+ read = pread(fd, buf, size, offset);
+ close(fd);
+ goto passthrough;
+ }
+
+ /* File does exist, but can't be opened. */
+ if (fd == -1 && errno != ENOENT) {
+ goto open_fail;
+ }
+
+ trans = (struct transcoder*)fi->fh;
+
+ if (!trans) {
+ mp3fs_error("Tried to read from unopen file: %s", origpath);
+ goto transcoder_fail;
+ }
+
+ read = transcoder_read(trans, buf, offset, size);
+
+transcoder_fail:
+passthrough:
+open_fail:
+ free(origpath);
+translate_fail:
+ if (read) {
+ return read;
+ } else {
+ return -errno;
+ }
+}
+
+static int mp3fs_statfs(const char *path, struct statvfs *stbuf) {
+ char* origpath;
+
+ mp3fs_debug("statfs %s", path);
+
+ errno = 0;
+
+ origpath = translate_path(path);
+ if (!origpath) {
+ goto translate_fail;
+ }
+
+ statvfs(origpath, stbuf);
+
+ free(origpath);
+translate_fail:
+ return -errno;
+}
+
+static int mp3fs_release(const char *path, struct fuse_file_info *fi) {
+ struct transcoder* trans;
+
+ mp3fs_debug("release %s", path);
+
+ trans = (struct transcoder*)fi->fh;
+ if (trans) {
+ transcoder_finish(trans);
+ transcoder_delete(trans);
+ }
+
+ return 0;
+}
+
+/* We need synchronous reads. */
+static void *mp3fs_init(struct fuse_conn_info *conn) {
+ conn->async_read = 0;
+
+ return NULL;
+}
+
+struct fuse_operations mp3fs_ops = {
+ .getattr = mp3fs_getattr,
+ .readlink = mp3fs_readlink,
+ .readdir = mp3fs_readdir,
+ .open = mp3fs_open,
+ .read = mp3fs_read,
+ .statfs = mp3fs_statfs,
+ .release = mp3fs_release,
+ .init = mp3fs_init,
+};
View
333 src/mp3fs.c
@@ -21,20 +21,8 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-#define FUSE_USE_VERSION 26
-#define _XOPEN_SOURCE 500
-
-#include <fuse.h>
#include <stdio.h>
-#include <stdlib.h>
#include <string.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <dirent.h>
-#include <errno.h>
-#include <limits.h>
-#include <sys/stat.h>
-#include <sys/statvfs.h>
#include "transcode.h"
@@ -76,327 +64,6 @@ static struct fuse_opt mp3fs_opts[] = {
FUSE_OPT_END
};
-/*
- * Translate file names from FUSE to the original absolute path. A buffer
- * is allocated using malloc for the translated path. It is the caller's
- * responsibility to free it.
- */
-char* translate_path(const char* path) {
- char* result;
- /*
- * Allocate buffer. The +2 is for the terminating '\0' and to
- * accomodate possibly translating .mp3 to .flac later.
- */
- result = malloc(strlen(params.basepath) + strlen(path) + 2);
-
- if (result) {
- strcpy(result, params.basepath);
- strcat(result, path);
- }
-
- return result;
-}
-
-/* Convert file extension between mp3 and flac. */
-void convert_path(char* path, int toflac) {
- char* ptr;
- ptr = strrchr(path, '.');
- if (toflac) {
- if (ptr && strcmp(ptr, ".mp3") == 0) {
- strcpy(ptr, ".flac");
- }
- } else {
- if (ptr && strcmp(ptr, ".flac") == 0) {
- strcpy(ptr, ".mp3");
- }
- }
-}
-
-static int mp3fs_readlink(const char *path, char *buf, size_t size) {
- char* origpath;
- ssize_t len;
-
- mp3fs_debug("readlink %s", path);
-
- errno = 0;
-
- origpath = translate_path(path);
- if (!origpath) {
- goto translate_fail;
- }
-
- convert_path(origpath, 1);
-
- len = readlink(origpath, buf, size - 2);
- if (len == -1) {
- goto readlink_fail;
- }
-
- buf[len] = '\0';
-
- convert_path(buf, 0);
-
-readlink_fail:
- free(origpath);
-translate_fail:
- return -errno;
-}
-
-static int mp3fs_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
- off_t offset, struct fuse_file_info *fi) {
- char* origpath;
- char* origfile;
- DIR *dp;
- struct dirent *de;
-
- mp3fs_debug("readdir %s", path);
-
- errno = 0;
-
- origpath = translate_path(path);
- if (!origpath) {
- goto translate_fail;
- }
-
- /* 2 for directory separator and NULL byte */
- origfile = malloc(strlen(origpath) + NAME_MAX + 2);
- if (!origfile) {
- goto origfile_fail;
- }
-
- dp = opendir(origpath);
- if (!dp) {
- goto opendir_fail;
- }
-
- while ((de = readdir(dp))) {
- struct stat st;
-
- snprintf(origfile, strlen(origpath) + NAME_MAX + 2, "%s/%s", origpath,
- de->d_name);
-
- if (lstat(origfile, &st) == -1) {
- goto stat_fail;
- } else {
- if (S_ISREG(st.st_mode) || S_ISLNK(st.st_mode)) {
- convert_path(de->d_name, 0);
- }
- }
-
- if (filler(buf, de->d_name, &st, 0)) break;
- }
-
-stat_fail:
- closedir(dp);
-opendir_fail:
- free(origfile);
-origfile_fail:
- free(origpath);
-translate_fail:
- return -errno;
-}
-
-static int mp3fs_getattr(const char *path, struct stat *stbuf) {
- char* origpath;
- struct transcoder* trans;
-
- mp3fs_debug("getattr %s", path);
-
- errno = 0;
-
- origpath = translate_path(path);
- if (!origpath) {
- goto translate_fail;
- }
-
- /* pass-through for regular files */
- if (lstat(origpath, stbuf) == 0) {
- goto passthrough;
- } else {
- /* Not really an error. */
- errno = 0;
- }
-
- convert_path(origpath, 1);
-
- if (lstat(origpath, stbuf) == -1) {
- goto stat_fail;
- }
-
- /*
- * Get size for resulting mp3 from regular file, otherwise it's a
- * symbolic link. */
- if (S_ISREG(stbuf->st_mode)) {
- trans = transcoder_new(origpath);
- if (!trans) {
- goto transcoder_fail;
- }
-
- stbuf->st_size = trans->totalsize;
- stbuf->st_blocks = (stbuf->st_size + 512 - 1) / 512;
-
- transcoder_finish(trans);
- transcoder_delete(trans);
- }
-
-transcoder_fail:
-stat_fail:
-passthrough:
- free(origpath);
-translate_fail:
- return -errno;
-}
-
-static int mp3fs_open(const char *path, struct fuse_file_info *fi) {
- char* origpath;
- struct transcoder* trans;
- int fd;
-
- mp3fs_debug("open %s", path);
-
- errno = 0;
-
- origpath = translate_path(path);
- if (!origpath) {
- goto translate_fail;
- }
-
- fd = open(origpath, fi->flags);
-
- /* File does exist, but can't be opened. */
- if (fd == -1 && errno != ENOENT) {
- goto open_fail;
- } else {
- /* Not really an error. */
- errno = 0;
- }
-
- /* File is real and can be opened. */
- if (fd != -1) {
- close(fd);
- goto passthrough;
- }
-
- convert_path(origpath, 1);
-
- trans = transcoder_new(origpath);
- if (!trans) {
- goto transcoder_fail;
- }
-
- /* Store transcoder in the fuse_file_info structure. */
- fi->fh = (uint64_t)trans;
-
-transcoder_fail:
-passthrough:
-open_fail:
- free(origpath);
-translate_fail:
- return -errno;
-}
-
-static int mp3fs_read(const char *path, char *buf, size_t size, off_t offset,
- struct fuse_file_info *fi) {
- char* origpath;
- int fd;
- int read = 0;
- struct transcoder* trans;
-
- mp3fs_debug("read %s: %zu bytes from %jd", path, size, (intmax_t)offset);
-
- errno = 0;
-
- origpath = translate_path(path);
- if (!origpath) {
- goto translate_fail;
- }
-
- /* If this is a real file, pass the call through. */
- fd = open(origpath, O_RDONLY);
- if (fd != -1) {
- read = pread(fd, buf, size, offset);
- close(fd);
- goto passthrough;
- }
-
- /* File does exist, but can't be opened. */
- if (fd == -1 && errno != ENOENT) {
- goto open_fail;
- }
-
- trans = (struct transcoder*)fi->fh;
-
- if (!trans) {
- mp3fs_error("Tried to read from unopen file: %s", origpath);
- goto transcoder_fail;
- }
-
- read = transcoder_read(trans, buf, offset, size);
-
-transcoder_fail:
-passthrough:
-open_fail:
- free(origpath);
-translate_fail:
- if (read) {
- return read;
- } else {
- return -errno;
- }
-}
-
-static int mp3fs_statfs(const char *path, struct statvfs *stbuf) {
- char* origpath;
-
- mp3fs_debug("statfs %s", path);
-
- errno = 0;
-
- origpath = translate_path(path);
- if (!origpath) {
- goto translate_fail;
- }
-
- statvfs(origpath, stbuf);
-
- free(origpath);
-translate_fail:
- return -errno;
-}
-
-static int mp3fs_release(const char *path, struct fuse_file_info *fi) {
- struct transcoder* trans;
-
- mp3fs_debug("release %s", path);
-
- trans = (struct transcoder*)fi->fh;
- if (trans) {
- transcoder_finish(trans);
- transcoder_delete(trans);
- }
-
- return 0;
-}
-
-/* We need synchronous reads. */
-static void *mp3fs_init(struct fuse_conn_info *conn) {
- conn->async_read = 0;
-
- return NULL;
-}
-
-
-static struct fuse_operations mp3fs_ops = {
- .getattr = mp3fs_getattr,
- .readlink = mp3fs_readlink,
- .readdir = mp3fs_readdir,
- .open = mp3fs_open,
- .read = mp3fs_read,
- .statfs = mp3fs_statfs,
- .release = mp3fs_release,
- .init = mp3fs_init,
-};
-
void usage(char *name) {
printf("Usage: %s [OPTION]... FLACDIR MP3DIR\n", name);
fputs("\
View
2 src/transcode.c
@@ -36,8 +36,6 @@
#include "transcode.h"
-extern struct mp3fs_params params;
-
/* Functions for dealing with the buffer */
/*
View
10 src/transcode.h
@@ -19,6 +19,9 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+#define FUSE_USE_VERSION 26
+
+#include <fuse.h>
#include <FLAC/metadata.h>
#include <FLAC/stream_decoder.h>
#include <lame/lame.h>
@@ -29,14 +32,17 @@
#define BUFSIZE 2 * FLAC_BLOCKSIZE
/* Global program parameters */
-struct mp3fs_params {
+extern struct mp3fs_params {
const char *basepath;
unsigned int bitrate;
unsigned int quality;
int debug;
int gainmode;
float gainref;
-};
+} params;
+
+/* Fuse operations struct */
+extern struct fuse_operations mp3fs_ops;
#define mp3fs_debug(f, ...) syslog(LOG_DEBUG, f, ## __VA_ARGS__)
#define mp3fs_info(f, ...) syslog(LOG_INFO, f, ## __VA_ARGS__)

0 comments on commit 14dd802

Please sign in to comment.