diff --git a/.gitignore b/.gitignore index c1ed1bc..7071364 100644 --- a/.gitignore +++ b/.gitignore @@ -2,4 +2,8 @@ .DS_Store coverage rdoc -pkg \ No newline at end of file +pkg +*.o +*.bundle +*.log +Makefile \ No newline at end of file diff --git a/Rakefile b/Rakefile index 0194495..2b1677e 100644 --- a/Rakefile +++ b/Rakefile @@ -10,6 +10,7 @@ begin gem.email = "kyle@kylemaxwell.com" gem.homepage = "http://github.com/fizx/fusefs" gem.authors = ["Kyle Maxwell"] + gem.extensions = ["ext/extconf.rb"] end rescue LoadError puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler" diff --git a/ext/Makefile b/ext/Makefile deleted file mode 100644 index 546fa14..0000000 --- a/ext/Makefile +++ /dev/null @@ -1,157 +0,0 @@ - -SHELL = /bin/sh - -#### Start of system configuration section. #### - -srcdir = . -topdir = /opt/local/lib/ruby/1.8/i686-darwin10 -hdrdir = $(topdir) -VPATH = $(srcdir):$(topdir):$(hdrdir) -exec_prefix = $(prefix) -prefix = $(DESTDIR)/opt/local -sharedstatedir = $(prefix)/com -mandir = $(DESTDIR)/opt/local/share/man -psdir = $(docdir) -oldincludedir = $(DESTDIR)/usr/include -localedir = $(datarootdir)/locale -bindir = $(exec_prefix)/bin -libexecdir = $(exec_prefix)/libexec -sitedir = $(libdir)/ruby/site_ruby -htmldir = $(docdir) -vendorarchdir = $(vendorlibdir)/$(sitearch) -includedir = $(prefix)/include -infodir = $(datarootdir)/info -vendorlibdir = $(vendordir)/$(ruby_version) -sysconfdir = $(prefix)/etc -libdir = $(exec_prefix)/lib -sbindir = $(exec_prefix)/sbin -rubylibdir = $(libdir)/ruby/$(ruby_version) -docdir = $(datarootdir)/doc/$(PACKAGE) -dvidir = $(docdir) -vendordir = $(DESTDIR)/opt/local/lib/ruby/vendor_ruby -datarootdir = $(prefix)/share -pdfdir = $(docdir) -archdir = $(rubylibdir)/$(arch) -sitearchdir = $(sitelibdir)/$(sitearch) -datadir = $(datarootdir) -localstatedir = $(prefix)/var -sitelibdir = $(sitedir)/$(ruby_version) - -CC = /usr/bin/gcc-4.2 -LIBRUBY = $(LIBRUBY_SO) -LIBRUBY_A = lib$(RUBY_SO_NAME)-static.a -LIBRUBYARG_SHARED = -l$(RUBY_SO_NAME) -LIBRUBYARG_STATIC = -l$(RUBY_SO_NAME)-static - -RUBY_EXTCONF_H = -CFLAGS = -fno-common -O2 -arch x86_64 -fno-common -pipe -fno-common $(cflags) -arch x86_64 -INCFLAGS = -I. -I. -I/opt/local/lib/ruby/1.8/i686-darwin10 -I. -DEFS = -CPPFLAGS = -I/opt/local/include -D_XOPEN_SOURCE -D_DARWIN_C_SOURCE -I/opt/local/include -CXXFLAGS = $(CFLAGS) -ldflags = -L. -L/opt/local/lib -dldflags = -archflag = -arch x86_64 -DLDFLAGS = $(ldflags) $(dldflags) $(archflag) -LDSHARED = $(CC) -dynamic -bundle -undefined suppress -flat_namespace -AR = ar -EXEEXT = - -RUBY_INSTALL_NAME = ruby -RUBY_SO_NAME = ruby -arch = i686-darwin10 -sitearch = i686-darwin10 -ruby_version = 1.8 -ruby = /opt/local/bin/ruby -RUBY = $(ruby) -RM = rm -f -MAKEDIRS = mkdir -p -INSTALL = /usr/bin/install -c -INSTALL_PROG = $(INSTALL) -m 0755 -INSTALL_DATA = $(INSTALL) -m 644 -COPY = cp - -#### End of system configuration section. #### - -preload = - -libpath = . $(libdir) -LIBPATH = -L. -L$(libdir) -DEFFILE = - -CLEANFILES = mkmf.log -DISTCLEANFILES = - -extout = -extout_prefix = -target_prefix = -LOCAL_LIBS = -LIBS = $(LIBRUBYARG_SHARED) -lfuse -lpthread -ldl -lobjc -SRCS = fusefs_fuse.c fusefs_lib.c -OBJS = fusefs_fuse.o fusefs_lib.o -TARGET = fusefs_lib -DLLIB = $(TARGET).bundle -EXTSTATIC = -STATIC_LIB = - -BINDIR = $(bindir) -RUBYCOMMONDIR = $(sitedir)$(target_prefix) -RUBYLIBDIR = $(sitelibdir)$(target_prefix) -RUBYARCHDIR = $(sitearchdir)$(target_prefix) - -TARGET_SO = $(DLLIB) -CLEANLIBS = $(TARGET).bundle $(TARGET).il? $(TARGET).tds $(TARGET).map -CLEANOBJS = *.o *.a *.s[ol] *.pdb *.exp *.bak - -all: $(DLLIB) -static: $(STATIC_LIB) - -clean: - @-$(RM) $(CLEANLIBS) $(CLEANOBJS) $(CLEANFILES) - -distclean: clean - @-$(RM) Makefile $(RUBY_EXTCONF_H) conftest.* mkmf.log - @-$(RM) core ruby$(EXEEXT) *~ $(DISTCLEANFILES) - -realclean: distclean -install: install-so install-rb - -install-so: $(RUBYARCHDIR) -install-so: $(RUBYARCHDIR)/$(DLLIB) -$(RUBYARCHDIR)/$(DLLIB): $(DLLIB) - $(INSTALL_PROG) $(DLLIB) $(RUBYARCHDIR) -install-rb: pre-install-rb install-rb-default -install-rb-default: pre-install-rb-default -pre-install-rb: Makefile -pre-install-rb-default: Makefile -$(RUBYARCHDIR): - $(MAKEDIRS) $@ - -site-install: site-install-so site-install-rb -site-install-so: install-so -site-install-rb: install-rb - -.SUFFIXES: .c .m .cc .cxx .cpp .C .o - -.cc.o: - $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) -c $< - -.cxx.o: - $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) -c $< - -.cpp.o: - $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) -c $< - -.C.o: - $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) -c $< - -.c.o: - $(CC) $(INCFLAGS) $(CPPFLAGS) $(CFLAGS) -c $< - -$(DLLIB): $(OBJS) Makefile - @-$(RM) $@ - $(LDSHARED) -o $@ $(OBJS) $(LIBPATH) $(DLDFLAGS) $(LOCAL_LIBS) $(LIBS) - - - -$(OBJS): ruby.h defines.h diff --git a/ext/extconf.rb b/ext/extconf.rb index 60b7b2a..ad1ba6d 100644 --- a/ext/extconf.rb +++ b/ext/extconf.rb @@ -1,6 +1,6 @@ require 'mkmf' dir_config('fusefs_lib.so') -if have_library('fuse') +if have_library('fuse_ino64') || have_library('fuse') create_makefile('fusefs_lib') else puts "No FUSE install available" diff --git a/ext/fusefs_fuse.c b/ext/fusefs_fuse.c index b36015e..f629c55 100644 --- a/ext/fusefs_fuse.c +++ b/ext/fusefs_fuse.c @@ -3,15 +3,10 @@ /* This is rewriting most of the things that occur * in fuse_main up through fuse_loop */ -#define FUSE_USE_VERSION 22 +#define FUSE_USE_VERSION 26 #define _FILE_OFFSET_BITS 64 #include -/* #include "fuse_i.h" -#include "fuse_compat.h" -#include "fuse_kernel.h" -#include "fuse_kernel_compat5.h" */ - #include #include #include @@ -24,25 +19,32 @@ #include #include -struct fuse * fuse_instance = NULL; -static unsigned int fusefd; +struct fuse *fuse_instance = NULL; +struct fuse_chan *fusech = NULL; static char *mounted_at = NULL; static int set_one_signal_handler(int signal, void (*handler)(int)); int fusefs_fd() { - return fusefd; + if(fusech == NULL) + return -1; + return fuse_chan_fd(fusech); } int fusefs_unmount() { + char buf[128]; + + if (mounted_at && fusech) { + fuse_unmount(mounted_at, fusech); + sprintf(buf, "/sbin/umount %s", mounted_at); + system(buf); + } if (fuse_instance) fuse_destroy(fuse_instance); fuse_instance = NULL; - if (mounted_at) - fuse_unmount(mounted_at); free(mounted_at); - fusefd = -1; + fusech = NULL; } static void @@ -53,38 +55,8 @@ fusefs_ehandler() { } int -fusefs_setup(char *mountpoint, const struct fuse_operations *op, char *opts) { - char fuse_new_opts[1024]; - char fuse_mount_opts[1024]; - char nopts[1024]; - - char *cur; - char *ptr; - - fuse_new_opts[0] = '\0'; - fuse_mount_opts[0] = '\0'; - - for (cur=opts;cur;cur = ptr) { - ptr = strchr(cur,','); - if (ptr) *(ptr++) = '\0'; - if (fuse_is_lib_option(cur)) { - if (fuse_new_opts[0]) { - strcpy(nopts,fuse_new_opts); - snprintf(fuse_new_opts,1024,"%s,%s",nopts,cur); - } else { - snprintf(fuse_new_opts,1024,"%s",cur); - } - } else { - if (fuse_mount_opts[0]) { - strcpy(nopts,fuse_mount_opts); - snprintf(fuse_mount_opts,1024,"%s,%s",nopts,cur); - } else { - snprintf(fuse_mount_opts,1024,"%s",cur); - } - } - } - - fusefd = -1; +fusefs_setup(char *mountpoint, const struct fuse_operations *op, struct fuse_args *opts) { + fusech = NULL; if (fuse_instance != NULL) { return 0; } @@ -93,10 +65,10 @@ fusefs_setup(char *mountpoint, const struct fuse_operations *op, char *opts) { } /* First, mount us */ - fusefd = fuse_mount(mountpoint, fuse_mount_opts[0] ? fuse_mount_opts : NULL); - if (fusefd == -1) return 0; + fusech = fuse_mount(mountpoint, opts); + if (fusech == NULL) return 0; - fuse_instance = fuse_new(fusefd, fuse_new_opts[0] ? fuse_new_opts : NULL, op, sizeof(*op)); + fuse_instance = fuse_new(fusech, opts, op, sizeof(*op), NULL); if (fuse_instance == NULL) goto err_unmount; @@ -115,7 +87,7 @@ fusefs_setup(char *mountpoint, const struct fuse_operations *op, char *opts) { err_destroy: fuse_destroy(fuse_instance); err_unmount: - fuse_unmount(mountpoint); + fuse_unmount(mountpoint, fusech); return 0; } diff --git a/ext/fusefs_fuse.h b/ext/fusefs_fuse.h index c68110f..72d9fd6 100644 --- a/ext/fusefs_fuse.h +++ b/ext/fusefs_fuse.h @@ -6,10 +6,12 @@ #ifndef __FUSEFS_FUSE_H_ #define __FUSEFS_FUSE_H_ +struct fuse_args; + int fusefs_fd(); int fusefs_unmount(); int fusefs_ehandler(); -int fusefs_setup(char *mountpoint, const struct fuse_operations *op, char *opts); +int fusefs_setup(char *mountpoint, const struct fuse_operations *op, struct fuse_args *opts); int fusefs_process(); int fusefs_uid(); int fusefs_gid(); diff --git a/ext/fusefs_fuse.o b/ext/fusefs_fuse.o deleted file mode 100644 index 9e75352..0000000 Binary files a/ext/fusefs_fuse.o and /dev/null differ diff --git a/ext/fusefs_lib.bundle b/ext/fusefs_lib.bundle deleted file mode 100755 index b1a4bab..0000000 Binary files a/ext/fusefs_lib.bundle and /dev/null differ diff --git a/ext/fusefs_lib.c b/ext/fusefs_lib.c index 7e04457..410c93a 100644 --- a/ext/fusefs_lib.c +++ b/ext/fusefs_lib.c @@ -6,7 +6,7 @@ /* #define DEBUG /* */ -#define FUSE_USE_VERSION 22 +#define FUSE_USE_VERSION 26 #define _FILE_OFFSET_BITS 64 #include @@ -280,9 +280,8 @@ rf_getattr(const char *path, struct stat *stbuf) { /* "/" is automatically a dir. */ if (strcmp(path,"/") == 0) { - stbuf->st_mode = S_IFDIR | 0555; - stbuf->st_size = 4096; - stbuf->st_nlink = 1; + stbuf->st_mode = S_IFDIR | 0755; + stbuf->st_nlink = 3; stbuf->st_uid = getuid(); stbuf->st_gid = getgid(); stbuf->st_mtime = init_time; @@ -1269,6 +1268,24 @@ rf_read(const char *path, char *buf, size_t size, off_t offset, return 0; } +static int +rf_fsyncdir(const char * path, int p, struct fuse_file_info *fi) +{ + return 0; +} + +static int +rf_utime(const char *path, struct utimbuf *ubuf) +{ + return 0; +} + +static int +rf_statfs(const char *path, struct statvfs *buf) +{ + return 0; +} + /* rf_oper * * Used for: FUSE utilizes this to call operations at the appropriate time. @@ -1289,6 +1306,9 @@ static struct fuse_operations rf_oper = { .utime = rf_touch, .read = rf_read, .write = rf_write, + .fsyncdir = rf_fsyncdir, + .utime = rf_utime, + .statfs = rf_statfs, }; /* rf_set_root @@ -1330,38 +1350,6 @@ rf_handle_editor(VALUE self, VALUE troo) { return Qtrue; } -char *valid_options[] = { - "default_permissions", - "allow_other", - "allow_root", - "direct_io", - "max_read=", - "fsname=", - NULL -}; - -int -rf_valid_option(char *option) { - char opt[32]; - char *ptr; - int i; - - strncpy(opt,option,31); - - if (ptr = strchr(opt,'*')) { - ptr++; - *ptr = '\0'; - } - - for (i=0;valid_options[i];i++) { - if (!strcasecmp(valid_options[i],opt)) { - return 1; - } - } - - return 0; -} - /* rf_mount_to * * Used by: FuseFS.mount_to(dir) @@ -1370,13 +1358,10 @@ rf_valid_option(char *option) { */ VALUE rf_mount_to(int argc, VALUE *argv, VALUE self) { + struct fuse_args *opts; + VALUE mountpoint; int i; - char opts[1024]; - char opts2[1024]; char *cur; - VALUE mountpoint; - - snprintf(opts,1024,"direct_io"); if (self != cFuseFS) { rb_raise(cFSException,"Error: 'mount_to' called outside of FuseFS?!"); @@ -1390,17 +1375,18 @@ rf_mount_to(int argc, VALUE *argv, VALUE self) { mountpoint = argv[0]; - Check_Type(mountpoint, T_STRING); + Check_Type(mountpoint, T_STRING); + opts = ALLOC(struct fuse_args); + opts->argc = argc; + opts->argv = ALLOC_N(char *, opts->argc); + opts->allocated = 1; + + opts->argv[0] = strdup("-odirect_io"); - for (i = 1;i < argc; i++) { - Check_Type(argv[i], T_STRING); - cur = STR2CSTR(argv[i]); - if (!rf_valid_option(cur)) { - rb_raise(rb_eArgError,"mount_under: \"%s\" - invalid argument.", cur); - return Qnil; - } - snprintf(opts2,1024,"%s,%s",opts,STR2CSTR(argv[i])); - strcpy(opts,opts2); + for (i = 1; i < argc; i++) { + cur = StringValuePtr(argv[i]); + opts->argv[i] = ALLOC_N(char, RSTRING(argv[i])->len + 2); + sprintf(opts->argv[i], "-o%s", cur); } rb_iv_set(cFuseFS,"@mountpoint",mountpoint); diff --git a/ext/fusefs_lib.o b/ext/fusefs_lib.o deleted file mode 100644 index 756f76b..0000000 Binary files a/ext/fusefs_lib.o and /dev/null differ diff --git a/ext/mkmf.log b/ext/mkmf.log deleted file mode 100644 index 4f2b8ef..0000000 --- a/ext/mkmf.log +++ /dev/null @@ -1,12 +0,0 @@ -have_library: checking for main() in -lfuse... -------------------- yes - -"/usr/bin/gcc-4.2 -o conftest -I. -I/opt/local/lib/ruby/1.8/i686-darwin10 -I. -I/opt/local/include -D_XOPEN_SOURCE -D_DARWIN_C_SOURCE -I/opt/local/include -O2 -arch x86_64 -fno-common -pipe -fno-common conftest.c -L. -L/opt/local/lib -L. -L/opt/local/lib -arch x86_64 -lruby-static -lfuse -lpthread -ldl -lobjc " -checked program was: -/* begin */ -1: /*top*/ -2: int main() { return 0; } -3: int t() { void ((*volatile p)()); p = (void ((*)()))main; return 0; } -/* end */ - --------------------- - diff --git a/fusefs.gemspec b/fusefs.gemspec index 6e10416..52f0d7e 100644 --- a/fusefs.gemspec +++ b/fusefs.gemspec @@ -12,6 +12,7 @@ Gem::Specification.new do |s| s.date = %q{2009-09-18} s.description = %q{Gemified} s.email = %q{kyle@kylemaxwell.com} + s.extensions = ["ext/extconf.rb"] s.extra_rdoc_files = [ "LICENSE", "README" @@ -27,15 +28,11 @@ Gem::Specification.new do |s| "TODO", "VERSION", "ext/MANIFEST", - "ext/Makefile", "ext/extconf.rb", "ext/fusefs_fuse.c", "ext/fusefs_fuse.h", - "ext/fusefs_fuse.o", - "ext/fusefs_lib.bundle", "ext/fusefs_lib.c", - "ext/fusefs_lib.o", - "ext/mkmf.log", + "fusefs.gemspec", "lib/fusefs.rb", "sample/demo.rb", "sample/dictfs.rb", diff --git a/lib/fusefs.rb b/lib/fusefs.rb index 39a8379..145c3eb 100644 --- a/lib/fusefs.rb +++ b/lib/fusefs.rb @@ -10,14 +10,18 @@ module FuseFS @running = true def FuseFS.run fd = FuseFS.fuse_fd - io = IO.for_fd(fd) + begin + io = IO.for_fd(fd) + rescue Errno::EBADF + raise "fuse is not mounted" + end while @running IO.select([io]) FuseFS.process end end def FuseFS.unmount - system("fusermount -u #{@mountpoint}") + system("umount #{@mountpoint}") end def FuseFS.exit @running = false @@ -83,7 +87,7 @@ def file?(path) @subdirs[base].file?(rest) end end - + # File Reading def read_file(path) base, rest = split_path(path) @@ -98,7 +102,24 @@ def read_file(path) @subdirs[base].read_file(rest) end end - + + # File sizing + def size(path) + base, rest = split_path(path) + case + when base.nil? + 0 + when rest.nil? + obj = @files[base] + obj.respond_to?(:size) ? obj.size : 0 + when ! @subdirs.has_key?(base) + 0 + else + dir = @subdirs[base] + dir.respond_to?(:size) ? dir.size(rest) : 0 + end + end + # Write to a file def can_write?(path) return false unless Process.uid == FuseFS.reader_uid