s4:torture: Initialize param arrays
[Samba.git] / source3 / printing / printing.c
blob70b2b11688d7c66367560f144b8a8467be030c6d
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 the 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 DEBUG(10,("traverse_fn_delete: pjob %u deleted due to pjob.starttime (%u) < ts->lpq_time (%u)\n",
971 (unsigned int)jobid,
972 (unsigned int)pjob.starttime,
973 (unsigned int)ts->lpq_time ));
974 pjob_delete(ts->ev, ts->msg_ctx,
975 ts->sharename, jobid);
976 } else
977 ts->total_jobs++;
978 return 0;
981 /* Save the pjob attributes we will store. */
982 ts->queue[i].sysjob = pjob.sysjob;
983 ts->queue[i].size = pjob.size;
984 ts->queue[i].page_count = pjob.page_count;
985 ts->queue[i].status = pjob.status;
986 ts->queue[i].priority = 1;
987 ts->queue[i].time = pjob.starttime;
988 fstrcpy(ts->queue[i].fs_user, pjob.user);
989 fstrcpy(ts->queue[i].fs_file, pjob.jobname);
991 ts->total_jobs++;
993 return 0;
996 /****************************************************************************
997 Check if the print queue has been updated recently enough.
998 ****************************************************************************/
1000 static void print_cache_flush(const char *sharename)
1002 fstring key;
1003 struct tdb_print_db *pdb = get_print_db_byname(sharename);
1005 if (!pdb)
1006 return;
1007 slprintf(key, sizeof(key)-1, "CACHE/%s", sharename);
1008 tdb_store_int32(pdb->tdb, key, -1);
1009 release_print_db(pdb);
1012 /****************************************************************************
1013 Check if someone already thinks they are doing the update.
1014 ****************************************************************************/
1016 static pid_t get_updating_pid(const char *sharename)
1018 fstring keystr;
1019 TDB_DATA data, key;
1020 pid_t updating_pid;
1021 struct tdb_print_db *pdb = get_print_db_byname(sharename);
1023 if (!pdb)
1024 return (pid_t)-1;
1025 slprintf(keystr, sizeof(keystr)-1, "UPDATING/%s", sharename);
1026 key = string_tdb_data(keystr);
1028 data = tdb_fetch(pdb->tdb, key);
1029 release_print_db(pdb);
1030 if (!data.dptr || data.dsize != sizeof(pid_t)) {
1031 SAFE_FREE(data.dptr);
1032 return (pid_t)-1;
1035 updating_pid = IVAL(data.dptr, 0);
1036 SAFE_FREE(data.dptr);
1038 if (process_exists_by_pid(updating_pid))
1039 return updating_pid;
1041 return (pid_t)-1;
1044 /****************************************************************************
1045 Set the fact that we're doing the update, or have finished doing the update
1046 in the tdb.
1047 ****************************************************************************/
1049 static void set_updating_pid(const fstring sharename, bool updating)
1051 fstring keystr;
1052 TDB_DATA key;
1053 TDB_DATA data;
1054 pid_t updating_pid = getpid();
1055 uint8_t buffer[4];
1057 struct tdb_print_db *pdb = get_print_db_byname(sharename);
1059 if (!pdb)
1060 return;
1062 slprintf(keystr, sizeof(keystr)-1, "UPDATING/%s", sharename);
1063 key = string_tdb_data(keystr);
1065 DEBUG(5, ("set_updating_pid: %supdating lpq cache for print share %s\n",
1066 updating ? "" : "not ",
1067 sharename ));
1069 if ( !updating ) {
1070 tdb_delete(pdb->tdb, key);
1071 release_print_db(pdb);
1072 return;
1075 SIVAL( buffer, 0, updating_pid);
1076 data.dptr = buffer;
1077 data.dsize = 4; /* we always assume this is a 4 byte value */
1079 tdb_store(pdb->tdb, key, data, TDB_REPLACE);
1080 release_print_db(pdb);
1083 /****************************************************************************
1084 Sort print jobs by submittal time.
1085 ****************************************************************************/
1087 static int printjob_comp(print_queue_struct *j1, print_queue_struct *j2)
1089 /* Silly cases */
1091 if (!j1 && !j2)
1092 return 0;
1093 if (!j1)
1094 return -1;
1095 if (!j2)
1096 return 1;
1098 /* Sort on job start time */
1100 if (j1->time == j2->time)
1101 return 0;
1102 return (j1->time > j2->time) ? 1 : -1;
1105 /****************************************************************************
1106 Store the sorted queue representation for later portmon retrieval.
1107 Skip deleted jobs
1108 ****************************************************************************/
1110 static void store_queue_struct(struct tdb_print_db *pdb, struct traverse_struct *pts)
1112 TDB_DATA data;
1113 int max_reported_jobs = lp_max_reported_print_jobs(pts->snum);
1114 print_queue_struct *queue = pts->queue;
1115 size_t len;
1116 size_t i;
1117 unsigned int qcount;
1119 if (max_reported_jobs && (max_reported_jobs < pts->qcount))
1120 pts->qcount = max_reported_jobs;
1121 qcount = 0;
1123 /* Work out the size. */
1124 data.dsize = 0;
1125 data.dsize += tdb_pack(NULL, 0, "d", qcount);
1127 for (i = 0; i < pts->qcount; i++) {
1128 if ( queue[i].status == LPQ_DELETED )
1129 continue;
1131 qcount++;
1132 data.dsize += tdb_pack(NULL, 0, "ddddddff",
1133 (uint32_t)queue[i].sysjob,
1134 (uint32_t)queue[i].size,
1135 (uint32_t)queue[i].page_count,
1136 (uint32_t)queue[i].status,
1137 (uint32_t)queue[i].priority,
1138 (uint32_t)queue[i].time,
1139 queue[i].fs_user,
1140 queue[i].fs_file);
1143 if ((data.dptr = (uint8_t *)SMB_MALLOC(data.dsize)) == NULL)
1144 return;
1146 len = 0;
1147 len += tdb_pack(data.dptr + len, data.dsize - len, "d", qcount);
1148 for (i = 0; i < pts->qcount; i++) {
1149 if ( queue[i].status == LPQ_DELETED )
1150 continue;
1152 len += tdb_pack(data.dptr + len, data.dsize - len, "ddddddff",
1153 (uint32_t)queue[i].sysjob,
1154 (uint32_t)queue[i].size,
1155 (uint32_t)queue[i].page_count,
1156 (uint32_t)queue[i].status,
1157 (uint32_t)queue[i].priority,
1158 (uint32_t)queue[i].time,
1159 queue[i].fs_user,
1160 queue[i].fs_file);
1163 tdb_store(pdb->tdb, string_tdb_data("INFO/linear_queue_array"), data,
1164 TDB_REPLACE);
1165 SAFE_FREE(data.dptr);
1166 return;
1169 static TDB_DATA get_jobs_added_data(struct tdb_print_db *pdb)
1171 TDB_DATA data;
1173 ZERO_STRUCT(data);
1175 data = tdb_fetch(pdb->tdb, string_tdb_data("INFO/jobs_added"));
1176 if (data.dptr == NULL || data.dsize == 0 || (data.dsize % 4 != 0)) {
1177 SAFE_FREE(data.dptr);
1178 ZERO_STRUCT(data);
1181 return data;
1184 static void check_job_added(const char *sharename, TDB_DATA data, uint32_t jobid)
1186 unsigned int i;
1187 unsigned int job_count = data.dsize / 4;
1189 for (i = 0; i < job_count; i++) {
1190 uint32_t ch_jobid;
1192 ch_jobid = IVAL(data.dptr, i*4);
1193 if (ch_jobid == jobid)
1194 remove_from_jobs_added(sharename, jobid);
1198 /****************************************************************************
1199 Check if the print queue has been updated recently enough.
1200 ****************************************************************************/
1202 static bool print_cache_expired(const char *sharename, bool check_pending)
1204 fstring key;
1205 time_t last_qscan_time, time_now = time(NULL);
1206 struct tdb_print_db *pdb = get_print_db_byname(sharename);
1207 bool result = False;
1209 if (!pdb)
1210 return False;
1212 snprintf(key, sizeof(key), "CACHE/%s", sharename);
1213 last_qscan_time = (time_t)tdb_fetch_int32(pdb->tdb, key);
1216 * Invalidate the queue for 3 reasons.
1217 * (1). last queue scan time == -1.
1218 * (2). Current time - last queue scan time > allowed cache time.
1219 * (3). last queue scan time > current time + MAX_CACHE_VALID_TIME (1 hour by default).
1220 * This last test picks up machines for which the clock has been moved
1221 * forward, an lpq scan done and then the clock moved back. Otherwise
1222 * that last lpq scan would stay around for a loooong loooong time... :-). JRA.
1225 if (last_qscan_time == ((time_t)-1)
1226 || (time_now - last_qscan_time) >= lp_lpq_cache_time()
1227 || last_qscan_time > (time_now + MAX_CACHE_VALID_TIME))
1229 uint32_t u;
1230 time_t msg_pending_time;
1232 DEBUG(4, ("print_cache_expired: cache expired for queue %s "
1233 "(last_qscan_time = %d, time now = %d, qcachetime = %d)\n",
1234 sharename, (int)last_qscan_time, (int)time_now,
1235 (int)lp_lpq_cache_time() ));
1237 /* check if another smbd has already sent a message to update the
1238 queue. Give the pending message one minute to clear and
1239 then send another message anyways. Make sure to check for
1240 clocks that have been run forward and then back again. */
1242 snprintf(key, sizeof(key), "MSG_PENDING/%s", sharename);
1244 if ( check_pending
1245 && tdb_fetch_uint32( pdb->tdb, key, &u )
1246 && (msg_pending_time=u) > 0
1247 && msg_pending_time <= time_now
1248 && (time_now - msg_pending_time) < 60 )
1250 DEBUG(4,("print_cache_expired: message already pending for %s. Accepting cache\n",
1251 sharename));
1252 goto done;
1255 result = True;
1258 done:
1259 release_print_db(pdb);
1260 return result;
1263 /****************************************************************************
1264 main work for updating the lpq cache for a printer queue
1265 ****************************************************************************/
1267 static void print_queue_update_internal(struct tevent_context *ev,
1268 struct messaging_context *msg_ctx,
1269 const char *sharename,
1270 struct printif *current_printif,
1271 char *lpq_command, char *lprm_command)
1273 size_t i, qcount;
1274 print_queue_struct *queue = NULL;
1275 print_status_struct status;
1276 print_status_struct old_status;
1277 struct printjob *pjob;
1278 struct traverse_struct tstruct;
1279 TDB_DATA data, key;
1280 TDB_DATA jcdata;
1281 fstring keystr, cachestr;
1282 struct tdb_print_db *pdb = get_print_db_byname(sharename);
1283 TALLOC_CTX *tmp_ctx = talloc_new(ev);
1285 if ((pdb == NULL) || (tmp_ctx == NULL)) {
1286 return;
1289 DEBUG(5,("print_queue_update_internal: printer = %s, type = %d, lpq command = [%s]\n",
1290 sharename, current_printif->type, lpq_command));
1293 * Update the cache time FIRST ! Stops others even
1294 * attempting to get the lock and doing this
1295 * if the lpq takes a long time.
1298 slprintf(cachestr, sizeof(cachestr)-1, "CACHE/%s", sharename);
1299 tdb_store_int32(pdb->tdb, cachestr, (int)time(NULL));
1301 /* get the current queue using the appropriate interface */
1302 ZERO_STRUCT(status);
1304 qcount = (*(current_printif->queue_get))(sharename,
1305 current_printif->type,
1306 lpq_command, &queue, &status);
1308 DBG_NOTICE("%zu job%s in queue for %s\n",
1309 qcount,
1310 (qcount != 1) ? "s" : "",
1311 sharename);
1313 /* Sort the queue by submission time otherwise they are displayed
1314 in hash order. */
1316 TYPESAFE_QSORT(queue, qcount, printjob_comp);
1319 any job in the internal database that is marked as spooled
1320 and doesn't exist in the system queue is considered finished
1321 and removed from the database
1323 any job in the system database but not in the internal database
1324 is added as a unix job
1326 fill in any system job numbers as we go
1328 jcdata = get_jobs_added_data(pdb);
1330 for (i=0; i<qcount; i++) {
1331 uint32_t jobid = sysjob_to_jobid_pdb(pdb, queue[i].sysjob);
1332 if (jobid == (uint32_t)-1) {
1333 /* assume its a unix print job */
1334 print_unix_job(ev, msg_ctx,
1335 sharename, &queue[i], jobid);
1336 continue;
1339 /* we have an active SMB print job - update its status */
1340 pjob = print_job_find(tmp_ctx, sharename, jobid);
1341 if (!pjob) {
1342 /* err, somethings wrong. Probably smbd was restarted
1343 with jobs in the queue. All we can do is treat them
1344 like unix jobs. Pity. */
1345 DEBUG(1, ("queued print job %d not found in jobs list, "
1346 "assuming unix job\n", jobid));
1347 print_unix_job(ev, msg_ctx,
1348 sharename, &queue[i], jobid);
1349 continue;
1352 /* don't reset the status on jobs to be deleted */
1354 if ( pjob->status != LPQ_DELETING )
1355 pjob->status = queue[i].status;
1357 pjob_store(ev, msg_ctx, sharename, jobid, pjob);
1359 check_job_added(sharename, jcdata, jobid);
1362 SAFE_FREE(jcdata.dptr);
1364 /* now delete any queued entries that don't appear in the
1365 system queue */
1366 tstruct.queue = queue;
1367 tstruct.qcount = qcount;
1368 tstruct.snum = -1;
1369 tstruct.total_jobs = 0;
1370 tstruct.lpq_time = time(NULL);
1371 tstruct.sharename = sharename;
1372 tstruct.lprm_command = lprm_command;
1373 tstruct.print_if = current_printif;
1374 tstruct.ev = ev;
1375 tstruct.msg_ctx = msg_ctx;
1376 tstruct.mem_ctx = tmp_ctx;
1378 tdb_traverse(pdb->tdb, traverse_fn_delete, (void *)&tstruct);
1380 /* Store the linearised queue, max jobs only. */
1381 store_queue_struct(pdb, &tstruct);
1383 SAFE_FREE(tstruct.queue);
1384 talloc_free(tmp_ctx);
1386 DBG_DEBUG("printer %s INFO, total_jobs = %zu\n",
1387 sharename,
1388 tstruct.total_jobs);
1390 tdb_store_int32(pdb->tdb, "INFO/total_jobs", tstruct.total_jobs);
1392 get_queue_status(sharename, &old_status);
1393 if (old_status.qcount != qcount) {
1394 DBG_DEBUG("Queue status change %zu jobs -> %zu jobs "
1395 "for printer %s\n",
1396 old_status.qcount,
1397 qcount,
1398 sharename);
1401 /* store the new queue status structure */
1402 slprintf(keystr, sizeof(keystr)-1, "STATUS/%s", sharename);
1403 key = string_tdb_data(keystr);
1405 status.qcount = qcount;
1406 data.dptr = (uint8_t *)&status;
1407 data.dsize = sizeof(status);
1408 tdb_store(pdb->tdb, key, data, TDB_REPLACE);
1411 * Update the cache time again. We want to do this call
1412 * as little as possible...
1415 slprintf(keystr, sizeof(keystr)-1, "CACHE/%s", sharename);
1416 tdb_store_int32(pdb->tdb, keystr, (int32_t)time(NULL));
1418 /* clear the msg pending record for this queue */
1420 snprintf(keystr, sizeof(keystr), "MSG_PENDING/%s", sharename);
1422 if ( !tdb_store_uint32( pdb->tdb, keystr, 0 ) ) {
1423 /* log a message but continue on */
1425 DEBUG(0,("print_queue_update: failed to store MSG_PENDING flag for [%s]!\n",
1426 sharename));
1429 release_print_db( pdb );
1431 return;
1434 /****************************************************************************
1435 Update the internal database from the system print queue for a queue.
1436 obtain a lock on the print queue before proceeding (needed when multiple
1437 smbd processes maytry to update the lpq cache concurrently).
1438 ****************************************************************************/
1440 static void print_queue_update_with_lock( struct tevent_context *ev,
1441 struct messaging_context *msg_ctx,
1442 const char *sharename,
1443 struct printif *current_printif,
1444 char *lpq_command, char *lprm_command )
1446 fstring keystr;
1447 struct tdb_print_db *pdb;
1449 DEBUG(5,("print_queue_update_with_lock: printer share = %s\n", sharename));
1450 pdb = get_print_db_byname(sharename);
1451 if (!pdb)
1452 return;
1454 if ( !print_cache_expired(sharename, False) ) {
1455 DEBUG(5,("print_queue_update_with_lock: print cache for %s is still ok\n", sharename));
1456 release_print_db(pdb);
1457 return;
1461 * Check to see if someone else is doing this update.
1462 * This is essentially a mutex on the update.
1465 if (get_updating_pid(sharename) != -1) {
1466 release_print_db(pdb);
1467 return;
1470 /* Lock the queue for the database update */
1472 slprintf(keystr, sizeof(keystr) - 1, "LOCK/%s", sharename);
1473 /* Only wait 10 seconds for this. */
1474 if (tdb_lock_bystring_with_timeout(pdb->tdb, keystr, 10) != 0) {
1475 DEBUG(0,("print_queue_update_with_lock: Failed to lock printer %s database\n", sharename));
1476 release_print_db(pdb);
1477 return;
1481 * Ensure that no one else got in here.
1482 * If the updating pid is still -1 then we are
1483 * the winner.
1486 if (get_updating_pid(sharename) != -1) {
1488 * Someone else is doing the update, exit.
1490 tdb_unlock_bystring(pdb->tdb, keystr);
1491 release_print_db(pdb);
1492 return;
1496 * We're going to do the update ourselves.
1499 /* Tell others we're doing the update. */
1500 set_updating_pid(sharename, True);
1503 * Allow others to enter and notice we're doing
1504 * the update.
1507 tdb_unlock_bystring(pdb->tdb, keystr);
1509 /* do the main work now */
1511 print_queue_update_internal(ev, msg_ctx,
1512 sharename, current_printif,
1513 lpq_command, lprm_command);
1515 /* Delete our pid from the db. */
1516 set_updating_pid(sharename, False);
1517 release_print_db(pdb);
1520 /****************************************************************************
1521 this is the receive function of the background lpq updater
1522 ****************************************************************************/
1523 void print_queue_receive(struct messaging_context *msg,
1524 void *private_data,
1525 uint32_t msg_type,
1526 struct server_id server_id,
1527 DATA_BLOB *data)
1529 fstring sharename;
1530 char *lpqcommand = NULL, *lprmcommand = NULL;
1531 int printing_type;
1532 size_t len;
1534 len = tdb_unpack( (uint8_t *)data->data, data->length, "fdPP",
1535 sharename,
1536 &printing_type,
1537 &lpqcommand,
1538 &lprmcommand );
1540 if ( len == -1 ) {
1541 SAFE_FREE(lpqcommand);
1542 SAFE_FREE(lprmcommand);
1543 DEBUG(0,("print_queue_receive: Got invalid print queue update message\n"));
1544 return;
1547 print_queue_update_with_lock(global_event_context(), msg, sharename,
1548 get_printer_fns_from_type((enum printing_types)printing_type),
1549 lpqcommand, lprmcommand );
1551 SAFE_FREE(lpqcommand);
1552 SAFE_FREE(lprmcommand);
1553 return;
1556 /****************************************************************************
1557 update the internal database from the system print queue for a queue
1558 ****************************************************************************/
1560 static void print_queue_update(struct messaging_context *msg_ctx,
1561 int snum, bool force)
1563 char key[268];
1564 fstring sharename;
1565 char *lpqcommand = NULL;
1566 char *lprmcommand = NULL;
1567 uint8_t *buffer = NULL;
1568 size_t len = 0;
1569 size_t newlen;
1570 struct tdb_print_db *pdb;
1571 int type;
1572 struct printif *current_printif;
1573 TALLOC_CTX *ctx = talloc_tos();
1574 const struct loadparm_substitution *lp_sub =
1575 loadparm_s3_global_substitution();
1577 fstrcpy( sharename, lp_const_servicename(snum));
1579 /* don't strip out characters like '$' from the printername */
1581 lpqcommand = talloc_string_sub2(ctx,
1582 lp_lpq_command(snum),
1583 "%p",
1584 lp_printername(talloc_tos(), lp_sub, snum),
1585 false, false, false);
1586 if (!lpqcommand) {
1587 return;
1589 lpqcommand = talloc_sub_full(ctx,
1590 lp_servicename(talloc_tos(), lp_sub, snum),
1591 current_user_info.unix_name,
1593 get_current_gid(NULL),
1594 get_current_username(),
1595 get_current_user_info_domain(),
1596 lpqcommand);
1597 if (!lpqcommand) {
1598 return;
1601 lprmcommand = talloc_string_sub2(ctx,
1602 lp_lprm_command(snum),
1603 "%p",
1604 lp_printername(talloc_tos(), lp_sub, snum),
1605 false, false, false);
1606 if (!lprmcommand) {
1607 return;
1609 lprmcommand = talloc_sub_full(ctx,
1610 lp_servicename(talloc_tos(), lp_sub, snum),
1611 current_user_info.unix_name,
1613 get_current_gid(NULL),
1614 get_current_username(),
1615 get_current_user_info_domain(),
1616 lprmcommand);
1617 if (!lprmcommand) {
1618 return;
1622 * Make sure that the background queue process exists.
1623 * Otherwise just do the update ourselves
1626 if ( force || background_lpq_updater_pid == -1 ) {
1627 DEBUG(4,("print_queue_update: updating queue [%s] myself\n", sharename));
1628 current_printif = get_printer_fns( snum );
1629 print_queue_update_with_lock(global_event_context(), msg_ctx,
1630 sharename, current_printif,
1631 lpqcommand, lprmcommand);
1633 return;
1636 type = lp_printing(snum);
1638 /* get the length */
1640 len = tdb_pack( NULL, 0, "fdPP",
1641 sharename,
1642 type,
1643 lpqcommand,
1644 lprmcommand );
1646 buffer = SMB_XMALLOC_ARRAY( uint8_t, len );
1648 /* now pack the buffer */
1649 newlen = tdb_pack( buffer, len, "fdPP",
1650 sharename,
1651 type,
1652 lpqcommand,
1653 lprmcommand );
1655 SMB_ASSERT( newlen == len );
1657 DEBUG(10,("print_queue_update: Sending message -> printer = %s, "
1658 "type = %d, lpq command = [%s] lprm command = [%s]\n",
1659 sharename, type, lpqcommand, lprmcommand ));
1661 /* here we set a msg pending record for other smbd processes
1662 to throttle the number of duplicate print_queue_update msgs
1663 sent. */
1665 pdb = get_print_db_byname(sharename);
1666 if (!pdb) {
1667 SAFE_FREE(buffer);
1668 return;
1671 snprintf(key, sizeof(key), "MSG_PENDING/%s", sharename);
1673 if ( !tdb_store_uint32( pdb->tdb, key, time(NULL) ) ) {
1674 /* log a message but continue on */
1676 DEBUG(0,("print_queue_update: failed to store MSG_PENDING flag for [%s]!\n",
1677 sharename));
1680 release_print_db( pdb );
1682 /* finally send the message */
1684 send_to_bgqd(msg_ctx, MSG_PRINTER_UPDATE, (uint8_t *)buffer, len);
1686 SAFE_FREE( buffer );
1688 return;
1691 /****************************************************************************
1692 Create/Update an entry in the print tdb that will allow us to send notify
1693 updates only to interested smbd's.
1694 ****************************************************************************/
1696 bool print_notify_register_pid(int snum)
1698 TDB_DATA data;
1699 struct tdb_print_db *pdb = NULL;
1700 TDB_CONTEXT *tdb = NULL;
1701 const char *printername;
1702 uint32_t mypid = (uint32_t)getpid();
1703 bool ret = False;
1704 size_t i;
1706 /* if (snum == -1), then the change notify request was
1707 on a print server handle and we need to register on
1708 all print queues */
1710 if (snum == -1)
1712 int num_services = lp_numservices();
1713 int idx;
1715 for ( idx=0; idx<num_services; idx++ ) {
1716 if (lp_snum_ok(idx) && lp_printable(idx) )
1717 print_notify_register_pid(idx);
1720 return True;
1722 else /* register for a specific printer */
1724 printername = lp_const_servicename(snum);
1725 pdb = get_print_db_byname(printername);
1726 if (!pdb)
1727 return False;
1728 tdb = pdb->tdb;
1731 if (tdb_lock_bystring_with_timeout(tdb, NOTIFY_PID_LIST_KEY, 10) != 0) {
1732 DEBUG(0,("print_notify_register_pid: Failed to lock printer %s\n",
1733 printername));
1734 if (pdb)
1735 release_print_db(pdb);
1736 return False;
1739 data = get_printer_notify_pid_list( tdb, printername, True );
1741 /* Add ourselves and increase the refcount. */
1743 for (i = 0; i < data.dsize; i += 8) {
1744 if (IVAL(data.dptr,i) == mypid) {
1745 uint32_t new_refcount = IVAL(data.dptr, i+4) + 1;
1746 SIVAL(data.dptr, i+4, new_refcount);
1747 break;
1751 if (i == data.dsize) {
1752 /* We weren't in the list. Realloc. */
1753 data.dptr = (uint8_t *)SMB_REALLOC(data.dptr, data.dsize + 8);
1754 if (!data.dptr) {
1755 DEBUG(0,("print_notify_register_pid: Relloc fail for printer %s\n",
1756 printername));
1757 goto done;
1759 data.dsize += 8;
1760 SIVAL(data.dptr,data.dsize - 8,mypid);
1761 SIVAL(data.dptr,data.dsize - 4,1); /* Refcount. */
1764 /* Store back the record. */
1765 if (tdb_store_bystring(tdb, NOTIFY_PID_LIST_KEY, data, TDB_REPLACE) != 0) {
1766 DEBUG(0,("print_notify_register_pid: Failed to update pid \
1767 list for printer %s\n", printername));
1768 goto done;
1771 ret = True;
1773 done:
1775 tdb_unlock_bystring(tdb, NOTIFY_PID_LIST_KEY);
1776 if (pdb)
1777 release_print_db(pdb);
1778 SAFE_FREE(data.dptr);
1779 return ret;
1782 /****************************************************************************
1783 Update an entry in the print tdb that will allow us to send notify
1784 updates only to interested smbd's.
1785 ****************************************************************************/
1787 bool print_notify_deregister_pid(int snum)
1789 TDB_DATA data;
1790 struct tdb_print_db *pdb = NULL;
1791 TDB_CONTEXT *tdb = NULL;
1792 const char *printername;
1793 uint32_t mypid = (uint32_t)getpid();
1794 size_t i;
1795 bool ret = False;
1797 /* if ( snum == -1 ), we are deregister a print server handle
1798 which means to deregister on all print queues */
1800 if (snum == -1)
1802 int num_services = lp_numservices();
1803 int idx;
1805 for ( idx=0; idx<num_services; idx++ ) {
1806 if ( lp_snum_ok(idx) && lp_printable(idx) )
1807 print_notify_deregister_pid(idx);
1810 return True;
1812 else /* deregister a specific printer */
1814 printername = lp_const_servicename(snum);
1815 pdb = get_print_db_byname(printername);
1816 if (!pdb)
1817 return False;
1818 tdb = pdb->tdb;
1821 if (tdb_lock_bystring_with_timeout(tdb, NOTIFY_PID_LIST_KEY, 10) != 0) {
1822 DEBUG(0,("print_notify_register_pid: Failed to lock \
1823 printer %s database\n", printername));
1824 if (pdb)
1825 release_print_db(pdb);
1826 return False;
1829 data = get_printer_notify_pid_list( tdb, printername, True );
1831 /* Reduce refcount. Remove ourselves if zero. */
1833 for (i = 0; i < data.dsize; ) {
1834 if (IVAL(data.dptr,i) == mypid) {
1835 uint32_t refcount = IVAL(data.dptr, i+4);
1837 refcount--;
1839 if (refcount == 0) {
1840 if (data.dsize - i > 8)
1841 memmove( &data.dptr[i], &data.dptr[i+8], data.dsize - i - 8);
1842 data.dsize -= 8;
1843 continue;
1845 SIVAL(data.dptr, i+4, refcount);
1848 i += 8;
1851 if (data.dsize == 0)
1852 SAFE_FREE(data.dptr);
1854 /* Store back the record. */
1855 if (tdb_store_bystring(tdb, NOTIFY_PID_LIST_KEY, data, TDB_REPLACE) != 0) {
1856 DEBUG(0,("print_notify_register_pid: Failed to update pid \
1857 list for printer %s\n", printername));
1858 goto done;
1861 ret = True;
1863 done:
1865 tdb_unlock_bystring(tdb, NOTIFY_PID_LIST_KEY);
1866 if (pdb)
1867 release_print_db(pdb);
1868 SAFE_FREE(data.dptr);
1869 return ret;
1872 /****************************************************************************
1873 Check if a jobid is valid. It is valid if it exists in the database.
1874 ****************************************************************************/
1876 bool print_job_exists(const char* sharename, uint32_t jobid)
1878 struct tdb_print_db *pdb = get_print_db_byname(sharename);
1879 bool ret;
1880 uint32_t tmp;
1882 if (!pdb)
1883 return False;
1884 ret = tdb_exists(pdb->tdb, print_key(jobid, &tmp));
1885 release_print_db(pdb);
1886 return ret;
1889 /****************************************************************************
1890 Return the device mode assigned to a specific print job.
1891 Only valid for the process doing the spooling and when the job
1892 has not been spooled.
1893 ****************************************************************************/
1895 struct spoolss_DeviceMode *print_job_devmode(TALLOC_CTX *mem_ctx,
1896 const char *sharename,
1897 uint32_t jobid)
1899 struct printjob *pjob = print_job_find(mem_ctx, sharename, jobid);
1900 if (pjob == NULL) {
1901 return NULL;
1904 return pjob->devmode;
1907 /****************************************************************************
1908 Set the name of a job. Only possible for owner.
1909 ****************************************************************************/
1911 bool print_job_set_name(struct tevent_context *ev,
1912 struct messaging_context *msg_ctx,
1913 const char *sharename, uint32_t jobid, const char *name)
1915 struct printjob *pjob;
1916 bool ret;
1917 TALLOC_CTX *tmp_ctx = talloc_new(ev);
1918 if (tmp_ctx == NULL) {
1919 return false;
1922 pjob = print_job_find(tmp_ctx, sharename, jobid);
1923 if (!pjob || pjob->pid != getpid()) {
1924 ret = false;
1925 goto err_out;
1928 fstrcpy(pjob->jobname, name);
1929 ret = pjob_store(ev, msg_ctx, sharename, jobid, pjob);
1930 err_out:
1931 talloc_free(tmp_ctx);
1932 return ret;
1935 /****************************************************************************
1936 Get the name of a job. Only possible for owner.
1937 ****************************************************************************/
1939 bool print_job_get_name(TALLOC_CTX *mem_ctx, const char *sharename, uint32_t jobid, char **name)
1941 struct printjob *pjob;
1943 pjob = print_job_find(mem_ctx, sharename, jobid);
1944 if (!pjob || pjob->pid != getpid()) {
1945 return false;
1948 *name = pjob->jobname;
1949 return true;
1953 /***************************************************************************
1954 Remove a jobid from the 'jobs added' list.
1955 ***************************************************************************/
1957 static bool remove_from_jobs_added(const char* sharename, uint32_t jobid)
1959 bool ret = remove_from_jobs_list("INFO/jobs_added", sharename, jobid);
1960 return ret;
1963 /****************************************************************************
1964 Delete a print job - don't update queue.
1965 ****************************************************************************/
1967 static bool print_job_delete1(struct tevent_context *ev,
1968 struct messaging_context *msg_ctx,
1969 int snum, uint32_t jobid)
1971 const char* sharename = lp_const_servicename(snum);
1972 const struct loadparm_substitution *lp_sub =
1973 loadparm_s3_global_substitution();
1974 struct printjob *pjob;
1975 int result = 0;
1976 struct printif *current_printif = get_printer_fns( snum );
1977 bool ret;
1978 TALLOC_CTX *tmp_ctx = talloc_new(ev);
1979 if (tmp_ctx == NULL) {
1980 return false;
1983 pjob = print_job_find(tmp_ctx, sharename, jobid);
1984 if (!pjob) {
1985 ret = false;
1986 goto err_out;
1990 * If already deleting just return.
1993 if (pjob->status == LPQ_DELETING) {
1994 ret = true;
1995 goto err_out;
1998 /* Hrm - we need to be able to cope with deleting a job before it
1999 has reached the spooler. Just mark it as LPQ_DELETING and
2000 let the print_queue_update() code remove the record */
2003 if (pjob->sysjob == -1) {
2004 DEBUG(5, ("attempt to delete job %u not seen by lpr\n", (unsigned int)jobid));
2007 /* Set the tdb entry to be deleting. */
2009 pjob->status = LPQ_DELETING;
2010 pjob_store(ev, msg_ctx, sharename, jobid, pjob);
2012 if (pjob->spooled && pjob->sysjob != -1)
2014 result = (*(current_printif->job_delete))(
2015 lp_printername(talloc_tos(), lp_sub, snum),
2016 lp_lprm_command(snum),
2017 pjob);
2019 /* Delete the tdb entry if the delete succeeded or the job hasn't
2020 been spooled. */
2022 if (result == 0) {
2023 struct tdb_print_db *pdb = get_print_db_byname(sharename);
2024 int njobs = 1;
2026 if (!pdb) {
2027 ret = false;
2028 goto err_out;
2030 pjob_delete(ev, msg_ctx, sharename, jobid);
2031 /* Ensure we keep a rough count of the number of total jobs... */
2032 tdb_change_int32_atomic(pdb->tdb, "INFO/total_jobs", &njobs, -1);
2033 release_print_db(pdb);
2037 remove_from_jobs_added( sharename, jobid );
2039 ret = (result == 0);
2040 err_out:
2041 talloc_free(tmp_ctx);
2042 return ret;
2045 /****************************************************************************
2046 Return true if the current user owns the print job.
2047 ****************************************************************************/
2049 static bool is_owner(const struct auth_session_info *server_info,
2050 const char *servicename,
2051 uint32_t jobid)
2053 struct printjob *pjob;
2054 bool ret;
2055 TALLOC_CTX *tmp_ctx = talloc_new(server_info);
2056 if (tmp_ctx == NULL) {
2057 return false;
2060 pjob = print_job_find(tmp_ctx, servicename, jobid);
2061 if (!pjob || !server_info) {
2062 ret = false;
2063 goto err_out;
2066 ret = strequal(pjob->user, server_info->unix_info->sanitized_username);
2067 err_out:
2068 talloc_free(tmp_ctx);
2069 return ret;
2072 /****************************************************************************
2073 Delete a print job.
2074 ****************************************************************************/
2076 WERROR print_job_delete(const struct auth_session_info *server_info,
2077 struct messaging_context *msg_ctx,
2078 int snum, uint32_t jobid)
2080 const char* sharename = lp_const_servicename(snum);
2081 const struct loadparm_substitution *lp_sub =
2082 loadparm_s3_global_substitution();
2083 struct printjob *pjob;
2084 bool owner;
2085 WERROR werr;
2086 TALLOC_CTX *tmp_ctx = talloc_new(msg_ctx);
2087 if (tmp_ctx == NULL) {
2088 return WERR_NOT_ENOUGH_MEMORY;
2091 owner = is_owner(server_info, lp_const_servicename(snum), jobid);
2093 /* Check access against security descriptor or whether the user
2094 owns their job. */
2096 if (!owner &&
2097 !W_ERROR_IS_OK(print_access_check(server_info, msg_ctx, snum,
2098 JOB_ACCESS_ADMINISTER))) {
2099 DEBUG(0, ("print job delete denied. "
2100 "User name: %s, Printer name: %s.\n",
2101 uidtoname(server_info->unix_token->uid),
2102 lp_printername(tmp_ctx, lp_sub, snum)));
2104 werr = WERR_ACCESS_DENIED;
2105 goto err_out;
2109 * get the spooled filename of the print job
2110 * if this works, then the file has not been spooled
2111 * to the underlying print system. Just delete the
2112 * spool file & return.
2115 pjob = print_job_find(tmp_ctx, sharename, jobid);
2116 if (!pjob || pjob->spooled || pjob->pid != getpid()) {
2117 DEBUG(10, ("Skipping spool file removal for job %u\n", jobid));
2118 } else {
2119 DEBUG(10, ("Removing spool file [%s]\n", pjob->filename));
2120 if (unlink(pjob->filename) == -1) {
2121 werr = map_werror_from_unix(errno);
2122 goto err_out;
2126 if (!print_job_delete1(global_event_context(), msg_ctx, snum, jobid)) {
2127 werr = WERR_ACCESS_DENIED;
2128 goto err_out;
2131 /* force update the database and say the delete failed if the
2132 job still exists */
2134 print_queue_update(msg_ctx, snum, True);
2136 pjob = print_job_find(tmp_ctx, sharename, jobid);
2137 if (pjob && (pjob->status != LPQ_DELETING)) {
2138 werr = WERR_ACCESS_DENIED;
2139 goto err_out;
2141 werr = WERR_PRINTER_HAS_JOBS_QUEUED;
2143 err_out:
2144 talloc_free(tmp_ctx);
2145 return werr;
2148 /****************************************************************************
2149 Pause a job.
2150 ****************************************************************************/
2152 WERROR print_job_pause(const struct auth_session_info *server_info,
2153 struct messaging_context *msg_ctx,
2154 int snum, uint32_t jobid)
2156 const char* sharename = lp_const_servicename(snum);
2157 const struct loadparm_substitution *lp_sub =
2158 loadparm_s3_global_substitution();
2159 struct printjob *pjob;
2160 int ret = -1;
2161 struct printif *current_printif = get_printer_fns( snum );
2162 WERROR werr;
2163 TALLOC_CTX *tmp_ctx = talloc_new(msg_ctx);
2164 if (tmp_ctx == NULL) {
2165 return WERR_NOT_ENOUGH_MEMORY;
2168 pjob = print_job_find(tmp_ctx, sharename, jobid);
2169 if (!pjob || !server_info) {
2170 DEBUG(10, ("print_job_pause: no pjob or user for jobid %u\n",
2171 (unsigned int)jobid ));
2172 werr = WERR_INVALID_PARAMETER;
2173 goto err_out;
2176 if (!pjob->spooled || pjob->sysjob == -1) {
2177 DEBUG(10, ("print_job_pause: not spooled or bad sysjob = %d for jobid %u\n",
2178 (int)pjob->sysjob, (unsigned int)jobid ));
2179 werr = WERR_INVALID_PARAMETER;
2180 goto err_out;
2183 if (!is_owner(server_info, lp_const_servicename(snum), jobid) &&
2184 !W_ERROR_IS_OK(print_access_check(server_info, msg_ctx, snum,
2185 JOB_ACCESS_ADMINISTER))) {
2186 DEBUG(0, ("print job pause denied. "
2187 "User name: %s, Printer name: %s.\n",
2188 uidtoname(server_info->unix_token->uid),
2189 lp_printername(tmp_ctx, lp_sub, snum)));
2191 werr = WERR_ACCESS_DENIED;
2192 goto err_out;
2195 /* need to pause the spooled entry */
2196 ret = (*(current_printif->job_pause))(snum, pjob);
2198 if (ret != 0) {
2199 werr = WERR_INVALID_PARAMETER;
2200 goto err_out;
2203 /* force update the database */
2204 print_cache_flush(lp_const_servicename(snum));
2206 /* Send a printer notify message */
2208 notify_job_status(global_event_context(), msg_ctx, sharename, jobid,
2209 JOB_STATUS_PAUSED);
2211 /* how do we tell if this succeeded? */
2212 werr = WERR_OK;
2213 err_out:
2214 talloc_free(tmp_ctx);
2215 return werr;
2218 /****************************************************************************
2219 Resume a job.
2220 ****************************************************************************/
2222 WERROR print_job_resume(const struct auth_session_info *server_info,
2223 struct messaging_context *msg_ctx,
2224 int snum, uint32_t jobid)
2226 const char *sharename = lp_const_servicename(snum);
2227 const struct loadparm_substitution *lp_sub =
2228 loadparm_s3_global_substitution();
2229 struct printjob *pjob;
2230 int ret;
2231 struct printif *current_printif = get_printer_fns( snum );
2232 WERROR werr;
2233 TALLOC_CTX *tmp_ctx = talloc_new(msg_ctx);
2234 if (tmp_ctx == NULL)
2235 return WERR_NOT_ENOUGH_MEMORY;
2237 pjob = print_job_find(tmp_ctx, sharename, jobid);
2238 if (!pjob || !server_info) {
2239 DEBUG(10, ("print_job_resume: no pjob or user for jobid %u\n",
2240 (unsigned int)jobid ));
2241 werr = WERR_INVALID_PARAMETER;
2242 goto err_out;
2245 if (!pjob->spooled || pjob->sysjob == -1) {
2246 DEBUG(10, ("print_job_resume: not spooled or bad sysjob = %d for jobid %u\n",
2247 (int)pjob->sysjob, (unsigned int)jobid ));
2248 werr = WERR_INVALID_PARAMETER;
2249 goto err_out;
2252 if (!is_owner(server_info, lp_const_servicename(snum), jobid) &&
2253 !W_ERROR_IS_OK(print_access_check(server_info, msg_ctx, snum,
2254 JOB_ACCESS_ADMINISTER))) {
2255 DEBUG(0, ("print job resume denied. "
2256 "User name: %s, Printer name: %s.\n",
2257 uidtoname(server_info->unix_token->uid),
2258 lp_printername(tmp_ctx, lp_sub, snum)));
2260 werr = WERR_ACCESS_DENIED;
2261 goto err_out;
2264 ret = (*(current_printif->job_resume))(snum, pjob);
2266 if (ret != 0) {
2267 werr = WERR_INVALID_PARAMETER;
2268 goto err_out;
2271 /* force update the database */
2272 print_cache_flush(lp_const_servicename(snum));
2274 /* Send a printer notify message */
2276 notify_job_status(global_event_context(), msg_ctx, sharename, jobid,
2277 JOB_STATUS_QUEUED);
2279 werr = WERR_OK;
2280 err_out:
2281 talloc_free(tmp_ctx);
2282 return werr;
2285 /****************************************************************************
2286 Write to a print file.
2287 ****************************************************************************/
2289 ssize_t print_job_write(struct tevent_context *ev,
2290 struct messaging_context *msg_ctx,
2291 int snum, uint32_t jobid, const char *buf, size_t size)
2293 const char* sharename = lp_const_servicename(snum);
2294 ssize_t return_code;
2295 struct printjob *pjob;
2296 TALLOC_CTX *tmp_ctx = talloc_new(ev);
2297 if (tmp_ctx == NULL) {
2298 return -1;
2301 pjob = print_job_find(tmp_ctx, sharename, jobid);
2302 if (!pjob) {
2303 return_code = -1;
2304 goto err_out;
2307 /* don't allow another process to get this info - it is meaningless */
2308 if (pjob->pid != getpid()) {
2309 return_code = -1;
2310 goto err_out;
2313 /* if SMBD is spooling this can't be allowed */
2314 if (pjob->status == PJOB_SMBD_SPOOLING) {
2315 return_code = -1;
2316 goto err_out;
2319 return_code = write_data(pjob->fd, buf, size);
2320 if (return_code > 0) {
2321 pjob->size += size;
2322 pjob_store(ev, msg_ctx, sharename, jobid, pjob);
2324 err_out:
2325 talloc_free(tmp_ctx);
2326 return return_code;
2329 /****************************************************************************
2330 Get the queue status - do not update if db is out of date.
2331 ****************************************************************************/
2333 static int get_queue_status(const char* sharename, print_status_struct *status)
2335 fstring keystr;
2336 TDB_DATA data;
2337 struct tdb_print_db *pdb = get_print_db_byname(sharename);
2338 int len;
2340 if (status) {
2341 ZERO_STRUCTP(status);
2344 if (!pdb)
2345 return 0;
2347 if (status) {
2348 fstr_sprintf(keystr, "STATUS/%s", sharename);
2349 data = tdb_fetch(pdb->tdb, string_tdb_data(keystr));
2350 if (data.dptr) {
2351 if (data.dsize == sizeof(print_status_struct))
2352 /* this memcpy is ok since the status struct was
2353 not packed before storing it in the tdb */
2354 memcpy(status, data.dptr, sizeof(print_status_struct));
2355 SAFE_FREE(data.dptr);
2358 len = tdb_fetch_int32(pdb->tdb, "INFO/total_jobs");
2359 release_print_db(pdb);
2360 return (len == -1 ? 0 : len);
2363 /****************************************************************************
2364 Determine the number of jobs in a queue.
2365 ****************************************************************************/
2367 int print_queue_length(struct messaging_context *msg_ctx, int snum,
2368 print_status_struct *pstatus)
2370 const char* sharename = lp_const_servicename( snum );
2371 print_status_struct status;
2372 int len;
2374 ZERO_STRUCT( status );
2376 /* make sure the database is up to date */
2377 if (print_cache_expired(lp_const_servicename(snum), True))
2378 print_queue_update(msg_ctx, snum, False);
2380 /* also fetch the queue status */
2381 memset(&status, 0, sizeof(status));
2382 len = get_queue_status(sharename, &status);
2384 if (pstatus)
2385 *pstatus = status;
2387 return len;
2390 /***************************************************************************
2391 Allocate a jobid. Hold the lock for as short a time as possible.
2392 ***************************************************************************/
2394 static WERROR allocate_print_jobid(struct tdb_print_db *pdb, int snum,
2395 const char *sharename, uint32_t *pjobid)
2397 int i;
2398 uint32_t jobid;
2399 enum TDB_ERROR terr;
2400 int ret;
2402 *pjobid = (uint32_t)-1;
2404 for (i = 0; i < 3; i++) {
2405 /* Lock the database - only wait 20 seconds. */
2406 ret = tdb_lock_bystring_with_timeout(pdb->tdb,
2407 "INFO/nextjob", 20);
2408 if (ret != 0) {
2409 DEBUG(0, ("allocate_print_jobid: "
2410 "Failed to lock printing database %s\n",
2411 sharename));
2412 terr = tdb_error(pdb->tdb);
2413 return ntstatus_to_werror(map_nt_error_from_tdb(terr));
2416 if (!tdb_fetch_uint32(pdb->tdb, "INFO/nextjob", &jobid)) {
2417 terr = tdb_error(pdb->tdb);
2418 if (terr != TDB_ERR_NOEXIST) {
2419 DEBUG(0, ("allocate_print_jobid: "
2420 "Failed to fetch INFO/nextjob "
2421 "for print queue %s\n", sharename));
2422 tdb_unlock_bystring(pdb->tdb, "INFO/nextjob");
2423 return ntstatus_to_werror(map_nt_error_from_tdb(terr));
2425 DEBUG(10, ("allocate_print_jobid: "
2426 "No existing jobid in %s\n", sharename));
2427 jobid = 0;
2430 DEBUG(10, ("allocate_print_jobid: "
2431 "Read jobid %u from %s\n", jobid, sharename));
2433 jobid = NEXT_JOBID(jobid);
2435 ret = tdb_store_int32(pdb->tdb, "INFO/nextjob", jobid);
2436 if (ret != 0) {
2437 terr = tdb_error(pdb->tdb);
2438 DEBUG(3, ("allocate_print_jobid: "
2439 "Failed to store INFO/nextjob.\n"));
2440 tdb_unlock_bystring(pdb->tdb, "INFO/nextjob");
2441 return ntstatus_to_werror(map_nt_error_from_tdb(terr));
2444 /* We've finished with the INFO/nextjob lock. */
2445 tdb_unlock_bystring(pdb->tdb, "INFO/nextjob");
2447 if (!print_job_exists(sharename, jobid)) {
2448 break;
2450 DEBUG(10, ("allocate_print_jobid: "
2451 "Found jobid %u in %s\n", jobid, sharename));
2454 if (i > 2) {
2455 DEBUG(0, ("allocate_print_jobid: "
2456 "Failed to allocate a print job for queue %s\n",
2457 sharename));
2458 /* Probably full... */
2459 return WERR_NO_SPOOL_SPACE;
2462 /* Store a dummy placeholder. */
2464 uint32_t tmp;
2465 TDB_DATA dummy = {
2466 .dsize = 0,
2468 if (tdb_store(pdb->tdb, print_key(jobid, &tmp), dummy,
2469 TDB_INSERT) != 0) {
2470 DEBUG(3, ("allocate_print_jobid: "
2471 "jobid (%d) failed to store placeholder.\n",
2472 jobid ));
2473 terr = tdb_error(pdb->tdb);
2474 return ntstatus_to_werror(map_nt_error_from_tdb(terr));
2478 *pjobid = jobid;
2479 return WERR_OK;
2482 /***************************************************************************
2483 Do all checks needed to determine if we can start a job.
2484 ***************************************************************************/
2486 static WERROR print_job_checks(const struct auth_session_info *server_info,
2487 struct messaging_context *msg_ctx,
2488 int snum, int *njobs)
2490 const char *sharename = lp_const_servicename(snum);
2491 const struct loadparm_substitution *lp_sub =
2492 loadparm_s3_global_substitution();
2493 uint64_t dspace, dsize;
2494 uint64_t minspace;
2495 int ret;
2497 if (!W_ERROR_IS_OK(print_access_check(server_info, msg_ctx, snum,
2498 PRINTER_ACCESS_USE))) {
2499 DEBUG(3, ("print_job_checks: "
2500 "job start denied by security descriptor\n"));
2501 return WERR_ACCESS_DENIED;
2504 if (!print_time_access_check(server_info, msg_ctx, sharename)) {
2505 DEBUG(3, ("print_job_checks: "
2506 "job start denied by time check\n"));
2507 return WERR_ACCESS_DENIED;
2510 /* see if we have sufficient disk space */
2511 if (lp_min_print_space(snum)) {
2512 minspace = lp_min_print_space(snum);
2513 ret = sys_fsusage(lp_path(talloc_tos(), lp_sub, snum), &dspace, &dsize);
2514 if (ret == 0 && dspace < 2*minspace) {
2515 DEBUG(3, ("print_job_checks: "
2516 "disk space check failed.\n"));
2517 return WERR_NO_SPOOL_SPACE;
2521 /* for autoloaded printers, check that the printcap entry still exists */
2522 if (lp_autoloaded(snum) &&
2523 !printer_list_printername_exists(sharename)) {
2524 DEBUG(3, ("print_job_checks: printer name %s check failed.\n",
2525 sharename));
2526 return WERR_ACCESS_DENIED;
2529 /* Insure the maximum queue size is not violated */
2530 *njobs = print_queue_length(msg_ctx, snum, NULL);
2531 if (*njobs > lp_maxprintjobs(snum)) {
2532 DEBUG(3, ("print_job_checks: Queue %s number of jobs (%d) "
2533 "larger than max printjobs per queue (%d).\n",
2534 sharename, *njobs, lp_maxprintjobs(snum)));
2535 return WERR_NO_SPOOL_SPACE;
2538 return WERR_OK;
2541 /***************************************************************************
2542 Create a job file.
2543 ***************************************************************************/
2545 static WERROR print_job_spool_file(int snum, uint32_t jobid,
2546 const char *output_file,
2547 struct printjob *pjob)
2549 const struct loadparm_substitution *lp_sub =
2550 loadparm_s3_global_substitution();
2551 WERROR werr;
2552 SMB_STRUCT_STAT st;
2553 const char *path;
2554 int len;
2555 mode_t mask;
2557 /* if this file is within the printer path, it means that smbd
2558 * is spooling it and will pass us control when it is finished.
2559 * Verify that the file name is ok, within path, and it is
2560 * already already there */
2561 if (output_file) {
2562 path = lp_path(talloc_tos(), lp_sub, snum);
2563 len = strlen(path);
2564 if (strncmp(output_file, path, len) == 0 &&
2565 (output_file[len - 1] == '/' || output_file[len] == '/')) {
2567 /* verify path is not too long */
2568 if (strlen(output_file) >= sizeof(pjob->filename)) {
2569 return WERR_INVALID_NAME;
2572 /* verify that the file exists */
2573 if (sys_stat(output_file, &st, false) != 0) {
2574 return WERR_INVALID_NAME;
2577 fstrcpy(pjob->filename, output_file);
2579 DEBUG(3, ("print_job_spool_file:"
2580 "External spooling activated\n"));
2582 /* we do not open the file until spooling is done */
2583 pjob->fd = -1;
2584 pjob->status = PJOB_SMBD_SPOOLING;
2586 return WERR_OK;
2590 slprintf(pjob->filename, sizeof(pjob->filename)-1,
2591 "%s/%sXXXXXX", lp_path(talloc_tos(), lp_sub, snum),
2592 PRINT_SPOOL_PREFIX);
2593 mask = umask(S_IRWXO | S_IRWXG);
2594 pjob->fd = mkstemp(pjob->filename);
2595 umask(mask);
2597 if (pjob->fd == -1) {
2598 werr = map_werror_from_unix(errno);
2599 if (W_ERROR_EQUAL(werr, WERR_ACCESS_DENIED)) {
2600 /* Common setup error, force a report. */
2601 DEBUG(0, ("print_job_spool_file: "
2602 "insufficient permissions to open spool "
2603 "file %s.\n", pjob->filename));
2604 } else {
2605 /* Normal case, report at level 3 and above. */
2606 DEBUG(3, ("print_job_spool_file: "
2607 "can't open spool file %s\n",
2608 pjob->filename));
2610 return werr;
2613 return WERR_OK;
2616 /***************************************************************************
2617 Start spooling a job - return the jobid.
2618 ***************************************************************************/
2620 WERROR print_job_start(const struct auth_session_info *server_info,
2621 struct messaging_context *msg_ctx,
2622 const char *clientmachine,
2623 int snum, const char *docname, const char *filename,
2624 struct spoolss_DeviceMode *devmode, uint32_t *_jobid)
2626 uint32_t jobid;
2627 char *path = NULL, *userstr = NULL;
2628 struct printjob pjob;
2629 const char *sharename = lp_const_servicename(snum);
2630 struct tdb_print_db *pdb = get_print_db_byname(sharename);
2631 const struct loadparm_substitution *lp_sub =
2632 loadparm_s3_global_substitution();
2633 int njobs;
2634 WERROR werr;
2636 if (!pdb) {
2637 return WERR_INTERNAL_DB_CORRUPTION;
2640 path = lp_path(talloc_tos(), lp_sub, snum);
2642 werr = print_job_checks(server_info, msg_ctx, snum, &njobs);
2643 if (!W_ERROR_IS_OK(werr)) {
2644 release_print_db(pdb);
2645 return werr;
2648 DEBUG(10, ("print_job_start: "
2649 "Queue %s number of jobs (%d), max printjobs = %d\n",
2650 sharename, njobs, lp_maxprintjobs(snum)));
2652 werr = allocate_print_jobid(pdb, snum, sharename, &jobid);
2653 if (!W_ERROR_IS_OK(werr)) {
2654 goto fail;
2657 /* create the database entry */
2659 ZERO_STRUCT(pjob);
2661 pjob.pid = getpid();
2662 pjob.jobid = jobid;
2663 pjob.sysjob = -1;
2664 pjob.fd = -1;
2665 pjob.starttime = time(NULL);
2666 pjob.status = LPQ_SPOOLING;
2667 pjob.size = 0;
2668 pjob.spooled = False;
2669 pjob.smbjob = True;
2670 pjob.devmode = devmode;
2672 fstrcpy(pjob.jobname, docname);
2674 fstrcpy(pjob.clientmachine, clientmachine);
2676 userstr = talloc_sub_full(talloc_tos(),
2677 sharename,
2678 server_info->unix_info->sanitized_username,
2679 path, server_info->unix_token->gid,
2680 server_info->unix_info->sanitized_username,
2681 server_info->info->domain_name,
2682 lp_printjob_username(snum));
2683 if (userstr == NULL) {
2684 werr = WERR_NOT_ENOUGH_MEMORY;
2685 goto fail;
2687 strlcpy(pjob.user, userstr, sizeof(pjob.user));
2688 TALLOC_FREE(userstr);
2690 fstrcpy(pjob.queuename, lp_const_servicename(snum));
2692 /* we have a job entry - now create the spool file */
2693 werr = print_job_spool_file(snum, jobid, filename, &pjob);
2694 if (!W_ERROR_IS_OK(werr)) {
2695 goto fail;
2698 pjob_store(global_event_context(), msg_ctx, sharename, jobid, &pjob);
2700 /* Update the 'jobs added' entry used by print_queue_status. */
2701 add_to_jobs_list(pdb, jobid, "INFO/jobs_added");
2703 /* Ensure we keep a rough count of the number of total jobs... */
2704 tdb_change_int32_atomic(pdb->tdb, "INFO/total_jobs", &njobs, 1);
2706 release_print_db(pdb);
2708 *_jobid = jobid;
2709 return WERR_OK;
2711 fail:
2712 if (jobid != -1) {
2713 pjob_delete(global_event_context(), msg_ctx, sharename, jobid);
2716 release_print_db(pdb);
2718 DEBUG(3, ("print_job_start: returning fail. "
2719 "Error = %s\n", win_errstr(werr)));
2720 return werr;
2723 /****************************************************************************
2724 Update the number of pages spooled to jobid
2725 ****************************************************************************/
2727 void print_job_endpage(struct messaging_context *msg_ctx,
2728 int snum, uint32_t jobid)
2730 const char* sharename = lp_const_servicename(snum);
2731 struct printjob *pjob;
2732 TALLOC_CTX *tmp_ctx = talloc_new(msg_ctx);
2733 if (tmp_ctx == NULL) {
2734 return;
2737 pjob = print_job_find(tmp_ctx, sharename, jobid);
2738 if (!pjob) {
2739 goto err_out;
2741 /* don't allow another process to get this info - it is meaningless */
2742 if (pjob->pid != getpid()) {
2743 goto err_out;
2746 pjob->page_count++;
2747 pjob_store(global_event_context(), msg_ctx, sharename, jobid, pjob);
2748 err_out:
2749 talloc_free(tmp_ctx);
2752 /****************************************************************************
2753 Print a file - called on closing the file. This spools the job.
2754 If normal close is false then we're tearing down the jobs - treat as an
2755 error.
2756 ****************************************************************************/
2758 NTSTATUS print_job_end(struct messaging_context *msg_ctx, int snum,
2759 uint32_t jobid, enum file_close_type close_type)
2761 const char* sharename = lp_const_servicename(snum);
2762 const struct loadparm_substitution *lp_sub =
2763 loadparm_s3_global_substitution();
2764 struct printjob *pjob;
2765 int ret;
2766 SMB_STRUCT_STAT sbuf;
2767 struct printif *current_printif = get_printer_fns(snum);
2768 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
2769 char *lpq_cmd;
2770 TALLOC_CTX *tmp_ctx = talloc_new(msg_ctx);
2771 if (tmp_ctx == NULL) {
2772 return NT_STATUS_NO_MEMORY;
2775 pjob = print_job_find(tmp_ctx, sharename, jobid);
2776 if (!pjob) {
2777 status = NT_STATUS_PRINT_CANCELLED;
2778 goto err_out;
2781 if (pjob->spooled || pjob->pid != getpid()) {
2782 status = NT_STATUS_ACCESS_DENIED;
2783 goto err_out;
2786 if (close_type == NORMAL_CLOSE || close_type == SHUTDOWN_CLOSE) {
2787 if (pjob->status == PJOB_SMBD_SPOOLING) {
2788 /* take over the file now, smbd is done */
2789 if (sys_stat(pjob->filename, &sbuf, false) != 0) {
2790 status = map_nt_error_from_unix(errno);
2791 DEBUG(3, ("print_job_end: "
2792 "stat file failed for jobid %d\n",
2793 jobid));
2794 goto fail;
2797 pjob->status = LPQ_SPOOLING;
2799 } else {
2801 if ((sys_fstat(pjob->fd, &sbuf, false) != 0)) {
2802 status = map_nt_error_from_unix(errno);
2803 close(pjob->fd);
2804 DEBUG(3, ("print_job_end: "
2805 "stat file failed for jobid %d\n",
2806 jobid));
2807 goto fail;
2810 close(pjob->fd);
2813 pjob->size = sbuf.st_ex_size;
2814 } else {
2817 * Not a normal close, something has gone wrong. Cleanup.
2819 if (pjob->fd != -1) {
2820 close(pjob->fd);
2822 goto fail;
2825 /* Technically, this is not quite right. If the printer has a separator
2826 * page turned on, the NT spooler prints the separator page even if the
2827 * print job is 0 bytes. 010215 JRR */
2828 if (pjob->size == 0 || pjob->status == LPQ_DELETING) {
2829 /* don't bother spooling empty files or something being deleted. */
2830 DEBUG(5,("print_job_end: canceling spool of %s (%s)\n",
2831 pjob->filename, pjob->size ? "deleted" : "zero length" ));
2832 unlink(pjob->filename);
2833 pjob_delete(global_event_context(), msg_ctx, sharename, jobid);
2834 return NT_STATUS_OK;
2837 /* don't strip out characters like '$' from the printername */
2838 lpq_cmd = talloc_string_sub2(tmp_ctx,
2839 lp_lpq_command(snum),
2840 "%p",
2841 lp_printername(talloc_tos(), lp_sub, snum),
2842 false, false, false);
2843 if (lpq_cmd == NULL) {
2844 status = NT_STATUS_PRINT_CANCELLED;
2845 goto fail;
2847 lpq_cmd = talloc_sub_full(tmp_ctx,
2848 lp_servicename(talloc_tos(), lp_sub, snum),
2849 current_user_info.unix_name,
2851 get_current_gid(NULL),
2852 get_current_username(),
2853 get_current_user_info_domain(),
2854 lpq_cmd);
2855 if (lpq_cmd == NULL) {
2856 status = NT_STATUS_PRINT_CANCELLED;
2857 goto fail;
2860 ret = (*(current_printif->job_submit))(snum, pjob,
2861 current_printif->type, lpq_cmd);
2862 if (ret) {
2863 status = NT_STATUS_PRINT_CANCELLED;
2864 goto fail;
2867 /* The print job has been successfully handed over to the back-end */
2869 pjob->spooled = True;
2870 pjob->status = LPQ_QUEUED;
2871 pjob_store(global_event_context(), msg_ctx, sharename, jobid, pjob);
2873 /* make sure the database is up to date */
2874 if (print_cache_expired(lp_const_servicename(snum), True))
2875 print_queue_update(msg_ctx, snum, False);
2877 return NT_STATUS_OK;
2879 fail:
2881 /* The print job was not successfully started. Cleanup */
2882 /* Still need to add proper error return propagation! 010122:JRR */
2883 pjob->fd = -1;
2884 unlink(pjob->filename);
2885 pjob_delete(global_event_context(), msg_ctx, sharename, jobid);
2886 err_out:
2887 talloc_free(tmp_ctx);
2888 return status;
2891 /****************************************************************************
2892 Get a snapshot of jobs in the system without traversing.
2893 ****************************************************************************/
2895 static bool get_stored_queue_info(struct messaging_context *msg_ctx,
2896 struct tdb_print_db *pdb, int snum,
2897 int *pcount, print_queue_struct **ppqueue)
2899 const struct loadparm_substitution *lp_sub =
2900 loadparm_s3_global_substitution();
2901 TDB_DATA data, cgdata, jcdata;
2902 print_queue_struct *queue = NULL;
2903 uint32_t qcount = 0;
2904 uint32_t extra_count = 0;
2905 uint32_t changed_count = 0;
2906 int total_count = 0;
2907 size_t len = 0;
2908 uint32_t i;
2909 int max_reported_jobs = lp_max_reported_print_jobs(snum);
2910 bool ret = false;
2911 const char* sharename = lp_servicename(talloc_tos(), lp_sub, snum);
2912 TALLOC_CTX *tmp_ctx = talloc_new(msg_ctx);
2913 if (tmp_ctx == NULL) {
2914 return false;
2917 /* make sure the database is up to date */
2918 if (print_cache_expired(lp_const_servicename(snum), True))
2919 print_queue_update(msg_ctx, snum, False);
2921 *pcount = 0;
2922 *ppqueue = NULL;
2924 ZERO_STRUCT(data);
2925 ZERO_STRUCT(cgdata);
2927 /* Get the stored queue data. */
2928 data = tdb_fetch(pdb->tdb, string_tdb_data("INFO/linear_queue_array"));
2930 if (data.dptr && data.dsize >= sizeof(qcount))
2931 len += tdb_unpack(data.dptr + len, data.dsize - len, "d", &qcount);
2933 /* Get the added jobs list. */
2934 cgdata = tdb_fetch(pdb->tdb, string_tdb_data("INFO/jobs_added"));
2935 if (cgdata.dptr != NULL && (cgdata.dsize % 4 == 0))
2936 extra_count = cgdata.dsize/4;
2938 /* Get the changed jobs list. */
2939 jcdata = tdb_fetch(pdb->tdb, string_tdb_data("INFO/jobs_changed"));
2940 if (jcdata.dptr != NULL && (jcdata.dsize % 4 == 0))
2941 changed_count = jcdata.dsize / 4;
2943 DEBUG(5,("get_stored_queue_info: qcount = %u, extra_count = %u\n", (unsigned int)qcount, (unsigned int)extra_count));
2945 /* Allocate the queue size. */
2946 if (qcount == 0 && extra_count == 0)
2947 goto out;
2949 if ((queue = SMB_MALLOC_ARRAY(print_queue_struct, qcount + extra_count)) == NULL)
2950 goto out;
2952 /* Retrieve the linearised queue data. */
2954 for(i = 0; i < qcount; i++) {
2955 uint32_t qjob, qsize, qpage_count, qstatus, qpriority, qtime;
2956 len += tdb_unpack(data.dptr + len, data.dsize - len, "ddddddff",
2957 &qjob,
2958 &qsize,
2959 &qpage_count,
2960 &qstatus,
2961 &qpriority,
2962 &qtime,
2963 queue[i].fs_user,
2964 queue[i].fs_file);
2965 queue[i].sysjob = qjob;
2966 queue[i].size = qsize;
2967 queue[i].page_count = qpage_count;
2968 queue[i].status = qstatus;
2969 queue[i].priority = qpriority;
2970 queue[i].time = qtime;
2973 total_count = qcount;
2975 /* Add new jobids to the queue. */
2976 for (i = 0; i < extra_count; i++) {
2977 uint32_t jobid;
2978 struct printjob *pjob;
2980 jobid = IVAL(cgdata.dptr, i*4);
2981 DEBUG(5,("get_stored_queue_info: added job = %u\n", (unsigned int)jobid));
2982 pjob = print_job_find(tmp_ctx, lp_const_servicename(snum), jobid);
2983 if (!pjob) {
2984 DEBUG(5,("get_stored_queue_info: failed to find added job = %u\n", (unsigned int)jobid));
2985 remove_from_jobs_added(sharename, jobid);
2986 continue;
2989 queue[total_count].sysjob = pjob->sysjob;
2990 queue[total_count].size = pjob->size;
2991 queue[total_count].page_count = pjob->page_count;
2992 queue[total_count].status = pjob->status;
2993 queue[total_count].priority = 1;
2994 queue[total_count].time = pjob->starttime;
2995 fstrcpy(queue[total_count].fs_user, pjob->user);
2996 fstrcpy(queue[total_count].fs_file, pjob->jobname);
2997 total_count++;
2998 talloc_free(pjob);
3001 /* Update the changed jobids. */
3002 for (i = 0; i < changed_count; i++) {
3003 uint32_t jobid = IVAL(jcdata.dptr, i * 4);
3004 struct printjob *pjob;
3005 uint32_t j;
3006 bool found = false;
3008 pjob = print_job_find(tmp_ctx, sharename, jobid);
3009 if (pjob == NULL) {
3010 DEBUG(5,("get_stored_queue_info: failed to find "
3011 "changed job = %u\n",
3012 (unsigned int)jobid));
3013 remove_from_jobs_changed(sharename, jobid);
3014 continue;
3017 for (j = 0; j < total_count; j++) {
3018 if (queue[j].sysjob == pjob->sysjob) {
3019 found = true;
3020 break;
3024 if (found) {
3025 DEBUG(5,("get_stored_queue_info: changed job: %u\n",
3026 (unsigned int)jobid));
3028 queue[j].sysjob = pjob->sysjob;
3029 queue[j].size = pjob->size;
3030 queue[j].page_count = pjob->page_count;
3031 queue[j].status = pjob->status;
3032 queue[j].priority = 1;
3033 queue[j].time = pjob->starttime;
3034 fstrcpy(queue[j].fs_user, pjob->user);
3035 fstrcpy(queue[j].fs_file, pjob->jobname);
3036 talloc_free(pjob);
3038 DEBUG(5,("updated queue[%u], jobid: %u, sysjob: %u, "
3039 "jobname: %s\n",
3040 (unsigned int)j, (unsigned int)jobid,
3041 (unsigned int)queue[j].sysjob, pjob->jobname));
3044 remove_from_jobs_changed(sharename, jobid);
3047 /* Sort the queue by submission time otherwise they are displayed
3048 in hash order. */
3050 TYPESAFE_QSORT(queue, total_count, printjob_comp);
3052 DEBUG(5,("get_stored_queue_info: total_count = %u\n", (unsigned int)total_count));
3054 if (max_reported_jobs && total_count > max_reported_jobs)
3055 total_count = max_reported_jobs;
3057 *ppqueue = queue;
3058 *pcount = total_count;
3060 ret = true;
3062 out:
3064 SAFE_FREE(data.dptr);
3065 SAFE_FREE(cgdata.dptr);
3066 talloc_free(tmp_ctx);
3067 return ret;
3070 /****************************************************************************
3071 Get a printer queue listing.
3072 set queue = NULL and status = NULL if you just want to update the cache
3073 ****************************************************************************/
3075 int print_queue_status(struct messaging_context *msg_ctx, int snum,
3076 print_queue_struct **ppqueue,
3077 print_status_struct *status)
3079 fstring keystr;
3080 TDB_DATA data, key;
3081 const char *sharename;
3082 struct tdb_print_db *pdb;
3083 int count = 0;
3085 /* make sure the database is up to date */
3087 if (print_cache_expired(lp_const_servicename(snum), True))
3088 print_queue_update(msg_ctx, snum, False);
3090 /* return if we are done */
3091 if ( !ppqueue || !status )
3092 return 0;
3094 *ppqueue = NULL;
3095 sharename = lp_const_servicename(snum);
3096 pdb = get_print_db_byname(sharename);
3098 if (!pdb)
3099 return 0;
3102 * Fetch the queue status. We must do this first, as there may
3103 * be no jobs in the queue.
3106 ZERO_STRUCTP(status);
3107 slprintf(keystr, sizeof(keystr)-1, "STATUS/%s", sharename);
3108 key = string_tdb_data(keystr);
3110 data = tdb_fetch(pdb->tdb, key);
3111 if (data.dptr) {
3112 if (data.dsize == sizeof(*status)) {
3113 /* this memcpy is ok since the status struct was
3114 not packed before storing it in the tdb */
3115 memcpy(status, data.dptr, sizeof(*status));
3117 SAFE_FREE(data.dptr);
3121 * Now, fetch the print queue information. We first count the number
3122 * of entries, and then only retrieve the queue if necessary.
3125 if (!get_stored_queue_info(msg_ctx, pdb, snum, &count, ppqueue)) {
3126 release_print_db(pdb);
3127 return 0;
3130 release_print_db(pdb);
3131 return count;
3134 /****************************************************************************
3135 Pause a queue.
3136 ****************************************************************************/
3138 WERROR print_queue_pause(const struct auth_session_info *server_info,
3139 struct messaging_context *msg_ctx, int snum)
3141 int ret;
3142 struct printif *current_printif = get_printer_fns( snum );
3144 if (!W_ERROR_IS_OK(print_access_check(server_info, msg_ctx, snum,
3145 PRINTER_ACCESS_ADMINISTER))) {
3146 return WERR_ACCESS_DENIED;
3150 become_root();
3152 ret = (*(current_printif->queue_pause))(snum);
3154 unbecome_root();
3156 if (ret != 0) {
3157 return WERR_INVALID_PARAMETER;
3160 /* force update the database */
3161 print_cache_flush(lp_const_servicename(snum));
3163 /* Send a printer notify message */
3165 notify_printer_status(global_event_context(), msg_ctx, snum,
3166 PRINTER_STATUS_PAUSED);
3168 return WERR_OK;
3171 /****************************************************************************
3172 Resume a queue.
3173 ****************************************************************************/
3175 WERROR print_queue_resume(const struct auth_session_info *server_info,
3176 struct messaging_context *msg_ctx, int snum)
3178 int ret;
3179 struct printif *current_printif = get_printer_fns( snum );
3181 if (!W_ERROR_IS_OK(print_access_check(server_info, msg_ctx, snum,
3182 PRINTER_ACCESS_ADMINISTER))) {
3183 return WERR_ACCESS_DENIED;
3186 become_root();
3188 ret = (*(current_printif->queue_resume))(snum);
3190 unbecome_root();
3192 if (ret != 0) {
3193 return WERR_INVALID_PARAMETER;
3196 /* make sure the database is up to date */
3197 if (print_cache_expired(lp_const_servicename(snum), True))
3198 print_queue_update(msg_ctx, snum, True);
3200 /* Send a printer notify message */
3202 notify_printer_status(global_event_context(), msg_ctx, snum,
3203 PRINTER_STATUS_OK);
3205 return WERR_OK;
3208 /****************************************************************************
3209 Purge a queue - implemented by deleting all jobs that we can delete.
3210 ****************************************************************************/
3212 WERROR print_queue_purge(const struct auth_session_info *server_info,
3213 struct messaging_context *msg_ctx, int snum)
3215 print_queue_struct *queue;
3216 print_status_struct status;
3217 int njobs, i;
3218 bool can_job_admin;
3220 /* Force and update so the count is accurate (i.e. not a cached count) */
3221 print_queue_update(msg_ctx, snum, True);
3223 can_job_admin = W_ERROR_IS_OK(print_access_check(server_info,
3224 msg_ctx,
3225 snum,
3226 JOB_ACCESS_ADMINISTER));
3227 njobs = print_queue_status(msg_ctx, snum, &queue, &status);
3229 if ( can_job_admin )
3230 become_root();
3232 for (i = 0; i < njobs; i++) {
3233 struct tdb_print_db *pdb;
3234 int jobid;
3235 bool owner;
3236 pdb = get_print_db_byname(lp_const_servicename(snum));
3237 if (pdb == NULL) {
3238 DEBUG(1, ("failed to find printdb for %s\n",
3239 lp_const_servicename(snum)));
3240 continue;
3242 jobid = sysjob_to_jobid_pdb(pdb, queue[i].sysjob);
3243 if (jobid == (uint32_t)-1) {
3244 DEBUG(2, ("jobid for system job %d not found\n",
3245 queue[i].sysjob));
3246 continue; /* unix job */
3248 owner = is_owner(server_info, lp_const_servicename(snum),
3249 jobid);
3251 if (owner || can_job_admin) {
3252 print_job_delete1(global_event_context(), msg_ctx,
3253 snum, jobid);
3257 if ( can_job_admin )
3258 unbecome_root();
3260 /* update the cache */
3261 print_queue_update(msg_ctx, snum, True);
3263 SAFE_FREE(queue);
3265 return WERR_OK;