/*
 * libnqs/unwelcome/secgrfir.c
 * 
 * DESCRIPTION:
 *
 *	Given two quota limits, report whether the second is greater
 *	than the first. If it is, return 1.  If not, return 0.
 *
 *	Original Author:
 *	-------
 *	Robert W. Sandstrom, Sterling Software Incorporated.
 *	January 24, 1986.
 */

#include <libnqs/license.h>
#include <libnqs/proto.h>

/*** secgrfir
 *
 *
 *	int secgrfir():
 *
 *	Given two quota limits, return 1 if the second limit
 *	is greater than the first limit. Otherwise return 0.
 *
 *	This function was originally designed to return 1 whenever
 *	the units were unequal. Then I considered the example
 *	1.2 GB, 1 GB.  The fractional part algorithm converts
 *	the UNITS of the first to MEGABYTES! Once the 12 comparisons
 *	to handle this were in, it seemed natural to add the remaining
 *	44.  This in turn allowed grandfather clauses and other benefits.
 *
 *	It is assumed that the number of bits in an unsigned
 *	long is at least 32.  It is further assumed that first_quota
 *	and second_quota are each < 2**32.
 */
int secgrfir (
	unsigned long first_quota,
	short first_units,
	unsigned long second_quota,
	short second_units)
{
    if (first_units == 0 || second_units == 0) {
	return (1);
    }
    /*
     * Below, we handle the 8 pairs where the units are identical.
     */
    if (first_units == second_units) {
	 return (second_quota > first_quota);
    }
    /*
     * Below, we handle the 56 remaining possible pairs of units.
     * Where the first units are coarser than the second units,
     * we have to add 1023, 1048575, 1073741823, BYTES_PER_WORD -1,
     * (BYTES_PER_WORD * 1024) -1, (BYTES_PER_WORD * 10485476) -1,
     * or (BYTES_PER_WORD * 1073741824) -1 to handle the case
     * "1 kb 1025 b", which would otherwise appear legal.
     */
    switch (first_units) {
    case QLM_BYTES:
	switch (second_units) {
	case QLM_WORDS:
	    /* no longer supported */
	    return -1;
	case QLM_KBYTES:
	    return (first_quota / 1024 < second_quota);
	case QLM_KWORDS:
	    /* no longer supported */
	    return -1;
	case QLM_MBYTES:
	    return (first_quota / 1048576L < second_quota);
	case QLM_MWORDS:
	    /* no longer supported */
	    return -1;
	case QLM_GBYTES:
	    return (first_quota / 1073741824L < second_quota);
	case QLM_GWORDS:
	    /* no longer supported */
	    return -1;
	}
    case QLM_WORDS:
        /* no longer supported */
        return -1;
    case QLM_KBYTES:
	switch (second_units) {
	case QLM_BYTES:
	    /* Before adding, check for overflow. */
	    if (second_quota > 4294967295U - 1023) {
		return (first_quota < 4194304L);
	    }
	    else {
		return (first_quota < (second_quota + 1023)/1024);
	    }
	case QLM_WORDS:
	    /* no longer supported */
	    return -1;
	case QLM_KWORDS:
	    /* no longer supported */
	    return -1;
	case QLM_MBYTES:
	    return (first_quota / 1024 < second_quota);
	case QLM_MWORDS:
	    /* no longer supported */
	    return -1;
	case QLM_GBYTES:
	    return (first_quota / 1048576L < second_quota);
	case QLM_GWORDS:
	    /* no longer supported */
	    return -1;
	}
    case QLM_KWORDS:
        /* no longer supported */
        return -1;
    case QLM_MBYTES:
	switch (second_units) {
	case QLM_BYTES:
	    /* Before adding, check for overflow. */
	    if (second_quota > 4294967295U - 1048575L) {
		return (first_quota < 4096);
	    }
	    else {
		return (first_quota < (second_quota + 1048575L)/1048576L);
	    }
	case QLM_WORDS:
	    /* no longer supported */
	    return -1;
	case QLM_KBYTES:
	    /* Before adding, check for overflow. */
	    if (second_quota > 4294967295U - 1023) {
		return (first_quota < 4194304L);
	    }
	    else {
		return (first_quota < (second_quota + 1023)/1024);
	    }
	case QLM_KWORDS:
	    /* no longer supported */
	    return -1;
	case QLM_MWORDS:
	    /* no longer supported */
	    return -1;
	case QLM_GBYTES:
	    return (first_quota / 1024 < second_quota);
	case QLM_GWORDS:
	    /* no longer supported */
	    return -1;
	}
    case QLM_MWORDS:
        /* no longer supported */
        return -1;
    case QLM_GBYTES:
	switch (second_units) {
	case QLM_BYTES:
	    /* Before adding, check for overflow. */
	    if (second_quota > 4294967295U - 1073741823L) {
		return (first_quota < 4);
	    }
	    else {
		return (first_quota < (second_quota + 1073741823L)/1073741824L);
	    }
	case QLM_WORDS:
	    /* no longer supported */
	    return (-1);
	case QLM_KBYTES:
	    /* Before adding, check for overflow. */
	    if (second_quota > 4294967295U - 1048575L) {
		return (first_quota < 4096);
	    }
	    else {
		return (first_quota < (second_quota + 1048575L)/1048576L);
	    }
	case QLM_KWORDS:
	    /* no longer supported */
	    return (-1);
	case QLM_MBYTES:
	    /* Before adding, check for overflow. */
	    if (second_quota > 4294967295U - 1023) {
		return (first_quota < 4194304L);
	    }
	    else {
		return (first_quota < (second_quota + 1023)/1024);
	    }
	case QLM_MWORDS:
	    /* no longer supported */
	    return (-1);
	case QLM_GWORDS:
	    /* no longer supported */
	    return -1;
	}
    case QLM_GWORDS:
        /* no longer supported */
        return -1;
    }
    return 0;
    /* keep IRIX compilers happy */
}				/* end secgrfir () */
