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