# include <config.h>
#endif
-#include <stdio.h>
+#include "vserver.hh"
+#include "util.h"
+
+#include <getopt.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
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<EXCLDIR> excldirs;
static vector<EXCLDIR> 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<EXCLDIR> &dirs, const char *path)
{
}
// 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;
string title;
public:
printer (const char *_title): title(_title){}
- void operator()(T a){
+ void operator()(T const &a){
cout << title << " " << a << endl;
}
};
/*
Load the list of all packages in a vserver
*/
-static void vunify_loadallpkg (string &refserver, list<PACKAGE_UNI> &packages)
+static void vunify_loadallpkg (Vserver const &refserver, list<PACKAGE_UNI> &packages)
{
FILE *fin = vutil_execdistcmd (K_PKGVERSION,refserver,NULL);
if (fin != NULL){
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{
}
};
#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<PACKAGE_UNI> &target_packages;
- int &ret;
- package_unifier(string &_ref,
- string &_target,
- list<PACKAGE_UNI> &_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<PACKAGE_UNI> &target_packages;
+ int &ret;
+
+ package_unifier(Vserver const &_ref,
+ Vserver const &_target,
+ list<PACKAGE_UNI> &_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<PACKAGE_UNI> &ref_packages;
- string &ref_server;
- int &ret;
- server_unifier(string _ref_server, list<PACKAGE_UNI> &_packages, int &_ret)
- : ref_packages(_packages),ref_server(_ref_server), ret(_ret)
- {}
- void operator()(string serv)
- {
- list<PACKAGE_UNI> pkgs;
- vunify_loadallpkg (serv,pkgs);
- for_each(ref_packages.begin(),ref_packages.end()
- ,package_unifier(ref_server,serv,pkgs,ret));
- }
+ list<PACKAGE_UNI> &ref_packages;
+ Vserver const &ref_server;
+ int &ret;
+
+ server_unifier(Vserver const &_ref_server, list<PACKAGE_UNI> &_packages, int &_ret)
+ : ref_packages(_packages),ref_server(_ref_server), ret(_ret)
+ {}
+
+ void operator()(Vserver const &serv)
+ {
+ list<PACKAGE_UNI> 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;
int main (int argc, char *argv[])
{
- int ret = -1;
- int i;
- for (i=1; i<argc; i++){
- const char *arg = argv[i];
- //const char *opt = argv[i+1];
- if (strcmp(arg,"--test")==0){
- testmode = true;
- }else if (strcmp(arg,"--undo")==0){
- undo = true;
- }else if (strcmp(arg,"--debug")==0){
- debug++;
- }else if (strcmp(arg,"--noflags")==0){
- ext2flags = 0;
- }else if (strcmp(arg,"--immutable")==0){
- ext2flags |= EXT2_IMMUTABLE_FILE_FL;
- }else if (strcmp(arg,"--immutable-mayunlink")==0){
- ext2flags |= EXT2_IMMUTABLE_LINK_FL;
- }else if (strcmp(arg,"--excldir")==0){
- i++;
- //excldirs[excldirs.size()] = EXCLDIR(argv[i]);
- excldirs.push_back (EXCLDIR(argv[i]));
- }else if (strcmp(arg,"--incldir")==0){
- i++;
- incldirs.push_back (EXCLDIR(argv[i]));
- }else{
- break;
- }
- }
- if (i==argc){
- usage();
- }else{
- string refserv = argv[i++];
- list<string> vservers;
- for (; i<argc && strcmp(argv[i],"--")!=0; i++){
- vservers.push_front (argv[i]);
- }
- for_each (vservers.begin(),vservers.end(),printer<string>("vservers"));
- if (i == argc || strcmp(argv[i],"--")!=0){
- usage();
- }else{
- i++;
- if (i < argc){
- list<PACKAGE_UNI> 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<Vserver> vservers;
+ while (optind<argc && strcmp(argv[optind], "--")!=0)
+ vservers.push_back(Vserver(argv[optind++]));
+ ++optind;
+ if (optind>=argc) {
+ std::cerr << "No packages specified" << std::endl;
+ return EXIT_FAILURE;
+ }
+ for_each (vservers.begin(),vservers.end(),printer<Vserver>("vservers"));
+ std::list<PACKAGE_UNI> 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;
+}