summaryrefslogtreecommitdiff
path: root/quotacheck_v2.c
diff options
context:
space:
mode:
Diffstat (limited to 'quotacheck_v2.c')
-rw-r--r--quotacheck_v2.c136
1 files changed, 98 insertions, 38 deletions
diff --git a/quotacheck_v2.c b/quotacheck_v2.c
index 7788237..b6a2d7f 100644
--- a/quotacheck_v2.c
+++ b/quotacheck_v2.c
@@ -18,8 +18,9 @@
#include "quotaio.h"
#include "quotaio_v2.h"
#include "quotacheck.h"
+#include "quota_tree.h"
-#define getdqbuf() smalloc(V2_DQBLKSIZE)
+#define getdqbuf() smalloc(QT_BLKSIZE)
#define freedqbuf(buf) free(buf)
#define SET_BLK(blk) (blkbmp[(blk) >> 3] |= 1 << ((blk) & 7))
@@ -28,14 +29,15 @@
typedef char *dqbuf_t;
static const int magics[MAXQUOTAS] = INITQMAGICS; /* Magics we should look for */
-static const int known_versions[MAXQUOTAS] = INITKNOWNVERSIONS; /* Versions we accept */
+static const int known_versions[MAXQUOTAS] = INIT_V2_VERSIONS; /* Versions we accept */
static char *blkbmp; /* Bitmap of checked blocks */
+static int detected_versions[MAXQUOTAS];
static int check_blkref(uint blk, uint blocks)
{
if (blk >= blocks)
return -1;
- if (blk && blk < V2_DQTREEOFF)
+ if (blk && blk < QT_TREEOFF)
return -1;
return 0;
}
@@ -69,25 +71,32 @@ static int check_info(char *filename, int fd, int type)
dflags = __le32_to_cpu(dinfo.dqi_flags);
filesize = lseek(fd, 0, SEEK_END);
if (check_blkref(freeblk, blocks) < 0 || dflags & ~V2_DQF_MASK ||
- check_blkref(freeent, blocks) < 0 || (filesize + V2_DQBLKSIZE - 1) >> V2_DQBLKSIZE_BITS != blocks) {
+ check_blkref(freeent, blocks) < 0 || (filesize + QT_BLKSIZE - 1) >> QT_BLKSIZE_BITS != blocks) {
errstr(_("WARNING - Quota file info was corrupted.\n"));
debug(FL_DEBUG, _("Size of file: %lu\nBlocks: %u Free block: %u Block with free entry: %u Flags: %x\n"),
(unsigned long)filesize, blocks, freeblk, freeent, dflags);
old_info[type].dqi_bgrace = MAX_DQ_TIME;
old_info[type].dqi_igrace = MAX_IQ_TIME;
- old_info[type].u.v2_mdqi.dqi_blocks =
- (filesize + V2_DQBLKSIZE - 1) >> V2_DQBLKSIZE_BITS;
+ old_info[type].u.v2_mdqi.dqi_qtree.dqi_blocks =
+ (filesize + QT_BLKSIZE - 1) >> QT_BLKSIZE_BITS;
old_info[type].u.v2_mdqi.dqi_flags = 0;
printf(_("Setting grace times and other flags to default values.\nAssuming number of blocks is %u.\n"),
- old_info[type].u.v2_mdqi.dqi_blocks);
+ old_info[type].u.v2_mdqi.dqi_qtree.dqi_blocks);
}
else {
old_info[type].dqi_bgrace = __le32_to_cpu(dinfo.dqi_bgrace);
old_info[type].dqi_igrace = __le32_to_cpu(dinfo.dqi_igrace);
- old_info[type].u.v2_mdqi.dqi_blocks = blocks;
+ old_info[type].u.v2_mdqi.dqi_qtree.dqi_blocks = blocks;
old_info[type].u.v2_mdqi.dqi_flags = dflags;
}
- old_info[type].u.v2_mdqi.dqi_free_blk = old_info[type].u.v2_mdqi.dqi_free_entry = 0; /* This won't be needed */
+ if (detected_versions[type] == 0)
+ old_info[type].u.v2_mdqi.dqi_qtree.dqi_entry_size = sizeof(struct v2r0_disk_dqblk);
+ else if (detected_versions[type] == 1)
+ old_info[type].u.v2_mdqi.dqi_qtree.dqi_entry_size = sizeof(struct v2r1_disk_dqblk);
+ /* Won't be needed */
+ old_info[type].u.v2_mdqi.dqi_qtree.dqi_free_blk = 0;
+ old_info[type].u.v2_mdqi.dqi_qtree.dqi_free_entry = 0;
+
debug(FL_DEBUG, _("File info done.\n"));
return 0;
}
@@ -120,7 +129,7 @@ static void blk_corrupted(int *corrupted, uint * lblk, uint blk, char *fmtstr, .
}
/* Convert dist quota format to utility one - copy just needed fields */
-static inline void disk2utildqblk(struct util_dqblk *u, struct v2_disk_dqblk *d)
+static void v2r0_disk2utildqblk(struct util_dqblk *u, struct v2r0_disk_dqblk *d)
{
u->dqb_ihardlimit = __le32_to_cpu(d->dqb_ihardlimit);
u->dqb_isoftlimit = __le32_to_cpu(d->dqb_isoftlimit);
@@ -130,23 +139,34 @@ static inline void disk2utildqblk(struct util_dqblk *u, struct v2_disk_dqblk *d)
u->dqb_btime = __le64_to_cpu(d->dqb_btime);
}
-/* Check whether given dquot is empty */
-static int empty_dquot(struct v2_disk_dqblk *d)
+/* Convert dist quota format to utility one - copy just needed fields */
+static void v2r1_disk2utildqblk(struct util_dqblk *u, struct v2r1_disk_dqblk *d)
{
- static struct v2_disk_dqblk fakedq;
-
- return !memcmp(&fakedq, d, sizeof(fakedq));
+ u->dqb_ihardlimit = __le64_to_cpu(d->dqb_ihardlimit);
+ u->dqb_isoftlimit = __le64_to_cpu(d->dqb_isoftlimit);
+ u->dqb_bhardlimit = __le64_to_cpu(d->dqb_bhardlimit);
+ u->dqb_bsoftlimit = __le64_to_cpu(d->dqb_bsoftlimit);
+ u->dqb_itime = __le64_to_cpu(d->dqb_itime);
+ u->dqb_btime = __le64_to_cpu(d->dqb_btime);
}
/* Put one entry info memory */
static int buffer_entry(dqbuf_t buf, uint blk, int *corrupted, uint * lblk, int cnt, int type)
{
- struct util_dqblk mdq, *fdq;
+ struct util_dqblk *fdq, mdq;
qid_t id;
struct dquot *cd;
+ struct qtree_mem_dqinfo *info = &old_info[type].u.v2_mdqi.dqi_qtree;
+ char *ddq = (char *)buf + sizeof(struct qt_disk_dqdbheader) + cnt * info->dqi_entry_size;
+
+ if (detected_versions[type] == 0) {
+ v2r0_disk2utildqblk(&mdq, (struct v2r0_disk_dqblk *)ddq);
+ id = __le32_to_cpu(((struct v2r0_disk_dqblk *)ddq)->dqb_id);
+ } else {
+ v2r1_disk2utildqblk(&mdq, (struct v2r1_disk_dqblk *)ddq);
+ id = __le32_to_cpu(((struct v2r1_disk_dqblk *)ddq)->dqb_id);
+ }
- disk2utildqblk(&mdq, ((struct v2_disk_dqblk *)(((char *)buf) + sizeof(struct v2_disk_dqdbheader))) + cnt);
- id = __le32_to_cpu(((struct v2_disk_dqblk *)(((char *)buf) + sizeof(struct v2_disk_dqdbheader)))[cnt].dqb_id);
cd = lookup_dquot(id, type);
if (cd != NODQUOT) {
fdq = &cd->dq_dqb;
@@ -213,13 +233,13 @@ static void check_read_blk(int fd, uint blk, dqbuf_t buf)
{
size_t rd;
- lseek(fd, blk << V2_DQBLKSIZE_BITS, SEEK_SET);
- rd = read(fd, buf, V2_DQBLKSIZE);
+ lseek(fd, blk << QT_BLKSIZE_BITS, SEEK_SET);
+ rd = read(fd, buf, QT_BLKSIZE);
if (rd < 0)
die(2, _("Cannot read block %u: %s\n"), blk, strerror(errno));
- if (rd != V2_DQBLKSIZE) {
+ if (rd != QT_BLKSIZE) {
debug(FL_VERBOSE | FL_DEBUG, _("Block %u is truncated.\n"), blk);
- memset(buf + rd, 0, V2_DQBLKSIZE - rd);
+ memset(buf + rd, 0, QT_BLKSIZE - rd);
}
}
@@ -242,20 +262,21 @@ static int check_tree_ref(uint blk, uint ref, uint blocks, int check_use, int *
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;
+ struct qt_disk_dqdbheader *head = (struct qt_disk_dqdbheader *)buf;
int i;
- struct v2_disk_dqblk *dd = (struct v2_disk_dqblk *)(head + 1);
+ char *dd = (char *)(head + 1);
+ struct qtree_mem_dqinfo *info = &old_info[type].u.v2_mdqi.dqi_qtree;
SET_BLK(blk);
check_read_blk(fd, blk, buf);
if (check_blkref(__le32_to_cpu(head->dqdh_next_free), blocks) < 0)
blk_corrupted(corrupted, lblk, blk, _("Illegal free block reference to block %u"),
__le32_to_cpu(head->dqdh_next_free));
- if (__le16_to_cpu(head->dqdh_entries) > V2_DQSTRINBLK)
+ if (__le16_to_cpu(head->dqdh_entries) > qtree_dqstr_in_blk(info))
blk_corrupted(corrupted, lblk, blk, _("Corrupted number of used entries (%u)"),
(uint) __le16_to_cpu(head->dqdh_entries));
- for (i = 0; i < V2_DQSTRINBLK; i++)
- if (!empty_dquot(dd + i))
+ for (i = 0; i < qtree_dqstr_in_blk(info); i++)
+ if (!qtree_entry_unused(info, dd + i * info->dqi_entry_size))
if (buffer_entry(buf, blk, corrupted, lblk, i, type) < 0) {
freedqbuf(buf);
return -1;
@@ -274,8 +295,8 @@ static int check_tree_blk(int fd, uint blk, int depth, int type, uint blocks, in
SET_BLK(blk);
check_read_blk(fd, blk, buf);
- for (i = 0; i < V2_DQBLKSIZE >> 2; i++)
- if (depth < V2_DQTREEDEPTH - 1) {
+ for (i = 0; i < QT_BLKSIZE >> 2; i++)
+ if (depth < QT_TREEDEPTH - 1) {
if (check_tree_ref(blk, __le32_to_cpu(r[i]), blocks, 1, corrupted, lblk) >= 0 &&
__le32_to_cpu(r[i])) /* Isn't block OK? */
if (check_tree_blk(fd, __le32_to_cpu(r[i]), depth + 1, type, blocks, corrupted, lblk) < 0) {
@@ -292,8 +313,26 @@ static int check_tree_blk(int fd, uint blk, int depth, int type, uint blocks, in
return 0;
}
+int v2_detect_version(char *filename, int fd, int type)
+{
+ struct v2_disk_dqheader head;
+ int err;
+
+ lseek(fd, 0, SEEK_SET);
+ err = read(fd, &head, sizeof(head));
+ if (err < 0 || err != sizeof(head))
+ return -1;
+ if (__le32_to_cpu(head.dqh_magic) != magics[type] ||
+ __le32_to_cpu(head.dqh_version) > known_versions[type]) {
+ errstr(_("Quota file %s has corrupted headers. You have to specify quota format on command line.\n"),
+ filename);
+ return -1;
+ }
+ return __le32_to_cpu(head.dqh_version);
+}
+
/* Check basic header */
-static int check_header(char *filename, int fd, int type)
+static int check_header(char *filename, int fd, int type, int version)
{
int err;
struct v2_disk_dqheader head;
@@ -308,34 +347,55 @@ static int check_header(char *filename, int fd, int type)
filename);
return -1;
}
- if (__le32_to_cpu(head.dqh_magic) != magics[type] || __le32_to_cpu(head.dqh_version) > known_versions[type])
+ if (__le32_to_cpu(head.dqh_magic) != magics[type] ||
+ __le32_to_cpu(head.dqh_version) > known_versions[type]) {
errstr(_("WARNING - Quota file %s has corrupted headers\n"),
filename);
+ }
+ if (__le32_to_cpu(head.dqh_version) != version) {
+ errstr(_("Quota file format version %d does not match the one "
+ "specified on command line (%d). Quota file header "
+ "may be corrupted.\n"),
+ __le32_to_cpu(head.dqh_version), version);
+ if (!ask_yn(_("Continue checking assuming version from command line?"), 1))
+ return -1;
+ detected_versions[type] = version;
+ } else
+ detected_versions[type] = __le32_to_cpu(head.dqh_version);
+
debug(FL_DEBUG, _("Headers checked.\n"));
return 0;
}
/* Load data from file to memory */
-int v2_buffer_file(char *filename, int fd, int type)
+int v2_buffer_file(char *filename, int fd, int type, int fmt)
{
uint blocks, lastblk = 0;
int corrupted = 0, ret = 0;
+ int version;
+
+ if (fmt == QF_VFSV0)
+ version = 0;
+ else if (fmt == QF_VFSV1)
+ version = 1;
+ else
+ die(3, _("Do not know how to buffer format %d\n"), fmt);
old_info[type].dqi_bgrace = MAX_DQ_TIME;
old_info[type].dqi_igrace = MAX_IQ_TIME;
if (flags & FL_NEWFILE)
return 0;
- if (check_header(filename, fd, type) < 0)
- return 0;
+ if (check_header(filename, fd, type, version) < 0)
+ return -1;
if (check_info(filename, fd, type) < 0)
- return 0;
+ return -1;
debug(FL_DEBUG, _("Headers of file %s checked. Going to load data...\n"),
filename);
- blocks = old_info[type].u.v2_mdqi.dqi_blocks;
+ blocks = old_info[type].u.v2_mdqi.dqi_qtree.dqi_blocks;
blkbmp = xmalloc((blocks + 7) >> 3);
memset(blkbmp, 0, (blocks + 7) >> 3);
- if (check_tree_ref(0, V2_DQTREEOFF, blocks, 1, &corrupted, &lastblk) >= 0)
- ret = check_tree_blk(fd, V2_DQTREEOFF, 0, type, blocks, &corrupted, &lastblk);
+ if (check_tree_ref(0, QT_TREEOFF, blocks, 1, &corrupted, &lastblk) >= 0)
+ ret = check_tree_blk(fd, QT_TREEOFF, 0, type, blocks, &corrupted, &lastblk);
else
errstr(_("Cannot gather quota data. Tree root node corrupted.\n"));
#ifdef DEBUG_MALLOC