Репозитории ALT
S: | 4.06.0.7.100b-alt1 |
5.1: | 3.14-alt1 |
4.1: | 3.14-alt1 |
4.0: | 3.14-alt1 |
3.0: | 3.13-alt1 |
Группа :: Система/Настройка/Прочее
Пакет: quota
Главная Изменения Спек Патчи Sources Загрузить Gear Bugs and FR Repocop
Патч: quota-3.14-alt1.patch
Скачать
Скачать
Changelog | 13 +++++
Makefile.in | 9 ++--
bylabel.c | 8 ++--
common.c | 4 +-
common.h | 8 ++--
configure.in | 17 +++++++
edquota.8 | 4 +-
edquota.c | 12 +++++-
quot.c | 2 +-
quota.1 | 43 ++++++++++++++----
quota.c | 17 +++++--
quotacheck.c | 14 ++++--
quotacheck_v2.c | 6 +-
quotagrpadmins | 4 +-
quotaio.c | 2 +-
quotaio_v2.c | 2 +-
quotaon.8 | 19 +++++---
quotaon.c | 14 ++++--
quotaon_xfs.c | 62 +++++++++++++++----------
quotaops.c | 29 +++++++-----
quotastats.c | 7 ++-
quotasys.c | 136 ++++++++++++++++++++++++++++++++++---------------------
quotasys.h | 6 ++-
quotatab | 4 +-
repquota.8 | 9 +++-
repquota.c | 28 +++++++++--
rquota_svc.c | 2 +-
warnquota.conf | 16 +++---
xqmstats.c | 3 +-
29 files changed, 331 insertions(+), 169 deletions(-)
diff --git a/Changelog b/Changelog
index 4e8e4bf..f6b6e37 100644
--- a/Changelog
+++ b/Changelog
@@ -1,3 +1,16 @@
+Changes in quota-tools from 3.14 to 3.15
+* pot.o is now compiled with CFLAGS (Ladislav Michnovic)
+* use -fPIE for compilation when available (Jan Kara, Ladislav Michnovic)
+* fixed some more problems XFS quotaon (Kouta Ooizumi, Jan Kara)
+* fixed two mistakes in quotaon(8) manpage (Utako Kusaka)
+* added option -A to quota(1) to report all NFS mountpoints (Jan Kara)
+* fixed XFS handling to work with loopback mounted devices (Jan Kara)
+* fixed mountpoints scanning to make XFS -x delete command work (Jan Kara)
+* fixes of signed vs unsigned int issues (Jan Kara)
+* fixed a format string bug in reporting of raw grace times in repquota (Jan Kara)
+* added repquota(8) option for better parsable output (Jan Kara)
+* fixed error handling in edquota(8) when creating tmp file (Jan Kara)
+
Changes in quota-tools from 3.13 to 3.14
* updated Polish translations (Jakub Bogusz)
* print user/group names in error messages when cannot get quota information (Michal Marek, Jan Kara)
diff --git a/Makefile.in b/Makefile.in
index c4a1ecc..8846cb8 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -1,7 +1,7 @@
PROGS = quotacheck quotaon quota quot repquota warnquota quotastats xqmstats edquota setquota convertquota rpc.rquotad
SOURCES = bylabel.c common.c convertquota.c edquota.c pot.c quot.c quota.c quotacheck.c quotacheck_v1.c quotacheck_v2.c quotaio.c quotaio_rpc.c quotaio_v1.c quotaio_v2.c quotaio_xfs.c quotaio_generic.c quotaon.c quotaon_xfs.c quotaops.c quotastats.c quotasys.c repquota.c rquota_client.c rquota_server.c rquota_svc.c setquota.c warnquota.c xqmstats.c svc_socket.c
VERSIONDEF = -DQUOTA_VERSION=\"3.14\"
-CFLAGS = @CFLAGS@ @EXT2_DIRECT@ -D_GNU_SOURCE -Wall -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 $(VERSIONDEF)
+CFLAGS = @CFLAGS@ @DEFS@ @EXT2_DIRECT@ -Wall $(VERSIONDEF)
EXT2LIBS = @EXT2LIBS@
RPCSRC = rquota.h rquota_xdr.c rquota_clnt.c
LIBS = @LIBS@
@@ -44,7 +44,7 @@ LIBOBJS += @LIBMALLOC@
.PHONY: all clean clobber realclean pot mo inst_mo
.%.d: %.c
- set -e; $(CC) -MM -MG $(CPPFLAGS) $< | \
+ set -e; $(CC) -MM -MG $(CPPFLAGS) $(CFLAGS) $< | \
sed 's/\($*\)\.o[ :]*/\1.o $@ : /g' > $@; \
[ -s $@ ] || rm -f $@
@@ -96,8 +96,8 @@ install: all @INSTMO@
-mkdir -p $(ROOTDIR)$(mandir)/man8
-$(INSTALL) -m 755 -d $(ROOTDIR)$(includedir)/rpcsvc
-$(INSTALL) -m 644 rquota.h rquota.x $(ROOTDIR)$(includedir)/rpcsvc
- -$(INSTALL) -s -m $(DEF_SBIN_MODE) quota $(ROOTDIR)$(bindir)
- -$(INSTALL) -s -m $(DEF_SBIN_MODE) rpc.rquotad $(ROOTDIR)$(sbindir)
+ -$(INSTALL) -m $(DEF_SBIN_MODE) quota $(ROOTDIR)$(bindir)
+ -$(INSTALL) -m $(DEF_SBIN_MODE) rpc.rquotad $(ROOTDIR)$(sbindir)
-$(INSTALL) -m $(DEF_MAN_MODE) *.1 $(ROOTDIR)$(mandir)/man1
-$(INSTALL) -m $(DEF_MAN_MODE) *.2 $(ROOTDIR)$(mandir)/man2
-$(INSTALL) -m $(DEF_MAN_MODE) *.3 $(ROOTDIR)$(mandir)/man3
@@ -131,7 +131,6 @@ rpc.rquotad: rquota_server.o rquota_svc.o svc_socket.o $(LIBOBJS)
$(CC) $(LDFLAGS) -o $@ $^ $(LIBS)
pot.o: pot.c pot.h
- $(CC) $(CFLAGS) -c $<
rquota.h: rquota.x
$(RPCGEN) -h -o $@ $<
diff --git a/bylabel.c b/bylabel.c
index ebf3a9e..37d761a 100644
--- a/bylabel.c
+++ b/bylabel.c
@@ -90,7 +90,7 @@ static int get_label_uuid(const char *device, char **label, char *uuid)
memcpy(uuid, e2sb.s_uuid, sizeof(e2sb.s_uuid));
namesize = sizeof(e2sb.s_volume_name);
*label = smalloc(namesize + 1);
- sstrncpy(*label, e2sb.s_volume_name, namesize);
+ sstrncpy(*label, (char *)e2sb.s_volume_name, namesize);
rv = 0;
}
else if (lseek(fd, 0, SEEK_SET) == 0
@@ -100,7 +100,7 @@ static int get_label_uuid(const char *device, char **label, char *uuid)
memcpy(uuid, xfsb.s_uuid, sizeof(xfsb.s_uuid));
namesize = sizeof(xfsb.s_fsname);
*label = smalloc(namesize + 1);
- sstrncpy(*label, xfsb.s_fsname, namesize);
+ sstrncpy(*label, (char *)xfsb.s_fsname, namesize);
rv = 0;
}
else if (lseek(fd, 65536, SEEK_SET) == 65536
@@ -109,7 +109,7 @@ static int get_label_uuid(const char *device, char **label, char *uuid)
memcpy(uuid, reisersb.s_uuid, sizeof(reisersb.s_uuid));
namesize = sizeof(reisersb.s_volume_name);
*label = smalloc(namesize + 1);
- sstrncpy(*label, reisersb.s_volume_name, namesize);
+ sstrncpy(*label, (char *)reisersb.s_volume_name, namesize);
rv = 0;
}
close(fd);
@@ -245,7 +245,7 @@ static char *get_spec_by_uuid(const char *s)
uuid[i] = ((fromhex(s[0]) << 4) | fromhex(s[1]));
s += 2;
}
- return get_spec_by_x(UUID, uuid);
+ return get_spec_by_x(UUID, (char *)uuid);
bad_uuid:
errstr(_("Found an invalid UUID: %s\n"), s);
diff --git a/common.c b/common.c
index a53728f..f1e8cfb 100644
--- a/common.c
+++ b/common.c
@@ -94,13 +94,13 @@ void *srealloc(void *ptr, size_t size)
return ret;
}
-void sstrncpy(char *d, const char *s, int len)
+void sstrncpy(char *d, const char *s, size_t len)
{
strncpy(d, s, len);
d[len - 1] = 0;
}
-void sstrncat(char *d, const char *s, int len)
+void sstrncat(char *d, const char *s, size_t len)
{
strncat(d, s, len);
d[len - 1] = 0;
diff --git a/common.h b/common.h
index 2085571..28bd2f0 100644
--- a/common.h
+++ b/common.h
@@ -19,10 +19,10 @@
extern char *progname;
/* Finish programs being */
-void die(int, char *, ...) __attribute__ ((__format__ (__printf__, 2, 3)));
+void die(int, char *, ...) __attribute__((__noreturn__, __format__(__printf__, 2, 3)));
/* Print an error */
-void errstr(char *, ...) __attribute__ ((__format__ (__printf__, 1, 2)));
+void errstr(char *, ...) __attribute__((__format__(__printf__, 1, 2)));
/* If use_syslog is called, all error reports using errstr() and die() are
* written to syslog instead of stderr */
@@ -35,10 +35,10 @@ void *smalloc(size_t);
void *srealloc(void *, size_t);
/* Safe strncpy - always finishes string */
-void sstrncpy(char *, const char *, int);
+void sstrncpy(char *, const char *, size_t);
/* Safe strncat - always finishes string */
-void sstrncat(char *, const char *, int);
+void sstrncat(char *, const char *, size_t);
/* Safe version of strdup() */
char *sstrdup(const char *s);
diff --git a/configure.in b/configure.in
index 6177da2..951e6a0 100644
--- a/configure.in
+++ b/configure.in
@@ -2,9 +2,26 @@ dnl Process this file with autoconf to produce a configure script.
AC_INIT(quota.c)
dnl Checks for programs.
+AC_GNU_SOURCE
AC_PROG_CC
AC_HEADER_STDC
AC_PROG_INSTALL
+AC_SYS_LARGEFILE
+
+dnl Check for compiler options
+AC_MSG_CHECKING(whether compiler supports PIE)
+oldCFLAGS="$CFLAGS"
+CFLAGS="$CFLAGS -fPIE"
+oldLDFLAGS="$LDFLAGS"
+LDFLAGS="$LDFLAGS -pie"
+AC_LINK_IFELSE([AC_LANG_PROGRAM([[]])], compilepie="yes")
+if test "x$compilepie" != "xyes"; then
+ CFLAGS="$oldCFLAGS"
+ LDFLAGS="$oldLDFLAGS"
+ AC_MSG_RESULT(no)
+else
+ AC_MSG_RESULT(yes)
+fi
dnl Checks for libraries.
AC_ARG_ENABLE(ldapmail, [ --enable-ldapmail=[yes/no/try] Enable ldap mail address lookups [default=no].],
diff --git a/edquota.8 b/edquota.8
index 320c00a..2c3c304 100644
--- a/edquota.8
+++ b/edquota.8
@@ -77,7 +77,7 @@ reads the temporary file and modifies the binary quota files to reflect
the changes made.
.LP
The editor invoked is
-.BR vi (1)
+.BR vitmp (1)
unless either the
.SB EDITOR
or the
@@ -150,7 +150,7 @@ mounted filesystems table
.PD
.SH SEE ALSO
.BR quota (1),
-.BR vi (1),
+.BR vitmp (1),
.BR quotactl (2),
.BR quotacheck (8),
.BR quotaon (8),
diff --git a/edquota.c b/edquota.c
index c1ff914..9d654ee 100644
--- a/edquota.c
+++ b/edquota.c
@@ -251,7 +251,16 @@ int main(int argc, char **argv)
strcpy(tmpfil, tmpdir);
strcat(tmpfil, "/EdP.aXXXXXX");
tmpfd = mkstemp(tmpfil);
- fchown(tmpfd, getuid(), getgid());
+ if (tmpfd < 0) {
+ errstr(_("Cannot create temporary file: %s\n"), strerror(errno));
+ ret = -1;
+ goto out;
+ }
+ if (fchown(tmpfd, getuid(), getgid()) < 0) {
+ errstr(_("Cannot change owner of temporary file: %s\n"), strerror(errno));
+ ret = -1;
+ goto out;
+ }
ret = 0;
if (flags & FL_EDIT_PERIOD) {
if (writetimes(handles, tmpfd) < 0) {
@@ -318,6 +327,7 @@ int main(int argc, char **argv)
freeprivs(curprivs);
}
}
+out:
if (dispose_handle_list(handles) == -1)
ret = -1;
diff --git a/quot.c b/quot.c
index 2184f80..77701b5 100644
--- a/quot.c
+++ b/quot.c
@@ -339,7 +339,7 @@ static void acctXFS(xfs_bstat_t *p)
static void checkXFS(const char *file, char *fsdir)
{
xfs_fsop_bulkreq_t bulkreq;
- __s64 last = 0;
+ __u64 last = 0;
__s32 count;
int i;
int sts;
diff --git a/quota.1 b/quota.1
index 355649c..601dced 100644
--- a/quota.1
+++ b/quota.1
@@ -7,18 +7,25 @@ quota \- display disk usage and limits
.B -F
.I format-name
] [
-.BR -guvsilw \ |
-.B q
-]
+.B -guqvswi
+] [
+.BR -l \ |
+[
+.BR -Q \ |\ -A
+]]
.br
.B quota
[
.B -F
.I format-name
] [
-.BR -uvsilw \ |
-.B q
-]
+.B -qvswi
+] [
+.BR -l \ |
+[
+.BR -Q \ |\ -A
+]]
+.B -u
.IR user ...
.br
.B quota
@@ -26,10 +33,24 @@ quota \- display disk usage and limits
.B -F
.I format-name
] [
-.BR -gvsilw \ |
-.B q
-]
+.B -qvswi
+] [
+.BR -l \ |
+[
+.BR -Q \ |\ -A
+]]
+.B -g
.IR group ...
+.br
+.B quota
+[
+.B -F
+.I format-name
+] [
+.B -qvswugQ
+]
+.B -f
+.IR filesystem ...
.SH DESCRIPTION
.B quota
displays users' disk usage and limits.
@@ -79,6 +100,10 @@ ignore mountpoints mounted by automounter
.B -l, --local-only
report quotas only on local filesystems (ie. ignore NFS mounted filesystems).
.TP
+.B -A, --all-nfs
+report quotas for all NFS filesystems even if they report to be on the same
+device.
+.TP
.B -q, --quiet
Print a more terse message,
containing only information
diff --git a/quota.c b/quota.c
index 0126059..221ccb8 100644
--- a/quota.c
+++ b/quota.c
@@ -43,6 +43,7 @@
#include <sys/param.h>
#include <getopt.h>
#include <stdio.h>
+#include <stdlib.h>
#include <pwd.h>
#include <grp.h>
#include <time.h>
@@ -71,6 +72,7 @@
#define FL_NOWRAP 256
#define FL_FSLIST 512
#define FL_NUMNAMES 1024
+#define FL_NFSALL 2048
int flags, fmt = -1;
char *progname;
@@ -78,9 +80,9 @@ char *progname;
void usage(void)
{
errstr( "%s%s%s%s%s",
- _("Usage: quota [-guqvsw] [-l | -Q] [-i] [-F quotaformat]\n"),
- _("\tquota [-qvsw] [-l | -Q] [-i] [-F quotaformat] -u username ...\n"),
- _("\tquota [-qvsw] [-l | -Q] [-i] [-F quotaformat] -g groupname ...\n"),
+ _("Usage: quota [-guqvsw] [-l | [-Q | -A]] [-i] [-F quotaformat]\n"),
+ _("\tquota [-qvsw] [-l | [-Q | -A]] [-i] [-F quotaformat] -u username ...\n"),
+ _("\tquota [-qvsw] [-l | [-Q | -A]] [-i] [-F quotaformat] -g groupname ...\n"),
_("\tquota [-qvswugQ] [-F quotaformat] -f filesystem ...\n"),
_("\n\
-u, --user display quota for user\n\
@@ -97,6 +99,7 @@ void usage(void)
-i, --no-autofs do not query autofs mountpoints\n\
-F, --format=formatname display quota of a specific format\n\
-f, --filesystem-list display quota information only for given filesystems\n\
+-A, --nfs-all display quota for all NFS mountpoints\n\
-h, --help display this help message and exit\n\
-V, --version display version information and exit\n\n"));
fprintf(stderr, _("Bugs to: %s\n"), MY_EMAIL);
@@ -126,7 +129,7 @@ int showquotas(int type, qid_t id, int mntcnt, char **mnt)
time(&now);
id2name(id, type, name);
- handles = create_handle_list(mntcnt, mnt, type, fmt, IOI_READONLY, ((flags & FL_NOAUTOFS) ? MS_NO_AUTOFS : 0) | ((flags & FL_LOCALONLY) ? MS_LOCALONLY : 0));
+ handles = create_handle_list(mntcnt, mnt, type, fmt, IOI_READONLY, ((flags & FL_NOAUTOFS) ? MS_NO_AUTOFS : 0) | ((flags & FL_LOCALONLY) ? MS_LOCALONLY : 0) | ((flags & FL_NFSALL) ? MS_NFS_ALL : 0));
qlist = getprivs(id, handles, !!(flags & FL_QUIETREFUSE));
over = 0;
for (q = qlist; q; q = q->dq_next) {
@@ -229,13 +232,14 @@ int main(int argc, char **argv)
{ "format", 1, NULL, 'F' },
{ "no-wrap", 0, NULL, 'w' },
{ "filesystem-list", 0, NULL, 'f' },
+ { "all-nfs", 0, NULL, 'A' },
{ NULL, 0, NULL, 0 }
};
gettexton();
progname = basename(argv[0]);
- while ((ret = getopt_long(argc, argv, "guqvsVliQF:wf", long_opts, NULL)) != -1) {
+ while ((ret = getopt_long(argc, argv, "guqvsVliQF:wfA", long_opts, NULL)) != -1) {
switch (ret) {
case 'g':
flags |= FL_GROUP;
@@ -274,6 +278,9 @@ int main(int argc, char **argv)
case 'f':
flags |= FL_FSLIST;
break;
+ case 'A':
+ flags |= FL_NFSALL;
+ break;
case 'V':
version();
exit(0);
diff --git a/quotacheck.c b/quotacheck.c
index 1f11296..a12c112 100644
--- a/quotacheck.c
+++ b/quotacheck.c
@@ -3,7 +3,7 @@
* Utility to check disk quotas
*
* Some parts of this utility are copied from old quotacheck by
- * Marco van Wieringen <mvw@planets.elm.net> and Edvard Tuinder <ed@elm.ent>
+ * Marco van Wieringen <mvw@planets.elm.net> and Edvard Tuinder <ed@elm.net>
*
* New quota format implementation - Jan Kara <jack@suse.cz> - Sponsored by SuSE CR
*/
@@ -516,7 +516,10 @@ static int scan_dir(char *pathname)
if ((dp = opendir(pathname)) == (DIR *) NULL)
die(2, _("\nCan open directory %s: %s\n"), pathname, strerror(errno));
- chdir(pathname);
+ if (chdir(pathname)) {
+ errstr(_("Cannot chdir to %s: %s\n"), pathname, strerror(errno));
+ goto out;
+ }
if (flags & FL_VERYVERBOSE)
blit(pathname);
while ((de = readdir(dp)) != (struct dirent *)NULL) {
@@ -601,7 +604,8 @@ int ask_yn(char *q, int def)
printf("%s [%c]: ", q, def ? 'y' : 'n');
fflush(stdout);
while (1) {
- fgets(a, sizeof(a)-1, stdin);
+ if (!fgets(a, sizeof(a)-1, stdin))
+ a[0] = '\0';
if (a[0] == '\n')
return def;
if (!strcasecmp(a, "y\n"))
@@ -1039,11 +1043,11 @@ static void check_all(void)
continue;
}
cfmt = fmt;
- if (uwant && hasquota(mnt, USRQUOTA))
+ if (uwant && hasquota(mnt, USRQUOTA, 0))
ucheck = 1;
else
ucheck = 0;
- if (gwant && hasquota(mnt, GRPQUOTA))
+ if (gwant && hasquota(mnt, GRPQUOTA, 0))
gcheck = 1;
else
gcheck = 0;
diff --git a/quotacheck_v2.c b/quotacheck_v2.c
index fe607a1..f567a2a 100644
--- a/quotacheck_v2.c
+++ b/quotacheck_v2.c
@@ -223,7 +223,7 @@ static void check_read_blk(int fd, uint blk, dqbuf_t buf)
}
}
-static int check_tree_ref(uint blk, uint ref, uint blocks, int check_use, uint * corrupted,
+static int check_tree_ref(uint blk, uint ref, uint blocks, int check_use, int * corrupted,
uint * lblk)
{
if (check_blkref(ref, blocks) < 0) {
@@ -239,7 +239,7 @@ static int check_tree_ref(uint blk, uint ref, uint blocks, int check_use, uint *
}
/* Check block with structures */
-static int check_data_blk(int fd, uint blk, int type, uint blocks, uint * corrupted, uint * lblk)
+static int check_data_blk(int fd, uint blk, int type, uint blocks, int * corrupted, uint * lblk)
{
dqbuf_t buf = getdqbuf();
struct v2_disk_dqdbheader *head = (struct v2_disk_dqdbheader *)buf;
@@ -265,7 +265,7 @@ static int check_data_blk(int fd, uint blk, int type, uint blocks, uint * corrup
}
/* Check one tree block */
-static int check_tree_blk(int fd, uint blk, int depth, int type, uint blocks, uint * corrupted,
+static int check_tree_blk(int fd, uint blk, int depth, int type, uint blocks, int * corrupted,
uint * lblk)
{
dqbuf_t buf = getdqbuf();
diff --git a/quotagrpadmins b/quotagrpadmins
index a1f2f46..e3d5549 100644
--- a/quotagrpadmins
+++ b/quotagrpadmins
@@ -4,5 +4,5 @@
# Comments begin with hash in the beginning of the line
# In this file you specify users responsible for space used by the group
-users: root
-mygroup: chief
+# users: root
+# mygroup: chief
diff --git a/quotaio.c b/quotaio.c
index b194666..bb87c4e 100644
--- a/quotaio.c
+++ b/quotaio.c
@@ -42,7 +42,7 @@ struct quota_handle *init_io(struct mntent *mnt, int type, int fmt, int flags)
struct quota_handle *h = smalloc(sizeof(struct quota_handle));
const char *mnt_fsname = NULL;
- if (!hasquota(mnt, type))
+ if (!hasquota(mnt, type, 0))
goto out_handle;
if (!(mnt_fsname = get_device_name(mnt->mnt_fsname)))
goto out_handle;
diff --git a/quotaio_v2.c b/quotaio_v2.c
index bf4aed0..39d0517 100644
--- a/quotaio_v2.c
+++ b/quotaio_v2.c
@@ -471,7 +471,7 @@ static int do_insert_tree(struct quota_handle *h, struct dquot *dquot, uint * tr
/* Wrapper for inserting quota structure into tree */
static inline void dq_insert_tree(struct quota_handle *h, struct dquot *dquot)
{
- int tmp = V2_DQTREEOFF;
+ uint tmp = V2_DQTREEOFF;
if (do_insert_tree(h, dquot, &tmp, 0) < 0)
die(2, _("Cannot write quota (id %u): %s\n"), (uint) dquot->dq_id, strerror(errno));
diff --git a/quotaon.8 b/quotaon.8
index 3b199dd..c15d13d 100644
--- a/quotaon.8
+++ b/quotaon.8
@@ -3,7 +3,7 @@
.SH NAME
quotaon, quotaoff \- turn filesystem quotas on and off
.SH SYNOPSIS
-.B /usr/sbin/quotaon
+.B /sbin/quotaon
[
.B \-vugfp
] [
@@ -12,7 +12,7 @@ quotaon, quotaoff \- turn filesystem quotas on and off
]
.IR filesystem .\|.\|.
.br
-.B /usr/sbin/quotaon
+.B /sbin/quotaon
[
.B \-avugfp
] [
@@ -20,7 +20,7 @@ quotaon, quotaoff \- turn filesystem quotas on and off
.I format-name
]
.LP
-.B /usr/sbin/quotaoff
+.B /sbin/quotaoff
[
.B \-vugp
]
@@ -30,7 +30,7 @@ quotaon, quotaoff \- turn filesystem quotas on and off
]
.IR filesystem .\|.\|.
.br
-.B /usr/sbin/quotaoff
+.B /sbin/quotaoff
[
.B \-avugp
]
@@ -152,7 +152,7 @@ ignored for other filesystem types.
It can only be used on a filesystem with quota previously turned off.
.TP
.B -x, --xfs-command enforce
-Switch off limit enforcement for XFS filesystems (perform
+Switch on/off limit enforcement for XFS filesystems (perform
quota accounting only).
This option is only applicable to XFS, and is silently
ignored for other filesystem types.
@@ -172,15 +172,18 @@ boot option.
.PP
To turn off quota limit enforcement on any XFS filesystem, first make
sure that quota accounting and enforcement are both turned on using
-.BR "repquota -s" .
+.B "repquota -v"
+.IR filesystem .
Then, use
-.B "quotaoff -vo"
+.B "quotaoff -v
+.I filesystem
to disable limit enforcement.
This may be done while the filesystem is mounted.
.PP
Turning on quota limit enforcement on an XFS filesystem is
achieved using
-.BR "quotaon -v" .
+.B "quotaon -v"
+.IR filesystem .
This may be done while the filesystem is mounted.
.SH FILES
.PD 0
diff --git a/quotaon.c b/quotaon.c
index 8d3034f..98a8124 100644
--- a/quotaon.c
+++ b/quotaon.c
@@ -174,7 +174,7 @@ static int newstate(struct mntent *mnt, int type, char *extra)
ret = xfs_newstate(mnt, type, extra, sflags);
}
else {
- if (!hasquota(mnt, type))
+ if (!hasquota(mnt, type, 0))
return 0;
usefmt = get_qf_name(mnt, type, fmt == -1 ? kernel_formats : (1 << fmt), NF_FORMAT, &extra);
if (usefmt < 0) {
@@ -234,6 +234,12 @@ static int quotaonoff(char *quotadev, char *quotadir, char *quotafile, int type,
if (kernel_iface == IFACE_GENERIC) {
qcmd = QCMD(Q_QUOTAON, type);
kqf = util2kernfmt(fmt);
+ if ((QFMT_VFS_OLD == kqf) &&
+ system("/sbin/modprobe -k quota_v1"))
+ ; /* ignore return code */
+ else if ((QFMT_VFS_V0 == kqf) &&
+ system("/sbin/modprobe -k quota_v2"))
+ ; /* ignore return code */
}
else {
qcmd = QCMD(Q_6_5_QUOTAON, type);
@@ -301,7 +307,7 @@ int v1_newstate(struct mntent *mnt, int type, char *file, int flags)
return 1;
if ((flags & STATEFLAG_OFF) && hasmntopt(mnt, MNTOPT_RSQUASH))
errs += quotarsquashonoff(dev, type, flags);
- if (hasquota(mnt, type))
+ if (hasquota(mnt, type, 0))
errs += quotaonoff((char *)dev, mnt->mnt_dir, file, type, QF_VFSOLD, flags);
if ((flags & STATEFLAG_ON) && hasmntopt(mnt, MNTOPT_RSQUASH))
errs += quotarsquashonoff(dev, type, flags);
@@ -319,7 +325,7 @@ int v2_newstate(struct mntent *mnt, int type, char *file, int flags)
if (!dev)
return 1;
- if (hasquota(mnt, type))
+ if (hasquota(mnt, type, 0))
errs = quotaonoff((char *)dev, mnt->mnt_dir, file, type, QF_VFSV0, flags);
free((char *)dev);
return errs;
@@ -346,7 +352,7 @@ int main(int argc, char **argv)
else if (!kernel_formats)
errstr(_("Warning: No quota format detected in the kernel.\n"));
- if (init_mounts_scan(mntcnt, mntpoints, 0) < 0)
+ if (init_mounts_scan(mntcnt, mntpoints, MS_XFS_DISABLED) < 0)
return 1;
while ((mnt = get_next_mount())) {
if (nfs_fstype(mnt->mnt_type)) {
diff --git a/quotaon_xfs.c b/quotaon_xfs.c
index a9aed6f..5707619 100644
--- a/quotaon_xfs.c
+++ b/quotaon_xfs.c
@@ -21,10 +21,11 @@
* Ensure we don't attempt to go into a dodgey state.
*/
-static int xfs_state_check(int qcmd, int type, int flags, char *dev, int roothack, int *xopts)
+static int xfs_state_check(int qcmd, int type, int flags, char *dev, int roothack, int xopts)
{
struct xfs_mem_dqinfo info;
int state;
+ char *acctstr = "";
/* we never want to operate via -a in XFS quota */
if (flags & STATEFLAG_ALL)
@@ -57,13 +58,11 @@ static int xfs_state_check(int qcmd, int type, int flags, char *dev, int roothac
return 1;
case Q_XFS_QUOTAON:
if (roothack) {
- *xopts |= (type == USRQUOTA) ?
- XFS_QUOTA_UDQ_ACCT : XFS_QUOTA_GDQ_ACCT;
printf(_("Enabling %s quota on root filesystem"
" (reboot to take effect)\n"), type2name(type));
return 1;
}
- errstr(_("Enable XFS %s quota during mount\n"),
+ errstr(_("Enable XFS %s quota accounting during mount\n"),
type2name(type));
return -1;
case Q_XFS_QUOTAOFF:
@@ -79,20 +78,26 @@ static int xfs_state_check(int qcmd, int type, int flags, char *dev, int roothac
return -1;
case Q_XFS_QUOTAON:
if (roothack) {
- *xopts |= (type == USRQUOTA) ?
- XFS_QUOTA_UDQ_ACCT : XFS_QUOTA_GDQ_ACCT;
printf(_("Enabling %s quota on root filesystem"
" (reboot to take effect)\n"), type2name(type));
return 1;
}
- printf(_("Enabling %s quota accounting on %s\n"), type2name(type), dev);
- *xopts |= (type == USRQUOTA) ? XFS_QUOTA_UDQ_ACCT : XFS_QUOTA_GDQ_ACCT;
- return 1;
+ if (xopts & XFS_QUOTA_UDQ_ENFD || xopts & XFS_QUOTA_GDQ_ENFD) {
+ printf(_("Enabling %s quota enforcement on %s\n"), type2name(type), dev);
+ return 1;
+ }
+ errstr(_("Already accounting %s quota on %s\n"),
+ type2name(type), dev);
+ return -1;
case Q_XFS_QUOTAOFF:
- printf(_("Disabling %s quota accounting on %s\n"),
- type2name(type), dev);
- *xopts |= (type == USRQUOTA) ? XFS_QUOTA_UDQ_ACCT : XFS_QUOTA_GDQ_ACCT;
- return 1;
+ if (xopts & XFS_QUOTA_UDQ_ACCT || xopts & XFS_QUOTA_GDQ_ACCT) {
+ printf(_("Disabling %s quota accounting on %s\n"),
+ type2name(type), dev);
+ return 1;
+ }
+ errstr(_("Quota enforcement already disabled for %s on %s\n"),
+ type2name(type), dev);
+ return -1;
}
break;
@@ -100,7 +105,7 @@ static int xfs_state_check(int qcmd, int type, int flags, char *dev, int roothac
switch (qcmd) {
case Q_XFS_QUOTARM:
errstr(_("Cannot delete %s quota on %s - "
- "switch quota enforcement off first\n"),
+ "switch quota enforcement and accounting off first\n"),
type2name(type), dev);
return -1;
case Q_XFS_QUOTAON:
@@ -108,9 +113,16 @@ static int xfs_state_check(int qcmd, int type, int flags, char *dev, int roothac
type2name(type), dev);
return -1;
case Q_XFS_QUOTAOFF:
- printf(_("Disabling %s quota enforcement on %s\n"),
- type2name(type), dev);
- *xopts |= (type == USRQUOTA) ? XFS_QUOTA_UDQ_ENFD : XFS_QUOTA_GDQ_ENFD;
+ if (xopts == XFS_QUOTA_UDQ_ACCT || xopts == XFS_QUOTA_GDQ_ACCT) {
+ errstr(_("Cannot switch off %s quota"
+ "accounting on %s when enforcement is on\n"),
+ type2name(type), dev);
+ return -1;
+ }
+ if (xopts & XFS_QUOTA_UDQ_ACCT || xopts & XFS_QUOTA_GDQ_ACCT)
+ acctstr = _("and accounting ");
+ printf(_("Disabling %s quota enforcement %son %s\n"),
+ type2name(type), acctstr, dev);
return 1;
}
break;
@@ -119,7 +131,7 @@ static int xfs_state_check(int qcmd, int type, int flags, char *dev, int roothac
return -1;
}
-static int xfs_onoff(char *dev, int type, int flags, int roothack, int *xopts)
+static int xfs_onoff(char *dev, int type, int flags, int roothack, int xopts)
{
int qoff, qcmd, check;
@@ -129,7 +141,7 @@ static int xfs_onoff(char *dev, int type, int flags, int roothack, int *xopts)
if (check != 1)
return (check < 0);
- if (quotactl(QCMD(qcmd, type), dev, 0, (void *)xopts) < 0) {
+ if (quotactl(QCMD(qcmd, type), dev, 0, (void *)&xopts) < 0) {
errstr(_("quotactl on %s: %s\n"), dev, strerror(errno));
return 1;
}
@@ -140,7 +152,7 @@ static int xfs_onoff(char *dev, int type, int flags, int roothack, int *xopts)
return 0;
}
-static int xfs_delete(char *dev, int type, int flags, int roothack, int *xopts)
+static int xfs_delete(char *dev, int type, int flags, int roothack, int xopts)
{
int qcmd, check;
@@ -149,7 +161,7 @@ static int xfs_delete(char *dev, int type, int flags, int roothack, int *xopts)
if (check != 1)
return (check < 0);
- if (quotactl(QCMD(qcmd, type), dev, 0, (void *)xopts) < 0) {
+ if (quotactl(QCMD(qcmd, type), dev, 0, (void *)&xopts) < 0) {
errstr(_("Failed to delete quota: %s\n"),
strerror(errno));
return 1;
@@ -199,22 +211,22 @@ int xfs_newstate(struct mntent *mnt, int type, char *xarg, int flags)
xopts |= (type == USRQUOTA) ?
(XFS_QUOTA_UDQ_ACCT | XFS_QUOTA_UDQ_ENFD) :
(XFS_QUOTA_GDQ_ACCT | XFS_QUOTA_GDQ_ENFD);
- err = xfs_onoff((char *)dev, type, flags, roothack, &xopts);
+ err = xfs_onoff((char *)dev, type, flags, roothack, xopts);
}
else if (strcmp(xarg, "account") == 0) {
/* only useful if we want root accounting only */
if (!roothack || !(flags & STATEFLAG_ON))
goto done;
xopts |= (type == USRQUOTA) ? XFS_QUOTA_UDQ_ACCT : XFS_QUOTA_GDQ_ACCT;
- err = xfs_onoff((char *)dev, type, flags, roothack, &xopts);
+ err = xfs_onoff((char *)dev, type, flags, roothack, xopts);
}
else if (strcmp(xarg, "enforce") == 0) {
xopts |= (type == USRQUOTA) ? XFS_QUOTA_UDQ_ENFD : XFS_QUOTA_GDQ_ENFD;
- err = xfs_onoff((char *)dev, type, flags, roothack, &xopts);
+ err = xfs_onoff((char *)dev, type, flags, roothack, xopts);
}
else if (strcmp(xarg, "delete") == 0) {
xopts |= (type == USRQUOTA) ? XFS_USER_QUOTA : XFS_GROUP_QUOTA;
- err = xfs_delete((char *)dev, type, flags, roothack, &xopts);
+ err = xfs_delete((char *)dev, type, flags, roothack, xopts);
}
else
die(1, _("Invalid argument \"%s\"\n"), xarg);
diff --git a/quotaops.c b/quotaops.c
index 868279c..9bd09c8 100644
--- a/quotaops.c
+++ b/quotaops.c
@@ -97,8 +97,8 @@ struct dquot *getprivs(qid_t id, struct quota_handle **handles, int quiet)
int j, ngroups;
uid_t euid;
gid_t gidset[NGROUPS], *gidsetp;
- char name[MAXNAMELEN];
#endif
+ char name[MAXNAMELEN];
for (i = 0; handles[i]; i++) {
#if defined(BSD_BEHAVIOUR)
@@ -154,9 +154,12 @@ struct dquot *getprivs(qid_t id, struct quota_handle **handles, int quiet)
if (!(q = handles[i]->qh_ops->read_dquot(handles[i], id))) {
/* If rpc.rquotad is not running filesystem might be just without quotas... */
if (errno != ENOENT && (errno != ECONNREFUSED || !quiet)) {
+ const char *err_text = strerror(errno);
+
id2name(id, handles[i]->qh_type, name);
- errstr(_("error while getting quota from %s for %s (id %u): %s\n"),
- handles[i]->qh_quotadev, name, id, strerror(errno));
+ errstr(_("error while getting %s quota on %s for %s [id %u]: %s\n"),
+ type2name(handles[i]->qh_type),
+ handles[i]->qh_quotadev, name, id, err_text);
}
continue;
}
@@ -218,7 +221,7 @@ int editprivs(char *tmpfile)
setuid(getuid());
if (!(ed = getenv("VISUAL")))
if (!(ed = getenv("EDITOR")))
- ed = _PATH_VI;
+ ed = "/bin/vitmp";
i = 0;
ed = actp = sstrdup(ed);
while (actp) {
@@ -253,9 +256,9 @@ int writeprivs(struct dquot *qlist, int outfd, char *name, int quotatype)
struct dquot *q;
FILE *fd;
- ftruncate(outfd, 0);
- lseek(outfd, 0, SEEK_SET);
- if (!(fd = fdopen(dup(outfd), "w")))
+ if (ftruncate(outfd, 0) ||
+ lseek(outfd, 0, SEEK_SET) ||
+ !(fd = fdopen(dup(outfd), "w")))
die(1, _("Cannot duplicate descriptor of file to write to: %s\n"), strerror(errno));
#if defined(ALT_FORMAT)
@@ -438,9 +441,9 @@ int writeindividualtimes(struct dquot *qlist, int outfd, char *name, int quotaty
time_t now;
char btimestr[MAXTIMELEN], itimestr[MAXTIMELEN];
- ftruncate(outfd, 0);
- lseek(outfd, 0, SEEK_SET);
- if (!(fd = fdopen(dup(outfd), "w")))
+ if (ftruncate(outfd, 0) ||
+ lseek(outfd, 0, SEEK_SET) ||
+ !(fd = fdopen(dup(outfd), "w")))
die(1, _("Cannot duplicate descriptor of file to write to: %s\n"), strerror(errno));
fprintf(fd, _("Times to enforce softlimit for %s %s (%cid %d):\n"),
@@ -540,9 +543,9 @@ int writetimes(struct quota_handle **handles, int outfd)
if (!handles[0])
return 0;
- ftruncate(outfd, 0);
- lseek(outfd, 0, SEEK_SET);
- if ((fd = fdopen(dup(outfd), "w")) == NULL)
+ if (ftruncate(outfd, 0) ||
+ lseek(outfd, 0, SEEK_SET) ||
+ !(fd = fdopen(dup(outfd), "w")))
die(1, _("Cannot duplicate descriptor of file to edit: %s\n"), strerror(errno));
#if defined(ALT_FORMAT)
diff --git a/quotastats.c b/quotastats.c
index e8498ff..95aef84 100644
--- a/quotastats.c
+++ b/quotastats.c
@@ -45,10 +45,13 @@ static int get_proc_num(char *name)
sstrncat(namebuf, name, PATH_MAX);
if (!(f = fopen(namebuf, "r"))) {
- errstr(_("Cannot read stat file %s: %s\n"), namebuf, strerror(errno));
+ errstr(_("Cannot read stat file %s: %m\n"), namebuf);
return -1;
}
- fscanf(f, "%d", &ret);
+ if (fscanf(f, "%d", &ret) < 0) {
+ errstr(_("Failed to read file %s: %m\n"), namebuf);
+ ret = -1;
+ }
fclose(f);
return ret;
}
diff --git a/quotasys.c b/quotasys.c
index a62f79a..a8e2e1b 100644
--- a/quotasys.c
+++ b/quotasys.c
@@ -366,10 +366,10 @@ void space2str(qsize_t space, char *buf, int format)
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]);
+ sprintf(buf, "%Lu%c", (unsigned long long)(space+(1 << (QUOTABLOCK_BITS*i))-1) >> (QUOTABLOCK_BITS*i), suffix[i]);
return;
}
- sprintf(buf, "%Lu", space);
+ sprintf(buf, "%Lu", (unsigned long long)space);
}
/*
@@ -390,21 +390,85 @@ void number2str(unsigned long long num, char *buf, int format)
sprintf(buf, "%Lu", num);
}
+/* Return if given option has nonempty argument */
+static char *hasmntoptarg(struct mntent *mnt, char *opt)
+{
+ char *p = hasmntopt(mnt, opt);
+
+ if (!p)
+ return NULL;
+ p += strlen(opt);
+ if (*p == '=' && p[1] != ',')
+ return p+1;
+ return NULL;
+}
+
+static char *get_loop_device_name(struct mntent *mnt, dev_t *dev)
+{
+ char *opt;
+
+ if (!(opt = hasmntoptarg(mnt, MNTOPT_LOOP)))
+ return NULL;
+
+ char loopdev[PATH_MAX];
+ unsigned i;
+
+ /* Copy the device name */
+ for (i = 0; *opt && *opt != ',' && i < sizeof(loopdev)-1; ++opt, ++i)
+ loopdev[i] = *opt;
+ loopdev[i] = 0;
+
+ struct stat st;
+ if (stat(loopdev, &st) < 0) {
+ errstr(_("Cannot stat() loopback device %s: %s\n"), loopdev, strerror(errno));
+ return NULL;
+ }
+ if (!S_ISBLK(st.st_mode)) {
+ errstr(_("Loopback device %s isn't block device!\n"), loopdev);
+ return NULL;
+ }
+ if (dev)
+ *dev = st.st_rdev;
+ return sstrdup(loopdev);
+}
+
/*
* Check for XFS filesystem with quota accounting enabled
*/
-static int hasxfsquota(struct mntent *mnt, int type)
+static int hasxfsquota(struct mntent *mnt, int type, int flags)
{
- int ret = 0;
+ int rc, ret = 0;
u_int16_t sbflags;
struct xfs_mem_dqinfo info;
- const char *dev = get_device_name(mnt->mnt_fsname);
+ const char *dev;
+ char *opt, *endopt;
+
+ if (flags & MS_XFS_DISABLED)
+ return 1;
+ dev = get_device_name(mnt->mnt_fsname);
if (!dev)
- return ret;
+ return 0;
+ /* Loopback mounted device with a loopback device in the arguments? */
+ if ((opt = hasmntopt(mnt, MNTOPT_LOOP)) && (opt = strchr(opt, '='))) {
+ free((char *)dev);
+ endopt = strchr(opt+1, ',');
+ if (!endopt)
+ dev = strdup(opt+1);
+ else
+ dev = strndup(opt+1, endopt-opt-1);
+ if (!dev)
+ return 0;
+ }
memset(&info, 0, sizeof(struct xfs_mem_dqinfo));
- if (!quotactl(QCMD(Q_XFS_GETQSTAT, type), dev, 0, (void *)&info)) {
+ rc = quotactl(QCMD(Q_XFS_GETQSTAT, type), dev, 0, (void *)&info);
+ if (rc && errno == ENOTBLK) {
+ free((char *)dev);
+ if ((dev = get_loop_device_name(mnt, NULL)))
+ rc = quotactl(QCMD(Q_XFS_GETQSTAT, type), dev, 0, (void *)&info);
+ }
+ if (!rc) {
sbflags = (info.qs_flags & 0xff00) >> 8;
if (type == USRQUOTA && (info.qs_flags & XFS_QUOTA_UDQ_ACCT))
ret = 1;
@@ -428,29 +492,16 @@ static int hasxfsquota(struct mntent *mnt, int type)
return ret;
}
-/* Return if given option has nonempty argument */
-char *hasmntoptarg(struct mntent *mnt, char *opt)
-{
- char *p = hasmntopt(mnt, opt);
-
- if (!p)
- return NULL;
- p += strlen(opt);
- if (*p == '=' && p[1] != ',')
- return p+1;
- return NULL;
-}
-
/*
* Check to see if a particular quota is to be enabled (filesystem mounted with proper option)
*/
-int hasquota(struct mntent *mnt, int type)
+int hasquota(struct mntent *mnt, int type, int flags)
{
if (!correct_fstype(mnt->mnt_type) || hasmntopt(mnt, MNTOPT_NOQUOTA))
return 0;
if (!strcmp(mnt->mnt_type, MNTTYPE_XFS))
- return hasxfsquota(mnt, type);
+ return hasxfsquota(mnt, type, flags);
if (nfs_fstype(mnt->mnt_type)) /* NFS always has quota or better there is no good way how to detect it */
return 1;
@@ -873,7 +924,7 @@ static int cache_mnt_table(int flags)
/* Further we are not interested in mountpoints without quotas and
we don't want to touch them */
- if (!hasquota(mnt, USRQUOTA) && !hasquota(mnt, GRPQUOTA)) {
+ if (!hasquota(mnt, USRQUOTA, flags) && !hasquota(mnt, GRPQUOTA, flags)) {
free((char *)devname);
continue;
}
@@ -913,32 +964,9 @@ static int cache_mnt_table(int flags)
free((char *)devname);
continue; /* We just ignore bind mounts... */
}
- else if ((opt = hasmntopt(mnt, MNTOPT_LOOP))) {
- char loopdev[PATH_MAX];
- int i;
-
- if (!(opt = strchr(opt, '='))) {
- errstr(_("Cannot find device of loopback mount in options for %s. Skipping.\n"), devname);
- free((char *)devname);
- continue;
- }
- /* Copy the device name */
- for (opt++, i = 0; *opt && i < sizeof(loopdev)-1 && *opt != ','; opt++, i++)
- loopdev[i] = *opt;
- loopdev[i] = 0;
- if (stat(loopdev, &st) < 0) { /* Can't stat loopback device? */
- errstr(_("Cannot stat() loopback device %s: %s\n"), opt, strerror(errno));
- free((char *)devname);
- continue;
- }
- if (!S_ISBLK(st.st_mode)) {
- errstr(_("Loopback device %s is not block device!\n"), opt);
- free((char *)devname);
- continue;
- }
- dev = st.st_rdev;
+ else if ((opt = get_loop_device_name(mnt, &dev))) {
free((char *)devname);
- devname = sstrdup(loopdev);
+ devname = opt;
} else {
if (!S_ISBLK(st.st_mode) && !S_ISCHR(st.st_mode))
goto unsupporteddev;
@@ -955,9 +983,13 @@ static int cache_mnt_table(int flags)
continue;
}
if (nfs_fstype(mnt->mnt_type)) {
- /* For network filesystems we must get device from root */
- dev = st.st_dev;
- for (i = 0; i < mnt_entries_cnt && mnt_entries[i].me_dev != dev; i++);
+ if (!(flags & MS_NFS_ALL)) {
+ /* For network filesystems we must get device from root */
+ dev = st.st_dev;
+ for (i = 0; i < mnt_entries_cnt && mnt_entries[i].me_dev != dev; i++);
+ }
+ else /* Always behave as if the device was unique */
+ i = mnt_entries_cnt;
}
}
if (i == mnt_entries_cnt) { /* New mounted device? */
@@ -1124,7 +1156,7 @@ restart:
break;
}
if (i == mnt_entries_cnt) {
- errstr(_("Mountpoint (or device) %s not found.\n"), sd->sd_name);
+ errstr(_("Mountpoint (or device) %s not found or has no quota enabled.\n"), sd->sd_name);
goto restart;
}
*pos = i;
diff --git a/quotasys.h b/quotasys.h
index 578cdb5..642eed3 100644
--- a/quotasys.h
+++ b/quotasys.h
@@ -96,7 +96,8 @@ void space2str(qsize_t, char *, int);
void number2str(unsigned long long, char *, int);
/* Check to see if particular quota is to be enabled */
-int hasquota(struct mntent *mnt, int type);
+/* Recognizes MS_XFS_DISABLED flag */
+int hasquota(struct mntent *mnt, int type, int flags);
/* Flags for get_qf_name() */
#define NF_EXIST 1 /* Check whether file exists */
@@ -130,6 +131,9 @@ int kern_quota_on(const char *dev, int type, int fmt);
#define MS_NO_AUTOFS 0x02 /* Ignore autofs mountpoints */
#define MS_QUIET 0x04 /* Be quiet with error reporting */
#define MS_LOCALONLY 0x08 /* Ignore nfs mountpoints */
+#define MS_XFS_DISABLED 0x10 /* Return also XFS mountpoints with quota disabled */
+#define MS_NFS_ALL 0x20 /* Don't filter NFS mountpoints on the same device */
+
/* Initialize mountpoints scan */
int init_mounts_scan(int dcnt, char **dirs, int flags);
diff --git a/quotatab b/quotatab
index 0ba9957..380a6e6 100644
--- a/quotatab
+++ b/quotatab
@@ -5,5 +5,5 @@
# Comments begin with hash in the beginning of the line
# Example of description
-/dev/loop0: This is loopback device
-/dev/hda4: Your home directory
+#/dev/loop0: This is loopback device
+#/dev/hda4: Your home directory
diff --git a/repquota.8 b/repquota.8
index cb2f196..43a0652 100644
--- a/repquota.8
+++ b/repquota.8
@@ -5,7 +5,7 @@ repquota \- summarize quotas for a filesystem
.SH SYNOPSIS
.B /usr/sbin/repquota
[
-.B \-vsiug
+.B \-vspiug
] [
.B \-c
|
@@ -22,7 +22,7 @@ repquota \- summarize quotas for a filesystem
.LP
.B /usr/sbin/repquota
[
-.B \-avtsiug
+.B \-avtpsiug
] [
.B \-c
|
@@ -95,6 +95,11 @@ Don't resolve UIDs/GIDs to names. This can speedup printing a lot.
Try to report used space, number of used inodes and limits in more appropriate units
than the default ones.
.TP
+.B -p, --raw-grace
+When user is in grace period, report time in seconds since epoch when his grace
+time runs out (or has run out). Field is '0' when no grace time is in effect.
+This is especially useful when parsing output by a script.
+.TP
.B -i, --no-autofs
Ignore mountpoints mounted by automounter.
.TP
diff --git a/repquota.c b/repquota.c
index ab57894..4420566 100644
--- a/repquota.c
+++ b/repquota.c
@@ -34,6 +34,7 @@
#define FL_NONAME 64 /* Don't translate ids to names */
#define FL_NOCACHE 128 /* Don't cache dquots before resolving */
#define FL_NOAUTOFS 256 /* Ignore autofs mountpoints */
+#define FL_RAWGRACE 512 /* Print grace times in seconds since epoch */
int flags, fmt = -1;
char **mnt;
@@ -50,6 +51,7 @@ static void usage(void)
-g, --group display information about groups\n\
-s, --human-readable show numbers in human friendly units (MB, GB, ...)\n\
-t, --truncate-names truncate names to 8 characters\n\
+-p, --raw-grace print grace time in seconds since epoch\n\
-n, --no-names do not translate uid/gid to name\n\
-i, --no-autofs avoid autofs mountpoints\n\
-c, --batch-translation translate big number of ids at once\n\
@@ -73,6 +75,7 @@ static void parse_options(int argcnt, char **argstr)
{ "group", 0, NULL, 'g' },
{ "help", 0, NULL, 'h' },
{ "truncate-names", 0, NULL, 't' },
+ { "raw-grace", 0, NULL, 'p' },
{ "human-readable", 0, NULL, 's' },
{ "no-names", 0, NULL, 'n' },
{ "cache", 0, NULL, 'c' },
@@ -82,7 +85,7 @@ static void parse_options(int argcnt, char **argstr)
{ NULL, 0, NULL, 0 }
};
- while ((ret = getopt_long(argcnt, argstr, "VavughtsncCiF:", long_opts, NULL)) != -1) {
+ while ((ret = getopt_long(argcnt, argstr, "VavughtspncCiF:", long_opts, NULL)) != -1) {
switch (ret) {
case '?':
case 'h':
@@ -105,6 +108,9 @@ static void parse_options(int argcnt, char **argstr)
case 't':
flags |= FL_TRUNCNAMES;
break;
+ case 'p':
+ flags |= FL_RAWGRACE;
+ break;
case 's':
flags |= FL_SHORTNUMS;
break;
@@ -174,9 +180,15 @@ static void print(struct dquot *dquot, char *name)
if (flags & FL_TRUNCNAMES)
pname[PRINTNAMELEN] = 0;
if (entry->dqb_bsoftlimit && toqb(entry->dqb_curspace) >= entry->dqb_bsoftlimit)
- difftime2str(entry->dqb_btime, time);
+ if (flags & FL_RAWGRACE)
+ sprintf(time, "%Lu", (unsigned long long)entry->dqb_btime);
+ else
+ difftime2str(entry->dqb_btime, time);
else
- time[0] = 0;
+ if (flags & FL_RAWGRACE)
+ strcpy(time, "0");
+ else
+ time[0] = 0;
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);
@@ -185,9 +197,15 @@ static void print(struct dquot *dquot, char *name)
overlim(entry->dqb_curinodes, entry->dqb_isoftlimit, entry->dqb_ihardlimit),
numbuf[0], numbuf[1], numbuf[2], time);
if (entry->dqb_isoftlimit && entry->dqb_curinodes >= entry->dqb_isoftlimit)
- difftime2str(entry->dqb_itime, time);
+ if (flags & FL_RAWGRACE)
+ sprintf(time, "%Lu", (unsigned long long)entry->dqb_itime);
+ else
+ difftime2str(entry->dqb_itime, time);
else
- time[0] = 0;
+ if (flags & FL_RAWGRACE)
+ strcpy(time, "0");
+ else
+ time[0] = 0;
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);
diff --git a/rquota_svc.c b/rquota_svc.c
index ce95710..f81199f 100644
--- a/rquota_svc.c
+++ b/rquota_svc.c
@@ -140,7 +140,7 @@ static void parse_options(int argc, char **argv)
break;
case 'p':
port = strtol(optarg, &endptr, 0);
- if (*endptr || port <= 0) {
+ if (*endptr || port <= 0 || port > 0xffff) {
errstr(_("Illegal port number: %s\n"), optarg);
show_help();
exit(1);
diff --git a/warnquota.conf b/warnquota.conf
index d80f7ae..3f13af1 100644
--- a/warnquota.conf
+++ b/warnquota.conf
@@ -4,16 +4,16 @@
# and even blank lines
# values can be quoted:
-MAIL_CMD = "/usr/my/sendmail/instead/sendmail -t"
-FROM = "bas@localhost"
+MAIL_CMD = "/usr/sbin/sendmail -t"
+FROM = "root@localhost"
# but they don't have to be:
-SUBJECT = Hey, user, clean up your account!
-CC_TO = "sysadm@localhost"
+SUBJECT = NOTE: You are exceeding your allocatted disk space limits
+CC_TO = "root@localhost"
# If you set this variable CC will be used only when user has less than
# specified grace time left (examples of possible times: 5 seconds, 1 minute,
# 12 hours, 5 days)
# CC_BEFORE = 2 days
-SUPPORT = "support@myhost.com"
+SUPPORT = "root@myhost.com"
PHONE = "(123) 456-1111 or (222) 333-4444"
# Text in the beginning of the mail (if not specified, default text is used)
# This way text can be split to more lines
@@ -21,11 +21,11 @@ PHONE = "(123) 456-1111 or (222) 333-4444"
# The expressions %i, %h, %d, and %% are substituted for user/group name,
# host name, domain name, and '%' respectively. For backward compatibility
# %s behaves as %i but is deprecated.
-MESSAGE = Hello user %i, I've noticed you use too much space\
- on my disk in %h.%d.|Delete your files on the following filesystems:|
+MESSAGE = Your disk usage has exceeded the agreeded limits on %h.%d.|\
+ Please delete any unnecessary files on the following filesystems:|
# Text in the end of the mail (if not specified, default text using SUPPORT and PHONE
# is created)
-SIGNATURE = See you!| Your admin of %h|
+SIGNATURE = root@%h.%d
# Following text is used for mails about group exceeding quotas
GROUP_MESSAGE = Hello, a group '%i' you're member of use too much space at %h.|\
I chose you to do the cleanup.|Delete group files on the following filesystems:|
diff --git a/xqmstats.c b/xqmstats.c
index 84e8edf..9054de0 100644
--- a/xqmstats.c
+++ b/xqmstats.c
@@ -38,7 +38,8 @@ int main(int argc, char **argv)
}
}
while (!feof(stats)) {
- fgets(buffer, 256, stats);
+ if (!fgets(buffer, 256, stats))
+ continue;
if (sscanf(buffer, "qm %u %u %u %u %u %u %u %u\n",
&values[0], &values[1], &values[2], &values[3],
&values[4], &values[5], &values[6], &values[7]) == 8)