+/**
+ * Inject an overlay fragment into the source table, end return the
+ * end of the injected fragment.
+ */
+static off_t overlay_inject_from_region(off_t beg,off_t end) {
+ int index = find_source( beg );
+ if ( index < 0 ) {
+ fprintf( stderr, "** Injecting %s at %ld failed\n",
+ overlay.source.filename, beg );
+ usage();
+ }
+ if ( end > ENDSOURCE( sources.array[ index ] ) ) {
+ end = ENDSOURCE( sources.array[ index ] );
+ }
+ struct Region frags[3] = {
+ { sources.array[ index ].start, beg },
+ { beg, end },
+ { end, ENDSOURCE( sources.array[ index ] ) } };
+#if DEBUG
+ int i;
+ for ( i = 0; i < 3; i++ ) {
+ fprintf( stderr, "frags[%d] = (%ld, %ld)\n",
+ i, frags[i].beg, frags[i].end );
+ }
+#endif
+ ssize_t size = frags[0].end - frags[0].beg;
+ if ( size ) {
+ // Handle any portion before injection point.
+ dup_source_item( index );
+ off_t point = sources.array[ index ].from + size;
+ sources.array[ index ].to = point;
+#if DEBUG
+ fprintf( stderr, "item %d ", index );
+ print_source( &sources.array[ index ] );
+#endif
+ // Adjust item after injection point
+ index++;
+ sources.array[ index ].start = beg;
+ sources.array[ index ].from = point;
+#if DEBUG
+ fprintf( stderr, "item %d adjust ", index );
+ print_source( &sources.array[ index ] );
+#endif
+ }
+ size = frags[2].end - frags[2].beg;
+ if ( size ) {
+ // Handle any remaining portion following injection fragment
+ dup_source_item( index );
+ sources.array[ index+1 ].start = frags[2].beg;
+ sources.array[ index+1 ].from += frags[1].end - frags[1].beg;
+#if DEBUG
+ fprintf( stderr, "item %d ", index+1 );
+ print_source( &sources.array[ index+1 ] );
+#endif
+ }
+ // Set up the injection fragment
+ sources.array[ index ].filename = overlay.source.filename;
+ sources.array[ index ].from = beg;
+ sources.array[ index ].to = end;
+ sources.array[ index ].fd = overlay.source.fd;
+#if DEBUG
+ fprintf( stderr, "item %d ", index );
+ print_source( &sources.array[ index ] );
+#endif
+ return end;
+}
+
+/**
+ * Inject the current (unopened) overlay into the source list.
+ */
+static void overlay_inject() {
+ overlay.source.fd = open( overlay.source.filename, O_RDONLY );
+ if ( overlay.source.fd < 0 ) {
+ perror( overlay.source.filename );
+ usage();
+ }
+
+ if ( lseek( overlay.source.fd, overlay.source.to, SEEK_SET ) < 0 ) {
+ perror( overlay.source.filename );
+ usage();
+ }
+ size_t count = 0;
+ size_t size = sizeof( overlay.count );
+ size_t n;
+ if ( ( n = read( overlay.source.fd, &count, size ) ) != size ) {
+ if ( n != 0 ) {
+ fprintf( stderr, "** error injecting %s\n",
+ overlay.source.filename );
+ usage();
+ }
+ fprintf( stderr, "** ignoring empty %s\n", overlay.source.filename );
+ }
+ if ( count == 0 ) {
+ close( overlay.source.fd );
+ return;
+ }
+ size = count * sizeof( struct Region );
+ overlay.table = calloc( sizeof( struct Region ), count );
+ if ( read( overlay.source.fd, overlay.table, size ) != size ) {
+ fprintf( stderr, "** error injecting %s\n", overlay.source.filename );
+ usage();
+ }
+ size_t i;
+ for ( i = 0; i < count; i++ ) {
+ off_t beg = overlay.table[i].beg;
+ while ( beg < overlay.table[i].end ) {
+#if DEBUG
+ fprintf( stderr, "inject [%ld,%ld] ", beg, overlay.table[i].end );
+ print_source( &overlay.source );
+#endif
+
+ beg = overlay_inject_from_region( beg, overlay.table[i].end );
+ }
+ }
+ free( overlay.table );
+ overlay.table = 0;
+}
+
+/**
+ * Each stacked overlay file is nested into to source list
+ */
+static void overlay_post_setup() {
+ char *end;
+ while ( ( end = strchr( overlay.source.filename, ':' ) ) ) {
+ *end = 0; //
+ overlay_inject();
+ overlay.source.filename = end + 1;
+ }
+ if ( *overlay.source.filename ) {
+ overlay.source.fd = open( overlay.source.filename,
+ O_RDWR | O_CREAT, S_IRUSR | S_IWUSR );
+ if ( overlay.source.fd < 0 ) {
+ perror( overlay.source.filename );
+ usage();
+ }
+ overlay_load();
+ }
+}
+