1*48747c68Shannken /* $NetBSD: quota_oldfiles.c,v 1.10 2022/04/26 15:36:42 hannken Exp $ */
28d70e807Sdholland
38d70e807Sdholland /*
48d70e807Sdholland * Copyright (c) 1980, 1990, 1993
58d70e807Sdholland * The Regents of the University of California. All rights reserved.
68d70e807Sdholland *
78d70e807Sdholland * This code is derived from software contributed to Berkeley by
88d70e807Sdholland * Robert Elz at The University of Melbourne.
98d70e807Sdholland *
108d70e807Sdholland * Redistribution and use in source and binary forms, with or without
118d70e807Sdholland * modification, are permitted provided that the following conditions
128d70e807Sdholland * are met:
138d70e807Sdholland * 1. Redistributions of source code must retain the above copyright
148d70e807Sdholland * notice, this list of conditions and the following disclaimer.
158d70e807Sdholland * 2. Redistributions in binary form must reproduce the above copyright
168d70e807Sdholland * notice, this list of conditions and the following disclaimer in the
178d70e807Sdholland * documentation and/or other materials provided with the distribution.
188d70e807Sdholland * 3. Neither the name of the University nor the names of its contributors
198d70e807Sdholland * may be used to endorse or promote products derived from this software
208d70e807Sdholland * without specific prior written permission.
218d70e807Sdholland *
228d70e807Sdholland * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
238d70e807Sdholland * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
248d70e807Sdholland * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
258d70e807Sdholland * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
268d70e807Sdholland * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
278d70e807Sdholland * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
288d70e807Sdholland * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
298d70e807Sdholland * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
308d70e807Sdholland * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
318d70e807Sdholland * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
328d70e807Sdholland * SUCH DAMAGE.
338d70e807Sdholland */
348d70e807Sdholland
351ce78a5fSdholland #include <sys/cdefs.h>
36*48747c68Shannken __RCSID("$NetBSD: quota_oldfiles.c,v 1.10 2022/04/26 15:36:42 hannken Exp $");
371ce78a5fSdholland
388d70e807Sdholland #include <sys/types.h>
398d70e807Sdholland #include <sys/stat.h>
408d70e807Sdholland #include <stdio.h>
418d70e807Sdholland #include <stdlib.h>
428d70e807Sdholland #include <string.h>
438d70e807Sdholland #include <unistd.h>
448d70e807Sdholland #include <fcntl.h>
458d70e807Sdholland #include <limits.h>
468d70e807Sdholland #include <fstab.h>
478d70e807Sdholland #include <errno.h>
488d70e807Sdholland #include <err.h>
498d70e807Sdholland
508d70e807Sdholland #include <ufs/ufs/quota1.h>
518d70e807Sdholland
528d70e807Sdholland #include <quota.h>
538d70e807Sdholland #include "quotapvt.h"
548d70e807Sdholland
55fa577c93Sdholland struct oldfiles_fstabentry {
56fa577c93Sdholland char *ofe_mountpoint;
57fa577c93Sdholland int ofe_hasuserquota;
58fa577c93Sdholland int ofe_hasgroupquota;
59fa577c93Sdholland char *ofe_userquotafile;
60fa577c93Sdholland char *ofe_groupquotafile;
61fa577c93Sdholland };
62fa577c93Sdholland
638d70e807Sdholland struct oldfiles_quotacursor {
648d70e807Sdholland unsigned oqc_doingusers;
658d70e807Sdholland unsigned oqc_doinggroups;
668d70e807Sdholland
678d70e807Sdholland unsigned oqc_numusers;
688d70e807Sdholland unsigned oqc_numgroups;
698d70e807Sdholland
708d70e807Sdholland unsigned oqc_didusers;
718d70e807Sdholland unsigned oqc_didgroups;
728d70e807Sdholland unsigned oqc_diddefault;
738d70e807Sdholland unsigned oqc_pos;
748d70e807Sdholland unsigned oqc_didblocks;
758d70e807Sdholland };
768d70e807Sdholland
77fa577c93Sdholland static struct oldfiles_fstabentry *__quota_oldfiles_fstab;
78fa577c93Sdholland static unsigned __quota_oldfiles_numfstab;
79fa577c93Sdholland static unsigned __quota_oldfiles_maxfstab;
80fa577c93Sdholland static int __quota_oldfiles_fstab_loaded;
81fa577c93Sdholland
82fa577c93Sdholland static const struct oldfiles_fstabentry *
__quota_oldfiles_find_fstabentry(const char * mountpoint)83fa577c93Sdholland __quota_oldfiles_find_fstabentry(const char *mountpoint)
84fa577c93Sdholland {
85fa577c93Sdholland unsigned i;
86fa577c93Sdholland
87fa577c93Sdholland for (i = 0; i < __quota_oldfiles_numfstab; i++) {
88fa577c93Sdholland if (!strcmp(mountpoint,
89fa577c93Sdholland __quota_oldfiles_fstab[i].ofe_mountpoint)) {
90fa577c93Sdholland return &__quota_oldfiles_fstab[i];
91fa577c93Sdholland }
92fa577c93Sdholland }
93fa577c93Sdholland return NULL;
94fa577c93Sdholland }
95fa577c93Sdholland
96fa577c93Sdholland static int
__quota_oldfiles_add_fstabentry(struct oldfiles_fstabentry * ofe)97fa577c93Sdholland __quota_oldfiles_add_fstabentry(struct oldfiles_fstabentry *ofe)
98fa577c93Sdholland {
99fa577c93Sdholland unsigned newmax;
100fa577c93Sdholland struct oldfiles_fstabentry *newptr;
101fa577c93Sdholland
102fa577c93Sdholland if (__quota_oldfiles_numfstab + 1 >= __quota_oldfiles_maxfstab) {
103fa577c93Sdholland if (__quota_oldfiles_maxfstab == 0) {
104fa577c93Sdholland newmax = 4;
105fa577c93Sdholland } else {
106fa577c93Sdholland newmax = __quota_oldfiles_maxfstab * 2;
107fa577c93Sdholland }
108fa577c93Sdholland newptr = realloc(__quota_oldfiles_fstab,
109fa577c93Sdholland newmax * sizeof(__quota_oldfiles_fstab[0]));
110fa577c93Sdholland if (newptr == NULL) {
111fa577c93Sdholland return -1;
112fa577c93Sdholland }
113fa577c93Sdholland __quota_oldfiles_maxfstab = newmax;
114fa577c93Sdholland __quota_oldfiles_fstab = newptr;
115fa577c93Sdholland }
116fa577c93Sdholland
117fa577c93Sdholland __quota_oldfiles_fstab[__quota_oldfiles_numfstab++] = *ofe;
118fa577c93Sdholland return 0;
119fa577c93Sdholland }
120fa577c93Sdholland
121fa577c93Sdholland static int
__quota_oldfiles_fill_fstabentry(const struct fstab * fs,struct oldfiles_fstabentry * ofe)122fa577c93Sdholland __quota_oldfiles_fill_fstabentry(const struct fstab *fs,
123fa577c93Sdholland struct oldfiles_fstabentry *ofe)
124fa577c93Sdholland {
125dfbeb140Sdholland char buf[256];
126fa577c93Sdholland char *opt, *state, *s;
127fa577c93Sdholland int serrno;
128fa577c93Sdholland int ret = 0;
129fa577c93Sdholland
130fa577c93Sdholland /*
131fa577c93Sdholland * Inspect the mount options to find the quota files.
132fa577c93Sdholland * XXX this info should be gotten from the kernel.
133fa577c93Sdholland *
134fa577c93Sdholland * The options are:
135fa577c93Sdholland * userquota[=path] enable user quotas
136fa577c93Sdholland * groupquota[=path] enable group quotas
137fa577c93Sdholland */
138fa577c93Sdholland
139fa577c93Sdholland ofe->ofe_mountpoint = NULL;
140fa577c93Sdholland ofe->ofe_hasuserquota = ofe->ofe_hasgroupquota = 0;
141fa577c93Sdholland ofe->ofe_userquotafile = ofe->ofe_groupquotafile = NULL;
142fa577c93Sdholland
143fa577c93Sdholland strlcpy(buf, fs->fs_mntops, sizeof(buf));
144fa577c93Sdholland for (opt = strtok_r(buf, ",", &state);
145fa577c93Sdholland opt != NULL;
146fa577c93Sdholland opt = strtok_r(NULL, ",", &state)) {
147fa577c93Sdholland s = strchr(opt, '=');
148fa577c93Sdholland if (s != NULL) {
149fa577c93Sdholland *(s++) = '\0';
150fa577c93Sdholland }
151fa577c93Sdholland if (!strcmp(opt, "userquota")) {
152fa577c93Sdholland ret = 1;
153fa577c93Sdholland ofe->ofe_hasuserquota = 1;
154fa577c93Sdholland if (s != NULL) {
155fa577c93Sdholland ofe->ofe_userquotafile = strdup(s);
156fa577c93Sdholland if (ofe->ofe_userquotafile == NULL) {
157fa577c93Sdholland goto fail;
158fa577c93Sdholland }
159fa577c93Sdholland }
160fa577c93Sdholland } else if (!strcmp(opt, "groupquota")) {
161fa577c93Sdholland ret = 1;
162fa577c93Sdholland ofe->ofe_hasgroupquota = 1;
163fa577c93Sdholland if (s != NULL) {
164fa577c93Sdholland ofe->ofe_groupquotafile = strdup(s);
165fa577c93Sdholland if (ofe->ofe_groupquotafile == NULL) {
166fa577c93Sdholland goto fail;
167fa577c93Sdholland }
168fa577c93Sdholland }
169fa577c93Sdholland }
170fa577c93Sdholland }
171fa577c93Sdholland
172fa577c93Sdholland if (ret == 1) {
173fa577c93Sdholland ofe->ofe_mountpoint = strdup(fs->fs_file);
174fa577c93Sdholland if (ofe->ofe_mountpoint == NULL) {
175fa577c93Sdholland goto fail;
176fa577c93Sdholland }
177fa577c93Sdholland }
178fa577c93Sdholland
179fa577c93Sdholland return ret;
180fa577c93Sdholland
181fa577c93Sdholland fail:
182fa577c93Sdholland serrno = errno;
183fa577c93Sdholland if (ofe->ofe_mountpoint != NULL) {
184fa577c93Sdholland free(ofe->ofe_mountpoint);
185fa577c93Sdholland }
186fa577c93Sdholland if (ofe->ofe_groupquotafile != NULL) {
187fa577c93Sdholland free(ofe->ofe_groupquotafile);
188fa577c93Sdholland }
189fa577c93Sdholland if (ofe->ofe_userquotafile != NULL) {
190fa577c93Sdholland free(ofe->ofe_userquotafile);
191fa577c93Sdholland }
192fa577c93Sdholland errno = serrno;
193fa577c93Sdholland return -1;
194fa577c93Sdholland }
195fa577c93Sdholland
196fa577c93Sdholland void
__quota_oldfiles_load_fstab(void)197fa577c93Sdholland __quota_oldfiles_load_fstab(void)
198fa577c93Sdholland {
199fa577c93Sdholland struct oldfiles_fstabentry ofe;
200fa577c93Sdholland struct fstab *fs;
201fa577c93Sdholland int result;
202fa577c93Sdholland
203fa577c93Sdholland if (__quota_oldfiles_fstab_loaded) {
204fa577c93Sdholland return;
205fa577c93Sdholland }
206fa577c93Sdholland
207fa577c93Sdholland /*
208addd71bdSnjoly * Check if fstab file exists before trying to parse it.
209addd71bdSnjoly * Avoid warnings from {get,set}fsent() if missing.
210addd71bdSnjoly */
211addd71bdSnjoly if (access(_PATH_FSTAB, F_OK) == -1 && errno == ENOENT)
212addd71bdSnjoly return;
213addd71bdSnjoly
214addd71bdSnjoly /*
215fa577c93Sdholland * XXX: should be able to handle ext2fs quota1 files too
216fa577c93Sdholland *
217fa577c93Sdholland * XXX: should use getfsent_r(), but there isn't one.
218fa577c93Sdholland */
219fa577c93Sdholland setfsent();
220fa577c93Sdholland while ((fs = getfsent()) != NULL) {
221fa577c93Sdholland if (!strcmp(fs->fs_vfstype, "ffs") ||
222fa577c93Sdholland !strcmp(fs->fs_vfstype, "lfs")) {
223fa577c93Sdholland result = __quota_oldfiles_fill_fstabentry(fs, &ofe);
224fa577c93Sdholland if (result == -1) {
225fa577c93Sdholland goto failed;
226fa577c93Sdholland }
227fa577c93Sdholland if (result == 0) {
228fa577c93Sdholland continue;
229fa577c93Sdholland }
230fa577c93Sdholland if (__quota_oldfiles_add_fstabentry(&ofe)) {
231fa577c93Sdholland goto failed;
232fa577c93Sdholland }
233fa577c93Sdholland }
234fa577c93Sdholland }
235fa577c93Sdholland endfsent();
236fa577c93Sdholland __quota_oldfiles_fstab_loaded = 1;
237fa577c93Sdholland
238fa577c93Sdholland return;
239fa577c93Sdholland failed:
240fa577c93Sdholland warn("Failed reading fstab");
241fa577c93Sdholland return;
242fa577c93Sdholland }
243fa577c93Sdholland
244fa577c93Sdholland int
__quota_oldfiles_infstab(const char * mountpoint)245fa577c93Sdholland __quota_oldfiles_infstab(const char *mountpoint)
246fa577c93Sdholland {
247fa577c93Sdholland return __quota_oldfiles_find_fstabentry(mountpoint) != NULL;
248fa577c93Sdholland }
249fa577c93Sdholland
2505f0d2c5fSdholland static void
__quota_oldfiles_defquotafile(struct quotahandle * qh,int idtype,char * buf,size_t maxlen)2515f0d2c5fSdholland __quota_oldfiles_defquotafile(struct quotahandle *qh, int idtype,
2525f0d2c5fSdholland char *buf, size_t maxlen)
2535f0d2c5fSdholland {
2545f0d2c5fSdholland static const char *const names[] = INITQFNAMES;
2555f0d2c5fSdholland
2565f0d2c5fSdholland (void)snprintf(buf, maxlen, "%s/%s.%s",
2575f0d2c5fSdholland qh->qh_mountpoint,
258*48747c68Shannken QUOTAFILENAME, names[idtype]);
2595f0d2c5fSdholland }
2605f0d2c5fSdholland
2615f0d2c5fSdholland const char *
__quota_oldfiles_getquotafile(struct quotahandle * qh,int idtype,char * buf,size_t maxlen)2625f0d2c5fSdholland __quota_oldfiles_getquotafile(struct quotahandle *qh, int idtype,
2635f0d2c5fSdholland char *buf, size_t maxlen)
2645f0d2c5fSdholland {
2655f0d2c5fSdholland const struct oldfiles_fstabentry *ofe;
2665f0d2c5fSdholland const char *file;
2675f0d2c5fSdholland
2685f0d2c5fSdholland ofe = __quota_oldfiles_find_fstabentry(qh->qh_mountpoint);
2695f0d2c5fSdholland if (ofe == NULL) {
2705f0d2c5fSdholland errno = ENXIO;
2715f0d2c5fSdholland return NULL;
2725f0d2c5fSdholland }
2735f0d2c5fSdholland
2745f0d2c5fSdholland switch (idtype) {
2755f0d2c5fSdholland case USRQUOTA:
2765f0d2c5fSdholland if (!ofe->ofe_hasuserquota) {
2775f0d2c5fSdholland errno = ENXIO;
2785f0d2c5fSdholland return NULL;
2795f0d2c5fSdholland }
2805f0d2c5fSdholland file = ofe->ofe_userquotafile;
2815f0d2c5fSdholland break;
2825f0d2c5fSdholland case GRPQUOTA:
2835f0d2c5fSdholland if (!ofe->ofe_hasgroupquota) {
2845f0d2c5fSdholland errno = ENXIO;
2855f0d2c5fSdholland return NULL;
2865f0d2c5fSdholland }
2875f0d2c5fSdholland file = ofe->ofe_groupquotafile;
2885f0d2c5fSdholland break;
2895f0d2c5fSdholland default:
2905f0d2c5fSdholland errno = EINVAL;
2915f0d2c5fSdholland return NULL;
2925f0d2c5fSdholland }
2935f0d2c5fSdholland
2945f0d2c5fSdholland if (file == NULL) {
2955f0d2c5fSdholland __quota_oldfiles_defquotafile(qh, idtype, buf, maxlen);
2965f0d2c5fSdholland file = buf;
2975f0d2c5fSdholland }
2985f0d2c5fSdholland return file;
2995f0d2c5fSdholland }
3005f0d2c5fSdholland
3018d70e807Sdholland static uint64_t
dqblk_getlimit(uint32_t val)30284ed28bfSdholland dqblk_getlimit(uint32_t val)
3038d70e807Sdholland {
3048d70e807Sdholland if (val == 0) {
3058d70e807Sdholland return QUOTA_NOLIMIT;
3068d70e807Sdholland } else {
3078d70e807Sdholland return val - 1;
3088d70e807Sdholland }
3098d70e807Sdholland }
3108d70e807Sdholland
31184ed28bfSdholland static uint32_t
dqblk_setlimit(uint64_t val)31284ed28bfSdholland dqblk_setlimit(uint64_t val)
31384ed28bfSdholland {
31484ed28bfSdholland if (val == QUOTA_NOLIMIT && val >= 0xffffffffUL) {
31584ed28bfSdholland return 0;
31684ed28bfSdholland } else {
31784ed28bfSdholland return (uint32_t)val + 1;
31884ed28bfSdholland }
31984ed28bfSdholland }
32084ed28bfSdholland
3218d70e807Sdholland static void
dqblk_getblocks(const struct dqblk * dq,struct quotaval * qv)3228d70e807Sdholland dqblk_getblocks(const struct dqblk *dq, struct quotaval *qv)
3238d70e807Sdholland {
32484ed28bfSdholland qv->qv_hardlimit = dqblk_getlimit(dq->dqb_bhardlimit);
32584ed28bfSdholland qv->qv_softlimit = dqblk_getlimit(dq->dqb_bsoftlimit);
3268d70e807Sdholland qv->qv_usage = dq->dqb_curblocks;
3278d70e807Sdholland qv->qv_expiretime = dq->dqb_btime;
3288d70e807Sdholland qv->qv_grace = QUOTA_NOTIME;
3298d70e807Sdholland }
3308d70e807Sdholland
3318d70e807Sdholland static void
dqblk_getfiles(const struct dqblk * dq,struct quotaval * qv)3328d70e807Sdholland dqblk_getfiles(const struct dqblk *dq, struct quotaval *qv)
3338d70e807Sdholland {
33484ed28bfSdholland qv->qv_hardlimit = dqblk_getlimit(dq->dqb_ihardlimit);
33584ed28bfSdholland qv->qv_softlimit = dqblk_getlimit(dq->dqb_isoftlimit);
3368d70e807Sdholland qv->qv_usage = dq->dqb_curinodes;
3378d70e807Sdholland qv->qv_expiretime = dq->dqb_itime;
3388d70e807Sdholland qv->qv_grace = QUOTA_NOTIME;
3398d70e807Sdholland }
3408d70e807Sdholland
34184ed28bfSdholland static void
dqblk_putblocks(const struct quotaval * qv,struct dqblk * dq)34284ed28bfSdholland dqblk_putblocks(const struct quotaval *qv, struct dqblk *dq)
34384ed28bfSdholland {
34484ed28bfSdholland dq->dqb_bhardlimit = dqblk_setlimit(qv->qv_hardlimit);
34584ed28bfSdholland dq->dqb_bsoftlimit = dqblk_setlimit(qv->qv_softlimit);
34684ed28bfSdholland dq->dqb_curblocks = qv->qv_usage;
34784ed28bfSdholland dq->dqb_btime = qv->qv_expiretime;
34884ed28bfSdholland /* ignore qv->qv_grace */
34984ed28bfSdholland }
35084ed28bfSdholland
35184ed28bfSdholland static void
dqblk_putfiles(const struct quotaval * qv,struct dqblk * dq)35284ed28bfSdholland dqblk_putfiles(const struct quotaval *qv, struct dqblk *dq)
35384ed28bfSdholland {
35484ed28bfSdholland dq->dqb_ihardlimit = dqblk_setlimit(qv->qv_hardlimit);
35584ed28bfSdholland dq->dqb_isoftlimit = dqblk_setlimit(qv->qv_softlimit);
35684ed28bfSdholland dq->dqb_curinodes = qv->qv_usage;
35784ed28bfSdholland dq->dqb_itime = qv->qv_expiretime;
35884ed28bfSdholland /* ignore qv->qv_grace */
35984ed28bfSdholland }
36084ed28bfSdholland
3618d70e807Sdholland static int
__quota_oldfiles_open(struct quotahandle * qh,const char * path,int * fd_ret)3628d70e807Sdholland __quota_oldfiles_open(struct quotahandle *qh, const char *path, int *fd_ret)
3638d70e807Sdholland {
3648d70e807Sdholland int fd;
3658d70e807Sdholland
3668d70e807Sdholland fd = open(path, O_RDWR);
3678d70e807Sdholland if (fd < 0 && (errno == EACCES || errno == EROFS)) {
3688d70e807Sdholland fd = open(path, O_RDONLY);
3698d70e807Sdholland if (fd < 0) {
3708d70e807Sdholland return -1;
3718d70e807Sdholland }
3728d70e807Sdholland }
3738d70e807Sdholland *fd_ret = fd;
3748d70e807Sdholland return 0;
3758d70e807Sdholland }
3768d70e807Sdholland
3778d70e807Sdholland int
__quota_oldfiles_initialize(struct quotahandle * qh)3788d70e807Sdholland __quota_oldfiles_initialize(struct quotahandle *qh)
3798d70e807Sdholland {
380fa577c93Sdholland const struct oldfiles_fstabentry *ofe;
3818d70e807Sdholland char path[PATH_MAX];
3828d70e807Sdholland const char *userquotafile, *groupquotafile;
3838d70e807Sdholland
384fa577c93Sdholland if (qh->qh_oldfilesopen) {
3858d70e807Sdholland /* already initialized */
3868d70e807Sdholland return 0;
3878d70e807Sdholland }
3888d70e807Sdholland
3898d70e807Sdholland /*
3908d70e807Sdholland * Find the fstab entry.
3918d70e807Sdholland */
392fa577c93Sdholland ofe = __quota_oldfiles_find_fstabentry(qh->qh_mountpoint);
393fa577c93Sdholland if (ofe == NULL) {
3948d70e807Sdholland warnx("%s not found in fstab", qh->qh_mountpoint);
3958d70e807Sdholland errno = ENXIO;
3968d70e807Sdholland return -1;
3978d70e807Sdholland }
3988d70e807Sdholland
399fa577c93Sdholland if (!ofe->ofe_hasuserquota && !ofe->ofe_hasgroupquota) {
4008d70e807Sdholland errno = ENXIO;
4018d70e807Sdholland return -1;
4028d70e807Sdholland }
4038d70e807Sdholland
404fa577c93Sdholland if (ofe->ofe_hasuserquota) {
405fa577c93Sdholland userquotafile = ofe->ofe_userquotafile;
4068d70e807Sdholland if (userquotafile == NULL) {
4075f0d2c5fSdholland __quota_oldfiles_defquotafile(qh, USRQUOTA,
4085f0d2c5fSdholland path, sizeof(path));
4098d70e807Sdholland userquotafile = path;
4108d70e807Sdholland }
4118d70e807Sdholland if (__quota_oldfiles_open(qh, userquotafile,
4128d70e807Sdholland &qh->qh_userfile)) {
4138d70e807Sdholland return -1;
4148d70e807Sdholland }
4158d70e807Sdholland }
416fa577c93Sdholland if (ofe->ofe_hasgroupquota) {
417fa577c93Sdholland groupquotafile = ofe->ofe_groupquotafile;
4188d70e807Sdholland if (groupquotafile == NULL) {
4195f0d2c5fSdholland __quota_oldfiles_defquotafile(qh, GRPQUOTA,
4205f0d2c5fSdholland path, sizeof(path));
4218d70e807Sdholland groupquotafile = path;
4228d70e807Sdholland }
4238d70e807Sdholland if (__quota_oldfiles_open(qh, groupquotafile,
4248d70e807Sdholland &qh->qh_groupfile)) {
4258d70e807Sdholland return -1;
4268d70e807Sdholland }
4278d70e807Sdholland }
4288d70e807Sdholland
429fa577c93Sdholland qh->qh_oldfilesopen = 1;
4308d70e807Sdholland
4318d70e807Sdholland return 0;
4328d70e807Sdholland }
4338d70e807Sdholland
4348d70e807Sdholland const char *
__quota_oldfiles_getimplname(struct quotahandle * qh)4358d70e807Sdholland __quota_oldfiles_getimplname(struct quotahandle *qh)
4368d70e807Sdholland {
437fa577c93Sdholland return "ufs/ffs quota v1 file access";
4388d70e807Sdholland }
4398d70e807Sdholland
4405f0d2c5fSdholland int
__quota_oldfiles_quotaon(struct quotahandle * qh,int idtype)4415f0d2c5fSdholland __quota_oldfiles_quotaon(struct quotahandle *qh, int idtype)
4425f0d2c5fSdholland {
4435f0d2c5fSdholland int result;
4445f0d2c5fSdholland
4455f0d2c5fSdholland /*
4465f0d2c5fSdholland * If we have the quota files open, close them.
4475f0d2c5fSdholland */
4485f0d2c5fSdholland
4495f0d2c5fSdholland if (qh->qh_oldfilesopen) {
4505f0d2c5fSdholland if (qh->qh_userfile >= 0) {
4515f0d2c5fSdholland close(qh->qh_userfile);
4525f0d2c5fSdholland qh->qh_userfile = -1;
4535f0d2c5fSdholland }
4545f0d2c5fSdholland if (qh->qh_groupfile >= 0) {
4555f0d2c5fSdholland close(qh->qh_groupfile);
4565f0d2c5fSdholland qh->qh_groupfile = -1;
4575f0d2c5fSdholland }
4585f0d2c5fSdholland qh->qh_oldfilesopen = 0;
4595f0d2c5fSdholland }
4605f0d2c5fSdholland
4615f0d2c5fSdholland /*
4625f0d2c5fSdholland * Go over to the syscall interface.
4635f0d2c5fSdholland */
4645f0d2c5fSdholland
46559b296daSdholland result = __quota_kernel_quotaon(qh, idtype);
4665f0d2c5fSdholland if (result < 0) {
4675f0d2c5fSdholland return -1;
4685f0d2c5fSdholland }
4695f0d2c5fSdholland
4705f0d2c5fSdholland /*
4715f0d2c5fSdholland * We succeeded, so all further access should be via the
4725f0d2c5fSdholland * kernel.
4735f0d2c5fSdholland */
4745f0d2c5fSdholland
47559b296daSdholland qh->qh_mode = QUOTA_MODE_KERNEL;
4765f0d2c5fSdholland return 0;
4775f0d2c5fSdholland }
4785f0d2c5fSdholland
4798d70e807Sdholland static int
__quota_oldfiles_doget(struct quotahandle * qh,const struct quotakey * qk,struct quotaval * qv,int * isallzero)4808d70e807Sdholland __quota_oldfiles_doget(struct quotahandle *qh, const struct quotakey *qk,
4818d70e807Sdholland struct quotaval *qv, int *isallzero)
4828d70e807Sdholland {
4838d70e807Sdholland int file;
4848d70e807Sdholland off_t pos;
4858d70e807Sdholland struct dqblk dq;
4868d70e807Sdholland ssize_t result;
4878d70e807Sdholland
488fa577c93Sdholland if (!qh->qh_oldfilesopen) {
489fa577c93Sdholland if (__quota_oldfiles_initialize(qh)) {
490fa577c93Sdholland return -1;
491fa577c93Sdholland }
492fa577c93Sdholland }
493fa577c93Sdholland
4948d70e807Sdholland switch (qk->qk_idtype) {
4958d70e807Sdholland case QUOTA_IDTYPE_USER:
4968d70e807Sdholland file = qh->qh_userfile;
4978d70e807Sdholland break;
4988d70e807Sdholland case QUOTA_IDTYPE_GROUP:
4998d70e807Sdholland file = qh->qh_groupfile;
5008d70e807Sdholland break;
5018d70e807Sdholland default:
5028d70e807Sdholland errno = EINVAL;
5038d70e807Sdholland return -1;
5048d70e807Sdholland }
5058d70e807Sdholland
5068d70e807Sdholland if (qk->qk_id == QUOTA_DEFAULTID) {
5078d70e807Sdholland pos = 0;
5088d70e807Sdholland } else {
5098d70e807Sdholland pos = qk->qk_id * sizeof(struct dqblk);
5108d70e807Sdholland }
5118d70e807Sdholland
5128d70e807Sdholland result = pread(file, &dq, sizeof(dq), pos);
5138d70e807Sdholland if (result < 0) {
5148d70e807Sdholland return -1;
51584ed28bfSdholland } else if (result == 0) {
51684ed28bfSdholland /* Past EOF; no quota info on file for this ID */
51784ed28bfSdholland errno = ENOENT;
51884ed28bfSdholland return -1;
51984ed28bfSdholland } else if ((size_t)result != sizeof(dq)) {
5208d70e807Sdholland errno = EFTYPE;
5218d70e807Sdholland return -1;
5228d70e807Sdholland }
5238d70e807Sdholland
5248d70e807Sdholland switch (qk->qk_objtype) {
5258d70e807Sdholland case QUOTA_OBJTYPE_BLOCKS:
5268d70e807Sdholland dqblk_getblocks(&dq, qv);
5278d70e807Sdholland break;
5288d70e807Sdholland case QUOTA_OBJTYPE_FILES:
5298d70e807Sdholland dqblk_getfiles(&dq, qv);
5308d70e807Sdholland break;
5318d70e807Sdholland default:
5328d70e807Sdholland errno = EINVAL;
5338d70e807Sdholland return -1;
5348d70e807Sdholland }
5358d70e807Sdholland
5368d70e807Sdholland if (qk->qk_id == QUOTA_DEFAULTID) {
5378d70e807Sdholland qv->qv_usage = 0;
5388d70e807Sdholland qv->qv_grace = qv->qv_expiretime;
5398d70e807Sdholland qv->qv_expiretime = QUOTA_NOTIME;
5408d70e807Sdholland } else if (qk->qk_id == 0) {
5418d70e807Sdholland qv->qv_hardlimit = 0;
5428d70e807Sdholland qv->qv_softlimit = 0;
5438d70e807Sdholland qv->qv_expiretime = QUOTA_NOTIME;
5448d70e807Sdholland qv->qv_grace = QUOTA_NOTIME;
5458d70e807Sdholland }
5468d70e807Sdholland
5478d70e807Sdholland if (isallzero != NULL) {
5488d70e807Sdholland if (dq.dqb_bhardlimit == 0 &&
5498d70e807Sdholland dq.dqb_bsoftlimit == 0 &&
5508d70e807Sdholland dq.dqb_curblocks == 0 &&
5518d70e807Sdholland dq.dqb_ihardlimit == 0 &&
5528d70e807Sdholland dq.dqb_isoftlimit == 0 &&
5538d70e807Sdholland dq.dqb_curinodes == 0 &&
5548d70e807Sdholland dq.dqb_btime == 0 &&
5558d70e807Sdholland dq.dqb_itime == 0) {
5568d70e807Sdholland *isallzero = 1;
5578d70e807Sdholland } else {
5588d70e807Sdholland *isallzero = 0;
5598d70e807Sdholland }
5608d70e807Sdholland }
5618d70e807Sdholland
5628d70e807Sdholland return 0;
5638d70e807Sdholland }
5648d70e807Sdholland
56584ed28bfSdholland static int
__quota_oldfiles_doput(struct quotahandle * qh,const struct quotakey * qk,const struct quotaval * qv)56684ed28bfSdholland __quota_oldfiles_doput(struct quotahandle *qh, const struct quotakey *qk,
56784ed28bfSdholland const struct quotaval *qv)
56884ed28bfSdholland {
56984ed28bfSdholland int file;
57084ed28bfSdholland off_t pos;
57184ed28bfSdholland struct quotaval qv2;
57284ed28bfSdholland struct dqblk dq;
57384ed28bfSdholland ssize_t result;
57484ed28bfSdholland
575fa577c93Sdholland if (!qh->qh_oldfilesopen) {
576fa577c93Sdholland if (__quota_oldfiles_initialize(qh)) {
577fa577c93Sdholland return -1;
578fa577c93Sdholland }
579fa577c93Sdholland }
580fa577c93Sdholland
58184ed28bfSdholland switch (qk->qk_idtype) {
58284ed28bfSdholland case QUOTA_IDTYPE_USER:
58384ed28bfSdholland file = qh->qh_userfile;
58484ed28bfSdholland break;
58584ed28bfSdholland case QUOTA_IDTYPE_GROUP:
58684ed28bfSdholland file = qh->qh_groupfile;
58784ed28bfSdholland break;
58884ed28bfSdholland default:
58984ed28bfSdholland errno = EINVAL;
59084ed28bfSdholland return -1;
59184ed28bfSdholland }
59284ed28bfSdholland
59384ed28bfSdholland if (qk->qk_id == QUOTA_DEFAULTID) {
59484ed28bfSdholland pos = 0;
59584ed28bfSdholland } else {
59684ed28bfSdholland pos = qk->qk_id * sizeof(struct dqblk);
59784ed28bfSdholland }
59884ed28bfSdholland
59984ed28bfSdholland result = pread(file, &dq, sizeof(dq), pos);
60084ed28bfSdholland if (result < 0) {
60184ed28bfSdholland return -1;
60284ed28bfSdholland } else if (result == 0) {
60384ed28bfSdholland /* Past EOF; fill in a blank dq to start from */
60484ed28bfSdholland dq.dqb_bhardlimit = 0;
60584ed28bfSdholland dq.dqb_bsoftlimit = 0;
60684ed28bfSdholland dq.dqb_curblocks = 0;
60784ed28bfSdholland dq.dqb_ihardlimit = 0;
60884ed28bfSdholland dq.dqb_isoftlimit = 0;
60984ed28bfSdholland dq.dqb_curinodes = 0;
61084ed28bfSdholland dq.dqb_btime = 0;
61184ed28bfSdholland dq.dqb_itime = 0;
61284ed28bfSdholland } else if ((size_t)result != sizeof(dq)) {
61384ed28bfSdholland errno = EFTYPE;
61484ed28bfSdholland return -1;
61584ed28bfSdholland }
61684ed28bfSdholland
61784ed28bfSdholland switch (qk->qk_objtype) {
61884ed28bfSdholland case QUOTA_OBJTYPE_BLOCKS:
61984ed28bfSdholland dqblk_getblocks(&dq, &qv2);
62084ed28bfSdholland break;
62184ed28bfSdholland case QUOTA_OBJTYPE_FILES:
62284ed28bfSdholland dqblk_getfiles(&dq, &qv2);
62384ed28bfSdholland break;
62484ed28bfSdholland default:
62584ed28bfSdholland errno = EINVAL;
62684ed28bfSdholland return -1;
62784ed28bfSdholland }
62884ed28bfSdholland
62984ed28bfSdholland if (qk->qk_id == QUOTA_DEFAULTID) {
63084ed28bfSdholland qv2.qv_hardlimit = qv->qv_hardlimit;
63184ed28bfSdholland qv2.qv_softlimit = qv->qv_softlimit;
63284ed28bfSdholland /* leave qv2.qv_usage unchanged */
63384ed28bfSdholland qv2.qv_expiretime = qv->qv_grace;
63484ed28bfSdholland /* skip qv2.qv_grace */
63584ed28bfSdholland
63684ed28bfSdholland /* ignore qv->qv_usage */
63784ed28bfSdholland /* ignore qv->qv_expiretime */
63884ed28bfSdholland } else if (qk->qk_id == 0) {
63984ed28bfSdholland /* leave qv2.qv_hardlimit unchanged */
64084ed28bfSdholland /* leave qv2.qv_softlimit unchanged */
64184ed28bfSdholland qv2.qv_usage = qv->qv_usage;
64284ed28bfSdholland /* leave qv2.qv_expiretime unchanged */
64384ed28bfSdholland /* skip qv2.qv_grace */
64484ed28bfSdholland
64584ed28bfSdholland /* ignore qv->qv_hardlimit */
64684ed28bfSdholland /* ignore qv->qv_softlimit */
64784ed28bfSdholland /* ignore qv->qv_expiretime */
64884ed28bfSdholland /* ignore qv->qv_grace */
64984ed28bfSdholland } else {
65084ed28bfSdholland qv2 = *qv;
65184ed28bfSdholland }
65284ed28bfSdholland
65384ed28bfSdholland switch (qk->qk_objtype) {
65484ed28bfSdholland case QUOTA_OBJTYPE_BLOCKS:
65584ed28bfSdholland dqblk_putblocks(&qv2, &dq);
65684ed28bfSdholland break;
65784ed28bfSdholland case QUOTA_OBJTYPE_FILES:
65884ed28bfSdholland dqblk_putfiles(&qv2, &dq);
65984ed28bfSdholland break;
66084ed28bfSdholland default:
66184ed28bfSdholland errno = EINVAL;
66284ed28bfSdholland return -1;
66384ed28bfSdholland }
66484ed28bfSdholland
66584ed28bfSdholland result = pwrite(file, &dq, sizeof(dq), pos);
66684ed28bfSdholland if (result < 0) {
66784ed28bfSdholland return -1;
66884ed28bfSdholland } else if ((size_t)result != sizeof(dq)) {
66984ed28bfSdholland /* ? */
67084ed28bfSdholland errno = EFTYPE;
67184ed28bfSdholland return -1;
67284ed28bfSdholland }
67384ed28bfSdholland
67484ed28bfSdholland return 0;
67584ed28bfSdholland }
67684ed28bfSdholland
6778d70e807Sdholland int
__quota_oldfiles_get(struct quotahandle * qh,const struct quotakey * qk,struct quotaval * qv)6788d70e807Sdholland __quota_oldfiles_get(struct quotahandle *qh, const struct quotakey *qk,
6798d70e807Sdholland struct quotaval *qv)
6808d70e807Sdholland {
6818d70e807Sdholland return __quota_oldfiles_doget(qh, qk, qv, NULL);
6828d70e807Sdholland }
6838d70e807Sdholland
68484ed28bfSdholland int
__quota_oldfiles_put(struct quotahandle * qh,const struct quotakey * qk,const struct quotaval * qv)68584ed28bfSdholland __quota_oldfiles_put(struct quotahandle *qh, const struct quotakey *qk,
68684ed28bfSdholland const struct quotaval *qv)
68784ed28bfSdholland {
68884ed28bfSdholland return __quota_oldfiles_doput(qh, qk, qv);
68984ed28bfSdholland }
69084ed28bfSdholland
69184ed28bfSdholland int
__quota_oldfiles_delete(struct quotahandle * qh,const struct quotakey * qk)69284ed28bfSdholland __quota_oldfiles_delete(struct quotahandle *qh, const struct quotakey *qk)
69384ed28bfSdholland {
69484ed28bfSdholland struct quotaval qv;
69584ed28bfSdholland
69684ed28bfSdholland quotaval_clear(&qv);
69784ed28bfSdholland return __quota_oldfiles_doput(qh, qk, &qv);
69884ed28bfSdholland }
69984ed28bfSdholland
7008d70e807Sdholland struct oldfiles_quotacursor *
__quota_oldfiles_cursor_create(struct quotahandle * qh)7018d70e807Sdholland __quota_oldfiles_cursor_create(struct quotahandle *qh)
7028d70e807Sdholland {
7038d70e807Sdholland struct oldfiles_quotacursor *oqc;
7048d70e807Sdholland struct stat st;
7058d70e807Sdholland int serrno;
7068d70e807Sdholland
707fa577c93Sdholland /* quota_opencursor calls initialize for us, no need to do it here */
708fa577c93Sdholland
7098d70e807Sdholland oqc = malloc(sizeof(*oqc));
7108d70e807Sdholland if (oqc == NULL) {
7118d70e807Sdholland return NULL;
7128d70e807Sdholland }
7138d70e807Sdholland
7148d70e807Sdholland oqc->oqc_didusers = 0;
7158d70e807Sdholland oqc->oqc_didgroups = 0;
7168d70e807Sdholland oqc->oqc_diddefault = 0;
7178d70e807Sdholland oqc->oqc_pos = 0;
7188d70e807Sdholland oqc->oqc_didblocks = 0;
7198d70e807Sdholland
7208d70e807Sdholland if (qh->qh_userfile >= 0) {
7218d70e807Sdholland oqc->oqc_doingusers = 1;
7228d70e807Sdholland } else {
7238d70e807Sdholland oqc->oqc_doingusers = 0;
7248d70e807Sdholland oqc->oqc_didusers = 1;
7258d70e807Sdholland }
7268d70e807Sdholland
7278d70e807Sdholland if (qh->qh_groupfile >= 0) {
7288d70e807Sdholland oqc->oqc_doinggroups = 1;
7298d70e807Sdholland } else {
7308d70e807Sdholland oqc->oqc_doinggroups = 0;
7318d70e807Sdholland oqc->oqc_didgroups = 1;
7328d70e807Sdholland }
7338d70e807Sdholland
7348d70e807Sdholland if (fstat(qh->qh_userfile, &st) < 0) {
7358d70e807Sdholland serrno = errno;
7368d70e807Sdholland free(oqc);
7378d70e807Sdholland errno = serrno;
7388d70e807Sdholland return NULL;
7398d70e807Sdholland }
7408d70e807Sdholland oqc->oqc_numusers = st.st_size / sizeof(struct dqblk);
7418d70e807Sdholland
7428d70e807Sdholland if (fstat(qh->qh_groupfile, &st) < 0) {
7438d70e807Sdholland serrno = errno;
7448d70e807Sdholland free(oqc);
7458d70e807Sdholland errno = serrno;
7468d70e807Sdholland return NULL;
7478d70e807Sdholland }
7488d70e807Sdholland oqc->oqc_numgroups = st.st_size / sizeof(struct dqblk);
7498d70e807Sdholland
7508d70e807Sdholland return oqc;
7518d70e807Sdholland }
7528d70e807Sdholland
7538d70e807Sdholland void
__quota_oldfiles_cursor_destroy(struct oldfiles_quotacursor * oqc)7548d70e807Sdholland __quota_oldfiles_cursor_destroy(struct oldfiles_quotacursor *oqc)
7558d70e807Sdholland {
7568d70e807Sdholland free(oqc);
7578d70e807Sdholland }
7588d70e807Sdholland
7598d70e807Sdholland int
__quota_oldfiles_cursor_skipidtype(struct oldfiles_quotacursor * oqc,int idtype)7608d70e807Sdholland __quota_oldfiles_cursor_skipidtype(struct oldfiles_quotacursor *oqc,
761832d4ca7Sdholland int idtype)
7628d70e807Sdholland {
7638d70e807Sdholland switch (idtype) {
7648d70e807Sdholland case QUOTA_IDTYPE_USER:
7658d70e807Sdholland oqc->oqc_doingusers = 0;
7668d70e807Sdholland oqc->oqc_didusers = 1;
7678d70e807Sdholland break;
7688d70e807Sdholland case QUOTA_IDTYPE_GROUP:
7698d70e807Sdholland oqc->oqc_doinggroups = 0;
7708d70e807Sdholland oqc->oqc_didgroups = 1;
7718d70e807Sdholland break;
7728d70e807Sdholland default:
7738d70e807Sdholland errno = EINVAL;
7748d70e807Sdholland return -1;
7758d70e807Sdholland }
7768d70e807Sdholland return 0;
7778d70e807Sdholland }
7788d70e807Sdholland
7798d70e807Sdholland int
__quota_oldfiles_cursor_get(struct quotahandle * qh,struct oldfiles_quotacursor * oqc,struct quotakey * key,struct quotaval * val)7808d70e807Sdholland __quota_oldfiles_cursor_get(struct quotahandle *qh,
7818d70e807Sdholland struct oldfiles_quotacursor *oqc,
7828d70e807Sdholland struct quotakey *key, struct quotaval *val)
7838d70e807Sdholland {
7848d70e807Sdholland unsigned maxpos;
7858d70e807Sdholland int isallzero;
7868d70e807Sdholland
7878d70e807Sdholland /* in case one of the sizes is zero */
7888d70e807Sdholland if (!oqc->oqc_didusers && oqc->oqc_pos >= oqc->oqc_numusers) {
7898d70e807Sdholland oqc->oqc_didusers = 1;
7908d70e807Sdholland }
7918d70e807Sdholland if (!oqc->oqc_didgroups && oqc->oqc_pos >= oqc->oqc_numgroups) {
7928d70e807Sdholland oqc->oqc_didgroups = 1;
7938d70e807Sdholland }
7948d70e807Sdholland
7958d70e807Sdholland again:
7968d70e807Sdholland /*
7978d70e807Sdholland * Figure out what to get
7988d70e807Sdholland */
7998d70e807Sdholland
8008d70e807Sdholland if (!oqc->oqc_didusers) {
8018d70e807Sdholland key->qk_idtype = QUOTA_IDTYPE_USER;
8028d70e807Sdholland maxpos = oqc->oqc_numusers;
8038d70e807Sdholland } else if (!oqc->oqc_didgroups) {
8048d70e807Sdholland key->qk_idtype = QUOTA_IDTYPE_GROUP;
8058d70e807Sdholland maxpos = oqc->oqc_numgroups;
8068d70e807Sdholland } else {
8078d70e807Sdholland errno = ENOENT;
8088d70e807Sdholland return -1;
8098d70e807Sdholland }
8108d70e807Sdholland
8118d70e807Sdholland if (!oqc->oqc_diddefault) {
8128d70e807Sdholland key->qk_id = QUOTA_DEFAULTID;
8138d70e807Sdholland } else {
8148d70e807Sdholland key->qk_id = oqc->oqc_pos;
8158d70e807Sdholland }
8168d70e807Sdholland
8178d70e807Sdholland if (!oqc->oqc_didblocks) {
8188d70e807Sdholland key->qk_objtype = QUOTA_OBJTYPE_BLOCKS;
8198d70e807Sdholland } else {
8208d70e807Sdholland key->qk_objtype = QUOTA_OBJTYPE_FILES;
8218d70e807Sdholland }
8228d70e807Sdholland
8238d70e807Sdholland /*
8248d70e807Sdholland * Get it
8258d70e807Sdholland */
8268d70e807Sdholland
8278d70e807Sdholland if (__quota_oldfiles_doget(qh, key, val, &isallzero)) {
8288d70e807Sdholland return -1;
8298d70e807Sdholland }
8308d70e807Sdholland
8318d70e807Sdholland /*
8328d70e807Sdholland * Advance the cursor
8338d70e807Sdholland */
8348d70e807Sdholland if (!oqc->oqc_didblocks) {
8358d70e807Sdholland oqc->oqc_didblocks = 1;
8368d70e807Sdholland } else {
8378d70e807Sdholland oqc->oqc_didblocks = 0;
8388d70e807Sdholland if (!oqc->oqc_diddefault) {
8398d70e807Sdholland oqc->oqc_diddefault = 1;
8408d70e807Sdholland } else {
8418d70e807Sdholland oqc->oqc_pos++;
8428d70e807Sdholland if (oqc->oqc_pos >= maxpos) {
8438d70e807Sdholland oqc->oqc_pos = 0;
8448d70e807Sdholland oqc->oqc_diddefault = 0;
8458d70e807Sdholland if (!oqc->oqc_didusers) {
8468d70e807Sdholland oqc->oqc_didusers = 1;
8478d70e807Sdholland } else {
8488d70e807Sdholland oqc->oqc_didgroups = 1;
8498d70e807Sdholland }
8508d70e807Sdholland }
8518d70e807Sdholland }
8528d70e807Sdholland }
8538d70e807Sdholland
8548d70e807Sdholland /*
8558d70e807Sdholland * If we got an all-zero dqblk (e.g. from the middle of a hole
8568d70e807Sdholland * in the quota file) don't bother returning it to the caller.
8578d70e807Sdholland *
8588d70e807Sdholland * ...unless we're at the end of the data, to avoid going past
8598d70e807Sdholland * the end and generating a spurious failure. There's no
8608d70e807Sdholland * reasonable way to make _atend detect empty entries at the
8618d70e807Sdholland * end of the quota files.
8628d70e807Sdholland */
8638d70e807Sdholland if (isallzero && (!oqc->oqc_didusers || !oqc->oqc_didgroups)) {
8648d70e807Sdholland goto again;
8658d70e807Sdholland }
8668d70e807Sdholland return 0;
8678d70e807Sdholland }
8688d70e807Sdholland
8698d70e807Sdholland int
__quota_oldfiles_cursor_getn(struct quotahandle * qh,struct oldfiles_quotacursor * oqc,struct quotakey * keys,struct quotaval * vals,unsigned maxnum)8708d70e807Sdholland __quota_oldfiles_cursor_getn(struct quotahandle *qh,
8718d70e807Sdholland struct oldfiles_quotacursor *oqc,
8728d70e807Sdholland struct quotakey *keys, struct quotaval *vals,
8738d70e807Sdholland unsigned maxnum)
8748d70e807Sdholland {
8758d70e807Sdholland unsigned i;
8768d70e807Sdholland
8778d70e807Sdholland if (maxnum > INT_MAX) {
8788d70e807Sdholland /* joker, eh? */
8798d70e807Sdholland errno = EINVAL;
8808d70e807Sdholland return -1;
8818d70e807Sdholland }
8828d70e807Sdholland
8838d70e807Sdholland for (i=0; i<maxnum; i++) {
8848d70e807Sdholland if (__quota_oldfiles_cursor_atend(oqc)) {
8858d70e807Sdholland break;
8868d70e807Sdholland }
8878d70e807Sdholland if (__quota_oldfiles_cursor_get(qh, oqc, &keys[i], &vals[i])) {
8888d70e807Sdholland if (i > 0) {
8898d70e807Sdholland /*
8908d70e807Sdholland * Succeed witih what we have so far;
8918d70e807Sdholland * the next attempt will hit the same
8928d70e807Sdholland * error again.
8938d70e807Sdholland */
8948d70e807Sdholland break;
8958d70e807Sdholland }
8968d70e807Sdholland return -1;
8978d70e807Sdholland }
8988d70e807Sdholland }
8998d70e807Sdholland return i;
9008d70e807Sdholland
9018d70e807Sdholland }
9028d70e807Sdholland
9038d70e807Sdholland int
__quota_oldfiles_cursor_atend(struct oldfiles_quotacursor * oqc)9048d70e807Sdholland __quota_oldfiles_cursor_atend(struct oldfiles_quotacursor *oqc)
9058d70e807Sdholland {
9068d70e807Sdholland /* in case one of the sizes is zero */
9078d70e807Sdholland if (!oqc->oqc_didusers && oqc->oqc_pos >= oqc->oqc_numusers) {
9088d70e807Sdholland oqc->oqc_didusers = 1;
9098d70e807Sdholland }
9108d70e807Sdholland if (!oqc->oqc_didgroups && oqc->oqc_pos >= oqc->oqc_numgroups) {
9118d70e807Sdholland oqc->oqc_didgroups = 1;
9128d70e807Sdholland }
9138d70e807Sdholland
9148d70e807Sdholland return oqc->oqc_didusers && oqc->oqc_didgroups;
9158d70e807Sdholland }
9168d70e807Sdholland
9178d70e807Sdholland int
__quota_oldfiles_cursor_rewind(struct oldfiles_quotacursor * oqc)9188d70e807Sdholland __quota_oldfiles_cursor_rewind(struct oldfiles_quotacursor *oqc)
9198d70e807Sdholland {
9208d70e807Sdholland oqc->oqc_didusers = 0;
9218d70e807Sdholland oqc->oqc_didgroups = 0;
9228d70e807Sdholland oqc->oqc_diddefault = 0;
9238d70e807Sdholland oqc->oqc_pos = 0;
9248d70e807Sdholland oqc->oqc_didblocks = 0;
9258d70e807Sdholland return 0;
9268d70e807Sdholland }
927