1
/* Copyright (C) 2001,2002 Red Hat, Inc.
3
* This is free software; you can redistribute it and/or modify it under
4
* the terms of the GNU Library General Public License as published by
5
* the Free Software Foundation; either version 2 of the License, or
6
* (at your option) any later version.
8
* This program is distributed in the hope that it will be useful, but
9
* WITHOUT ANY WARRANTY; without even the implied warranty of
10
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11
* General Public License for more details.
13
* You should have received a copy of the GNU Library General Public
14
* License along with this program; if not, write to the Free Software
15
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18
#ident "$Id: userquota.c,v 1.5 2004/09/02 18:32:43 mitr Exp $"
21
#include "../config.h"
24
#include <sys/types.h>
26
#include <sys/syscall.h>
27
#include <linux/quota.h>
28
#include <linux/unistd.h>
38
#include "userquota.h"
43
#define MIN(A,B) (((A)<(B))?(A):(B))
46
#define MAX_IQ_TIME (7 * 24 * 60 * 60)
50
#define MAX_DQ_TIME (7 * 24 * 60 * 60)
53
long quotactl(int cmd, const char* special, qid_t id, caddr_t addr);
54
_syscall4(long,quotactl,int,cmd,const char*,special,qid_t,id,caddr_t,addr);
56
static const char *quota_flags[] = { "usrquota", "grpquota", };
57
static const char *quota_suffixes[] = INITQFNAMES;
60
quota_get_specials(const char *flag)
69
fp = fopen(_PATH_MOUNTED, "r");
74
while ((ent = getmntent(fp)) != NULL) {
75
if (hasmntopt(ent, flag) || hasmntopt(ent, "quota")) {
76
char **tmp = malloc(sizeof(char *) * (count + 2));
78
for (i = 0; i < count + 1; i++) {
83
tmp[count] = strdup(ent->mnt_fsname);
84
tmp[count + 1] = NULL;
96
quota_get_specials_user()
98
return quota_get_specials(quota_flags[USRQUOTA]);
102
quota_get_specials_group()
104
return quota_get_specials(quota_flags[GRPQUOTA]);
108
quota_free_specials(char **specials)
111
for (i = 0; (specials != NULL) && (specials[i] != NULL); i++) {
114
if (specials != NULL) {
120
quota_toggle_ext(struct mntent *ent, const char *option, int command,
127
/* FIXME: hardcoded GRPQUOTA???
128
FIXME: "quota" implies "usrquota" or both? */
129
if (hasmntopt(ent, option) ||
130
((strcmp(option, "usrquota") == 0)
131
&& hasmntopt(ent, "quota"))) {
132
snprintf(buf, sizeof(buf), "%s/%s.%s", ent->mnt_dir,
133
QUOTAFILENAME, quota_suffixes[GRPQUOTA]);
134
if (stat(buf, &st) == 0) {
135
if ((st.st_mode & 0777) != 0600) {
136
fd = open(buf, O_RDWR);
139
if (fstat(fd, &ist) == 0) {
150
ret = quotactl(QCMD(command, GRPQUOTA),
151
ent->mnt_fsname, 0, buf);
153
if (errno == EBUSY) {
166
quota_toggle(int command)
172
fp = fopen(_PATH_MOUNTED, "r");
177
while ((ent = getmntent(fp)) != NULL) {
178
ret = quota_toggle_ext(ent, quota_flags[USRQUOTA],
183
ret = quota_toggle_ext(ent, quota_flags[GRPQUOTA],
198
return quota_toggle(Q_QUOTAON);
204
return quota_toggle(Q_QUOTAOFF);
208
quota_get(int type, int id, const char *special,
209
int32_t * inode_usage, int32_t * inode_soft,
210
int32_t * inode_hard, int32_t * inode_grace,
211
int32_t * block_usage, int32_t * block_soft,
212
int32_t * block_hard, int32_t * block_grace)
214
struct mem_dqblk dqblk;
215
struct mem_dqinfo dqinfo;
218
memset(&dqblk, 0, sizeof(dqblk));
219
memset(&dqinfo, 0, sizeof(dqinfo));
222
quotactl(QCMD(Q_GETQUOTA, type), special, id,
226
quotactl(QCMD(Q_GETINFO, type), special, id,
231
*inode_usage = dqblk.dqb_curinodes;
233
*inode_soft = dqblk.dqb_isoftlimit;
235
*inode_hard = dqblk.dqb_ihardlimit;
237
*inode_grace = dqinfo.dqi_igrace;
241
(dqblk.dqb_curspace + QUOTABLOCK_SIZE -
242
1) / QUOTABLOCK_SIZE;
244
*block_soft = dqblk.dqb_bsoftlimit;
246
*block_hard = dqblk.dqb_bhardlimit;
248
*block_grace = dqinfo.dqi_bgrace;
254
quota_set(int type, int id, const char *special,
255
int32_t inode_soft, int32_t inode_hard, int32_t inode_grace,
256
int32_t block_soft, int32_t block_hard, int32_t block_grace)
258
struct mem_dqblk dqblk;
259
struct mem_dqinfo dqinfo;
262
memset(&dqblk, 0, sizeof(dqblk));
263
memset(&dqinfo, 0, sizeof(dqinfo));
266
quotactl(QCMD(Q_GETQUOTA, type), special, id,
270
quotactl(QCMD(Q_GETINFO, type), special, id,
274
if (inode_soft != -1)
275
dqblk.dqb_isoftlimit = inode_soft;
276
if (inode_hard != -1)
277
dqblk.dqb_ihardlimit = inode_hard;
278
if (inode_grace != -1)
279
dqinfo.dqi_igrace = MIN(inode_grace, MAX_IQ_TIME);
280
if (block_soft != -1)
281
dqblk.dqb_bsoftlimit = block_soft;
282
if (block_hard != -1)
283
dqblk.dqb_bhardlimit = block_hard;
284
if (block_grace != -1)
285
dqinfo.dqi_bgrace = MIN(block_grace, MAX_IQ_TIME);
288
ret = quotactl(QCMD(Q_SETQLIM, type), special, id,
292
ret = quotactl(QCMD(Q_SETGRACE, type), special, id,
299
quota_get_user(uid_t uid, const char *special,
300
int32_t * inode_usage, int32_t * inode_soft,
301
int32_t * inode_hard, int32_t * inode_grace,
302
int32_t * block_usage, int32_t * block_soft,
303
int32_t * block_hard, int32_t * block_grace)
305
return quota_get(USRQUOTA, uid, special,
306
inode_usage, inode_soft, inode_hard, inode_grace,
307
block_usage, block_soft, block_hard, block_grace);
311
quota_set_user(uid_t uid, const char *special,
312
int32_t inode_soft, int32_t inode_hard,
313
int32_t inode_grace, int32_t block_soft,
314
int32_t block_hard, int32_t block_grace)
316
return quota_set(USRQUOTA, uid, special, inode_soft, inode_hard,
317
inode_grace, block_soft, block_hard, block_grace);
321
quota_get_group(gid_t gid, const char *special,
322
int32_t * inode_usage, int32_t * inode_soft,
323
int32_t * inode_hard, int32_t * inode_grace,
324
int32_t * block_usage, int32_t * block_soft,
325
int32_t * block_hard, int32_t * block_grace)
327
return quota_get(GRPQUOTA, gid, special,
328
inode_usage, inode_soft, inode_hard, inode_grace,
329
block_usage, block_soft, block_hard, block_grace);
333
quota_set_group(gid_t gid, const char *special,
334
int32_t inode_soft, int32_t inode_hard,
335
int32_t inode_grace, int32_t block_soft,
336
int32_t block_hard, int32_t block_grace)
338
return quota_set(GRPQUOTA, gid, special, inode_soft, inode_hard,
339
inode_grace, block_soft, block_hard, block_grace);