time_t mtime;
time_t ctime;
} times;
-
+
+static struct Source overlay;
+
#if DEBUG
static void print_source(struct Source *p) {
fprintf( stderr, "%p { %s, %ld, %ld, %ld, %d }\n",
return ( s == n ) && *(range+c) == 0;
}
+static void usage();
+
+static void setup_overlay(char *filename) {
+ overlay.filename = filename;
+ overlay.fd = open( filename, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR );
+ if ( overlay.fd < 0 ) {
+ perror( filename );
+ usage();
+ }
+}
+
static int setup_sources(char **argv,int i,int n) {
sources.array = calloc( n, sizeof( struct Source ) );
if ( sources.array == 0 ) {
return lo;
}
+#define OBUFSZ 1048576
+static int overlay_merge(char *buf,off_t off,size_t size) {
+ static char obuf[ OBUFSZ ];
+#if DEBUG
+ fprintf( stderr, "merge %ld %ld\n", off, size );
+#endif
+ while ( size > 0 ) {
+ size_t n = size < OBUFSZ? size : OBUFSZ;
+ off_t ox = lseek( overlay.fd, off, SEEK_SET );
+#if DEBUG
+ fprintf( stderr, " seek %ld %ld %ld\n", off, ox, n );
+#endif
+ if ( ox < 0 ) {
+ perror( overlay.filename );
+ return -ENOENT;
+ }
+ if ( ox < off ) {
+ break;
+ }
+ n = read( overlay.fd, obuf, n );
+#if DEBUG
+ fprintf( stderr, " got %ld\n", n );
+#endif
+ if ( n < 0 ) {
+ perror( overlay.filename );
+ return -ENOENT;
+ }
+ if ( n == 0 ) {
+ break;
+ }
+ char *p = obuf;
+ while ( n-- > 0 ) {
+ if ( *p ) {
+ *buf = *p;
+ }
+ p++;
+ buf++;
+ size--;
+ off++;
+ }
+ }
+#if DEBUG
+ fprintf( stderr, "merged\n" );
+#endif
+ return 0;
+}
+
// Read <size> bytes from <offset> in file
static int fusefile_read(const char *path, char *buf, size_t size,
off_t off, struct fuse_file_info *fi)
n, sources.array[i].fd );
#endif
ssize_t r = read( sources.array[i].fd, buf + rr, n );
+ if ( overlay.filename ) {
+ int x = overlay_merge( buf + rr, off + rr, r );
+ if ( x ) {
+ return x;
+ }
+ }
#if DEBUG
fprintf( stderr, " got %ld bytes\n", r );
#endif
if ( index < 0 ) {
return -EIO; // past EOF
}
- struct Source *source = &sources.array[ index ];
+ struct Source *source =
+ overlay.filename? &overlay : &sources.array[ index ];
off_t from = off - source->start + source->from;
off_t max = source->to - from;
if ( lseek( source->fd, from, SEEK_SET ) < 0 ) {
}
fuseargc = i;
mnt = argv[ i++ ]; // First non-option argument is the mount pount
+ char *overlaytag = "-overlay:";
+ int overlaytagsize = strlen( overlaytag );
+ if ( strncmp( argv[i], overlaytag, overlaytagsize ) == 0 ) {
+ // consume "-overlay:filename"
+ setup_overlay( argv[i++] + overlaytagsize ); // Need a writable file
+ if ( i >= argc ) {
+ usage();
+ }
+ }
if ( setup_sources( argv, i, argc-i ) ) {
return 1;
}
+ overlay.to = sources.size; // Register total size.
if ( stat( mnt, &stbuf ) == -1 ) {
int fd = open( mnt, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR );
if ( fd < 0 ) {