Load cups into easysw/current.
[thirdparty/cups.git] / scheduler / quotas.c
1 /*
2  * "$Id: quotas.c 4729 2005-09-30 17:46:19Z mike $"
3  *
4  *   Quota routines for the Common UNIX Printing System (CUPS).
5  *
6  *   Copyright 1997-2005 by Easy Software Products.
7  *
8  *   These coded instructions, statements, and computer programs are the
9  *   property of Easy Software Products and are protected by Federal
10  *   copyright law.  Distribution and use rights are outlined in the file
11  *   "LICENSE.txt" which should have been included with this file.  If this
12  *   file is missing or damaged please contact Easy Software Products
13  *   at:
14  *
15  *       Attn: CUPS Licensing Information
16  *       Easy Software Products
17  *       44141 Airport View Drive, Suite 204
18  *       Hollywood, Maryland 20636 USA
19  *
20  *       Voice: (301) 373-9600
21  *       EMail: cups-info@cups.org
22  *         WWW: http://www.cups.org
23  *
24  * Contents:
25  *
26  *   cupsdAddQuota()    - Add a quota record for this printer and user.
27  *   cupsdFindQuota()   - Find a quota record.
28  *   cupsdFreeQuotas()  - Free quotas for a printer.
29  *   cupsdUpdateQuota() - Update quota data for the specified printer and user.
30  *   compare()          - Compare two quota records...
31  */
32
33 /*
34  * Include necessary headers...
35  */
36
37 #include "cupsd.h"
38
39
40 /*
41  * Local functions...
42  */
43
44 static int      compare(const cupsd_quota_t *q1, const cupsd_quota_t *q2);
45
46
47 /*
48  * 'cupsdAddQuota()' - Add a quota record for this printer and user.
49  */
50
51 cupsd_quota_t *                         /* O - Quota data */
52 cupsdAddQuota(cupsd_printer_t *p,       /* I - Printer */
53               const char      *username)/* I - User */
54 {
55   cupsd_quota_t *q;                     /* New quota data */
56
57
58   if (!p || !username)
59     return (NULL);
60
61   if (p->num_quotas == 0)
62     q = malloc(sizeof(cupsd_quota_t));
63   else
64     q = realloc(p->quotas, sizeof(cupsd_quota_t) * (p->num_quotas + 1));
65
66   if (!q)
67     return (NULL);
68
69   p->quotas = q;
70   q         += p->num_quotas;
71   p->num_quotas ++;
72
73   memset(q, 0, sizeof(cupsd_quota_t));
74   strlcpy(q->username, username, sizeof(q->username));
75
76   if (p->num_quotas > 1)
77     qsort(p->quotas, p->num_quotas, sizeof(cupsd_quota_t),
78           (int (*)(const void *, const void *))compare);
79
80   return (cupsdFindQuota(p, username));
81 }
82
83
84 /*
85  * 'cupsdFindQuota()' - Find a quota record.
86  */
87
88 cupsd_quota_t *                         /* O - Quota data */
89 cupsdFindQuota(
90     cupsd_printer_t *p,                 /* I - Printer */
91     const char      *username)          /* I - User */
92 {
93   cupsd_quota_t *q,                     /* Quota data pointer */
94                 match;                  /* Search data */
95
96
97   if (!p || !username)
98     return (NULL);
99
100   if (p->num_quotas == 0)
101     q = NULL;
102   else
103   {
104     strlcpy(match.username, username, sizeof(match.username));
105
106     q = bsearch(&match, p->quotas, p->num_quotas, sizeof(cupsd_quota_t),
107                 (int(*)(const void *, const void *))compare);
108   }
109
110   if (q)
111     return (q);
112   else
113     return (cupsdAddQuota(p, username));
114 }
115
116
117 /*
118  * 'cupsdFreeQuotas()' - Free quotas for a printer.
119  */
120
121 void
122 cupsdFreeQuotas(cupsd_printer_t *p)             /* I - Printer */
123 {
124   if (!p)
125     return;
126
127   if (p->num_quotas)
128     free(p->quotas);
129
130   p->num_quotas = 0;
131   p->quotas     = NULL;
132 }
133
134
135 /*
136  * 'cupsdUpdateQuota()' - Update quota data for the specified printer and user.
137  */
138
139 cupsd_quota_t *                         /* O - Quota data */
140 cupsdUpdateQuota(
141     cupsd_printer_t *p,                 /* I - Printer */
142     const char      *username,          /* I - User */
143     int             pages,              /* I - Number of pages */
144     int             k)                  /* I - Number of kilobytes */
145 {
146   cupsd_quota_t         *q;             /* Quota data */
147   cupsd_job_t           *job;           /* Current job */
148   time_t                curtime;        /* Current time */
149   ipp_attribute_t       *attr;          /* Job attribute */
150
151
152   if (!p || !username)
153     return (NULL);
154
155   if (!p->k_limit && !p->page_limit)
156     return (NULL);
157
158   if ((q = cupsdFindQuota(p, username)) == NULL)
159     return (NULL);
160
161   cupsdLogMessage(CUPSD_LOG_DEBUG,
162                   "cupsdUpdateQuota: p=%s username=%s pages=%d k=%d",
163                   p->name, username, pages, k);
164
165   curtime = time(NULL);
166
167   if (curtime < q->next_update)
168   {
169     q->page_count += pages;
170     q->k_count    += k;
171
172     return (q);
173   }
174
175   if (p->quota_period)
176     curtime -= p->quota_period;
177   else
178     curtime = 0;
179
180   q->next_update = 0;
181   q->page_count  = 0;
182   q->k_count     = 0;
183
184   for (job = (cupsd_job_t *)cupsArrayFirst(Jobs);
185        job;
186        job = (cupsd_job_t *)cupsArrayNext(Jobs))
187   {
188     if (strcasecmp(job->dest, p->name) != 0 ||
189         strcasecmp(job->username, q->username) != 0)
190       continue;
191
192     if ((attr = ippFindAttribute(job->attrs, "time-at-completion",
193                                  IPP_TAG_INTEGER)) == NULL)
194       if ((attr = ippFindAttribute(job->attrs, "time-at-processing",
195                                    IPP_TAG_INTEGER)) == NULL)
196         attr = ippFindAttribute(job->attrs, "time-at-creation",
197                                 IPP_TAG_INTEGER);
198
199     if (attr == NULL)
200       break;
201
202     if (attr->values[0].integer < curtime)
203     {
204       if (JobAutoPurge)
205         cupsdCancelJob(job, 1);
206
207       continue;
208     }
209
210     if (q->next_update == 0)
211       q->next_update = attr->values[0].integer + p->quota_period;
212
213     if ((attr = ippFindAttribute(job->attrs, "job-media-sheets-completed",
214                                  IPP_TAG_INTEGER)) != NULL)
215       q->page_count += attr->values[0].integer;
216
217     if ((attr = ippFindAttribute(job->attrs, "job-k-octets",
218                                  IPP_TAG_INTEGER)) != NULL)
219       q->k_count += attr->values[0].integer;
220   }
221
222   return (q);
223 }
224
225
226 /*
227  * 'compare()' - Compare two quota records...
228  */
229
230 static int                              /* O - Result of comparison */
231 compare(const cupsd_quota_t *q1,        /* I - First quota record */
232         const cupsd_quota_t *q2)        /* I - Second quota record */
233 {
234   return (strcasecmp(q1->username, q2->username));
235 }
236
237
238 /*
239  * End of "$Id: quotas.c 4729 2005-09-30 17:46:19Z mike $".
240  */