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

« back to all changes in this revision

Viewing changes to libmount/src/context.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) 2010 Karel Zak <kzak@redhat.com>
 
3
 *
 
4
 * This file may be redistributed under the terms of the
 
5
 * GNU Lesser General Public License.
 
6
 */
 
7
 
 
8
/**
 
9
 * SECTION: context
 
10
 * @title: Library high-level context
 
11
 * @short_description: high-level API to mount/umount devices.
 
12
 *
 
13
 * <informalexample>
 
14
 *   <programlisting>
 
15
 *      struct libmnt_context *cxt = mnt_new_context();
 
16
 *
 
17
 *      mnt_context_set_options(cxt, "aaa,bbb,ccc=CCC");
 
18
 *      mnt_context_set_mflags(cxt, MS_NOATIME|MS_NOEXEC);
 
19
 *      mnt_context_set_target(cxt, "/mnt/foo");
 
20
 *
 
21
 *      if (!mnt_context_mount(cxt))
 
22
 *              printf("successfully mounted\n");
 
23
 *      mnt_free_context(cxt);
 
24
 *
 
25
 *   </programlisting>
 
26
 * </informalexample>
 
27
 *
 
28
 * This code is similar to:
 
29
 *
 
30
 *   mount -o aaa,bbb,ccc=CCC,noatime,noexec /mnt/foo
 
31
 *
 
32
 */
 
33
 
 
34
#include "mountP.h"
 
35
 
 
36
/**
 
37
 * mnt_new_context:
 
38
 *
 
39
 * Returns: newly allocated mount context
 
40
 */
 
41
struct libmnt_context *mnt_new_context(void)
 
42
{
 
43
        struct libmnt_context *cxt;
 
44
        uid_t ruid, euid;
 
45
 
 
46
        cxt = calloc(1, sizeof(*cxt));
 
47
        if (!cxt)
 
48
                return NULL;
 
49
 
 
50
        ruid = getuid();
 
51
        euid = geteuid();
 
52
 
 
53
        cxt->syscall_status = 1;        /* not called yet */
 
54
        cxt->helper_exec_status = 1;
 
55
        cxt->loopdev_fd = -1;
 
56
 
 
57
        /* if we're really root and aren't running setuid */
 
58
        cxt->restricted = (uid_t) 0 == ruid && ruid == euid ? 0 : 1;
 
59
 
 
60
        DBG(CXT, mnt_debug_h(cxt, "----> allocate %s",
 
61
                                cxt->restricted ? "[RESTRICTED]" : ""));
 
62
 
 
63
        mnt_has_regular_mtab(&cxt->mtab_path, &cxt->mtab_writable);
 
64
 
 
65
        if (!cxt->mtab_writable)
 
66
                /* use /run/mount/utab if /etc/mtab is useless */
 
67
                mnt_has_regular_utab(&cxt->utab_path, &cxt->utab_writable);
 
68
 
 
69
        return cxt;
 
70
}
 
71
 
 
72
/**
 
73
 * mnt_free_context:
 
74
 * @cxt: mount context
 
75
 *
 
76
 * Deallocates context struct.
 
77
 */
 
78
void mnt_free_context(struct libmnt_context *cxt)
 
79
{
 
80
        if (!cxt)
 
81
                return;
 
82
 
 
83
        mnt_reset_context(cxt);
 
84
 
 
85
        free(cxt->fstype_pattern);
 
86
        free(cxt->optstr_pattern);
 
87
 
 
88
        if (!(cxt->flags & MNT_FL_EXTERN_FSTAB))
 
89
                mnt_free_table(cxt->fstab);
 
90
        if (!(cxt->flags & MNT_FL_EXTERN_CACHE))
 
91
                mnt_free_cache(cxt->cache);
 
92
 
 
93
        mnt_context_clear_loopdev(cxt);
 
94
        mnt_free_lock(cxt->lock);
 
95
        mnt_free_update(cxt->update);
 
96
 
 
97
        DBG(CXT, mnt_debug_h(cxt, "<---- free"));
 
98
        free(cxt);
 
99
}
 
100
 
 
101
/**
 
102
 * mnt_reset_context:
 
103
 * @cxt: mount context
 
104
 *
 
105
 * Resets all information in the context that are directly related to
 
106
 * the latest mount (spec, source, target, mount options, ....)
 
107
 *
 
108
 * The match patters, cached fstab, cached canonicalized paths and tags and
 
109
 * [e]uid are not reseted. You have to use
 
110
 *
 
111
 *      mnt_context_set_fstab(cxt, NULL);
 
112
 *      mnt_context_set_cache(cxt, NULL);
 
113
 *      mnt_context_set_fstype_pattern(cxt, NULL);
 
114
 *      mnt_context_set_options_pattern(cxt, NULL);
 
115
 *
 
116
 *
 
117
 * to reset these stuff.
 
118
 *
 
119
 * Returns: 0 on success, negative number in case of error.
 
120
 */
 
121
int mnt_reset_context(struct libmnt_context *cxt)
 
122
{
 
123
        int fl;
 
124
 
 
125
        if (!cxt)
 
126
                return -EINVAL;
 
127
 
 
128
        DBG(CXT, mnt_debug_h(cxt, "<---- reset [status=%d] ---->",
 
129
                                mnt_context_get_status(cxt)));
 
130
 
 
131
        fl = cxt->flags;
 
132
 
 
133
        if (!(cxt->flags & MNT_FL_EXTERN_FS))
 
134
                mnt_free_fs(cxt->fs);
 
135
 
 
136
        mnt_free_table(cxt->mtab);
 
137
 
 
138
        free(cxt->helper);
 
139
        free(cxt->orig_user);
 
140
 
 
141
        cxt->fs = NULL;
 
142
        cxt->mtab = NULL;
 
143
        cxt->ambi = 0;
 
144
        cxt->helper = NULL;
 
145
        cxt->orig_user = NULL;
 
146
        cxt->mountflags = 0;
 
147
        cxt->user_mountflags = 0;
 
148
        cxt->mountdata = NULL;
 
149
        cxt->flags = MNT_FL_DEFAULT;
 
150
        cxt->syscall_status = 1;
 
151
        cxt->helper_exec_status = 1;
 
152
        cxt->helper_status = 0;
 
153
 
 
154
        /* restore non-resetable flags */
 
155
        cxt->flags |= (fl & MNT_FL_EXTERN_FSTAB);
 
156
        cxt->flags |= (fl & MNT_FL_EXTERN_CACHE);
 
157
        cxt->flags |= (fl & MNT_FL_NOMTAB);
 
158
        cxt->flags |= (fl & MNT_FL_FAKE);
 
159
        cxt->flags |= (fl & MNT_FL_SLOPPY);
 
160
        cxt->flags |= (fl & MNT_FL_VERBOSE);
 
161
        cxt->flags |= (fl & MNT_FL_NOHELPERS);
 
162
        cxt->flags |= (fl & MNT_FL_LOOPDEL);
 
163
        cxt->flags |= (fl & MNT_FL_LAZY);
 
164
        cxt->flags |= (fl & MNT_FL_FORCE);
 
165
        cxt->flags |= (fl & MNT_FL_NOCANONICALIZE);
 
166
        cxt->flags |= (fl & MNT_FL_RDONLY_UMOUNT);
 
167
        return 0;
 
168
}
 
169
 
 
170
static int set_flag(struct libmnt_context *cxt, int flag, int enable)
 
171
{
 
172
        if (!cxt)
 
173
                return -EINVAL;
 
174
        if (enable)
 
175
                cxt->flags |= flag;
 
176
        else
 
177
                cxt->flags &= ~flag;
 
178
        return 0;
 
179
}
 
180
 
 
181
/**
 
182
 * mnt_context_is_restricted:
 
183
 * @cxt: mount context
 
184
 *
 
185
 * Returns: 0 for unrestricted mount (user is root), or 1 for non-root mounts
 
186
 */
 
187
int mnt_context_is_restricted(struct libmnt_context *cxt)
 
188
{
 
189
        assert(cxt);
 
190
        return cxt->restricted;
 
191
}
 
192
 
 
193
/**
 
194
 * mnt_context_set_optsmode
 
195
 * @cxt: mount context
 
196
 * @mode: mask, see MNT_OMASK_* flags in libmount mount.h
 
197
 *
 
198
 * Controls how to use mount options from fstab/mtab.
 
199
 *
 
200
 * Returns: 0 on success, negative number in case of error.
 
201
 */
 
202
int mnt_context_set_optsmode(struct libmnt_context *cxt, int mode)
 
203
{
 
204
        if (!cxt)
 
205
                return -EINVAL;
 
206
        cxt->optsmode = mode;
 
207
        return 0;
 
208
}
 
209
 
 
210
/**
 
211
 * mnt_context_get_optsmode
 
212
 * @cxt: mount context
 
213
 *
 
214
 * Returns: MNT_OMASK_* mask or zero.
 
215
 */
 
216
 
 
217
int mnt_context_get_optsmode(struct libmnt_context *cxt)
 
218
{
 
219
        return cxt ? cxt->optsmode : 0;
 
220
}
 
221
 
 
222
/**
 
223
 * mnt_context_disable_canonicalize:
 
224
 * @cxt: mount context
 
225
 * @disable: TRUE or FALSE
 
226
 *
 
227
 * Enable/disable paths canonicalization and tags evaluation. The libmount context
 
228
 * canonicalies paths when search in fstab and when prepare source and target paths
 
229
 * for mount(2) syscall.
 
230
 *
 
231
 * This fuction has effect to the private fstab instance only (see
 
232
 * mnt_context_set_fstab()). If you want to use an external fstab then you need
 
233
 * manage your private struct libmnt_cache (see mnt_table_set_cache(fstab, NULL).
 
234
 *
 
235
 * Returns: 0 on success, negative number in case of error.
 
236
 */
 
237
int mnt_context_disable_canonicalize(struct libmnt_context *cxt, int disable)
 
238
{
 
239
        return set_flag(cxt, MNT_FL_NOCANONICALIZE, disable);
 
240
}
 
241
 
 
242
/**
 
243
 * mnt_context_enable_lazy:
 
244
 * @cxt: mount context
 
245
 * @enable: TRUE or FALSE
 
246
 *
 
247
 * Enable/disable lazy umount (see umount(8) man page, option -l).
 
248
 *
 
249
 * Returns: 0 on success, negative number in case of error.
 
250
 */
 
251
int mnt_context_enable_lazy(struct libmnt_context *cxt, int enable)
 
252
{
 
253
        return set_flag(cxt, MNT_FL_LAZY, enable);
 
254
}
 
255
 
 
256
/**
 
257
 * mnt_context_is_lazy:
 
258
 * @cxt: mount context
 
259
 *
 
260
 * Returns: 1 if lazy umount is enabled or 0
 
261
 */
 
262
int mnt_context_is_lazy(struct libmnt_context *cxt)
 
263
{
 
264
        return cxt && (cxt->flags & MNT_FL_LAZY) ? 1 : 0;
 
265
}
 
266
 
 
267
 
 
268
/**
 
269
 * mnt_context_enable_rdonly_umount:
 
270
 * @cxt: mount context
 
271
 * @enable: TRUE or FALSE
 
272
 *
 
273
 * Enable/disable read-only remount on failed umount(2)
 
274
 * (see umount(8) man page, option -r).
 
275
 *
 
276
 * Returns: 0 on success, negative number in case of error.
 
277
 */
 
278
int mnt_context_enable_rdonly_umount(struct libmnt_context *cxt, int enable)
 
279
{
 
280
        return set_flag(cxt, MNT_FL_RDONLY_UMOUNT, enable);
 
281
}
 
282
 
 
283
/**
 
284
 * mnt_context_is_rdonly_umount
 
285
 * @cxt: mount context
 
286
 *
 
287
 * See also mnt_context_enable_rdonly_umount() and see umount(8) man page,
 
288
 * option -r.
 
289
 *
 
290
 * Returns: 1 if read-only remount failed umount(2) is enables or 0
 
291
 */
 
292
int mnt_context_is_rdonly_umount(struct libmnt_context *cxt)
 
293
{
 
294
        return cxt && (cxt->flags & MNT_FL_RDONLY_UMOUNT) ? 1 : 0;
 
295
}
 
296
 
 
297
/**
 
298
 * mnt_context_disable_helpers:
 
299
 * @cxt: mount context
 
300
 * @disable: TRUE or FALSE
 
301
 *
 
302
 * Enable/disable /sbin/[u]mount.* helpers (see mount(8) man page, option -i).
 
303
 *
 
304
 * Returns: 0 on success, negative number in case of error.
 
305
 */
 
306
int mnt_context_disable_helpers(struct libmnt_context *cxt, int disable)
 
307
{
 
308
        return set_flag(cxt, MNT_FL_NOHELPERS, disable);
 
309
}
 
310
 
 
311
/**
 
312
 * mnt_context_enable_sloppy:
 
313
 * @cxt: mount context
 
314
 * @enable: TRUE or FALSE
 
315
 *
 
316
 * Set/unset sloppy mounting (see mount(8) man page, option -s).
 
317
 *
 
318
 * Returns: 0 on success, negative number in case of error.
 
319
 */
 
320
int mnt_context_enable_sloppy(struct libmnt_context *cxt, int enable)
 
321
{
 
322
        return set_flag(cxt, MNT_FL_SLOPPY, enable);
 
323
}
 
324
 
 
325
/**
 
326
 * mnt_context_is_sloppy:
 
327
 * @cxt: mount context
 
328
 *
 
329
 * Returns: 1 if sloppy flag is enabled or 0
 
330
 */
 
331
int mnt_context_is_sloppy(struct libmnt_context *cxt)
 
332
{
 
333
        return cxt && (cxt->flags & MNT_FL_SLOPPY) ? 1 : 0;
 
334
}
 
335
 
 
336
/**
 
337
 * mnt_context_enable_fake:
 
338
 * @cxt: mount context
 
339
 * @enable: TRUE or FALSE
 
340
 *
 
341
 * Enable/disable fake mounting (see mount(8) man page, option -f).
 
342
 *
 
343
 * Returns: 0 on success, negative number in case of error.
 
344
 */
 
345
int mnt_context_enable_fake(struct libmnt_context *cxt, int enable)
 
346
{
 
347
        return set_flag(cxt, MNT_FL_FAKE, enable);
 
348
}
 
349
 
 
350
/**
 
351
 * mnt_context_is_fake:
 
352
 * @cxt: mount context
 
353
 *
 
354
 * Returns: 1 if fake flag is enabled or 0
 
355
 */
 
356
int mnt_context_is_fake(struct libmnt_context *cxt)
 
357
{
 
358
        return cxt && (cxt->flags & MNT_FL_FAKE) ? 1 : 0;
 
359
}
 
360
 
 
361
/**
 
362
 * mnt_context_disable_mtab:
 
363
 * @cxt: mount context
 
364
 * @disable: TRUE or FALSE
 
365
 *
 
366
 * Disable/enable mtab update (see mount(8) man page, option -n).
 
367
 *
 
368
 * Returns: 0 on success, negative number in case of error.
 
369
 */
 
370
int mnt_context_disable_mtab(struct libmnt_context *cxt, int disable)
 
371
{
 
372
        return set_flag(cxt, MNT_FL_NOMTAB, disable);
 
373
}
 
374
 
 
375
/**
 
376
 * mnt_context_is_nomtab
 
377
 * @cxt: mount context
 
378
 *
 
379
 * Returns: 1 if no-mtab is enabled or 0
 
380
 */
 
381
int mnt_context_is_nomtab(struct libmnt_context *cxt)
 
382
{
 
383
        return cxt && (cxt->flags & MNT_FL_NOMTAB) ? 1 : 0;
 
384
}
 
385
 
 
386
/**
 
387
 * mnt_context_enable_force:
 
388
 * @cxt: mount context
 
389
 * @enable: TRUE or FALSE
 
390
 *
 
391
 * Enable/disable force umounting (see umount(8) man page, option -f).
 
392
 *
 
393
 * Returns: 0 on success, negative number in case of error.
 
394
 */
 
395
int mnt_context_enable_force(struct libmnt_context *cxt, int enable)
 
396
{
 
397
        return set_flag(cxt, MNT_FL_FORCE, enable);
 
398
}
 
399
 
 
400
/**
 
401
 * mnt_context_is_force
 
402
 * @cxt: mount context
 
403
 *
 
404
 * Returns: 1 if force umounting flag is enabled or 0
 
405
 */
 
406
int mnt_context_is_force(struct libmnt_context *cxt)
 
407
{
 
408
        return cxt && (cxt->flags & MNT_FL_FORCE) ? 1 : 0;
 
409
}
 
410
 
 
411
/**
 
412
 * mnt_context_enable_verbose:
 
413
 * @cxt: mount context
 
414
 * @enable: TRUE or FALSE
 
415
 *
 
416
 * Enable/disable verbose output (TODO: not implemented yet)
 
417
 *
 
418
 * Returns: 0 on success, negative number in case of error.
 
419
 */
 
420
int mnt_context_enable_verbose(struct libmnt_context *cxt, int enable)
 
421
{
 
422
        return set_flag(cxt, MNT_FL_VERBOSE, enable);
 
423
}
 
424
 
 
425
/**
 
426
 * mnt_context_is_verbose
 
427
 * @cxt: mount context
 
428
 *
 
429
 * Returns: 1 if verbose flag is enabled or 0
 
430
 */
 
431
int mnt_context_is_verbose(struct libmnt_context *cxt)
 
432
{
 
433
        return cxt && (cxt->flags & MNT_FL_VERBOSE) ? 1 : 0;
 
434
}
 
435
 
 
436
/**
 
437
 * mnt_context_enable_loopdel:
 
438
 * @cxt: mount context
 
439
 * @enable: TRUE or FALSE
 
440
 *
 
441
 * Enable/disable loop delete (destroy) after umount (see umount(8), option -d)
 
442
 *
 
443
 * Returns: 0 on success, negative number in case of error.
 
444
 */
 
445
int mnt_context_enable_loopdel(struct libmnt_context *cxt, int enable)
 
446
{
 
447
        return set_flag(cxt, MNT_FL_LOOPDEL, enable);
 
448
}
 
449
 
 
450
/**
 
451
 * mnt_context_set_fs:
 
452
 * @cxt: mount context
 
453
 * @fs: filesystem description
 
454
 *
 
455
 * The mount context uses private @fs by default. This function allows to
 
456
 * overwrite the private @fs with an external instance. Note that the external
 
457
 * @fs instance is not deallocated by mnt_free_context() or mnt_reset_context().
 
458
 *
 
459
 * The @fs will be modified by mnt_context_set_{source,target,options,fstype}
 
460
 * functions, If the @fs is NULL then all current FS specific setting (source,
 
461
 * target, etc., exclude spec) is reseted.
 
462
 *
 
463
 * Returns: 0 on success, negative number in case of error.
 
464
 */
 
465
int mnt_context_set_fs(struct libmnt_context *cxt, struct libmnt_fs *fs)
 
466
{
 
467
        if (!cxt)
 
468
                return -EINVAL;
 
469
        if (!(cxt->flags & MNT_FL_EXTERN_FS))
 
470
                mnt_free_fs(cxt->fs);
 
471
 
 
472
        set_flag(cxt, MNT_FL_EXTERN_FS, fs != NULL);
 
473
        cxt->fs = fs;
 
474
        return 0;
 
475
}
 
476
 
 
477
/**
 
478
 * mnt_context_get_fs:
 
479
 * @cxt: mount context
 
480
 *
 
481
 * The FS contains the basic description of mountpoint, fs type and so on.
 
482
 * Note that the FS is modified by mnt_context_set_{source,target,options,fstype}
 
483
 * functions.
 
484
 *
 
485
 * Returns: pointer to FS description or NULL in case of calloc() errrr.
 
486
 */
 
487
struct libmnt_fs *mnt_context_get_fs(struct libmnt_context *cxt)
 
488
{
 
489
        if (!cxt)
 
490
                return NULL;
 
491
        if (!cxt->fs) {
 
492
                cxt->fs = mnt_new_fs();
 
493
                cxt->flags &= ~MNT_FL_EXTERN_FS;
 
494
        }
 
495
        return cxt->fs;
 
496
}
 
497
 
 
498
/**
 
499
 * mnt_context_set_source:
 
500
 * @cxt: mount context
 
501
 * @source: mount source (device, directory, UUID, LABEL, ...)
 
502
 *
 
503
 * Returns: 0 on success, negative number in case of error.
 
504
 */
 
505
int mnt_context_set_source(struct libmnt_context *cxt, const char *source)
 
506
{
 
507
        return mnt_fs_set_source(mnt_context_get_fs(cxt), source);
 
508
}
 
509
 
 
510
/**
 
511
 * mnt_context_get_source:
 
512
 * @cxt: mount context
 
513
 *
 
514
 * Returns: returns pointer or NULL in case of error pr if not set.
 
515
 */
 
516
const char *mnt_context_get_source(struct libmnt_context *cxt)
 
517
{
 
518
        return mnt_fs_get_source(mnt_context_get_fs(cxt));
 
519
}
 
520
 
 
521
/**
 
522
 * mnt_context_set_target:
 
523
 * @cxt: mount context
 
524
 * @target: mountpoint
 
525
 *
 
526
 * Returns: 0 on success, negative number in case of error.
 
527
 */
 
528
int mnt_context_set_target(struct libmnt_context *cxt, const char *target)
 
529
{
 
530
        return mnt_fs_set_target(mnt_context_get_fs(cxt), target);
 
531
}
 
532
 
 
533
/**
 
534
 * mnt_context_get_target:
 
535
 * @cxt: mount context
 
536
 *
 
537
 * Returns: returns pointer or NULL in case of error pr if not set.
 
538
 */
 
539
const char *mnt_context_get_target(struct libmnt_context *cxt)
 
540
{
 
541
        return mnt_fs_get_target(mnt_context_get_fs(cxt));
 
542
}
 
543
 
 
544
/**
 
545
 * mnt_context_set_fstype:
 
546
 * @cxt: mount context
 
547
 * @fstype: filesystem type
 
548
 *
 
549
 * Note that the @fstype has to be the real FS type. For comma-separated list of
 
550
 * filesystems or for "nofs" notation use mnt_context_set_fstype_pattern().
 
551
 *
 
552
 * Returns: 0 on success, negative number in case of error.
 
553
 */
 
554
int mnt_context_set_fstype(struct libmnt_context *cxt, const char *fstype)
 
555
{
 
556
        if (fstype && strchr(fstype, ','))
 
557
                return -EINVAL;
 
558
        return mnt_fs_set_fstype(mnt_context_get_fs(cxt), fstype);
 
559
}
 
560
 
 
561
/**
 
562
 * mnt_context_get_fstype:
 
563
 * @cxt: mount context
 
564
 *
 
565
 * Returns: returns pointer or NULL in case of error pr if not set.
 
566
 */
 
567
const char *mnt_context_get_fstype(struct libmnt_context *cxt)
 
568
{
 
569
        return mnt_fs_get_fstype(mnt_context_get_fs(cxt));
 
570
}
 
571
 
 
572
/**
 
573
 * mnt_context_set_options:
 
574
 * @cxt: mount context
 
575
 * @optstr: comma delimited mount options
 
576
 *
 
577
 * Returns: 0 on success, negative number in case of error.
 
578
 */
 
579
int mnt_context_set_options(struct libmnt_context *cxt, const char *optstr)
 
580
{
 
581
        return mnt_fs_set_options(mnt_context_get_fs(cxt), optstr);
 
582
}
 
583
 
 
584
/**
 
585
 * mnt_context_append_options:
 
586
 * @cxt: mount context
 
587
 * @optstr: comma delimited mount options
 
588
 *
 
589
 * Returns: 0 on success, negative number in case of error.
 
590
 */
 
591
int mnt_context_append_options(struct libmnt_context *cxt, const char *optstr)
 
592
{
 
593
        return mnt_fs_append_options(mnt_context_get_fs(cxt), optstr);
 
594
}
 
595
 
 
596
/**
 
597
 * mnt_context_set_fstype_pattern:
 
598
 * @cxt: mount context
 
599
 * @pattern: FS name pattern (or NULL to reset the current setting)
 
600
 *
 
601
 * See mount(8), option -t.
 
602
 *
 
603
 * Returns: 0 on success, negative number in case of error.
 
604
 */
 
605
int mnt_context_set_fstype_pattern(struct libmnt_context *cxt, const char *pattern)
 
606
{
 
607
        char *p = NULL;
 
608
 
 
609
        if (!cxt)
 
610
                return -EINVAL;
 
611
        if (pattern) {
 
612
                p = strdup(pattern);
 
613
                if (!p)
 
614
                        return -ENOMEM;
 
615
        }
 
616
        free(cxt->fstype_pattern);
 
617
        cxt->fstype_pattern = p;
 
618
        return 0;
 
619
}
 
620
 
 
621
/**
 
622
 * mnt_context_set_options_pattern:
 
623
 * @cxt: mount context
 
624
 * @pattern: options pattern (or NULL to reset the current setting)
 
625
 *
 
626
 * See mount(8), option -O.
 
627
 *
 
628
 * Returns: 0 on success, negative number in case of error.
 
629
 */
 
630
int mnt_context_set_options_pattern(struct libmnt_context *cxt, const char *pattern)
 
631
{
 
632
        char *p = NULL;
 
633
 
 
634
        if (!cxt)
 
635
                return -EINVAL;
 
636
        if (pattern) {
 
637
                p = strdup(pattern);
 
638
                if (!p)
 
639
                        return -ENOMEM;
 
640
        }
 
641
        free(cxt->optstr_pattern);
 
642
        cxt->optstr_pattern = p;
 
643
        return 0;
 
644
}
 
645
 
 
646
/**
 
647
 * mnt_context_set_fstab:
 
648
 * @cxt: mount context
 
649
 * @tb: fstab
 
650
 *
 
651
 * The mount context reads /etc/fstab to the the private struct libmnt_table by default.
 
652
 * This function allows to overwrite the private fstab with an external
 
653
 * instance. Note that the external instance is not deallocated by mnt_free_context().
 
654
 *
 
655
 * The fstab is used read-only and is not modified, it should be possible to
 
656
 * share the fstab between more mount contexts (TODO: tests it.)
 
657
 *
 
658
 * If the @tb argument is NULL then the current private fstab instance is
 
659
 * reseted.
 
660
 *
 
661
 * Returns: 0 on success, negative number in case of error.
 
662
 */
 
663
int mnt_context_set_fstab(struct libmnt_context *cxt, struct libmnt_table *tb)
 
664
{
 
665
        if (!cxt)
 
666
                return -EINVAL;
 
667
        if (!(cxt->flags & MNT_FL_EXTERN_FSTAB))
 
668
                mnt_free_table(cxt->fstab);
 
669
 
 
670
        set_flag(cxt, MNT_FL_EXTERN_FSTAB, tb != NULL);
 
671
        cxt->fstab = tb;
 
672
        return 0;
 
673
}
 
674
 
 
675
/**
 
676
 * mnt_context_get_fstab:
 
677
 * @cxt: mount context
 
678
 * @tb: returns fstab
 
679
 *
 
680
 * See also mnt_table_parse_fstab() for more details about fstab.
 
681
 *
 
682
 * Returns: 0 on success, negative number in case of error.
 
683
 */
 
684
int mnt_context_get_fstab(struct libmnt_context *cxt, struct libmnt_table **tb)
 
685
{
 
686
        struct libmnt_cache *cache;
 
687
 
 
688
        if (!cxt)
 
689
                return -EINVAL;
 
690
 
 
691
        if (!cxt->fstab) {
 
692
                int rc;
 
693
 
 
694
                cxt->fstab = mnt_new_table();
 
695
                if (!cxt->fstab)
 
696
                        return -ENOMEM;
 
697
                if (cxt->table_errcb)
 
698
                        mnt_table_set_parser_errcb(cxt->fstab, cxt->table_errcb);
 
699
                cxt->flags &= ~MNT_FL_EXTERN_FSTAB;
 
700
                rc = mnt_table_parse_fstab(cxt->fstab, NULL);
 
701
                if (rc)
 
702
                        return rc;
 
703
        }
 
704
 
 
705
        cache = mnt_context_get_cache(cxt);
 
706
 
 
707
        /*  never touch an external fstab */
 
708
        if (!(cxt->flags & MNT_FL_EXTERN_FSTAB))
 
709
                mnt_table_set_cache(cxt->fstab, cache);
 
710
 
 
711
        if (tb)
 
712
                *tb = cxt->fstab;
 
713
        return 0;
 
714
}
 
715
 
 
716
/**
 
717
 * mnt_context_get_mtab:
 
718
 * @cxt: mount context
 
719
 * @tb: returns mtab
 
720
 *
 
721
 * See also mnt_table_parse_mtab() for more details about mtab/mountinfo. The
 
722
 * result will deallocated by mnt_free_context(@cxt).
 
723
 *
 
724
 * Returns: 0 on success, negative number in case of error.
 
725
 */
 
726
int mnt_context_get_mtab(struct libmnt_context *cxt, struct libmnt_table **tb)
 
727
{
 
728
        struct libmnt_cache *cache;
 
729
 
 
730
        if (!cxt)
 
731
                return -EINVAL;
 
732
 
 
733
        if (!cxt->mtab) {
 
734
                int rc;
 
735
 
 
736
                cxt->mtab = mnt_new_table();
 
737
                if (!cxt->mtab)
 
738
                        return -ENOMEM;
 
739
 
 
740
                if (cxt->table_errcb)
 
741
                        mnt_table_set_parser_errcb(cxt->mtab, cxt->table_errcb);
 
742
 
 
743
                rc = mnt_table_parse_mtab(cxt->mtab, cxt->mtab_path);
 
744
                if (rc)
 
745
                        return rc;
 
746
        }
 
747
 
 
748
        cache = mnt_context_get_cache(cxt);
 
749
        mnt_table_set_cache(cxt->mtab, cache);
 
750
 
 
751
        if (tb)
 
752
                *tb = cxt->mtab;
 
753
        return 0;
 
754
}
 
755
 
 
756
/**
 
757
 * mnt_context_get_table:
 
758
 * @cxt: mount context
 
759
 * @filename: e.g. /proc/self/mountinfo
 
760
 * @tb: returns the table
 
761
 *
 
762
 * This function allocates a new table and parses the @file. The parser error
 
763
 * callback and cache for tags and paths is set according to the @cxt setting.
 
764
 * See also mnt_table_parse_file().
 
765
 *
 
766
 * It's strongly recommended use mnt_context_get_mtab() and
 
767
 * mnt_context_get_fstab() functions for mtab and fstab files. This function
 
768
 * does not care about LIBMOUNT_* env.variables and does not merge userspace
 
769
 * options.
 
770
 *
 
771
 * The result will NOT be deallocated by mnt_free_context(@cxt).
 
772
 *
 
773
 * Returns: 0 on success, negative number in case of error.
 
774
 */
 
775
int mnt_context_get_table(struct libmnt_context *cxt,
 
776
                          const char *filename, struct libmnt_table **tb)
 
777
{
 
778
        struct libmnt_cache *cache;
 
779
        int rc;
 
780
 
 
781
        if (!cxt || !tb)
 
782
                return -EINVAL;
 
783
 
 
784
        *tb = mnt_new_table();
 
785
        if (!*tb)
 
786
                return -ENOMEM;
 
787
 
 
788
        if (cxt->table_errcb)
 
789
                mnt_table_set_parser_errcb(*tb, cxt->table_errcb);
 
790
 
 
791
        rc = mnt_table_parse_file(*tb, filename);
 
792
        if (rc) {
 
793
                mnt_free_table(*tb);
 
794
                return rc;
 
795
        }
 
796
 
 
797
        cache = mnt_context_get_cache(cxt);
 
798
        if (cache)
 
799
                mnt_table_set_cache(*tb, cache);
 
800
 
 
801
        return 0;
 
802
}
 
803
 
 
804
/**
 
805
 * mnt_context_set_tables_errcb
 
806
 * @cxt: mount context
 
807
 * @cb: pointer to callback function
 
808
 *
 
809
 * The error callback is used for all tab files (e.g. mtab, fstab)
 
810
 * parsed within the context.
 
811
 *
 
812
 * See also mnt_context_get_mtab(),
 
813
 *          mnt_context_get_fstab(),
 
814
 *          mnt_table_set_parser_errcb().
 
815
 *
 
816
 * Returns: 0 on success, negative number in case of error.
 
817
 */
 
818
int mnt_context_set_tables_errcb(struct libmnt_context *cxt,
 
819
        int (*cb)(struct libmnt_table *tb, const char *filename, int line))
 
820
{
 
821
        if (!cxt)
 
822
                return -EINVAL;
 
823
 
 
824
        cxt->table_errcb = cb;
 
825
        return 0;
 
826
}
 
827
 
 
828
/**
 
829
 * mnt_context_set_cache:
 
830
 * @cxt: mount context
 
831
 * @cache: cache instance or nULL
 
832
 *
 
833
 * The mount context maintains a private struct libmnt_cache by default.  This function
 
834
 * allows to overwrite the private cache with an external instance. Note that
 
835
 * the external instance is not deallocated by mnt_free_context().
 
836
 *
 
837
 * If the @cache argument is NULL then the current private cache instance is
 
838
 * reseted.
 
839
 *
 
840
 * Returns: 0 on success, negative number in case of error.
 
841
 */
 
842
int mnt_context_set_cache(struct libmnt_context *cxt, struct libmnt_cache *cache)
 
843
{
 
844
        if (!cxt)
 
845
                return -EINVAL;
 
846
        if (!(cxt->flags & MNT_FL_EXTERN_CACHE))
 
847
                mnt_free_cache(cxt->cache);
 
848
 
 
849
        set_flag(cxt, MNT_FL_EXTERN_CACHE, cache != NULL);
 
850
        cxt->cache = cache;
 
851
        return 0;
 
852
}
 
853
 
 
854
/**
 
855
 * mnt_context_get_cache
 
856
 * @cxt: mount context
 
857
 *
 
858
 * See also mnt_context_set_cache().
 
859
 *
 
860
 * Returns: pointer to cache or NULL if canonicalization is disabled.
 
861
 */
 
862
struct libmnt_cache *mnt_context_get_cache(struct libmnt_context *cxt)
 
863
{
 
864
        if (!cxt || (cxt->flags & MNT_FL_NOCANONICALIZE))
 
865
                return NULL;
 
866
 
 
867
        if (!cxt->cache) {
 
868
                cxt->cache = mnt_new_cache();
 
869
                if (!cxt->cache)
 
870
                        return NULL;
 
871
                cxt->flags &= ~MNT_FL_EXTERN_CACHE;
 
872
        }
 
873
        return cxt->cache;
 
874
}
 
875
 
 
876
/**
 
877
 * mnt_context_get_lock:
 
878
 * @cxt: mount context
 
879
 *
 
880
 * The libmount applications don't have to care about mtab locking, but with a
 
881
 * small exception: the application has to be able to remove the lock file when
 
882
 * interrupted by signal or signals have to be ignored when the lock is locked.
 
883
 *
 
884
 * The default behavior is to ignore all signals (except SIGALRM and
 
885
 * SIGTRAP for mtab udate) when the lock is locked. If this behavior
 
886
 * is unacceptable then use:
 
887
 *
 
888
 *      lc = mnt_context_get_lock(cxt);
 
889
 *      if (lc)
 
890
 *              mnt_lock_block_signals(lc, FALSE);
 
891
 *
 
892
 * and don't forget to call mnt_unlock_file(lc) before exit.
 
893
 *
 
894
 * Returns: pointer to lock struct or NULL.
 
895
 */
 
896
struct libmnt_lock *mnt_context_get_lock(struct libmnt_context *cxt)
 
897
{
 
898
        /*
 
899
         * DON'T call this function within libmount, it will always allocate
 
900
         * the lock. The mnt_update_* functions are able to allocate the lock
 
901
         * only when mtab/utab update is really necessary.
 
902
         */
 
903
        if (!cxt || (cxt->flags & MNT_FL_NOMTAB))
 
904
                return NULL;
 
905
 
 
906
        if (!cxt->lock) {
 
907
                cxt->lock = mnt_new_lock(cxt->mtab_writable ?
 
908
                                cxt->mtab_path : cxt->utab_path, 0);
 
909
                if (cxt->lock)
 
910
                        mnt_lock_block_signals(cxt->lock, TRUE);
 
911
        }
 
912
        return cxt->lock;
 
913
}
 
914
 
 
915
/**
 
916
 * mnt_context_set_mflags:
 
917
 * @cxt: mount context
 
918
 * @flags: mount(2) flags (MS_* flags)
 
919
 *
 
920
 * Sets mount flags (see mount(2) man page).
 
921
 *
 
922
 * Note that mount context allows to define mount options by mount flags. It
 
923
 * means you can for example use
 
924
 *
 
925
 *      mnt_context_set_mflags(cxt, MS_NOEXEC | MS_NOSUID);
 
926
 *
 
927
 * rather than
 
928
 *
 
929
 *      mnt_context_set_options(cxt, "noexec,nosuid");
 
930
 *
 
931
 * these both calls have the same effect.
 
932
 *
 
933
 * Returns: 0 on success, negative number in case of error.
 
934
 */
 
935
int mnt_context_set_mflags(struct libmnt_context *cxt, unsigned long flags)
 
936
{
 
937
        if (!cxt)
 
938
                return -EINVAL;
 
939
        cxt->mountflags = flags;
 
940
        return 0;
 
941
}
 
942
 
 
943
/**
 
944
 * mnt_context_get_mflags:
 
945
 * @cxt: mount context
 
946
 * @flags: returns MS_* mount flags
 
947
 *
 
948
 * Converts mount options string to MS_* flags and bitewise-OR the result with
 
949
 * already defined flags (see mnt_context_set_mflags()).
 
950
 *
 
951
 * Returns: 0 on success, negative number in case of error.
 
952
 */
 
953
int mnt_context_get_mflags(struct libmnt_context *cxt, unsigned long *flags)
 
954
{
 
955
        int rc = 0;
 
956
        if (!cxt || !flags)
 
957
                return -EINVAL;
 
958
 
 
959
        *flags = 0;
 
960
        if (!(cxt->flags & MNT_FL_MOUNTFLAGS_MERGED) && cxt->fs) {
 
961
                const char *o = mnt_fs_get_options(cxt->fs);
 
962
                if (o)
 
963
                        rc = mnt_optstr_get_flags(o, flags,
 
964
                                    mnt_get_builtin_optmap(MNT_LINUX_MAP));
 
965
        }
 
966
        if (!rc)
 
967
                *flags |= cxt->mountflags;
 
968
        return rc;
 
969
}
 
970
 
 
971
/**
 
972
 * mnt_context_set_user_mflags:
 
973
 * @cxt: mount context
 
974
 * @flags: mount(2) flags (MNT_MS_* flags, e.g. MNT_MS_LOOP)
 
975
 *
 
976
 * Sets userspace mount flags.
 
977
 *
 
978
 * See also notest for mnt_context_set_mflags().
 
979
 *
 
980
 * Returns: 0 on success, negative number in case of error.
 
981
 */
 
982
int mnt_context_set_user_mflags(struct libmnt_context *cxt, unsigned long flags)
 
983
{
 
984
        if (!cxt)
 
985
                return -EINVAL;
 
986
        cxt->user_mountflags = flags;
 
987
        return 0;
 
988
}
 
989
 
 
990
/**
 
991
 * mnt_context_get_user_mflags:
 
992
 * @cxt: mount context
 
993
 * @flags: returns mount flags
 
994
 *
 
995
 * Converts mount options string to MNT_MS_* flags and bitewise-OR the result
 
996
 * with already defined flags (see mnt_context_set_user_mflags()).
 
997
 *
 
998
 * Returns: 0 on success, negative number in case of error.
 
999
 */
 
1000
int mnt_context_get_user_mflags(struct libmnt_context *cxt, unsigned long *flags)
 
1001
{
 
1002
        int rc = 0;
 
1003
        if (!cxt || !flags)
 
1004
                return -EINVAL;
 
1005
 
 
1006
        *flags = 0;
 
1007
        if (!(cxt->flags & MNT_FL_MOUNTFLAGS_MERGED) && cxt->fs) {
 
1008
                const char *o = mnt_fs_get_user_options(cxt->fs);
 
1009
                if (o)
 
1010
                        rc = mnt_optstr_get_flags(o, flags,
 
1011
                                mnt_get_builtin_optmap(MNT_USERSPACE_MAP));
 
1012
        }
 
1013
        if (!rc)
 
1014
                *flags |= cxt->user_mountflags;
 
1015
        return rc;
 
1016
}
 
1017
 
 
1018
/**
 
1019
 * mnt_context_set_mountdata:
 
1020
 * @cxt: mount context
 
1021
 * @data: mount(2) data
 
1022
 *
 
1023
 * The mount context generates mountdata from mount options by default. This
 
1024
 * function allows to overwrite this behavior, and @data will be used instead
 
1025
 * of mount options.
 
1026
 *
 
1027
 * The libmount does not deallocated the data by mnt_free_context(). Note that
 
1028
 * NULL is also valid mount data.
 
1029
 *
 
1030
 * Returns: 0 on success, negative number in case of error.
 
1031
 */
 
1032
int mnt_context_set_mountdata(struct libmnt_context *cxt, void *data)
 
1033
{
 
1034
        if (!cxt)
 
1035
                return -EINVAL;
 
1036
        cxt->mountdata = data;
 
1037
        cxt->flags |= MNT_FL_MOUNTDATA;
 
1038
        return 0;
 
1039
}
 
1040
 
 
1041
/*
 
1042
 * Translates LABEL/UUID/path to mountable path
 
1043
 */
 
1044
int mnt_context_prepare_srcpath(struct libmnt_context *cxt)
 
1045
{
 
1046
        const char *path = NULL;
 
1047
        struct libmnt_cache *cache;
 
1048
        const char *t, *v, *src;
 
1049
        int rc = 0;
 
1050
 
 
1051
        assert(cxt);
 
1052
        assert(cxt->fs);
 
1053
        assert((cxt->flags & MNT_FL_MOUNTFLAGS_MERGED));
 
1054
 
 
1055
        if (!cxt || !cxt->fs)
 
1056
                return -EINVAL;
 
1057
 
 
1058
        DBG(CXT, mnt_debug_h(cxt, "preparing source path"));
 
1059
 
 
1060
        src = mnt_fs_get_source(cxt->fs);
 
1061
 
 
1062
        /* ignore filesystems without source or filesystems
 
1063
         * where the source is quasi-path (//foo/bar)
 
1064
         */
 
1065
        if (!src || (cxt->fs->flags & MNT_FS_NET))
 
1066
                return 0;
 
1067
 
 
1068
        DBG(CXT, mnt_debug_h(cxt, "srcpath '%s'", src));
 
1069
 
 
1070
        cache = mnt_context_get_cache(cxt);
 
1071
 
 
1072
        if (!mnt_fs_get_tag(cxt->fs, &t, &v)) {
 
1073
                /*
 
1074
                 * Source is TAG (evaluate)
 
1075
                 */
 
1076
                if (cache)
 
1077
                        path = mnt_resolve_tag(t, v, cache);
 
1078
 
 
1079
                rc = path ? mnt_fs_set_source(cxt->fs, path) : -EINVAL;
 
1080
 
 
1081
        } else if (cache) {
 
1082
                /*
 
1083
                 * Source is PATH (canonicalize)
 
1084
                 */
 
1085
                path = mnt_resolve_path(src, cache);
 
1086
                if (path && strcmp(path, src))
 
1087
                        rc = mnt_fs_set_source(cxt->fs, path);
 
1088
         }
 
1089
 
 
1090
        if (rc) {
 
1091
                DBG(CXT, mnt_debug_h(cxt, "failed to prepare srcpath [rc=%d]", rc));
 
1092
                return rc;
 
1093
        }
 
1094
 
 
1095
        if (!path)
 
1096
                path = src;
 
1097
 
 
1098
        if ((cxt->mountflags & (MS_BIND | MS_MOVE | MS_PROPAGATION)) ||
 
1099
            (cxt->fs->flags & MNT_FS_PSEUDO)) {
 
1100
                DBG(CXT, mnt_debug_h(cxt, "PROPAGATION/pseudo FS source: %s", path));
 
1101
                return rc;
 
1102
        }
 
1103
 
 
1104
        /*
 
1105
         * Initialize loop device
 
1106
         */
 
1107
        if (mnt_context_is_loopdev(cxt)) {
 
1108
                rc = mnt_context_setup_loopdev(cxt);
 
1109
                if (rc)
 
1110
                        return rc;
 
1111
        }
 
1112
 
 
1113
        DBG(CXT, mnt_debug_h(cxt, "final srcpath '%s'",
 
1114
                                mnt_fs_get_source(cxt->fs)));
 
1115
        return 0;
 
1116
}
 
1117
 
 
1118
int mnt_context_prepare_target(struct libmnt_context *cxt)
 
1119
{
 
1120
        const char *tgt;
 
1121
        struct libmnt_cache *cache;
 
1122
        int rc = 0;
 
1123
 
 
1124
        assert(cxt);
 
1125
        assert(cxt->fs);
 
1126
        assert((cxt->flags & MNT_FL_MOUNTFLAGS_MERGED));
 
1127
 
 
1128
        if (!cxt || !cxt->fs)
 
1129
                return -EINVAL;
 
1130
 
 
1131
        DBG(CXT, mnt_debug_h(cxt, "preparing target path"));
 
1132
 
 
1133
        tgt = mnt_fs_get_target(cxt->fs);
 
1134
        if (!tgt)
 
1135
                return 0;
 
1136
 
 
1137
        cache = mnt_context_get_cache(cxt);
 
1138
        if (cache) {
 
1139
                char *path = mnt_resolve_path(tgt, cache);
 
1140
                if (strcmp(path, tgt))
 
1141
                        rc = mnt_fs_set_target(cxt->fs, path);
 
1142
        }
 
1143
 
 
1144
        if (rc)
 
1145
                DBG(CXT, mnt_debug_h(cxt, "failed to prepare target"));
 
1146
        else
 
1147
                DBG(CXT, mnt_debug_h(cxt, "final target '%s'",
 
1148
                                        mnt_fs_get_target(cxt->fs)));
 
1149
        return 0;
 
1150
}
 
1151
 
 
1152
int mnt_context_guess_fstype(struct libmnt_context *cxt)
 
1153
{
 
1154
        char *type;
 
1155
        const char *dev;
 
1156
        int rc = -EINVAL;
 
1157
 
 
1158
        assert(cxt);
 
1159
        assert(cxt->fs);
 
1160
        assert((cxt->flags & MNT_FL_MOUNTFLAGS_MERGED));
 
1161
 
 
1162
        if (!cxt || !cxt->fs)
 
1163
                return -EINVAL;
 
1164
 
 
1165
        if (cxt->mountflags & (MS_BIND | MS_MOVE | MS_PROPAGATION))
 
1166
                goto none;
 
1167
 
 
1168
        type = (char *) mnt_fs_get_fstype(cxt->fs);
 
1169
        if (type && !strcmp(type, "auto")) {
 
1170
                mnt_fs_set_fstype(cxt->fs, NULL);
 
1171
                type = NULL;
 
1172
        }
 
1173
 
 
1174
        if (type)
 
1175
                goto done;
 
1176
        if (cxt->flags & MS_REMOUNT)
 
1177
                goto none;
 
1178
        if (cxt->fstype_pattern)
 
1179
                goto done;
 
1180
 
 
1181
        dev = mnt_fs_get_srcpath(cxt->fs);
 
1182
        if (!dev)
 
1183
                goto err;
 
1184
 
 
1185
        if (access(dev, F_OK) == 0) {
 
1186
                struct libmnt_cache *cache = mnt_context_get_cache(cxt);
 
1187
 
 
1188
                type = mnt_get_fstype(dev, &cxt->ambi, cache);
 
1189
                if (type) {
 
1190
                        rc = mnt_fs_set_fstype(cxt->fs, type);
 
1191
                        if (!cache)
 
1192
                                free(type);     /* type is not cached */
 
1193
                }
 
1194
        } else {
 
1195
                if (strchr(dev, ':') != NULL)
 
1196
                        rc = mnt_fs_set_fstype(cxt->fs, "nfs");
 
1197
                else if (!strncmp(dev, "//", 2))
 
1198
                        rc = mnt_fs_set_fstype(cxt->fs, "cifs");
 
1199
        }
 
1200
        if (rc)
 
1201
                goto err;
 
1202
done:
 
1203
        DBG(CXT, mnt_debug_h(cxt, "FS type: %s",
 
1204
                                mnt_fs_get_fstype(cxt->fs)));
 
1205
        return 0;
 
1206
none:
 
1207
        return mnt_fs_set_fstype(cxt->fs, "none");
 
1208
err:
 
1209
        DBG(CXT, mnt_debug_h(cxt, "failed to detect FS type"));
 
1210
        return rc;
 
1211
}
 
1212
 
 
1213
/*
 
1214
 * The default is to use fstype from cxt->fs, this could be overwritten by
 
1215
 * @type. The @act is MNT_ACT_{MOUNT,UMOUNT}.
 
1216
 *
 
1217
 * Returns: 0 on success or negative number in case of error. Note that success
 
1218
 * does not mean that there is any usable helper, you have to check cxt->helper.
 
1219
 */
 
1220
int mnt_context_prepare_helper(struct libmnt_context *cxt, const char *name,
 
1221
                                const char *type)
 
1222
{
 
1223
        char search_path[] = FS_SEARCH_PATH;            /* from config.h */
 
1224
        char *p = NULL, *path;
 
1225
 
 
1226
        assert(cxt);
 
1227
        assert(cxt->fs);
 
1228
        assert((cxt->flags & MNT_FL_MOUNTFLAGS_MERGED));
 
1229
 
 
1230
        if (!type)
 
1231
                type = mnt_fs_get_fstype(cxt->fs);
 
1232
 
 
1233
        if ((cxt->flags & MNT_FL_NOHELPERS) || !type ||
 
1234
            !strcmp(type, "none") || (cxt->fs->flags & MNT_FS_SWAP))
 
1235
                return 0;
 
1236
 
 
1237
        path = strtok_r(search_path, ":", &p);
 
1238
        while (path) {
 
1239
                char helper[PATH_MAX];
 
1240
                struct stat st;
 
1241
                int rc;
 
1242
 
 
1243
                rc = snprintf(helper, sizeof(helper), "%s/%s.%s",
 
1244
                                                path, name, type);
 
1245
                path = strtok_r(NULL, ":", &p);
 
1246
 
 
1247
                if (rc < 0 || (size_t) rc >= sizeof(helper))
 
1248
                        continue;
 
1249
 
 
1250
                rc = stat(helper, &st);
 
1251
                if (rc == -1 && errno == ENOENT && strchr(type, '.')) {
 
1252
                        /* If type ends with ".subtype" try without it */
 
1253
                        *strrchr(helper, '.') = '\0';
 
1254
                        rc = stat(helper, &st);
 
1255
                }
 
1256
 
 
1257
                DBG(CXT, mnt_debug_h(cxt, "%-25s ... %s", helper,
 
1258
                                        rc ? "not found" : "found"));
 
1259
                if (rc)
 
1260
                        continue;
 
1261
 
 
1262
                free(cxt->helper);
 
1263
                cxt->helper = strdup(helper);
 
1264
                if (!cxt->helper)
 
1265
                        return -ENOMEM;
 
1266
                return 0;
 
1267
        }
 
1268
 
 
1269
        return 0;
 
1270
}
 
1271
 
 
1272
int mnt_context_merge_mflags(struct libmnt_context *cxt)
 
1273
{
 
1274
        unsigned long fl = 0;
 
1275
        int rc;
 
1276
 
 
1277
        assert(cxt);
 
1278
 
 
1279
        DBG(CXT, mnt_debug_h(cxt, "merging mount flags"));
 
1280
 
 
1281
        rc = mnt_context_get_mflags(cxt, &fl);
 
1282
        if (rc)
 
1283
                return rc;
 
1284
        cxt->mountflags = fl;
 
1285
 
 
1286
        /* TODO: if cxt->fs->fs_optstr contains 'ro' then set the MS_RDONLY to
 
1287
         * mount flags, it's possible that superblock is read-only, but VFS is
 
1288
         * read-write.
 
1289
         */
 
1290
 
 
1291
        fl = 0;
 
1292
        rc = mnt_context_get_user_mflags(cxt, &fl);
 
1293
        if (rc)
 
1294
                return rc;
 
1295
        cxt->user_mountflags = fl;
 
1296
 
 
1297
        DBG(CXT, mnt_debug_h(cxt, "final flags: VFS=%08lx user=%08lx",
 
1298
                        cxt->mountflags, cxt->user_mountflags));
 
1299
 
 
1300
        cxt->flags |= MNT_FL_MOUNTFLAGS_MERGED;
 
1301
        return 0;
 
1302
}
 
1303
 
 
1304
/*
 
1305
 * Prepare /etc/mtab or /run/mount/utab
 
1306
 */
 
1307
int mnt_context_prepare_update(struct libmnt_context *cxt)
 
1308
{
 
1309
        int rc;
 
1310
        const char *target;
 
1311
 
 
1312
        assert(cxt);
 
1313
        assert(cxt->fs);
 
1314
        assert(cxt->action);
 
1315
        assert((cxt->flags & MNT_FL_MOUNTFLAGS_MERGED));
 
1316
 
 
1317
        DBG(CXT, mnt_debug_h(cxt, "prepare update"));
 
1318
 
 
1319
        if (cxt->mountflags & MS_PROPAGATION) {
 
1320
                DBG(CXT, mnt_debug_h(cxt, "skip update: MS_PROPAGATION"));
 
1321
                return 0;
 
1322
        }
 
1323
 
 
1324
        target = mnt_fs_get_target(cxt->fs);
 
1325
 
 
1326
        if (cxt->action == MNT_ACT_UMOUNT && target && !strcmp(target, "/"))
 
1327
                /* Don't try to touch mtab if umounting root FS */
 
1328
                cxt->flags |= MNT_FL_NOMTAB;
 
1329
 
 
1330
        if (cxt->flags & MNT_FL_NOMTAB) {
 
1331
                DBG(CXT, mnt_debug_h(cxt, "skip update: NOMTAB flag"));
 
1332
                return 0;
 
1333
        }
 
1334
        if (cxt->helper) {
 
1335
                DBG(CXT, mnt_debug_h(cxt, "skip update: external helper"));
 
1336
                return 0;
 
1337
        }
 
1338
        if (!cxt->mtab_writable && !cxt->utab_writable) {
 
1339
                DBG(CXT, mnt_debug_h(cxt, "skip update: no writable destination"));
 
1340
                return 0;
 
1341
        }
 
1342
        /* 0 = success, 1 = not called yet */
 
1343
        if (cxt->syscall_status != 1 && cxt->syscall_status != 0) {
 
1344
                DBG(CXT, mnt_debug_h(cxt,
 
1345
                                "skip update: syscall failed [status=%d]",
 
1346
                                cxt->syscall_status));
 
1347
                return 0;
 
1348
        }
 
1349
        if (!cxt->update) {
 
1350
                cxt->update = mnt_new_update();
 
1351
                if (!cxt->update)
 
1352
                        return -ENOMEM;
 
1353
 
 
1354
                mnt_update_set_filename(cxt->update,
 
1355
                                cxt->mtab_writable ? cxt->mtab_path : cxt->utab_path,
 
1356
                                !cxt->mtab_writable);
 
1357
        }
 
1358
 
 
1359
        if (cxt->action == MNT_ACT_UMOUNT)
 
1360
                rc = mnt_update_set_fs(cxt->update, cxt->mountflags,
 
1361
                                        mnt_fs_get_target(cxt->fs), NULL);
 
1362
        else
 
1363
                rc = mnt_update_set_fs(cxt->update, cxt->mountflags,
 
1364
                                        NULL, cxt->fs);
 
1365
 
 
1366
        return rc < 0 ? rc : 0;
 
1367
}
 
1368
 
 
1369
int mnt_context_update_tabs(struct libmnt_context *cxt)
 
1370
{
 
1371
        unsigned long fl;
 
1372
 
 
1373
        assert(cxt);
 
1374
 
 
1375
        if (cxt->flags & MNT_FL_NOMTAB) {
 
1376
                DBG(CXT, mnt_debug_h(cxt, "don't update: NOMTAB flag"));
 
1377
                return 0;
 
1378
        }
 
1379
        if (cxt->helper) {
 
1380
                DBG(CXT, mnt_debug_h(cxt, "don't update: external helper"));
 
1381
                return 0;
 
1382
        }
 
1383
        if (!cxt->update || !mnt_update_is_ready(cxt->update)) {
 
1384
                DBG(CXT, mnt_debug_h(cxt, "don't update: no update prepared"));
 
1385
                return 0;
 
1386
        }
 
1387
        if (cxt->syscall_status) {
 
1388
                DBG(CXT, mnt_debug_h(cxt, "don't update: syscall failed/not called"));
 
1389
                return 0;
 
1390
        }
 
1391
 
 
1392
        fl = mnt_update_get_mflags(cxt->update);
 
1393
        if ((cxt->mountflags & MS_RDONLY) != (fl & MS_RDONLY))
 
1394
                /*
 
1395
                 * fix MS_RDONLY in options
 
1396
                 */
 
1397
                mnt_update_force_rdonly(cxt->update,
 
1398
                                cxt->mountflags & MS_RDONLY);
 
1399
 
 
1400
        return mnt_update_table(cxt->update, cxt->lock);
 
1401
}
 
1402
 
 
1403
static int apply_table(struct libmnt_context *cxt, struct libmnt_table *tb,
 
1404
                     int direction)
 
1405
{
 
1406
        struct libmnt_fs *fs = NULL;
 
1407
        const char *src = NULL, *tgt = NULL;
 
1408
        int rc;
 
1409
 
 
1410
        assert(cxt);
 
1411
        assert(cxt->fs);
 
1412
 
 
1413
        if (!cxt->fs)
 
1414
                return -EINVAL;
 
1415
 
 
1416
        src = mnt_fs_get_source(cxt->fs);
 
1417
        tgt = mnt_fs_get_target(cxt->fs);
 
1418
 
 
1419
        if (tgt && src)
 
1420
                fs = mnt_table_find_pair(tb, src, tgt, direction);
 
1421
        else {
 
1422
                if (src)
 
1423
                        fs = mnt_table_find_source(tb, src, direction);
 
1424
                else if (tgt)
 
1425
                        fs = mnt_table_find_target(tb, tgt, direction);
 
1426
 
 
1427
                if (!fs) {
 
1428
                        /* swap source and target (if @src is not LABEL/UUID),
 
1429
                         * for example in
 
1430
                         *
 
1431
                         *      mount /foo/bar
 
1432
                         *
 
1433
                         * the path could be a mountpoint as well as source (for
 
1434
                         * example bind mount, symlink to device, ...).
 
1435
                         */
 
1436
                        if (src && !mnt_fs_get_tag(cxt->fs, NULL, NULL))
 
1437
                                fs = mnt_table_find_target(tb, src, direction);
 
1438
                        if (!fs && tgt)
 
1439
                                fs = mnt_table_find_source(tb, tgt, direction);
 
1440
                }
 
1441
        }
 
1442
 
 
1443
        if (!fs)
 
1444
                return -EINVAL;
 
1445
 
 
1446
        DBG(CXT, mnt_debug_h(cxt, "apply entry:"));
 
1447
        DBG(CXT, mnt_fs_print_debug(fs, stderr));
 
1448
 
 
1449
        /* copy from tab to our FS description
 
1450
         */
 
1451
        rc = mnt_fs_set_source(cxt->fs, mnt_fs_get_source(fs));
 
1452
        if (!rc)
 
1453
                rc = mnt_fs_set_target(cxt->fs, mnt_fs_get_target(fs));
 
1454
 
 
1455
        if (!rc && !mnt_fs_get_fstype(cxt->fs))
 
1456
                rc = mnt_fs_set_fstype(cxt->fs, mnt_fs_get_fstype(fs));
 
1457
 
 
1458
        if (rc)
 
1459
                return rc;
 
1460
 
 
1461
        if (cxt->optsmode & MNT_OMODE_IGNORE)
 
1462
                ;
 
1463
        else if (cxt->optsmode & MNT_OMODE_REPLACE)
 
1464
                rc = mnt_fs_set_options(cxt->fs, mnt_fs_get_options(fs));
 
1465
 
 
1466
        else if (cxt->optsmode & MNT_OMODE_APPEND)
 
1467
                rc = mnt_fs_append_options(cxt->fs, mnt_fs_get_options(fs));
 
1468
 
 
1469
        else if (cxt->optsmode & MNT_OMODE_PREPEND)
 
1470
                rc = mnt_fs_prepend_options(cxt->fs, mnt_fs_get_options(fs));
 
1471
 
 
1472
        if (!rc)
 
1473
                cxt->flags |= MNT_FL_TAB_APPLIED;
 
1474
        return rc;
 
1475
}
 
1476
 
 
1477
/**
 
1478
 * mnt_context_apply_fstab:
 
1479
 * @cxt: mount context
 
1480
 *
 
1481
 * This function is optional.
 
1482
 *
 
1483
 * Returns: 0 on success, negative number in case of error.
 
1484
 */
 
1485
int mnt_context_apply_fstab(struct libmnt_context *cxt)
 
1486
{
 
1487
        int rc = -1;
 
1488
        struct libmnt_table *tab = NULL;
 
1489
        const char *src = NULL, *tgt = NULL;
 
1490
 
 
1491
        assert(cxt);
 
1492
        assert(cxt->fs);
 
1493
 
 
1494
        if (!cxt)
 
1495
                return -EINVAL;
 
1496
 
 
1497
        if (cxt->flags & MNT_FL_TAB_APPLIED)
 
1498
                return 0;
 
1499
 
 
1500
        if (mnt_context_is_restricted(cxt)) {
 
1501
                DBG(CXT, mnt_debug_h(cxt, "force fstab usage for non-root users!"));
 
1502
                cxt->optsmode = MNT_OMODE_USER;
 
1503
        } else if (cxt->optsmode == 0) {
 
1504
                DBG(CXT, mnt_debug_h(cxt, "use default optmode"));
 
1505
                cxt->optsmode = MNT_OMODE_AUTO;
 
1506
 
 
1507
        }
 
1508
 
 
1509
        if (cxt->fs) {
 
1510
                src = mnt_fs_get_source(cxt->fs);
 
1511
                tgt = mnt_fs_get_target(cxt->fs);
 
1512
        }
 
1513
 
 
1514
        DBG(CXT, mnt_debug_h(cxt, "OPTSMODE: ignore=%d, append=%d, prepend=%d, "
 
1515
                                  "replace=%d, force=%d, fstab=%d, mtab=%d",
 
1516
                                  cxt->optsmode & MNT_OMODE_IGNORE ? 1 : 0,
 
1517
                                  cxt->optsmode & MNT_OMODE_APPEND ? 1 : 0,
 
1518
                                  cxt->optsmode & MNT_OMODE_PREPEND ? 1 : 0,
 
1519
                                  cxt->optsmode & MNT_OMODE_REPLACE ? 1 : 0,
 
1520
                                  cxt->optsmode & MNT_OMODE_FORCE ? 1 : 0,
 
1521
                                  cxt->optsmode & MNT_OMODE_FSTAB ? 1 : 0,
 
1522
                                  cxt->optsmode & MNT_OMODE_MTAB ? 1 : 0));
 
1523
 
 
1524
        /* fstab is not required if source and target are specified */
 
1525
        if (src && tgt && !(cxt->optsmode & MNT_OMODE_FORCE)) {
 
1526
                DBG(CXT, mnt_debug_h(cxt, "fstab not required -- skip"));
 
1527
                return 0;
 
1528
        }
 
1529
 
 
1530
        DBG(CXT, mnt_debug_h(cxt,
 
1531
                "trying to apply fstab (src=%s, target=%s)", src, tgt));
 
1532
 
 
1533
        /* let's initialize cxt->fs */
 
1534
        mnt_context_get_fs(cxt);
 
1535
 
 
1536
        /* try fstab */
 
1537
        if (cxt->optsmode & MNT_OMODE_FSTAB) {
 
1538
                rc = mnt_context_get_fstab(cxt, &tab);
 
1539
                if (!rc)
 
1540
                        rc = apply_table(cxt, tab, MNT_ITER_FORWARD);
 
1541
        }
 
1542
 
 
1543
        /* try mtab */
 
1544
        if (rc < 0 && (cxt->optsmode & MNT_OMODE_MTAB)) {
 
1545
                DBG(CXT, mnt_debug_h(cxt, "tring to apply from mtab"));
 
1546
                rc = mnt_context_get_mtab(cxt, &tab);
 
1547
                if (!rc)
 
1548
                        rc = apply_table(cxt, tab, MNT_ITER_BACKWARD);
 
1549
        }
 
1550
        if (rc)
 
1551
                DBG(CXT, mnt_debug_h(cxt, "failed to find entry in fstab/mtab"));
 
1552
        return rc;
 
1553
}
 
1554
 
 
1555
/**
 
1556
 * mnt_context_get_status:
 
1557
 * @cxt: mount context
 
1558
 *
 
1559
 * Returns: 1 if /sbin/mount.type or mount(2) syscall was successfull.
 
1560
 */
 
1561
int mnt_context_get_status(struct libmnt_context *cxt)
 
1562
{
 
1563
        return cxt && (!cxt->syscall_status || !cxt->helper_exec_status);
 
1564
}
 
1565
 
 
1566
/**
 
1567
 * mnt_context_set_syscall_status:
 
1568
 * @cxt: mount context
 
1569
 * @status: mount(2) status
 
1570
 *
 
1571
 * The @status should be 0 on succcess, or negative number on error (-1 or
 
1572
 * -errno).
 
1573
 *
 
1574
 * This function should be used if [u]mount(2) syscall was NOT called by
 
1575
 * libmount (by mnt_context_mount() or mnt_context_do_mount()) only.
 
1576
 *
 
1577
 * Returns: 0 or negative number in case of error.
 
1578
 */
 
1579
int mnt_context_set_syscall_status(struct libmnt_context *cxt, int status)
 
1580
{
 
1581
        if (!cxt)
 
1582
                return -EINVAL;
 
1583
 
 
1584
        DBG(CXT, mnt_debug_h(cxt, "syscall status set to: %d", status));
 
1585
        cxt->syscall_status = status;
 
1586
        return 0;
 
1587
}
 
1588
 
 
1589
/**
 
1590
 * mnt_context_strerror
 
1591
 * @cxt: context
 
1592
 * @buf: buffer
 
1593
 * @bufsiz: size of the buffer
 
1594
 *
 
1595
 * Returns: 0 or negative number in case of error.
 
1596
 */
 
1597
int mnt_context_strerror(struct libmnt_context *cxt __attribute__((__unused__)),
 
1598
                         char *buf __attribute__((__unused__)),
 
1599
                         size_t bufsiz __attribute__((__unused__)))
 
1600
{
 
1601
        /* TODO: based on cxt->syscall_errno or cxt->helper_status */
 
1602
        return 0;
 
1603
}
 
1604
 
 
1605
/**
 
1606
 * mnt_context_init_helper
 
1607
 * @cxt: mount context
 
1608
 * @action: MNT_ACT_{UMOUNT,MOUNT}
 
1609
 * @flags: not used now
 
1610
 *
 
1611
 * This function infors libmount that used from [u]mount.type helper.
 
1612
 *
 
1613
 * The function also calls mnt_context_disable_helpers() to avoid recursive
 
1614
 * mount.type helpers calling. It you really want to call another
 
1615
 * mount.type helper from your helper than you have to explicitly enable this
 
1616
 * feature by:
 
1617
 *
 
1618
 *       mnt_context_disable_helpers(cxt, FALSE);
 
1619
 *
 
1620
 * Returns: 0 on success, negative number in case of error.
 
1621
 */
 
1622
int mnt_context_init_helper(struct libmnt_context *cxt, int action,
 
1623
                            int flags __attribute__((__unused__)))
 
1624
{
 
1625
        int rc = mnt_context_disable_helpers(cxt, TRUE);
 
1626
 
 
1627
        if (!rc)
 
1628
                rc = set_flag(cxt, MNT_FL_HELPER, 1);
 
1629
        if (!rc)
 
1630
                cxt->action = action;
 
1631
 
 
1632
        DBG(CXT, mnt_debug_h(cxt, "initialized for [u]mount.<type> helper [rc=%d]", rc));
 
1633
        return rc;
 
1634
}
 
1635
 
 
1636
/**
 
1637
 * mnt_context_helper_setopt:
 
1638
 * @cxt: context
 
1639
 * @c: getopt() result
 
1640
 * @arg: getopt() optarg
 
1641
 *
 
1642
 * This function applies [u]mount.type command line option (for example parsed
 
1643
 * by getopt or getopt_long) to @cxt. All unknown options are ignored and
 
1644
 * then 1 is returned.
 
1645
 *
 
1646
 * Returns: negative number on error, 1 if @c is unknown option, 0 on success.
 
1647
 */
 
1648
int mnt_context_helper_setopt(struct libmnt_context *cxt, int c, char *arg)
 
1649
{
 
1650
        if (cxt) {
 
1651
                switch(cxt->action) {
 
1652
                case MNT_ACT_MOUNT:
 
1653
                        return mnt_context_mount_setopt(cxt, c, arg);
 
1654
                case MNT_ACT_UMOUNT:
 
1655
                        return mnt_context_umount_setopt(cxt, c, arg);
 
1656
                }
 
1657
        }
 
1658
        return -EINVAL;
 
1659
}
 
1660
 
 
1661
/**
 
1662
 * mnt_context_is_fs_mounted:
 
1663
 * @cxt: context
 
1664
 * @fs: filesystem
 
1665
 * @mounted: returns 1 for mounted and 0 for non-mounted filesystems
 
1666
 *
 
1667
 * Returns: 0 on success and negative number in case of error.
 
1668
 */
 
1669
int mnt_context_is_fs_mounted(struct libmnt_context *cxt,
 
1670
                              struct libmnt_fs *fs, int *mounted)
 
1671
{
 
1672
        struct libmnt_table *mtab;
 
1673
        int rc;
 
1674
 
 
1675
        if (!cxt || !fs || !mounted)
 
1676
                return -EINVAL;
 
1677
 
 
1678
        rc = mnt_context_get_mtab(cxt, &mtab);
 
1679
        if (rc)
 
1680
                return rc;
 
1681
 
 
1682
        *mounted = mnt_table_is_fs_mounted(mtab, fs);
 
1683
        return 0;
 
1684
}
 
1685
 
 
1686
#ifdef TEST_PROGRAM
 
1687
 
 
1688
struct libmnt_lock *lock;
 
1689
 
 
1690
static void lock_fallback(void)
 
1691
{
 
1692
        if (lock)
 
1693
                mnt_unlock_file(lock);
 
1694
}
 
1695
 
 
1696
int test_mount(struct libmnt_test *ts, int argc, char *argv[])
 
1697
{
 
1698
        int idx = 1, rc = 0;
 
1699
        struct libmnt_context *cxt;
 
1700
 
 
1701
        if (argc < 2)
 
1702
                return -EINVAL;
 
1703
 
 
1704
        cxt = mnt_new_context();
 
1705
        if (!cxt)
 
1706
                return -ENOMEM;
 
1707
 
 
1708
        if (!strcmp(argv[idx], "-o")) {
 
1709
                mnt_context_set_options(cxt, argv[idx + 1]);
 
1710
                idx += 2;
 
1711
        }
 
1712
        if (!strcmp(argv[idx], "-t")) {
 
1713
                /* TODO: use mnt_context_set_fstype_pattern() */
 
1714
                mnt_context_set_fstype(cxt, argv[idx + 1]);
 
1715
                idx += 2;
 
1716
        }
 
1717
 
 
1718
        if (argc == idx + 1)
 
1719
                /* mount <mountpont>|<device> */
 
1720
                mnt_context_set_target(cxt, argv[idx++]);
 
1721
 
 
1722
        else if (argc == idx + 2) {
 
1723
                /* mount <device> <mountpoint> */
 
1724
                mnt_context_set_source(cxt, argv[idx++]);
 
1725
                mnt_context_set_target(cxt, argv[idx++]);
 
1726
        }
 
1727
 
 
1728
        /* this is unnecessary -- libmount is able to internaly
 
1729
         * create and manage the lock
 
1730
         */
 
1731
        lock = mnt_context_get_lock(cxt);
 
1732
        if (lock)
 
1733
                atexit(lock_fallback);
 
1734
 
 
1735
        rc = mnt_context_mount(cxt);
 
1736
        if (rc)
 
1737
                printf("failed to mount %s\n", strerror(errno));
 
1738
        else
 
1739
                printf("successfully mounted\n");
 
1740
 
 
1741
        mnt_free_context(cxt);
 
1742
        return rc;
 
1743
}
 
1744
 
 
1745
int test_umount(struct libmnt_test *ts, int argc, char *argv[])
 
1746
{
 
1747
        int idx = 1, rc = 0;
 
1748
        struct libmnt_context *cxt;
 
1749
 
 
1750
        if (argc < 2)
 
1751
                return -EINVAL;
 
1752
 
 
1753
        cxt = mnt_new_context();
 
1754
        if (!cxt)
 
1755
                return -ENOMEM;
 
1756
 
 
1757
        if (!strcmp(argv[idx], "-t")) {
 
1758
                mnt_context_set_fstype(cxt, argv[idx + 1]);
 
1759
                idx += 2;
 
1760
        }
 
1761
 
 
1762
        if (!strcmp(argv[idx], "-f")) {
 
1763
                mnt_context_enable_force(cxt, TRUE);
 
1764
                idx++;
 
1765
        }
 
1766
 
 
1767
        if (!strcmp(argv[idx], "-l")) {
 
1768
                mnt_context_enable_lazy(cxt, TRUE);
 
1769
                idx++;
 
1770
        }
 
1771
 
 
1772
        if (!strcmp(argv[idx], "-r")) {
 
1773
                mnt_context_enable_rdonly_umount(cxt, TRUE);
 
1774
                idx++;
 
1775
        }
 
1776
 
 
1777
        if (argc == idx + 1) {
 
1778
                /* mount <mountpont>|<device> */
 
1779
                mnt_context_set_target(cxt, argv[idx++]);
 
1780
        } else {
 
1781
                rc = -EINVAL;
 
1782
                goto err;
 
1783
        }
 
1784
 
 
1785
        lock = mnt_context_get_lock(cxt);
 
1786
        if (lock)
 
1787
                atexit(lock_fallback);
 
1788
 
 
1789
        rc = mnt_context_umount(cxt);
 
1790
        if (rc)
 
1791
                printf("failed to umount\n");
 
1792
        else
 
1793
                printf("successfully umounted\n");
 
1794
err:
 
1795
        mnt_free_context(cxt);
 
1796
        return rc;
 
1797
}
 
1798
 
 
1799
int test_flags(struct libmnt_test *ts, int argc, char *argv[])
 
1800
{
 
1801
        int idx = 1, rc = 0;
 
1802
        struct libmnt_context *cxt;
 
1803
        const char *opt = NULL;
 
1804
        unsigned long flags = 0;
 
1805
 
 
1806
        if (argc < 2)
 
1807
                return -EINVAL;
 
1808
 
 
1809
        cxt = mnt_new_context();
 
1810
        if (!cxt)
 
1811
                return -ENOMEM;
 
1812
 
 
1813
        if (!strcmp(argv[idx], "-o")) {
 
1814
                mnt_context_set_options(cxt, argv[idx + 1]);
 
1815
                idx += 2;
 
1816
        }
 
1817
 
 
1818
        if (argc == idx + 1)
 
1819
                /* mount <mountpont>|<device> */
 
1820
                mnt_context_set_target(cxt, argv[idx++]);
 
1821
 
 
1822
        rc = mnt_context_prepare_mount(cxt);
 
1823
        if (rc)
 
1824
                printf("failed to prepare mount %s\n", strerror(-rc));
 
1825
 
 
1826
        opt = mnt_fs_get_options(cxt->fs);
 
1827
        if (opt)
 
1828
                fprintf(stdout, "options: %s\n", opt);
 
1829
 
 
1830
        mnt_context_get_mflags(cxt, &flags);
 
1831
        fprintf(stdout, "flags: %08lx\n", flags);
 
1832
 
 
1833
        mnt_free_context(cxt);
 
1834
        return rc;
 
1835
}
 
1836
 
 
1837
int test_mountall(struct libmnt_test *ts, int argc, char *argv[])
 
1838
{
 
1839
        struct libmnt_context *cxt;
 
1840
        struct libmnt_iter *itr;
 
1841
        struct libmnt_fs *fs;
 
1842
        int mntrc, ignored, idx = 1;
 
1843
 
 
1844
        cxt = mnt_new_context();
 
1845
        itr = mnt_new_iter(MNT_ITER_FORWARD);
 
1846
 
 
1847
        if (!cxt || !itr)
 
1848
                return -ENOMEM;
 
1849
 
 
1850
        if (argc > 2) {
 
1851
                if (!strcmp(argv[idx], "-O")) {
 
1852
                        mnt_context_set_options_pattern(cxt, argv[idx + 1]);
 
1853
                        idx += 2;
 
1854
                }
 
1855
                if (!strcmp(argv[idx], "-t")) {
 
1856
                        mnt_context_set_fstype_pattern(cxt, argv[idx + 1]);
 
1857
                        idx += 2;
 
1858
                }
 
1859
        }
 
1860
 
 
1861
        while (mnt_context_next_mount(cxt, itr, &fs, &mntrc, &ignored) == 0) {
 
1862
 
 
1863
                const char *tgt = mnt_fs_get_target(fs);
 
1864
 
 
1865
                if (ignored == 1)
 
1866
                        printf("%s: ignored: not match\n", tgt);
 
1867
                else if (ignored == 2)
 
1868
                        printf("%s: ignored: already mounted\n", tgt);
 
1869
 
 
1870
                else if (!mnt_context_get_status(cxt)) {
 
1871
                        if (mntrc > 0) {
 
1872
                                errno = mntrc;
 
1873
                                warn("%s: mount failed", tgt);
 
1874
                        } else
 
1875
                                warnx("%s: mount failed", tgt);
 
1876
                } else
 
1877
                        printf("%s: successfully mounted\n", tgt);
 
1878
        }
 
1879
 
 
1880
        mnt_free_context(cxt);
 
1881
        return 0;
 
1882
}
 
1883
 
 
1884
int main(int argc, char *argv[])
 
1885
{
 
1886
        struct libmnt_test tss[] = {
 
1887
        { "--mount",  test_mount,  "[-o <opts>] [-t <type>] <spec>|<src> <target>" },
 
1888
        { "--umount", test_umount, "[-t <type>] [-f][-l][-r] <src>|<target>" },
 
1889
        { "--mount-all", test_mountall,  "[-O <pattern>] [-t <pattern] mount all filesystems from fstab" },
 
1890
        { "--flags", test_flags,   "[-o <opts>] <spec>" },
 
1891
        { NULL }};
 
1892
 
 
1893
        umask(S_IWGRP|S_IWOTH); /* to be compatible with mount(8) */
 
1894
 
 
1895
        return mnt_run_test(tss, argc, argv);
 
1896
}
 
1897
 
 
1898
#endif /* TEST_PROGRAM */