added Vector_zeroEnd() function
[util-vserver.git] / util-vserver / src / vcheck.cc
1 // $Id$
2
3 // Copyright (C) 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
4 // based on vcheck.cc by Jacques Gelinas
5 //  
6 // This program is free software; you can redistribute it and/or modify
7 // it under the terms of the GNU General Public License as published by
8 // the Free Software Foundation; either version 2, or (at your option)
9 // 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
14 // GNU 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, write to the Free Software
18 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19
20 /*
21         This utility is used to compare two vservers. One is known to
22         be clean and the other is potentially corrupted (cracked). The
23         goal of this program is to run the rpm verify command, but using
24         the RPM database of the first vserver.
25 */
26 #ifdef HAVE_CONFIG_H
27 #  include <config.h>
28 #endif
29
30 #include <stdio.h>
31 #include <fcntl.h>
32 #include <unistd.h>
33 #include <errno.h>
34 #include <dirent.h>
35
36 #include <string>
37 #include <vector>
38 #include <list>
39 #include <set>
40 #include "vutil.h"
41
42 using namespace std;
43
44
45 static void usage()
46 {
47         cerr <<
48                 "vcheck version " << VERSION <<
49                 "\n\n"
50                 "vcheck [ options ] reference-server chk-vservers\n"
51                 "\n"
52                 "--diffpkgs: Shows which package differ.\n"
53                 "            + means the package only exists in chk-server.\n"
54                 "            - means the package does not exist in chk-server.\n"
55                 "            ! means the servers have different version.\n"
56                 "\n"
57                 "--verify: Execute an RPM verify on common packages.\n"
58                 "--debug: Turn on some (useless) debugging messages.\n"
59                 ;
60 }
61
62 typedef list<Package> PACKAGES;
63
64 /*
65         Delete a directory silently
66 */
67 static int vcheck_deldir (const string &path)
68 {
69         int ret = -1;
70         struct stat st;
71         if (lstat(path.c_str(),&st)==-1){
72                 ret = 0;
73         }else{
74                 if (!S_ISDIR(st.st_mode)){
75                         fprintf (stderr,"%s already exist and is not a directory\n"
76                                 ,path.c_str());
77                         exit (-1);
78                 }else{
79                         DIR *d = opendir (path.c_str());
80                         if (d != NULL){
81                                 struct dirent *ent;
82                                 ret = 0;
83                                 while ((ent=readdir(d))!=NULL){
84                                         if (strcmp(ent->d_name,".")!=0
85                                                 && strcmp(ent->d_name,"..")!=0){
86                                                 string tmp = path + "/" + ent->d_name;
87                                                 if (unlink(tmp.c_str())==-1){
88                                                         fprintf (stderr,"Can't delete file %s (%s)\n",tmp.c_str()
89                                                                 ,strerror(errno));
90                                                         ret = -1;
91                                                         break;
92                                                 }
93                                         }
94                                 }
95                                 closedir (d);
96                                 rmdir (path.c_str());
97                         }
98                 }
99         }
100         return ret;
101 }
102                 
103
104 static int vcheck_copydb (const string &refserv, const string &path)
105 {
106         int ret = -1;
107         string refpath = refserv + "/var/lib/rpm";
108         DIR *d = opendir (refpath.c_str());
109         if (d == NULL){
110                 fprintf (stderr,"Can't open directory %s (%s)\n",refpath.c_str()
111                         ,strerror(errno));
112         }else{
113                 ret = 0;
114                 struct dirent *ent;
115                 while ((ent=readdir(d))!=NULL){
116                         if (strcmp(ent->d_name,".")!=0
117                                 && strcmp(ent->d_name,"..")!=0){
118                                 string srcpath = refpath + "/" + ent->d_name;
119                                 const char *spath = srcpath.c_str();
120                                 struct stat st;
121                                 if (stat(spath,&st)!=-1){
122                                         string dstpath = path + "/" + ent->d_name;
123                                         if (file_copy (spath,dstpath.c_str(),st) == -1){
124                                                 ret = -1;
125                                                 break;
126                                         }
127                                 }else{
128                                         ret = -1;
129                                         fprintf (stderr,"Can't stat %s (%s)\n",spath,strerror(errno));
130                                         break;
131                                 }
132                         }
133                 }
134                 closedir (d);
135         }
136         return ret;
137 }
138
139 class cmp_name{
140 public:
141         int operator()(const Package &p1, const Package &p2){
142                 return strcmp(p1.name.c_str(),p2.name.c_str());
143         }
144 };
145
146
147 int main (int argc, char *argv[])
148 {
149         int ret = -1;
150         bool diffpkg = false;
151         bool verify = false;
152         int i;
153         for (i=1; i<argc; i++){
154                 const char *arg = argv[i];
155                 //const char *opt = argv[i+1];
156                 if (strcmp(arg,"--diffpkg")==0){
157                         diffpkg = true;
158                 }else if (strcmp(arg,"--verify")==0){
159                         verify = true;
160                 }else if (strcmp(arg,"--debug")==0){
161                         debug++;
162                 }else{
163                         break;
164                 }
165         }
166         if (i!=argc-2){
167                 usage();
168         }else{
169                 string refserv = argv[i++];
170                 string chkserv = argv[i];
171                 PACKAGES refpkgs,chkpkgs;
172                 // Load the package list from both vservers
173                 vutil_loadallpkg (refserv,refpkgs);
174                 vutil_loadallpkg (chkserv,chkpkgs);
175                 PACKAGES common, differ, added, removed;
176                 // Find which package are different, missing and added
177                 // to chkserv
178                 for (PACKAGES::iterator it=refpkgs.begin(); it!=refpkgs.end(); it++){
179                         PACKAGES::iterator f = find_if(chkpkgs.begin(),chkpkgs.end(),same_name(*it));
180                         if (f == chkpkgs.end()){
181                                 removed.push_back (*it);
182                         }else if (f->version != it->version){
183                                 differ.push_back (*it);
184                         }else{
185                                 common.push_back (*it);
186                         }
187                 }
188                 for (list<Package>::iterator it=chkpkgs.begin(); it!=chkpkgs.end(); it++){
189                         list<Package>::iterator f = find_if(refpkgs.begin(),refpkgs.end(),same_name(*it));
190                         if (f == refpkgs.end()){
191                                 added.push_back (*it);
192                         }
193                 }
194                 differ.sort ();
195                 added.sort();
196                 removed.sort();
197                 common.sort ();
198                 bool something = false;
199                 if (diffpkg){
200                         for (PACKAGES::iterator it=removed.begin(); it!=removed.end(); it++){
201                                 printf ("- %s\n",it->name.c_str());
202                         }
203                         for (PACKAGES::iterator it=added.begin(); it!=added.end(); it++){
204                                 printf ("+ %s\n",it->name.c_str());
205                         }
206                         for (PACKAGES::iterator it=differ.begin(); it!=differ.end(); it++){
207                                 printf ("! %s\n",it->name.c_str());
208                         }
209                         something = true;
210                 }
211                 if (verify){
212                         // We copy the rpm database from the reference vserver to
213                         // the target vserver
214                         string dbpath = chkserv + "/tmp/vcheck.db";
215                         vcheck_deldir (dbpath);
216                         if (mkdir (dbpath.c_str(),0)==-1){
217                                 fprintf (stderr,"Can't create directory %s (%s)\n"
218                                         ,dbpath.c_str(),strerror(errno));
219                         }else if (vcheck_copydb (refserv,dbpath) != -1){
220                                 // We only compare the common package
221                                 string cmd = "rpm --dbpath /tmp/vcheck.db --root " + chkserv + " -V";
222                                 for (PACKAGES::iterator it=common.begin(); it!=common.end(); it++){
223                                         //printf ("compare %s\n",it->name.c_str());
224                                         cmd += " " + it->name;
225                                 }
226                                 if (debug) printf ("CMD: %s\n",cmd.c_str());
227                                 system (cmd.c_str());
228                         }
229                         vcheck_deldir (dbpath);
230                         something = true;
231                 }
232                 if (!something){
233                         fprintf (stderr,"Nothing to do !!!\n\n");
234                         usage();
235                 }
236         }
237         return ret;
238 }
239
240
241