/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (the "License"). You may not use this file except in compliance * with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright (c) 1999 by Sun Microsystems, Inc. * All rights reserved. */ #pragma ident "%Z%%M% %I% %E% SMI" /* * fastfs * user interface to dio (delayed IO) functionality */ #include #include #include #include #include #include #include #include #include #include /* * make vfstab look like fstab */ #include #define fstab vfstab #define FSTAB VFSTAB #define fs_spec vfs_special #define fs_file vfs_mountp #define setmntent fopen #define endmntent fclose #define mntent mnttab #define mnt_fsname mnt_special #define mnt_dir mnt_mountp #define mnt_type mnt_fstype #define MNTTYPE_42 "ufs" #define MNTINFO_DEV "dev" #define MOUNTED MNTTAB static struct mntent * mygetmntent(f, name) FILE *f; char *name; { static struct mntent mt; int status; if ((status = getmntent(f, &mt)) == 0) return (&mt); switch (status) { case EOF: break; /* normal exit condition */ case MNT_TOOLONG: (void) fprintf(stderr, "%s has a line that is too long\n", name); break; case MNT_TOOMANY: (void) fprintf(stderr, "%s has a line with too many entries\n", name); break; case MNT_TOOFEW: (void) fprintf(stderr, "%s has a line with too few entries\n", name); break; default: (void) fprintf(stderr, "Unknown return code, %d, from getmntent() on %s\n", status, name); break; } return (NULL); } /* * -a = all * -f = fast * -s = safe */ static int all = 0; static int fast = 0; static int safe = 0; /* * exitstatus * 0 all ok * 1 internal error * 2 system call error */ static int exitstatus = 0; /* * list of filenames */ struct filename { struct filename *fn_next; char *fn_name; }; static struct filename *fnanchor = 0; /* * for prettyprint */ static int firsttime = 0; /* * no safe's printed */ static int no_safes_printed = 0; static void exitusage(void); static void printstatusline(char *, char *); static void printstatus(char *); static void getmntnames(void); static void getcmdnames(int, char **, int); static void setdio(char *); int main(int argc, char **argv) { int c; struct filename *fnp; (void) setlocale(LC_ALL, ""); #if !defined(TEXT_DOMAIN) #define TEXT_DOMAIN "SYS_TEST" #endif (void) textdomain(TEXT_DOMAIN); exitstatus = 0; /* * process command line */ opterr = 0; optarg = 0; while ((c = getopt(argc, argv, "afs")) != -1) switch (c) { case 'a': all = 1; break; case 'f': fast = 1; break; case 's': safe = 1; break; default: exitusage(); break; } if (argc == 1) { no_safes_printed = 1; all = 1; } if (all) /* * use /etc/mtab */ getmntnames(); else /* * use command line */ getcmdnames(argc, argv, optind); /* * for each filename, doit */ for (fnp = fnanchor; fnp; fnp = fnp->fn_next) { if (fast || safe) setdio(fnp->fn_name); else printstatus(fnp->fn_name); } /* * all done */ return (exitstatus); } /* * exitusage * bad command line, give hint */ static void exitusage(void) { (void) fprintf(stderr, "usage: fastfs [-vfs] [-a] [file system ...]\n"); exit(1); } /* * printstatusline * prettyprint the status line */ static void printstatusline(fn, mode) char *fn; char *mode; { if (firsttime++ == 0) (void) printf("%-20s %-10s\n", "Filesystem", "Mode"); (void) printf("%-20s %-10s\n", fn, mode); } /* * printstatus * get and prettyprint file system lock status */ static void printstatus(fn) char *fn; { int fd; int dioval; fd = open(fn, O_RDONLY); if (fd == -1) { perror(fn); exitstatus = 2; return; } if (ioctl(fd, _FIOGDIO, &dioval) == -1) { perror(fn); (void) close(fd); exitstatus = 2; return; } if (dioval) printstatusline(fn, "fast"); else if (no_safes_printed == 0) printstatusline(fn, "safe"); (void) close(fd); } /* * getmntnames * file names from /etc/mtab */ static void getmntnames(void) { int fnlen; struct filename *fnp; struct filename *fnpc; FILE *mnttab; struct mntent *mntp; fnpc = fnanchor; mnttab = setmntent(MOUNTED, "r"); while ((mntp = mygetmntent(mnttab, MOUNTED)) != NULL) { if (mntp->mnt_type == (char *)0 || strcmp(mntp->mnt_type, MNTTYPE_42) != 0) continue; if (mntp->mnt_dir == (char *)0) mntp->mnt_dir = ""; fnlen = strlen(mntp->mnt_dir) + 1; fnp = (struct filename *)malloc(sizeof (struct filename)); fnp->fn_name = malloc((u_int)fnlen); (void) strcpy(fnp->fn_name, mntp->mnt_dir); fnp->fn_next = NULL; if (fnpc) fnpc->fn_next = fnp; else fnanchor = fnp; fnpc = fnp; } (void) endmntent(mnttab); } /* * getcmdnames * file names from command line */ static void getcmdnames(argc, argv, i) int argc; char **argv; int i; { struct filename *fnp; struct filename *fnpc; for (fnpc = fnanchor; i < argc; ++i) { fnp = (struct filename *)malloc(sizeof (struct filename)); fnp->fn_name = *(argv+i); fnp->fn_next = NULL; if (fnpc) fnpc->fn_next = fnp; else fnanchor = fnp; fnpc = fnp; } } /* * setdio * set the dio mode */ static void setdio(fn) char *fn; { int fd; int dioval; fd = open(fn, O_RDONLY); if (fd == -1) { perror(fn); exitstatus = 2; return; } if (fast) dioval = 1; if (safe) dioval = 0; if (ioctl(fd, _FIOSDIO, &dioval) == -1) { perror(fn); exitstatus = 2; } (void) close(fd); }