s4:kdc: split out a sdb_keys_free() helper function
[Samba.git] / source3 / printing / printing.c
blob67d798fbb214a3bc03c2a93b8399b647e51a6d49
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 "system/syslog.h"
24 #include "system/filesys.h"
25 #include "printing.h"
26 #include "../librpc/gen_ndr/ndr_spoolss.h"
27 #include "nt_printing.h"
28 #include "../librpc/gen_ndr/netlogon.h"
29 #include "printing/notify.h"
30 #include "printing/pcap.h"
31 #include "printing/printer_list.h"
32 #include "printing/queue_process.h"
33 #include "serverid.h"
34 #include "smbd/smbd.h"
35 #include "auth.h"
36 #include "messages.h"
37 #include "util_tdb.h"
38 #include "lib/param/loadparm.h"
39 #include "lib/util/sys_rw_data.h"
40 #include "lib/util/string_wrappers.h"
41 #include "lib/global_contexts.h"
42 #include "source3/printing/rap_jobid.h"
43 #include "source3/lib/substitute.h"
45 extern userdom_struct current_user_info;
47 /* Current printer interface */
48 static bool remove_from_jobs_added(const char* sharename, uint32_t jobid);
50 static int get_queue_status(const char* sharename, print_status_struct *);
52 /****************************************************************************
53 Initialise the printing backend. Called once at startup before the fork().
54 ****************************************************************************/
56 bool print_backend_init(struct messaging_context *msg_ctx)
58 const char *sversion = "INFO/version";
59 int services = lp_numservices();
60 int snum;
61 bool ok;
62 char *print_cache_path;
64 if (!printer_list_parent_init()) {
65 return false;
68 print_cache_path = cache_path(talloc_tos(), "printing");
69 if (print_cache_path == NULL) {
70 return false;
72 ok = directory_create_or_exist(print_cache_path, 0755);
73 TALLOC_FREE(print_cache_path);
74 if (!ok) {
75 return false;
78 /* handle a Samba upgrade */
80 for (snum = 0; snum < services; snum++) {
81 struct tdb_print_db *pdb;
82 if (!lp_printable(snum))
83 continue;
85 pdb = get_print_db_byname(lp_const_servicename(snum));
86 if (!pdb)
87 continue;
88 if (tdb_lock_bystring(pdb->tdb, sversion) != 0) {
89 DEBUG(0,("print_backend_init: Failed to open printer %s database\n", lp_const_servicename(snum) ));
90 release_print_db(pdb);
91 return False;
93 if (tdb_fetch_int32(pdb->tdb, sversion) != PRINT_DATABASE_VERSION) {
94 tdb_wipe_all(pdb->tdb);
95 tdb_store_int32(pdb->tdb, sversion, PRINT_DATABASE_VERSION);
97 tdb_unlock_bystring(pdb->tdb, sversion);
98 release_print_db(pdb);
101 close_all_print_db(); /* Don't leave any open. */
103 /* do NT print initialization... */
104 return nt_printing_init(msg_ctx);
107 /****************************************************************************
108 Shut down printing backend. Called once at shutdown to close the tdb.
109 ****************************************************************************/
111 void printing_end(void)
113 close_all_print_db(); /* Don't leave any open. */
116 /****************************************************************************
117 Retrieve the set of printing functions for a given service. This allows
118 us to set the printer function table based on the value of the 'printing'
119 service parameter.
121 Use the generic interface as the default and only use cups interface only
122 when asked for (and only when supported)
123 ****************************************************************************/
125 static struct printif *get_printer_fns_from_type( enum printing_types type )
127 struct printif *printer_fns = &generic_printif;
129 #ifdef HAVE_CUPS
130 if ( type == PRINT_CUPS ) {
131 printer_fns = &cups_printif;
133 #endif /* HAVE_CUPS */
135 #ifdef HAVE_IPRINT
136 if ( type == PRINT_IPRINT ) {
137 printer_fns = &iprint_printif;
139 #endif /* HAVE_IPRINT */
141 printer_fns->type = type;
143 return printer_fns;
146 static struct printif *get_printer_fns( int snum )
148 return get_printer_fns_from_type( (enum printing_types)lp_printing(snum) );
152 /****************************************************************************
153 Useful function to generate a tdb key.
154 ****************************************************************************/
156 static TDB_DATA print_key(uint32_t jobid, uint32_t *tmp)
158 TDB_DATA ret;
160 SIVAL(tmp, 0, jobid);
161 ret.dptr = (uint8_t *)tmp;
162 ret.dsize = sizeof(*tmp);
163 return ret;
166 /****************************************************************************
167 Pack the devicemode to store it in a tdb.
168 ****************************************************************************/
169 static int pack_devicemode(struct spoolss_DeviceMode *devmode, uint8_t *buf, int buflen)
171 enum ndr_err_code ndr_err;
172 DATA_BLOB blob = { .data = NULL };
173 int len = 0;
175 if (devmode) {
176 ndr_err = ndr_push_struct_blob(&blob, talloc_tos(),
177 devmode,
178 (ndr_push_flags_fn_t)
179 ndr_push_spoolss_DeviceMode);
180 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
181 DEBUG(10, ("pack_devicemode: "
182 "error encoding spoolss_DeviceMode\n"));
183 goto done;
187 len = tdb_pack(buf, buflen, "B", blob.length, blob.data);
189 if (devmode) {
190 DEBUG(8, ("Packed devicemode [%s]\n", devmode->formname));
193 done:
194 return len;
197 /****************************************************************************
198 Unpack the devicemode to store it in a tdb.
199 ****************************************************************************/
200 static int unpack_devicemode(TALLOC_CTX *mem_ctx,
201 const uint8_t *buf, int buflen,
202 struct spoolss_DeviceMode **devmode)
204 struct spoolss_DeviceMode *dm;
205 enum ndr_err_code ndr_err;
206 char *data = NULL;
207 uint32_t data_len = 0;
208 DATA_BLOB blob;
209 int len = 0;
211 *devmode = NULL;
213 len = tdb_unpack(buf, buflen, "B", &data_len, &data);
214 if (!data) {
215 return len;
218 dm = talloc_zero(mem_ctx, struct spoolss_DeviceMode);
219 if (!dm) {
220 goto done;
223 blob = data_blob_const(data, data_len);
225 ndr_err = ndr_pull_struct_blob(&blob, dm, dm,
226 (ndr_pull_flags_fn_t)ndr_pull_spoolss_DeviceMode);
227 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
228 DEBUG(10, ("unpack_devicemode: "
229 "error parsing spoolss_DeviceMode\n"));
230 goto done;
233 DEBUG(8, ("Unpacked devicemode [%s](%s)\n",
234 dm->devicename, dm->formname));
235 if (dm->driverextra_data.data) {
236 DEBUG(8, ("with a private section of %d bytes\n",
237 dm->__driverextra_length));
240 *devmode = dm;
242 done:
243 SAFE_FREE(data);
244 return len;
247 /***********************************************************************
248 unpack a pjob from a tdb buffer
249 ***********************************************************************/
251 static int unpack_pjob(TALLOC_CTX *mem_ctx, uint8_t *buf, int buflen,
252 struct printjob *pjob)
254 int len = 0;
255 int used;
256 uint32_t pjpid, pjjobid, pjsysjob, pjfd, pjstarttime, pjstatus;
257 uint32_t pjsize, pjpage_count, pjspooled, pjsmbjob;
259 if (!buf || !pjob) {
260 return -1;
263 len += tdb_unpack(buf+len, buflen-len, "ddddddddddfffff",
264 &pjpid,
265 &pjjobid,
266 &pjsysjob,
267 &pjfd,
268 &pjstarttime,
269 &pjstatus,
270 &pjsize,
271 &pjpage_count,
272 &pjspooled,
273 &pjsmbjob,
274 pjob->filename,
275 pjob->jobname,
276 pjob->user,
277 pjob->clientmachine,
278 pjob->queuename);
280 if (len == -1) {
281 return -1;
284 used = unpack_devicemode(mem_ctx, buf+len, buflen-len, &pjob->devmode);
285 if (used == -1) {
286 return -1;
289 len += used;
291 pjob->pid = pjpid;
292 pjob->jobid = pjjobid;
293 pjob->sysjob = pjsysjob;
294 pjob->fd = pjfd;
295 pjob->starttime = pjstarttime;
296 pjob->status = pjstatus;
297 pjob->size = pjsize;
298 pjob->page_count = pjpage_count;
299 pjob->spooled = pjspooled;
300 pjob->smbjob = pjsmbjob;
302 return len;
306 /****************************************************************************
307 Useful function to find a print job in the database.
308 ****************************************************************************/
310 static struct printjob *print_job_find(TALLOC_CTX *mem_ctx,
311 const char *sharename,
312 uint32_t jobid)
314 struct printjob *pjob;
315 uint32_t tmp;
316 TDB_DATA ret;
317 struct tdb_print_db *pdb = get_print_db_byname(sharename);
319 DEBUG(10,("print_job_find: looking up job %u for share %s\n",
320 (unsigned int)jobid, sharename ));
322 if (!pdb) {
323 return NULL;
326 ret = tdb_fetch(pdb->tdb, print_key(jobid, &tmp));
327 release_print_db(pdb);
329 if (!ret.dptr) {
330 DEBUG(10, ("print_job_find: failed to find jobid %u.\n",
331 jobid));
332 return NULL;
335 pjob = talloc_zero(mem_ctx, struct printjob);
336 if (pjob == NULL) {
337 goto err_out;
340 if (unpack_pjob(mem_ctx, ret.dptr, ret.dsize, pjob) == -1) {
341 DEBUG(10, ("failed to unpack jobid %u.\n", jobid));
342 talloc_free(pjob);
343 pjob = NULL;
344 goto err_out;
347 DEBUG(10,("print_job_find: returning system job %d for jobid %u.\n",
348 pjob->sysjob, jobid));
349 SMB_ASSERT(pjob->jobid == jobid);
351 err_out:
352 SAFE_FREE(ret.dptr);
353 return pjob;
356 struct job_traverse_state {
357 int sysjob;
358 uint32_t jobid;
361 /* find spoolss jobid based on sysjob */
362 static int sysjob_to_jobid_traverse_fn(TDB_CONTEXT *the_tdb, TDB_DATA key,
363 TDB_DATA data, void *private_data)
365 struct printjob *pjob;
366 struct job_traverse_state *state =
367 (struct job_traverse_state *)private_data;
369 if (!data.dptr || data.dsize == 0)
370 return 0;
372 pjob = (struct printjob *)data.dptr;
373 if (key.dsize != sizeof(uint32_t))
374 return 0;
376 if (state->sysjob == pjob->sysjob) {
377 state->jobid = pjob->jobid;
378 return 1;
381 return 0;
384 uint32_t sysjob_to_jobid_pdb(struct tdb_print_db *pdb, int sysjob)
386 struct job_traverse_state state;
388 state.sysjob = sysjob;
389 state.jobid = (uint32_t)-1;
391 tdb_traverse(pdb->tdb, sysjob_to_jobid_traverse_fn, &state);
393 return state.jobid;
396 /****************************************************************************
397 This is a *horribly expensive call as we have to iterate through all the
398 current printer tdb's. Don't do this often ! JRA.
399 ****************************************************************************/
401 uint32_t sysjob_to_jobid(int unix_jobid)
403 int services = lp_numservices();
404 int snum;
405 struct job_traverse_state state;
407 state.sysjob = unix_jobid;
408 state.jobid = (uint32_t)-1;
410 for (snum = 0; snum < services; snum++) {
411 struct tdb_print_db *pdb;
412 if (!lp_printable(snum))
413 continue;
414 pdb = get_print_db_byname(lp_const_servicename(snum));
415 if (!pdb) {
416 continue;
418 tdb_traverse(pdb->tdb, sysjob_to_jobid_traverse_fn, &state);
419 release_print_db(pdb);
420 if (state.jobid != (uint32_t)-1)
421 return state.jobid;
423 return (uint32_t)-1;
426 /* find sysjob based on spoolss jobid */
427 static int jobid_to_sysjob_traverse_fn(TDB_CONTEXT *the_tdb, TDB_DATA key,
428 TDB_DATA data, void *private_data)
430 struct printjob *pjob;
431 struct job_traverse_state *state =
432 (struct job_traverse_state *)private_data;
434 if (!data.dptr || data.dsize == 0)
435 return 0;
437 pjob = (struct printjob *)data.dptr;
438 if (key.dsize != sizeof(uint32_t))
439 return 0;
441 if (state->jobid == pjob->jobid) {
442 state->sysjob = pjob->sysjob;
443 return 1;
446 return 0;
449 int jobid_to_sysjob_pdb(struct tdb_print_db *pdb, uint32_t jobid)
451 struct job_traverse_state state;
453 state.sysjob = -1;
454 state.jobid = jobid;
456 tdb_traverse(pdb->tdb, jobid_to_sysjob_traverse_fn, &state);
458 return state.sysjob;
461 /****************************************************************************
462 Send notifications based on what has changed after a pjob_store.
463 ****************************************************************************/
465 static const struct {
466 uint32_t lpq_status;
467 uint32_t spoolss_status;
468 } lpq_to_spoolss_status_map[] = {
469 { LPQ_QUEUED, JOB_STATUS_QUEUED },
470 { LPQ_PAUSED, JOB_STATUS_PAUSED },
471 { LPQ_SPOOLING, JOB_STATUS_SPOOLING },
472 { LPQ_PRINTING, JOB_STATUS_PRINTING },
473 { LPQ_DELETING, JOB_STATUS_DELETING },
474 { LPQ_OFFLINE, JOB_STATUS_OFFLINE },
475 { LPQ_PAPEROUT, JOB_STATUS_PAPEROUT },
476 { LPQ_PRINTED, JOB_STATUS_PRINTED },
477 { LPQ_DELETED, JOB_STATUS_DELETED },
478 { LPQ_BLOCKED, JOB_STATUS_BLOCKED_DEVQ },
479 { LPQ_USER_INTERVENTION, JOB_STATUS_USER_INTERVENTION },
480 { (uint32_t)-1, 0 }
483 /* Convert a lpq status value stored in printing.tdb into the
484 appropriate win32 API constant. */
486 static uint32_t map_to_spoolss_status(uint32_t lpq_status)
488 int i = 0;
490 while (lpq_to_spoolss_status_map[i].lpq_status != -1) {
491 if (lpq_to_spoolss_status_map[i].lpq_status == lpq_status)
492 return lpq_to_spoolss_status_map[i].spoolss_status;
493 i++;
496 return 0;
499 /***************************************************************************
500 Append a jobid to a list
501 ***************************************************************************/
503 static bool add_to_jobs_list(
504 struct tdb_print_db *pdb, uint32_t jobid, const char *key)
506 uint8_t store_jobid[sizeof(uint32_t)];
507 TDB_DATA data = {
508 .dptr = store_jobid, .dsize = sizeof(store_jobid)
510 int ret;
512 SIVAL(&store_jobid, 0, jobid);
514 DBG_DEBUG("Added jobid %"PRIu32" to %s\n", jobid, key);
516 ret = tdb_append(pdb->tdb, string_tdb_data(key), data);
517 return ret == 0;
520 /***************************************************************************
521 Remove a jobid from the 'jobs changed' list.
522 ***************************************************************************/
524 static bool remove_from_jobs_list(
525 const char *keystr, const char *sharename, uint32_t jobid)
527 struct tdb_print_db *pdb = get_print_db_byname(sharename);
528 TDB_DATA data, key;
529 size_t job_count, i;
530 bool ret = False;
531 bool gotlock = False;
533 if (!pdb) {
534 return False;
537 ZERO_STRUCT(data);
539 key = string_tdb_data(keystr);
541 if (tdb_chainlock_with_timeout(pdb->tdb, key, 5) != 0)
542 goto out;
544 gotlock = True;
546 data = tdb_fetch(pdb->tdb, key);
548 if (data.dptr == NULL || data.dsize == 0 || (data.dsize % 4 != 0))
549 goto out;
551 job_count = data.dsize / 4;
552 for (i = 0; i < job_count; i++) {
553 uint32_t ch_jobid;
555 ch_jobid = IVAL(data.dptr, i*4);
556 if (ch_jobid == jobid) {
557 if (i < job_count -1 )
558 memmove(data.dptr + (i*4), data.dptr + (i*4) + 4, (job_count - i - 1)*4 );
559 data.dsize -= 4;
560 if (tdb_store(pdb->tdb, key, data, TDB_REPLACE) != 0)
561 goto out;
562 break;
566 ret = True;
567 out:
569 if (gotlock)
570 tdb_chainunlock(pdb->tdb, key);
571 SAFE_FREE(data.dptr);
572 release_print_db(pdb);
573 if (ret)
574 DBG_DEBUG("removed jobid %"PRIu32"\n", jobid);
575 else
576 DBG_DEBUG("Failed to remove jobid %"PRIu32"\n", jobid);
577 return ret;
580 static bool remove_from_jobs_changed(const char* sharename, uint32_t jobid)
582 bool ret = remove_from_jobs_list(
583 "INFO/jobs_changed", sharename, jobid);
584 return ret;
587 static void pjob_store_notify(struct tevent_context *ev,
588 struct messaging_context *msg_ctx,
589 const char* sharename, uint32_t jobid,
590 struct printjob *old_data,
591 struct printjob *new_data,
592 bool *pchanged)
594 bool new_job = false;
595 bool changed = false;
597 if (old_data == NULL) {
598 new_job = true;
601 /* ACHTUNG! Due to a bug in Samba's spoolss parsing of the
602 NOTIFY_INFO_DATA buffer, we *have* to send the job submission
603 time first or else we'll end up with potential alignment
604 errors. I don't think the systemtime should be spooled as
605 a string, but this gets us around that error.
606 --jerry (i'll feel dirty for this) */
608 if (new_job) {
609 notify_job_submitted(ev, msg_ctx,
610 sharename, jobid, new_data->starttime);
611 notify_job_username(ev, msg_ctx,
612 sharename, jobid, new_data->user);
613 notify_job_name(ev, msg_ctx,
614 sharename, jobid, new_data->jobname);
615 notify_job_status(ev, msg_ctx,
616 sharename, jobid, map_to_spoolss_status(new_data->status));
617 notify_job_total_bytes(ev, msg_ctx,
618 sharename, jobid, new_data->size);
619 notify_job_total_pages(ev, msg_ctx,
620 sharename, jobid, new_data->page_count);
621 } else {
622 if (!strequal(old_data->jobname, new_data->jobname)) {
623 notify_job_name(ev, msg_ctx, sharename,
624 jobid, new_data->jobname);
625 changed = true;
628 if (old_data->status != new_data->status) {
629 notify_job_status(ev, msg_ctx,
630 sharename, jobid,
631 map_to_spoolss_status(new_data->status));
634 if (old_data->size != new_data->size) {
635 notify_job_total_bytes(ev, msg_ctx,
636 sharename, jobid, new_data->size);
639 if (old_data->page_count != new_data->page_count) {
640 notify_job_total_pages(ev, msg_ctx,
641 sharename, jobid,
642 new_data->page_count);
646 *pchanged = changed;
649 /****************************************************************************
650 Store a job structure back to the database.
651 ****************************************************************************/
653 static bool pjob_store(struct tevent_context *ev,
654 struct messaging_context *msg_ctx,
655 const char* sharename, uint32_t jobid,
656 struct printjob *pjob)
658 uint32_t tmp;
659 TDB_DATA old_data, new_data;
660 bool ret = False;
661 struct tdb_print_db *pdb = get_print_db_byname(sharename);
662 uint8_t *buf = NULL;
663 int len, newlen, buflen;
666 if (!pdb)
667 return False;
669 /* Get old data */
671 old_data = tdb_fetch(pdb->tdb, print_key(jobid, &tmp));
673 /* Doh! Now we have to pack/unpack data since the NT_DEVICEMODE was added */
675 newlen = 0;
677 do {
678 len = 0;
679 buflen = newlen;
680 len += tdb_pack(buf+len, buflen-len, "ddddddddddfffff",
681 (uint32_t)pjob->pid,
682 (uint32_t)pjob->jobid,
683 (uint32_t)pjob->sysjob,
684 (uint32_t)pjob->fd,
685 (uint32_t)pjob->starttime,
686 (uint32_t)pjob->status,
687 (uint32_t)pjob->size,
688 (uint32_t)pjob->page_count,
689 (uint32_t)pjob->spooled,
690 (uint32_t)pjob->smbjob,
691 pjob->filename,
692 pjob->jobname,
693 pjob->user,
694 pjob->clientmachine,
695 pjob->queuename);
697 len += pack_devicemode(pjob->devmode, buf+len, buflen-len);
699 if (buflen != len) {
700 buf = (uint8_t *)SMB_REALLOC(buf, len);
701 if (!buf) {
702 DEBUG(0,("pjob_store: failed to enlarge buffer!\n"));
703 goto done;
705 newlen = len;
707 } while ( buflen != len );
710 /* Store new data */
712 new_data.dptr = buf;
713 new_data.dsize = len;
714 ret = (tdb_store(pdb->tdb, print_key(jobid, &tmp), new_data,
715 TDB_REPLACE) == 0);
717 /* Send notify updates for what has changed */
719 if (ret) {
720 bool changed = false;
721 struct printjob old_pjob;
723 if (old_data.dsize) {
724 TALLOC_CTX *tmp_ctx = talloc_new(ev);
725 if (tmp_ctx == NULL)
726 goto done;
728 len = unpack_pjob(tmp_ctx, old_data.dptr,
729 old_data.dsize, &old_pjob);
730 if (len != -1 ) {
731 pjob_store_notify(ev,
732 msg_ctx,
733 sharename, jobid, &old_pjob,
734 pjob,
735 &changed);
736 if (changed) {
737 add_to_jobs_list(
738 pdb,
739 jobid,
740 "INFO/jobs_changed");
743 talloc_free(tmp_ctx);
745 } else {
746 /* new job */
747 pjob_store_notify(ev, msg_ctx,
748 sharename, jobid, NULL, pjob,
749 &changed);
753 done:
754 release_print_db(pdb);
755 SAFE_FREE( old_data.dptr );
756 SAFE_FREE( buf );
758 return ret;
761 /****************************************************************************
762 Remove a job structure from the database.
763 ****************************************************************************/
765 static void pjob_delete(struct tevent_context *ev,
766 struct messaging_context *msg_ctx,
767 const char* sharename, uint32_t jobid)
769 uint32_t tmp;
770 struct printjob *pjob;
771 uint32_t job_status = 0;
772 struct tdb_print_db *pdb;
773 TALLOC_CTX *tmp_ctx = talloc_new(ev);
774 if (tmp_ctx == NULL) {
775 return;
778 pdb = get_print_db_byname(sharename);
779 if (!pdb) {
780 goto err_out;
783 pjob = print_job_find(tmp_ctx, sharename, jobid);
784 if (!pjob) {
785 DEBUG(5, ("we were asked to delete nonexistent job %u\n",
786 jobid));
787 goto err_release;
790 /* We must cycle through JOB_STATUS_DELETING and
791 JOB_STATUS_DELETED for the port monitor to delete the job
792 properly. */
794 job_status = JOB_STATUS_DELETING|JOB_STATUS_DELETED;
795 notify_job_status(ev, msg_ctx, sharename, jobid, job_status);
797 /* Remove from printing.tdb */
799 tdb_delete(pdb->tdb, print_key(jobid, &tmp));
800 remove_from_jobs_added(sharename, jobid);
801 rap_jobid_delete(sharename, jobid);
802 err_release:
803 release_print_db(pdb);
804 err_out:
805 talloc_free(tmp_ctx);
808 /****************************************************************************
809 List a unix job in the print database.
810 ****************************************************************************/
812 static void print_unix_job(struct tevent_context *ev,
813 struct messaging_context *msg_ctx,
814 const char *sharename, print_queue_struct *q,
815 uint32_t jobid)
817 struct printjob pj, *old_pj;
818 TALLOC_CTX *tmp_ctx = talloc_new(ev);
819 if (tmp_ctx == NULL) {
820 return;
823 if (jobid == (uint32_t)-1) {
824 jobid = q->sysjob + UNIX_JOB_START;
827 /* Preserve the timestamp on an existing unix print job */
829 old_pj = print_job_find(tmp_ctx, sharename, jobid);
831 ZERO_STRUCT(pj);
833 pj.pid = (pid_t)-1;
834 pj.jobid = jobid;
835 pj.sysjob = q->sysjob;
836 pj.fd = -1;
837 pj.starttime = old_pj ? old_pj->starttime : q->time;
838 pj.status = q->status;
839 pj.size = q->size;
840 pj.spooled = True;
841 fstrcpy(pj.filename, old_pj ? old_pj->filename : "");
842 if (jobid < UNIX_JOB_START) {
843 pj.smbjob = True;
844 fstrcpy(pj.jobname, old_pj ? old_pj->jobname : "Remote Downlevel Document");
845 } else {
846 pj.smbjob = False;
847 fstrcpy(pj.jobname, old_pj ? old_pj->jobname : q->fs_file);
849 fstrcpy(pj.user, old_pj ? old_pj->user : q->fs_user);
850 fstrcpy(pj.queuename, old_pj ? old_pj->queuename : sharename );
852 pjob_store(ev, msg_ctx, sharename, jobid, &pj);
853 talloc_free(tmp_ctx);
857 struct traverse_struct {
858 print_queue_struct *queue;
859 size_t qcount, snum, maxcount, total_jobs;
860 const char *sharename;
861 time_t lpq_time;
862 const char *lprm_command;
863 struct printif *print_if;
864 struct tevent_context *ev;
865 struct messaging_context *msg_ctx;
866 TALLOC_CTX *mem_ctx;
869 /****************************************************************************
870 Utility fn to delete any jobs that are no longer active.
871 ****************************************************************************/
873 static int traverse_fn_delete(TDB_CONTEXT *t, TDB_DATA key, TDB_DATA data, void *state)
875 struct traverse_struct *ts = (struct traverse_struct *)state;
876 struct printjob pjob;
877 uint32_t jobid;
878 size_t i = 0;
880 if ( key.dsize != sizeof(jobid) )
881 return 0;
883 if (unpack_pjob(ts->mem_ctx, data.dptr, data.dsize, &pjob) == -1)
884 return 0;
885 talloc_free(pjob.devmode);
886 jobid = pjob.jobid;
888 if (!pjob.smbjob) {
889 /* remove a unix job if it isn't in the system queue any more */
890 for (i=0;i<ts->qcount;i++) {
891 if (ts->queue[i].sysjob == pjob.sysjob) {
892 break;
895 if (i == ts->qcount) {
896 DEBUG(10,("traverse_fn_delete: pjob %u deleted due to !smbjob\n",
897 (unsigned int)jobid ));
898 pjob_delete(ts->ev, ts->msg_ctx,
899 ts->sharename, jobid);
900 return 0;
903 /* need to continue the the bottom of the function to
904 save the correct attributes */
907 /* maybe it hasn't been spooled yet */
908 if (!pjob.spooled) {
909 /* if a job is not spooled and the process doesn't
910 exist then kill it. This cleans up after smbd
911 deaths */
912 if (!process_exists_by_pid(pjob.pid)) {
913 DEBUG(10,("traverse_fn_delete: pjob %u deleted due to !process_exists (%u)\n",
914 (unsigned int)jobid, (unsigned int)pjob.pid ));
915 pjob_delete(ts->ev, ts->msg_ctx,
916 ts->sharename, jobid);
917 } else
918 ts->total_jobs++;
919 return 0;
922 /* this check only makes sense for jobs submitted from Windows clients */
924 if (pjob.smbjob) {
925 for (i=0;i<ts->qcount;i++) {
926 if ( pjob.status == LPQ_DELETED )
927 continue;
929 if (ts->queue[i].sysjob == pjob.sysjob) {
931 /* try to clean up any jobs that need to be deleted */
933 if ( pjob.status == LPQ_DELETING ) {
934 int result;
936 result = (*(ts->print_if->job_delete))(
937 ts->sharename, ts->lprm_command, &pjob );
939 if ( result != 0 ) {
940 /* if we can't delete, then reset the job status */
941 pjob.status = LPQ_QUEUED;
942 pjob_store(ts->ev, ts->msg_ctx,
943 ts->sharename, jobid, &pjob);
945 else {
946 /* if we deleted the job, the remove the tdb record */
947 pjob_delete(ts->ev,
948 ts->msg_ctx,
949 ts->sharename, jobid);
950 pjob.status = LPQ_DELETED;
955 break;
960 /* The job isn't in the system queue - we have to assume it has
961 completed, so delete the database entry. */
963 if (i == ts->qcount) {
965 /* A race can occur between the time a job is spooled and
966 when it appears in the lpq output. This happens when
967 the job is added to printing.tdb when another smbd
968 running print_queue_update() has completed a lpq and
969 is currently traversing the printing tdb and deleting jobs.
970 Don't delete the job if it was submitted after the lpq_time. */
972 if (pjob.starttime < ts->lpq_time) {
973 DEBUG(10,("traverse_fn_delete: pjob %u deleted due to pjob.starttime (%u) < ts->lpq_time (%u)\n",
974 (unsigned int)jobid,
975 (unsigned int)pjob.starttime,
976 (unsigned int)ts->lpq_time ));
977 pjob_delete(ts->ev, ts->msg_ctx,
978 ts->sharename, jobid);
979 } else
980 ts->total_jobs++;
981 return 0;
984 /* Save the pjob attributes we will store. */
985 ts->queue[i].sysjob = pjob.sysjob;
986 ts->queue[i].size = pjob.size;
987 ts->queue[i].page_count = pjob.page_count;
988 ts->queue[i].status = pjob.status;
989 ts->queue[i].priority = 1;
990 ts->queue[i].time = pjob.starttime;
991 fstrcpy(ts->queue[i].fs_user, pjob.user);
992 fstrcpy(ts->queue[i].fs_file, pjob.jobname);
994 ts->total_jobs++;
996 return 0;
999 /****************************************************************************
1000 Check if the print queue has been updated recently enough.
1001 ****************************************************************************/
1003 static void print_cache_flush(const char *sharename)
1005 fstring key;
1006 struct tdb_print_db *pdb = get_print_db_byname(sharename);
1008 if (!pdb)
1009 return;
1010 slprintf(key, sizeof(key)-1, "CACHE/%s", sharename);
1011 tdb_store_int32(pdb->tdb, key, -1);
1012 release_print_db(pdb);
1015 /****************************************************************************
1016 Check if someone already thinks they are doing the update.
1017 ****************************************************************************/
1019 static pid_t get_updating_pid(const char *sharename)
1021 fstring keystr;
1022 TDB_DATA data, key;
1023 pid_t updating_pid;
1024 struct tdb_print_db *pdb = get_print_db_byname(sharename);
1026 if (!pdb)
1027 return (pid_t)-1;
1028 slprintf(keystr, sizeof(keystr)-1, "UPDATING/%s", sharename);
1029 key = string_tdb_data(keystr);
1031 data = tdb_fetch(pdb->tdb, key);
1032 release_print_db(pdb);
1033 if (!data.dptr || data.dsize != sizeof(pid_t)) {
1034 SAFE_FREE(data.dptr);
1035 return (pid_t)-1;
1038 updating_pid = IVAL(data.dptr, 0);
1039 SAFE_FREE(data.dptr);
1041 if (process_exists_by_pid(updating_pid))
1042 return updating_pid;
1044 return (pid_t)-1;
1047 /****************************************************************************
1048 Set the fact that we're doing the update, or have finished doing the update
1049 in the tdb.
1050 ****************************************************************************/
1052 static void set_updating_pid(const fstring sharename, bool updating)
1054 fstring keystr;
1055 TDB_DATA key;
1056 TDB_DATA data;
1057 pid_t updating_pid = getpid();
1058 uint8_t buffer[4];
1060 struct tdb_print_db *pdb = get_print_db_byname(sharename);
1062 if (!pdb)
1063 return;
1065 slprintf(keystr, sizeof(keystr)-1, "UPDATING/%s", sharename);
1066 key = string_tdb_data(keystr);
1068 DEBUG(5, ("set_updating_pid: %supdating lpq cache for print share %s\n",
1069 updating ? "" : "not ",
1070 sharename ));
1072 if ( !updating ) {
1073 tdb_delete(pdb->tdb, key);
1074 release_print_db(pdb);
1075 return;
1078 SIVAL( buffer, 0, updating_pid);
1079 data.dptr = buffer;
1080 data.dsize = 4; /* we always assume this is a 4 byte value */
1082 tdb_store(pdb->tdb, key, data, TDB_REPLACE);
1083 release_print_db(pdb);
1086 /****************************************************************************
1087 Sort print jobs by submittal time.
1088 ****************************************************************************/
1090 static int printjob_comp(print_queue_struct *j1, print_queue_struct *j2)
1092 /* Silly cases */
1094 if (!j1 && !j2)
1095 return 0;
1096 if (!j1)
1097 return -1;
1098 if (!j2)
1099 return 1;
1101 /* Sort on job start time */
1103 if (j1->time == j2->time)
1104 return 0;
1105 return (j1->time > j2->time) ? 1 : -1;
1108 /****************************************************************************
1109 Store the sorted queue representation for later portmon retrieval.
1110 Skip deleted jobs
1111 ****************************************************************************/
1113 static void store_queue_struct(struct tdb_print_db *pdb, struct traverse_struct *pts)
1115 TDB_DATA data;
1116 int max_reported_jobs = lp_max_reported_print_jobs(pts->snum);
1117 print_queue_struct *queue = pts->queue;
1118 size_t len;
1119 size_t i;
1120 unsigned int qcount;
1122 if (max_reported_jobs && (max_reported_jobs < pts->qcount))
1123 pts->qcount = max_reported_jobs;
1124 qcount = 0;
1126 /* Work out the size. */
1127 data.dsize = 0;
1128 data.dsize += tdb_pack(NULL, 0, "d", qcount);
1130 for (i = 0; i < pts->qcount; i++) {
1131 if ( queue[i].status == LPQ_DELETED )
1132 continue;
1134 qcount++;
1135 data.dsize += tdb_pack(NULL, 0, "ddddddff",
1136 (uint32_t)queue[i].sysjob,
1137 (uint32_t)queue[i].size,
1138 (uint32_t)queue[i].page_count,
1139 (uint32_t)queue[i].status,
1140 (uint32_t)queue[i].priority,
1141 (uint32_t)queue[i].time,
1142 queue[i].fs_user,
1143 queue[i].fs_file);
1146 if ((data.dptr = (uint8_t *)SMB_MALLOC(data.dsize)) == NULL)
1147 return;
1149 len = 0;
1150 len += tdb_pack(data.dptr + len, data.dsize - len, "d", qcount);
1151 for (i = 0; i < pts->qcount; i++) {
1152 if ( queue[i].status == LPQ_DELETED )
1153 continue;
1155 len += tdb_pack(data.dptr + len, data.dsize - len, "ddddddff",
1156 (uint32_t)queue[i].sysjob,
1157 (uint32_t)queue[i].size,
1158 (uint32_t)queue[i].page_count,
1159 (uint32_t)queue[i].status,
1160 (uint32_t)queue[i].priority,
1161 (uint32_t)queue[i].time,
1162 queue[i].fs_user,
1163 queue[i].fs_file);
1166 tdb_store(pdb->tdb, string_tdb_data("INFO/linear_queue_array"), data,
1167 TDB_REPLACE);
1168 SAFE_FREE(data.dptr);
1169 return;
1172 static TDB_DATA get_jobs_added_data(struct tdb_print_db *pdb)
1174 TDB_DATA data;
1176 ZERO_STRUCT(data);
1178 data = tdb_fetch(pdb->tdb, string_tdb_data("INFO/jobs_added"));
1179 if (data.dptr == NULL || data.dsize == 0 || (data.dsize % 4 != 0)) {
1180 SAFE_FREE(data.dptr);
1181 ZERO_STRUCT(data);
1184 return data;
1187 static void check_job_added(const char *sharename, TDB_DATA data, uint32_t jobid)
1189 unsigned int i;
1190 unsigned int job_count = data.dsize / 4;
1192 for (i = 0; i < job_count; i++) {
1193 uint32_t ch_jobid;
1195 ch_jobid = IVAL(data.dptr, i*4);
1196 if (ch_jobid == jobid)
1197 remove_from_jobs_added(sharename, jobid);
1201 /****************************************************************************
1202 Check if the print queue has been updated recently enough.
1203 ****************************************************************************/
1205 static bool print_cache_expired(const char *sharename, bool check_pending)
1207 fstring key;
1208 time_t last_qscan_time, time_now = time(NULL);
1209 struct tdb_print_db *pdb = get_print_db_byname(sharename);
1210 bool result = False;
1212 if (!pdb)
1213 return False;
1215 snprintf(key, sizeof(key), "CACHE/%s", sharename);
1216 last_qscan_time = (time_t)tdb_fetch_int32(pdb->tdb, key);
1219 * Invalidate the queue for 3 reasons.
1220 * (1). last queue scan time == -1.
1221 * (2). Current time - last queue scan time > allowed cache time.
1222 * (3). last queue scan time > current time + MAX_CACHE_VALID_TIME (1 hour by default).
1223 * This last test picks up machines for which the clock has been moved
1224 * forward, an lpq scan done and then the clock moved back. Otherwise
1225 * that last lpq scan would stay around for a loooong loooong time... :-). JRA.
1228 if (last_qscan_time == ((time_t)-1)
1229 || (time_now - last_qscan_time) >= lp_lpq_cache_time()
1230 || last_qscan_time > (time_now + MAX_CACHE_VALID_TIME))
1232 uint32_t u;
1233 time_t msg_pending_time;
1235 DEBUG(4, ("print_cache_expired: cache expired for queue %s "
1236 "(last_qscan_time = %d, time now = %d, qcachetime = %d)\n",
1237 sharename, (int)last_qscan_time, (int)time_now,
1238 (int)lp_lpq_cache_time() ));
1240 /* check if another smbd has already sent a message to update the
1241 queue. Give the pending message one minute to clear and
1242 then send another message anyways. Make sure to check for
1243 clocks that have been run forward and then back again. */
1245 snprintf(key, sizeof(key), "MSG_PENDING/%s", sharename);
1247 if ( check_pending
1248 && tdb_fetch_uint32( pdb->tdb, key, &u )
1249 && (msg_pending_time=u) > 0
1250 && msg_pending_time <= time_now
1251 && (time_now - msg_pending_time) < 60 )
1253 DEBUG(4,("print_cache_expired: message already pending for %s. Accepting cache\n",
1254 sharename));
1255 goto done;
1258 result = True;
1261 done:
1262 release_print_db(pdb);
1263 return result;
1266 /****************************************************************************
1267 main work for updating the lpq cache for a printer queue
1268 ****************************************************************************/
1270 static void print_queue_update_internal(struct tevent_context *ev,
1271 struct messaging_context *msg_ctx,
1272 const char *sharename,
1273 struct printif *current_printif,
1274 char *lpq_command, char *lprm_command)
1276 size_t i, qcount;
1277 print_queue_struct *queue = NULL;
1278 print_status_struct status;
1279 print_status_struct old_status;
1280 struct printjob *pjob;
1281 struct traverse_struct tstruct;
1282 TDB_DATA data, key;
1283 TDB_DATA jcdata;
1284 fstring keystr, cachestr;
1285 struct tdb_print_db *pdb = get_print_db_byname(sharename);
1286 TALLOC_CTX *tmp_ctx = talloc_new(ev);
1288 if ((pdb == NULL) || (tmp_ctx == NULL)) {
1289 return;
1292 DEBUG(5,("print_queue_update_internal: printer = %s, type = %d, lpq command = [%s]\n",
1293 sharename, current_printif->type, lpq_command));
1296 * Update the cache time FIRST ! Stops others even
1297 * attempting to get the lock and doing this
1298 * if the lpq takes a long time.
1301 slprintf(cachestr, sizeof(cachestr)-1, "CACHE/%s", sharename);
1302 tdb_store_int32(pdb->tdb, cachestr, (int)time(NULL));
1304 /* get the current queue using the appropriate interface */
1305 ZERO_STRUCT(status);
1307 qcount = (*(current_printif->queue_get))(sharename,
1308 current_printif->type,
1309 lpq_command, &queue, &status);
1311 DBG_NOTICE("%zu job%s in queue for %s\n",
1312 qcount,
1313 (qcount != 1) ? "s" : "",
1314 sharename);
1316 /* Sort the queue by submission time otherwise they are displayed
1317 in hash order. */
1319 TYPESAFE_QSORT(queue, qcount, printjob_comp);
1322 any job in the internal database that is marked as spooled
1323 and doesn't exist in the system queue is considered finished
1324 and removed from the database
1326 any job in the system database but not in the internal database
1327 is added as a unix job
1329 fill in any system job numbers as we go
1331 jcdata = get_jobs_added_data(pdb);
1333 for (i=0; i<qcount; i++) {
1334 uint32_t jobid = sysjob_to_jobid_pdb(pdb, queue[i].sysjob);
1335 if (jobid == (uint32_t)-1) {
1336 /* assume its a unix print job */
1337 print_unix_job(ev, msg_ctx,
1338 sharename, &queue[i], jobid);
1339 continue;
1342 /* we have an active SMB print job - update its status */
1343 pjob = print_job_find(tmp_ctx, sharename, jobid);
1344 if (!pjob) {
1345 /* err, somethings wrong. Probably smbd was restarted
1346 with jobs in the queue. All we can do is treat them
1347 like unix jobs. Pity. */
1348 DEBUG(1, ("queued print job %d not found in jobs list, "
1349 "assuming unix job\n", jobid));
1350 print_unix_job(ev, msg_ctx,
1351 sharename, &queue[i], jobid);
1352 continue;
1355 /* don't reset the status on jobs to be deleted */
1357 if ( pjob->status != LPQ_DELETING )
1358 pjob->status = queue[i].status;
1360 pjob_store(ev, msg_ctx, sharename, jobid, pjob);
1362 check_job_added(sharename, jcdata, jobid);
1365 SAFE_FREE(jcdata.dptr);
1367 /* now delete any queued entries that don't appear in the
1368 system queue */
1369 tstruct.queue = queue;
1370 tstruct.qcount = qcount;
1371 tstruct.snum = -1;
1372 tstruct.total_jobs = 0;
1373 tstruct.lpq_time = time(NULL);
1374 tstruct.sharename = sharename;
1375 tstruct.lprm_command = lprm_command;
1376 tstruct.print_if = current_printif;
1377 tstruct.ev = ev;
1378 tstruct.msg_ctx = msg_ctx;
1379 tstruct.mem_ctx = tmp_ctx;
1381 tdb_traverse(pdb->tdb, traverse_fn_delete, (void *)&tstruct);
1383 /* Store the linearised queue, max jobs only. */
1384 store_queue_struct(pdb, &tstruct);
1386 SAFE_FREE(tstruct.queue);
1387 talloc_free(tmp_ctx);
1389 DBG_DEBUG("printer %s INFO, total_jobs = %zu\n",
1390 sharename,
1391 tstruct.total_jobs);
1393 tdb_store_int32(pdb->tdb, "INFO/total_jobs", tstruct.total_jobs);
1395 get_queue_status(sharename, &old_status);
1396 if (old_status.qcount != qcount) {
1397 DBG_DEBUG("Queue status change %zu jobs -> %zu jobs "
1398 "for printer %s\n",
1399 old_status.qcount,
1400 qcount,
1401 sharename);
1404 /* store the new queue status structure */
1405 slprintf(keystr, sizeof(keystr)-1, "STATUS/%s", sharename);
1406 key = string_tdb_data(keystr);
1408 status.qcount = qcount;
1409 data.dptr = (uint8_t *)&status;
1410 data.dsize = sizeof(status);
1411 tdb_store(pdb->tdb, key, data, TDB_REPLACE);
1414 * Update the cache time again. We want to do this call
1415 * as little as possible...
1418 slprintf(keystr, sizeof(keystr)-1, "CACHE/%s", sharename);
1419 tdb_store_int32(pdb->tdb, keystr, (int32_t)time(NULL));
1421 /* clear the msg pending record for this queue */
1423 snprintf(keystr, sizeof(keystr), "MSG_PENDING/%s", sharename);
1425 if ( !tdb_store_uint32( pdb->tdb, keystr, 0 ) ) {
1426 /* log a message but continue on */
1428 DEBUG(0,("print_queue_update: failed to store MSG_PENDING flag for [%s]!\n",
1429 sharename));
1432 release_print_db( pdb );
1434 return;
1437 /****************************************************************************
1438 Update the internal database from the system print queue for a queue.
1439 obtain a lock on the print queue before proceeding (needed when mutiple
1440 smbd processes maytry to update the lpq cache concurrently).
1441 ****************************************************************************/
1443 static void print_queue_update_with_lock( struct tevent_context *ev,
1444 struct messaging_context *msg_ctx,
1445 const char *sharename,
1446 struct printif *current_printif,
1447 char *lpq_command, char *lprm_command )
1449 fstring keystr;
1450 struct tdb_print_db *pdb;
1452 DEBUG(5,("print_queue_update_with_lock: printer share = %s\n", sharename));
1453 pdb = get_print_db_byname(sharename);
1454 if (!pdb)
1455 return;
1457 if ( !print_cache_expired(sharename, False) ) {
1458 DEBUG(5,("print_queue_update_with_lock: print cache for %s is still ok\n", sharename));
1459 release_print_db(pdb);
1460 return;
1464 * Check to see if someone else is doing this update.
1465 * This is essentially a mutex on the update.
1468 if (get_updating_pid(sharename) != -1) {
1469 release_print_db(pdb);
1470 return;
1473 /* Lock the queue for the database update */
1475 slprintf(keystr, sizeof(keystr) - 1, "LOCK/%s", sharename);
1476 /* Only wait 10 seconds for this. */
1477 if (tdb_lock_bystring_with_timeout(pdb->tdb, keystr, 10) != 0) {
1478 DEBUG(0,("print_queue_update_with_lock: Failed to lock printer %s database\n", sharename));
1479 release_print_db(pdb);
1480 return;
1484 * Ensure that no one else got in here.
1485 * If the updating pid is still -1 then we are
1486 * the winner.
1489 if (get_updating_pid(sharename) != -1) {
1491 * Someone else is doing the update, exit.
1493 tdb_unlock_bystring(pdb->tdb, keystr);
1494 release_print_db(pdb);
1495 return;
1499 * We're going to do the update ourselves.
1502 /* Tell others we're doing the update. */
1503 set_updating_pid(sharename, True);
1506 * Allow others to enter and notice we're doing
1507 * the update.
1510 tdb_unlock_bystring(pdb->tdb, keystr);
1512 /* do the main work now */
1514 print_queue_update_internal(ev, msg_ctx,
1515 sharename, current_printif,
1516 lpq_command, lprm_command);
1518 /* Delete our pid from the db. */
1519 set_updating_pid(sharename, False);
1520 release_print_db(pdb);
1523 /****************************************************************************
1524 this is the receive function of the background lpq updater
1525 ****************************************************************************/
1526 void print_queue_receive(struct messaging_context *msg,
1527 void *private_data,
1528 uint32_t msg_type,
1529 struct server_id server_id,
1530 DATA_BLOB *data)
1532 fstring sharename;
1533 char *lpqcommand = NULL, *lprmcommand = NULL;
1534 int printing_type;
1535 size_t len;
1537 len = tdb_unpack( (uint8_t *)data->data, data->length, "fdPP",
1538 sharename,
1539 &printing_type,
1540 &lpqcommand,
1541 &lprmcommand );
1543 if ( len == -1 ) {
1544 SAFE_FREE(lpqcommand);
1545 SAFE_FREE(lprmcommand);
1546 DEBUG(0,("print_queue_receive: Got invalid print queue update message\n"));
1547 return;
1550 print_queue_update_with_lock(global_event_context(), msg, sharename,
1551 get_printer_fns_from_type((enum printing_types)printing_type),
1552 lpqcommand, lprmcommand );
1554 SAFE_FREE(lpqcommand);
1555 SAFE_FREE(lprmcommand);
1556 return;
1559 /****************************************************************************
1560 update the internal database from the system print queue for a queue
1561 ****************************************************************************/
1563 static void print_queue_update(struct messaging_context *msg_ctx,
1564 int snum, bool force)
1566 char key[268];
1567 fstring sharename;
1568 char *lpqcommand = NULL;
1569 char *lprmcommand = NULL;
1570 uint8_t *buffer = NULL;
1571 size_t len = 0;
1572 size_t newlen;
1573 struct tdb_print_db *pdb;
1574 int type;
1575 struct printif *current_printif;
1576 TALLOC_CTX *ctx = talloc_tos();
1577 const struct loadparm_substitution *lp_sub =
1578 loadparm_s3_global_substitution();
1580 fstrcpy( sharename, lp_const_servicename(snum));
1582 /* don't strip out characters like '$' from the printername */
1584 lpqcommand = talloc_string_sub2(ctx,
1585 lp_lpq_command(snum),
1586 "%p",
1587 lp_printername(talloc_tos(), lp_sub, snum),
1588 false, false, false);
1589 if (!lpqcommand) {
1590 return;
1592 lpqcommand = talloc_sub_full(ctx,
1593 lp_servicename(talloc_tos(), lp_sub, snum),
1594 current_user_info.unix_name,
1596 get_current_gid(NULL),
1597 get_current_username(),
1598 current_user_info.domain,
1599 lpqcommand);
1600 if (!lpqcommand) {
1601 return;
1604 lprmcommand = talloc_string_sub2(ctx,
1605 lp_lprm_command(snum),
1606 "%p",
1607 lp_printername(talloc_tos(), lp_sub, snum),
1608 false, false, false);
1609 if (!lprmcommand) {
1610 return;
1612 lprmcommand = talloc_sub_full(ctx,
1613 lp_servicename(talloc_tos(), lp_sub, snum),
1614 current_user_info.unix_name,
1616 get_current_gid(NULL),
1617 get_current_username(),
1618 current_user_info.domain,
1619 lprmcommand);
1620 if (!lprmcommand) {
1621 return;
1625 * Make sure that the background queue process exists.
1626 * Otherwise just do the update ourselves
1629 if ( force || background_lpq_updater_pid == -1 ) {
1630 DEBUG(4,("print_queue_update: updating queue [%s] myself\n", sharename));
1631 current_printif = get_printer_fns( snum );
1632 print_queue_update_with_lock(global_event_context(), msg_ctx,
1633 sharename, current_printif,
1634 lpqcommand, lprmcommand);
1636 return;
1639 type = lp_printing(snum);
1641 /* get the length */
1643 len = tdb_pack( NULL, 0, "fdPP",
1644 sharename,
1645 type,
1646 lpqcommand,
1647 lprmcommand );
1649 buffer = SMB_XMALLOC_ARRAY( uint8_t, len );
1651 /* now pack the buffer */
1652 newlen = tdb_pack( buffer, len, "fdPP",
1653 sharename,
1654 type,
1655 lpqcommand,
1656 lprmcommand );
1658 SMB_ASSERT( newlen == len );
1660 DEBUG(10,("print_queue_update: Sending message -> printer = %s, "
1661 "type = %d, lpq command = [%s] lprm command = [%s]\n",
1662 sharename, type, lpqcommand, lprmcommand ));
1664 /* here we set a msg pending record for other smbd processes
1665 to throttle the number of duplicate print_queue_update msgs
1666 sent. */
1668 pdb = get_print_db_byname(sharename);
1669 if (!pdb) {
1670 SAFE_FREE(buffer);
1671 return;
1674 snprintf(key, sizeof(key), "MSG_PENDING/%s", sharename);
1676 if ( !tdb_store_uint32( pdb->tdb, key, time(NULL) ) ) {
1677 /* log a message but continue on */
1679 DEBUG(0,("print_queue_update: failed to store MSG_PENDING flag for [%s]!\n",
1680 sharename));
1683 release_print_db( pdb );
1685 /* finally send the message */
1687 send_to_bgqd(msg_ctx, MSG_PRINTER_UPDATE, (uint8_t *)buffer, len);
1689 SAFE_FREE( buffer );
1691 return;
1694 /****************************************************************************
1695 Create/Update an entry in the print tdb that will allow us to send notify
1696 updates only to interested smbd's.
1697 ****************************************************************************/
1699 bool print_notify_register_pid(int snum)
1701 TDB_DATA data;
1702 struct tdb_print_db *pdb = NULL;
1703 TDB_CONTEXT *tdb = NULL;
1704 const char *printername;
1705 uint32_t mypid = (uint32_t)getpid();
1706 bool ret = False;
1707 size_t i;
1709 /* if (snum == -1), then the change notify request was
1710 on a print server handle and we need to register on
1711 all print queus */
1713 if (snum == -1)
1715 int num_services = lp_numservices();
1716 int idx;
1718 for ( idx=0; idx<num_services; idx++ ) {
1719 if (lp_snum_ok(idx) && lp_printable(idx) )
1720 print_notify_register_pid(idx);
1723 return True;
1725 else /* register for a specific printer */
1727 printername = lp_const_servicename(snum);
1728 pdb = get_print_db_byname(printername);
1729 if (!pdb)
1730 return False;
1731 tdb = pdb->tdb;
1734 if (tdb_lock_bystring_with_timeout(tdb, NOTIFY_PID_LIST_KEY, 10) != 0) {
1735 DEBUG(0,("print_notify_register_pid: Failed to lock printer %s\n",
1736 printername));
1737 if (pdb)
1738 release_print_db(pdb);
1739 return False;
1742 data = get_printer_notify_pid_list( tdb, printername, True );
1744 /* Add ourselves and increase the refcount. */
1746 for (i = 0; i < data.dsize; i += 8) {
1747 if (IVAL(data.dptr,i) == mypid) {
1748 uint32_t new_refcount = IVAL(data.dptr, i+4) + 1;
1749 SIVAL(data.dptr, i+4, new_refcount);
1750 break;
1754 if (i == data.dsize) {
1755 /* We weren't in the list. Realloc. */
1756 data.dptr = (uint8_t *)SMB_REALLOC(data.dptr, data.dsize + 8);
1757 if (!data.dptr) {
1758 DEBUG(0,("print_notify_register_pid: Relloc fail for printer %s\n",
1759 printername));
1760 goto done;
1762 data.dsize += 8;
1763 SIVAL(data.dptr,data.dsize - 8,mypid);
1764 SIVAL(data.dptr,data.dsize - 4,1); /* Refcount. */
1767 /* Store back the record. */
1768 if (tdb_store_bystring(tdb, NOTIFY_PID_LIST_KEY, data, TDB_REPLACE) != 0) {
1769 DEBUG(0,("print_notify_register_pid: Failed to update pid \
1770 list for printer %s\n", printername));
1771 goto done;
1774 ret = True;
1776 done:
1778 tdb_unlock_bystring(tdb, NOTIFY_PID_LIST_KEY);
1779 if (pdb)
1780 release_print_db(pdb);
1781 SAFE_FREE(data.dptr);
1782 return ret;
1785 /****************************************************************************
1786 Update an entry in the print tdb that will allow us to send notify
1787 updates only to interested smbd's.
1788 ****************************************************************************/
1790 bool print_notify_deregister_pid(int snum)
1792 TDB_DATA data;
1793 struct tdb_print_db *pdb = NULL;
1794 TDB_CONTEXT *tdb = NULL;
1795 const char *printername;
1796 uint32_t mypid = (uint32_t)getpid();
1797 size_t i;
1798 bool ret = False;
1800 /* if ( snum == -1 ), we are deregister a print server handle
1801 which means to deregister on all print queues */
1803 if (snum == -1)
1805 int num_services = lp_numservices();
1806 int idx;
1808 for ( idx=0; idx<num_services; idx++ ) {
1809 if ( lp_snum_ok(idx) && lp_printable(idx) )
1810 print_notify_deregister_pid(idx);
1813 return True;
1815 else /* deregister a specific printer */
1817 printername = lp_const_servicename(snum);
1818 pdb = get_print_db_byname(printername);
1819 if (!pdb)
1820 return False;
1821 tdb = pdb->tdb;
1824 if (tdb_lock_bystring_with_timeout(tdb, NOTIFY_PID_LIST_KEY, 10) != 0) {
1825 DEBUG(0,("print_notify_register_pid: Failed to lock \
1826 printer %s database\n", printername));
1827 if (pdb)
1828 release_print_db(pdb);
1829 return False;
1832 data = get_printer_notify_pid_list( tdb, printername, True );
1834 /* Reduce refcount. Remove ourselves if zero. */
1836 for (i = 0; i < data.dsize; ) {
1837 if (IVAL(data.dptr,i) == mypid) {
1838 uint32_t refcount = IVAL(data.dptr, i+4);
1840 refcount--;
1842 if (refcount == 0) {
1843 if (data.dsize - i > 8)
1844 memmove( &data.dptr[i], &data.dptr[i+8], data.dsize - i - 8);
1845 data.dsize -= 8;
1846 continue;
1848 SIVAL(data.dptr, i+4, refcount);
1851 i += 8;
1854 if (data.dsize == 0)
1855 SAFE_FREE(data.dptr);
1857 /* Store back the record. */
1858 if (tdb_store_bystring(tdb, NOTIFY_PID_LIST_KEY, data, TDB_REPLACE) != 0) {
1859 DEBUG(0,("print_notify_register_pid: Failed to update pid \
1860 list for printer %s\n", printername));
1861 goto done;
1864 ret = True;
1866 done:
1868 tdb_unlock_bystring(tdb, NOTIFY_PID_LIST_KEY);
1869 if (pdb)
1870 release_print_db(pdb);
1871 SAFE_FREE(data.dptr);
1872 return ret;
1875 /****************************************************************************
1876 Check if a jobid is valid. It is valid if it exists in the database.
1877 ****************************************************************************/
1879 bool print_job_exists(const char* sharename, uint32_t jobid)
1881 struct tdb_print_db *pdb = get_print_db_byname(sharename);
1882 bool ret;
1883 uint32_t tmp;
1885 if (!pdb)
1886 return False;
1887 ret = tdb_exists(pdb->tdb, print_key(jobid, &tmp));
1888 release_print_db(pdb);
1889 return ret;
1892 /****************************************************************************
1893 Return the device mode asigned to a specific print job.
1894 Only valid for the process doing the spooling and when the job
1895 has not been spooled.
1896 ****************************************************************************/
1898 struct spoolss_DeviceMode *print_job_devmode(TALLOC_CTX *mem_ctx,
1899 const char *sharename,
1900 uint32_t jobid)
1902 struct printjob *pjob = print_job_find(mem_ctx, sharename, jobid);
1903 if (pjob == NULL) {
1904 return NULL;
1907 return pjob->devmode;
1910 /****************************************************************************
1911 Set the name of a job. Only possible for owner.
1912 ****************************************************************************/
1914 bool print_job_set_name(struct tevent_context *ev,
1915 struct messaging_context *msg_ctx,
1916 const char *sharename, uint32_t jobid, const char *name)
1918 struct printjob *pjob;
1919 bool ret;
1920 TALLOC_CTX *tmp_ctx = talloc_new(ev);
1921 if (tmp_ctx == NULL) {
1922 return false;
1925 pjob = print_job_find(tmp_ctx, sharename, jobid);
1926 if (!pjob || pjob->pid != getpid()) {
1927 ret = false;
1928 goto err_out;
1931 fstrcpy(pjob->jobname, name);
1932 ret = pjob_store(ev, msg_ctx, sharename, jobid, pjob);
1933 err_out:
1934 talloc_free(tmp_ctx);
1935 return ret;
1938 /****************************************************************************
1939 Get the name of a job. Only possible for owner.
1940 ****************************************************************************/
1942 bool print_job_get_name(TALLOC_CTX *mem_ctx, const char *sharename, uint32_t jobid, char **name)
1944 struct printjob *pjob;
1946 pjob = print_job_find(mem_ctx, sharename, jobid);
1947 if (!pjob || pjob->pid != getpid()) {
1948 return false;
1951 *name = pjob->jobname;
1952 return true;
1956 /***************************************************************************
1957 Remove a jobid from the 'jobs added' list.
1958 ***************************************************************************/
1960 static bool remove_from_jobs_added(const char* sharename, uint32_t jobid)
1962 bool ret = remove_from_jobs_list("INFO/jobs_added", sharename, jobid);
1963 return ret;
1966 /****************************************************************************
1967 Delete a print job - don't update queue.
1968 ****************************************************************************/
1970 static bool print_job_delete1(struct tevent_context *ev,
1971 struct messaging_context *msg_ctx,
1972 int snum, uint32_t jobid)
1974 const char* sharename = lp_const_servicename(snum);
1975 const struct loadparm_substitution *lp_sub =
1976 loadparm_s3_global_substitution();
1977 struct printjob *pjob;
1978 int result = 0;
1979 struct printif *current_printif = get_printer_fns( snum );
1980 bool ret;
1981 TALLOC_CTX *tmp_ctx = talloc_new(ev);
1982 if (tmp_ctx == NULL) {
1983 return false;
1986 pjob = print_job_find(tmp_ctx, sharename, jobid);
1987 if (!pjob) {
1988 ret = false;
1989 goto err_out;
1993 * If already deleting just return.
1996 if (pjob->status == LPQ_DELETING) {
1997 ret = true;
1998 goto err_out;
2001 /* Hrm - we need to be able to cope with deleting a job before it
2002 has reached the spooler. Just mark it as LPQ_DELETING and
2003 let the print_queue_update() code rmeove the record */
2006 if (pjob->sysjob == -1) {
2007 DEBUG(5, ("attempt to delete job %u not seen by lpr\n", (unsigned int)jobid));
2010 /* Set the tdb entry to be deleting. */
2012 pjob->status = LPQ_DELETING;
2013 pjob_store(ev, msg_ctx, sharename, jobid, pjob);
2015 if (pjob->spooled && pjob->sysjob != -1)
2017 result = (*(current_printif->job_delete))(
2018 lp_printername(talloc_tos(), lp_sub, snum),
2019 lp_lprm_command(snum),
2020 pjob);
2022 /* Delete the tdb entry if the delete succeeded or the job hasn't
2023 been spooled. */
2025 if (result == 0) {
2026 struct tdb_print_db *pdb = get_print_db_byname(sharename);
2027 int njobs = 1;
2029 if (!pdb) {
2030 ret = false;
2031 goto err_out;
2033 pjob_delete(ev, msg_ctx, sharename, jobid);
2034 /* Ensure we keep a rough count of the number of total jobs... */
2035 tdb_change_int32_atomic(pdb->tdb, "INFO/total_jobs", &njobs, -1);
2036 release_print_db(pdb);
2040 remove_from_jobs_added( sharename, jobid );
2042 ret = (result == 0);
2043 err_out:
2044 talloc_free(tmp_ctx);
2045 return ret;
2048 /****************************************************************************
2049 Return true if the current user owns the print job.
2050 ****************************************************************************/
2052 static bool is_owner(const struct auth_session_info *server_info,
2053 const char *servicename,
2054 uint32_t jobid)
2056 struct printjob *pjob;
2057 bool ret;
2058 TALLOC_CTX *tmp_ctx = talloc_new(server_info);
2059 if (tmp_ctx == NULL) {
2060 return false;
2063 pjob = print_job_find(tmp_ctx, servicename, jobid);
2064 if (!pjob || !server_info) {
2065 ret = false;
2066 goto err_out;
2069 ret = strequal(pjob->user, server_info->unix_info->sanitized_username);
2070 err_out:
2071 talloc_free(tmp_ctx);
2072 return ret;
2075 /****************************************************************************
2076 Delete a print job.
2077 ****************************************************************************/
2079 WERROR print_job_delete(const struct auth_session_info *server_info,
2080 struct messaging_context *msg_ctx,
2081 int snum, uint32_t jobid)
2083 const char* sharename = lp_const_servicename(snum);
2084 const struct loadparm_substitution *lp_sub =
2085 loadparm_s3_global_substitution();
2086 struct printjob *pjob;
2087 bool owner;
2088 WERROR werr;
2089 TALLOC_CTX *tmp_ctx = talloc_new(msg_ctx);
2090 if (tmp_ctx == NULL) {
2091 return WERR_NOT_ENOUGH_MEMORY;
2094 owner = is_owner(server_info, lp_const_servicename(snum), jobid);
2096 /* Check access against security descriptor or whether the user
2097 owns their job. */
2099 if (!owner &&
2100 !W_ERROR_IS_OK(print_access_check(server_info, msg_ctx, snum,
2101 JOB_ACCESS_ADMINISTER))) {
2102 DEBUG(0, ("print job delete denied."
2103 "User name: %s, Printer name: %s.",
2104 uidtoname(server_info->unix_token->uid),
2105 lp_printername(tmp_ctx, lp_sub, snum)));
2107 werr = WERR_ACCESS_DENIED;
2108 goto err_out;
2112 * get the spooled filename of the print job
2113 * if this works, then the file has not been spooled
2114 * to the underlying print system. Just delete the
2115 * spool file & return.
2118 pjob = print_job_find(tmp_ctx, sharename, jobid);
2119 if (!pjob || pjob->spooled || pjob->pid != getpid()) {
2120 DEBUG(10, ("Skipping spool file removal for job %u\n", jobid));
2121 } else {
2122 DEBUG(10, ("Removing spool file [%s]\n", pjob->filename));
2123 if (unlink(pjob->filename) == -1) {
2124 werr = map_werror_from_unix(errno);
2125 goto err_out;
2129 if (!print_job_delete1(global_event_context(), msg_ctx, snum, jobid)) {
2130 werr = WERR_ACCESS_DENIED;
2131 goto err_out;
2134 /* force update the database and say the delete failed if the
2135 job still exists */
2137 print_queue_update(msg_ctx, snum, True);
2139 pjob = print_job_find(tmp_ctx, sharename, jobid);
2140 if (pjob && (pjob->status != LPQ_DELETING)) {
2141 werr = WERR_ACCESS_DENIED;
2142 goto err_out;
2144 werr = WERR_PRINTER_HAS_JOBS_QUEUED;
2146 err_out:
2147 talloc_free(tmp_ctx);
2148 return werr;
2151 /****************************************************************************
2152 Pause a job.
2153 ****************************************************************************/
2155 WERROR print_job_pause(const struct auth_session_info *server_info,
2156 struct messaging_context *msg_ctx,
2157 int snum, uint32_t jobid)
2159 const char* sharename = lp_const_servicename(snum);
2160 const struct loadparm_substitution *lp_sub =
2161 loadparm_s3_global_substitution();
2162 struct printjob *pjob;
2163 int ret = -1;
2164 struct printif *current_printif = get_printer_fns( snum );
2165 WERROR werr;
2166 TALLOC_CTX *tmp_ctx = talloc_new(msg_ctx);
2167 if (tmp_ctx == NULL) {
2168 return WERR_NOT_ENOUGH_MEMORY;
2171 pjob = print_job_find(tmp_ctx, sharename, jobid);
2172 if (!pjob || !server_info) {
2173 DEBUG(10, ("print_job_pause: no pjob or user for jobid %u\n",
2174 (unsigned int)jobid ));
2175 werr = WERR_INVALID_PARAMETER;
2176 goto err_out;
2179 if (!pjob->spooled || pjob->sysjob == -1) {
2180 DEBUG(10, ("print_job_pause: not spooled or bad sysjob = %d for jobid %u\n",
2181 (int)pjob->sysjob, (unsigned int)jobid ));
2182 werr = WERR_INVALID_PARAMETER;
2183 goto err_out;
2186 if (!is_owner(server_info, lp_const_servicename(snum), jobid) &&
2187 !W_ERROR_IS_OK(print_access_check(server_info, msg_ctx, snum,
2188 JOB_ACCESS_ADMINISTER))) {
2189 DEBUG(0, ("print job pause denied."
2190 "User name: %s, Printer name: %s.",
2191 uidtoname(server_info->unix_token->uid),
2192 lp_printername(tmp_ctx, lp_sub, snum)));
2194 werr = WERR_ACCESS_DENIED;
2195 goto err_out;
2198 /* need to pause the spooled entry */
2199 ret = (*(current_printif->job_pause))(snum, pjob);
2201 if (ret != 0) {
2202 werr = WERR_INVALID_PARAMETER;
2203 goto err_out;
2206 /* force update the database */
2207 print_cache_flush(lp_const_servicename(snum));
2209 /* Send a printer notify message */
2211 notify_job_status(global_event_context(), msg_ctx, sharename, jobid,
2212 JOB_STATUS_PAUSED);
2214 /* how do we tell if this succeeded? */
2215 werr = WERR_OK;
2216 err_out:
2217 talloc_free(tmp_ctx);
2218 return werr;
2221 /****************************************************************************
2222 Resume a job.
2223 ****************************************************************************/
2225 WERROR print_job_resume(const struct auth_session_info *server_info,
2226 struct messaging_context *msg_ctx,
2227 int snum, uint32_t jobid)
2229 const char *sharename = lp_const_servicename(snum);
2230 const struct loadparm_substitution *lp_sub =
2231 loadparm_s3_global_substitution();
2232 struct printjob *pjob;
2233 int ret;
2234 struct printif *current_printif = get_printer_fns( snum );
2235 WERROR werr;
2236 TALLOC_CTX *tmp_ctx = talloc_new(msg_ctx);
2237 if (tmp_ctx == NULL)
2238 return WERR_NOT_ENOUGH_MEMORY;
2240 pjob = print_job_find(tmp_ctx, sharename, jobid);
2241 if (!pjob || !server_info) {
2242 DEBUG(10, ("print_job_resume: no pjob or user for jobid %u\n",
2243 (unsigned int)jobid ));
2244 werr = WERR_INVALID_PARAMETER;
2245 goto err_out;
2248 if (!pjob->spooled || pjob->sysjob == -1) {
2249 DEBUG(10, ("print_job_resume: not spooled or bad sysjob = %d for jobid %u\n",
2250 (int)pjob->sysjob, (unsigned int)jobid ));
2251 werr = WERR_INVALID_PARAMETER;
2252 goto err_out;
2255 if (!is_owner(server_info, lp_const_servicename(snum), jobid) &&
2256 !W_ERROR_IS_OK(print_access_check(server_info, msg_ctx, snum,
2257 JOB_ACCESS_ADMINISTER))) {
2258 DEBUG(0, ("print job resume denied."
2259 "User name: %s, Printer name: %s.",
2260 uidtoname(server_info->unix_token->uid),
2261 lp_printername(tmp_ctx, lp_sub, snum)));
2263 werr = WERR_ACCESS_DENIED;
2264 goto err_out;
2267 ret = (*(current_printif->job_resume))(snum, pjob);
2269 if (ret != 0) {
2270 werr = WERR_INVALID_PARAMETER;
2271 goto err_out;
2274 /* force update the database */
2275 print_cache_flush(lp_const_servicename(snum));
2277 /* Send a printer notify message */
2279 notify_job_status(global_event_context(), msg_ctx, sharename, jobid,
2280 JOB_STATUS_QUEUED);
2282 werr = WERR_OK;
2283 err_out:
2284 talloc_free(tmp_ctx);
2285 return werr;
2288 /****************************************************************************
2289 Write to a print file.
2290 ****************************************************************************/
2292 ssize_t print_job_write(struct tevent_context *ev,
2293 struct messaging_context *msg_ctx,
2294 int snum, uint32_t jobid, const char *buf, size_t size)
2296 const char* sharename = lp_const_servicename(snum);
2297 ssize_t return_code;
2298 struct printjob *pjob;
2299 TALLOC_CTX *tmp_ctx = talloc_new(ev);
2300 if (tmp_ctx == NULL) {
2301 return -1;
2304 pjob = print_job_find(tmp_ctx, sharename, jobid);
2305 if (!pjob) {
2306 return_code = -1;
2307 goto err_out;
2310 /* don't allow another process to get this info - it is meaningless */
2311 if (pjob->pid != getpid()) {
2312 return_code = -1;
2313 goto err_out;
2316 /* if SMBD is spooling this can't be allowed */
2317 if (pjob->status == PJOB_SMBD_SPOOLING) {
2318 return_code = -1;
2319 goto err_out;
2322 return_code = write_data(pjob->fd, buf, size);
2323 if (return_code > 0) {
2324 pjob->size += size;
2325 pjob_store(ev, msg_ctx, sharename, jobid, pjob);
2327 err_out:
2328 talloc_free(tmp_ctx);
2329 return return_code;
2332 /****************************************************************************
2333 Get the queue status - do not update if db is out of date.
2334 ****************************************************************************/
2336 static int get_queue_status(const char* sharename, print_status_struct *status)
2338 fstring keystr;
2339 TDB_DATA data;
2340 struct tdb_print_db *pdb = get_print_db_byname(sharename);
2341 int len;
2343 if (status) {
2344 ZERO_STRUCTP(status);
2347 if (!pdb)
2348 return 0;
2350 if (status) {
2351 fstr_sprintf(keystr, "STATUS/%s", sharename);
2352 data = tdb_fetch(pdb->tdb, string_tdb_data(keystr));
2353 if (data.dptr) {
2354 if (data.dsize == sizeof(print_status_struct))
2355 /* this memcpy is ok since the status struct was
2356 not packed before storing it in the tdb */
2357 memcpy(status, data.dptr, sizeof(print_status_struct));
2358 SAFE_FREE(data.dptr);
2361 len = tdb_fetch_int32(pdb->tdb, "INFO/total_jobs");
2362 release_print_db(pdb);
2363 return (len == -1 ? 0 : len);
2366 /****************************************************************************
2367 Determine the number of jobs in a queue.
2368 ****************************************************************************/
2370 int print_queue_length(struct messaging_context *msg_ctx, int snum,
2371 print_status_struct *pstatus)
2373 const char* sharename = lp_const_servicename( snum );
2374 print_status_struct status;
2375 int len;
2377 ZERO_STRUCT( status );
2379 /* make sure the database is up to date */
2380 if (print_cache_expired(lp_const_servicename(snum), True))
2381 print_queue_update(msg_ctx, snum, False);
2383 /* also fetch the queue status */
2384 memset(&status, 0, sizeof(status));
2385 len = get_queue_status(sharename, &status);
2387 if (pstatus)
2388 *pstatus = status;
2390 return len;
2393 /***************************************************************************
2394 Allocate a jobid. Hold the lock for as short a time as possible.
2395 ***************************************************************************/
2397 static WERROR allocate_print_jobid(struct tdb_print_db *pdb, int snum,
2398 const char *sharename, uint32_t *pjobid)
2400 int i;
2401 uint32_t jobid;
2402 enum TDB_ERROR terr;
2403 int ret;
2405 *pjobid = (uint32_t)-1;
2407 for (i = 0; i < 3; i++) {
2408 /* Lock the database - only wait 20 seconds. */
2409 ret = tdb_lock_bystring_with_timeout(pdb->tdb,
2410 "INFO/nextjob", 20);
2411 if (ret != 0) {
2412 DEBUG(0, ("allocate_print_jobid: "
2413 "Failed to lock printing database %s\n",
2414 sharename));
2415 terr = tdb_error(pdb->tdb);
2416 return ntstatus_to_werror(map_nt_error_from_tdb(terr));
2419 if (!tdb_fetch_uint32(pdb->tdb, "INFO/nextjob", &jobid)) {
2420 terr = tdb_error(pdb->tdb);
2421 if (terr != TDB_ERR_NOEXIST) {
2422 DEBUG(0, ("allocate_print_jobid: "
2423 "Failed to fetch INFO/nextjob "
2424 "for print queue %s\n", sharename));
2425 tdb_unlock_bystring(pdb->tdb, "INFO/nextjob");
2426 return ntstatus_to_werror(map_nt_error_from_tdb(terr));
2428 DEBUG(10, ("allocate_print_jobid: "
2429 "No existing jobid in %s\n", sharename));
2430 jobid = 0;
2433 DEBUG(10, ("allocate_print_jobid: "
2434 "Read jobid %u from %s\n", jobid, sharename));
2436 jobid = NEXT_JOBID(jobid);
2438 ret = tdb_store_int32(pdb->tdb, "INFO/nextjob", jobid);
2439 if (ret != 0) {
2440 terr = tdb_error(pdb->tdb);
2441 DEBUG(3, ("allocate_print_jobid: "
2442 "Failed to store INFO/nextjob.\n"));
2443 tdb_unlock_bystring(pdb->tdb, "INFO/nextjob");
2444 return ntstatus_to_werror(map_nt_error_from_tdb(terr));
2447 /* We've finished with the INFO/nextjob lock. */
2448 tdb_unlock_bystring(pdb->tdb, "INFO/nextjob");
2450 if (!print_job_exists(sharename, jobid)) {
2451 break;
2453 DEBUG(10, ("allocate_print_jobid: "
2454 "Found jobid %u in %s\n", jobid, sharename));
2457 if (i > 2) {
2458 DEBUG(0, ("allocate_print_jobid: "
2459 "Failed to allocate a print job for queue %s\n",
2460 sharename));
2461 /* Probably full... */
2462 return WERR_NO_SPOOL_SPACE;
2465 /* Store a dummy placeholder. */
2467 uint32_t tmp;
2468 TDB_DATA dum;
2469 dum.dptr = NULL;
2470 dum.dsize = 0;
2471 if (tdb_store(pdb->tdb, print_key(jobid, &tmp), dum,
2472 TDB_INSERT) != 0) {
2473 DEBUG(3, ("allocate_print_jobid: "
2474 "jobid (%d) failed to store placeholder.\n",
2475 jobid ));
2476 terr = tdb_error(pdb->tdb);
2477 return ntstatus_to_werror(map_nt_error_from_tdb(terr));
2481 *pjobid = jobid;
2482 return WERR_OK;
2485 /***************************************************************************
2486 Do all checks needed to determine if we can start a job.
2487 ***************************************************************************/
2489 static WERROR print_job_checks(const struct auth_session_info *server_info,
2490 struct messaging_context *msg_ctx,
2491 int snum, int *njobs)
2493 const char *sharename = lp_const_servicename(snum);
2494 const struct loadparm_substitution *lp_sub =
2495 loadparm_s3_global_substitution();
2496 uint64_t dspace, dsize;
2497 uint64_t minspace;
2498 int ret;
2500 if (!W_ERROR_IS_OK(print_access_check(server_info, msg_ctx, snum,
2501 PRINTER_ACCESS_USE))) {
2502 DEBUG(3, ("print_job_checks: "
2503 "job start denied by security descriptor\n"));
2504 return WERR_ACCESS_DENIED;
2507 if (!print_time_access_check(server_info, msg_ctx, sharename)) {
2508 DEBUG(3, ("print_job_checks: "
2509 "job start denied by time check\n"));
2510 return WERR_ACCESS_DENIED;
2513 /* see if we have sufficient disk space */
2514 if (lp_min_print_space(snum)) {
2515 minspace = lp_min_print_space(snum);
2516 ret = sys_fsusage(lp_path(talloc_tos(), lp_sub, snum), &dspace, &dsize);
2517 if (ret == 0 && dspace < 2*minspace) {
2518 DEBUG(3, ("print_job_checks: "
2519 "disk space check failed.\n"));
2520 return WERR_NO_SPOOL_SPACE;
2524 /* for autoloaded printers, check that the printcap entry still exists */
2525 if (lp_autoloaded(snum) &&
2526 !printer_list_printername_exists(sharename)) {
2527 DEBUG(3, ("print_job_checks: printer name %s check failed.\n",
2528 sharename));
2529 return WERR_ACCESS_DENIED;
2532 /* Insure the maximum queue size is not violated */
2533 *njobs = print_queue_length(msg_ctx, snum, NULL);
2534 if (*njobs > lp_maxprintjobs(snum)) {
2535 DEBUG(3, ("print_job_checks: Queue %s number of jobs (%d) "
2536 "larger than max printjobs per queue (%d).\n",
2537 sharename, *njobs, lp_maxprintjobs(snum)));
2538 return WERR_NO_SPOOL_SPACE;
2541 return WERR_OK;
2544 /***************************************************************************
2545 Create a job file.
2546 ***************************************************************************/
2548 static WERROR print_job_spool_file(int snum, uint32_t jobid,
2549 const char *output_file,
2550 struct printjob *pjob)
2552 const struct loadparm_substitution *lp_sub =
2553 loadparm_s3_global_substitution();
2554 WERROR werr;
2555 SMB_STRUCT_STAT st;
2556 const char *path;
2557 int len;
2558 mode_t mask;
2560 /* if this file is within the printer path, it means that smbd
2561 * is spooling it and will pass us control when it is finished.
2562 * Verify that the file name is ok, within path, and it is
2563 * already already there */
2564 if (output_file) {
2565 path = lp_path(talloc_tos(), lp_sub, snum);
2566 len = strlen(path);
2567 if (strncmp(output_file, path, len) == 0 &&
2568 (output_file[len - 1] == '/' || output_file[len] == '/')) {
2570 /* verify path is not too long */
2571 if (strlen(output_file) >= sizeof(pjob->filename)) {
2572 return WERR_INVALID_NAME;
2575 /* verify that the file exists */
2576 if (sys_stat(output_file, &st, false) != 0) {
2577 return WERR_INVALID_NAME;
2580 fstrcpy(pjob->filename, output_file);
2582 DEBUG(3, ("print_job_spool_file:"
2583 "External spooling activated\n"));
2585 /* we do not open the file until spooling is done */
2586 pjob->fd = -1;
2587 pjob->status = PJOB_SMBD_SPOOLING;
2589 return WERR_OK;
2593 slprintf(pjob->filename, sizeof(pjob->filename)-1,
2594 "%s/%sXXXXXX", lp_path(talloc_tos(), lp_sub, snum),
2595 PRINT_SPOOL_PREFIX);
2596 mask = umask(S_IRWXO | S_IRWXG);
2597 pjob->fd = mkstemp(pjob->filename);
2598 umask(mask);
2600 if (pjob->fd == -1) {
2601 werr = map_werror_from_unix(errno);
2602 if (W_ERROR_EQUAL(werr, WERR_ACCESS_DENIED)) {
2603 /* Common setup error, force a report. */
2604 DEBUG(0, ("print_job_spool_file: "
2605 "insufficient permissions to open spool "
2606 "file %s.\n", pjob->filename));
2607 } else {
2608 /* Normal case, report at level 3 and above. */
2609 DEBUG(3, ("print_job_spool_file: "
2610 "can't open spool file %s\n",
2611 pjob->filename));
2613 return werr;
2616 return WERR_OK;
2619 /***************************************************************************
2620 Start spooling a job - return the jobid.
2621 ***************************************************************************/
2623 WERROR print_job_start(const struct auth_session_info *server_info,
2624 struct messaging_context *msg_ctx,
2625 const char *clientmachine,
2626 int snum, const char *docname, const char *filename,
2627 struct spoolss_DeviceMode *devmode, uint32_t *_jobid)
2629 uint32_t jobid;
2630 char *path = NULL, *userstr = NULL;
2631 struct printjob pjob;
2632 const char *sharename = lp_const_servicename(snum);
2633 struct tdb_print_db *pdb = get_print_db_byname(sharename);
2634 const struct loadparm_substitution *lp_sub =
2635 loadparm_s3_global_substitution();
2636 int njobs;
2637 WERROR werr;
2639 if (!pdb) {
2640 return WERR_INTERNAL_DB_CORRUPTION;
2643 path = lp_path(talloc_tos(), lp_sub, snum);
2645 werr = print_job_checks(server_info, msg_ctx, snum, &njobs);
2646 if (!W_ERROR_IS_OK(werr)) {
2647 release_print_db(pdb);
2648 return werr;
2651 DEBUG(10, ("print_job_start: "
2652 "Queue %s number of jobs (%d), max printjobs = %d\n",
2653 sharename, njobs, lp_maxprintjobs(snum)));
2655 werr = allocate_print_jobid(pdb, snum, sharename, &jobid);
2656 if (!W_ERROR_IS_OK(werr)) {
2657 goto fail;
2660 /* create the database entry */
2662 ZERO_STRUCT(pjob);
2664 pjob.pid = getpid();
2665 pjob.jobid = jobid;
2666 pjob.sysjob = -1;
2667 pjob.fd = -1;
2668 pjob.starttime = time(NULL);
2669 pjob.status = LPQ_SPOOLING;
2670 pjob.size = 0;
2671 pjob.spooled = False;
2672 pjob.smbjob = True;
2673 pjob.devmode = devmode;
2675 fstrcpy(pjob.jobname, docname);
2677 fstrcpy(pjob.clientmachine, clientmachine);
2679 userstr = talloc_sub_full(talloc_tos(),
2680 sharename,
2681 server_info->unix_info->sanitized_username,
2682 path, server_info->unix_token->gid,
2683 server_info->unix_info->sanitized_username,
2684 server_info->info->domain_name,
2685 lp_printjob_username(snum));
2686 if (userstr == NULL) {
2687 werr = WERR_NOT_ENOUGH_MEMORY;
2688 goto fail;
2690 strlcpy(pjob.user, userstr, sizeof(pjob.user));
2691 TALLOC_FREE(userstr);
2693 fstrcpy(pjob.queuename, lp_const_servicename(snum));
2695 /* we have a job entry - now create the spool file */
2696 werr = print_job_spool_file(snum, jobid, filename, &pjob);
2697 if (!W_ERROR_IS_OK(werr)) {
2698 goto fail;
2701 pjob_store(global_event_context(), msg_ctx, sharename, jobid, &pjob);
2703 /* Update the 'jobs added' entry used by print_queue_status. */
2704 add_to_jobs_list(pdb, jobid, "INFO/jobs_added");
2706 /* Ensure we keep a rough count of the number of total jobs... */
2707 tdb_change_int32_atomic(pdb->tdb, "INFO/total_jobs", &njobs, 1);
2709 release_print_db(pdb);
2711 *_jobid = jobid;
2712 return WERR_OK;
2714 fail:
2715 if (jobid != -1) {
2716 pjob_delete(global_event_context(), msg_ctx, sharename, jobid);
2719 release_print_db(pdb);
2721 DEBUG(3, ("print_job_start: returning fail. "
2722 "Error = %s\n", win_errstr(werr)));
2723 return werr;
2726 /****************************************************************************
2727 Update the number of pages spooled to jobid
2728 ****************************************************************************/
2730 void print_job_endpage(struct messaging_context *msg_ctx,
2731 int snum, uint32_t jobid)
2733 const char* sharename = lp_const_servicename(snum);
2734 struct printjob *pjob;
2735 TALLOC_CTX *tmp_ctx = talloc_new(msg_ctx);
2736 if (tmp_ctx == NULL) {
2737 return;
2740 pjob = print_job_find(tmp_ctx, sharename, jobid);
2741 if (!pjob) {
2742 goto err_out;
2744 /* don't allow another process to get this info - it is meaningless */
2745 if (pjob->pid != getpid()) {
2746 goto err_out;
2749 pjob->page_count++;
2750 pjob_store(global_event_context(), msg_ctx, sharename, jobid, pjob);
2751 err_out:
2752 talloc_free(tmp_ctx);
2755 /****************************************************************************
2756 Print a file - called on closing the file. This spools the job.
2757 If normal close is false then we're tearing down the jobs - treat as an
2758 error.
2759 ****************************************************************************/
2761 NTSTATUS print_job_end(struct messaging_context *msg_ctx, int snum,
2762 uint32_t jobid, enum file_close_type close_type)
2764 const char* sharename = lp_const_servicename(snum);
2765 const struct loadparm_substitution *lp_sub =
2766 loadparm_s3_global_substitution();
2767 struct printjob *pjob;
2768 int ret;
2769 SMB_STRUCT_STAT sbuf;
2770 struct printif *current_printif = get_printer_fns(snum);
2771 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
2772 char *lpq_cmd;
2773 TALLOC_CTX *tmp_ctx = talloc_new(msg_ctx);
2774 if (tmp_ctx == NULL) {
2775 return NT_STATUS_NO_MEMORY;
2778 pjob = print_job_find(tmp_ctx, sharename, jobid);
2779 if (!pjob) {
2780 status = NT_STATUS_PRINT_CANCELLED;
2781 goto err_out;
2784 if (pjob->spooled || pjob->pid != getpid()) {
2785 status = NT_STATUS_ACCESS_DENIED;
2786 goto err_out;
2789 if (close_type == NORMAL_CLOSE || close_type == SHUTDOWN_CLOSE) {
2790 if (pjob->status == PJOB_SMBD_SPOOLING) {
2791 /* take over the file now, smbd is done */
2792 if (sys_stat(pjob->filename, &sbuf, false) != 0) {
2793 status = map_nt_error_from_unix(errno);
2794 DEBUG(3, ("print_job_end: "
2795 "stat file failed for jobid %d\n",
2796 jobid));
2797 goto fail;
2800 pjob->status = LPQ_SPOOLING;
2802 } else {
2804 if ((sys_fstat(pjob->fd, &sbuf, false) != 0)) {
2805 status = map_nt_error_from_unix(errno);
2806 close(pjob->fd);
2807 DEBUG(3, ("print_job_end: "
2808 "stat file failed for jobid %d\n",
2809 jobid));
2810 goto fail;
2813 close(pjob->fd);
2816 pjob->size = sbuf.st_ex_size;
2817 } else {
2820 * Not a normal close, something has gone wrong. Cleanup.
2822 if (pjob->fd != -1) {
2823 close(pjob->fd);
2825 goto fail;
2828 /* Technically, this is not quite right. If the printer has a separator
2829 * page turned on, the NT spooler prints the separator page even if the
2830 * print job is 0 bytes. 010215 JRR */
2831 if (pjob->size == 0 || pjob->status == LPQ_DELETING) {
2832 /* don't bother spooling empty files or something being deleted. */
2833 DEBUG(5,("print_job_end: canceling spool of %s (%s)\n",
2834 pjob->filename, pjob->size ? "deleted" : "zero length" ));
2835 unlink(pjob->filename);
2836 pjob_delete(global_event_context(), msg_ctx, sharename, jobid);
2837 return NT_STATUS_OK;
2840 /* don't strip out characters like '$' from the printername */
2841 lpq_cmd = talloc_string_sub2(tmp_ctx,
2842 lp_lpq_command(snum),
2843 "%p",
2844 lp_printername(talloc_tos(), lp_sub, snum),
2845 false, false, false);
2846 if (lpq_cmd == NULL) {
2847 status = NT_STATUS_PRINT_CANCELLED;
2848 goto fail;
2850 lpq_cmd = talloc_sub_full(tmp_ctx,
2851 lp_servicename(talloc_tos(), lp_sub, snum),
2852 current_user_info.unix_name,
2854 get_current_gid(NULL),
2855 get_current_username(),
2856 current_user_info.domain,
2857 lpq_cmd);
2858 if (lpq_cmd == NULL) {
2859 status = NT_STATUS_PRINT_CANCELLED;
2860 goto fail;
2863 ret = (*(current_printif->job_submit))(snum, pjob,
2864 current_printif->type, lpq_cmd);
2865 if (ret) {
2866 status = NT_STATUS_PRINT_CANCELLED;
2867 goto fail;
2870 /* The print job has been successfully handed over to the back-end */
2872 pjob->spooled = True;
2873 pjob->status = LPQ_QUEUED;
2874 pjob_store(global_event_context(), msg_ctx, sharename, jobid, pjob);
2876 /* make sure the database is up to date */
2877 if (print_cache_expired(lp_const_servicename(snum), True))
2878 print_queue_update(msg_ctx, snum, False);
2880 return NT_STATUS_OK;
2882 fail:
2884 /* The print job was not successfully started. Cleanup */
2885 /* Still need to add proper error return propagation! 010122:JRR */
2886 pjob->fd = -1;
2887 unlink(pjob->filename);
2888 pjob_delete(global_event_context(), msg_ctx, sharename, jobid);
2889 err_out:
2890 talloc_free(tmp_ctx);
2891 return status;
2894 /****************************************************************************
2895 Get a snapshot of jobs in the system without traversing.
2896 ****************************************************************************/
2898 static bool get_stored_queue_info(struct messaging_context *msg_ctx,
2899 struct tdb_print_db *pdb, int snum,
2900 int *pcount, print_queue_struct **ppqueue)
2902 const struct loadparm_substitution *lp_sub =
2903 loadparm_s3_global_substitution();
2904 TDB_DATA data, cgdata, jcdata;
2905 print_queue_struct *queue = NULL;
2906 uint32_t qcount = 0;
2907 uint32_t extra_count = 0;
2908 uint32_t changed_count = 0;
2909 int total_count = 0;
2910 size_t len = 0;
2911 uint32_t i;
2912 int max_reported_jobs = lp_max_reported_print_jobs(snum);
2913 bool ret = false;
2914 const char* sharename = lp_servicename(talloc_tos(), lp_sub, snum);
2915 TALLOC_CTX *tmp_ctx = talloc_new(msg_ctx);
2916 if (tmp_ctx == NULL) {
2917 return false;
2920 /* make sure the database is up to date */
2921 if (print_cache_expired(lp_const_servicename(snum), True))
2922 print_queue_update(msg_ctx, snum, False);
2924 *pcount = 0;
2925 *ppqueue = NULL;
2927 ZERO_STRUCT(data);
2928 ZERO_STRUCT(cgdata);
2930 /* Get the stored queue data. */
2931 data = tdb_fetch(pdb->tdb, string_tdb_data("INFO/linear_queue_array"));
2933 if (data.dptr && data.dsize >= sizeof(qcount))
2934 len += tdb_unpack(data.dptr + len, data.dsize - len, "d", &qcount);
2936 /* Get the added jobs list. */
2937 cgdata = tdb_fetch(pdb->tdb, string_tdb_data("INFO/jobs_added"));
2938 if (cgdata.dptr != NULL && (cgdata.dsize % 4 == 0))
2939 extra_count = cgdata.dsize/4;
2941 /* Get the changed jobs list. */
2942 jcdata = tdb_fetch(pdb->tdb, string_tdb_data("INFO/jobs_changed"));
2943 if (jcdata.dptr != NULL && (jcdata.dsize % 4 == 0))
2944 changed_count = jcdata.dsize / 4;
2946 DEBUG(5,("get_stored_queue_info: qcount = %u, extra_count = %u\n", (unsigned int)qcount, (unsigned int)extra_count));
2948 /* Allocate the queue size. */
2949 if (qcount == 0 && extra_count == 0)
2950 goto out;
2952 if ((queue = SMB_MALLOC_ARRAY(print_queue_struct, qcount + extra_count)) == NULL)
2953 goto out;
2955 /* Retrieve the linearised queue data. */
2957 for(i = 0; i < qcount; i++) {
2958 uint32_t qjob, qsize, qpage_count, qstatus, qpriority, qtime;
2959 len += tdb_unpack(data.dptr + len, data.dsize - len, "ddddddff",
2960 &qjob,
2961 &qsize,
2962 &qpage_count,
2963 &qstatus,
2964 &qpriority,
2965 &qtime,
2966 queue[i].fs_user,
2967 queue[i].fs_file);
2968 queue[i].sysjob = qjob;
2969 queue[i].size = qsize;
2970 queue[i].page_count = qpage_count;
2971 queue[i].status = qstatus;
2972 queue[i].priority = qpriority;
2973 queue[i].time = qtime;
2976 total_count = qcount;
2978 /* Add new jobids to the queue. */
2979 for (i = 0; i < extra_count; i++) {
2980 uint32_t jobid;
2981 struct printjob *pjob;
2983 jobid = IVAL(cgdata.dptr, i*4);
2984 DEBUG(5,("get_stored_queue_info: added job = %u\n", (unsigned int)jobid));
2985 pjob = print_job_find(tmp_ctx, lp_const_servicename(snum), jobid);
2986 if (!pjob) {
2987 DEBUG(5,("get_stored_queue_info: failed to find added job = %u\n", (unsigned int)jobid));
2988 remove_from_jobs_added(sharename, jobid);
2989 continue;
2992 queue[total_count].sysjob = pjob->sysjob;
2993 queue[total_count].size = pjob->size;
2994 queue[total_count].page_count = pjob->page_count;
2995 queue[total_count].status = pjob->status;
2996 queue[total_count].priority = 1;
2997 queue[total_count].time = pjob->starttime;
2998 fstrcpy(queue[total_count].fs_user, pjob->user);
2999 fstrcpy(queue[total_count].fs_file, pjob->jobname);
3000 total_count++;
3001 talloc_free(pjob);
3004 /* Update the changed jobids. */
3005 for (i = 0; i < changed_count; i++) {
3006 uint32_t jobid = IVAL(jcdata.dptr, i * 4);
3007 struct printjob *pjob;
3008 uint32_t j;
3009 bool found = false;
3011 pjob = print_job_find(tmp_ctx, sharename, jobid);
3012 if (pjob == NULL) {
3013 DEBUG(5,("get_stored_queue_info: failed to find "
3014 "changed job = %u\n",
3015 (unsigned int)jobid));
3016 remove_from_jobs_changed(sharename, jobid);
3017 continue;
3020 for (j = 0; j < total_count; j++) {
3021 if (queue[j].sysjob == pjob->sysjob) {
3022 found = true;
3023 break;
3027 if (found) {
3028 DEBUG(5,("get_stored_queue_info: changed job: %u\n",
3029 (unsigned int)jobid));
3031 queue[j].sysjob = pjob->sysjob;
3032 queue[j].size = pjob->size;
3033 queue[j].page_count = pjob->page_count;
3034 queue[j].status = pjob->status;
3035 queue[j].priority = 1;
3036 queue[j].time = pjob->starttime;
3037 fstrcpy(queue[j].fs_user, pjob->user);
3038 fstrcpy(queue[j].fs_file, pjob->jobname);
3039 talloc_free(pjob);
3041 DEBUG(5,("updated queue[%u], jobid: %u, sysjob: %u, "
3042 "jobname: %s\n",
3043 (unsigned int)j, (unsigned int)jobid,
3044 (unsigned int)queue[j].sysjob, pjob->jobname));
3047 remove_from_jobs_changed(sharename, jobid);
3050 /* Sort the queue by submission time otherwise they are displayed
3051 in hash order. */
3053 TYPESAFE_QSORT(queue, total_count, printjob_comp);
3055 DEBUG(5,("get_stored_queue_info: total_count = %u\n", (unsigned int)total_count));
3057 if (max_reported_jobs && total_count > max_reported_jobs)
3058 total_count = max_reported_jobs;
3060 *ppqueue = queue;
3061 *pcount = total_count;
3063 ret = true;
3065 out:
3067 SAFE_FREE(data.dptr);
3068 SAFE_FREE(cgdata.dptr);
3069 talloc_free(tmp_ctx);
3070 return ret;
3073 /****************************************************************************
3074 Get a printer queue listing.
3075 set queue = NULL and status = NULL if you just want to update the cache
3076 ****************************************************************************/
3078 int print_queue_status(struct messaging_context *msg_ctx, int snum,
3079 print_queue_struct **ppqueue,
3080 print_status_struct *status)
3082 fstring keystr;
3083 TDB_DATA data, key;
3084 const char *sharename;
3085 struct tdb_print_db *pdb;
3086 int count = 0;
3088 /* make sure the database is up to date */
3090 if (print_cache_expired(lp_const_servicename(snum), True))
3091 print_queue_update(msg_ctx, snum, False);
3093 /* return if we are done */
3094 if ( !ppqueue || !status )
3095 return 0;
3097 *ppqueue = NULL;
3098 sharename = lp_const_servicename(snum);
3099 pdb = get_print_db_byname(sharename);
3101 if (!pdb)
3102 return 0;
3105 * Fetch the queue status. We must do this first, as there may
3106 * be no jobs in the queue.
3109 ZERO_STRUCTP(status);
3110 slprintf(keystr, sizeof(keystr)-1, "STATUS/%s", sharename);
3111 key = string_tdb_data(keystr);
3113 data = tdb_fetch(pdb->tdb, key);
3114 if (data.dptr) {
3115 if (data.dsize == sizeof(*status)) {
3116 /* this memcpy is ok since the status struct was
3117 not packed before storing it in the tdb */
3118 memcpy(status, data.dptr, sizeof(*status));
3120 SAFE_FREE(data.dptr);
3124 * Now, fetch the print queue information. We first count the number
3125 * of entries, and then only retrieve the queue if necessary.
3128 if (!get_stored_queue_info(msg_ctx, pdb, snum, &count, ppqueue)) {
3129 release_print_db(pdb);
3130 return 0;
3133 release_print_db(pdb);
3134 return count;
3137 /****************************************************************************
3138 Pause a queue.
3139 ****************************************************************************/
3141 WERROR print_queue_pause(const struct auth_session_info *server_info,
3142 struct messaging_context *msg_ctx, int snum)
3144 int ret;
3145 struct printif *current_printif = get_printer_fns( snum );
3147 if (!W_ERROR_IS_OK(print_access_check(server_info, msg_ctx, snum,
3148 PRINTER_ACCESS_ADMINISTER))) {
3149 return WERR_ACCESS_DENIED;
3153 become_root();
3155 ret = (*(current_printif->queue_pause))(snum);
3157 unbecome_root();
3159 if (ret != 0) {
3160 return WERR_INVALID_PARAMETER;
3163 /* force update the database */
3164 print_cache_flush(lp_const_servicename(snum));
3166 /* Send a printer notify message */
3168 notify_printer_status(global_event_context(), msg_ctx, snum,
3169 PRINTER_STATUS_PAUSED);
3171 return WERR_OK;
3174 /****************************************************************************
3175 Resume a queue.
3176 ****************************************************************************/
3178 WERROR print_queue_resume(const struct auth_session_info *server_info,
3179 struct messaging_context *msg_ctx, int snum)
3181 int ret;
3182 struct printif *current_printif = get_printer_fns( snum );
3184 if (!W_ERROR_IS_OK(print_access_check(server_info, msg_ctx, snum,
3185 PRINTER_ACCESS_ADMINISTER))) {
3186 return WERR_ACCESS_DENIED;
3189 become_root();
3191 ret = (*(current_printif->queue_resume))(snum);
3193 unbecome_root();
3195 if (ret != 0) {
3196 return WERR_INVALID_PARAMETER;
3199 /* make sure the database is up to date */
3200 if (print_cache_expired(lp_const_servicename(snum), True))
3201 print_queue_update(msg_ctx, snum, True);
3203 /* Send a printer notify message */
3205 notify_printer_status(global_event_context(), msg_ctx, snum,
3206 PRINTER_STATUS_OK);
3208 return WERR_OK;
3211 /****************************************************************************
3212 Purge a queue - implemented by deleting all jobs that we can delete.
3213 ****************************************************************************/
3215 WERROR print_queue_purge(const struct auth_session_info *server_info,
3216 struct messaging_context *msg_ctx, int snum)
3218 print_queue_struct *queue;
3219 print_status_struct status;
3220 int njobs, i;
3221 bool can_job_admin;
3223 /* Force and update so the count is accurate (i.e. not a cached count) */
3224 print_queue_update(msg_ctx, snum, True);
3226 can_job_admin = W_ERROR_IS_OK(print_access_check(server_info,
3227 msg_ctx,
3228 snum,
3229 JOB_ACCESS_ADMINISTER));
3230 njobs = print_queue_status(msg_ctx, snum, &queue, &status);
3232 if ( can_job_admin )
3233 become_root();
3235 for (i = 0; i < njobs; i++) {
3236 struct tdb_print_db *pdb;
3237 int jobid;
3238 bool owner;
3239 pdb = get_print_db_byname(lp_const_servicename(snum));
3240 if (pdb == NULL) {
3241 DEBUG(1, ("failed to find printdb for %s\n",
3242 lp_const_servicename(snum)));
3243 continue;
3245 jobid = sysjob_to_jobid_pdb(pdb, queue[i].sysjob);
3246 if (jobid == (uint32_t)-1) {
3247 DEBUG(2, ("jobid for system job %d not found\n",
3248 queue[i].sysjob));
3249 continue; /* unix job */
3251 owner = is_owner(server_info, lp_const_servicename(snum),
3252 jobid);
3254 if (owner || can_job_admin) {
3255 print_job_delete1(global_event_context(), msg_ctx,
3256 snum, jobid);
3260 if ( can_job_admin )
3261 unbecome_root();
3263 /* update the cache */
3264 print_queue_update(msg_ctx, snum, True);
3266 SAFE_FREE(queue);
3268 return WERR_OK;