/* This utility is used to compare two vservers. One is known to be clean and the other is potentially corrupted (cracked). The goal of this program is to run the rpm verify command, but using the RPM database of the first vserver. */ #include #include #include #include #include #include #include #include #include #include "vutil.h" using namespace std; static void usage() { cerr << "vcheck version " << VERSION << "\n\n" "vcheck [ options ] reference-server chk-vservers\n" "\n" "--diffpkgs: Shows which package differ.\n" " + means the package only exists in chk-server.\n" " - means the package does not exist in chk-server.\n" " ! means the servers have different version.\n" "\n" "--verify: Execute an RPM verify on common packages.\n" "--debug: Turn on some (useless) debugging messages.\n" ; } typedef list PACKAGES; /* Delete a directory silently */ static int vcheck_deldir (const string &path) { int ret = -1; struct stat64 st; if (lstat64(path.c_str(),&st)==-1){ ret = 0; }else{ if (!S_ISDIR(st.st_mode)){ fprintf (stderr,"%s already exist and is not a directory\n" ,path.c_str()); exit (-1); }else{ DIR *d = opendir (path.c_str()); if (d != NULL){ struct dirent *ent; ret = 0; while ((ent=readdir(d))!=NULL){ if (strcmp(ent->d_name,".")!=0 && strcmp(ent->d_name,"..")!=0){ string tmp = path + "/" + ent->d_name; if (unlink(tmp.c_str())==-1){ fprintf (stderr,"Can't delete file %s (%s)\n",tmp.c_str() ,strerror(errno)); ret = -1; break; } } } closedir (d); rmdir (path.c_str()); } } } return ret; } static int vcheck_copydb (const string &refserv, const string &path) { int ret = -1; string refpath = refserv + "/var/lib/rpm"; DIR *d = opendir (refpath.c_str()); if (d == NULL){ fprintf (stderr,"Can't open directory %s (%s)\n",refpath.c_str() ,strerror(errno)); }else{ ret = 0; struct dirent *ent; while ((ent=readdir(d))!=NULL){ if (strcmp(ent->d_name,".")!=0 && strcmp(ent->d_name,"..")!=0){ string srcpath = refpath + "/" + ent->d_name; const char *spath = srcpath.c_str(); struct stat64 st; if (stat64(spath,&st)!=-1){ string dstpath = path + "/" + ent->d_name; if (file_copy (spath,dstpath.c_str(),st) == -1){ ret = -1; break; } }else{ ret = -1; fprintf (stderr,"Can't stat %s (%s)\n",spath,strerror(errno)); break; } } } closedir (d); } return ret; } class cmp_name{ public: int operator()(const PACKAGE &p1, const PACKAGE &p2){ return strcmp(p1.name.c_str(),p2.name.c_str()); } }; int main (int argc, char *argv[]) { int ret = -1; bool diffpkg = false; bool verify = false; int i; for (i=1; iversion != it->version){ differ.push_back (*it); }else{ common.push_back (*it); } } for (list::iterator it=chkpkgs.begin(); it!=chkpkgs.end(); it++){ list::iterator f = find_if(refpkgs.begin(),refpkgs.end(),same_name(*it)); if (f == refpkgs.end()){ added.push_back (*it); } } differ.sort (); added.sort(); removed.sort(); common.sort (); bool something = false; if (diffpkg){ for (PACKAGES::iterator it=removed.begin(); it!=removed.end(); it++){ printf ("- %s\n",it->name.c_str()); } for (PACKAGES::iterator it=added.begin(); it!=added.end(); it++){ printf ("+ %s\n",it->name.c_str()); } for (PACKAGES::iterator it=differ.begin(); it!=differ.end(); it++){ printf ("! %s\n",it->name.c_str()); } something = true; } if (verify){ // We copy the rpm database from the reference vserver to // the target vserver string dbpath = chkserv + "/tmp/vcheck.db"; vcheck_deldir (dbpath); if (mkdir (dbpath.c_str(),0)==-1){ fprintf (stderr,"Can't create directory %s (%s)\n" ,dbpath.c_str(),strerror(errno)); }else if (vcheck_copydb (refserv,dbpath) != -1){ // We only compare the common package string cmd = "rpm --dbpath /tmp/vcheck.db --root " + chkserv + " -V"; for (PACKAGES::iterator it=common.begin(); it!=common.end(); it++){ //printf ("compare %s\n",it->name.c_str()); cmd += " " + it->name; } if (debug) printf ("CMD: %s\n",cmd.c_str()); system (cmd.c_str()); } vcheck_deldir (dbpath); something = true; } if (!something){ fprintf (stderr,"Nothing to do !!!\n\n"); usage(); } } return ret; }