summaryrefslogtreecommitdiff
path: root/src/cstore/unionfs/cstore-unionfs.hpp
blob: dd44d9af61b2bff689c6eb330fc2aa3a08f9cde9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
/*
 * 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 <http://www.gnu.org/licenses/>.
 */

#ifndef _CSTORE_UNIONFS_H_
#define _CSTORE_UNIONFS_H_
#include <vector>
#include <string>

#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>

#include <boost/filesystem.hpp>

#include <cli_cstore.h>
#include <cstore/cstore.hpp>

namespace b_fs = boost::filesystem;

class UnionfsCstore : public Cstore {
public:
  UnionfsCstore(bool use_edit_level = false);
  UnionfsCstore(const string& session_id, string& env);
  ~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
  map<const void *, pair<b_fs::path, b_fs::path> > 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<string>& path_comps) {
    for (unsigned int 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<b_fs::path, b_fs::path> p;
    p.first = mutable_cfg_path;
    p.second = tmpl_path;
    saved_paths[handle] = p;
  };
  void restore_paths(const void *handle = NULL) {
    map<const void *, pair<b_fs::path, b_fs::path> >::iterator it
      = saved_paths.find(handle);
    if (it == saved_paths.end()) {
      exit_internal("restore_paths: handle not found\n");
    }
    pair<b_fs::path, b_fs::path> 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<string>& cnodes, bool active_cfg);
  void get_all_tmpl_child_node_names(vector<string>& cnodes) {
    get_all_child_dir_names(tmpl_path, cnodes);
  };
  bool write_value_vec(const vector<string>& 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();
  bool remove_comment();
  bool set_comment(const string& comment);
  bool discard_changes(unsigned long long& num_removed);

  // observers for work path
  bool marked_changed();
  bool marked_display_default();

  // observers for work path or active path
  bool cfg_node_exists(bool active_cfg);
  bool read_value_vec(vector<string>& vvec, bool active_cfg);
  bool marked_deactivated(bool active_cfg);
  bool get_comment(string& comment, 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<string>& 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<string>& 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);
};

#endif /* _CSTORE_UNIONFS_H_ */