Include -Wunreachable-code when building.
[sysvinit.git] / src / mountpoint.c
1 /*
2 * mountpoint See if a directory is a mountpoint.
3 *
4 * Author: Miquel van Smoorenburg.
5 *
6 * Version: @(#)mountpoint 2.85-12 17-Mar-2004 miquels@cistron.nl
7 *
8 * This file is part of the sysvinit suite,
9 * Copyright (C) 1991-2004 Miquel van Smoorenburg.
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 will 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
23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
24 */
25
26 #include <sys/stat.h>
27 #include <unistd.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <errno.h>
31 #include <stdarg.h>
32 #include <getopt.h>
33 #include <stdio.h>
34
35 int dostat(char *path, struct stat *st, int do_lstat, int quiet)
36 {
37 int n;
38
39 if (do_lstat)
40 n = lstat(path, st);
41 else
42 n = stat(path, st);
43
44 if (n != 0) {
45 if (!quiet)
46 fprintf(stderr, "mountpoint: %s: %s\n", path,
47 strerror(errno));
48 return -1;
49 }
50 return 0;
51 }
52
53 void usage(void) {
54 fprintf(stderr, "Usage: mountpoint [-q] [-d] [-x] path\n");
55 exit(1);
56 }
57
58 int main(int argc, char **argv)
59 {
60 struct stat st, st2;
61 char buf[256];
62 char *path;
63 int quiet = 0;
64 int showdev = 0;
65 int xdev = 0;
66 int c, r;
67
68 while ((c = getopt(argc, argv, "dqx")) != EOF) switch(c) {
69 case 'd':
70 showdev = 1;
71 break;
72 case 'q':
73 quiet = 1;
74 break;
75 case 'x':
76 xdev = 1;
77 break;
78 default:
79 usage();
80 break;
81 }
82 if (optind != argc - 1) usage();
83 path = argv[optind];
84
85 if (dostat(path, &st, !xdev, quiet) < 0)
86 return 1;
87
88 if (xdev) {
89 #ifdef __linux__
90 if (!S_ISBLK(st.st_mode))
91 #else
92 if (!S_ISBLK(st.st_mode) && !S_ISCHR(st.st_mode))
93 #endif
94 {
95 if (quiet)
96 printf("\n");
97 else
98 fprintf(stderr, "mountpoint: %s: not a block device\n",
99 path);
100 return 1;
101 }
102 printf("%u:%u\n", major(st.st_rdev), minor(st.st_rdev));
103 return 0;
104 }
105
106 if (!S_ISDIR(st.st_mode)) {
107 if (!quiet)
108 fprintf(stderr, "mountpoint: %s: not a directory\n",
109 path);
110 return 1;
111 }
112
113 memset(buf, 0, sizeof(buf));
114 strncpy(buf, path, sizeof(buf) - 4);
115 strcat(buf, "/..");
116 if (dostat(buf, &st2, 0, quiet) < 0)
117 return 1;
118
119 r = (st.st_dev != st2.st_dev) ||
120 (st.st_dev == st2.st_dev && st.st_ino == st2.st_ino);
121
122 if (!quiet && !showdev)
123 printf("%s is %sa mountpoint\n", path, r ? "" : "not ");
124 if (showdev)
125 printf("%u:%u\n", major(st.st_dev), minor(st.st_dev));
126
127 return r ? 0 : 1;
128 }