1 /* 2 * Copyright (c) 1980, 1990 Regents of the University of California. 3 * All rights reserved. 4 * 5 * This code is derived from software contributed to Berkeley by 6 * Robert Elz at The University of Melbourne. 7 * 8 * %sccs.include.redist.c% 9 */ 10 11 #ifndef lint 12 char copyright[] = 13 "@(#) Copyright (c) 1980, 1990 Regents of the University of California.\n\ 14 All rights reserved.\n"; 15 #endif /* not lint */ 16 17 #ifndef lint 18 static char sccsid[] = "@(#)quotaon.c 5.11 (Berkeley) 06/01/90"; 19 #endif /* not lint */ 20 21 /* 22 * Turn quota on/off for a filesystem. 23 */ 24 #include <sys/param.h> 25 #include <sys/file.h> 26 #include <sys/mount.h> 27 #include <ufs/quota.h> 28 #include <stdio.h> 29 #include <fstab.h> 30 31 int aflag; /* all file systems */ 32 int gflag; /* operate on group quotas */ 33 int uflag; /* operate on user quotas */ 34 int vflag; /* verbose */ 35 36 main(argc, argv) 37 int argc; 38 char **argv; 39 { 40 register struct fstab *fs; 41 char ch, *qfnp, *whoami, *rindex(); 42 long argnum, done = 0; 43 int i, offmode = 0, errs = 0; 44 extern char *optarg; 45 extern int optind; 46 47 whoami = rindex(*argv, '/') + 1; 48 if (whoami == (char *)1) 49 whoami = *argv; 50 if (strcmp(whoami, "quotaoff") == 0) 51 offmode++; 52 else if (strcmp(whoami, "quotaon") != 0) { 53 fprintf(stderr, "Name must be quotaon or quotaoff not %s\n", 54 whoami); 55 exit(1); 56 } 57 while ((ch = getopt(argc, argv, "avug")) != EOF) { 58 switch(ch) { 59 case 'a': 60 aflag++; 61 break; 62 case 'g': 63 gflag++; 64 break; 65 case 'u': 66 uflag++; 67 break; 68 case 'v': 69 vflag++; 70 break; 71 default: 72 usage(whoami); 73 } 74 } 75 argc -= optind; 76 argv += optind; 77 if (argc <= 0 && !aflag) 78 usage(whoami); 79 if (!gflag && !uflag) { 80 gflag++; 81 uflag++; 82 } 83 setfsent(); 84 while ((fs = getfsent()) != NULL) { 85 if (strcmp(fs->fs_vfstype, "ufs") || 86 strcmp(fs->fs_type, FSTAB_RW)) 87 continue; 88 if (aflag) { 89 if (gflag && hasquota(fs, GRPQUOTA, &qfnp)) 90 errs += quotaonoff(fs, offmode, GRPQUOTA, qfnp); 91 if (uflag && hasquota(fs, USRQUOTA, &qfnp)) 92 errs += quotaonoff(fs, offmode, USRQUOTA, qfnp); 93 continue; 94 } 95 if ((argnum = oneof(fs->fs_file, argv, argc)) >= 0 || 96 (argnum = oneof(fs->fs_spec, argv, argc)) >= 0) { 97 done |= 1 << argnum; 98 if (gflag && hasquota(fs, GRPQUOTA, &qfnp)) 99 errs += quotaonoff(fs, offmode, GRPQUOTA, qfnp); 100 if (uflag && hasquota(fs, USRQUOTA, &qfnp)) 101 errs += quotaonoff(fs, offmode, USRQUOTA, qfnp); 102 } 103 } 104 endfsent(); 105 for (i = 0; i < argc; i++) 106 if ((done & (1 << i)) == 0) 107 fprintf(stderr, "%s not found in fstab\n", 108 argv[i]); 109 exit(errs); 110 } 111 112 usage(whoami) 113 char *whoami; 114 { 115 116 fprintf(stderr, "Usage:\n\t%s [-g] [-u] [-v] -a\n", whoami); 117 fprintf(stderr, "\t%s [-g] [-u] [-v] filesys ...\n", whoami); 118 exit(1); 119 } 120 121 quotaonoff(fs, offmode, type, qfpathname) 122 register struct fstab *fs; 123 int offmode, type; 124 char *qfpathname; 125 { 126 127 if (strcmp(fs->fs_file, "/") && readonly(fs)) 128 return (1); 129 if (offmode) { 130 if (quotactl(fs->fs_file, QCMD(Q_QUOTAOFF, type), 0, 0) < 0) { 131 fprintf(stderr, "quotaoff: "); 132 perror(fs->fs_file); 133 return (1); 134 } 135 if (vflag) 136 printf("%s: quotas turned off\n", fs->fs_file); 137 return (0); 138 } 139 if (quotactl(fs->fs_file, QCMD(Q_QUOTAON, type), 0, qfpathname) < 0) { 140 fprintf(stderr, "quotaon: using %s on", qfpathname); 141 perror(fs->fs_file); 142 return (1); 143 } 144 if (vflag) 145 printf("%s: %s quotas turned on\n", fs->fs_file, 146 qfextension[type]); 147 return (0); 148 } 149 150 /* 151 * Check to see if target appears in list of size cnt. 152 */ 153 oneof(target, list, cnt) 154 register char *target, *list[]; 155 int cnt; 156 { 157 register int i; 158 159 for (i = 0; i < cnt; i++) 160 if (strcmp(target, list[i]) == 0) 161 return (i); 162 return (-1); 163 } 164 165 /* 166 * Check to see if a particular quota is to be enabled. 167 */ 168 hasquota(fs, type, qfnamep) 169 register struct fstab *fs; 170 int type; 171 char **qfnamep; 172 { 173 register char *opt; 174 char *cp, *index(), *strtok(); 175 static char initname, usrname[100], grpname[100]; 176 static char buf[BUFSIZ]; 177 178 if (!initname) { 179 sprintf(usrname, "%s%s", qfextension[USRQUOTA], qfname); 180 sprintf(grpname, "%s%s", qfextension[GRPQUOTA], qfname); 181 initname = 1; 182 } 183 strcpy(buf, fs->fs_mntops); 184 for (opt = strtok(buf, ","); opt; opt = strtok(NULL, ",")) { 185 if (cp = index(opt, '=')) 186 *cp++ = '\0'; 187 if (type == USRQUOTA && strcmp(opt, usrname) == 0) 188 break; 189 if (type == GRPQUOTA && strcmp(opt, grpname) == 0) 190 break; 191 } 192 if (!opt) 193 return (0); 194 if (cp) { 195 *qfnamep = cp; 196 return (1); 197 } 198 (void) sprintf(buf, "%s/%s.%s", fs->fs_file, qfname, qfextension[type]); 199 *qfnamep = buf; 200 return (1); 201 } 202 203 /* 204 * Verify file system is mounted and not readonly. 205 */ 206 readonly(fs) 207 register struct fstab *fs; 208 { 209 struct statfs fsbuf; 210 211 if (statfs(fs->fs_file, &fsbuf) < 0 || 212 strcmp(fsbuf.f_mntonname, fs->fs_file) || 213 strcmp(fsbuf.f_mntfromname, fs->fs_spec)) { 214 printf("%s: not mounted\n", fs->fs_file); 215 return (1); 216 } 217 if (fsbuf.f_flags & MNT_RDONLY) { 218 printf("%s: mounted read-only\n", fs->fs_file); 219 return (1); 220 } 221 return (0); 222 } 223