PageRenderTime 49ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/src/netbsd/src/sbin/umount/umount.c

https://bitbucket.org/killerpenguinassassins/open_distrib_devel
C | 399 lines | 322 code | 41 blank | 36 comment | 94 complexity | e97b31c6f2d3bb6df3b83c80817e8a14 MD5 | raw file
Possible License(s): CC0-1.0, MIT, LGPL-2.0, LGPL-3.0, WTFPL, GPL-2.0, BSD-2-Clause, AGPL-3.0, CC-BY-SA-3.0, MPL-2.0, JSON, BSD-3-Clause-No-Nuclear-License-2014, LGPL-2.1, CPL-1.0, AGPL-1.0, 0BSD, ISC, Apache-2.0, GPL-3.0, IPL-1.0, MPL-2.0-no-copyleft-exception, BSD-3-Clause
  1. /* $NetBSD: umount.c,v 1.43 2008/08/05 20:57:45 pooka Exp $ */
  2. /*-
  3. * Copyright (c) 1980, 1989, 1993
  4. * The Regents of the University of California. All rights reserved.
  5. *
  6. * Redistribution and use in source and binary forms, with or without
  7. * modification, are permitted provided that the following conditions
  8. * are met:
  9. * 1. Redistributions of source code must retain the above copyright
  10. * notice, this list of conditions and the following disclaimer.
  11. * 2. Redistributions in binary form must reproduce the above copyright
  12. * notice, this list of conditions and the following disclaimer in the
  13. * documentation and/or other materials provided with the distribution.
  14. * 3. Neither the name of the University nor the names of its contributors
  15. * may be used to endorse or promote products derived from this software
  16. * without specific prior written permission.
  17. *
  18. * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  19. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  20. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  21. * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  22. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  23. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  24. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  25. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  26. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  27. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  28. * SUCH DAMAGE.
  29. */
  30. #include <sys/cdefs.h>
  31. #ifndef lint
  32. __COPYRIGHT("@(#) Copyright (c) 1980, 1989, 1993\
  33. The Regents of the University of California. All rights reserved.");
  34. #endif /* not lint */
  35. #ifndef lint
  36. #if 0
  37. static char sccsid[] = "@(#)umount.c 8.8 (Berkeley) 5/8/95";
  38. #else
  39. __RCSID("$NetBSD: umount.c,v 1.43 2008/08/05 20:57:45 pooka Exp $");
  40. #endif
  41. #endif /* not lint */
  42. #include <sys/param.h>
  43. #include <sys/stat.h>
  44. #include <sys/mount.h>
  45. #include <sys/time.h>
  46. #ifndef SMALL
  47. #include <sys/socket.h>
  48. #include <netdb.h>
  49. #include <rpc/rpc.h>
  50. #include <rpc/pmap_clnt.h>
  51. #include <rpc/pmap_prot.h>
  52. #include <nfs/rpcv2.h>
  53. #endif /* !SMALL */
  54. #include <err.h>
  55. #include <fstab.h>
  56. #include <stdio.h>
  57. #include <stdlib.h>
  58. #include <string.h>
  59. #include <unistd.h>
  60. typedef enum { MNTANY, MNTON, MNTFROM } mntwhat;
  61. #ifndef SMALL
  62. #include "mountprog.h"
  63. static int fake, verbose;
  64. static char *nfshost;
  65. static struct addrinfo *nfshost_ai = NULL;
  66. static int namematch(const struct addrinfo *);
  67. static int sacmp(const struct sockaddr *, const struct sockaddr *);
  68. static int xdr_dir(XDR *, char *);
  69. #endif /* !SMALL */
  70. static int fflag;
  71. static char *getmntname(const char *, mntwhat, char **);
  72. static int umountfs(const char *, const char **, int);
  73. static void usage(void) __dead;
  74. int
  75. main(int argc, char *argv[])
  76. {
  77. int ch, errs, all = 0, raw = 0;
  78. #ifndef SMALL
  79. int mnts;
  80. struct statvfs *mntbuf;
  81. struct addrinfo hints;
  82. #endif /* SMALL */
  83. const char **typelist = NULL;
  84. /* Start disks transferring immediately. */
  85. sync();
  86. #ifdef SMALL
  87. #define OPTS "fR"
  88. #else
  89. #define OPTS "AaFfh:Rt:v"
  90. #endif
  91. while ((ch = getopt(argc, argv, OPTS)) != -1)
  92. switch (ch) {
  93. case 'f':
  94. fflag = MNT_FORCE;
  95. break;
  96. case 'R':
  97. raw = 1;
  98. break;
  99. #ifndef SMALL
  100. case 'A':
  101. case 'a':
  102. all = 1;
  103. break;
  104. case 'F':
  105. fake = 1;
  106. break;
  107. case 'h': /* -h implies -A. */
  108. all = 1;
  109. nfshost = optarg;
  110. break;
  111. case 't':
  112. if (typelist != NULL)
  113. errx(1, "only one -t option may be specified.");
  114. typelist = makevfslist(optarg);
  115. break;
  116. case 'v':
  117. verbose = 1;
  118. break;
  119. #endif /* !SMALL */
  120. default:
  121. usage();
  122. /* NOTREACHED */
  123. }
  124. argc -= optind;
  125. argv += optind;
  126. if ((argc == 0 && !all) || (argc != 0 && all) || (all && raw))
  127. usage();
  128. #ifndef SMALL
  129. /* -h implies "-t nfs" if no -t flag. */
  130. if ((nfshost != NULL) && (typelist == NULL))
  131. typelist = makevfslist("nfs");
  132. if (nfshost != NULL) {
  133. memset(&hints, 0, sizeof hints);
  134. getaddrinfo(nfshost, NULL, &hints, &nfshost_ai);
  135. }
  136. errs = 0;
  137. if (all) {
  138. if ((mnts = getmntinfo(&mntbuf, ST_NOWAIT)) == 0) {
  139. warn("getmntinfo");
  140. errs = 1;
  141. }
  142. for (errs = 0, mnts--; mnts > 0; mnts--) {
  143. if (checkvfsname(mntbuf[mnts].f_fstypename, typelist))
  144. continue;
  145. if (umountfs(mntbuf[mnts].f_mntonname, typelist,
  146. 1) != 0)
  147. errs = 1;
  148. }
  149. } else
  150. #endif /* !SMALL */
  151. for (errs = 0; *argv != NULL; ++argv)
  152. if (umountfs(*argv, typelist, raw) != 0)
  153. errs = 1;
  154. return errs;
  155. }
  156. static int
  157. umountfs(const char *name, const char **typelist, int raw)
  158. {
  159. #ifndef SMALL
  160. enum clnt_stat clnt_stat;
  161. struct timeval try;
  162. CLIENT *clp;
  163. char *hostp = NULL;
  164. struct addrinfo *ai = NULL, hints;
  165. #endif /* !SMALL */
  166. const char *mntpt;
  167. char *type, rname[MAXPATHLEN];
  168. mntwhat what;
  169. struct stat sb;
  170. if (raw) {
  171. mntpt = name;
  172. } else {
  173. what = MNTANY;
  174. if (realpath(name, rname) != NULL) {
  175. name = rname;
  176. if (stat(name, &sb) == 0) {
  177. if (S_ISBLK(sb.st_mode))
  178. what = MNTON;
  179. else if (S_ISDIR(sb.st_mode))
  180. what = MNTFROM;
  181. }
  182. }
  183. #ifdef SMALL
  184. else {
  185. warn("%s", rname);
  186. return 1;
  187. }
  188. #endif /* SMALL */
  189. mntpt = name;
  190. switch (what) {
  191. case MNTON:
  192. if ((mntpt = getmntname(name, MNTON, &type)) == NULL) {
  193. warnx("%s: not currently mounted", name);
  194. return (1);
  195. }
  196. break;
  197. case MNTFROM:
  198. if ((name = getmntname(mntpt, MNTFROM, &type)) == NULL) {
  199. warnx("%s: not currently mounted", mntpt);
  200. return (1);
  201. }
  202. break;
  203. default:
  204. if ((name = getmntname(mntpt, MNTFROM, &type)) == NULL) {
  205. name = mntpt;
  206. if ((mntpt = getmntname(name, MNTON, &type)) == NULL) {
  207. warnx("%s: not currently mounted", name);
  208. return 1;
  209. }
  210. }
  211. }
  212. #ifndef SMALL
  213. if (checkvfsname(type, typelist))
  214. return 1;
  215. (void)memset(&hints, 0, sizeof hints);
  216. if (!strncmp(type, MOUNT_NFS,
  217. sizeof(((struct statvfs *)NULL)->f_fstypename))) {
  218. char *delimp;
  219. /* look for host:mountpoint */
  220. if ((delimp = strrchr(name, ':')) != NULL) {
  221. int len = delimp - name;
  222. hostp = malloc(len + 1);
  223. if (hostp == NULL)
  224. return 1;
  225. memcpy(hostp, name, len);
  226. hostp[len] = 0;
  227. name += len + 1;
  228. getaddrinfo(hostp, NULL, &hints, &ai);
  229. }
  230. }
  231. if (!namematch(ai))
  232. return 1;
  233. #endif /* ! SMALL */
  234. }
  235. #ifndef SMALL
  236. if (verbose)
  237. (void)printf("%s: unmount from %s\n", name, mntpt);
  238. if (fake)
  239. return 0;
  240. #endif /* ! SMALL */
  241. if (unmount(mntpt, fflag) == -1) {
  242. warn("%s", mntpt);
  243. return 1;
  244. }
  245. #ifndef SMALL
  246. if (ai != NULL && !(fflag & MNT_FORCE)) {
  247. clp = clnt_create(hostp, RPCPROG_MNT, RPCMNT_VER1, "udp");
  248. if (clp == NULL) {
  249. clnt_pcreateerror("Cannot MNT PRC");
  250. return 1;
  251. }
  252. clp->cl_auth = authsys_create_default();
  253. try.tv_sec = 20;
  254. try.tv_usec = 0;
  255. clnt_stat = clnt_call(clp, RPCMNT_UMOUNT, xdr_dir,
  256. __UNCONST(name), xdr_void, NULL, try);
  257. if (clnt_stat != RPC_SUCCESS) {
  258. clnt_perror(clp, "Bad MNT RPC");
  259. return 1;
  260. }
  261. auth_destroy(clp->cl_auth);
  262. clnt_destroy(clp);
  263. }
  264. #endif /* ! SMALL */
  265. return 0;
  266. }
  267. static char *
  268. getmntname(const char *name, mntwhat what, char **type)
  269. {
  270. static struct statvfs *mntbuf;
  271. static int mntsize;
  272. int i;
  273. if (mntbuf == NULL &&
  274. (mntsize = getmntinfo(&mntbuf, MNT_NOWAIT)) == 0) {
  275. warn("getmntinfo");
  276. return (NULL);
  277. }
  278. for (i = mntsize - 1; i >= 0; i--) {
  279. if ((what == MNTON) && !strcmp(mntbuf[i].f_mntfromname, name)) {
  280. if (type)
  281. *type = mntbuf[i].f_fstypename;
  282. return (mntbuf[i].f_mntonname);
  283. }
  284. if ((what == MNTFROM) && !strcmp(mntbuf[i].f_mntonname, name)) {
  285. if (type)
  286. *type = mntbuf[i].f_fstypename;
  287. return (mntbuf[i].f_mntfromname);
  288. }
  289. }
  290. return (NULL);
  291. }
  292. #ifndef SMALL
  293. static int
  294. sacmp(const struct sockaddr *sa1, const struct sockaddr *sa2)
  295. {
  296. const void *p1, *p2;
  297. size_t len;
  298. if (sa1->sa_family != sa2->sa_family)
  299. return 1;
  300. switch (sa1->sa_family) {
  301. case AF_INET:
  302. p1 = &((const struct sockaddr_in *)sa1)->sin_addr;
  303. p2 = &((const struct sockaddr_in *)sa2)->sin_addr;
  304. len = 4;
  305. break;
  306. case AF_INET6:
  307. p1 = &((const struct sockaddr_in6 *)sa1)->sin6_addr;
  308. p2 = &((const struct sockaddr_in6 *)sa2)->sin6_addr;
  309. len = 16;
  310. if (((const struct sockaddr_in6 *)sa1)->sin6_scope_id !=
  311. ((const struct sockaddr_in6 *)sa2)->sin6_scope_id)
  312. return 1;
  313. break;
  314. default:
  315. return 1;
  316. }
  317. return memcmp(p1, p2, len);
  318. }
  319. static int
  320. namematch(const struct addrinfo *ai)
  321. {
  322. struct addrinfo *aip;
  323. if (nfshost == NULL || nfshost_ai == NULL)
  324. return (1);
  325. while (ai != NULL) {
  326. aip = nfshost_ai;
  327. while (aip != NULL) {
  328. if (sacmp(ai->ai_addr, aip->ai_addr) == 0)
  329. return 1;
  330. aip = aip->ai_next;
  331. }
  332. ai = ai->ai_next;
  333. }
  334. return 0;
  335. }
  336. /*
  337. * xdr routines for mount rpc's
  338. */
  339. static int
  340. xdr_dir(XDR *xdrsp, char *dirp)
  341. {
  342. return xdr_string(xdrsp, &dirp, RPCMNT_PATHLEN);
  343. }
  344. #endif /* !SMALL */
  345. static void
  346. usage(void)
  347. {
  348. #ifdef SMALL
  349. (void)fprintf(stderr,
  350. "Usage: %s [-fR] special | node\n", getprogname());
  351. #else
  352. (void)fprintf(stderr,
  353. "Usage: %s [-fvFR] [-t fstypelist] special | node\n"
  354. "\t %s -a[fvF] [-h host] [-t fstypelist]\n", getprogname(),
  355. getprogname());
  356. #endif /* SMALL */
  357. exit(1);
  358. }