1 /* Copyright (C) 2007  John Whitney
2  *
3  * This program is free software; you can redistribute it and/or modify
4  * it under the terms of the GNU General Public License as published by
5  * the Free Software Foundation; version 2 of the License.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  * GNU General Public License for more details.
11  *
12  * Author: John Whitney <jjw@deltup.org>
13  */
14 
15 #include <stdlib.h>
16 #include <sys/signal.h>
17 #include <string>
18 #include <vector>
19 #include <list>
20 using namespace std;
21 #include "file.h"
22 #include "bpatch.h"
23 #include <sys/wait.h>
24 #include "filetypes.h"
25 
26 bool verbose = false;
27 
error(string message)28 void error(string message) {
29   fprintf(stderr, "error: %s\n", message.c_str());
30   exit(1);
31 }
32 
invoke_system(string prog,string args)33 int invoke_system(string prog, string args) {
34 //  printf("%s\n", ret);
35   int ret = system((prog + " " + args).c_str());
36   if (WIFSIGNALED(ret) &&
37       (WTERMSIG(ret) == SIGINT || WTERMSIG(ret) == SIGQUIT))
38     error("Caught signal");
39   if (ret==0x7F00) error(string("A required executable, ") + prog + ", was not found");
40   return ret;
41 }
42 
remove_file(string name)43 void remove_file(string name) {
44   invoke_system("rm", string("-f ") + name);
45 }
46 
move_file(string from,string to)47 int move_file(string from, string to) {
48   return invoke_system("mv", from+" "+to);
49 }
50 
cat(string infile,string outfile,bool append)51 int cat(string infile, string outfile, bool append) {
52   return invoke_system("cat", infile+ (append?" >> ":" > ")+outfile+" 2> /dev/null");
53 }
54 
inflate(string command,string infile,string outfile,bool append)55 int inflate(string command, string infile, string outfile, bool append) {
56   return invoke_system(command, string("-c ")+
57                infile+(append?" >> ":" > ")+outfile+" 2> /dev/null");
58 }
59 
deflate(string command,string infile,string outfile,char lev,bool append)60 int deflate(string command, string infile, string outfile, char lev, bool append) {
61   return invoke_system("cat", infile + " | " + command + " -"+lev+
62 	              (append?" >> ":" > ") + outfile);
63 }
64 
makeDelta(bool bdelta,string file1,string file2,string deltaName)65 int makeDelta(bool bdelta, string file1, string file2, string deltaName) {
66   if (bdelta)
67     return invoke_system("bdelta", file1+" " +file2+" " + deltaName);
68   else
69     return invoke_system("xdelta", string("delta -0 --pristine ")+
70                   file1+" "+
71                   file2+" "+
72                   deltaName+" 2> /dev/null");
73 };
74 
determine_filetype(string s)75 int determine_filetype(string s) {
76   if (s.substr(0,3)=="DTU") return DTU;
77   if (s.substr(0,2)=="\037\213" ||
78       s.substr(0,2)=="\037\236") return GZIP;
79   if (s.substr(0,2)=="BZ") return BZIP2;
80   if (s.substr(0,4)=="PK\003\004") return ZIP;
81   if (s.substr(0,4)=="%XDZ") return XDELTA;
82   if (s.substr(0,3)=="BDT") return BDELTA;
83   return UNKNOWN_FMT;
84 }
85 
determine_filetype(Injectable_IStream & f)86 int determine_filetype(Injectable_IStream &f) {
87   char c[4];
88   f.read(c, 4);
89   f.inject(c, 4);
90   unsigned fmt = determine_filetype(c);
91   if (fmt!=UNKNOWN_FMT) return fmt;
92 
93   char tarheader[512];
94   f.read(tarheader, 512);
95   f.inject(tarheader, 512);
96   if (strncmp(tarheader+257, "ustar", 5)==0) return TARBALL;
97   return UNKNOWN_FMT;
98 }
99 
determine_filetype_fname(string fname)100 int determine_filetype_fname(string fname) {
101   FILE *f = fopen(fname.c_str(), "rb");
102   char header[4];
103   fread(header, 1, 4, f);
104   fclose(f);
105   return determine_filetype(header);
106 }
107 
apply_patch(string file1,string file2,string deltaName)108 int apply_patch(string file1, string file2, string deltaName) {
109   unsigned patchfiletype = determine_filetype_fname(deltaName);
110   bool failure;
111   if (patchfiletype == BDELTA)
112     failure = do_bdelta_patch(
113       file1.c_str(),
114       file2.c_str(),
115       deltaName.c_str());
116   else if (patchfiletype == XDELTA)
117     failure = invoke_system("xdelta",
118       string("patch --pristine ")+
119       deltaName+" "+
120       file1+" "+
121       file2);
122   else return 2;
123   if (failure) return 1;
124   return 0;
125 }
filesMatch(string file1,string file2)126 bool filesMatch(string file1, string file2) {
127   return !invoke_system("cmp", file1+" "+file2+ " > /dev/null");
128 }
129 
program_exists(string prog)130 bool program_exists(string prog) {
131   prog += " 2> /dev/null";
132   return !(system(prog.c_str())==0x7F00);
133 }
134 
135 
136