950771fc287744266c1cf0510f5eb5c953535b5d
[rrq/fusefile.git] / fusefile-olydump.c
1 /***
2     fusefile-merge - merge a fusefile overlay into its underling
3
4     Copyright (C) 2023-  Ralph Ronnquist
5
6     This program is free software: you can redistribute it and/or
7     modify it under the terms of the GNU General Public License as
8     published by the Free Software Foundation, either version 3 of the
9     License, or (at your option) any later version.
10
11     This program is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14     General Public License for more details.
15
16     You should have received a copy of the GNU General Public License
17     along with this program. If not, see
18     <http://www.gnu.org/licenses/>.
19 */
20
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <unistd.h>
25 #include <time.h>
26 #include <errno.h>
27 #include <sys/types.h>
28 #include <sys/stat.h>
29 #include <fcntl.h>
30 #include <sys/mman.h>
31
32 /**
33  * An overlay file consists of a data block followed by a count of
34  * struct Region elements plus that many elements.
35  */
36 struct Region {
37     off_t beg;
38     off_t end;
39 };
40
41 /**
42  * Table head
43  */
44 struct Table {
45     size_t count;
46     struct Region regions[];
47 };
48
49 struct FileInfo {
50     char *name;
51     size_t size;
52 };
53
54 struct FileInfo basefile, olyfile;
55
56 /**
57  * 
58  */
59 static struct Table *loadtable() {
60     if ( basefile.size >= olyfile.size ) {
61 #if DEBUG
62         fprintf( stderr, "basefile.size >= olyfile.size\n" );
63 #endif
64         return 0;
65     }
66     size_t tbl = ( olyfile.size - basefile.size );
67     if ( ( tbl % sizeof( off_t ) ) != 0 ) {
68 #if DEBUG
69         fprintf( stderr, "( tbl %% sizeof( off_t ) ) != 0\n" );
70 #endif
71         return 0;
72     }
73     size_t count = tbl / sizeof( off_t );
74     if ( ( count & 1 ) == 0 ) { // Needs an odd number of off_t values
75 #if DEBUG
76         fprintf( stderr, "( count & 1 ) == 0\n" );
77 #endif
78         return 0;
79     }
80     count = ( count - 1 ) / 2;
81     int fd = open( olyfile.name, O_RDONLY );
82     if ( fd < 0 ) {
83         perror( olyfile.name );
84         return 0;
85     }
86     struct Table *ptr =
87         mmap( 0, tbl, PROT_READ, MAP_PRIVATE, fd, basefile.size );
88     return  ( ptr->count != count )? 0 : ptr;
89 }
90
91 static void usage() {
92     fprintf( stderr, "Usage: basefile overlayfile\n" );
93     exit( 1 );
94 }
95
96 /**
97  * Application entry. This program dumps the overlay table as a
98  * fusefile fragments sequence, with newline?
99  */
100 int main(int argc,char **argv) {
101     static struct stat info;
102     
103     if ( argc != 3 ) {
104         usage();
105     }
106     basefile.name = argv[1];
107     if ( stat( basefile.name, &info ) ) {
108         perror( basefile.name );
109         exit( 1 );
110     }
111     basefile.size = info.st_size;
112     
113     olyfile.name = argv[2];
114     if ( stat( olyfile.name, &info ) ) {
115         perror( olyfile.name );
116         exit( 1 );
117     }
118     olyfile.size = info.st_size;
119
120     struct Table *table = loadtable();
121     if ( table == 0 ) {
122         fprintf( stderr, "%s is not onverlay for %s\n",
123                  olyfile.name, basefile.name );
124         fprintf( stderr, "   %s: %ld\n", basefile.name, basefile.size );
125         fprintf( stderr, "   %s: %ld\n", olyfile.name, olyfile.size );
126         exit( 1 );
127     }
128     int i;
129     size_t pos = 0;
130     for ( i = 0; i < table->count; i++ ) {
131         struct Region *r = &(table->regions[i]);
132         if ( pos < r->beg ) {
133             fprintf( stdout, "%s/%ld:%ld\n", basefile.name, pos, r->beg );
134         }
135         fprintf( stdout, "%s/%ld:%ld\n", olyfile.name, r->beg, r->end );
136         pos = r->end;
137     }
138     if ( pos < basefile.size ) {
139         fprintf( stdout, "%s/%ld:%ld\n", basefile.name, pos, basefile.size );
140     }
141     return( 0 );
142 }