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