-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 On Tuesday 08 October 2002 00:13, you wrote: > On Monday 07 October 2002 16:01, Alon Barzilai wrote: > > mount -t iso9660 -o ro 1.iso /mnt/disk1 > > mount -t iso9660 -o ro 2.iso /mnt/disk1 > > This is called "union mount". Linux does not have this feature (I think BSD > has it).
Actually, there were some noises made by Al Viro that were implying that this is something which is in his tree. Meanwhile - If you are into development then you can use use (file systems in user space) and the attached file (by yours truly) to get you started. I haven't tested it well and I *** KNOW *** that it has problems and just didn't have any time to work on it.... What can you expect out of 25 minutes of coding ?...:) Have fun Mark -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.0.6 (GNU/Linux) Comment: For info see http://www.gnupg.org iD8DBQE9ohECxlxDIcceXTgRAg/hAJ43vOxo5r9EdcLYVdV4Qi7EBwnTbwCeI8Vu 718vcwQ8HO8QV7aa/IUEsbk= =Sf5b -----END PGP SIGNATURE-----
diff -urN fuse-0.95/example/Makefile.am fuse-0.95-mark/example/Makefile.am --- fuse-0.95/example/Makefile.am Wed Nov 21 11:52:42 2001 +++ fuse-0.95-mark/example/Makefile.am Thu Jan 10 16:08:26 2002 @@ -1,9 +1,11 @@ ## Process this file with automake to produce Makefile.in -noinst_PROGRAMS = fusexmp null hello +noinst_PROGRAMS = fusexmp null hello mount union_mount fusexmp_SOURCES = fusexmp.c null_SOURCES = null.c hello_SOURCES = hello.c +mount_SOURCES = mount.c +union_mount_SOURCES = union_mount.c LDADD = ../lib/libfuse.a -lpthread diff -urN fuse-0.95/example/Makefile.in fuse-0.95-mark/example/Makefile.in --- fuse-0.95/example/Makefile.in Wed Jan 9 15:51:33 2002 +++ fuse-0.95-mark/example/Makefile.in Thu Jan 10 16:11:27 2002 @@ -1,6 +1,6 @@ -# Makefile.in generated automatically by automake 1.4-p4 from Makefile.am +# Makefile.in generated automatically by automake 1.4-p5 from Makefile.am -# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc. +# Copyright (C) 1994, 1995-8, 1999, 2001 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. @@ -66,11 +66,13 @@ VERSION = @VERSION@ kmoduledir = @kmoduledir@ -noinst_PROGRAMS = fusexmp null hello +noinst_PROGRAMS = fusexmp null hello mount union_mount fusexmp_SOURCES = fusexmp.c null_SOURCES = null.c hello_SOURCES = hello.c +mount_SOURCES = mount.c +union_mount_SOURCES = union_mount.c LDADD = ../lib/libfuse.a -lpthread mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs @@ -95,6 +97,14 @@ hello_LDADD = $(LDADD) hello_DEPENDENCIES = ../lib/libfuse.a hello_LDFLAGS = +mount_OBJECTS = mount.o +mount_LDADD = $(LDADD) +mount_DEPENDENCIES = ../lib/libfuse.a +mount_LDFLAGS = +union_mount_OBJECTS = union_mount.o +union_mount_LDADD = $(LDADD) +union_mount_DEPENDENCIES = ../lib/libfuse.a +union_mount_LDFLAGS = CFLAGS = @CFLAGS@ COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) CCLD = $(CC) @@ -104,10 +114,10 @@ DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST) -TAR = tar +TAR = gtar GZIP_ENV = --best -SOURCES = $(fusexmp_SOURCES) $(null_SOURCES) $(hello_SOURCES) -OBJECTS = $(fusexmp_OBJECTS) $(null_OBJECTS) $(hello_OBJECTS) +SOURCES = $(fusexmp_SOURCES) $(null_SOURCES) $(hello_SOURCES) $(mount_SOURCES) $(union_mount_SOURCES) +OBJECTS = $(fusexmp_OBJECTS) $(null_OBJECTS) $(hello_OBJECTS) $(mount_OBJECTS) $(union_mount_OBJECTS) all: all-redirect .SUFFIXES: @@ -160,6 +170,14 @@ @rm -f hello $(LINK) $(hello_LDFLAGS) $(hello_OBJECTS) $(hello_LDADD) $(LIBS) +mount: $(mount_OBJECTS) $(mount_DEPENDENCIES) + @rm -f mount + $(LINK) $(mount_LDFLAGS) $(mount_OBJECTS) $(mount_LDADD) $(LIBS) + +union_mount: $(union_mount_OBJECTS) $(union_mount_DEPENDENCIES) + @rm -f union_mount + $(LINK) $(union_mount_LDFLAGS) $(union_mount_OBJECTS) $(union_mount_LDADD) $(LIBS) + tags: TAGS ID: $(HEADERS) $(SOURCES) $(LISP) @@ -204,7 +222,6 @@ || cp -p $$d/$$file $(distdir)/$$file || :; \ fi; \ done - info-am: info: info-am dvi-am: diff -urN fuse-0.95/example/fusexmp.c fuse-0.95-mark/example/fusexmp.c --- fuse-0.95/example/fusexmp.c Tue Jan 8 11:40:12 2002 +++ fuse-0.95-mark/example/fusexmp.c Thu Jan 10 16:12:06 2002 @@ -18,6 +18,7 @@ #include <dirent.h> #include <errno.h> #include <sys/statfs.h> +#include <string.h> static int xmp_getattr(const char *path, struct stat *stbuf) { diff -urN fuse-0.95/example/hello.c fuse-0.95-mark/example/hello.c --- fuse-0.95/example/hello.c Tue Jan 8 11:40:12 2002 +++ fuse-0.95-mark/example/hello.c Thu Jan 10 14:39:15 2002 @@ -10,6 +10,7 @@ #include <stdio.h> #include <errno.h> #include <fcntl.h> +#include <string.h> static const char *hello_str = "Hello World!\n"; static const char *hello_path = "/hello"; diff -urN fuse-0.95/example/mount.c fuse-0.95-mark/example/mount.c --- fuse-0.95/example/mount.c Thu Jan 1 02:00:00 1970 +++ fuse-0.95-mark/example/mount.c Thu Jan 10 16:09:02 2002 @@ -0,0 +1,286 @@ +/* + FUSE: Filesystem in Userspace + Copyright (C) 2001 Miklos Szeredi ([EMAIL PROTECTED]) + + This program can be distributed under the terms of the GNU GPL. + See the file COPYING. + + This example shows mounting of single directory (whatever file system + it is originally). +*/ + +#ifdef linux +/* For pread()/pwrite() */ +#define _XOPEN_SOURCE 500 +#endif + +#include <fuse.h> +#include <stdio.h> +#include <unistd.h> +#include <fcntl.h> +#include <dirent.h> +#include <errno.h> +#include <sys/statfs.h> +#include <string.h> + +static char* dir="/home/mark/first"; +#define SIZE 1024 + +static void copy_it(const char* path,char* temp) { + *temp='\0'; + strncat(temp,dir,SIZE); + strncat(temp,path,SIZE); +} + +static int xmp_getattr(const char *path, struct stat *stbuf) +{ + int res; + char temp[SIZE]; + copy_it(path,temp); + res=lstat(temp, stbuf); + if(res==-1) + return(-errno); + return(0); +} + +static int xmp_readlink(const char *path, char *buf, size_t size) +{ + int res; + char temp[SIZE]; + copy_it(path,temp); + res=readlink(temp,buf,size-1); + if(res==-1) + return(-errno); + buf[res]='\0'; + return 0; +} + + +static int xmp_getdir(const char *path, fuse_dirh_t h, fuse_dirfil_t filler) +{ + DIR *dp; + struct dirent *de; + int res = 0; + char temp[SIZE]; + copy_it(path,temp); + dp=opendir(temp); + if(dp==NULL) + return(-errno); + while((de = readdir(dp)) != NULL) { + res = filler(h, de->d_name, de->d_type); + if(res != 0) + break; + } + closedir(dp); + return(res); +} + +static int xmp_mknod(const char *path, mode_t mode, dev_t rdev) +{ + int res; + char temp[SIZE]; + copy_it(path,temp); + res=mknod(temp,mode,rdev); + if(res==-1) + return(-errno); + return(0); +} + +static int xmp_mkdir(const char *path, mode_t mode) +{ + int res; + char temp[SIZE]; + copy_it(path,temp); + res=mkdir(temp,mode); + if(res==-1) + return(-errno); + return(0); +} + +static int xmp_unlink(const char *path) +{ + int res; + char temp[SIZE]; + copy_it(path,temp); + res = unlink(temp); + if(res == -1) + return -errno; + return 0; +} + +static int xmp_rmdir(const char *path) +{ + int res; + char temp[SIZE]; + copy_it(path,temp); + res=rmdir(temp); + if(res==-1) + return(-errno); + return 0; +} + +static int xmp_symlink(const char *from, const char *to) +{ + int res; + char from_temp[SIZE]; + char to_temp[SIZE]; + copy_it(from,from_temp); + copy_it(to,to_temp); + res = symlink(from_temp, to_temp); + if(res == -1) + return(-errno); + return 0; +} + +static int xmp_rename(const char *from, const char *to) +{ + int res; + char from_temp[SIZE]; + char to_temp[SIZE]; + copy_it(from,from_temp); + copy_it(to,to_temp); + res = rename(from_temp, to_temp); + if(res == -1) + return -errno; + return 0; +} + +static int xmp_link(const char *from, const char *to) +{ + int res; + char from_temp[SIZE]; + char to_temp[SIZE]; + copy_it(from,from_temp); + copy_it(to,to_temp); + res = link(from_temp, to_temp); + if(res == -1) + return -errno; + return 0; +} + +static int xmp_chmod(const char *path, mode_t mode) +{ + int res; + char temp[SIZE]; + copy_it(path,temp); + res = chmod(temp, mode); + if(res == -1) + return -errno; + return 0; +} + +static int xmp_chown(const char *path, uid_t uid, gid_t gid) +{ + int res; + char temp[SIZE]; + copy_it(path,temp); + res = lchown(temp, uid, gid); + if(res == -1) + return -errno; + return 0; +} + +static int xmp_truncate(const char *path, off_t size) +{ + int res; + char temp[SIZE]; + copy_it(path,temp); + res = truncate(temp, size); + if(res == -1) + return -errno; + return 0; +} + +static int xmp_utime(const char *path, struct utimbuf *buf) +{ + int res; + char temp[SIZE]; + copy_it(path,temp); + res = utime(temp, buf); + if(res == -1) + return -errno; + return 0; +} + + +static int xmp_open(const char *path, int flags) +{ + int res; + char temp[SIZE]; + copy_it(path,temp); + res = open(temp, flags); + if(res == -1) + return(-errno); + close(res); + return 0; +} + +static int xmp_read(const char *path, char *buf, size_t size, off_t offset) +{ + int fd; + int res; + char temp[SIZE]; + copy_it(path,temp); + fd = open(temp, O_RDONLY); + if(fd == -1) + return -errno; + res = pread(fd, buf, size, offset); + if(res == -1) + res = -errno; + close(fd); + return res; +} + +static int xmp_write(const char *path, const char *buf, size_t size, + off_t offset) +{ + int fd; + int res; + char temp[SIZE]; + copy_it(path,temp); + fd = open(temp, O_RDONLY); + fd = open(temp, O_WRONLY); + if(fd == -1) + return -errno; + res = pwrite(fd, buf, size, offset); + if(res == -1) + res = -errno; + close(fd); + return res; +} + +static int xmp_statfs(struct statfs *fst) +{ + struct statfs st; + int rv = statfs(dir,&st); + if(!rv) + memcpy(fst,&st,sizeof(st)); + return rv; +} + +static struct fuse_operations xmp_oper = { + getattr: xmp_getattr, + readlink: xmp_readlink, + getdir: xmp_getdir, + mknod: xmp_mknod, + mkdir: xmp_mkdir, + symlink: xmp_symlink, + unlink: xmp_unlink, + rmdir: xmp_rmdir, + rename: xmp_rename, + link: xmp_link, + chmod: xmp_chmod, + chown: xmp_chown, + truncate: xmp_truncate, + utime: xmp_utime, + open: xmp_open, + read: xmp_read, + write: xmp_write, + statfs: xmp_statfs, +}; + +int main(int argc, char *argv[]) +{ + fuse_main(argc, argv, &xmp_oper); + return 0; +} diff -urN fuse-0.95/example/null.c fuse-0.95-mark/example/null.c --- fuse-0.95/example/null.c Tue Jan 8 11:40:12 2002 +++ fuse-0.95-mark/example/null.c Wed Jan 9 19:18:21 2002 @@ -11,6 +11,7 @@ #include <unistd.h> #include <time.h> #include <errno.h> +#include <string.h> #define UNUSED __attribute__((unused)) diff -urN fuse-0.95/example/union_mount.c fuse-0.95-mark/example/union_mount.c --- fuse-0.95/example/union_mount.c Thu Jan 1 02:00:00 1970 +++ fuse-0.95-mark/example/union_mount.c Thu Jan 10 16:10:59 2002 @@ -0,0 +1,341 @@ +/* + FUSE: Filesystem in Userspace + Copyright (C) 2001 Miklos Szeredi ([EMAIL PROTECTED]) + + This program can be distributed under the terms of the GNU GPL. + See the file COPYING. + + This example shows how to union mount two or more directories. + It creates a single directory where files in all directories are + shown. When writing to the directory, the directory designated by + a special number is the only one which gets written to. This + could be useful for many things (change a single file on a CDROM + without copying it's content to a hard drive ? you get my meaning...). +*/ + +#ifdef linux +/* For pread()/pwrite() */ +#define _XOPEN_SOURCE 500 +#endif + +#include <fuse.h> +#include <stdio.h> +#include <unistd.h> +#include <fcntl.h> +#include <dirent.h> +#include <errno.h> +#include <sys/statfs.h> +#include <string.h> + +#define SIZE 1024 +#define NUM 2 +#define NODE 1 +static const char dir[NUM][SIZE]={ + "/home/mark/test/second", + "/home/mark/test/first" +}; + +static void copy_it(const char* path,char* temp,const char* dir) { + *temp='\0'; + strncat(temp,dir,SIZE); + strncat(temp,path,SIZE); +} + +static int xmp_getattr(const char *path, struct stat *stbuf) +{ + int res; + int i; + int found=0; + for(i=0;i<NUM;i++) { + char temp[SIZE]; + copy_it(path,temp,dir[i]); + res=lstat(temp, stbuf); + if(res!=-1) { + found=1; + return(0); + } + } + return(-1); +} + +static int xmp_readlink(const char *path, char *buf, size_t size) +{ + int res; + int i; + for(i=0;i<NUM;i++) { + char temp[SIZE]; + copy_it(path,temp,dir[i]); + res=readlink(temp,buf,size-1); + if(res!=-1) { + buf[res]='\0'; + return(0); + } + } + return(-1); +} + +/* FIXME: add hash to avoid duplicates here */ +static int xmp_getdir(const char *path, fuse_dirh_t h, fuse_dirfil_t filler) +{ + DIR *dp; + struct dirent *de; + int res = 0; + int i; + int error=1; + for(i=0;i<NUM;i++) { + char temp[SIZE]; + copy_it(path,temp,dir[i]); + dp=opendir(temp); + if(dp==NULL) + continue; + error=0; + while((de = readdir(dp)) != NULL) { + res = filler(h, de->d_name, de->d_type); + if(res != 0) + break; + } + closedir(dp); + } + if(error) { + return(-1); + } else { + return(0); + } +} + +static int xmp_mknod(const char *path, mode_t mode, dev_t rdev) +{ + int res; + char temp[SIZE]; + copy_it(path,temp,dir[NODE]); + res=mknod(temp,mode,rdev); + if(res==-1) + return(-errno); + return(0); +} + +static int xmp_mkdir(const char *path, mode_t mode) +{ + int res; + char temp[SIZE]; + copy_it(path,temp,dir[NODE]); + res=mkdir(temp,mode); + if(res==-1) + return(-errno); + return(0); +} + +static int xmp_unlink(const char *path) +{ + int res; + char temp[SIZE]; + copy_it(path,temp,dir[NODE]); + res = unlink(temp); + if(res == -1) + return -errno; + return 0; +} + +static int xmp_rmdir(const char *path) +{ + int res; + char temp[SIZE]; + copy_it(path,temp,dir[NODE]); + res=rmdir(temp); + if(res==-1) + return(-errno); + return 0; +} + +static int xmp_symlink(const char *from, const char *to) +{ + int res; + char from_temp[SIZE]; + char to_temp[SIZE]; + copy_it(from,from_temp,dir[NODE]); + copy_it(to,to_temp,dir[NODE]); + res = symlink(from_temp, to_temp); + if(res == -1) + return(-errno); + return 0; +} + +static int xmp_rename(const char *from, const char *to) +{ + int res; + char from_temp[SIZE]; + char to_temp[SIZE]; + copy_it(from,from_temp,dir[NODE]); + copy_it(to,to_temp,dir[NODE]); + res = rename(from_temp, to_temp); + if(res == -1) + return -errno; + return 0; +} + +static int xmp_link(const char *from, const char *to) +{ + int res; + char from_temp[SIZE]; + char to_temp[SIZE]; + copy_it(from,from_temp,dir[NODE]); + copy_it(to,to_temp,dir[NODE]); + res = link(from_temp, to_temp); + if(res == -1) + return -errno; + return 0; +} + +static int xmp_chmod(const char *path, mode_t mode) +{ + int i; + for(i=0;i<NUM;i++) { + int res; + char temp[SIZE]; + copy_it(path,temp,dir[i]); + res = chmod(temp, mode); + if(res != -1) + return (0); + } + return(-1); +} + +static int xmp_chown(const char *path, uid_t uid, gid_t gid) +{ + int i; + for(i=0;i<NUM;i++) { + int res; + char temp[SIZE]; + copy_it(path,temp,dir[i]); + res = lchown(temp, uid, gid); + if(res != -1) { + return(0); + } + } + return(-1); +} + +static int xmp_truncate(const char *path, off_t size) +{ + int i; + for(i=0;i<NUM;i++) { + int res; + char temp[SIZE]; + copy_it(path,temp,dir[i]); + res = truncate(temp, size); + if(res != -1) { + return(0); + } + } + return(-1); +} + +static int xmp_utime(const char *path, struct utimbuf *buf) +{ + int i; + for(i=0;i<NUM;i++) { + int res; + char temp[SIZE]; + copy_it(path,temp,dir[i]); + res = utime(temp, buf); + if(res!=-1) { + return(0); + } + } + return(-1); +} + + +static int xmp_open(const char *path, int flags) +{ + int i; + for(i=0;i<NUM;i++) { + int res; + char temp[SIZE]; + copy_it(path,temp,dir[i]); + res = open(temp, flags); + if(res!=-1) { + close(res); + return(0); + } + } + return(-1); +} + +static int xmp_read(const char *path, char *buf, size_t size, off_t offset) +{ + int i; + for(i=0;i<NUM;i++) { + int fd; + int res; + char temp[SIZE]; + copy_it(path,temp,dir[i]); + fd = open(temp, O_RDONLY); + if(fd==-1) + continue; + res=pread(fd, buf, size, offset); + if(res!=-1) { + close(fd); + return(0); + } + } + return(-1); +} + +static int xmp_write(const char *path, const char *buf, size_t size, + off_t offset) +{ + int i; + for(i=0;i<NUM;i++) { + int fd; + int res; + char temp[SIZE]; + copy_it(path,temp,dir[i]); + fd = open(temp, O_RDONLY); + fd = open(temp, O_WRONLY); + if(fd == -1) + continue; + res = pwrite(fd, buf, size, offset); + if(res!=-1) { + close(fd); + return(0); + } + } + return(-1); +} + +static int xmp_statfs(struct statfs *fst) +{ + struct statfs st; + int rv = statfs(dir[NODE],&st); + if(!rv) + memcpy(fst,&st,sizeof(st)); + return rv; +} + +static struct fuse_operations xmp_oper = { + getattr: xmp_getattr, + readlink: xmp_readlink, + getdir: xmp_getdir, + mknod: xmp_mknod, + mkdir: xmp_mkdir, + symlink: xmp_symlink, + unlink: xmp_unlink, + rmdir: xmp_rmdir, + rename: xmp_rename, + link: xmp_link, + chmod: xmp_chmod, + chown: xmp_chown, + truncate: xmp_truncate, + utime: xmp_utime, + open: xmp_open, + read: xmp_read, + write: xmp_write, + statfs: xmp_statfs, +}; + +int main(int argc, char *argv[]) +{ + fuse_main(argc, argv, &xmp_oper); + return 0; +}