Regular dirs added in the next commit.
Change-Id: I2b859f71174c690fa2c1658f2986fad60dd803e9
struct DirBackendAdd {
virtual fs::path AddSubsessionPrepare (const fs::path& subsession_path, int uid, int gid) const = 0;
+ virtual bool AddSubsessionPrepareFromTemplate (const std::string_view subsession_name, const fs::path& main_path, int uid, int gid) const = 0;
virtual void AddSubsessionFinalize (const fs::path& tmpdir_path, const fs::path& subsession_path, int uid, int gid) const = 0;
virtual void AddSubsessionCleanupFailure (const fs::path& tmpdir_path, const fs::path& subsession_path) const = 0;
virtual std::string_view TemplateName() const = 0;
throw;
}
+bool DirBackendAddFixedSize::AddSubsessionPrepareFromTemplate (const std::string_view subsession_name, const fs::path& main_path, int uid, int gid) const
+{
+ if (!OS::have_resize2fs())
+ return false;
+
+ const auto template_dir = main_path / TemplateName();
+ const auto template_img = DirBackendFixedSize::GetImagePathFromSubsessionPath(template_dir);
+ const auto subsession_dir = main_path / subsession_name;
+ const auto subsession_img = DirBackendFixedSize::GetImagePathFromSubsessionPath(subsession_dir);
+
+ /* Unmount to make sure the image copy is in a consistent state. */
+ OS::do_umount(template_dir);
+
+ try {
+ /* Note that this could be slightly faster if we kept two copies
+ * of the template and just renamed one of them, then later after
+ * sending the "adding done" D-Bus event we would clone the other
+ * copy. However that would come with a disk usage trade-off and
+ * make for more complicated sessiond architecture. */
+ fs::copy_file(template_img, subsession_img);
+ } catch (const std::exception &ex) {
+ LOGE("Could not copy template image '%s' to '%s' for uid=%d: %s"
+ , template_img.c_str()
+ , subsession_img.c_str()
+ , uid
+ , ex.what()
+ );
+
+ OS::do_mount(template_img, template_dir);
+ throw;
+ }
+
+ OS::do_mount(template_img, template_dir);
+
+ try {
+ OS::do_resize2fs(subsession_img, size_kB);
+ OS::change_owner_and_group(subsession_img, uid, gid);
+ fs::create_directory(subsession_dir);
+ } catch (const std::exception &ex) {
+ LOGE("Could not work on image '%s' for uid=%d: %s"
+ , subsession_img.c_str()
+ , uid
+ , ex.what()
+ );
+ throw;
+ }
+
+ OS::do_mount(subsession_img, subsession_dir);
+ return true;
+}
+
void DirBackendAddFixedSize::AddSubsessionCleanupFailure (const fs::path& tmpdir_path, const fs::path& subsession_path) const
{
auto tmp_image_path = DirBackendFixedSize::GetImagePathFromSubsessionPath(subsession_path);
DirBackendAddFixedSize(uint32_t s) : size_kB(s) { }
fs::path AddSubsessionPrepare (const fs::path& subsession_path, int uid, int gid) const override;
+ bool AddSubsessionPrepareFromTemplate (const std::string_view subsession_name, const fs::path& main_path, int uid, int gid) const override;
void AddSubsessionFinalize (const fs::path& tmpdir_path, const fs::path& subsession_path, int uid, int gid) const override;
void AddSubsessionCleanupFailure (const fs::path& tmpdir_path, const fs::path& subsession_path) const override;
std::string_view TemplateName() const override;
fs::rename(tmpdir_path, subsession_path);
}
+bool DirBackendAddRegularDir::AddSubsessionPrepareFromTemplate (const std::string_view subsession_name, const fs::path& main_path, int uid, int gid) const
+{
+ return false; // not supported yet
+}
+
void DirBackendAddRegularDir::AddSubsessionCleanupFailure (const fs::path& tmpdir_path, const fs::path& subsession_path) const
{
fs::remove_all(tmpdir_path);
struct DirBackendAddRegularDir : public DirBackendAdd {
fs::path AddSubsessionPrepare (const fs::path& subsession_path, int uid, int gid) const override;
+ bool AddSubsessionPrepareFromTemplate (const std::string_view subsession_name, const fs::path& main_path, int uid, int gid) const override;
void AddSubsessionFinalize (const fs::path& tmpdir_path, const fs::path& subsession_path, int uid, int gid) const override;
void AddSubsessionCleanupFailure (const fs::path& tmpdir_path, const fs::path& subsession_path) const override;
std::string_view TemplateName() const override;
throw std::runtime_error("Couldn't add user subsession data");
}
+ try {
+ const bool added_via_template = backend.AddSubsessionPrepareFromTemplate
+ ( subsession_id
+ , main_path
+ , session_uid
+ , OS::get_gid_from_name(system_share_group)
+ );
+ if (added_via_template)
+ return;
+ }
+ catch (const std::exception &ex) {
+ LOGE("Exception while creating subsession from template [session_uid=%d subsession_id=%s]: %s", session_uid, subsession_id.data(), ex.what());
+ }
+
add_user_subsession_inner(main_path, session_uid, subsession_id, backend, false);
}