Beispiel #1
1
/*
 * Convert a quota file from one format to another.
 */
int
quota_convert(struct quotafile *qf, int wordsize)
{
	struct quotafile *newqf;
	struct dqhdr64 dqh;
	struct dqblk dqblk;
	struct group *grp;
	int serrno, maxid, id, fd;

	/*
	 * Quotas must not be active and quotafile must be open
	 * for reading and writing.
	 */
	if ((qf->accmode & O_RDWR) != O_RDWR || qf->fd == -1) {
		errno = EBADF;
		return (-1);
	}
	if ((wordsize != 32 && wordsize != 64) ||
	     wordsize == qf->wordsize) {
		errno = EINVAL;
		return (-1);
	}
	maxid = quota_maxid(qf);
	if ((newqf = calloc(1, sizeof(*qf))) == NULL) {
		errno = ENOMEM;
		return (-1);
	}
	*newqf = *qf;
	snprintf(newqf->qfname, MAXPATHLEN + 1, "%s_%d.orig", qf->qfname,
	    qf->wordsize);
	if (rename(qf->qfname, newqf->qfname) < 0) {
		free(newqf);
		return (-1);
	}
	if ((newqf->fd = open(qf->qfname, O_RDWR|O_CREAT|O_TRUNC, 0)) < 0) {
		serrno = errno;
		goto error;
	}
	newqf->wordsize = wordsize;
	if (wordsize == 64) {
		memset(&dqh, 0, sizeof(dqh));
		memcpy(dqh.dqh_magic, Q_DQHDR64_MAGIC, sizeof(dqh.dqh_magic));
		dqh.dqh_version = htobe32(Q_DQHDR64_VERSION);
		dqh.dqh_hdrlen = htobe32(sizeof(struct dqhdr64));
		dqh.dqh_reclen = htobe32(sizeof(struct dqblk64));
		if (write(newqf->fd, &dqh, sizeof(dqh)) != sizeof(dqh)) {
			serrno = errno;
			goto error;
		}
	}
	grp = getgrnam(QUOTAGROUP);
	fchown(newqf->fd, 0, grp ? grp->gr_gid : 0);
	fchmod(newqf->fd, 0640);
	for (id = 0; id <= maxid; id++) {
		if ((quota_read(qf, &dqblk, id)) < 0)
			break;
		switch (newqf->wordsize) {
		case 32:
			if ((quota_write32(newqf, &dqblk, id)) < 0)
				break;
			continue;
		case 64:
			if ((quota_write64(newqf, &dqblk, id)) < 0)
				break;
			continue;
		default:
			errno = EINVAL;
			break;
		}
	}
	if (id < maxid) {
		serrno = errno;
		goto error;
	}
	/*
	 * Update the passed in quotafile to reference the new file
	 * of the converted format size.
	 */
	fd = qf->fd;
	qf->fd = newqf->fd;
	newqf->fd = fd;
	qf->wordsize = newqf->wordsize;
	quota_close(newqf);
	return (0);
error:
	/* put back the original file */
	(void) rename(newqf->qfname, qf->qfname);
	quota_close(newqf);
	errno = serrno;
	return (-1);
}
Beispiel #2
0
/*
 * Update a specified quota file.
 */
int
update(const char *fsname, struct quotafile *qf, int type)
{
	struct fileusage *fup;
	u_long id, lastid, highid = 0;
	struct dqblk dqbuf;
	struct stat sb;
	static struct dqblk zerodqbuf;
	static struct fileusage zerofileusage;

	/*
	 * Scan the on-disk quota file and record any usage changes.
	 */
	lastid = quota_maxid(qf);
	for (id = 0; id <= lastid; id++) {
		if (quota_read(qf, &dqbuf, id) < 0)
			dqbuf = zerodqbuf;
		if ((fup = lookup(id, type)) == NULL)
			fup = &zerofileusage;
		if (fup->fu_curinodes || fup->fu_curblocks ||
		    dqbuf.dqb_bsoftlimit || dqbuf.dqb_bhardlimit ||
		    dqbuf.dqb_isoftlimit || dqbuf.dqb_ihardlimit)
			highid = id;
		if (dqbuf.dqb_curinodes == fup->fu_curinodes &&
		    dqbuf.dqb_curblocks == fup->fu_curblocks) {
			fup->fu_curinodes = 0;
			fup->fu_curblocks = 0;
			continue;
		}
		printchanges(fsname, type, &dqbuf, fup, id);
		dqbuf.dqb_curinodes = fup->fu_curinodes;
		dqbuf.dqb_curblocks = fup->fu_curblocks;
		(void) quota_write_usage(qf, &dqbuf, id);
		fup->fu_curinodes = 0;
		fup->fu_curblocks = 0;
	}

	/*
	 * Walk the hash table looking for ids with non-zero usage
	 * that are not currently recorded in the quota file. E.g.
	 * ids that are past the end of the current file.
	 */
	for (id = 0; id < FUHASH; id++) {
		for (fup = fuhead[type][id]; fup != NULL; fup = fup->fu_next) {
			if (fup->fu_id <= lastid)
				continue;
			if (fup->fu_curinodes == 0 && fup->fu_curblocks == 0)
				continue;
			bzero(&dqbuf, sizeof(struct dqblk));
			if (fup->fu_id > highid)
				highid = fup->fu_id;
			printchanges(fsname, type, &dqbuf, fup, fup->fu_id);
			dqbuf.dqb_curinodes = fup->fu_curinodes;
			dqbuf.dqb_curblocks = fup->fu_curblocks;
			(void) quota_write_usage(qf, &dqbuf, fup->fu_id);
			fup->fu_curinodes = 0;
			fup->fu_curblocks = 0;
		}
	}
	/*
	 * If this is old format file, then size may be smaller,
	 * so ensure that we only truncate when it will make things
	 * smaller, and not if it will grow an old format file.
	 */
	if (highid < lastid &&
	    stat(quota_qfname(qf), &sb) == 0 &&
	    sb.st_size > (((off_t)highid + 2) * sizeof(struct dqblk)))
		truncate(quota_qfname(qf),
		    (((off_t)highid + 2) * sizeof(struct dqblk)));
	return (0);
}
Beispiel #3
0
int
repquota(struct fstab *fs, int type)
{
	struct fileusage *fup;
	struct quotafile *qf;
	u_long id, maxid;
	struct dqblk dqbuf;
	static int multiple = 0;

	if ((qf = quota_open(fs, type, O_RDONLY)) == NULL) {
		if (vflag && !aflag) {
			if (multiple++)
				printf("\n");
			fprintf(stdout, "*** No %s quotas on %s (%s)\n",
			    qfextension[type], fs->fs_file, fs->fs_spec);
			return(1);
		}
		return(0);
	}
	if (multiple++)
		printf("\n");
	if (vflag)
		fprintf(stdout, "*** Report for %s quotas on %s (%s)\n",
		    qfextension[type], fs->fs_file, fs->fs_spec);
	printf("%*s           Block  limits                    File  limits\n",
		max(MAXLOGNAME - 1, 10), " ");
	printf("User%*s  used   soft   hard  grace     used    soft    hard  grace\n",
		max(MAXLOGNAME - 1, 10), " ");
	maxid = quota_maxid(qf);
	for (id = 0; id <= maxid; id++) {
		if (quota_read(qf, &dqbuf, id) != 0)
			break;
		if (dqbuf.dqb_curinodes == 0 && dqbuf.dqb_curblocks == 0)
			continue;
		if ((fup = lookup(id, type)) == 0)
			fup = addid(id, type, (char *)0);
		printf("%-*s ", max(MAXLOGNAME - 1, 10), fup->fu_name);
		printf("%c%c", 
		    dqbuf.dqb_bsoftlimit &&
		    dqbuf.dqb_curblocks >=
		    dqbuf.dqb_bsoftlimit ? '+' : '-',
		    dqbuf.dqb_isoftlimit &&
		    dqbuf.dqb_curinodes >=
		    dqbuf.dqb_isoftlimit ? '+' : '-');
		prthumanval(dqbuf.dqb_curblocks);
		prthumanval(dqbuf.dqb_bsoftlimit);
		prthumanval(dqbuf.dqb_bhardlimit);
		printf(" %6s",
		    dqbuf.dqb_bsoftlimit &&
		    dqbuf.dqb_curblocks >=
		    dqbuf.dqb_bsoftlimit ?
		    timeprt(dqbuf.dqb_btime) : "-");
		printf("  %7ju %7ju %7ju %6s\n",
		    (uintmax_t)dqbuf.dqb_curinodes,
		    (uintmax_t)dqbuf.dqb_isoftlimit,
		    (uintmax_t)dqbuf.dqb_ihardlimit,
		    dqbuf.dqb_isoftlimit &&
		    dqbuf.dqb_curinodes >=
		    dqbuf.dqb_isoftlimit ?
		    timeprt(dqbuf.dqb_itime) : "-");
	}
	quota_close(qf);
	return (0);
}