/*
* Copyright (C) 2010 Vyatta, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
#ifndef _CSTORE_UNIONFS_H_
#define _CSTORE_UNIONFS_H_
#include
#include
#include
#include
#include
#include
#include
#include
#include
namespace b_fs = boost::filesystem;
class UnionfsCstore : public Cstore {
public:
UnionfsCstore(bool use_edit_level = false);
UnionfsCstore(const string& session_id, string& env);
virtual ~UnionfsCstore();
////// public virtual functions declared in base class
bool markSessionUnsaved();
bool unmarkSessionUnsaved();
bool sessionUnsaved();
bool sessionChanged();
bool setupSession();
bool teardownSession();
bool inSession();
private:
// constants
static const string C_ENV_TMPL_ROOT;
static const string C_ENV_WORK_ROOT;
static const string C_ENV_ACTIVE_ROOT;
static const string C_ENV_CHANGE_ROOT;
static const string C_ENV_TMP_ROOT;
static const string C_DEF_TMPL_ROOT;
static const string C_DEF_CFG_ROOT;
static const string C_DEF_ACTIVE_ROOT;
static const string C_DEF_CHANGE_PREFIX;
static const string C_DEF_WORK_PREFIX;
static const string C_DEF_TMP_PREFIX;
static const string C_MARKER_DEF_VALUE;
static const string C_MARKER_DEACTIVATE;
static const string C_MARKER_CHANGED;
static const string C_MARKER_UNSAVED;
static const string C_COMMITTED_MARKER_FILE;
static const string C_COMMENT_FILE;
static const string C_TAG_NAME;
static const string C_VAL_NAME;
static const string C_DEF_NAME;
static const size_t MAX_FILE_READ_SIZE = 8192;
// root dirs (constant)
b_fs::path work_root; // working root (union)
b_fs::path active_root; // active root (readonly part of union)
b_fs::path change_root; // change root (r/w part of union)
b_fs::path tmp_root; // temp root
b_fs::path tmpl_root; // template root
// path buffers
b_fs::path mutable_cfg_path; // mutable part of config path
b_fs::path tmpl_path; // whole template path
Cstore::MapT > saved_paths;
// saved mutable part of cfg path and whole template path
////// virtual functions defined in base class
// begin path modifiers
void push_tmpl_path(const string& new_comp) {
push_path(tmpl_path, new_comp);
};
void push_tmpl_path_tag() {
push_tmpl_path(C_TAG_NAME);
};
string pop_tmpl_path() {
return pop_path(tmpl_path);
};
void push_cfg_path(const string& new_comp) {
push_path(mutable_cfg_path, new_comp);
};
void push_cfg_path_val() {
push_cfg_path(C_VAL_NAME);
};
string pop_cfg_path() {
return pop_path(mutable_cfg_path);
};
void append_cfg_path(const vector& path_comps) {
for (size_t i = 0; i < path_comps.size(); i++) {
push_cfg_path(path_comps[i]);
}
};
void reset_paths() {
tmpl_path = tmpl_root;
mutable_cfg_path = "";
};
void save_paths(const void *handle = NULL) {
pair p;
p.first = mutable_cfg_path;
p.second = tmpl_path;
saved_paths[handle] = p;
};
void restore_paths(const void *handle = NULL) {
Cstore::MapT >::iterator it
= saved_paths.find(handle);
if (it == saved_paths.end()) {
exit_internal("restore_paths: handle not found\n");
}
pair p = saved_paths[handle];
mutable_cfg_path = p.first;
tmpl_path = p.second;
};
bool cfg_path_at_root() {
return (!mutable_cfg_path.has_parent_path());
};
bool tmpl_path_at_root() {
return (tmpl_path.file_string() == tmpl_root.file_string());
};
// end path modifiers
// these operate on current tmpl path
bool tmpl_node_exists();
bool tmpl_parse(vtw_def& def);
// these operate on current work path
bool add_node();
bool remove_node();
void get_all_child_node_names_impl(vector& cnodes, bool active_cfg);
void get_all_tmpl_child_node_names(vector& cnodes) {
get_all_child_dir_names(tmpl_path, cnodes);
};
bool write_value_vec(const vector& vvec, bool active_cfg);
bool rename_child_node(const string& oname, const string& nname);
bool copy_child_node(const string& oname, const string& nname);
bool mark_display_default();
bool unmark_display_default();
bool mark_deactivated();
bool unmark_deactivated();
bool unmark_deactivated_descendants();
bool mark_changed_with_ancestors();
bool unmark_changed_with_descendants();
bool remove_comment();
bool set_comment(const string& comment);
bool discard_changes(unsigned long long& num_removed);
// observers for work path
bool cfg_node_changed();
// observers for work path or active path
bool cfg_node_exists(bool active_cfg);
bool read_value_vec(vector& vvec, bool active_cfg);
bool marked_deactivated(bool active_cfg);
bool get_comment(string& comment, bool active_cfg);
bool marked_display_default(bool active_cfg);
// observers during commit operation
bool marked_committed(const vtw_def& def, bool is_set);
// these operate on both current tmpl and work paths
bool validate_val_impl(vtw_def *def, char *value);
// observers for "edit/tmpl levels" (for "edit"-related operations).
// note that these should be moved to base class in the future.
string get_edit_level_path() {
return cfg_path_to_str();
};
string get_tmpl_level_path() {
return tmpl_path_to_str();
};
void get_edit_level(vector& path_comps);
bool edit_level_at_root() {
return cfg_path_at_root();
};
// for testing/debugging
string cfg_path_to_str();
string tmpl_path_to_str();
////// private functions
b_fs::path get_work_path() { return (work_root / mutable_cfg_path); };
b_fs::path get_active_path() { return (active_root / mutable_cfg_path); };
b_fs::path get_change_path() { return (change_root / mutable_cfg_path); };
void push_path(b_fs::path& old_path, const string& new_comp);
string pop_path(b_fs::path& path);
void get_all_child_dir_names(b_fs::path root, vector& nodes);
bool write_file(const string& file, const string& data);
bool create_file(const string& file) {
return write_file(file, "");
};
bool read_whole_file(const b_fs::path& file, string& data);
bool committed_marker_exists(const string& marker);
void recursive_copy_dir(const b_fs::path& src, const b_fs::path& dst);
// boost fs operations wrappers
bool b_fs_exists(const b_fs::path& path) {
try { return b_fs::exists(path); } catch (...) { return false; }
};
bool b_fs_is_directory(const b_fs::path& path) {
try { return b_fs::is_directory(path); } catch (...) { return false; }
};
bool b_fs_is_regular(const b_fs::path& path) {
try { return b_fs::is_regular(path); } catch (...) { return false; }
};
};
#endif /* _CSTORE_UNIONFS_H_ */