📄 click-install.cc
字号:
/* * click-install.cc -- configuration installer for Click kernel module * Eddie Kohler * * Copyright (c) 1999-2000 Massachusetts Institute of Technology * Copyright (c) 2000 Mazu Networks, Inc. * Copyright (c) 2002 International Computer Science Institute * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, subject to the conditions * listed in the Click LICENSE file. These conditions include: you must * preserve this copyright notice, and you cannot mention the copyright * holders in advertising related to the Software without their permission. * The Software is provided WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED. This * notice is a summary of the Click LICENSE file; the license in that file is * legally binding. */#include <click/config.h>#include "common.hh"#include "routert.hh"#include "lexert.hh"#include <click/error.hh>#include <click/confparse.hh>#include <click/clp.h>#include <click/driver.hh>#include "toolutils.hh"#include <stdio.h>#include <stdlib.h>#include <string.h>#include <ctype.h>#include <errno.h>#include <sys/time.h>#include <sys/types.h>#include <sys/stat.h>#if FOR_BSDMODULE# include <sys/param.h># include <sys/mount.h>#elif FOR_LINUXMODULE && HAVE_CLICKFS# include <sys/mount.h>#endif#include <fcntl.h>#include <unistd.h>#define HELP_OPT 300#define VERSION_OPT 301#define CLICKPATH_OPT 302#define ROUTER_OPT 303#define EXPRESSION_OPT 304#define UNINSTALL_OPT 305#define HOTSWAP_OPT 306#define MAP_OPT 307#define VERBOSE_OPT 308#define THREADS_OPT 309#define PRIVATE_OPT 310#define PRIORITY_OPT 311static Clp_Option options[] = { { "cabalistic", 0, PRIVATE_OPT, 0, Clp_Negate }, { "clickpath", 'C', CLICKPATH_OPT, Clp_ArgString, 0 }, { "expression", 'e', EXPRESSION_OPT, Clp_ArgString, 0 }, { "file", 'f', ROUTER_OPT, Clp_ArgString, 0 }, { "help", 0, HELP_OPT, 0, 0 }, { "hot-swap", 'h', HOTSWAP_OPT, 0, Clp_Negate }, { "hotswap", 'h', HOTSWAP_OPT, 0, Clp_Negate }, { "priority", 'n', PRIORITY_OPT, Clp_ArgInt, 0 },#if FOR_LINUXMODULE { "map", 'm', MAP_OPT, 0, 0 }, { "private", 'p', PRIVATE_OPT, 0, Clp_Negate }, { "threads", 't', THREADS_OPT, Clp_ArgUnsigned, 0 },#endif { "uninstall", 'u', UNINSTALL_OPT, 0, Clp_Negate }, { "verbose", 'V', VERBOSE_OPT, 0, Clp_Negate }, { "version", 'v', VERSION_OPT, 0, 0 },};static const char *program_name;#if FOR_LINUXMODULE static bool output_map;#endifstatic String::Initializer string_initializer;static String tmpdir;static String click_compile_prog;voidshort_usage(){ fprintf(stderr, "Usage: %s [OPTION]... [ROUTERFILE]\n\Try '%s --help' for more information.\n", program_name, program_name);}voidusage(){ printf("\'Click-install' installs a kernel Click configuration. It loads the Click\n\kernel module, and any other necessary modules, as required.\n\\n\Usage: %s [OPTION]... [ROUTERFILE]\n\\n\Options:\n\ -f, --file FILE Read router configuration from FILE.\n\ -e, --expression EXPR Use EXPR as router configuration.\n\ -h, --hot-swap Hot-swap install new configuration.\n\ -u, --uninstall Uninstall Click from kernel, then reinstall.\n\ -n, --priority N Set kernel thread priority to N (lower is better).\n", program_name);#if FOR_LINUXMODULE printf("\ -p, --private Make /proc/click readable only by root.\n\ -t, --threads N Use N threads (multithreaded Click only).\n\ -m, --map Print load map to the standard output.\n");#endif printf("\ -V, --verbose Print information about files installed.\n\ -C, --clickpath PATH Use PATH for CLICKPATH.\n\ --help Print this message and exit.\n\ -v, --version Print version number and exit.\n\\n\Report bugs to <click@pdos.lcs.mit.edu>.\n");}static voidprepare_tmpdir(RouterT *r, ErrorHandler *errh){ ContextErrorHandler cerrh(errh, "While preparing to compile packages:"); BailErrorHandler berrh(&cerrh); // change to temporary directory tmpdir = click_mktmpdir(&berrh); assert(tmpdir); if (chdir(tmpdir.cc()) < 0) berrh.fatal("cannot chdir to %s: %s", tmpdir.cc(), strerror(errno)); // find compile program click_compile_prog = clickpath_find_file("click-compile", "bin", CLICK_BINDIR, &cerrh); assert(click_compile_prog); // look for .hh files if (r) { const Vector<ArchiveElement> &archive = r->archive(); for (int i = 0; i < archive.size(); i++) if (archive[i].name.substring(-3) == ".hh") { String filename = archive[i].name; FILE *f = fopen(filename.c_str(), "w"); if (!f) cerrh.warning("%s: %s", filename.c_str(), strerror(errno)); else { fwrite(archive[i].data.data(), 1, archive[i].data.length(), f); fclose(f); } } }}static voidcompile_archive_packages(RouterT *r, ErrorHandler *errh){ Vector<String> requirements = r->requirements(); // go over requirements for (int i = 0; i < requirements.size(); i++) { const String &req = requirements[i]; // skip if already have object file if (r->archive_index(req + OBJSUFFIX) >= 0) continue; // look for source file, prepare temporary directory int source_ae = r->archive_index(req + CXXSUFFIX); if (source_ae < 0) source_ae = r->archive_index(req + ".cc"); if (source_ae < 0) continue; if (!tmpdir) prepare_tmpdir(r, errh); // found source file, so compile it ArchiveElement ae = r->archive(source_ae); errh->message("Compiling package %s from config archive", ae.name.cc()); ContextErrorHandler cerrh (errh, "While compiling package '" + req + OBJSUFFIX "':"); // write .cc file String filename = req + ".cc"; String source_text = ae.data; FILE *f = fopen(filename.c_str(), "w"); if (!f) cerrh.fatal("%s: %s", filename.c_str(), strerror(errno)); fwrite(source_text.data(), 1, source_text.length(), f); fclose(f); // run click-compile String compile_command = click_compile_prog + " --driver=" COMPILETARGET " --package=" + req + OBJSUFFIX " " + filename; int compile_retval = system(compile_command.cc()); if (compile_retval == 127) cerrh.fatal("could not run '%s'", compile_command.cc()); else if (compile_retval < 0) cerrh.fatal("could not run '%s': %s", compile_command.cc(), strerror(errno)); else if (compile_retval != 0) cerrh.fatal("'%s' failed", compile_command.cc()); // grab object file and add to archive ArchiveElement obj_ae = init_archive_element(req + OBJSUFFIX, 0600); obj_ae.data = file_string(req + OBJSUFFIX, &cerrh); r->add_archive(obj_ae); }}static voidinstall_module(const String &filename, const String &options, ErrorHandler *errh){#if FOR_LINUXMODULE String cmdline = "/sbin/insmod "; if (output_map) cmdline += "-m "; cmdline += filename; if (options) cmdline += " " + options; int retval = system(cmdline.cc()); if (retval != 0) errh->fatal("'%s' failed", cmdline.cc());#else String cmdline = "/sbin/kldload " + filename; assert(!options); int retval = system(cmdline.cc()); if (retval != 0) errh->fatal("'%s' failed", cmdline.cc());#endif}static voidinstall_required_packages(RouterT *r, HashMap<String, int> &packages, HashMap<String, int> &active_modules, ErrorHandler *errh){ // check for uncompiled archive packages and try to compile them compile_archive_packages(r, errh); Vector<String> requirements = r->requirements(); // go over requirements for (int i = 0; i < requirements.size(); i++) { String req = requirements[i]; // look for object in archive int obj_aei = r->archive_index(req + OBJSUFFIX); if (obj_aei >= 0) { // install archived objects. mark them with leading underscores. // may require renaming to avoid clashes in 'insmod' // choose module name String insmod_name = "_" + req + OBJSUFFIX; while (active_modules[insmod_name] >= 0) insmod_name = "_" + insmod_name; if (verbose) errh->message("Installing package %s (%s" OBJSUFFIX " from config archive)", insmod_name.cc(), req.cc()); // install module if (!tmpdir) prepare_tmpdir(0, errh); const ArchiveElement &ae = r->archive(obj_aei); String tmpnam = tmpdir + insmod_name; FILE *f = fopen(tmpnam.c_str(), "w"); if (!f) errh->fatal("%s: %s", tmpnam.c_str(), strerror(errno)); fwrite(ae.data.data(), 1, ae.data.length(), f); fclose(f); install_module(tmpnam, String(), errh); // cleanup packages.insert(req, 1); active_modules.insert(insmod_name, 1); } else if (packages[req] < 0) { // install required package from CLICKPATH String filename = req + OBJSUFFIX; String pathname = clickpath_find_file(filename, "lib", CLICK_LIBDIR); if (!pathname) { filename = req + ".o"; pathname = clickpath_find_file(filename, "lib", CLICK_LIBDIR); if (!pathname) errh->fatal("cannot find required package '%s" OBJSUFFIX "'\nin CLICKPATH or '%s'", req.cc(), CLICK_LIBDIR); } // install module if (verbose) errh->message("Installing package %s (%s)", req.cc(), pathname.cc()); install_module(pathname, String(), errh);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -