00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <config.h>
00021
00022 #include "sbuild-chroot.h"
00023 #include "sbuild-chroot-directory.h"
00024 #include "sbuild-chroot-plain.h"
00025 #include "sbuild-chroot-file.h"
00026 #include "sbuild-chroot-block-device.h"
00027 #include "sbuild-chroot-lvm-snapshot.h"
00028 #include "sbuild-lock.h"
00029
00030 #include <algorithm>
00031 #include <cerrno>
00032 #include <map>
00033 #include <set>
00034 #include <utility>
00035
00036 #include <ext/stdio_filebuf.h>
00037
00038 #include <sys/types.h>
00039 #include <sys/stat.h>
00040 #include <fcntl.h>
00041
00042 #include <boost/format.hpp>
00043
00044 using boost::format;
00045 using namespace sbuild;
00046
00047 namespace
00048 {
00049
00050 typedef std::pair<sbuild::chroot::error_code,const char *> emap;
00051
00056 emap init_errors[] =
00057 {
00058 emap(sbuild::chroot::CHROOT_CREATE, N_("Chroot creation failed")),
00059 emap(sbuild::chroot::CHROOT_DEVICE, N_("Device name not set")),
00060
00061 emap(sbuild::chroot::CHROOT_TYPE, N_("Unknown chroot type '%1%'")),
00062 emap(sbuild::chroot::DEVICE_ABS, N_("Device must have an absolute path")),
00063 emap(sbuild::chroot::DEVICE_LOCK, N_("Failed to lock device")),
00064 emap(sbuild::chroot::DEVICE_NOTBLOCK, N_("File is not a block device")),
00065 emap(sbuild::chroot::DEVICE_STAT, N_("Failed to stat device")),
00066 emap(sbuild::chroot::DEVICE_UNLOCK, N_("Failed to unlock device")),
00067 emap(sbuild::chroot::FILE_ABS, N_("File must have an absolute path")),
00068 emap(sbuild::chroot::FILE_LOCK, N_("Failed to acquire file lock")),
00069 emap(sbuild::chroot::FILE_NOTREG, N_("File is not a regular file")),
00070 emap(sbuild::chroot::FILE_OWNER, N_("File is not owned by user root")),
00071 emap(sbuild::chroot::FILE_PERMS, N_("File has write permissions for others")),
00072 emap(sbuild::chroot::FILE_STAT, N_("Failed to stat file")),
00073 emap(sbuild::chroot::FILE_UNLOCK, N_("Failed to discard file lock")),
00074 emap(sbuild::chroot::LOCATION_ABS, N_("Location must have an absolute path")),
00075
00076 emap(sbuild::chroot::SESSION_UNLINK, N_("Failed to unlink session file")),
00077 emap(sbuild::chroot::SESSION_WRITE, N_("Failed to write session file"))
00078 };
00079
00080 }
00081
00082 template<>
00083 error<sbuild::chroot::error_code>::map_type
00084 error<sbuild::chroot::error_code>::error_strings
00085 (init_errors,
00086 init_errors + (sizeof(init_errors) / sizeof(init_errors[0])));
00087
00088 sbuild::chroot::chroot ():
00089 name(),
00090 description(),
00091 priority(0),
00092 users(),
00093 groups(),
00094 root_users(),
00095 root_groups(),
00096 aliases(),
00097 mount_location(),
00098 location(),
00099 mount_device(),
00100 active(false),
00101 original(true),
00102 run_setup_scripts(false),
00103 run_exec_scripts(false),
00104 command_prefix(),
00105 persona(
00106 #ifdef __linux__
00107 personality("linux")
00108 #else
00109 personality("undefined")
00110 #endif
00111 )
00112 {
00113 }
00114
00115 sbuild::chroot::~chroot ()
00116 {
00117 }
00118
00119 sbuild::chroot::ptr
00120 sbuild::chroot::create (std::string const& type)
00121 {
00122 chroot *new_chroot = 0;
00123
00124 if (type == "directory")
00125 new_chroot = new chroot_directory();
00126 else if (type == "plain")
00127 new_chroot = new chroot_plain();
00128 else if (type == "file")
00129 new_chroot = new chroot_file();
00130 else if (type == "block-device")
00131 new_chroot = new chroot_block_device();
00132 else if (type == "lvm-snapshot")
00133 new_chroot = new chroot_lvm_snapshot();
00134 else
00135 throw error(type, CHROOT_TYPE);
00136
00137 if (new_chroot == 0)
00138 throw error(CHROOT_CREATE);
00139
00140 return ptr(new_chroot);
00141 }
00142
00143 std::string const&
00144 sbuild::chroot::get_name () const
00145 {
00146 return this->name;
00147 }
00148
00149 void
00150 sbuild::chroot::set_name (std::string const& name)
00151 {
00152 this->name = name;
00153 }
00154
00155 std::string const&
00156 sbuild::chroot::get_description () const
00157 {
00158 return this->description;
00159 }
00160
00161 void
00162 sbuild::chroot::set_description (std::string const& description)
00163 {
00164 this->description = description;
00165 }
00166
00167 std::string const&
00168 sbuild::chroot::get_mount_location () const
00169 {
00170 return this->mount_location;
00171 }
00172
00173 void
00174 sbuild::chroot::set_mount_location (std::string const& location)
00175 {
00176 if (!location.empty() && !is_absname(location))
00177 throw error(location, LOCATION_ABS);
00178 this->mount_location = location;
00179 }
00180
00181 std::string const&
00182 sbuild::chroot::get_location () const
00183 {
00184 return this->location;
00185 }
00186
00187 void
00188 sbuild::chroot::set_location (std::string const& location)
00189 {
00190 if (!location.empty() && !is_absname(location))
00191 throw error(location, LOCATION_ABS);
00192
00193 this->location = location;
00194 }
00195
00196 std::string
00197 sbuild::chroot::get_path () const
00198 {
00199 return get_mount_location() + get_location();
00200 }
00201
00202 std::string const&
00203 sbuild::chroot::get_mount_device () const
00204 {
00205 return this->mount_device;
00206 }
00207
00208 void
00209 sbuild::chroot::set_mount_device (std::string const& device)
00210 {
00211 if (!device.empty() && !is_absname(device))
00212 throw error(device, DEVICE_ABS);
00213 this->mount_device = device;
00214 }
00215
00216 unsigned int
00217 sbuild::chroot::get_priority () const
00218 {
00219 return this->priority;
00220 }
00221
00222 void
00223 sbuild::chroot::set_priority (unsigned int priority)
00224 {
00225 this->priority = priority;
00226 }
00227
00228 string_list const&
00229 sbuild::chroot::get_users () const
00230 {
00231 return this->users;
00232 }
00233
00234 void
00235 sbuild::chroot::set_users (string_list const& users)
00236 {
00237 this->users = users;
00238 }
00239
00240 string_list const&
00241 sbuild::chroot::get_groups () const
00242 {
00243 return this->groups;
00244 }
00245
00246 void
00247 sbuild::chroot::set_groups (string_list const& groups)
00248 {
00249 this->groups = groups;
00250 }
00251
00252 string_list const&
00253 sbuild::chroot::get_root_users () const
00254 {
00255 return this->root_users;
00256 }
00257
00258 void
00259 sbuild::chroot::set_root_users (string_list const& users)
00260 {
00261 this->root_users = users;
00262 }
00263
00264 string_list const&
00265 sbuild::chroot::get_root_groups () const
00266 {
00267 return this->root_groups;
00268 }
00269
00270 void
00271 sbuild::chroot::set_root_groups (string_list const& groups)
00272 {
00273 this->root_groups = groups;
00274 }
00275
00276 string_list const&
00277 sbuild::chroot::get_aliases () const
00278 {
00279 return this->aliases;
00280 }
00281
00282 void
00283 sbuild::chroot::set_aliases (string_list const& aliases)
00284 {
00285 this->aliases = aliases;
00286 }
00287
00288 bool
00289 sbuild::chroot::get_active () const
00290 {
00291 return this->active;
00292 }
00293
00294 void
00295 sbuild::chroot::set_active (bool active)
00296 {
00297 this->active = active;
00298 }
00299
00300 bool
00301 sbuild::chroot::get_original () const
00302 {
00303 return this->original;
00304 }
00305
00306 void
00307 sbuild::chroot::set_original (bool original)
00308 {
00309 this->original = original;
00310 }
00311
00312 bool
00313 sbuild::chroot::get_run_setup_scripts () const
00314 {
00315 return this->run_setup_scripts;
00316 }
00317
00318 void
00319 sbuild::chroot::set_run_setup_scripts (bool run_setup_scripts)
00320 {
00321 this->run_setup_scripts = run_setup_scripts;
00322 }
00323
00324 bool
00325 sbuild::chroot::get_run_exec_scripts () const
00326 {
00327 return this->run_exec_scripts;
00328 }
00329
00330 void
00331 sbuild::chroot::set_run_exec_scripts (bool run_exec_scripts)
00332 {
00333 this->run_exec_scripts = run_exec_scripts;
00334 }
00335
00336 string_list const&
00337 sbuild::chroot::get_command_prefix () const
00338 {
00339 return this->command_prefix;
00340 }
00341
00342 void
00343 sbuild::chroot::set_command_prefix (string_list const& command_prefix)
00344 {
00345 this->command_prefix = command_prefix;
00346 }
00347
00348 personality const&
00349 sbuild::chroot::get_persona () const
00350 {
00351 return this->persona;
00352 }
00353
00354 void
00355 sbuild::chroot::set_persona (personality const& persona)
00356 {
00357 this->persona = persona;
00358 }
00359
00360 void
00361 sbuild::chroot::setup_env (environment& env)
00362 {
00363 env.add("CHROOT_TYPE", get_chroot_type());
00364 env.add("CHROOT_NAME", get_name());
00365 env.add("CHROOT_DESCRIPTION", get_description());
00366 env.add("CHROOT_LOCATION", get_location());
00367 env.add("CHROOT_MOUNT_LOCATION", get_mount_location());
00368 env.add("CHROOT_PATH", get_path());
00369 env.add("CHROOT_MOUNT_DEVICE", get_mount_device());
00370 }
00371
00372 void
00373 sbuild::chroot::setup_session_info (bool start)
00374 {
00375
00376 std::string file = std::string(SCHROOT_SESSION_DIR) + "/" + get_name();
00377
00378 if (start)
00379 {
00380 int fd = open(file.c_str(), O_CREAT|O_EXCL|O_WRONLY, 0664);
00381 if (fd < 0)
00382 throw error(file, SESSION_WRITE, strerror(errno));
00383
00384
00385
00386 #ifdef SCHROOT_FILEBUF_OLD
00387 __gnu_cxx::stdio_filebuf<char> fdbuf(fd, std::ios::out, true, BUFSIZ);
00388 #else
00389 __gnu_cxx::stdio_filebuf<char> fdbuf(fd, std::ios::out);
00390 #endif
00391 std::ostream output(&fdbuf);
00392 output.imbue(std::locale::classic());
00393
00394 sbuild::file_lock lock(fd);
00395 try
00396 {
00397 lock.set_lock(lock::LOCK_EXCLUSIVE, 2);
00398 }
00399 catch (lock::error const& e)
00400 {
00401 throw error(file, FILE_LOCK, e);
00402 }
00403
00404 keyfile details;
00405 get_keyfile(details);
00406 output << details;
00407
00408 try
00409 {
00410 lock.unset_lock();
00411 }
00412 catch (lock::error const& e)
00413 {
00414 throw error(file, FILE_UNLOCK, e);
00415 }
00416 }
00417 else
00418 {
00419 if (unlink(file.c_str()) != 0)
00420 throw error(file, SESSION_UNLINK, strerror(errno));
00421 }
00422 }
00423
00424 void
00425 sbuild::chroot::lock (setup_type type)
00426 {
00427 setup_lock(type, true, 0);
00428 }
00429
00430 void
00431 sbuild::chroot::unlock (setup_type type,
00432 int status)
00433 {
00434 setup_lock(type, false, status);
00435 }
00436
00437
00438 void
00439 sbuild::chroot::get_details (format_detail& detail) const
00440 {
00441 detail
00442 .add(_("Name"), get_name())
00443 .add(_("Description"), get_description())
00444 .add(_("Type"), get_chroot_type())
00445 .add(_("Priority"), get_priority())
00446 .add(_("Users"), get_users())
00447 .add(_("Groups"), get_groups())
00448 .add(_("Root Users"), get_root_users())
00449 .add(_("Root Groups"), get_root_groups())
00450 .add(_("Aliases"), get_aliases())
00451 .add(_("Run Setup Scripts"), get_run_setup_scripts())
00452 .add(_("Run Execution Scripts"),
00453 get_run_exec_scripts())
00454 .add(_("Session Managed"),
00455 static_cast<bool>(get_session_flags() & chroot::SESSION_CREATE));
00456
00457 if (!get_command_prefix().empty())
00458 detail.add(_("Command Prefix"), get_command_prefix());
00459
00460 detail.add(_("Personality"), get_persona().get_name());
00461
00462
00463 if (!get_location().empty())
00464 detail.add(_("Location"), get_location());
00465 if (!get_mount_location().empty())
00466 detail.add(_("Mount Location"), get_mount_location());
00467 if (!get_path().empty())
00468 detail.add(_("Path"), get_path());
00469 if (!get_mount_device().empty())
00470
00471 detail.add(_("Mount Device"), get_mount_device());
00472 }
00473
00474 void
00475 sbuild::chroot::print_details (std::ostream& stream) const
00476 {
00477 format_detail fmt((this->active == true ? _("Session") : _("Chroot")),
00478 stream.getloc());
00479
00480 get_details(fmt);
00481
00482 stream << fmt;
00483 }
00484
00485 void
00486 sbuild::chroot::get_keyfile (keyfile& keyfile) const
00487 {
00488 keyfile.remove_group(get_name());
00489
00490 keyfile::set_object_value(*this, &chroot::get_chroot_type,
00491 keyfile, get_name(), "type");
00492
00493 keyfile::set_object_value(*this, &chroot::get_active,
00494 keyfile, get_name(), "active");
00495
00496 keyfile::set_object_value(*this, &chroot::get_run_setup_scripts,
00497 keyfile, get_name(), "run-setup-scripts");
00498
00499 keyfile::set_object_value(*this, &chroot::get_run_exec_scripts,
00500 keyfile, get_name(), "run-exec-scripts");
00501
00502 keyfile::set_object_value(*this, &chroot::get_priority,
00503 keyfile, get_name(), "priority");
00504
00505 keyfile::set_object_list_value(*this, &chroot::get_aliases,
00506 keyfile, get_name(), "aliases");
00507
00508 keyfile::set_object_value(*this, &chroot::get_description,
00509 keyfile, get_name(), "description");
00510
00511 keyfile::set_object_list_value(*this, &chroot::get_users,
00512 keyfile, get_name(), "users");
00513
00514 keyfile::set_object_list_value(*this, &chroot::get_groups,
00515 keyfile, get_name(), "groups");
00516
00517 keyfile::set_object_list_value(*this, &chroot::get_root_users,
00518 keyfile, get_name(), "root-users");
00519
00520 keyfile::set_object_list_value(*this, &chroot::get_root_groups,
00521 keyfile, get_name(), "root-groups");
00522
00523 if (get_active())
00524 keyfile::set_object_value(*this, &chroot::get_mount_location,
00525 keyfile, get_name(), "mount-location");
00526
00527 if (get_active())
00528 keyfile::set_object_value(*this, &chroot::get_mount_device,
00529 keyfile, get_name(), "mount-device");
00530
00531 keyfile::set_object_list_value(*this, &chroot::get_command_prefix,
00532 keyfile, get_name(), "command-prefix");
00533
00534 keyfile::set_object_value(*this, &chroot::get_persona,
00535 keyfile, get_name(), "personality");
00536 }
00537
00538 void
00539 sbuild::chroot::set_keyfile (keyfile const& keyfile)
00540 {
00541
00542
00543 keyfile::get_object_value(*this, &chroot::set_active,
00544 keyfile, get_name(), "active",
00545 keyfile::PRIORITY_REQUIRED);
00546
00547 keyfile::get_object_value(*this, &chroot::set_run_setup_scripts,
00548 keyfile, get_name(), "run-setup-scripts",
00549 keyfile::PRIORITY_OPTIONAL);
00550
00551 keyfile::get_object_value(*this, &chroot::set_run_exec_scripts,
00552 keyfile, get_name(), "run-session-scripts",
00553 keyfile::PRIORITY_DEPRECATED);
00554 keyfile::get_object_value(*this, &chroot::set_run_exec_scripts,
00555 keyfile, get_name(), "run-exec-scripts",
00556 keyfile::PRIORITY_OPTIONAL);
00557
00558 keyfile::get_object_value(*this, &chroot::set_priority,
00559 keyfile, get_name(), "priority",
00560 keyfile::PRIORITY_OPTIONAL);
00561
00562 keyfile::get_object_list_value(*this, &chroot::set_aliases,
00563 keyfile, get_name(), "aliases",
00564 keyfile::PRIORITY_OPTIONAL);
00565
00566 keyfile::get_object_value(*this, &chroot::set_description,
00567 keyfile, get_name(), "description",
00568 keyfile::PRIORITY_OPTIONAL);
00569
00570 keyfile::get_object_list_value(*this, &chroot::set_users,
00571 keyfile, get_name(), "users",
00572 keyfile::PRIORITY_OPTIONAL);
00573
00574 keyfile::get_object_list_value(*this, &chroot::set_groups,
00575 keyfile, get_name(), "groups",
00576 keyfile::PRIORITY_OPTIONAL);
00577
00578 keyfile::get_object_list_value(*this, &chroot::set_root_users,
00579 keyfile, get_name(), "root-users",
00580 keyfile::PRIORITY_OPTIONAL);
00581
00582 keyfile::get_object_list_value(*this, &chroot::set_root_groups,
00583 keyfile, get_name(), "root-groups",
00584 keyfile::PRIORITY_OPTIONAL);
00585
00586 keyfile::get_object_value(*this, &chroot::set_mount_location,
00587 keyfile, get_name(), "mount-location",
00588 get_active() ?
00589 keyfile::PRIORITY_REQUIRED :
00590 keyfile::PRIORITY_DISALLOWED);
00591
00592 keyfile::get_object_value(*this, &chroot::set_mount_device,
00593 keyfile, get_name(), "mount-device",
00594 get_active() ?
00595 keyfile::PRIORITY_OPTIONAL :
00596 keyfile::PRIORITY_DISALLOWED);
00597
00598 keyfile::get_object_list_value(*this, &chroot::set_command_prefix,
00599 keyfile, get_name(), "command-prefix",
00600 keyfile::PRIORITY_OPTIONAL);
00601
00602 keyfile::get_object_value(*this, &chroot::set_persona,
00603 keyfile, get_name(), "personality",
00604 keyfile::PRIORITY_OPTIONAL);
00605 }