]> git.ipfire.org Git - thirdparty/cups.git/blame - scheduler/quotas.c
Merge changes from CUPS 1.4svn-r8362.
[thirdparty/cups.git] / scheduler / quotas.c
CommitLineData
ef416fc2 1/*
2e4ff8af 2 * "$Id: quotas.c 6947 2007-09-12 21:09:49Z mike $"
ef416fc2 3 *
4 * Quota routines for the Common UNIX Printing System (CUPS).
5 *
dfd5680b 6 * Copyright 2007-2009 by Apple Inc.
7594b224 7 * Copyright 1997-2007 by Easy Software Products.
ef416fc2 8 *
9 * These coded instructions, statements, and computer programs are the
bc44d920 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/".
ef416fc2 14 *
15 * Contents:
16 *
3d8365b8 17 * cupsdFindQuota() - Find a quota record.
ef416fc2 18 * cupsdFreeQuotas() - Free quotas for a printer.
19 * cupsdUpdateQuota() - Update quota data for the specified printer and user.
e1d6a774 20 * add_quota() - Add a quota record for this printer and user.
fa73b229 21 * compare_quotas() - Compare two quota records...
ef416fc2 22 */
23
24/*
25 * Include necessary headers...
26 */
27
28#include "cupsd.h"
29
30
31/*
32 * Local functions...
33 */
34
e1d6a774 35static cupsd_quota_t *add_quota(cupsd_printer_t *p, const char *username);
36static int compare_quotas(const cupsd_quota_t *q1,
37 const cupsd_quota_t *q2);
3d8365b8 38
39
40/*
41 * 'cupsdFindQuota()' - Find a quota record.
42 */
43
44cupsd_quota_t * /* O - Quota data */
45cupsdFindQuota(
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 */
db1f069b 51 char *ptr; /* Pointer into username */
3d8365b8 52
53
54 if (!p || !username)
55 return (NULL);
56
57 strlcpy(match.username, username, sizeof(match.username));
db1f069b
MS
58 if ((ptr = strchr(match.username, '@')) != NULL)
59 *ptr = '\0'; /* Strip @domain/@KDC */
3d8365b8 60
61 if ((q = (cupsd_quota_t *)cupsArrayFind(p->quotas, &match)) != NULL)
62 return (q);
63 else
64 return (add_quota(p, username));
65}
ef416fc2 66
67
68/*
69 * 'cupsdFreeQuotas()' - Free quotas for a printer.
70 */
71
72void
fa73b229 73cupsdFreeQuotas(cupsd_printer_t *p) /* I - Printer */
ef416fc2 74{
fa73b229 75 cupsd_quota_t *q; /* Current quota record */
76
77
ef416fc2 78 if (!p)
79 return;
80
fa73b229 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);
ef416fc2 87
fa73b229 88 p->quotas = NULL;
ef416fc2 89}
90
91
92/*
93 * 'cupsdUpdateQuota()' - Update quota data for the specified printer and user.
94 */
95
96cupsd_quota_t * /* O - Quota data */
97cupsdUpdateQuota(
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
3d8365b8 115 if ((q = cupsdFindQuota(p, username)) == NULL)
ef416fc2 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
7594b224 122#if defined(__APPLE__) && defined(HAVE_DLFCN_H)
123 /*
124 * Use Apple PrintService quota enforcement if installed (X Server only)
125 */
126
127 if (AppleQuotas && PSQUpdateQuotaProc)
128 {
129 q->page_count = (*PSQUpdateQuotaProc)(p->name, p->info, username, pages, 0);
130
131 return (q);
132 }
133#endif /* __APPLE__ && HAVE_DLFCN_H */
134
ef416fc2 135 curtime = time(NULL);
136
137 if (curtime < q->next_update)
138 {
139 q->page_count += pages;
140 q->k_count += k;
141
142 return (q);
143 }
144
145 if (p->quota_period)
146 curtime -= p->quota_period;
147 else
148 curtime = 0;
149
150 q->next_update = 0;
151 q->page_count = 0;
152 q->k_count = 0;
153
154 for (job = (cupsd_job_t *)cupsArrayFirst(Jobs);
155 job;
156 job = (cupsd_job_t *)cupsArrayNext(Jobs))
157 {
dfd5680b
MS
158 /*
159 * We only care about the current printer/class and user...
160 */
161
ef416fc2 162 if (strcasecmp(job->dest, p->name) != 0 ||
163 strcasecmp(job->username, q->username) != 0)
164 continue;
165
dfd5680b
MS
166 /*
167 * Make sure attributes are loaded; we always call cupsdLoadJob() to ensure
168 * the access_time member is updated so the job isn't unloaded right away...
169 */
170
171 if (!cupsdLoadJob(job))
172 continue;
173
ef416fc2 174 if ((attr = ippFindAttribute(job->attrs, "time-at-completion",
175 IPP_TAG_INTEGER)) == NULL)
176 if ((attr = ippFindAttribute(job->attrs, "time-at-processing",
177 IPP_TAG_INTEGER)) == NULL)
178 attr = ippFindAttribute(job->attrs, "time-at-creation",
179 IPP_TAG_INTEGER);
180
dfd5680b
MS
181 if (!attr)
182 {
183 /*
184 * This should never happen since cupsdLoadJob() checks for
185 * time-at-creation, but if it does just ignore this job...
186 */
187
188 continue;
189 }
ef416fc2 190
191 if (attr->values[0].integer < curtime)
192 {
dfd5680b
MS
193 /*
194 * This job is too old to count towards the quota, ignore it...
195 */
196
ef416fc2 197 if (JobAutoPurge)
07725fee 198 cupsdCancelJob(job, 1, IPP_JOB_CANCELED);
ef416fc2 199
200 continue;
201 }
202
203 if (q->next_update == 0)
204 q->next_update = attr->values[0].integer + p->quota_period;
205
206 if ((attr = ippFindAttribute(job->attrs, "job-media-sheets-completed",
207 IPP_TAG_INTEGER)) != NULL)
208 q->page_count += attr->values[0].integer;
209
210 if ((attr = ippFindAttribute(job->attrs, "job-k-octets",
211 IPP_TAG_INTEGER)) != NULL)
212 q->k_count += attr->values[0].integer;
213 }
214
215 return (q);
216}
217
218
e1d6a774 219/*
220 * 'add_quota()' - Add a quota record for this printer and user.
221 */
222
07725fee 223static cupsd_quota_t * /* O - Quota data */
e1d6a774 224add_quota(cupsd_printer_t *p, /* I - Printer */
225 const char *username) /* I - User */
226{
227 cupsd_quota_t *q; /* New quota data */
db1f069b 228 char *ptr; /* Pointer into username */
e1d6a774 229
230
231 if (!p || !username)
232 return (NULL);
233
234 if (!p->quotas)
235 p->quotas = cupsArrayNew((cups_array_func_t)compare_quotas, NULL);
236
237 if (!p->quotas)
238 return (NULL);
239
240 if ((q = calloc(1, sizeof(cupsd_quota_t))) == NULL)
241 return (NULL);
242
243 strlcpy(q->username, username, sizeof(q->username));
db1f069b
MS
244 if ((ptr = strchr(q->username, '@')) != NULL)
245 *ptr = '\0'; /* Strip @domain/@KDC */
e1d6a774 246
247 cupsArrayAdd(p->quotas, q);
248
249 return (q);
250}
251
252
ef416fc2 253/*
fa73b229 254 * 'compare_quotas()' - Compare two quota records...
ef416fc2 255 */
256
257static int /* O - Result of comparison */
fa73b229 258compare_quotas(const cupsd_quota_t *q1, /* I - First quota record */
259 const cupsd_quota_t *q2) /* I - Second quota record */
ef416fc2 260{
261 return (strcasecmp(q1->username, q2->username));
262}
263
264
265/*
2e4ff8af 266 * End of "$Id: quotas.c 6947 2007-09-12 21:09:49Z mike $".
ef416fc2 267 */