]>
Commit | Line | Data |
---|---|---|
d115ee9b KZ |
1 | /* |
2 | * Copyright (C) 2008-2009 Karel Zak <kzak@redhat.com> | |
3 | * | |
4 | * This file may be redistributed under the terms of the | |
5 | * GNU Lesser General Public License. | |
d115ee9b KZ |
6 | */ |
7 | ||
192c6aad KZ |
8 | /** |
9 | * SECTION: fs | |
10 | * @title: Filesystem | |
63de90d4 | 11 | * @short_description: represents one entry from fstab, mtab, or mountinfo file |
192c6aad KZ |
12 | * |
13 | */ | |
d115ee9b | 14 | #include <ctype.h> |
8e368761 | 15 | #include <blkid.h> |
9ecdf48f | 16 | #include <stddef.h> |
d115ee9b | 17 | |
d115ee9b | 18 | #include "mountP.h" |
b106d052 | 19 | #include "strutils.h" |
d115ee9b KZ |
20 | |
21 | /** | |
22 | * mnt_new_fs: | |
23 | * | |
68164f6c | 24 | * Returns: newly allocated struct libmnt_fs. |
d115ee9b | 25 | */ |
68164f6c | 26 | struct libmnt_fs *mnt_new_fs(void) |
d115ee9b | 27 | { |
68164f6c | 28 | struct libmnt_fs *fs = calloc(1, sizeof(*fs)); |
d115ee9b KZ |
29 | if (!fs) |
30 | return NULL; | |
31 | ||
309139c7 | 32 | /*DBG(FS, mnt_debug_h(fs, "alloc"));*/ |
d115ee9b KZ |
33 | INIT_LIST_HEAD(&fs->ents); |
34 | return fs; | |
35 | } | |
36 | ||
37 | /** | |
38 | * mnt_free_fs: | |
39 | * @fs: fs pointer | |
40 | * | |
41 | * Deallocates the fs. | |
42 | */ | |
68164f6c | 43 | void mnt_free_fs(struct libmnt_fs *fs) |
d115ee9b KZ |
44 | { |
45 | if (!fs) | |
46 | return; | |
47 | list_del(&fs->ents); | |
48 | ||
309139c7 KZ |
49 | /*DBG(FS, mnt_debug_h(fs, "free"));*/ |
50 | ||
d115ee9b | 51 | free(fs->source); |
dd369652 | 52 | free(fs->bindsrc); |
d115ee9b KZ |
53 | free(fs->tagname); |
54 | free(fs->tagval); | |
0b3953a3 | 55 | free(fs->root); |
ce4dd666 | 56 | free(fs->swaptype); |
d115ee9b KZ |
57 | free(fs->target); |
58 | free(fs->fstype); | |
f2b3a3a3 | 59 | free(fs->optstr); |
d115ee9b KZ |
60 | free(fs->vfs_optstr); |
61 | free(fs->fs_optstr); | |
76a06ca4 KZ |
62 | free(fs->user_optstr); |
63 | free(fs->attrs); | |
45b6445f | 64 | free(fs->opt_fields); |
d115ee9b KZ |
65 | |
66 | free(fs); | |
67 | } | |
68 | ||
309139c7 KZ |
69 | /** |
70 | * mnt_reset_fs: | |
71 | * @fs: fs pointer | |
72 | * | |
73 | * Resets (zeroize) @fs. | |
74 | */ | |
75 | void mnt_reset_fs(struct libmnt_fs *fs) | |
76 | { | |
77 | if (fs) | |
78 | memset(fs, 0, sizeof(*fs)); | |
79 | } | |
80 | ||
81 | static inline int update_str(char **dest, const char *src) | |
9ecdf48f | 82 | { |
8b95253f KZ |
83 | size_t sz; |
84 | char *x; | |
85 | ||
86 | assert(dest); | |
9ecdf48f | 87 | |
8b95253f KZ |
88 | if (!src) { |
89 | free(*dest); | |
90 | *dest = NULL; | |
9ecdf48f | 91 | return 0; /* source (old) is empty */ |
8b95253f | 92 | } |
9ecdf48f | 93 | |
8b95253f KZ |
94 | sz = strlen(src) + 1; |
95 | x = realloc(*dest, sz); | |
96 | if (!x) | |
56be757f | 97 | return -ENOMEM; |
8b95253f KZ |
98 | *dest = x; |
99 | memcpy(*dest, src, sz); | |
9ecdf48f KZ |
100 | return 0; |
101 | } | |
102 | ||
8b95253f KZ |
103 | static inline int cpy_str_at_offset(void *new, const void *old, size_t offset) |
104 | { | |
105 | char **o = (char **) (old + offset); | |
106 | char **n = (char **) (new + offset); | |
107 | ||
309139c7 KZ |
108 | if (*n) |
109 | return 0; /* already set, not overwrite */ | |
110 | ||
111 | return update_str(n, *o); | |
8b95253f KZ |
112 | } |
113 | ||
9ecdf48f KZ |
114 | /** |
115 | * mnt_copy_fs: | |
309139c7 KZ |
116 | * @dest: destination FS |
117 | * @src: source FS | |
118 | * | |
119 | * If @dest is NULL, then a new FS is allocated, if any @dest field is already | |
120 | * set then the field is NOT overwrited. | |
9ecdf48f KZ |
121 | * |
122 | * This function does not copy userdata (se mnt_fs_set_userdata()). A new copy is | |
123 | * not linked with any existing mnt_tab. | |
124 | * | |
309139c7 | 125 | * Returns: @dest or NULL in case of error |
9ecdf48f | 126 | */ |
309139c7 KZ |
127 | struct libmnt_fs *mnt_copy_fs(struct libmnt_fs *dest, |
128 | const struct libmnt_fs *src) | |
9ecdf48f | 129 | { |
309139c7 | 130 | const struct libmnt_fs *org = dest; |
9ecdf48f | 131 | |
52a285bf KZ |
132 | if (!src) |
133 | return NULL; | |
309139c7 KZ |
134 | if (!dest) { |
135 | dest = mnt_new_fs(); | |
136 | if (!dest) | |
137 | return NULL; | |
138 | } | |
9ecdf48f | 139 | |
309139c7 | 140 | /*DBG(FS, mnt_debug_h(dest, "copy from %p", src));*/ |
9ecdf48f | 141 | |
309139c7 KZ |
142 | dest->id = src->id; |
143 | dest->parent = src->parent; | |
144 | dest->devno = src->devno; | |
f7f29b56 | 145 | dest->tid = src->tid; |
309139c7 KZ |
146 | |
147 | if (cpy_str_at_offset(dest, src, offsetof(struct libmnt_fs, source))) | |
9ecdf48f | 148 | goto err; |
309139c7 | 149 | if (cpy_str_at_offset(dest, src, offsetof(struct libmnt_fs, tagname))) |
9ecdf48f | 150 | goto err; |
309139c7 | 151 | if (cpy_str_at_offset(dest, src, offsetof(struct libmnt_fs, tagval))) |
9ecdf48f | 152 | goto err; |
309139c7 | 153 | if (cpy_str_at_offset(dest, src, offsetof(struct libmnt_fs, root))) |
9ecdf48f | 154 | goto err; |
ce4dd666 KZ |
155 | if (cpy_str_at_offset(dest, src, offsetof(struct libmnt_fs, swaptype))) |
156 | goto err; | |
309139c7 | 157 | if (cpy_str_at_offset(dest, src, offsetof(struct libmnt_fs, target))) |
9ecdf48f | 158 | goto err; |
309139c7 | 159 | if (cpy_str_at_offset(dest, src, offsetof(struct libmnt_fs, fstype))) |
9ecdf48f | 160 | goto err; |
f2b3a3a3 KZ |
161 | if (cpy_str_at_offset(dest, src, offsetof(struct libmnt_fs, optstr))) |
162 | goto err; | |
309139c7 | 163 | if (cpy_str_at_offset(dest, src, offsetof(struct libmnt_fs, vfs_optstr))) |
9ecdf48f | 164 | goto err; |
309139c7 | 165 | if (cpy_str_at_offset(dest, src, offsetof(struct libmnt_fs, fs_optstr))) |
9ecdf48f | 166 | goto err; |
309139c7 | 167 | if (cpy_str_at_offset(dest, src, offsetof(struct libmnt_fs, user_optstr))) |
76a06ca4 | 168 | goto err; |
309139c7 | 169 | if (cpy_str_at_offset(dest, src, offsetof(struct libmnt_fs, attrs))) |
76a06ca4 | 170 | goto err; |
c4c66355 KZ |
171 | if (cpy_str_at_offset(dest, src, offsetof(struct libmnt_fs, bindsrc))) |
172 | goto err; | |
76a06ca4 | 173 | |
309139c7 KZ |
174 | dest->freq = src->freq; |
175 | dest->passno = src->passno; | |
176 | dest->flags = src->flags; | |
ce4dd666 KZ |
177 | dest->size = src->size; |
178 | dest->usedsize = src->usedsize; | |
179 | dest->priority = src->priority; | |
9ecdf48f | 180 | |
309139c7 | 181 | return dest; |
9ecdf48f | 182 | err: |
309139c7 KZ |
183 | if (!org) |
184 | mnt_free_fs(dest); | |
9ecdf48f KZ |
185 | return NULL; |
186 | } | |
187 | ||
0f32f1e2 | 188 | /* |
f84fa6f7 KZ |
189 | * This function copies all @fs description except information that does not |
190 | * belong to /etc/mtab (e.g. VFS and userspace mount options with MNT_NOMTAB | |
191 | * mask). | |
192 | * | |
193 | * Returns: copy of @fs. | |
194 | */ | |
68164f6c | 195 | struct libmnt_fs *mnt_copy_mtab_fs(const struct libmnt_fs *fs) |
f84fa6f7 | 196 | { |
68164f6c | 197 | struct libmnt_fs *n = mnt_new_fs(); |
f84fa6f7 | 198 | |
4569bbea | 199 | assert(fs); |
f84fa6f7 KZ |
200 | if (!n) |
201 | return NULL; | |
202 | ||
68164f6c | 203 | if (cpy_str_at_offset(n, fs, offsetof(struct libmnt_fs, source))) |
f84fa6f7 | 204 | goto err; |
68164f6c | 205 | if (cpy_str_at_offset(n, fs, offsetof(struct libmnt_fs, target))) |
f84fa6f7 | 206 | goto err; |
68164f6c | 207 | if (cpy_str_at_offset(n, fs, offsetof(struct libmnt_fs, fstype))) |
f84fa6f7 KZ |
208 | goto err; |
209 | ||
210 | if (fs->vfs_optstr) { | |
211 | char *p = NULL; | |
212 | mnt_optstr_get_options(fs->vfs_optstr, &p, | |
213 | mnt_get_builtin_optmap(MNT_LINUX_MAP), | |
214 | MNT_NOMTAB); | |
215 | n->vfs_optstr = p; | |
216 | } | |
217 | ||
218 | if (fs->user_optstr) { | |
219 | char *p = NULL; | |
220 | mnt_optstr_get_options(fs->user_optstr, &p, | |
221 | mnt_get_builtin_optmap(MNT_USERSPACE_MAP), | |
222 | MNT_NOMTAB); | |
223 | n->user_optstr = p; | |
224 | } | |
225 | ||
68164f6c | 226 | if (cpy_str_at_offset(n, fs, offsetof(struct libmnt_fs, fs_optstr))) |
f84fa6f7 KZ |
227 | goto err; |
228 | ||
f2b3a3a3 KZ |
229 | /* we cannot copy original optstr, the new optstr has to be without |
230 | * non-mtab options -- so, let's generate a new string */ | |
231 | n->optstr = mnt_fs_strdup_options(n); | |
232 | ||
f84fa6f7 KZ |
233 | n->freq = fs->freq; |
234 | n->passno = fs->passno; | |
235 | n->flags = fs->flags; | |
236 | ||
237 | return n; | |
238 | err: | |
239 | mnt_free_fs(n); | |
240 | return NULL; | |
241 | ||
242 | } | |
243 | ||
26b4f9e4 KZ |
244 | /** |
245 | * mnt_fs_get_userdata: | |
68164f6c | 246 | * @fs: struct libmnt_file instance |
26b4f9e4 | 247 | * |
192c6aad | 248 | * Returns: private data set by mnt_fs_set_userdata() or NULL. |
26b4f9e4 | 249 | */ |
68164f6c | 250 | void *mnt_fs_get_userdata(struct libmnt_fs *fs) |
26b4f9e4 | 251 | { |
4569bbea | 252 | assert(fs); |
26b4f9e4 KZ |
253 | return fs ? fs->userdata : NULL; |
254 | } | |
255 | ||
256 | /** | |
257 | * mnt_fs_set_userdata: | |
68164f6c | 258 | * @fs: struct libmnt_file instance |
0f32f1e2 | 259 | * @data: user data |
26b4f9e4 KZ |
260 | * |
261 | * The "userdata" are library independent data. | |
262 | * | |
56be757f | 263 | * Returns: 0 or negative number in case of error (if @fs is NULL). |
26b4f9e4 | 264 | */ |
68164f6c | 265 | int mnt_fs_set_userdata(struct libmnt_fs *fs, void *data) |
26b4f9e4 | 266 | { |
4569bbea | 267 | assert(fs); |
26b4f9e4 | 268 | if (!fs) |
56be757f | 269 | return -EINVAL; |
26b4f9e4 KZ |
270 | fs->userdata = data; |
271 | return 0; | |
272 | } | |
273 | ||
d115ee9b KZ |
274 | /** |
275 | * mnt_fs_get_srcpath: | |
68164f6c | 276 | * @fs: struct libmnt_file (fstab/mtab/mountinfo) fs |
d115ee9b KZ |
277 | * |
278 | * The mount "source path" is: | |
192c6aad KZ |
279 | * - a directory for 'bind' mounts (in fstab or mtab only) |
280 | * - a device name for standard mounts | |
d115ee9b KZ |
281 | * |
282 | * See also mnt_fs_get_tag() and mnt_fs_get_source(). | |
283 | * | |
192c6aad | 284 | * Returns: mount source path or NULL in case of error or when the path |
d115ee9b | 285 | * is not defined. |
d115ee9b | 286 | */ |
68164f6c | 287 | const char *mnt_fs_get_srcpath(struct libmnt_fs *fs) |
d115ee9b KZ |
288 | { |
289 | assert(fs); | |
290 | if (!fs) | |
291 | return NULL; | |
292 | ||
293 | /* fstab-like fs */ | |
294 | if (fs->tagname) | |
295 | return NULL; /* the source contains a "NAME=value" */ | |
296 | return fs->source; | |
297 | } | |
298 | ||
299 | /** | |
3d735589 | 300 | * mnt_fs_get_source: |
68164f6c | 301 | * @fs: struct libmnt_file (fstab/mtab/mountinfo) fs |
d115ee9b | 302 | * |
192c6aad | 303 | * Returns: mount source. Note that the source could be unparsed TAG |
d115ee9b KZ |
304 | * (LABEL/UUID). See also mnt_fs_get_srcpath() and mnt_fs_get_tag(). |
305 | */ | |
68164f6c | 306 | const char *mnt_fs_get_source(struct libmnt_fs *fs) |
d115ee9b | 307 | { |
4569bbea | 308 | assert(fs); |
d115ee9b KZ |
309 | return fs ? fs->source : NULL; |
310 | } | |
311 | ||
5af0769d | 312 | /* |
39e119f5 | 313 | * Used by parser ONLY (@source has to be freed on error) |
5af0769d | 314 | */ |
68164f6c | 315 | int __mnt_fs_set_source_ptr(struct libmnt_fs *fs, char *source) |
d115ee9b | 316 | { |
b2d0b74d KZ |
317 | char *t = NULL, *v = NULL; |
318 | ||
d115ee9b KZ |
319 | assert(fs); |
320 | ||
2c6b25f0 KZ |
321 | if (source && blkid_parse_tag_string(source, &t, &v) == 0 && |
322 | !mnt_valid_tagname(t)) { | |
323 | /* parsable but unknown tag -- ignore */ | |
324 | free(t); | |
325 | free(v); | |
326 | t = v = NULL; | |
d115ee9b KZ |
327 | } |
328 | ||
b2d0b74d KZ |
329 | if (fs->source != source) |
330 | free(fs->source); | |
331 | ||
332 | free(fs->tagname); | |
333 | free(fs->tagval); | |
334 | ||
d115ee9b | 335 | fs->source = source; |
b2d0b74d KZ |
336 | fs->tagname = t; |
337 | fs->tagval = v; | |
d115ee9b KZ |
338 | return 0; |
339 | } | |
340 | ||
341 | /** | |
342 | * mnt_fs_set_source: | |
343 | * @fs: fstab/mtab/mountinfo entry | |
344 | * @source: new source | |
345 | * | |
192c6aad KZ |
346 | * This function creates a private copy (strdup()) of @source. |
347 | * | |
56be757f | 348 | * Returns: 0 on success or negative number in case of error. |
d115ee9b | 349 | */ |
68164f6c | 350 | int mnt_fs_set_source(struct libmnt_fs *fs, const char *source) |
d115ee9b | 351 | { |
f5017242 | 352 | char *p = NULL; |
b2d0b74d | 353 | int rc; |
d115ee9b | 354 | |
4569bbea | 355 | assert(fs); |
f5017242 | 356 | if (!fs) |
56be757f | 357 | return -EINVAL; |
d0ce7c07 | 358 | |
f5017242 KZ |
359 | if (source) { |
360 | p = strdup(source); | |
361 | if (!p) | |
362 | return -ENOMEM; | |
363 | } | |
d115ee9b | 364 | |
b2d0b74d KZ |
365 | rc = __mnt_fs_set_source_ptr(fs, p); |
366 | if (rc) | |
367 | free(p); | |
368 | return rc; | |
d115ee9b KZ |
369 | } |
370 | ||
6699e742 KZ |
371 | /** |
372 | * mnt_fs_streq_srcpath: | |
373 | * @fs: fs | |
374 | * @path: source path | |
375 | * | |
376 | * Compares @fs source path with @path. The tailing slash is ignored. | |
377 | * See also mnt_fs_match_source(). | |
378 | * | |
379 | * Returns: 1 if @fs source path equal to @path, otherwise 0. | |
380 | */ | |
ab8c6e05 KZ |
381 | int mnt_fs_streq_srcpath(struct libmnt_fs *fs, const char *path) |
382 | { | |
6699e742 | 383 | const char *p; |
ab8c6e05 | 384 | |
4569bbea | 385 | assert(fs); |
6699e742 | 386 | if (!fs) |
ab8c6e05 KZ |
387 | return 0; |
388 | ||
6699e742 | 389 | p = mnt_fs_get_srcpath(fs); |
ab8c6e05 | 390 | |
6699e742 KZ |
391 | if (!mnt_fs_is_pseudofs(fs)) |
392 | return streq_except_trailing_slash(p, path); | |
393 | ||
394 | if (!p && !path) | |
395 | return 1; | |
396 | ||
397 | return p && path && strcmp(p, path) == 0; | |
ab8c6e05 KZ |
398 | } |
399 | ||
6699e742 KZ |
400 | /** |
401 | * mnt_fs_streq_target: | |
402 | * @fs: fs | |
403 | * @path: mount point | |
404 | * | |
405 | * Compares @fs target path with @path. The tailing slash is ignored. | |
406 | * See also mnt_fs_match_target(). | |
407 | * | |
408 | * Returns: 1 if @fs target path equal to @path, otherwise 0. | |
409 | */ | |
410 | int mnt_fs_streq_target(struct libmnt_fs *fs, const char *path) | |
411 | { | |
4569bbea | 412 | assert(fs); |
6699e742 KZ |
413 | return fs && streq_except_trailing_slash(mnt_fs_get_target(fs), path); |
414 | } | |
ab8c6e05 | 415 | |
d115ee9b KZ |
416 | /** |
417 | * mnt_fs_get_tag: | |
418 | * @fs: fs | |
419 | * @name: returns pointer to NAME string | |
420 | * @value: returns pointer to VALUE string | |
421 | * | |
422 | * "TAG" is NAME=VALUE (e.g. LABEL=foo) | |
423 | * | |
192c6aad KZ |
424 | * The TAG is the first column in the fstab file. The TAG or "srcpath" has to |
425 | * be always set for all entries. | |
d115ee9b KZ |
426 | * |
427 | * See also mnt_fs_get_source(). | |
428 | * | |
192c6aad KZ |
429 | * <informalexample> |
430 | * <programlisting> | |
d115ee9b | 431 | * char *src; |
68164f6c | 432 | * struct libmnt_fs *fs = mnt_table_find_target(tb, "/home", MNT_ITER_FORWARD); |
d115ee9b KZ |
433 | * |
434 | * if (!fs) | |
435 | * goto err; | |
436 | * | |
437 | * src = mnt_fs_get_srcpath(fs); | |
438 | * if (!src) { | |
439 | * char *tag, *val; | |
440 | * if (mnt_fs_get_tag(fs, &tag, &val) == 0) | |
441 | * printf("%s: %s\n", tag, val); // LABEL or UUID | |
442 | * } else | |
443 | * printf("device: %s\n", src); // device or bind path | |
192c6aad KZ |
444 | * </programlisting> |
445 | * </informalexample> | |
d115ee9b | 446 | * |
56be757f | 447 | * Returns: 0 on success or negative number in case that a TAG is not defined. |
d115ee9b | 448 | */ |
68164f6c | 449 | int mnt_fs_get_tag(struct libmnt_fs *fs, const char **name, const char **value) |
d115ee9b | 450 | { |
4569bbea | 451 | assert(fs); |
d115ee9b | 452 | if (fs == NULL || !fs->tagname) |
56be757f | 453 | return -EINVAL; |
d115ee9b KZ |
454 | if (name) |
455 | *name = fs->tagname; | |
456 | if (value) | |
457 | *value = fs->tagval; | |
458 | return 0; | |
459 | } | |
460 | ||
461 | /** | |
462 | * mnt_fs_get_target: | |
463 | * @fs: fstab/mtab/mountinfo entry pointer | |
464 | * | |
192c6aad | 465 | * Returns: pointer to mountpoint path or NULL |
d115ee9b | 466 | */ |
68164f6c | 467 | const char *mnt_fs_get_target(struct libmnt_fs *fs) |
d115ee9b KZ |
468 | { |
469 | assert(fs); | |
470 | return fs ? fs->target : NULL; | |
471 | } | |
472 | ||
473 | /** | |
474 | * mnt_fs_set_target: | |
475 | * @fs: fstab/mtab/mountinfo entry | |
476 | * @target: mountpoint | |
477 | * | |
192c6aad KZ |
478 | * This function creates a private copy (strdup()) of @target. |
479 | * | |
56be757f | 480 | * Returns: 0 on success or negative number in case of error. |
d115ee9b | 481 | */ |
68164f6c | 482 | int mnt_fs_set_target(struct libmnt_fs *fs, const char *target) |
d115ee9b | 483 | { |
f5017242 | 484 | char *p = NULL; |
d115ee9b KZ |
485 | |
486 | assert(fs); | |
f5017242 | 487 | if (!fs) |
56be757f | 488 | return -EINVAL; |
f5017242 KZ |
489 | if (target) { |
490 | p = strdup(target); | |
491 | if (!p) | |
492 | return -ENOMEM; | |
493 | } | |
d115ee9b KZ |
494 | free(fs->target); |
495 | fs->target = p; | |
496 | ||
497 | return 0; | |
498 | } | |
499 | ||
c70d9d76 | 500 | static int mnt_fs_get_flags(struct libmnt_fs *fs) |
309139c7 KZ |
501 | { |
502 | return fs ? fs->flags : 0; | |
503 | } | |
504 | ||
4b9d67a2 KZ |
505 | /** |
506 | * mnt_fs_get_propagation: | |
507 | * @fs: mountinfo entry | |
508 | * @flags: returns propagation MS_* flags as present in mountinfo file | |
509 | * | |
510 | * Note that this function set @flags to zero if not found any propagation flag | |
511 | * in mountinfo file. The kernel default is MS_PRIVATE, this flag is not stored | |
512 | * in the mountinfo file. | |
513 | * | |
514 | * Returns: 0 on success or negative number in case of error. | |
515 | */ | |
516 | int mnt_fs_get_propagation(struct libmnt_fs *fs, unsigned long *flags) | |
517 | { | |
4569bbea | 518 | assert(fs); |
4b9d67a2 KZ |
519 | if (!fs || !flags) |
520 | return -EINVAL; | |
521 | ||
522 | *flags = 0; | |
523 | ||
524 | if (!fs->opt_fields) | |
525 | return 0; | |
526 | ||
527 | /* | |
528 | * The optional fields format is incompatible with mount options | |
529 | * ... we have to parse the field here. | |
530 | */ | |
531 | *flags |= strstr(fs->opt_fields, "shared:") ? MS_SHARED : MS_PRIVATE; | |
532 | ||
533 | if (strstr(fs->opt_fields, "master:")) | |
534 | *flags |= MS_SLAVE; | |
535 | if (strstr(fs->opt_fields, "unbindable")) | |
536 | *flags |= MS_UNBINDABLE; | |
537 | ||
538 | return 0; | |
539 | } | |
540 | ||
309139c7 KZ |
541 | /** |
542 | * mnt_fs_is_kernel: | |
543 | * @fs: filesystem | |
544 | * | |
545 | * Returns: 1 if the filesystem description is read from kernel e.g. /proc/mounts. | |
546 | */ | |
547 | int mnt_fs_is_kernel(struct libmnt_fs *fs) | |
548 | { | |
c70d9d76 KZ |
549 | return mnt_fs_get_flags(fs) & MNT_FS_KERNEL; |
550 | } | |
551 | ||
552 | /** | |
553 | * mnt_fs_is_swaparea: | |
554 | * @fs: filesystem | |
555 | * | |
556 | * Returns: 1 if the filesystem uses "swap" as a type | |
557 | */ | |
558 | int mnt_fs_is_swaparea(struct libmnt_fs *fs) | |
559 | { | |
4569bbea | 560 | assert(fs); |
c70d9d76 KZ |
561 | return mnt_fs_get_flags(fs) & MNT_FS_SWAP; |
562 | } | |
563 | ||
564 | /** | |
565 | * mnt_fs_is_pseudofs: | |
566 | * @fs: filesystem | |
567 | * | |
568 | * Returns: 1 if the filesystem is a pseudo fs type (proc, cgroups) | |
569 | */ | |
b928ab01 | 570 | int mnt_fs_is_pseudofs(struct libmnt_fs *fs) |
c70d9d76 | 571 | { |
4569bbea | 572 | assert(fs); |
c70d9d76 KZ |
573 | return mnt_fs_get_flags(fs) & MNT_FS_PSEUDO; |
574 | } | |
575 | ||
576 | /** | |
577 | * mnt_fs_is_netfs: | |
578 | * @fs: filesystem | |
579 | * | |
580 | * Returns: 1 if the filesystem is a network filesystem | |
581 | */ | |
582 | int mnt_fs_is_netfs(struct libmnt_fs *fs) | |
583 | { | |
4569bbea | 584 | assert(fs); |
c70d9d76 | 585 | return mnt_fs_get_flags(fs) & MNT_FS_NET; |
309139c7 KZ |
586 | } |
587 | ||
d115ee9b KZ |
588 | /** |
589 | * mnt_fs_get_fstype: | |
590 | * @fs: fstab/mtab/mountinfo entry pointer | |
591 | * | |
192c6aad | 592 | * Returns: pointer to filesystem type. |
d115ee9b | 593 | */ |
68164f6c | 594 | const char *mnt_fs_get_fstype(struct libmnt_fs *fs) |
d115ee9b KZ |
595 | { |
596 | assert(fs); | |
597 | return fs ? fs->fstype : NULL; | |
598 | } | |
599 | ||
68164f6c KZ |
600 | /* Used by struct libmnt_file parser only */ |
601 | int __mnt_fs_set_fstype_ptr(struct libmnt_fs *fs, char *fstype) | |
d115ee9b KZ |
602 | { |
603 | assert(fs); | |
604 | ||
b2d0b74d KZ |
605 | if (fstype != fs->fstype) |
606 | free(fs->fstype); | |
607 | ||
d115ee9b KZ |
608 | fs->fstype = fstype; |
609 | fs->flags &= ~MNT_FS_PSEUDO; | |
610 | fs->flags &= ~MNT_FS_NET; | |
5dfc9843 | 611 | fs->flags &= ~MNT_FS_SWAP; |
d115ee9b KZ |
612 | |
613 | /* save info about pseudo filesystems */ | |
8485e709 KZ |
614 | if (fs->fstype) { |
615 | if (mnt_fstype_is_pseudofs(fs->fstype)) | |
616 | fs->flags |= MNT_FS_PSEUDO; | |
617 | else if (mnt_fstype_is_netfs(fs->fstype)) | |
618 | fs->flags |= MNT_FS_NET; | |
619 | else if (!strcmp(fs->fstype, "swap")) | |
620 | fs->flags |= MNT_FS_SWAP; | |
621 | } | |
d115ee9b KZ |
622 | return 0; |
623 | } | |
624 | ||
625 | /** | |
626 | * mnt_fs_set_fstype: | |
627 | * @fs: fstab/mtab/mountinfo entry | |
628 | * @fstype: filesystem type | |
629 | * | |
192c6aad KZ |
630 | * This function creates a private copy (strdup()) of @fstype. |
631 | * | |
56be757f | 632 | * Returns: 0 on success or negative number in case of error. |
d115ee9b | 633 | */ |
68164f6c | 634 | int mnt_fs_set_fstype(struct libmnt_fs *fs, const char *fstype) |
d115ee9b | 635 | { |
8485e709 | 636 | char *p = NULL; |
d115ee9b | 637 | |
4569bbea | 638 | assert(fs); |
8485e709 | 639 | if (!fs) |
56be757f | 640 | return -EINVAL; |
8485e709 KZ |
641 | if (fstype) { |
642 | p = strdup(fstype); | |
643 | if (!p) | |
644 | return -ENOMEM; | |
645 | } | |
f5017242 | 646 | return __mnt_fs_set_fstype_ptr(fs, p); |
d115ee9b KZ |
647 | } |
648 | ||
76a06ca4 KZ |
649 | /* |
650 | * Merges @vfs and @fs options strings into a new string. | |
651 | * This function cares about 'ro/rw' options. The 'ro' is | |
652 | * always used if @vfs or @fs is read-only. | |
653 | * For example: | |
654 | * | |
655 | * mnt_merge_optstr("rw,noexec", "ro,journal=update") | |
656 | * | |
657 | * returns: "ro,noexec,journal=update" | |
658 | * | |
659 | * mnt_merge_optstr("rw,noexec", "rw,journal=update") | |
660 | * | |
661 | * returns: "rw,noexec,journal=update" | |
662 | */ | |
663 | static char *merge_optstr(const char *vfs, const char *fs) | |
664 | { | |
665 | char *res, *p; | |
666 | size_t sz; | |
667 | int ro = 0, rw = 0; | |
668 | ||
669 | if (!vfs && !fs) | |
670 | return NULL; | |
671 | if (!vfs || !fs) | |
672 | return strdup(fs ? fs : vfs); | |
673 | if (!strcmp(vfs, fs)) | |
674 | return strdup(vfs); /* e.g. "aaa" and "aaa" */ | |
675 | ||
676 | /* leave space for leading "r[ow],", "," and trailing zero */ | |
677 | sz = strlen(vfs) + strlen(fs) + 5; | |
678 | res = malloc(sz); | |
679 | if (!res) | |
680 | return NULL; | |
681 | p = res + 3; /* make a room for rw/ro flag */ | |
682 | ||
683 | snprintf(p, sz - 3, "%s,%s", vfs, fs); | |
684 | ||
685 | /* remove 'rw' flags */ | |
686 | rw += !mnt_optstr_remove_option(&p, "rw"); /* from vfs */ | |
687 | rw += !mnt_optstr_remove_option(&p, "rw"); /* from fs */ | |
688 | ||
689 | /* remove 'ro' flags if necessary */ | |
690 | if (rw != 2) { | |
691 | ro += !mnt_optstr_remove_option(&p, "ro"); | |
692 | if (ro + rw < 2) | |
693 | ro += !mnt_optstr_remove_option(&p, "ro"); | |
694 | } | |
695 | ||
696 | if (!strlen(p)) | |
697 | memcpy(res, ro ? "ro" : "rw", 3); | |
698 | else | |
699 | memcpy(res, ro ? "ro," : "rw,", 3); | |
700 | return res; | |
701 | } | |
702 | ||
d115ee9b | 703 | /** |
76a06ca4 | 704 | * mnt_fs_strdup_options: |
d115ee9b KZ |
705 | * @fs: fstab/mtab/mountinfo entry pointer |
706 | * | |
76a06ca4 KZ |
707 | * Merges all mount options (VFS, FS and userspace) to the one options string |
708 | * and returns the result. This function does not modigy @fs. | |
709 | * | |
710 | * Returns: pointer to string (can be freed by free(3)) or NULL in case of error. | |
d115ee9b | 711 | */ |
68164f6c | 712 | char *mnt_fs_strdup_options(struct libmnt_fs *fs) |
d115ee9b | 713 | { |
76a06ca4 KZ |
714 | char *res; |
715 | ||
d115ee9b | 716 | assert(fs); |
76a06ca4 | 717 | errno = 0; |
f2b3a3a3 KZ |
718 | if (fs->optstr) |
719 | return strdup(fs->optstr); | |
720 | ||
76a06ca4 | 721 | res = merge_optstr(fs->vfs_optstr, fs->fs_optstr); |
87a07a4c | 722 | if (!res && errno) |
76a06ca4 KZ |
723 | return NULL; |
724 | if (fs->user_optstr) { | |
725 | if (mnt_optstr_append_option(&res, fs->user_optstr, NULL)) { | |
726 | free(res); | |
727 | res = NULL; | |
728 | } | |
729 | } | |
730 | return res; | |
d115ee9b KZ |
731 | } |
732 | ||
f2b3a3a3 KZ |
733 | /** |
734 | * mnt_fs_get_options: | |
735 | * @fs: fstab/mtab/mountinfo entry pointer | |
736 | * | |
737 | * Returns: pointer to string or NULL in case of error. | |
738 | */ | |
739 | const char *mnt_fs_get_options(struct libmnt_fs *fs) | |
740 | { | |
741 | assert(fs); | |
742 | return fs ? fs->optstr : NULL; | |
743 | } | |
744 | ||
e47a1931 OO |
745 | /** |
746 | * mnt_fs_get_optional_fields | |
747 | * @fs: mountinfo entry pointer | |
748 | * | |
749 | * Returns: pointer to string with mountinfo optional fields | |
750 | * or NULL in case of error. | |
751 | */ | |
752 | const char *mnt_fs_get_optional_fields(struct libmnt_fs *fs) | |
753 | { | |
754 | assert(fs); | |
755 | return fs ? fs->opt_fields : NULL; | |
756 | } | |
f2b3a3a3 | 757 | |
76a06ca4 KZ |
758 | /** |
759 | * mnt_fs_set_options: | |
760 | * @fs: fstab/mtab/mountinfo entry pointer | |
0f32f1e2 | 761 | * @optstr: options string |
76a06ca4 KZ |
762 | * |
763 | * Splits @optstr to VFS, FS and userspace mount options and update relevat | |
764 | * parts of @fs. | |
765 | * | |
766 | * Returns: 0 on success, or negative number icase of error. | |
767 | */ | |
68164f6c | 768 | int mnt_fs_set_options(struct libmnt_fs *fs, const char *optstr) |
d115ee9b | 769 | { |
f2b3a3a3 | 770 | char *v = NULL, *f = NULL, *u = NULL, *n = NULL; |
192c6aad | 771 | |
d115ee9b | 772 | assert(fs); |
be1a5180 | 773 | if (!fs) |
56be757f | 774 | return -EINVAL; |
76a06ca4 KZ |
775 | if (optstr) { |
776 | int rc = mnt_split_optstr(optstr, &u, &v, &f, 0, 0); | |
56be757f KZ |
777 | if (rc) |
778 | return rc; | |
f2b3a3a3 KZ |
779 | n = strdup(optstr); |
780 | if (!n) | |
781 | return -ENOMEM; | |
3661b841 | 782 | } |
192c6aad | 783 | |
d115ee9b KZ |
784 | free(fs->fs_optstr); |
785 | free(fs->vfs_optstr); | |
76a06ca4 | 786 | free(fs->user_optstr); |
f2b3a3a3 | 787 | free(fs->optstr); |
d6fead1e | 788 | |
3661b841 KZ |
789 | fs->fs_optstr = f; |
790 | fs->vfs_optstr = v; | |
76a06ca4 | 791 | fs->user_optstr = u; |
f2b3a3a3 KZ |
792 | fs->optstr = n; |
793 | ||
192c6aad | 794 | return 0; |
d115ee9b KZ |
795 | } |
796 | ||
76a06ca4 KZ |
797 | /** |
798 | * mnt_fs_append_options: | |
799 | * @fs: fstab/mtab/mountinfo entry | |
800 | * @optstr: mount options | |
801 | * | |
802 | * Parses (splits) @optstr and appends results to VFS, FS and userspace lists | |
803 | * of options. | |
804 | * | |
805 | * If @optstr is NULL then @fs is not modified and 0 is returned. | |
806 | * | |
807 | * Returns: 0 on success or negative number in case of error. | |
808 | */ | |
68164f6c | 809 | int mnt_fs_append_options(struct libmnt_fs *fs, const char *optstr) |
b2d0b74d | 810 | { |
76a06ca4 | 811 | char *v = NULL, *f = NULL, *u = NULL; |
b2d0b74d KZ |
812 | int rc; |
813 | ||
814 | assert(fs); | |
76a06ca4 KZ |
815 | if (!fs) |
816 | return -EINVAL; | |
817 | if (!optstr) | |
818 | return 0; | |
819 | ||
820 | rc = mnt_split_optstr((char *) optstr, &u, &v, &f, 0, 0); | |
821 | if (!rc && v) | |
822 | rc = mnt_optstr_append_option(&fs->vfs_optstr, v, NULL); | |
823 | if (!rc && f) | |
f2b3a3a3 | 824 | rc = mnt_optstr_append_option(&fs->fs_optstr, f, NULL); |
76a06ca4 | 825 | if (!rc && u) |
f2b3a3a3 KZ |
826 | rc = mnt_optstr_append_option(&fs->user_optstr, u, NULL); |
827 | if (!rc) | |
828 | rc = mnt_optstr_append_option(&fs->optstr, optstr, NULL); | |
829 | ||
830 | free(v); | |
831 | free(f); | |
832 | free(u); | |
76a06ca4 | 833 | |
b2d0b74d KZ |
834 | return rc; |
835 | } | |
836 | ||
3661b841 | 837 | /** |
76a06ca4 KZ |
838 | * mnt_fs_prepend_options: |
839 | * @fs: fstab/mtab/mountinfo entry | |
840 | * @optstr: mount options | |
841 | * | |
842 | * Parses (splits) @optstr and prepands results to VFS, FS and userspace lists | |
843 | * of options. | |
844 | * | |
845 | * If @optstr is NULL then @fs is not modified and 0 is returned. | |
846 | * | |
847 | * Returns: 0 on success or negative number in case of error. | |
848 | */ | |
68164f6c | 849 | int mnt_fs_prepend_options(struct libmnt_fs *fs, const char *optstr) |
76a06ca4 KZ |
850 | { |
851 | char *v = NULL, *f = NULL, *u = NULL; | |
852 | int rc; | |
853 | ||
854 | assert(fs); | |
76a06ca4 KZ |
855 | if (!fs) |
856 | return -EINVAL; | |
857 | if (!optstr) | |
858 | return 0; | |
859 | ||
860 | rc = mnt_split_optstr((char *) optstr, &u, &v, &f, 0, 0); | |
861 | if (!rc && v) | |
862 | rc = mnt_optstr_prepend_option(&fs->vfs_optstr, v, NULL); | |
863 | if (!rc && f) | |
864 | rc = mnt_optstr_prepend_option(&fs->fs_optstr, f, NULL); | |
865 | if (!rc && u) | |
866 | rc = mnt_optstr_prepend_option(&fs->user_optstr, u, NULL); | |
f2b3a3a3 KZ |
867 | if (!rc) |
868 | rc = mnt_optstr_prepend_option(&fs->optstr, optstr, NULL); | |
869 | ||
870 | free(v); | |
871 | free(f); | |
872 | free(u); | |
76a06ca4 KZ |
873 | |
874 | return rc; | |
875 | } | |
876 | ||
877 | /* | |
878 | * mnt_fs_get_fs_options: | |
879 | * @fs: fstab/mtab/mountinfo entry pointer | |
880 | * | |
881 | * Returns: pointer to superblock (fs-depend) mount option string or NULL. | |
882 | */ | |
68164f6c | 883 | const char *mnt_fs_get_fs_options(struct libmnt_fs *fs) |
76a06ca4 KZ |
884 | { |
885 | assert(fs); | |
886 | return fs ? fs->fs_optstr : NULL; | |
887 | } | |
888 | ||
76a06ca4 KZ |
889 | /** |
890 | * mnt_fs_get_vfs_options: | |
891 | * @fs: fstab/mtab entry pointer | |
892 | * | |
893 | * Returns: pointer to fs-independent (VFS) mount option string or NULL. | |
894 | */ | |
68164f6c | 895 | const char *mnt_fs_get_vfs_options(struct libmnt_fs *fs) |
76a06ca4 | 896 | { |
569f95b7 | 897 | assert(fs); |
76a06ca4 KZ |
898 | return fs ? fs->vfs_optstr : NULL; |
899 | } | |
900 | ||
76a06ca4 | 901 | /** |
68164f6c | 902 | * mnt_fs_get_user_options: |
76a06ca4 KZ |
903 | * @fs: fstab/mtab entry pointer |
904 | * | |
905 | * Returns: pointer to userspace mount option string or NULL. | |
906 | */ | |
68164f6c | 907 | const char *mnt_fs_get_user_options(struct libmnt_fs *fs) |
76a06ca4 KZ |
908 | { |
909 | assert(fs); | |
910 | return fs ? fs->user_optstr : NULL; | |
569f95b7 KZ |
911 | } |
912 | ||
d115ee9b | 913 | /** |
76a06ca4 KZ |
914 | * mnt_fs_get_attributes: |
915 | * @fs: fstab/mtab entry pointer | |
d115ee9b | 916 | * |
76a06ca4 | 917 | * Returns: pointer to attributes string or NULL. |
d115ee9b | 918 | */ |
68164f6c | 919 | const char *mnt_fs_get_attributes(struct libmnt_fs *fs) |
d115ee9b KZ |
920 | { |
921 | assert(fs); | |
76a06ca4 | 922 | return fs ? fs->attrs : NULL; |
d115ee9b KZ |
923 | } |
924 | ||
925 | /** | |
76a06ca4 KZ |
926 | * mnt_fs_set_attributes: |
927 | * @fs: fstab/mtab/mountinfo entry | |
928 | * @optstr: options string | |
d115ee9b | 929 | * |
76a06ca4 KZ |
930 | * Sets mount attributes. The attributes are mount(2) and mount(8) independent |
931 | * options, these options are not send to kernel and are not interpreted by | |
a362ae60 | 932 | * libmount. The attributes are stored in /run/mount/utab only. |
76a06ca4 KZ |
933 | * |
934 | * The atrtributes are managed by libmount in userspace only. It's possible | |
935 | * that information stored in userspace will not be available for libmount | |
7007991f | 936 | * after CLONE_FS unshare. Be careful, and don't use attributes if possible. |
76a06ca4 KZ |
937 | * |
938 | * Returns: 0 on success or negative number in case of error. | |
d115ee9b | 939 | */ |
68164f6c | 940 | int mnt_fs_set_attributes(struct libmnt_fs *fs, const char *optstr) |
d115ee9b | 941 | { |
76a06ca4 KZ |
942 | char *p = NULL; |
943 | ||
4569bbea | 944 | assert(fs); |
76a06ca4 KZ |
945 | if (!fs) |
946 | return -EINVAL; | |
947 | if (optstr) { | |
948 | p = strdup(optstr); | |
949 | if (!p) | |
950 | return -ENOMEM; | |
951 | } | |
952 | free(fs->attrs); | |
953 | fs->attrs = p; | |
954 | ||
955 | return 0; | |
956 | } | |
957 | ||
958 | /** | |
959 | * mnt_fs_append_attributes | |
960 | * @fs: fstab/mtab/mountinfo entry | |
961 | * @optstr: options string | |
962 | * | |
963 | * Appends mount attributes. (See mnt_fs_set_attributes()). | |
964 | * | |
965 | * Returns: 0 on success or negative number in case of error. | |
966 | */ | |
68164f6c | 967 | int mnt_fs_append_attributes(struct libmnt_fs *fs, const char *optstr) |
76a06ca4 KZ |
968 | { |
969 | if (!fs) | |
970 | return -EINVAL; | |
971 | if (!optstr) | |
972 | return 0; | |
973 | return mnt_optstr_append_option(&fs->attrs, optstr, NULL); | |
974 | } | |
975 | ||
976 | /** | |
977 | * mnt_fs_prepend_attributes | |
978 | * @fs: fstab/mtab/mountinfo entry | |
979 | * @optstr: options string | |
980 | * | |
981 | * Prepends mount attributes. (See mnt_fs_set_attributes()). | |
982 | * | |
983 | * Returns: 0 on success or negative number in case of error. | |
984 | */ | |
68164f6c | 985 | int mnt_fs_prepend_attributes(struct libmnt_fs *fs, const char *optstr) |
76a06ca4 | 986 | { |
4569bbea | 987 | assert(fs); |
76a06ca4 KZ |
988 | if (!fs) |
989 | return -EINVAL; | |
990 | if (!optstr) | |
991 | return 0; | |
992 | return mnt_optstr_prepend_option(&fs->attrs, optstr, NULL); | |
d115ee9b KZ |
993 | } |
994 | ||
995 | ||
996 | /** | |
997 | * mnt_fs_get_freq: | |
998 | * @fs: fstab/mtab/mountinfo entry pointer | |
999 | * | |
3d735589 | 1000 | * Returns: dump frequency in days. |
d115ee9b | 1001 | */ |
68164f6c | 1002 | int mnt_fs_get_freq(struct libmnt_fs *fs) |
d115ee9b KZ |
1003 | { |
1004 | assert(fs); | |
1005 | return fs ? fs->freq : 0; | |
1006 | } | |
1007 | ||
1008 | /** | |
1009 | * mnt_fs_set_freq: | |
efe73c3e | 1010 | * @fs: fstab/mtab entry pointer |
d115ee9b KZ |
1011 | * @freq: dump frequency in days |
1012 | * | |
56be757f | 1013 | * Returns: 0 on success or negative number in case of error. |
d115ee9b | 1014 | */ |
68164f6c | 1015 | int mnt_fs_set_freq(struct libmnt_fs *fs, int freq) |
d115ee9b KZ |
1016 | { |
1017 | assert(fs); | |
d115ee9b | 1018 | if (!fs) |
56be757f | 1019 | return -EINVAL; |
d115ee9b KZ |
1020 | fs->freq = freq; |
1021 | return 0; | |
1022 | } | |
1023 | ||
1024 | /** | |
1025 | * mnt_fs_get_passno: | |
efe73c3e | 1026 | * @fs: fstab/mtab entry pointer |
d115ee9b | 1027 | * |
192c6aad | 1028 | * Returns: "pass number on parallel fsck". |
d115ee9b | 1029 | */ |
68164f6c | 1030 | int mnt_fs_get_passno(struct libmnt_fs *fs) |
d115ee9b KZ |
1031 | { |
1032 | assert(fs); | |
1033 | return fs ? fs->passno: 0; | |
1034 | } | |
1035 | ||
1036 | /** | |
1037 | * mnt_fs_set_passno: | |
efe73c3e | 1038 | * @fs: fstab/mtab entry pointer |
d115ee9b KZ |
1039 | * @passno: pass number |
1040 | * | |
56be757f | 1041 | * Returns: 0 on success or negative number in case of error. |
d115ee9b | 1042 | */ |
68164f6c | 1043 | int mnt_fs_set_passno(struct libmnt_fs *fs, int passno) |
d115ee9b KZ |
1044 | { |
1045 | assert(fs); | |
d115ee9b | 1046 | if (!fs) |
56be757f | 1047 | return -EINVAL; |
d115ee9b KZ |
1048 | fs->passno = passno; |
1049 | return 0; | |
1050 | } | |
1051 | ||
0b3953a3 KZ |
1052 | /** |
1053 | * mnt_fs_get_root: | |
1054 | * @fs: /proc/self/mountinfo entry | |
1055 | * | |
1056 | * Returns: root of the mount within the filesystem or NULL | |
1057 | */ | |
68164f6c | 1058 | const char *mnt_fs_get_root(struct libmnt_fs *fs) |
0b3953a3 KZ |
1059 | { |
1060 | assert(fs); | |
1061 | return fs ? fs->root : NULL; | |
1062 | } | |
1063 | ||
9ecdf48f KZ |
1064 | /** |
1065 | * mnt_fs_set_root: | |
1066 | * @fs: mountinfo entry | |
1067 | * @root: path | |
1068 | * | |
56be757f | 1069 | * Returns: 0 on success or negative number in case of error. |
9ecdf48f | 1070 | */ |
68164f6c | 1071 | int mnt_fs_set_root(struct libmnt_fs *fs, const char *root) |
9ecdf48f KZ |
1072 | { |
1073 | char *p = NULL; | |
1074 | ||
1075 | assert(fs); | |
1076 | if (!fs) | |
56be757f | 1077 | return -EINVAL; |
9ecdf48f KZ |
1078 | if (root) { |
1079 | p = strdup(root); | |
1080 | if (!p) | |
56be757f | 1081 | return -ENOMEM; |
9ecdf48f KZ |
1082 | } |
1083 | free(fs->root); | |
1084 | fs->root = p; | |
1085 | return 0; | |
1086 | } | |
1087 | ||
ce4dd666 KZ |
1088 | /** |
1089 | * mnt_fs_get_swaptype: | |
1090 | * @fs: /proc/swaps entry | |
1091 | * | |
1092 | * Returns: swap type or NULL | |
1093 | */ | |
1094 | const char *mnt_fs_get_swaptype(struct libmnt_fs *fs) | |
1095 | { | |
1096 | assert(fs); | |
1097 | return fs ? fs->swaptype : NULL; | |
1098 | } | |
1099 | ||
1100 | /** | |
1101 | * mnt_fs_get_size: | |
1102 | * @fs: /proc/swaps entry | |
1103 | * | |
1104 | * Returns: size | |
1105 | */ | |
1106 | off_t mnt_fs_get_size(struct libmnt_fs *fs) | |
1107 | { | |
1108 | assert(fs); | |
1109 | return fs ? fs->size : 0; | |
1110 | } | |
1111 | ||
1112 | /** | |
1113 | * mnt_fs_get_usedsize: | |
1114 | * @fs: /proc/swaps entry | |
1115 | * | |
1116 | * Returns: used size | |
1117 | */ | |
1118 | off_t mnt_fs_get_usedsize(struct libmnt_fs *fs) | |
1119 | { | |
1120 | assert(fs); | |
1121 | return fs ? fs->usedsize : 0; | |
1122 | } | |
1123 | ||
1124 | /** | |
1125 | * mnt_fs_get_priority: | |
1126 | * @fs: /proc/swaps entry | |
1127 | * | |
1128 | * Returns: priority | |
1129 | */ | |
1130 | int mnt_fs_get_priority(struct libmnt_fs *fs) | |
1131 | { | |
1132 | assert(fs); | |
1133 | return fs ? fs->priority : 0; | |
1134 | } | |
1135 | ||
1136 | /** | |
1137 | * mnt_fs_set_priority: | |
1138 | * @fs: /proc/swaps entry | |
1139 | * | |
1140 | * Returns: 0 or -1 in case of error | |
1141 | */ | |
1142 | int mnt_fs_set_priority(struct libmnt_fs *fs, int prio) | |
1143 | { | |
1144 | assert(fs); | |
1145 | if (!fs) | |
1146 | return -EINVAL; | |
1147 | fs->priority = prio; | |
1148 | return 0; | |
1149 | } | |
1150 | ||
dd369652 KZ |
1151 | /** |
1152 | * mnt_fs_get_bindsrc: | |
a362ae60 | 1153 | * @fs: /run/mount/utab entry |
dd369652 KZ |
1154 | * |
1155 | * Returns: full path that was used for mount(2) on MS_BIND | |
1156 | */ | |
68164f6c | 1157 | const char *mnt_fs_get_bindsrc(struct libmnt_fs *fs) |
dd369652 KZ |
1158 | { |
1159 | assert(fs); | |
1160 | return fs ? fs->bindsrc : NULL; | |
1161 | } | |
1162 | ||
1163 | /** | |
1164 | * mnt_fs_set_bindsrc: | |
1165 | * @fs: filesystem | |
1166 | * @src: path | |
1167 | * | |
1168 | * Returns: 0 on success or negative number in case of error. | |
1169 | */ | |
68164f6c | 1170 | int mnt_fs_set_bindsrc(struct libmnt_fs *fs, const char *src) |
dd369652 KZ |
1171 | { |
1172 | char *p = NULL; | |
1173 | ||
1174 | assert(fs); | |
1175 | if (!fs) | |
1176 | return -EINVAL; | |
1177 | if (src) { | |
1178 | p = strdup(src); | |
1179 | if (!p) | |
1180 | return -ENOMEM; | |
1181 | } | |
1182 | free(fs->bindsrc); | |
1183 | fs->bindsrc = p; | |
1184 | return 0; | |
1185 | } | |
1186 | ||
efe73c3e KZ |
1187 | /** |
1188 | * mnt_fs_get_id: | |
1189 | * @fs: /proc/self/mountinfo entry | |
1190 | * | |
56be757f | 1191 | * Returns: mount ID (unique identifier of the mount) or negative number in case of error. |
efe73c3e | 1192 | */ |
68164f6c | 1193 | int mnt_fs_get_id(struct libmnt_fs *fs) |
efe73c3e KZ |
1194 | { |
1195 | assert(fs); | |
56be757f | 1196 | return fs ? fs->id : -EINVAL; |
efe73c3e KZ |
1197 | } |
1198 | ||
1199 | /** | |
1200 | * mnt_fs_get_parent_id: | |
1201 | * @fs: /proc/self/mountinfo entry | |
1202 | * | |
56be757f | 1203 | * Returns: parent mount ID or negative number in case of error. |
efe73c3e | 1204 | */ |
68164f6c | 1205 | int mnt_fs_get_parent_id(struct libmnt_fs *fs) |
efe73c3e KZ |
1206 | { |
1207 | assert(fs); | |
56be757f | 1208 | return fs ? fs->parent : -EINVAL; |
efe73c3e KZ |
1209 | } |
1210 | ||
1211 | /** | |
1212 | * mnt_fs_get_devno: | |
0b3953a3 | 1213 | * @fs: /proc/self/mountinfo entry |
efe73c3e KZ |
1214 | * |
1215 | * Returns: value of st_dev for files on filesystem or 0 in case of error. | |
1216 | */ | |
68164f6c | 1217 | dev_t mnt_fs_get_devno(struct libmnt_fs *fs) |
efe73c3e KZ |
1218 | { |
1219 | assert(fs); | |
1220 | return fs ? fs->devno : 0; | |
1221 | } | |
1222 | ||
f7f29b56 KZ |
1223 | /** |
1224 | * mnt_fs_get_tid: | |
a3bb7e65 | 1225 | * @fs: /proc/tid/mountinfo entry |
f7f29b56 KZ |
1226 | * |
1227 | * Returns: TID (task ID) for filesystems read from mountinfo file | |
1228 | */ | |
1229 | pid_t mnt_fs_get_tid(struct libmnt_fs *fs) | |
1230 | { | |
1231 | assert(fs); | |
1232 | return fs ? fs->tid : 0; | |
1233 | } | |
1234 | ||
d115ee9b KZ |
1235 | /** |
1236 | * mnt_fs_get_option: | |
1237 | * @fs: fstab/mtab/mountinfo entry pointer | |
1238 | * @name: option name | |
1239 | * @value: returns pointer to the begin of the value (e.g. name=VALUE) or NULL | |
1240 | * @valsz: returns size of options value or 0 | |
1241 | * | |
56be757f | 1242 | * Returns: 0 on success, 1 when not found the @name or negative number in case of error. |
d115ee9b | 1243 | */ |
68164f6c | 1244 | int mnt_fs_get_option(struct libmnt_fs *fs, const char *name, |
d115ee9b KZ |
1245 | char **value, size_t *valsz) |
1246 | { | |
76a06ca4 KZ |
1247 | char rc = 1; |
1248 | ||
4569bbea | 1249 | assert(fs); |
ba2bdf41 KZ |
1250 | if (!fs) |
1251 | return -EINVAL; | |
76a06ca4 KZ |
1252 | if (fs->fs_optstr) |
1253 | rc = mnt_optstr_get_option(fs->fs_optstr, name, value, valsz); | |
1254 | if (rc == 1 && fs->vfs_optstr) | |
1255 | rc = mnt_optstr_get_option(fs->vfs_optstr, name, value, valsz); | |
1256 | if (rc == 1 && fs->user_optstr) | |
1257 | rc = mnt_optstr_get_option(fs->user_optstr, name, value, valsz); | |
1258 | return rc; | |
1259 | } | |
1260 | ||
1261 | /** | |
1262 | * mnt_fs_get_attribute: | |
1263 | * @fs: fstab/mtab/mountinfo entry pointer | |
1264 | * @name: option name | |
1265 | * @value: returns pointer to the begin of the value (e.g. name=VALUE) or NULL | |
1266 | * @valsz: returns size of options value or 0 | |
1267 | * | |
1268 | * Returns: 0 on success, 1 when not found the @name or negative number in case of error. | |
1269 | */ | |
68164f6c | 1270 | int mnt_fs_get_attribute(struct libmnt_fs *fs, const char *name, |
76a06ca4 KZ |
1271 | char **value, size_t *valsz) |
1272 | { | |
1273 | char rc = 1; | |
1274 | ||
4569bbea KZ |
1275 | assert(fs); |
1276 | if (!fs) | |
1277 | return -EINVAL; | |
76a06ca4 KZ |
1278 | if (fs->attrs) |
1279 | rc = mnt_optstr_get_option(fs->attrs, name, value, valsz); | |
1280 | return rc; | |
d115ee9b KZ |
1281 | } |
1282 | ||
3fca8422 KZ |
1283 | /** |
1284 | * mnt_fs_match_target: | |
1285 | * @fs: filesystem | |
1286 | * @target: mountpoint path | |
1287 | * @cache: tags/paths cache or NULL | |
1288 | * | |
1289 | * Possible are three attempts: | |
1290 | * 1) compare @target with @fs->target | |
1291 | * 2) realpath(@target) with @fs->target | |
fa705b54 KZ |
1292 | * 3) realpath(@target) with realpath(@fs->target) if @fs is not from |
1293 | * /proc/self/mountinfo. | |
3fca8422 KZ |
1294 | * |
1295 | * The 2nd and 3rd attempts are not performed when @cache is NULL. | |
1296 | * | |
192c6aad | 1297 | * Returns: 1 if @fs target is equal to @target else 0. |
3fca8422 | 1298 | */ |
16b8db49 KZ |
1299 | int mnt_fs_match_target(struct libmnt_fs *fs, const char *target, |
1300 | struct libmnt_cache *cache) | |
3fca8422 KZ |
1301 | { |
1302 | int rc = 0; | |
1303 | ||
4569bbea | 1304 | assert(fs); |
3fca8422 KZ |
1305 | if (!fs || !target || !fs->target) |
1306 | return 0; | |
1307 | ||
1308 | /* 1) native paths */ | |
6699e742 | 1309 | rc = mnt_fs_streq_target(fs, target); |
3fca8422 KZ |
1310 | |
1311 | if (!rc && cache) { | |
1312 | /* 2) - canonicalized and non-canonicalized */ | |
1313 | char *cn = mnt_resolve_path(target, cache); | |
1314 | rc = (cn && strcmp(cn, fs->target) == 0); | |
1315 | ||
1316 | /* 3) - canonicalized and canonicalized */ | |
fa705b54 | 1317 | if (!rc && cn && !mnt_fs_is_kernel(fs)) { |
3fca8422 KZ |
1318 | char *tcn = mnt_resolve_path(fs->target, cache); |
1319 | rc = (tcn && strcmp(cn, tcn) == 0); | |
1320 | } | |
1321 | } | |
1322 | ||
1323 | return rc; | |
1324 | } | |
1325 | ||
1326 | /** | |
1327 | * mnt_fs_match_source: | |
1328 | * @fs: filesystem | |
f12aac6e | 1329 | * @source: tag or path (device or so) or NULL |
3fca8422 KZ |
1330 | * @cache: tags/paths cache or NULL |
1331 | * | |
1332 | * Possible are four attempts: | |
1333 | * 1) compare @source with @fs->source | |
1334 | * 2) compare realpath(@source) with @fs->source | |
1335 | * 3) compare realpath(@source) with realpath(@fs->source) | |
1336 | * 4) compare realpath(@source) with evaluated tag from @fs->source | |
1337 | * | |
1338 | * The 2nd, 3rd and 4th attempts are not performed when @cache is NULL. The | |
1339 | * 2nd and 3rd attempts are not performed if @fs->source is tag. | |
1340 | * | |
192c6aad | 1341 | * Returns: 1 if @fs source is equal to @source else 0. |
3fca8422 | 1342 | */ |
16b8db49 KZ |
1343 | int mnt_fs_match_source(struct libmnt_fs *fs, const char *source, |
1344 | struct libmnt_cache *cache) | |
3fca8422 | 1345 | { |
3fca8422 KZ |
1346 | char *cn; |
1347 | const char *src, *t, *v; | |
1348 | ||
4569bbea | 1349 | assert(fs); |
f12aac6e KZ |
1350 | if (!fs) |
1351 | return 0; | |
1352 | ||
ab8c6e05 KZ |
1353 | /* 1) native paths... */ |
1354 | if (mnt_fs_streq_srcpath(fs, source) == 1) | |
f12aac6e KZ |
1355 | return 1; |
1356 | ||
ab8c6e05 | 1357 | if (!source || !fs->source) |
3fca8422 KZ |
1358 | return 0; |
1359 | ||
ab8c6e05 KZ |
1360 | /* ... and tags */ |
1361 | if (fs->tagname && strcmp(source, fs->source) == 0) | |
3ef87248 | 1362 | return 1; |
3fca8422 | 1363 | |
3ef87248 KZ |
1364 | if (!cache) |
1365 | return 0; | |
3fca8422 KZ |
1366 | if (fs->flags & (MNT_FS_NET | MNT_FS_PSEUDO)) |
1367 | return 0; | |
1368 | ||
1369 | cn = mnt_resolve_spec(source, cache); | |
1370 | if (!cn) | |
1371 | return 0; | |
1372 | ||
1373 | /* 2) canonicalized and native */ | |
1374 | src = mnt_fs_get_srcpath(fs); | |
ab8c6e05 | 1375 | if (src && mnt_fs_streq_srcpath(fs, cn)) |
3ef87248 | 1376 | return 1; |
3fca8422 KZ |
1377 | |
1378 | /* 3) canonicalized and canonicalized */ | |
3ef87248 | 1379 | if (src) { |
3fca8422 | 1380 | src = mnt_resolve_path(src, cache); |
3ef87248 KZ |
1381 | if (src && !strcmp(cn, src)) |
1382 | return 1; | |
3fca8422 | 1383 | } |
3ef87248 KZ |
1384 | if (src || mnt_fs_get_tag(fs, &t, &v)) |
1385 | /* src path does not match and tag is not defined */ | |
3fca8422 KZ |
1386 | return 0; |
1387 | ||
1388 | /* read @source's tags to the cache */ | |
ba7232a1 | 1389 | if (mnt_cache_read_tags(cache, cn) < 0) { |
3fca8422 KZ |
1390 | if (errno == EACCES) { |
1391 | /* we don't have permissions to read TAGs from | |
1392 | * @source, but can translate @fs tag to devname. | |
1393 | * | |
1394 | * (because libblkid uses udev symlinks and this is | |
1395 | * accessible for non-root uses) | |
1396 | */ | |
1397 | char *x = mnt_resolve_tag(t, v, cache); | |
1398 | if (x && !strcmp(x, cn)) | |
1399 | return 1; | |
1400 | } | |
1401 | return 0; | |
1402 | } | |
1403 | ||
1404 | /* 4) has the @source a tag that matches with tag from @fs ? */ | |
3ef87248 KZ |
1405 | if (mnt_cache_device_has_tag(cache, cn, t, v)) |
1406 | return 1; | |
3fca8422 | 1407 | |
3ef87248 | 1408 | return 0; |
3fca8422 KZ |
1409 | } |
1410 | ||
1411 | /** | |
1412 | * mnt_fs_match_fstype: | |
1413 | * @fs: filesystem | |
1414 | * @types: filesystem name or comma delimited list of filesystems | |
1415 | * | |
1416 | * For more details see mnt_match_fstype(). | |
1417 | * | |
192c6aad | 1418 | * Returns: 1 if @fs type is matching to @types else 0. The function returns |
3fca8422 KZ |
1419 | * 0 when types is NULL. |
1420 | */ | |
68164f6c | 1421 | int mnt_fs_match_fstype(struct libmnt_fs *fs, const char *types) |
3fca8422 | 1422 | { |
4569bbea | 1423 | assert(fs); |
3fca8422 KZ |
1424 | return mnt_match_fstype(fs->fstype, types); |
1425 | } | |
1426 | ||
1427 | /** | |
1428 | * mnt_fs_match_options: | |
1429 | * @fs: filesystem | |
1430 | * @options: comma delimited list of options (and nooptions) | |
1431 | * | |
1432 | * For more details see mnt_match_options(). | |
1433 | * | |
192c6aad | 1434 | * Returns: 1 if @fs type is matching to @options else 0. The function returns |
3fca8422 KZ |
1435 | * 0 when types is NULL. |
1436 | */ | |
68164f6c | 1437 | int mnt_fs_match_options(struct libmnt_fs *fs, const char *options) |
3fca8422 | 1438 | { |
4569bbea | 1439 | assert(fs); |
d84508cf | 1440 | return mnt_match_options(mnt_fs_get_options(fs), options); |
3fca8422 KZ |
1441 | } |
1442 | ||
d115ee9b KZ |
1443 | /** |
1444 | * mnt_fs_print_debug | |
1445 | * @fs: fstab/mtab/mountinfo entry | |
486d3972 | 1446 | * @file: file stream |
d115ee9b | 1447 | * |
56be757f | 1448 | * Returns: 0 on success or negative number in case of error. |
d115ee9b | 1449 | */ |
68164f6c | 1450 | int mnt_fs_print_debug(struct libmnt_fs *fs, FILE *file) |
d115ee9b | 1451 | { |
4569bbea | 1452 | if (!fs || !file) |
56be757f | 1453 | return -EINVAL; |
d115ee9b | 1454 | fprintf(file, "------ fs: %p\n", fs); |
77417bc0 KZ |
1455 | fprintf(file, "source: %s\n", mnt_fs_get_source(fs)); |
1456 | fprintf(file, "target: %s\n", mnt_fs_get_target(fs)); | |
1457 | fprintf(file, "fstype: %s\n", mnt_fs_get_fstype(fs)); | |
76a06ca4 | 1458 | |
f2b3a3a3 KZ |
1459 | if (mnt_fs_get_options(fs)) |
1460 | fprintf(file, "optstr: %s\n", mnt_fs_get_options(fs)); | |
76a06ca4 KZ |
1461 | if (mnt_fs_get_vfs_options(fs)) |
1462 | fprintf(file, "VFS-optstr: %s\n", mnt_fs_get_vfs_options(fs)); | |
1463 | if (mnt_fs_get_fs_options(fs)) | |
1464 | fprintf(file, "FS-opstr: %s\n", mnt_fs_get_fs_options(fs)); | |
68164f6c KZ |
1465 | if (mnt_fs_get_user_options(fs)) |
1466 | fprintf(file, "user-optstr: %s\n", mnt_fs_get_user_options(fs)); | |
e47a1931 OO |
1467 | if (mnt_fs_get_optional_fields(fs)) |
1468 | fprintf(file, "optional-fields: '%s'\n", mnt_fs_get_optional_fields(fs)); | |
76a06ca4 KZ |
1469 | if (mnt_fs_get_attributes(fs)) |
1470 | fprintf(file, "attributes: %s\n", mnt_fs_get_attributes(fs)); | |
dd369652 KZ |
1471 | |
1472 | if (mnt_fs_get_root(fs)) | |
77417bc0 | 1473 | fprintf(file, "root: %s\n", mnt_fs_get_root(fs)); |
ce4dd666 KZ |
1474 | |
1475 | if (mnt_fs_get_swaptype(fs)) | |
1476 | fprintf(file, "swaptype: %s\n", mnt_fs_get_swaptype(fs)); | |
1477 | if (mnt_fs_get_size(fs)) | |
1478 | fprintf(file, "size: %jd\n", mnt_fs_get_size(fs)); | |
1479 | if (mnt_fs_get_usedsize(fs)) | |
1480 | fprintf(file, "usedsize: %jd\n", mnt_fs_get_usedsize(fs)); | |
1481 | if (mnt_fs_get_priority(fs)) | |
1482 | fprintf(file, "priority: %d\n", mnt_fs_get_priority(fs)); | |
1483 | ||
dd369652 KZ |
1484 | if (mnt_fs_get_bindsrc(fs)) |
1485 | fprintf(file, "bindsrc: %s\n", mnt_fs_get_bindsrc(fs)); | |
9dd75aa6 | 1486 | if (mnt_fs_get_freq(fs)) |
77417bc0 | 1487 | fprintf(file, "freq: %d\n", mnt_fs_get_freq(fs)); |
9dd75aa6 | 1488 | if (mnt_fs_get_passno(fs)) |
77417bc0 | 1489 | fprintf(file, "pass: %d\n", mnt_fs_get_passno(fs)); |
9dd75aa6 | 1490 | if (mnt_fs_get_id(fs)) |
77417bc0 | 1491 | fprintf(file, "id: %d\n", mnt_fs_get_id(fs)); |
9dd75aa6 | 1492 | if (mnt_fs_get_parent_id(fs)) |
77417bc0 | 1493 | fprintf(file, "parent: %d\n", mnt_fs_get_parent_id(fs)); |
9dd75aa6 | 1494 | if (mnt_fs_get_devno(fs)) |
77417bc0 | 1495 | fprintf(file, "devno: %d:%d\n", major(mnt_fs_get_devno(fs)), |
f7f29b56 KZ |
1496 | minor(mnt_fs_get_devno(fs))); |
1497 | if (mnt_fs_get_tid(fs)) | |
1498 | fprintf(file, "tid: %d\n", mnt_fs_get_tid(fs)); | |
1499 | ||
d115ee9b KZ |
1500 | return 0; |
1501 | } | |
8b95253f KZ |
1502 | |
1503 | /** | |
1504 | * mnt_free_mntent: | |
1505 | * @mnt: mount entry | |
1506 | * | |
1507 | * Deallocates "mntent.h" mount entry. | |
1508 | */ | |
1509 | void mnt_free_mntent(struct mntent *mnt) | |
1510 | { | |
1511 | if (mnt) { | |
1512 | free(mnt->mnt_fsname); | |
1513 | free(mnt->mnt_dir); | |
1514 | free(mnt->mnt_type); | |
1515 | free(mnt->mnt_opts); | |
1516 | free(mnt); | |
1517 | } | |
1518 | } | |
1519 | ||
1520 | /** | |
1521 | * mnt_fs_to_mntent: | |
1522 | * @fs: filesystem | |
1523 | * @mnt: mount description (as described in mntent.h) | |
1524 | * | |
1525 | * Copies information from @fs to struct mntent @mnt. If @mnt is already set | |
1526 | * then the struct mntent items are reallocated and updated. See also | |
1527 | * mnt_free_mntent(). | |
1528 | * | |
1529 | * Returns: 0 on success and negative number in case of error. | |
1530 | */ | |
68164f6c | 1531 | int mnt_fs_to_mntent(struct libmnt_fs *fs, struct mntent **mnt) |
8b95253f KZ |
1532 | { |
1533 | int rc; | |
1534 | struct mntent *m; | |
1535 | ||
4569bbea KZ |
1536 | assert(fs); |
1537 | assert(mnt); | |
8b95253f KZ |
1538 | if (!fs || !mnt) |
1539 | return -EINVAL; | |
1540 | ||
1541 | m = *mnt; | |
1542 | if (!m) { | |
1543 | m = calloc(1, sizeof(*m)); | |
1544 | if (!m) | |
1545 | return -ENOMEM; | |
1546 | } | |
1547 | ||
309139c7 | 1548 | if ((rc = update_str(&m->mnt_fsname, mnt_fs_get_source(fs)))) |
8b95253f | 1549 | goto err; |
309139c7 | 1550 | if ((rc = update_str(&m->mnt_dir, mnt_fs_get_target(fs)))) |
8b95253f | 1551 | goto err; |
309139c7 | 1552 | if ((rc = update_str(&m->mnt_type, mnt_fs_get_fstype(fs)))) |
8b95253f | 1553 | goto err; |
76a06ca4 KZ |
1554 | |
1555 | errno = 0; | |
1556 | m->mnt_opts = mnt_fs_strdup_options(fs); | |
1557 | if (!m->mnt_opts && errno) { | |
1558 | rc = -errno; | |
8b95253f | 1559 | goto err; |
76a06ca4 KZ |
1560 | } |
1561 | ||
8b95253f KZ |
1562 | m->mnt_freq = mnt_fs_get_freq(fs); |
1563 | m->mnt_passno = mnt_fs_get_passno(fs); | |
1564 | ||
de511a88 KZ |
1565 | if (!m->mnt_fsname) { |
1566 | m->mnt_fsname = strdup("none"); | |
1567 | if (!m->mnt_fsname) | |
1568 | goto err; | |
1569 | } | |
8b95253f KZ |
1570 | *mnt = m; |
1571 | ||
1572 | return 0; | |
1573 | err: | |
1574 | if (m != *mnt) | |
1575 | mnt_free_mntent(m); | |
1576 | return rc; | |
1577 | } |