From: Ralph Ronnquist Date: Sun, 7 Aug 2022 07:06:49 +0000 (+1000) Subject: added overlay option X-Git-Tag: 0.5~4 X-Git-Url: https://git.rrq.au/?a=commitdiff_plain;h=a31db9efc8aa6da6cffecf4cff409730e96cbb86;p=rrq%2Ffusefile.git added overlay option --- diff --git a/fusefile.c b/fusefile.c index 59dcaa5..8371d1f 100644 --- a/fusefile.c +++ b/fusefile.c @@ -53,7 +53,9 @@ static struct { 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", @@ -67,6 +69,17 @@ static int RANGE(int s,int 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 ) { @@ -225,6 +238,53 @@ static int find_source(off_t offset) { 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 bytes from in file static int fusefile_read(const char *path, char *buf, size_t size, off_t off, struct fuse_file_info *fi) @@ -271,6 +331,12 @@ static int fusefile_read(const char *path, char *buf, size_t size, 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 @@ -322,7 +388,8 @@ static int write_block(off_t off,const char *buf,size_t size) { 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 ) { @@ -539,9 +606,19 @@ int main(int argc, char *argv[]) } 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 ) {