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