1 1.56 kre /* $NetBSD: umount.c,v 1.56 2025/07/01 20:11:13 kre Exp $ */ 2 1.13 cgd 3 1.1 cgd /*- 4 1.7 mycroft * Copyright (c) 1980, 1989, 1993 5 1.7 mycroft * The Regents of the University of California. All rights reserved. 6 1.1 cgd * 7 1.1 cgd * Redistribution and use in source and binary forms, with or without 8 1.1 cgd * modification, are permitted provided that the following conditions 9 1.1 cgd * are met: 10 1.1 cgd * 1. Redistributions of source code must retain the above copyright 11 1.1 cgd * notice, this list of conditions and the following disclaimer. 12 1.1 cgd * 2. Redistributions in binary form must reproduce the above copyright 13 1.1 cgd * notice, this list of conditions and the following disclaimer in the 14 1.1 cgd * documentation and/or other materials provided with the distribution. 15 1.29 agc * 3. Neither the name of the University nor the names of its contributors 16 1.1 cgd * may be used to endorse or promote products derived from this software 17 1.1 cgd * without specific prior written permission. 18 1.1 cgd * 19 1.1 cgd * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 20 1.1 cgd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 1.1 cgd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 1.1 cgd * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 23 1.1 cgd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 1.1 cgd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 1.1 cgd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 1.1 cgd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 1.1 cgd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 1.1 cgd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 1.1 cgd * SUCH DAMAGE. 30 1.1 cgd */ 31 1.1 cgd 32 1.19 lukem #include <sys/cdefs.h> 33 1.1 cgd #ifndef lint 34 1.42 lukem __COPYRIGHT("@(#) Copyright (c) 1980, 1989, 1993\ 35 1.42 lukem The Regents of the University of California. All rights reserved."); 36 1.1 cgd #endif /* not lint */ 37 1.1 cgd 38 1.1 cgd #ifndef lint 39 1.13 cgd #if 0 40 1.20 lukem static char sccsid[] = "@(#)umount.c 8.8 (Berkeley) 5/8/95"; 41 1.13 cgd #else 42 1.56 kre __RCSID("$NetBSD: umount.c,v 1.56 2025/07/01 20:11:13 kre Exp $"); 43 1.13 cgd #endif 44 1.1 cgd #endif /* not lint */ 45 1.1 cgd 46 1.1 cgd #include <sys/param.h> 47 1.1 cgd #include <sys/stat.h> 48 1.1 cgd #include <sys/mount.h> 49 1.1 cgd #include <sys/time.h> 50 1.34 christos #ifndef SMALL 51 1.1 cgd #include <sys/socket.h> 52 1.7 mycroft 53 1.1 cgd #include <netdb.h> 54 1.1 cgd #include <rpc/rpc.h> 55 1.1 cgd #include <rpc/pmap_clnt.h> 56 1.1 cgd #include <rpc/pmap_prot.h> 57 1.1 cgd #include <nfs/rpcv2.h> 58 1.46 christos #include <nfs/nfsmount.h> 59 1.54 christos 60 1.54 christos #include <dev/vndvar.h> 61 1.54 christos #include <sys/ioctl.h> 62 1.54 christos #include <fcntl.h> 63 1.34 christos #endif /* !SMALL */ 64 1.1 cgd 65 1.6 cgd #include <err.h> 66 1.50 dholland #include <errno.h> 67 1.1 cgd #include <fstab.h> 68 1.1 cgd #include <stdio.h> 69 1.7 mycroft #include <stdlib.h> 70 1.1 cgd #include <string.h> 71 1.6 cgd #include <unistd.h> 72 1.53 christos #include <util.h> 73 1.1 cgd 74 1.18 pk typedef enum { MNTANY, MNTON, MNTFROM } mntwhat; 75 1.7 mycroft 76 1.34 christos #ifndef SMALL 77 1.43 pooka #include "mountprog.h" 78 1.34 christos 79 1.54 christos static int dflag, fake, verbose; 80 1.34 christos static char *nfshost; 81 1.34 christos static struct addrinfo *nfshost_ai = NULL; 82 1.34 christos 83 1.34 christos static int namematch(const struct addrinfo *); 84 1.34 christos static int sacmp(const struct sockaddr *, const struct sockaddr *); 85 1.34 christos static int xdr_dir(XDR *, char *); 86 1.44 christos static const char *getmntproto(const char *); 87 1.54 christos static int vn_detach(const char *); 88 1.34 christos #endif /* !SMALL */ 89 1.34 christos 90 1.54 christos static int all, fflag; 91 1.34 christos static char *getmntname(const char *, mntwhat, char **); 92 1.35 chs static int umountfs(const char *, const char **, int); 93 1.41 perry static void usage(void) __dead; 94 1.34 christos 95 1.6 cgd int 96 1.31 dsl main(int argc, char *argv[]) 97 1.1 cgd { 98 1.54 christos int ch, errs, raw = 0; 99 1.53 christos char mntfromname[MAXPATHLEN]; 100 1.34 christos #ifndef SMALL 101 1.34 christos int mnts; 102 1.33 christos struct statvfs *mntbuf; 103 1.28 fvdl struct addrinfo hints; 104 1.34 christos #endif /* SMALL */ 105 1.34 christos const char **typelist = NULL; 106 1.1 cgd 107 1.34 christos #ifdef SMALL 108 1.37 erh #define OPTS "fR" 109 1.34 christos #else 110 1.54 christos #define OPTS "AadFfh:Rt:v" 111 1.34 christos #endif 112 1.34 christos while ((ch = getopt(argc, argv, OPTS)) != -1) 113 1.7 mycroft switch (ch) { 114 1.34 christos case 'f': 115 1.34 christos fflag = MNT_FORCE; 116 1.34 christos break; 117 1.34 christos case 'R': 118 1.34 christos raw = 1; 119 1.34 christos break; 120 1.34 christos #ifndef SMALL 121 1.20 lukem case 'A': 122 1.7 mycroft case 'a': 123 1.7 mycroft all = 1; 124 1.7 mycroft break; 125 1.54 christos case 'd': 126 1.54 christos dflag = 1; 127 1.54 christos break; 128 1.7 mycroft case 'F': 129 1.7 mycroft fake = 1; 130 1.1 cgd break; 131 1.20 lukem case 'h': /* -h implies -A. */ 132 1.27 chs all = 1; 133 1.7 mycroft nfshost = optarg; 134 1.1 cgd break; 135 1.1 cgd case 't': 136 1.12 mycroft if (typelist != NULL) 137 1.12 mycroft errx(1, "only one -t option may be specified."); 138 1.20 lukem typelist = makevfslist(optarg); 139 1.1 cgd break; 140 1.7 mycroft case 'v': 141 1.56 kre verbose++; 142 1.1 cgd break; 143 1.34 christos #endif /* !SMALL */ 144 1.1 cgd default: 145 1.1 cgd usage(); 146 1.1 cgd /* NOTREACHED */ 147 1.1 cgd } 148 1.1 cgd argc -= optind; 149 1.1 cgd argv += optind; 150 1.1 cgd 151 1.24 fair if ((argc == 0 && !all) || (argc != 0 && all) || (all && raw)) 152 1.1 cgd usage(); 153 1.7 mycroft 154 1.34 christos #ifndef SMALL 155 1.7 mycroft /* -h implies "-t nfs" if no -t flag. */ 156 1.7 mycroft if ((nfshost != NULL) && (typelist == NULL)) 157 1.20 lukem typelist = makevfslist("nfs"); 158 1.28 fvdl 159 1.28 fvdl if (nfshost != NULL) { 160 1.28 fvdl memset(&hints, 0, sizeof hints); 161 1.52 dholland if (getaddrinfo(nfshost, NULL, &hints, &nfshost_ai) != 0) { 162 1.52 dholland nfshost_ai = NULL; 163 1.52 dholland } 164 1.28 fvdl } 165 1.7 mycroft 166 1.20 lukem errs = 0; 167 1.27 chs if (all) { 168 1.34 christos if ((mnts = getmntinfo(&mntbuf, ST_NOWAIT)) == 0) { 169 1.20 lukem warn("getmntinfo"); 170 1.20 lukem errs = 1; 171 1.20 lukem } 172 1.20 lukem for (errs = 0, mnts--; mnts > 0; mnts--) { 173 1.20 lukem if (checkvfsname(mntbuf[mnts].f_fstypename, typelist)) 174 1.20 lukem continue; 175 1.35 chs if (umountfs(mntbuf[mnts].f_mntonname, typelist, 176 1.37 erh 1) != 0) 177 1.20 lukem errs = 1; 178 1.20 lukem } 179 1.34 christos } else 180 1.34 christos #endif /* !SMALL */ 181 1.53 christos for (errs = 0; *argv != NULL; ++argv) { 182 1.53 christos if (getfsspecname(mntfromname, sizeof(mntfromname), 183 1.53 christos *argv) == NULL) 184 1.53 christos err(EXIT_FAILURE, "%s", mntfromname); 185 1.53 christos if (umountfs(mntfromname, typelist, raw) != 0) 186 1.7 mycroft errs = 1; 187 1.53 christos } 188 1.34 christos return errs; 189 1.1 cgd } 190 1.1 cgd 191 1.34 christos static int 192 1.35 chs umountfs(const char *name, const char **typelist, int raw) 193 1.1 cgd { 194 1.34 christos #ifndef SMALL 195 1.7 mycroft enum clnt_stat clnt_stat; 196 1.28 fvdl struct timeval try; 197 1.7 mycroft CLIENT *clp; 198 1.34 christos char *hostp = NULL; 199 1.34 christos struct addrinfo *ai = NULL, hints; 200 1.47 christos const char *proto = NULL; 201 1.55 christos struct statvfs sfs; 202 1.34 christos #endif /* !SMALL */ 203 1.34 christos const char *mntpt; 204 1.50 dholland char *type, rname[MAXPATHLEN], umountprog[MAXPATHLEN]; 205 1.18 pk mntwhat what; 206 1.34 christos struct stat sb; 207 1.7 mycroft 208 1.24 fair if (raw) { 209 1.24 fair mntpt = name; 210 1.24 fair } else { 211 1.7 mycroft 212 1.24 fair what = MNTANY; 213 1.30 dsl if (realpath(name, rname) != NULL) { 214 1.30 dsl name = rname; 215 1.24 fair 216 1.30 dsl if (stat(name, &sb) == 0) { 217 1.30 dsl if (S_ISBLK(sb.st_mode)) 218 1.30 dsl what = MNTON; 219 1.30 dsl else if (S_ISDIR(sb.st_mode)) 220 1.30 dsl what = MNTFROM; 221 1.30 dsl } 222 1.17 pk } 223 1.34 christos #ifdef SMALL 224 1.34 christos else { 225 1.49 dholland warn("%s", name); 226 1.34 christos return 1; 227 1.34 christos } 228 1.34 christos #endif /* SMALL */ 229 1.30 dsl mntpt = name; 230 1.24 fair 231 1.24 fair switch (what) { 232 1.24 fair case MNTON: 233 1.20 lukem if ((mntpt = getmntname(name, MNTON, &type)) == NULL) { 234 1.15 mycroft warnx("%s: not currently mounted", name); 235 1.15 mycroft return (1); 236 1.15 mycroft } 237 1.24 fair break; 238 1.24 fair case MNTFROM: 239 1.24 fair if ((name = getmntname(mntpt, MNTFROM, &type)) == NULL) { 240 1.24 fair warnx("%s: not currently mounted", mntpt); 241 1.24 fair return (1); 242 1.24 fair } 243 1.24 fair break; 244 1.24 fair default: 245 1.24 fair if ((name = getmntname(mntpt, MNTFROM, &type)) == NULL) { 246 1.30 dsl name = mntpt; 247 1.24 fair if ((mntpt = getmntname(name, MNTON, &type)) == NULL) { 248 1.24 fair warnx("%s: not currently mounted", name); 249 1.34 christos return 1; 250 1.24 fair } 251 1.24 fair } 252 1.1 cgd } 253 1.7 mycroft 254 1.34 christos #ifndef SMALL 255 1.24 fair if (checkvfsname(type, typelist)) 256 1.34 christos return 1; 257 1.1 cgd 258 1.34 christos (void)memset(&hints, 0, sizeof hints); 259 1.40 christos if (!strncmp(type, MOUNT_NFS, 260 1.40 christos sizeof(((struct statvfs *)NULL)->f_fstypename))) { 261 1.32 dsl char *delimp; 262 1.46 christos proto = getmntproto(mntpt); 263 1.30 dsl /* look for host:mountpoint */ 264 1.30 dsl if ((delimp = strrchr(name, ':')) != NULL) { 265 1.32 dsl int len = delimp - name; 266 1.32 dsl hostp = malloc(len + 1); 267 1.32 dsl if (hostp == NULL) 268 1.32 dsl return 1; 269 1.32 dsl memcpy(hostp, name, len); 270 1.32 dsl hostp[len] = 0; 271 1.32 dsl name += len + 1; 272 1.52 dholland if (getaddrinfo(hostp, NULL, &hints, &ai) != 0) 273 1.52 dholland ai = NULL; 274 1.24 fair } 275 1.20 lukem } 276 1.24 fair 277 1.28 fvdl if (!namematch(ai)) 278 1.34 christos return 1; 279 1.34 christos #endif /* ! SMALL */ 280 1.51 dholland snprintf(umountprog, sizeof(umountprog), "umount_%s", type); 281 1.10 mycroft } 282 1.7 mycroft 283 1.34 christos #ifndef SMALL 284 1.50 dholland if (verbose) { 285 1.56 kre (void)printf("%s: %sunmount from %s\n", 286 1.56 kre name, fake ? "fake " : "", mntpt); 287 1.50 dholland /* put this before the test of FAKE */ 288 1.56 kre if (!raw && verbose > 1) { 289 1.56 kre int OK = 1; 290 1.56 kre if (fake) { 291 1.56 kre OK = faccessat(AT_FDCWD, umountprog, 292 1.56 kre X_OK, AT_EACCESS); 293 1.56 kre } 294 1.56 kre (void)printf("Trying unmount program %s%s\n", 295 1.56 kre umountprog, 296 1.56 kre (fake && OK < 0) ? ": would fail" : ""); 297 1.50 dholland } 298 1.50 dholland } 299 1.7 mycroft if (fake) 300 1.34 christos return 0; 301 1.34 christos #endif /* ! SMALL */ 302 1.1 cgd 303 1.50 dholland if (!raw) { 304 1.50 dholland /* 305 1.50 dholland * The only options that need to be passed on are -f 306 1.50 dholland * and -v. 307 1.50 dholland */ 308 1.50 dholland char *args[3]; 309 1.50 dholland unsigned nargs = 0; 310 1.50 dholland 311 1.50 dholland args[nargs++] = umountprog; 312 1.50 dholland if (fflag == MNT_FORCE) { 313 1.50 dholland args[nargs++] = __UNCONST("-f"); 314 1.50 dholland } 315 1.50 dholland #ifndef SMALL 316 1.50 dholland if (verbose) { 317 1.50 dholland args[nargs++] = __UNCONST("-v"); 318 1.50 dholland } 319 1.50 dholland #endif 320 1.50 dholland execvp(umountprog, args); 321 1.50 dholland if (errno != ENOENT) { 322 1.50 dholland warn("%s: execvp", umountprog); 323 1.50 dholland } 324 1.50 dholland } 325 1.50 dholland 326 1.50 dholland #ifndef SMALL 327 1.56 kre if (verbose > 1) 328 1.50 dholland (void)printf("(No separate unmount program.)\n"); 329 1.54 christos 330 1.54 christos if (dflag && statvfs(mntpt, &sfs) == -1) { 331 1.54 christos warn("%s: statvfs", mntpt); 332 1.54 christos return 1; 333 1.54 christos } 334 1.50 dholland #endif 335 1.50 dholland 336 1.39 pooka if (unmount(mntpt, fflag) == -1) { 337 1.6 cgd warn("%s", mntpt); 338 1.34 christos return 1; 339 1.1 cgd } 340 1.1 cgd 341 1.34 christos #ifndef SMALL 342 1.32 dsl if (ai != NULL && !(fflag & MNT_FORCE)) { 343 1.46 christos clp = clnt_create(hostp, RPCPROG_MNT, RPCMNT_VER1, proto); 344 1.28 fvdl if (clp == NULL) { 345 1.1 cgd clnt_pcreateerror("Cannot MNT PRC"); 346 1.34 christos return 1; 347 1.1 cgd } 348 1.28 fvdl clp->cl_auth = authsys_create_default(); 349 1.1 cgd try.tv_sec = 20; 350 1.1 cgd try.tv_usec = 0; 351 1.38 christos clnt_stat = clnt_call(clp, RPCMNT_UMOUNT, xdr_dir, 352 1.38 christos __UNCONST(name), xdr_void, NULL, try); 353 1.1 cgd if (clnt_stat != RPC_SUCCESS) { 354 1.1 cgd clnt_perror(clp, "Bad MNT RPC"); 355 1.34 christos return 1; 356 1.1 cgd } 357 1.1 cgd auth_destroy(clp->cl_auth); 358 1.1 cgd clnt_destroy(clp); 359 1.1 cgd } 360 1.54 christos 361 1.54 christos if (dflag) { 362 1.54 christos if (vn_detach(sfs.f_mntfromname) == 0) { 363 1.54 christos if (verbose) 364 1.54 christos (void)printf("%s: detached\n", 365 1.54 christos sfs.f_mntfromname); 366 1.54 christos } else if (!all) 367 1.54 christos return (-1); 368 1.54 christos } 369 1.34 christos #endif /* ! SMALL */ 370 1.34 christos return 0; 371 1.1 cgd } 372 1.1 cgd 373 1.34 christos static char * 374 1.31 dsl getmntname(const char *name, mntwhat what, char **type) 375 1.1 cgd { 376 1.33 christos static struct statvfs *mntbuf; 377 1.20 lukem static int mntsize; 378 1.53 christos static char mntfromname[MAXPATHLEN]; 379 1.20 lukem int i; 380 1.1 cgd 381 1.20 lukem if (mntbuf == NULL && 382 1.20 lukem (mntsize = getmntinfo(&mntbuf, MNT_NOWAIT)) == 0) { 383 1.7 mycroft warn("getmntinfo"); 384 1.7 mycroft return (NULL); 385 1.1 cgd } 386 1.21 drochner for (i = mntsize - 1; i >= 0; i--) { 387 1.7 mycroft if ((what == MNTON) && !strcmp(mntbuf[i].f_mntfromname, name)) { 388 1.7 mycroft if (type) 389 1.20 lukem *type = mntbuf[i].f_fstypename; 390 1.1 cgd return (mntbuf[i].f_mntonname); 391 1.1 cgd } 392 1.7 mycroft if ((what == MNTFROM) && !strcmp(mntbuf[i].f_mntonname, name)) { 393 1.7 mycroft if (type) 394 1.20 lukem *type = mntbuf[i].f_fstypename; 395 1.53 christos if (getfsspecname(mntfromname, sizeof(mntfromname), 396 1.53 christos mntbuf[i].f_mntfromname) == NULL) 397 1.53 christos err(EXIT_FAILURE, "%s", mntfromname); 398 1.53 christos return mntfromname; 399 1.1 cgd } 400 1.1 cgd } 401 1.7 mycroft return (NULL); 402 1.1 cgd } 403 1.1 cgd 404 1.34 christos #ifndef SMALL 405 1.34 christos static int 406 1.31 dsl sacmp(const struct sockaddr *sa1, const struct sockaddr *sa2) 407 1.1 cgd { 408 1.38 christos const void *p1, *p2; 409 1.38 christos size_t len; 410 1.28 fvdl 411 1.28 fvdl if (sa1->sa_family != sa2->sa_family) 412 1.28 fvdl return 1; 413 1.28 fvdl 414 1.28 fvdl switch (sa1->sa_family) { 415 1.28 fvdl case AF_INET: 416 1.38 christos p1 = &((const struct sockaddr_in *)sa1)->sin_addr; 417 1.38 christos p2 = &((const struct sockaddr_in *)sa2)->sin_addr; 418 1.28 fvdl len = 4; 419 1.28 fvdl break; 420 1.28 fvdl case AF_INET6: 421 1.38 christos p1 = &((const struct sockaddr_in6 *)sa1)->sin6_addr; 422 1.38 christos p2 = &((const struct sockaddr_in6 *)sa2)->sin6_addr; 423 1.28 fvdl len = 16; 424 1.38 christos if (((const struct sockaddr_in6 *)sa1)->sin6_scope_id != 425 1.38 christos ((const struct sockaddr_in6 *)sa2)->sin6_scope_id) 426 1.28 fvdl return 1; 427 1.28 fvdl break; 428 1.28 fvdl default: 429 1.28 fvdl return 1; 430 1.28 fvdl } 431 1.28 fvdl 432 1.28 fvdl return memcmp(p1, p2, len); 433 1.28 fvdl } 434 1.7 mycroft 435 1.34 christos static int 436 1.31 dsl namematch(const struct addrinfo *ai) 437 1.28 fvdl { 438 1.28 fvdl struct addrinfo *aip; 439 1.1 cgd 440 1.28 fvdl if (nfshost == NULL || nfshost_ai == NULL) 441 1.7 mycroft return (1); 442 1.7 mycroft 443 1.28 fvdl while (ai != NULL) { 444 1.28 fvdl aip = nfshost_ai; 445 1.28 fvdl while (aip != NULL) { 446 1.28 fvdl if (sacmp(ai->ai_addr, aip->ai_addr) == 0) 447 1.28 fvdl return 1; 448 1.28 fvdl aip = aip->ai_next; 449 1.1 cgd } 450 1.28 fvdl ai = ai->ai_next; 451 1.1 cgd } 452 1.28 fvdl 453 1.28 fvdl return 0; 454 1.1 cgd } 455 1.1 cgd 456 1.1 cgd /* 457 1.1 cgd * xdr routines for mount rpc's 458 1.1 cgd */ 459 1.34 christos static int 460 1.31 dsl xdr_dir(XDR *xdrsp, char *dirp) 461 1.1 cgd { 462 1.34 christos return xdr_string(xdrsp, &dirp, RPCMNT_PATHLEN); 463 1.1 cgd } 464 1.44 christos 465 1.44 christos static const char * 466 1.46 christos getmntproto(const char *name) 467 1.44 christos { 468 1.44 christos struct nfs_args nfsargs; 469 1.46 christos struct sockaddr_storage ss; 470 1.44 christos 471 1.46 christos nfsargs.sotype = SOCK_DGRAM; 472 1.46 christos nfsargs.addr = (struct sockaddr *)&ss; 473 1.46 christos nfsargs.addrlen = sizeof(ss); 474 1.46 christos (void)mount("nfs", name, MNT_GETARGS, &nfsargs, sizeof(nfsargs)); 475 1.46 christos return nfsargs.sotype == SOCK_STREAM ? "tcp" : "udp"; 476 1.44 christos } 477 1.54 christos 478 1.54 christos int 479 1.54 christos vn_detach(const char *dev) 480 1.54 christos { 481 1.54 christos struct vnd_ioctl vndio; 482 1.54 christos char rdev[MAXPATHLEN + 1]; 483 1.54 christos int fd; 484 1.54 christos 485 1.54 christos if (strncmp(dev, "/dev/vnd", sizeof("/dev/vnd") - 1)) { 486 1.54 christos if (!all) 487 1.54 christos warnx("invalid vnd device: %s", dev); 488 1.54 christos return -1; 489 1.54 christos } 490 1.54 christos 491 1.54 christos if ((fd = opendisk(dev, O_RDWR, rdev, sizeof(rdev), 0)) == -1) { 492 1.54 christos warn("%s: opendisk", rdev); 493 1.54 christos return -1; 494 1.54 christos } 495 1.54 christos 496 1.54 christos memset(&vndio, 0, sizeof(vndio)); 497 1.54 christos vndio.vnd_flags = fflag ? VNDIOF_FORCE : 0; 498 1.54 christos 499 1.54 christos if (ioctl(fd, VNDIOCCLR, &vndio) == -1) { 500 1.54 christos warn("%s: VNDIOCCLR", rdev); 501 1.54 christos close(fd); 502 1.54 christos return -1; 503 1.54 christos } 504 1.54 christos close(fd); 505 1.54 christos 506 1.54 christos return 0; 507 1.54 christos } 508 1.34 christos #endif /* !SMALL */ 509 1.7 mycroft 510 1.34 christos static void 511 1.31 dsl usage(void) 512 1.7 mycroft { 513 1.34 christos #ifdef SMALL 514 1.34 christos (void)fprintf(stderr, 515 1.34 christos "Usage: %s [-fR] special | node\n", getprogname()); 516 1.34 christos #else 517 1.7 mycroft (void)fprintf(stderr, 518 1.54 christos "Usage: %s [-dfvFR] [-t fstypelist] special | node\n" 519 1.54 christos "\t %s -a[dfvF] [-h host] [-t fstypelist]\n", getprogname(), 520 1.34 christos getprogname()); 521 1.34 christos #endif /* SMALL */ 522 1.7 mycroft exit(1); 523 1.7 mycroft } 524