#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace std; namespace fs = experimental::filesystem; // Global variables int verbose = false; string tab = "\t\t\t\t\t"; bool verif = false; bool list = false; bool mountpoints = false; bool partitions = false; bool generateauto_inst = false; void help(char * cmd) { printf("Usage: %s [-lavVf]\n", cmd); printf("-a Execute all commands\n" ); printf("-f Verify the modified files and save them\n"); printf("-g Generate auto_inst.cfg.pl\n"); printf("-h Display this help\n"); printf("-l List of the first level packages installed\n"); printf("-m Keep mount points\n"); printf("-p Keep partitioning\n"); printf("-v Verbose\n"); printf("-V Display the version of this software\n"); exit(EXIT_FAILURE); } void whatprovides(string filepath) { string cmd = "urpmi_rpm-find-leaves"; cmd += " >" + filepath; system(cmd.c_str()); } string array2string(array buffer) { int i = 0; string line; while(buffer[i] != '\n' ) { line.push_back(buffer[i]); i++; } return line; } bool savenonemptydir(string filepath, string needle="*") { int rsyncErrors = 0; int pos; string rsyncdestination = "files/"; string rsynccmd = "rsync -aqP --relative "; if (fs::is_directory(filepath)) { pos = filepath.find(needle); if (pos != string::npos and (pos == filepath.length() - 2) and !fs::is_empty(filepath) ) { cout << filepath << endl; } } return rsyncErrors; } bool fstabAnanlyze() { string fstabpath = "/etc/fstab"; string line; bool returncode = EXIT_SUCCESS; int pos = 0; int posstart = 0; int npos = 0; vector fstabarray; ifstream file; int nline = 0; array mountpoints{"/", "/home /var, "}; file.open(fstabpath); if(file.good()) { while (getline(file, line)) { while ((pos = line.find(" ") != string::npos)) { fstabarray.push_back(line.substr(posstart, pos - posstart)); posstart = pos; } npos = 0; if () } }else { cout << "Error opening " + fstabpath << endl; exit(EXIT_FAILURE); } return returncode; } bool savedirs() { bool returncode = false; string filepath; string line; string rsyncdestination = "files/"; string rsynccmd = "rsync -aqP --relative -m "; int rsyncErrors = 0; ifstream confFile("config/savedir.conf"); if (confFile.is_open()) { while (getline(confFile, line)) { filepath = line; //if (fs::exists(filepath)) //{ if (verbose) cout << "Directory to save: " + filepath << endl; rsynccmd = "rsync -aqP --relative " + filepath + " " + rsyncdestination; if (verbose) cout << "rsync command: " + rsynccmd << endl; if (system(rsynccmd.c_str()) != 0) { rsyncErrors ++; } //}else cout << filepath << "not exists"<< endl; } }else { cout << "can't open config/savedir.conf" << endl; exit(EXIT_FAILURE); } return returncode; } int recursedir(string dir, string needle, function func) { int returncode = EXIT_SUCCESS; string filepath; for (const auto & file : fs::recursive_directory_iterator(dir)) { filepath = (string ) file.path(); cout << filepath << endl; returncode |= func(dir, needle); } return returncode; } /* int saveOptLocal() { int result; int rsyncErrors = EXIT_SUCCESS; string cmd; string rsynccmd = "rsync -aqP --relative -m "; string rsyncdestination = "files/"; for(auto var : dirlist) { cout << "Saving" + var << endl; cmd = rsynccmd + var + " " + rsyncdestination; if (verbose) printf("rsync command: %s\n", cmd.c_str()); if ((result = system(cmd.c_str())) != 0) { rsyncErrors ++; } } return rsyncErrors; } */ void verification() { int result; int i = 0; int rsyncErrors = 0; array buffer; string cmd = "rpm -a --verify"; string line; string filepath; string rsyncdestination = "files/"; string rsynccmd = "rsync -aqP --relative "; string etcdir = "/etc"; string dir; int log; if (verbose) cout << "save '.d' non empty directories"; recursedir(etcdir, ".d",&savenonemptydir); savedirs(); printf("Verifying packages installed\n"); flush(cout); unique_ptr pipe(popen(cmd.c_str(), "r"), pclose); if (!pipe) { throw std::runtime_error("popen() failed!"); } while(fgets(buffer.data(), buffer.size(), pipe.get()) != NULL) { line = array2string(buffer); log = line.find(".log"); //cout << "log = " << line.length() << " ---> "; //printf("%s\n", line.c_str()); if (line.at(2) == '5' and log != (line.length() - 4)) { line.erase(0, 13); if (verbose) cout << "file to save: " + line<< endl; cmd = rsynccmd + line + " " + rsyncdestination; if (verbose) printf("rsync command: %s\n", cmd.c_str()); if ((result = system(cmd.c_str())) != 0) { printf("Rsync error: %i\n", result); rsyncErrors ++; } } buffer.fill(0); } // save all non empties directories finishing by ".d" in /etc if (rsyncErrors != 0) printf("rsync returned %i errors", rsyncErrors); } bool enabledmedias(string filename) { bool returnCode = EXIT_SUCCESS; bool start = false; bool flag = false; bool ignore = false; string temp = ""; string medias = "\t\t'enabled_media' => [\n"; string line; int i = 0; printf("searching enabled medias\n"); ifstream file("/etc/urpmi/urpmi.cfg"); if (file.is_open()) { while (getline(file, line)) { //printf("%s\n", line.c_str()); //cout << "start =" << start; if (start == false) { if (line.front() != '{' and line.front() != '\0' and line.front() != '}') { //cout << "passed"; start = true; flag = false; i = 0; do { i = line.find(" ", i+1); if (line[i-1] == '\\') { flag = true; line.erase(i-1, 1); }else { break; } }while(flag == true); line.erase(i); temp = line; printf("%s", temp.c_str()); line.clear(); }else { continue; } }else { array buffer; if (line.front() == '}') { if (!temp.empty() and ignore != true) { cout << " ==> adding to medias list\n"; medias += tab + temp + ",\n"; }else { cout << endl; } start = false; temp.clear(); ignore = false; continue; } if (line.find("ignore") != string::npos) { //cout << "found 'ignore'\n"; ignore = true; } } } printf("Medias:\n%s\n", medias.c_str()); file.close(); medias += tab + "],\n"; ofstream file(filename, ofstream::app); file << medias.c_str(); file.close(); }else return EXIT_FAILURE; return returnCode; } bool keyboardlayout(string filename) { bool returncode = EXIT_SUCCESS; int i; string cmd = "setxkbmap -query"; string line; string str; array buffer; printf("looking for keyboard layout\n"); flush(cout); unique_ptr pipe(popen(cmd.c_str(), "r"), pclose); if (!pipe) { throw std::runtime_error("popen() failed!"); } while(fgets(buffer.data(), buffer.size(), pipe.get()) != NULL) { line = array2string(buffer); cout << line << endl; i = line.find("layout:"); if (i != string::npos) { i = line.find_last_of(' '); line.erase(0, i+1); break; } cout << line << endl; line.clear(); buffer.fill(0); } cout << "result =>" << line << endl; ofstream file(filename, ofstream::app); if(file.is_open()) { str = "\t\t'keyboard' => {\n" + tab + "'GRP_TOGGLE' => '',\n" + tab + "'KEYBOARD' => '" + line + "'\n" + tab + "},\n"; file << str; file.close(); }else return EXIT_FAILURE; return returncode; } string getvalue( string line) { string value; int i; if ((i = line.find("=")) != string::npos) { value = line.substr(i+1, string::npos); } return value; } bool mklocale(string filename) { string localeconf = "/etc/locale.conf"; bool returncode = EXIT_SUCCESS; int i; int flag = 0; int utf8 = 0; string country; string lang; string line; string str; string value; vector languages; ifstream ifile (localeconf); ofstream ofile (filename, ofstream::app); if (ifile.is_open() and ofile.is_open()) { while (getline(ifile, line)) { value = getvalue(line); //cout << "Value ===>" + value << endl; if((i = line.find("COUNTRY")) != string::npos) { country = value; }else if((i = line.find("LANG=")) != string::npos) { lang = value.substr(0, 2); if (value.find("UTF-8") != string::npos) { utf8 = 1; } }else if((i = line.find("LANGUAGE")) != string::npos) { i = value.find(":"); languages.push_back(value.substr(i+1,string::npos)); } } } ofstream file(filename, ofstream::app); str = "\t\t'locale' => {\n" + tab + "'IM' => undef,\n" + tab + "'country' => '" + country + "'\n" + tab + "'lang' => '" + lang + "'\n"; str += tab + "'langs' => {\n"; //for(auto & elem : languages) flag = 0; for(i=0; i< languages.size(); i++) { if (flag == 0) { str += tab + "\t\t'" + languages[i] + "' => 1"; }else { str += ",\n" + tab + "\t\t'" + languages[i] + "' => 1"; } } str += "\n" + tab + "\t\t},\n"; str += tab + "'utf8' => 1\n" + tab + "},\n"; file << str; file.close(); return returncode; } bool miscellaneous(string filename) { bool returncode = EXIT_SUCCESS; int r; bool numlock = 0; string str; r = system("systemctl status numlock"); if (r == 0) { numlock = 1; } str = "\t\t'miscellaneous' => {\n" + tab + "'numlock' => " + to_string(numlock) + ",\n" + tab + "'HDPARM' => 1,\n\t\t},\n"; ofstream file(filename, ofstream::app); file << str; file.close(); return returncode; } int mkauto_inst(string pkgsfile) { bool returnCode = EXIT_SUCCESS; bool flag =false; string dirpath = "auto_inst.files"; string auto_inst_file = "auto_inst.cfg.pl"; string header = "auto_inst.cfg.pl.header"; string users = "auto_inst.cfg.pl.users"; string footer = "auto_inst.cfg.pl.footer"; string cmd = "cp " + dirpath + "/" + header + " ./" + auto_inst_file; int i = 0; string line; cout << "\n\n" + cmd << endl; returnCode |= system(cmd.c_str()); cout << "copying packages\n"; ifstream ifile(pkgsfile); ofstream ofile("./" + auto_inst_file, ofstream::app); if (ifile.is_open() and ofile.is_open()) { while (getline(ifile, line)) { if (flag == false) { flag = true; line = tab + line; ofile << line; }else { line = ",\n" + tab + line; ofile << line; } } ofile << "\n" + tab + "],\n"; ifile.close(); ofile.close(); }else { cout << "error file not open"; return 1; } returnCode |= enabledmedias(auto_inst_file); returnCode |= keyboardlayout(auto_inst_file); returnCode |= mklocale(auto_inst_file); returnCode |= miscellaneous(auto_inst_file); return returnCode; } int main(int argc, char** argv) { //bool x64 = 0; string pkgsfile = "pkgsfile.txt"; int opt = 0; int exitcode = EXIT_SUCCESS; // listing arguments if(argc>1) { while((opt = getopt(argc, argv, "valmpVfg")) != -1) { switch (opt) { case 'f': verif = true; break; case 'l': list = true; break; case 'a': list = true; verif = true; generateauto_inst = true; break; case 'v': verbose = true; break; case 'g': generateauto_inst = true; list = true; break; case 'm': mountpoints = true; break; case 'p': partitions = true; default: help(argv[0]); } } }else { cout << "no args\n"; help(argv[0]); } /* // getting processeur architecture if (uname(&buffer) < 0) { perror("uname"); exit(EXIT_FAILURE); } if ( strcmp(buffer.machine, "x86_64") == 0) { x64 = true; } if (verbose) printf("architecture is %s\n", buffer.machine); */ if (list == true) { whatprovides(pkgsfile); } if( verif == true) { verification(); } if(generateauto_inst == true) { mkauto_inst(pkgsfile); } cout << "finished\n"; exit(exitcode); }