summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjkar8572 <jkar8572>2001-08-15 20:13:42 +0000
committerjkar8572 <jkar8572>2001-08-15 20:13:42 +0000
commit59157c4442d31775624ad5b8b0bd3e0e3548b624 (patch)
treebb6267b7fe46ef8f5da69c11827e9cfd69e612e1
parent805ee8ff8b05468a2f2ce09db619bded1d6a687d (diff)
downloadlinuxquota-59157c4442d31775624ad5b8b0bd3e0e3548b624.tar.gz
Fixed a few error messages.
Implemented new mountpoint scanning. Implemented caching for scanning in old quota format. Implemented automatic choice of appropriate units in repquota, quota.
-rw-r--r--common.c41
-rw-r--r--common.h9
-rw-r--r--convertquota.c40
-rw-r--r--edquota.c4
-rw-r--r--quot.c48
-rw-r--r--quota.113
-rw-r--r--quota.c35
-rw-r--r--quotacheck.c119
-rw-r--r--quotaio.c9
-rw-r--r--quotaio_v1.c33
-rw-r--r--quotaio_v1.h2
-rw-r--r--quotaon.c40
-rw-r--r--quotaon_xfs.c2
-rw-r--r--quotasys.c337
-rw-r--r--quotasys.h19
-rw-r--r--repquota.88
-rw-r--r--repquota.c32
-rw-r--r--rquota_client.c5
-rw-r--r--rquota_server.c62
-rw-r--r--rquota_svc.c20
-rw-r--r--setquota.c2
21 files changed, 542 insertions, 338 deletions
diff --git a/common.c b/common.c
index 91db878..576adb2 100644
--- a/common.c
+++ b/common.c
@@ -42,7 +42,18 @@ void *smalloc(size_t size)
void *ret = malloc(size);
if (!ret) {
- puts("Not enough memory.\n");
+ fputs("Not enough memory.\n", stderr);
+ exit(3);
+ }
+ return ret;
+}
+
+void *srealloc(void *ptr, size_t size)
+{
+ void *ret = realloc(ptr, size);
+
+ if (!ret) {
+ fputs("Not enough memory.\n", stderr);
exit(3);
}
return ret;
@@ -71,34 +82,6 @@ char *sstrdup(const char *s)
return r;
}
-int devcmp(const char *mtab_dev, char *user_dev)
-{
- struct stat mtab_stat, user_stat;
-
- if (stat(mtab_dev, &mtab_stat) < 0 || stat(user_dev, &user_stat) < 0)
- return (strcmp(mtab_dev, user_dev) == 0);
- if (!S_ISBLK(mtab_stat.st_mode) || !S_ISBLK(user_stat.st_mode))
- return 0;
- if (mtab_stat.st_rdev != user_stat.st_rdev)
- return 0;
- return 1;
-}
-
-int dircmp(char *mtab_dir, char *user_dir)
-{
- struct stat mtab_stat, user_stat;
-
- if (stat(mtab_dir, &mtab_stat) < 0 || stat(user_dir, &user_stat) < 0)
- return (strcmp(mtab_dir, user_dir) == 0);
- if (!S_ISDIR(mtab_stat.st_mode) || !S_ISDIR(user_stat.st_mode))
- return 0;
- if (mtab_stat.st_dev != user_stat.st_dev)
- return 0;
- if (mtab_stat.st_ino != user_stat.st_ino)
- return 0;
- return 1;
-}
-
void version(void)
{
printf(_("Quota utilities version %s.\n"), QUOTA_VERSION);
diff --git a/common.h b/common.h
index 175d038..bd196cb 100644
--- a/common.h
+++ b/common.h
@@ -21,6 +21,9 @@ void errstr(char *, ...);
/* malloc() with error check */
void *smalloc(size_t);
+/* realloc() with error check */
+void *srealloc(void *, size_t);
+
/* Safe strncpy - always finishes string */
void sstrncpy(char *, const char *, int);
@@ -30,12 +33,6 @@ void sstrncat(char *, const char *, int);
/* Safe version of strdup() */
char *sstrdup(const char *s);
-/* Test whether two file names are for the same device */
-int devcmp(const char *mtab_dev, char *user_dev);
-
-/* Test whether two file names are for the same directory */
-int dircmp(char *mtab_dir, char *user_dir);
-
/* Print version string */
void version(void);
diff --git a/convertquota.c b/convertquota.c
index bb7ac07..ceaf6e7 100644
--- a/convertquota.c
+++ b/convertquota.c
@@ -95,35 +95,19 @@ int convert_dquot(struct dquot *dquot, char *name)
return 0;
}
-void convert_file(int type)
+void convert_file(int type, struct mntent *mnt)
{
struct quota_handle *qo;
char *qfname, namebuf[PATH_MAX];
- FILE *mntf;
- struct mntent *mnt;
- const char *dev;
-
- if (!(mntf = setmntent(MOUNTED, "r")))
- die(2, _("Can't open %s: %s\n"), MOUNTED, strerror(errno));
- while ((mnt = getmntent(mntf))) {
- if (!(dev = get_device_name(mnt->mnt_fsname)))
- continue;
- if (devcmp(dev, mntpoint) || dircmp(mnt->mnt_dir, mntpoint)) {
- free((void *)dev);
- break;
- }
- free((void *)dev);
- }
- if (!mnt)
- die(1, _("Can't find given mountpoint %s\n"), mntpoint);
+
if (!(qo = init_io(mnt, type, QF_VFSOLD, 1))) {
errstr(_("Can't open old format file for %ss on %s\n"),
- type2name(type), mntpoint);
+ type2name(type), mnt->mnt_dir);
return;
}
if (!(qn = new_io(mnt, type, QF_VFSV0))) {
errstr(_("Can't create file for %ss for new format on %s: %s\n"),
- type2name(type), mntpoint, strerror(errno));
+ type2name(type), mnt->mnt_dir, strerror(errno));
end_io(qo);
return;
}
@@ -136,23 +120,29 @@ void convert_file(int type)
namebuf, qfname, strerror(errno));
free(qfname);
}
- endmntent(mntf);
end_io(qo);
end_io(qn);
}
int main(int argc, char **argv)
{
+ struct mntent *mnt;
+
gettexton();
progname = basename(argv[0]);
parse_options(argc, argv);
-
+ if (init_mounts_scan(1, &mntpoint) < 0)
+ return 1;
+ if (!(mnt = get_next_mount())) {
+ end_mounts_scan();
+ return 1;
+ }
if (ucv)
- convert_file(USRQUOTA);
-
+ convert_file(USRQUOTA, mnt);
if (gcv)
- convert_file(GRPQUOTA);
+ convert_file(GRPQUOTA, mnt);
+ end_mounts_scan();
return 0;
}
diff --git a/edquota.c b/edquota.c
index 749b1d0..cd7f5b6 100644
--- a/edquota.c
+++ b/edquota.c
@@ -34,7 +34,7 @@
#ident "$Copyright: (c) 1980, 1990 Regents of the University of California. $"
#ident "$Copyright: All rights reserved. $"
-#ident "$Id: edquota.c,v 1.5 2001/07/16 03:24:49 jkar8572 Exp $"
+#ident "$Id: edquota.c,v 1.6 2001/08/15 20:13:42 jkar8572 Exp $"
/*
* Disk quota editor.
@@ -73,7 +73,7 @@ void usage(void)
_("\tedquota -g [-F formatname] [-p groupname] groupname ...\n"),
_("\tedquota [-u] [-F formatname] -t\n"), _("\tedquota -g [-F formatname] -t\n"));
#endif
- errstr(_("Bugs to: %s\n"), MY_EMAIL);
+ fprintf(stderr, _("Bugs to: %s\n"), MY_EMAIL);
exit(1);
}
diff --git a/quot.c b/quot.c
index e8291d5..6738e45 100644
--- a/quot.c
+++ b/quot.c
@@ -55,6 +55,7 @@
#include "common.h"
#include "mntopt.h"
#include "bylabel.h"
+#include "quotasys.h"
#define TSIZE 500
__uint64_t sizes[TSIZE];
@@ -69,7 +70,7 @@ static int vflag;
static time_t now;
char *progname;
-static void mounttable(char *);
+static void mounttable(void);
static char *idname(__uint32_t, int);
static void report(const char *, char *, int);
static void creport(const char *, char *);
@@ -118,55 +119,32 @@ int main(int argc, char **argv)
usage();
if (!uflag && !gflag)
uflag++;
- if (aflag)
- mounttable(NULL);
- else {
- while (optind < argc)
- mounttable(argv[optind++]);
- }
+ if (init_mounts_scan(aflag ? 0 : argc - optind, argv + optind) < 0)
+ return 1;
+ mounttable();
+ end_mounts_scan();
return 0;
}
-static void mounttable(char *entry)
+static void mounttable(void)
{
+ int doit = 0;
struct mntent *mntp;
- const char *dev;
- FILE *mtab;
- int doit;
-
- if ((mtab = setmntent(MOUNTED, "r")) == NULL) {
- errstr(_("no " MOUNTED " file\n"));
- exit(1);
- }
- while ((mntp = getmntent(mtab)) != NULL) {
- doit = 0;
- dev = get_device_name(mntp->mnt_fsname);
- if (entry && !dircmp(mntp->mnt_dir, entry) && !devcmp(dev, entry)) {
- free((char *)dev);
- continue;
- }
+ while ((mntp = get_next_mount())) {
/* Currently, only XFS is implemented... */
if (strcmp(mntp->mnt_type, MNTTYPE_XFS) == 0) {
- checkXFS(dev, mntp->mnt_dir);
+ checkXFS(mntp->mnt_fsname, mntp->mnt_dir);
doit = 1;
}
/* ...additional filesystems types here. */
if (doit) {
- if (cflag) creport(dev, mntp->mnt_dir);
- if (!cflag && uflag) report(dev, mntp->mnt_dir, 0);
- if (!cflag && gflag) report(dev, mntp->mnt_dir, 1);
- }
- free((char *)dev);
- if (entry != NULL) {
- entry = NULL; /* found, bail out */
- break;
+ if (cflag) creport(mntp->mnt_fsname, mntp->mnt_dir);
+ if (!cflag && uflag) report(mntp->mnt_fsname, mntp->mnt_dir, 0);
+ if (!cflag && gflag) report(mntp->mnt_fsname, mntp->mnt_dir, 1);
}
}
- if (entry != NULL)
- errstr(_("cannot locate block device for %s\n"), entry);
- endmntent(mtab);
}
static int qcmp(du_t * p1, du_t * p2)
diff --git a/quota.1 b/quota.1
index 8cf75b8..9f14523 100644
--- a/quota.1
+++ b/quota.1
@@ -6,21 +6,21 @@ quota [
.B -F
.I format-name
] [
-.B -guv | q
+.B -guvs | q
]
.br
quota [
.B -F
.I format-name
] [
-.B -uv | q
+.B -uvs | q
] user
.br
quota [
.B -F
.I format-name
] [
-.B -gv | q
+.B -gvs | q
] group
.SH DESCRIPTION
.B Quota
@@ -58,7 +58,12 @@ flag is equivalent to the default.
will display quotas on filesystems
where no storage is allocated.
.TP
-.B -q
+.B \-s
+flag will make
+.BR quota(1)
+try to choose units for showing limits, used space and used inodes.
+.TP
+.B \-q
Print a more terse message,
containing only information
on filesystems where usage is over quota.
diff --git a/quota.c b/quota.c
index 8fcbb71..317e28c 100644
--- a/quota.c
+++ b/quota.c
@@ -34,7 +34,7 @@
#ident "$Copyright: (c) 1980, 1990 Regents of the University of California. $"
#ident "$Copyright: All rights reserved. $"
-#ident "$Id: quota.c,v 1.6 2001/07/17 21:10:57 jkar8572 Exp $"
+#ident "$Id: quota.c,v 1.7 2001/08/15 20:13:42 jkar8572 Exp $"
/*
* Disk quota reporting program.
@@ -60,7 +60,7 @@
#include "pot.h"
#include "common.h"
-int qflag, vflag, fmt = -1;
+int qflag, vflag, sflag, fmt = -1;
char *progname;
void usage(void);
@@ -76,7 +76,7 @@ int main(int argc, char **argv)
gettexton();
progname = basename(argv[0]);
- while ((ret = getopt(argc, argv, "guqvVF:")) != -1) {
+ while ((ret = getopt(argc, argv, "guqvsVF:")) != -1) {
switch (ret) {
case 'g':
gflag++;
@@ -94,6 +94,9 @@ int main(int argc, char **argv)
if ((fmt = name2fmt(optarg)) == QF_ERROR) /* Error? */
exit(1);
break;
+ case 's':
+ sflag++;
+ break;
case 'V':
version();
exit(0);
@@ -137,10 +140,10 @@ int main(int argc, char **argv)
void usage(void)
{
errstr( "%s%s%s",
- _("Usage: quota [-guqv] [-F quotaformat]\n"),
- _("\tquota [-qv] [-F quotaformat] -u username ...\n"),
- _("\tquota [-qv] [-F quotaformat] -g groupname ...\n"));
- errstr(_("Bugs to: %s\n"), MY_EMAIL);
+ _("Usage: quota [-guqvs] [-F quotaformat]\n"),
+ _("\tquota [-qvs] [-F quotaformat] -u username ...\n"),
+ _("\tquota [-qvs] [-F quotaformat] -g groupname ...\n"));
+ fprintf(stderr, _("Bugs to: %s\n"), MY_EMAIL);
exit(1);
}
@@ -197,6 +200,8 @@ int showquotas(int type, qid_t id)
continue;
}
if (vflag || q->dq_dqb.dqb_curspace || q->dq_dqb.dqb_curinodes) {
+ char numbuf[3][MAXNUMLEN];
+
if (!lines++)
heading(type, id, name, "");
if (strlen(q->dq_h->qh_quotadev) > 15)
@@ -205,14 +210,18 @@ int showquotas(int type, qid_t id)
printf("%15s", q->dq_h->qh_quotadev);
if (msgb)
difftime2str(q->dq_dqb.dqb_btime, timebuf);
- printf(" %7Lu%c %6Lu %7Lu %7s", (long long)toqb(q->dq_dqb.dqb_curspace),
- msgb ? '*' : ' ', (long long)q->dq_dqb.dqb_bsoftlimit,
- (long long)q->dq_dqb.dqb_bhardlimit, msgb ? timebuf : "");
+ space2str(toqb(q->dq_dqb.dqb_curspace), numbuf[0], sflag);
+ space2str(q->dq_dqb.dqb_bsoftlimit, numbuf[1], sflag);
+ space2str(q->dq_dqb.dqb_bhardlimit, numbuf[2], sflag);
+ printf(" %7s%c %6s %7s %7s", numbuf[0], msgb ? '*' : ' ', numbuf[1],
+ numbuf[2], msgb ? timebuf : "");
if (msgi)
difftime2str(q->dq_dqb.dqb_itime, timebuf);
- printf(" %7Lu%c %6Lu %7Lu %7s\n", (long long)q->dq_dqb.dqb_curinodes,
- msgi ? '*' : ' ', (long long)q->dq_dqb.dqb_isoftlimit,
- (long long)q->dq_dqb.dqb_ihardlimit, msgi ? timebuf : "");
+ number2str(q->dq_dqb.dqb_curinodes, numbuf[0], sflag);
+ number2str(q->dq_dqb.dqb_isoftlimit, numbuf[1], sflag);
+ number2str(q->dq_dqb.dqb_ihardlimit, numbuf[2], sflag);
+ printf(" %7s%c %6s %7s %7s\n", numbuf[0], msgi ? '*' : ' ', numbuf[1],
+ numbuf[2], msgi ? timebuf : "");
continue;
}
}
diff --git a/quotacheck.c b/quotacheck.c
index 1ea81b9..f0a2fce 100644
--- a/quotacheck.c
+++ b/quotacheck.c
@@ -8,7 +8,7 @@
* New quota format implementation - Jan Kara <jack@suse.cz> - Sponsored by SuSE CR
*/
-#ident "$Id: quotacheck.c,v 1.15 2001/08/10 11:23:14 jkar8572 Exp $"
+#ident "$Id: quotacheck.c,v 1.16 2001/08/15 20:13:42 jkar8572 Exp $"
#include <dirent.h>
#include <stdio.h>
@@ -534,7 +534,7 @@ int ask_yn(char *q, int def)
}
/* Do checks and buffer quota file into memory */
-static int process_file(char *mnt_fsname, struct mntent *mnt, int type)
+static int process_file(struct mntent *mnt, int type)
{
char *qfname = NULL;
int fd = -1, ret;
@@ -542,7 +542,7 @@ static int process_file(char *mnt_fsname, struct mntent *mnt, int type)
debug(FL_DEBUG | FL_VERBOSE, _("Going to check %s quota file of %s\n"), type2name(type),
mnt->mnt_dir);
- if (kern_quota_on(mnt_fsname, type, (1 << cfmt)) > 0) { /* Is quota enabled? */
+ if (kern_quota_on(mnt->mnt_fsname, type, (1 << cfmt)) > 0) { /* Is quota enabled? */
if (!(flags & FL_FORCE)) {
if (flags & FL_INTERACTIVE) {
printf(_("Quota for %ss is enabled on mountpoint %s so quotacheck might damage the file.\n"), type2name(type), mnt->mnt_dir);
@@ -557,15 +557,14 @@ Please turn quotas off or use -f to force checking.\n"),
type2name(type), mnt->mnt_dir);
}
/* At least sync quotas so damage will be smaller */
- if (quotactl(QCMD(Q_SYNC, type), mnt_fsname, 0, NULL) < 0)
- die(4, _("Error while syncing quotas on %s: %s\n"), mnt_fsname, strerror(errno));
+ if (quotactl(QCMD(Q_SYNC, type), mnt->mnt_fsname, 0, NULL) < 0)
+ die(4, _("Error while syncing quotas on %s: %s\n"), mnt->mnt_fsname, strerror(errno));
}
if (!(flags & FL_NEWFILE)) { /* Need to really buffer file? */
qfname = get_qf_name(mnt, type, cfmt);
if (!qfname) {
- errstr(_("Cannot get quotafile name for %s\n"),
- mnt_fsname);
+ errstr(_("Cannot get quotafile name for %s\n"), mnt->mnt_fsname);
return -1;
}
if ((fd = open(qfname, O_RDONLY)) < 0) {
@@ -580,8 +579,7 @@ Please turn quotas off or use -f to force checking.\n"),
memset(old_info + type, 0, sizeof(old_info[type]));
switch (cfmt) {
case QF_TOONEW:
- errstr(_("Too new quotafile format on %s\n"),
- mnt_fsname);
+ errstr(_("Too new quotafile format on %s\n"), mnt->mnt_fsname);
ret = -1;
break;
case QF_VFSOLD:
@@ -656,7 +654,7 @@ static int rename_files(struct mntent *mnt, int type)
* quota file. As quotafiles doesn't account to quotas we don't have to
* bother about accounting new blocks for quota file
*/
-static int dump_to_file(char *mnt_fsname, struct mntent *mnt, int type)
+static int dump_to_file(struct mntent *mnt, int type)
{
struct dquot *dquot;
uint i;
@@ -687,21 +685,21 @@ static int dump_to_file(char *mnt_fsname, struct mntent *mnt, int type)
}
if (rename_files(mnt, type) < 0)
return -1;
- if (cfmt == kern_quota_on(mnt_fsname, type, 1 << cfmt)) { /* Quota turned on? */
+ if (cfmt == kern_quota_on(mnt->mnt_fsname, type, 1 << cfmt)) { /* Quota turned on? */
char *filename;
filename = get_qf_name(mnt, type, cfmt);
- if (quotactl(QCMD(Q_QUOTAOFF, type), mnt_fsname, 0, NULL)
- || quotactl(QCMD(Q_QUOTAON, type), mnt_fsname, 0, filename))
+ if (quotactl(QCMD(Q_QUOTAOFF, type), mnt->mnt_fsname, 0, NULL)
+ || quotactl(QCMD(Q_QUOTAON, type), mnt->mnt_fsname, 0, filename))
errstr(_("Cannot turn %s quotas on %s off and on: %s\nKernel won't know about changes quotacheck did.\n"),
- type2name(type), mnt_fsname, strerror(errno));
+ type2name(type), mnt->mnt_fsname, strerror(errno));
free(filename);
}
return 0;
}
/* Buffer quotafile, run filesystem scan, dump quotafiles */
-static void check_dir(char *mnt_fsname, struct mntent *mnt)
+static void check_dir(struct mntent *mnt)
{
struct stat st;
int remounted = 0;
@@ -715,14 +713,14 @@ static void check_dir(char *mnt_fsname, struct mntent *mnt)
cur_dev = st.st_dev;
files_done = dirs_done = 0;
if (ucheck) {
- if (process_file(mnt_fsname, mnt, USRQUOTA) >= 0)
+ if (process_file(mnt, USRQUOTA) >= 0)
add_to_quota(USRQUOTA, st.st_ino, st.st_uid, st.st_gid, st.st_mode,
st.st_nlink, qspace);
else
ucheck = 0;
}
if (gcheck) {
- if (process_file(mnt_fsname, mnt, GRPQUOTA) >= 0)
+ if (process_file(mnt, GRPQUOTA) >= 0)
add_to_quota(GRPQUOTA, st.st_ino, st.st_uid, st.st_gid, st.st_mode,
st.st_nlink, qspace);
else
@@ -756,13 +754,13 @@ Please stop all programs writing to filesystem or use -m flag to force checking.
remounted = 1;
debug(FL_DEBUG | FL_VERBOSE, _("Filesystem remounted read-only\n"));
}
- debug(FL_VERBOSE, _("Scanning %s [%s] "), mnt_fsname, mnt->mnt_dir);
+ debug(FL_VERBOSE, _("Scanning %s [%s] "), mnt->mnt_fsname, mnt->mnt_dir);
#if defined(EXT2_DIRECT)
if (!strcmp(mnt->mnt_type, MNTTYPE_EXT2) || !strcmp(mnt->mnt_type, MNTTYPE_EXT3)) {
- if (ext2_direct_scan(mnt_fsname) < 0)
+ if (ext2_direct_scan(mnt->mnt_fsname) < 0)
goto out;
}
- else if (mnt_fsname) {
+ else {
#else
if (mnt->mnt_dir) {
#endif
@@ -780,10 +778,10 @@ Please stop all programs writing to filesystem or use -m flag to force checking.
debug(FL_DEBUG | FL_VERBOSE, _("Filesystem remounted RW.\n"));
}
if (ucheck)
- dump_to_file(mnt_fsname, mnt, USRQUOTA);
+ dump_to_file(mnt, USRQUOTA);
if (gcheck)
- dump_to_file(mnt_fsname, mnt, GRPQUOTA);
- out:
+ dump_to_file(mnt, GRPQUOTA);
+out:
remove_list();
}
@@ -806,66 +804,43 @@ static int detect_filename_format(struct mntent *mnt, int type)
static void check_all(void)
{
- FILE *mntf;
struct mntent *mnt;
- const char *mnt_fslabel;
- char *devlist[MAXMNTPOINTS];
- int gotmnt = 0, i, checked = 0;
-
- if (!(mntf = setmntent(MOUNTED, "r")))
- die(2, _("Cannot open %s: %s\n"), MOUNTED, strerror(errno));
- while ((mnt = getmntent(mntf))) {
- if (gotmnt == MAXMNTPOINTS)
- die(3, _("Too many mountpoints. Please report to: %s\n"), MY_EMAIL);
- if (!(devlist[gotmnt] = (char *)get_device_name(mnt->mnt_fsname)))
+ int checked = 0;
+
+ if (init_mounts_scan((flags & FL_ALL) ? 0 : 1, &mntpoint) < 0)
+ die(2, _("Can't initialize mountpoint scan.\n"));
+ while ((mnt = get_next_mount())) {
+ if (flags & FL_ALL && flags & FL_NOROOT && !strcmp(mnt->mnt_dir, "/"))
continue;
- for (i = 0; i < gotmnt && !devcmp(devlist[i], devlist[gotmnt]); i++);
- /* We already have this mountpoint? */
- if (i < gotmnt) {
- free(devlist[gotmnt]);
+ if (!strcmp(mnt->mnt_type, MNTTYPE_XFS)) {
+ debug(FL_DEBUG | FL_VERBOSE, _("Skipping %s [%s]\n"), mnt->mnt_fsname, mnt->mnt_dir);
continue;
}
- gotmnt++;
- if ((mnt_fslabel = strchr(mnt->mnt_fsname, '=')))
- mnt_fslabel++;
+ cfmt = fmt;
+ if (uwant && hasquota(mnt, USRQUOTA))
+ ucheck = 1;
else
- mnt_fslabel = devlist[gotmnt - 1];
- if ((flags & FL_ALL && (!(flags & FL_NOROOT) || strcmp(mnt->mnt_dir, "/"))) ||
- (mntpoint && (devcmp(mntpoint, devlist[gotmnt - 1]) || dircmp(mntpoint, mnt->mnt_dir)))) {
- if (!strcmp(mnt->mnt_type, MNTTYPE_XFS) ||
- !strcmp(mnt->mnt_type, MNTTYPE_NFS)) {
- debug(FL_DEBUG | FL_VERBOSE, _("Skipping %s [%s]\n"), mnt_fslabel,
- mnt->mnt_dir);
- continue;
- }
- cfmt = fmt;
- if (uwant && hasquota(mnt, USRQUOTA))
- ucheck = 1;
- else
- ucheck = 0;
- if (gwant && hasquota(mnt, GRPQUOTA))
- gcheck = 1;
- else
- gcheck = 0;
- if (!ucheck && !gcheck)
+ ucheck = 0;
+ if (gwant && hasquota(mnt, GRPQUOTA))
+ gcheck = 1;
+ else
+ gcheck = 0;
+ if (!ucheck && !gcheck)
+ continue;
+ if (cfmt == -1) {
+ if ((cfmt = detect_filename_format(mnt, ucheck ? USRQUOTA : GRPQUOTA)) == -1) {
+ errstr(_("Cannot guess format from filename on %s. Please specify format on commandline.\n"),
+ mnt->mnt_fsname);
continue;
- if (cfmt == -1) {
- if ((cfmt = detect_filename_format(mnt, ucheck ? USRQUOTA : GRPQUOTA)) == -1) {
- errstr(_("Cannot guess format from filename on %s. Please specify format on commandline.\n"),
- mnt_fslabel);
- continue;
- }
- debug(FL_DEBUG | FL_VERBOSE, _("Detected quota format %s\n"), fmt2name(cfmt));
}
- checked++;
- check_dir(devlist[gotmnt - 1], mnt);
+ debug(FL_DEBUG | FL_VERBOSE, _("Detected quota format %s\n"), fmt2name(cfmt));
}
+ checked++;
+ check_dir(mnt);
}
- endmntent(mntf);
+ end_mounts_scan();
if (!checked)
errstr(_("Can't find filesystem to check or filesystem not mounted with quota option.\n"));
- for (i = 0; i < gotmnt; i++)
- free(devlist[i]);
}
int main(int argc, char **argv)
diff --git a/quotaio.c b/quotaio.c
index d54f731..6c0f90e 100644
--- a/quotaio.c
+++ b/quotaio.c
@@ -126,13 +126,12 @@ struct quota_handle *init_io(struct mntent *mnt, int type, int fmt, int flags)
/* Check file format */
h->qh_fmt = detect_qf_format(fd, type);
if (h->qh_fmt == -2) {
- errstr(_("Quotafile format too new in %s\n"),
- qfname);
+ errstr(_("Quotafile format too new in %s\n"), qfname);
goto out_lock;
}
if (fmt != -1 && h->qh_fmt != fmt) {
errstr(_("Quotafile format detected differs from the specified one (or the one kernel uses on the file).\n"));
- goto out_handle;
+ goto out_lock;
}
}
else {
@@ -151,10 +150,10 @@ struct quota_handle *init_io(struct mntent *mnt, int type, int fmt, int flags)
goto out_lock;
}
return h;
- out_lock:
+out_lock:
if (fd != -1)
flock(fd, LOCK_UN);
- out_handle:
+out_handle:
if (qfname)
free(qfname);
free(h);
diff --git a/quotaio_v1.c b/quotaio_v1.c
index c3165b9..93b77b8 100644
--- a/quotaio_v1.c
+++ b/quotaio_v1.c
@@ -34,7 +34,7 @@
#ident "$Copyright: (c) 1980, 1990 Regents of the University of California. $"
#ident "$Copyright: All rights reserved. $"
-#ident "$Id: quotaio_v1.c,v 1.6 2001/07/17 21:02:55 jkar8572 Exp $"
+#ident "$Id: quotaio_v1.c,v 1.7 2001/08/15 20:13:42 jkar8572 Exp $"
#include <unistd.h>
#include <errno.h>
@@ -282,11 +282,13 @@ static int v1_commit_dquot(struct dquot *dquot)
/*
* Scan all dquots in file and call callback on each
*/
+#define SCANBUFSIZE 256
+
static int v1_scan_dquots(struct quota_handle *h, int (*process_dquot) (struct dquot *, char *))
{
- int rd;
- char name[MAXNAMELEN];
- struct v1_disk_dqblk ddqblk;
+ int rd, scanbufpos = 0, scanbufsize = 0;
+ char name[MAXNAMELEN], scanbuf[sizeof(struct v1_disk_dqblk)*SCANBUFSIZE];
+ struct v1_disk_dqblk *ddqblk;
struct dquot *dquot = get_empty_dquot();
qid_t id = 0;
@@ -297,13 +299,23 @@ static int v1_scan_dquots(struct quota_handle *h, int (*process_dquot) (struct d
memset(dquot, 0, sizeof(*dquot));
dquot->dq_h = h;
lseek(h->qh_fd, 0, SEEK_SET);
- for(id = 0; (rd = read(h->qh_fd, &ddqblk, sizeof(ddqblk))) == sizeof(ddqblk); id++) {
- if ((ddqblk.dqb_ihardlimit | ddqblk.dqb_isoftlimit |
- ddqblk.dqb_bhardlimit | ddqblk.dqb_bsoftlimit |
- ddqblk.dqb_curblocks | ddqblk.dqb_curinodes |
- ddqblk.dqb_itime | ddqblk.dqb_btime) == 0)
+ for(id = 0; ; id++, scanbufpos++) {
+ if (scanbufpos >= scanbufsize) {
+ rd = read(h->qh_fd, scanbuf, sizeof(scanbuf));
+ if (rd < 0 || rd % sizeof(struct v1_disk_dqblk))
+ goto out_err;
+ if (!rd)
+ break;
+ scanbufpos = 0;
+ scanbufsize = rd / sizeof(struct v1_disk_dqblk);
+ }
+ ddqblk = ((struct v1_disk_dqblk *)scanbuf) + scanbufpos;
+ if ((ddqblk->dqb_ihardlimit | ddqblk->dqb_isoftlimit |
+ ddqblk->dqb_bhardlimit | ddqblk->dqb_bsoftlimit |
+ ddqblk->dqb_curblocks | ddqblk->dqb_curinodes |
+ ddqblk->dqb_itime | ddqblk->dqb_btime) == 0)
continue;
- v1_disk2memdqblk(&dquot->dq_dqb, &ddqblk);
+ v1_disk2memdqblk(&dquot->dq_dqb, ddqblk);
dquot->dq_id = id;
id2name(dquot->dq_id, h->qh_type, name);
if ((rd = process_dquot(dquot, name)) < 0) {
@@ -313,5 +325,6 @@ static int v1_scan_dquots(struct quota_handle *h, int (*process_dquot) (struct d
}
if (!rd) /* EOF? */
return 0;
+out_err:
return -1; /* Some read errstr... */
}
diff --git a/quotaio_v1.h b/quotaio_v1.h
index a91a975..aa9448e 100644
--- a/quotaio_v1.h
+++ b/quotaio_v1.h
@@ -18,7 +18,7 @@ struct v1_disk_dqblk {
u_int32_t dqb_bsoftlimit; /* preferred limit on disk blks */
u_int32_t dqb_curblocks; /* current block count */
u_int32_t dqb_ihardlimit; /* maximum # allocated inodes */
- u_int32_t dqb_isoftlimit; /* preferred limit on disk blks */
+ u_int32_t dqb_isoftlimit; /* preferred limit on inodes */
u_int32_t dqb_curinodes; /* current # allocated inodes */
time_t dqb_btime; /* time limit for excessive disk use */
time_t dqb_itime; /* time limit for excessive files */
diff --git a/quotaon.c b/quotaon.c
index 677325f..2b36082 100644
--- a/quotaon.c
+++ b/quotaon.c
@@ -34,7 +34,7 @@
#ident "$Copyright: (c) 1980, 1990 Regents of the University of California $"
#ident "$Copyright: All rights reserved. $"
-#ident "$Id: quotaon.c,v 1.5 2001/05/15 09:28:49 jkar8572 Exp $"
+#ident "$Id: quotaon.c,v 1.6 2001/08/15 20:13:42 jkar8572 Exp $"
/*
* Turn quota on/off for a filesystem.
@@ -61,19 +61,6 @@ static void usage(void)
}
/*
- * Check to see if target appears in list of size cnt.
- */
-static int oneof(char *dir, char *dev, char *list[], int cnt)
-{
- int i;
-
- for (i = 0; i < cnt; i++)
- if (devcmp(dev, list[i]) || dircmp(dir, list[i]))
- return (i);
- return (-1);
-}
-
-/*
* For both VFS quota formats, need to pass in the quota file;
* for XFS quota manager, pass on the -x command line option.
*/
@@ -110,9 +97,7 @@ static int newstate(struct mntent *mnt, int offmode, int type, char *extra)
int main(int argc, char **argv)
{
- FILE *fp;
struct mntent *mnt;
- long argnum, done = 0;
char *xarg = NULL;
int c, offmode = 0, errs = 0;
@@ -163,20 +148,12 @@ int main(int argc, char **argv)
kqf = kern_quota_format();
- fp = setmntent(MNTTAB, "r");
- while ((mnt = getmntent(fp))) {
- if (aflag) {
- if (hasmntopt(mnt, MNTOPT_NOAUTO) || !strcmp(mnt->mnt_type, MNTTYPE_NFS))
- continue;
- }
- else {
- if ((argnum = oneof(mnt->mnt_dir, mnt->mnt_fsname, argv, argc)) >= 0)
- done |= 1 << argnum;
- else
- continue;
- }
+ if (init_mounts_scan(aflag ? 0 : argc, argv) < 0)
+ return 1;
+ while ((mnt = get_next_mount())) {
if (!strcmp(mnt->mnt_type, MNTTYPE_NFS)) {
- fprintf(stderr, "%s: Quota can't be turned on on NFS filesystem\n", mnt->mnt_fsname);
+ if (!aflag)
+ fprintf(stderr, "%s: Quota can't be turned on on NFS filesystem\n", mnt->mnt_fsname);
continue;
}
@@ -185,11 +162,8 @@ int main(int argc, char **argv)
if (uflag)
errs += newstate(mnt, offmode, USRQUOTA, xarg);
}
- endmntent(fp);
+ end_mounts_scan();
- for (c = 0; c < argc; c++)
- if ((done & (1 << c)) == 0)
- errstr(_("%s not found in fstab\n"), argv[c]);
return errs;
}
diff --git a/quotaon_xfs.c b/quotaon_xfs.c
index f9d1918..70e9e75 100644
--- a/quotaon_xfs.c
+++ b/quotaon_xfs.c
@@ -150,7 +150,7 @@ static int xfs_delete(char *dev, int type, int flags, int rootfs, int *xopts)
return (check < 0);
if (quotactl(QCMD(qcmd, type), dev, 0, (void *)xopts) < 0) {
- errstr(_("Failed to delete quota: %s"),
+ errstr(_("Failed to delete quota: %s\n"),
strerror(errno));
return 1;
}
diff --git a/quotasys.c b/quotasys.c
index 300ac55..21d3a72 100644
--- a/quotasys.c
+++ b/quotasys.c
@@ -211,6 +211,42 @@ void time2str(time_t seconds, char *buf, int flags)
}
/*
+ * Convert number in quota blocks to some nice short form for printing
+ */
+void space2str(qsize_t space, char *buf, int format)
+{
+ int i;
+ char suffix[8] = " MGT";
+
+ space = qb2kb(space);
+ if (format)
+ for (i = 3; i > 0; i--)
+ if (space >= (1LL << (QUOTABLOCK_BITS*i))*100) {
+ sprintf(buf, "%Lu%c", (space+(1 << (QUOTABLOCK_BITS*i))-1) >> (QUOTABLOCK_BITS*i), suffix[i]);
+ return;
+ }
+ sprintf(buf, "%Lu", space);
+}
+
+/*
+ * Convert number to some nice short form for printing
+ */
+void number2str(unsigned long long num, char *buf, int format)
+{
+ int i;
+ unsigned long long div;
+ char suffix[8] = " kmgt";
+
+ if (format)
+ for (i = 4, div = 1000000000000LL; i > 0; i--, div /= 1000)
+ if (num >= 100*div) {
+ sprintf(buf, "%Lu%c", (num+div-1) / div, suffix[i]);
+ return;
+ }
+ sprintf(buf, "%Lu", num);
+}
+
+/*
* Check for XFS filesystem with quota accounting enabled
*/
static int hasxfsquota(struct mntent *mnt, int type)
@@ -341,48 +377,31 @@ char *get_qf_name(struct mntent *mnt, int type, int fmt)
struct quota_handle **create_handle_list(int count, char **mntpoints, int type, int fmt,
int flags)
{
- FILE *mntf;
struct mntent *mnt;
- int i, gotmnt = 0;
+ int gotmnt = 0;
static struct quota_handle *hlist[MAXMNTPOINTS];
- const char *dev;
- if (!(mntf = setmntent(MOUNTED, "r")))
- die(2, _("Can't open %s: %s\n"), MOUNTED, strerror(errno));
- while ((mnt = getmntent(mntf))) {
- if (!(dev = get_device_name(mnt->mnt_fsname)))
- continue;
- /* Do we already have this device? (filesystem may be mounted multiple times) */
- for (i = 0; i < gotmnt && !devcmp_handle(dev, hlist[i]); i++);
- if (i < gotmnt)
- continue;
- for (i = 0; i < count; i++)
- /* Is this the filesystem we want? */
- if (devcmp(dev, mntpoints[i]) || dircmp(mnt->mnt_dir, mntpoints[i]))
- break;
- free((char *)dev);
- if (!count || i < count) {
- if (strcmp(mnt->mnt_type, MNTTYPE_NFS)) { /* No NFS? */
- if (gotmnt == MAXMNTPOINTS)
- die(3, _("Too many mountpoints. Please report to: %s\n"),
- MY_EMAIL);
- if (!(hlist[gotmnt] = init_io(mnt, type, fmt, flags)))
- continue;
- gotmnt++;
- }
- else if (!(flags & IOI_LOCALONLY) && (fmt == -1 || fmt == QF_RPC)) { /* Use NFS? */
+ if (init_mounts_scan(count, mntpoints) < 0)
+ die(2, _("Can't initialize mountpoint scan.\n"));
+ while ((mnt = get_next_mount())) {
+ if (strcmp(mnt->mnt_type, MNTTYPE_NFS)) { /* No NFS? */
+ if (gotmnt+1 == MAXMNTPOINTS)
+ die(2, _("Too many mountpoints with quota. Contact %s\n"), MY_EMAIL);
+ if (!(hlist[gotmnt] = init_io(mnt, type, fmt, flags)))
+ continue;
+ gotmnt++;
+ }
+ else if (!(flags & IOI_LOCALONLY) && (fmt == -1 || fmt == QF_RPC)) { /* Use NFS? */
#ifdef RPC
- if (gotmnt == MAXMNTPOINTS)
- die(3, _("Too many mountpoints. Please report to: %s\n"),
- MY_EMAIL);
- if (!(hlist[gotmnt] = init_io(mnt, type, fmt, flags)))
- continue;
- gotmnt++;
+ if (gotmnt+1 == MAXMNTPOINTS)
+ die(2, _("Too many mountpoints with quota. Contact %s\n"), MY_EMAIL);
+ if (!(hlist[gotmnt] = init_io(mnt, type, fmt, flags)))
+ continue;
+ gotmnt++;
#endif
- }
}
}
- endmntent(mntf);
+ end_mounts_scan();
hlist[gotmnt] = NULL;
if (count && gotmnt != count)
die(1, _("Not all specified mountpoints are using quota.\n"));
@@ -518,3 +537,251 @@ int kern_quota_on(const char *dev, int type, int fmt)
return QF_VFSOLD;
return -1;
}
+
+/*
+ *
+ * mtab/fstab handling routines
+ *
+ */
+
+struct mount_entry {
+ char *me_type; /* Type of filesystem for given entry */
+ char *me_opts; /* Options of filesystem */
+ dev_t me_dev; /* Device filesystem is mounted on */
+ ino_t me_ino; /* Inode number of root of filesystem */
+ const char *me_devname; /* Name of device (after pass through get_device_name()) */
+ const char *me_dir; /* One of mountpoints of filesystem */
+};
+
+struct searched_dir {
+ int sd_dir; /* Is searched dir mountpoint or in fact device? */
+ dev_t sd_dev; /* Device mountpoint lies on */
+ ino_t sd_ino; /* Inode number of mountpoint */
+ const char *sd_name; /* Name of given dir/device */
+};
+
+#define ALLOC_ENTRIES_NUM 16 /* Allocate entries by this number */
+
+static int mnt_entries_cnt; /* Number of cached mountpoint entries */
+static struct mount_entry *mnt_entries; /* Cached mounted filesystems */
+static int check_dirs_cnt, act_checked; /* Number of dirs to check; Actual checked dir/(mountpoint in case of -a) */
+static struct searched_dir *check_dirs; /* Directories to check */
+
+/* Cache mtab/fstab */
+static int cache_mnt_table(void)
+{
+ FILE *mntf;
+ struct mntent *mnt;
+ struct stat st;
+ int allocated = 0, i;
+ dev_t dev;
+ char mntpointbuf[PATH_MAX];
+
+ if (!(mntf = setmntent(_PATH_MOUNTED, "r"))) {
+ if (errno != ENOENT) {
+ errstr(_("Can't open %s: %s\n"), _PATH_MOUNTED, strerror(errno));
+ return -1;
+ }
+ else /* Fallback on fstab when mtab not available */
+ if (!(mntf = setmntent(_PATH_MNTTAB, "r"))) {
+ errstr(_("Can't open %s: %s\n"), _PATH_MNTTAB, strerror(errno));
+ return -1;
+ }
+ }
+ mnt_entries = smalloc(sizeof(struct mount_entry) * ALLOC_ENTRIES_NUM);
+ allocated += ALLOC_ENTRIES_NUM;
+ while ((mnt = getmntent(mntf))) {
+ const char *devname;
+
+ if (!CORRECT_FSTYPE(mnt->mnt_type)) /* Just basic filtering */
+ continue;
+ if (!(devname = get_device_name(mnt->mnt_fsname))) {
+ errstr(_("Can't get device name for %s\n"), mnt->mnt_fsname);
+ continue;
+ }
+ if (!realpath(mnt->mnt_dir, mntpointbuf)) {
+ errstr(_("Can't resolve mountpoint path %s: %s\n"), mnt->mnt_dir, strerror(errno));
+ free((char *)devname);
+ continue;
+ }
+ if (strcmp(mnt->mnt_type, MNTTYPE_NFS)) {
+ if (stat(devname, &st) < 0) { /* Can't stat mounted device? */
+ errstr(_("Can't stat() mounted device %s: %s\n"), devname, strerror(errno));
+ free((char *)devname);
+ continue;
+ }
+ if (!S_ISBLK(st.st_mode) && !S_ISCHR(st.st_mode))
+ errstr(_("Warning: Device %s is not block nor character device.\n"), devname);
+ dev = st.st_rdev;
+ for (i = 0; i < mnt_entries_cnt && mnt_entries[i].me_dev != dev; i++);
+ }
+ else { /* Cope with network filesystems */
+ dev = 0;
+ for (i = 0; i < mnt_entries_cnt && strcmp(mnt_entries[i].me_devname, devname); i++);
+ }
+ if (i == mnt_entries_cnt) { /* New mounted device? */
+ if (stat(mnt->mnt_dir, &st) < 0) { /* Can't stat mountpoint? We have better ignore it... */
+ errstr(_("Can't stat() mountpoint %s: %s\n"), mnt->mnt_dir, strerror(errno));
+ free((char *)devname);
+ continue;
+ }
+ if (allocated == mnt_entries_cnt) {
+ allocated += ALLOC_ENTRIES_NUM;
+ mnt_entries = srealloc(mnt_entries, allocated * sizeof(struct mount_entry));
+ }
+ mnt_entries[i].me_type = sstrdup(mnt->mnt_type);
+ mnt_entries[i].me_opts = sstrdup(mnt->mnt_opts);
+ mnt_entries[i].me_dev = dev;
+ mnt_entries[i].me_ino = st.st_ino;
+ mnt_entries[i].me_devname = devname;
+ mnt_entries[i].me_dir = sstrdup(mntpointbuf);
+ mnt_entries_cnt++;
+ }
+ else
+ free((char *)devname); /* We don't need it any more */
+ }
+ endmntent(mntf);
+ return 0;
+}
+
+/* Process and store given paths */
+static int process_dirs(int dcnt, char **dirs)
+{
+ struct stat st;
+ int i;
+ char mntpointbuf[PATH_MAX];
+
+ check_dirs_cnt = 0;
+ act_checked = -1;
+ if (dcnt) {
+ check_dirs = smalloc(sizeof(struct searched_dir) * dcnt);
+ for (i = 0; i < dcnt; i++) {
+ if (stat(dirs[i], &st) < 0) {
+ errstr(_("Can't stat() given mountpoint %s: %s\n"), dirs[i], strerror(errno));
+ continue;
+ }
+ check_dirs[check_dirs_cnt].sd_dir = S_ISDIR(st.st_mode);
+ if (S_ISDIR(st.st_mode)) {
+ check_dirs[check_dirs_cnt].sd_dev = st.st_dev;
+ check_dirs[check_dirs_cnt].sd_ino = st.st_ino;
+ }
+ else if (S_ISBLK(st.st_mode) || S_ISCHR(st.st_mode))
+ check_dirs[check_dirs_cnt].sd_dev = st.st_rdev;
+ else {
+ errstr(_("Specified path %s is not directory nor device.\n"), dirs[i]);
+ continue;
+ }
+ if (!realpath(dirs[i], mntpointbuf)) {
+ errstr(_("Can't resolve path %s: %s\n"), dirs[i], strerror(errno));
+ continue;
+ }
+ check_dirs[check_dirs_cnt].sd_name = sstrdup(mntpointbuf);
+ check_dirs_cnt++;
+ }
+ }
+ return 0;
+}
+
+/*
+ * Initialize mountpoint scan
+ */
+int init_mounts_scan(int dcnt, char **dirs)
+{
+ if (cache_mnt_table() < 0)
+ return -1;
+ return process_dirs(dcnt, dirs);
+}
+
+/* Find next usable mountpoint when scanning all mountpoints */
+static int find_next_entry_all(int *pos)
+{
+ struct mntent mnt;
+
+restart:
+ if (++act_checked == mnt_entries_cnt)
+ return 0;
+ mnt.mnt_fsname = (char *)mnt_entries[act_checked].me_devname;
+ mnt.mnt_type = mnt_entries[act_checked].me_type;
+ mnt.mnt_opts = mnt_entries[act_checked].me_opts;
+ mnt.mnt_dir = (char *)mnt_entries[act_checked].me_dir;
+ if (hasmntopt(&mnt, MNTOPT_NOAUTO))
+ goto restart;
+ *pos = act_checked;
+ return 1;
+}
+
+/* Find next usable mountpoint when scanning selected mountpoints */
+static int find_next_entry_sel(int *pos)
+{
+ int i;
+ struct searched_dir *sd;
+
+restart:
+ if (++act_checked == check_dirs_cnt)
+ return 0;
+ sd = check_dirs + act_checked;
+ for (i = 0; i < mnt_entries_cnt; i++) {
+ if (sd->sd_dir) {
+ if (sd->sd_dev == mnt_entries[i].me_dev && sd->sd_ino == mnt_entries[i].me_ino)
+ break;
+ }
+ else
+ if (sd->sd_dev == mnt_entries[i].me_dev)
+ break;
+ }
+ if (i == mnt_entries_cnt) {
+ errstr(_("Mountpoint (or device) %s not found.\n"), sd->sd_name);
+ goto restart;
+ }
+ *pos = i;
+ return 1;
+}
+
+/*
+ * Return next directory from the list
+ */
+struct mntent *get_next_mount(void)
+{
+ static struct mntent mnt;
+ int mntpos;
+
+ if (!check_dirs_cnt) { /* Scan all mountpoints? */
+ if (!find_next_entry_all(&mntpos))
+ return NULL;
+ mnt.mnt_dir = (char *)mnt_entries[mntpos].me_dir;
+ }
+ else {
+ if (!find_next_entry_sel(&mntpos))
+ return NULL;
+ mnt.mnt_dir = (char *)check_dirs[act_checked].sd_name;
+ }
+ mnt.mnt_fsname = (char *)mnt_entries[mntpos].me_devname;
+ mnt.mnt_type = mnt_entries[mntpos].me_type;
+ mnt.mnt_opts = mnt_entries[mntpos].me_opts;
+ return &mnt;
+}
+
+/*
+ * Free all structures allocated for mountpoint scan
+ */
+void end_mounts_scan(void)
+{
+ int i;
+
+ for (i = 0; i < mnt_entries_cnt; i++) {
+ free(mnt_entries[i].me_type);
+ free(mnt_entries[i].me_opts);
+ free((char *)mnt_entries[i].me_devname);
+ free((char *)mnt_entries[i].me_dir);
+ }
+ free(mnt_entries);
+ mnt_entries = NULL;
+ mnt_entries_cnt = 0;
+ if (check_dirs_cnt) {
+ for (i = 0; i < check_dirs_cnt; i++)
+ free((char *)check_dirs[i].sd_name);
+ free(check_dirs);
+ }
+ check_dirs = NULL;
+ check_dirs_cnt = 0;
+}
diff --git a/quotasys.h b/quotasys.h
index 48544e5..ed10d80 100644
--- a/quotasys.h
+++ b/quotasys.h
@@ -9,10 +9,12 @@
#include <sys/types.h>
#include "mntopt.h"
+#include "quota.h"
#define MAXNAMELEN 64 /* Maximal length of user/group name */
#define MAXTIMELEN 40 /* Maximal length of time string */
-#define MAXMNTPOINTS 128 /* Maximal number of processed mountpoints per one run */
+#define MAXNUMLEN 32 /* Maximal length of number */
+#define MAXMNTPOINTS 128 /* Maximal number of mountpoints with quota */
/* Flags for formatting time */
#define TF_ROUND 0x1 /* Should be printed time rounded? */
@@ -58,6 +60,12 @@ void difftime2str(time_t, char *);
/* Convert time to printable form */
void time2str(time_t, char *, int);
+/* Convert number in quota blocks to short printable form */
+void space2str(qsize_t, char *, int);
+
+/* Convert number to short printable form */
+void number2str(unsigned long long, char *, int);
+
/* Check to see if particular quota is to be enabled */
int hasquota(struct mntent *mnt, int type);
@@ -85,4 +93,13 @@ int kern_quota_format(void);
/* Check whether is quota turned on on given device for given type */
int kern_quota_on(const char *dev, int type, int fmt);
+/* Initialize mountpoints scan */
+int init_mounts_scan(int dcnt, char **dirs);
+
+/* Return next mountpoint for scan */
+struct mntent *get_next_mount(void);
+
+/* Free all structures associated with mountpoints scan */
+void end_mounts_scan(void);
+
#endif /* _QUOTASYS_H */
diff --git a/repquota.8 b/repquota.8
index 2125bdd..43b6d26 100644
--- a/repquota.8
+++ b/repquota.8
@@ -5,7 +5,7 @@ repquota \- summarize quotas for a filesystem
.SH SYNOPSIS
.B /usr/sbin/repquota
[
-.B \-vtug
+.B \-vtsug
] [
.B \-F
.I format-name
@@ -14,7 +14,7 @@ repquota \- summarize quotas for a filesystem
.LP
.B /usr/sbin/repquota
[
-.B \-avtug
+.B \-avtsug
] [
.B \-F
.I format-name
@@ -49,6 +49,10 @@ information.
Truncate user/group names longer than 9 characters. This results in nicer output when
there are such names.
.TP
+.B \-s
+Try to report used space, number of used inodes and limits in more appropriate units
+than default ones.
+.TP
.B \-F \f2format-name\f1
Report quota for specified format (ie. don't perform format autodetection).
Possible format names are:
diff --git a/repquota.c b/repquota.c
index 4d5733d..749c6b4 100644
--- a/repquota.c
+++ b/repquota.c
@@ -26,6 +26,7 @@
#define FL_VERBOSE 4
#define FL_ALL 8
#define FL_TRUNCNAMES 16
+#define FL_SHORTNUMS 32
int flags, fmt = -1;
char **mnt;
@@ -34,8 +35,8 @@ char *progname;
static void usage(void)
{
- errstr(_("Utility for reporting quotas.\nUsage:\n%s [-vugt] [-F quotaformat] (-a | mntpoint)\n"), progname);
- errstr(_("Bugs to %s\n"), MY_EMAIL);
+ errstr(_("Utility for reporting quotas.\nUsage:\n%s [-vugts] [-F quotaformat] (-a | mntpoint)\n"), progname);
+ fprintf(stderr, _("Bugs to %s\n"), MY_EMAIL);
exit(1);
}
@@ -49,7 +50,7 @@ static void parse_options(int argcnt, char **argstr)
else
slash++;
- while ((ret = getopt(argcnt, argstr, "VavughtF:")) != -1) {
+ while ((ret = getopt(argcnt, argstr, "VavughtsF:")) != -1) {
switch (ret) {
case '?':
case 'h':
@@ -72,6 +73,9 @@ static void parse_options(int argcnt, char **argstr)
case 't':
flags |= FL_TRUNCNAMES;
break;
+ case 's':
+ flags |= FL_SHORTNUMS;
+ break;
case 'F':
if ((fmt = name2fmt(optarg)) == QF_ERROR)
exit(1);
@@ -107,6 +111,8 @@ static int print(struct dquot *dquot, char *name)
{
char pname[MAXNAMELEN];
char time[MAXTIMELEN];
+ char numbuf[3][MAXNUMLEN];
+
struct util_dqblk *entry = &dquot->dq_dqb;
if (!entry->dqb_curspace && !entry->dqb_curinodes && !(flags & FL_VERBOSE))
@@ -115,16 +121,18 @@ static int print(struct dquot *dquot, char *name)
if (flags & FL_TRUNCNAMES)
pname[PRINTNAMELEN] = 0;
difftime2str(entry->dqb_btime, time);
- printf("%-*s %c%c%8Lu%8Lu%8Lu%7s", PRINTNAMELEN, pname,
- overlim(qb2kb(toqb(entry->dqb_curspace)), qb2kb(entry->dqb_bsoftlimit),
- qb2kb(entry->dqb_bhardlimit)), overlim(entry->dqb_curinodes,
- entry->dqb_isoftlimit,
- entry->dqb_ihardlimit),
- (long long)qb2kb(toqb(entry->dqb_curspace)), (long long)qb2kb(entry->dqb_bsoftlimit),
- (long long)qb2kb(entry->dqb_bhardlimit), time);
+ space2str(toqb(entry->dqb_curspace), numbuf[0], flags & FL_SHORTNUMS);
+ space2str(entry->dqb_bsoftlimit, numbuf[1], flags & FL_SHORTNUMS);
+ space2str(entry->dqb_bhardlimit, numbuf[2], flags & FL_SHORTNUMS);
+ printf("%-*s %c%c %7s %7s %7s %6s", PRINTNAMELEN, pname,
+ overlim(qb2kb(toqb(entry->dqb_curspace)), qb2kb(entry->dqb_bsoftlimit), qb2kb(entry->dqb_bhardlimit)),
+ overlim(entry->dqb_curinodes, entry->dqb_isoftlimit, entry->dqb_ihardlimit),
+ numbuf[0], numbuf[1], numbuf[2], time);
difftime2str(entry->dqb_itime, time);
- printf("%8Lu%6Lu%6Lu%7s\n", (long long)entry->dqb_curinodes,
- (long long)entry->dqb_isoftlimit, (long long)entry->dqb_ihardlimit, time);
+ number2str(entry->dqb_curinodes, numbuf[0], flags & FL_SHORTNUMS);
+ number2str(entry->dqb_isoftlimit, numbuf[1], flags & FL_SHORTNUMS);
+ number2str(entry->dqb_ihardlimit, numbuf[2], flags & FL_SHORTNUMS);
+ printf(" %7s %5s %5s %6s\n", numbuf[0], numbuf[1], numbuf[2], time);
return 0;
}
diff --git a/rquota_client.c b/rquota_client.c
index 5efc920..553bc10 100644
--- a/rquota_client.c
+++ b/rquota_client.c
@@ -9,7 +9,7 @@
*
* This part does the rpc-communication with the rquotad.
*
- * Version: $Id: rquota_client.c,v 1.3 2001/07/17 21:02:55 jkar8572 Exp $
+ * Version: $Id: rquota_client.c,v 1.4 2001/08/15 20:13:42 jkar8572 Exp $
*
* Author: Marco van Wieringen <mvw@planets.elm.net>
*
@@ -168,11 +168,12 @@ void rpc_rquota_get(struct dquot *dquot)
*/
auth_destroy(clnt->cl_auth);
clnt_destroy(clnt);
+ puts("get2");
}
else {
result = NULL;
}
-
+ printf("result: %p, status: %d\n", result, result?result->status:0);
if (result == NULL || !result->status) {
if (dquot->dq_h->qh_type == USRQUOTA) {
/*
diff --git a/rquota_server.c b/rquota_server.c
index 65d5dc2..c7b1a4c 100644
--- a/rquota_server.c
+++ b/rquota_server.c
@@ -9,7 +9,7 @@
*
* This part does the lookup of the info.
*
- * Version: $Id: rquota_server.c,v 1.5 2001/07/17 21:02:55 jkar8572 Exp $
+ * Version: $Id: rquota_server.c,v 1.6 2001/08/15 20:13:42 jkar8572 Exp $
*
* Author: Marco van Wieringen <mvw@planets.elm.net>
*
@@ -127,9 +127,6 @@ setquota_rslt *setquotainfo(int flags, caddr_t * argp, struct svc_req *rqstp)
setquota_args *args;
ext_setquota_args *ext_args;
} arguments;
- struct stat st;
- dev_t device;
- FILE *mntf;
struct util_dqblk dqblk;
struct dquot *dquot;
struct mntent *mnt;
@@ -184,25 +181,19 @@ setquota_rslt *setquotainfo(int flags, caddr_t * argp, struct svc_req *rqstp)
}
result.status = Q_NOQUOTA;
- if (stat(pathname, &st) == -1)
- return (&result);
-
- device = st.st_dev;
result.setquota_rslt_u.sqr_rquota.rq_bsize = RPC_DQBLK_SIZE;
- mntf = setmntent(_PATH_MOUNTED, "r");
- while ((mnt = getmntent(mntf))) {
- if (stat(mnt->mnt_dir, &st) == -1)
- continue;
- if (st.st_dev != device)
- continue;
- if (!(handles[0] = init_io(mnt, type, -1, 0)))
- continue;
- break;
+ if (init_mounts_scan(1, &pathname) < 0)
+ goto out;
+ if (!(mnt = get_next_mount())) {
+ end_mounts_scan();
+ goto out;
}
- endmntent(mntf);
- if (!handles[0])
+ if (!(handles[0] = init_io(mnt, type, -1, 0))) {
+ end_mounts_scan();
goto out;
+ }
+ end_mounts_scan();
if (!(dquot = handles[0]->qh_ops->read_dquot(handles[0], id)))
goto out;
if (qcmd == QCMD(Q_RPC_SETQLIM, type) || qcmd == QCMD(Q_RPC_SETQUOTA, type)) {
@@ -220,7 +211,7 @@ setquota_rslt *setquotainfo(int flags, caddr_t * argp, struct svc_req *rqstp)
if (handles[0]->qh_ops->commit_dquot(dquot) == -1)
goto out;
result.status = Q_OK;
- out:
+out:
dispose_handle_list(handles);
#else
result.status = Q_EPERM;
@@ -235,9 +226,6 @@ getquota_rslt *getquotainfo(int flags, caddr_t * argp, struct svc_req * rqstp)
getquota_args *args;
ext_getquota_args *ext_args;
} arguments;
- struct stat st;
- dev_t device;
- FILE *mntf;
struct dquot *dquot = NULL;
struct mntent *mnt;
char *pathname;
@@ -289,26 +277,21 @@ getquota_rslt *getquotainfo(int flags, caddr_t * argp, struct svc_req * rqstp)
}
result.status = Q_NOQUOTA;
-
- if (stat(pathname, &st) == -1)
- return (&result);
-
- device = st.st_dev;
result.getquota_rslt_u.gqr_rquota.rq_bsize = RPC_DQBLK_SIZE;
- mntf = setmntent(_PATH_MOUNTED, "r");
- while ((mnt = getmntent(mntf))) {
- if (stat(mnt->mnt_dir, &st) == -1)
- continue;
- if (st.st_dev != device)
- continue;
- if (!(handles[0] = init_io(mnt, type, -1, IOI_READONLY)))
- continue;
- break;
+ if (init_mounts_scan(1, &pathname) < 0)
+ goto out;
+ if (!(mnt = get_next_mount())) {
+ end_mounts_scan();
+ goto out;
}
- endmntent(mntf);
- if (!handles[0])
+ printf("dev: %s dir: %s\n", mnt->mnt_fsname, mnt->mnt_dir);
+ if (!(handles[0] = init_io(mnt, type, -1, IOI_READONLY))) {
+ end_mounts_scan();
goto out;
+ }
+ printf("Returned: %p\n", handles[0]);
+ end_mounts_scan();
if (!(flags & ACTIVE) || QIO_ENABLED(handles[0]))
dquot = handles[0]->qh_ops->read_dquot(handles[0], id);
if (dquot) {
@@ -319,6 +302,7 @@ getquota_rslt *getquotainfo(int flags, caddr_t * argp, struct svc_req * rqstp)
}
out:
dispose_handle_list(handles);
+ printf("state: %d\n", result.status);
return (&result);
}
diff --git a/rquota_svc.c b/rquota_svc.c
index 6baf0a3..90734e9 100644
--- a/rquota_svc.c
+++ b/rquota_svc.c
@@ -10,7 +10,7 @@
*
* Author: Marco van Wieringen <mvw@planets.elm.net>
*
- * Version: $Id: rquota_svc.c,v 1.2 2001/05/02 09:32:22 jkar8572 Exp $
+ * Version: $Id: rquota_svc.c,v 1.3 2001/08/15 20:13:42 jkar8572 Exp $
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
@@ -118,7 +118,7 @@ static void rquotaprog_1(struct svc_req *rqstp, register SVCXPRT * transp)
svcerr_systemerr(transp);
}
if (!svc_freeargs(transp, xdr_argument, (caddr_t) & argument)) {
- errstr(_("unable to free arguments"));
+ errstr(_("unable to free arguments\n"));
exit(1);
}
return;
@@ -196,7 +196,7 @@ static void rquotaprog_2(struct svc_req *rqstp, register SVCXPRT * transp)
svcerr_systemerr(transp);
}
if (!svc_freeargs(transp, xdr_argument, (caddr_t) & argument)) {
- errstr(_("unable to free arguments"));
+ errstr(_("unable to free arguments\n"));
exit(1);
}
return;
@@ -219,35 +219,35 @@ int main(int argc, char **argv)
transp = svcudp_create(RPC_ANYSOCK);
if (transp == NULL) {
- errstr(_("cannot create udp service."));
+ errstr(_("cannot create udp service.\n"));
exit(1);
}
if (!svc_register(transp, RQUOTAPROG, RQUOTAVERS, rquotaprog_1, IPPROTO_UDP)) {
- errstr(_("unable to register (RQUOTAPROG, RQUOTAVERS, udp)."));
+ errstr(_("unable to register (RQUOTAPROG, RQUOTAVERS, udp).\n"));
exit(1);
}
if (!svc_register(transp, RQUOTAPROG, EXT_RQUOTAVERS, rquotaprog_2, IPPROTO_UDP)) {
- errstr(_("unable to register (RQUOTAPROG, EXT_RQUOTAVERS, udp)."));
+ errstr(_("unable to register (RQUOTAPROG, EXT_RQUOTAVERS, udp).\n"));
exit(1);
}
transp = svctcp_create(RPC_ANYSOCK, 0, 0);
if (transp == NULL) {
- errstr(_("cannot create tcp service."));
+ errstr(_("cannot create tcp service.\n"));
exit(1);
}
if (!svc_register(transp, RQUOTAPROG, RQUOTAVERS, rquotaprog_1, IPPROTO_TCP)) {
- errstr(_("unable to register (RQUOTAPROG, RQUOTAVERS, tcp)."));
+ errstr(_("unable to register (RQUOTAPROG, RQUOTAVERS, tcp).\n"));
exit(1);
}
if (!svc_register(transp, RQUOTAPROG, EXT_RQUOTAVERS, rquotaprog_2, IPPROTO_TCP)) {
- errstr(_("unable to register (RQUOTAPROG, EXT_RQUOTAVERS, tcp)."));
+ errstr(_("unable to register (RQUOTAPROG, EXT_RQUOTAVERS, tcp).\n"));
exit(1);
}
daemon(1, 1);
svc_run();
- errstr(_("svc_run returned"));
+ errstr(_("svc_run returned\n"));
exit(1);
/* NOTREACHED */
}
diff --git a/setquota.c b/setquota.c
index d5236dd..e9c5ea3 100644
--- a/setquota.c
+++ b/setquota.c
@@ -50,7 +50,7 @@ static void usage(void)
" setquota [-u|-g] [-F quotaformat] <-p protouser|protogroup> <user|group> -a|<filesystem>...\n"
" setquota [-u|-g] [-F quotaformat] -t <blockgrace> <inodegrace> -a|<filesystem>...\n"));
#endif
- errstr(_("Bugs to: %s\n"), MY_EMAIL);
+ fprintf(stderr, _("Bugs to: %s\n"), MY_EMAIL);
exit(1);
}