~ubuntu-branches/ubuntu/utopic/libuser/utopic-proposed

« back to all changes in this revision

Viewing changes to lib/userquota.c

  • Committer: Bazaar Package Importer
  • Author(s): Ghe Rivero
  • Date: 2005-09-30 16:22:04 UTC
  • Revision ID: james.westby@ubuntu.com-20050930162204-qubxaa7e2lbovdgh
Tags: upstream-0.54.dfsg.1
ImportĀ upstreamĀ versionĀ 0.54.dfsg.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Copyright (C) 2001,2002 Red Hat, Inc.
 
2
 *
 
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.
 
7
 *
 
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.
 
12
 *
 
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.
 
16
 */
 
17
 
 
18
#ident "$Id: userquota.c,v 1.5 2004/09/02 18:32:43 mitr Exp $"
 
19
 
 
20
#ifdef HAVE_CONFIG_H
 
21
#include "../config.h"
 
22
#endif
 
23
 
 
24
#include <sys/types.h>
 
25
#include <sys/stat.h>
 
26
#include <sys/syscall.h>
 
27
#include <linux/quota.h>
 
28
#include <linux/unistd.h>
 
29
#include <errno.h>
 
30
#include <fcntl.h>
 
31
#include <limits.h>
 
32
#include <mntent.h>
 
33
#include <paths.h>
 
34
#include <stdio.h>
 
35
#include <stdlib.h>
 
36
#include <string.h>
 
37
#include <unistd.h>
 
38
#include "userquota.h"
 
39
 
 
40
#ifdef MIN
 
41
#undef MIN
 
42
#endif
 
43
#define MIN(A,B) (((A)<(B))?(A):(B))
 
44
 
 
45
#ifndef MAX_IQ_TIME
 
46
#define MAX_IQ_TIME (7 * 24 * 60 * 60)
 
47
#endif
 
48
 
 
49
#ifndef MAX_DQ_TIME
 
50
#define MAX_DQ_TIME (7 * 24 * 60 * 60)
 
51
#endif
 
52
 
 
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);
 
55
 
 
56
static const char *quota_flags[] = { "usrquota", "grpquota", };
 
57
static const char *quota_suffixes[] = INITQFNAMES;
 
58
 
 
59
static char **
 
60
quota_get_specials(const char *flag)
 
61
{
 
62
        FILE *fp;
 
63
        struct mntent *ent;
 
64
        int count, i;
 
65
        char **ret = NULL;
 
66
 
 
67
        count = 0;
 
68
 
 
69
        fp = fopen(_PATH_MOUNTED, "r");
 
70
        if (fp == NULL) {
 
71
                return NULL;
 
72
        }
 
73
 
 
74
        while ((ent = getmntent(fp)) != NULL) {
 
75
                if (hasmntopt(ent, flag) || hasmntopt(ent, "quota")) {
 
76
                        char **tmp = malloc(sizeof(char *) * (count + 2));
 
77
                        if (ret != NULL) {
 
78
                                for (i = 0; i < count + 1; i++) {
 
79
                                        tmp[i] = ret[i];
 
80
                                }
 
81
                                free(ret);
 
82
                        }
 
83
                        tmp[count] = strdup(ent->mnt_fsname);
 
84
                        tmp[count + 1] = NULL;
 
85
                        count++;
 
86
                        ret = tmp;
 
87
                }
 
88
        }
 
89
 
 
90
        endmntent(fp);
 
91
 
 
92
        return ret;
 
93
}
 
94
 
 
95
char **
 
96
quota_get_specials_user()
 
97
{
 
98
        return quota_get_specials(quota_flags[USRQUOTA]);
 
99
}
 
100
 
 
101
char **
 
102
quota_get_specials_group()
 
103
{
 
104
        return quota_get_specials(quota_flags[GRPQUOTA]);
 
105
}
 
106
 
 
107
void
 
108
quota_free_specials(char **specials)
 
109
{
 
110
        int i;
 
111
        for (i = 0; (specials != NULL) && (specials[i] != NULL); i++) {
 
112
                free(specials[i]);
 
113
        }
 
114
        if (specials != NULL) {
 
115
                free(specials);
 
116
        }
 
117
}
 
118
 
 
119
static int
 
120
quota_toggle_ext(struct mntent *ent, const char *option, int command,
 
121
                 int flag)
 
122
{
 
123
        char buf[PATH_MAX];
 
124
        struct stat st;
 
125
        int ret = 0, fd;
 
126
 
 
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);
 
137
                                if (fd != -1) {
 
138
                                        struct stat ist;
 
139
                                        if (fstat(fd, &ist) == 0) {
 
140
                                                if ((ist.st_dev ==
 
141
                                                     st.st_dev)
 
142
                                                    && (ist.st_ino ==
 
143
                                                        st.st_ino)) {
 
144
                                                        fchmod(fd, 0600);
 
145
                                                }
 
146
                                        }
 
147
                                        close(fd);
 
148
                                }
 
149
                        }
 
150
                        ret = quotactl(QCMD(command, GRPQUOTA),
 
151
                                       ent->mnt_fsname, 0, buf);
 
152
                        if (ret == -1) {
 
153
                                if (errno == EBUSY) {
 
154
                                        ret = 0;
 
155
                                }
 
156
                        }
 
157
                        if (ret == -1) {
 
158
                                return ret;
 
159
                        }
 
160
                }
 
161
        }
 
162
        return ret;
 
163
}
 
164
 
 
165
static int
 
166
quota_toggle(int command)
 
167
{
 
168
        int ret = 0;
 
169
        struct mntent *ent;
 
170
        FILE *fp;
 
171
 
 
172
        fp = fopen(_PATH_MOUNTED, "r");
 
173
        if (fp == NULL) {
 
174
                return -1;
 
175
        }
 
176
 
 
177
        while ((ent = getmntent(fp)) != NULL) {
 
178
                ret = quota_toggle_ext(ent, quota_flags[USRQUOTA],
 
179
                                       command, USRQUOTA);
 
180
                if (ret != 0) {
 
181
                        break;
 
182
                }
 
183
                ret = quota_toggle_ext(ent, quota_flags[GRPQUOTA],
 
184
                                       command, GRPQUOTA);
 
185
                if (ret != 0) {
 
186
                        break;
 
187
                }
 
188
        }
 
189
 
 
190
        endmntent(fp);
 
191
 
 
192
        return ret;
 
193
}
 
194
 
 
195
int
 
196
quota_on()
 
197
{
 
198
        return quota_toggle(Q_QUOTAON);
 
199
}
 
200
 
 
201
int
 
202
quota_off()
 
203
{
 
204
        return quota_toggle(Q_QUOTAOFF);
 
205
}
 
206
 
 
207
static int
 
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)
 
213
{
 
214
        struct mem_dqblk dqblk;
 
215
        struct mem_dqinfo dqinfo;
 
216
        int ret = 0;
 
217
 
 
218
        memset(&dqblk, 0, sizeof(dqblk));
 
219
        memset(&dqinfo, 0, sizeof(dqinfo));
 
220
 
 
221
        ret =
 
222
            quotactl(QCMD(Q_GETQUOTA, type), special, id,
 
223
                     (caddr_t) & dqblk);
 
224
        if (ret == 0)
 
225
                ret =
 
226
                    quotactl(QCMD(Q_GETINFO, type), special, id,
 
227
                             (caddr_t) & dqinfo);
 
228
 
 
229
        if (ret == 0) {
 
230
                if (inode_usage)
 
231
                        *inode_usage = dqblk.dqb_curinodes;
 
232
                if (inode_soft)
 
233
                        *inode_soft = dqblk.dqb_isoftlimit;
 
234
                if (inode_hard)
 
235
                        *inode_hard = dqblk.dqb_ihardlimit;
 
236
                if (inode_grace)
 
237
                        *inode_grace = dqinfo.dqi_igrace;
 
238
 
 
239
                if (block_usage)
 
240
                        *block_usage =
 
241
                            (dqblk.dqb_curspace + QUOTABLOCK_SIZE -
 
242
                             1) / QUOTABLOCK_SIZE;
 
243
                if (block_soft)
 
244
                        *block_soft = dqblk.dqb_bsoftlimit;
 
245
                if (block_hard)
 
246
                        *block_hard = dqblk.dqb_bhardlimit;
 
247
                if (block_grace)
 
248
                        *block_grace = dqinfo.dqi_bgrace;
 
249
        }
 
250
        return ret;
 
251
}
 
252
 
 
253
static int
 
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)
 
257
{
 
258
        struct mem_dqblk dqblk;
 
259
        struct mem_dqinfo dqinfo;
 
260
        int ret = 0;
 
261
 
 
262
        memset(&dqblk, 0, sizeof(dqblk));
 
263
        memset(&dqinfo, 0, sizeof(dqinfo));
 
264
 
 
265
        ret =
 
266
            quotactl(QCMD(Q_GETQUOTA, type), special, id,
 
267
                     (caddr_t) & dqblk);
 
268
        if (ret == 0)
 
269
                ret =
 
270
                    quotactl(QCMD(Q_GETINFO, type), special, id,
 
271
                             (caddr_t) & dqinfo);
 
272
 
 
273
        if (ret == 0) {
 
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);
 
286
        }
 
287
        if (ret == 0) {
 
288
                ret = quotactl(QCMD(Q_SETQLIM, type), special, id,
 
289
                               (caddr_t) & dqblk);
 
290
        }
 
291
        if (ret == 0) {
 
292
                ret = quotactl(QCMD(Q_SETGRACE, type), special, id,
 
293
                               (caddr_t) & dqinfo);
 
294
        }
 
295
        return ret;
 
296
}
 
297
 
 
298
int
 
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)
 
304
{
 
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);
 
308
}
 
309
 
 
310
int
 
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)
 
315
{
 
316
        return quota_set(USRQUOTA, uid, special, inode_soft, inode_hard,
 
317
                         inode_grace, block_soft, block_hard, block_grace);
 
318
}
 
319
 
 
320
int
 
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)
 
326
{
 
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);
 
330
}
 
331
 
 
332
int
 
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)
 
337
{
 
338
        return quota_set(GRPQUOTA, gid, special, inode_soft, inode_hard,
 
339
                         inode_grace, block_soft, block_hard, block_grace);
 
340
}