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