touchup code so we handle errors better
[portage.git] / src / tbz2tool.c
1 /* $Id: /var/cvsroot/gentoo-src/portage/src/tbz2tool.c,v 1.3.2.1 2004/11/05 13:49:22 jstubbs Exp $ */
2
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <sys/types.h>
6 #include <sys/stat.h>
7 #include <unistd.h>
8 #include <errno.h>
9 #include <string.h>
10
11 /*buffered reading/writing size*/
12 #define BUFLEN 262144 
13 char *myname="tbz2tool";
14 struct stat *mystat=NULL;
15 void *mybuf;
16 FILE *datafile, *dbfile, *outfile, *infile;
17 unsigned char endbuf[8];
18 long seekto,insize;
19
20 int exists(const char *myfile) {
21         int result;
22         result=stat(myfile,mystat);
23         if (result==-1)
24                 return 0;
25         return 1;
26 }
27
28 void writefile(FILE *src, FILE *dest) {
29         int count=1;
30         while (count) {
31                 count=fread(mybuf, 1, BUFLEN, src);
32                 fwrite(mybuf, 1, count, dest);
33         }
34 }
35
36 void writefileto(FILE *src, FILE *dest, int endpos) {
37         int pos=ftell(src);
38         int thiscount;
39         while (pos < endpos) {
40                 /* thiscount=how much to read */
41                 thiscount=endpos-pos;
42                 if (thiscount>BUFLEN)
43                         thiscount=BUFLEN;
44                 thiscount=fread(mybuf, 1, thiscount , src);
45                 /* thiscount=how much we actually did read */
46                 if (thiscount==0)
47                         /* eof -- shouldn't happen */
48                         break;
49                 /* update internal position counter */
50                 pos+=thiscount;
51                 fwrite(mybuf, 1, thiscount, dest);
52         }
53 }
54
55 int main(int argc, char **argv) {
56         if ((argc==2) && (!(strcmp(argv[1],"--help"))))
57                 goto usage;
58         if (argc!=5) {
59                 printf("%s: four arguments expected\n",myname);
60                 goto error;
61         }
62         if (!(mystat=(struct stat *) malloc(sizeof(struct stat))))
63                 goto memalloc;
64                 
65         if (!(mybuf=(void *) malloc(BUFLEN))) {
66                 free(mystat);
67                 goto memalloc;
68         }
69         
70         /* JOIN MODE */
71         if (!(strcmp(argv[1],"join"))) {
72         
73                 /* check if datafile exists */
74                 if (!(exists(argv[2]))) {
75                         printf("%s: %s doesn't exist\n",myname,argv[2]);
76                         free(mystat);
77                         goto error;
78                 }
79                 
80                 /* check if dbfile exists */
81                 if (!(exists(argv[3]))) {
82                         printf("%s: %s doesn't exist\n",myname,argv[3]);
83                         free(mystat);
84                         goto error;
85                 }
86                 /* create end buffer for later use */
87                 endbuf[0]=((mystat->st_size) & 0xff000000) >> 24;
88                 endbuf[1]=((mystat->st_size) & 0x00ff0000) >> 16;
89                 endbuf[2]=((mystat->st_size) & 0x0000ff00) >> 8;
90                 endbuf[3]=(mystat->st_size) & 0x000000ff;
91                 endbuf[4]='S';
92                 endbuf[5]='T';
93                 endbuf[6]='O';
94                 endbuf[7]='P';
95         
96                 /* if outfile exists, unlink first (safer) */
97                 if (exists(argv[4])) 
98                         unlink(argv[4]);
99                 
100                 /* open datafile for reading */
101                 if ((datafile=fopen(argv[2],"r"))==NULL) {
102                         free(mybuf);
103                         free(mystat);
104                         printf("%s: Error opening %s\n",myname,argv[2]);
105                         goto error;
106                 }
107                 
108                 /* open dbfile for reading */
109                 if ((dbfile=fopen(argv[3],"r"))==NULL) {
110                         fclose(datafile);
111                         free(mybuf);
112                         free(mystat);
113                         printf("%s: Error opening %s\n",myname,argv[3]);
114                         goto error;
115                 }
116         
117                 /* open outfile for writing */
118                 if ((outfile=fopen(argv[4],"a"))==NULL) {
119                         fclose(dbfile);
120                         fclose(datafile);
121                         free(mybuf);
122                         free(mystat);
123                         printf("%s: Error opening %s\n",myname,argv[4]);
124                         goto error;
125                 }
126         
127                 writefile(datafile,outfile);
128                 writefile(dbfile,outfile);
129                 fwrite(endbuf,1,8,outfile);
130                 fclose(outfile);
131                 fclose(dbfile);
132                 fclose(datafile);
133                 free(mybuf);
134                 free(mystat);
135                 exit(0);        
136         
137         /* SPLIT MODE */
138         } else if (!(strcmp(argv[1],"split"))) {
139         
140                 /* check if infile exists */
141                 if (!(exists(argv[2]))) {
142                         printf("%s: %s doesn't exist\n",myname,argv[2]);
143                         free(mystat);
144                         goto error;
145                 }
146                 
147                 /* store infile size for later use */
148
149                 insize=mystat->st_size;
150                 
151                 /* if datafile exists, unlink first (safer) */
152                 if (exists(argv[3])) 
153                         unlink(argv[3]);
154                 
155                 /* if dbfile exists, unlink first (safer) */
156                 if (exists(argv[4])) 
157                         unlink(argv[4]);
158         
159                 /* open infile for reading */
160                 if ((infile=fopen(argv[2],"r"))==NULL) {
161                         free(mybuf);
162                         free(mystat);
163                         printf("%s: Error opening %s\n",myname,argv[2]);
164                         goto error;
165                 }
166                 
167                 /* read in end buffer */
168                 fseek(infile,-8,SEEK_END);      
169                 fread(endbuf,1,8,infile);
170                 /* quick end buffer read and verification */
171                 if ( (endbuf[4]!='S') || (endbuf[5]!='T') || (endbuf[6]!='O') || (endbuf[7]!='P') )     {
172                         fclose(infile);
173                         free(mybuf);
174                         free(mystat);
175                         printf("%s: %s appears to be corrupt (end buffer invalid)\n",myname,argv[2]);
176                         goto error;
177                 }
178                 
179                 seekto=0;
180                 seekto=seekto+endbuf[0]*256*256*256;
181                 seekto=seekto+endbuf[1]*256*256;
182                 seekto=seekto+endbuf[2]*256;
183                 seekto=seekto+endbuf[3];
184                 
185                 /* open datafile for writing */
186                 if ((datafile=fopen(argv[3],"a"))==NULL) {
187                         fclose(infile);
188                         free(mybuf);
189                         free(mystat);
190                         printf("%s: Error opening %s\n",myname,argv[3]);
191                         goto error;
192                 }
193         
194                 /* open dbfile for writing */
195                 if ((dbfile=fopen(argv[4],"a"))==NULL) {
196                         fclose(datafile);
197                         fclose(infile);
198                         free(mybuf);
199                         free(mystat);
200                         printf("%s: Error opening %s\n",myname,argv[4]);
201                         goto error;
202                 }
203
204                 rewind(infile);
205                 writefileto(infile,datafile,insize-(seekto+8));
206                 fseek(infile,-(seekto+8),SEEK_END);
207                 writefileto(infile,dbfile,insize-8);
208                 fclose(infile);
209                 fclose(dbfile);
210                 fclose(datafile);
211                 free(mybuf);
212                 free(mystat);
213                 exit(0);        
214                 
215         } else {
216                 free(mybuf);
217                 free(mystat);
218                 goto usage;
219         }
220         
221         usage:
222         printf("Usage: %s join DATAFILE DBFILE OUTFILE (datafile + dbfile -> outfile)\n       %s split INFILE DATAFILE DBFILE (infile -> datafile + dbfile)\n",myname,myname);
223 error:
224         exit(1);
225 memalloc:
226         printf("%s: memory allocation error\n",myname);
227         exit(2);
228 }