Skip to content
API Documentation
BastionGuard™
FsTabEntry.vala
Go to the documentation of this file.
1/*
2 * FsTabEntry.vala
3 *
4 * Copyright 2012-2018 Tony George <teejeetech@gmail.com>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19 * MA 02110-1301, USA.
20 *
21 *
22 */
23
24using TeeJee.Logging;
29using TeeJee.System;
30using TeeJee.Misc;
31
32public class FsTabEntry : GLib.Object{
33
34 public bool is_comment = false;
35 public bool is_empty_line = false;
36
37 public string device_string = "";
38 public string mount_point = "";
39 public string type = "";
40 public string options = "defaults";
41 public string dump = "0";
42 public string pass = "0";
43 public string line = "";
44
45 public string device_uuid {
46 owned get{
47 if (device_string.down().has_prefix("uuid=")){
48 return device_string.replace("\"","").replace("'","").split("=")[1];
49 }
50 else{
51 return "";
52 }
53 }
54 set {
55 device_string = "UUID=%s".printf(value);
56 }
57 }
58
59 public static Gee.ArrayList<FsTabEntry> read_file(string file_path){
60
61 var list = new Gee.ArrayList<FsTabEntry>();
62
63 if (!file_exists(file_path)){ return list; }
64
65 string text = file_read(file_path);
66
67 string[] lines = text.split("\n");
68
69 foreach(string line in lines){
70
71 var entry = new FsTabEntry();
72 list.add(entry);
73
74 entry.is_comment = line.strip().has_prefix("#");
75 entry.is_empty_line = (line.strip().length == 0);
76
77 if (entry.is_comment){
78
79 entry.line = line;
80 }
81 else if (entry.is_empty_line){
82
83 entry.line = "";
84 }
85 else{
86 entry.line = line;
87
88 string[] parts = line.replace("\t"," ").split(" ");
89
90 int part_num = -1;
91
92 foreach(string part in parts){
93
94 if (part.strip().length == 0) { continue; }
95
96 switch (++part_num){
97 case 0:
98 entry.device_string = part.strip();
99 break;
100 case 1:
101 entry.mount_point = part.strip();
102 break;
103 case 2:
104 entry.type = part.strip();
105 break;
106 case 3:
107 entry.options = part.strip();
108 break;
109 case 4:
110 entry.dump = part.strip();
111 break;
112 case 5:
113 entry.pass = part.strip();
114 break;
115 }
116 }
117 }
118 }
119
120 return list;
121 }
122
123 public static string write_file(
124 Gee.ArrayList<FsTabEntry> entries, string file_path,
125 bool keep_comments_and_empty_lines = false){
126
127 string text = "";
128
129 if (!keep_comments_and_empty_lines){
130 text += "# <file system> <mount point> <type> <options> <dump> <pass>\n\n";
131 }
132
133 foreach(var entry in entries){
134 if (entry.is_comment || entry.is_empty_line){
135 if (keep_comments_and_empty_lines){
136 text += "%s\n".printf(entry.line);
137 }
138 }
139 else {
140 text += "%s\t%s\t%s\t%s\t%s\t%s\n".printf(
141 entry.device_string, entry.mount_point, entry.type,
142 entry.options, entry.dump, entry.pass);
143 }
144 }
145
146 // sort the entries based on mount path
147 // this is required to ensure that base paths are mounted before child paths
148
149 entries.sort((a, b)=>{
150 return strcmp(a.mount_point, b.mount_point);
151 });
152
153 if (file_exists(file_path)){
154 file_delete(file_path);
155 }
156
157 file_write(file_path, text);
158
159 return text;
160 }
161
162 public string subvolume_name(){
163
164 if (options.down().contains("subvol=")){
165 string txt = options.split("subvol=")[1].split(",")[0].strip();
166 if (txt.has_prefix("/") && (txt.split("/").length == 2)){
167 txt = txt.split("/")[1];
168 }
169 return txt;
170 }
171 else{
172 return "";
173 }
174 }
175
176 public bool is_for_system_directory(){
177
178 if (mount_point.has_prefix("/mnt")
179 || mount_point.has_prefix("/mount")
180 || mount_point.has_prefix("/sdcard")
181 || mount_point.has_prefix("/cdrom")
182 || mount_point.has_prefix("/media")
183 || (mount_point == "none")
184 || !mount_point.has_prefix("/")
185 || (!device_string.has_prefix("/dev/") && !device_string.down().has_prefix("uuid="))){
186
187 return false;
188 }
189 else{
190 return true;
191 }
192 }
193
194 public static FsTabEntry? find_entry_by_mount_point(Gee.ArrayList<FsTabEntry> entries, string mount_path){
195
196 foreach(var entry in entries){
197 if (entry.mount_point == mount_path){
198 return entry;
199 }
200 }
201 return null;
202 }
203
204 public Device? resolve_device(Gee.ArrayList<CryptTabEntry> crypttab, Gtk.Window? parent_window){
205
206 Device dev_fstab = null;
207 if (device_uuid.length > 0){
208 dev_fstab = Device.get_device_by_uuid(device_uuid);
209 }
210 else{
211 dev_fstab = Device.get_device_by_name(device_string);
212 }
213
214 if (dev_fstab == null){
215
216 /*
217 Check if the device mentioned in fstab entry is a mapped device.
218 If it is, then try finding the parent device which may be available on the current system.
219 Prompt user to unlock it if found.
220
221 Note:
222 Mapped name may be different on running system, or it may be same.
223 Since it is not reliable, we will try to identify the parent instead of the mapped device.
224 */
225
226 if (device_string.has_prefix("/dev/mapper/")){
227
228 string mapped_name = device_string.replace("/dev/mapper/","");
229
230 foreach(var item in crypttab){
231
232 if (item.mapped_name == mapped_name){
233
234 // we found the entry for the mapped device
235 device_string = item.device_string;
236
237 if (device_uuid.length > 0){
238
239 // we have the parent's uuid. get the luks device and prompt user to unlock it.
240 var dev_luks = Device.get_device_by_uuid(device_uuid);
241
242 if (dev_luks != null){
243
244 string msg_out, msg_err;
245 var dev_unlocked = Device.luks_unlock(
246 dev_luks, "", "", parent_window, out msg_out, out msg_err);
247
248 if (dev_unlocked != null){
249 dev_fstab = dev_unlocked;
250 }
251 else{
252 dev_fstab = dev_luks; // map to parent
253 }
254 }
255 }
256 else{
257 // nothing to do: we don't have the parent's uuid
258 }
259
260 break;
261 }
262 }
263 }
264 }
265
266 return dev_fstab;
267 }
268
269 public void append_option(string option){
270
271 if (!options.contains(option)){
272 options += ",%s".printf(option);
273 }
274
275 if(options.has_prefix(",")){
276 options = options[1:options.length];
277 }
278
279 options = options.strip();
280 }
281
282 public void remove_option(string option){
283
284 options = options.replace(option,"").strip();
285
286 if(options.has_prefix(",")){
287 options = options[1:options.length];
288 }
289
290 if (options.has_suffix(",")){
291 options = options[0:options.length - 1];
292 }
293
294 options = options.strip();
295 }
296}
static ? Device get_device_by_uuid(string uuid)
Definition Device.vala:1081
static ? Device get_device_by_name(string file_name)
Definition Device.vala:1086
string dump
string device_string
string mount_point
string options
bool is_empty_line
string pass
bool is_comment
string line
string type
bool file_exists(string file_path)
string? file_read(string file_path)
bool file_write(string file_path, string contents)
bool file_delete(string file_path)