]> git.ipfire.org Git - thirdparty/cups.git/blob - scheduler/quotas.c
Update svn:keyword properties.
[thirdparty/cups.git] / scheduler / quotas.c
1 /*
2 * "$Id$"
3 *
4 * Quota routines for the CUPS scheduler.
5 *
6 * Copyright 2007-2011 by Apple Inc.
7 * Copyright 1997-2007 by Easy Software Products.
8 *
9 * These coded instructions, statements, and computer programs are the
10 * property of Apple Inc. and are protected by Federal copyright
11 * law. Distribution and use rights are outlined in the file "LICENSE.txt"
12 * which should have been included with this file. If this file is
13 * file is missing or damaged, see the license at "http://www.cups.org/".
14 *
15 * Contents:
16 *
17 * cupsdFindQuota() - Find a quota record.
18 * cupsdFreeQuotas() - Free quotas for a printer.
19 * cupsdUpdateQuota() - Update quota data for the specified printer and user.
20 * add_quota() - Add a quota record for this printer and user.
21 * compare_quotas() - Compare two quota records...
22 */
23
24 /*
25 * Include necessary headers...
26 */
27
28 #include "cupsd.h"
29
30
31 /*
32 * Local functions...
33 */
34
35 static cupsd_quota_t *add_quota(cupsd_printer_t *p, const char *username);
36 static int compare_quotas(const cupsd_quota_t *q1,
37 const cupsd_quota_t *q2);
38
39
40 /*
41 * 'cupsdFindQuota()' - Find a quota record.
42 */
43
44 cupsd_quota_t * /* O - Quota data */
45 cupsdFindQuota(
46 cupsd_printer_t *p, /* I - Printer */
47 const char *username) /* I - User */
48 {
49 cupsd_quota_t *q, /* Quota data pointer */
50 match; /* Search data */
51 char *ptr; /* Pointer into username */
52
53
54 if (!p || !username)
55 return (NULL);
56
57 strlcpy(match.username, username, sizeof(match.username));
58 if ((ptr = strchr(match.username, '@')) != NULL)
59 *ptr = '\0'; /* Strip @domain/@KDC */
60
61 if ((q = (cupsd_quota_t *)cupsArrayFind(p->quotas, &match)) != NULL)
62 return (q);
63 else
64 return (add_quota(p, username));
65 }
66
67
68 /*
69 * 'cupsdFreeQuotas()' - Free quotas for a printer.
70 */
71
72 void
73 cupsdFreeQuotas(cupsd_printer_t *p) /* I - Printer */
74 {
75 cupsd_quota_t *q; /* Current quota record */
76
77
78 if (!p)
79 return;
80
81 for (q = (cupsd_quota_t *)cupsArrayFirst(p->quotas);
82 q;
83 q = (cupsd_quota_t *)cupsArrayNext(p->quotas))
84 free(q);
85
86 cupsArrayDelete(p->quotas);
87
88 p->quotas = NULL;
89 }
90
91
92 /*
93 * 'cupsdUpdateQuota()' - Update quota data for the specified printer and user.
94 */
95
96 cupsd_quota_t * /* O - Quota data */
97 cupsdUpdateQuota(
98 cupsd_printer_t *p, /* I - Printer */
99 const char *username, /* I - User */
100 int pages, /* I - Number of pages */
101 int k) /* I - Number of kilobytes */
102 {
103 cupsd_quota_t *q; /* Quota data */
104 cupsd_job_t *job; /* Current job */
105 time_t curtime; /* Current time */
106 ipp_attribute_t *attr; /* Job attribute */
107
108
109 if (!p || !username)
110 return (NULL);
111
112 if (!p->k_limit && !p->page_limit)
113 return (NULL);
114
115 if ((q = cupsdFindQuota(p, username)) == NULL)
116 return (NULL);
117
118 cupsdLogMessage(CUPSD_LOG_DEBUG,
119 "cupsdUpdateQuota: p=%s username=%s pages=%d k=%d",
120 p->name, username, pages, k);
121
122 curtime = time(NULL);
123
124 if (curtime < q->next_update)
125 {
126 q->page_count += pages;
127 q->k_count += k;
128
129 return (q);
130 }
131
132 if (p->quota_period)
133 curtime -= p->quota_period;
134 else
135 curtime = 0;
136
137 q->next_update = 0;
138 q->page_count = 0;
139 q->k_count = 0;
140
141 for (job = (cupsd_job_t *)cupsArrayFirst(Jobs);
142 job;
143 job = (cupsd_job_t *)cupsArrayNext(Jobs))
144 {
145 /*
146 * We only care about the current printer/class and user...
147 */
148
149 if (_cups_strcasecmp(job->dest, p->name) != 0 ||
150 _cups_strcasecmp(job->username, q->username) != 0)
151 continue;
152
153 /*
154 * Make sure attributes are loaded; we always call cupsdLoadJob() to ensure
155 * the access_time member is updated so the job isn't unloaded right away...
156 */
157
158 if (!cupsdLoadJob(job))
159 continue;
160
161 if ((attr = ippFindAttribute(job->attrs, "time-at-completion",
162 IPP_TAG_INTEGER)) == NULL)
163 if ((attr = ippFindAttribute(job->attrs, "time-at-processing",
164 IPP_TAG_INTEGER)) == NULL)
165 attr = ippFindAttribute(job->attrs, "time-at-creation",
166 IPP_TAG_INTEGER);
167
168 if (attr->values[0].integer < curtime)
169 {
170 /*
171 * This job is too old to count towards the quota, ignore it...
172 */
173
174 if (JobAutoPurge && !job->printer && job->state_value > IPP_JOB_STOPPED)
175 cupsdDeleteJob(job, CUPSD_JOB_PURGE);
176
177 continue;
178 }
179
180 if (q->next_update == 0)
181 q->next_update = attr->values[0].integer + p->quota_period;
182
183 if ((attr = ippFindAttribute(job->attrs, "job-media-sheets-completed",
184 IPP_TAG_INTEGER)) != NULL)
185 q->page_count += attr->values[0].integer;
186
187 if ((attr = ippFindAttribute(job->attrs, "job-k-octets",
188 IPP_TAG_INTEGER)) != NULL)
189 q->k_count += attr->values[0].integer;
190 }
191
192 return (q);
193 }
194
195
196 /*
197 * 'add_quota()' - Add a quota record for this printer and user.
198 */
199
200 static cupsd_quota_t * /* O - Quota data */
201 add_quota(cupsd_printer_t *p, /* I - Printer */
202 const char *username) /* I - User */
203 {
204 cupsd_quota_t *q; /* New quota data */
205 char *ptr; /* Pointer into username */
206
207
208 if (!p || !username)
209 return (NULL);
210
211 if (!p->quotas)
212 p->quotas = cupsArrayNew((cups_array_func_t)compare_quotas, NULL);
213
214 if (!p->quotas)
215 return (NULL);
216
217 if ((q = calloc(1, sizeof(cupsd_quota_t))) == NULL)
218 return (NULL);
219
220 strlcpy(q->username, username, sizeof(q->username));
221 if ((ptr = strchr(q->username, '@')) != NULL)
222 *ptr = '\0'; /* Strip @domain/@KDC */
223
224 cupsArrayAdd(p->quotas, q);
225
226 return (q);
227 }
228
229
230 /*
231 * 'compare_quotas()' - Compare two quota records...
232 */
233
234 static int /* O - Result of comparison */
235 compare_quotas(const cupsd_quota_t *q1, /* I - First quota record */
236 const cupsd_quota_t *q2) /* I - Second quota record */
237 {
238 return (_cups_strcasecmp(q1->username, q2->username));
239 }
240
241
242 /*
243 * End of "$Id$".
244 */