/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
/* All Rights Reserved */
/*
* University Copyright- Copyright (c) 1982, 1986, 1988
* The Regents of the University of California
* All Rights Reserved
*
* University Acknowledgment- Portions of this document are derived from
* software developed by the University of California, Berkeley, and its
* contributors.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
/*
* Disk quota editor.
*/
#include <stdlib.h>
#include <stdio.h>
#include <signal.h>
#include <errno.h>
#include <pwd.h>
#include <ctype.h>
#include <fcntl.h>
#include <string.h>
#include <strings.h>
#include <unistd.h>
#include <iso/limits_iso.h>
#if DEV_BSIZE < 1024
#else
#endif
struct fsquot {
char *fsq_fs;
char *fsq_dev;
char *fsq_qfile;
};
static int editit(void);
static char *next(char *, char *);
static int alldigits(char *);
static void setupfs(void);
static void sigsetmask(uint_t);
static void usage(void);
int
{
char *basename;
int opt;
int i;
if (argc < 2) {
usage();
}
(void) printf("Warning: "
"Quotas are not compiled into this kernel\n");
(void) sleep(3);
}
if (getuid()) {
exit(32);
}
setupfs();
exit(32);
}
exit(32);
}
switch (opt) {
case 't':
gettimes(0);
if (editit())
puttimes(0);
exit(0);
/*NOTREACHED*/
case 'p':
exit(32);
}
usage();
}
exit(32);
}
}
exit(0);
/*NOTREACHED*/
case 'V': /* Print command line */
{
char *optt;
int optc;
(void) printf("edquota -F UFS");
if (optt)
}
(void) putchar('\n');
}
break;
case '?':
usage();
}
continue;
if (editit())
if (uid == 0) {
(void) printf("edquota: Note that uid 0's quotas "
"are used as default values for other users,\n");
(void) printf("not as a limit on the uid 0 user.\n");
}
}
return (0);
}
static uid_t
{
errno = 0;
/* name would cause overflow in uid */
name);
(void) sleep(1);
return (-1);
}
else {
(void) sleep(1);
return (-1);
}
return (uid);
}
static int
editit(void)
{
char *ed;
/*CONSTANTCONDITION*/
while (1) {
"You have too many processes\n");
return (0);
}
perror("fork");
return (0);
}
if (pid == 0) {
(void) sigsetmask(omask);
"Can't exec editor \"%s\": ", ed);
perror("");
exit(32);
}
break;
break;
}
/*
* Certain editors can exit with a non-zero status even
* though everything is peachy. Best to ask the user what
* we'll "break" the while loop before we get here.)
*/
(void) printf("updated file may contain errors.\n");
/*CONSTANTCONDITION*/
while (1) {
(void) printf("Edit again (e) or quit, "
"discarding changes (q)? ");
return (0);
}
break;
}
}
if (*resp == 'e') {
continue;
} else {
/*
* Since (*resp == 'q'), then we just
* want to break out of here and return
* the failure.
*/
break;
}
} else {
break; /* Successful return from editor */
}
}
(void) sigsetmask(omask);
return (!status);
}
static void
{
exit(32);
}
"fs %s blocks (soft = %lu, hard = %lu) "
"inodes (soft = %lu, hard = %lu)\n",
}
static void
{
int changed = 0;
int quota_entry_printed;
return;
}
int n;
break;
*cp++ = '\0';
cp++;
break;
*cp++ = '\0';
break;
}
continue;
}
cp++;
/*
* At this point, dp points to the mount point of the
* file system and cp points to the remainder of the
* quota definition string.
*/
"blocks (soft = %llu, hard = %llu) "
"inodes (soft = %llu, hard = %llu)\n",
if (n != 4) {
continue;
}
/*
* The values in dqb_bsoftlimit and dqb_bhardlimit
* are specified in 1k blocks in the edited quota
* file (the one we're reading), but are specified in
* disk blocks in the data structure passed to quotactl().
* That means that the maximum allowed value for the
* hard and soft block limits in the edited quota file
* is the maximum number of disk blocks allowed in a
* quota (which is 2^32 - 1, since it's a 32-bit unsigned
* quantity), converted to 1k blocks.
*/
quota_entry_printed = 0; /* only print quota entry once */
if (tmp_bsoftlimit > max_limit) {
if (!quota_entry_printed) {
quota_entry_printed = 1;
}
"error: soft limit for blocks exceeds maximum allowed value,\n"
" soft limit for blocks set to %lu\n", max_limit);
}
if (tmp_bhardlimit > max_limit) {
if (!quota_entry_printed) {
quota_entry_printed = 1;
}
"error: hard limit for blocks exceeds maximum allowed value,\n"
" hard limit for blocks set to %lu\n", max_limit);
}
/*
* Now check the file limits against their maximum, which
* is UINT_MAX (since it must fit in a uint32_t).
*/
if (tmp_fsoftlimit > max_limit) {
if (!quota_entry_printed) {
quota_entry_printed = 1;
}
"error: soft limit for files exceeds maximum allowed value,\n"
" soft limit for files set to %lu\n", max_limit);
}
if (tmp_fhardlimit > max_limit) {
if (!quota_entry_printed) {
quota_entry_printed = 1;
}
"error: hard limit for files exceeds maximum allowed value,\n"
" hard limit for files set to %lu\n", max_limit);
}
changed++;
/*
* It we are decreasing the soft limits, set the time limits
* to zero, in case the user is now over quota.
* the time limit will be started the next time the
* user does an allocation.
*/
}
if (changed)
}
static void
{
exit(32);
}
"fs %s blocks time limit = %s, files time limit = %s\n",
}
}
static void
{
int changed = 0;
return;
}
int n;
break;
*cp++ = '\0';
cp++;
break;
*cp++ = '\0';
break;
}
continue;
}
cp++;
"blocks time limit = %lf %[^,], "
"files time limit = %lf %s\n",
if (n != 4 ||
continue;
}
changed++;
}
if (changed)
}
static char *
{
char *dp;
return (cp);
cp++;
}
return ((char *)0);
}
static int
alldigits(char *s)
{
int c = *s++;
do {
if (!isdigit(c))
return (0);
} while ((c = *s++) != '\0');
return (1);
}
static struct {
} cunits [] = {
{60*60*24*28, "month"},
{60*60*24*7, "week"},
{60*60*24, "day"},
{60*60, "hour"},
{60, "min"},
{1, "sec"}
};
static void
{
double value;
int i;
if (time == 0) {
return;
}
break;
}
static int
{
int i;
if (value == 0.0) {
*timep = 0;
return (1);
}
break;
}
return (0);
return (1);
}
static void
setupfs(void)
{
}
continue;
continue;
continue;
continue;
}
}
}
}
static void
{
int fd;
continue;
}
sizeof (struct dqblk))) {
case 0:
/*
* Convert implicit 0 quota (EOF)
* into an explicit one (zero'ed dqblk)
*/
sizeof (struct dqblk));
break;
case sizeof (struct dqblk): /* OK */
break;
default: /* ERROR */
"edquota: read error in ");
break;
}
}
}
}
static void
{
int fd;
continue;
}
}
}
}
}
static void
{
int i;
for (i = 0; i < 32; i++)
if (omask & (1 << i)) {
"Bad signal 0x%x\n", (1 << i));
}
}
}
static uint_t
{
int i;
for (i = 0; i < 32; i++)
if (omask & (1 << i)) {
"Bad signal 0x%x\n", (1 << i));
}
if (i == 0)
}
return (previous);
}
static void
usage(void)
{
exit(1);
}
static int
{
int fd;
int status;
/*
* need to find an acceptable fd to send this Q_ALLSYNC down
* on, it needs to be a ufs fd for vfs to at least call the
* real quotactl() in the kernel
* Here, try to simply find the starting mountpoint of the
* first mounted ufs file system
*/
}
/*
* Find the mount point of the special device. This is
* because the fcntl that implements the quotactl call has
* to go to a real file, and not to the block device.
*/
perror("open");
}
qfile[0] = '\0';
/*
* check that it is a ufs file system
* for all quotactl()s except Q_ALLSYNC check that
* the file system is read-write since changes in the
* quotas file may be required
* for Q_ALLSYNC, this check is skipped since this option
* is to determine if quotas are configured into the system
*/
continue;
return (-1);
}
break;
}
return (-1);
}
}
}
if (qfile[0] == '\0') {
return (-1);
}
{
int open_flags;
} else {
sizeof (qfile)) {
return (-1);
}
open_flags = O_RDWR;
}
perror("open");
}
}
return (status);
}