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

« back to all changes in this revision

Viewing changes to shlibs/mount/src/tab.c

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

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * Copyright (C) 2008-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: tab
10
 
 * @title: Table of filesystems
11
 
 * @short_description: container for entries from fstab/mtab/mountinfo
12
 
 *
13
 
 *
14
 
 * Note that mnt_table_find_* functions are mount(8) compatible. These functions
15
 
 * try to found an entry in more iterations where the first attempt is always
16
 
 * based on comparison with unmodified (non-canonicalized or un-evaluated)
17
 
 * paths or tags. For example fstab with two entries:
18
 
 * <informalexample>
19
 
 *   <programlisting>
20
 
 *      LABEL=foo       /foo    auto   rw
21
 
 *      /dev/foo        /foo    auto   rw
22
 
 *  </programlisting>
23
 
 * </informalexample>
24
 
 *
25
 
 * where both lines are used for the *same* device, then
26
 
 * <informalexample>
27
 
 *  <programlisting>
28
 
 *      mnt_table_find_source(tb, "/dev/foo", &fs);
29
 
 *  </programlisting>
30
 
 * </informalexample>
31
 
 * will returns the second line, and
32
 
 * <informalexample>
33
 
 *  <programlisting>
34
 
 *      mnt_table_find_source(tb, "LABEL=foo", &fs);
35
 
 *  </programlisting>
36
 
 * </informalexample>
37
 
 * will returns the first entry, and
38
 
 * <informalexample>
39
 
 *  <programlisting>
40
 
 *      mnt_table_find_source(tb, "UUID=anyuuid", &fs);
41
 
 *  </programlisting>
42
 
 * </informalexample>
43
 
 * will returns the first entry (if UUID matches with the device).
44
 
 */
45
 
 
46
 
#include <string.h>
47
 
#include <stdlib.h>
48
 
#include <ctype.h>
49
 
#include <errno.h>
50
 
#include <limits.h>
51
 
#include <sys/types.h>
52
 
#include <sys/stat.h>
53
 
#include <unistd.h>
54
 
#include <blkid.h>
55
 
 
56
 
#include "nls.h"
57
 
#include "mountP.h"
58
 
#include "c.h"
59
 
 
60
 
/**
61
 
 * mnt_new_table:
62
 
 *
63
 
 * The tab is a container for struct libmnt_fs entries that usually represents a fstab,
64
 
 * mtab or mountinfo file from your system.
65
 
 *
66
 
 * See also mnt_table_parse_file().
67
 
 *
68
 
 * Returns: newly allocated tab struct.
69
 
 */
70
 
struct libmnt_table *mnt_new_table(void)
71
 
{
72
 
        struct libmnt_table *tb = NULL;
73
 
 
74
 
        tb = calloc(1, sizeof(*tb));
75
 
        if (!tb)
76
 
                return NULL;
77
 
 
78
 
        DBG(TAB, mnt_debug_h(tb, "alloc"));
79
 
 
80
 
        INIT_LIST_HEAD(&tb->ents);
81
 
        return tb;
82
 
}
83
 
 
84
 
/**
85
 
 * mnt_free_table:
86
 
 * @tb: tab pointer
87
 
 *
88
 
 * Deallocates tab struct and all entries.
89
 
 */
90
 
void mnt_free_table(struct libmnt_table *tb)
91
 
{
92
 
        if (!tb)
93
 
                return;
94
 
 
95
 
        DBG(TAB, mnt_debug_h(tb, "free"));
96
 
 
97
 
        while (!list_empty(&tb->ents)) {
98
 
                struct libmnt_fs *fs = list_entry(tb->ents.next,
99
 
                                                  struct libmnt_fs, ents);
100
 
                mnt_free_fs(fs);
101
 
        }
102
 
 
103
 
        free(tb);
104
 
}
105
 
 
106
 
/**
107
 
 * mnt_table_get_nents:
108
 
 * @tb: pointer to tab
109
 
 *
110
 
 * Returns: number of valid entries in tab.
111
 
 */
112
 
int mnt_table_get_nents(struct libmnt_table *tb)
113
 
{
114
 
        assert(tb);
115
 
        return tb ? tb->nents : 0;
116
 
}
117
 
 
118
 
/**
119
 
 * mnt_table_set_cache:
120
 
 * @tb: pointer to tab
121
 
 * @mpc: pointer to struct libmnt_cache instance
122
 
 *
123
 
 * Setups a cache for canonicalized paths and evaluated tags (LABEL/UUID). The
124
 
 * cache is recommended for mnt_table_find_*() functions.
125
 
 *
126
 
 * The cache could be shared between more tabs. Be careful when you share the
127
 
 * same cache between more threads -- currently the cache does not provide any
128
 
 * locking method.
129
 
 *
130
 
 * See also mnt_new_cache().
131
 
 *
132
 
 * Returns: 0 on success or negative number in case of error.
133
 
 */
134
 
int mnt_table_set_cache(struct libmnt_table *tb, struct libmnt_cache *mpc)
135
 
{
136
 
        assert(tb);
137
 
        if (!tb)
138
 
                return -EINVAL;
139
 
        tb->cache = mpc;
140
 
        return 0;
141
 
}
142
 
 
143
 
/**
144
 
 * mnt_table_get_cache:
145
 
 * @tb: pointer to tab
146
 
 *
147
 
 * Returns: pointer to struct libmnt_cache instance or NULL.
148
 
 */
149
 
struct libmnt_cache *mnt_table_get_cache(struct libmnt_table *tb)
150
 
{
151
 
        assert(tb);
152
 
        return tb ? tb->cache : NULL;
153
 
}
154
 
 
155
 
/**
156
 
 * mnt_table_add_fs:
157
 
 * @tb: tab pointer
158
 
 * @fs: new entry
159
 
 *
160
 
 * Adds a new entry to tab.
161
 
 *
162
 
 * Returns: 0 on success or negative number in case of error.
163
 
 */
164
 
int mnt_table_add_fs(struct libmnt_table *tb, struct libmnt_fs *fs)
165
 
{
166
 
        assert(tb);
167
 
        assert(fs);
168
 
 
169
 
        if (!tb || !fs)
170
 
                return -EINVAL;
171
 
 
172
 
        list_add_tail(&fs->ents, &tb->ents);
173
 
 
174
 
        DBG(TAB, mnt_debug_h(tb, "add entry: %s %s",
175
 
                        mnt_fs_get_source(fs), mnt_fs_get_target(fs)));
176
 
        tb->nents++;
177
 
        return 0;
178
 
}
179
 
 
180
 
/**
181
 
 * mnt_table_remove_fs:
182
 
 * @tb: tab pointer
183
 
 * @fs: new entry
184
 
 *
185
 
 * Returns: 0 on success or negative number in case of error.
186
 
 */
187
 
int mnt_table_remove_fs(struct libmnt_table *tb, struct libmnt_fs *fs)
188
 
{
189
 
        assert(tb);
190
 
        assert(fs);
191
 
 
192
 
        if (!tb || !fs)
193
 
                return -EINVAL;
194
 
        list_del(&fs->ents);
195
 
        tb->nents--;
196
 
        return 0;
197
 
}
198
 
 
199
 
/**
200
 
 * mnt_table_get_root_fs:
201
 
 * @tb: mountinfo file (/proc/self/mountinfo)
202
 
 * @root: returns pointer to the root filesystem (/)
203
 
 *
204
 
 * Returns: 0 on success or -1 case of error.
205
 
 */
206
 
int mnt_table_get_root_fs(struct libmnt_table *tb, struct libmnt_fs **root)
207
 
{
208
 
        struct libmnt_iter itr;
209
 
        struct libmnt_fs *fs;
210
 
        int root_id = 0;
211
 
 
212
 
        assert(tb);
213
 
        assert(root);
214
 
 
215
 
        if (!tb || !root)
216
 
                return -EINVAL;
217
 
 
218
 
        DBG(TAB, mnt_debug_h(tb, "lookup root fs"));
219
 
 
220
 
        mnt_reset_iter(&itr, MNT_ITER_FORWARD);
221
 
        while(mnt_table_next_fs(tb, &itr, &fs) == 0) {
222
 
                int id = mnt_fs_get_parent_id(fs);
223
 
                if (!id)
224
 
                        break;          /* @tab is not mountinfo file? */
225
 
 
226
 
                if (!*root || id < root_id) {
227
 
                        *root = fs;
228
 
                        root_id = id;
229
 
                }
230
 
        }
231
 
 
232
 
        return root_id ? 0 : -EINVAL;
233
 
}
234
 
 
235
 
/**
236
 
 * mnt_table_next_child_fs:
237
 
 * @tb: mountinfo file (/proc/self/mountinfo)
238
 
 * @itr: iterator
239
 
 * @parent: parental FS
240
 
 * @chld: returns the next child filesystem
241
 
 *
242
 
 * Note that filesystems are returned in the order how was mounted (according to
243
 
 * IDs in /proc/self/mountinfo).
244
 
 *
245
 
 * Returns: 0 on success, negative number in case of error or 1 at end of list.
246
 
 */
247
 
int mnt_table_next_child_fs(struct libmnt_table *tb, struct libmnt_iter *itr,
248
 
                        struct libmnt_fs *parent, struct libmnt_fs **chld)
249
 
{
250
 
        struct libmnt_fs *fs;
251
 
        int parent_id, lastchld_id = 0, chld_id = 0;
252
 
 
253
 
        if (!tb || !itr || !parent)
254
 
                return -EINVAL;
255
 
 
256
 
        DBG(TAB, mnt_debug_h(tb, "lookup next child of %s",
257
 
                                mnt_fs_get_target(parent)));
258
 
 
259
 
        parent_id = mnt_fs_get_id(parent);
260
 
        if (!parent_id)
261
 
                return -EINVAL;
262
 
 
263
 
        /* get ID of the previously returned child */
264
 
        if (itr->head && itr->p != itr->head) {
265
 
                MNT_ITER_ITERATE(itr, fs, struct libmnt_fs, ents);
266
 
                lastchld_id = mnt_fs_get_id(fs);
267
 
        }
268
 
 
269
 
        *chld = NULL;
270
 
 
271
 
        mnt_reset_iter(itr, MNT_ITER_FORWARD);
272
 
        while(mnt_table_next_fs(tb, itr, &fs) == 0) {
273
 
                int id;
274
 
 
275
 
                if (mnt_fs_get_parent_id(fs) != parent_id)
276
 
                        continue;
277
 
 
278
 
                id = mnt_fs_get_id(fs);
279
 
 
280
 
                if ((!lastchld_id || id > lastchld_id) &&
281
 
                    (!*chld || id < chld_id)) {
282
 
                        *chld = fs;
283
 
                        chld_id = id;
284
 
                }
285
 
        }
286
 
 
287
 
        if (!chld_id)
288
 
                return 1;       /* end of iterator */
289
 
 
290
 
        /* set the iterator to the @chld for the next call */
291
 
        mnt_table_set_iter(tb, itr, *chld);
292
 
 
293
 
        return 0;
294
 
}
295
 
 
296
 
/**
297
 
 * mnt_table_next_fs:
298
 
 * @tb: tab pointer
299
 
 * @itr: iterator
300
 
 * @fs: returns the next tab entry
301
 
 *
302
 
 * Returns: 0 on success, negative number in case of error or 1 at end of list.
303
 
 *
304
 
 * Example:
305
 
 * <informalexample>
306
 
 *   <programlisting>
307
 
 *      while(mnt_table_next_fs(tb, itr, &fs) == 0) {
308
 
 *              const char *dir = mnt_fs_get_target(fs);
309
 
 *              printf("mount point: %s\n", dir);
310
 
 *      }
311
 
 *      mnt_free_table(fi);
312
 
 *   </programlisting>
313
 
 * </informalexample>
314
 
 *
315
 
 * lists all mountpoints from fstab in backward order.
316
 
 */
317
 
int mnt_table_next_fs(struct libmnt_table *tb, struct libmnt_iter *itr, struct libmnt_fs **fs)
318
 
{
319
 
        int rc = 1;
320
 
 
321
 
        assert(tb);
322
 
        assert(itr);
323
 
        assert(fs);
324
 
 
325
 
        if (!tb || !itr || !fs)
326
 
                return -EINVAL;
327
 
        *fs = NULL;
328
 
 
329
 
        if (!itr->head)
330
 
                MNT_ITER_INIT(itr, &tb->ents);
331
 
        if (itr->p != itr->head) {
332
 
                MNT_ITER_ITERATE(itr, *fs, struct libmnt_fs, ents);
333
 
                rc = 0;
334
 
        }
335
 
 
336
 
        return rc;
337
 
}
338
 
 
339
 
/**
340
 
 * mnt_table_find_next_fs:
341
 
 * @tb: table
342
 
 * @itr: iterator
343
 
 * @match_func: function returns 1 or 0
344
 
 * @userdata: extra data for match_func
345
 
 * @fs: returns pointer to the next matching table entry
346
 
 *
347
 
 * This function allows search in @tb.
348
 
 *
349
 
 * Returns: negative number in case of error, 1 at end of table or 0 o success.
350
 
 */
351
 
int mnt_table_find_next_fs(struct libmnt_table *tb, struct libmnt_iter *itr,
352
 
                int (*match_func)(struct libmnt_fs *, void *), void *userdata,
353
 
                struct libmnt_fs **fs)
354
 
{
355
 
        if (!tb || !itr || !fs || !match_func)
356
 
                return -EINVAL;
357
 
 
358
 
        DBG(TAB, mnt_debug_h(tb, "lookup next fs"));
359
 
 
360
 
        if (!itr->head)
361
 
                MNT_ITER_INIT(itr, &tb->ents);
362
 
 
363
 
        do {
364
 
                if (itr->p != itr->head)
365
 
                        MNT_ITER_ITERATE(itr, *fs, struct libmnt_fs, ents);
366
 
                else
367
 
                        break;                  /* end */
368
 
 
369
 
                if (match_func(*fs, userdata))
370
 
                        return 0;
371
 
        } while(1);
372
 
 
373
 
        *fs = NULL;
374
 
        return 1;
375
 
}
376
 
 
377
 
/**
378
 
 * mnt_table_set_iter:
379
 
 * @tb: tab pointer
380
 
 * @itr: iterator
381
 
 * @fs: tab entry
382
 
 *
383
 
 * Sets @iter to the position of @fs in the file @tb.
384
 
 *
385
 
 * Returns: 0 on success, negative number in case of error.
386
 
 */
387
 
int mnt_table_set_iter(struct libmnt_table *tb, struct libmnt_iter *itr, struct libmnt_fs *fs)
388
 
{
389
 
        assert(tb);
390
 
        assert(itr);
391
 
        assert(fs);
392
 
 
393
 
        if (!tb || !itr || !fs)
394
 
                return -EINVAL;
395
 
 
396
 
        MNT_ITER_INIT(itr, &tb->ents);
397
 
        itr->p = &fs->ents;
398
 
 
399
 
        return 0;
400
 
}
401
 
 
402
 
/**
403
 
 * mnt_table_find_target:
404
 
 * @tb: tab pointer
405
 
 * @path: mountpoint directory
406
 
 * @direction: MNT_ITER_{FORWARD,BACKWARD}
407
 
 *
408
 
 * Try to lookup an entry in given tab, possible are three iterations, first
409
 
 * with @path, second with realpath(@path) and third with realpath(@path)
410
 
 * against realpath(fs->target). The 2nd and 3rd iterations are not performed
411
 
 * when @tb cache is not set (see mnt_table_set_cache()).
412
 
 *
413
 
 * Returns: a tab entry or NULL.
414
 
 */
415
 
struct libmnt_fs *mnt_table_find_target(struct libmnt_table *tb, const char *path, int direction)
416
 
{
417
 
        struct libmnt_iter itr;
418
 
        struct libmnt_fs *fs = NULL;
419
 
        char *cn;
420
 
 
421
 
        assert(tb);
422
 
        assert(path);
423
 
 
424
 
        if (!tb || !path)
425
 
                return NULL;
426
 
 
427
 
        DBG(TAB, mnt_debug_h(tb, "lookup TARGET: %s", path));
428
 
 
429
 
        /* native @target */
430
 
        mnt_reset_iter(&itr, direction);
431
 
        while(mnt_table_next_fs(tb, &itr, &fs) == 0)
432
 
                if (fs->target && strcmp(fs->target, path) == 0)
433
 
                        return fs;
434
 
 
435
 
        if (!tb->cache || !(cn = mnt_resolve_path(path, tb->cache)))
436
 
                return NULL;
437
 
 
438
 
        /* canonicalized paths in struct libmnt_table */
439
 
        mnt_reset_iter(&itr, direction);
440
 
        while(mnt_table_next_fs(tb, &itr, &fs) == 0) {
441
 
                if (fs->target && strcmp(fs->target, cn) == 0)
442
 
                        return fs;
443
 
        }
444
 
 
445
 
        /* non-canonicaled path in struct libmnt_table */
446
 
        mnt_reset_iter(&itr, direction);
447
 
        while(mnt_table_next_fs(tb, &itr, &fs) == 0) {
448
 
                char *p;
449
 
 
450
 
                if (!fs->target || !(fs->flags & MNT_FS_SWAP) ||
451
 
                    (*fs->target == '/' && *(fs->target + 1) == '\0'))
452
 
                       continue;
453
 
 
454
 
                p = mnt_resolve_path(fs->target, tb->cache);
455
 
                if (strcmp(cn, p) == 0)
456
 
                        return fs;
457
 
        }
458
 
        return NULL;
459
 
}
460
 
 
461
 
/**
462
 
 * mnt_table_find_srcpath:
463
 
 * @tb: tab pointer
464
 
 * @path: source path (devname or dirname)
465
 
 * @direction: MNT_ITER_{FORWARD,BACKWARD}
466
 
 *
467
 
 * Try to lookup an entry in given tab, possible are four iterations, first
468
 
 * with @path, second with realpath(@path), third with tags (LABEL, UUID, ..)
469
 
 * from @path and fourth with realpath(@path) against realpath(entry->srcpath).
470
 
 *
471
 
 * The 2nd, 3rd and 4th iterations are not performed when @tb cache is not
472
 
 * set (see mnt_table_set_cache()).
473
 
 *
474
 
 * Returns: a tab entry or NULL.
475
 
 */
476
 
struct libmnt_fs *mnt_table_find_srcpath(struct libmnt_table *tb, const char *path, int direction)
477
 
{
478
 
        struct libmnt_iter itr;
479
 
        struct libmnt_fs *fs = NULL;
480
 
        int ntags = 0;
481
 
        char *cn;
482
 
        const char *p;
483
 
 
484
 
        assert(tb);
485
 
        assert(path);
486
 
 
487
 
        DBG(TAB, mnt_debug_h(tb, "lookup srcpath: %s", path));
488
 
 
489
 
        /* native paths */
490
 
        mnt_reset_iter(&itr, direction);
491
 
        while(mnt_table_next_fs(tb, &itr, &fs) == 0) {
492
 
                p = mnt_fs_get_srcpath(fs);
493
 
                if (p && strcmp(p, path) == 0)
494
 
                        return fs;
495
 
                if (!p)
496
 
                        /* mnt_fs_get_srcpath() returs nothing, it's TAG */
497
 
                        ntags++;
498
 
        }
499
 
 
500
 
        if (!tb->cache || !(cn = mnt_resolve_path(path, tb->cache)))
501
 
                return NULL;
502
 
 
503
 
        /* canonicalized paths in struct libmnt_table */
504
 
        if (ntags < mnt_table_get_nents(tb)) {
505
 
                mnt_reset_iter(&itr, direction);
506
 
                while(mnt_table_next_fs(tb, &itr, &fs) == 0) {
507
 
                        p = mnt_fs_get_srcpath(fs);
508
 
                        if (p && strcmp(p, cn) == 0)
509
 
                                return fs;
510
 
                }
511
 
        }
512
 
 
513
 
        /* evaluated tag */
514
 
        if (ntags) {
515
 
                int rc = mnt_cache_read_tags(tb->cache, cn);
516
 
 
517
 
                mnt_reset_iter(&itr, direction);
518
 
 
519
 
                if (rc == 0) {
520
 
                        /* @path's TAGs are in the cache */
521
 
                        while(mnt_table_next_fs(tb, &itr, &fs) == 0) {
522
 
                                const char *t, *v;
523
 
 
524
 
                                if (mnt_fs_get_tag(fs, &t, &v))
525
 
                                        continue;
526
 
 
527
 
                                if (mnt_cache_device_has_tag(tb->cache, cn, t, v))
528
 
                                        return fs;
529
 
                        }
530
 
                } else if (rc < 0 && errno == EACCES) {
531
 
                        /* @path is unaccessible, try evaluate all TAGs in @tb
532
 
                         * by udev symlinks -- this could be expensive on systems
533
 
                         * with huge fstab/mtab */
534
 
                         while(mnt_table_next_fs(tb, &itr, &fs) == 0) {
535
 
                                 const char *t, *v, *x;
536
 
                                 if (mnt_fs_get_tag(fs, &t, &v))
537
 
                                         continue;
538
 
                                 x = mnt_resolve_tag(t, v, tb->cache);
539
 
                                 if (x && !strcmp(x, cn))
540
 
                                         return fs;
541
 
                         }
542
 
                }
543
 
        }
544
 
 
545
 
        /* non-canonicalized paths in struct libmnt_table */
546
 
        if (ntags <= mnt_table_get_nents(tb)) {
547
 
                mnt_reset_iter(&itr, direction);
548
 
                while(mnt_table_next_fs(tb, &itr, &fs) == 0) {
549
 
                        if (fs->flags & (MNT_FS_NET | MNT_FS_PSEUDO))
550
 
                                continue;
551
 
                        p = mnt_fs_get_srcpath(fs);
552
 
                        if (p)
553
 
                                p = mnt_resolve_path(p, tb->cache);
554
 
                        if (p && strcmp(cn, p) == 0)
555
 
                                return fs;
556
 
                }
557
 
        }
558
 
 
559
 
        return NULL;
560
 
}
561
 
 
562
 
 
563
 
/**
564
 
 * mnt_table_find_tag:
565
 
 * @tb: tab pointer
566
 
 * @tag: tag name (e.g "LABEL", "UUID", ...)
567
 
 * @val: tag value
568
 
 * @direction: MNT_ITER_{FORWARD,BACKWARD}
569
 
 *
570
 
 * Try to lookup an entry in given tab, first attempt is lookup by @tag and
571
 
 * @val, for the second attempt the tag is evaluated (converted to the device
572
 
 * name) and mnt_table_find_srcpath() is preformed. The second attempt is not
573
 
 * performed when @tb cache is not set (see mnt_table_set_cache()).
574
 
 
575
 
 * Returns: a tab entry or NULL.
576
 
 */
577
 
struct libmnt_fs *mnt_table_find_tag(struct libmnt_table *tb, const char *tag,
578
 
                        const char *val, int direction)
579
 
{
580
 
        struct libmnt_iter itr;
581
 
        struct libmnt_fs *fs = NULL;
582
 
 
583
 
        assert(tb);
584
 
        assert(tag);
585
 
        assert(val);
586
 
 
587
 
        if (!tb || !tag || !val)
588
 
                return NULL;
589
 
 
590
 
        DBG(TAB, mnt_debug_h(tb, "lookup by TAG: %s %s", tag, val));
591
 
 
592
 
        /* look up by TAG */
593
 
        mnt_reset_iter(&itr, direction);
594
 
        while(mnt_table_next_fs(tb, &itr, &fs) == 0) {
595
 
                if (fs->tagname && fs->tagval &&
596
 
                    strcmp(fs->tagname, tag) == 0 &&
597
 
                    strcmp(fs->tagval, val) == 0)
598
 
                        return fs;
599
 
        }
600
 
 
601
 
        if (tb->cache) {
602
 
                /* look up by device name */
603
 
                char *cn = mnt_resolve_tag(tag, val, tb->cache);
604
 
                if (cn)
605
 
                        return mnt_table_find_srcpath(tb, cn, direction);
606
 
        }
607
 
        return NULL;
608
 
}
609
 
 
610
 
/**
611
 
 * mnt_table_find_source:
612
 
 * @tb: tab pointer
613
 
 * @source: TAG or path
614
 
 * @direction: MNT_ITER_{FORWARD,BACKWARD}
615
 
 *
616
 
 * This is high-level API for mnt_table_find_{srcpath,tag}. You needn't to care
617
 
 * about @source format (device, LABEL, UUID, ...). This function parses @source
618
 
 * and calls mnt_table_find_tag() or mnt_table_find_srcpath().
619
 
 *
620
 
 * Returns: a tab entry or NULL.
621
 
 */
622
 
struct libmnt_fs *mnt_table_find_source(struct libmnt_table *tb, const char *source, int direction)
623
 
{
624
 
        struct libmnt_fs *fs = NULL;
625
 
 
626
 
        assert(tb);
627
 
        assert(source);
628
 
 
629
 
        if (!tb || !source)
630
 
                return NULL;
631
 
 
632
 
        DBG(TAB, mnt_debug_h(tb, "lookup SOURCE: %s", source));
633
 
 
634
 
        if (strchr(source, '=')) {
635
 
                char *tag, *val;
636
 
 
637
 
                if (blkid_parse_tag_string(source, &tag, &val) == 0) {
638
 
 
639
 
                        fs = mnt_table_find_tag(tb, tag, val, direction);
640
 
 
641
 
                        free(tag);
642
 
                        free(val);
643
 
                }
644
 
        } else
645
 
                fs = mnt_table_find_srcpath(tb, source, direction);
646
 
 
647
 
        return fs;
648
 
}
649
 
 
650
 
/**
651
 
 * mnt_table_find_pair
652
 
 * @tb: tab pointer
653
 
 * @source: TAG or path
654
 
 * @target: mountpoint
655
 
 * @direction: MNT_ITER_{FORWARD,BACKWARD}
656
 
 *
657
 
 * This function is implemented by mnt_fs_match_source() and
658
 
 * mnt_fs_match_target() functions. It means that this is more expensive that
659
 
 * others mnt_table_find_* function, because every @tab entry is fully evaluated.
660
 
 *
661
 
 * Returns: a tab entry or NULL.
662
 
 */
663
 
struct libmnt_fs *mnt_table_find_pair(struct libmnt_table *tb, const char *source,
664
 
                        const char *target, int direction)
665
 
{
666
 
        struct libmnt_fs *fs = NULL;
667
 
        struct libmnt_iter itr;
668
 
 
669
 
        assert(tb);
670
 
        assert(source);
671
 
        assert(target);
672
 
 
673
 
        if (!tb || !source || !target)
674
 
                return NULL;
675
 
 
676
 
        DBG(TAB, mnt_debug_h(tb, "lookup SOURCE: %s TARGET: %s", source, target));
677
 
 
678
 
        mnt_reset_iter(&itr, direction);
679
 
        while(mnt_table_next_fs(tb, &itr, &fs) == 0) {
680
 
 
681
 
                if (mnt_fs_match_target(fs, target, tb->cache) &&
682
 
                    mnt_fs_match_source(fs, source, tb->cache))
683
 
                        return fs;
684
 
        }
685
 
 
686
 
        return NULL;
687
 
}
688
 
 
689
 
#ifdef TEST_PROGRAM
690
 
 
691
 
static int parser_errcb(struct libmnt_table *tb, const char *filename, int line)
692
 
{
693
 
        fprintf(stderr, "%s:%d: parse error\n", filename, line);
694
 
 
695
 
        return 1;       /* all errors are recoverable -- this is default */
696
 
}
697
 
 
698
 
struct libmnt_table *create_table(const char *file)
699
 
{
700
 
        struct libmnt_table *tb;
701
 
 
702
 
        if (!file)
703
 
                return NULL;
704
 
        tb = mnt_new_table();
705
 
        if (!tb)
706
 
                goto err;
707
 
 
708
 
        mnt_table_set_parser_errcb(tb, parser_errcb);
709
 
 
710
 
        if (mnt_table_parse_file(tb, file) != 0)
711
 
                goto err;
712
 
        return tb;
713
 
err:
714
 
        fprintf(stderr, "%s: parsing failed\n", file);
715
 
        mnt_free_table(tb);
716
 
        return NULL;
717
 
}
718
 
 
719
 
int test_copy_fs(struct libmnt_test *ts, int argc, char *argv[])
720
 
{
721
 
        struct libmnt_table *tb;
722
 
        struct libmnt_fs *fs;
723
 
        int rc = -1;
724
 
 
725
 
        tb = create_table(argv[1]);
726
 
        if (!tb)
727
 
                return -1;
728
 
 
729
 
        fs = mnt_table_find_target(tb, "/", MNT_ITER_FORWARD);
730
 
        if (!fs)
731
 
                goto done;
732
 
 
733
 
        printf("ORIGINAL:\n");
734
 
        mnt_fs_print_debug(fs, stdout);
735
 
 
736
 
        fs = mnt_copy_fs(NULL, fs);
737
 
        if (!fs)
738
 
                goto done;
739
 
 
740
 
        printf("COPY:\n");
741
 
        mnt_fs_print_debug(fs, stdout);
742
 
        mnt_free_fs(fs);
743
 
        rc = 0;
744
 
done:
745
 
        mnt_free_table(tb);
746
 
        return rc;
747
 
}
748
 
 
749
 
int test_parse(struct libmnt_test *ts, int argc, char *argv[])
750
 
{
751
 
        struct libmnt_table *tb = NULL;
752
 
        struct libmnt_iter *itr = NULL;
753
 
        struct libmnt_fs *fs;
754
 
        int rc = -1;
755
 
 
756
 
        tb = create_table(argv[1]);
757
 
        if (!tb)
758
 
                return -1;
759
 
 
760
 
        itr = mnt_new_iter(MNT_ITER_FORWARD);
761
 
        if (!itr)
762
 
                goto done;
763
 
 
764
 
        while(mnt_table_next_fs(tb, itr, &fs) == 0)
765
 
                mnt_fs_print_debug(fs, stdout);
766
 
        rc = 0;
767
 
done:
768
 
        mnt_free_iter(itr);
769
 
        mnt_free_table(tb);
770
 
        return rc;
771
 
}
772
 
 
773
 
int test_find(struct libmnt_test *ts, int argc, char *argv[], int dr)
774
 
{
775
 
        struct libmnt_table *tb;
776
 
        struct libmnt_fs *fs = NULL;
777
 
        struct libmnt_cache *mpc = NULL;
778
 
        const char *file, *find, *what;
779
 
        int rc = -1;
780
 
 
781
 
        if (argc != 4) {
782
 
                fprintf(stderr, "try --help\n");
783
 
                return -EINVAL;
784
 
        }
785
 
 
786
 
        file = argv[1], find = argv[2], what = argv[3];
787
 
 
788
 
        tb = create_table(file);
789
 
        if (!tb)
790
 
                goto done;
791
 
 
792
 
        /* create a cache for canonicalized paths */
793
 
        mpc = mnt_new_cache();
794
 
        if (!mpc)
795
 
                goto done;
796
 
        mnt_table_set_cache(tb, mpc);
797
 
 
798
 
        if (strcasecmp(find, "source") == 0)
799
 
                fs = mnt_table_find_source(tb, what, dr);
800
 
        else if (strcasecmp(find, "target") == 0)
801
 
                fs = mnt_table_find_target(tb, what, dr);
802
 
 
803
 
        if (!fs)
804
 
                fprintf(stderr, "%s: not found %s '%s'\n", file, find, what);
805
 
        else {
806
 
                mnt_fs_print_debug(fs, stdout);
807
 
                rc = 0;
808
 
        }
809
 
done:
810
 
        mnt_free_table(tb);
811
 
        mnt_free_cache(mpc);
812
 
        return rc;
813
 
}
814
 
 
815
 
int test_find_bw(struct libmnt_test *ts, int argc, char *argv[])
816
 
{
817
 
        return test_find(ts, argc, argv, MNT_ITER_BACKWARD);
818
 
}
819
 
 
820
 
int test_find_fw(struct libmnt_test *ts, int argc, char *argv[])
821
 
{
822
 
        return test_find(ts, argc, argv, MNT_ITER_FORWARD);
823
 
}
824
 
 
825
 
int test_find_pair(struct libmnt_test *ts, int argc, char *argv[])
826
 
{
827
 
        struct libmnt_table *tb;
828
 
        struct libmnt_fs *fs;
829
 
        int rc = -1;
830
 
 
831
 
        tb = create_table(argv[1]);
832
 
        if (!tb)
833
 
                return -1;
834
 
 
835
 
        fs = mnt_table_find_pair(tb, argv[2], argv[3], MNT_ITER_FORWARD);
836
 
        if (!fs)
837
 
                goto done;
838
 
 
839
 
        mnt_fs_print_debug(fs, stdout);
840
 
        rc = 0;
841
 
done:
842
 
        mnt_free_table(tb);
843
 
        return rc;
844
 
}
845
 
 
846
 
int main(int argc, char *argv[])
847
 
{
848
 
        struct libmnt_test tss[] = {
849
 
        { "--parse",    test_parse,        "<file>  parse and print tab" },
850
 
        { "--find-forward",  test_find_fw, "<file> <source|target> <string>" },
851
 
        { "--find-backward", test_find_bw, "<file> <source|target> <string>" },
852
 
        { "--find-pair",     test_find_pair, "<file> <source> <target>" },
853
 
        { "--copy-fs",       test_copy_fs, "<file>  copy root FS from the file" },
854
 
        { NULL }
855
 
        };
856
 
 
857
 
        return mnt_run_test(tss, argc, argv);
858
 
}
859
 
 
860
 
#endif /* TEST_PROGRAM */