Line data Source code
1 : /*
2 : Unix SMB/Netbios implementation.
3 : Version 3.0
4 : printing backend routines
5 : Copyright (C) Andrew Tridgell 1992-2000
6 : Copyright (C) Jeremy Allison 2002
7 :
8 : This program is free software; you can redistribute it and/or modify
9 : it under the terms of the GNU General Public License as published by
10 : the Free Software Foundation; either version 3 of the License, or
11 : (at your option) any later version.
12 :
13 : This program is distributed in the hope that it will be useful,
14 : but WITHOUT ANY WARRANTY; without even the implied warranty of
15 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 : GNU General Public License for more details.
17 :
18 : You should have received a copy of the GNU General Public License
19 : along with this program. If not, see <http://www.gnu.org/licenses/>.
20 : */
21 :
22 : #include "includes.h"
23 : #include "smbd/globals.h"
24 : #include "system/syslog.h"
25 : #include "system/filesys.h"
26 : #include "printing.h"
27 : #include "../librpc/gen_ndr/ndr_spoolss.h"
28 : #include "nt_printing.h"
29 : #include "../librpc/gen_ndr/netlogon.h"
30 : #include "printing/notify.h"
31 : #include "printing/pcap.h"
32 : #include "printing/printer_list.h"
33 : #include "printing/queue_process.h"
34 : #include "serverid.h"
35 : #include "smbd/smbd.h"
36 : #include "auth.h"
37 : #include "messages.h"
38 : #include "util_tdb.h"
39 : #include "lib/param/loadparm.h"
40 : #include "lib/util/sys_rw_data.h"
41 : #include "lib/util/string_wrappers.h"
42 : #include "lib/global_contexts.h"
43 : #include "source3/printing/rap_jobid.h"
44 : #include "source3/lib/substitute.h"
45 :
46 : extern userdom_struct current_user_info;
47 :
48 : /* Current printer interface */
49 : static bool remove_from_jobs_added(const char* sharename, uint32_t jobid);
50 :
51 : static int get_queue_status(const char* sharename, print_status_struct *);
52 :
53 : /****************************************************************************
54 : Initialise the printing backend. Called once at startup before the fork().
55 : ****************************************************************************/
56 :
57 28 : bool print_backend_init(struct messaging_context *msg_ctx)
58 : {
59 28 : const char *sversion = "INFO/version";
60 28 : int services = lp_numservices();
61 0 : int snum;
62 0 : bool ok;
63 0 : char *print_cache_path;
64 :
65 28 : print_cache_path = cache_path(talloc_tos(), "printing");
66 28 : if (print_cache_path == NULL) {
67 0 : return false;
68 : }
69 28 : ok = directory_create_or_exist(print_cache_path, 0755);
70 28 : TALLOC_FREE(print_cache_path);
71 28 : if (!ok) {
72 0 : return false;
73 : }
74 :
75 : /* handle a Samba upgrade */
76 :
77 2094 : for (snum = 0; snum < services; snum++) {
78 0 : struct tdb_print_db *pdb;
79 2066 : if (!lp_printable(snum))
80 1918 : continue;
81 :
82 148 : pdb = get_print_db_byname(lp_const_servicename(snum));
83 148 : if (!pdb)
84 0 : continue;
85 148 : if (tdb_lock_bystring(pdb->tdb, sversion) != 0) {
86 0 : DEBUG(0,("print_backend_init: Failed to open printer %s database\n", lp_const_servicename(snum) ));
87 0 : release_print_db(pdb);
88 0 : return False;
89 : }
90 148 : if (tdb_fetch_int32(pdb->tdb, sversion) != PRINT_DATABASE_VERSION) {
91 58 : tdb_wipe_all(pdb->tdb);
92 58 : tdb_store_int32(pdb->tdb, sversion, PRINT_DATABASE_VERSION);
93 : }
94 148 : tdb_unlock_bystring(pdb->tdb, sversion);
95 148 : release_print_db(pdb);
96 : }
97 :
98 28 : close_all_print_db(); /* Don't leave any open. */
99 :
100 : /* do NT print initialization... */
101 28 : return nt_printing_init(msg_ctx);
102 : }
103 :
104 : /****************************************************************************
105 : Shut down printing backend. Called once at shutdown to close the tdb.
106 : ****************************************************************************/
107 :
108 0 : void printing_end(void)
109 : {
110 0 : close_all_print_db(); /* Don't leave any open. */
111 0 : }
112 :
113 : /****************************************************************************
114 : Retrieve the set of printing functions for a given service. This allows
115 : us to set the printer function table based on the value of the 'printing'
116 : service parameter.
117 :
118 : Use the generic interface as the default and only use cups interface only
119 : when asked for (and only when supported)
120 : ****************************************************************************/
121 :
122 2855 : static struct printif *get_printer_fns_from_type( enum printing_types type )
123 : {
124 2855 : struct printif *printer_fns = &generic_printif;
125 :
126 : #ifdef HAVE_CUPS
127 2855 : if ( type == PRINT_CUPS ) {
128 0 : printer_fns = &cups_printif;
129 : }
130 : #endif /* HAVE_CUPS */
131 :
132 : #ifdef HAVE_IPRINT
133 2855 : if ( type == PRINT_IPRINT ) {
134 0 : printer_fns = &iprint_printif;
135 : }
136 : #endif /* HAVE_IPRINT */
137 :
138 2855 : printer_fns->type = type;
139 :
140 2855 : return printer_fns;
141 : }
142 :
143 1526 : static struct printif *get_printer_fns( int snum )
144 : {
145 1526 : return get_printer_fns_from_type( (enum printing_types)lp_printing(snum) );
146 : }
147 :
148 :
149 : /****************************************************************************
150 : Useful function to generate a tdb key.
151 : ****************************************************************************/
152 :
153 27102 : static TDB_DATA print_key(uint32_t jobid, uint32_t *tmp)
154 : {
155 0 : TDB_DATA ret;
156 :
157 27102 : SIVAL(tmp, 0, jobid);
158 27102 : ret.dptr = (uint8_t *)tmp;
159 27102 : ret.dsize = sizeof(*tmp);
160 27102 : return ret;
161 : }
162 :
163 : /****************************************************************************
164 : Pack the devicemode to store it in a tdb.
165 : ****************************************************************************/
166 15300 : static int pack_devicemode(struct spoolss_DeviceMode *devmode, uint8_t *buf, int buflen)
167 : {
168 0 : enum ndr_err_code ndr_err;
169 15300 : DATA_BLOB blob = { .data = NULL };
170 15300 : int len = 0;
171 :
172 15300 : if (devmode) {
173 0 : ndr_err = ndr_push_struct_blob(&blob, talloc_tos(),
174 : devmode,
175 : (ndr_push_flags_fn_t)
176 : ndr_push_spoolss_DeviceMode);
177 0 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
178 0 : DEBUG(10, ("pack_devicemode: "
179 : "error encoding spoolss_DeviceMode\n"));
180 0 : goto done;
181 : }
182 : }
183 :
184 15300 : len = tdb_pack(buf, buflen, "B", blob.length, blob.data);
185 :
186 15300 : if (devmode) {
187 0 : DEBUG(8, ("Packed devicemode [%s]\n", devmode->formname));
188 : }
189 :
190 15300 : done:
191 15300 : return len;
192 : }
193 :
194 : /****************************************************************************
195 : Unpack the devicemode to store it in a tdb.
196 : ****************************************************************************/
197 19073 : static int unpack_devicemode(TALLOC_CTX *mem_ctx,
198 : const uint8_t *buf, int buflen,
199 : struct spoolss_DeviceMode **devmode)
200 : {
201 0 : struct spoolss_DeviceMode *dm;
202 0 : enum ndr_err_code ndr_err;
203 19073 : char *data = NULL;
204 19073 : uint32_t data_len = 0;
205 0 : DATA_BLOB blob;
206 19073 : int len = 0;
207 :
208 19073 : *devmode = NULL;
209 :
210 19073 : len = tdb_unpack(buf, buflen, "B", &data_len, &data);
211 19073 : if (!data) {
212 19073 : return len;
213 : }
214 :
215 0 : dm = talloc_zero(mem_ctx, struct spoolss_DeviceMode);
216 0 : if (!dm) {
217 0 : goto done;
218 : }
219 :
220 0 : blob = data_blob_const(data, data_len);
221 :
222 0 : ndr_err = ndr_pull_struct_blob(&blob, dm, dm,
223 : (ndr_pull_flags_fn_t)ndr_pull_spoolss_DeviceMode);
224 0 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
225 0 : DEBUG(10, ("unpack_devicemode: "
226 : "error parsing spoolss_DeviceMode\n"));
227 0 : goto done;
228 : }
229 :
230 0 : DEBUG(8, ("Unpacked devicemode [%s](%s)\n",
231 : dm->devicename, dm->formname));
232 0 : if (dm->driverextra_data.data) {
233 0 : DEBUG(8, ("with a private section of %d bytes\n",
234 : dm->__driverextra_length));
235 : }
236 :
237 0 : *devmode = dm;
238 :
239 0 : done:
240 0 : SAFE_FREE(data);
241 0 : return len;
242 : }
243 :
244 : /***********************************************************************
245 : unpack a pjob from a tdb buffer
246 : ***********************************************************************/
247 :
248 19073 : static int unpack_pjob(TALLOC_CTX *mem_ctx, uint8_t *buf, int buflen,
249 : struct printjob *pjob)
250 : {
251 19073 : int len = 0;
252 0 : int used;
253 0 : uint32_t pjpid, pjjobid, pjsysjob, pjfd, pjstarttime, pjstatus;
254 0 : uint32_t pjsize, pjpage_count, pjspooled, pjsmbjob;
255 :
256 19073 : if (!buf || !pjob) {
257 0 : return -1;
258 : }
259 :
260 38146 : len += tdb_unpack(buf+len, buflen-len, "ddddddddddfffff",
261 : &pjpid,
262 : &pjjobid,
263 : &pjsysjob,
264 : &pjfd,
265 : &pjstarttime,
266 : &pjstatus,
267 : &pjsize,
268 : &pjpage_count,
269 : &pjspooled,
270 : &pjsmbjob,
271 19073 : pjob->filename,
272 19073 : pjob->jobname,
273 19073 : pjob->user,
274 19073 : pjob->clientmachine,
275 19073 : pjob->queuename);
276 :
277 19073 : if (len == -1) {
278 0 : return -1;
279 : }
280 :
281 19073 : used = unpack_devicemode(mem_ctx, buf+len, buflen-len, &pjob->devmode);
282 19073 : if (used == -1) {
283 0 : return -1;
284 : }
285 :
286 19073 : len += used;
287 :
288 19073 : pjob->pid = pjpid;
289 19073 : pjob->jobid = pjjobid;
290 19073 : pjob->sysjob = pjsysjob;
291 19073 : pjob->fd = pjfd;
292 19073 : pjob->starttime = pjstarttime;
293 19073 : pjob->status = pjstatus;
294 19073 : pjob->size = pjsize;
295 19073 : pjob->page_count = pjpage_count;
296 19073 : pjob->spooled = pjspooled;
297 19073 : pjob->smbjob = pjsmbjob;
298 :
299 19073 : return len;
300 :
301 : }
302 :
303 : /****************************************************************************
304 : Useful function to find a print job in the database.
305 : ****************************************************************************/
306 :
307 9152 : static struct printjob *print_job_find(TALLOC_CTX *mem_ctx,
308 : const char *sharename,
309 : uint32_t jobid)
310 : {
311 0 : struct printjob *pjob;
312 0 : uint32_t tmp;
313 0 : TDB_DATA ret;
314 9152 : struct tdb_print_db *pdb = get_print_db_byname(sharename);
315 :
316 9152 : DEBUG(10,("print_job_find: looking up job %u for share %s\n",
317 : (unsigned int)jobid, sharename ));
318 :
319 9152 : if (!pdb) {
320 0 : return NULL;
321 : }
322 :
323 9152 : ret = tdb_fetch(pdb->tdb, print_key(jobid, &tmp));
324 9152 : release_print_db(pdb);
325 :
326 9152 : if (!ret.dptr) {
327 307 : DEBUG(10, ("print_job_find: failed to find jobid %u.\n",
328 : jobid));
329 307 : return NULL;
330 : }
331 :
332 8845 : pjob = talloc_zero(mem_ctx, struct printjob);
333 8845 : if (pjob == NULL) {
334 0 : goto err_out;
335 : }
336 :
337 8845 : if (unpack_pjob(mem_ctx, ret.dptr, ret.dsize, pjob) == -1) {
338 0 : DEBUG(10, ("failed to unpack jobid %u.\n", jobid));
339 0 : talloc_free(pjob);
340 0 : pjob = NULL;
341 0 : goto err_out;
342 : }
343 :
344 8845 : DEBUG(10,("print_job_find: returning system job %d for jobid %u.\n",
345 : pjob->sysjob, jobid));
346 8845 : SMB_ASSERT(pjob->jobid == jobid);
347 :
348 8845 : err_out:
349 8845 : SAFE_FREE(ret.dptr);
350 8845 : return pjob;
351 : }
352 :
353 : struct job_traverse_state {
354 : int sysjob;
355 : uint32_t jobid;
356 : };
357 :
358 : /* find spoolss jobid based on sysjob */
359 23424 : static int sysjob_to_jobid_traverse_fn(TDB_CONTEXT *the_tdb, TDB_DATA key,
360 : TDB_DATA data, void *private_data)
361 : {
362 0 : struct printjob *pjob;
363 23424 : struct job_traverse_state *state =
364 : (struct job_traverse_state *)private_data;
365 :
366 23424 : if (!data.dptr || data.dsize == 0)
367 1574 : return 0;
368 :
369 21850 : pjob = (struct printjob *)data.dptr;
370 21850 : if (key.dsize != sizeof(uint32_t))
371 12387 : return 0;
372 :
373 9463 : if (state->sysjob == pjob->sysjob) {
374 2683 : state->jobid = pjob->jobid;
375 2683 : return 1;
376 : }
377 :
378 6780 : return 0;
379 : }
380 :
381 2694 : uint32_t sysjob_to_jobid_pdb(struct tdb_print_db *pdb, int sysjob)
382 : {
383 0 : struct job_traverse_state state;
384 :
385 2694 : state.sysjob = sysjob;
386 2694 : state.jobid = (uint32_t)-1;
387 :
388 2694 : tdb_traverse(pdb->tdb, sysjob_to_jobid_traverse_fn, &state);
389 :
390 2694 : return state.jobid;
391 : }
392 :
393 : /****************************************************************************
394 : This is a *horribly expensive call as we have to iterate through all the
395 : current printer tdb's. Don't do this often ! JRA.
396 : ****************************************************************************/
397 :
398 0 : uint32_t sysjob_to_jobid(int unix_jobid)
399 : {
400 0 : int services = lp_numservices();
401 0 : int snum;
402 0 : struct job_traverse_state state;
403 :
404 0 : state.sysjob = unix_jobid;
405 0 : state.jobid = (uint32_t)-1;
406 :
407 0 : for (snum = 0; snum < services; snum++) {
408 0 : struct tdb_print_db *pdb;
409 0 : if (!lp_printable(snum))
410 0 : continue;
411 0 : pdb = get_print_db_byname(lp_const_servicename(snum));
412 0 : if (!pdb) {
413 0 : continue;
414 : }
415 0 : tdb_traverse(pdb->tdb, sysjob_to_jobid_traverse_fn, &state);
416 0 : release_print_db(pdb);
417 0 : if (state.jobid != (uint32_t)-1)
418 0 : return state.jobid;
419 : }
420 0 : return (uint32_t)-1;
421 : }
422 :
423 : /* find sysjob based on spoolss jobid */
424 14479 : static int jobid_to_sysjob_traverse_fn(TDB_CONTEXT *the_tdb, TDB_DATA key,
425 : TDB_DATA data, void *private_data)
426 : {
427 0 : struct printjob *pjob;
428 14479 : struct job_traverse_state *state =
429 : (struct job_traverse_state *)private_data;
430 :
431 14479 : if (!data.dptr || data.dsize == 0)
432 313 : return 0;
433 :
434 14166 : pjob = (struct printjob *)data.dptr;
435 14166 : if (key.dsize != sizeof(uint32_t))
436 9947 : return 0;
437 :
438 4219 : if (state->jobid == pjob->jobid) {
439 2048 : state->sysjob = pjob->sysjob;
440 2048 : return 1;
441 : }
442 :
443 2171 : return 0;
444 : }
445 :
446 2048 : int jobid_to_sysjob_pdb(struct tdb_print_db *pdb, uint32_t jobid)
447 : {
448 0 : struct job_traverse_state state;
449 :
450 2048 : state.sysjob = -1;
451 2048 : state.jobid = jobid;
452 :
453 2048 : tdb_traverse(pdb->tdb, jobid_to_sysjob_traverse_fn, &state);
454 :
455 2048 : return state.sysjob;
456 : }
457 :
458 : /****************************************************************************
459 : Send notifications based on what has changed after a pjob_store.
460 : ****************************************************************************/
461 :
462 : static const struct {
463 : uint32_t lpq_status;
464 : uint32_t spoolss_status;
465 : } lpq_to_spoolss_status_map[] = {
466 : { LPQ_QUEUED, JOB_STATUS_QUEUED },
467 : { LPQ_PAUSED, JOB_STATUS_PAUSED },
468 : { LPQ_SPOOLING, JOB_STATUS_SPOOLING },
469 : { LPQ_PRINTING, JOB_STATUS_PRINTING },
470 : { LPQ_DELETING, JOB_STATUS_DELETING },
471 : { LPQ_OFFLINE, JOB_STATUS_OFFLINE },
472 : { LPQ_PAPEROUT, JOB_STATUS_PAPEROUT },
473 : { LPQ_PRINTED, JOB_STATUS_PRINTED },
474 : { LPQ_DELETED, JOB_STATUS_DELETED },
475 : { LPQ_BLOCKED, JOB_STATUS_BLOCKED_DEVQ },
476 : { LPQ_USER_INTERVENTION, JOB_STATUS_USER_INTERVENTION },
477 : { (uint32_t)-1, 0 }
478 : };
479 :
480 : /* Convert a lpq status value stored in printing.tdb into the
481 : appropriate win32 API constant. */
482 :
483 1409 : static uint32_t map_to_spoolss_status(uint32_t lpq_status)
484 : {
485 1409 : int i = 0;
486 :
487 4393 : while (lpq_to_spoolss_status_map[i].lpq_status != -1) {
488 4365 : if (lpq_to_spoolss_status_map[i].lpq_status == lpq_status)
489 1381 : return lpq_to_spoolss_status_map[i].spoolss_status;
490 2984 : i++;
491 : }
492 :
493 28 : return 0;
494 : }
495 :
496 : /***************************************************************************
497 : Append a jobid to a list
498 : ***************************************************************************/
499 :
500 700 : static bool add_to_jobs_list(
501 : struct tdb_print_db *pdb, uint32_t jobid, const char *key)
502 : {
503 0 : uint8_t store_jobid[sizeof(uint32_t)];
504 700 : TDB_DATA data = {
505 : .dptr = store_jobid, .dsize = sizeof(store_jobid)
506 : };
507 0 : int ret;
508 :
509 700 : SIVAL(&store_jobid, 0, jobid);
510 :
511 700 : DBG_DEBUG("Added jobid %"PRIu32" to %s\n", jobid, key);
512 :
513 700 : ret = tdb_append(pdb->tdb, string_tdb_data(key), data);
514 700 : return ret == 0;
515 : }
516 :
517 : /***************************************************************************
518 : Remove a jobid from the 'jobs changed' list.
519 : ***************************************************************************/
520 :
521 1384 : static bool remove_from_jobs_list(
522 : const char *keystr, const char *sharename, uint32_t jobid)
523 : {
524 1384 : struct tdb_print_db *pdb = get_print_db_byname(sharename);
525 0 : TDB_DATA data, key;
526 0 : size_t job_count, i;
527 1384 : bool ret = False;
528 1384 : bool gotlock = False;
529 :
530 1384 : if (!pdb) {
531 0 : return False;
532 : }
533 :
534 1384 : ZERO_STRUCT(data);
535 :
536 1384 : key = string_tdb_data(keystr);
537 :
538 1384 : if (tdb_chainlock_with_timeout(pdb->tdb, key, 5) != 0)
539 0 : goto out;
540 :
541 1384 : gotlock = True;
542 :
543 1384 : data = tdb_fetch(pdb->tdb, key);
544 :
545 1384 : if (data.dptr == NULL || data.dsize == 0 || (data.dsize % 4 != 0))
546 611 : goto out;
547 :
548 773 : job_count = data.dsize / 4;
549 871 : for (i = 0; i < job_count; i++) {
550 0 : uint32_t ch_jobid;
551 :
552 798 : ch_jobid = IVAL(data.dptr, i*4);
553 798 : if (ch_jobid == jobid) {
554 700 : if (i < job_count -1 )
555 311 : memmove(data.dptr + (i*4), data.dptr + (i*4) + 4, (job_count - i - 1)*4 );
556 700 : data.dsize -= 4;
557 700 : if (tdb_store(pdb->tdb, key, data, TDB_REPLACE) != 0)
558 0 : goto out;
559 700 : break;
560 : }
561 : }
562 :
563 773 : ret = True;
564 1384 : out:
565 :
566 1384 : if (gotlock)
567 1384 : tdb_chainunlock(pdb->tdb, key);
568 1384 : SAFE_FREE(data.dptr);
569 1384 : release_print_db(pdb);
570 1384 : if (ret)
571 773 : DBG_DEBUG("removed jobid %"PRIu32"\n", jobid);
572 : else
573 611 : DBG_DEBUG("Failed to remove jobid %"PRIu32"\n", jobid);
574 1384 : return ret;
575 : }
576 :
577 32 : static bool remove_from_jobs_changed(const char* sharename, uint32_t jobid)
578 : {
579 32 : bool ret = remove_from_jobs_list(
580 : "INFO/jobs_changed", sharename, jobid);
581 32 : return ret;
582 : }
583 :
584 7650 : static void pjob_store_notify(struct tevent_context *ev,
585 : struct messaging_context *msg_ctx,
586 : const char* sharename, uint32_t jobid,
587 : struct printjob *old_data,
588 : struct printjob *new_data,
589 : bool *pchanged)
590 : {
591 7650 : bool new_job = false;
592 7650 : bool changed = false;
593 :
594 7650 : if (old_data == NULL) {
595 679 : new_job = true;
596 : }
597 :
598 : /* ACHTUNG! Due to a bug in Samba's spoolss parsing of the
599 : NOTIFY_INFO_DATA buffer, we *have* to send the job submission
600 : time first or else we'll end up with potential alignment
601 : errors. I don't think the systemtime should be spooled as
602 : a string, but this gets us around that error.
603 : --jerry (i'll feel dirty for this) */
604 :
605 7650 : if (new_job) {
606 679 : notify_job_submitted(ev, msg_ctx,
607 : sharename, jobid, new_data->starttime);
608 679 : notify_job_username(ev, msg_ctx,
609 679 : sharename, jobid, new_data->user);
610 679 : notify_job_name(ev, msg_ctx,
611 679 : sharename, jobid, new_data->jobname);
612 679 : notify_job_status(ev, msg_ctx,
613 679 : sharename, jobid, map_to_spoolss_status(new_data->status));
614 679 : notify_job_total_bytes(ev, msg_ctx,
615 679 : sharename, jobid, new_data->size);
616 679 : notify_job_total_pages(ev, msg_ctx,
617 679 : sharename, jobid, new_data->page_count);
618 : } else {
619 6971 : if (!strequal(old_data->jobname, new_data->jobname)) {
620 32 : notify_job_name(ev, msg_ctx, sharename,
621 32 : jobid, new_data->jobname);
622 32 : changed = true;
623 : }
624 :
625 6971 : if (old_data->status != new_data->status) {
626 730 : notify_job_status(ev, msg_ctx,
627 : sharename, jobid,
628 730 : map_to_spoolss_status(new_data->status));
629 : }
630 :
631 6971 : if (old_data->size != new_data->size) {
632 1942 : notify_job_total_bytes(ev, msg_ctx,
633 1942 : sharename, jobid, new_data->size);
634 : }
635 :
636 6971 : if (old_data->page_count != new_data->page_count) {
637 1920 : notify_job_total_pages(ev, msg_ctx,
638 : sharename, jobid,
639 1920 : new_data->page_count);
640 : }
641 : }
642 :
643 7650 : *pchanged = changed;
644 7650 : }
645 :
646 : /****************************************************************************
647 : Store a job structure back to the database.
648 : ****************************************************************************/
649 :
650 7650 : static bool pjob_store(struct tevent_context *ev,
651 : struct messaging_context *msg_ctx,
652 : const char* sharename, uint32_t jobid,
653 : struct printjob *pjob)
654 : {
655 0 : uint32_t tmp;
656 0 : TDB_DATA old_data, new_data;
657 7650 : bool ret = False;
658 7650 : struct tdb_print_db *pdb = get_print_db_byname(sharename);
659 7650 : uint8_t *buf = NULL;
660 0 : int len, newlen, buflen;
661 :
662 :
663 7650 : if (!pdb)
664 0 : return False;
665 :
666 : /* Get old data */
667 :
668 7650 : old_data = tdb_fetch(pdb->tdb, print_key(jobid, &tmp));
669 :
670 : /* Doh! Now we have to pack/unpack data since the NT_DEVICEMODE was added */
671 :
672 7650 : newlen = 0;
673 :
674 0 : do {
675 15300 : len = 0;
676 15300 : buflen = newlen;
677 30600 : len += tdb_pack(buf+len, buflen-len, "ddddddddddfffff",
678 15300 : (uint32_t)pjob->pid,
679 15300 : (uint32_t)pjob->jobid,
680 15300 : (uint32_t)pjob->sysjob,
681 15300 : (uint32_t)pjob->fd,
682 15300 : (uint32_t)pjob->starttime,
683 15300 : (uint32_t)pjob->status,
684 15300 : (uint32_t)pjob->size,
685 15300 : (uint32_t)pjob->page_count,
686 15300 : (uint32_t)pjob->spooled,
687 15300 : (uint32_t)pjob->smbjob,
688 15300 : pjob->filename,
689 15300 : pjob->jobname,
690 15300 : pjob->user,
691 15300 : pjob->clientmachine,
692 15300 : pjob->queuename);
693 :
694 15300 : len += pack_devicemode(pjob->devmode, buf+len, buflen-len);
695 :
696 15300 : if (buflen != len) {
697 7650 : buf = (uint8_t *)SMB_REALLOC(buf, len);
698 7650 : if (!buf) {
699 0 : DEBUG(0,("pjob_store: failed to enlarge buffer!\n"));
700 0 : goto done;
701 : }
702 7650 : newlen = len;
703 : }
704 15300 : } while ( buflen != len );
705 :
706 :
707 : /* Store new data */
708 :
709 7650 : new_data.dptr = buf;
710 7650 : new_data.dsize = len;
711 7650 : ret = (tdb_store(pdb->tdb, print_key(jobid, &tmp), new_data,
712 : TDB_REPLACE) == 0);
713 :
714 : /* Send notify updates for what has changed */
715 :
716 7650 : if (ret) {
717 7650 : bool changed = false;
718 0 : struct printjob old_pjob;
719 :
720 7650 : if (old_data.dsize) {
721 6971 : TALLOC_CTX *tmp_ctx = talloc_new(ev);
722 6971 : if (tmp_ctx == NULL)
723 0 : goto done;
724 :
725 6971 : len = unpack_pjob(tmp_ctx, old_data.dptr,
726 6971 : old_data.dsize, &old_pjob);
727 6971 : if (len != -1 ) {
728 6971 : pjob_store_notify(ev,
729 : msg_ctx,
730 : sharename, jobid, &old_pjob,
731 : pjob,
732 : &changed);
733 6971 : if (changed) {
734 32 : add_to_jobs_list(
735 : pdb,
736 : jobid,
737 : "INFO/jobs_changed");
738 : }
739 : }
740 6971 : talloc_free(tmp_ctx);
741 :
742 : } else {
743 : /* new job */
744 679 : pjob_store_notify(ev, msg_ctx,
745 : sharename, jobid, NULL, pjob,
746 : &changed);
747 : }
748 : }
749 :
750 0 : done:
751 7650 : release_print_db(pdb);
752 7650 : SAFE_FREE( old_data.dptr );
753 7650 : SAFE_FREE( buf );
754 :
755 7650 : return ret;
756 : }
757 :
758 : /****************************************************************************
759 : Remove a job structure from the database.
760 : ****************************************************************************/
761 :
762 682 : static void pjob_delete(struct tevent_context *ev,
763 : struct messaging_context *msg_ctx,
764 : const char* sharename, uint32_t jobid)
765 : {
766 0 : uint32_t tmp;
767 0 : struct printjob *pjob;
768 682 : uint32_t job_status = 0;
769 0 : struct tdb_print_db *pdb;
770 682 : TALLOC_CTX *tmp_ctx = talloc_new(ev);
771 682 : if (tmp_ctx == NULL) {
772 0 : return;
773 : }
774 :
775 682 : pdb = get_print_db_byname(sharename);
776 682 : if (!pdb) {
777 0 : goto err_out;
778 : }
779 :
780 682 : pjob = print_job_find(tmp_ctx, sharename, jobid);
781 682 : if (!pjob) {
782 8 : DEBUG(5, ("we were asked to delete nonexistent job %u\n",
783 : jobid));
784 8 : goto err_release;
785 : }
786 :
787 : /* We must cycle through JOB_STATUS_DELETING and
788 : JOB_STATUS_DELETED for the port monitor to delete the job
789 : properly. */
790 :
791 674 : job_status = JOB_STATUS_DELETING|JOB_STATUS_DELETED;
792 674 : notify_job_status(ev, msg_ctx, sharename, jobid, job_status);
793 :
794 : /* Remove from printing.tdb */
795 :
796 674 : tdb_delete(pdb->tdb, print_key(jobid, &tmp));
797 674 : remove_from_jobs_added(sharename, jobid);
798 674 : rap_jobid_delete(sharename, jobid);
799 682 : err_release:
800 682 : release_print_db(pdb);
801 682 : err_out:
802 682 : talloc_free(tmp_ctx);
803 : }
804 :
805 : /****************************************************************************
806 : List a unix job in the print database.
807 : ****************************************************************************/
808 :
809 11 : static void print_unix_job(struct tevent_context *ev,
810 : struct messaging_context *msg_ctx,
811 : const char *sharename, print_queue_struct *q,
812 : uint32_t jobid)
813 : {
814 0 : struct printjob pj, *old_pj;
815 11 : TALLOC_CTX *tmp_ctx = talloc_new(ev);
816 11 : if (tmp_ctx == NULL) {
817 0 : return;
818 : }
819 :
820 11 : if (jobid == (uint32_t)-1) {
821 11 : jobid = q->sysjob + UNIX_JOB_START;
822 : }
823 :
824 : /* Preserve the timestamp on an existing unix print job */
825 :
826 11 : old_pj = print_job_find(tmp_ctx, sharename, jobid);
827 :
828 11 : ZERO_STRUCT(pj);
829 :
830 11 : pj.pid = (pid_t)-1;
831 11 : pj.jobid = jobid;
832 11 : pj.sysjob = q->sysjob;
833 11 : pj.fd = -1;
834 11 : pj.starttime = old_pj ? old_pj->starttime : q->time;
835 11 : pj.status = q->status;
836 11 : pj.size = q->size;
837 11 : pj.spooled = True;
838 11 : fstrcpy(pj.filename, old_pj ? old_pj->filename : "");
839 11 : if (jobid < UNIX_JOB_START) {
840 0 : pj.smbjob = True;
841 0 : fstrcpy(pj.jobname, old_pj ? old_pj->jobname : "Remote Downlevel Document");
842 : } else {
843 11 : pj.smbjob = False;
844 11 : fstrcpy(pj.jobname, old_pj ? old_pj->jobname : q->fs_file);
845 : }
846 11 : fstrcpy(pj.user, old_pj ? old_pj->user : q->fs_user);
847 11 : fstrcpy(pj.queuename, old_pj ? old_pj->queuename : sharename );
848 :
849 11 : pjob_store(ev, msg_ctx, sharename, jobid, &pj);
850 11 : talloc_free(tmp_ctx);
851 : }
852 :
853 :
854 : struct traverse_struct {
855 : print_queue_struct *queue;
856 : size_t qcount, snum, maxcount, total_jobs;
857 : const char *sharename;
858 : time_t lpq_time;
859 : const char *lprm_command;
860 : struct printif *print_if;
861 : struct tevent_context *ev;
862 : struct messaging_context *msg_ctx;
863 : TALLOC_CTX *mem_ctx;
864 : };
865 :
866 : /****************************************************************************
867 : Utility fn to delete any jobs that are no longer active.
868 : ****************************************************************************/
869 :
870 17184 : static int traverse_fn_delete(TDB_CONTEXT *t, TDB_DATA key, TDB_DATA data, void *state)
871 : {
872 17184 : struct traverse_struct *ts = (struct traverse_struct *)state;
873 0 : struct printjob pjob;
874 0 : uint32_t jobid;
875 17184 : size_t i = 0;
876 :
877 17184 : if ( key.dsize != sizeof(jobid) )
878 13927 : return 0;
879 :
880 3257 : if (unpack_pjob(ts->mem_ctx, data.dptr, data.dsize, &pjob) == -1)
881 0 : return 0;
882 3257 : talloc_free(pjob.devmode);
883 3257 : jobid = pjob.jobid;
884 :
885 3257 : if (!pjob.smbjob) {
886 : /* remove a unix job if it isn't in the system queue any more */
887 88 : for (i=0;i<ts->qcount;i++) {
888 77 : if (ts->queue[i].sysjob == pjob.sysjob) {
889 11 : break;
890 : }
891 : }
892 22 : if (i == ts->qcount) {
893 11 : DEBUG(10,("traverse_fn_delete: pjob %u deleted due to !smbjob\n",
894 : (unsigned int)jobid ));
895 11 : pjob_delete(ts->ev, ts->msg_ctx,
896 : ts->sharename, jobid);
897 11 : return 0;
898 : }
899 :
900 : /* need to continue the the bottom of the function to
901 : save the correct attributes */
902 : }
903 :
904 : /* maybe it hasn't been spooled yet */
905 3246 : if (!pjob.spooled) {
906 : /* if a job is not spooled and the process doesn't
907 : exist then kill it. This cleans up after smbd
908 : deaths */
909 669 : if (!process_exists_by_pid(pjob.pid)) {
910 0 : DEBUG(10,("traverse_fn_delete: pjob %u deleted due to !process_exists (%u)\n",
911 : (unsigned int)jobid, (unsigned int)pjob.pid ));
912 0 : pjob_delete(ts->ev, ts->msg_ctx,
913 : ts->sharename, jobid);
914 : } else
915 669 : ts->total_jobs++;
916 669 : return 0;
917 : }
918 :
919 : /* this check only makes sense for jobs submitted from Windows clients */
920 :
921 2577 : if (pjob.smbjob) {
922 7759 : for (i=0;i<ts->qcount;i++) {
923 7580 : if ( pjob.status == LPQ_DELETED )
924 0 : continue;
925 :
926 7580 : if (ts->queue[i].sysjob == pjob.sysjob) {
927 :
928 : /* try to clean up any jobs that need to be deleted */
929 :
930 2387 : if ( pjob.status == LPQ_DELETING ) {
931 0 : int result;
932 :
933 9 : result = (*(ts->print_if->job_delete))(
934 : ts->sharename, ts->lprm_command, &pjob );
935 :
936 9 : if ( result != 0 ) {
937 : /* if we can't delete, then reset the job status */
938 0 : pjob.status = LPQ_QUEUED;
939 0 : pjob_store(ts->ev, ts->msg_ctx,
940 : ts->sharename, jobid, &pjob);
941 : }
942 : else {
943 : /* if we deleted the job, the remove the tdb record */
944 9 : pjob_delete(ts->ev,
945 : ts->msg_ctx,
946 : ts->sharename, jobid);
947 9 : pjob.status = LPQ_DELETED;
948 : }
949 :
950 : }
951 :
952 2387 : break;
953 : }
954 : }
955 : }
956 :
957 : /* The job isn't in the system queue - we have to assume it has
958 : completed, so delete the database entry. */
959 :
960 2577 : if (i == ts->qcount) {
961 :
962 : /* A race can occur between the time a job is spooled and
963 : when it appears in the lpq output. This happens when
964 : the job is added to printing.tdb when another smbd
965 : running print_queue_update() has completed a lpq and
966 : is currently traversing the printing tdb and deleting jobs.
967 : Don't delete the job if it was submitted after the lpq_time. */
968 :
969 179 : if (pjob.starttime < ts->lpq_time) {
970 48 : DEBUG(10,("traverse_fn_delete: pjob %u deleted due to pjob.starttime (%u) < ts->lpq_time (%u)\n",
971 : (unsigned int)jobid,
972 : (unsigned int)pjob.starttime,
973 : (unsigned int)ts->lpq_time ));
974 48 : pjob_delete(ts->ev, ts->msg_ctx,
975 : ts->sharename, jobid);
976 : } else
977 131 : ts->total_jobs++;
978 179 : return 0;
979 : }
980 :
981 : /* Save the pjob attributes we will store. */
982 2398 : ts->queue[i].sysjob = pjob.sysjob;
983 2398 : ts->queue[i].size = pjob.size;
984 2398 : ts->queue[i].page_count = pjob.page_count;
985 2398 : ts->queue[i].status = pjob.status;
986 2398 : ts->queue[i].priority = 1;
987 2398 : ts->queue[i].time = pjob.starttime;
988 2398 : fstrcpy(ts->queue[i].fs_user, pjob.user);
989 2398 : fstrcpy(ts->queue[i].fs_file, pjob.jobname);
990 :
991 2398 : ts->total_jobs++;
992 :
993 2398 : return 0;
994 : }
995 :
996 : /****************************************************************************
997 : Check if the print queue has been updated recently enough.
998 : ****************************************************************************/
999 :
1000 116 : static void print_cache_flush(const char *sharename)
1001 : {
1002 0 : fstring key;
1003 116 : struct tdb_print_db *pdb = get_print_db_byname(sharename);
1004 :
1005 116 : if (!pdb)
1006 0 : return;
1007 116 : slprintf(key, sizeof(key)-1, "CACHE/%s", sharename);
1008 116 : tdb_store_int32(pdb->tdb, key, -1);
1009 116 : release_print_db(pdb);
1010 : }
1011 :
1012 : /****************************************************************************
1013 : Check if someone already thinks they are doing the update.
1014 : ****************************************************************************/
1015 :
1016 3324 : static pid_t get_updating_pid(const char *sharename)
1017 : {
1018 0 : fstring keystr;
1019 0 : TDB_DATA data, key;
1020 0 : pid_t updating_pid;
1021 3324 : struct tdb_print_db *pdb = get_print_db_byname(sharename);
1022 :
1023 3324 : if (!pdb)
1024 0 : return (pid_t)-1;
1025 3324 : slprintf(keystr, sizeof(keystr)-1, "UPDATING/%s", sharename);
1026 3324 : key = string_tdb_data(keystr);
1027 :
1028 3324 : data = tdb_fetch(pdb->tdb, key);
1029 3324 : release_print_db(pdb);
1030 3324 : if (!data.dptr || data.dsize != sizeof(pid_t)) {
1031 3261 : SAFE_FREE(data.dptr);
1032 3261 : return (pid_t)-1;
1033 : }
1034 :
1035 63 : updating_pid = IVAL(data.dptr, 0);
1036 63 : SAFE_FREE(data.dptr);
1037 :
1038 63 : if (process_exists_by_pid(updating_pid))
1039 63 : return updating_pid;
1040 :
1041 0 : return (pid_t)-1;
1042 : }
1043 :
1044 : /****************************************************************************
1045 : Set the fact that we're doing the update, or have finished doing the update
1046 : in the tdb.
1047 : ****************************************************************************/
1048 :
1049 3260 : static void set_updating_pid(const fstring sharename, bool updating)
1050 : {
1051 0 : fstring keystr;
1052 0 : TDB_DATA key;
1053 0 : TDB_DATA data;
1054 3260 : pid_t updating_pid = getpid();
1055 0 : uint8_t buffer[4];
1056 :
1057 3260 : struct tdb_print_db *pdb = get_print_db_byname(sharename);
1058 :
1059 3260 : if (!pdb)
1060 1630 : return;
1061 :
1062 3260 : slprintf(keystr, sizeof(keystr)-1, "UPDATING/%s", sharename);
1063 3260 : key = string_tdb_data(keystr);
1064 :
1065 3260 : DEBUG(5, ("set_updating_pid: %supdating lpq cache for print share %s\n",
1066 : updating ? "" : "not ",
1067 : sharename ));
1068 :
1069 3260 : if ( !updating ) {
1070 1630 : tdb_delete(pdb->tdb, key);
1071 1630 : release_print_db(pdb);
1072 1630 : return;
1073 : }
1074 :
1075 1630 : SIVAL( buffer, 0, updating_pid);
1076 1630 : data.dptr = buffer;
1077 1630 : data.dsize = 4; /* we always assume this is a 4 byte value */
1078 :
1079 1630 : tdb_store(pdb->tdb, key, data, TDB_REPLACE);
1080 1630 : release_print_db(pdb);
1081 : }
1082 :
1083 : /****************************************************************************
1084 : Sort print jobs by submittal time.
1085 : ****************************************************************************/
1086 :
1087 5144 : static int printjob_comp(print_queue_struct *j1, print_queue_struct *j2)
1088 : {
1089 : /* Silly cases */
1090 :
1091 5144 : if (!j1 && !j2)
1092 0 : return 0;
1093 5144 : if (!j1)
1094 0 : return -1;
1095 5144 : if (!j2)
1096 0 : return 1;
1097 :
1098 : /* Sort on job start time */
1099 :
1100 5144 : if (j1->time == j2->time)
1101 3934 : return 0;
1102 1210 : return (j1->time > j2->time) ? 1 : -1;
1103 : }
1104 :
1105 : /****************************************************************************
1106 : Store the sorted queue representation for later portmon retrieval.
1107 : Skip deleted jobs
1108 : ****************************************************************************/
1109 :
1110 1630 : static void store_queue_struct(struct tdb_print_db *pdb, struct traverse_struct *pts)
1111 : {
1112 0 : TDB_DATA data;
1113 1630 : int max_reported_jobs = lp_max_reported_print_jobs(pts->snum);
1114 1630 : print_queue_struct *queue = pts->queue;
1115 0 : size_t len;
1116 0 : size_t i;
1117 0 : unsigned int qcount;
1118 :
1119 1630 : if (max_reported_jobs && (max_reported_jobs < pts->qcount))
1120 0 : pts->qcount = max_reported_jobs;
1121 1630 : qcount = 0;
1122 :
1123 : /* Work out the size. */
1124 1630 : data.dsize = 0;
1125 1630 : data.dsize += tdb_pack(NULL, 0, "d", qcount);
1126 :
1127 4028 : for (i = 0; i < pts->qcount; i++) {
1128 2398 : if ( queue[i].status == LPQ_DELETED )
1129 9 : continue;
1130 :
1131 2389 : qcount++;
1132 2389 : data.dsize += tdb_pack(NULL, 0, "ddddddff",
1133 2389 : (uint32_t)queue[i].sysjob,
1134 2389 : (uint32_t)queue[i].size,
1135 2389 : (uint32_t)queue[i].page_count,
1136 2389 : (uint32_t)queue[i].status,
1137 2389 : (uint32_t)queue[i].priority,
1138 2389 : (uint32_t)queue[i].time,
1139 2389 : queue[i].fs_user,
1140 2389 : queue[i].fs_file);
1141 : }
1142 :
1143 1630 : if ((data.dptr = (uint8_t *)SMB_MALLOC(data.dsize)) == NULL)
1144 0 : return;
1145 :
1146 1630 : len = 0;
1147 1630 : len += tdb_pack(data.dptr + len, data.dsize - len, "d", qcount);
1148 4028 : for (i = 0; i < pts->qcount; i++) {
1149 2398 : if ( queue[i].status == LPQ_DELETED )
1150 9 : continue;
1151 :
1152 2389 : len += tdb_pack(data.dptr + len, data.dsize - len, "ddddddff",
1153 2389 : (uint32_t)queue[i].sysjob,
1154 2389 : (uint32_t)queue[i].size,
1155 2389 : (uint32_t)queue[i].page_count,
1156 2389 : (uint32_t)queue[i].status,
1157 2389 : (uint32_t)queue[i].priority,
1158 2389 : (uint32_t)queue[i].time,
1159 2389 : queue[i].fs_user,
1160 2389 : queue[i].fs_file);
1161 : }
1162 :
1163 1630 : tdb_store(pdb->tdb, string_tdb_data("INFO/linear_queue_array"), data,
1164 : TDB_REPLACE);
1165 1630 : SAFE_FREE(data.dptr);
1166 1630 : return;
1167 : }
1168 :
1169 1630 : static TDB_DATA get_jobs_added_data(struct tdb_print_db *pdb)
1170 : {
1171 0 : TDB_DATA data;
1172 :
1173 1630 : ZERO_STRUCT(data);
1174 :
1175 1630 : data = tdb_fetch(pdb->tdb, string_tdb_data("INFO/jobs_added"));
1176 1630 : if (data.dptr == NULL || data.dsize == 0 || (data.dsize % 4 != 0)) {
1177 901 : SAFE_FREE(data.dptr);
1178 901 : ZERO_STRUCT(data);
1179 : }
1180 :
1181 1630 : return data;
1182 : }
1183 :
1184 2387 : static void check_job_added(const char *sharename, TDB_DATA data, uint32_t jobid)
1185 : {
1186 0 : unsigned int i;
1187 2387 : unsigned int job_count = data.dsize / 4;
1188 :
1189 4943 : for (i = 0; i < job_count; i++) {
1190 0 : uint32_t ch_jobid;
1191 :
1192 2556 : ch_jobid = IVAL(data.dptr, i*4);
1193 2556 : if (ch_jobid == jobid)
1194 340 : remove_from_jobs_added(sharename, jobid);
1195 : }
1196 2387 : }
1197 :
1198 : /****************************************************************************
1199 : Check if the print queue has been updated recently enough.
1200 : ****************************************************************************/
1201 :
1202 4863 : static bool print_cache_expired(const char *sharename, bool check_pending)
1203 : {
1204 0 : fstring key;
1205 4863 : time_t last_qscan_time, time_now = time(NULL);
1206 4863 : struct tdb_print_db *pdb = get_print_db_byname(sharename);
1207 4863 : bool result = False;
1208 :
1209 4863 : if (!pdb)
1210 0 : return False;
1211 :
1212 4863 : snprintf(key, sizeof(key), "CACHE/%s", sharename);
1213 4863 : last_qscan_time = (time_t)tdb_fetch_int32(pdb->tdb, key);
1214 :
1215 : /*
1216 : * Invalidate the queue for 3 reasons.
1217 : * (1). last queue scan time == -1.
1218 : * (2). Current time - last queue scan time > allowed cache time.
1219 : * (3). last queue scan time > current time + MAX_CACHE_VALID_TIME (1 hour by default).
1220 : * This last test picks up machines for which the clock has been moved
1221 : * forward, an lpq scan done and then the clock moved back. Otherwise
1222 : * that last lpq scan would stay around for a loooong loooong time... :-). JRA.
1223 : */
1224 :
1225 4863 : if (last_qscan_time == ((time_t)-1)
1226 4628 : || (time_now - last_qscan_time) >= lp_lpq_cache_time()
1227 0 : || last_qscan_time > (time_now + MAX_CACHE_VALID_TIME))
1228 : {
1229 0 : uint32_t u;
1230 0 : time_t msg_pending_time;
1231 :
1232 4863 : DEBUG(4, ("print_cache_expired: cache expired for queue %s "
1233 : "(last_qscan_time = %d, time now = %d, qcachetime = %d)\n",
1234 : sharename, (int)last_qscan_time, (int)time_now,
1235 : (int)lp_lpq_cache_time() ));
1236 :
1237 : /* check if another smbd has already sent a message to update the
1238 : queue. Give the pending message one minute to clear and
1239 : then send another message anyways. Make sure to check for
1240 : clocks that have been run forward and then back again. */
1241 :
1242 4863 : snprintf(key, sizeof(key), "MSG_PENDING/%s", sharename);
1243 :
1244 4863 : if ( check_pending
1245 3170 : && tdb_fetch_uint32( pdb->tdb, key, &u )
1246 3114 : && (msg_pending_time=u) > 0
1247 1807 : && msg_pending_time <= time_now
1248 1807 : && (time_now - msg_pending_time) < 60 )
1249 : {
1250 1807 : DEBUG(4,("print_cache_expired: message already pending for %s. Accepting cache\n",
1251 : sharename));
1252 1807 : goto done;
1253 : }
1254 :
1255 3056 : result = True;
1256 : }
1257 :
1258 0 : done:
1259 4863 : release_print_db(pdb);
1260 4863 : return result;
1261 : }
1262 :
1263 : /****************************************************************************
1264 : main work for updating the lpq cache for a printer queue
1265 : ****************************************************************************/
1266 :
1267 1630 : static void print_queue_update_internal(struct tevent_context *ev,
1268 : struct messaging_context *msg_ctx,
1269 : const char *sharename,
1270 : struct printif *current_printif,
1271 : char *lpq_command, char *lprm_command)
1272 : {
1273 0 : size_t i, qcount;
1274 1630 : print_queue_struct *queue = NULL;
1275 0 : print_status_struct status;
1276 0 : print_status_struct old_status;
1277 0 : struct printjob *pjob;
1278 0 : struct traverse_struct tstruct;
1279 0 : TDB_DATA data, key;
1280 0 : TDB_DATA jcdata;
1281 0 : fstring keystr, cachestr;
1282 1630 : struct tdb_print_db *pdb = get_print_db_byname(sharename);
1283 1630 : TALLOC_CTX *tmp_ctx = talloc_new(ev);
1284 :
1285 1630 : if ((pdb == NULL) || (tmp_ctx == NULL)) {
1286 0 : return;
1287 : }
1288 :
1289 1630 : DEBUG(5,("print_queue_update_internal: printer = %s, type = %d, lpq command = [%s]\n",
1290 : sharename, current_printif->type, lpq_command));
1291 :
1292 : /*
1293 : * Update the cache time FIRST ! Stops others even
1294 : * attempting to get the lock and doing this
1295 : * if the lpq takes a long time.
1296 : */
1297 :
1298 1630 : slprintf(cachestr, sizeof(cachestr)-1, "CACHE/%s", sharename);
1299 1630 : tdb_store_int32(pdb->tdb, cachestr, (int)time(NULL));
1300 :
1301 : /* get the current queue using the appropriate interface */
1302 1630 : ZERO_STRUCT(status);
1303 :
1304 1630 : qcount = (*(current_printif->queue_get))(sharename,
1305 : current_printif->type,
1306 : lpq_command, &queue, &status);
1307 :
1308 1630 : DBG_NOTICE("%zu job%s in queue for %s\n",
1309 : qcount,
1310 : (qcount != 1) ? "s" : "",
1311 : sharename);
1312 :
1313 : /* Sort the queue by submission time otherwise they are displayed
1314 : in hash order. */
1315 :
1316 1630 : TYPESAFE_QSORT(queue, qcount, printjob_comp);
1317 :
1318 : /*
1319 : any job in the internal database that is marked as spooled
1320 : and doesn't exist in the system queue is considered finished
1321 : and removed from the database
1322 :
1323 : any job in the system database but not in the internal database
1324 : is added as a unix job
1325 :
1326 : fill in any system job numbers as we go
1327 : */
1328 1630 : jcdata = get_jobs_added_data(pdb);
1329 :
1330 4028 : for (i=0; i<qcount; i++) {
1331 2398 : uint32_t jobid = sysjob_to_jobid_pdb(pdb, queue[i].sysjob);
1332 2398 : if (jobid == (uint32_t)-1) {
1333 : /* assume its a unix print job */
1334 11 : print_unix_job(ev, msg_ctx,
1335 11 : sharename, &queue[i], jobid);
1336 11 : continue;
1337 : }
1338 :
1339 : /* we have an active SMB print job - update its status */
1340 2387 : pjob = print_job_find(tmp_ctx, sharename, jobid);
1341 2387 : if (!pjob) {
1342 : /* err, somethings wrong. Probably smbd was restarted
1343 : with jobs in the queue. All we can do is treat them
1344 : like unix jobs. Pity. */
1345 0 : DEBUG(1, ("queued print job %d not found in jobs list, "
1346 : "assuming unix job\n", jobid));
1347 0 : print_unix_job(ev, msg_ctx,
1348 0 : sharename, &queue[i], jobid);
1349 0 : continue;
1350 : }
1351 :
1352 : /* don't reset the status on jobs to be deleted */
1353 :
1354 2387 : if ( pjob->status != LPQ_DELETING )
1355 2378 : pjob->status = queue[i].status;
1356 :
1357 2387 : pjob_store(ev, msg_ctx, sharename, jobid, pjob);
1358 :
1359 2387 : check_job_added(sharename, jcdata, jobid);
1360 : }
1361 :
1362 1630 : SAFE_FREE(jcdata.dptr);
1363 :
1364 : /* now delete any queued entries that don't appear in the
1365 : system queue */
1366 1630 : tstruct.queue = queue;
1367 1630 : tstruct.qcount = qcount;
1368 1630 : tstruct.snum = -1;
1369 1630 : tstruct.total_jobs = 0;
1370 1630 : tstruct.lpq_time = time(NULL);
1371 1630 : tstruct.sharename = sharename;
1372 1630 : tstruct.lprm_command = lprm_command;
1373 1630 : tstruct.print_if = current_printif;
1374 1630 : tstruct.ev = ev;
1375 1630 : tstruct.msg_ctx = msg_ctx;
1376 1630 : tstruct.mem_ctx = tmp_ctx;
1377 :
1378 1630 : tdb_traverse(pdb->tdb, traverse_fn_delete, (void *)&tstruct);
1379 :
1380 : /* Store the linearised queue, max jobs only. */
1381 1630 : store_queue_struct(pdb, &tstruct);
1382 :
1383 1630 : SAFE_FREE(tstruct.queue);
1384 1630 : talloc_free(tmp_ctx);
1385 :
1386 1630 : DBG_DEBUG("printer %s INFO, total_jobs = %zu\n",
1387 : sharename,
1388 : tstruct.total_jobs);
1389 :
1390 1630 : tdb_store_int32(pdb->tdb, "INFO/total_jobs", tstruct.total_jobs);
1391 :
1392 1630 : get_queue_status(sharename, &old_status);
1393 1630 : if (old_status.qcount != qcount) {
1394 595 : DBG_DEBUG("Queue status change %zu jobs -> %zu jobs "
1395 : "for printer %s\n",
1396 : old_status.qcount,
1397 : qcount,
1398 : sharename);
1399 : }
1400 :
1401 : /* store the new queue status structure */
1402 1630 : slprintf(keystr, sizeof(keystr)-1, "STATUS/%s", sharename);
1403 1630 : key = string_tdb_data(keystr);
1404 :
1405 1630 : status.qcount = qcount;
1406 1630 : data.dptr = (uint8_t *)&status;
1407 1630 : data.dsize = sizeof(status);
1408 1630 : tdb_store(pdb->tdb, key, data, TDB_REPLACE);
1409 :
1410 : /*
1411 : * Update the cache time again. We want to do this call
1412 : * as little as possible...
1413 : */
1414 :
1415 1630 : slprintf(keystr, sizeof(keystr)-1, "CACHE/%s", sharename);
1416 1630 : tdb_store_int32(pdb->tdb, keystr, (int32_t)time(NULL));
1417 :
1418 : /* clear the msg pending record for this queue */
1419 :
1420 1630 : snprintf(keystr, sizeof(keystr), "MSG_PENDING/%s", sharename);
1421 :
1422 1630 : if ( !tdb_store_uint32( pdb->tdb, keystr, 0 ) ) {
1423 : /* log a message but continue on */
1424 :
1425 0 : DEBUG(0,("print_queue_update: failed to store MSG_PENDING flag for [%s]!\n",
1426 : sharename));
1427 : }
1428 :
1429 1630 : release_print_db( pdb );
1430 :
1431 1630 : return;
1432 : }
1433 :
1434 : /****************************************************************************
1435 : Update the internal database from the system print queue for a queue.
1436 : obtain a lock on the print queue before proceeding (needed when multiple
1437 : smbd processes maytry to update the lpq cache concurrently).
1438 : ****************************************************************************/
1439 :
1440 1693 : static void print_queue_update_with_lock( struct tevent_context *ev,
1441 : struct messaging_context *msg_ctx,
1442 : const char *sharename,
1443 : struct printif *current_printif,
1444 : char *lpq_command, char *lprm_command )
1445 : {
1446 0 : fstring keystr;
1447 0 : struct tdb_print_db *pdb;
1448 :
1449 1693 : DEBUG(5,("print_queue_update_with_lock: printer share = %s\n", sharename));
1450 1693 : pdb = get_print_db_byname(sharename);
1451 1693 : if (!pdb)
1452 63 : return;
1453 :
1454 1693 : if ( !print_cache_expired(sharename, False) ) {
1455 0 : DEBUG(5,("print_queue_update_with_lock: print cache for %s is still ok\n", sharename));
1456 0 : release_print_db(pdb);
1457 0 : return;
1458 : }
1459 :
1460 : /*
1461 : * Check to see if someone else is doing this update.
1462 : * This is essentially a mutex on the update.
1463 : */
1464 :
1465 1693 : if (get_updating_pid(sharename) != -1) {
1466 62 : release_print_db(pdb);
1467 62 : return;
1468 : }
1469 :
1470 : /* Lock the queue for the database update */
1471 :
1472 1631 : slprintf(keystr, sizeof(keystr) - 1, "LOCK/%s", sharename);
1473 : /* Only wait 10 seconds for this. */
1474 1631 : if (tdb_lock_bystring_with_timeout(pdb->tdb, keystr, 10) != 0) {
1475 0 : DEBUG(0,("print_queue_update_with_lock: Failed to lock printer %s database\n", sharename));
1476 0 : release_print_db(pdb);
1477 0 : return;
1478 : }
1479 :
1480 : /*
1481 : * Ensure that no one else got in here.
1482 : * If the updating pid is still -1 then we are
1483 : * the winner.
1484 : */
1485 :
1486 1631 : if (get_updating_pid(sharename) != -1) {
1487 : /*
1488 : * Someone else is doing the update, exit.
1489 : */
1490 1 : tdb_unlock_bystring(pdb->tdb, keystr);
1491 1 : release_print_db(pdb);
1492 1 : return;
1493 : }
1494 :
1495 : /*
1496 : * We're going to do the update ourselves.
1497 : */
1498 :
1499 : /* Tell others we're doing the update. */
1500 1630 : set_updating_pid(sharename, True);
1501 :
1502 : /*
1503 : * Allow others to enter and notice we're doing
1504 : * the update.
1505 : */
1506 :
1507 1630 : tdb_unlock_bystring(pdb->tdb, keystr);
1508 :
1509 : /* do the main work now */
1510 :
1511 1630 : print_queue_update_internal(ev, msg_ctx,
1512 : sharename, current_printif,
1513 : lpq_command, lprm_command);
1514 :
1515 : /* Delete our pid from the db. */
1516 1630 : set_updating_pid(sharename, False);
1517 1630 : release_print_db(pdb);
1518 : }
1519 :
1520 : /****************************************************************************
1521 : this is the receive function of the background lpq updater
1522 : ****************************************************************************/
1523 1329 : void print_queue_receive(struct messaging_context *msg,
1524 : void *private_data,
1525 : uint32_t msg_type,
1526 : struct server_id server_id,
1527 : DATA_BLOB *data)
1528 : {
1529 0 : fstring sharename;
1530 1329 : char *lpqcommand = NULL, *lprmcommand = NULL;
1531 0 : int printing_type;
1532 0 : size_t len;
1533 :
1534 1329 : len = tdb_unpack( (uint8_t *)data->data, data->length, "fdPP",
1535 : sharename,
1536 : &printing_type,
1537 : &lpqcommand,
1538 : &lprmcommand );
1539 :
1540 1329 : if ( len == -1 ) {
1541 0 : SAFE_FREE(lpqcommand);
1542 0 : SAFE_FREE(lprmcommand);
1543 0 : DEBUG(0,("print_queue_receive: Got invalid print queue update message\n"));
1544 0 : return;
1545 : }
1546 :
1547 1329 : print_queue_update_with_lock(global_event_context(), msg, sharename,
1548 : get_printer_fns_from_type((enum printing_types)printing_type),
1549 : lpqcommand, lprmcommand );
1550 :
1551 1329 : SAFE_FREE(lpqcommand);
1552 1329 : SAFE_FREE(lprmcommand);
1553 1329 : return;
1554 : }
1555 :
1556 : /****************************************************************************
1557 : update the internal database from the system print queue for a queue
1558 : ****************************************************************************/
1559 :
1560 1693 : static void print_queue_update(struct messaging_context *msg_ctx,
1561 : int snum, bool force)
1562 : {
1563 0 : char key[268];
1564 0 : fstring sharename;
1565 1693 : char *lpqcommand = NULL;
1566 1693 : char *lprmcommand = NULL;
1567 1693 : uint8_t *buffer = NULL;
1568 1693 : size_t len = 0;
1569 0 : size_t newlen;
1570 0 : struct tdb_print_db *pdb;
1571 0 : int type;
1572 0 : struct printif *current_printif;
1573 1693 : TALLOC_CTX *ctx = talloc_tos();
1574 0 : const struct loadparm_substitution *lp_sub =
1575 1693 : loadparm_s3_global_substitution();
1576 :
1577 1693 : fstrcpy( sharename, lp_const_servicename(snum));
1578 :
1579 : /* don't strip out characters like '$' from the printername */
1580 :
1581 1693 : lpqcommand = talloc_string_sub2(ctx,
1582 : lp_lpq_command(snum),
1583 : "%p",
1584 : lp_printername(talloc_tos(), lp_sub, snum),
1585 : false, false, false);
1586 1693 : if (!lpqcommand) {
1587 0 : return;
1588 : }
1589 3386 : lpqcommand = talloc_sub_full(ctx,
1590 1693 : lp_servicename(talloc_tos(), lp_sub, snum),
1591 : current_user_info.unix_name,
1592 : "",
1593 : get_current_gid(NULL),
1594 : get_current_username(),
1595 : get_current_user_info_domain(),
1596 : lpqcommand);
1597 1693 : if (!lpqcommand) {
1598 0 : return;
1599 : }
1600 :
1601 1693 : lprmcommand = talloc_string_sub2(ctx,
1602 : lp_lprm_command(snum),
1603 : "%p",
1604 : lp_printername(talloc_tos(), lp_sub, snum),
1605 : false, false, false);
1606 1693 : if (!lprmcommand) {
1607 0 : return;
1608 : }
1609 3386 : lprmcommand = talloc_sub_full(ctx,
1610 1693 : lp_servicename(talloc_tos(), lp_sub, snum),
1611 : current_user_info.unix_name,
1612 : "",
1613 : get_current_gid(NULL),
1614 : get_current_username(),
1615 : get_current_user_info_domain(),
1616 : lprmcommand);
1617 1693 : if (!lprmcommand) {
1618 0 : return;
1619 : }
1620 :
1621 : /*
1622 : * Make sure that the background queue process exists.
1623 : * Otherwise just do the update ourselves
1624 : */
1625 :
1626 1693 : if ( force || background_lpq_updater_pid == -1 ) {
1627 364 : DEBUG(4,("print_queue_update: updating queue [%s] myself\n", sharename));
1628 364 : current_printif = get_printer_fns( snum );
1629 364 : print_queue_update_with_lock(global_event_context(), msg_ctx,
1630 : sharename, current_printif,
1631 : lpqcommand, lprmcommand);
1632 :
1633 364 : return;
1634 : }
1635 :
1636 1329 : type = lp_printing(snum);
1637 :
1638 : /* get the length */
1639 :
1640 1329 : len = tdb_pack( NULL, 0, "fdPP",
1641 : sharename,
1642 : type,
1643 : lpqcommand,
1644 : lprmcommand );
1645 :
1646 1329 : buffer = SMB_XMALLOC_ARRAY( uint8_t, len );
1647 :
1648 : /* now pack the buffer */
1649 1329 : newlen = tdb_pack( buffer, len, "fdPP",
1650 : sharename,
1651 : type,
1652 : lpqcommand,
1653 : lprmcommand );
1654 :
1655 1329 : SMB_ASSERT( newlen == len );
1656 :
1657 1329 : DEBUG(10,("print_queue_update: Sending message -> printer = %s, "
1658 : "type = %d, lpq command = [%s] lprm command = [%s]\n",
1659 : sharename, type, lpqcommand, lprmcommand ));
1660 :
1661 : /* here we set a msg pending record for other smbd processes
1662 : to throttle the number of duplicate print_queue_update msgs
1663 : sent. */
1664 :
1665 1329 : pdb = get_print_db_byname(sharename);
1666 1329 : if (!pdb) {
1667 0 : SAFE_FREE(buffer);
1668 0 : return;
1669 : }
1670 :
1671 1329 : snprintf(key, sizeof(key), "MSG_PENDING/%s", sharename);
1672 :
1673 1329 : if ( !tdb_store_uint32( pdb->tdb, key, time(NULL) ) ) {
1674 : /* log a message but continue on */
1675 :
1676 0 : DEBUG(0,("print_queue_update: failed to store MSG_PENDING flag for [%s]!\n",
1677 : sharename));
1678 : }
1679 :
1680 1329 : release_print_db( pdb );
1681 :
1682 : /* finally send the message */
1683 :
1684 1329 : send_to_bgqd(msg_ctx, MSG_PRINTER_UPDATE, (uint8_t *)buffer, len);
1685 :
1686 1329 : SAFE_FREE( buffer );
1687 :
1688 1329 : return;
1689 : }
1690 :
1691 : /****************************************************************************
1692 : Create/Update an entry in the print tdb that will allow us to send notify
1693 : updates only to interested smbd's.
1694 : ****************************************************************************/
1695 :
1696 12 : bool print_notify_register_pid(int snum)
1697 : {
1698 0 : TDB_DATA data;
1699 12 : struct tdb_print_db *pdb = NULL;
1700 12 : TDB_CONTEXT *tdb = NULL;
1701 0 : const char *printername;
1702 12 : uint32_t mypid = (uint32_t)getpid();
1703 12 : bool ret = False;
1704 0 : size_t i;
1705 :
1706 : /* if (snum == -1), then the change notify request was
1707 : on a print server handle and we need to register on
1708 : all print queues */
1709 :
1710 12 : if (snum == -1)
1711 : {
1712 2 : int num_services = lp_numservices();
1713 0 : int idx;
1714 :
1715 246 : for ( idx=0; idx<num_services; idx++ ) {
1716 244 : if (lp_snum_ok(idx) && lp_printable(idx) )
1717 10 : print_notify_register_pid(idx);
1718 : }
1719 :
1720 2 : return True;
1721 : }
1722 : else /* register for a specific printer */
1723 : {
1724 10 : printername = lp_const_servicename(snum);
1725 10 : pdb = get_print_db_byname(printername);
1726 10 : if (!pdb)
1727 0 : return False;
1728 10 : tdb = pdb->tdb;
1729 : }
1730 :
1731 10 : if (tdb_lock_bystring_with_timeout(tdb, NOTIFY_PID_LIST_KEY, 10) != 0) {
1732 0 : DEBUG(0,("print_notify_register_pid: Failed to lock printer %s\n",
1733 : printername));
1734 0 : if (pdb)
1735 0 : release_print_db(pdb);
1736 0 : return False;
1737 : }
1738 :
1739 10 : data = get_printer_notify_pid_list( tdb, printername, True );
1740 :
1741 : /* Add ourselves and increase the refcount. */
1742 :
1743 10 : for (i = 0; i < data.dsize; i += 8) {
1744 0 : if (IVAL(data.dptr,i) == mypid) {
1745 0 : uint32_t new_refcount = IVAL(data.dptr, i+4) + 1;
1746 0 : SIVAL(data.dptr, i+4, new_refcount);
1747 0 : break;
1748 : }
1749 : }
1750 :
1751 10 : if (i == data.dsize) {
1752 : /* We weren't in the list. Realloc. */
1753 10 : data.dptr = (uint8_t *)SMB_REALLOC(data.dptr, data.dsize + 8);
1754 10 : if (!data.dptr) {
1755 0 : DEBUG(0,("print_notify_register_pid: Relloc fail for printer %s\n",
1756 : printername));
1757 0 : goto done;
1758 : }
1759 10 : data.dsize += 8;
1760 10 : SIVAL(data.dptr,data.dsize - 8,mypid);
1761 10 : SIVAL(data.dptr,data.dsize - 4,1); /* Refcount. */
1762 : }
1763 :
1764 : /* Store back the record. */
1765 10 : if (tdb_store_bystring(tdb, NOTIFY_PID_LIST_KEY, data, TDB_REPLACE) != 0) {
1766 0 : DEBUG(0,("print_notify_register_pid: Failed to update pid \
1767 : list for printer %s\n", printername));
1768 0 : goto done;
1769 : }
1770 :
1771 10 : ret = True;
1772 :
1773 10 : done:
1774 :
1775 10 : tdb_unlock_bystring(tdb, NOTIFY_PID_LIST_KEY);
1776 10 : if (pdb)
1777 10 : release_print_db(pdb);
1778 10 : SAFE_FREE(data.dptr);
1779 10 : return ret;
1780 : }
1781 :
1782 : /****************************************************************************
1783 : Update an entry in the print tdb that will allow us to send notify
1784 : updates only to interested smbd's.
1785 : ****************************************************************************/
1786 :
1787 12 : bool print_notify_deregister_pid(int snum)
1788 : {
1789 0 : TDB_DATA data;
1790 12 : struct tdb_print_db *pdb = NULL;
1791 12 : TDB_CONTEXT *tdb = NULL;
1792 0 : const char *printername;
1793 12 : uint32_t mypid = (uint32_t)getpid();
1794 0 : size_t i;
1795 12 : bool ret = False;
1796 :
1797 : /* if ( snum == -1 ), we are deregister a print server handle
1798 : which means to deregister on all print queues */
1799 :
1800 12 : if (snum == -1)
1801 : {
1802 2 : int num_services = lp_numservices();
1803 0 : int idx;
1804 :
1805 246 : for ( idx=0; idx<num_services; idx++ ) {
1806 244 : if ( lp_snum_ok(idx) && lp_printable(idx) )
1807 10 : print_notify_deregister_pid(idx);
1808 : }
1809 :
1810 2 : return True;
1811 : }
1812 : else /* deregister a specific printer */
1813 : {
1814 10 : printername = lp_const_servicename(snum);
1815 10 : pdb = get_print_db_byname(printername);
1816 10 : if (!pdb)
1817 0 : return False;
1818 10 : tdb = pdb->tdb;
1819 : }
1820 :
1821 10 : if (tdb_lock_bystring_with_timeout(tdb, NOTIFY_PID_LIST_KEY, 10) != 0) {
1822 0 : DEBUG(0,("print_notify_register_pid: Failed to lock \
1823 : printer %s database\n", printername));
1824 0 : if (pdb)
1825 0 : release_print_db(pdb);
1826 0 : return False;
1827 : }
1828 :
1829 10 : data = get_printer_notify_pid_list( tdb, printername, True );
1830 :
1831 : /* Reduce refcount. Remove ourselves if zero. */
1832 :
1833 20 : for (i = 0; i < data.dsize; ) {
1834 10 : if (IVAL(data.dptr,i) == mypid) {
1835 10 : uint32_t refcount = IVAL(data.dptr, i+4);
1836 :
1837 10 : refcount--;
1838 :
1839 10 : if (refcount == 0) {
1840 10 : if (data.dsize - i > 8)
1841 0 : memmove( &data.dptr[i], &data.dptr[i+8], data.dsize - i - 8);
1842 10 : data.dsize -= 8;
1843 10 : continue;
1844 : }
1845 0 : SIVAL(data.dptr, i+4, refcount);
1846 : }
1847 :
1848 0 : i += 8;
1849 : }
1850 :
1851 10 : if (data.dsize == 0)
1852 10 : SAFE_FREE(data.dptr);
1853 :
1854 : /* Store back the record. */
1855 10 : if (tdb_store_bystring(tdb, NOTIFY_PID_LIST_KEY, data, TDB_REPLACE) != 0) {
1856 0 : DEBUG(0,("print_notify_register_pid: Failed to update pid \
1857 : list for printer %s\n", printername));
1858 0 : goto done;
1859 : }
1860 :
1861 10 : ret = True;
1862 :
1863 10 : done:
1864 :
1865 10 : tdb_unlock_bystring(tdb, NOTIFY_PID_LIST_KEY);
1866 10 : if (pdb)
1867 10 : release_print_db(pdb);
1868 10 : SAFE_FREE(data.dptr);
1869 10 : return ret;
1870 : }
1871 :
1872 : /****************************************************************************
1873 : Check if a jobid is valid. It is valid if it exists in the database.
1874 : ****************************************************************************/
1875 :
1876 1308 : bool print_job_exists(const char* sharename, uint32_t jobid)
1877 : {
1878 1308 : struct tdb_print_db *pdb = get_print_db_byname(sharename);
1879 0 : bool ret;
1880 0 : uint32_t tmp;
1881 :
1882 1308 : if (!pdb)
1883 0 : return False;
1884 1308 : ret = tdb_exists(pdb->tdb, print_key(jobid, &tmp));
1885 1308 : release_print_db(pdb);
1886 1308 : return ret;
1887 : }
1888 :
1889 : /****************************************************************************
1890 : Return the device mode assigned to a specific print job.
1891 : Only valid for the process doing the spooling and when the job
1892 : has not been spooled.
1893 : ****************************************************************************/
1894 :
1895 0 : struct spoolss_DeviceMode *print_job_devmode(TALLOC_CTX *mem_ctx,
1896 : const char *sharename,
1897 : uint32_t jobid)
1898 : {
1899 0 : struct printjob *pjob = print_job_find(mem_ctx, sharename, jobid);
1900 0 : if (pjob == NULL) {
1901 0 : return NULL;
1902 : }
1903 :
1904 0 : return pjob->devmode;
1905 : }
1906 :
1907 : /****************************************************************************
1908 : Set the name of a job. Only possible for owner.
1909 : ****************************************************************************/
1910 :
1911 32 : bool print_job_set_name(struct tevent_context *ev,
1912 : struct messaging_context *msg_ctx,
1913 : const char *sharename, uint32_t jobid, const char *name)
1914 : {
1915 0 : struct printjob *pjob;
1916 0 : bool ret;
1917 32 : TALLOC_CTX *tmp_ctx = talloc_new(ev);
1918 32 : if (tmp_ctx == NULL) {
1919 0 : return false;
1920 : }
1921 :
1922 32 : pjob = print_job_find(tmp_ctx, sharename, jobid);
1923 32 : if (!pjob || pjob->pid != getpid()) {
1924 0 : ret = false;
1925 0 : goto err_out;
1926 : }
1927 :
1928 32 : fstrcpy(pjob->jobname, name);
1929 32 : ret = pjob_store(ev, msg_ctx, sharename, jobid, pjob);
1930 32 : err_out:
1931 32 : talloc_free(tmp_ctx);
1932 32 : return ret;
1933 : }
1934 :
1935 : /****************************************************************************
1936 : Get the name of a job. Only possible for owner.
1937 : ****************************************************************************/
1938 :
1939 32 : bool print_job_get_name(TALLOC_CTX *mem_ctx, const char *sharename, uint32_t jobid, char **name)
1940 : {
1941 0 : struct printjob *pjob;
1942 :
1943 32 : pjob = print_job_find(mem_ctx, sharename, jobid);
1944 32 : if (!pjob || pjob->pid != getpid()) {
1945 0 : return false;
1946 : }
1947 :
1948 32 : *name = pjob->jobname;
1949 32 : return true;
1950 : }
1951 :
1952 :
1953 : /***************************************************************************
1954 : Remove a jobid from the 'jobs added' list.
1955 : ***************************************************************************/
1956 :
1957 1352 : static bool remove_from_jobs_added(const char* sharename, uint32_t jobid)
1958 : {
1959 1352 : bool ret = remove_from_jobs_list("INFO/jobs_added", sharename, jobid);
1960 1352 : return ret;
1961 : }
1962 :
1963 : /****************************************************************************
1964 : Delete a print job - don't update queue.
1965 : ****************************************************************************/
1966 :
1967 338 : static bool print_job_delete1(struct tevent_context *ev,
1968 : struct messaging_context *msg_ctx,
1969 : int snum, uint32_t jobid)
1970 : {
1971 338 : const char* sharename = lp_const_servicename(snum);
1972 0 : const struct loadparm_substitution *lp_sub =
1973 338 : loadparm_s3_global_substitution();
1974 0 : struct printjob *pjob;
1975 338 : int result = 0;
1976 338 : struct printif *current_printif = get_printer_fns( snum );
1977 0 : bool ret;
1978 338 : TALLOC_CTX *tmp_ctx = talloc_new(ev);
1979 338 : if (tmp_ctx == NULL) {
1980 0 : return false;
1981 : }
1982 :
1983 338 : pjob = print_job_find(tmp_ctx, sharename, jobid);
1984 338 : if (!pjob) {
1985 0 : ret = false;
1986 0 : goto err_out;
1987 : }
1988 :
1989 : /*
1990 : * If already deleting just return.
1991 : */
1992 :
1993 338 : if (pjob->status == LPQ_DELETING) {
1994 0 : ret = true;
1995 0 : goto err_out;
1996 : }
1997 :
1998 : /* Hrm - we need to be able to cope with deleting a job before it
1999 : has reached the spooler. Just mark it as LPQ_DELETING and
2000 : let the print_queue_update() code remove the record */
2001 :
2002 :
2003 338 : if (pjob->sysjob == -1) {
2004 18 : DEBUG(5, ("attempt to delete job %u not seen by lpr\n", (unsigned int)jobid));
2005 : }
2006 :
2007 : /* Set the tdb entry to be deleting. */
2008 :
2009 338 : pjob->status = LPQ_DELETING;
2010 338 : pjob_store(ev, msg_ctx, sharename, jobid, pjob);
2011 :
2012 338 : if (pjob->spooled && pjob->sysjob != -1)
2013 : {
2014 320 : result = (*(current_printif->job_delete))(
2015 : lp_printername(talloc_tos(), lp_sub, snum),
2016 : lp_lprm_command(snum),
2017 : pjob);
2018 :
2019 : /* Delete the tdb entry if the delete succeeded or the job hasn't
2020 : been spooled. */
2021 :
2022 320 : if (result == 0) {
2023 320 : struct tdb_print_db *pdb = get_print_db_byname(sharename);
2024 320 : int njobs = 1;
2025 :
2026 320 : if (!pdb) {
2027 0 : ret = false;
2028 0 : goto err_out;
2029 : }
2030 320 : pjob_delete(ev, msg_ctx, sharename, jobid);
2031 : /* Ensure we keep a rough count of the number of total jobs... */
2032 320 : tdb_change_int32_atomic(pdb->tdb, "INFO/total_jobs", &njobs, -1);
2033 320 : release_print_db(pdb);
2034 : }
2035 : }
2036 :
2037 338 : remove_from_jobs_added( sharename, jobid );
2038 :
2039 338 : ret = (result == 0);
2040 338 : err_out:
2041 338 : talloc_free(tmp_ctx);
2042 338 : return ret;
2043 : }
2044 :
2045 : /****************************************************************************
2046 : Return true if the current user owns the print job.
2047 : ****************************************************************************/
2048 :
2049 402 : static bool is_owner(const struct auth_session_info *server_info,
2050 : const char *servicename,
2051 : uint32_t jobid)
2052 : {
2053 0 : struct printjob *pjob;
2054 0 : bool ret;
2055 402 : TALLOC_CTX *tmp_ctx = talloc_new(server_info);
2056 402 : if (tmp_ctx == NULL) {
2057 0 : return false;
2058 : }
2059 :
2060 402 : pjob = print_job_find(tmp_ctx, servicename, jobid);
2061 402 : if (!pjob || !server_info) {
2062 0 : ret = false;
2063 0 : goto err_out;
2064 : }
2065 :
2066 402 : ret = strequal(pjob->user, server_info->unix_info->sanitized_username);
2067 402 : err_out:
2068 402 : talloc_free(tmp_ctx);
2069 402 : return ret;
2070 : }
2071 :
2072 : /****************************************************************************
2073 : Delete a print job.
2074 : ****************************************************************************/
2075 :
2076 306 : WERROR print_job_delete(const struct auth_session_info *server_info,
2077 : struct messaging_context *msg_ctx,
2078 : int snum, uint32_t jobid)
2079 : {
2080 306 : const char* sharename = lp_const_servicename(snum);
2081 0 : const struct loadparm_substitution *lp_sub =
2082 306 : loadparm_s3_global_substitution();
2083 0 : struct printjob *pjob;
2084 0 : bool owner;
2085 0 : WERROR werr;
2086 306 : TALLOC_CTX *tmp_ctx = talloc_new(msg_ctx);
2087 306 : if (tmp_ctx == NULL) {
2088 0 : return WERR_NOT_ENOUGH_MEMORY;
2089 : }
2090 :
2091 306 : owner = is_owner(server_info, lp_const_servicename(snum), jobid);
2092 :
2093 : /* Check access against security descriptor or whether the user
2094 : owns their job. */
2095 :
2096 306 : if (!owner &&
2097 0 : !W_ERROR_IS_OK(print_access_check(server_info, msg_ctx, snum,
2098 : JOB_ACCESS_ADMINISTER))) {
2099 0 : DEBUG(0, ("print job delete denied. "
2100 : "User name: %s, Printer name: %s.\n",
2101 : uidtoname(server_info->unix_token->uid),
2102 : lp_printername(tmp_ctx, lp_sub, snum)));
2103 :
2104 0 : werr = WERR_ACCESS_DENIED;
2105 0 : goto err_out;
2106 : }
2107 :
2108 : /*
2109 : * get the spooled filename of the print job
2110 : * if this works, then the file has not been spooled
2111 : * to the underlying print system. Just delete the
2112 : * spool file & return.
2113 : */
2114 :
2115 306 : pjob = print_job_find(tmp_ctx, sharename, jobid);
2116 306 : if (!pjob || pjob->spooled || pjob->pid != getpid()) {
2117 306 : DEBUG(10, ("Skipping spool file removal for job %u\n", jobid));
2118 : } else {
2119 0 : DEBUG(10, ("Removing spool file [%s]\n", pjob->filename));
2120 0 : if (unlink(pjob->filename) == -1) {
2121 0 : werr = map_werror_from_unix(errno);
2122 0 : goto err_out;
2123 : }
2124 : }
2125 :
2126 306 : if (!print_job_delete1(global_event_context(), msg_ctx, snum, jobid)) {
2127 0 : werr = WERR_ACCESS_DENIED;
2128 0 : goto err_out;
2129 : }
2130 :
2131 : /* force update the database and say the delete failed if the
2132 : job still exists */
2133 :
2134 306 : print_queue_update(msg_ctx, snum, True);
2135 :
2136 306 : pjob = print_job_find(tmp_ctx, sharename, jobid);
2137 306 : if (pjob && (pjob->status != LPQ_DELETING)) {
2138 0 : werr = WERR_ACCESS_DENIED;
2139 0 : goto err_out;
2140 : }
2141 306 : werr = WERR_PRINTER_HAS_JOBS_QUEUED;
2142 :
2143 306 : err_out:
2144 306 : talloc_free(tmp_ctx);
2145 306 : return werr;
2146 : }
2147 :
2148 : /****************************************************************************
2149 : Pause a job.
2150 : ****************************************************************************/
2151 :
2152 32 : WERROR print_job_pause(const struct auth_session_info *server_info,
2153 : struct messaging_context *msg_ctx,
2154 : int snum, uint32_t jobid)
2155 : {
2156 32 : const char* sharename = lp_const_servicename(snum);
2157 0 : const struct loadparm_substitution *lp_sub =
2158 32 : loadparm_s3_global_substitution();
2159 0 : struct printjob *pjob;
2160 32 : int ret = -1;
2161 32 : struct printif *current_printif = get_printer_fns( snum );
2162 0 : WERROR werr;
2163 32 : TALLOC_CTX *tmp_ctx = talloc_new(msg_ctx);
2164 32 : if (tmp_ctx == NULL) {
2165 0 : return WERR_NOT_ENOUGH_MEMORY;
2166 : }
2167 :
2168 32 : pjob = print_job_find(tmp_ctx, sharename, jobid);
2169 32 : if (!pjob || !server_info) {
2170 0 : DEBUG(10, ("print_job_pause: no pjob or user for jobid %u\n",
2171 : (unsigned int)jobid ));
2172 0 : werr = WERR_INVALID_PARAMETER;
2173 0 : goto err_out;
2174 : }
2175 :
2176 32 : if (!pjob->spooled || pjob->sysjob == -1) {
2177 0 : DEBUG(10, ("print_job_pause: not spooled or bad sysjob = %d for jobid %u\n",
2178 : (int)pjob->sysjob, (unsigned int)jobid ));
2179 0 : werr = WERR_INVALID_PARAMETER;
2180 0 : goto err_out;
2181 : }
2182 :
2183 32 : if (!is_owner(server_info, lp_const_servicename(snum), jobid) &&
2184 0 : !W_ERROR_IS_OK(print_access_check(server_info, msg_ctx, snum,
2185 : JOB_ACCESS_ADMINISTER))) {
2186 0 : DEBUG(0, ("print job pause denied. "
2187 : "User name: %s, Printer name: %s.\n",
2188 : uidtoname(server_info->unix_token->uid),
2189 : lp_printername(tmp_ctx, lp_sub, snum)));
2190 :
2191 0 : werr = WERR_ACCESS_DENIED;
2192 0 : goto err_out;
2193 : }
2194 :
2195 : /* need to pause the spooled entry */
2196 32 : ret = (*(current_printif->job_pause))(snum, pjob);
2197 :
2198 32 : if (ret != 0) {
2199 0 : werr = WERR_INVALID_PARAMETER;
2200 0 : goto err_out;
2201 : }
2202 :
2203 : /* force update the database */
2204 32 : print_cache_flush(lp_const_servicename(snum));
2205 :
2206 : /* Send a printer notify message */
2207 :
2208 32 : notify_job_status(global_event_context(), msg_ctx, sharename, jobid,
2209 : JOB_STATUS_PAUSED);
2210 :
2211 : /* how do we tell if this succeeded? */
2212 32 : werr = WERR_OK;
2213 32 : err_out:
2214 32 : talloc_free(tmp_ctx);
2215 32 : return werr;
2216 : }
2217 :
2218 : /****************************************************************************
2219 : Resume a job.
2220 : ****************************************************************************/
2221 :
2222 32 : WERROR print_job_resume(const struct auth_session_info *server_info,
2223 : struct messaging_context *msg_ctx,
2224 : int snum, uint32_t jobid)
2225 : {
2226 32 : const char *sharename = lp_const_servicename(snum);
2227 0 : const struct loadparm_substitution *lp_sub =
2228 32 : loadparm_s3_global_substitution();
2229 0 : struct printjob *pjob;
2230 0 : int ret;
2231 32 : struct printif *current_printif = get_printer_fns( snum );
2232 0 : WERROR werr;
2233 32 : TALLOC_CTX *tmp_ctx = talloc_new(msg_ctx);
2234 32 : if (tmp_ctx == NULL)
2235 0 : return WERR_NOT_ENOUGH_MEMORY;
2236 :
2237 32 : pjob = print_job_find(tmp_ctx, sharename, jobid);
2238 32 : if (!pjob || !server_info) {
2239 0 : DEBUG(10, ("print_job_resume: no pjob or user for jobid %u\n",
2240 : (unsigned int)jobid ));
2241 0 : werr = WERR_INVALID_PARAMETER;
2242 0 : goto err_out;
2243 : }
2244 :
2245 32 : if (!pjob->spooled || pjob->sysjob == -1) {
2246 0 : DEBUG(10, ("print_job_resume: not spooled or bad sysjob = %d for jobid %u\n",
2247 : (int)pjob->sysjob, (unsigned int)jobid ));
2248 0 : werr = WERR_INVALID_PARAMETER;
2249 0 : goto err_out;
2250 : }
2251 :
2252 32 : if (!is_owner(server_info, lp_const_servicename(snum), jobid) &&
2253 0 : !W_ERROR_IS_OK(print_access_check(server_info, msg_ctx, snum,
2254 : JOB_ACCESS_ADMINISTER))) {
2255 0 : DEBUG(0, ("print job resume denied. "
2256 : "User name: %s, Printer name: %s.\n",
2257 : uidtoname(server_info->unix_token->uid),
2258 : lp_printername(tmp_ctx, lp_sub, snum)));
2259 :
2260 0 : werr = WERR_ACCESS_DENIED;
2261 0 : goto err_out;
2262 : }
2263 :
2264 32 : ret = (*(current_printif->job_resume))(snum, pjob);
2265 :
2266 32 : if (ret != 0) {
2267 0 : werr = WERR_INVALID_PARAMETER;
2268 0 : goto err_out;
2269 : }
2270 :
2271 : /* force update the database */
2272 32 : print_cache_flush(lp_const_servicename(snum));
2273 :
2274 : /* Send a printer notify message */
2275 :
2276 32 : notify_job_status(global_event_context(), msg_ctx, sharename, jobid,
2277 : JOB_STATUS_QUEUED);
2278 :
2279 32 : werr = WERR_OK;
2280 32 : err_out:
2281 32 : talloc_free(tmp_ctx);
2282 32 : return werr;
2283 : }
2284 :
2285 : /****************************************************************************
2286 : Write to a print file.
2287 : ****************************************************************************/
2288 :
2289 1920 : ssize_t print_job_write(struct tevent_context *ev,
2290 : struct messaging_context *msg_ctx,
2291 : int snum, uint32_t jobid, const char *buf, size_t size)
2292 : {
2293 1920 : const char* sharename = lp_const_servicename(snum);
2294 0 : ssize_t return_code;
2295 0 : struct printjob *pjob;
2296 1920 : TALLOC_CTX *tmp_ctx = talloc_new(ev);
2297 1920 : if (tmp_ctx == NULL) {
2298 0 : return -1;
2299 : }
2300 :
2301 1920 : pjob = print_job_find(tmp_ctx, sharename, jobid);
2302 1920 : if (!pjob) {
2303 0 : return_code = -1;
2304 0 : goto err_out;
2305 : }
2306 :
2307 : /* don't allow another process to get this info - it is meaningless */
2308 1920 : if (pjob->pid != getpid()) {
2309 0 : return_code = -1;
2310 0 : goto err_out;
2311 : }
2312 :
2313 : /* if SMBD is spooling this can't be allowed */
2314 1920 : if (pjob->status == PJOB_SMBD_SPOOLING) {
2315 0 : return_code = -1;
2316 0 : goto err_out;
2317 : }
2318 :
2319 1920 : return_code = write_data(pjob->fd, buf, size);
2320 1920 : if (return_code > 0) {
2321 1920 : pjob->size += size;
2322 1920 : pjob_store(ev, msg_ctx, sharename, jobid, pjob);
2323 : }
2324 0 : err_out:
2325 1920 : talloc_free(tmp_ctx);
2326 1920 : return return_code;
2327 : }
2328 :
2329 : /****************************************************************************
2330 : Get the queue status - do not update if db is out of date.
2331 : ****************************************************************************/
2332 :
2333 3934 : static int get_queue_status(const char* sharename, print_status_struct *status)
2334 : {
2335 0 : fstring keystr;
2336 0 : TDB_DATA data;
2337 3934 : struct tdb_print_db *pdb = get_print_db_byname(sharename);
2338 0 : int len;
2339 :
2340 3934 : if (status) {
2341 3934 : ZERO_STRUCTP(status);
2342 : }
2343 :
2344 3934 : if (!pdb)
2345 0 : return 0;
2346 :
2347 3934 : if (status) {
2348 3934 : fstr_sprintf(keystr, "STATUS/%s", sharename);
2349 3934 : data = tdb_fetch(pdb->tdb, string_tdb_data(keystr));
2350 3934 : if (data.dptr) {
2351 3763 : if (data.dsize == sizeof(print_status_struct))
2352 : /* this memcpy is ok since the status struct was
2353 : not packed before storing it in the tdb */
2354 3763 : memcpy(status, data.dptr, sizeof(print_status_struct));
2355 3763 : SAFE_FREE(data.dptr);
2356 : }
2357 : }
2358 3934 : len = tdb_fetch_int32(pdb->tdb, "INFO/total_jobs");
2359 3934 : release_print_db(pdb);
2360 3934 : return (len == -1 ? 0 : len);
2361 : }
2362 :
2363 : /****************************************************************************
2364 : Determine the number of jobs in a queue.
2365 : ****************************************************************************/
2366 :
2367 2304 : int print_queue_length(struct messaging_context *msg_ctx, int snum,
2368 : print_status_struct *pstatus)
2369 : {
2370 2304 : const char* sharename = lp_const_servicename( snum );
2371 0 : print_status_struct status;
2372 0 : int len;
2373 :
2374 2304 : ZERO_STRUCT( status );
2375 :
2376 : /* make sure the database is up to date */
2377 2304 : if (print_cache_expired(lp_const_servicename(snum), True))
2378 896 : print_queue_update(msg_ctx, snum, False);
2379 :
2380 : /* also fetch the queue status */
2381 2304 : memset(&status, 0, sizeof(status));
2382 2304 : len = get_queue_status(sharename, &status);
2383 :
2384 2304 : if (pstatus)
2385 1636 : *pstatus = status;
2386 :
2387 2304 : return len;
2388 : }
2389 :
2390 : /***************************************************************************
2391 : Allocate a jobid. Hold the lock for as short a time as possible.
2392 : ***************************************************************************/
2393 :
2394 668 : static WERROR allocate_print_jobid(struct tdb_print_db *pdb, int snum,
2395 : const char *sharename, uint32_t *pjobid)
2396 : {
2397 0 : int i;
2398 0 : uint32_t jobid;
2399 0 : enum TDB_ERROR terr;
2400 0 : int ret;
2401 :
2402 668 : *pjobid = (uint32_t)-1;
2403 :
2404 668 : for (i = 0; i < 3; i++) {
2405 : /* Lock the database - only wait 20 seconds. */
2406 668 : ret = tdb_lock_bystring_with_timeout(pdb->tdb,
2407 : "INFO/nextjob", 20);
2408 668 : if (ret != 0) {
2409 0 : DEBUG(0, ("allocate_print_jobid: "
2410 : "Failed to lock printing database %s\n",
2411 : sharename));
2412 0 : terr = tdb_error(pdb->tdb);
2413 0 : return ntstatus_to_werror(map_nt_error_from_tdb(terr));
2414 : }
2415 :
2416 668 : if (!tdb_fetch_uint32(pdb->tdb, "INFO/nextjob", &jobid)) {
2417 32 : terr = tdb_error(pdb->tdb);
2418 32 : if (terr != TDB_ERR_NOEXIST) {
2419 0 : DEBUG(0, ("allocate_print_jobid: "
2420 : "Failed to fetch INFO/nextjob "
2421 : "for print queue %s\n", sharename));
2422 0 : tdb_unlock_bystring(pdb->tdb, "INFO/nextjob");
2423 0 : return ntstatus_to_werror(map_nt_error_from_tdb(terr));
2424 : }
2425 32 : DEBUG(10, ("allocate_print_jobid: "
2426 : "No existing jobid in %s\n", sharename));
2427 32 : jobid = 0;
2428 : }
2429 :
2430 668 : DEBUG(10, ("allocate_print_jobid: "
2431 : "Read jobid %u from %s\n", jobid, sharename));
2432 :
2433 668 : jobid = NEXT_JOBID(jobid);
2434 :
2435 668 : ret = tdb_store_int32(pdb->tdb, "INFO/nextjob", jobid);
2436 668 : if (ret != 0) {
2437 0 : terr = tdb_error(pdb->tdb);
2438 0 : DEBUG(3, ("allocate_print_jobid: "
2439 : "Failed to store INFO/nextjob.\n"));
2440 0 : tdb_unlock_bystring(pdb->tdb, "INFO/nextjob");
2441 0 : return ntstatus_to_werror(map_nt_error_from_tdb(terr));
2442 : }
2443 :
2444 : /* We've finished with the INFO/nextjob lock. */
2445 668 : tdb_unlock_bystring(pdb->tdb, "INFO/nextjob");
2446 :
2447 668 : if (!print_job_exists(sharename, jobid)) {
2448 668 : break;
2449 : }
2450 0 : DEBUG(10, ("allocate_print_jobid: "
2451 : "Found jobid %u in %s\n", jobid, sharename));
2452 : }
2453 :
2454 668 : if (i > 2) {
2455 0 : DEBUG(0, ("allocate_print_jobid: "
2456 : "Failed to allocate a print job for queue %s\n",
2457 : sharename));
2458 : /* Probably full... */
2459 0 : return WERR_NO_SPOOL_SPACE;
2460 : }
2461 :
2462 : /* Store a dummy placeholder. */
2463 : {
2464 0 : uint32_t tmp;
2465 668 : TDB_DATA dummy = {
2466 : .dsize = 0,
2467 : };
2468 668 : if (tdb_store(pdb->tdb, print_key(jobid, &tmp), dummy,
2469 : TDB_INSERT) != 0) {
2470 0 : DEBUG(3, ("allocate_print_jobid: "
2471 : "jobid (%d) failed to store placeholder.\n",
2472 : jobid ));
2473 0 : terr = tdb_error(pdb->tdb);
2474 0 : return ntstatus_to_werror(map_nt_error_from_tdb(terr));
2475 : }
2476 : }
2477 :
2478 668 : *pjobid = jobid;
2479 668 : return WERR_OK;
2480 : }
2481 :
2482 : /***************************************************************************
2483 : Do all checks needed to determine if we can start a job.
2484 : ***************************************************************************/
2485 :
2486 668 : static WERROR print_job_checks(const struct auth_session_info *server_info,
2487 : struct messaging_context *msg_ctx,
2488 : int snum, int *njobs)
2489 : {
2490 668 : const char *sharename = lp_const_servicename(snum);
2491 0 : const struct loadparm_substitution *lp_sub =
2492 668 : loadparm_s3_global_substitution();
2493 0 : uint64_t dspace, dsize;
2494 0 : uint64_t minspace;
2495 0 : int ret;
2496 :
2497 668 : if (!W_ERROR_IS_OK(print_access_check(server_info, msg_ctx, snum,
2498 : PRINTER_ACCESS_USE))) {
2499 0 : DEBUG(3, ("print_job_checks: "
2500 : "job start denied by security descriptor\n"));
2501 0 : return WERR_ACCESS_DENIED;
2502 : }
2503 :
2504 668 : if (!print_time_access_check(server_info, msg_ctx, sharename)) {
2505 0 : DEBUG(3, ("print_job_checks: "
2506 : "job start denied by time check\n"));
2507 0 : return WERR_ACCESS_DENIED;
2508 : }
2509 :
2510 : /* see if we have sufficient disk space */
2511 668 : if (lp_min_print_space(snum)) {
2512 0 : minspace = lp_min_print_space(snum);
2513 0 : ret = sys_fsusage(lp_path(talloc_tos(), lp_sub, snum), &dspace, &dsize);
2514 0 : if (ret == 0 && dspace < 2*minspace) {
2515 0 : DEBUG(3, ("print_job_checks: "
2516 : "disk space check failed.\n"));
2517 0 : return WERR_NO_SPOOL_SPACE;
2518 : }
2519 : }
2520 :
2521 : /* for autoloaded printers, check that the printcap entry still exists */
2522 668 : if (lp_autoloaded(snum) &&
2523 0 : !printer_list_printername_exists(sharename)) {
2524 0 : DEBUG(3, ("print_job_checks: printer name %s check failed.\n",
2525 : sharename));
2526 0 : return WERR_ACCESS_DENIED;
2527 : }
2528 :
2529 : /* Insure the maximum queue size is not violated */
2530 668 : *njobs = print_queue_length(msg_ctx, snum, NULL);
2531 668 : if (*njobs > lp_maxprintjobs(snum)) {
2532 0 : DEBUG(3, ("print_job_checks: Queue %s number of jobs (%d) "
2533 : "larger than max printjobs per queue (%d).\n",
2534 : sharename, *njobs, lp_maxprintjobs(snum)));
2535 0 : return WERR_NO_SPOOL_SPACE;
2536 : }
2537 :
2538 668 : return WERR_OK;
2539 : }
2540 :
2541 : /***************************************************************************
2542 : Create a job file.
2543 : ***************************************************************************/
2544 :
2545 668 : static WERROR print_job_spool_file(int snum, uint32_t jobid,
2546 : const char *output_file,
2547 : struct printjob *pjob)
2548 : {
2549 0 : const struct loadparm_substitution *lp_sub =
2550 668 : loadparm_s3_global_substitution();
2551 0 : WERROR werr;
2552 0 : SMB_STRUCT_STAT st;
2553 0 : const char *path;
2554 0 : int len;
2555 0 : mode_t mask;
2556 :
2557 : /* if this file is within the printer path, it means that smbd
2558 : * is spooling it and will pass us control when it is finished.
2559 : * Verify that the file name is ok, within path, and it is
2560 : * already already there */
2561 668 : if (output_file) {
2562 28 : path = lp_path(talloc_tos(), lp_sub, snum);
2563 28 : len = strlen(path);
2564 28 : if (strncmp(output_file, path, len) == 0 &&
2565 28 : (output_file[len - 1] == '/' || output_file[len] == '/')) {
2566 :
2567 : /* verify path is not too long */
2568 28 : if (strlen(output_file) >= sizeof(pjob->filename)) {
2569 0 : return WERR_INVALID_NAME;
2570 : }
2571 :
2572 : /* verify that the file exists */
2573 28 : if (sys_stat(output_file, &st, false) != 0) {
2574 0 : return WERR_INVALID_NAME;
2575 : }
2576 :
2577 28 : fstrcpy(pjob->filename, output_file);
2578 :
2579 28 : DEBUG(3, ("print_job_spool_file:"
2580 : "External spooling activated\n"));
2581 :
2582 : /* we do not open the file until spooling is done */
2583 28 : pjob->fd = -1;
2584 28 : pjob->status = PJOB_SMBD_SPOOLING;
2585 :
2586 28 : return WERR_OK;
2587 : }
2588 : }
2589 :
2590 640 : slprintf(pjob->filename, sizeof(pjob->filename)-1,
2591 : "%s/%sXXXXXX", lp_path(talloc_tos(), lp_sub, snum),
2592 : PRINT_SPOOL_PREFIX);
2593 640 : mask = umask(S_IRWXO | S_IRWXG);
2594 640 : pjob->fd = mkstemp(pjob->filename);
2595 640 : umask(mask);
2596 :
2597 640 : if (pjob->fd == -1) {
2598 0 : werr = map_werror_from_unix(errno);
2599 0 : if (W_ERROR_EQUAL(werr, WERR_ACCESS_DENIED)) {
2600 : /* Common setup error, force a report. */
2601 0 : DEBUG(0, ("print_job_spool_file: "
2602 : "insufficient permissions to open spool "
2603 : "file %s.\n", pjob->filename));
2604 : } else {
2605 : /* Normal case, report at level 3 and above. */
2606 0 : DEBUG(3, ("print_job_spool_file: "
2607 : "can't open spool file %s\n",
2608 : pjob->filename));
2609 : }
2610 0 : return werr;
2611 : }
2612 :
2613 640 : return WERR_OK;
2614 : }
2615 :
2616 : /***************************************************************************
2617 : Start spooling a job - return the jobid.
2618 : ***************************************************************************/
2619 :
2620 668 : WERROR print_job_start(const struct auth_session_info *server_info,
2621 : struct messaging_context *msg_ctx,
2622 : const char *clientmachine,
2623 : int snum, const char *docname, const char *filename,
2624 : struct spoolss_DeviceMode *devmode, uint32_t *_jobid)
2625 : {
2626 0 : uint32_t jobid;
2627 668 : char *path = NULL, *userstr = NULL;
2628 0 : struct printjob pjob;
2629 668 : const char *sharename = lp_const_servicename(snum);
2630 668 : struct tdb_print_db *pdb = get_print_db_byname(sharename);
2631 0 : const struct loadparm_substitution *lp_sub =
2632 668 : loadparm_s3_global_substitution();
2633 0 : int njobs;
2634 0 : WERROR werr;
2635 :
2636 668 : if (!pdb) {
2637 0 : return WERR_INTERNAL_DB_CORRUPTION;
2638 : }
2639 :
2640 668 : path = lp_path(talloc_tos(), lp_sub, snum);
2641 :
2642 668 : werr = print_job_checks(server_info, msg_ctx, snum, &njobs);
2643 668 : if (!W_ERROR_IS_OK(werr)) {
2644 0 : release_print_db(pdb);
2645 0 : return werr;
2646 : }
2647 :
2648 668 : DEBUG(10, ("print_job_start: "
2649 : "Queue %s number of jobs (%d), max printjobs = %d\n",
2650 : sharename, njobs, lp_maxprintjobs(snum)));
2651 :
2652 668 : werr = allocate_print_jobid(pdb, snum, sharename, &jobid);
2653 668 : if (!W_ERROR_IS_OK(werr)) {
2654 0 : goto fail;
2655 : }
2656 :
2657 : /* create the database entry */
2658 :
2659 668 : ZERO_STRUCT(pjob);
2660 :
2661 668 : pjob.pid = getpid();
2662 668 : pjob.jobid = jobid;
2663 668 : pjob.sysjob = -1;
2664 668 : pjob.fd = -1;
2665 668 : pjob.starttime = time(NULL);
2666 668 : pjob.status = LPQ_SPOOLING;
2667 668 : pjob.size = 0;
2668 668 : pjob.spooled = False;
2669 668 : pjob.smbjob = True;
2670 668 : pjob.devmode = devmode;
2671 :
2672 668 : fstrcpy(pjob.jobname, docname);
2673 :
2674 668 : fstrcpy(pjob.clientmachine, clientmachine);
2675 :
2676 1336 : userstr = talloc_sub_full(talloc_tos(),
2677 : sharename,
2678 668 : server_info->unix_info->sanitized_username,
2679 668 : path, server_info->unix_token->gid,
2680 668 : server_info->unix_info->sanitized_username,
2681 668 : server_info->info->domain_name,
2682 : lp_printjob_username(snum));
2683 668 : if (userstr == NULL) {
2684 0 : werr = WERR_NOT_ENOUGH_MEMORY;
2685 0 : goto fail;
2686 : }
2687 668 : strlcpy(pjob.user, userstr, sizeof(pjob.user));
2688 668 : TALLOC_FREE(userstr);
2689 :
2690 668 : fstrcpy(pjob.queuename, lp_const_servicename(snum));
2691 :
2692 : /* we have a job entry - now create the spool file */
2693 668 : werr = print_job_spool_file(snum, jobid, filename, &pjob);
2694 668 : if (!W_ERROR_IS_OK(werr)) {
2695 0 : goto fail;
2696 : }
2697 :
2698 668 : pjob_store(global_event_context(), msg_ctx, sharename, jobid, &pjob);
2699 :
2700 : /* Update the 'jobs added' entry used by print_queue_status. */
2701 668 : add_to_jobs_list(pdb, jobid, "INFO/jobs_added");
2702 :
2703 : /* Ensure we keep a rough count of the number of total jobs... */
2704 668 : tdb_change_int32_atomic(pdb->tdb, "INFO/total_jobs", &njobs, 1);
2705 :
2706 668 : release_print_db(pdb);
2707 :
2708 668 : *_jobid = jobid;
2709 668 : return WERR_OK;
2710 :
2711 0 : fail:
2712 0 : if (jobid != -1) {
2713 0 : pjob_delete(global_event_context(), msg_ctx, sharename, jobid);
2714 : }
2715 :
2716 0 : release_print_db(pdb);
2717 :
2718 0 : DEBUG(3, ("print_job_start: returning fail. "
2719 : "Error = %s\n", win_errstr(werr)));
2720 0 : return werr;
2721 : }
2722 :
2723 : /****************************************************************************
2724 : Update the number of pages spooled to jobid
2725 : ****************************************************************************/
2726 :
2727 1920 : void print_job_endpage(struct messaging_context *msg_ctx,
2728 : int snum, uint32_t jobid)
2729 : {
2730 1920 : const char* sharename = lp_const_servicename(snum);
2731 0 : struct printjob *pjob;
2732 1920 : TALLOC_CTX *tmp_ctx = talloc_new(msg_ctx);
2733 1920 : if (tmp_ctx == NULL) {
2734 0 : return;
2735 : }
2736 :
2737 1920 : pjob = print_job_find(tmp_ctx, sharename, jobid);
2738 1920 : if (!pjob) {
2739 0 : goto err_out;
2740 : }
2741 : /* don't allow another process to get this info - it is meaningless */
2742 1920 : if (pjob->pid != getpid()) {
2743 0 : goto err_out;
2744 : }
2745 :
2746 1920 : pjob->page_count++;
2747 1920 : pjob_store(global_event_context(), msg_ctx, sharename, jobid, pjob);
2748 1920 : err_out:
2749 1920 : talloc_free(tmp_ctx);
2750 : }
2751 :
2752 : /****************************************************************************
2753 : Print a file - called on closing the file. This spools the job.
2754 : If normal close is false then we're tearing down the jobs - treat as an
2755 : error.
2756 : ****************************************************************************/
2757 :
2758 668 : NTSTATUS print_job_end(struct messaging_context *msg_ctx, int snum,
2759 : uint32_t jobid, enum file_close_type close_type)
2760 : {
2761 668 : const char* sharename = lp_const_servicename(snum);
2762 0 : const struct loadparm_substitution *lp_sub =
2763 668 : loadparm_s3_global_substitution();
2764 0 : struct printjob *pjob;
2765 0 : int ret;
2766 0 : SMB_STRUCT_STAT sbuf;
2767 668 : struct printif *current_printif = get_printer_fns(snum);
2768 668 : NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
2769 0 : char *lpq_cmd;
2770 668 : TALLOC_CTX *tmp_ctx = talloc_new(msg_ctx);
2771 668 : if (tmp_ctx == NULL) {
2772 0 : return NT_STATUS_NO_MEMORY;
2773 : }
2774 :
2775 668 : pjob = print_job_find(tmp_ctx, sharename, jobid);
2776 668 : if (!pjob) {
2777 0 : status = NT_STATUS_PRINT_CANCELLED;
2778 0 : goto err_out;
2779 : }
2780 :
2781 668 : if (pjob->spooled || pjob->pid != getpid()) {
2782 0 : status = NT_STATUS_ACCESS_DENIED;
2783 0 : goto err_out;
2784 : }
2785 :
2786 668 : if (close_type == NORMAL_CLOSE || close_type == SHUTDOWN_CLOSE) {
2787 668 : if (pjob->status == PJOB_SMBD_SPOOLING) {
2788 : /* take over the file now, smbd is done */
2789 28 : if (sys_stat(pjob->filename, &sbuf, false) != 0) {
2790 0 : status = map_nt_error_from_unix(errno);
2791 0 : DEBUG(3, ("print_job_end: "
2792 : "stat file failed for jobid %d\n",
2793 : jobid));
2794 0 : goto fail;
2795 : }
2796 :
2797 28 : pjob->status = LPQ_SPOOLING;
2798 :
2799 : } else {
2800 :
2801 640 : if ((sys_fstat(pjob->fd, &sbuf, false) != 0)) {
2802 0 : status = map_nt_error_from_unix(errno);
2803 0 : close(pjob->fd);
2804 0 : DEBUG(3, ("print_job_end: "
2805 : "stat file failed for jobid %d\n",
2806 : jobid));
2807 0 : goto fail;
2808 : }
2809 :
2810 640 : close(pjob->fd);
2811 : }
2812 :
2813 668 : pjob->size = sbuf.st_ex_size;
2814 : } else {
2815 :
2816 : /*
2817 : * Not a normal close, something has gone wrong. Cleanup.
2818 : */
2819 0 : if (pjob->fd != -1) {
2820 0 : close(pjob->fd);
2821 : }
2822 0 : goto fail;
2823 : }
2824 :
2825 : /* Technically, this is not quite right. If the printer has a separator
2826 : * page turned on, the NT spooler prints the separator page even if the
2827 : * print job is 0 bytes. 010215 JRR */
2828 668 : if (pjob->size == 0 || pjob->status == LPQ_DELETING) {
2829 : /* don't bother spooling empty files or something being deleted. */
2830 2 : DEBUG(5,("print_job_end: canceling spool of %s (%s)\n",
2831 : pjob->filename, pjob->size ? "deleted" : "zero length" ));
2832 2 : unlink(pjob->filename);
2833 2 : pjob_delete(global_event_context(), msg_ctx, sharename, jobid);
2834 2 : return NT_STATUS_OK;
2835 : }
2836 :
2837 : /* don't strip out characters like '$' from the printername */
2838 666 : lpq_cmd = talloc_string_sub2(tmp_ctx,
2839 : lp_lpq_command(snum),
2840 : "%p",
2841 : lp_printername(talloc_tos(), lp_sub, snum),
2842 : false, false, false);
2843 666 : if (lpq_cmd == NULL) {
2844 0 : status = NT_STATUS_PRINT_CANCELLED;
2845 0 : goto fail;
2846 : }
2847 1332 : lpq_cmd = talloc_sub_full(tmp_ctx,
2848 666 : lp_servicename(talloc_tos(), lp_sub, snum),
2849 : current_user_info.unix_name,
2850 : "",
2851 : get_current_gid(NULL),
2852 : get_current_username(),
2853 : get_current_user_info_domain(),
2854 : lpq_cmd);
2855 666 : if (lpq_cmd == NULL) {
2856 0 : status = NT_STATUS_PRINT_CANCELLED;
2857 0 : goto fail;
2858 : }
2859 :
2860 666 : ret = (*(current_printif->job_submit))(snum, pjob,
2861 : current_printif->type, lpq_cmd);
2862 666 : if (ret) {
2863 292 : status = NT_STATUS_PRINT_CANCELLED;
2864 292 : goto fail;
2865 : }
2866 :
2867 : /* The print job has been successfully handed over to the back-end */
2868 :
2869 374 : pjob->spooled = True;
2870 374 : pjob->status = LPQ_QUEUED;
2871 374 : pjob_store(global_event_context(), msg_ctx, sharename, jobid, pjob);
2872 :
2873 : /* make sure the database is up to date */
2874 374 : if (print_cache_expired(lp_const_servicename(snum), True))
2875 372 : print_queue_update(msg_ctx, snum, False);
2876 :
2877 374 : return NT_STATUS_OK;
2878 :
2879 292 : fail:
2880 :
2881 : /* The print job was not successfully started. Cleanup */
2882 : /* Still need to add proper error return propagation! 010122:JRR */
2883 292 : pjob->fd = -1;
2884 292 : unlink(pjob->filename);
2885 292 : pjob_delete(global_event_context(), msg_ctx, sharename, jobid);
2886 292 : err_out:
2887 292 : talloc_free(tmp_ctx);
2888 292 : return status;
2889 : }
2890 :
2891 : /****************************************************************************
2892 : Get a snapshot of jobs in the system without traversing.
2893 : ****************************************************************************/
2894 :
2895 226 : static bool get_stored_queue_info(struct messaging_context *msg_ctx,
2896 : struct tdb_print_db *pdb, int snum,
2897 : int *pcount, print_queue_struct **ppqueue)
2898 : {
2899 0 : const struct loadparm_substitution *lp_sub =
2900 226 : loadparm_s3_global_substitution();
2901 0 : TDB_DATA data, cgdata, jcdata;
2902 226 : print_queue_struct *queue = NULL;
2903 226 : uint32_t qcount = 0;
2904 226 : uint32_t extra_count = 0;
2905 226 : uint32_t changed_count = 0;
2906 226 : int total_count = 0;
2907 226 : size_t len = 0;
2908 0 : uint32_t i;
2909 226 : int max_reported_jobs = lp_max_reported_print_jobs(snum);
2910 226 : bool ret = false;
2911 226 : const char* sharename = lp_servicename(talloc_tos(), lp_sub, snum);
2912 226 : TALLOC_CTX *tmp_ctx = talloc_new(msg_ctx);
2913 226 : if (tmp_ctx == NULL) {
2914 0 : return false;
2915 : }
2916 :
2917 : /* make sure the database is up to date */
2918 226 : if (print_cache_expired(lp_const_servicename(snum), True))
2919 0 : print_queue_update(msg_ctx, snum, False);
2920 :
2921 226 : *pcount = 0;
2922 226 : *ppqueue = NULL;
2923 :
2924 226 : ZERO_STRUCT(data);
2925 226 : ZERO_STRUCT(cgdata);
2926 :
2927 : /* Get the stored queue data. */
2928 226 : data = tdb_fetch(pdb->tdb, string_tdb_data("INFO/linear_queue_array"));
2929 :
2930 226 : if (data.dptr && data.dsize >= sizeof(qcount))
2931 226 : len += tdb_unpack(data.dptr + len, data.dsize - len, "d", &qcount);
2932 :
2933 : /* Get the added jobs list. */
2934 226 : cgdata = tdb_fetch(pdb->tdb, string_tdb_data("INFO/jobs_added"));
2935 226 : if (cgdata.dptr != NULL && (cgdata.dsize % 4 == 0))
2936 226 : extra_count = cgdata.dsize/4;
2937 :
2938 : /* Get the changed jobs list. */
2939 226 : jcdata = tdb_fetch(pdb->tdb, string_tdb_data("INFO/jobs_changed"));
2940 226 : if (jcdata.dptr != NULL && (jcdata.dsize % 4 == 0))
2941 168 : changed_count = jcdata.dsize / 4;
2942 :
2943 226 : DEBUG(5,("get_stored_queue_info: qcount = %u, extra_count = %u\n", (unsigned int)qcount, (unsigned int)extra_count));
2944 :
2945 : /* Allocate the queue size. */
2946 226 : if (qcount == 0 && extra_count == 0)
2947 54 : goto out;
2948 :
2949 172 : if ((queue = SMB_MALLOC_ARRAY(print_queue_struct, qcount + extra_count)) == NULL)
2950 0 : goto out;
2951 :
2952 : /* Retrieve the linearised queue data. */
2953 :
2954 1440 : for(i = 0; i < qcount; i++) {
2955 0 : uint32_t qjob, qsize, qpage_count, qstatus, qpriority, qtime;
2956 2536 : len += tdb_unpack(data.dptr + len, data.dsize - len, "ddddddff",
2957 : &qjob,
2958 : &qsize,
2959 : &qpage_count,
2960 : &qstatus,
2961 : &qpriority,
2962 : &qtime,
2963 1268 : queue[i].fs_user,
2964 1268 : queue[i].fs_file);
2965 1268 : queue[i].sysjob = qjob;
2966 1268 : queue[i].size = qsize;
2967 1268 : queue[i].page_count = qpage_count;
2968 1268 : queue[i].status = qstatus;
2969 1268 : queue[i].priority = qpriority;
2970 1268 : queue[i].time = qtime;
2971 : }
2972 :
2973 172 : total_count = qcount;
2974 :
2975 : /* Add new jobids to the queue. */
2976 224 : for (i = 0; i < extra_count; i++) {
2977 0 : uint32_t jobid;
2978 0 : struct printjob *pjob;
2979 :
2980 52 : jobid = IVAL(cgdata.dptr, i*4);
2981 52 : DEBUG(5,("get_stored_queue_info: added job = %u\n", (unsigned int)jobid));
2982 52 : pjob = print_job_find(tmp_ctx, lp_const_servicename(snum), jobid);
2983 52 : if (!pjob) {
2984 0 : DEBUG(5,("get_stored_queue_info: failed to find added job = %u\n", (unsigned int)jobid));
2985 0 : remove_from_jobs_added(sharename, jobid);
2986 0 : continue;
2987 : }
2988 :
2989 52 : queue[total_count].sysjob = pjob->sysjob;
2990 52 : queue[total_count].size = pjob->size;
2991 52 : queue[total_count].page_count = pjob->page_count;
2992 52 : queue[total_count].status = pjob->status;
2993 52 : queue[total_count].priority = 1;
2994 52 : queue[total_count].time = pjob->starttime;
2995 52 : fstrcpy(queue[total_count].fs_user, pjob->user);
2996 52 : fstrcpy(queue[total_count].fs_file, pjob->jobname);
2997 52 : total_count++;
2998 52 : talloc_free(pjob);
2999 : }
3000 :
3001 : /* Update the changed jobids. */
3002 204 : for (i = 0; i < changed_count; i++) {
3003 32 : uint32_t jobid = IVAL(jcdata.dptr, i * 4);
3004 0 : struct printjob *pjob;
3005 0 : uint32_t j;
3006 32 : bool found = false;
3007 :
3008 32 : pjob = print_job_find(tmp_ctx, sharename, jobid);
3009 32 : if (pjob == NULL) {
3010 0 : DEBUG(5,("get_stored_queue_info: failed to find "
3011 : "changed job = %u\n",
3012 : (unsigned int)jobid));
3013 0 : remove_from_jobs_changed(sharename, jobid);
3014 0 : continue;
3015 : }
3016 :
3017 144 : for (j = 0; j < total_count; j++) {
3018 144 : if (queue[j].sysjob == pjob->sysjob) {
3019 32 : found = true;
3020 32 : break;
3021 : }
3022 : }
3023 :
3024 32 : if (found) {
3025 32 : DEBUG(5,("get_stored_queue_info: changed job: %u\n",
3026 : (unsigned int)jobid));
3027 :
3028 32 : queue[j].sysjob = pjob->sysjob;
3029 32 : queue[j].size = pjob->size;
3030 32 : queue[j].page_count = pjob->page_count;
3031 32 : queue[j].status = pjob->status;
3032 32 : queue[j].priority = 1;
3033 32 : queue[j].time = pjob->starttime;
3034 32 : fstrcpy(queue[j].fs_user, pjob->user);
3035 32 : fstrcpy(queue[j].fs_file, pjob->jobname);
3036 32 : talloc_free(pjob);
3037 :
3038 32 : DEBUG(5,("updated queue[%u], jobid: %u, sysjob: %u, "
3039 : "jobname: %s\n",
3040 : (unsigned int)j, (unsigned int)jobid,
3041 : (unsigned int)queue[j].sysjob, pjob->jobname));
3042 : }
3043 :
3044 32 : remove_from_jobs_changed(sharename, jobid);
3045 : }
3046 :
3047 : /* Sort the queue by submission time otherwise they are displayed
3048 : in hash order. */
3049 :
3050 172 : TYPESAFE_QSORT(queue, total_count, printjob_comp);
3051 :
3052 172 : DEBUG(5,("get_stored_queue_info: total_count = %u\n", (unsigned int)total_count));
3053 :
3054 172 : if (max_reported_jobs && total_count > max_reported_jobs)
3055 0 : total_count = max_reported_jobs;
3056 :
3057 172 : *ppqueue = queue;
3058 172 : *pcount = total_count;
3059 :
3060 172 : ret = true;
3061 :
3062 226 : out:
3063 :
3064 226 : SAFE_FREE(data.dptr);
3065 226 : SAFE_FREE(cgdata.dptr);
3066 226 : talloc_free(tmp_ctx);
3067 226 : return ret;
3068 : }
3069 :
3070 : /****************************************************************************
3071 : Get a printer queue listing.
3072 : set queue = NULL and status = NULL if you just want to update the cache
3073 : ****************************************************************************/
3074 :
3075 226 : int print_queue_status(struct messaging_context *msg_ctx, int snum,
3076 : print_queue_struct **ppqueue,
3077 : print_status_struct *status)
3078 : {
3079 0 : fstring keystr;
3080 0 : TDB_DATA data, key;
3081 0 : const char *sharename;
3082 0 : struct tdb_print_db *pdb;
3083 226 : int count = 0;
3084 :
3085 : /* make sure the database is up to date */
3086 :
3087 226 : if (print_cache_expired(lp_const_servicename(snum), True))
3088 61 : print_queue_update(msg_ctx, snum, False);
3089 :
3090 : /* return if we are done */
3091 226 : if ( !ppqueue || !status )
3092 0 : return 0;
3093 :
3094 226 : *ppqueue = NULL;
3095 226 : sharename = lp_const_servicename(snum);
3096 226 : pdb = get_print_db_byname(sharename);
3097 :
3098 226 : if (!pdb)
3099 0 : return 0;
3100 :
3101 : /*
3102 : * Fetch the queue status. We must do this first, as there may
3103 : * be no jobs in the queue.
3104 : */
3105 :
3106 226 : ZERO_STRUCTP(status);
3107 226 : slprintf(keystr, sizeof(keystr)-1, "STATUS/%s", sharename);
3108 226 : key = string_tdb_data(keystr);
3109 :
3110 226 : data = tdb_fetch(pdb->tdb, key);
3111 226 : if (data.dptr) {
3112 226 : if (data.dsize == sizeof(*status)) {
3113 : /* this memcpy is ok since the status struct was
3114 : not packed before storing it in the tdb */
3115 226 : memcpy(status, data.dptr, sizeof(*status));
3116 : }
3117 226 : SAFE_FREE(data.dptr);
3118 : }
3119 :
3120 : /*
3121 : * Now, fetch the print queue information. We first count the number
3122 : * of entries, and then only retrieve the queue if necessary.
3123 : */
3124 :
3125 226 : if (!get_stored_queue_info(msg_ctx, pdb, snum, &count, ppqueue)) {
3126 54 : release_print_db(pdb);
3127 54 : return 0;
3128 : }
3129 :
3130 172 : release_print_db(pdb);
3131 172 : return count;
3132 : }
3133 :
3134 : /****************************************************************************
3135 : Pause a queue.
3136 : ****************************************************************************/
3137 :
3138 52 : WERROR print_queue_pause(const struct auth_session_info *server_info,
3139 : struct messaging_context *msg_ctx, int snum)
3140 : {
3141 0 : int ret;
3142 52 : struct printif *current_printif = get_printer_fns( snum );
3143 :
3144 52 : if (!W_ERROR_IS_OK(print_access_check(server_info, msg_ctx, snum,
3145 : PRINTER_ACCESS_ADMINISTER))) {
3146 0 : return WERR_ACCESS_DENIED;
3147 : }
3148 :
3149 :
3150 52 : become_root();
3151 :
3152 52 : ret = (*(current_printif->queue_pause))(snum);
3153 :
3154 52 : unbecome_root();
3155 :
3156 52 : if (ret != 0) {
3157 0 : return WERR_INVALID_PARAMETER;
3158 : }
3159 :
3160 : /* force update the database */
3161 52 : print_cache_flush(lp_const_servicename(snum));
3162 :
3163 : /* Send a printer notify message */
3164 :
3165 52 : notify_printer_status(global_event_context(), msg_ctx, snum,
3166 : PRINTER_STATUS_PAUSED);
3167 :
3168 52 : return WERR_OK;
3169 : }
3170 :
3171 : /****************************************************************************
3172 : Resume a queue.
3173 : ****************************************************************************/
3174 :
3175 40 : WERROR print_queue_resume(const struct auth_session_info *server_info,
3176 : struct messaging_context *msg_ctx, int snum)
3177 : {
3178 0 : int ret;
3179 40 : struct printif *current_printif = get_printer_fns( snum );
3180 :
3181 40 : if (!W_ERROR_IS_OK(print_access_check(server_info, msg_ctx, snum,
3182 : PRINTER_ACCESS_ADMINISTER))) {
3183 0 : return WERR_ACCESS_DENIED;
3184 : }
3185 :
3186 40 : become_root();
3187 :
3188 40 : ret = (*(current_printif->queue_resume))(snum);
3189 :
3190 40 : unbecome_root();
3191 :
3192 40 : if (ret != 0) {
3193 0 : return WERR_INVALID_PARAMETER;
3194 : }
3195 :
3196 : /* make sure the database is up to date */
3197 40 : if (print_cache_expired(lp_const_servicename(snum), True))
3198 34 : print_queue_update(msg_ctx, snum, True);
3199 :
3200 : /* Send a printer notify message */
3201 :
3202 40 : notify_printer_status(global_event_context(), msg_ctx, snum,
3203 : PRINTER_STATUS_OK);
3204 :
3205 40 : return WERR_OK;
3206 : }
3207 :
3208 : /****************************************************************************
3209 : Purge a queue - implemented by deleting all jobs that we can delete.
3210 : ****************************************************************************/
3211 :
3212 12 : WERROR print_queue_purge(const struct auth_session_info *server_info,
3213 : struct messaging_context *msg_ctx, int snum)
3214 : {
3215 0 : print_queue_struct *queue;
3216 0 : print_status_struct status;
3217 0 : int njobs, i;
3218 0 : bool can_job_admin;
3219 :
3220 : /* Force and update so the count is accurate (i.e. not a cached count) */
3221 12 : print_queue_update(msg_ctx, snum, True);
3222 :
3223 12 : can_job_admin = W_ERROR_IS_OK(print_access_check(server_info,
3224 : msg_ctx,
3225 : snum,
3226 : JOB_ACCESS_ADMINISTER));
3227 12 : njobs = print_queue_status(msg_ctx, snum, &queue, &status);
3228 :
3229 12 : if ( can_job_admin )
3230 12 : become_root();
3231 :
3232 44 : for (i = 0; i < njobs; i++) {
3233 0 : struct tdb_print_db *pdb;
3234 0 : int jobid;
3235 0 : bool owner;
3236 32 : pdb = get_print_db_byname(lp_const_servicename(snum));
3237 32 : if (pdb == NULL) {
3238 0 : DEBUG(1, ("failed to find printdb for %s\n",
3239 : lp_const_servicename(snum)));
3240 0 : continue;
3241 : }
3242 32 : jobid = sysjob_to_jobid_pdb(pdb, queue[i].sysjob);
3243 32 : if (jobid == (uint32_t)-1) {
3244 0 : DEBUG(2, ("jobid for system job %d not found\n",
3245 : queue[i].sysjob));
3246 0 : continue; /* unix job */
3247 : }
3248 32 : owner = is_owner(server_info, lp_const_servicename(snum),
3249 : jobid);
3250 :
3251 32 : if (owner || can_job_admin) {
3252 32 : print_job_delete1(global_event_context(), msg_ctx,
3253 : snum, jobid);
3254 : }
3255 : }
3256 :
3257 12 : if ( can_job_admin )
3258 12 : unbecome_root();
3259 :
3260 : /* update the cache */
3261 12 : print_queue_update(msg_ctx, snum, True);
3262 :
3263 12 : SAFE_FREE(queue);
3264 :
3265 12 : return WERR_OK;
3266 : }
|