12 |
#include "libbb.h" |
#include "libbb.h" |
13 |
|
|
14 |
int mountpoint_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
int mountpoint_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
15 |
int mountpoint_main(int argc, char **argv) |
int mountpoint_main(int argc UNUSED_PARAM, char **argv) |
16 |
{ |
{ |
17 |
struct stat st; |
struct stat st; |
18 |
|
const char *msg; |
19 |
char *arg; |
char *arg; |
20 |
int opt = getopt32(argv, "qdx"); |
int rc, opt; |
21 |
|
|
22 |
|
opt_complementary = "=1"; /* must have one argument */ |
23 |
|
opt = getopt32(argv, "qdxn"); |
24 |
#define OPT_q (1) |
#define OPT_q (1) |
25 |
#define OPT_d (2) |
#define OPT_d (2) |
26 |
#define OPT_x (4) |
#define OPT_x (4) |
27 |
|
#define OPT_n (8) |
28 |
|
arg = argv[optind]; |
29 |
|
msg = "%s"; |
30 |
|
|
31 |
if (optind != argc - 1) |
rc = (opt & OPT_x) ? stat(arg, &st) : lstat(arg, &st); |
32 |
bb_show_usage(); |
if (rc != 0) |
33 |
|
goto err; |
34 |
|
|
35 |
arg = argv[optind]; |
if (opt & OPT_x) { |
36 |
|
if (S_ISBLK(st.st_mode)) { |
37 |
|
printf("%u:%u\n", major(st.st_rdev), |
38 |
|
minor(st.st_rdev)); |
39 |
|
return EXIT_SUCCESS; |
40 |
|
} |
41 |
|
errno = 0; /* make perror_msg work as error_msg */ |
42 |
|
msg = "%s: not a block device"; |
43 |
|
goto err; |
44 |
|
} |
45 |
|
|
46 |
if ( (opt & OPT_x && stat(arg, &st) == 0) || (lstat(arg, &st) == 0) ) { |
errno = ENOTDIR; |
47 |
if (opt & OPT_x) { |
if (S_ISDIR(st.st_mode)) { |
48 |
if (S_ISBLK(st.st_mode)) { |
dev_t st_dev = st.st_dev; |
49 |
printf("%u:%u\n", major(st.st_rdev), |
ino_t st_ino = st.st_ino; |
50 |
minor(st.st_rdev)); |
char *p = xasprintf("%s/..", arg); |
51 |
return EXIT_SUCCESS; |
|
52 |
} else { |
if (stat(p, &st) == 0) { |
53 |
if (opt & OPT_q) |
//int is_mnt = (st_dev != st.st_dev) || (st_dev == st.st_dev && st_ino == st.st_ino); |
54 |
bb_putchar('\n'); |
int is_not_mnt = (st_dev == st.st_dev) && (st_ino != st.st_ino); |
55 |
else |
|
56 |
bb_error_msg("%s: not a block device", arg); |
if (opt & OPT_d) |
57 |
} |
printf("%u:%u\n", major(st_dev), minor(st_dev)); |
58 |
return EXIT_FAILURE; |
if (opt & OPT_n) { |
59 |
} else |
const char *d = find_block_device(arg); |
60 |
if (S_ISDIR(st.st_mode)) { |
/* name is undefined, but device is mounted -> anonymous superblock! */ |
61 |
dev_t st_dev = st.st_dev; |
/* happens with btrfs */ |
62 |
ino_t st_ino = st.st_ino; |
if (!d) { |
63 |
char *p = xasprintf("%s/..", arg); |
d = "UNKNOWN"; |
64 |
|
/* TODO: iterate /proc/mounts, or /proc/self/mountinfo |
65 |
if (stat(p, &st) == 0) { |
* to find out the device name */ |
66 |
int ret = (st_dev != st.st_dev) || |
} |
67 |
(st_dev == st.st_dev && st_ino == st.st_ino); |
printf("%s %s\n", d, arg); |
|
if (opt & OPT_d) |
|
|
printf("%u:%u\n", major(st_dev), minor(st_dev)); |
|
|
else if (!(opt & OPT_q)) |
|
|
printf("%s is %sa mountpoint\n", arg, ret?"":"not "); |
|
|
return !ret; |
|
68 |
} |
} |
69 |
} else { |
if (!(opt & (OPT_q | OPT_d | OPT_n))) |
70 |
if (!(opt & OPT_q)) |
printf("%s is %sa mountpoint\n", arg, is_not_mnt ? "not " : ""); |
71 |
bb_error_msg("%s: not a directory", arg); |
return is_not_mnt; |
|
return EXIT_FAILURE; |
|
72 |
} |
} |
73 |
|
arg = p; |
74 |
|
/* else: stat had set errno, just fall through */ |
75 |
} |
} |
76 |
|
|
77 |
|
err: |
78 |
if (!(opt & OPT_q)) |
if (!(opt & OPT_q)) |
79 |
bb_simple_perror_msg(arg); |
bb_perror_msg(msg, arg); |
80 |
return EXIT_FAILURE; |
return EXIT_FAILURE; |
81 |
} |
} |