ctdb-tests: Update statd-callout tests to handle both modes
[samba4-gss.git] / source3 / printing / printing.c
blob48d221de127b65be72ac2a5445700aa8575b3fdf
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
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.
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.
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/>.
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"
46 extern userdom_struct current_user_info;
48 /* Current printer interface */
49 static bool remove_from_jobs_added(const char* sharename, uint32_t jobid);
51 static int get_queue_status(const char* sharename, print_status_struct *);
53 /****************************************************************************
54 Initialise the printing backend. Called once at startup before the fork().
55 ****************************************************************************/
57 bool print_backend_init(struct messaging_context *msg_ctx)
59 const char *sversion = "INFO/version";
60 int services = lp_numservices();
61 int snum;
62 bool ok;
63 char *print_cache_path;
65 print_cache_path = cache_path(talloc_tos(), "printing");
66 if (print_cache_path == NULL) {
67 return false;
69 ok = directory_create_or_exist(print_cache_path, 0755);
70 TALLOC_FREE(print_cache_path);
71 if (!ok) {
72 return false;
75 /* handle a Samba upgrade */
77 for (snum = 0; snum < services; snum++) {
78 struct tdb_print_db *pdb;
79 if (!lp_printable(snum))
80 continue;
82 pdb = get_print_db_byname(lp_const_servicename(snum));
83 if (!pdb)
84 continue;
85 if (tdb_lock_bystring(pdb->tdb, sversion) != 0) {
86 DEBUG(0,("print_backend_init: Failed to open printer %s database\n", lp_const_servicename(snum) ));
87 release_print_db(pdb);
88 return False;
90 if (tdb_fetch_int32(pdb->tdb, sversion) != PRINT_DATABASE_VERSION) {
91 tdb_wipe_all(pdb->tdb);
92 tdb_store_int32(pdb->tdb, sversion, PRINT_DATABASE_VERSION);
94 tdb_unlock_bystring(pdb->tdb, sversion);
95 release_print_db(pdb);
98 close_all_print_db(); /* Don't leave any open. */
100 /* do NT print initialization... */
101 return nt_printing_init(msg_ctx);
104 /****************************************************************************
105 Shut down printing backend. Called once at shutdown to close the tdb.
106 ****************************************************************************/
108 void printing_end(void)
110 close_all_print_db(); /* Don't leave any open. */
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.
118 Use the generic interface as the default and only use cups interface only
119 when asked for (and only when supported)
120 ****************************************************************************/
122 static struct printif *get_printer_fns_from_type( enum printing_types type )
124 struct printif *printer_fns = &generic_printif;
126 #ifdef HAVE_CUPS
127 if ( type == PRINT_CUPS ) {
128 printer_fns = &cups_printif;
130 #endif /* HAVE_CUPS */
132 #ifdef HAVE_IPRINT
133 if ( type == PRINT_IPRINT ) {
134 printer_fns = &iprint_printif;
136 #endif /* HAVE_IPRINT */
138 printer_fns->type = type;
140 return printer_fns;
143 static struct printif *get_printer_fns( int snum )
145 return get_printer_fns_from_type( (enum printing_types)lp_printing(snum) );
149 /****************************************************************************
150 Useful function to generate a tdb key.
151 ****************************************************************************/
153 static TDB_DATA print_key(uint32_t jobid, uint32_t *tmp)
155 TDB_DATA ret;
157 SIVAL(tmp, 0, jobid);
158 ret.dptr = (uint8_t *)tmp;
159 ret.dsize = sizeof(*tmp);
160 return ret;
163 /****************************************************************************
164 Pack the devicemode to store it in a tdb.
165 ****************************************************************************/
166 static int pack_devicemode(struct spoolss_DeviceMode *devmode, uint8_t *buf, int buflen)
168 enum ndr_err_code ndr_err;
169 DATA_BLOB blob = { .data = NULL };
170 int len = 0;
172 if (devmode) {
173 ndr_err = ndr_push_struct_blob(&blob, talloc_tos(),
174 devmode,
175 (ndr_push_flags_fn_t)
176 ndr_push_spoolss_DeviceMode);
177 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
178 DEBUG(10, ("pack_devicemode: "
179 "error encoding spoolss_DeviceMode\n"));
180 goto done;
184 len = tdb_pack(buf, buflen, "B", blob.length, blob.data);
186 if (devmode) {
187 DEBUG(8, ("Packed devicemode [%s]\n", devmode->formname));
190 done:
191 return len;
194 /****************************************************************************
195 Unpack the devicemode to store it in a tdb.
196 ****************************************************************************/
197 static int unpack_devicemode(TALLOC_CTX *mem_ctx,
198 const uint8_t *buf, int buflen,
199 struct spoolss_DeviceMode **devmode)
201 struct spoolss_DeviceMode *dm;
202 enum ndr_err_code ndr_err;
203 char *data = NULL;
204 uint32_t data_len = 0;
205 DATA_BLOB blob;
206 int len = 0;
208 *devmode = NULL;
210 len = tdb_unpack(buf, buflen, "B", &data_len, &data);
211 if (!data) {
212 return len;
215 dm = talloc_zero(mem_ctx, struct spoolss_DeviceMode);
216 if (!dm) {
217 goto done;
220 blob = data_blob_const(data, data_len);
222 ndr_err = ndr_pull_struct_blob(&blob, dm, dm,
223 (ndr_pull_flags_fn_t)ndr_pull_spoolss_DeviceMode);
224 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
225 DEBUG(10, ("unpack_devicemode: "
226 "error parsing spoolss_DeviceMode\n"));
227 goto done;
230 DEBUG(8, ("Unpacked devicemode [%s](%s)\n",
231 dm->devicename, dm->formname));
232 if (dm->driverextra_data.data) {
233 DEBUG(8, ("with a private section of %d bytes\n",
234 dm->__driverextra_length));
237 *devmode = dm;
239 done:
240 SAFE_FREE(data);
241 return len;
244 /***********************************************************************
245 unpack a pjob from a tdb buffer
246 ***********************************************************************/
248 static int unpack_pjob(TALLOC_CTX *mem_ctx, uint8_t *buf, int buflen,
249 struct printjob *pjob)
251 int len = 0;
252 int used;
253 uint32_t pjpid, pjjobid, pjsysjob, pjfd, pjstarttime, pjstatus;
254 uint32_t pjsize, pjpage_count, pjspooled, pjsmbjob;
256 if (!buf || !pjob) {
257 return -1;
260 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 pjob->filename,
272 pjob->jobname,
273 pjob->user,
274 pjob->clientmachine,
275 pjob->queuename);
277 if (len == -1) {
278 return -1;
281 used = unpack_devicemode(mem_ctx, buf+len, buflen-len, &pjob->devmode);
282 if (used == -1) {
283 return -1;
286 len += used;
288 pjob->pid = pjpid;
289 pjob->jobid = pjjobid;
290 pjob->sysjob = pjsysjob;
291 pjob->fd = pjfd;
292 pjob->starttime = pjstarttime;
293 pjob->status = pjstatus;
294 pjob->size = pjsize;
295 pjob->page_count = pjpage_count;
296 pjob->spooled = pjspooled;
297 pjob->smbjob = pjsmbjob;
299 return len;
303 /****************************************************************************
304 Useful function to find a print job in the database.
305 ****************************************************************************/
307 static struct printjob *print_job_find(TALLOC_CTX *mem_ctx,
308 const char *sharename,
309 uint32_t jobid)
311 struct printjob *pjob;
312 uint32_t tmp;
313 TDB_DATA ret;
314 struct tdb_print_db *pdb = get_print_db_byname(sharename);
316 DEBUG(10,("print_job_find: looking up job %u for share %s\n",
317 (unsigned int)jobid, sharename ));
319 if (!pdb) {
320 return NULL;
323 ret = tdb_fetch(pdb->tdb, print_key(jobid, &tmp));
324 release_print_db(pdb);
326 if (!ret.dptr) {
327 DEBUG(10, ("print_job_find: failed to find jobid %u.\n",
328 jobid));
329 return NULL;
332 pjob = talloc_zero(mem_ctx, struct printjob);
333 if (pjob == NULL) {
334 goto err_out;
337 if (unpack_pjob(mem_ctx, ret.dptr, ret.dsize, pjob) == -1) {
338 DEBUG(10, ("failed to unpack jobid %u.\n", jobid));
339 talloc_free(pjob);
340 pjob = NULL;
341 goto err_out;
344 DEBUG(10,("print_job_find: returning system job %d for jobid %u.\n",
345 pjob->sysjob, jobid));
346 SMB_ASSERT(pjob->jobid == jobid);
348 err_out:
349 SAFE_FREE(ret.dptr);
350 return pjob;
353 struct job_traverse_state {
354 int sysjob;
355 uint32_t jobid;
358 /* find spoolss jobid based on sysjob */
359 static int sysjob_to_jobid_traverse_fn(TDB_CONTEXT *the_tdb, TDB_DATA key,
360 TDB_DATA data, void *private_data)
362 struct printjob *pjob;
363 struct job_traverse_state *state =
364 (struct job_traverse_state *)private_data;
366 if (!data.dptr || data.dsize == 0)
367 return 0;
369 pjob = (struct printjob *)data.dptr;
370 if (key.dsize != sizeof(uint32_t))
371 return 0;
373 if (state->sysjob == pjob->sysjob) {
374 state->jobid = pjob->jobid;
375 return 1;
378 return 0;
381 uint32_t sysjob_to_jobid_pdb(struct tdb_print_db *pdb, int sysjob)
383 struct job_traverse_state state;
385 state.sysjob = sysjob;
386 state.jobid = (uint32_t)-1;
388 tdb_traverse(pdb->tdb, sysjob_to_jobid_traverse_fn, &state);
390 return state.jobid;
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 ****************************************************************************/
398 uint32_t sysjob_to_jobid(int unix_jobid)
400 int services = lp_numservices();
401 int snum;
402 struct job_traverse_state state;
404 state.sysjob = unix_jobid;
405 state.jobid = (uint32_t)-1;
407 for (snum = 0; snum < services; snum++) {
408 struct tdb_print_db *pdb;
409 if (!lp_printable(snum))
410 continue;
411 pdb = get_print_db_byname(lp_const_servicename(snum));
412 if (!pdb) {
413 continue;
415 tdb_traverse(pdb->tdb, sysjob_to_jobid_traverse_fn, &state);
416 release_print_db(pdb);
417 if (state.jobid != (uint32_t)-1)
418 return state.jobid;
420 return (uint32_t)-1;
423 /* find sysjob based on spoolss jobid */
424 static int jobid_to_sysjob_traverse_fn(TDB_CONTEXT *the_tdb, TDB_DATA key,
425 TDB_DATA data, void *private_data)
427 struct printjob *pjob;
428 struct job_traverse_state *state =
429 (struct job_traverse_state *)private_data;
431 if (!data.dptr || data.dsize == 0)
432 return 0;
434 pjob = (struct printjob *)data.dptr;
435 if (key.dsize != sizeof(uint32_t))
436 return 0;
438 if (state->jobid == pjob->jobid) {
439 state->sysjob = pjob->sysjob;
440 return 1;
443 return 0;
446 int jobid_to_sysjob_pdb(struct tdb_print_db *pdb, uint32_t jobid)
448 struct job_traverse_state state;
450 state.sysjob = -1;
451 state.jobid = jobid;
453 tdb_traverse(pdb->tdb, jobid_to_sysjob_traverse_fn, &state);
455 return state.sysjob;
458 /****************************************************************************
459 Send notifications based on what has changed after a pjob_store.
460 ****************************************************************************/
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 }
480 /* Convert a lpq status value stored in printing.tdb into the
481 appropriate win32 API constant. */
483 static uint32_t map_to_spoolss_status(uint32_t lpq_status)
485 int i = 0;
487 while (lpq_to_spoolss_status_map[i].lpq_status != -1) {
488 if (lpq_to_spoolss_status_map[i].lpq_status == lpq_status)
489 return lpq_to_spoolss_status_map[i].spoolss_status;
490 i++;
493 return 0;
496 /***************************************************************************
497 Append a jobid to a list
498 ***************************************************************************/
500 static bool add_to_jobs_list(
501 struct tdb_print_db *pdb, uint32_t jobid, const char *key)
503 uint8_t store_jobid[sizeof(uint32_t)];
504 TDB_DATA data = {
505 .dptr = store_jobid, .dsize = sizeof(store_jobid)
507 int ret;
509 SIVAL(&store_jobid, 0, jobid);
511 DBG_DEBUG("Added jobid %"PRIu32" to %s\n", jobid, key);
513 ret = tdb_append(pdb->tdb, string_tdb_data(key), data);
514 return ret == 0;
517 /***************************************************************************
518 Remove a jobid from the 'jobs changed' list.
519 ***************************************************************************/
521 static bool remove_from_jobs_list(
522 const char *keystr, const char *sharename, uint32_t jobid)
524 struct tdb_print_db *pdb = get_print_db_byname(sharename);
525 TDB_DATA data, key;
526 size_t job_count, i;
527 bool ret = False;
528 bool gotlock = False;
530 if (!pdb) {
531 return False;
534 ZERO_STRUCT(data);
536 key = string_tdb_data(keystr);
538 if (tdb_chainlock_with_timeout(pdb->tdb, key, 5) != 0)
539 goto out;
541 gotlock = True;
543 data = tdb_fetch(pdb->tdb, key);
545 if (data.dptr == NULL || data.dsize == 0 || (data.dsize % 4 != 0))
546 goto out;
548 job_count = data.dsize / 4;
549 for (i = 0; i < job_count; i++) {
550 uint32_t ch_jobid;
552 ch_jobid = IVAL(data.dptr, i*4);
553 if (ch_jobid == jobid) {
554 if (i < job_count -1 )
555 memmove(data.dptr + (i*4), data.dptr + (i*4) + 4, (job_count - i - 1)*4 );
556 data.dsize -= 4;
557 if (tdb_store(pdb->tdb, key, data, TDB_REPLACE) != 0)
558 goto out;
559 break;
563 ret = True;
564 out:
566 if (gotlock)
567 tdb_chainunlock(pdb->tdb, key);
568 SAFE_FREE(data.dptr);
569 release_print_db(pdb);
570 if (ret)
571 DBG_DEBUG("removed jobid %"PRIu32"\n", jobid);
572 else
573 DBG_DEBUG("Failed to remove jobid %"PRIu32"\n", jobid);
574 return ret;
577 static bool remove_from_jobs_changed(const char* sharename, uint32_t jobid)
579 bool ret = remove_from_jobs_list(
580 "INFO/jobs_changed", sharename, jobid);
581 return ret;
584 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)
591 bool new_job = false;
592 bool changed = false;
594 if (old_data == NULL) {
595 new_job = true;
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) */
605 if (new_job) {
606 notify_job_submitted(ev, msg_ctx,
607 sharename, jobid, new_data->starttime);
608 notify_job_username(ev, msg_ctx,
609 sharename, jobid, new_data->user);
610 notify_job_name(ev, msg_ctx,
611 sharename, jobid, new_data->jobname);
612 notify_job_status(ev, msg_ctx,
613 sharename, jobid, map_to_spoolss_status(new_data->status));
614 notify_job_total_bytes(ev, msg_ctx,
615 sharename, jobid, new_data->size);
616 notify_job_total_pages(ev, msg_ctx,
617 sharename, jobid, new_data->page_count);
618 } else {
619 if (!strequal(old_data->jobname, new_data->jobname)) {
620 notify_job_name(ev, msg_ctx, sharename,
621 jobid, new_data->jobname);
622 changed = true;
625 if (old_data->status != new_data->status) {
626 notify_job_status(ev, msg_ctx,
627 sharename, jobid,
628 map_to_spoolss_status(new_data->status));
631 if (old_data->size != new_data->size) {
632 notify_job_total_bytes(ev, msg_ctx,
633 sharename, jobid, new_data->size);
636 if (old_data->page_count != new_data->page_count) {
637 notify_job_total_pages(ev, msg_ctx,
638 sharename, jobid,
639 new_data->page_count);
643 *pchanged = changed;
646 /****************************************************************************
647 Store a job structure back to the database.
648 ****************************************************************************/
650 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)
655 uint32_t tmp;
656 TDB_DATA old_data, new_data;
657 bool ret = False;
658 struct tdb_print_db *pdb = get_print_db_byname(sharename);
659 uint8_t *buf = NULL;
660 int len, newlen, buflen;
663 if (!pdb)
664 return False;
666 /* Get old data */
668 old_data = tdb_fetch(pdb->tdb, print_key(jobid, &tmp));
670 /* Doh! Now we have to pack/unpack data since the NT_DEVICEMODE was added */
672 newlen = 0;
674 do {
675 len = 0;
676 buflen = newlen;
677 len += tdb_pack(buf+len, buflen-len, "ddddddddddfffff",
678 (uint32_t)pjob->pid,
679 (uint32_t)pjob->jobid,
680 (uint32_t)pjob->sysjob,
681 (uint32_t)pjob->fd,
682 (uint32_t)pjob->starttime,
683 (uint32_t)pjob->status,
684 (uint32_t)pjob->size,
685 (uint32_t)pjob->page_count,
686 (uint32_t)pjob->spooled,
687 (uint32_t)pjob->smbjob,
688 pjob->filename,
689 pjob->jobname,
690 pjob->user,
691 pjob->clientmachine,
692 pjob->queuename);
694 len += pack_devicemode(pjob->devmode, buf+len, buflen-len);
696 if (buflen != len) {
697 buf = (uint8_t *)SMB_REALLOC(buf, len);
698 if (!buf) {
699 DEBUG(0,("pjob_store: failed to enlarge buffer!\n"));
700 goto done;
702 newlen = len;
704 } while ( buflen != len );
707 /* Store new data */
709 new_data.dptr = buf;
710 new_data.dsize = len;
711 ret = (tdb_store(pdb->tdb, print_key(jobid, &tmp), new_data,
712 TDB_REPLACE) == 0);
714 /* Send notify updates for what has changed */
716 if (ret) {
717 bool changed = false;
718 struct printjob old_pjob;
720 if (old_data.dsize) {
721 TALLOC_CTX *tmp_ctx = talloc_new(ev);
722 if (tmp_ctx == NULL)
723 goto done;
725 len = unpack_pjob(tmp_ctx, old_data.dptr,
726 old_data.dsize, &old_pjob);
727 if (len != -1 ) {
728 pjob_store_notify(ev,
729 msg_ctx,
730 sharename, jobid, &old_pjob,
731 pjob,
732 &changed);
733 if (changed) {
734 add_to_jobs_list(
735 pdb,
736 jobid,
737 "INFO/jobs_changed");
740 talloc_free(tmp_ctx);
742 } else {
743 /* new job */
744 pjob_store_notify(ev, msg_ctx,
745 sharename, jobid, NULL, pjob,
746 &changed);
750 done:
751 release_print_db(pdb);
752 SAFE_FREE( old_data.dptr );
753 SAFE_FREE( buf );
755 return ret;
758 /****************************************************************************
759 Remove a job structure from the database.
760 ****************************************************************************/
762 static void pjob_delete(struct tevent_context *ev,
763 struct messaging_context *msg_ctx,
764 const char* sharename, uint32_t jobid)
766 uint32_t tmp;
767 struct printjob *pjob;
768 uint32_t job_status = 0;
769 struct tdb_print_db *pdb;
770 TALLOC_CTX *tmp_ctx = talloc_new(ev);
771 if (tmp_ctx == NULL) {
772 return;
775 pdb = get_print_db_byname(sharename);
776 if (!pdb) {
777 goto err_out;
780 pjob = print_job_find(tmp_ctx, sharename, jobid);
781 if (!pjob) {
782 DEBUG(5, ("we were asked to delete nonexistent job %u\n",
783 jobid));
784 goto err_release;
787 /* We must cycle through JOB_STATUS_DELETING and
788 JOB_STATUS_DELETED for the port monitor to delete the job
789 properly. */
791 job_status = JOB_STATUS_DELETING|JOB_STATUS_DELETED;
792 notify_job_status(ev, msg_ctx, sharename, jobid, job_status);
794 /* Remove from printing.tdb */
796 tdb_delete(pdb->tdb, print_key(jobid, &tmp));
797 remove_from_jobs_added(sharename, jobid);
798 rap_jobid_delete(sharename, jobid);
799 err_release:
800 release_print_db(pdb);
801 err_out:
802 talloc_free(tmp_ctx);
805 /****************************************************************************
806 List a unix job in the print database.
807 ****************************************************************************/
809 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)
814 struct printjob pj, *old_pj;
815 TALLOC_CTX *tmp_ctx = talloc_new(ev);
816 if (tmp_ctx == NULL) {
817 return;
820 if (jobid == (uint32_t)-1) {
821 jobid = q->sysjob + UNIX_JOB_START;
824 /* Preserve the timestamp on an existing unix print job */
826 old_pj = print_job_find(tmp_ctx, sharename, jobid);
828 ZERO_STRUCT(pj);
830 pj.pid = (pid_t)-1;
831 pj.jobid = jobid;
832 pj.sysjob = q->sysjob;
833 pj.fd = -1;
834 pj.starttime = old_pj ? old_pj->starttime : q->time;
835 pj.status = q->status;
836 pj.size = q->size;
837 pj.spooled = True;
838 fstrcpy(pj.filename, old_pj ? old_pj->filename : "");
839 if (jobid < UNIX_JOB_START) {
840 pj.smbjob = True;
841 fstrcpy(pj.jobname, old_pj ? old_pj->jobname : "Remote Downlevel Document");
842 } else {
843 pj.smbjob = False;
844 fstrcpy(pj.jobname, old_pj ? old_pj->jobname : q->fs_file);
846 fstrcpy(pj.user, old_pj ? old_pj->user : q->fs_user);
847 fstrcpy(pj.queuename, old_pj ? old_pj->queuename : sharename );
849 pjob_store(ev, msg_ctx, sharename, jobid, &pj);
850 talloc_free(tmp_ctx);
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;
866 /****************************************************************************
867 Utility fn to delete any jobs that are no longer active.
868 ****************************************************************************/
870 static int traverse_fn_delete(TDB_CONTEXT *t, TDB_DATA key, TDB_DATA data, void *state)
872 struct traverse_struct *ts = (struct traverse_struct *)state;
873 struct printjob pjob;
874 uint32_t jobid;
875 size_t i = 0;
877 if ( key.dsize != sizeof(jobid) )
878 return 0;
880 if (unpack_pjob(ts->mem_ctx, data.dptr, data.dsize, &pjob) == -1)
881 return 0;
882 talloc_free(pjob.devmode);
883 jobid = pjob.jobid;
885 if (!pjob.smbjob) {
886 /* remove a unix job if it isn't in the system queue any more */
887 for (i=0;i<ts->qcount;i++) {
888 if (ts->queue[i].sysjob == pjob.sysjob) {
889 break;
892 if (i == ts->qcount) {
893 DEBUG(10,("traverse_fn_delete: pjob %u deleted due to !smbjob\n",
894 (unsigned int)jobid ));
895 pjob_delete(ts->ev, ts->msg_ctx,
896 ts->sharename, jobid);
897 return 0;
900 /* need to continue at the bottom of the function to
901 save the correct attributes */
904 /* maybe it hasn't been spooled yet */
905 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 if (!process_exists_by_pid(pjob.pid)) {
910 DEBUG(10,("traverse_fn_delete: pjob %u deleted due to !process_exists (%u)\n",
911 (unsigned int)jobid, (unsigned int)pjob.pid ));
912 pjob_delete(ts->ev, ts->msg_ctx,
913 ts->sharename, jobid);
914 } else
915 ts->total_jobs++;
916 return 0;
919 /* this check only makes sense for jobs submitted from Windows clients */
921 if (pjob.smbjob) {
922 for (i=0;i<ts->qcount;i++) {
923 if ( pjob.status == LPQ_DELETED )
924 continue;
926 if (ts->queue[i].sysjob == pjob.sysjob) {
928 /* try to clean up any jobs that need to be deleted */
930 if ( pjob.status == LPQ_DELETING ) {
931 int result;
933 result = (*(ts->print_if->job_delete))(
934 ts->sharename, ts->lprm_command, &pjob );
936 if ( result != 0 ) {
937 /* if we can't delete, then reset the job status */
938 pjob.status = LPQ_QUEUED;
939 pjob_store(ts->ev, ts->msg_ctx,
940 ts->sharename, jobid, &pjob);
942 else {
943 /* if we deleted the job, the remove the tdb record */
944 pjob_delete(ts->ev,
945 ts->msg_ctx,
946 ts->sharename, jobid);
947 pjob.status = LPQ_DELETED;
952 break;
957 /* The job isn't in the system queue - we have to assume it has
958 completed, so delete the database entry. */
960 if (i == ts->qcount) {
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. */
969 if (pjob.starttime < ts->lpq_time) {
970 DBG_DEBUG("pjob %u deleted due to pjob.starttime "
971 "(%" PRIu64 ") < ts->lpq_time (%" PRIu64
972 ")\n",
973 (unsigned int)jobid,
974 (uint64_t)pjob.starttime,
975 (uint64_t)ts->lpq_time);
976 pjob_delete(ts->ev, ts->msg_ctx,
977 ts->sharename, jobid);
978 } else
979 ts->total_jobs++;
980 return 0;
983 /* Save the pjob attributes we will store. */
984 ts->queue[i].sysjob = pjob.sysjob;
985 ts->queue[i].size = pjob.size;
986 ts->queue[i].page_count = pjob.page_count;
987 ts->queue[i].status = pjob.status;
988 ts->queue[i].priority = 1;
989 ts->queue[i].time = pjob.starttime;
990 fstrcpy(ts->queue[i].fs_user, pjob.user);
991 fstrcpy(ts->queue[i].fs_file, pjob.jobname);
993 ts->total_jobs++;
995 return 0;
998 /****************************************************************************
999 Check if the print queue has been updated recently enough.
1000 ****************************************************************************/
1002 static void print_cache_flush(const char *sharename)
1004 fstring key;
1005 struct tdb_print_db *pdb = get_print_db_byname(sharename);
1007 if (!pdb)
1008 return;
1009 slprintf(key, sizeof(key)-1, "CACHE/%s", sharename);
1010 tdb_store_int32(pdb->tdb, key, -1);
1011 release_print_db(pdb);
1014 /****************************************************************************
1015 Check if someone already thinks they are doing the update.
1016 ****************************************************************************/
1018 static pid_t get_updating_pid(const char *sharename)
1020 fstring keystr;
1021 TDB_DATA data, key;
1022 pid_t updating_pid;
1023 struct tdb_print_db *pdb = get_print_db_byname(sharename);
1025 if (!pdb)
1026 return (pid_t)-1;
1027 slprintf(keystr, sizeof(keystr)-1, "UPDATING/%s", sharename);
1028 key = string_tdb_data(keystr);
1030 data = tdb_fetch(pdb->tdb, key);
1031 release_print_db(pdb);
1032 if (!data.dptr || data.dsize != sizeof(pid_t)) {
1033 SAFE_FREE(data.dptr);
1034 return (pid_t)-1;
1037 updating_pid = IVAL(data.dptr, 0);
1038 SAFE_FREE(data.dptr);
1040 if (process_exists_by_pid(updating_pid))
1041 return updating_pid;
1043 return (pid_t)-1;
1046 /****************************************************************************
1047 Set the fact that we're doing the update, or have finished doing the update
1048 in the tdb.
1049 ****************************************************************************/
1051 static void set_updating_pid(const fstring sharename, bool updating)
1053 fstring keystr;
1054 TDB_DATA key;
1055 TDB_DATA data;
1056 pid_t updating_pid = getpid();
1057 uint8_t buffer[4];
1059 struct tdb_print_db *pdb = get_print_db_byname(sharename);
1061 if (!pdb)
1062 return;
1064 slprintf(keystr, sizeof(keystr)-1, "UPDATING/%s", sharename);
1065 key = string_tdb_data(keystr);
1067 DEBUG(5, ("set_updating_pid: %supdating lpq cache for print share %s\n",
1068 updating ? "" : "not ",
1069 sharename ));
1071 if ( !updating ) {
1072 tdb_delete(pdb->tdb, key);
1073 release_print_db(pdb);
1074 return;
1077 SIVAL( buffer, 0, updating_pid);
1078 data.dptr = buffer;
1079 data.dsize = 4; /* we always assume this is a 4 byte value */
1081 tdb_store(pdb->tdb, key, data, TDB_REPLACE);
1082 release_print_db(pdb);
1085 /****************************************************************************
1086 Sort print jobs by submittal time.
1087 ****************************************************************************/
1089 static int printjob_comp(print_queue_struct *j1, print_queue_struct *j2)
1091 /* Silly cases */
1093 if (!j1 && !j2)
1094 return 0;
1095 if (!j1)
1096 return -1;
1097 if (!j2)
1098 return 1;
1100 /* Sort on job start time */
1102 if (j1->time == j2->time)
1103 return 0;
1104 return (j1->time > j2->time) ? 1 : -1;
1107 /****************************************************************************
1108 Store the sorted queue representation for later portmon retrieval.
1109 Skip deleted jobs
1110 ****************************************************************************/
1112 static void store_queue_struct(struct tdb_print_db *pdb, struct traverse_struct *pts)
1114 TDB_DATA data;
1115 int max_reported_jobs = lp_max_reported_print_jobs(pts->snum);
1116 print_queue_struct *queue = pts->queue;
1117 size_t len;
1118 size_t i;
1119 unsigned int qcount;
1121 if (max_reported_jobs && (max_reported_jobs < pts->qcount))
1122 pts->qcount = max_reported_jobs;
1123 qcount = 0;
1125 /* Work out the size. */
1126 data.dsize = 0;
1127 data.dsize += tdb_pack(NULL, 0, "d", qcount);
1129 for (i = 0; i < pts->qcount; i++) {
1130 if ( queue[i].status == LPQ_DELETED )
1131 continue;
1133 qcount++;
1134 data.dsize += tdb_pack(NULL, 0, "ddddddff",
1135 (uint32_t)queue[i].sysjob,
1136 (uint32_t)queue[i].size,
1137 (uint32_t)queue[i].page_count,
1138 (uint32_t)queue[i].status,
1139 (uint32_t)queue[i].priority,
1140 (uint32_t)queue[i].time,
1141 queue[i].fs_user,
1142 queue[i].fs_file);
1145 if ((data.dptr = (uint8_t *)SMB_MALLOC(data.dsize)) == NULL)
1146 return;
1148 len = 0;
1149 len += tdb_pack(data.dptr + len, data.dsize - len, "d", qcount);
1150 for (i = 0; i < pts->qcount; i++) {
1151 if ( queue[i].status == LPQ_DELETED )
1152 continue;
1154 len += tdb_pack(data.dptr + len, data.dsize - len, "ddddddff",
1155 (uint32_t)queue[i].sysjob,
1156 (uint32_t)queue[i].size,
1157 (uint32_t)queue[i].page_count,
1158 (uint32_t)queue[i].status,
1159 (uint32_t)queue[i].priority,
1160 (uint32_t)queue[i].time,
1161 queue[i].fs_user,
1162 queue[i].fs_file);
1165 tdb_store(pdb->tdb, string_tdb_data("INFO/linear_queue_array"), data,
1166 TDB_REPLACE);
1167 SAFE_FREE(data.dptr);
1168 return;
1171 static TDB_DATA get_jobs_added_data(struct tdb_print_db *pdb)
1173 TDB_DATA data;
1175 ZERO_STRUCT(data);
1177 data = tdb_fetch(pdb->tdb, string_tdb_data("INFO/jobs_added"));
1178 if (data.dptr == NULL || data.dsize == 0 || (data.dsize % 4 != 0)) {
1179 SAFE_FREE(data.dptr);
1180 ZERO_STRUCT(data);
1183 return data;
1186 static void check_job_added(const char *sharename, TDB_DATA data, uint32_t jobid)
1188 unsigned int i;
1189 unsigned int job_count = data.dsize / 4;
1191 for (i = 0; i < job_count; i++) {
1192 uint32_t ch_jobid;
1194 ch_jobid = IVAL(data.dptr, i*4);
1195 if (ch_jobid == jobid)
1196 remove_from_jobs_added(sharename, jobid);
1200 /****************************************************************************
1201 Check if the print queue has been updated recently enough.
1202 ****************************************************************************/
1204 static bool print_cache_expired(const char *sharename, bool check_pending)
1206 fstring key;
1207 time_t last_qscan_time, time_now = time(NULL);
1208 struct tdb_print_db *pdb = get_print_db_byname(sharename);
1209 bool result = False;
1211 if (!pdb)
1212 return False;
1214 snprintf(key, sizeof(key), "CACHE/%s", sharename);
1215 last_qscan_time = (time_t)tdb_fetch_int32(pdb->tdb, key);
1218 * Invalidate the queue for 3 reasons.
1219 * (1). last queue scan time == -1.
1220 * (2). Current time - last queue scan time > allowed cache time.
1221 * (3). last queue scan time > current time + MAX_CACHE_VALID_TIME (1 hour by default).
1222 * This last test picks up machines for which the clock has been moved
1223 * forward, an lpq scan done and then the clock moved back. Otherwise
1224 * that last lpq scan would stay around for a loooong loooong time... :-). JRA.
1227 if (last_qscan_time == ((time_t)-1)
1228 || (time_now - last_qscan_time) >= lp_lpq_cache_time()
1229 || last_qscan_time > (time_now + MAX_CACHE_VALID_TIME))
1231 uint32_t u;
1232 time_t msg_pending_time;
1234 DBG_INFO("cache expired for queue %s "
1235 "(last_qscan_time = %" PRIu64 ", time now = %" PRIu64
1236 ", qcachetime = %d)\n",
1237 sharename,
1238 (uint64_t)last_qscan_time,
1239 (uint64_t)time_now,
1240 lp_lpq_cache_time());
1242 /* check if another smbd has already sent a message to update the
1243 queue. Give the pending message one minute to clear and
1244 then send another message anyways. Make sure to check for
1245 clocks that have been run forward and then back again. */
1247 snprintf(key, sizeof(key), "MSG_PENDING/%s", sharename);
1249 if ( check_pending
1250 && tdb_fetch_uint32( pdb->tdb, key, &u )
1251 && (msg_pending_time=u) > 0
1252 && msg_pending_time <= time_now
1253 && (time_now - msg_pending_time) < 60 )
1255 DEBUG(4,("print_cache_expired: message already pending for %s. Accepting cache\n",
1256 sharename));
1257 goto done;
1260 result = True;
1263 done:
1264 release_print_db(pdb);
1265 return result;
1268 /****************************************************************************
1269 main work for updating the lpq cache for a printer queue
1270 ****************************************************************************/
1272 static void print_queue_update_internal(struct tevent_context *ev,
1273 struct messaging_context *msg_ctx,
1274 const char *sharename,
1275 struct printif *current_printif,
1276 char *lpq_command, char *lprm_command)
1278 size_t i, qcount;
1279 print_queue_struct *queue = NULL;
1280 print_status_struct status;
1281 print_status_struct old_status;
1282 struct printjob *pjob;
1283 struct traverse_struct tstruct;
1284 TDB_DATA data, key;
1285 TDB_DATA jcdata;
1286 fstring keystr, cachestr;
1287 struct tdb_print_db *pdb = get_print_db_byname(sharename);
1288 TALLOC_CTX *tmp_ctx = talloc_new(ev);
1290 if ((pdb == NULL) || (tmp_ctx == NULL)) {
1291 return;
1294 DEBUG(5,("print_queue_update_internal: printer = %s, type = %d, lpq command = [%s]\n",
1295 sharename, current_printif->type, lpq_command));
1298 * Update the cache time FIRST ! Stops others even
1299 * attempting to get the lock and doing this
1300 * if the lpq takes a long time.
1303 slprintf(cachestr, sizeof(cachestr)-1, "CACHE/%s", sharename);
1304 tdb_store_int32(pdb->tdb, cachestr, (int)time(NULL));
1306 /* get the current queue using the appropriate interface */
1307 ZERO_STRUCT(status);
1309 qcount = (*(current_printif->queue_get))(sharename,
1310 current_printif->type,
1311 lpq_command, &queue, &status);
1313 DBG_NOTICE("%zu job%s in queue for %s\n",
1314 qcount,
1315 (qcount != 1) ? "s" : "",
1316 sharename);
1318 /* Sort the queue by submission time otherwise they are displayed
1319 in hash order. */
1321 TYPESAFE_QSORT(queue, qcount, printjob_comp);
1324 any job in the internal database that is marked as spooled
1325 and doesn't exist in the system queue is considered finished
1326 and removed from the database
1328 any job in the system database but not in the internal database
1329 is added as a unix job
1331 fill in any system job numbers as we go
1333 jcdata = get_jobs_added_data(pdb);
1335 for (i=0; i<qcount; i++) {
1336 uint32_t jobid = sysjob_to_jobid_pdb(pdb, queue[i].sysjob);
1337 if (jobid == (uint32_t)-1) {
1338 /* assume its a unix print job */
1339 print_unix_job(ev, msg_ctx,
1340 sharename, &queue[i], jobid);
1341 continue;
1344 /* we have an active SMB print job - update its status */
1345 pjob = print_job_find(tmp_ctx, sharename, jobid);
1346 if (!pjob) {
1347 /* err, somethings wrong. Probably smbd was restarted
1348 with jobs in the queue. All we can do is treat them
1349 like unix jobs. Pity. */
1350 DEBUG(1, ("queued print job %d not found in jobs list, "
1351 "assuming unix job\n", jobid));
1352 print_unix_job(ev, msg_ctx,
1353 sharename, &queue[i], jobid);
1354 continue;
1357 /* don't reset the status on jobs to be deleted */
1359 if ( pjob->status != LPQ_DELETING )
1360 pjob->status = queue[i].status;
1362 pjob_store(ev, msg_ctx, sharename, jobid, pjob);
1364 check_job_added(sharename, jcdata, jobid);
1367 SAFE_FREE(jcdata.dptr);
1369 /* now delete any queued entries that don't appear in the
1370 system queue */
1371 tstruct.queue = queue;
1372 tstruct.qcount = qcount;
1373 tstruct.snum = -1;
1374 tstruct.total_jobs = 0;
1375 tstruct.lpq_time = time(NULL);
1376 tstruct.sharename = sharename;
1377 tstruct.lprm_command = lprm_command;
1378 tstruct.print_if = current_printif;
1379 tstruct.ev = ev;
1380 tstruct.msg_ctx = msg_ctx;
1381 tstruct.mem_ctx = tmp_ctx;
1383 tdb_traverse(pdb->tdb, traverse_fn_delete, (void *)&tstruct);
1385 /* Store the linearised queue, max jobs only. */
1386 store_queue_struct(pdb, &tstruct);
1388 SAFE_FREE(tstruct.queue);
1389 talloc_free(tmp_ctx);
1391 DBG_DEBUG("printer %s INFO, total_jobs = %zu\n",
1392 sharename,
1393 tstruct.total_jobs);
1395 tdb_store_int32(pdb->tdb, "INFO/total_jobs", tstruct.total_jobs);
1397 get_queue_status(sharename, &old_status);
1398 if (old_status.qcount != qcount) {
1399 DBG_DEBUG("Queue status change %zu jobs -> %zu jobs "
1400 "for printer %s\n",
1401 old_status.qcount,
1402 qcount,
1403 sharename);
1406 /* store the new queue status structure */
1407 slprintf(keystr, sizeof(keystr)-1, "STATUS/%s", sharename);
1408 key = string_tdb_data(keystr);
1410 status.qcount = qcount;
1411 data.dptr = (uint8_t *)&status;
1412 data.dsize = sizeof(status);
1413 tdb_store(pdb->tdb, key, data, TDB_REPLACE);
1416 * Update the cache time again. We want to do this call
1417 * as little as possible...
1420 slprintf(keystr, sizeof(keystr)-1, "CACHE/%s", sharename);
1421 tdb_store_int32(pdb->tdb, keystr, (int32_t)time(NULL));
1423 /* clear the msg pending record for this queue */
1425 snprintf(keystr, sizeof(keystr), "MSG_PENDING/%s", sharename);
1427 if ( !tdb_store_uint32( pdb->tdb, keystr, 0 ) ) {
1428 /* log a message but continue on */
1430 DEBUG(0,("print_queue_update: failed to store MSG_PENDING flag for [%s]!\n",
1431 sharename));
1434 release_print_db( pdb );
1436 return;
1439 /****************************************************************************
1440 Update the internal database from the system print queue for a queue.
1441 obtain a lock on the print queue before proceeding (needed when multiple
1442 smbd processes maytry to update the lpq cache concurrently).
1443 ****************************************************************************/
1445 static void print_queue_update_with_lock( struct tevent_context *ev,
1446 struct messaging_context *msg_ctx,
1447 const char *sharename,
1448 struct printif *current_printif,
1449 char *lpq_command, char *lprm_command )
1451 fstring keystr;
1452 struct tdb_print_db *pdb;
1454 DEBUG(5,("print_queue_update_with_lock: printer share = %s\n", sharename));
1455 pdb = get_print_db_byname(sharename);
1456 if (!pdb)
1457 return;
1459 if ( !print_cache_expired(sharename, False) ) {
1460 DEBUG(5,("print_queue_update_with_lock: print cache for %s is still ok\n", sharename));
1461 release_print_db(pdb);
1462 return;
1466 * Check to see if someone else is doing this update.
1467 * This is essentially a mutex on the update.
1470 if (get_updating_pid(sharename) != -1) {
1471 release_print_db(pdb);
1472 return;
1475 /* Lock the queue for the database update */
1477 slprintf(keystr, sizeof(keystr) - 1, "LOCK/%s", sharename);
1478 /* Only wait 10 seconds for this. */
1479 if (tdb_lock_bystring_with_timeout(pdb->tdb, keystr, 10) != 0) {
1480 DEBUG(0,("print_queue_update_with_lock: Failed to lock printer %s database\n", sharename));
1481 release_print_db(pdb);
1482 return;
1486 * Ensure that no one else got in here.
1487 * If the updating pid is still -1 then we are
1488 * the winner.
1491 if (get_updating_pid(sharename) != -1) {
1493 * Someone else is doing the update, exit.
1495 tdb_unlock_bystring(pdb->tdb, keystr);
1496 release_print_db(pdb);
1497 return;
1501 * We're going to do the update ourselves.
1504 /* Tell others we're doing the update. */
1505 set_updating_pid(sharename, True);
1508 * Allow others to enter and notice we're doing
1509 * the update.
1512 tdb_unlock_bystring(pdb->tdb, keystr);
1514 /* do the main work now */
1516 print_queue_update_internal(ev, msg_ctx,
1517 sharename, current_printif,
1518 lpq_command, lprm_command);
1520 /* Delete our pid from the db. */
1521 set_updating_pid(sharename, False);
1522 release_print_db(pdb);
1525 /****************************************************************************
1526 this is the receive function of the background lpq updater
1527 ****************************************************************************/
1528 void print_queue_receive(struct messaging_context *msg,
1529 void *private_data,
1530 uint32_t msg_type,
1531 struct server_id server_id,
1532 DATA_BLOB *data)
1534 fstring sharename;
1535 char *lpqcommand = NULL, *lprmcommand = NULL;
1536 int printing_type;
1537 size_t len;
1539 len = tdb_unpack( (uint8_t *)data->data, data->length, "fdPP",
1540 sharename,
1541 &printing_type,
1542 &lpqcommand,
1543 &lprmcommand );
1545 if ( len == -1 ) {
1546 SAFE_FREE(lpqcommand);
1547 SAFE_FREE(lprmcommand);
1548 DEBUG(0,("print_queue_receive: Got invalid print queue update message\n"));
1549 return;
1552 print_queue_update_with_lock(global_event_context(), msg, sharename,
1553 get_printer_fns_from_type((enum printing_types)printing_type),
1554 lpqcommand, lprmcommand );
1556 SAFE_FREE(lpqcommand);
1557 SAFE_FREE(lprmcommand);
1558 return;
1561 /****************************************************************************
1562 update the internal database from the system print queue for a queue
1563 ****************************************************************************/
1565 static void print_queue_update(struct messaging_context *msg_ctx,
1566 int snum, bool force)
1568 char key[268];
1569 fstring sharename;
1570 char *lpqcommand = NULL;
1571 char *lprmcommand = NULL;
1572 uint8_t *buffer = NULL;
1573 size_t len = 0;
1574 size_t newlen;
1575 struct tdb_print_db *pdb;
1576 int type;
1577 struct printif *current_printif;
1578 TALLOC_CTX *ctx = talloc_tos();
1579 const struct loadparm_substitution *lp_sub =
1580 loadparm_s3_global_substitution();
1582 fstrcpy( sharename, lp_const_servicename(snum));
1584 /* don't strip out characters like '$' from the printername */
1586 lpqcommand = talloc_string_sub2(ctx,
1587 lp_lpq_command(snum),
1588 "%p",
1589 lp_printername(talloc_tos(), lp_sub, snum),
1590 false, false, false);
1591 if (!lpqcommand) {
1592 return;
1594 lpqcommand = talloc_sub_full(ctx,
1595 lp_servicename(talloc_tos(), lp_sub, snum),
1596 current_user_info.unix_name,
1598 get_current_gid(NULL),
1599 get_current_username(),
1600 get_current_user_info_domain(),
1601 lpqcommand);
1602 if (!lpqcommand) {
1603 return;
1606 lprmcommand = talloc_string_sub2(ctx,
1607 lp_lprm_command(snum),
1608 "%p",
1609 lp_printername(talloc_tos(), lp_sub, snum),
1610 false, false, false);
1611 if (!lprmcommand) {
1612 return;
1614 lprmcommand = talloc_sub_full(ctx,
1615 lp_servicename(talloc_tos(), lp_sub, snum),
1616 current_user_info.unix_name,
1618 get_current_gid(NULL),
1619 get_current_username(),
1620 get_current_user_info_domain(),
1621 lprmcommand);
1622 if (!lprmcommand) {
1623 return;
1627 * Make sure that the background queue process exists.
1628 * Otherwise just do the update ourselves
1631 if ( force || background_lpq_updater_pid == -1 ) {
1632 DEBUG(4,("print_queue_update: updating queue [%s] myself\n", sharename));
1633 current_printif = get_printer_fns( snum );
1634 print_queue_update_with_lock(global_event_context(), msg_ctx,
1635 sharename, current_printif,
1636 lpqcommand, lprmcommand);
1638 return;
1641 type = lp_printing(snum);
1643 /* get the length */
1645 len = tdb_pack( NULL, 0, "fdPP",
1646 sharename,
1647 type,
1648 lpqcommand,
1649 lprmcommand );
1651 buffer = SMB_XMALLOC_ARRAY( uint8_t, len );
1653 /* now pack the buffer */
1654 newlen = tdb_pack( buffer, len, "fdPP",
1655 sharename,
1656 type,
1657 lpqcommand,
1658 lprmcommand );
1660 SMB_ASSERT( newlen == len );
1662 DEBUG(10,("print_queue_update: Sending message -> printer = %s, "
1663 "type = %d, lpq command = [%s] lprm command = [%s]\n",
1664 sharename, type, lpqcommand, lprmcommand ));
1666 /* here we set a msg pending record for other smbd processes
1667 to throttle the number of duplicate print_queue_update msgs
1668 sent. */
1670 pdb = get_print_db_byname(sharename);
1671 if (!pdb) {
1672 SAFE_FREE(buffer);
1673 return;
1676 snprintf(key, sizeof(key), "MSG_PENDING/%s", sharename);
1678 if ( !tdb_store_uint32( pdb->tdb, key, time(NULL) ) ) {
1679 /* log a message but continue on */
1681 DEBUG(0,("print_queue_update: failed to store MSG_PENDING flag for [%s]!\n",
1682 sharename));
1685 release_print_db( pdb );
1687 /* finally send the message */
1689 send_to_bgqd(msg_ctx, MSG_PRINTER_UPDATE, (uint8_t *)buffer, len);
1691 SAFE_FREE( buffer );
1693 return;
1696 /****************************************************************************
1697 Create/Update an entry in the print tdb that will allow us to send notify
1698 updates only to interested smbd's.
1699 ****************************************************************************/
1701 bool print_notify_register_pid(int snum)
1703 TDB_DATA data;
1704 struct tdb_print_db *pdb = NULL;
1705 TDB_CONTEXT *tdb = NULL;
1706 const char *printername;
1707 uint32_t mypid = (uint32_t)getpid();
1708 bool ret = False;
1709 size_t i;
1711 /* if (snum == -1), then the change notify request was
1712 on a print server handle and we need to register on
1713 all print queues */
1715 if (snum == -1)
1717 int num_services = lp_numservices();
1718 int idx;
1720 for ( idx=0; idx<num_services; idx++ ) {
1721 if (lp_snum_ok(idx) && lp_printable(idx) )
1722 print_notify_register_pid(idx);
1725 return True;
1727 else /* register for a specific printer */
1729 printername = lp_const_servicename(snum);
1730 pdb = get_print_db_byname(printername);
1731 if (!pdb)
1732 return False;
1733 tdb = pdb->tdb;
1736 if (tdb_lock_bystring_with_timeout(tdb, NOTIFY_PID_LIST_KEY, 10) != 0) {
1737 DEBUG(0,("print_notify_register_pid: Failed to lock printer %s\n",
1738 printername));
1739 if (pdb)
1740 release_print_db(pdb);
1741 return False;
1744 data = get_printer_notify_pid_list( tdb, printername, True );
1746 /* Add ourselves and increase the refcount. */
1748 for (i = 0; i < data.dsize; i += 8) {
1749 if (IVAL(data.dptr,i) == mypid) {
1750 uint32_t new_refcount = IVAL(data.dptr, i+4) + 1;
1751 SIVAL(data.dptr, i+4, new_refcount);
1752 break;
1756 if (i == data.dsize) {
1757 /* We weren't in the list. Realloc. */
1758 data.dptr = (uint8_t *)SMB_REALLOC(data.dptr, data.dsize + 8);
1759 if (!data.dptr) {
1760 DEBUG(0,("print_notify_register_pid: Relloc fail for printer %s\n",
1761 printername));
1762 goto done;
1764 data.dsize += 8;
1765 SIVAL(data.dptr,data.dsize - 8,mypid);
1766 SIVAL(data.dptr,data.dsize - 4,1); /* Refcount. */
1769 /* Store back the record. */
1770 if (tdb_store_bystring(tdb, NOTIFY_PID_LIST_KEY, data, TDB_REPLACE) != 0) {
1771 DEBUG(0,("print_notify_register_pid: Failed to update pid \
1772 list for printer %s\n", printername));
1773 goto done;
1776 ret = True;
1778 done:
1780 tdb_unlock_bystring(tdb, NOTIFY_PID_LIST_KEY);
1781 if (pdb)
1782 release_print_db(pdb);
1783 SAFE_FREE(data.dptr);
1784 return ret;
1787 /****************************************************************************
1788 Update an entry in the print tdb that will allow us to send notify
1789 updates only to interested smbd's.
1790 ****************************************************************************/
1792 bool print_notify_deregister_pid(int snum)
1794 TDB_DATA data;
1795 struct tdb_print_db *pdb = NULL;
1796 TDB_CONTEXT *tdb = NULL;
1797 const char *printername;
1798 uint32_t mypid = (uint32_t)getpid();
1799 size_t i;
1800 bool ret = False;
1802 /* if ( snum == -1 ), we are deregister a print server handle
1803 which means to deregister on all print queues */
1805 if (snum == -1)
1807 int num_services = lp_numservices();
1808 int idx;
1810 for ( idx=0; idx<num_services; idx++ ) {
1811 if ( lp_snum_ok(idx) && lp_printable(idx) )
1812 print_notify_deregister_pid(idx);
1815 return True;
1817 else /* deregister a specific printer */
1819 printername = lp_const_servicename(snum);
1820 pdb = get_print_db_byname(printername);
1821 if (!pdb)
1822 return False;
1823 tdb = pdb->tdb;
1826 if (tdb_lock_bystring_with_timeout(tdb, NOTIFY_PID_LIST_KEY, 10) != 0) {
1827 DEBUG(0,("print_notify_register_pid: Failed to lock \
1828 printer %s database\n", printername));
1829 if (pdb)
1830 release_print_db(pdb);
1831 return False;
1834 data = get_printer_notify_pid_list( tdb, printername, True );
1836 /* Reduce refcount. Remove ourselves if zero. */
1838 for (i = 0; i < data.dsize; ) {
1839 if (IVAL(data.dptr,i) == mypid) {
1840 uint32_t refcount = IVAL(data.dptr, i+4);
1842 refcount--;
1844 if (refcount == 0) {
1845 if (data.dsize - i > 8)
1846 memmove( &data.dptr[i], &data.dptr[i+8], data.dsize - i - 8);
1847 data.dsize -= 8;
1848 continue;
1850 SIVAL(data.dptr, i+4, refcount);
1853 i += 8;
1856 if (data.dsize == 0)
1857 SAFE_FREE(data.dptr);
1859 /* Store back the record. */
1860 if (tdb_store_bystring(tdb, NOTIFY_PID_LIST_KEY, data, TDB_REPLACE) != 0) {
1861 DEBUG(0,("print_notify_register_pid: Failed to update pid \
1862 list for printer %s\n", printername));
1863 goto done;
1866 ret = True;
1868 done:
1870 tdb_unlock_bystring(tdb, NOTIFY_PID_LIST_KEY);
1871 if (pdb)
1872 release_print_db(pdb);
1873 SAFE_FREE(data.dptr);
1874 return ret;
1877 /****************************************************************************
1878 Check if a jobid is valid. It is valid if it exists in the database.
1879 ****************************************************************************/
1881 bool print_job_exists(const char* sharename, uint32_t jobid)
1883 struct tdb_print_db *pdb = get_print_db_byname(sharename);
1884 bool ret;
1885 uint32_t tmp;
1887 if (!pdb)
1888 return False;
1889 ret = tdb_exists(pdb->tdb, print_key(jobid, &tmp));
1890 release_print_db(pdb);
1891 return ret;
1894 /****************************************************************************
1895 Return the device mode assigned to a specific print job.
1896 Only valid for the process doing the spooling and when the job
1897 has not been spooled.
1898 ****************************************************************************/
1900 struct spoolss_DeviceMode *print_job_devmode(TALLOC_CTX *mem_ctx,
1901 const char *sharename,
1902 uint32_t jobid)
1904 struct printjob *pjob = print_job_find(mem_ctx, sharename, jobid);
1905 if (pjob == NULL) {
1906 return NULL;
1909 return pjob->devmode;
1912 /****************************************************************************
1913 Set the name of a job. Only possible for owner.
1914 ****************************************************************************/
1916 bool print_job_set_name(struct tevent_context *ev,
1917 struct messaging_context *msg_ctx,
1918 const char *sharename, uint32_t jobid, const char *name)
1920 struct printjob *pjob;
1921 bool ret;
1922 TALLOC_CTX *tmp_ctx = talloc_new(ev);
1923 if (tmp_ctx == NULL) {
1924 return false;
1927 pjob = print_job_find(tmp_ctx, sharename, jobid);
1928 if (!pjob || pjob->pid != getpid()) {
1929 ret = false;
1930 goto err_out;
1933 fstrcpy(pjob->jobname, name);
1934 ret = pjob_store(ev, msg_ctx, sharename, jobid, pjob);
1935 err_out:
1936 talloc_free(tmp_ctx);
1937 return ret;
1940 /****************************************************************************
1941 Get the name of a job. Only possible for owner.
1942 ****************************************************************************/
1944 bool print_job_get_name(TALLOC_CTX *mem_ctx, const char *sharename, uint32_t jobid, char **name)
1946 struct printjob *pjob;
1948 pjob = print_job_find(mem_ctx, sharename, jobid);
1949 if (!pjob || pjob->pid != getpid()) {
1950 return false;
1953 *name = pjob->jobname;
1954 return true;
1958 /***************************************************************************
1959 Remove a jobid from the 'jobs added' list.
1960 ***************************************************************************/
1962 static bool remove_from_jobs_added(const char* sharename, uint32_t jobid)
1964 bool ret = remove_from_jobs_list("INFO/jobs_added", sharename, jobid);
1965 return ret;
1968 /****************************************************************************
1969 Delete a print job - don't update queue.
1970 ****************************************************************************/
1972 static bool print_job_delete1(struct tevent_context *ev,
1973 struct messaging_context *msg_ctx,
1974 int snum, uint32_t jobid)
1976 const char* sharename = lp_const_servicename(snum);
1977 const struct loadparm_substitution *lp_sub =
1978 loadparm_s3_global_substitution();
1979 struct printjob *pjob;
1980 int result = 0;
1981 struct printif *current_printif = get_printer_fns( snum );
1982 bool ret;
1983 TALLOC_CTX *tmp_ctx = talloc_new(ev);
1984 if (tmp_ctx == NULL) {
1985 return false;
1988 pjob = print_job_find(tmp_ctx, sharename, jobid);
1989 if (!pjob) {
1990 ret = false;
1991 goto err_out;
1995 * If already deleting just return.
1998 if (pjob->status == LPQ_DELETING) {
1999 ret = true;
2000 goto err_out;
2003 /* Hrm - we need to be able to cope with deleting a job before it
2004 has reached the spooler. Just mark it as LPQ_DELETING and
2005 let the print_queue_update() code remove the record */
2008 if (pjob->sysjob == -1) {
2009 DEBUG(5, ("attempt to delete job %u not seen by lpr\n", (unsigned int)jobid));
2012 /* Set the tdb entry to be deleting. */
2014 pjob->status = LPQ_DELETING;
2015 pjob_store(ev, msg_ctx, sharename, jobid, pjob);
2017 if (pjob->spooled && pjob->sysjob != -1)
2019 result = (*(current_printif->job_delete))(
2020 lp_printername(talloc_tos(), lp_sub, snum),
2021 lp_lprm_command(snum),
2022 pjob);
2024 /* Delete the tdb entry if the delete succeeded or the job hasn't
2025 been spooled. */
2027 if (result == 0) {
2028 struct tdb_print_db *pdb = get_print_db_byname(sharename);
2029 int njobs = 1;
2031 if (!pdb) {
2032 ret = false;
2033 goto err_out;
2035 pjob_delete(ev, msg_ctx, sharename, jobid);
2036 /* Ensure we keep a rough count of the number of total jobs... */
2037 tdb_change_int32_atomic(pdb->tdb, "INFO/total_jobs", &njobs, -1);
2038 release_print_db(pdb);
2042 remove_from_jobs_added( sharename, jobid );
2044 ret = (result == 0);
2045 err_out:
2046 talloc_free(tmp_ctx);
2047 return ret;
2050 /****************************************************************************
2051 Return true if the current user owns the print job.
2052 ****************************************************************************/
2054 static bool is_owner(const struct auth_session_info *server_info,
2055 const char *servicename,
2056 uint32_t jobid)
2058 struct printjob *pjob;
2059 bool ret;
2060 TALLOC_CTX *tmp_ctx = talloc_new(server_info);
2061 if (tmp_ctx == NULL) {
2062 return false;
2065 pjob = print_job_find(tmp_ctx, servicename, jobid);
2066 if (!pjob || !server_info) {
2067 ret = false;
2068 goto err_out;
2071 ret = strequal(pjob->user, server_info->unix_info->sanitized_username);
2072 err_out:
2073 talloc_free(tmp_ctx);
2074 return ret;
2077 /****************************************************************************
2078 Delete a print job.
2079 ****************************************************************************/
2081 WERROR print_job_delete(const struct auth_session_info *server_info,
2082 struct messaging_context *msg_ctx,
2083 int snum, uint32_t jobid)
2085 const char* sharename = lp_const_servicename(snum);
2086 const struct loadparm_substitution *lp_sub =
2087 loadparm_s3_global_substitution();
2088 struct printjob *pjob;
2089 bool owner;
2090 WERROR werr;
2091 TALLOC_CTX *tmp_ctx = talloc_new(msg_ctx);
2092 if (tmp_ctx == NULL) {
2093 return WERR_NOT_ENOUGH_MEMORY;
2096 owner = is_owner(server_info, lp_const_servicename(snum), jobid);
2098 /* Check access against security descriptor or whether the user
2099 owns their job. */
2101 if (!owner &&
2102 !W_ERROR_IS_OK(print_access_check(server_info, msg_ctx, snum,
2103 JOB_ACCESS_ADMINISTER))) {
2104 DEBUG(0, ("print job delete denied. "
2105 "User name: %s, Printer name: %s.\n",
2106 uidtoname(server_info->unix_token->uid),
2107 lp_printername(tmp_ctx, lp_sub, snum)));
2109 werr = WERR_ACCESS_DENIED;
2110 goto err_out;
2114 * get the spooled filename of the print job
2115 * if this works, then the file has not been spooled
2116 * to the underlying print system. Just delete the
2117 * spool file & return.
2120 pjob = print_job_find(tmp_ctx, sharename, jobid);
2121 if (!pjob || pjob->spooled || pjob->pid != getpid()) {
2122 DEBUG(10, ("Skipping spool file removal for job %u\n", jobid));
2123 } else {
2124 DEBUG(10, ("Removing spool file [%s]\n", pjob->filename));
2125 if (unlink(pjob->filename) == -1) {
2126 werr = map_werror_from_unix(errno);
2127 goto err_out;
2131 if (!print_job_delete1(global_event_context(), msg_ctx, snum, jobid)) {
2132 werr = WERR_ACCESS_DENIED;
2133 goto err_out;
2136 /* force update the database and say the delete failed if the
2137 job still exists */
2139 print_queue_update(msg_ctx, snum, True);
2141 pjob = print_job_find(tmp_ctx, sharename, jobid);
2142 if (pjob && (pjob->status != LPQ_DELETING)) {
2143 werr = WERR_ACCESS_DENIED;
2144 goto err_out;
2146 werr = WERR_PRINTER_HAS_JOBS_QUEUED;
2148 err_out:
2149 talloc_free(tmp_ctx);
2150 return werr;
2153 /****************************************************************************
2154 Pause a job.
2155 ****************************************************************************/
2157 WERROR print_job_pause(const struct auth_session_info *server_info,
2158 struct messaging_context *msg_ctx,
2159 int snum, uint32_t jobid)
2161 const char* sharename = lp_const_servicename(snum);
2162 const struct loadparm_substitution *lp_sub =
2163 loadparm_s3_global_substitution();
2164 struct printjob *pjob;
2165 int ret = -1;
2166 struct printif *current_printif = get_printer_fns( snum );
2167 WERROR werr;
2168 TALLOC_CTX *tmp_ctx = talloc_new(msg_ctx);
2169 if (tmp_ctx == NULL) {
2170 return WERR_NOT_ENOUGH_MEMORY;
2173 pjob = print_job_find(tmp_ctx, sharename, jobid);
2174 if (!pjob || !server_info) {
2175 DEBUG(10, ("print_job_pause: no pjob or user for jobid %u\n",
2176 (unsigned int)jobid ));
2177 werr = WERR_INVALID_PARAMETER;
2178 goto err_out;
2181 if (!pjob->spooled || pjob->sysjob == -1) {
2182 DEBUG(10, ("print_job_pause: not spooled or bad sysjob = %d for jobid %u\n",
2183 (int)pjob->sysjob, (unsigned int)jobid ));
2184 werr = WERR_INVALID_PARAMETER;
2185 goto err_out;
2188 if (!is_owner(server_info, lp_const_servicename(snum), jobid) &&
2189 !W_ERROR_IS_OK(print_access_check(server_info, msg_ctx, snum,
2190 JOB_ACCESS_ADMINISTER))) {
2191 DEBUG(0, ("print job pause denied. "
2192 "User name: %s, Printer name: %s.\n",
2193 uidtoname(server_info->unix_token->uid),
2194 lp_printername(tmp_ctx, lp_sub, snum)));
2196 werr = WERR_ACCESS_DENIED;
2197 goto err_out;
2200 /* need to pause the spooled entry */
2201 ret = (*(current_printif->job_pause))(snum, pjob);
2203 if (ret != 0) {
2204 werr = WERR_INVALID_PARAMETER;
2205 goto err_out;
2208 /* force update the database */
2209 print_cache_flush(lp_const_servicename(snum));
2211 /* Send a printer notify message */
2213 notify_job_status(global_event_context(), msg_ctx, sharename, jobid,
2214 JOB_STATUS_PAUSED);
2216 /* how do we tell if this succeeded? */
2217 werr = WERR_OK;
2218 err_out:
2219 talloc_free(tmp_ctx);
2220 return werr;
2223 /****************************************************************************
2224 Resume a job.
2225 ****************************************************************************/
2227 WERROR print_job_resume(const struct auth_session_info *server_info,
2228 struct messaging_context *msg_ctx,
2229 int snum, uint32_t jobid)
2231 const char *sharename = lp_const_servicename(snum);
2232 const struct loadparm_substitution *lp_sub =
2233 loadparm_s3_global_substitution();
2234 struct printjob *pjob;
2235 int ret;
2236 struct printif *current_printif = get_printer_fns( snum );
2237 WERROR werr;
2238 TALLOC_CTX *tmp_ctx = talloc_new(msg_ctx);
2239 if (tmp_ctx == NULL)
2240 return WERR_NOT_ENOUGH_MEMORY;
2242 pjob = print_job_find(tmp_ctx, sharename, jobid);
2243 if (!pjob || !server_info) {
2244 DEBUG(10, ("print_job_resume: no pjob or user for jobid %u\n",
2245 (unsigned int)jobid ));
2246 werr = WERR_INVALID_PARAMETER;
2247 goto err_out;
2250 if (!pjob->spooled || pjob->sysjob == -1) {
2251 DEBUG(10, ("print_job_resume: not spooled or bad sysjob = %d for jobid %u\n",
2252 (int)pjob->sysjob, (unsigned int)jobid ));
2253 werr = WERR_INVALID_PARAMETER;
2254 goto err_out;
2257 if (!is_owner(server_info, lp_const_servicename(snum), jobid) &&
2258 !W_ERROR_IS_OK(print_access_check(server_info, msg_ctx, snum,
2259 JOB_ACCESS_ADMINISTER))) {
2260 DEBUG(0, ("print job resume denied. "
2261 "User name: %s, Printer name: %s.\n",
2262 uidtoname(server_info->unix_token->uid),
2263 lp_printername(tmp_ctx, lp_sub, snum)));
2265 werr = WERR_ACCESS_DENIED;
2266 goto err_out;
2269 ret = (*(current_printif->job_resume))(snum, pjob);
2271 if (ret != 0) {
2272 werr = WERR_INVALID_PARAMETER;
2273 goto err_out;
2276 /* force update the database */
2277 print_cache_flush(lp_const_servicename(snum));
2279 /* Send a printer notify message */
2281 notify_job_status(global_event_context(), msg_ctx, sharename, jobid,
2282 JOB_STATUS_QUEUED);
2284 werr = WERR_OK;
2285 err_out:
2286 talloc_free(tmp_ctx);
2287 return werr;
2290 /****************************************************************************
2291 Write to a print file.
2292 ****************************************************************************/
2294 ssize_t print_job_write(struct tevent_context *ev,
2295 struct messaging_context *msg_ctx,
2296 int snum, uint32_t jobid, const char *buf, size_t size)
2298 const char* sharename = lp_const_servicename(snum);
2299 ssize_t return_code;
2300 struct printjob *pjob;
2301 TALLOC_CTX *tmp_ctx = talloc_new(ev);
2302 if (tmp_ctx == NULL) {
2303 return -1;
2306 pjob = print_job_find(tmp_ctx, sharename, jobid);
2307 if (!pjob) {
2308 return_code = -1;
2309 goto err_out;
2312 /* don't allow another process to get this info - it is meaningless */
2313 if (pjob->pid != getpid()) {
2314 return_code = -1;
2315 goto err_out;
2318 /* if SMBD is spooling this can't be allowed */
2319 if (pjob->status == PJOB_SMBD_SPOOLING) {
2320 return_code = -1;
2321 goto err_out;
2324 return_code = write_data(pjob->fd, buf, size);
2325 if (return_code > 0) {
2326 pjob->size += size;
2327 pjob_store(ev, msg_ctx, sharename, jobid, pjob);
2329 err_out:
2330 talloc_free(tmp_ctx);
2331 return return_code;
2334 /****************************************************************************
2335 Get the queue status - do not update if db is out of date.
2336 ****************************************************************************/
2338 static int get_queue_status(const char* sharename, print_status_struct *status)
2340 fstring keystr;
2341 TDB_DATA data;
2342 struct tdb_print_db *pdb = get_print_db_byname(sharename);
2343 int len;
2345 if (status) {
2346 ZERO_STRUCTP(status);
2349 if (!pdb)
2350 return 0;
2352 if (status) {
2353 fstr_sprintf(keystr, "STATUS/%s", sharename);
2354 data = tdb_fetch(pdb->tdb, string_tdb_data(keystr));
2355 if (data.dptr) {
2356 if (data.dsize == sizeof(print_status_struct))
2357 /* this memcpy is ok since the status struct was
2358 not packed before storing it in the tdb */
2359 memcpy(status, data.dptr, sizeof(print_status_struct));
2360 SAFE_FREE(data.dptr);
2363 len = tdb_fetch_int32(pdb->tdb, "INFO/total_jobs");
2364 release_print_db(pdb);
2365 return (len == -1 ? 0 : len);
2368 /****************************************************************************
2369 Determine the number of jobs in a queue.
2370 ****************************************************************************/
2372 int print_queue_length(struct messaging_context *msg_ctx, int snum,
2373 print_status_struct *pstatus)
2375 const char* sharename = lp_const_servicename( snum );
2376 print_status_struct status;
2377 int len;
2379 ZERO_STRUCT( status );
2381 /* make sure the database is up to date */
2382 if (print_cache_expired(lp_const_servicename(snum), True))
2383 print_queue_update(msg_ctx, snum, False);
2385 /* also fetch the queue status */
2386 memset(&status, 0, sizeof(status));
2387 len = get_queue_status(sharename, &status);
2389 if (pstatus)
2390 *pstatus = status;
2392 return len;
2395 /***************************************************************************
2396 Allocate a jobid. Hold the lock for as short a time as possible.
2397 ***************************************************************************/
2399 static WERROR allocate_print_jobid(struct tdb_print_db *pdb, int snum,
2400 const char *sharename, uint32_t *pjobid)
2402 int i;
2403 uint32_t jobid;
2404 enum TDB_ERROR terr;
2405 int ret;
2407 *pjobid = (uint32_t)-1;
2409 for (i = 0; i < 3; i++) {
2410 /* Lock the database - only wait 20 seconds. */
2411 ret = tdb_lock_bystring_with_timeout(pdb->tdb,
2412 "INFO/nextjob", 20);
2413 if (ret != 0) {
2414 DEBUG(0, ("allocate_print_jobid: "
2415 "Failed to lock printing database %s\n",
2416 sharename));
2417 terr = tdb_error(pdb->tdb);
2418 return ntstatus_to_werror(map_nt_error_from_tdb(terr));
2421 if (!tdb_fetch_uint32(pdb->tdb, "INFO/nextjob", &jobid)) {
2422 terr = tdb_error(pdb->tdb);
2423 if (terr != TDB_ERR_NOEXIST) {
2424 DEBUG(0, ("allocate_print_jobid: "
2425 "Failed to fetch INFO/nextjob "
2426 "for print queue %s\n", sharename));
2427 tdb_unlock_bystring(pdb->tdb, "INFO/nextjob");
2428 return ntstatus_to_werror(map_nt_error_from_tdb(terr));
2430 DEBUG(10, ("allocate_print_jobid: "
2431 "No existing jobid in %s\n", sharename));
2432 jobid = 0;
2435 DEBUG(10, ("allocate_print_jobid: "
2436 "Read jobid %u from %s\n", jobid, sharename));
2438 jobid = NEXT_JOBID(jobid);
2440 ret = tdb_store_int32(pdb->tdb, "INFO/nextjob", jobid);
2441 if (ret != 0) {
2442 terr = tdb_error(pdb->tdb);
2443 DEBUG(3, ("allocate_print_jobid: "
2444 "Failed to store INFO/nextjob.\n"));
2445 tdb_unlock_bystring(pdb->tdb, "INFO/nextjob");
2446 return ntstatus_to_werror(map_nt_error_from_tdb(terr));
2449 /* We've finished with the INFO/nextjob lock. */
2450 tdb_unlock_bystring(pdb->tdb, "INFO/nextjob");
2452 if (!print_job_exists(sharename, jobid)) {
2453 break;
2455 DEBUG(10, ("allocate_print_jobid: "
2456 "Found jobid %u in %s\n", jobid, sharename));
2459 if (i > 2) {
2460 DEBUG(0, ("allocate_print_jobid: "
2461 "Failed to allocate a print job for queue %s\n",
2462 sharename));
2463 /* Probably full... */
2464 return WERR_NO_SPOOL_SPACE;
2467 /* Store a dummy placeholder. */
2469 uint32_t tmp;
2470 TDB_DATA dummy = {
2471 .dsize = 0,
2473 if (tdb_store(pdb->tdb, print_key(jobid, &tmp), dummy,
2474 TDB_INSERT) != 0) {
2475 DEBUG(3, ("allocate_print_jobid: "
2476 "jobid (%d) failed to store placeholder.\n",
2477 jobid ));
2478 terr = tdb_error(pdb->tdb);
2479 return ntstatus_to_werror(map_nt_error_from_tdb(terr));
2483 *pjobid = jobid;
2484 return WERR_OK;
2487 /***************************************************************************
2488 Do all checks needed to determine if we can start a job.
2489 ***************************************************************************/
2491 static WERROR print_job_checks(const struct auth_session_info *server_info,
2492 struct messaging_context *msg_ctx,
2493 int snum, int *njobs)
2495 const char *sharename = lp_const_servicename(snum);
2496 const struct loadparm_substitution *lp_sub =
2497 loadparm_s3_global_substitution();
2498 uint64_t dspace, dsize;
2499 uint64_t minspace;
2500 int ret;
2502 if (!W_ERROR_IS_OK(print_access_check(server_info, msg_ctx, snum,
2503 PRINTER_ACCESS_USE))) {
2504 DEBUG(3, ("print_job_checks: "
2505 "job start denied by security descriptor\n"));
2506 return WERR_ACCESS_DENIED;
2509 if (!print_time_access_check(server_info, msg_ctx, sharename)) {
2510 DEBUG(3, ("print_job_checks: "
2511 "job start denied by time check\n"));
2512 return WERR_ACCESS_DENIED;
2515 /* see if we have sufficient disk space */
2516 if (lp_min_print_space(snum)) {
2517 minspace = lp_min_print_space(snum);
2518 ret = sys_fsusage(lp_path(talloc_tos(), lp_sub, snum), &dspace, &dsize);
2519 if (ret == 0 && dspace < 2*minspace) {
2520 DEBUG(3, ("print_job_checks: "
2521 "disk space check failed.\n"));
2522 return WERR_NO_SPOOL_SPACE;
2526 /* for autoloaded printers, check that the printcap entry still exists */
2527 if (lp_autoloaded(snum) &&
2528 !printer_list_printername_exists(sharename)) {
2529 DEBUG(3, ("print_job_checks: printer name %s check failed.\n",
2530 sharename));
2531 return WERR_ACCESS_DENIED;
2534 /* Insure the maximum queue size is not violated */
2535 *njobs = print_queue_length(msg_ctx, snum, NULL);
2536 if (*njobs > lp_maxprintjobs(snum)) {
2537 DEBUG(3, ("print_job_checks: Queue %s number of jobs (%d) "
2538 "larger than max printjobs per queue (%d).\n",
2539 sharename, *njobs, lp_maxprintjobs(snum)));
2540 return WERR_NO_SPOOL_SPACE;
2543 return WERR_OK;
2546 /***************************************************************************
2547 Create a job file.
2548 ***************************************************************************/
2550 static WERROR print_job_spool_file(int snum, uint32_t jobid,
2551 const char *output_file,
2552 struct printjob *pjob)
2554 const struct loadparm_substitution *lp_sub =
2555 loadparm_s3_global_substitution();
2556 WERROR werr;
2557 SMB_STRUCT_STAT st;
2558 const char *path;
2559 int len;
2560 mode_t mask;
2562 /* if this file is within the printer path, it means that smbd
2563 * is spooling it and will pass us control when it is finished.
2564 * Verify that the file name is ok, within path, and it is
2565 * already already there */
2566 if (output_file) {
2567 path = lp_path(talloc_tos(), lp_sub, snum);
2568 len = strlen(path);
2569 if (strncmp(output_file, path, len) == 0 &&
2570 (output_file[len - 1] == '/' || output_file[len] == '/')) {
2572 /* verify path is not too long */
2573 if (strlen(output_file) >= sizeof(pjob->filename)) {
2574 return WERR_INVALID_NAME;
2577 /* verify that the file exists */
2578 if (sys_stat(output_file, &st, false) != 0) {
2579 return WERR_INVALID_NAME;
2582 fstrcpy(pjob->filename, output_file);
2584 DEBUG(3, ("print_job_spool_file:"
2585 "External spooling activated\n"));
2587 /* we do not open the file until spooling is done */
2588 pjob->fd = -1;
2589 pjob->status = PJOB_SMBD_SPOOLING;
2591 return WERR_OK;
2595 slprintf(pjob->filename, sizeof(pjob->filename)-1,
2596 "%s/%sXXXXXX", lp_path(talloc_tos(), lp_sub, snum),
2597 PRINT_SPOOL_PREFIX);
2598 mask = umask(S_IRWXO | S_IRWXG);
2599 pjob->fd = mkstemp(pjob->filename);
2600 umask(mask);
2602 if (pjob->fd == -1) {
2603 werr = map_werror_from_unix(errno);
2604 if (W_ERROR_EQUAL(werr, WERR_ACCESS_DENIED)) {
2605 /* Common setup error, force a report. */
2606 DEBUG(0, ("print_job_spool_file: "
2607 "insufficient permissions to open spool "
2608 "file %s.\n", pjob->filename));
2609 } else {
2610 /* Normal case, report at level 3 and above. */
2611 DEBUG(3, ("print_job_spool_file: "
2612 "can't open spool file %s\n",
2613 pjob->filename));
2615 return werr;
2618 return WERR_OK;
2621 /***************************************************************************
2622 Start spooling a job - return the jobid.
2623 ***************************************************************************/
2625 WERROR print_job_start(const struct auth_session_info *server_info,
2626 struct messaging_context *msg_ctx,
2627 const char *clientmachine,
2628 int snum, const char *docname, const char *filename,
2629 struct spoolss_DeviceMode *devmode, uint32_t *_jobid)
2631 uint32_t jobid;
2632 char *path = NULL, *userstr = NULL;
2633 struct printjob pjob;
2634 const char *sharename = lp_const_servicename(snum);
2635 struct tdb_print_db *pdb = get_print_db_byname(sharename);
2636 const struct loadparm_substitution *lp_sub =
2637 loadparm_s3_global_substitution();
2638 int njobs;
2639 WERROR werr;
2641 if (!pdb) {
2642 return WERR_INTERNAL_DB_CORRUPTION;
2645 path = lp_path(talloc_tos(), lp_sub, snum);
2647 werr = print_job_checks(server_info, msg_ctx, snum, &njobs);
2648 if (!W_ERROR_IS_OK(werr)) {
2649 release_print_db(pdb);
2650 return werr;
2653 DEBUG(10, ("print_job_start: "
2654 "Queue %s number of jobs (%d), max printjobs = %d\n",
2655 sharename, njobs, lp_maxprintjobs(snum)));
2657 werr = allocate_print_jobid(pdb, snum, sharename, &jobid);
2658 if (!W_ERROR_IS_OK(werr)) {
2659 goto fail;
2662 /* create the database entry */
2664 ZERO_STRUCT(pjob);
2666 pjob.pid = getpid();
2667 pjob.jobid = jobid;
2668 pjob.sysjob = -1;
2669 pjob.fd = -1;
2670 pjob.starttime = time(NULL);
2671 pjob.status = LPQ_SPOOLING;
2672 pjob.size = 0;
2673 pjob.spooled = False;
2674 pjob.smbjob = True;
2675 pjob.devmode = devmode;
2677 fstrcpy(pjob.jobname, docname);
2679 fstrcpy(pjob.clientmachine, clientmachine);
2681 userstr = talloc_sub_full(talloc_tos(),
2682 sharename,
2683 server_info->unix_info->sanitized_username,
2684 path, server_info->unix_token->gid,
2685 server_info->unix_info->sanitized_username,
2686 server_info->info->domain_name,
2687 lp_printjob_username(snum));
2688 if (userstr == NULL) {
2689 werr = WERR_NOT_ENOUGH_MEMORY;
2690 goto fail;
2692 strlcpy(pjob.user, userstr, sizeof(pjob.user));
2693 TALLOC_FREE(userstr);
2695 fstrcpy(pjob.queuename, lp_const_servicename(snum));
2697 /* we have a job entry - now create the spool file */
2698 werr = print_job_spool_file(snum, jobid, filename, &pjob);
2699 if (!W_ERROR_IS_OK(werr)) {
2700 goto fail;
2703 pjob_store(global_event_context(), msg_ctx, sharename, jobid, &pjob);
2705 /* Update the 'jobs added' entry used by print_queue_status. */
2706 add_to_jobs_list(pdb, jobid, "INFO/jobs_added");
2708 /* Ensure we keep a rough count of the number of total jobs... */
2709 tdb_change_int32_atomic(pdb->tdb, "INFO/total_jobs", &njobs, 1);
2711 release_print_db(pdb);
2713 *_jobid = jobid;
2714 return WERR_OK;
2716 fail:
2717 if (jobid != -1) {
2718 pjob_delete(global_event_context(), msg_ctx, sharename, jobid);
2721 release_print_db(pdb);
2723 DEBUG(3, ("print_job_start: returning fail. "
2724 "Error = %s\n", win_errstr(werr)));
2725 return werr;
2728 /****************************************************************************
2729 Update the number of pages spooled to jobid
2730 ****************************************************************************/
2732 void print_job_endpage(struct messaging_context *msg_ctx,
2733 int snum, uint32_t jobid)
2735 const char* sharename = lp_const_servicename(snum);
2736 struct printjob *pjob;
2737 TALLOC_CTX *tmp_ctx = talloc_new(msg_ctx);
2738 if (tmp_ctx == NULL) {
2739 return;
2742 pjob = print_job_find(tmp_ctx, sharename, jobid);
2743 if (!pjob) {
2744 goto err_out;
2746 /* don't allow another process to get this info - it is meaningless */
2747 if (pjob->pid != getpid()) {
2748 goto err_out;
2751 pjob->page_count++;
2752 pjob_store(global_event_context(), msg_ctx, sharename, jobid, pjob);
2753 err_out:
2754 talloc_free(tmp_ctx);
2757 /****************************************************************************
2758 Print a file - called on closing the file. This spools the job.
2759 If normal close is false then we're tearing down the jobs - treat as an
2760 error.
2761 ****************************************************************************/
2763 NTSTATUS print_job_end(struct messaging_context *msg_ctx, int snum,
2764 uint32_t jobid, enum file_close_type close_type)
2766 const char* sharename = lp_const_servicename(snum);
2767 const struct loadparm_substitution *lp_sub =
2768 loadparm_s3_global_substitution();
2769 struct printjob *pjob;
2770 int ret;
2771 SMB_STRUCT_STAT sbuf;
2772 struct printif *current_printif = get_printer_fns(snum);
2773 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
2774 char *lpq_cmd;
2775 TALLOC_CTX *tmp_ctx = talloc_new(msg_ctx);
2776 if (tmp_ctx == NULL) {
2777 return NT_STATUS_NO_MEMORY;
2780 pjob = print_job_find(tmp_ctx, sharename, jobid);
2781 if (!pjob) {
2782 status = NT_STATUS_PRINT_CANCELLED;
2783 goto err_out;
2786 if (pjob->spooled || pjob->pid != getpid()) {
2787 status = NT_STATUS_ACCESS_DENIED;
2788 goto err_out;
2791 if (close_type == NORMAL_CLOSE || close_type == SHUTDOWN_CLOSE) {
2792 if (pjob->status == PJOB_SMBD_SPOOLING) {
2793 /* take over the file now, smbd is done */
2794 if (sys_stat(pjob->filename, &sbuf, false) != 0) {
2795 status = map_nt_error_from_unix(errno);
2796 DEBUG(3, ("print_job_end: "
2797 "stat file failed for jobid %d\n",
2798 jobid));
2799 goto fail;
2802 pjob->status = LPQ_SPOOLING;
2804 } else {
2806 if ((sys_fstat(pjob->fd, &sbuf, false) != 0)) {
2807 status = map_nt_error_from_unix(errno);
2808 close(pjob->fd);
2809 DEBUG(3, ("print_job_end: "
2810 "stat file failed for jobid %d\n",
2811 jobid));
2812 goto fail;
2815 close(pjob->fd);
2818 pjob->size = sbuf.st_ex_size;
2819 } else {
2822 * Not a normal close, something has gone wrong. Cleanup.
2824 if (pjob->fd != -1) {
2825 close(pjob->fd);
2827 goto fail;
2830 /* Technically, this is not quite right. If the printer has a separator
2831 * page turned on, the NT spooler prints the separator page even if the
2832 * print job is 0 bytes. 010215 JRR */
2833 if (pjob->size == 0 || pjob->status == LPQ_DELETING) {
2834 /* don't bother spooling empty files or something being deleted. */
2835 DEBUG(5,("print_job_end: canceling spool of %s (%s)\n",
2836 pjob->filename, pjob->size ? "deleted" : "zero length" ));
2837 unlink(pjob->filename);
2838 pjob_delete(global_event_context(), msg_ctx, sharename, jobid);
2839 return NT_STATUS_OK;
2842 /* don't strip out characters like '$' from the printername */
2843 lpq_cmd = talloc_string_sub2(tmp_ctx,
2844 lp_lpq_command(snum),
2845 "%p",
2846 lp_printername(talloc_tos(), lp_sub, snum),
2847 false, false, false);
2848 if (lpq_cmd == NULL) {
2849 status = NT_STATUS_PRINT_CANCELLED;
2850 goto fail;
2852 lpq_cmd = talloc_sub_full(tmp_ctx,
2853 lp_servicename(talloc_tos(), lp_sub, snum),
2854 current_user_info.unix_name,
2856 get_current_gid(NULL),
2857 get_current_username(),
2858 get_current_user_info_domain(),
2859 lpq_cmd);
2860 if (lpq_cmd == NULL) {
2861 status = NT_STATUS_PRINT_CANCELLED;
2862 goto fail;
2865 ret = (*(current_printif->job_submit))(snum, pjob,
2866 current_printif->type, lpq_cmd);
2867 if (ret) {
2868 status = NT_STATUS_PRINT_CANCELLED;
2869 goto fail;
2872 /* The print job has been successfully handed over to the back-end */
2874 pjob->spooled = True;
2875 pjob->status = LPQ_QUEUED;
2876 pjob_store(global_event_context(), msg_ctx, sharename, jobid, pjob);
2878 /* make sure the database is up to date */
2879 if (print_cache_expired(lp_const_servicename(snum), True))
2880 print_queue_update(msg_ctx, snum, False);
2882 return NT_STATUS_OK;
2884 fail:
2886 /* The print job was not successfully started. Cleanup */
2887 /* Still need to add proper error return propagation! 010122:JRR */
2888 pjob->fd = -1;
2889 unlink(pjob->filename);
2890 pjob_delete(global_event_context(), msg_ctx, sharename, jobid);
2891 err_out:
2892 talloc_free(tmp_ctx);
2893 return status;
2896 /****************************************************************************
2897 Get a snapshot of jobs in the system without traversing.
2898 ****************************************************************************/
2900 static bool get_stored_queue_info(struct messaging_context *msg_ctx,
2901 struct tdb_print_db *pdb, int snum,
2902 int *pcount, print_queue_struct **ppqueue)
2904 const struct loadparm_substitution *lp_sub =
2905 loadparm_s3_global_substitution();
2906 TDB_DATA data, cgdata, jcdata;
2907 print_queue_struct *queue = NULL;
2908 uint32_t qcount = 0;
2909 uint32_t extra_count = 0;
2910 uint32_t changed_count = 0;
2911 int total_count = 0;
2912 size_t len = 0;
2913 uint32_t i;
2914 int max_reported_jobs = lp_max_reported_print_jobs(snum);
2915 bool ret = false;
2916 const char* sharename = lp_servicename(talloc_tos(), lp_sub, snum);
2917 TALLOC_CTX *tmp_ctx = talloc_new(msg_ctx);
2918 if (tmp_ctx == NULL) {
2919 return false;
2922 /* make sure the database is up to date */
2923 if (print_cache_expired(lp_const_servicename(snum), True))
2924 print_queue_update(msg_ctx, snum, False);
2926 *pcount = 0;
2927 *ppqueue = NULL;
2929 ZERO_STRUCT(data);
2930 ZERO_STRUCT(cgdata);
2932 /* Get the stored queue data. */
2933 data = tdb_fetch(pdb->tdb, string_tdb_data("INFO/linear_queue_array"));
2935 if (data.dptr && data.dsize >= sizeof(qcount))
2936 len += tdb_unpack(data.dptr + len, data.dsize - len, "d", &qcount);
2938 /* Get the added jobs list. */
2939 cgdata = tdb_fetch(pdb->tdb, string_tdb_data("INFO/jobs_added"));
2940 if (cgdata.dptr != NULL && (cgdata.dsize % 4 == 0))
2941 extra_count = cgdata.dsize/4;
2943 /* Get the changed jobs list. */
2944 jcdata = tdb_fetch(pdb->tdb, string_tdb_data("INFO/jobs_changed"));
2945 if (jcdata.dptr != NULL && (jcdata.dsize % 4 == 0))
2946 changed_count = jcdata.dsize / 4;
2948 DEBUG(5,("get_stored_queue_info: qcount = %u, extra_count = %u\n", (unsigned int)qcount, (unsigned int)extra_count));
2950 /* Allocate the queue size. */
2951 if (qcount == 0 && extra_count == 0)
2952 goto out;
2954 if ((queue = SMB_MALLOC_ARRAY(print_queue_struct, qcount + extra_count)) == NULL)
2955 goto out;
2957 /* Retrieve the linearised queue data. */
2959 for(i = 0; i < qcount; i++) {
2960 uint32_t qjob, qsize, qpage_count, qstatus, qpriority, qtime;
2961 len += tdb_unpack(data.dptr + len, data.dsize - len, "ddddddff",
2962 &qjob,
2963 &qsize,
2964 &qpage_count,
2965 &qstatus,
2966 &qpriority,
2967 &qtime,
2968 queue[i].fs_user,
2969 queue[i].fs_file);
2970 queue[i].sysjob = qjob;
2971 queue[i].size = qsize;
2972 queue[i].page_count = qpage_count;
2973 queue[i].status = qstatus;
2974 queue[i].priority = qpriority;
2975 queue[i].time = qtime;
2978 total_count = qcount;
2980 /* Add new jobids to the queue. */
2981 for (i = 0; i < extra_count; i++) {
2982 uint32_t jobid;
2983 struct printjob *pjob;
2985 jobid = IVAL(cgdata.dptr, i*4);
2986 DEBUG(5,("get_stored_queue_info: added job = %u\n", (unsigned int)jobid));
2987 pjob = print_job_find(tmp_ctx, lp_const_servicename(snum), jobid);
2988 if (!pjob) {
2989 DEBUG(5,("get_stored_queue_info: failed to find added job = %u\n", (unsigned int)jobid));
2990 remove_from_jobs_added(sharename, jobid);
2991 continue;
2994 queue[total_count].sysjob = pjob->sysjob;
2995 queue[total_count].size = pjob->size;
2996 queue[total_count].page_count = pjob->page_count;
2997 queue[total_count].status = pjob->status;
2998 queue[total_count].priority = 1;
2999 queue[total_count].time = pjob->starttime;
3000 fstrcpy(queue[total_count].fs_user, pjob->user);
3001 fstrcpy(queue[total_count].fs_file, pjob->jobname);
3002 total_count++;
3003 talloc_free(pjob);
3006 /* Update the changed jobids. */
3007 for (i = 0; i < changed_count; i++) {
3008 uint32_t jobid = IVAL(jcdata.dptr, i * 4);
3009 struct printjob *pjob;
3010 uint32_t j;
3011 bool found = false;
3013 pjob = print_job_find(tmp_ctx, sharename, jobid);
3014 if (pjob == NULL) {
3015 DEBUG(5,("get_stored_queue_info: failed to find "
3016 "changed job = %u\n",
3017 (unsigned int)jobid));
3018 remove_from_jobs_changed(sharename, jobid);
3019 continue;
3022 for (j = 0; j < total_count; j++) {
3023 if (queue[j].sysjob == pjob->sysjob) {
3024 found = true;
3025 break;
3029 if (found) {
3030 DEBUG(5,("get_stored_queue_info: changed job: %u\n",
3031 (unsigned int)jobid));
3033 queue[j].sysjob = pjob->sysjob;
3034 queue[j].size = pjob->size;
3035 queue[j].page_count = pjob->page_count;
3036 queue[j].status = pjob->status;
3037 queue[j].priority = 1;
3038 queue[j].time = pjob->starttime;
3039 fstrcpy(queue[j].fs_user, pjob->user);
3040 fstrcpy(queue[j].fs_file, pjob->jobname);
3041 talloc_free(pjob);
3043 DEBUG(5,("updated queue[%u], jobid: %u, sysjob: %u, "
3044 "jobname: %s\n",
3045 (unsigned int)j, (unsigned int)jobid,
3046 (unsigned int)queue[j].sysjob, pjob->jobname));
3049 remove_from_jobs_changed(sharename, jobid);
3052 /* Sort the queue by submission time otherwise they are displayed
3053 in hash order. */
3055 TYPESAFE_QSORT(queue, total_count, printjob_comp);
3057 DEBUG(5,("get_stored_queue_info: total_count = %u\n", (unsigned int)total_count));
3059 if (max_reported_jobs && total_count > max_reported_jobs)
3060 total_count = max_reported_jobs;
3062 *ppqueue = queue;
3063 *pcount = total_count;
3065 ret = true;
3067 out:
3069 SAFE_FREE(data.dptr);
3070 SAFE_FREE(cgdata.dptr);
3071 talloc_free(tmp_ctx);
3072 return ret;
3075 /****************************************************************************
3076 Get a printer queue listing.
3077 set queue = NULL and status = NULL if you just want to update the cache
3078 ****************************************************************************/
3080 int print_queue_status(struct messaging_context *msg_ctx, int snum,
3081 print_queue_struct **ppqueue,
3082 print_status_struct *status)
3084 fstring keystr;
3085 TDB_DATA data, key;
3086 const char *sharename;
3087 struct tdb_print_db *pdb;
3088 int count = 0;
3090 /* make sure the database is up to date */
3092 if (print_cache_expired(lp_const_servicename(snum), True))
3093 print_queue_update(msg_ctx, snum, False);
3095 /* return if we are done */
3096 if ( !ppqueue || !status )
3097 return 0;
3099 *ppqueue = NULL;
3100 sharename = lp_const_servicename(snum);
3101 pdb = get_print_db_byname(sharename);
3103 if (!pdb)
3104 return 0;
3107 * Fetch the queue status. We must do this first, as there may
3108 * be no jobs in the queue.
3111 ZERO_STRUCTP(status);
3112 slprintf(keystr, sizeof(keystr)-1, "STATUS/%s", sharename);
3113 key = string_tdb_data(keystr);
3115 data = tdb_fetch(pdb->tdb, key);
3116 if (data.dptr) {
3117 if (data.dsize == sizeof(*status)) {
3118 /* this memcpy is ok since the status struct was
3119 not packed before storing it in the tdb */
3120 memcpy(status, data.dptr, sizeof(*status));
3122 SAFE_FREE(data.dptr);
3126 * Now, fetch the print queue information. We first count the number
3127 * of entries, and then only retrieve the queue if necessary.
3130 if (!get_stored_queue_info(msg_ctx, pdb, snum, &count, ppqueue)) {
3131 release_print_db(pdb);
3132 return 0;
3135 release_print_db(pdb);
3136 return count;
3139 /****************************************************************************
3140 Pause a queue.
3141 ****************************************************************************/
3143 WERROR print_queue_pause(const struct auth_session_info *server_info,
3144 struct messaging_context *msg_ctx, int snum)
3146 int ret;
3147 struct printif *current_printif = get_printer_fns( snum );
3149 if (!W_ERROR_IS_OK(print_access_check(server_info, msg_ctx, snum,
3150 PRINTER_ACCESS_ADMINISTER))) {
3151 return WERR_ACCESS_DENIED;
3155 become_root();
3157 ret = (*(current_printif->queue_pause))(snum);
3159 unbecome_root();
3161 if (ret != 0) {
3162 return WERR_INVALID_PARAMETER;
3165 /* force update the database */
3166 print_cache_flush(lp_const_servicename(snum));
3168 /* Send a printer notify message */
3170 notify_printer_status(global_event_context(), msg_ctx, snum,
3171 PRINTER_STATUS_PAUSED);
3173 return WERR_OK;
3176 /****************************************************************************
3177 Resume a queue.
3178 ****************************************************************************/
3180 WERROR print_queue_resume(const struct auth_session_info *server_info,
3181 struct messaging_context *msg_ctx, int snum)
3183 int ret;
3184 struct printif *current_printif = get_printer_fns( snum );
3186 if (!W_ERROR_IS_OK(print_access_check(server_info, msg_ctx, snum,
3187 PRINTER_ACCESS_ADMINISTER))) {
3188 return WERR_ACCESS_DENIED;
3191 become_root();
3193 ret = (*(current_printif->queue_resume))(snum);
3195 unbecome_root();
3197 if (ret != 0) {
3198 return WERR_INVALID_PARAMETER;
3201 /* make sure the database is up to date */
3202 if (print_cache_expired(lp_const_servicename(snum), True))
3203 print_queue_update(msg_ctx, snum, True);
3205 /* Send a printer notify message */
3207 notify_printer_status(global_event_context(), msg_ctx, snum,
3208 PRINTER_STATUS_OK);
3210 return WERR_OK;
3213 /****************************************************************************
3214 Purge a queue - implemented by deleting all jobs that we can delete.
3215 ****************************************************************************/
3217 WERROR print_queue_purge(const struct auth_session_info *server_info,
3218 struct messaging_context *msg_ctx, int snum)
3220 print_queue_struct *queue;
3221 print_status_struct status;
3222 int njobs, i;
3223 bool can_job_admin;
3225 /* Force and update so the count is accurate (i.e. not a cached count) */
3226 print_queue_update(msg_ctx, snum, True);
3228 can_job_admin = W_ERROR_IS_OK(print_access_check(server_info,
3229 msg_ctx,
3230 snum,
3231 JOB_ACCESS_ADMINISTER));
3232 njobs = print_queue_status(msg_ctx, snum, &queue, &status);
3234 if ( can_job_admin )
3235 become_root();
3237 for (i = 0; i < njobs; i++) {
3238 struct tdb_print_db *pdb;
3239 int jobid;
3240 bool owner;
3241 pdb = get_print_db_byname(lp_const_servicename(snum));
3242 if (pdb == NULL) {
3243 DEBUG(1, ("failed to find printdb for %s\n",
3244 lp_const_servicename(snum)));
3245 continue;
3247 jobid = sysjob_to_jobid_pdb(pdb, queue[i].sysjob);
3248 if (jobid == (uint32_t)-1) {
3249 DEBUG(2, ("jobid for system job %d not found\n",
3250 queue[i].sysjob));
3251 continue; /* unix job */
3253 owner = is_owner(server_info, lp_const_servicename(snum),
3254 jobid);
3256 if (owner || can_job_admin) {
3257 print_job_delete1(global_event_context(), msg_ctx,
3258 snum, jobid);
3262 if ( can_job_admin )
3263 unbecome_root();
3265 /* update the cache */
3266 print_queue_update(msg_ctx, snum, True);
3268 SAFE_FREE(queue);
3270 return WERR_OK;