#include "cupsd.h"
static int compare(const quota_t *q1, const quota_t *q2);
quota_t *
AddQuota(printer_t *p,
const char *username)
{
quota_t *q;
if (!p || !username)
return (NULL);
if (p->num_quotas == 0)
q = malloc(sizeof(quota_t));
else
q = realloc(p->quotas, sizeof(quota_t) * (p->num_quotas + 1));
if (!q)
return (NULL);
p->quotas = q;
q += p->num_quotas;
p->num_quotas ++;
memset(q, 0, sizeof(quota_t));
strlcpy(q->username, username, sizeof(q->username));
if (p->num_quotas > 1)
qsort(p->quotas, p->num_quotas, sizeof(quota_t),
(int (*)(const void *, const void *))compare);
return (FindQuota(p, username));
}
quota_t *
FindQuota(printer_t *p,
const char *username)
{
quota_t *q,
match;
if (!p || !username)
return (NULL);
if (p->num_quotas == 0)
q = NULL;
else
{
strlcpy(match.username, username, sizeof(match.username));
q = bsearch(&match, p->quotas, p->num_quotas, sizeof(quota_t),
(int(*)(const void *, const void *))compare);
}
if (q)
return (q);
else
return (AddQuota(p, username));
}
void
FreeQuotas(printer_t *p)
{
if (!p)
return;
if (p->num_quotas)
free(p->quotas);
p->num_quotas = 0;
p->quotas = NULL;
}
quota_t *
UpdateQuota(printer_t *p,
const char *username,
int pages,
int k)
{
quota_t *q;
job_t *job,
*next;
time_t curtime;
ipp_attribute_t *attr;
if (!p || !username)
return (NULL);
if (!p->k_limit && !p->page_limit)
return (NULL);
if ((q = FindQuota(p, username)) == NULL)
return (NULL);
LogMessage(L_DEBUG, "UpdateQuota: p=%s username=%s pages=%d k=%d",
p->name, username, pages, k);
curtime = time(NULL);
if (curtime < q->next_update)
{
q->page_count += pages;
q->k_count += k;
return (q);
}
if (p->quota_period)
curtime -= p->quota_period;
else
curtime = 0;
q->next_update = 0;
q->page_count = 0;
q->k_count = 0;
for (job = Jobs; job; job = next)
{
next = job->next;
if (strcasecmp(job->dest, p->name) != 0 ||
strcasecmp(job->username, q->username) != 0)
continue;
if ((attr = ippFindAttribute(job->attrs, "time-at-completion",
IPP_TAG_INTEGER)) == NULL)
if ((attr = ippFindAttribute(job->attrs, "time-at-processing",
IPP_TAG_INTEGER)) == NULL)
attr = ippFindAttribute(job->attrs, "time-at-creation",
IPP_TAG_INTEGER);
if (attr == NULL)
break;
if (attr->values[0].integer < curtime)
{
if (JobAutoPurge)
CancelJob(job->id, 1);
continue;
}
if (q->next_update == 0)
q->next_update = attr->values[0].integer + p->quota_period;
if ((attr = ippFindAttribute(job->attrs, "job-media-sheets-completed",
IPP_TAG_INTEGER)) != NULL)
q->page_count += attr->values[0].integer;
if ((attr = ippFindAttribute(job->attrs, "job-k-octets",
IPP_TAG_INTEGER)) != NULL)
q->k_count += attr->values[0].integer;
}
return (q);
}
static int
compare(const quota_t *q1,
const quota_t *q2)
{
return (strcasecmp(q1->username, q2->username));
}