]>
Commit | Line | Data |
---|---|---|
6c40a53d KZ |
1 | /* |
2 | * Copyright (C) 2010 Karel Zak <kzak@redhat.com> | |
3 | * | |
4 | * This file may be redistributed under the terms of the | |
5 | * GNU Lesser General Public License. | |
6 | */ | |
7 | ||
8 | /** | |
30493710 | 9 | * SECTION: update |
63de90d4 KZ |
10 | * @title: Tables update |
11 | * @short_description: userspace mount information management | |
0f32f1e2 | 12 | * |
d58b3157 OO |
13 | * The struct libmnt_update provides an abstraction to manage mount options in |
14 | * userspace independently of system configuration. This low-level API works on | |
15 | * systems both with and without /etc/mtab. On systems without the regular /etc/mtab | |
16 | * file, the userspace mount options (e.g. user=) are stored in the /run/mount/utab | |
63de90d4 | 17 | * file. |
0f32f1e2 | 18 | * |
68164f6c | 19 | * It's recommended to use high-level struct libmnt_context API. |
6c40a53d | 20 | */ |
1d0cd73f KZ |
21 | #include <sys/file.h> |
22 | #include <fcntl.h> | |
8f60ea34 | 23 | #include <signal.h> |
6c40a53d | 24 | |
6c40a53d KZ |
25 | #include "mountP.h" |
26 | #include "mangle.h" | |
27 | #include "pathnames.h" | |
28 | ||
68164f6c | 29 | struct libmnt_update { |
1d0cd73f | 30 | char *target; |
68164f6c | 31 | struct libmnt_fs *fs; |
77417bc0 | 32 | char *filename; |
1d0cd73f KZ |
33 | unsigned long mountflags; |
34 | int userspace_only; | |
35 | int ready; | |
c4c66355 KZ |
36 | |
37 | struct libmnt_table *mountinfo; | |
6c40a53d KZ |
38 | }; |
39 | ||
c4c66355 KZ |
40 | static int set_fs_root(struct libmnt_update *upd, struct libmnt_fs *fs, unsigned long mountflags); |
41 | static int utab_new_entry(struct libmnt_update *upd, struct libmnt_fs *fs, unsigned long mountflags); | |
1d0cd73f | 42 | |
6c40a53d | 43 | /** |
30493710 | 44 | * mnt_new_update: |
6c40a53d | 45 | * |
1d0cd73f | 46 | * Returns: newly allocated update handler |
6c40a53d | 47 | */ |
68164f6c | 48 | struct libmnt_update *mnt_new_update(void) |
6c40a53d | 49 | { |
68164f6c | 50 | struct libmnt_update *upd; |
6c40a53d | 51 | |
68164f6c | 52 | upd = calloc(1, sizeof(*upd)); |
30493710 | 53 | if (!upd) |
6c40a53d KZ |
54 | return NULL; |
55 | ||
83a78332 | 56 | DBG(UPDATE, ul_debugobj(upd, "allocate")); |
30493710 | 57 | return upd; |
6c40a53d KZ |
58 | } |
59 | ||
60 | /** | |
30493710 KZ |
61 | * mnt_free_update: |
62 | * @upd: update | |
6c40a53d | 63 | * |
68164f6c | 64 | * Deallocates struct libmnt_update handler. |
6c40a53d | 65 | */ |
68164f6c | 66 | void mnt_free_update(struct libmnt_update *upd) |
6c40a53d | 67 | { |
30493710 | 68 | if (!upd) |
6c40a53d KZ |
69 | return; |
70 | ||
83a78332 | 71 | DBG(UPDATE, ul_debugobj(upd, "free")); |
6c40a53d | 72 | |
26d0c0ae | 73 | mnt_unref_fs(upd->fs); |
c9f1585e | 74 | mnt_unref_table(upd->mountinfo); |
1d0cd73f | 75 | free(upd->target); |
77417bc0 | 76 | free(upd->filename); |
30493710 | 77 | free(upd); |
6c40a53d KZ |
78 | } |
79 | ||
77417bc0 | 80 | /* |
6f5788c5 | 81 | * Returns 0 on success, <0 in case of error. |
77417bc0 | 82 | */ |
c570f567 KZ |
83 | int mnt_update_set_filename(struct libmnt_update *upd, const char *filename, |
84 | int userspace_only) | |
77417bc0 KZ |
85 | { |
86 | const char *path = NULL; | |
87 | int rw = 0; | |
88 | ||
ba2bdf41 KZ |
89 | if (!upd) |
90 | return -EINVAL; | |
77417bc0 KZ |
91 | |
92 | /* filename explicitly defined */ | |
93 | if (filename) { | |
94 | char *p = strdup(filename); | |
95 | if (!p) | |
96 | return -ENOMEM; | |
97 | ||
98 | upd->userspace_only = userspace_only; | |
99 | free(upd->filename); | |
100 | upd->filename = p; | |
101 | } | |
102 | ||
103 | if (upd->filename) | |
104 | return 0; | |
105 | ||
a362ae60 | 106 | /* detect tab filename -- /etc/mtab or /run/mount/utab |
77417bc0 | 107 | */ |
e778642a | 108 | #ifdef USE_LIBMOUNT_SUPPORT_MTAB |
77417bc0 | 109 | mnt_has_regular_mtab(&path, &rw); |
e778642a | 110 | #endif |
77417bc0 KZ |
111 | if (!rw) { |
112 | path = NULL; | |
113 | mnt_has_regular_utab(&path, &rw); | |
114 | if (!rw) | |
6f5788c5 | 115 | return -EACCES; |
77417bc0 KZ |
116 | upd->userspace_only = TRUE; |
117 | } | |
118 | upd->filename = strdup(path); | |
119 | if (!upd->filename) | |
120 | return -ENOMEM; | |
121 | ||
122 | return 0; | |
123 | } | |
124 | ||
36bda5cb KZ |
125 | /** |
126 | * mnt_update_get_filename: | |
127 | * @upd: update | |
128 | * | |
d58b3157 | 129 | * This function returns the file name (e.g. /etc/mtab) of the up-dated file. |
36bda5cb KZ |
130 | * |
131 | * Returns: pointer to filename that will be updated or NULL in case of error. | |
132 | */ | |
68164f6c | 133 | const char *mnt_update_get_filename(struct libmnt_update *upd) |
36bda5cb | 134 | { |
86cd5870 | 135 | return upd ? upd->filename : NULL; |
36bda5cb KZ |
136 | } |
137 | ||
6c40a53d | 138 | /** |
1d0cd73f KZ |
139 | * mnt_update_is_ready: |
140 | * @upd: update handler | |
d300992d | 141 | * |
1d0cd73f | 142 | * Returns: 1 if entry described by @upd is successfully prepared and will be |
d58b3157 | 143 | * written to the mtab/utab file. |
d300992d | 144 | */ |
68164f6c | 145 | int mnt_update_is_ready(struct libmnt_update *upd) |
d300992d | 146 | { |
1d0cd73f | 147 | return upd ? upd->ready : FALSE; |
6c40a53d KZ |
148 | } |
149 | ||
6c40a53d | 150 | /** |
30493710 | 151 | * mnt_update_set_fs: |
1d0cd73f KZ |
152 | * @upd: update handler |
153 | * @mountflags: MS_* flags | |
f12aac6e | 154 | * @target: umount target, must be NULL for mount |
2915bdc0 | 155 | * @fs: mount filesystem description, must be NULL for umount |
d300992d | 156 | * |
6f5788c5 | 157 | * Returns: <0 in case on error, 0 on success, 1 if update is unnecessary. |
6c40a53d | 158 | */ |
68164f6c KZ |
159 | int mnt_update_set_fs(struct libmnt_update *upd, unsigned long mountflags, |
160 | const char *target, struct libmnt_fs *fs) | |
6c40a53d | 161 | { |
77417bc0 KZ |
162 | int rc; |
163 | ||
30493710 | 164 | if (!upd) |
3a5b1b1d | 165 | return -EINVAL; |
2915bdc0 KZ |
166 | if ((mountflags & MS_MOVE) && (!fs || !mnt_fs_get_srcpath(fs))) |
167 | return -EINVAL; | |
168 | if (target && fs) | |
169 | return -EINVAL; | |
6c40a53d | 170 | |
83a78332 | 171 | DBG(UPDATE, ul_debugobj(upd, |
26e42d81 | 172 | "resetting FS [fs=0x%p, target=%s, flags=0x%08lx]", |
1d0cd73f | 173 | fs, target, mountflags)); |
87a07a4c | 174 | if (fs) { |
83a78332 | 175 | DBG(UPDATE, ul_debugobj(upd, "FS template:")); |
87a07a4c KZ |
176 | DBG(UPDATE, mnt_fs_print_debug(fs, stderr)); |
177 | } | |
6c40a53d | 178 | |
26d0c0ae | 179 | mnt_unref_fs(upd->fs); |
1d0cd73f KZ |
180 | free(upd->target); |
181 | upd->ready = FALSE; | |
182 | upd->fs = NULL; | |
183 | upd->target = NULL; | |
36bda5cb KZ |
184 | upd->mountflags = 0; |
185 | ||
186 | if (mountflags & MS_PROPAGATION) | |
187 | return 1; | |
188 | ||
1d0cd73f | 189 | upd->mountflags = mountflags; |
6c40a53d | 190 | |
77417bc0 | 191 | rc = mnt_update_set_filename(upd, NULL, 0); |
6f5788c5 | 192 | if (rc) { |
83a78332 | 193 | DBG(UPDATE, ul_debugobj(upd, "no writable file available [rc=%d]", rc)); |
77417bc0 | 194 | return rc; /* error or no file available (rc = 1) */ |
6f5788c5 | 195 | } |
2915bdc0 KZ |
196 | if (target) { |
197 | upd->target = strdup(target); | |
198 | if (!upd->target) | |
199 | return -ENOMEM; | |
200 | ||
201 | } else if (fs) { | |
1d0cd73f | 202 | if (upd->userspace_only && !(mountflags & MS_MOVE)) { |
8228372b | 203 | rc = utab_new_entry(upd, fs, mountflags); |
1d0cd73f KZ |
204 | if (rc) |
205 | return rc; | |
206 | } else { | |
f84fa6f7 | 207 | upd->fs = mnt_copy_mtab_fs(fs); |
1d0cd73f KZ |
208 | if (!upd->fs) |
209 | return -ENOMEM; | |
f84fa6f7 | 210 | |
1d0cd73f KZ |
211 | } |
212 | } | |
6c40a53d | 213 | |
1d0cd73f | 214 | |
83a78332 | 215 | DBG(UPDATE, ul_debugobj(upd, "ready")); |
1d0cd73f | 216 | upd->ready = TRUE; |
7714c689 | 217 | return 0; |
6c40a53d KZ |
218 | } |
219 | ||
36bda5cb | 220 | /** |
f84fa6f7 KZ |
221 | * mnt_update_get_fs: |
222 | * @upd: update | |
223 | * | |
224 | * Returns: update filesystem entry or NULL | |
97e23b5e | 225 | */ |
68164f6c | 226 | struct libmnt_fs *mnt_update_get_fs(struct libmnt_update *upd) |
97e23b5e KZ |
227 | { |
228 | return upd ? upd->fs : NULL; | |
229 | } | |
1d0cd73f | 230 | |
36bda5cb | 231 | /** |
68164f6c | 232 | * mnt_update_get_mflags: |
36bda5cb KZ |
233 | * @upd: update |
234 | * | |
235 | * Returns: mount flags as was set by mnt_update_set_fs() | |
236 | */ | |
68164f6c | 237 | unsigned long mnt_update_get_mflags(struct libmnt_update *upd) |
36bda5cb KZ |
238 | { |
239 | return upd ? upd->mountflags : 0; | |
240 | } | |
241 | ||
242 | /** | |
243 | * mnt_update_force_rdonly: | |
244 | * @upd: update | |
245 | * @rdonly: is read-only? | |
246 | * | |
247 | * Returns: 0 on success and negative number in case of error. | |
248 | */ | |
68164f6c | 249 | int mnt_update_force_rdonly(struct libmnt_update *upd, int rdonly) |
36bda5cb KZ |
250 | { |
251 | int rc = 0; | |
252 | ||
253 | if (!upd || !upd->fs) | |
254 | return -EINVAL; | |
255 | ||
256 | if (rdonly && (upd->mountflags & MS_RDONLY)) | |
257 | return 0; | |
258 | if (!rdonly && !(upd->mountflags & MS_RDONLY)) | |
259 | return 0; | |
260 | ||
261 | if (!upd->userspace_only) { | |
262 | /* /etc/mtab -- we care about VFS options there */ | |
f2b3a3a3 | 263 | const char *o = mnt_fs_get_options(upd->fs); |
36bda5cb KZ |
264 | char *n = o ? strdup(o) : NULL; |
265 | ||
266 | if (n) | |
267 | mnt_optstr_remove_option(&n, rdonly ? "rw" : "ro"); | |
268 | if (!mnt_optstr_prepend_option(&n, rdonly ? "ro" : "rw", NULL)) | |
f2b3a3a3 | 269 | rc = mnt_fs_set_options(upd->fs, n); |
36bda5cb KZ |
270 | |
271 | free(n); | |
272 | } | |
273 | ||
274 | if (rdonly) | |
275 | upd->mountflags &= ~MS_RDONLY; | |
276 | else | |
277 | upd->mountflags |= MS_RDONLY; | |
278 | ||
279 | return rc; | |
280 | } | |
281 | ||
7e0c0619 | 282 | |
6c40a53d | 283 | /* |
d58b3157 | 284 | * Allocates an utab entry (upd->fs) for mount/remount. This function should be |
c4c66355 | 285 | * called *before* mount(2) syscall. The @fs is used as a read-only template. |
1d0cd73f | 286 | * |
d58b3157 | 287 | * Returns: 0 on success, negative number on error, 1 if utab's update is |
1d0cd73f | 288 | * unnecessary. |
6c40a53d | 289 | */ |
c4c66355 KZ |
290 | static int utab_new_entry(struct libmnt_update *upd, struct libmnt_fs *fs, |
291 | unsigned long mountflags) | |
6c40a53d | 292 | { |
1d0cd73f | 293 | int rc = 0; |
76a06ca4 | 294 | const char *o = NULL, *a = NULL; |
f84fa6f7 | 295 | char *u = NULL; |
6c40a53d KZ |
296 | |
297 | assert(fs); | |
c4c66355 KZ |
298 | assert(upd); |
299 | assert(upd->fs == NULL); | |
1d0cd73f | 300 | assert(!(mountflags & MS_MOVE)); |
6c40a53d | 301 | |
83a78332 | 302 | DBG(UPDATE, ul_debug("prepare utab entry")); |
6c40a53d | 303 | |
68164f6c | 304 | o = mnt_fs_get_user_options(fs); |
76a06ca4 | 305 | a = mnt_fs_get_attributes(fs); |
c4c66355 | 306 | upd->fs = NULL; |
76a06ca4 | 307 | |
f84fa6f7 KZ |
308 | if (o) { |
309 | /* remove non-mtab options */ | |
310 | rc = mnt_optstr_get_options(o, &u, | |
311 | mnt_get_builtin_optmap(MNT_USERSPACE_MAP), | |
312 | MNT_NOMTAB); | |
313 | if (rc) | |
314 | goto err; | |
315 | } | |
316 | ||
317 | if (!u && !a) { | |
83a78332 | 318 | DBG(UPDATE, ul_debug("utab entry unnecessary (no options)")); |
f84fa6f7 KZ |
319 | return 1; |
320 | } | |
1d0cd73f KZ |
321 | |
322 | /* allocate the entry */ | |
c4c66355 KZ |
323 | upd->fs = mnt_copy_fs(NULL, fs); |
324 | if (!upd->fs) { | |
1d0cd73f KZ |
325 | rc = -ENOMEM; |
326 | goto err; | |
6c40a53d KZ |
327 | } |
328 | ||
c4c66355 | 329 | rc = mnt_fs_set_options(upd->fs, u); |
76a06ca4 KZ |
330 | if (rc) |
331 | goto err; | |
c4c66355 | 332 | rc = mnt_fs_set_attributes(upd->fs, a); |
1d0cd73f KZ |
333 | if (rc) |
334 | goto err; | |
6c40a53d | 335 | |
1d0cd73f | 336 | if (!(mountflags & MS_REMOUNT)) { |
c4c66355 | 337 | rc = set_fs_root(upd, fs, mountflags); |
1d0cd73f KZ |
338 | if (rc) |
339 | goto err; | |
340 | } | |
6c40a53d | 341 | |
f84fa6f7 | 342 | free(u); |
83a78332 | 343 | DBG(UPDATE, ul_debug("utab entry OK")); |
6c40a53d | 344 | return 0; |
1d0cd73f | 345 | err: |
f84fa6f7 | 346 | free(u); |
26d0c0ae | 347 | mnt_unref_fs(upd->fs); |
c4c66355 | 348 | upd->fs = NULL; |
1d0cd73f | 349 | return rc; |
6c40a53d KZ |
350 | } |
351 | ||
c4c66355 KZ |
352 | /* |
353 | * Sets fs-root and fs-type to @upd->fs according to the @fs template and | |
d58b3157 | 354 | * @mountfalgs. For MS_BIND mountflag it reads information about the source |
c4c66355 KZ |
355 | * filesystem from /proc/self/mountinfo. |
356 | */ | |
357 | static int set_fs_root(struct libmnt_update *upd, struct libmnt_fs *fs, | |
358 | unsigned long mountflags) | |
6c40a53d | 359 | { |
c4c66355 KZ |
360 | struct libmnt_fs *src_fs; |
361 | char *fsroot = NULL; | |
e9cd2e2b | 362 | const char *src, *fstype; |
c4c66355 | 363 | int rc = 0; |
1d0cd73f | 364 | |
83a78332 | 365 | DBG(UPDATE, ul_debug("setting FS root")); |
6c40a53d | 366 | |
c4c66355 KZ |
367 | assert(upd); |
368 | assert(upd->fs); | |
369 | assert(fs); | |
6c40a53d | 370 | |
e9cd2e2b KZ |
371 | fstype = mnt_fs_get_fstype(fs); |
372 | ||
1d0cd73f | 373 | if (mountflags & MS_BIND) { |
c4c66355 KZ |
374 | if (!upd->mountinfo) |
375 | upd->mountinfo = mnt_new_table_from_file(_PATH_PROC_MOUNTINFO); | |
6c40a53d | 376 | src = mnt_fs_get_srcpath(fs); |
dd369652 | 377 | if (src) { |
c4c66355 KZ |
378 | rc = mnt_fs_set_bindsrc(upd->fs, src); |
379 | if (rc) | |
380 | goto err; | |
f84fa6f7 | 381 | } |
e9cd2e2b KZ |
382 | |
383 | } else if (fstype && (strcmp(fstype, "btrfs") == 0 || strcmp(fstype, "auto") == 0)) { | |
384 | if (!upd->mountinfo) | |
385 | upd->mountinfo = mnt_new_table_from_file(_PATH_PROC_MOUNTINFO); | |
c4c66355 | 386 | } |
6c40a53d | 387 | |
c4c66355 KZ |
388 | src_fs = mnt_table_get_fs_root(upd->mountinfo, fs, |
389 | mountflags, &fsroot); | |
390 | if (src_fs) { | |
6c40a53d | 391 | src = mnt_fs_get_srcpath(src_fs); |
c4c66355 | 392 | rc = mnt_fs_set_source(upd->fs, src); |
dd369652 KZ |
393 | if (rc) |
394 | goto err; | |
6c40a53d | 395 | |
c4c66355 | 396 | mnt_fs_set_fstype(upd->fs, mnt_fs_get_fstype(src_fs)); |
6c40a53d KZ |
397 | } |
398 | ||
c4c66355 | 399 | upd->fs->root = fsroot; |
6c40a53d KZ |
400 | return 0; |
401 | err: | |
c4c66355 | 402 | free(fsroot); |
1d0cd73f | 403 | return rc; |
d300992d KZ |
404 | } |
405 | ||
68af0bcc KZ |
406 | /* mtab and fstab update -- returns zero on success |
407 | */ | |
68164f6c | 408 | static int fprintf_mtab_fs(FILE *f, struct libmnt_fs *fs) |
6c40a53d | 409 | { |
cb90e24e | 410 | const char *o, *src, *fstype, *comm; |
1d0cd73f KZ |
411 | char *m1, *m2, *m3, *m4; |
412 | int rc; | |
6c40a53d | 413 | |
1d0cd73f KZ |
414 | assert(fs); |
415 | assert(f); | |
1b56aae8 | 416 | |
cb90e24e | 417 | comm = mnt_fs_get_comment(fs); |
b5962110 KZ |
418 | src = mnt_fs_get_source(fs); |
419 | fstype = mnt_fs_get_fstype(fs); | |
420 | o = mnt_fs_get_options(fs); | |
76a06ca4 | 421 | |
b5962110 | 422 | m1 = src ? mangle(src) : "none"; |
1d0cd73f | 423 | m2 = mangle(mnt_fs_get_target(fs)); |
b5962110 KZ |
424 | m3 = fstype ? mangle(fstype) : "none"; |
425 | m4 = o ? mangle(o) : "rw"; | |
1b56aae8 | 426 | |
68af0bcc | 427 | if (m1 && m2 && m3 && m4) { |
cb90e24e OO |
428 | if (comm) |
429 | fputs(comm, f); | |
68af0bcc | 430 | rc = fprintf(f, "%s %s %s %s %d %d\n", |
1d0cd73f KZ |
431 | m1, m2, m3, m4, |
432 | mnt_fs_get_freq(fs), | |
433 | mnt_fs_get_passno(fs)); | |
68af0bcc KZ |
434 | if (rc > 0) |
435 | rc = 0; | |
436 | } else | |
1d0cd73f | 437 | rc = -ENOMEM; |
6c40a53d | 438 | |
b5962110 KZ |
439 | if (src) |
440 | free(m1); | |
1d0cd73f | 441 | free(m2); |
b5962110 KZ |
442 | if (fstype) |
443 | free(m3); | |
444 | if (o) | |
445 | free(m4); | |
3a5b1b1d | 446 | |
1d0cd73f KZ |
447 | return rc; |
448 | } | |
6c40a53d | 449 | |
68164f6c | 450 | static int fprintf_utab_fs(FILE *f, struct libmnt_fs *fs) |
1d0cd73f | 451 | { |
dd369652 | 452 | char *p; |
68af0bcc | 453 | int rc = 0; |
4e92d2b0 | 454 | |
1d0cd73f KZ |
455 | if (!fs || !f) |
456 | return -EINVAL; | |
dd369652 KZ |
457 | |
458 | p = mangle(mnt_fs_get_source(fs)); | |
459 | if (p) { | |
68af0bcc | 460 | rc = fprintf(f, "SRC=%s ", p); |
dd369652 KZ |
461 | free(p); |
462 | } | |
68af0bcc KZ |
463 | if (rc >= 0) { |
464 | p = mangle(mnt_fs_get_target(fs)); | |
465 | if (p) { | |
466 | rc = fprintf(f, "TARGET=%s ", p); | |
467 | free(p); | |
468 | } | |
dd369652 | 469 | } |
68af0bcc KZ |
470 | if (rc >= 0) { |
471 | p = mangle(mnt_fs_get_root(fs)); | |
472 | if (p) { | |
473 | rc = fprintf(f, "ROOT=%s ", p); | |
474 | free(p); | |
475 | } | |
dd369652 | 476 | } |
68af0bcc KZ |
477 | if (rc >= 0) { |
478 | p = mangle(mnt_fs_get_bindsrc(fs)); | |
479 | if (p) { | |
480 | rc = fprintf(f, "BINDSRC=%s ", p); | |
481 | free(p); | |
482 | } | |
dd369652 | 483 | } |
68af0bcc KZ |
484 | if (rc >= 0) { |
485 | p = mangle(mnt_fs_get_attributes(fs)); | |
486 | if (p) { | |
487 | rc = fprintf(f, "ATTRS=%s ", p); | |
488 | free(p); | |
489 | } | |
76a06ca4 | 490 | } |
68af0bcc KZ |
491 | if (rc >= 0) { |
492 | p = mangle(mnt_fs_get_user_options(fs)); | |
493 | if (p) { | |
494 | rc = fprintf(f, "OPTS=%s", p); | |
495 | free(p); | |
496 | } | |
dd369652 | 497 | } |
68af0bcc KZ |
498 | if (rc >= 0) |
499 | rc = fprintf(f, "\n"); | |
dd369652 | 500 | |
68af0bcc KZ |
501 | if (rc > 0) |
502 | rc = 0; /* success */ | |
503 | return rc; | |
6c40a53d KZ |
504 | } |
505 | ||
68164f6c | 506 | static int update_table(struct libmnt_update *upd, struct libmnt_table *tb) |
6c40a53d KZ |
507 | { |
508 | FILE *f; | |
1d0cd73f KZ |
509 | int rc, fd; |
510 | char *uq = NULL; | |
6c40a53d | 511 | |
77417bc0 | 512 | if (!tb || !upd->filename) |
1d0cd73f | 513 | return -EINVAL; |
6c40a53d | 514 | |
83a78332 | 515 | DBG(UPDATE, ul_debugobj(upd, "%s: updating", upd->filename)); |
3f31a959 | 516 | |
4b6cf485 | 517 | fd = mnt_open_uniq_filename(upd->filename, &uq); |
1d0cd73f KZ |
518 | if (fd < 0) |
519 | return fd; /* error */ | |
520 | ||
1eb8539d | 521 | f = fdopen(fd, "w" UL_CLOEXECSTR); |
6c40a53d | 522 | if (f) { |
1d0cd73f | 523 | struct stat st; |
68164f6c KZ |
524 | struct libmnt_iter itr; |
525 | struct libmnt_fs *fs; | |
1d0cd73f KZ |
526 | |
527 | mnt_reset_iter(&itr, MNT_ITER_FORWARD); | |
cb90e24e OO |
528 | |
529 | if (tb->comms && mnt_table_get_intro_comment(tb)) | |
530 | fputs(mnt_table_get_intro_comment(tb), f); | |
531 | ||
68164f6c | 532 | while(mnt_table_next_fs(tb, &itr, &fs) == 0) { |
1d0cd73f | 533 | if (upd->userspace_only) |
68af0bcc | 534 | rc = fprintf_utab_fs(f, fs); |
1d0cd73f | 535 | else |
68af0bcc KZ |
536 | rc = fprintf_mtab_fs(f, fs); |
537 | if (rc) { | |
83a78332 | 538 | DBG(UPDATE, ul_debugobj(upd, |
68af0bcc KZ |
539 | "%s: write entry failed: %m", uq)); |
540 | goto leave; | |
541 | } | |
542 | } | |
3035ba93 OO |
543 | if (tb->comms && mnt_table_get_trailing_comment(tb)) |
544 | fputs(mnt_table_get_trailing_comment(tb), f); | |
68af0bcc KZ |
545 | |
546 | if (fflush(f) != 0) { | |
547 | rc = -errno; | |
83a78332 | 548 | DBG(UPDATE, ul_debugobj(upd, "%s: fflush failed: %m", uq)); |
68af0bcc | 549 | goto leave; |
1d0cd73f | 550 | } |
68af0bcc | 551 | |
1d0cd73f KZ |
552 | rc = fchmod(fd, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH) ? -errno : 0; |
553 | ||
77417bc0 | 554 | if (!rc && stat(upd->filename, &st) == 0) |
1d0cd73f KZ |
555 | /* Copy uid/gid from the present file before renaming. */ |
556 | rc = fchown(fd, st.st_uid, st.st_gid) ? -errno : 0; | |
557 | ||
6c40a53d | 558 | fclose(f); |
80140144 | 559 | f = NULL; |
a9ddf316 KZ |
560 | |
561 | if (!rc) | |
562 | rc = rename(uq, upd->filename) ? -errno : 0; | |
1d0cd73f KZ |
563 | } else { |
564 | rc = -errno; | |
565 | close(fd); | |
6c40a53d | 566 | } |
1d0cd73f | 567 | |
68af0bcc | 568 | leave: |
80140144 KZ |
569 | if (f) |
570 | fclose(f); | |
571 | ||
1d0cd73f KZ |
572 | unlink(uq); /* be paranoid */ |
573 | free(uq); | |
6c40a53d KZ |
574 | return rc; |
575 | } | |
576 | ||
d22f2822 OO |
577 | /** |
578 | * mnt_table_write_file | |
579 | * @tb: parsed file (e.g. fstab) | |
580 | * @file: target | |
581 | * | |
582 | * This function writes @tb to @file. | |
583 | * | |
584 | * Returns: 0 on success, negative number on error. | |
585 | */ | |
586 | int mnt_table_write_file(struct libmnt_table *tb, FILE *file) | |
587 | { | |
588 | int rc = 0; | |
589 | struct libmnt_iter itr; | |
590 | struct libmnt_fs *fs; | |
591 | ||
592 | if (tb->comms && mnt_table_get_intro_comment(tb)) | |
593 | fputs(mnt_table_get_intro_comment(tb), file); | |
594 | ||
595 | mnt_reset_iter(&itr, MNT_ITER_FORWARD); | |
596 | while(mnt_table_next_fs(tb, &itr, &fs) == 0) { | |
597 | rc = fprintf_mtab_fs(file, fs); | |
598 | if (rc) | |
599 | return rc; | |
600 | } | |
3035ba93 OO |
601 | if (tb->comms && mnt_table_get_trailing_comment(tb)) |
602 | fputs(mnt_table_get_trailing_comment(tb), file); | |
d22f2822 OO |
603 | |
604 | if (fflush(file) != 0) | |
605 | rc = -errno; | |
606 | ||
83a78332 | 607 | DBG(TAB, ul_debugobj(tb, "write file done [rc=%d]", rc)); |
d22f2822 OO |
608 | return rc; |
609 | } | |
610 | ||
611 | /** | |
612 | * mnt_table_replace_file | |
613 | * @tb: parsed file (e.g. fstab) | |
614 | * @filename: target | |
615 | * | |
d58b3157 | 616 | * This function replaces @file by the new content from @tb. |
d22f2822 OO |
617 | * |
618 | * Returns: 0 on success, negative number on error. | |
619 | */ | |
620 | int mnt_table_replace_file(struct libmnt_table *tb, const char *filename) | |
621 | { | |
622 | int fd, rc = 0; | |
623 | FILE *f; | |
624 | char *uq = NULL; | |
625 | ||
83a78332 | 626 | DBG(TAB, ul_debugobj(tb, "%s: replacing", filename)); |
d22f2822 OO |
627 | |
628 | fd = mnt_open_uniq_filename(filename, &uq); | |
629 | if (fd < 0) | |
630 | return fd; /* error */ | |
631 | ||
632 | f = fdopen(fd, "w" UL_CLOEXECSTR); | |
633 | if (f) { | |
634 | struct stat st; | |
635 | ||
636 | mnt_table_write_file(tb, f); | |
637 | ||
a84ec176 KZ |
638 | if (fflush(f) != 0) { |
639 | rc = -errno; | |
83a78332 | 640 | DBG(UPDATE, ul_debug("%s: fflush failed: %m", uq)); |
a84ec176 KZ |
641 | goto leave; |
642 | } | |
643 | ||
d22f2822 OO |
644 | rc = fchmod(fd, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH) ? -errno : 0; |
645 | ||
646 | if (!rc && stat(filename, &st) == 0) | |
647 | /* Copy uid/gid from the present file before renaming. */ | |
648 | rc = fchown(fd, st.st_uid, st.st_gid) ? -errno : 0; | |
649 | ||
650 | fclose(f); | |
a84ec176 KZ |
651 | f = NULL; |
652 | ||
d22f2822 | 653 | if (!rc) |
a84ec176 | 654 | rc = rename(uq, filename) ? -errno : 0; |
d22f2822 OO |
655 | } else { |
656 | rc = -errno; | |
657 | close(fd); | |
658 | } | |
659 | ||
a84ec176 KZ |
660 | leave: |
661 | if (f) | |
662 | fclose(f); | |
d22f2822 OO |
663 | unlink(uq); |
664 | free(uq); | |
665 | ||
83a78332 | 666 | DBG(TAB, ul_debugobj(tb, "replace done [rc=%d]", rc)); |
d22f2822 OO |
667 | return rc; |
668 | } | |
a84ec176 | 669 | |
c3085df6 KZ |
670 | static int add_file_entry(struct libmnt_table *tb, struct libmnt_update *upd) |
671 | { | |
4569bbea KZ |
672 | struct libmnt_fs *fs; |
673 | ||
674 | assert(upd); | |
c3085df6 | 675 | |
4569bbea | 676 | fs = mnt_copy_fs(NULL, upd->fs); |
c3085df6 KZ |
677 | if (!fs) |
678 | return -ENOMEM; | |
679 | ||
680 | mnt_table_add_fs(tb, fs); | |
26d0c0ae KZ |
681 | mnt_unref_fs(fs); |
682 | ||
c3085df6 KZ |
683 | return update_table(upd, tb); |
684 | } | |
685 | ||
68164f6c | 686 | static int update_add_entry(struct libmnt_update *upd, struct libmnt_lock *lc) |
6c40a53d | 687 | { |
68af0bcc | 688 | struct libmnt_table *tb; |
8f60ea34 | 689 | int rc = 0; |
6c40a53d | 690 | |
30493710 | 691 | assert(upd); |
1d0cd73f | 692 | assert(upd->fs); |
6c40a53d | 693 | |
83a78332 | 694 | DBG(UPDATE, ul_debugobj(upd, "%s: add entry", upd->filename)); |
6c40a53d | 695 | |
86cd5870 | 696 | if (lc) |
8f60ea34 KZ |
697 | rc = mnt_lock_file(lc); |
698 | if (rc) | |
699 | return rc; | |
6c40a53d | 700 | |
68af0bcc KZ |
701 | tb = __mnt_new_table_from_file(upd->filename, |
702 | upd->userspace_only ? MNT_FMT_UTAB : MNT_FMT_MTAB); | |
c3085df6 KZ |
703 | if (tb) |
704 | rc = add_file_entry(tb, upd); | |
86cd5870 | 705 | if (lc) |
1d0cd73f | 706 | mnt_unlock_file(lc); |
68af0bcc | 707 | |
c9f1585e | 708 | mnt_unref_table(tb); |
1d0cd73f KZ |
709 | return rc; |
710 | } | |
6c40a53d | 711 | |
68164f6c | 712 | static int update_remove_entry(struct libmnt_update *upd, struct libmnt_lock *lc) |
1d0cd73f | 713 | { |
68164f6c | 714 | struct libmnt_table *tb; |
8f60ea34 | 715 | int rc = 0; |
6c40a53d | 716 | |
1d0cd73f KZ |
717 | assert(upd); |
718 | assert(upd->target); | |
719 | ||
83a78332 | 720 | DBG(UPDATE, ul_debugobj(upd, "%s: remove entry", upd->filename)); |
1d0cd73f | 721 | |
86cd5870 | 722 | if (lc) |
8f60ea34 KZ |
723 | rc = mnt_lock_file(lc); |
724 | if (rc) | |
725 | return rc; | |
1d0cd73f | 726 | |
68164f6c | 727 | tb = __mnt_new_table_from_file(upd->filename, |
dd369652 | 728 | upd->userspace_only ? MNT_FMT_UTAB : MNT_FMT_MTAB); |
1d0cd73f | 729 | if (tb) { |
68164f6c | 730 | struct libmnt_fs *rem = mnt_table_find_target(tb, upd->target, MNT_ITER_BACKWARD); |
1d0cd73f | 731 | if (rem) { |
68164f6c KZ |
732 | mnt_table_remove_fs(tb, rem); |
733 | rc = update_table(upd, tb); | |
1d0cd73f | 734 | } |
1d0cd73f | 735 | } |
86cd5870 | 736 | if (lc) |
1d0cd73f | 737 | mnt_unlock_file(lc); |
6f5788c5 | 738 | |
c9f1585e | 739 | mnt_unref_table(tb); |
6c40a53d KZ |
740 | return rc; |
741 | } | |
742 | ||
68164f6c | 743 | static int update_modify_target(struct libmnt_update *upd, struct libmnt_lock *lc) |
6c40a53d | 744 | { |
68164f6c | 745 | struct libmnt_table *tb = NULL; |
8f60ea34 | 746 | int rc = 0; |
1d0cd73f | 747 | |
4569bbea | 748 | assert(upd); |
83a78332 | 749 | DBG(UPDATE, ul_debugobj(upd, "%s: modify target", upd->filename)); |
1d0cd73f | 750 | |
86cd5870 | 751 | if (lc) |
8f60ea34 KZ |
752 | rc = mnt_lock_file(lc); |
753 | if (rc) | |
754 | return rc; | |
1d0cd73f | 755 | |
68164f6c | 756 | tb = __mnt_new_table_from_file(upd->filename, |
dd369652 | 757 | upd->userspace_only ? MNT_FMT_UTAB : MNT_FMT_MTAB); |
1d0cd73f | 758 | if (tb) { |
68164f6c | 759 | struct libmnt_fs *cur = mnt_table_find_target(tb, |
2915bdc0 | 760 | mnt_fs_get_srcpath(upd->fs), MNT_ITER_BACKWARD); |
1d0cd73f KZ |
761 | if (cur) { |
762 | rc = mnt_fs_set_target(cur, mnt_fs_get_target(upd->fs)); | |
763 | if (!rc) | |
68164f6c | 764 | rc = update_table(upd, tb); |
1d0cd73f | 765 | } |
1d0cd73f | 766 | } |
8f60ea34 | 767 | |
86cd5870 | 768 | if (lc) |
1d0cd73f | 769 | mnt_unlock_file(lc); |
6f5788c5 | 770 | |
c9f1585e | 771 | mnt_unref_table(tb); |
1d0cd73f KZ |
772 | return rc; |
773 | } | |
6c40a53d | 774 | |
68164f6c | 775 | static int update_modify_options(struct libmnt_update *upd, struct libmnt_lock *lc) |
1d0cd73f | 776 | { |
68164f6c | 777 | struct libmnt_table *tb = NULL; |
8f60ea34 | 778 | int rc = 0; |
68164f6c | 779 | struct libmnt_fs *fs; |
6c40a53d | 780 | |
1d0cd73f KZ |
781 | assert(upd); |
782 | assert(upd->fs); | |
6c40a53d | 783 | |
83a78332 | 784 | DBG(UPDATE, ul_debugobj(upd, "%s: modify options", upd->filename)); |
1d0cd73f | 785 | |
76a06ca4 KZ |
786 | fs = upd->fs; |
787 | ||
86cd5870 | 788 | if (lc) |
8f60ea34 KZ |
789 | rc = mnt_lock_file(lc); |
790 | if (rc) | |
791 | return rc; | |
1d0cd73f | 792 | |
68164f6c | 793 | tb = __mnt_new_table_from_file(upd->filename, |
dd369652 | 794 | upd->userspace_only ? MNT_FMT_UTAB : MNT_FMT_MTAB); |
1d0cd73f | 795 | if (tb) { |
68164f6c | 796 | struct libmnt_fs *cur = mnt_table_find_target(tb, |
76a06ca4 | 797 | mnt_fs_get_target(fs), |
1d0cd73f KZ |
798 | MNT_ITER_BACKWARD); |
799 | if (cur) { | |
76a06ca4 KZ |
800 | if (upd->userspace_only) |
801 | rc = mnt_fs_set_attributes(cur, mnt_fs_get_attributes(fs)); | |
76a06ca4 | 802 | if (!rc) |
f2b3a3a3 | 803 | rc = mnt_fs_set_options(cur, mnt_fs_get_options(fs)); |
1d0cd73f | 804 | if (!rc) |
68164f6c | 805 | rc = update_table(upd, tb); |
c3085df6 KZ |
806 | } else |
807 | rc = add_file_entry(tb, upd); /* not found, add new */ | |
6c40a53d | 808 | } |
76a06ca4 | 809 | |
86cd5870 | 810 | if (lc) |
1d0cd73f | 811 | mnt_unlock_file(lc); |
6f5788c5 | 812 | |
c9f1585e | 813 | mnt_unref_table(tb); |
6c40a53d KZ |
814 | return rc; |
815 | } | |
816 | ||
817 | /** | |
68164f6c | 818 | * mnt_update_table: |
0f32f1e2 | 819 | * @upd: update |
5976114f | 820 | * @lc: lock or NULL |
6c40a53d | 821 | * |
a362ae60 | 822 | * High-level API to update /etc/mtab (or private /run/mount/utab file). |
6c40a53d | 823 | * |
5976114f | 824 | * The @lc lock is optional and will be created if necessary. Note that |
d58b3157 | 825 | * an automatically created lock blocks all signals. |
5976114f KZ |
826 | * |
827 | * See also mnt_lock_block_signals() and mnt_context_get_lock(). | |
828 | * | |
1d0cd73f | 829 | * Returns: 0 on success, negative number on error. |
6c40a53d | 830 | */ |
68164f6c | 831 | int mnt_update_table(struct libmnt_update *upd, struct libmnt_lock *lc) |
6c40a53d | 832 | { |
c570f567 | 833 | struct libmnt_lock *lc0 = lc; |
1d0cd73f KZ |
834 | int rc = -EINVAL; |
835 | ||
8726371f | 836 | if (!upd || !upd->filename) |
1d0cd73f KZ |
837 | return -EINVAL; |
838 | if (!upd->ready) | |
d300992d | 839 | return 0; |
6c40a53d | 840 | |
83a78332 | 841 | DBG(UPDATE, ul_debugobj(upd, "%s: update tab", upd->filename)); |
f84fa6f7 KZ |
842 | if (upd->fs) { |
843 | DBG(UPDATE, mnt_fs_print_debug(upd->fs, stderr)); | |
844 | } | |
86cd5870 | 845 | if (!lc) { |
c570f567 | 846 | lc = mnt_new_lock(upd->filename, 0); |
5976114f KZ |
847 | if (lc) |
848 | mnt_lock_block_signals(lc, TRUE); | |
849 | } | |
86cd5870 KZ |
850 | if (lc && upd->userspace_only) |
851 | mnt_lock_use_simplelock(lc, TRUE); /* use flock */ | |
c570f567 | 852 | |
1d0cd73f | 853 | if (!upd->fs && upd->target) |
77417bc0 | 854 | rc = update_remove_entry(upd, lc); /* umount */ |
1d0cd73f | 855 | else if (upd->mountflags & MS_MOVE) |
77417bc0 | 856 | rc = update_modify_target(upd, lc); /* move */ |
1d0cd73f | 857 | else if (upd->mountflags & MS_REMOUNT) |
77417bc0 | 858 | rc = update_modify_options(upd, lc); /* remount */ |
1d0cd73f | 859 | else if (upd->fs) |
77417bc0 | 860 | rc = update_add_entry(upd, lc); /* mount */ |
1d0cd73f KZ |
861 | |
862 | upd->ready = FALSE; | |
83a78332 | 863 | DBG(UPDATE, ul_debugobj(upd, "%s: update tab: done [rc=%d]", |
77417bc0 | 864 | upd->filename, rc)); |
c570f567 KZ |
865 | if (lc != lc0) |
866 | mnt_free_lock(lc); | |
1d0cd73f | 867 | return rc; |
6c40a53d KZ |
868 | } |
869 | ||
7e0c0619 KZ |
870 | int mnt_update_already_done(struct libmnt_update *upd, struct libmnt_lock *lc) |
871 | { | |
872 | struct libmnt_table *tb = NULL; | |
873 | struct libmnt_lock *lc0 = lc; | |
874 | int rc = 0; | |
875 | ||
876 | if (!upd || !upd->filename || (!upd->fs && !upd->target)) | |
877 | return -EINVAL; | |
878 | ||
83a78332 | 879 | DBG(UPDATE, ul_debugobj(upd, "%s: checking for previous update", upd->filename)); |
7e0c0619 KZ |
880 | |
881 | if (!lc) { | |
882 | lc = mnt_new_lock(upd->filename, 0); | |
883 | if (lc) | |
884 | mnt_lock_block_signals(lc, TRUE); | |
885 | } | |
886 | if (lc && upd->userspace_only) | |
887 | mnt_lock_use_simplelock(lc, TRUE); /* use flock */ | |
888 | if (lc) | |
889 | rc = mnt_lock_file(lc); | |
890 | if (rc) | |
891 | goto done; | |
892 | ||
893 | tb = __mnt_new_table_from_file(upd->filename, | |
894 | upd->userspace_only ? MNT_FMT_UTAB : MNT_FMT_MTAB); | |
895 | if (lc) | |
896 | mnt_unlock_file(lc); | |
897 | if (!tb) | |
898 | goto done; | |
899 | ||
900 | if (upd->fs) { | |
901 | /* mount */ | |
902 | const char *tgt = mnt_fs_get_target(upd->fs); | |
903 | const char *src = mnt_fs_get_bindsrc(upd->fs) ? | |
904 | mnt_fs_get_bindsrc(upd->fs) : | |
905 | mnt_fs_get_source(upd->fs); | |
906 | ||
907 | if (mnt_table_find_pair(tb, src, tgt, MNT_ITER_BACKWARD)) { | |
83a78332 | 908 | DBG(UPDATE, ul_debugobj(upd, "%s: found %s %s", |
7e0c0619 KZ |
909 | upd->filename, src, tgt)); |
910 | rc = 1; | |
911 | } | |
912 | } else if (upd->target) { | |
913 | /* umount */ | |
914 | if (!mnt_table_find_target(tb, upd->target, MNT_ITER_BACKWARD)) { | |
83a78332 | 915 | DBG(UPDATE, ul_debugobj(upd, "%s: not-found (umounted) %s", |
7e0c0619 KZ |
916 | upd->filename, upd->target)); |
917 | rc = 1; | |
918 | } | |
919 | } | |
920 | ||
921 | mnt_unref_table(tb); | |
922 | done: | |
923 | if (lc && lc != lc0) | |
924 | mnt_free_lock(lc); | |
83a78332 | 925 | DBG(UPDATE, ul_debugobj(upd, "%s: previous update check done [rc=%d]", |
7e0c0619 KZ |
926 | upd->filename, rc)); |
927 | return rc; | |
928 | } | |
929 | ||
930 | ||
6c40a53d KZ |
931 | #ifdef TEST_PROGRAM |
932 | ||
68164f6c | 933 | static int update(const char *target, struct libmnt_fs *fs, unsigned long mountflags) |
6c40a53d | 934 | { |
36bda5cb | 935 | int rc; |
68164f6c | 936 | struct libmnt_update *upd; |
6c40a53d | 937 | |
83a78332 | 938 | DBG(UPDATE, ul_debug("update test")); |
3a5b1b1d | 939 | |
77417bc0 KZ |
940 | upd = mnt_new_update(); |
941 | if (!upd) | |
942 | return -ENOMEM; | |
7714c689 | 943 | |
1d0cd73f | 944 | rc = mnt_update_set_fs(upd, mountflags, target, fs); |
1d0cd73f | 945 | if (rc == 1) { |
7c118af7 | 946 | /* update is unnecessary */ |
1d0cd73f KZ |
947 | rc = 0; |
948 | goto done; | |
949 | } | |
7c118af7 KZ |
950 | if (rc) { |
951 | fprintf(stderr, "failed to set FS\n"); | |
952 | goto done; | |
953 | } | |
30493710 | 954 | |
d58b3157 | 955 | /* [... mount(2) call should be here...] */ |
30493710 | 956 | |
5976114f | 957 | rc = mnt_update_table(upd, NULL); |
1d0cd73f | 958 | done: |
8dece036 | 959 | mnt_free_update(upd); |
30493710 KZ |
960 | return rc; |
961 | } | |
962 | ||
68164f6c | 963 | static int test_add(struct libmnt_test *ts, int argc, char *argv[]) |
30493710 | 964 | { |
68164f6c | 965 | struct libmnt_fs *fs = mnt_new_fs(); |
1d0cd73f | 966 | int rc; |
30493710 | 967 | |
1d0cd73f | 968 | if (argc < 5 || !fs) |
30493710 KZ |
969 | return -1; |
970 | mnt_fs_set_source(fs, argv[1]); | |
971 | mnt_fs_set_target(fs, argv[2]); | |
972 | mnt_fs_set_fstype(fs, argv[3]); | |
76a06ca4 | 973 | mnt_fs_set_options(fs, argv[4]); |
30493710 | 974 | |
1d0cd73f | 975 | rc = update(NULL, fs, 0); |
26d0c0ae | 976 | mnt_unref_fs(fs); |
6c40a53d KZ |
977 | return rc; |
978 | } | |
979 | ||
68164f6c | 980 | static int test_remove(struct libmnt_test *ts, int argc, char *argv[]) |
6c40a53d | 981 | { |
1d0cd73f | 982 | if (argc < 2) |
6c40a53d | 983 | return -1; |
1d0cd73f | 984 | return update(argv[1], NULL, 0); |
6c40a53d KZ |
985 | } |
986 | ||
68164f6c | 987 | static int test_move(struct libmnt_test *ts, int argc, char *argv[]) |
6c40a53d | 988 | { |
68164f6c | 989 | struct libmnt_fs *fs = mnt_new_fs(); |
1d0cd73f | 990 | int rc; |
6c40a53d | 991 | |
1d0cd73f | 992 | if (argc < 3) |
6c40a53d | 993 | return -1; |
25bca458 | 994 | mnt_fs_set_source(fs, argv[1]); |
7714c689 | 995 | mnt_fs_set_target(fs, argv[2]); |
25bca458 KZ |
996 | |
997 | rc = update(NULL, fs, MS_MOVE); | |
7714c689 | 998 | |
26d0c0ae | 999 | mnt_unref_fs(fs); |
6c40a53d KZ |
1000 | return rc; |
1001 | } | |
1002 | ||
68164f6c | 1003 | static int test_remount(struct libmnt_test *ts, int argc, char *argv[]) |
6c40a53d | 1004 | { |
68164f6c | 1005 | struct libmnt_fs *fs = mnt_new_fs(); |
1d0cd73f | 1006 | int rc; |
6c40a53d | 1007 | |
1d0cd73f | 1008 | if (argc < 3) |
6c40a53d | 1009 | return -1; |
7714c689 | 1010 | mnt_fs_set_target(fs, argv[1]); |
76a06ca4 | 1011 | mnt_fs_set_options(fs, argv[2]); |
7714c689 | 1012 | |
1d0cd73f | 1013 | rc = update(NULL, fs, MS_REMOUNT); |
26d0c0ae | 1014 | mnt_unref_fs(fs); |
6c40a53d KZ |
1015 | return rc; |
1016 | } | |
1017 | ||
d22f2822 OO |
1018 | static int test_replace(struct libmnt_test *ts, int argc, char *argv[]) |
1019 | { | |
1020 | struct libmnt_fs *fs = mnt_new_fs(); | |
1021 | struct libmnt_table *tb = mnt_new_table(); | |
1022 | int rc; | |
1023 | ||
1024 | if (argc < 3) | |
1025 | return -1; | |
1026 | ||
1027 | mnt_table_enable_comments(tb, TRUE); | |
1028 | mnt_table_parse_fstab(tb, NULL); | |
1029 | ||
1030 | mnt_fs_set_source(fs, argv[1]); | |
1031 | mnt_fs_set_target(fs, argv[2]); | |
1032 | mnt_fs_append_comment(fs, "# this is new filesystem\n"); | |
26d0c0ae | 1033 | |
d22f2822 | 1034 | mnt_table_add_fs(tb, fs); |
26d0c0ae | 1035 | mnt_unref_fs(fs); |
d22f2822 OO |
1036 | |
1037 | rc = mnt_table_replace_file(tb, mnt_get_fstab_path()); | |
c9f1585e | 1038 | mnt_unref_table(tb); |
d22f2822 OO |
1039 | return rc; |
1040 | } | |
1041 | ||
6c40a53d KZ |
1042 | int main(int argc, char *argv[]) |
1043 | { | |
68164f6c | 1044 | struct libmnt_test tss[] = { |
d58b3157 | 1045 | { "--add", test_add, "<src> <target> <type> <options> add a line to mtab" }, |
6c40a53d KZ |
1046 | { "--remove", test_remove, "<target> MS_REMOUNT mtab change" }, |
1047 | { "--move", test_move, "<old_target> <target> MS_MOVE mtab change" }, | |
1048 | { "--remount",test_remount, "<target> <options> MS_REMOUNT mtab change" }, | |
d22f2822 | 1049 | { "--replace",test_replace, "<src> <target> Add a line to LIBMOUNT_FSTAB and replace the original file" }, |
6c40a53d KZ |
1050 | { NULL } |
1051 | }; | |
1052 | ||
1053 | return mnt_run_test(tss, argc, argv); | |
1054 | } | |
1055 | ||
1056 | #endif /* TEST_PROGRAM */ |