]>
Commit | Line | Data |
---|---|---|
5dc7ec18 | 1 | /* |
55fce87f | 2 | * $Source$ |
3 | * $Author$ | |
4 | * $Header$ | |
5dc7ec18 | 5 | * |
55fce87f | 6 | * Copyright (C) 1987 by the Massachusetts Institute of Technology |
5dc7ec18 | 7 | * |
55fce87f | 8 | * Set quota on specified device for specified user to specified value. |
5dc7ec18 | 9 | * |
55fce87f | 10 | * Uses the NFS style quota system/quotactl rather than the Melbourne |
5dc7ec18 | 11 | * quota system. |
55fce87f | 12 | * |
5dc7ec18 | 13 | */ |
14 | ||
15 | #ifndef lint | |
16 | static char *rcsid_setquota_c = "$Header$"; | |
17 | #endif lint | |
18 | ||
19 | #include <stdio.h> | |
20 | #include <ctype.h> | |
55fce87f | 21 | #include <mntent.h> |
22 | ||
23 | #include <sys/file.h> | |
5dc7ec18 | 24 | #include <sys/param.h> |
25 | #include <sys/time.h> | |
26 | #include <ufs/quota.h> | |
27 | ||
28 | #define kb(n) (howmany(dbtob(n), 1024)) | |
29 | ||
55fce87f | 30 | static char device[20]; |
31 | static char quotafilename[30]; | |
32 | static struct dqblk zblk = {0}; | |
33 | ||
5eaef520 | 34 | int main(int argc, char **argv) |
5dc7ec18 | 35 | { |
5eaef520 | 36 | int uid, uid_low, uid_high, soft_quota, qfd; |
37 | struct dqblk db, odb; | |
38 | int uflag = 0; | |
39 | int range_mode = 0; | |
40 | ||
41 | while (argc > 4 && *argv[1] == '-') | |
42 | { | |
43 | switch (argv[1][1]) | |
44 | { | |
45 | case 'u': | |
46 | uflag = 1; | |
47 | --argc; | |
48 | ++argv; | |
49 | break; | |
50 | case 'r': | |
51 | range_mode = 1; | |
52 | --argc; | |
53 | ++argv; | |
54 | break; | |
55 | default: | |
55fce87f | 56 | goto usage; |
5dc7ec18 | 57 | } |
5eaef520 | 58 | } |
55fce87f | 59 | |
5eaef520 | 60 | if ((argc != 4 && !range_mode) || (argc != 5 && range_mode)) |
61 | { | |
62 | usage: | |
63 | fprintf(stderr, "usage: setquota [-u] special uid quota\n" | |
64 | "setquota -r [-u] special uid_low uid_high quota\n" | |
65 | "-u means set limit to <quota> + cur usage\n" | |
66 | "special is a mounted filesystem special device\n" | |
67 | "quota is in 1KB units\n"); | |
68 | exit(1); | |
69 | } | |
55fce87f | 70 | |
5eaef520 | 71 | if ((!range_mode && (!isdigit(*argv[2]) || !isdigit(*argv[3]))) || |
72 | (range_mode && (!isdigit(*argv[2]) || !isdigit(*argv[3]) || | |
73 | !isdigit(*argv[4])))) | |
74 | { | |
75 | fprintf(stderr, "setquota: uid and quota must be numeric\n"); | |
76 | goto usage; | |
77 | } | |
55fce87f | 78 | |
5eaef520 | 79 | if (range_mode) |
80 | { | |
81 | uid_low = atoi(argv[2]); | |
82 | uid_high = atoi(argv[3]); | |
83 | soft_quota = atoi(argv[4]); | |
84 | if (uid_low > uid_high) | |
85 | { | |
86 | fprintf(stderr, "setquota: range error\n"); | |
87 | exit(1); | |
88 | } | |
89 | } | |
90 | else | |
91 | { | |
92 | uid_low = uid_high = atoi(argv[2]); | |
93 | soft_quota = atoi(argv[3]); | |
94 | } | |
95 | ||
96 | get_device(argv[1]); | |
55fce87f | 97 | |
5eaef520 | 98 | for (uid = uid_low; uid <= uid_high; uid++) |
99 | { | |
100 | if (quotactl(Q_GETQUOTA, device, uid, &odb)) | |
101 | { | |
102 | if (!(qfd = open(quotafilename, O_RDWR))) | |
103 | { | |
55fce87f | 104 | perror("No quota file"); |
105 | exit(1); | |
106 | } | |
107 | ||
5eaef520 | 108 | lseek(qfd, 32767 * sizeof(struct dqblk), L_SET); |
109 | write(qfd, &zblk, sizeof(struct dqblk)); | |
110 | close(qfd); | |
55fce87f | 111 | |
5eaef520 | 112 | if (quotactl(Q_GETQUOTA, device, uid, &odb) != 0) |
113 | { | |
55fce87f | 114 | perror("Can't get current quota info"); |
115 | exit(1); | |
116 | } | |
5dc7ec18 | 117 | } |
5eaef520 | 118 | |
119 | db.dqb_bsoftlimit = soft_quota; | |
120 | db.dqb_bhardlimit = (db.dqb_bsoftlimit * 6) / 5; | |
121 | db.dqb_fsoftlimit = soft_quota / 2; | |
122 | db.dqb_fhardlimit = (db.dqb_fsoftlimit * 6) / 5; | |
123 | db.dqb_btimelimit = odb.dqb_btimelimit; | |
124 | db.dqb_ftimelimit = odb.dqb_ftimelimit; | |
125 | ||
126 | db.dqb_bsoftlimit *= btodb(1024); | |
127 | db.dqb_bhardlimit *= btodb(1024); | |
128 | ||
129 | if (uflag) | |
130 | { | |
131 | db.dqb_bhardlimit += odb.dqb_curblocks; | |
132 | db.dqb_bsoftlimit += odb.dqb_curblocks; | |
133 | db.dqb_fhardlimit += odb.dqb_curfiles; | |
134 | db.dqb_fsoftlimit += odb.dqb_curfiles; | |
5dc7ec18 | 135 | } |
55fce87f | 136 | |
5eaef520 | 137 | if (quotactl(Q_SETQLIM, device, uid, &db) < 0) |
138 | { | |
139 | fprintf(stderr, "quotactl: %d on ", uid); | |
140 | perror(device); | |
141 | exit(1); | |
142 | } | |
143 | } | |
144 | ||
145 | if (quotactl(Q_SYNC, device, 0, 0) < 0) | |
146 | { | |
147 | perror("can't sync disk quota"); | |
148 | exit(1); | |
149 | } | |
150 | ||
151 | exit(0); | |
5dc7ec18 | 152 | } |
5eaef520 | 153 | |
154 | get_device(char *device_or_dir) | |
55fce87f | 155 | { |
44d12d58 | 156 | struct mntent *mntp; |
55fce87f | 157 | FILE *fstab; |
158 | ||
159 | fstab = setmntent(MNTTAB, "r"); | |
5eaef520 | 160 | while (mntp = getmntent(fstab)) |
161 | { | |
162 | if (!strcmp(mntp->mnt_fsname, device_or_dir) || | |
163 | !strcmp(mntp->mnt_dir, device_or_dir)) | |
164 | { | |
165 | strcpy(device, mntp->mnt_fsname); | |
166 | sprintf(quotafilename, "%s/quotas", mntp->mnt_dir); | |
167 | endmntent(fstab); | |
168 | return; | |
169 | } | |
55fce87f | 170 | } |
55fce87f | 171 | fprintf(stderr, "%s not mounted.\n", device_or_dir); |
172 | exit(1); | |
173 | } |