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

« back to all changes in this revision

Viewing changes to sys-utils/mountpoint.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
 * mountpoint(1) - see if a directory is a mountpoint
 
3
 *
 
4
 * This is libmount based reimplementation of the mountpoit(1)
 
5
 * from sysvinit project.
 
6
 *
 
7
 *
 
8
 * Copyright (C) 2011 Red Hat, Inc. All rights reserved.
 
9
 * Written by Karel Zak <kzak@redhat.com>
 
10
 *
 
11
 * This program is free software; you can redistribute it and/or modify
 
12
 * it under the terms of the GNU General Public License as published by
 
13
 * the Free Software Foundation; either version 2 of the License, or
 
14
 * (at your option) any later version.
 
15
 *
 
16
 * This program is distributed in the hope that it would be useful,
 
17
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
18
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
19
 * GNU General Public License for more details.
 
20
 *
 
21
 * You should have received a copy of the GNU General Public License
 
22
 * along with this program; if not, write to the Free Software Foundation,
 
23
 * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
24
 */
 
25
 
 
26
#include <stdio.h>
 
27
#include <stdlib.h>
 
28
#include <errno.h>
 
29
#include <string.h>
 
30
#include <getopt.h>
 
31
#include <unistd.h>
 
32
#include <sys/types.h>
 
33
#include <sys/stat.h>
 
34
 
 
35
#include <libmount.h>
 
36
 
 
37
#include "nls.h"
 
38
#include "xalloc.h"
 
39
#include "c.h"
 
40
 
 
41
static int quiet;
 
42
 
 
43
static dev_t dir_to_device(const char *spec)
 
44
{
 
45
        struct libmnt_table *tb = mnt_new_table_from_file("/proc/self/mountinfo");
 
46
        struct libmnt_fs *fs;
 
47
        struct libmnt_cache *cache;
 
48
        dev_t res = 0;
 
49
 
 
50
        if (!tb) {
 
51
                /*
 
52
                 * Fallback. Traditional way to detect mountpoints. This way
 
53
                 * is independent on /proc, but not able to detect bind mounts.
 
54
                 */
 
55
                struct stat pst, st;
 
56
                char buf[PATH_MAX], *cn;
 
57
                int len;
 
58
 
 
59
                if (stat(spec, &st) != 0)
 
60
                        return 0;
 
61
 
 
62
                cn = mnt_resolve_path(spec, NULL);      /* canonicalize */
 
63
 
 
64
                len = snprintf(buf, sizeof(buf), "%s/..", cn ? cn : spec);
 
65
                free(cn);
 
66
 
 
67
                if (len < 0 || (size_t) len + 1 > sizeof(buf))
 
68
                        return 0;
 
69
                if (stat(buf, &pst) !=0)
 
70
                        return 0;
 
71
 
 
72
                if ((st.st_dev != pst.st_dev) ||
 
73
                    (st.st_dev == pst.st_dev && st.st_ino == pst.st_ino))
 
74
                        return st.st_dev;
 
75
 
 
76
                return 0;
 
77
        }
 
78
 
 
79
        /* to canonicalize all necessary paths */
 
80
        cache = mnt_new_cache();
 
81
        mnt_table_set_cache(tb, cache);
 
82
 
 
83
        fs = mnt_table_find_target(tb, spec, MNT_ITER_BACKWARD);
 
84
        if (fs && mnt_fs_get_target(fs))
 
85
                res = mnt_fs_get_devno(fs);
 
86
 
 
87
        mnt_free_table(tb);
 
88
        mnt_free_cache(cache);
 
89
        return res;
 
90
}
 
91
 
 
92
static int print_devno(const char *devname, struct stat *st)
 
93
{
 
94
        struct stat stbuf;
 
95
 
 
96
        if (!st && stat(devname, &stbuf) == 0)
 
97
                st = &stbuf;
 
98
        if (!st)
 
99
                return -1;
 
100
        if (!S_ISBLK(st->st_mode)) {
 
101
                if (!quiet)
 
102
                        warnx(_("%s: not a block device"), devname);
 
103
                return -1;
 
104
        }
 
105
        printf("%u:%u\n", major(st->st_rdev), minor(st->st_rdev));
 
106
        return 0;
 
107
}
 
108
 
 
109
static void __attribute__((__noreturn__)) usage(FILE *out)
 
110
{
 
111
        fputs(_("\nUsage:\n"), out);
 
112
        fprintf(out,
 
113
              _(" %1$s [-qd] /path/to/directory\n"
 
114
                " %1$s -x /dev/device\n"), program_invocation_short_name);
 
115
 
 
116
        fputs(_("\nOptions:\n"), out);
 
117
        fputs(_(" -q, --quiet        quiet mode - don't print anything\n"
 
118
                " -d, --fs-devno     print maj:min device number of the filesystem\n"
 
119
                " -x, --devno        print maj:min device number of the block device\n"
 
120
                " -h, --help         this help\n"), out);
 
121
 
 
122
        fprintf(out, _("\nFor more information see mountpoint(1).\n"));
 
123
 
 
124
        exit(out == stderr ? EXIT_FAILURE : EXIT_SUCCESS);
 
125
}
 
126
 
 
127
int main(int argc, char **argv)
 
128
{
 
129
        int c, fs_devno = 0, dev_devno = 0, rc = 0;
 
130
        char *spec;
 
131
        struct stat st;
 
132
 
 
133
        static const struct option longopts[] = {
 
134
                { "quiet", 0, 0, 'q' },
 
135
                { "fs-devno", 0, 0, 'd' },
 
136
                { "devno", 0, 0, 'x' },
 
137
                { "help", 0, 0, 'h' },
 
138
                { NULL, 0, 0, 0 }
 
139
        };
 
140
 
 
141
        setlocale(LC_ALL, "");
 
142
        bindtextdomain(PACKAGE, LOCALEDIR);
 
143
        textdomain(PACKAGE);
 
144
 
 
145
        mnt_init_debug(0);
 
146
 
 
147
        while ((c = getopt_long(argc, argv, "qdxh", longopts, NULL)) != -1) {
 
148
 
 
149
                switch(c) {
 
150
                case 'q':
 
151
                        quiet = 1;
 
152
                        break;
 
153
                case 'd':
 
154
                        fs_devno = 1;
 
155
                        break;
 
156
                case 'x':
 
157
                        dev_devno = 1;
 
158
                        break;
 
159
                case 'h':
 
160
                        usage(stdout);
 
161
                        break;
 
162
                default:
 
163
                        usage(stderr);
 
164
                        break;
 
165
                }
 
166
        }
 
167
 
 
168
        if (optind + 1 != argc)
 
169
                usage(stderr);
 
170
 
 
171
        spec = argv[optind++];
 
172
 
 
173
        if (stat(spec, &st)) {
 
174
                if (!quiet)
 
175
                        err(EXIT_FAILURE, "%s", spec);
 
176
                return EXIT_FAILURE;
 
177
        }
 
178
        if (dev_devno)
 
179
                rc = print_devno(spec, &st);
 
180
        else {
 
181
                dev_t src;
 
182
 
 
183
                if (!S_ISDIR(st.st_mode)) {
 
184
                        if (!quiet)
 
185
                                errx(EXIT_FAILURE, _("%s: not a directory"), spec);
 
186
                        return EXIT_FAILURE;
 
187
                }
 
188
                src = dir_to_device(spec);
 
189
                if (!src) {
 
190
                        if (!quiet)
 
191
                                printf(_("%s is not a mountpoint\n"), spec);
 
192
                        return EXIT_FAILURE;
 
193
                }
 
194
                if (fs_devno)
 
195
                        printf("%u:%u\n", major(src), minor(src));
 
196
                else if (!quiet)
 
197
                        printf(_("%s is a mountpoint\n"), spec);
 
198
        }
 
199
 
 
200
        return rc ? EXIT_FAILURE : EXIT_SUCCESS;
 
201
}