1/* 2 * Copyright (c) 1999, 2002, 2005 Apple Computer, Inc. All rights reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. Please obtain a copy of the License at 10 * http://www.opensource.apple.com/apsl/ and read it before using this 11 * file. 12 * 13 * The Original Code and all software distributed under the License are 14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 * Please see the License for the specific language governing rights and 19 * limitations under the License. 20 * 21 * @APPLE_LICENSE_HEADER_END@ 22 */ 23/* 24 * Copyright (c) 1980, 1990, 1993 25 * The Regents of the University of California. All rights reserved. 26 * 27 * This code is derived from software contributed to Berkeley by 28 * Robert Elz at The University of Melbourne. 29 * 30 * Redistribution and use in source and binary forms, with or without 31 * modification, are permitted provided that the following conditions 32 * are met: 33 * 1. Redistributions of source code must retain the above copyright 34 * notice, this list of conditions and the following disclaimer. 35 * 2. Redistributions in binary form must reproduce the above copyright 36 * notice, this list of conditions and the following disclaimer in the 37 * documentation and/or other materials provided with the distribution. 38 * 3. All advertising materials mentioning features or use of this software 39 * must display the following acknowledgement: 40 * This product includes software developed by the University of 41 * California, Berkeley and its contributors. 42 * 4. Neither the name of the University nor the names of its contributors 43 * may be used to endorse or promote products derived from this software 44 * without specific prior written permission. 45 * 46 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 47 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 48 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 49 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 50 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 51 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 52 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 53 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 54 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 55 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 56 * SUCH DAMAGE. 57 */ 58 59#include <sys/cdefs.h> 60 61#ifndef lint 62__unused static char copyright[] = 63"@(#) Copyright (c) 1980, 1990, 1993\n\ 64 The Regents of the University of California. All rights reserved.\n"; 65#endif /* not lint */ 66 67#ifndef lint 68__unused static char sccsid[] = "@(#)quotaon.c 8.1 (Berkeley) 6/6/93"; 69#endif /* not lint */ 70 71/* 72 * Turn quota on/off for a filesystem. 73 */ 74#include <sys/param.h> 75#include <sys/file.h> 76#include <sys/mount.h> 77#ifdef __APPLE__ 78#include <sys/stat.h> 79#endif /* __APPLE__ */ 80#include <sys/appleapiopts.h> 81#include <sys/quota.h> 82#include <stdio.h> 83#include <fstab.h> 84#include <string.h> 85#include <stdlib.h> 86#include <unistd.h> 87 88/* Internal functions */ 89void usage(char *whoami); 90 91char *qfname = QUOTAFILENAME; 92char *qfextension[] = INITQFNAMES; 93 94int aflag; /* all file systems */ 95int gflag; /* operate on group quotas */ 96int uflag; /* operate on user quotas */ 97int vflag; /* verbose */ 98 99/* Function prototypes */ 100#ifdef __APPLE__ 101int hasquota(register struct statfs *, int, char **); 102int quotaonoff(register struct statfs *, int, int, char *); 103#else 104int hasquota(register struct fstab *, int, char **); 105int quotaonoff(register struct fstab *, int, int, char *); 106#endif /* __APPLE__ */ 107 108int oneof(register char *, register char **, int); 109 110int main(argc, argv) 111 int argc; 112 char **argv; 113{ 114 char ch, *qfnp, *whoami, *rindex(); 115 long argnum, done = 0; 116 int i, offmode = 0, errs = 0; 117#ifdef __APPLE__ 118 int nfst; 119 struct statfs *fst; 120#endif /* __APPLE__ */ 121 122 whoami = rindex(*argv, '/') + 1; 123 if (whoami == (char *)1) 124 whoami = *argv; 125 if (strcmp(whoami, "quotaoff") == 0) 126 offmode++; 127 else if (strcmp(whoami, "quotaon") != 0) { 128 fprintf(stderr, "Name must be quotaon or quotaoff not %s\n", 129 whoami); 130 exit(1); 131 } 132 while ((ch = getopt(argc, argv, "avug")) != EOF) { 133 switch(ch) { 134 case 'a': 135 aflag++; 136 break; 137 case 'g': 138 gflag++; 139 break; 140 case 'u': 141 uflag++; 142 break; 143 case 'v': 144 vflag++; 145 break; 146 default: 147 usage(whoami); 148 } 149 } 150 argc -= optind; 151 argv += optind; 152 if (argc <= 0 && !aflag) 153 usage(whoami); 154 if (!gflag && !uflag) { 155 gflag++; 156 uflag++; 157 } 158 159#ifdef __APPLE__ 160 nfst = getmntinfo(&fst, MNT_WAIT); 161 if (nfst==0) { 162 fprintf(stderr, "no filesystems mounted"); 163 return(1); 164 } 165 166 for (i=0; i<nfst; i++) { 167 if(strcmp(fst[i].f_fstypename, "hfs")) { 168 continue; 169 } 170 if(fst[i].f_flags & MNT_RDONLY) { 171 errs++; 172 continue; 173 } 174 175 if (aflag) { 176 if (gflag && hasquota(&fst[i], GRPQUOTA, &qfnp)) 177 errs += quotaonoff(&fst[i], offmode, GRPQUOTA, qfnp); 178 if (uflag && hasquota(&fst[i], USRQUOTA, &qfnp)) 179 errs += quotaonoff(&fst[i], offmode, USRQUOTA, qfnp); 180 continue; 181 } 182 if ((argnum = oneof(fst[i].f_mntonname, argv, argc)) >= 0 || 183 (argnum = oneof(fst[i].f_mntfromname, argv, argc)) >= 0) { 184 done |= 1 << argnum; 185 if (gflag && hasquota(&fst[i], GRPQUOTA, &qfnp)) 186 errs += quotaonoff(&fst[i], offmode, GRPQUOTA, qfnp); 187 if (uflag && hasquota(&fst[i], USRQUOTA, &qfnp)) 188 errs += quotaonoff(&fst[i], offmode, USRQUOTA, qfnp); 189 } 190 } 191#else 192 register struct fstab *fs; 193 setfsent(); 194 while ((fs = getfsent()) != NULL) { 195 if (strcmp(fs->fs_vfstype, "ufs") || 196 strcmp(fs->fs_type, FSTAB_RW)) 197 continue; 198 if (aflag) { 199 if (gflag && hasquota(fs, GRPQUOTA, &qfnp)) 200 errs += quotaonoff(fs, offmode, GRPQUOTA, qfnp); 201 if (uflag && hasquota(fs, USRQUOTA, &qfnp)) 202 errs += quotaonoff(fs, offmode, USRQUOTA, qfnp); 203 continue; 204 } 205 if ((argnum = oneof(fs->fs_file, argv, argc)) >= 0 || 206 (argnum = oneof(fs->fs_spec, argv, argc)) >= 0) { 207 done |= 1 << argnum; 208 if (gflag && hasquota(fs, GRPQUOTA, &qfnp)) 209 errs += quotaonoff(fs, offmode, GRPQUOTA, qfnp); 210 if (uflag && hasquota(fs, USRQUOTA, &qfnp)) 211 errs += quotaonoff(fs, offmode, USRQUOTA, qfnp); 212 } 213 } 214 endfsent(); 215#endif /* __APPLE__ */ 216 for (i = 0; i < argc; i++) 217 if ((done & (1 << i)) == 0) 218 fprintf(stderr, "%s not found in fstab\n", 219 argv[i]); 220 exit(errs); 221} 222 223void usage(whoami) 224 char *whoami; 225{ 226 227 fprintf(stderr, "Usage:\n\t%s [-g] [-u] [-v] -a\n", whoami); 228 fprintf(stderr, "\t%s [-g] [-u] [-v] filesys ...\n", whoami); 229 exit(1); 230} 231 232#ifdef __APPLE__ 233int quotaonoff(fst, offmode, type, qfpathname) 234 register struct statfs *fst; 235 int offmode, type; 236 char *qfpathname; 237{ 238 if (strcmp(fst->f_mntonname, "/") && (fst->f_flags & MNT_RDONLY)) 239 return (1); 240 if (offmode) { 241 if (quotactl(fst->f_mntonname, QCMD(Q_QUOTAOFF, type), 0, 0) < 0) { 242 fprintf(stderr, "quotaoff: "); 243 perror(fst->f_mntonname); 244 return (1); 245 } 246 if (vflag) 247 printf("%s: %s quotas turned off\n", fst->f_mntonname, 248 qfextension[type]); 249 return (0); 250 } 251 if (quotactl(fst->f_mntonname, QCMD(Q_QUOTAON, type), 0, qfpathname) < 0) { 252 fprintf(stderr, "quotaon: using %s on ", qfpathname); 253 perror(fst->f_mntonname); 254 return (1); 255 } 256 if (vflag) 257 printf("%s: %s quotas turned on\n", fst->f_mntonname, 258 qfextension[type]); 259 return (0); 260} 261#else 262int quotaonoff(fs, offmode, type, qfpathname) 263 register struct fstab *fs; 264 int offmode, type; 265 char *qfpathname; 266{ 267 268 if (strcmp(fs->fs_file, "/") && readonly(fs)) 269 return (1); 270 if (offmode) { 271 if (quotactl(fs->fs_file, QCMD(Q_QUOTAOFF, type), 0, 0) < 0) { 272 fprintf(stderr, "quotaoff: "); 273 perror(fs->fs_file); 274 return (1); 275 } 276 if (vflag) 277 printf("%s: quotas turned off\n", fs->fs_file); 278 return (0); 279 } 280 if (quotactl(fs->fs_file, QCMD(Q_QUOTAON, type), 0, qfpathname) < 0) { 281 fprintf(stderr, "quotaon: using %s on", qfpathname); 282 perror(fs->fs_file); 283 return (1); 284 } 285 if (vflag) 286 printf("%s: %s quotas turned on\n", fs->fs_file, 287 qfextension[type]); 288 return (0); 289} 290#endif /* __APPLE__ */ 291 292/* 293 * Check to see if target appears in list of size cnt. 294 */ 295int oneof(target, list, cnt) 296 register char *target, *list[]; 297 int cnt; 298{ 299 register int i; 300 301 for (i = 0; i < cnt; i++) 302 if (strcmp(target, list[i]) == 0) 303 return (i); 304 return (-1); 305} 306 307/* 308 * Check to see if a particular quota is to be enabled. 309 */ 310#ifdef __APPLE__ 311int hasquota(fst, type, qfnamep) 312 register struct statfs *fst; 313 int type; 314 char **qfnamep; 315{ 316 struct stat sb; 317 static char initname, usrname[100], grpname[100]; 318 static char buf[BUFSIZ]; 319 320 if (!initname) { 321 snprintf(usrname, sizeof(usrname), "%s%s", qfextension[USRQUOTA], qfname); 322 snprintf(grpname, sizeof(grpname), "%s%s", qfextension[GRPQUOTA], qfname); 323 initname = 1; 324 } 325 326 /* 327 We only support the default path to the 328 on disk quota files. 329 */ 330 331 (void)snprintf(buf, sizeof(buf), "%s/%s.%s", fst->f_mntonname, 332 QUOTAOPSNAME, qfextension[type] ); 333 if (stat(buf, &sb) != 0) { 334 /* There appears to be no mount option file */ 335 return(0); 336 } 337 338 339 (void) snprintf(buf, sizeof(buf), "%s/%s.%s", fst->f_mntonname, qfname, qfextension[type]); 340 *qfnamep = buf; 341 return (1); 342} 343#else 344int hasquota(fs, type, qfnamep) 345 register struct fstab *fs; 346 int type; 347 char **qfnamep; 348{ 349 register char *opt; 350 char *cp, *index(), *strtok(); 351 static char initname, usrname[100], grpname[100]; 352 static char buf[BUFSIZ]; 353 354 if (!initname) { 355 snprintf(usrname, sizeof(usrname), "%s%s", qfextension[USRQUOTA], qfname); 356 snprintf(grpname, sizeof(grpname), "%s%s", qfextension[GRPQUOTA], qfname); 357 initname = 1; 358 } 359 strlcpy(buf, fs->fs_mntops, sizeof(buf)); 360 for (opt = strtok(buf, ","); opt; opt = strtok(NULL, ",")) { 361 if (cp = index(opt, '=')) 362 *cp++ = '\0'; 363 if (type == USRQUOTA && strcmp(opt, usrname) == 0) 364 break; 365 if (type == GRPQUOTA && strcmp(opt, grpname) == 0) 366 break; 367 } 368 if (!opt) 369 return (0); 370 if (cp) { 371 *qfnamep = cp; 372 return (1); 373 } 374 (void) snprintf(buf, sizeof(buf), "%s/%s.%s", fs->fs_file, qfname, qfextension[type]); 375 *qfnamep = buf; 376 return (1); 377} 378#endif /* __APPLE__ */ 379 380 381/* 382 * Verify file system is mounted and not readonly. 383 */ 384int readonly(fs) 385 register struct fstab *fs; 386{ 387 struct statfs fsbuf; 388 389 if (statfs(fs->fs_file, &fsbuf) < 0 || 390 strcmp(fsbuf.f_mntonname, fs->fs_file) || 391 strcmp(fsbuf.f_mntfromname, fs->fs_spec)) { 392 printf("%s: not mounted\n", fs->fs_file); 393 return (1); 394 } 395 if (fsbuf.f_flags & MNT_RDONLY) { 396 printf("%s: mounted read-only\n", fs->fs_file); 397 return (1); 398 } 399 return (0); 400} 401