2 * Copyright (c) 1980, 1990 Regents of the University of California. All
5 * This code is derived from software contributed to Berkeley by Robert Elz at
6 * The University of Melbourne.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions are
10 * met: 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer. 2.
12 * Redistributions in binary form must reproduce the above copyright notice,
13 * this list of conditions and the following disclaimer in the documentation
14 * and/or other materials provided with the distribution. 3. All advertising
15 * materials mentioning features or use of this software must display the
16 * following acknowledgement: This product includes software developed by the
17 * University of California, Berkeley and its contributors. 4. Neither the
18 * name of the University nor the names of its contributors may be used to
19 * endorse or promote products derived from this software without specific
20 * prior written permission.
22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
23 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
24 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
25 * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR
26 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
28 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
40 #include <sys/types.h>
61 #define FL_EDIT_PERIOD 1
62 #define FL_EDIT_TIMES 2
65 #define FL_NO_MIXED_PATHS 16
76 #if defined(RPC_SETQUOTA)
77 char *rpcflag = "[-rm] ";
81 errstr(_("Usage:\n\tedquota %1$s[-u] [-F formatname] [-p username] [-f filesystem] username ...\n\
82 \tedquota %1$s-g [-F formatname] [-p groupname] [-f filesystem] groupname ...\n\
83 \tedquota %1$s[-u|g] [-F formatname] [-f filesystem] -t\n\
84 \tedquota %1$s[-u|g] [-F formatname] [-f filesystem] -T username|groupname ...\n"), rpcflag);
86 -u, --user edit user data\n\
87 -g, --group edit group data\n"), stderr);
88 #if defined(RPC_SETQUOTA)
89 fputs(_("-r, --remote edit remote quota (via RPC)\n\
90 -m, --no-mixed-pathnames trim leading slashes from NFSv4 mountpoints\n"), stderr);
92 fputs(_("-F, --format=formatname edit quotas of a specific format\n\
93 -p, --prototype=name copy data from a prototype user/group\n\
94 --always-resolve always try to resolve name, even if it is\n\
95 composed only of digits\n\
96 -f, --filesystem=filesystem edit data only on a specific filesystem\n\
97 -t, --edit-period edit grace period\n\
98 -T, --edit-times edit grace time of a user/group\n\
99 -h, --help display this help text and exit\n\
100 -V, --version display version information and exit\n\n"), stderr);
101 fprintf(stderr, _("Bugs to: %s\n"), MY_EMAIL);
105 int parse_options(int argc, char **argv)
108 struct option long_opts[] = {
109 { "help", 0, NULL, 'h' },
110 { "version", 0, NULL, 'V' },
111 { "prototype", 1, NULL, 'p' },
112 { "user", 0, NULL, 'u' },
113 { "group", 0, NULL, 'g' },
114 { "format", 1, NULL, 'F' },
115 { "filesystem", 1, NULL, 'f' },
116 #if defined(RPC_SETQUOTA)
117 { "remote", 0, NULL, 'r' },
118 { "no-mixed-pathnames", 0, NULL, 'm' },
120 { "always-resolve", 0, NULL, 256 },
121 { "edit-period", 0, NULL, 't' },
122 { "edit-times", 0, NULL, 'T' },
129 quotatype = USRQUOTA;
130 #if defined(RPC_SETQUOTA)
131 while ((ret = getopt_long(argc, argv, "ugrmntTVp:F:f:", long_opts, NULL)) != -1) {
133 while ((ret = getopt_long(argc, argv, "ugtTVp:F:f:", long_opts, NULL)) != -1) {
140 quotatype = GRPQUOTA;
142 #if defined(RPC_SETQUOTA)
148 flags |= FL_NO_MIXED_PATHS;
152 quotatype = USRQUOTA;
155 flags |= FL_EDIT_PERIOD;
158 flags |= FL_EDIT_TIMES;
161 if ((fmt = name2fmt(optarg)) == QF_ERROR) /* Error? */
168 flags |= FL_NUMNAMES;
179 if (((flags & FL_EDIT_PERIOD) && argc != 0) || ((flags & FL_EDIT_TIMES) && argc < 1))
181 if ((flags & (FL_EDIT_PERIOD | FL_EDIT_TIMES)) && protoname) {
182 errstr(_("Prototype name does not make sense when editing grace period or times.\n"));
188 void copy_prototype(int argc, char **argv, struct quota_handle **handles)
190 int ret, protoid, id;
191 struct dquot *protoprivs, *curprivs, *pprivs, *cprivs;
194 protoid = name2id(protoname, quotatype, !!(flags & FL_NUMNAMES), NULL);
195 protoprivs = getprivs(protoid, handles, 0);
197 id = name2id(*argv, quotatype, !!(flags & FL_NUMNAMES), NULL);
198 curprivs = getprivs(id, handles, 0);
200 die(1, _("Cannot get quota information for user %s\n"), *argv);
203 for (pprivs = protoprivs, cprivs = curprivs; pprivs && cprivs;
204 pprivs = pprivs->dq_next, cprivs = cprivs->dq_next) {
205 if (!devcmp_handles(pprivs->dq_h, cprivs->dq_h)) {
206 errstr(_("fsname mismatch\n"));
209 cprivs->dq_dqb.dqb_bsoftlimit =
210 pprivs->dq_dqb.dqb_bsoftlimit;
211 cprivs->dq_dqb.dqb_bhardlimit =
212 pprivs->dq_dqb.dqb_bhardlimit;
213 cprivs->dq_dqb.dqb_isoftlimit =
214 pprivs->dq_dqb.dqb_isoftlimit;
215 cprivs->dq_dqb.dqb_ihardlimit =
216 pprivs->dq_dqb.dqb_ihardlimit;
217 update_grace_times(cprivs);
219 if (putprivs(curprivs, COMMIT_LIMITS) == -1)
223 if (dispose_handle_list(handles) == -1)
225 freeprivs(protoprivs);
229 int main(int argc, char **argv)
231 struct dquot *curprivs;
233 struct quota_handle **handles;
234 char *tmpfil, *tmpdir = NULL;
237 progname = basename(argv[0]);
238 ret = parse_options(argc, argv);
242 init_kernel_interface();
243 handles = create_handle_list(dirname ? 1 : 0, dirname ? &dirname : NULL, quotatype, fmt,
244 (flags & FL_NO_MIXED_PATHS) ? 0 : IOI_NFS_MIXED_PATHS,
245 (flags & FL_REMOTE) ? 0 : MS_LOCALONLY);
247 dispose_handle_list(handles);
248 fputs(_("No filesystems with quota detected.\n"), stderr);
252 copy_prototype(argc, argv, handles);
255 if (getuid() == geteuid() && getgid() == getegid())
256 tmpdir = getenv("TMPDIR");
259 tmpfil = smalloc(strlen(tmpdir) + strlen("/EdP.aXXXXXX") + 1);
260 strcpy(tmpfil, tmpdir);
261 strcat(tmpfil, "/EdP.aXXXXXX");
262 tmpfd = mkstemp(tmpfil);
264 errstr(_("Cannot create temporary file: %s\n"), strerror(errno));
268 if (fchown(tmpfd, getuid(), getgid()) < 0) {
269 errstr(_("Cannot change owner of temporary file: %s\n"), strerror(errno));
274 if (flags & FL_EDIT_PERIOD) {
275 if (writetimes(handles, tmpfd) < 0) {
276 errstr(_("Cannot write grace times to file.\n"));
279 if (editprivs(tmpfil) < 0) {
280 errstr(_("Error while editing grace times.\n"));
283 if (readtimes(handles, tmpfd) < 0) {
284 errstr(_("Failed to parse grace times file.\n"));
288 else if (flags & FL_EDIT_TIMES) {
289 for (; argc > 0; argc--, argv++) {
290 id = name2id(*argv, quotatype, !!(flags & FL_NUMNAMES), NULL);
291 curprivs = getprivs(id, handles, 0);
293 die(1, _("Cannot get quota information for user %s.\n"), *argv);
294 if (writeindividualtimes(curprivs, tmpfd, *argv, quotatype) < 0) {
295 errstr(_("Cannot write individual grace times to file.\n"));
299 if (editprivs(tmpfil) < 0) {
300 errstr(_("Error while editing individual grace times.\n"));
304 if (readindividualtimes(curprivs, tmpfd) < 0) {
305 errstr(_("Cannot read individual grace times from file.\n"));
309 if (putprivs(curprivs, COMMIT_TIMES) == -1)
315 for (; argc > 0; argc--, argv++) {
316 id = name2id(*argv, quotatype, !!(flags & FL_NUMNAMES), NULL);
317 curprivs = getprivs(id, handles, 0);
319 die(1, _("Cannot get quota information for user %s.\n"), *argv);
320 if (writeprivs(curprivs, tmpfd, *argv, quotatype) < 0) {
321 errstr(_("Cannot write quotas to file.\n"));
325 if (editprivs(tmpfil) < 0) {
326 errstr(_("Error while editing quotas.\n"));
331 if ((tmpfd = open(tmpfil, O_RDONLY)) < 0)
332 die(1, _("Cannot reopen!"));
333 if (readprivs(curprivs, tmpfd) < 0) {
334 errstr(_("Cannot read quotas from file.\n"));
338 if (putprivs(curprivs, COMMIT_LIMITS) == -1)
344 if (dispose_handle_list(handles) == -1)