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

« back to all changes in this revision

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