~ubuntu-branches/ubuntu/trusty/util-linux/trusty-proposed

« back to all changes in this revision

Viewing changes to libmount/src/fs.c

  • Committer: Package Import Robot
  • Author(s): LaMont Jones
  • Date: 2011-11-03 15:38:23 UTC
  • mto: (4.5.5 sid) (1.6.4)
  • mto: This revision was merged to the branch mainline in revision 85.
  • Revision ID: package-import@ubuntu.com-20111103153823-10sx16jprzxlhkqf
ImportĀ upstreamĀ versionĀ 2.20.1

Show diffs side-by-side

added added

removed removed

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