From a99e4575737b21af0baae4e36ae5d5969741ddd9 Mon Sep 17 00:00:00 2001 From: Enrico Scholz Date: Tue, 21 Oct 2003 13:24:29 +0000 Subject: [PATCH] use 'Vserver' class instead of 'string' use getopt() reindented large parts git-svn-id: http://svn.linux-vserver.org/svn/util-vserver/trunk@255 94cd875c-1c1d-0410-91d2-eb244daf1a30 --- util-vserver/src/vunify.cc | 395 +++++++++++++++++++++++++-------------------- 1 file changed, 217 insertions(+), 178 deletions(-) diff --git a/util-vserver/src/vunify.cc b/util-vserver/src/vunify.cc index 7d89a0f..88b5c82 100644 --- a/util-vserver/src/vunify.cc +++ b/util-vserver/src/vunify.cc @@ -29,7 +29,10 @@ # include #endif -#include +#include "vserver.hh" +#include "util.h" + +#include #include #include #include @@ -58,40 +61,76 @@ struct EXCLDIR{ len = prefix.size(); } }; + +#define OPTION_TEST 1024 +#define OPTION_UNDO 1025 +#define OPTION_DEBUG 1026 +#define OPTION_NOFLAGS 1027 +#define OPTION_IMMUTABLE 1028 +#define OPTION_IMM_UNLINK 1029 +#define OPTION_EXCLDIR 1030 +#define OPTION_INCLDIR 1031 + +static struct option const +CMDLINE_OPTIONS[] = { + { "help", no_argument, 0, 'h' }, + { "version", no_argument, 0, 'v' }, + { "test", no_argument, 0, OPTION_TEST }, + { "undo", no_argument, 0, OPTION_UNDO }, + { "debug", no_argument, 0, OPTION_DEBUG }, + { "noflags", no_argument, 0, OPTION_NOFLAGS }, + { "immutable", no_argument, 0, OPTION_IMMUTABLE }, + { "immutable-mayunlink", no_argument, 0, OPTION_IMM_UNLINK }, + { "excldir", required_argument, 0, OPTION_EXCLDIR }, + { "incldir", required_argument, 0, OPTION_INCLDIR }, + { 0,0,0,0 } +}; + + static vector excldirs; static vector incldirs; +static void +showHelp(std::ostream &out, char const *, int exit_code) +{ + out << "Usage: \n" + "vunify [ options ] reference-server vservers ... -- packages\n" + "vunify [ options ] reference-server vservers ... -- ALL\n" + "\n" + "--test: Show what will be done, do not do it.\n" + "--undo: Put back the file in place, using copies from the\n" + " reference server.\n" + "--debug: Prints some debugging messages.\n" + "--noflags: Do not put any immutable flags on the file\n" + "--immutable: Set the immutable_file bit on the files.\n" + "--immutable-mayunlink: Sets the immutable_link flag on files.\n" + "\n" + "--excldir: None of the files under a given directory will be unified\n" + "\tThe directory is expressed in absolute/logical form (relative\n" + "\tto the vserver root (ex: /var/log)\n" + "\n" + "--incldir: All the files under a given directory will be unified\n" + "\tThe directory is expressed in absolute/logical form (relative\n" + "\tto the vserver root (ex: /var/log)\n" + "\n" + "By default, the immutable_file and immutable_link flags are\n" + "set on the files. So if you want no immutable flags, you must\n" + "use --noflags. If you want a single flag, you must use\n" + "--noflags first, then the --immutable or --immutable-mayunlink\n" + "flag.\n"; -static void usage() + std::exit(exit_code); +} + +static void +showVersion() { - cerr << - "vunify version " << VERSION << - "\n\n" - "vunify [ options ] reference-server vservers ... -- packages\n" - "vunify [ options ] reference-server vservers ... -- ALL\n" - "\n" - "--test: Show what will be done, do not do it.\n" - "--undo: Put back the file in place, using copies from the\n" - " reference server.\n" - "--debug: Prints some debugging messages.\n" - "--noflags: Do not put any immutable flags on the file\n" - "--immutable: Set the immutable_file bit on the files.\n" - "--immutable-mayunlink: Sets the immutable_link flag on files.\n" - "\n" - "--excldir: None of the files under a given directory will be unified\n" - "\tThe directory is expressed in absolute/logical form (relative\n" - "\tto the vserver root (ex: /var/log)\n" - "\n" - "--incldir: All the files under a given directory will be unified\n" - "\tThe directory is expressed in absolute/logical form (relative\n" - "\tto the vserver root (ex: /var/log)\n" - "\n" - "By default, the immutable_file and immutable_link flags are\n" - "set on the files. So if you want no immutable flags, you must\n" - "use --noflags. If you want a single flag, you must use\n" - "--noflags first, then the --immutable or --immutable-mayunlink\n" - "flag.\n" - ; + std::cout << "vunify " VERSION " -- unifies files of vservers\n" + "This program is part of " PACKAGE_STRING "\n\n" + "Copyright (C) 2003 Enrico Scholz\n" + VERSION_COPYRIGHT_DISCLAIMER; + + std::exit(0); } static bool vunify_inside (vector &dirs, const char *path) @@ -123,7 +162,7 @@ public: { } // Load the file member of the package, but exclude configuration file - void loadfiles(const string &ref) + void loadfiles(Vserver const &ref) { if (files.empty()){ if (debug) cout << "Loading files for package " << name << endl; @@ -170,7 +209,7 @@ template string title; public: printer (const char *_title): title(_title){} - void operator()(T a){ + void operator()(T const &a){ cout << title << " " << a << endl; } }; @@ -179,7 +218,7 @@ template /* Load the list of all packages in a vserver */ -static void vunify_loadallpkg (string &refserver, list &packages) +static void vunify_loadallpkg (Vserver const &refserver, list &packages) { FILE *fin = vutil_execdistcmd (K_PKGVERSION,refserver,NULL); if (fin != NULL){ @@ -200,48 +239,56 @@ static void vunify_loadallpkg (string &refserver, list &packages) the immutable flag is done */ class file_unifier{ - string &ref_server,&target_server; - int &ret; - public: - file_unifier(string &_ref, string &_target, int &_ret) - : ref_server(_ref),target_server(_target), ret(_ret) - {} - void operator()(const string &file) - { - string refpath = "/vservers/" + ref_server + file; - string dstpath = "/vservers/" + target_server + file; - if (debug) cout << "Unify " << refpath << " -> " << dstpath << endl; - struct stat st; - if (stat(refpath.c_str(),&st)==-1){ - if (debug) cout << "File " << refpath << " does not exist, ignored\n"; - }else if (setext2flag(refpath.c_str(),false,ext2flags)==-1){ - ret = -1; - }else if (vbuild_unlink(dstpath.c_str())==-1){ - ret = -1; - cerr << "Can't delete file " << dstpath - << " (" << strerror(errno) << ")\n"; - }else{ - if (undo){ - if (vbuild_file_copy(refpath.c_str(),dstpath.c_str(),st)==-1){ - ret = -1; - cerr << "Can't copy file " << refpath << " to " << dstpath - << " (" << strerror(errno) << ")\n"; - } - }else{ - if (vbuild_link(refpath.c_str(),dstpath.c_str())==-1){ - ret = -1; - cerr << "Can't link file " << refpath << " to " << dstpath - << " (" << strerror(errno) << ")\n"; - } - } - // We put back the original immutable because other vservers - // may be unified on it. - if (setext2flag(refpath.c_str(),true,ext2flags)==-1){ - ret = -1; - } - } + Vserver const &ref_server; + Vserver const &target_server; + int &ret; + + public: + file_unifier(Vserver const &_ref, Vserver const &_target, int &_ret) + : ref_server(_ref),target_server(_target), ret(_ret) + {} + + void operator()(const string &file) + { + std::string refpath = ref_server.getVdir(); + refpath += file; + + std::string dstpath = target_server.getVdir(); + dstpath += file; + + if (debug) cout << "Unify " << refpath << " -> " << dstpath << endl; + struct stat st; + if (stat(refpath.c_str(),&st)==-1){ + if (debug) cout << "File " << refpath << " does not exist, ignored\n"; + }else if (setext2flag(refpath.c_str(),false,ext2flags)==-1){ + ret = -1; + }else if (vbuild_unlink(dstpath.c_str())==-1){ + ret = -1; + cerr << "Can't delete file " << dstpath + << " (" << strerror(errno) << ")\n"; + }else{ + if (undo){ + if (vbuild_file_copy(refpath.c_str(),dstpath.c_str(),st)==-1){ + ret = -1; + cerr << "Can't copy file " << refpath << " to " << dstpath + << " (" << strerror(errno) << ")\n"; + } + }else{ + if (vbuild_link(refpath.c_str(),dstpath.c_str())==-1){ + ret = -1; + cerr << "Can't link file " << refpath << " to " << dstpath + << " (" << strerror(errno) << ")\n"; + } } + // We put back the original immutable because other vservers + // may be unified on it. + if (setext2flag(refpath.c_str(),true,ext2flags)==-1){ + ret = -1; + } + } + } }; + #if 0 // Check if two package have the same name (but potentially different version) class same_name{ @@ -254,61 +301,66 @@ public: } }; #endif -// Predicate to decide if a package must be unified + // Predicate to decide if a package must be unified class package_unifier{ -public: - string &ref_server,&target_server; - list &target_packages; - int &ret; - package_unifier(string &_ref, - string &_target, - list &_target_packages, - int &_ret) - : ref_server(_ref),target_server(_target) - , target_packages(_target_packages) , ret(_ret) - {} - void operator()(PACKAGE_UNI &pkg) - { - if (find(target_packages.begin(),target_packages.end(),pkg) - !=target_packages.end()){ - // Ok, the package is also in the target vserver - cout << "Unify pkg " << pkg << " from " << ref_server << " to " - << target_server << endl; - - if (!testmode || debug){ - pkg.loadfiles(ref_server); - for_each (pkg.files.begin(),pkg.files.end() - ,file_unifier(ref_server,target_server,ret)); - } - }else if (testmode){ - // The package is missing, in test mode we provide more information - if (find_if(target_packages.begin(),target_packages.end(),same_name(pkg)) - !=target_packages.end()){ - cout << pkg << " exist in server " << target_server << " not unified\n"; - }else{ - cout << pkg << " does not exist in server " << target_server << endl; - } - } + public: + Vserver const &ref_server; + Vserver const &target_server; + list &target_packages; + int &ret; + + package_unifier(Vserver const &_ref, + Vserver const &_target, + list &_target_packages, + int &_ret) : + ref_server(_ref),target_server(_target), + target_packages(_target_packages), ret(_ret) + {} + void operator()(PACKAGE_UNI &pkg) + { + if (find(target_packages.begin(),target_packages.end(),pkg) + !=target_packages.end()){ + // Ok, the package is also in the target vserver + cout << "Unify pkg " << pkg << " from " << ref_server << " to " + << target_server << endl; + + if (!testmode || debug){ + pkg.loadfiles(ref_server); + for_each (pkg.files.begin(),pkg.files.end() + ,file_unifier(ref_server,target_server,ret)); } + }else if (testmode){ + // The package is missing, in test mode we provide more information + if (find_if(target_packages.begin(),target_packages.end(),same_name(pkg)) + !=target_packages.end()){ + cout << pkg << " exist in server " << target_server << " not unified\n"; + }else{ + cout << pkg << " does not exist in server " << target_server << endl; + } + } + } }; // For each vserver, find the common packages and unify them class server_unifier{ public: - list &ref_packages; - string &ref_server; - int &ret; - server_unifier(string _ref_server, list &_packages, int &_ret) - : ref_packages(_packages),ref_server(_ref_server), ret(_ret) - {} - void operator()(string serv) - { - list pkgs; - vunify_loadallpkg (serv,pkgs); - for_each(ref_packages.begin(),ref_packages.end() - ,package_unifier(ref_server,serv,pkgs,ret)); - } + list &ref_packages; + Vserver const &ref_server; + int &ret; + + server_unifier(Vserver const &_ref_server, list &_packages, int &_ret) + : ref_packages(_packages),ref_server(_ref_server), ret(_ret) + {} + + void operator()(Vserver const &serv) + { + list pkgs; + vunify_loadallpkg (serv,pkgs); + for_each(ref_packages.begin(),ref_packages.end() + ,package_unifier(ref_server,serv,pkgs,ret)); + } }; + class deleteif{ public: char **argv0,**argvn; @@ -328,65 +380,52 @@ public: int main (int argc, char *argv[]) { - int ret = -1; - int i; - for (i=1; i vservers; - for (; i("vservers")); - if (i == argc || strcmp(argv[i],"--")!=0){ - usage(); - }else{ - i++; - if (i < argc){ - list packages; - vunify_loadallpkg (refserv,packages); - if (i != argc-1 || strcmp(argv[i],"ALL")!=0){ - // We keep only the packages supplied on the command line - packages.remove_if(deleteif (argv+i,argv+argc)); - } - ret = 0; - umask (0); - for_each (vservers.begin(),vservers.end(),server_unifier(refserv,packages,ret)); - }else{ - usage(); - } - } - } - return ret; -} + while (1) { + int c = getopt_long(argc, argv, "hv", CMDLINE_OPTIONS, 0); + switch (c) { + case 'h' : showHelp(std::cout, argv[0], 0); break; + case 'v' : showVersion(); break; + case OPTION_TEST : testmode = true; break; + case OPTION_UNDO : undo = true; break; + case OPTION_DEBUG : ++debug; break; + case OPTION_NOFLAGS : ext2flags = 0; break; + case OPTION_IMMUTABLE : ext2flags |= EXT2_IMMUTABLE_FILE_FL; break; + case OPTION_IMM_UNLINK : ext2flags |= EXT2_IMMUTABLE_LINK_FL; break; + case OPTION_EXCLDIR : excldirs.push_back(EXCLDIR(optarg)); break; + case OPTION_INCLDIR : incldirs.push_back(EXCLDIR(optarg)); break; + default : + std::cerr << "Try '" << argv[0] << " --help' for more information." << std::endl; + return EXIT_FAILURE; + } + } + + if (optind+1>=argc) { + std::cerr << "No vserver specified" << std::endl; + return EXIT_FAILURE; + } + + Vserver refserv(argv[optind++]); + std::vector vservers; + while (optind=argc) { + std::cerr << "No packages specified" << std::endl; + return EXIT_FAILURE; + } + for_each (vservers.begin(),vservers.end(),printer("vservers")); + std::list packages; + vunify_loadallpkg(refserv, packages); + + if (optind!=argc-1 || strcmp(argv[optind], "ALL")!=0) + packages.remove_if(deleteif(argv+optind, argv+argc)); + int ret = EXIT_SUCCESS; + umask(0); + for_each(vservers.begin(), vservers.end(), server_unifier(refserv,packages,ret)); + + return ret; +} -- 1.8.1.5