summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--convertquota.c18
-rw-r--r--quot.c22
-rw-r--r--quot.h2
-rw-r--r--quota.h2
-rw-r--r--quotacheck.c130
-rw-r--r--quotaio.c50
-rw-r--r--quotaio.h7
-rw-r--r--quotaon.c67
-rw-r--r--quotaon.h4
-rw-r--r--quotaon_xfs.c25
-rw-r--r--quotasys.c307
-rw-r--r--quotasys.h30
-rw-r--r--rquota_server.c4
13 files changed, 349 insertions, 319 deletions
diff --git a/convertquota.c b/convertquota.c
index 483abf1..7df948e 100644
--- a/convertquota.c
+++ b/convertquota.c
@@ -287,7 +287,7 @@ static int convert_dquot(struct dquot *dquot, char *name)
return 0;
}
-static int rename_file(int type, int fmt, struct mntent *mnt)
+static int rename_file(int type, int fmt, struct mount_entry *mnt)
{
char *qfname, namebuf[PATH_MAX];
int ret = 0;
@@ -307,19 +307,19 @@ static int rename_file(int type, int fmt, struct mntent *mnt)
return ret;
}
-static int convert_format(int type, struct mntent *mnt)
+static int convert_format(int type, struct mount_entry *mnt)
{
struct quota_handle *qo;
int ret = 0;
if (!(qo = init_io(mnt, type, infmt, IOI_INITSCAN))) {
errstr(_("Cannot open old format file for %ss on %s\n"),
- type2name(type), mnt->mnt_dir);
+ type2name(type), mnt->me_dir);
return -1;
}
if (!(qn = new_io(mnt, type, outfmt))) {
errstr(_("Cannot create file for %ss for new format on %s: %s\n"),
- type2name(type), mnt->mnt_dir, strerror(errno));
+ type2name(type), mnt->me_dir, strerror(errno));
end_io(qo);
return -1;
}
@@ -332,7 +332,7 @@ static int convert_format(int type, struct mntent *mnt)
return ret;
}
-static int convert_endian(int type, struct mntent *mnt)
+static int convert_endian(int type, struct mount_entry *mnt)
{
int ret = 0;
int ofd;
@@ -341,7 +341,7 @@ static int convert_endian(int type, struct mntent *mnt)
if (get_qf_name(mnt, type, QF_VFSV0, NF_EXIST, &qfname) < 0)
return -1;
if ((ofd = open(qfname, O_RDONLY)) < 0) {
- errstr(_("Cannot open old quota file on %s: %s\n"), mnt->mnt_dir, strerror(errno));
+ errstr(_("Cannot open old quota file on %s: %s\n"), mnt->me_dir, strerror(errno));
free(qfname);
return -1;
}
@@ -352,7 +352,7 @@ static int convert_endian(int type, struct mntent *mnt)
}
if (!(qn = new_io(mnt, type, QF_VFSV0))) {
errstr(_("Cannot create file for %ss for new format on %s: %s\n"),
- type2name(type), mnt->mnt_dir, strerror(errno));
+ type2name(type), mnt->me_dir, strerror(errno));
close(ofd);
return -1;
}
@@ -369,7 +369,7 @@ static int convert_endian(int type, struct mntent *mnt)
return rename_file(type, QF_VFSV0, mnt);
}
-static int convert_file(int type, struct mntent *mnt)
+static int convert_file(int type, struct mount_entry *mnt)
{
switch (action) {
case ACT_FORMAT:
@@ -383,7 +383,7 @@ static int convert_file(int type, struct mntent *mnt)
int main(int argc, char **argv)
{
- struct mntent *mnt;
+ struct mount_entry *mnt;
int ret = 0;
gettexton();
diff --git a/quot.c b/quot.c
index d9114a4..efff122 100644
--- a/quot.c
+++ b/quot.c
@@ -73,8 +73,8 @@ char *progname;
static void mounttable(void);
static char *idname(__uint32_t, int);
-static void report(const char *, char *, int);
-static void creport(const char *, char *);
+static void report(const char *, const char *, int);
+static void creport(const char *, const char *);
static void usage(void)
{
@@ -139,20 +139,20 @@ int main(int argc, char **argv)
static void mounttable(void)
{
int doit = 0;
- struct mntent *mntp;
+ struct mount_entry *mntp;
while ((mntp = get_next_mount())) {
/* Currently, only XFS is implemented... */
- if (strcmp(mntp->mnt_type, MNTTYPE_XFS) == 0) {
- checkXFS(mntp->mnt_fsname, mntp->mnt_dir);
+ if (strcmp(mntp->me_type, MNTTYPE_XFS) == 0) {
+ checkXFS(mntp->me_devname, mntp->me_dir);
doit = 1;
}
/* ...additional filesystems types here. */
if (doit) {
- 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 (cflag) creport(mntp->me_devname, mntp->me_dir);
+ if (!cflag && uflag) report(mntp->me_devname, mntp->me_dir, 0);
+ if (!cflag && gflag) report(mntp->me_devname, mntp->me_dir, 1);
}
}
}
@@ -170,7 +170,7 @@ static int qcmp(du_t * p1, du_t * p2)
return 0;
}
-static void creport(const char *file, char *fsdir)
+static void creport(const char *file, const char *fsdir)
{
int i;
__uint64_t t = 0;
@@ -188,7 +188,7 @@ static void creport(const char *file, char *fsdir)
(unsigned long long) (overflow + t));
}
-static void report(const char *file, char *fsdir, int type)
+static void report(const char *file, const char *fsdir, int type)
{
du_t *dp;
@@ -334,7 +334,7 @@ static void acctXFS(xfs_bstat_t *p)
}
}
-static void checkXFS(const char *file, char *fsdir)
+static void checkXFS(const char *file, const char *fsdir)
{
xfs_fsop_bulkreq_t bulkreq;
__u64 last = 0;
diff --git a/quot.h b/quot.h
index 4f3de0b..07ea39d 100644
--- a/quot.h
+++ b/quot.h
@@ -106,7 +106,7 @@ typedef struct xfs_fsop_bulkreq {
#endif
#define NBSTAT 4069 /* XFS bulkstat inodes */
-static void checkXFS(const char *file, char *fsdir);
+static void checkXFS(const char *file, const char *fsdir);
/*
* === End of XFS specific types and definitions ===
diff --git a/quota.h b/quota.h
index 565fc7e..0491975 100644
--- a/quota.h
+++ b/quota.h
@@ -95,6 +95,8 @@ struct if_dqblk {
#define IIF_FLAGS 4
#define IIF_ALL (IIF_BGRACE | IIF_IGRACE | IIF_FLAGS)
+#define DQF_SYS_FILE 0x10000 /* Quota stored in a system file */
+
struct if_dqinfo {
u_int64_t dqi_bgrace;
u_int64_t dqi_igrace;
diff --git a/quotacheck.c b/quotacheck.c
index 129f838..2da562b 100644
--- a/quotacheck.c
+++ b/quotacheck.c
@@ -243,7 +243,7 @@ static void remove_list(void)
}
/* Get size used by file */
-static loff_t getqsize(char *fname, struct stat *st)
+static loff_t getqsize(const char *fname, struct stat *st)
{
static char ioctl_fail_warn;
int fd;
@@ -269,7 +269,7 @@ static loff_t getqsize(char *fname, struct stat *st)
/*
* Show a blitting cursor as means of visual progress indicator.
*/
-static inline void blit(char *msg)
+static inline void blit(const char *msg)
{
static int bitc = 0;
static const char bits[] = "|/-\\";
@@ -413,7 +413,7 @@ static void parse_options(int argcnt, char **argstr)
}
#if defined(EXT2_DIRECT)
-static int ext2_direct_scan(char *device)
+static int ext2_direct_scan(const char *device)
{
ext2_ino_t i_num;
ext2_filsys fs;
@@ -490,7 +490,7 @@ static int ext2_direct_scan(char *device)
* of the files to the appropriate quotas. When we find a dir we recursivly call
* ourself to scan that dir.
*/
-static int scan_dir(char *pathname)
+static int scan_dir(const char *pathname)
{
struct dirs *dir_stack = NULL;
struct dirs *new_dir;
@@ -613,18 +613,18 @@ int ask_yn(char *q, int def)
}
/* Do checks and buffer quota file into memory */
-static int process_file(struct mntent *mnt, int type)
+static int process_file(struct mount_entry *mnt, int type)
{
char *qfname = NULL;
int fd = -1, ret;
debug(FL_DEBUG, _("Going to check %s quota file of %s\n"), type2name(type),
- mnt->mnt_dir);
+ mnt->me_dir);
- if (kern_quota_on(mnt->mnt_fsname, type, cfmt) >= 0) { /* Is quota enabled? */
+ if (kern_quota_on(mnt, type, 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);
+ printf(_("Quota for %ss is enabled on mountpoint %s so quotacheck might damage the file.\n"), type2name(type), mnt->me_dir);
if (!ask_yn(_("Should I continue"), 0)) {
printf(_("As you wish... Canceling check of this file.\n"));
return -1;
@@ -633,17 +633,17 @@ static int process_file(struct mntent *mnt, int type)
else
die(6, _("Quota for %ss is enabled on mountpoint %s so quotacheck might damage the file.\n\
Please turn quotas off or use -f to force checking.\n"),
- type2name(type), mnt->mnt_dir);
+ type2name(type), mnt->me_dir);
}
/* At least sync quotas so damage will be smaller */
if (quotactl(QCMD((kernel_iface == IFACE_GENERIC)? Q_SYNC : Q_6_5_SYNC, type),
- mnt->mnt_fsname, 0, NULL) < 0)
- die(4, _("Error while syncing quotas on %s: %s\n"), mnt->mnt_fsname, strerror(errno));
+ mnt->me_devname, 0, NULL) < 0)
+ die(4, _("Error while syncing quotas on %s: %s\n"), mnt->me_devname, strerror(errno));
}
if (!(flags & FL_NEWFILE)) { /* Need to buffer file? */
if (get_qf_name(mnt, type, cfmt, 0, &qfname) < 0) {
- errstr(_("Cannot get quotafile name for %s\n"), mnt->mnt_fsname);
+ errstr(_("Cannot get quotafile name for %s\n"), mnt->me_devname);
return -1;
}
if ((fd = open(qfname, O_RDONLY)) < 0) {
@@ -675,7 +675,7 @@ Please turn quotas off or use -f to force checking.\n"),
}
/* Backup old quotafile and rename new one to right name */
-static int rename_files(struct mntent *mnt, int type)
+static int rename_files(struct mount_entry *mnt, int type)
{
char *filename, newfilename[PATH_MAX];
struct stat st;
@@ -690,7 +690,7 @@ static int rename_files(struct mntent *mnt, int type)
debug(FL_DEBUG, _("Renaming new files to proper names.\n"));
if (get_qf_name(mnt, type, cfmt, 0, &filename) < 0)
- die(2, _("Cannot get name of old quotafile on %s.\n"), mnt->mnt_dir);
+ die(2, _("Cannot get name of old quotafile on %s.\n"), mnt->me_dir);
if (stat(filename, &st) < 0) { /* File doesn't exist? */
if (errno == ENOENT) {
debug(FL_DEBUG | FL_VERBOSE, _("Old file not found.\n"));
@@ -781,7 +781,7 @@ rename_new:
* 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(struct mntent *mnt, int type)
+static int dump_to_file(struct mount_entry *mnt, int type)
{
struct dquot *dquot;
uint i;
@@ -828,16 +828,16 @@ static int dump_to_file(struct mntent *mnt, int type)
return -1;
}
debug(FL_DEBUG, _("Data dumped.\n"));
- if (kern_quota_on(mnt->mnt_fsname, type, cfmt) >= 0) { /* Quota turned on? */
+ if (kern_quota_on(mnt, type, cfmt) >= 0) { /* Quota turned on? */
char *filename;
if (get_qf_name(mnt, type, cfmt, NF_FORMAT, &filename) < 0)
- errstr(_("Cannot find checked quota file for %ss on %s!\n"), type2name(type), mnt->mnt_fsname);
+ errstr(_("Cannot find checked quota file for %ss on %s!\n"), type2name(type), mnt->me_devname);
else {
if (quotactl(QCMD((kernel_iface == IFACE_GENERIC) ? Q_QUOTAOFF : Q_6_5_QUOTAOFF, type),
- mnt->mnt_fsname, 0, NULL) < 0)
+ mnt->me_devname, 0, NULL) < 0)
errstr(_("Cannot turn %s quotas off on %s: %s\nKernel won't know about changes quotacheck did.\n"),
- type2name(type), mnt->mnt_fsname, strerror(errno));
+ type2name(type), mnt->me_devname, strerror(errno));
else {
int ret;
@@ -845,12 +845,12 @@ static int dump_to_file(struct mntent *mnt, int type)
rename_files(mnt, type);
if (kernel_iface == IFACE_GENERIC)
- ret = quotactl(QCMD(Q_QUOTAON, type), mnt->mnt_fsname, util2kernfmt(cfmt), filename);
+ ret = quotactl(QCMD(Q_QUOTAON, type), mnt->me_devname, util2kernfmt(cfmt), filename);
else
- ret = quotactl(QCMD(Q_6_5_QUOTAON, type), mnt->mnt_fsname, 0, filename);
+ ret = quotactl(QCMD(Q_6_5_QUOTAON, type), mnt->me_devname, 0, filename);
if (ret < 0)
errstr(_("Cannot turn %s quotas on on %s: %s\nKernel won't know about changes quotacheck did.\n"),
- type2name(type), mnt->mnt_fsname, strerror(errno));
+ type2name(type), mnt->me_devname, strerror(errno));
}
free(filename);
}
@@ -863,7 +863,7 @@ static int dump_to_file(struct mntent *mnt, int type)
/* Substract space used by old quota file from usage.
* Return non-zero in case of failure, zero otherwise. */
-static int sub_quota_file(struct mntent *mnt, int qtype, int ftype)
+static int sub_quota_file(struct mount_entry *mnt, int qtype, int ftype)
{
char *filename;
struct stat st;
@@ -901,16 +901,16 @@ static int sub_quota_file(struct mntent *mnt, int qtype, int ftype)
/* Buffer quotafile, run filesystem scan, dump quotafiles.
* Return non-zero value in case of failure, zero otherwise. */
-static int check_dir(struct mntent *mnt)
+static int check_dir(struct mount_entry *mnt)
{
struct stat st;
int remounted = 0;
int failed = 0;
- if (lstat(mnt->mnt_dir, &st) < 0)
- die(2, _("Cannot stat mountpoint %s: %s\n"), mnt->mnt_dir, strerror(errno));
+ if (lstat(mnt->me_dir, &st) < 0)
+ die(2, _("Cannot stat mountpoint %s: %s\n"), mnt->me_dir, strerror(errno));
if (!S_ISDIR(st.st_mode))
- die(2, _("Mountpoint %s is not a directory?!\n"), mnt->mnt_dir);
+ die(2, _("Mountpoint %s is not a directory?!\n"), mnt->me_dir);
cur_dev = st.st_dev;
files_done = dirs_done = 0;
/*
@@ -932,10 +932,10 @@ static int check_dir(struct mntent *mnt)
if (!(flags & FL_NOREMOUNT)) {
/* Now we try to remount fs read-only to prevent races when scanning filesystem */
if (mount
- (NULL, mnt->mnt_dir, mnt->mnt_type, MS_MGC_VAL | MS_REMOUNT | MS_RDONLY,
+ (NULL, mnt->me_dir, mnt->me_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->me_dir);
if (!ask_yn(_("Should I continue"), 0)) {
printf(_("As you wish... Canceling check of this file.\n"));
failed = -1;
@@ -944,7 +944,7 @@ static int check_dir(struct mntent *mnt)
}
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);
+Please stop all programs writing to filesystem or use -m flag to force checking.\n"), mnt->me_dir);
failed = -1;
goto out;
}
@@ -954,19 +954,19 @@ Please stop all programs writing to filesystem or use -m flag to force checking.
debug(FL_DEBUG, _("Filesystem remounted read-only\n"));
}
start_scan:
- debug(FL_VERBOSE, _("Scanning %s [%s] "), mnt->mnt_fsname, mnt->mnt_dir);
+ debug(FL_VERBOSE, _("Scanning %s [%s] "), mnt->me_devname, mnt->me_dir);
#if defined(EXT2_DIRECT)
- if (!strcmp(mnt->mnt_type, MNTTYPE_EXT2) || !strcmp(mnt->mnt_type, MNTTYPE_EXT3) || !strcmp(mnt->mnt_type, MNTTYPE_NEXT3)) {
- if ((failed = ext2_direct_scan(mnt->mnt_fsname)) < 0)
+ if (!strcmp(mnt->me_type, MNTTYPE_EXT2) || !strcmp(mnt->me_type, MNTTYPE_EXT3) || !strcmp(mnt->me_type, MNTTYPE_NEXT3)) {
+ if ((failed = ext2_direct_scan(mnt->me_devname)) < 0)
goto out;
}
else {
#else
- if (mnt->mnt_dir) {
+ if (mnt->me_dir) {
#endif
if (flags & FL_VERYVERBOSE)
putchar('\n');
- if ((failed = scan_dir(mnt->mnt_dir)) < 0)
+ if ((failed = scan_dir(mnt->me_dir)) < 0)
goto out;
}
dirs_done++;
@@ -983,8 +983,8 @@ start_scan:
debug(FL_DEBUG | FL_VERBOSE, _("Checked %d directories and %d files\n"), dirs_done,
files_done);
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);
+ if (mount(NULL, mnt->me_dir, mnt->me_type, MS_MGC_VAL | MS_REMOUNT, NULL) < 0)
+ die(4, _("Cannot remount filesystem %s read-write. cannot write new quota files.\n"), mnt->me_dir);
debug(FL_DEBUG, _("Filesystem remounted RW.\n"));
}
if (ucheck)
@@ -997,7 +997,7 @@ out:
}
/* Detect quota format from filename of present files */
-static int detect_filename_format(struct mntent *mnt, int type)
+static int detect_filename_format(struct mount_entry *mnt, int type)
{
char *option;
struct stat statbuf;
@@ -1005,36 +1005,36 @@ static int detect_filename_format(struct mntent *mnt, int type)
int journal = 0;
int fmt;
- if (strcmp(mnt->mnt_type, MNTTYPE_XFS) == 0 ||
- strcmp(mnt->mnt_type, MNTTYPE_GFS2) == 0)
+ if (strcmp(mnt->me_type, MNTTYPE_XFS) == 0 ||
+ strcmp(mnt->me_type, MNTTYPE_GFS2) == 0)
return QF_XFS;
if (type == USRQUOTA) {
- if ((option = hasmntopt(mnt, MNTOPT_USRQUOTA)))
+ if ((option = str_hasmntopt(mnt->me_opts, MNTOPT_USRQUOTA)))
option += strlen(MNTOPT_USRQUOTA);
- else if (hasmntopt(mnt, MNTOPT_USRJQUOTA)) {
+ else if ((option = str_hasmntopt(mnt->me_opts, MNTOPT_USRJQUOTA))) {
journal = 1;
option += strlen(MNTOPT_USRJQUOTA);
}
- else if ((option = hasmntopt(mnt, MNTOPT_QUOTA)))
+ else if ((option = str_hasmntopt(mnt->me_opts, MNTOPT_QUOTA)))
option += strlen(MNTOPT_QUOTA);
}
else {
- if ((option = hasmntopt(mnt, MNTOPT_GRPQUOTA)))
+ if ((option = str_hasmntopt(mnt->me_opts, MNTOPT_GRPQUOTA)))
option += strlen(MNTOPT_GRPQUOTA);
- else if (hasmntopt(mnt, MNTOPT_GRPJQUOTA)) {
+ else if ((option = str_hasmntopt(mnt->me_opts, MNTOPT_GRPJQUOTA))) {
journal = 1;
option += strlen(MNTOPT_GRPJQUOTA);
}
}
if (!option)
- die(2, _("Cannot find quota option on filesystem %s with quotas!\n"), mnt->mnt_dir);
+ die(2, _("Cannot find quota option on filesystem %s with quotas!\n"), mnt->me_dir);
if (journal) {
char fmtbuf[64], *space;
- if (!(option = hasmntopt(mnt, MNTOPT_JQFMT))) {
+ if (!(option = str_hasmntopt(mnt->me_opts, MNTOPT_JQFMT))) {
jquota_err:
- errstr(_("Cannot detect quota format for journalled quota on %s\n"), mnt->mnt_dir);
+ errstr(_("Cannot detect quota format for journalled quota on %s\n"), mnt->me_dir);
return -1;
}
option += strlen(MNTOPT_JQFMT);
@@ -1053,7 +1053,7 @@ jquota_err:
}
else if (*option == '=') /* If the file name is specified we can't detect quota format from it... */
return -1;
- snprintf(namebuf, PATH_MAX, "%s/%s.%s", mnt->mnt_dir, basenames[QF_VFSV0], extensions[type]);
+ snprintf(namebuf, PATH_MAX, "%s/%s.%s", mnt->me_dir, basenames[QF_VFSV0], extensions[type]);
if (!stat(namebuf, &statbuf)) {
int fd = open(namebuf, O_RDONLY);
if (fd < 0)
@@ -1065,7 +1065,7 @@ jquota_err:
}
if (errno != ENOENT)
return -1;
- snprintf(namebuf, PATH_MAX, "%s/%s.%s", mnt->mnt_dir, basenames[QF_VFSOLD], extensions[type]);
+ snprintf(namebuf, PATH_MAX, "%s/%s.%s", mnt->me_dir, basenames[QF_VFSOLD], extensions[type]);
if (!stat(namebuf, &statbuf))
return QF_VFSOLD;
/* Old quota files don't exist, just create VFSv0 format if available */
@@ -1128,7 +1128,7 @@ warn:
/* Return 0 in case of success, non-zero otherwise. */
static int check_all(void)
{
- struct mntent *mnt;
+ struct mount_entry *mnt;
int checked = 0;
static int warned;
int failed = 0;
@@ -1136,18 +1136,18 @@ static int check_all(void)
if (init_mounts_scan((flags & FL_ALL) ? 0 : 1, &mntpoint, 0) < 0)
die(2, _("Cannot initialize mountpoint scan.\n"));
while ((mnt = get_next_mount())) {
- if (flags & FL_ALL && flags & FL_NOROOT && !strcmp(mnt->mnt_dir, "/"))
+ if (flags & FL_ALL && flags & FL_NOROOT && !strcmp(mnt->me_dir, "/"))
continue;
- if (!compatible_fs_qfmt(mnt->mnt_type, fmt)) {
- debug(FL_DEBUG | FL_VERBOSE, _("Skipping %s [%s]\n"), mnt->mnt_fsname, mnt->mnt_dir);
+ if (!compatible_fs_qfmt(mnt->me_type, fmt)) {
+ debug(FL_DEBUG | FL_VERBOSE, _("Skipping %s [%s]\n"), mnt->me_devname, mnt->me_dir);
continue;
}
cfmt = fmt;
- if (uwant && hasquota(mnt, USRQUOTA, 0))
+ if (uwant && me_hasquota(mnt, USRQUOTA))
ucheck = 1;
else
ucheck = 0;
- if (gwant && hasquota(mnt, GRPQUOTA, 0))
+ if (gwant && me_hasquota(mnt, GRPQUOTA))
gcheck = 1;
else
gcheck = 0;
@@ -1157,20 +1157,22 @@ static int check_all(void)
cfmt = detect_filename_format(mnt, ucheck ? USRQUOTA : GRPQUOTA);
if (cfmt == -1) {
errstr(_("Cannot guess format from filename on %s. Please specify format on commandline.\n"),
- mnt->mnt_fsname);
+ mnt->me_devname);
failed = -1;
continue;
}
debug(FL_DEBUG, _("Detected quota format %s\n"), fmt2name(cfmt));
}
- if (flags & FL_VERBOSE && !hasmntopt(mnt, MNTOPT_USRJQUOTA) &&
- !hasmntopt(mnt, MNTOPT_GRPJQUOTA) && !warned &&
- (!strcmp(mnt->mnt_type, MNTTYPE_EXT3) ||
- !strcmp(mnt->mnt_type, MNTTYPE_EXT4) ||
- !strcmp(mnt->mnt_type, MNTTYPE_NEXT3) ||
- !strcmp(mnt->mnt_type, MNTTYPE_EXT4DEV) ||
- !strcmp(mnt->mnt_type, MNTTYPE_REISER))) {
+ if (flags & FL_VERBOSE &&
+ !str_hasmntopt(mnt->me_opts, MNTOPT_USRJQUOTA) &&
+ !str_hasmntopt(mnt->me_opts, MNTOPT_GRPJQUOTA) &&
+ !warned &&
+ (!strcmp(mnt->me_type, MNTTYPE_EXT3) ||
+ !strcmp(mnt->me_type, MNTTYPE_EXT4) ||
+ !strcmp(mnt->me_type, MNTTYPE_NEXT3) ||
+ !strcmp(mnt->me_type, MNTTYPE_EXT4DEV) ||
+ !strcmp(mnt->me_type, MNTTYPE_REISER))) {
warned = 1;
warn_if_jquota_supported();
}
diff --git a/quotaio.c b/quotaio.c
index 257252d..d3c7cb6 100644
--- a/quotaio.c
+++ b/quotaio.c
@@ -37,19 +37,16 @@ struct disk_dqheader {
/*
* Detect quota format and initialize quota IO
*/
-struct quota_handle *init_io(struct mntent *mnt, int type, int fmt, int flags)
+struct quota_handle *init_io(struct mount_entry *mnt, int type, int fmt, int flags)
{
char *qfname = NULL;
int fd = -1, kernfmt;
struct quota_handle *h = smalloc(sizeof(struct quota_handle));
- const char *mnt_fsname = NULL;
int nameflag;
- if (!hasquota(mnt, type, 0))
+ if (!me_hasquota(mnt, type))
goto out_handle;
- if (!(mnt_fsname = get_device_name(mnt->mnt_fsname)))
- goto out_handle;
- if (stat(mnt_fsname, &h->qh_stat) < 0)
+ if (stat(mnt->me_devname, &h->qh_stat) < 0)
memset(&h->qh_stat, 0, sizeof(struct stat));
h->qh_io_flags = 0;
if (flags & IOI_READONLY)
@@ -57,11 +54,10 @@ struct quota_handle *init_io(struct mntent *mnt, int type, int fmt, int flags)
if (flags & IOI_NFS_MIXED_PATHS)
h->qh_io_flags |= IOFL_NFS_MIXED_PATHS;
h->qh_type = type;
- sstrncpy(h->qh_quotadev, mnt_fsname, sizeof(h->qh_quotadev));
- free((char *)mnt_fsname);
- sstrncpy(h->qh_fstype, mnt->mnt_type, MAX_FSTYPE_LEN);
- sstrncpy(h->qh_dir, mnt->mnt_dir, PATH_MAX);
- if (nfs_fstype(mnt->mnt_type)) { /* NFS filesystem? */
+ sstrncpy(h->qh_quotadev, mnt->me_devname, sizeof(h->qh_quotadev));
+ sstrncpy(h->qh_fstype, mnt->me_type, MAX_FSTYPE_LEN);
+ sstrncpy(h->qh_dir, mnt->me_dir, PATH_MAX);
+ if (nfs_fstype(mnt->me_type)) { /* NFS filesystem? */
if (fmt != -1 && fmt != QF_RPC) { /* User wanted some other format? */
errstr(_("Only RPC quota format is allowed on NFS filesystem.\n"));
goto out_handle;
@@ -82,8 +78,8 @@ struct quota_handle *init_io(struct mntent *mnt, int type, int fmt, int flags)
goto out_handle;
}
- if (!strcmp(mnt->mnt_type, MNTTYPE_XFS) || /* XFS filesystem? */
- !strcmp(mnt->mnt_type, MNTTYPE_GFS2)) { /* XFS filesystem? */
+ if (!strcmp(mnt->me_type, MNTTYPE_XFS) || /* XFS filesystem? */
+ !strcmp(mnt->me_type, MNTTYPE_GFS2)) { /* XFS filesystem? */
if (fmt != -1 && fmt != QF_XFS) { /* User wanted some other format? */
errstr(_("Only XFS quota format is allowed on XFS filesystem.\n"));
goto out_handle;
@@ -101,14 +97,14 @@ struct quota_handle *init_io(struct mntent *mnt, int type, int fmt, int flags)
}
if (kern_qfmt_supp(fmt)) { /* Quota compiled and desired format available? */
/* Quota turned on? */
- kernfmt = kern_quota_on(h->qh_quotadev, type, fmt);
+ kernfmt = kern_quota_on(mnt, type, fmt);
if (kernfmt >= 0) {
h->qh_io_flags |= IOFL_QUOTAON;
fmt = kernfmt; /* Default is kernel used format */
}
}
- if (meta_qf_fstype(mnt->mnt_type)) {
+ if (meta_qf_fstype(mnt->me_type) || mnt->me_qfmt[type] == QF_META) {
if (!QIO_ENABLED(h)) {
errstr(_("Quota not supported by the filesystem.\n"));
goto out_handle;
@@ -193,21 +189,30 @@ out_handle:
/*
* Create new quotafile of specified format on given filesystem
*/
-struct quota_handle *new_io(struct mntent *mnt, int type, int fmt)
+struct quota_handle *new_io(struct mount_entry *mnt, int type, int fmt)
{
char *qfname;
int fd;
struct quota_handle *h;
- const char *mnt_fsname;
char namebuf[PATH_MAX];
if (fmt == -1)
fmt = QF_VFSV0;
- else if (fmt == QF_RPC || fmt == QF_XFS || meta_qf_fstype(mnt->mnt_type)) {
+ else if (fmt == QF_RPC || fmt == QF_XFS) {
errstr(_("Creation of %s quota format is not supported.\n"),
fmt2name(fmt));
return NULL;
}
+ /*
+ * For filesystems which never have quotas in quota files or for
+ * filesystems which have quotas already stored in system files we
+ * refuse to create anything.
+ */
+ if (meta_qf_fstype(mnt->me_type) || mnt->me_qfmt[type] == QF_META) {
+ errstr(_("Quota on %s is stored in system files and must"
+ " be manipulated by fs tools.\n"), mnt->me_dir);
+ return NULL;
+ }
if (get_qf_name(mnt, type, fmt, 0, &qfname) < 0)
return NULL;
sstrncpy(namebuf, qfname, PATH_MAX);
@@ -218,16 +223,13 @@ struct quota_handle *new_io(struct mntent *mnt, int type, int fmt)
namebuf, strerror(errno));
return NULL;
}
- if (!(mnt_fsname = get_device_name(mnt->mnt_fsname)))
- goto out_fd;
h = smalloc(sizeof(struct quota_handle));
h->qh_fd = fd;
h->qh_io_flags = 0;
- sstrncpy(h->qh_quotadev, mnt_fsname, sizeof(h->qh_quotadev));
- sstrncpy(h->qh_fstype, mnt->mnt_type, MAX_FSTYPE_LEN);
- sstrncpy(h->qh_dir, mnt->mnt_dir, PATH_MAX);
- free((char *)mnt_fsname);
+ sstrncpy(h->qh_quotadev, mnt->me_devname, sizeof(h->qh_quotadev));
+ sstrncpy(h->qh_fstype, mnt->me_type, MAX_FSTYPE_LEN);
+ sstrncpy(h->qh_dir, mnt->me_dir, PATH_MAX);
h->qh_type = type;
h->qh_fmt = fmt;
memset(&h->qh_info, 0, sizeof(h->qh_info));
diff --git a/quotaio.h b/quotaio.h
index 3cd33ba..2c373b2 100644
--- a/quotaio.h
+++ b/quotaio.h
@@ -40,6 +40,7 @@
#define QF_RPC 3 /* RPC should be used on given filesystem */
#define QF_XFS 4 /* XFS quota format */
#define QF_META 5 /* Quota files are hidden, we don't care about the format */
+#define QF_VFSUNKNOWN 6 /* Some VFS quotas, we didn't detect particular format yet */
static inline int is_tree_qfmt(int fmt)
{
@@ -164,11 +165,13 @@ static inline void mark_quotafile_info_dirty(struct quota_handle *h)
#define QIO_ENABLED(h) ((h)->qh_io_flags & IOFL_QUOTAON)
#define QIO_RO(h) ((h)->qh_io_flags & IOFL_RO)
+struct mount_entry;
+
/* Check quota format used on specified medium and initialize it */
-struct quota_handle *init_io(struct mntent *mnt, int type, int fmt, int flags);
+struct quota_handle *init_io(struct mount_entry *mnt, int type, int fmt, int flags);
/* Create new quotafile of specified format on given filesystem */
-struct quota_handle *new_io(struct mntent *mnt, int type, int fmt);
+struct quota_handle *new_io(struct mount_entry *mnt, int type, int fmt);
/* Close quotafile */
int end_io(struct quota_handle *h);
diff --git a/quotaon.c b/quotaon.c
index f374423..a8e780f 100644
--- a/quotaon.c
+++ b/quotaon.c
@@ -197,7 +197,7 @@ static int quotarsquashonoff(const char *quotadev, int type, int flags)
/*
* Enable/disable VFS quota on given filesystem
*/
-static int quotaonoff(char *quotadev, char *quotadir, char *quotafile, int type, int fmt, int flags)
+static int quotaonoff(const char *quotadev, const char *quotadir, char *quotafile, int type, int fmt, int flags)
{
int qcmd, kqf;
@@ -239,42 +239,31 @@ static int quotaonoff(char *quotadev, char *quotadir, char *quotafile, int type,
/*
* Enable/disable quota/rootsquash on given filesystem (version 1)
*/
-static int v1_newstate(struct mntent *mnt, int type, char *file, int flags, int fmt)
+static int v1_newstate(struct mount_entry *mnt, int type, char *file, int flags, int fmt)
{
int errs = 0;
- const char *dev = get_device_name(mnt->mnt_fsname);
- if (!dev)
- return 1;
- if ((flags & STATEFLAG_OFF) && hasmntopt(mnt, MNTOPT_RSQUASH))
- errs += quotarsquashonoff(dev, type, flags);
- 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);
- free((char *)dev);
+ if ((flags & STATEFLAG_OFF) && str_hasmntopt(mnt->me_opts, MNTOPT_RSQUASH))
+ errs += quotarsquashonoff(mnt->me_devname, type, flags);
+ errs += quotaonoff(mnt->me_devname, mnt->me_dir, file, type, QF_VFSOLD, flags);
+ if ((flags & STATEFLAG_ON) && str_hasmntopt(mnt->me_opts, MNTOPT_RSQUASH))
+ errs += quotarsquashonoff(mnt->me_devname, type, flags);
return errs;
}
/*
* Enable/disable quota on given filesystem (generic VFS quota)
*/
-static int v2_newstate(struct mntent *mnt, int type, char *file, int flags, int fmt)
+static int v2_newstate(struct mount_entry *mnt, int type, char *file, int flags, int fmt)
{
- const char *dev = get_device_name(mnt->mnt_fsname);
- int errs = 0;
-
- if (!dev)
- return 1;
- errs = quotaonoff((char *)dev, mnt->mnt_dir, file, type, fmt, flags);
- free((char *)dev);
- return errs;
+ return quotaonoff(mnt->me_devname, mnt->me_dir, file, type, fmt, flags);
}
/*
* For both VFS quota formats, need to pass in the quota file;
* for XFS quota manager, pass on the -x command line option.
*/
-static int newstate(struct mntent *mnt, int type, char *extra)
+static int newstate(struct mount_entry *mnt, int type, char *extra)
{
int sflags, ret = 0;
@@ -282,26 +271,24 @@ static int newstate(struct mntent *mnt, int type, char *extra)
if (flags & FL_ALL)
sflags |= STATEFLAG_ALL;
- if (!strcmp(mnt->mnt_type, MNTTYPE_GFS2)) {
+ if (!strcmp(mnt->me_type, MNTTYPE_GFS2)) {
errstr(_("Cannot change state of GFS2 quota.\n"));
return 1;
- } else if (!strcmp(mnt->mnt_type, MNTTYPE_XFS)) { /* XFS filesystem has special handling... */
+ } else if (!strcmp(mnt->me_type, MNTTYPE_XFS)) { /* XFS filesystem has special handling... */
if (!kern_qfmt_supp(QF_XFS)) {
errstr(_("Cannot change state of XFS quota. It's not compiled in kernel.\n"));
return 1;
}
ret = xfs_newstate(mnt, type, extra, sflags);
}
- else if (meta_qf_fstype(mnt->mnt_type)) {
- if (!hasquota(mnt, type, 0))
- return 0;
+ else if (mnt->me_qfmt[type] == QF_META) {
/* Must be non-empty because empty path is always invalid. */
ret = v2_newstate(mnt, type, ".", sflags, QF_VFSV0);
}
else {
int usefmt;
- if (!hasquota(mnt, type, 0))
+ if (!me_hasquota(mnt, type))
return 0;
if (fmt == -1) {
if (get_qf_name(mnt, type, QF_VFSV0,
@@ -314,12 +301,12 @@ static int newstate(struct mntent *mnt, int type, char *extra)
NF_FORMAT, &extra) >= 0)
usefmt = QF_VFSOLD;
else {
- errstr(_("Cannot find quota file on %s [%s] to turn quotas on/off.\n"), mnt->mnt_dir, mnt->mnt_fsname);
+ errstr(_("Cannot find quota file on %s [%s] to turn quotas on/off.\n"), mnt->me_dir, mnt->me_devname);
return 1;
}
} else {
if (get_qf_name(mnt, type, fmt, NF_FORMAT, &extra) < 0) {
- errstr(_("Quota file on %s [%s] does not exist or has wrong format.\n"), mnt->mnt_dir, mnt->mnt_fsname);
+ errstr(_("Quota file on %s [%s] does not exist or has wrong format.\n"), mnt->me_dir, mnt->me_devname);
return 1;
}
usefmt = fmt;
@@ -334,23 +321,23 @@ static int newstate(struct mntent *mnt, int type, char *extra)
}
/* Print state of quota (on/off) */
-static int print_state(struct mntent *mnt, int type)
+static int print_state(struct mount_entry *mnt, int type)
{
int on = 0;
- if (!strcmp(mnt->mnt_type, MNTTYPE_XFS) ||
- !strcmp(mnt->mnt_type, MNTTYPE_GFS2)) {
+ if (!strcmp(mnt->me_type, MNTTYPE_XFS) ||
+ !strcmp(mnt->me_type, MNTTYPE_GFS2)) {
if (kern_qfmt_supp(QF_XFS))
- on = kern_quota_on(mnt->mnt_fsname, type, QF_XFS) != -1;
+ on = kern_quota_on(mnt, type, QF_XFS) != -1;
}
else if (kernel_iface == IFACE_GENERIC)
- on = kern_quota_on(mnt->mnt_fsname, type, -1) != -1;
+ on = kern_quota_on(mnt, type, -1) != -1;
else if (kern_qfmt_supp(QF_VFSV0))
- on = kern_quota_on(mnt->mnt_fsname, type, QF_VFSV0) != -1;
+ on = kern_quota_on(mnt, type, QF_VFSV0) != -1;
else if (kern_qfmt_supp(QF_VFSOLD))
- on = kern_quota_on(mnt->mnt_fsname, type, QF_VFSOLD) != -1;
+ on = kern_quota_on(mnt, type, QF_VFSOLD) != -1;
- printf(_("%s quota on %s (%s) is %s\n"), type2name(type), mnt->mnt_dir, mnt->mnt_fsname,
+ printf(_("%s quota on %s (%s) is %s\n"), type2name(type), mnt->me_dir, mnt->me_devname,
on ? _("on") : _("off"));
return on;
@@ -358,7 +345,7 @@ static int print_state(struct mntent *mnt, int type)
int main(int argc, char **argv)
{
- struct mntent *mnt;
+ struct mount_entry *mnt;
int errs = 0;
gettexton();
@@ -380,9 +367,9 @@ int main(int argc, char **argv)
if (init_mounts_scan(mntcnt, mntpoints, MS_XFS_DISABLED | MS_LOCALONLY) < 0)
return 1;
while ((mnt = get_next_mount())) {
- if (nfs_fstype(mnt->mnt_type)) {
+ if (nfs_fstype(mnt->me_type)) {
if (!(flags & FL_ALL))
- errstr(_("%s: Quota cannot be turned on on NFS filesystem\n"), mnt->mnt_fsname);
+ errstr(_("%s: Quota cannot be turned on on NFS filesystem\n"), mnt->me_devname);
continue;
}
diff --git a/quotaon.h b/quotaon.h
index baf3246..3e449ba 100644
--- a/quotaon.h
+++ b/quotaon.h
@@ -14,6 +14,6 @@
#define STATEFLAG_OFF 0x02
#define STATEFLAG_ALL 0x04
-typedef int (newstate_t) (struct mntent * mnt, int type, char *file, int flags);
-extern int xfs_newstate(struct mntent *mnt, int type, char *file, int flags);
+typedef int (newstate_t) (struct mount_entry * mnt, int type, char *file, int flags);
+extern int xfs_newstate(struct mount_entry *mnt, int type, char *file, int flags);
extern int pinfo(char *fmt, ...);
diff --git a/quotaon_xfs.c b/quotaon_xfs.c
index 0028a88..a271e71 100644
--- a/quotaon_xfs.c
+++ b/quotaon_xfs.c
@@ -22,7 +22,7 @@
* 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, const char *dev, int roothack, int xopts)
{
struct xfs_mem_dqinfo info;
int state;
@@ -132,7 +132,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(const char *dev, int type, int flags, int roothack, int xopts)
{
int qoff, qcmd, check;
@@ -153,7 +153,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(const char *dev, int type, int flags, int roothack, int xopts)
{
int qcmd, check;
@@ -178,15 +178,11 @@ static int xfs_delete(char *dev, int type, int flags, int roothack, int xopts)
* root filesystem.
* We are passed in the new requested state through "type" & "xarg".
*/
-int xfs_newstate(struct mntent *mnt, int type, char *xarg, int flags)
+int xfs_newstate(struct mount_entry *mnt, int type, char *xarg, int flags)
{
int err = 1;
int xopts = 0;
int roothack = 0;
- const char *dev = get_device_name(mnt->mnt_fsname);
-
- if (!dev)
- return err;
#ifdef XFS_ROOTHACK
/*
@@ -194,11 +190,11 @@ int xfs_newstate(struct mntent *mnt, int type, char *xarg, int flags)
* hack to allow enabling quota on the root filesystem without
* having to specify it at mount time.
*/
- if ((strcmp(mnt->mnt_dir, "/") == 0)) {
+ if ((strcmp(mnt->me_dir, "/") == 0)) {
struct xfs_mem_dqinfo info;
u_int16_t sbflags = 0;
- if (!quotactl(QCMD(Q_XFS_GETQSTAT, type), dev, 0, (void *)&info))
+ if (!quotactl(QCMD(Q_XFS_GETQSTAT, type), mnt->me_devname, 0, (void *)&info))
sbflags = (info.qs_flags & 0xff00) >> 8;
if ((type == USRQUOTA && (sbflags & XFS_QUOTA_UDQ_ACCT)) &&
@@ -210,22 +206,21 @@ int xfs_newstate(struct mntent *mnt, int type, char *xarg, int flags)
if (xarg == NULL) { /* only enfd on/off */
xopts |= (type == USRQUOTA) ? XFS_QUOTA_UDQ_ENFD :
XFS_QUOTA_GDQ_ENFD;
- err = xfs_onoff((char *)dev, type, flags, roothack, xopts);
+ err = xfs_onoff(mnt->me_devname, type, flags, roothack, xopts);
}
else if (strcmp(xarg, "account") == 0) {
xopts |= (type == USRQUOTA) ? XFS_QUOTA_UDQ_ACCT : XFS_QUOTA_GDQ_ACCT;
- err = xfs_onoff((char *)dev, type, flags, roothack, xopts);
+ err = xfs_onoff(mnt->me_devname, 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(mnt->me_devname, 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(mnt->me_devname, type, flags, roothack, xopts);
}
else
die(1, _("Invalid argument \"%s\"\n"), xarg);
- free((char *)dev);
return err;
}
diff --git a/quotasys.c b/quotasys.c
index 16b59a6..73a0799 100644
--- a/quotasys.c
+++ b/quotasys.c
@@ -242,7 +242,7 @@ char *fmt2name(int fmt)
/*
* Convert kernel to utility quota format number
*/
-int kern2utilfmt(int kernfmt)
+static int kern2utilfmt(int kernfmt)
{
switch (kernfmt) {
case QFMT_VFS_OLD:
@@ -385,41 +385,27 @@ void number2str(unsigned long long num, char *buf, int format)
}
/*
+ * Wrappers for mount options processing functions
+ */
+
+/*
* Check for XFS filesystem with quota accounting enabled
*/
-static int hasxfsquota(struct mntent *mnt, int type, int flags)
+static int hasxfsquota(const char *dev, struct mntent *mnt, int type, int flags)
{
- int ret = 0;
u_int16_t sbflags;
struct xfs_mem_dqinfo info;
- const char *dev;
- char *opt, *endopt;
if (flags & MS_XFS_DISABLED)
- return 1;
-
- dev = get_device_name(mnt->mnt_fsname);
- if (!dev)
- 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;
- }
+ return QF_XFS;
memset(&info, 0, sizeof(struct xfs_mem_dqinfo));
if (!quotactl(QCMD(Q_XFS_GETQSTAT, type), dev, 0, (void *)&info)) {
sbflags = (info.qs_flags & 0xff00) >> 8;
if (type == USRQUOTA && (info.qs_flags & XFS_QUOTA_UDQ_ACCT))
- ret = 1;
+ return QF_XFS;
else if (type == GRPQUOTA && (info.qs_flags & XFS_QUOTA_GDQ_ACCT))
- ret = 1;
+ return QF_XFS;
#ifdef XFS_ROOTHACK
/*
* Old XFS filesystems (up to XFS 1.2 / Linux 2.5.47) had a
@@ -427,21 +413,58 @@ static int hasxfsquota(struct mntent *mnt, int type, int flags)
* having to specify it at mount time.
*/
else if (strcmp(mnt->mnt_dir, "/"))
- ret = 0;
+ return QF_ERROR;
else if (type == USRQUOTA && (sbflags & XFS_QUOTA_UDQ_ACCT))
- ret = 1;
+ return QF_XFS;
else if (type == GRPQUOTA && (sbflags & XFS_QUOTA_GDQ_ACCT))
- ret = 1;
+ return QF_XFS;
#endif /* XFS_ROOTHACK */
}
- free((char *)dev);
- return ret;
+
+ return QF_ERROR;
+}
+
+static int hasvfsmetaquota(const char *dev, struct mntent *mnt, int type, int flags)
+{
+ uint32_t fmt;
+
+ if (!quotactl(QCMD(Q_GETFMT, type), dev, 0, (void *)&fmt))
+ return QF_META;
+ return QF_ERROR;
+}
+
+/* Return pointer to given mount option in mount option string */
+char *str_hasmntopt(const char *optstring, const char *opt)
+{
+ const char *p = optstring;
+ const char *s;
+ int len = strlen(opt);
+
+ do {
+ s = p;
+ while (*p && *p != ',' && *p != '=')
+ p++;
+ /* Found option? */
+ if (p - s == len && !strncmp(s, opt, len))
+ return (char *)s;
+ /* Skip mount option argument if there's any */
+ if (*p == '=') {
+ p++;
+ while (*p && *p != ',')
+ p++;
+ }
+ /* Skip separating ',' */
+ if (*p)
+ p++;
+ } while (*p);
+
+ return NULL;
}
/* Return if given option has nonempty argument */
-char *hasmntoptarg(struct mntent *mnt, char *opt)
+static char *hasmntoptarg(const char *optstring, const char *opt)
{
- char *p = hasmntopt(mnt, opt);
+ char *p = str_hasmntopt(optstring, opt);
if (!p)
return NULL;
@@ -451,27 +474,52 @@ char *hasmntoptarg(struct mntent *mnt, char *opt)
return NULL;
}
+/* Copy out mount option argument to a buffer */
+static void copy_mntoptarg(char *buf, const char *optarg, int buflen)
+{
+ char *sep = strchr(optarg, ',');
+
+ if (!sep)
+ sstrncpy(buf, optarg, min(buflen, strlen(optarg) + 1));
+ else
+ sstrncpy(buf, optarg, min(buflen, sep - optarg + 1));
+}
+
/*
* Check to see if a particular quota is to be enabled (filesystem mounted with proper option)
*/
-int hasquota(struct mntent *mnt, int type, int flags)
+static int hasquota(const char *dev, struct mntent *mnt, int type, int flags)
{
- if (hasmntopt(mnt, MNTOPT_NOQUOTA))
- return 0;
-
if (!strcmp(mnt->mnt_type, MNTTYPE_GFS2) ||
!strcmp(mnt->mnt_type, MNTTYPE_XFS))
- 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;
-
- if ((type == USRQUOTA) && (hasmntopt(mnt, MNTOPT_USRQUOTA) || hasmntoptarg(mnt, MNTOPT_USRJQUOTA)))
- return 1;
- if ((type == GRPQUOTA) && (hasmntopt(mnt, MNTOPT_GRPQUOTA) || hasmntoptarg(mnt, MNTOPT_GRPJQUOTA)))
- return 1;
+ return hasxfsquota(dev, mnt, type, flags);
+ if (!strcmp(mnt->mnt_type, MNTTYPE_OCFS2))
+ return hasvfsmetaquota(dev, mnt, type, flags);
+ /*
+ * For ext4 we check whether it has quota in system files and if not,
+ * we fall back on checking standard quotas. Furthermore we cannot use
+ * standard GETFMT quotactl because that does not distinguish between
+ * quota in system file and quota in ordinary file.
+ */
+ if (!strcmp(mnt->mnt_type, MNTTYPE_EXT4)) {
+ struct if_dqinfo kinfo;
+
+ if (quotactl(QCMD(Q_GETINFO, type), dev, 0, (void *)&kinfo) == 0) {
+ if (kinfo.dqi_flags & DQF_SYS_FILE)
+ return QF_META;
+ }
+ }
+ /* NFS always has quota or better there is no good way how to detect it */
+ if (nfs_fstype(mnt->mnt_type))
+ return QF_RPC;
+
+ if ((type == USRQUOTA) && (hasmntopt(mnt, MNTOPT_USRQUOTA) || hasmntoptarg(mnt->mnt_opts, MNTOPT_USRJQUOTA)))
+ return QF_VFSUNKNOWN;
+ if ((type == GRPQUOTA) && (hasmntopt(mnt, MNTOPT_GRPQUOTA) || hasmntoptarg(mnt->mnt_opts, MNTOPT_GRPJQUOTA)))
+ return QF_VFSUNKNOWN;
if ((type == USRQUOTA) && hasmntopt(mnt, MNTOPT_QUOTA))
- return 1;
- return 0;
+ return QF_VFSUNKNOWN;
+ return -1;
}
/* Check whether quotafile for given format exists - return its name in namebuf */
@@ -513,36 +561,36 @@ static int check_fmtfile_ok(char *name, int type, int fmt, int flags)
* otherwise return -1.
* Note that formats without quotafile *must* be detected prior to calling this function
*/
-int get_qf_name(struct mntent *mnt, int type, int fmt, int flags, char **filename)
+int get_qf_name(struct mount_entry *mnt, int type, int fmt, int flags, char **filename)
{
char *option, *pathname, has_quota_file_definition = 0;
char qfullname[PATH_MAX];
qfullname[0] = 0;
- if (type == USRQUOTA && (option = hasmntopt(mnt, MNTOPT_USRQUOTA))) {
+ if (type == USRQUOTA && (option = str_hasmntopt(mnt->me_opts, MNTOPT_USRQUOTA))) {
if (*(pathname = option + strlen(MNTOPT_USRQUOTA)) == '=')
has_quota_file_definition = 1;
}
- else if (type == USRQUOTA && (option = hasmntoptarg(mnt, MNTOPT_USRJQUOTA))) {
+ else if (type == USRQUOTA && (option = hasmntoptarg(mnt->me_opts, MNTOPT_USRJQUOTA))) {
pathname = option;
has_quota_file_definition = 1;
- sstrncpy(qfullname, mnt->mnt_dir, sizeof(qfullname));
+ sstrncpy(qfullname, mnt->me_dir, sizeof(qfullname));
sstrncat(qfullname, "/", sizeof(qfullname));
}
- else if (type == GRPQUOTA && (option = hasmntopt(mnt, MNTOPT_GRPQUOTA))) {
+ else if (type == GRPQUOTA && (option = str_hasmntopt(mnt->me_opts, MNTOPT_GRPQUOTA))) {
pathname = option + strlen(MNTOPT_GRPQUOTA);
if (*pathname == '=') {
has_quota_file_definition = 1;
pathname++;
}
}
- else if (type == GRPQUOTA && (option = hasmntoptarg(mnt, MNTOPT_GRPJQUOTA))) {
+ else if (type == GRPQUOTA && (option = hasmntoptarg(mnt->me_opts, MNTOPT_GRPJQUOTA))) {
pathname = option;
has_quota_file_definition = 1;
- sstrncpy(qfullname, mnt->mnt_dir, sizeof(qfullname));
+ sstrncpy(qfullname, mnt->me_dir, sizeof(qfullname));
sstrncat(qfullname, "/", sizeof(qfullname));
}
- else if (type == USRQUOTA && (option = hasmntopt(mnt, MNTOPT_QUOTA))) {
+ else if (type == USRQUOTA && (option = str_hasmntopt(mnt->me_opts, MNTOPT_QUOTA))) {
pathname = option + strlen(MNTOPT_QUOTA);
if (*pathname == '=') {
has_quota_file_definition = 1;
@@ -553,14 +601,11 @@ int get_qf_name(struct mntent *mnt, int type, int fmt, int flags, char **filenam
return -1;
if (has_quota_file_definition) {
- if ((option = strchr(pathname, ','))) {
- int tocopy = min(option - pathname + 1,
- sizeof(qfullname) - strlen(qfullname));
- sstrncpy(qfullname + strlen(qfullname), pathname, tocopy);
- } else
- sstrncat(qfullname, pathname, sizeof(qfullname));
+ int len = strlen(qfullname);
+
+ copy_mntoptarg(qfullname + len, pathname, sizeof(qfullname) - len);
} else {
- snprintf(qfullname, PATH_MAX, "%s/%s.%s", mnt->mnt_dir,
+ snprintf(qfullname, PATH_MAX, "%s/%s.%s", mnt->me_dir,
basenames[fmt], extensions[type]);
}
if (check_fmtfile_ok(qfullname, type, fmt, flags)) {
@@ -579,7 +624,7 @@ int get_qf_name(struct mntent *mnt, int type, int fmt, int flags, char **filenam
struct quota_handle **create_handle_list(int count, char **mntpoints, int type, int fmt,
int ioflags, int mntflags)
{
- struct mntent *mnt;
+ struct mount_entry *mnt;
int gotmnt = 0;
static int hlist_allocated = 0;
static struct quota_handle **hlist = NULL;
@@ -613,18 +658,18 @@ add_entry:
else {
switch (fmt) {
case QF_RPC:
- if (nfs_fstype(mnt->mnt_type))
+ if (nfs_fstype(mnt->me_type))
goto add_entry;
break;
case QF_XFS:
- if (!strcmp(mnt->mnt_type, MNTTYPE_XFS) ||
- !strcmp(mnt->mnt_type, MNTTYPE_GFS2))
+ if (!strcmp(mnt->me_type, MNTTYPE_XFS) ||
+ !strcmp(mnt->me_type, MNTTYPE_GFS2))
goto add_entry;
break;
default:
- if (strcmp(mnt->mnt_type, MNTTYPE_XFS) &&
- strcmp(mnt->mnt_type, MNTTYPE_GFS2) &&
- !nfs_fstype(mnt->mnt_type))
+ if (strcmp(mnt->me_type, MNTTYPE_XFS) &&
+ strcmp(mnt->me_type, MNTTYPE_GFS2) &&
+ !nfs_fstype(mnt->me_type))
goto add_entry;
break;
}
@@ -818,13 +863,30 @@ static int xfs_kern_quota_on(const char *dev, int type)
/*
* Check whether is quota turned on on given device for given type
*/
-int kern_quota_on(const char *dev, int type, int fmt)
+int kern_quota_on(struct mount_entry *mnt, int type, int fmt)
{
+ if (mnt->me_qfmt[type] < 0)
+ return -1;
+ if (fmt == QF_RPC)
+ return -1;
+ if (mnt->me_qfmt[type] == QF_XFS) {
+ if ((fmt == -1 || fmt == QF_XFS) &&
+ xfs_kern_quota_on(mnt->me_devname, type)) /* XFS quota format */
+ return QF_XFS;
+ return -1;
+ }
+ /* No more chances for XFS format to succeed... */
+ if (fmt == QF_XFS)
+ return -1;
+ /* Meta format is always enabled */
+ if (mnt->me_qfmt[type] == QF_META)
+ return QF_META;
+
/* Check whether quota is turned on... */
if (kernel_iface == IFACE_GENERIC) {
int actfmt;
- if (quotactl(QCMD(Q_GETFMT, type), dev, 0,
+ if (quotactl(QCMD(Q_GETFMT, type), mnt->me_devname, 0,
(void *)&actfmt) >= 0) {
actfmt = kern2utilfmt(actfmt);
if (actfmt >= 0)
@@ -832,15 +894,12 @@ int kern_quota_on(const char *dev, int type, int fmt)
}
} else {
if ((fmt == -1 || fmt == QF_VFSV0) &&
- v2_kern_quota_on(dev, type)) /* VFSv0 quota format */
+ v2_kern_quota_on(mnt->me_devname, type))
return QF_VFSV0;
if ((fmt == -1 || fmt == QF_VFSOLD) &&
- v1_kern_quota_on(dev, type)) /* Old quota format */
+ v1_kern_quota_on(mnt->me_devname, type))
return QF_VFSOLD;
}
- if ((fmt == -1 || fmt == QF_XFS) &&
- xfs_kern_quota_on(dev, type)) /* XFS quota format */
- return QF_XFS;
return -1;
}
@@ -850,15 +909,6 @@ int kern_quota_on(const char *dev, int type, int fmt)
*
*/
-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 */
@@ -906,6 +956,8 @@ alloc:
allocated += ALLOC_ENTRIES_NUM;
while ((mnt = getmntent(mntf))) {
const char *devname;
+ char *opt;
+ int qfmt[MAXQUOTAS];
if (!(devname = get_device_name(mnt->mnt_fsname))) {
errstr(_("Cannot get device name for %s\n"), mnt->mnt_fsname);
@@ -936,10 +988,27 @@ alloc:
free((char *)devname);
continue;
}
+ if (hasmntopt(mnt, MNTOPT_NOQUOTA)) {
+ free((char *)devname);
+ continue;
+ }
+ if (hasmntopt(mnt, MNTOPT_BIND)) {
+ free((char *)devname);
+ continue; /* We just ignore bind mounts... */
+ }
+ if ((opt = hasmntoptarg(mnt->mnt_opts, MNTOPT_LOOP))) {
+ char loopdev[PATH_MAX];
+
+ copy_mntoptarg(opt, loopdev, PATH_MAX);
+ free((char *)devname);
+ devname = sstrdup(loopdev);
+ }
/* Further we are not interested in mountpoints without quotas and
we don't want to touch them */
- if (!hasquota(mnt, USRQUOTA, flags) && !hasquota(mnt, GRPQUOTA, flags)) {
+ qfmt[USRQUOTA] = hasquota(devname, mnt, USRQUOTA, flags);
+ qfmt[GRPQUOTA] = hasquota(devname, mnt, GRPQUOTA, flags);
+ if (qfmt[USRQUOTA] < 0 && qfmt[GRPQUOTA] < 0) {
free((char *)devname);
continue;
}
@@ -967,50 +1036,12 @@ alloc:
free((char *)devname);
continue;
}
- if (!S_ISBLK(st.st_mode) && !S_ISCHR(st.st_mode) && !S_ISREG(st.st_mode) && !S_ISDIR(st.st_mode)) {
- unsupporteddev:
+ if (!S_ISBLK(st.st_mode) && !S_ISCHR(st.st_mode)) {
errstr(_("Device (%s) filesystem is mounted on unsupported device type. Skipping.\n"), devname);
free((char *)devname);
continue;
- } else {
- char *opt;
-
- if (hasmntopt(mnt, MNTOPT_BIND)) {
- 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;
- free((char *)devname);
- devname = sstrdup(loopdev);
- } else {
- if (!S_ISBLK(st.st_mode) && !S_ISCHR(st.st_mode))
- goto unsupporteddev;
- dev = st.st_rdev;
- }
}
+ dev = st.st_rdev;
for (i = 0; i < mnt_entries_cnt && mnt_entries[i].me_dev != dev; i++);
}
/* Cope with network filesystems or new mountpoint */
@@ -1040,7 +1071,9 @@ alloc:
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[i].me__dir = sstrdup(mntpointbuf);
+ mnt_entries[i].me_dir = NULL;
+ memcpy(&mnt_entries[i].me_qfmt, qfmt, sizeof(qfmt));
mnt_entries_cnt++;
}
else
@@ -1059,7 +1092,7 @@ static const char *find_dir_mntpoint(struct stat *st)
for (i = 0; i < mnt_entries_cnt; i++)
if (mnt_entries[i].me_dev == st->st_dev) {
st->st_ino = mnt_entries[i].me_ino;
- return mnt_entries[i].me_dir;
+ return mnt_entries[i].me__dir;
}
return NULL;
}
@@ -1122,7 +1155,7 @@ static int process_dirs(int dcnt, char **dirs, int flags)
errstr(_("Cannot find mountpoint for device %s\n"), dirs[i]);
continue;
}
- sstrncpy(mntpointbuf, mnt_entries[mentry].me_dir, PATH_MAX-1);
+ sstrncpy(mntpointbuf, mnt_entries[mentry].me__dir, PATH_MAX-1);
}
else {
errstr(_("Specified path %s is not directory nor device.\n"), dirs[i]);
@@ -1158,14 +1191,8 @@ int init_mounts_scan(int dcnt, char **dirs, int flags)
/* Find next usable mountpoint when scanning all mountpoints */
static int find_next_entry_all(int *pos)
{
- struct mntent mnt;
-
while (++act_checked < mnt_entries_cnt) {
- 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))
+ if (!str_hasmntopt(mnt_entries[act_checked].me_opts, MNTOPT_NOAUTO))
break;
}
if (act_checked >= mnt_entries_cnt)
@@ -1204,25 +1231,21 @@ restart:
/*
* Return next directory from the list
*/
-struct mntent *get_next_mount(void)
+struct mount_entry *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;
+ mnt_entries[mntpos].me_dir = 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_entries[mntpos].me_dir = 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;
+ return &mnt_entries[mntpos];
}
/*
@@ -1236,7 +1259,7 @@ void end_mounts_scan(void)
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((char *)mnt_entries[i].me__dir);
}
free(mnt_entries);
mnt_entries = NULL;
diff --git a/quotasys.h b/quotasys.h
index 005b275..1cebf7e 100644
--- a/quotasys.h
+++ b/quotasys.h
@@ -36,6 +36,17 @@
/* Supported kernel interface */
extern int kernel_iface;
+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 mountpoint of a filesystem (strdup()ed) */
+ const char *me_dir; /* Current mountpoint of a filesystem to process */
+ int me_qfmt[MAXQUOTAS]; /* Detected quota formats */
+};
+
/*
* Exported functions
*/
@@ -95,18 +106,23 @@ 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 */
-/* Recognizes MS_XFS_DISABLED flag */
-int hasquota(struct mntent *mnt, int type, int flags);
+/* Return pointer to given mount option in mount option string */
+char *str_hasmntopt(const char *optstring, const char *opt);
+
+/* Check to see if particular quota type is configured */
+static inline int me_hasquota(struct mount_entry *mnt, int type)
+{
+ return mnt->me_qfmt[type] >= 0;
+}
/* Flags for get_qf_name() */
#define NF_EXIST 1 /* Check whether file exists */
#define NF_FORMAT 2 /* Check whether file is in proper format */
/* Get quotafile name for given entry */
-int get_qf_name(struct mntent *mnt, int type, int fmt, int flags, char **filename);
+int get_qf_name(struct mount_entry *mnt, int type, int fmt, int flags, char **filename);
/* Detect newest quota format with existing file */
-int detect_quota_files(struct mntent *mnt, int type, int fmt);
+int detect_quota_files(struct mount_entry *mnt, int type, int fmt);
/* Create NULL-terminated list of handles for quotafiles for given mountpoints */
struct quota_handle **create_handle_list(int count, char **mntpoints, int type, int fmt,
@@ -124,7 +140,7 @@ int devcmp_handles(struct quota_handle *a, struct quota_handle *b);
void init_kernel_interface(void);
/* Check whether is quota turned on on given device for given type */
-int kern_quota_on(const char *dev, int type, int fmt);
+int kern_quota_on(struct mount_entry *mnt, int type, int fmt);
/* Return whether kernel is able to handle given format */
int kern_qfmt_supp(int fmt);
@@ -141,7 +157,7 @@ int kern_qfmt_supp(int fmt);
int init_mounts_scan(int dcnt, char **dirs, int flags);
/* Return next mountpoint for scan */
-struct mntent *get_next_mount(void);
+struct mount_entry *get_next_mount(void);
/* Free all structures associated with mountpoints scan */
void end_mounts_scan(void);
diff --git a/rquota_server.c b/rquota_server.c
index 3293de7..bb270e6 100644
--- a/rquota_server.c
+++ b/rquota_server.c
@@ -147,7 +147,7 @@ setquota_rslt *setquotainfo(int lflags, caddr_t * argp, struct svc_req *rqstp)
} arguments;
struct util_dqblk dqblk;
struct dquot *dquot;
- struct mntent *mnt;
+ struct mount_entry *mnt;
char pathname[PATH_MAX] = {0};
char *pathp = pathname;
int id, qcmd, type;
@@ -239,7 +239,7 @@ getquota_rslt *getquotainfo(int lflags, caddr_t * argp, struct svc_req * rqstp)
ext_getquota_args *ext_args;
} arguments;
struct dquot *dquot = NULL;
- struct mntent *mnt;
+ struct mount_entry *mnt;
char pathname[PATH_MAX] = {0};
char *pathp = pathname;
int id, type;