1 /* 2 * Copyright (c) 1980, 1989 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms is permitted 6 * provided that all copyright information, including this notice, 7 * is retained in all such forms, and that any documentation, 8 * advertising or other materials related to such distribution and 9 * use acknowledge that the software was 10 * developed by the University of California, Berkeley. The name 11 * of the University may not be used to endorse or promote products 12 * derived from this software without specific prior written permission. 13 * 14 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 15 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 16 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 17 */ 18 19 #ifndef lint 20 char copyright[] = 21 "@(#) Copyright (c) 1980, 1989 The Regents of the University of California.\n\ 22 All rights reserved.\n"; 23 #endif /* not lint */ 24 25 #ifndef lint 26 static char sccsid[] = "@(#)umount.c 5.14 (Berkeley) 02/27/91"; 27 #endif /* not lint */ 28 29 #include <sys/param.h> 30 #include <sys/stat.h> 31 #include <sys/mount.h> 32 33 #ifdef NFS 34 #include <sys/time.h> 35 #include <sys/socket.h> 36 #include <sys/socketvar.h> 37 #include <netdb.h> 38 #include <rpc/rpc.h> 39 #include <rpc/pmap_clnt.h> 40 #include <rpc/pmap_prot.h> 41 #include <nfs/rpcv2.h> 42 #endif 43 44 #include <fstab.h> 45 #include <stdio.h> 46 #include <string.h> 47 48 #ifdef NFS 49 int xdr_dir(); 50 char *nfshost; 51 #endif 52 53 int vflag, all, errs, fake; 54 int fflag = MNT_NOFORCE; 55 char *getmntname(); 56 57 #define MNTON 1 58 #define MNTFROM 2 59 #define MNTTYPE 3 60 61 int *typelist, *maketypelist(); 62 63 main(argc, argv) 64 int argc; 65 char **argv; 66 { 67 extern char *optarg; 68 extern int optind; 69 int ch; 70 71 sync(); 72 while ((ch = getopt(argc, argv, "afFh:t:v")) != EOF) 73 switch((char)ch) { 74 case 'v': 75 vflag++; 76 break; 77 case 'f': 78 fflag = MNT_FORCE; 79 break; 80 case 'F': 81 fake++; 82 break; 83 case 'a': 84 all++; 85 break; 86 case 't': 87 typelist = maketypelist(optarg); 88 break; 89 #ifdef NFS 90 case 'h': 91 /* -h flag implies -a, and "-t nfs" if no -t flag */ 92 nfshost = optarg; 93 all++; 94 if (typelist == NULL) 95 typelist = maketypelist("nfs"); 96 break; 97 #endif /* NFS */ 98 case '?': 99 default: 100 usage(); 101 /* NOTREACHED */ 102 } 103 argc -= optind; 104 argv += optind; 105 106 if (argc == 0 && !all) 107 usage(); 108 if (all) { 109 if (argc > 0) 110 usage(); 111 if (setfsent() == 0) 112 perror(FSTAB), exit(1); 113 umountall(typelist); 114 exit(0); 115 } else 116 setfsent(); 117 while (argc > 0) { 118 if (umountfs(*argv++, 0) == 0) 119 errs++; 120 argc--; 121 } 122 exit(errs); 123 } 124 125 usage() 126 { 127 fprintf(stderr, 128 "%s\n%s\n", 129 "Usage: umount [-fv] special | node", 130 #ifndef NFS 131 " or umount -a[fv] [-t fstypelist]" 132 #else 133 " or umount -a[fv] [-h host] [-t fstypelist]" 134 #endif 135 ); 136 exit(1); 137 } 138 139 umountall(typelist) 140 char **typelist; 141 { 142 register struct fstab *fs; 143 struct fstab *allocfsent(); 144 145 if ((fs = getfsent()) == (struct fstab *)0) 146 return; 147 fs = allocfsent(fs); 148 umountall(typelist); 149 if (strcmp(fs->fs_file, "/") == 0) { 150 freefsent(fs); 151 return; 152 } 153 if (strcmp(fs->fs_type, FSTAB_RW) && 154 strcmp(fs->fs_type, FSTAB_RO) && 155 strcmp(fs->fs_type, FSTAB_RQ)) { 156 freefsent(fs); 157 return; 158 } 159 (void) umountfs(fs->fs_file, typelist); 160 freefsent(fs); 161 } 162 163 struct fstab * 164 allocfsent(fs) 165 register struct fstab *fs; 166 { 167 register struct fstab *new; 168 register char *cp; 169 170 new = (struct fstab *)malloc((unsigned)sizeof (*fs)); 171 cp = (char *)malloc((unsigned)strlen(fs->fs_file) + 1); 172 strcpy(cp, fs->fs_file); 173 new->fs_file = cp; 174 cp = (char *)malloc((unsigned)strlen(fs->fs_type) + 1); 175 strcpy(cp, fs->fs_type); 176 new->fs_type = cp; 177 cp = (char *)malloc((unsigned)strlen(fs->fs_spec) + 1); 178 strcpy(cp, fs->fs_spec); 179 new->fs_spec = cp; 180 new->fs_passno = fs->fs_passno; 181 new->fs_freq = fs->fs_freq; 182 return (new); 183 } 184 185 freefsent(fs) 186 register struct fstab *fs; 187 { 188 189 if (fs->fs_file) 190 free(fs->fs_file); 191 if (fs->fs_spec) 192 free(fs->fs_spec); 193 if (fs->fs_type) 194 free(fs->fs_type); 195 free((char *)fs); 196 } 197 198 umountfs(name, typelist) 199 char *name; 200 int *typelist; 201 { 202 char *mntpt; 203 struct stat stbuf; 204 int type; 205 #ifdef NFS 206 register CLIENT *clp; 207 struct hostent *hp = 0; 208 struct sockaddr_in saddr; 209 struct timeval pertry, try; 210 enum clnt_stat clnt_stat; 211 int so = RPC_ANYSOCK; 212 char *hostp, *delimp; 213 #endif /* NFS */ 214 215 if (stat(name, &stbuf) < 0) { 216 if ((mntpt = getmntname(name, MNTON, &type)) == 0) 217 return (0); 218 } else if ((stbuf.st_mode & S_IFMT) == S_IFBLK) { 219 if ((mntpt = getmntname(name, MNTON, &type)) == 0) 220 return (0); 221 } else if ((stbuf.st_mode & S_IFMT) == S_IFDIR) { 222 mntpt = name; 223 if ((name = getmntname(mntpt, MNTFROM, &type)) == 0) 224 return (0); 225 } else { 226 fprintf(stderr, "%s: not a directory or special device\n", 227 name); 228 return (0); 229 } 230 231 if (badtype(type, typelist)) 232 return(1); 233 #ifdef NFS 234 if ((delimp = index(name, '@')) != NULL) { 235 hostp = delimp + 1; 236 *delimp = '\0'; 237 hp = gethostbyname(hostp); 238 *delimp = '@'; 239 } else if ((delimp = index(name, ':')) != NULL) { 240 *delimp = '\0'; 241 hostp = name; 242 hp = gethostbyname(hostp); 243 name = delimp+1; 244 *delimp = ':'; 245 } 246 247 if (!namematch(hp, nfshost)) 248 return(1); 249 #endif /* NFS */ 250 if (!fake && unmount(mntpt, fflag) < 0) { 251 perror(mntpt); 252 return (0); 253 } 254 if (vflag) 255 fprintf(stderr, "%s: Unmounted from %s\n", name, mntpt); 256 257 #ifdef NFS 258 if (!fake && hp != NULL && (fflag & MNT_FORCE) == 0) { 259 *delimp = '\0'; 260 bcopy(hp->h_addr,(caddr_t)&saddr.sin_addr,hp->h_length); 261 saddr.sin_family = AF_INET; 262 saddr.sin_port = 0; 263 pertry.tv_sec = 3; 264 pertry.tv_usec = 0; 265 if ((clp = clntudp_create(&saddr, RPCPROG_MNT, RPCMNT_VER1, 266 pertry, &so)) == NULL) { 267 clnt_pcreateerror("Cannot MNT PRC"); 268 return (1); 269 } 270 clp->cl_auth = authunix_create_default(); 271 try.tv_sec = 20; 272 try.tv_usec = 0; 273 clnt_stat = clnt_call(clp, RPCMNT_UMOUNT, xdr_dir, name, 274 xdr_void, (caddr_t)0, try); 275 if (clnt_stat != RPC_SUCCESS) { 276 clnt_perror(clp, "Bad MNT RPC"); 277 return (1); 278 } 279 auth_destroy(clp->cl_auth); 280 clnt_destroy(clp); 281 } 282 #endif /* NFS */ 283 return (1); 284 } 285 286 char * 287 getmntname(name, what, type) 288 char *name; 289 int what; 290 int *type; 291 { 292 int mntsize, i; 293 struct statfs *mntbuf; 294 295 if ((mntsize = getmntinfo(&mntbuf, MNT_NOWAIT)) == 0) { 296 perror("umount"); 297 return (0); 298 } 299 for (i = 0; i < mntsize; i++) { 300 if (what == MNTON && !strcmp(mntbuf[i].f_mntfromname, name)) { 301 if (type) 302 *type = mntbuf[i].f_type; 303 return (mntbuf[i].f_mntonname); 304 } 305 if (what == MNTFROM && !strcmp(mntbuf[i].f_mntonname, name)) { 306 if (type) 307 *type = mntbuf[i].f_type; 308 return (mntbuf[i].f_mntfromname); 309 } 310 } 311 fprintf(stderr, "%s: not currently mounted\n", name); 312 return (0); 313 } 314 315 static int skipvfs; 316 317 badtype(type, typelist) 318 int type; 319 int *typelist; 320 { 321 if (typelist == 0) 322 return(0); 323 while (*typelist) { 324 if (type == *typelist) 325 return(skipvfs); 326 typelist++; 327 } 328 return(!skipvfs); 329 } 330 331 int * 332 maketypelist(fslist) 333 char *fslist; 334 { 335 register char *nextcp; 336 register int *av, i; 337 338 if (fslist == NULL) 339 return(NULL); 340 if (fslist[0] == 'n' && fslist[1] == 'o') { 341 fslist += 2; 342 skipvfs = 1; 343 } else 344 skipvfs = 0; 345 for (i = 0, nextcp = fslist; *nextcp; nextcp++) 346 if (*nextcp == ',') 347 i++; 348 av = (int *)malloc((i+2) * sizeof(int)); 349 if (av == NULL) 350 return(NULL); 351 for (i = 0; fslist; fslist = nextcp) { 352 if (nextcp = index(fslist, ',')) 353 *nextcp++ = '\0'; 354 if (strcmp(fslist, "ufs") == 0) 355 av[i++] = MOUNT_UFS; 356 else if (strcmp(fslist, "nfs") == 0) 357 av[i++] = MOUNT_NFS; 358 else if (strcmp(fslist, "mfs") == 0) 359 av[i++] = MOUNT_MFS; 360 else if (strcmp(fslist, "pc") == 0) 361 av[i++] = MOUNT_PC; 362 } 363 av[i++] = 0; 364 return(av); 365 } 366 367 #ifdef NFS 368 namematch(hp, nfshost) 369 struct hostent *hp; 370 char *nfshost; 371 { 372 register char *cp; 373 register char **np; 374 375 if (hp == NULL || nfshost == NULL) 376 return(1); 377 if (strcasecmp(nfshost, hp->h_name) == 0) 378 return(1); 379 if (cp = index(hp->h_name, '.')) { 380 *cp = '\0'; 381 if (strcasecmp(nfshost, hp->h_name) == 0) 382 return(1); 383 } 384 for (np = hp->h_aliases; *np; np++) { 385 if (strcasecmp(nfshost, *np) == 0) 386 return(1); 387 if (cp = index(*np, '.')) { 388 *cp = '\0'; 389 if (strcasecmp(nfshost, *np) == 0) 390 return(1); 391 } 392 } 393 return(0); 394 } 395 396 /* 397 * xdr routines for mount rpc's 398 */ 399 xdr_dir(xdrsp, dirp) 400 XDR *xdrsp; 401 char *dirp; 402 { 403 return (xdr_string(xdrsp, &dirp, RPCMNT_PATHLEN)); 404 } 405 #endif /* NFS */ 406