summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--quotacheck.817
-rw-r--r--quotacheck.c84
-rw-r--r--quotacheck.h1
-rw-r--r--quotacheck_v2.c6
-rw-r--r--quotaon.c16
-rw-r--r--quotasys.c25
6 files changed, 86 insertions, 63 deletions
diff --git a/quotacheck.8 b/quotacheck.8
index 7c5f5b2..1fe707b 100644
--- a/quotacheck.8
+++ b/quotacheck.8
@@ -4,7 +4,7 @@ quotacheck \- scan a filesystem for disk usage, create, check and repair quota f
.SH SYNOPSIS
.B quotacheck
[
-.B \-gucfinvdMmR
+.B \-gubcfinvdMmR
] [
.B \-F
.I quota-format
@@ -19,10 +19,10 @@ examines each filesystem, builds a table of current disk usage, and
compares this table against that recorded in the disk quota file for the
filesystem (this step is ommitted if option
.B -c
-is specified). If any inconsistencies are detected, both the quota file
+is specified). If any inconsistencies are detected, both the quota file
and the current system copy of the incorrect quotas are updated (the
-latter only occurs if an active filesystem is checked). By default,
-only user quotas are checked.
+latter only occurs if an active filesystem is checked which is not advised).
+By default, only user quotas are checked.
.B quotacheck
expects each filesystem to be checked to have quota files named
.I [a]quota.user
@@ -70,6 +70,11 @@ ignore the failure to remount the filesystem read-only with option
.BR \-M .
.SH OPTIONS
.TP
+.B \-b
+Forces
+.B quotacheck
+to make backups of the quota file before writing the new data.
+.TP
.B \-v
.B quotacheck
reports its operation as it progresses. Normally it operates silently.
@@ -91,6 +96,8 @@ or on the filesystems specified are to be checked.
.TP
.B \-c
Don't read existing quota files. Just perform a new scan and save it to disk.
+.B quotacheck
+also skips scanning of old quota files when they are not found.
.TP
.B \-f
Forces checking of filesystems with quotas enabled. This is not
@@ -120,7 +127,7 @@ exits or asks user for input. When this option is set, the first entry found
is always used (this option works in interactive mode too).
.TP
.B \-F \f2format-name\f1
-Check quota quota for specified format (ie. don't perform format
+Check quota for specified format (ie. don't perform format
auto-detection). This is recommended as detection might not work well on
corrupted quota files. Possible format names are:
.B vfsold
diff --git a/quotacheck.c b/quotacheck.c
index f12fadd..5bfb41a 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.17 2001/08/30 10:11:24 jkar8572 Exp $"
+#ident "$Id: quotacheck.c,v 1.18 2001/09/04 16:21:58 jkar8572 Exp $"
#include <dirent.h>
#include <stdio.h>
@@ -286,8 +286,11 @@ static void parse_options(int argcnt, char **argstr)
{
int ret;
- while ((ret = getopt(argcnt, argstr, "VhcvugidnfF:mMRa")) != -1) {
- switch (ret) {
+ while ((ret = getopt(argcnt, argstr, "VhbcvugidnfF:mMRa")) != -1) {
+ switch (ret) {
+ case 'b':
+ flags |= FL_BACKUPS;
+ break;
case 'g':
gwant = 1;
break;
@@ -539,7 +542,7 @@ static int process_file(struct mntent *mnt, int type)
char *qfname = NULL;
int fd = -1, ret;
- debug(FL_DEBUG | FL_VERBOSE, _("Going to check %s quota file of %s\n"), type2name(type),
+ debug(FL_DEBUG, _("Going to check %s quota file of %s\n"), type2name(type),
mnt->mnt_dir);
if (kern_quota_on(mnt->mnt_fsname, type, (1 << cfmt)) > 0) { /* Is quota enabled? */
@@ -605,32 +608,34 @@ static int rename_files(struct mntent *mnt, int type)
if (!(filename = get_qf_name(mnt, type, cfmt)))
die(2, _("Cannot get name of old quotafile on %s.\n"), mnt->mnt_dir);
- debug(FL_DEBUG | FL_VERBOSE, _("Data dumped.\nRenaming old quotafile to %s~\n"), filename);
- if (stat(filename, &st) < 0) { /* File doesn't exist? */
- if (errno == ENOENT) {
- debug(FL_DEBUG | FL_VERBOSE, _("Old file not found.\n"));
- goto rename_new;
+ if (flags & FL_BACKUPS) {
+ debug(FL_DEBUG, _("Data dumped.\nRenaming old quotafile to %s~\n"), filename);
+ if (stat(filename, &st) < 0) { /* File doesn't exist? */
+ if (errno == ENOENT) {
+ debug(FL_DEBUG | FL_VERBOSE, _("Old file not found.\n"));
+ goto rename_new;
+ }
+ errstr(_("Error while searching for old quota file %s: %s\n"),
+ filename, strerror(errno));
+ free(filename);
+ return -1;
+ }
+ mode = st.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO);
+ /* Backup old file */
+ strcpy(newfilename, filename);
+ /* Make backingup safe */
+ sstrncat(newfilename, "~", PATH_MAX);
+ if (newfilename[strlen(newfilename) - 1] != '~')
+ die(8, _("Name of quota file too long. Contact %s.\n"), MY_EMAIL);
+ if (rename(filename, newfilename) < 0) {
+ errstr(_("Cannot rename old quotafile %s to %s: %s\n"),
+ filename, newfilename, strerror(errno));
+ free(filename);
+ return -1;
}
- errstr(_("Error while searching for old quota file %s: %s\n"),
- filename, strerror(errno));
- free(filename);
- return -1;
- }
- mode = st.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO);
- /* Backup old file */
- strcpy(newfilename, filename);
- /* Make backingup safe */
- sstrncat(newfilename, "~", PATH_MAX);
- if (newfilename[strlen(newfilename) - 1] != '~')
- die(8, _("Name of quota file too long. Contact %s.\n"), MY_EMAIL);
- if (rename(filename, newfilename) < 0) {
- errstr(_("Cannot rename old quotafile %s to %s: %s\n"),
- filename, newfilename, strerror(errno));
- free(filename);
- return -1;
}
- debug(FL_DEBUG | FL_VERBOSE, _("Renaming new quotafile\n"));
- rename_new:
+ debug(FL_DEBUG, _("Renaming new quotafile\n"));
+rename_new:
/* Rename new file to right name */
strcpy(newfilename, filename);
sstrncat(newfilename, ".new", PATH_MAX);
@@ -660,7 +665,7 @@ static int dump_to_file(struct mntent *mnt, int type)
uint i;
struct quota_handle *h;
- debug(FL_DEBUG | FL_VERBOSE, _("Dumping gathered data for %ss.\n"), type2name(type));
+ debug(FL_DEBUG, _("Dumping gathered data for %ss.\n"), type2name(type));
if (!(h = new_io(mnt, type, cfmt))) {
errstr(_("Cannot initialize IO on new quotafile: %s\n"),
strerror(errno));
@@ -684,7 +689,7 @@ static int dump_to_file(struct mntent *mnt, int type)
return -1;
}
if (rename_files(mnt, type) < 0)
- return -1;
+ return -1;
if (cfmt == kern_quota_on(mnt->mnt_fsname, type, 1 << cfmt)) { /* Quota turned on? */
char *filename;
@@ -734,25 +739,21 @@ static void check_dir(struct mntent *mnt)
(NULL, mnt->mnt_dir, mnt->mnt_type, MS_MGC_VAL | MS_REMOUNT | MS_RDONLY,
NULL) < 0 && !(flags & FL_FORCEREMOUNT)) {
if (flags & FL_INTERACTIVE) {
- printf(_
- ("Cannot remount filesystem mounted on %s read-only. Counted values might not be right.\n"),
-mnt->mnt_dir);
+ printf(_("Cannot remount filesystem mounted on %s read-only. Counted values might not be right.\n"), mnt->mnt_dir);
if (!ask_yn(_("Should I continue"), 0)) {
printf(_("As you wish... Canceling check of this file.\n"));
goto out;
}
}
else {
- errstr(
- _("Cannot remount filesystem mounted on %s read-only so counted values might not be right.\n\
-Please stop all programs writing to filesystem or use -m flag to force checking.\n"),
- mnt->mnt_dir);
+ errstr(_("Cannot remount filesystem mounted on %s read-only so counted values might not be right.\n\
+Please stop all programs writing to filesystem or use -m flag to force checking.\n"), mnt->mnt_dir);
goto out;
}
}
else
remounted = 1;
- debug(FL_DEBUG | FL_VERBOSE, _("Filesystem remounted read-only\n"));
+ debug(FL_DEBUG, _("Filesystem remounted read-only\n"));
}
debug(FL_VERBOSE, _("Scanning %s [%s] "), mnt->mnt_fsname, mnt->mnt_dir);
#if defined(EXT2_DIRECT)
@@ -775,7 +776,7 @@ Please stop all programs writing to filesystem or use -m flag to force checking.
if (remounted) {
if (mount(NULL, mnt->mnt_dir, mnt->mnt_type, MS_MGC_VAL | MS_REMOUNT, NULL) < 0)
die(4, _("Cannot remount filesystem %s read-write. cannot write new quota files.\n"), mnt->mnt_dir);
- debug(FL_DEBUG | FL_VERBOSE, _("Filesystem remounted RW.\n"));
+ debug(FL_DEBUG, _("Filesystem remounted RW.\n"));
}
if (ucheck)
dump_to_file(mnt, USRQUOTA);
@@ -814,7 +815,8 @@ static int detect_filename_format(struct mntent *mnt, int type)
snprintf(namebuf, PATH_MAX, "%s/%s.%s", mnt->mnt_dir, basenames[QF_VFSOLD], extensions[type]);
if (!stat(namebuf, &statbuf))
return QF_VFSOLD;
- /* Old quota files don't exist, just return newest format... */
+ /* Old quota files don't exist, just create newest quotafile available */
+ flags |= FL_NEWFILE;
return QF_VFSV0;
}
@@ -849,7 +851,7 @@ static void check_all(void)
mnt->mnt_fsname);
continue;
}
- debug(FL_DEBUG | FL_VERBOSE, _("Detected quota format %s\n"), fmt2name(cfmt));
+ debug(FL_DEBUG, _("Detected quota format %s\n"), fmt2name(cfmt));
}
checked++;
check_dir(mnt);
diff --git a/quotacheck.h b/quotacheck.h
index fd09aad..09a5c09 100644
--- a/quotacheck.h
+++ b/quotacheck.h
@@ -24,6 +24,7 @@
#define FL_NOREMOUNT 128 /* Don't try to remount filesystem RO */
#define FL_ALL 256 /* Scan all mountpoints with quota? */
#define FL_NOROOT 512 /* Scan all mountpoints except root */
+#define FL_BACKUPS 1024 /* Create backup of old quota file? */
extern int flags; /* Options from command line */
extern struct util_dqinfo old_info[MAXQUOTAS]; /* Loaded info from file */
diff --git a/quotacheck_v2.c b/quotacheck_v2.c
index 8c88d79..6ede24e 100644
--- a/quotacheck_v2.c
+++ b/quotacheck_v2.c
@@ -48,7 +48,7 @@ static int check_info(char *filename, int fd, int type)
off_t filesize;
int err;
- debug(FL_VERBOSE, _("Checking quotafile info...\n"));
+ debug(FL_DEBUG, _("Checking quotafile info...\n"));
lseek(fd, V2_DQINFOOFF, SEEK_SET);
err = read(fd, &dinfo, sizeof(struct v2_disk_dqinfo));
@@ -322,7 +322,7 @@ int v2_buffer_file(char *filename, int fd, int type)
return 0;
if (check_info(filename, fd, type) < 0)
return 0;
- debug(FL_DEBUG | FL_VERBOSE, _("Headers of file %s checked. Going to load data...\n"),
+ debug(FL_DEBUG, _("Headers of file %s checked. Going to load data...\n"),
filename);
blocks = old_info[type].u.v2_mdqi.dqi_blocks;
blkbmp = xmalloc((blocks + 7) >> 3);
@@ -341,7 +341,7 @@ int v2_buffer_file(char *filename, int fd, int type)
errstr(_("WARNING - Some data might be changed due to corruption.\n"));
}
else
- debug(FL_DEBUG | FL_VERBOSE, _("Not found any corrupted blocks. Congratulations.\n"));
+ debug(FL_DEBUG, _("Not found any corrupted blocks. Congratulations.\n"));
return ret;
}
diff --git a/quotaon.c b/quotaon.c
index 523242d..f1575b3 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.7 2001/08/30 10:11:24 jkar8572 Exp $"
+#ident "$Id: quotaon.c,v 1.8 2001/09/04 16:21:58 jkar8572 Exp $"
/*
* Turn quota on/off for a filesystem.
@@ -175,27 +175,27 @@ int main(int argc, char **argv)
/*
* Enable/disable VFS quota on given filesystem
*/
-static int quotaonoff(char *quotadev, char *quotafile, int type, int flags)
+static int quotaonoff(char *quotadev, char *quotadir, char *quotafile, int type, int flags)
{
int qcmd;
if (flags & STATEFLAG_OFF) {
qcmd = QCMD(Q_QUOTAOFF, type);
if (quotactl(qcmd, quotadev, 0, NULL) < 0) {
- errstr(_("quotactl on %s: %s\n"), quotadev, strerror(errno));
+ errstr(_("quotactl on %s [%s]: %s\n"), quotadev, quotadir, strerror(errno));
return 1;
}
if (flags & STATEFLAG_VERBOSE)
- printf(_("%s: %s quotas turned off\n"), quotadev, type2name(type));
+ printf(_("%s [%s]: %s quotas turned off\n"), quotadev, quotadir, type2name(type));
return 0;
}
qcmd = QCMD(Q_QUOTAON, type);
if (quotactl(qcmd, quotadev, 0, (void *)quotafile) < 0) {
- errstr(_("using %s on %s: %s\n"), quotafile, quotadev, strerror(errno));
+ errstr(_("using %s on %s [%s]: %s\n"), quotafile, quotadev, quotadir, strerror(errno));
return 1;
}
if (flags & STATEFLAG_VERBOSE)
- printf(_("%s: %s quotas turned on\n"), quotadev, type2name(type));
+ printf(_("%s [%s]: %s quotas turned on\n"), quotadev, quotadir, type2name(type));
return 0;
}
@@ -233,7 +233,7 @@ int v1_newstate(struct mntent *mnt, int type, char *file, int flags)
if ((flags & STATEFLAG_OFF) && hasmntopt(mnt, MNTOPT_RSQUASH))
errs += quotarsquashonoff(dev, type, flags);
if (hasquota(mnt, type))
- errs += quotaonoff((char *)dev, file, type, flags);
+ errs += quotaonoff((char *)dev, mnt->mnt_dir, file, type, flags);
if ((flags & STATEFLAG_ON) && hasmntopt(mnt, MNTOPT_RSQUASH))
errs += quotarsquashonoff(dev, type, flags);
free((char *)dev);
@@ -251,7 +251,7 @@ int v2_newstate(struct mntent *mnt, int type, char *file, int flags)
if (!dev)
return 1;
if (hasquota(mnt, type))
- errs = quotaonoff((char *)dev, file, type, flags);
+ errs = quotaonoff((char *)dev, mnt->mnt_dir, file, type, flags);
free((char *)dev);
return errs;
}
diff --git a/quotasys.c b/quotasys.c
index 21d3a72..f25a80a 100644
--- a/quotasys.c
+++ b/quotasys.c
@@ -657,27 +657,40 @@ static int process_dirs(int dcnt, char **dirs)
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));
+ errstr(_("Can't stat() given mountpoint %s: %s\nSkipping...\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;
+ if (!realpath(dirs[i], mntpointbuf)) {
+ errstr(_("Can't resolve path %s: %s\n"), dirs[i], strerror(errno));
+ continue;
+ }
}
- else if (S_ISBLK(st.st_mode) || S_ISCHR(st.st_mode))
+ else if (S_ISBLK(st.st_mode) || S_ISCHR(st.st_mode)) {
+ int mentry;
+
check_dirs[check_dirs_cnt].sd_dev = st.st_rdev;
+ for (mentry = 0; mentry < mnt_entries_cnt && mnt_entries[mentry].me_dev != st.st_rdev; mentry++);
+ if (mentry == mnt_entries_cnt) {
+ errstr(_("Can't find mountpoint for device %s\n"), dirs[i]);
+ continue;
+ }
+ strcpy(mntpointbuf, mnt_entries[mentry].me_dir);
+ }
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++;
}
+ if (!check_dirs_cnt) {
+ errstr(_("No correct mountpoint specified.\n"));
+ return -1;
+ }
}
return 0;
}