1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright 2003 Sun Microsystems, Inc. All rights reserved. 24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 25*7c478bd9Sstevel@tonic-gate */ 26*7c478bd9Sstevel@tonic-gate 27*7c478bd9Sstevel@tonic-gate /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 28*7c478bd9Sstevel@tonic-gate /* All Rights Reserved */ 29*7c478bd9Sstevel@tonic-gate 30*7c478bd9Sstevel@tonic-gate /* 31*7c478bd9Sstevel@tonic-gate * University Copyright- Copyright (c) 1982, 1986, 1988 32*7c478bd9Sstevel@tonic-gate * The Regents of the University of California 33*7c478bd9Sstevel@tonic-gate * All Rights Reserved 34*7c478bd9Sstevel@tonic-gate * 35*7c478bd9Sstevel@tonic-gate * University Acknowledgment- Portions of this document are derived from 36*7c478bd9Sstevel@tonic-gate * software developed by the University of California, Berkeley, and its 37*7c478bd9Sstevel@tonic-gate * contributors. 38*7c478bd9Sstevel@tonic-gate */ 39*7c478bd9Sstevel@tonic-gate 40*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 41*7c478bd9Sstevel@tonic-gate 42*7c478bd9Sstevel@tonic-gate /* 43*7c478bd9Sstevel@tonic-gate * Fix up / report on disc quotas & usage 44*7c478bd9Sstevel@tonic-gate */ 45*7c478bd9Sstevel@tonic-gate #include <stdlib.h> 46*7c478bd9Sstevel@tonic-gate #include <string.h> 47*7c478bd9Sstevel@tonic-gate #include <stdio.h> 48*7c478bd9Sstevel@tonic-gate #include <ctype.h> 49*7c478bd9Sstevel@tonic-gate #include <signal.h> 50*7c478bd9Sstevel@tonic-gate #include <errno.h> 51*7c478bd9Sstevel@tonic-gate #include <fcntl.h> 52*7c478bd9Sstevel@tonic-gate #include <sys/filio.h> 53*7c478bd9Sstevel@tonic-gate #include <limits.h> 54*7c478bd9Sstevel@tonic-gate #include <sys/param.h> 55*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 56*7c478bd9Sstevel@tonic-gate #include <sys/mntent.h> 57*7c478bd9Sstevel@tonic-gate 58*7c478bd9Sstevel@tonic-gate #include <sys/vnode.h> 59*7c478bd9Sstevel@tonic-gate #include <sys/fs/ufs_inode.h> 60*7c478bd9Sstevel@tonic-gate #include <sys/fs/ufs_fs.h> 61*7c478bd9Sstevel@tonic-gate #include <sys/fs/ufs_quota.h> 62*7c478bd9Sstevel@tonic-gate #include <sys/stat.h> 63*7c478bd9Sstevel@tonic-gate #include <sys/wait.h> 64*7c478bd9Sstevel@tonic-gate #include <sys/mnttab.h> 65*7c478bd9Sstevel@tonic-gate #include <sys/vfstab.h> 66*7c478bd9Sstevel@tonic-gate #include <pwd.h> 67*7c478bd9Sstevel@tonic-gate #include <iso/limits_iso.h> 68*7c478bd9Sstevel@tonic-gate 69*7c478bd9Sstevel@tonic-gate union { 70*7c478bd9Sstevel@tonic-gate struct fs sblk; 71*7c478bd9Sstevel@tonic-gate char dummy[MAXBSIZE]; 72*7c478bd9Sstevel@tonic-gate } un; 73*7c478bd9Sstevel@tonic-gate #define sblock un.sblk 74*7c478bd9Sstevel@tonic-gate 75*7c478bd9Sstevel@tonic-gate #define ITABSZ 256 76*7c478bd9Sstevel@tonic-gate struct dinode itab[ITABSZ]; 77*7c478bd9Sstevel@tonic-gate struct dinode *dp; 78*7c478bd9Sstevel@tonic-gate 79*7c478bd9Sstevel@tonic-gate struct fileusage { 80*7c478bd9Sstevel@tonic-gate struct fileusage *fu_next; 81*7c478bd9Sstevel@tonic-gate ulong_t fu_curfiles; 82*7c478bd9Sstevel@tonic-gate uint64_t fu_curblocks; 83*7c478bd9Sstevel@tonic-gate uid_t fu_uid; 84*7c478bd9Sstevel@tonic-gate }; 85*7c478bd9Sstevel@tonic-gate #define FUHASH 997 86*7c478bd9Sstevel@tonic-gate struct fileusage *fuhead[FUHASH]; 87*7c478bd9Sstevel@tonic-gate struct fileusage *lookup(uid_t); 88*7c478bd9Sstevel@tonic-gate struct fileusage *adduid(uid_t); 89*7c478bd9Sstevel@tonic-gate 90*7c478bd9Sstevel@tonic-gate int fi; 91*7c478bd9Sstevel@tonic-gate ino_t ino; 92*7c478bd9Sstevel@tonic-gate struct dinode *ginode(); 93*7c478bd9Sstevel@tonic-gate char *mntopt(), *hasvfsopt(), *hasmntopt(); 94*7c478bd9Sstevel@tonic-gate 95*7c478bd9Sstevel@tonic-gate extern int optind; 96*7c478bd9Sstevel@tonic-gate extern char *optarg; 97*7c478bd9Sstevel@tonic-gate extern int fsync(int); 98*7c478bd9Sstevel@tonic-gate 99*7c478bd9Sstevel@tonic-gate static void acct(); 100*7c478bd9Sstevel@tonic-gate static void bread(); 101*7c478bd9Sstevel@tonic-gate static void usage(); 102*7c478bd9Sstevel@tonic-gate static int chkquota(); 103*7c478bd9Sstevel@tonic-gate static int quotactl(); 104*7c478bd9Sstevel@tonic-gate static int preen(); 105*7c478bd9Sstevel@tonic-gate static int waiter(); 106*7c478bd9Sstevel@tonic-gate static int oneof(); 107*7c478bd9Sstevel@tonic-gate 108*7c478bd9Sstevel@tonic-gate int vflag; /* verbose */ 109*7c478bd9Sstevel@tonic-gate int aflag; /* all file systems */ 110*7c478bd9Sstevel@tonic-gate int pflag; /* fsck like parallel check */ 111*7c478bd9Sstevel@tonic-gate int fflag; /* force flag */ 112*7c478bd9Sstevel@tonic-gate 113*7c478bd9Sstevel@tonic-gate #define QFNAME "quotas" 114*7c478bd9Sstevel@tonic-gate #define CHUNK 50 115*7c478bd9Sstevel@tonic-gate char **listbuf; 116*7c478bd9Sstevel@tonic-gate struct dqblk zerodqbuf; 117*7c478bd9Sstevel@tonic-gate struct fileusage zerofileusage; 118*7c478bd9Sstevel@tonic-gate 119*7c478bd9Sstevel@tonic-gate void 120*7c478bd9Sstevel@tonic-gate main(int argc, char **argv) 121*7c478bd9Sstevel@tonic-gate { 122*7c478bd9Sstevel@tonic-gate struct mnttab mntp; 123*7c478bd9Sstevel@tonic-gate struct vfstab vfsbuf; 124*7c478bd9Sstevel@tonic-gate char **listp; 125*7c478bd9Sstevel@tonic-gate int listcnt; 126*7c478bd9Sstevel@tonic-gate int listmax = 0; 127*7c478bd9Sstevel@tonic-gate char quotafile[MAXPATHLEN]; 128*7c478bd9Sstevel@tonic-gate FILE *mtab, *vfstab; 129*7c478bd9Sstevel@tonic-gate int errs = 0; 130*7c478bd9Sstevel@tonic-gate int opt; 131*7c478bd9Sstevel@tonic-gate 132*7c478bd9Sstevel@tonic-gate if ((listbuf = (char **)malloc(sizeof (char *) * CHUNK)) == NULL) { 133*7c478bd9Sstevel@tonic-gate fprintf(stderr, "Can't alloc lisbuf array."); 134*7c478bd9Sstevel@tonic-gate exit(31+1); 135*7c478bd9Sstevel@tonic-gate } 136*7c478bd9Sstevel@tonic-gate listmax = CHUNK; 137*7c478bd9Sstevel@tonic-gate while ((opt = getopt(argc, argv, "vapVf")) != EOF) { 138*7c478bd9Sstevel@tonic-gate switch (opt) { 139*7c478bd9Sstevel@tonic-gate 140*7c478bd9Sstevel@tonic-gate case 'v': 141*7c478bd9Sstevel@tonic-gate vflag++; 142*7c478bd9Sstevel@tonic-gate break; 143*7c478bd9Sstevel@tonic-gate 144*7c478bd9Sstevel@tonic-gate case 'a': 145*7c478bd9Sstevel@tonic-gate aflag++; 146*7c478bd9Sstevel@tonic-gate break; 147*7c478bd9Sstevel@tonic-gate 148*7c478bd9Sstevel@tonic-gate case 'p': 149*7c478bd9Sstevel@tonic-gate pflag++; 150*7c478bd9Sstevel@tonic-gate break; 151*7c478bd9Sstevel@tonic-gate 152*7c478bd9Sstevel@tonic-gate case 'V': /* Print command line */ 153*7c478bd9Sstevel@tonic-gate { 154*7c478bd9Sstevel@tonic-gate char *opt_text; 155*7c478bd9Sstevel@tonic-gate int opt_count; 156*7c478bd9Sstevel@tonic-gate 157*7c478bd9Sstevel@tonic-gate (void) fprintf(stdout, "quotacheck -F UFS "); 158*7c478bd9Sstevel@tonic-gate for (opt_count = 1; opt_count < argc; 159*7c478bd9Sstevel@tonic-gate opt_count++) { 160*7c478bd9Sstevel@tonic-gate opt_text = argv[opt_count]; 161*7c478bd9Sstevel@tonic-gate if (opt_text) 162*7c478bd9Sstevel@tonic-gate (void) fprintf(stdout, " %s ", 163*7c478bd9Sstevel@tonic-gate opt_text); 164*7c478bd9Sstevel@tonic-gate } 165*7c478bd9Sstevel@tonic-gate (void) fprintf(stdout, "\n"); 166*7c478bd9Sstevel@tonic-gate } 167*7c478bd9Sstevel@tonic-gate break; 168*7c478bd9Sstevel@tonic-gate 169*7c478bd9Sstevel@tonic-gate case 'f': 170*7c478bd9Sstevel@tonic-gate fflag++; 171*7c478bd9Sstevel@tonic-gate break; 172*7c478bd9Sstevel@tonic-gate 173*7c478bd9Sstevel@tonic-gate case '?': 174*7c478bd9Sstevel@tonic-gate usage(); 175*7c478bd9Sstevel@tonic-gate } 176*7c478bd9Sstevel@tonic-gate } 177*7c478bd9Sstevel@tonic-gate if (argc <= optind && !aflag) { 178*7c478bd9Sstevel@tonic-gate usage(); 179*7c478bd9Sstevel@tonic-gate } 180*7c478bd9Sstevel@tonic-gate 181*7c478bd9Sstevel@tonic-gate if (quotactl(Q_ALLSYNC, NULL, (uid_t)0, NULL) < 0 && 182*7c478bd9Sstevel@tonic-gate errno == EINVAL && vflag) 183*7c478bd9Sstevel@tonic-gate printf("Warning: Quotas are not compiled into this kernel\n"); 184*7c478bd9Sstevel@tonic-gate sync(); 185*7c478bd9Sstevel@tonic-gate 186*7c478bd9Sstevel@tonic-gate if (aflag) { 187*7c478bd9Sstevel@tonic-gate /* 188*7c478bd9Sstevel@tonic-gate * Go through vfstab and make a list of appropriate 189*7c478bd9Sstevel@tonic-gate * filesystems. 190*7c478bd9Sstevel@tonic-gate */ 191*7c478bd9Sstevel@tonic-gate listp = listbuf; 192*7c478bd9Sstevel@tonic-gate listcnt = 0; 193*7c478bd9Sstevel@tonic-gate if ((vfstab = fopen(VFSTAB, "r")) == NULL) { 194*7c478bd9Sstevel@tonic-gate fprintf(stderr, "Can't open "); 195*7c478bd9Sstevel@tonic-gate perror(VFSTAB); 196*7c478bd9Sstevel@tonic-gate exit(31+8); 197*7c478bd9Sstevel@tonic-gate } 198*7c478bd9Sstevel@tonic-gate while (getvfsent(vfstab, &vfsbuf) == NULL) { 199*7c478bd9Sstevel@tonic-gate if (strcmp(vfsbuf.vfs_fstype, MNTTYPE_UFS) != 0 || 200*7c478bd9Sstevel@tonic-gate (vfsbuf.vfs_mntopts == 0) || 201*7c478bd9Sstevel@tonic-gate hasvfsopt(&vfsbuf, MNTOPT_RO) || 202*7c478bd9Sstevel@tonic-gate (!hasvfsopt(&vfsbuf, MNTOPT_RQ) && 203*7c478bd9Sstevel@tonic-gate !hasvfsopt(&vfsbuf, MNTOPT_QUOTA))) 204*7c478bd9Sstevel@tonic-gate continue; 205*7c478bd9Sstevel@tonic-gate *listp = malloc(strlen(vfsbuf.vfs_special) + 1); 206*7c478bd9Sstevel@tonic-gate strcpy(*listp, vfsbuf.vfs_special); 207*7c478bd9Sstevel@tonic-gate listp++; 208*7c478bd9Sstevel@tonic-gate listcnt++; 209*7c478bd9Sstevel@tonic-gate /* grow listbuf if needed */ 210*7c478bd9Sstevel@tonic-gate if (listcnt >= listmax) { 211*7c478bd9Sstevel@tonic-gate listmax += CHUNK; 212*7c478bd9Sstevel@tonic-gate listbuf = (char **)realloc(listbuf, 213*7c478bd9Sstevel@tonic-gate sizeof (char *) * listmax); 214*7c478bd9Sstevel@tonic-gate if (listbuf == NULL) { 215*7c478bd9Sstevel@tonic-gate fprintf(stderr, 216*7c478bd9Sstevel@tonic-gate "Can't grow listbuf.\n"); 217*7c478bd9Sstevel@tonic-gate exit(31+1); 218*7c478bd9Sstevel@tonic-gate } 219*7c478bd9Sstevel@tonic-gate listp = &listbuf[listcnt]; 220*7c478bd9Sstevel@tonic-gate } 221*7c478bd9Sstevel@tonic-gate } 222*7c478bd9Sstevel@tonic-gate fclose(vfstab); 223*7c478bd9Sstevel@tonic-gate *listp = (char *)0; 224*7c478bd9Sstevel@tonic-gate listp = listbuf; 225*7c478bd9Sstevel@tonic-gate } else { 226*7c478bd9Sstevel@tonic-gate listp = &argv[optind]; 227*7c478bd9Sstevel@tonic-gate listcnt = argc - optind; 228*7c478bd9Sstevel@tonic-gate } 229*7c478bd9Sstevel@tonic-gate if (pflag) { 230*7c478bd9Sstevel@tonic-gate errs = preen(listcnt, listp); 231*7c478bd9Sstevel@tonic-gate } else { 232*7c478bd9Sstevel@tonic-gate if ((mtab = fopen(MNTTAB, "r")) == NULL) { 233*7c478bd9Sstevel@tonic-gate fprintf(stderr, "Can't open "); 234*7c478bd9Sstevel@tonic-gate perror(MNTTAB); 235*7c478bd9Sstevel@tonic-gate exit(31+8); 236*7c478bd9Sstevel@tonic-gate } 237*7c478bd9Sstevel@tonic-gate while (getmntent(mtab, &mntp) == NULL) { 238*7c478bd9Sstevel@tonic-gate if (strcmp(mntp.mnt_fstype, MNTTYPE_UFS) == 0 && 239*7c478bd9Sstevel@tonic-gate !hasmntopt(&mntp, MNTOPT_RO) && 240*7c478bd9Sstevel@tonic-gate (oneof(mntp.mnt_special, listp, listcnt) || 241*7c478bd9Sstevel@tonic-gate oneof(mntp.mnt_mountp, listp, listcnt))) { 242*7c478bd9Sstevel@tonic-gate (void) snprintf(quotafile, sizeof (quotafile), 243*7c478bd9Sstevel@tonic-gate "%s/%s", mntp.mnt_mountp, QFNAME); 244*7c478bd9Sstevel@tonic-gate errs += 245*7c478bd9Sstevel@tonic-gate chkquota(mntp.mnt_special, 246*7c478bd9Sstevel@tonic-gate mntp.mnt_mountp, quotafile); 247*7c478bd9Sstevel@tonic-gate } 248*7c478bd9Sstevel@tonic-gate } 249*7c478bd9Sstevel@tonic-gate fclose(mtab); 250*7c478bd9Sstevel@tonic-gate } 251*7c478bd9Sstevel@tonic-gate while (listcnt--) { 252*7c478bd9Sstevel@tonic-gate if (*listp) { 253*7c478bd9Sstevel@tonic-gate fprintf(stderr, "Cannot check %s\n", *listp); 254*7c478bd9Sstevel@tonic-gate errs++; 255*7c478bd9Sstevel@tonic-gate } 256*7c478bd9Sstevel@tonic-gate listp++; 257*7c478bd9Sstevel@tonic-gate } 258*7c478bd9Sstevel@tonic-gate if (errs > 0) 259*7c478bd9Sstevel@tonic-gate errs += 31; 260*7c478bd9Sstevel@tonic-gate exit(errs); 261*7c478bd9Sstevel@tonic-gate } 262*7c478bd9Sstevel@tonic-gate 263*7c478bd9Sstevel@tonic-gate static struct active { 264*7c478bd9Sstevel@tonic-gate char *rdev; 265*7c478bd9Sstevel@tonic-gate pid_t pid; 266*7c478bd9Sstevel@tonic-gate struct active *nxt; 267*7c478bd9Sstevel@tonic-gate }; 268*7c478bd9Sstevel@tonic-gate 269*7c478bd9Sstevel@tonic-gate int 270*7c478bd9Sstevel@tonic-gate preen(listcnt, listp) 271*7c478bd9Sstevel@tonic-gate int listcnt; 272*7c478bd9Sstevel@tonic-gate char **listp; 273*7c478bd9Sstevel@tonic-gate { 274*7c478bd9Sstevel@tonic-gate register int i, rc, errs; 275*7c478bd9Sstevel@tonic-gate register char **lp, *rdev, *bdev; 276*7c478bd9Sstevel@tonic-gate extern char *getfullrawname(), *getfullblkname(); 277*7c478bd9Sstevel@tonic-gate struct mnttab mntp, mpref; 278*7c478bd9Sstevel@tonic-gate struct active *alist, *ap; 279*7c478bd9Sstevel@tonic-gate FILE *mtab; 280*7c478bd9Sstevel@tonic-gate char quotafile[MAXPATHLEN]; 281*7c478bd9Sstevel@tonic-gate char name[MAXPATHLEN]; 282*7c478bd9Sstevel@tonic-gate int nactive, serially; 283*7c478bd9Sstevel@tonic-gate 284*7c478bd9Sstevel@tonic-gate if ((mtab = fopen(MNTTAB, "r")) == NULL) { 285*7c478bd9Sstevel@tonic-gate fprintf(stderr, "Can't open "); 286*7c478bd9Sstevel@tonic-gate perror(MNTTAB); 287*7c478bd9Sstevel@tonic-gate exit(31+8); 288*7c478bd9Sstevel@tonic-gate } 289*7c478bd9Sstevel@tonic-gate memset(&mpref, 0, sizeof (struct mnttab)); 290*7c478bd9Sstevel@tonic-gate errs = 0; 291*7c478bd9Sstevel@tonic-gate 292*7c478bd9Sstevel@tonic-gate for (lp = listp, i = 0; i < listcnt; lp++, i++) { 293*7c478bd9Sstevel@tonic-gate serially = 0; 294*7c478bd9Sstevel@tonic-gate rdev = getfullrawname(*lp); 295*7c478bd9Sstevel@tonic-gate if (rdev == NULL || *rdev == '\0') { 296*7c478bd9Sstevel@tonic-gate fprintf(stderr, "can't get rawname for `%s'\n", *lp); 297*7c478bd9Sstevel@tonic-gate serially = 1; 298*7c478bd9Sstevel@tonic-gate } else if (preen_addev(rdev) != 0) { 299*7c478bd9Sstevel@tonic-gate fprintf(stderr, "preen_addev error\n"); 300*7c478bd9Sstevel@tonic-gate serially = 1; 301*7c478bd9Sstevel@tonic-gate } 302*7c478bd9Sstevel@tonic-gate 303*7c478bd9Sstevel@tonic-gate if (rdev != NULL) 304*7c478bd9Sstevel@tonic-gate free(rdev); 305*7c478bd9Sstevel@tonic-gate 306*7c478bd9Sstevel@tonic-gate if (serially) { 307*7c478bd9Sstevel@tonic-gate rewind(mtab); 308*7c478bd9Sstevel@tonic-gate mpref.mnt_special = *lp; 309*7c478bd9Sstevel@tonic-gate if (getmntany(mtab, &mntp, &mpref) == 0 && 310*7c478bd9Sstevel@tonic-gate strcmp(mntp.mnt_fstype, MNTTYPE_UFS) == 0 && 311*7c478bd9Sstevel@tonic-gate !hasmntopt(&mntp, MNTOPT_RO)) { 312*7c478bd9Sstevel@tonic-gate errs += (31+chkquota(mntp.mnt_special, 313*7c478bd9Sstevel@tonic-gate mntp.mnt_mountp, quotafile)); 314*7c478bd9Sstevel@tonic-gate *lp = (char *)0; 315*7c478bd9Sstevel@tonic-gate } 316*7c478bd9Sstevel@tonic-gate } 317*7c478bd9Sstevel@tonic-gate } 318*7c478bd9Sstevel@tonic-gate 319*7c478bd9Sstevel@tonic-gate nactive = 0; 320*7c478bd9Sstevel@tonic-gate alist = NULL; 321*7c478bd9Sstevel@tonic-gate while ((rc = preen_getdev(name)) > 0) { 322*7c478bd9Sstevel@tonic-gate switch (rc) { 323*7c478bd9Sstevel@tonic-gate case 1: 324*7c478bd9Sstevel@tonic-gate bdev = getfullblkname(name); 325*7c478bd9Sstevel@tonic-gate if (bdev == NULL || *bdev == '\0') { 326*7c478bd9Sstevel@tonic-gate fprintf(stderr, "can't get blkname for `%s'\n", 327*7c478bd9Sstevel@tonic-gate name); 328*7c478bd9Sstevel@tonic-gate if (bdev) 329*7c478bd9Sstevel@tonic-gate free(bdev); 330*7c478bd9Sstevel@tonic-gate continue; 331*7c478bd9Sstevel@tonic-gate } 332*7c478bd9Sstevel@tonic-gate rewind(mtab); 333*7c478bd9Sstevel@tonic-gate mpref.mnt_special = bdev; 334*7c478bd9Sstevel@tonic-gate if (getmntany(mtab, &mntp, &mpref) != 0) { 335*7c478bd9Sstevel@tonic-gate fprintf(stderr, "`%s' not mounted?\n", name); 336*7c478bd9Sstevel@tonic-gate preen_releasedev(name); 337*7c478bd9Sstevel@tonic-gate free(bdev); 338*7c478bd9Sstevel@tonic-gate continue; 339*7c478bd9Sstevel@tonic-gate } else if (strcmp(mntp.mnt_fstype, MNTTYPE_UFS) != 0 || 340*7c478bd9Sstevel@tonic-gate hasmntopt(&mntp, MNTOPT_RO) || 341*7c478bd9Sstevel@tonic-gate (!oneof(mntp.mnt_special, listp, listcnt) && 342*7c478bd9Sstevel@tonic-gate !oneof(mntp.mnt_mountp, listp, listcnt))) { 343*7c478bd9Sstevel@tonic-gate preen_releasedev(name); 344*7c478bd9Sstevel@tonic-gate free(bdev); 345*7c478bd9Sstevel@tonic-gate continue; 346*7c478bd9Sstevel@tonic-gate } 347*7c478bd9Sstevel@tonic-gate free(bdev); 348*7c478bd9Sstevel@tonic-gate ap = (struct active *)malloc(sizeof (struct active)); 349*7c478bd9Sstevel@tonic-gate if (ap == NULL) { 350*7c478bd9Sstevel@tonic-gate fprintf(stderr, "out of memory\n"); 351*7c478bd9Sstevel@tonic-gate exit(31+8); 352*7c478bd9Sstevel@tonic-gate } 353*7c478bd9Sstevel@tonic-gate ap->rdev = (char *)strdup(name); 354*7c478bd9Sstevel@tonic-gate if (ap->rdev == NULL) { 355*7c478bd9Sstevel@tonic-gate fprintf(stderr, "out of memory\n"); 356*7c478bd9Sstevel@tonic-gate exit(31+8); 357*7c478bd9Sstevel@tonic-gate } 358*7c478bd9Sstevel@tonic-gate ap->nxt = alist; 359*7c478bd9Sstevel@tonic-gate alist = ap; 360*7c478bd9Sstevel@tonic-gate switch (ap->pid = fork()) { 361*7c478bd9Sstevel@tonic-gate case -1: 362*7c478bd9Sstevel@tonic-gate perror("fork"); 363*7c478bd9Sstevel@tonic-gate exit(31+8); 364*7c478bd9Sstevel@tonic-gate break; 365*7c478bd9Sstevel@tonic-gate case 0: 366*7c478bd9Sstevel@tonic-gate (void) snprintf(quotafile, sizeof (quotafile), 367*7c478bd9Sstevel@tonic-gate "%s/%s", mntp.mnt_mountp, QFNAME); 368*7c478bd9Sstevel@tonic-gate exit(31+chkquota(mntp.mnt_special, 369*7c478bd9Sstevel@tonic-gate mntp.mnt_mountp, quotafile)); 370*7c478bd9Sstevel@tonic-gate break; 371*7c478bd9Sstevel@tonic-gate default: 372*7c478bd9Sstevel@tonic-gate nactive++; 373*7c478bd9Sstevel@tonic-gate break; 374*7c478bd9Sstevel@tonic-gate } 375*7c478bd9Sstevel@tonic-gate break; 376*7c478bd9Sstevel@tonic-gate case 2: 377*7c478bd9Sstevel@tonic-gate errs += waiter(&alist); 378*7c478bd9Sstevel@tonic-gate nactive--; 379*7c478bd9Sstevel@tonic-gate break; 380*7c478bd9Sstevel@tonic-gate } 381*7c478bd9Sstevel@tonic-gate } 382*7c478bd9Sstevel@tonic-gate fclose(mtab); 383*7c478bd9Sstevel@tonic-gate 384*7c478bd9Sstevel@tonic-gate while (nactive > 0) { 385*7c478bd9Sstevel@tonic-gate errs += waiter(&alist); 386*7c478bd9Sstevel@tonic-gate nactive--; 387*7c478bd9Sstevel@tonic-gate } 388*7c478bd9Sstevel@tonic-gate return (errs); 389*7c478bd9Sstevel@tonic-gate } 390*7c478bd9Sstevel@tonic-gate 391*7c478bd9Sstevel@tonic-gate int 392*7c478bd9Sstevel@tonic-gate waiter(alp) 393*7c478bd9Sstevel@tonic-gate struct active **alp; 394*7c478bd9Sstevel@tonic-gate { 395*7c478bd9Sstevel@tonic-gate pid_t curpid; 396*7c478bd9Sstevel@tonic-gate int status; 397*7c478bd9Sstevel@tonic-gate register struct active *ap, *lap; 398*7c478bd9Sstevel@tonic-gate 399*7c478bd9Sstevel@tonic-gate curpid = wait(&status); 400*7c478bd9Sstevel@tonic-gate if (curpid == -1) { 401*7c478bd9Sstevel@tonic-gate if (errno == ECHILD) 402*7c478bd9Sstevel@tonic-gate return (0); 403*7c478bd9Sstevel@tonic-gate perror("wait"); 404*7c478bd9Sstevel@tonic-gate exit(31+8); 405*7c478bd9Sstevel@tonic-gate } 406*7c478bd9Sstevel@tonic-gate 407*7c478bd9Sstevel@tonic-gate for (lap = NULL, ap = *alp; ap != NULL; lap = ap, ap = ap->nxt) { 408*7c478bd9Sstevel@tonic-gate if (ap->pid == curpid) 409*7c478bd9Sstevel@tonic-gate break; 410*7c478bd9Sstevel@tonic-gate } 411*7c478bd9Sstevel@tonic-gate 412*7c478bd9Sstevel@tonic-gate if (ap == NULL) { 413*7c478bd9Sstevel@tonic-gate fprintf(stderr, "wait returns unknown pid\n"); 414*7c478bd9Sstevel@tonic-gate exit(31+8); 415*7c478bd9Sstevel@tonic-gate } else if (lap) { 416*7c478bd9Sstevel@tonic-gate lap->nxt = ap->nxt; 417*7c478bd9Sstevel@tonic-gate } else { 418*7c478bd9Sstevel@tonic-gate *alp = ap->nxt; 419*7c478bd9Sstevel@tonic-gate } 420*7c478bd9Sstevel@tonic-gate preen_releasedev(ap->rdev); 421*7c478bd9Sstevel@tonic-gate free(ap->rdev); 422*7c478bd9Sstevel@tonic-gate free(ap); 423*7c478bd9Sstevel@tonic-gate return (WHIBYTE(status)); 424*7c478bd9Sstevel@tonic-gate } 425*7c478bd9Sstevel@tonic-gate 426*7c478bd9Sstevel@tonic-gate int 427*7c478bd9Sstevel@tonic-gate chkquota(fsdev, fsfile, qffile) 428*7c478bd9Sstevel@tonic-gate char *fsdev; 429*7c478bd9Sstevel@tonic-gate char *fsfile; 430*7c478bd9Sstevel@tonic-gate char *qffile; 431*7c478bd9Sstevel@tonic-gate { 432*7c478bd9Sstevel@tonic-gate register struct fileusage *fup; 433*7c478bd9Sstevel@tonic-gate dev_t quotadev; 434*7c478bd9Sstevel@tonic-gate FILE *qf; 435*7c478bd9Sstevel@tonic-gate uid_t uid; 436*7c478bd9Sstevel@tonic-gate struct passwd *pw; 437*7c478bd9Sstevel@tonic-gate int cg, i; 438*7c478bd9Sstevel@tonic-gate char *rawdisk; 439*7c478bd9Sstevel@tonic-gate struct stat64 statb; 440*7c478bd9Sstevel@tonic-gate struct dqblk dqbuf; 441*7c478bd9Sstevel@tonic-gate extern char *getfullrawname(); 442*7c478bd9Sstevel@tonic-gate 443*7c478bd9Sstevel@tonic-gate if ((rawdisk = getfullrawname(fsdev)) == NULL) { 444*7c478bd9Sstevel@tonic-gate fprintf(stderr, "malloc failed\n"); 445*7c478bd9Sstevel@tonic-gate return (1); 446*7c478bd9Sstevel@tonic-gate } 447*7c478bd9Sstevel@tonic-gate 448*7c478bd9Sstevel@tonic-gate if (*rawdisk == '\0') { 449*7c478bd9Sstevel@tonic-gate fprintf(stderr, "Could not find character device for %s\n", 450*7c478bd9Sstevel@tonic-gate fsdev); 451*7c478bd9Sstevel@tonic-gate return (1); 452*7c478bd9Sstevel@tonic-gate } 453*7c478bd9Sstevel@tonic-gate 454*7c478bd9Sstevel@tonic-gate if (vflag) 455*7c478bd9Sstevel@tonic-gate printf("*** Checking quotas for %s (%s)\n", rawdisk, fsfile); 456*7c478bd9Sstevel@tonic-gate fi = open64(rawdisk, 0); 457*7c478bd9Sstevel@tonic-gate if (fi < 0) { 458*7c478bd9Sstevel@tonic-gate perror(rawdisk); 459*7c478bd9Sstevel@tonic-gate return (1); 460*7c478bd9Sstevel@tonic-gate } 461*7c478bd9Sstevel@tonic-gate qf = fopen64(qffile, "r+"); 462*7c478bd9Sstevel@tonic-gate if (qf == NULL) { 463*7c478bd9Sstevel@tonic-gate perror(qffile); 464*7c478bd9Sstevel@tonic-gate close(fi); 465*7c478bd9Sstevel@tonic-gate return (1); 466*7c478bd9Sstevel@tonic-gate } 467*7c478bd9Sstevel@tonic-gate if (fstat64(fileno(qf), &statb) < 0) { 468*7c478bd9Sstevel@tonic-gate perror(qffile); 469*7c478bd9Sstevel@tonic-gate fclose(qf); 470*7c478bd9Sstevel@tonic-gate close(fi); 471*7c478bd9Sstevel@tonic-gate return (1); 472*7c478bd9Sstevel@tonic-gate } 473*7c478bd9Sstevel@tonic-gate quotadev = statb.st_dev; 474*7c478bd9Sstevel@tonic-gate if (stat64(fsdev, &statb) < 0) { 475*7c478bd9Sstevel@tonic-gate perror(fsdev); 476*7c478bd9Sstevel@tonic-gate fclose(qf); 477*7c478bd9Sstevel@tonic-gate close(fi); 478*7c478bd9Sstevel@tonic-gate return (1); 479*7c478bd9Sstevel@tonic-gate } 480*7c478bd9Sstevel@tonic-gate if (quotadev != statb.st_rdev) { 481*7c478bd9Sstevel@tonic-gate fprintf(stderr, "%s dev (0x%x) mismatch %s dev (0x%x)\n", 482*7c478bd9Sstevel@tonic-gate qffile, quotadev, fsdev, statb.st_rdev); 483*7c478bd9Sstevel@tonic-gate fclose(qf); 484*7c478bd9Sstevel@tonic-gate close(fi); 485*7c478bd9Sstevel@tonic-gate return (1); 486*7c478bd9Sstevel@tonic-gate } 487*7c478bd9Sstevel@tonic-gate bread((diskaddr_t)SBLOCK, (char *)&sblock, SBSIZE); 488*7c478bd9Sstevel@tonic-gate 489*7c478bd9Sstevel@tonic-gate /* 490*7c478bd9Sstevel@tonic-gate * Flush filesystem since we are going to read 491*7c478bd9Sstevel@tonic-gate * disk raw and we want to make sure everything is 492*7c478bd9Sstevel@tonic-gate * synced to disk before we read it. 493*7c478bd9Sstevel@tonic-gate */ 494*7c478bd9Sstevel@tonic-gate 495*7c478bd9Sstevel@tonic-gate if (ioctl(fileno(qf), _FIOFFS, NULL) == -1) { 496*7c478bd9Sstevel@tonic-gate perror(qffile); 497*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s: cannot flush file system.\n", 498*7c478bd9Sstevel@tonic-gate qffile); 499*7c478bd9Sstevel@tonic-gate (void) fclose(qf); 500*7c478bd9Sstevel@tonic-gate return (1); 501*7c478bd9Sstevel@tonic-gate } 502*7c478bd9Sstevel@tonic-gate 503*7c478bd9Sstevel@tonic-gate /* 504*7c478bd9Sstevel@tonic-gate * no need to quotacheck a rw, mounted, and logging file system 505*7c478bd9Sstevel@tonic-gate */ 506*7c478bd9Sstevel@tonic-gate if ((fflag == 0) && pflag && 507*7c478bd9Sstevel@tonic-gate (FSOKAY == (sblock.fs_state + sblock.fs_time)) && 508*7c478bd9Sstevel@tonic-gate (sblock.fs_clean == FSLOG)) { 509*7c478bd9Sstevel@tonic-gate fclose(qf); 510*7c478bd9Sstevel@tonic-gate close(fi); 511*7c478bd9Sstevel@tonic-gate return (0); 512*7c478bd9Sstevel@tonic-gate } 513*7c478bd9Sstevel@tonic-gate ino = 0; 514*7c478bd9Sstevel@tonic-gate for (cg = 0; cg < sblock.fs_ncg; cg++) { 515*7c478bd9Sstevel@tonic-gate dp = NULL; 516*7c478bd9Sstevel@tonic-gate for (i = 0; i < sblock.fs_ipg; i++) 517*7c478bd9Sstevel@tonic-gate acct(ginode()); 518*7c478bd9Sstevel@tonic-gate } 519*7c478bd9Sstevel@tonic-gate for (uid = 0; uid <= MAXUID && uid >= 0; uid++) { 520*7c478bd9Sstevel@tonic-gate (void) fread(&dqbuf, sizeof (struct dqblk), 1, qf); 521*7c478bd9Sstevel@tonic-gate if (feof(qf)) 522*7c478bd9Sstevel@tonic-gate break; 523*7c478bd9Sstevel@tonic-gate fup = lookup(uid); 524*7c478bd9Sstevel@tonic-gate if (fup == 0) 525*7c478bd9Sstevel@tonic-gate fup = &zerofileusage; 526*7c478bd9Sstevel@tonic-gate if (dqbuf.dqb_bhardlimit == 0 && dqbuf.dqb_bsoftlimit == 0 && 527*7c478bd9Sstevel@tonic-gate dqbuf.dqb_fhardlimit == 0 && dqbuf.dqb_fsoftlimit == 0) { 528*7c478bd9Sstevel@tonic-gate fup->fu_curfiles = 0; 529*7c478bd9Sstevel@tonic-gate fup->fu_curblocks = 0; 530*7c478bd9Sstevel@tonic-gate } 531*7c478bd9Sstevel@tonic-gate if (dqbuf.dqb_curfiles == fup->fu_curfiles && 532*7c478bd9Sstevel@tonic-gate dqbuf.dqb_curblocks == fup->fu_curblocks) { 533*7c478bd9Sstevel@tonic-gate fup->fu_curfiles = 0; 534*7c478bd9Sstevel@tonic-gate fup->fu_curblocks = 0; 535*7c478bd9Sstevel@tonic-gate continue; 536*7c478bd9Sstevel@tonic-gate } 537*7c478bd9Sstevel@tonic-gate /* 538*7c478bd9Sstevel@tonic-gate * The maximum number of blocks that can be stored in the 539*7c478bd9Sstevel@tonic-gate * dqb_curblocks field in the quota record is 2^32 - 1, 540*7c478bd9Sstevel@tonic-gate * since it must fit into an unsigned 32-bit quantity. 541*7c478bd9Sstevel@tonic-gate * If this user has more blocks than that, print a message 542*7c478bd9Sstevel@tonic-gate * to that effect and reduce the count of allocated blocks 543*7c478bd9Sstevel@tonic-gate * to the maximum value, which is UINT_MAX. 544*7c478bd9Sstevel@tonic-gate */ 545*7c478bd9Sstevel@tonic-gate if (fup->fu_curblocks > UINT_MAX) { 546*7c478bd9Sstevel@tonic-gate if (pflag || aflag) 547*7c478bd9Sstevel@tonic-gate printf("%s: ", rawdisk); 548*7c478bd9Sstevel@tonic-gate printf("512-byte blocks allocated to user "); 549*7c478bd9Sstevel@tonic-gate if ((pw = getpwuid(uid)) && pw->pw_name[0]) 550*7c478bd9Sstevel@tonic-gate printf("%-10s ", pw->pw_name); 551*7c478bd9Sstevel@tonic-gate else 552*7c478bd9Sstevel@tonic-gate printf("#%-9d ", uid); 553*7c478bd9Sstevel@tonic-gate printf(" = %lld\n", fup->fu_curblocks); 554*7c478bd9Sstevel@tonic-gate printf( 555*7c478bd9Sstevel@tonic-gate "This exceeds the maximum number of blocks recordable in a quota record.\n"); 556*7c478bd9Sstevel@tonic-gate printf( 557*7c478bd9Sstevel@tonic-gate "The value will be set to the maximum, which is %lu.\n", UINT_MAX); 558*7c478bd9Sstevel@tonic-gate fup->fu_curblocks = UINT_MAX; 559*7c478bd9Sstevel@tonic-gate } 560*7c478bd9Sstevel@tonic-gate 561*7c478bd9Sstevel@tonic-gate if (vflag) { 562*7c478bd9Sstevel@tonic-gate if (pflag || aflag) 563*7c478bd9Sstevel@tonic-gate printf("%s: ", rawdisk); 564*7c478bd9Sstevel@tonic-gate if ((pw = getpwuid(uid)) && pw->pw_name[0]) 565*7c478bd9Sstevel@tonic-gate printf("%-10s fixed:", pw->pw_name); 566*7c478bd9Sstevel@tonic-gate else 567*7c478bd9Sstevel@tonic-gate printf("#%-9d fixed:", uid); 568*7c478bd9Sstevel@tonic-gate if (dqbuf.dqb_curfiles != fup->fu_curfiles) 569*7c478bd9Sstevel@tonic-gate printf(" files %lu -> %lu", 570*7c478bd9Sstevel@tonic-gate dqbuf.dqb_curfiles, fup->fu_curfiles); 571*7c478bd9Sstevel@tonic-gate if (dqbuf.dqb_curblocks != fup->fu_curblocks) 572*7c478bd9Sstevel@tonic-gate printf(" blocks %lu -> %llu", 573*7c478bd9Sstevel@tonic-gate dqbuf.dqb_curblocks, fup->fu_curblocks); 574*7c478bd9Sstevel@tonic-gate printf("\n"); 575*7c478bd9Sstevel@tonic-gate } 576*7c478bd9Sstevel@tonic-gate dqbuf.dqb_curfiles = fup->fu_curfiles; 577*7c478bd9Sstevel@tonic-gate dqbuf.dqb_curblocks = fup->fu_curblocks; 578*7c478bd9Sstevel@tonic-gate /* 579*7c478bd9Sstevel@tonic-gate * If quotas are not enabled for the current filesystem 580*7c478bd9Sstevel@tonic-gate * then just update the quotas file directly. 581*7c478bd9Sstevel@tonic-gate */ 582*7c478bd9Sstevel@tonic-gate if ((quotactl(Q_SETQUOTA, fsfile, uid, &dqbuf) < 0) && 583*7c478bd9Sstevel@tonic-gate (errno == ESRCH)) { 584*7c478bd9Sstevel@tonic-gate /* back up, overwrite the entry we just read */ 585*7c478bd9Sstevel@tonic-gate (void) fseeko64(qf, (offset_t)dqoff(uid), 0); 586*7c478bd9Sstevel@tonic-gate (void) fwrite(&dqbuf, sizeof (struct dqblk), 1, qf); 587*7c478bd9Sstevel@tonic-gate (void) fflush(qf); 588*7c478bd9Sstevel@tonic-gate } 589*7c478bd9Sstevel@tonic-gate fup->fu_curfiles = 0; 590*7c478bd9Sstevel@tonic-gate fup->fu_curblocks = 0; 591*7c478bd9Sstevel@tonic-gate } 592*7c478bd9Sstevel@tonic-gate (void) fflush(qf); 593*7c478bd9Sstevel@tonic-gate (void) fsync(fileno(qf)); 594*7c478bd9Sstevel@tonic-gate fclose(qf); 595*7c478bd9Sstevel@tonic-gate close(fi); 596*7c478bd9Sstevel@tonic-gate return (0); 597*7c478bd9Sstevel@tonic-gate } 598*7c478bd9Sstevel@tonic-gate 599*7c478bd9Sstevel@tonic-gate void 600*7c478bd9Sstevel@tonic-gate acct(ip) 601*7c478bd9Sstevel@tonic-gate register struct dinode *ip; 602*7c478bd9Sstevel@tonic-gate { 603*7c478bd9Sstevel@tonic-gate register struct fileusage *fup; 604*7c478bd9Sstevel@tonic-gate 605*7c478bd9Sstevel@tonic-gate if (ip == NULL) 606*7c478bd9Sstevel@tonic-gate return; 607*7c478bd9Sstevel@tonic-gate ip->di_mode = ip->di_smode; 608*7c478bd9Sstevel@tonic-gate if (ip->di_suid != UID_LONG) { 609*7c478bd9Sstevel@tonic-gate ip->di_uid = ip->di_suid; 610*7c478bd9Sstevel@tonic-gate } 611*7c478bd9Sstevel@tonic-gate if (ip->di_mode == 0) 612*7c478bd9Sstevel@tonic-gate return; 613*7c478bd9Sstevel@tonic-gate fup = adduid(ip->di_uid); 614*7c478bd9Sstevel@tonic-gate fup->fu_curfiles++; 615*7c478bd9Sstevel@tonic-gate if ((ip->di_mode & IFMT) == IFCHR || (ip->di_mode & IFMT) == IFBLK) 616*7c478bd9Sstevel@tonic-gate return; 617*7c478bd9Sstevel@tonic-gate fup->fu_curblocks += ip->di_blocks; 618*7c478bd9Sstevel@tonic-gate } 619*7c478bd9Sstevel@tonic-gate 620*7c478bd9Sstevel@tonic-gate int 621*7c478bd9Sstevel@tonic-gate oneof(target, olistp, on) 622*7c478bd9Sstevel@tonic-gate char *target; 623*7c478bd9Sstevel@tonic-gate register char **olistp; 624*7c478bd9Sstevel@tonic-gate register int on; 625*7c478bd9Sstevel@tonic-gate { 626*7c478bd9Sstevel@tonic-gate char **listp = olistp; 627*7c478bd9Sstevel@tonic-gate int n = on; 628*7c478bd9Sstevel@tonic-gate 629*7c478bd9Sstevel@tonic-gate while (n--) { 630*7c478bd9Sstevel@tonic-gate if (*listp && strcmp(target, *listp) == 0) { 631*7c478bd9Sstevel@tonic-gate *listp = (char *)0; 632*7c478bd9Sstevel@tonic-gate return (1); 633*7c478bd9Sstevel@tonic-gate } 634*7c478bd9Sstevel@tonic-gate listp++; 635*7c478bd9Sstevel@tonic-gate } 636*7c478bd9Sstevel@tonic-gate return (0); 637*7c478bd9Sstevel@tonic-gate } 638*7c478bd9Sstevel@tonic-gate 639*7c478bd9Sstevel@tonic-gate struct dinode * 640*7c478bd9Sstevel@tonic-gate ginode() 641*7c478bd9Sstevel@tonic-gate { 642*7c478bd9Sstevel@tonic-gate ulong_t iblk; 643*7c478bd9Sstevel@tonic-gate 644*7c478bd9Sstevel@tonic-gate if (dp == NULL || ++dp >= &itab[ITABSZ]) { 645*7c478bd9Sstevel@tonic-gate iblk = itod(&sblock, ino); 646*7c478bd9Sstevel@tonic-gate bread(fsbtodb(&sblock, iblk), 647*7c478bd9Sstevel@tonic-gate (char *)itab, sizeof (itab)); 648*7c478bd9Sstevel@tonic-gate dp = &itab[(int)ino % (int)INOPB(&sblock)]; 649*7c478bd9Sstevel@tonic-gate } 650*7c478bd9Sstevel@tonic-gate if (ino++ < UFSROOTINO) 651*7c478bd9Sstevel@tonic-gate return (NULL); 652*7c478bd9Sstevel@tonic-gate return (dp); 653*7c478bd9Sstevel@tonic-gate } 654*7c478bd9Sstevel@tonic-gate 655*7c478bd9Sstevel@tonic-gate void 656*7c478bd9Sstevel@tonic-gate bread(diskaddr_t bno, char *buf, int cnt) 657*7c478bd9Sstevel@tonic-gate { 658*7c478bd9Sstevel@tonic-gate extern offset_t llseek(); 659*7c478bd9Sstevel@tonic-gate offset_t pos; 660*7c478bd9Sstevel@tonic-gate 661*7c478bd9Sstevel@tonic-gate pos = (offset_t)bno * DEV_BSIZE; 662*7c478bd9Sstevel@tonic-gate if (llseek(fi, pos, 0) != pos) { 663*7c478bd9Sstevel@tonic-gate perror("lseek"); 664*7c478bd9Sstevel@tonic-gate exit(31+1); 665*7c478bd9Sstevel@tonic-gate } 666*7c478bd9Sstevel@tonic-gate if (read(fi, buf, cnt) != cnt) { 667*7c478bd9Sstevel@tonic-gate perror("read"); 668*7c478bd9Sstevel@tonic-gate exit(31+1); 669*7c478bd9Sstevel@tonic-gate } 670*7c478bd9Sstevel@tonic-gate } 671*7c478bd9Sstevel@tonic-gate 672*7c478bd9Sstevel@tonic-gate struct fileusage * 673*7c478bd9Sstevel@tonic-gate lookup(uid_t uid) 674*7c478bd9Sstevel@tonic-gate { 675*7c478bd9Sstevel@tonic-gate register struct fileusage *fup; 676*7c478bd9Sstevel@tonic-gate 677*7c478bd9Sstevel@tonic-gate for (fup = fuhead[uid % FUHASH]; fup != 0; fup = fup->fu_next) 678*7c478bd9Sstevel@tonic-gate if (fup->fu_uid == uid) 679*7c478bd9Sstevel@tonic-gate return (fup); 680*7c478bd9Sstevel@tonic-gate return ((struct fileusage *)0); 681*7c478bd9Sstevel@tonic-gate } 682*7c478bd9Sstevel@tonic-gate 683*7c478bd9Sstevel@tonic-gate struct fileusage * 684*7c478bd9Sstevel@tonic-gate adduid(uid_t uid) 685*7c478bd9Sstevel@tonic-gate { 686*7c478bd9Sstevel@tonic-gate struct fileusage *fup, **fhp; 687*7c478bd9Sstevel@tonic-gate 688*7c478bd9Sstevel@tonic-gate fup = lookup(uid); 689*7c478bd9Sstevel@tonic-gate if (fup != 0) 690*7c478bd9Sstevel@tonic-gate return (fup); 691*7c478bd9Sstevel@tonic-gate fup = (struct fileusage *)calloc(1, sizeof (struct fileusage)); 692*7c478bd9Sstevel@tonic-gate if (fup == 0) { 693*7c478bd9Sstevel@tonic-gate fprintf(stderr, "out of memory for fileusage structures\n"); 694*7c478bd9Sstevel@tonic-gate exit(31+1); 695*7c478bd9Sstevel@tonic-gate } 696*7c478bd9Sstevel@tonic-gate fhp = &fuhead[uid % FUHASH]; 697*7c478bd9Sstevel@tonic-gate fup->fu_next = *fhp; 698*7c478bd9Sstevel@tonic-gate *fhp = fup; 699*7c478bd9Sstevel@tonic-gate fup->fu_uid = uid; 700*7c478bd9Sstevel@tonic-gate return (fup); 701*7c478bd9Sstevel@tonic-gate } 702*7c478bd9Sstevel@tonic-gate 703*7c478bd9Sstevel@tonic-gate void 704*7c478bd9Sstevel@tonic-gate usage() 705*7c478bd9Sstevel@tonic-gate { 706*7c478bd9Sstevel@tonic-gate fprintf(stderr, "ufs usage:\n"); 707*7c478bd9Sstevel@tonic-gate fprintf(stderr, "\tquotacheck [-v] [-f] [-p] -a\n"); 708*7c478bd9Sstevel@tonic-gate fprintf(stderr, "\tquotacheck [-v] [-f] [-p] filesys ...\n"); 709*7c478bd9Sstevel@tonic-gate exit(31+1); 710*7c478bd9Sstevel@tonic-gate } 711*7c478bd9Sstevel@tonic-gate 712*7c478bd9Sstevel@tonic-gate int 713*7c478bd9Sstevel@tonic-gate quotactl(cmd, mountp, uid, addr) 714*7c478bd9Sstevel@tonic-gate int cmd; 715*7c478bd9Sstevel@tonic-gate char *mountp; 716*7c478bd9Sstevel@tonic-gate uid_t uid; 717*7c478bd9Sstevel@tonic-gate caddr_t addr; 718*7c478bd9Sstevel@tonic-gate { 719*7c478bd9Sstevel@tonic-gate int fd; 720*7c478bd9Sstevel@tonic-gate int status; 721*7c478bd9Sstevel@tonic-gate struct quotctl quota; 722*7c478bd9Sstevel@tonic-gate char qfile[MAXPATHLEN]; 723*7c478bd9Sstevel@tonic-gate FILE *fstab; 724*7c478bd9Sstevel@tonic-gate struct mnttab mntp; 725*7c478bd9Sstevel@tonic-gate 726*7c478bd9Sstevel@tonic-gate 727*7c478bd9Sstevel@tonic-gate if ((mountp == NULL) && (cmd == Q_ALLSYNC)) { 728*7c478bd9Sstevel@tonic-gate /* 729*7c478bd9Sstevel@tonic-gate * Find the mount point of any ufs file system. This is 730*7c478bd9Sstevel@tonic-gate * because the ioctl that implements the quotactl call has 731*7c478bd9Sstevel@tonic-gate * to go to a real file, and not to the block device. 732*7c478bd9Sstevel@tonic-gate */ 733*7c478bd9Sstevel@tonic-gate if ((fstab = fopen(MNTTAB, "r")) == NULL) { 734*7c478bd9Sstevel@tonic-gate fprintf(stderr, "%s: ", MNTTAB); 735*7c478bd9Sstevel@tonic-gate perror("open"); 736*7c478bd9Sstevel@tonic-gate exit(31+1); 737*7c478bd9Sstevel@tonic-gate } 738*7c478bd9Sstevel@tonic-gate fd = -1; 739*7c478bd9Sstevel@tonic-gate while ((status = getmntent(fstab, &mntp)) == NULL) { 740*7c478bd9Sstevel@tonic-gate if (strcmp(mntp.mnt_fstype, MNTTYPE_UFS) != 0 || 741*7c478bd9Sstevel@tonic-gate hasmntopt(&mntp, MNTOPT_RO)) 742*7c478bd9Sstevel@tonic-gate continue; 743*7c478bd9Sstevel@tonic-gate if ((strlcpy(qfile, mntp.mnt_mountp, 744*7c478bd9Sstevel@tonic-gate sizeof (qfile)) >= sizeof (qfile)) || 745*7c478bd9Sstevel@tonic-gate (strlcat(qfile, "/" QFNAME, sizeof (qfile)) >= 746*7c478bd9Sstevel@tonic-gate sizeof (qfile))) { 747*7c478bd9Sstevel@tonic-gate continue; 748*7c478bd9Sstevel@tonic-gate } 749*7c478bd9Sstevel@tonic-gate if ((fd = open64(qfile, O_RDWR)) == -1) 750*7c478bd9Sstevel@tonic-gate break; 751*7c478bd9Sstevel@tonic-gate } 752*7c478bd9Sstevel@tonic-gate fclose(fstab); 753*7c478bd9Sstevel@tonic-gate if (fd == -1) { 754*7c478bd9Sstevel@tonic-gate errno = ENOENT; 755*7c478bd9Sstevel@tonic-gate return (-1); 756*7c478bd9Sstevel@tonic-gate } 757*7c478bd9Sstevel@tonic-gate } else { 758*7c478bd9Sstevel@tonic-gate if (mountp == NULL || mountp[0] == '\0') { 759*7c478bd9Sstevel@tonic-gate errno = ENOENT; 760*7c478bd9Sstevel@tonic-gate return (-1); 761*7c478bd9Sstevel@tonic-gate } 762*7c478bd9Sstevel@tonic-gate if ((strlcpy(qfile, mountp, sizeof (qfile)) >= 763*7c478bd9Sstevel@tonic-gate sizeof (qfile)) || 764*7c478bd9Sstevel@tonic-gate (strlcat(qfile, "/" QFNAME, sizeof (qfile)) >= 765*7c478bd9Sstevel@tonic-gate sizeof (qfile))) { 766*7c478bd9Sstevel@tonic-gate errno = ENOENT; 767*7c478bd9Sstevel@tonic-gate return (-1); 768*7c478bd9Sstevel@tonic-gate } 769*7c478bd9Sstevel@tonic-gate if ((fd = open64(qfile, O_RDWR)) < 0) { 770*7c478bd9Sstevel@tonic-gate fprintf(stderr, "quotactl: "); 771*7c478bd9Sstevel@tonic-gate perror("open"); 772*7c478bd9Sstevel@tonic-gate exit(31+1); 773*7c478bd9Sstevel@tonic-gate } 774*7c478bd9Sstevel@tonic-gate } /* else */ 775*7c478bd9Sstevel@tonic-gate 776*7c478bd9Sstevel@tonic-gate quota.op = cmd; 777*7c478bd9Sstevel@tonic-gate quota.uid = uid; 778*7c478bd9Sstevel@tonic-gate quota.addr = addr; 779*7c478bd9Sstevel@tonic-gate status = ioctl(fd, Q_QUOTACTL, "a); 780*7c478bd9Sstevel@tonic-gate if (fd != 0) 781*7c478bd9Sstevel@tonic-gate close(fd); 782*7c478bd9Sstevel@tonic-gate return (status); 783*7c478bd9Sstevel@tonic-gate } 784*7c478bd9Sstevel@tonic-gate 785*7c478bd9Sstevel@tonic-gate char * 786*7c478bd9Sstevel@tonic-gate hasvfsopt(vfs, opt) 787*7c478bd9Sstevel@tonic-gate register struct vfstab *vfs; 788*7c478bd9Sstevel@tonic-gate register char *opt; 789*7c478bd9Sstevel@tonic-gate { 790*7c478bd9Sstevel@tonic-gate char *f, *opts; 791*7c478bd9Sstevel@tonic-gate static char *tmpopts; 792*7c478bd9Sstevel@tonic-gate 793*7c478bd9Sstevel@tonic-gate if (tmpopts == 0) { 794*7c478bd9Sstevel@tonic-gate tmpopts = (char *)calloc(256, sizeof (char)); 795*7c478bd9Sstevel@tonic-gate if (tmpopts == 0) 796*7c478bd9Sstevel@tonic-gate return (0); 797*7c478bd9Sstevel@tonic-gate } 798*7c478bd9Sstevel@tonic-gate strcpy(tmpopts, vfs->vfs_mntopts); 799*7c478bd9Sstevel@tonic-gate opts = tmpopts; 800*7c478bd9Sstevel@tonic-gate f = mntopt(&opts); 801*7c478bd9Sstevel@tonic-gate for (; *f; f = mntopt(&opts)) { 802*7c478bd9Sstevel@tonic-gate if (strncmp(opt, f, strlen(opt)) == 0) 803*7c478bd9Sstevel@tonic-gate return (f - tmpopts + vfs->vfs_mntopts); 804*7c478bd9Sstevel@tonic-gate } 805*7c478bd9Sstevel@tonic-gate return (NULL); 806*7c478bd9Sstevel@tonic-gate } 807