138
* Discover mount server's hostname/address by examining mount options
140
* Returns a pointer to a string that the caller must free, on
141
* success; otherwise NULL is returned.
143
* Detect NFSv4 mounts.
145
* Consult /proc/mounts to determine if the mount point
146
* is an NFSv4 mount. The kernel is authoritative about
147
* what type of mount this is.
149
* Returns 1 if "mc" is an NFSv4 mount, zero if not, and
150
* -1 if some error occurred.
143
static char *nfs_umount_hostname(struct mount_options *options,
152
static int nfs_umount_is_vers4(const struct mntentchn *mc)
148
option = po_get(options, "mountaddr");
151
option = po_get(options, "mounthost");
154
option = po_get(options, "addr");
154
char buffer[LINELEN], *next;
158
if ((f = fopen(MOUNTSFILE, "r")) == NULL) {
159
fprintf(stderr, "%s: %s\n",
160
MOUNTSFILE, strerror(errno));
165
while (fgets(buffer, sizeof(buffer), f) != NULL) {
166
char *device, *mntdir, *type, *flags;
167
struct mount_options *options;
170
next = strchr(line, '\n');
174
device = strtok(line, " \t");
177
mntdir = strtok(NULL, " \t");
180
if (strcmp(device, mc->m.mnt_fsname) != 0 &&
181
strcmp(mntdir, mc->m.mnt_dir) != 0)
184
type = strtok(NULL, " \t");
187
if (strcmp(type, "nfs4") == 0)
190
flags = strtok(NULL, " \t");
193
options = po_split(flags);
194
if (options != NULL) {
195
unsigned long version;
198
rc = nfs_nfs_version(options, &version);
200
if (rc && version == 4)
207
fprintf(stderr, "%s was not found in %s\n",
208
mc->m.mnt_dir, MOUNTSFILE);
162
return strdup(option);
166
* Returns EX_SUCCESS if mount options and device name have been
167
* parsed successfully; otherwise EX_FAIL.
169
static int nfs_umount_do_umnt(struct mount_options *options,
170
char **hostname, char **dirname)
174
struct sockaddr_in s4;
175
struct sockaddr_in6 s6;
177
struct sockaddr *sap = &address.sa;
178
socklen_t salen = sizeof(address);
179
struct pmap nfs_pmap, mnt_pmap;
182
if (!nfs_options2pmap(options, &nfs_pmap, &mnt_pmap))
185
/* Skip UMNT call for vers=4 mounts */
186
if (nfs_pmap.pm_vers == 4)
189
*hostname = nfs_umount_hostname(options, *hostname);
191
nfs_error(_("%s: out of memory"), progname);
195
if (!nfs_mount_proto_family(options, &family))
197
if (!nfs_lookup(*hostname, family, sap, &salen))
198
/* nfs_lookup reports any errors */
201
if (nfs_advise_umount(sap, salen, &mnt_pmap, dirname) == 0)
202
/* nfs_advise_umount reports any errors */
209
* Pick up certain mount options used during the original mount
210
* from /etc/mtab. The basics include the server's IP address and
211
* the server pathname of the share to unregister.
213
* These options might also describe the mount port, mount protocol
214
* version, and transport protocol used to punch through a firewall.
215
* We will need this information to get through the firewall again
218
* Note that option parsing failures won't necessarily cause the
219
* umount request to fail. Those values will be left zero in the
220
* pmap tuple. If the GETPORT call later fails to disambiguate them,
223
static int nfs_umount23(const char *devname, char *string)
225
char *hostname, *dirname;
226
struct mount_options *options;
227
int result = EX_FAIL;
229
if (!nfs_parse_devname(devname, &hostname, &dirname))
232
options = po_split(string);
234
result = nfs_umount_do_umnt(options, &hostname, &dirname);
237
nfs_error(_("%s: option parsing error"), progname);
216
fprintf(stderr, "NFSv4 mount point detected\n");
222
fprintf(stderr, "Legacy NFS mount point detected\n");
244
227
static struct option umount_longopts[] =
367
if (!lazy && strcmp(mc->m.mnt_type, "nfs4") != 0)
368
/* We ignore the error from nfs_umount23.
369
* If the actual umount succeeds (in del_mtab),
370
* we don't want to signal an error, as that
371
* could cause /sbin/mount to retry!
373
nfs_umount23(mc->m.mnt_fsname, mc->m.mnt_opts);
374
ret = del_mtab(mc->m.mnt_fsname, mc->m.mnt_dir) ?: ret;
340
switch (nfs_umount_is_vers4(mc)) {
342
/* We ignore the error from nfs_umount23.
343
* If the actual umount succeeds (in del_mtab),
344
* we don't want to signal an error, as that
345
* could cause /sbin/mount to retry!
347
nfs_umount23(mc->m.mnt_fsname, mc->m.mnt_opts);
355
ret = del_mtab(mc->m.mnt_fsname, mc->m.mnt_dir);
375
356
} else if (*spec != '/') {
377
358
ret = nfs_umount23(spec, "tcp,v3");