Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/contrib/openzfs/lib/libspl/os/linux/getmntany.c
48546 views
1
// SPDX-License-Identifier: CDDL-1.0
2
/*
3
* CDDL HEADER START
4
*
5
* The contents of this file are subject to the terms of the
6
* Common Development and Distribution License, Version 1.0 only
7
* (the "License"). You may not use this file except in compliance
8
* with the License.
9
*
10
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
11
* or https://opensource.org/licenses/CDDL-1.0.
12
* See the License for the specific language governing permissions
13
* and limitations under the License.
14
*
15
* When distributing Covered Code, include this CDDL HEADER in each
16
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
17
* If applicable, add the following below this CDDL HEADER, with the
18
* fields enclosed by brackets "[]" replaced with your own identifying
19
* information: Portions Copyright [yyyy] [name of copyright owner]
20
*
21
* CDDL HEADER END
22
*/
23
/*
24
* Copyright 2005 Sun Microsystems, Inc. All rights reserved.
25
* Copyright 2006 Ricardo Correia. All rights reserved.
26
* Use is subject to license terms.
27
*/
28
29
/* Copyright (c) 1988 AT&T */
30
/* All Rights Reserved */
31
32
#include <stdio.h>
33
#include <string.h>
34
#include <mntent.h>
35
#include <sys/errno.h>
36
#include <sys/mnttab.h>
37
38
#include <sys/types.h>
39
#include <sys/sysmacros.h>
40
#include <sys/stat.h>
41
#include <unistd.h>
42
#include <libzutil.h>
43
44
#define BUFSIZE (MNT_LINE_MAX + 2)
45
46
static __thread char buf[BUFSIZE];
47
48
#define DIFF(xx) ( \
49
(mrefp->xx != NULL) && \
50
(mgetp->xx == NULL || strcmp(mrefp->xx, mgetp->xx) != 0))
51
52
int
53
getmntany(FILE *fp, struct mnttab *mgetp, struct mnttab *mrefp)
54
{
55
int ret;
56
57
while (
58
((ret = _sol_getmntent(fp, mgetp)) == 0) && (
59
DIFF(mnt_special) || DIFF(mnt_mountp) ||
60
DIFF(mnt_fstype) || DIFF(mnt_mntopts))) { }
61
62
return (ret);
63
}
64
65
int
66
_sol_getmntent(FILE *fp, struct mnttab *mgetp)
67
{
68
struct mntent mntbuf;
69
struct mntent *ret;
70
71
ret = getmntent_r(fp, &mntbuf, buf, BUFSIZE);
72
73
if (ret != NULL) {
74
mgetp->mnt_special = mntbuf.mnt_fsname;
75
mgetp->mnt_mountp = mntbuf.mnt_dir;
76
mgetp->mnt_fstype = mntbuf.mnt_type;
77
mgetp->mnt_mntopts = mntbuf.mnt_opts;
78
return (0);
79
}
80
81
if (feof(fp))
82
return (-1);
83
84
return (MNT_TOOLONG);
85
}
86
87
static int
88
getextmntent_impl(FILE *fp, struct extmnttab *mp, uint64_t *mnt_id)
89
{
90
int ret;
91
struct stat64 st;
92
93
*mnt_id = 0;
94
ret = _sol_getmntent(fp, (struct mnttab *)mp);
95
if (ret == 0) {
96
#ifdef HAVE_STATX_MNT_ID
97
struct statx stx;
98
if (statx(AT_FDCWD, mp->mnt_mountp,
99
AT_STATX_SYNC_AS_STAT | AT_SYMLINK_NOFOLLOW,
100
STATX_MNT_ID, &stx) == 0 && (stx.stx_mask & STATX_MNT_ID))
101
*mnt_id = stx.stx_mnt_id;
102
#endif
103
if (stat64(mp->mnt_mountp, &st) != 0) {
104
mp->mnt_major = 0;
105
mp->mnt_minor = 0;
106
return (ret);
107
}
108
mp->mnt_major = major(st.st_dev);
109
mp->mnt_minor = minor(st.st_dev);
110
}
111
112
return (ret);
113
}
114
115
int
116
getextmntent(const char *path, struct extmnttab *entry, struct stat64 *statbuf)
117
{
118
struct stat64 st;
119
FILE *fp;
120
int match;
121
boolean_t have_mnt_id = B_FALSE;
122
uint64_t target_mnt_id = 0;
123
uint64_t entry_mnt_id;
124
#ifdef HAVE_STATX_MNT_ID
125
struct statx stx;
126
#endif
127
128
if (strlen(path) >= MAXPATHLEN) {
129
(void) fprintf(stderr, "invalid object; pathname too long\n");
130
return (-1);
131
}
132
133
/*
134
* Search for the path in /proc/self/mounts. Rather than looking for the
135
* specific path, which can be fooled by non-standard paths (i.e. ".."
136
* or "//"), we stat() the path and search for the corresponding
137
* (major,minor) device pair.
138
*/
139
if (stat64(path, statbuf) != 0) {
140
(void) fprintf(stderr, "cannot open '%s': %s\n",
141
path, zfs_strerror(errno));
142
return (-1);
143
}
144
145
#ifdef HAVE_STATX_MNT_ID
146
if (statx(AT_FDCWD, path, AT_STATX_SYNC_AS_STAT | AT_SYMLINK_NOFOLLOW,
147
STATX_MNT_ID, &stx) == 0 && (stx.stx_mask & STATX_MNT_ID)) {
148
have_mnt_id = B_TRUE;
149
target_mnt_id = stx.stx_mnt_id;
150
}
151
#endif
152
153
if ((fp = fopen(MNTTAB, "re")) == NULL) {
154
(void) fprintf(stderr, "cannot open %s\n", MNTTAB);
155
return (-1);
156
}
157
158
/*
159
* Search for the given (major,minor) pair in the mount table.
160
*/
161
162
match = 0;
163
while (getextmntent_impl(fp, entry, &entry_mnt_id) == 0) {
164
if (have_mnt_id) {
165
match = (entry_mnt_id == target_mnt_id);
166
} else {
167
match = makedev(entry->mnt_major, entry->mnt_minor) ==
168
statbuf->st_dev;
169
}
170
if (match)
171
break;
172
}
173
(void) fclose(fp);
174
175
if (!match) {
176
(void) fprintf(stderr, "cannot find mountpoint for '%s'\n",
177
path);
178
return (-1);
179
}
180
181
if (stat64(entry->mnt_mountp, &st) != 0) {
182
entry->mnt_major = 0;
183
entry->mnt_minor = 0;
184
return (-1);
185
}
186
187
return (0);
188
}
189
190