]>
Commit | Line | Data |
---|---|---|
1 | /* | |
2 | * $Source$ | |
3 | * $Author$ | |
4 | * $Header$ | |
5 | * | |
6 | * Copyright (C) 1987 by the Massachusetts Institute of Technology | |
7 | * | |
8 | * Set quota on specified device for specified user to specified value. | |
9 | * | |
10 | * Uses the NFS style quota system/quotactl rather than the Melbourne | |
11 | * quota system. | |
12 | * | |
13 | */ | |
14 | ||
15 | #ifndef lint | |
16 | static char *rcsid_setquota_c = "$Header$"; | |
17 | #endif lint | |
18 | ||
19 | #include <stdio.h> | |
20 | #include <ctype.h> | |
21 | #include <mntent.h> | |
22 | ||
23 | #include <sys/file.h> | |
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 | ||
30 | static char device[20]; | |
31 | static char quotafilename[30]; | |
32 | static struct dqblk zblk = {0}; | |
33 | ||
34 | int main(int argc, char **argv) | |
35 | { | |
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: | |
56 | goto usage; | |
57 | } | |
58 | } | |
59 | ||
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 | } | |
70 | ||
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 | } | |
78 | ||
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]); | |
97 | ||
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 | { | |
104 | perror("No quota file"); | |
105 | exit(1); | |
106 | } | |
107 | ||
108 | lseek(qfd, 32767 * sizeof(struct dqblk), L_SET); | |
109 | write(qfd, &zblk, sizeof(struct dqblk)); | |
110 | close(qfd); | |
111 | ||
112 | if (quotactl(Q_GETQUOTA, device, uid, &odb) != 0) | |
113 | { | |
114 | perror("Can't get current quota info"); | |
115 | exit(1); | |
116 | } | |
117 | } | |
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; | |
135 | } | |
136 | ||
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); | |
152 | } | |
153 | ||
154 | get_device(char *device_or_dir) | |
155 | { | |
156 | struct mntent *mntp; | |
157 | FILE *fstab; | |
158 | ||
159 | fstab = setmntent(MNTTAB, "r"); | |
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 | } | |
170 | } | |
171 | fprintf(stderr, "%s not mounted.\n", device_or_dir); | |
172 | exit(1); | |
173 | } |