CVE-2020-25719 kdc: Avoid races and multiple DB lookups in s4u2self check
[Samba.git] / source3 / printing / printing.c
blob499334df03f0d36cc8bbd0542689211cd4dff22d
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"
44 extern userdom_struct current_user_info;
46 /* Current printer interface */
47 static bool remove_from_jobs_added(const char* sharename, uint32_t jobid);
49 static int get_queue_status(const char* sharename, print_status_struct *);
51 /****************************************************************************
52 Initialise the printing backend. Called once at startup before the fork().
53 ****************************************************************************/
55 bool print_backend_init(struct messaging_context *msg_ctx)
57 const char *sversion = "INFO/version";
58 int services = lp_numservices();
59 int snum;
60 bool ok;
61 char *print_cache_path;
63 if (!printer_list_parent_init()) {
64 return false;
67 print_cache_path = cache_path(talloc_tos(), "printing");
68 if (print_cache_path == NULL) {
69 return false;
71 ok = directory_create_or_exist(print_cache_path, 0755);
72 TALLOC_FREE(print_cache_path);
73 if (!ok) {
74 return false;
77 /* handle a Samba upgrade */
79 for (snum = 0; snum < services; snum++) {
80 struct tdb_print_db *pdb;
81 if (!lp_printable(snum))
82 continue;
84 pdb = get_print_db_byname(lp_const_servicename(snum));
85 if (!pdb)
86 continue;
87 if (tdb_lock_bystring(pdb->tdb, sversion) != 0) {
88 DEBUG(0,("print_backend_init: Failed to open printer %s database\n", lp_const_servicename(snum) ));
89 release_print_db(pdb);
90 return False;
92 if (tdb_fetch_int32(pdb->tdb, sversion) != PRINT_DATABASE_VERSION) {
93 tdb_wipe_all(pdb->tdb);
94 tdb_store_int32(pdb->tdb, sversion, PRINT_DATABASE_VERSION);
96 tdb_unlock_bystring(pdb->tdb, sversion);
97 release_print_db(pdb);
100 close_all_print_db(); /* Don't leave any open. */
102 /* do NT print initialization... */
103 return nt_printing_init(msg_ctx);
106 /****************************************************************************
107 Shut down printing backend. Called once at shutdown to close the tdb.
108 ****************************************************************************/
110 void printing_end(void)
112 close_all_print_db(); /* Don't leave any open. */
115 /****************************************************************************
116 Retrieve the set of printing functions for a given service. This allows
117 us to set the printer function table based on the value of the 'printing'
118 service parameter.
120 Use the generic interface as the default and only use cups interface only
121 when asked for (and only when supported)
122 ****************************************************************************/
124 static struct printif *get_printer_fns_from_type( enum printing_types type )
126 struct printif *printer_fns = &generic_printif;
128 #ifdef HAVE_CUPS
129 if ( type == PRINT_CUPS ) {
130 printer_fns = &cups_printif;
132 #endif /* HAVE_CUPS */
134 #ifdef HAVE_IPRINT
135 if ( type == PRINT_IPRINT ) {
136 printer_fns = &iprint_printif;
138 #endif /* HAVE_IPRINT */
140 printer_fns->type = type;
142 return printer_fns;
145 static struct printif *get_printer_fns( int snum )
147 return get_printer_fns_from_type( (enum printing_types)lp_printing(snum) );
151 /****************************************************************************
152 Useful function to generate a tdb key.
153 ****************************************************************************/
155 static TDB_DATA print_key(uint32_t jobid, uint32_t *tmp)
157 TDB_DATA ret;
159 SIVAL(tmp, 0, jobid);
160 ret.dptr = (uint8_t *)tmp;
161 ret.dsize = sizeof(*tmp);
162 return ret;
165 /****************************************************************************
166 Pack the devicemode to store it in a tdb.
167 ****************************************************************************/
168 static int pack_devicemode(struct spoolss_DeviceMode *devmode, uint8_t *buf, int buflen)
170 enum ndr_err_code ndr_err;
171 DATA_BLOB blob = { .data = NULL };
172 int len = 0;
174 if (devmode) {
175 ndr_err = ndr_push_struct_blob(&blob, talloc_tos(),
176 devmode,
177 (ndr_push_flags_fn_t)
178 ndr_push_spoolss_DeviceMode);
179 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
180 DEBUG(10, ("pack_devicemode: "
181 "error encoding spoolss_DeviceMode\n"));
182 goto done;
186 len = tdb_pack(buf, buflen, "B", blob.length, blob.data);
188 if (devmode) {
189 DEBUG(8, ("Packed devicemode [%s]\n", devmode->formname));
192 done:
193 return len;
196 /****************************************************************************
197 Unpack the devicemode to store it in a tdb.
198 ****************************************************************************/
199 static int unpack_devicemode(TALLOC_CTX *mem_ctx,
200 const uint8_t *buf, int buflen,
201 struct spoolss_DeviceMode **devmode)
203 struct spoolss_DeviceMode *dm;
204 enum ndr_err_code ndr_err;
205 char *data = NULL;
206 uint32_t data_len = 0;
207 DATA_BLOB blob;
208 int len = 0;
210 *devmode = NULL;
212 len = tdb_unpack(buf, buflen, "B", &data_len, &data);
213 if (!data) {
214 return len;
217 dm = talloc_zero(mem_ctx, struct spoolss_DeviceMode);
218 if (!dm) {
219 goto done;
222 blob = data_blob_const(data, data_len);
224 ndr_err = ndr_pull_struct_blob(&blob, dm, dm,
225 (ndr_pull_flags_fn_t)ndr_pull_spoolss_DeviceMode);
226 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
227 DEBUG(10, ("unpack_devicemode: "
228 "error parsing spoolss_DeviceMode\n"));
229 goto done;
232 DEBUG(8, ("Unpacked devicemode [%s](%s)\n",
233 dm->devicename, dm->formname));
234 if (dm->driverextra_data.data) {
235 DEBUG(8, ("with a private section of %d bytes\n",
236 dm->__driverextra_length));
239 *devmode = dm;
241 done:
242 SAFE_FREE(data);
243 return len;
246 /***********************************************************************
247 unpack a pjob from a tdb buffer
248 ***********************************************************************/
250 static int unpack_pjob(TALLOC_CTX *mem_ctx, uint8_t *buf, int buflen,
251 struct printjob *pjob)
253 int len = 0;
254 int used;
255 uint32_t pjpid, pjjobid, pjsysjob, pjfd, pjstarttime, pjstatus;
256 uint32_t pjsize, pjpage_count, pjspooled, pjsmbjob;
258 if (!buf || !pjob) {
259 return -1;
262 len += tdb_unpack(buf+len, buflen-len, "ddddddddddfffff",
263 &pjpid,
264 &pjjobid,
265 &pjsysjob,
266 &pjfd,
267 &pjstarttime,
268 &pjstatus,
269 &pjsize,
270 &pjpage_count,
271 &pjspooled,
272 &pjsmbjob,
273 pjob->filename,
274 pjob->jobname,
275 pjob->user,
276 pjob->clientmachine,
277 pjob->queuename);
279 if (len == -1) {
280 return -1;
283 used = unpack_devicemode(mem_ctx, buf+len, buflen-len, &pjob->devmode);
284 if (used == -1) {
285 return -1;
288 len += used;
290 pjob->pid = pjpid;
291 pjob->jobid = pjjobid;
292 pjob->sysjob = pjsysjob;
293 pjob->fd = pjfd;
294 pjob->starttime = pjstarttime;
295 pjob->status = pjstatus;
296 pjob->size = pjsize;
297 pjob->page_count = pjpage_count;
298 pjob->spooled = pjspooled;
299 pjob->smbjob = pjsmbjob;
301 return len;
305 /****************************************************************************
306 Useful function to find a print job in the database.
307 ****************************************************************************/
309 static struct printjob *print_job_find(TALLOC_CTX *mem_ctx,
310 const char *sharename,
311 uint32_t jobid)
313 struct printjob *pjob;
314 uint32_t tmp;
315 TDB_DATA ret;
316 struct tdb_print_db *pdb = get_print_db_byname(sharename);
318 DEBUG(10,("print_job_find: looking up job %u for share %s\n",
319 (unsigned int)jobid, sharename ));
321 if (!pdb) {
322 return NULL;
325 ret = tdb_fetch(pdb->tdb, print_key(jobid, &tmp));
326 release_print_db(pdb);
328 if (!ret.dptr) {
329 DEBUG(10, ("print_job_find: failed to find jobid %u.\n",
330 jobid));
331 return NULL;
334 pjob = talloc_zero(mem_ctx, struct printjob);
335 if (pjob == NULL) {
336 goto err_out;
339 if (unpack_pjob(mem_ctx, ret.dptr, ret.dsize, pjob) == -1) {
340 DEBUG(10, ("failed to unpack jobid %u.\n", jobid));
341 talloc_free(pjob);
342 pjob = NULL;
343 goto err_out;
346 DEBUG(10,("print_job_find: returning system job %d for jobid %u.\n",
347 pjob->sysjob, jobid));
348 SMB_ASSERT(pjob->jobid == jobid);
350 err_out:
351 SAFE_FREE(ret.dptr);
352 return pjob;
355 struct job_traverse_state {
356 int sysjob;
357 uint32_t jobid;
360 /* find spoolss jobid based on sysjob */
361 static int sysjob_to_jobid_traverse_fn(TDB_CONTEXT *the_tdb, TDB_DATA key,
362 TDB_DATA data, void *private_data)
364 struct printjob *pjob;
365 struct job_traverse_state *state =
366 (struct job_traverse_state *)private_data;
368 if (!data.dptr || data.dsize == 0)
369 return 0;
371 pjob = (struct printjob *)data.dptr;
372 if (key.dsize != sizeof(uint32_t))
373 return 0;
375 if (state->sysjob == pjob->sysjob) {
376 state->jobid = pjob->jobid;
377 return 1;
380 return 0;
383 uint32_t sysjob_to_jobid_pdb(struct tdb_print_db *pdb, int sysjob)
385 struct job_traverse_state state;
387 state.sysjob = sysjob;
388 state.jobid = (uint32_t)-1;
390 tdb_traverse(pdb->tdb, sysjob_to_jobid_traverse_fn, &state);
392 return state.jobid;
395 /****************************************************************************
396 This is a *horribly expensive call as we have to iterate through all the
397 current printer tdb's. Don't do this often ! JRA.
398 ****************************************************************************/
400 uint32_t sysjob_to_jobid(int unix_jobid)
402 int services = lp_numservices();
403 int snum;
404 struct job_traverse_state state;
406 state.sysjob = unix_jobid;
407 state.jobid = (uint32_t)-1;
409 for (snum = 0; snum < services; snum++) {
410 struct tdb_print_db *pdb;
411 if (!lp_printable(snum))
412 continue;
413 pdb = get_print_db_byname(lp_const_servicename(snum));
414 if (!pdb) {
415 continue;
417 tdb_traverse(pdb->tdb, sysjob_to_jobid_traverse_fn, &state);
418 release_print_db(pdb);
419 if (state.jobid != (uint32_t)-1)
420 return state.jobid;
422 return (uint32_t)-1;
425 /* find sysjob based on spoolss jobid */
426 static int jobid_to_sysjob_traverse_fn(TDB_CONTEXT *the_tdb, TDB_DATA key,
427 TDB_DATA data, void *private_data)
429 struct printjob *pjob;
430 struct job_traverse_state *state =
431 (struct job_traverse_state *)private_data;
433 if (!data.dptr || data.dsize == 0)
434 return 0;
436 pjob = (struct printjob *)data.dptr;
437 if (key.dsize != sizeof(uint32_t))
438 return 0;
440 if (state->jobid == pjob->jobid) {
441 state->sysjob = pjob->sysjob;
442 return 1;
445 return 0;
448 int jobid_to_sysjob_pdb(struct tdb_print_db *pdb, uint32_t jobid)
450 struct job_traverse_state state;
452 state.sysjob = -1;
453 state.jobid = jobid;
455 tdb_traverse(pdb->tdb, jobid_to_sysjob_traverse_fn, &state);
457 return state.sysjob;
460 /****************************************************************************
461 Send notifications based on what has changed after a pjob_store.
462 ****************************************************************************/
464 static const struct {
465 uint32_t lpq_status;
466 uint32_t spoolss_status;
467 } lpq_to_spoolss_status_map[] = {
468 { LPQ_QUEUED, JOB_STATUS_QUEUED },
469 { LPQ_PAUSED, JOB_STATUS_PAUSED },
470 { LPQ_SPOOLING, JOB_STATUS_SPOOLING },
471 { LPQ_PRINTING, JOB_STATUS_PRINTING },
472 { LPQ_DELETING, JOB_STATUS_DELETING },
473 { LPQ_OFFLINE, JOB_STATUS_OFFLINE },
474 { LPQ_PAPEROUT, JOB_STATUS_PAPEROUT },
475 { LPQ_PRINTED, JOB_STATUS_PRINTED },
476 { LPQ_DELETED, JOB_STATUS_DELETED },
477 { LPQ_BLOCKED, JOB_STATUS_BLOCKED_DEVQ },
478 { LPQ_USER_INTERVENTION, JOB_STATUS_USER_INTERVENTION },
479 { (uint32_t)-1, 0 }
482 /* Convert a lpq status value stored in printing.tdb into the
483 appropriate win32 API constant. */
485 static uint32_t map_to_spoolss_status(uint32_t lpq_status)
487 int i = 0;
489 while (lpq_to_spoolss_status_map[i].lpq_status != -1) {
490 if (lpq_to_spoolss_status_map[i].lpq_status == lpq_status)
491 return lpq_to_spoolss_status_map[i].spoolss_status;
492 i++;
495 return 0;
498 /***************************************************************************
499 Append a jobid to a list
500 ***************************************************************************/
502 static bool add_to_jobs_list(
503 struct tdb_print_db *pdb, uint32_t jobid, const char *key)
505 uint8_t store_jobid[sizeof(uint32_t)];
506 TDB_DATA data = {
507 .dptr = store_jobid, .dsize = sizeof(store_jobid)
509 int ret;
511 SIVAL(&store_jobid, 0, jobid);
513 DBG_DEBUG("Added jobid %"PRIu32" to %s\n", jobid, key);
515 ret = tdb_append(pdb->tdb, string_tdb_data(key), data);
516 return ret == 0;
519 /***************************************************************************
520 Remove a jobid from the 'jobs changed' list.
521 ***************************************************************************/
523 static bool remove_from_jobs_list(
524 const char *keystr, const char *sharename, uint32_t jobid)
526 struct tdb_print_db *pdb = get_print_db_byname(sharename);
527 TDB_DATA data, key;
528 size_t job_count, i;
529 bool ret = False;
530 bool gotlock = False;
532 if (!pdb) {
533 return False;
536 ZERO_STRUCT(data);
538 key = string_tdb_data(keystr);
540 if (tdb_chainlock_with_timeout(pdb->tdb, key, 5) != 0)
541 goto out;
543 gotlock = True;
545 data = tdb_fetch(pdb->tdb, key);
547 if (data.dptr == NULL || data.dsize == 0 || (data.dsize % 4 != 0))
548 goto out;
550 job_count = data.dsize / 4;
551 for (i = 0; i < job_count; i++) {
552 uint32_t ch_jobid;
554 ch_jobid = IVAL(data.dptr, i*4);
555 if (ch_jobid == jobid) {
556 if (i < job_count -1 )
557 memmove(data.dptr + (i*4), data.dptr + (i*4) + 4, (job_count - i - 1)*4 );
558 data.dsize -= 4;
559 if (tdb_store(pdb->tdb, key, data, TDB_REPLACE) != 0)
560 goto out;
561 break;
565 ret = True;
566 out:
568 if (gotlock)
569 tdb_chainunlock(pdb->tdb, key);
570 SAFE_FREE(data.dptr);
571 release_print_db(pdb);
572 if (ret)
573 DBG_DEBUG("removed jobid %"PRIu32"\n", jobid);
574 else
575 DBG_DEBUG("Failed to remove jobid %"PRIu32"\n", jobid);
576 return ret;
579 static bool remove_from_jobs_changed(const char* sharename, uint32_t jobid)
581 bool ret = remove_from_jobs_list(
582 "INFO/jobs_changed", sharename, jobid);
583 return ret;
586 static void pjob_store_notify(struct tevent_context *ev,
587 struct messaging_context *msg_ctx,
588 const char* sharename, uint32_t jobid,
589 struct printjob *old_data,
590 struct printjob *new_data,
591 bool *pchanged)
593 bool new_job = false;
594 bool changed = false;
596 if (old_data == NULL) {
597 new_job = true;
600 /* ACHTUNG! Due to a bug in Samba's spoolss parsing of the
601 NOTIFY_INFO_DATA buffer, we *have* to send the job submission
602 time first or else we'll end up with potential alignment
603 errors. I don't think the systemtime should be spooled as
604 a string, but this gets us around that error.
605 --jerry (i'll feel dirty for this) */
607 if (new_job) {
608 notify_job_submitted(ev, msg_ctx,
609 sharename, jobid, new_data->starttime);
610 notify_job_username(ev, msg_ctx,
611 sharename, jobid, new_data->user);
612 notify_job_name(ev, msg_ctx,
613 sharename, jobid, new_data->jobname);
614 notify_job_status(ev, msg_ctx,
615 sharename, jobid, map_to_spoolss_status(new_data->status));
616 notify_job_total_bytes(ev, msg_ctx,
617 sharename, jobid, new_data->size);
618 notify_job_total_pages(ev, msg_ctx,
619 sharename, jobid, new_data->page_count);
620 } else {
621 if (!strequal(old_data->jobname, new_data->jobname)) {
622 notify_job_name(ev, msg_ctx, sharename,
623 jobid, new_data->jobname);
624 changed = true;
627 if (old_data->status != new_data->status) {
628 notify_job_status(ev, msg_ctx,
629 sharename, jobid,
630 map_to_spoolss_status(new_data->status));
633 if (old_data->size != new_data->size) {
634 notify_job_total_bytes(ev, msg_ctx,
635 sharename, jobid, new_data->size);
638 if (old_data->page_count != new_data->page_count) {
639 notify_job_total_pages(ev, msg_ctx,
640 sharename, jobid,
641 new_data->page_count);
645 *pchanged = changed;
648 /****************************************************************************
649 Store a job structure back to the database.
650 ****************************************************************************/
652 static bool pjob_store(struct tevent_context *ev,
653 struct messaging_context *msg_ctx,
654 const char* sharename, uint32_t jobid,
655 struct printjob *pjob)
657 uint32_t tmp;
658 TDB_DATA old_data, new_data;
659 bool ret = False;
660 struct tdb_print_db *pdb = get_print_db_byname(sharename);
661 uint8_t *buf = NULL;
662 int len, newlen, buflen;
665 if (!pdb)
666 return False;
668 /* Get old data */
670 old_data = tdb_fetch(pdb->tdb, print_key(jobid, &tmp));
672 /* Doh! Now we have to pack/unpack data since the NT_DEVICEMODE was added */
674 newlen = 0;
676 do {
677 len = 0;
678 buflen = newlen;
679 len += tdb_pack(buf+len, buflen-len, "ddddddddddfffff",
680 (uint32_t)pjob->pid,
681 (uint32_t)pjob->jobid,
682 (uint32_t)pjob->sysjob,
683 (uint32_t)pjob->fd,
684 (uint32_t)pjob->starttime,
685 (uint32_t)pjob->status,
686 (uint32_t)pjob->size,
687 (uint32_t)pjob->page_count,
688 (uint32_t)pjob->spooled,
689 (uint32_t)pjob->smbjob,
690 pjob->filename,
691 pjob->jobname,
692 pjob->user,
693 pjob->clientmachine,
694 pjob->queuename);
696 len += pack_devicemode(pjob->devmode, buf+len, buflen-len);
698 if (buflen != len) {
699 buf = (uint8_t *)SMB_REALLOC(buf, len);
700 if (!buf) {
701 DEBUG(0,("pjob_store: failed to enlarge buffer!\n"));
702 goto done;
704 newlen = len;
706 } while ( buflen != len );
709 /* Store new data */
711 new_data.dptr = buf;
712 new_data.dsize = len;
713 ret = (tdb_store(pdb->tdb, print_key(jobid, &tmp), new_data,
714 TDB_REPLACE) == 0);
716 /* Send notify updates for what has changed */
718 if (ret) {
719 bool changed = false;
720 struct printjob old_pjob;
722 if (old_data.dsize) {
723 TALLOC_CTX *tmp_ctx = talloc_new(ev);
724 if (tmp_ctx == NULL)
725 goto done;
727 len = unpack_pjob(tmp_ctx, old_data.dptr,
728 old_data.dsize, &old_pjob);
729 if (len != -1 ) {
730 pjob_store_notify(ev,
731 msg_ctx,
732 sharename, jobid, &old_pjob,
733 pjob,
734 &changed);
735 if (changed) {
736 add_to_jobs_list(
737 pdb,
738 jobid,
739 "INFO/jobs_changed");
742 talloc_free(tmp_ctx);
744 } else {
745 /* new job */
746 pjob_store_notify(ev, msg_ctx,
747 sharename, jobid, NULL, pjob,
748 &changed);
752 done:
753 release_print_db(pdb);
754 SAFE_FREE( old_data.dptr );
755 SAFE_FREE( buf );
757 return ret;
760 /****************************************************************************
761 Remove a job structure from the database.
762 ****************************************************************************/
764 static void pjob_delete(struct tevent_context *ev,
765 struct messaging_context *msg_ctx,
766 const char* sharename, uint32_t jobid)
768 uint32_t tmp;
769 struct printjob *pjob;
770 uint32_t job_status = 0;
771 struct tdb_print_db *pdb;
772 TALLOC_CTX *tmp_ctx = talloc_new(ev);
773 if (tmp_ctx == NULL) {
774 return;
777 pdb = get_print_db_byname(sharename);
778 if (!pdb) {
779 goto err_out;
782 pjob = print_job_find(tmp_ctx, sharename, jobid);
783 if (!pjob) {
784 DEBUG(5, ("we were asked to delete nonexistent job %u\n",
785 jobid));
786 goto err_release;
789 /* We must cycle through JOB_STATUS_DELETING and
790 JOB_STATUS_DELETED for the port monitor to delete the job
791 properly. */
793 job_status = JOB_STATUS_DELETING|JOB_STATUS_DELETED;
794 notify_job_status(ev, msg_ctx, sharename, jobid, job_status);
796 /* Remove from printing.tdb */
798 tdb_delete(pdb->tdb, print_key(jobid, &tmp));
799 remove_from_jobs_added(sharename, jobid);
800 rap_jobid_delete(sharename, jobid);
801 err_release:
802 release_print_db(pdb);
803 err_out:
804 talloc_free(tmp_ctx);
807 /****************************************************************************
808 List a unix job in the print database.
809 ****************************************************************************/
811 static void print_unix_job(struct tevent_context *ev,
812 struct messaging_context *msg_ctx,
813 const char *sharename, print_queue_struct *q,
814 uint32_t jobid)
816 struct printjob pj, *old_pj;
817 TALLOC_CTX *tmp_ctx = talloc_new(ev);
818 if (tmp_ctx == NULL) {
819 return;
822 if (jobid == (uint32_t)-1) {
823 jobid = q->sysjob + UNIX_JOB_START;
826 /* Preserve the timestamp on an existing unix print job */
828 old_pj = print_job_find(tmp_ctx, sharename, jobid);
830 ZERO_STRUCT(pj);
832 pj.pid = (pid_t)-1;
833 pj.jobid = jobid;
834 pj.sysjob = q->sysjob;
835 pj.fd = -1;
836 pj.starttime = old_pj ? old_pj->starttime : q->time;
837 pj.status = q->status;
838 pj.size = q->size;
839 pj.spooled = True;
840 fstrcpy(pj.filename, old_pj ? old_pj->filename : "");
841 if (jobid < UNIX_JOB_START) {
842 pj.smbjob = True;
843 fstrcpy(pj.jobname, old_pj ? old_pj->jobname : "Remote Downlevel Document");
844 } else {
845 pj.smbjob = False;
846 fstrcpy(pj.jobname, old_pj ? old_pj->jobname : q->fs_file);
848 fstrcpy(pj.user, old_pj ? old_pj->user : q->fs_user);
849 fstrcpy(pj.queuename, old_pj ? old_pj->queuename : sharename );
851 pjob_store(ev, msg_ctx, sharename, jobid, &pj);
852 talloc_free(tmp_ctx);
856 struct traverse_struct {
857 print_queue_struct *queue;
858 size_t qcount, snum, maxcount, total_jobs;
859 const char *sharename;
860 time_t lpq_time;
861 const char *lprm_command;
862 struct printif *print_if;
863 struct tevent_context *ev;
864 struct messaging_context *msg_ctx;
865 TALLOC_CTX *mem_ctx;
868 /****************************************************************************
869 Utility fn to delete any jobs that are no longer active.
870 ****************************************************************************/
872 static int traverse_fn_delete(TDB_CONTEXT *t, TDB_DATA key, TDB_DATA data, void *state)
874 struct traverse_struct *ts = (struct traverse_struct *)state;
875 struct printjob pjob;
876 uint32_t jobid;
877 size_t i = 0;
879 if ( key.dsize != sizeof(jobid) )
880 return 0;
882 if (unpack_pjob(ts->mem_ctx, data.dptr, data.dsize, &pjob) == -1)
883 return 0;
884 talloc_free(pjob.devmode);
885 jobid = pjob.jobid;
887 if (!pjob.smbjob) {
888 /* remove a unix job if it isn't in the system queue any more */
889 for (i=0;i<ts->qcount;i++) {
890 if (ts->queue[i].sysjob == pjob.sysjob) {
891 break;
894 if (i == ts->qcount) {
895 DEBUG(10,("traverse_fn_delete: pjob %u deleted due to !smbjob\n",
896 (unsigned int)jobid ));
897 pjob_delete(ts->ev, ts->msg_ctx,
898 ts->sharename, jobid);
899 return 0;
902 /* need to continue the the bottom of the function to
903 save the correct attributes */
906 /* maybe it hasn't been spooled yet */
907 if (!pjob.spooled) {
908 /* if a job is not spooled and the process doesn't
909 exist then kill it. This cleans up after smbd
910 deaths */
911 if (!process_exists_by_pid(pjob.pid)) {
912 DEBUG(10,("traverse_fn_delete: pjob %u deleted due to !process_exists (%u)\n",
913 (unsigned int)jobid, (unsigned int)pjob.pid ));
914 pjob_delete(ts->ev, ts->msg_ctx,
915 ts->sharename, jobid);
916 } else
917 ts->total_jobs++;
918 return 0;
921 /* this check only makes sense for jobs submitted from Windows clients */
923 if (pjob.smbjob) {
924 for (i=0;i<ts->qcount;i++) {
925 if ( pjob.status == LPQ_DELETED )
926 continue;
928 if (ts->queue[i].sysjob == pjob.sysjob) {
930 /* try to clean up any jobs that need to be deleted */
932 if ( pjob.status == LPQ_DELETING ) {
933 int result;
935 result = (*(ts->print_if->job_delete))(
936 ts->sharename, ts->lprm_command, &pjob );
938 if ( result != 0 ) {
939 /* if we can't delete, then reset the job status */
940 pjob.status = LPQ_QUEUED;
941 pjob_store(ts->ev, ts->msg_ctx,
942 ts->sharename, jobid, &pjob);
944 else {
945 /* if we deleted the job, the remove the tdb record */
946 pjob_delete(ts->ev,
947 ts->msg_ctx,
948 ts->sharename, jobid);
949 pjob.status = LPQ_DELETED;
954 break;
959 /* The job isn't in the system queue - we have to assume it has
960 completed, so delete the database entry. */
962 if (i == ts->qcount) {
964 /* A race can occur between the time a job is spooled and
965 when it appears in the lpq output. This happens when
966 the job is added to printing.tdb when another smbd
967 running print_queue_update() has completed a lpq and
968 is currently traversing the printing tdb and deleting jobs.
969 Don't delete the job if it was submitted after the lpq_time. */
971 if (pjob.starttime < ts->lpq_time) {
972 DEBUG(10,("traverse_fn_delete: pjob %u deleted due to pjob.starttime (%u) < ts->lpq_time (%u)\n",
973 (unsigned int)jobid,
974 (unsigned int)pjob.starttime,
975 (unsigned int)ts->lpq_time ));
976 pjob_delete(ts->ev, ts->msg_ctx,
977 ts->sharename, jobid);
978 } else
979 ts->total_jobs++;
980 return 0;
983 /* Save the pjob attributes we will store. */
984 ts->queue[i].sysjob = pjob.sysjob;
985 ts->queue[i].size = pjob.size;
986 ts->queue[i].page_count = pjob.page_count;
987 ts->queue[i].status = pjob.status;
988 ts->queue[i].priority = 1;
989 ts->queue[i].time = pjob.starttime;
990 fstrcpy(ts->queue[i].fs_user, pjob.user);
991 fstrcpy(ts->queue[i].fs_file, pjob.jobname);
993 ts->total_jobs++;
995 return 0;
998 /****************************************************************************
999 Check if the print queue has been updated recently enough.
1000 ****************************************************************************/
1002 static void print_cache_flush(const char *sharename)
1004 fstring key;
1005 struct tdb_print_db *pdb = get_print_db_byname(sharename);
1007 if (!pdb)
1008 return;
1009 slprintf(key, sizeof(key)-1, "CACHE/%s", sharename);
1010 tdb_store_int32(pdb->tdb, key, -1);
1011 release_print_db(pdb);
1014 /****************************************************************************
1015 Check if someone already thinks they are doing the update.
1016 ****************************************************************************/
1018 static pid_t get_updating_pid(const char *sharename)
1020 fstring keystr;
1021 TDB_DATA data, key;
1022 pid_t updating_pid;
1023 struct tdb_print_db *pdb = get_print_db_byname(sharename);
1025 if (!pdb)
1026 return (pid_t)-1;
1027 slprintf(keystr, sizeof(keystr)-1, "UPDATING/%s", sharename);
1028 key = string_tdb_data(keystr);
1030 data = tdb_fetch(pdb->tdb, key);
1031 release_print_db(pdb);
1032 if (!data.dptr || data.dsize != sizeof(pid_t)) {
1033 SAFE_FREE(data.dptr);
1034 return (pid_t)-1;
1037 updating_pid = IVAL(data.dptr, 0);
1038 SAFE_FREE(data.dptr);
1040 if (process_exists_by_pid(updating_pid))
1041 return updating_pid;
1043 return (pid_t)-1;
1046 /****************************************************************************
1047 Set the fact that we're doing the update, or have finished doing the update
1048 in the tdb.
1049 ****************************************************************************/
1051 static void set_updating_pid(const fstring sharename, bool updating)
1053 fstring keystr;
1054 TDB_DATA key;
1055 TDB_DATA data;
1056 pid_t updating_pid = getpid();
1057 uint8_t buffer[4];
1059 struct tdb_print_db *pdb = get_print_db_byname(sharename);
1061 if (!pdb)
1062 return;
1064 slprintf(keystr, sizeof(keystr)-1, "UPDATING/%s", sharename);
1065 key = string_tdb_data(keystr);
1067 DEBUG(5, ("set_updating_pid: %supdating lpq cache for print share %s\n",
1068 updating ? "" : "not ",
1069 sharename ));
1071 if ( !updating ) {
1072 tdb_delete(pdb->tdb, key);
1073 release_print_db(pdb);
1074 return;
1077 SIVAL( buffer, 0, updating_pid);
1078 data.dptr = buffer;
1079 data.dsize = 4; /* we always assume this is a 4 byte value */
1081 tdb_store(pdb->tdb, key, data, TDB_REPLACE);
1082 release_print_db(pdb);
1085 /****************************************************************************
1086 Sort print jobs by submittal time.
1087 ****************************************************************************/
1089 static int printjob_comp(print_queue_struct *j1, print_queue_struct *j2)
1091 /* Silly cases */
1093 if (!j1 && !j2)
1094 return 0;
1095 if (!j1)
1096 return -1;
1097 if (!j2)
1098 return 1;
1100 /* Sort on job start time */
1102 if (j1->time == j2->time)
1103 return 0;
1104 return (j1->time > j2->time) ? 1 : -1;
1107 /****************************************************************************
1108 Store the sorted queue representation for later portmon retrieval.
1109 Skip deleted jobs
1110 ****************************************************************************/
1112 static void store_queue_struct(struct tdb_print_db *pdb, struct traverse_struct *pts)
1114 TDB_DATA data;
1115 int max_reported_jobs = lp_max_reported_print_jobs(pts->snum);
1116 print_queue_struct *queue = pts->queue;
1117 size_t len;
1118 size_t i;
1119 unsigned int qcount;
1121 if (max_reported_jobs && (max_reported_jobs < pts->qcount))
1122 pts->qcount = max_reported_jobs;
1123 qcount = 0;
1125 /* Work out the size. */
1126 data.dsize = 0;
1127 data.dsize += tdb_pack(NULL, 0, "d", qcount);
1129 for (i = 0; i < pts->qcount; i++) {
1130 if ( queue[i].status == LPQ_DELETED )
1131 continue;
1133 qcount++;
1134 data.dsize += tdb_pack(NULL, 0, "ddddddff",
1135 (uint32_t)queue[i].sysjob,
1136 (uint32_t)queue[i].size,
1137 (uint32_t)queue[i].page_count,
1138 (uint32_t)queue[i].status,
1139 (uint32_t)queue[i].priority,
1140 (uint32_t)queue[i].time,
1141 queue[i].fs_user,
1142 queue[i].fs_file);
1145 if ((data.dptr = (uint8_t *)SMB_MALLOC(data.dsize)) == NULL)
1146 return;
1148 len = 0;
1149 len += tdb_pack(data.dptr + len, data.dsize - len, "d", qcount);
1150 for (i = 0; i < pts->qcount; i++) {
1151 if ( queue[i].status == LPQ_DELETED )
1152 continue;
1154 len += tdb_pack(data.dptr + len, data.dsize - len, "ddddddff",
1155 (uint32_t)queue[i].sysjob,
1156 (uint32_t)queue[i].size,
1157 (uint32_t)queue[i].page_count,
1158 (uint32_t)queue[i].status,
1159 (uint32_t)queue[i].priority,
1160 (uint32_t)queue[i].time,
1161 queue[i].fs_user,
1162 queue[i].fs_file);
1165 tdb_store(pdb->tdb, string_tdb_data("INFO/linear_queue_array"), data,
1166 TDB_REPLACE);
1167 SAFE_FREE(data.dptr);
1168 return;
1171 static TDB_DATA get_jobs_added_data(struct tdb_print_db *pdb)
1173 TDB_DATA data;
1175 ZERO_STRUCT(data);
1177 data = tdb_fetch(pdb->tdb, string_tdb_data("INFO/jobs_added"));
1178 if (data.dptr == NULL || data.dsize == 0 || (data.dsize % 4 != 0)) {
1179 SAFE_FREE(data.dptr);
1180 ZERO_STRUCT(data);
1183 return data;
1186 static void check_job_added(const char *sharename, TDB_DATA data, uint32_t jobid)
1188 unsigned int i;
1189 unsigned int job_count = data.dsize / 4;
1191 for (i = 0; i < job_count; i++) {
1192 uint32_t ch_jobid;
1194 ch_jobid = IVAL(data.dptr, i*4);
1195 if (ch_jobid == jobid)
1196 remove_from_jobs_added(sharename, jobid);
1200 /****************************************************************************
1201 Check if the print queue has been updated recently enough.
1202 ****************************************************************************/
1204 static bool print_cache_expired(const char *sharename, bool check_pending)
1206 fstring key;
1207 time_t last_qscan_time, time_now = time(NULL);
1208 struct tdb_print_db *pdb = get_print_db_byname(sharename);
1209 bool result = False;
1211 if (!pdb)
1212 return False;
1214 snprintf(key, sizeof(key), "CACHE/%s", sharename);
1215 last_qscan_time = (time_t)tdb_fetch_int32(pdb->tdb, key);
1218 * Invalidate the queue for 3 reasons.
1219 * (1). last queue scan time == -1.
1220 * (2). Current time - last queue scan time > allowed cache time.
1221 * (3). last queue scan time > current time + MAX_CACHE_VALID_TIME (1 hour by default).
1222 * This last test picks up machines for which the clock has been moved
1223 * forward, an lpq scan done and then the clock moved back. Otherwise
1224 * that last lpq scan would stay around for a loooong loooong time... :-). JRA.
1227 if (last_qscan_time == ((time_t)-1)
1228 || (time_now - last_qscan_time) >= lp_lpq_cache_time()
1229 || last_qscan_time > (time_now + MAX_CACHE_VALID_TIME))
1231 uint32_t u;
1232 time_t msg_pending_time;
1234 DEBUG(4, ("print_cache_expired: cache expired for queue %s "
1235 "(last_qscan_time = %d, time now = %d, qcachetime = %d)\n",
1236 sharename, (int)last_qscan_time, (int)time_now,
1237 (int)lp_lpq_cache_time() ));
1239 /* check if another smbd has already sent a message to update the
1240 queue. Give the pending message one minute to clear and
1241 then send another message anyways. Make sure to check for
1242 clocks that have been run forward and then back again. */
1244 snprintf(key, sizeof(key), "MSG_PENDING/%s", sharename);
1246 if ( check_pending
1247 && tdb_fetch_uint32( pdb->tdb, key, &u )
1248 && (msg_pending_time=u) > 0
1249 && msg_pending_time <= time_now
1250 && (time_now - msg_pending_time) < 60 )
1252 DEBUG(4,("print_cache_expired: message already pending for %s. Accepting cache\n",
1253 sharename));
1254 goto done;
1257 result = True;
1260 done:
1261 release_print_db(pdb);
1262 return result;
1265 /****************************************************************************
1266 main work for updating the lpq cache for a printer queue
1267 ****************************************************************************/
1269 static void print_queue_update_internal(struct tevent_context *ev,
1270 struct messaging_context *msg_ctx,
1271 const char *sharename,
1272 struct printif *current_printif,
1273 char *lpq_command, char *lprm_command)
1275 size_t i, qcount;
1276 print_queue_struct *queue = NULL;
1277 print_status_struct status;
1278 print_status_struct old_status;
1279 struct printjob *pjob;
1280 struct traverse_struct tstruct;
1281 TDB_DATA data, key;
1282 TDB_DATA jcdata;
1283 fstring keystr, cachestr;
1284 struct tdb_print_db *pdb = get_print_db_byname(sharename);
1285 TALLOC_CTX *tmp_ctx = talloc_new(ev);
1287 if ((pdb == NULL) || (tmp_ctx == NULL)) {
1288 return;
1291 DEBUG(5,("print_queue_update_internal: printer = %s, type = %d, lpq command = [%s]\n",
1292 sharename, current_printif->type, lpq_command));
1295 * Update the cache time FIRST ! Stops others even
1296 * attempting to get the lock and doing this
1297 * if the lpq takes a long time.
1300 slprintf(cachestr, sizeof(cachestr)-1, "CACHE/%s", sharename);
1301 tdb_store_int32(pdb->tdb, cachestr, (int)time(NULL));
1303 /* get the current queue using the appropriate interface */
1304 ZERO_STRUCT(status);
1306 qcount = (*(current_printif->queue_get))(sharename,
1307 current_printif->type,
1308 lpq_command, &queue, &status);
1310 DBG_NOTICE("%zu job%s in queue for %s\n",
1311 qcount,
1312 (qcount != 1) ? "s" : "",
1313 sharename);
1315 /* Sort the queue by submission time otherwise they are displayed
1316 in hash order. */
1318 TYPESAFE_QSORT(queue, qcount, printjob_comp);
1321 any job in the internal database that is marked as spooled
1322 and doesn't exist in the system queue is considered finished
1323 and removed from the database
1325 any job in the system database but not in the internal database
1326 is added as a unix job
1328 fill in any system job numbers as we go
1330 jcdata = get_jobs_added_data(pdb);
1332 for (i=0; i<qcount; i++) {
1333 uint32_t jobid = sysjob_to_jobid_pdb(pdb, queue[i].sysjob);
1334 if (jobid == (uint32_t)-1) {
1335 /* assume its a unix print job */
1336 print_unix_job(ev, msg_ctx,
1337 sharename, &queue[i], jobid);
1338 continue;
1341 /* we have an active SMB print job - update its status */
1342 pjob = print_job_find(tmp_ctx, sharename, jobid);
1343 if (!pjob) {
1344 /* err, somethings wrong. Probably smbd was restarted
1345 with jobs in the queue. All we can do is treat them
1346 like unix jobs. Pity. */
1347 DEBUG(1, ("queued print job %d not found in jobs list, "
1348 "assuming unix job\n", jobid));
1349 print_unix_job(ev, msg_ctx,
1350 sharename, &queue[i], jobid);
1351 continue;
1354 /* don't reset the status on jobs to be deleted */
1356 if ( pjob->status != LPQ_DELETING )
1357 pjob->status = queue[i].status;
1359 pjob_store(ev, msg_ctx, sharename, jobid, pjob);
1361 check_job_added(sharename, jcdata, jobid);
1364 SAFE_FREE(jcdata.dptr);
1366 /* now delete any queued entries that don't appear in the
1367 system queue */
1368 tstruct.queue = queue;
1369 tstruct.qcount = qcount;
1370 tstruct.snum = -1;
1371 tstruct.total_jobs = 0;
1372 tstruct.lpq_time = time(NULL);
1373 tstruct.sharename = sharename;
1374 tstruct.lprm_command = lprm_command;
1375 tstruct.print_if = current_printif;
1376 tstruct.ev = ev;
1377 tstruct.msg_ctx = msg_ctx;
1378 tstruct.mem_ctx = tmp_ctx;
1380 tdb_traverse(pdb->tdb, traverse_fn_delete, (void *)&tstruct);
1382 /* Store the linearised queue, max jobs only. */
1383 store_queue_struct(pdb, &tstruct);
1385 SAFE_FREE(tstruct.queue);
1386 talloc_free(tmp_ctx);
1388 DBG_DEBUG("printer %s INFO, total_jobs = %zu\n",
1389 sharename,
1390 tstruct.total_jobs);
1392 tdb_store_int32(pdb->tdb, "INFO/total_jobs", tstruct.total_jobs);
1394 get_queue_status(sharename, &old_status);
1395 if (old_status.qcount != qcount) {
1396 DBG_DEBUG("Queue status change %zu jobs -> %zu jobs "
1397 "for printer %s\n",
1398 old_status.qcount,
1399 qcount,
1400 sharename);
1403 /* store the new queue status structure */
1404 slprintf(keystr, sizeof(keystr)-1, "STATUS/%s", sharename);
1405 key = string_tdb_data(keystr);
1407 status.qcount = qcount;
1408 data.dptr = (uint8_t *)&status;
1409 data.dsize = sizeof(status);
1410 tdb_store(pdb->tdb, key, data, TDB_REPLACE);
1413 * Update the cache time again. We want to do this call
1414 * as little as possible...
1417 slprintf(keystr, sizeof(keystr)-1, "CACHE/%s", sharename);
1418 tdb_store_int32(pdb->tdb, keystr, (int32_t)time(NULL));
1420 /* clear the msg pending record for this queue */
1422 snprintf(keystr, sizeof(keystr), "MSG_PENDING/%s", sharename);
1424 if ( !tdb_store_uint32( pdb->tdb, keystr, 0 ) ) {
1425 /* log a message but continue on */
1427 DEBUG(0,("print_queue_update: failed to store MSG_PENDING flag for [%s]!\n",
1428 sharename));
1431 release_print_db( pdb );
1433 return;
1436 /****************************************************************************
1437 Update the internal database from the system print queue for a queue.
1438 obtain a lock on the print queue before proceeding (needed when mutiple
1439 smbd processes maytry to update the lpq cache concurrently).
1440 ****************************************************************************/
1442 static void print_queue_update_with_lock( struct tevent_context *ev,
1443 struct messaging_context *msg_ctx,
1444 const char *sharename,
1445 struct printif *current_printif,
1446 char *lpq_command, char *lprm_command )
1448 fstring keystr;
1449 struct tdb_print_db *pdb;
1451 DEBUG(5,("print_queue_update_with_lock: printer share = %s\n", sharename));
1452 pdb = get_print_db_byname(sharename);
1453 if (!pdb)
1454 return;
1456 if ( !print_cache_expired(sharename, False) ) {
1457 DEBUG(5,("print_queue_update_with_lock: print cache for %s is still ok\n", sharename));
1458 release_print_db(pdb);
1459 return;
1463 * Check to see if someone else is doing this update.
1464 * This is essentially a mutex on the update.
1467 if (get_updating_pid(sharename) != -1) {
1468 release_print_db(pdb);
1469 return;
1472 /* Lock the queue for the database update */
1474 slprintf(keystr, sizeof(keystr) - 1, "LOCK/%s", sharename);
1475 /* Only wait 10 seconds for this. */
1476 if (tdb_lock_bystring_with_timeout(pdb->tdb, keystr, 10) != 0) {
1477 DEBUG(0,("print_queue_update_with_lock: Failed to lock printer %s database\n", sharename));
1478 release_print_db(pdb);
1479 return;
1483 * Ensure that no one else got in here.
1484 * If the updating pid is still -1 then we are
1485 * the winner.
1488 if (get_updating_pid(sharename) != -1) {
1490 * Someone else is doing the update, exit.
1492 tdb_unlock_bystring(pdb->tdb, keystr);
1493 release_print_db(pdb);
1494 return;
1498 * We're going to do the update ourselves.
1501 /* Tell others we're doing the update. */
1502 set_updating_pid(sharename, True);
1505 * Allow others to enter and notice we're doing
1506 * the update.
1509 tdb_unlock_bystring(pdb->tdb, keystr);
1511 /* do the main work now */
1513 print_queue_update_internal(ev, msg_ctx,
1514 sharename, current_printif,
1515 lpq_command, lprm_command);
1517 /* Delete our pid from the db. */
1518 set_updating_pid(sharename, False);
1519 release_print_db(pdb);
1522 /****************************************************************************
1523 this is the receive function of the background lpq updater
1524 ****************************************************************************/
1525 void print_queue_receive(struct messaging_context *msg,
1526 void *private_data,
1527 uint32_t msg_type,
1528 struct server_id server_id,
1529 DATA_BLOB *data)
1531 fstring sharename;
1532 char *lpqcommand = NULL, *lprmcommand = NULL;
1533 int printing_type;
1534 size_t len;
1536 len = tdb_unpack( (uint8_t *)data->data, data->length, "fdPP",
1537 sharename,
1538 &printing_type,
1539 &lpqcommand,
1540 &lprmcommand );
1542 if ( len == -1 ) {
1543 SAFE_FREE(lpqcommand);
1544 SAFE_FREE(lprmcommand);
1545 DEBUG(0,("print_queue_receive: Got invalid print queue update message\n"));
1546 return;
1549 print_queue_update_with_lock(global_event_context(), msg, sharename,
1550 get_printer_fns_from_type((enum printing_types)printing_type),
1551 lpqcommand, lprmcommand );
1553 SAFE_FREE(lpqcommand);
1554 SAFE_FREE(lprmcommand);
1555 return;
1558 /****************************************************************************
1559 update the internal database from the system print queue for a queue
1560 ****************************************************************************/
1562 static void print_queue_update(struct messaging_context *msg_ctx,
1563 int snum, bool force)
1565 char key[268];
1566 fstring sharename;
1567 char *lpqcommand = NULL;
1568 char *lprmcommand = NULL;
1569 uint8_t *buffer = NULL;
1570 size_t len = 0;
1571 size_t newlen;
1572 struct tdb_print_db *pdb;
1573 int type;
1574 struct printif *current_printif;
1575 TALLOC_CTX *ctx = talloc_tos();
1576 const struct loadparm_substitution *lp_sub =
1577 loadparm_s3_global_substitution();
1579 fstrcpy( sharename, lp_const_servicename(snum));
1581 /* don't strip out characters like '$' from the printername */
1583 lpqcommand = talloc_string_sub2(ctx,
1584 lp_lpq_command(snum),
1585 "%p",
1586 lp_printername(talloc_tos(), lp_sub, snum),
1587 false, false, false);
1588 if (!lpqcommand) {
1589 return;
1591 lpqcommand = talloc_sub_full(ctx,
1592 lp_servicename(talloc_tos(), lp_sub, snum),
1593 current_user_info.unix_name,
1595 get_current_gid(NULL),
1596 get_current_username(),
1597 current_user_info.domain,
1598 lpqcommand);
1599 if (!lpqcommand) {
1600 return;
1603 lprmcommand = talloc_string_sub2(ctx,
1604 lp_lprm_command(snum),
1605 "%p",
1606 lp_printername(talloc_tos(), lp_sub, snum),
1607 false, false, false);
1608 if (!lprmcommand) {
1609 return;
1611 lprmcommand = talloc_sub_full(ctx,
1612 lp_servicename(talloc_tos(), lp_sub, snum),
1613 current_user_info.unix_name,
1615 get_current_gid(NULL),
1616 get_current_username(),
1617 current_user_info.domain,
1618 lprmcommand);
1619 if (!lprmcommand) {
1620 return;
1624 * Make sure that the background queue process exists.
1625 * Otherwise just do the update ourselves
1628 if ( force || background_lpq_updater_pid == -1 ) {
1629 DEBUG(4,("print_queue_update: updating queue [%s] myself\n", sharename));
1630 current_printif = get_printer_fns( snum );
1631 print_queue_update_with_lock(global_event_context(), msg_ctx,
1632 sharename, current_printif,
1633 lpqcommand, lprmcommand);
1635 return;
1638 type = lp_printing(snum);
1640 /* get the length */
1642 len = tdb_pack( NULL, 0, "fdPP",
1643 sharename,
1644 type,
1645 lpqcommand,
1646 lprmcommand );
1648 buffer = SMB_XMALLOC_ARRAY( uint8_t, len );
1650 /* now pack the buffer */
1651 newlen = tdb_pack( buffer, len, "fdPP",
1652 sharename,
1653 type,
1654 lpqcommand,
1655 lprmcommand );
1657 SMB_ASSERT( newlen == len );
1659 DEBUG(10,("print_queue_update: Sending message -> printer = %s, "
1660 "type = %d, lpq command = [%s] lprm command = [%s]\n",
1661 sharename, type, lpqcommand, lprmcommand ));
1663 /* here we set a msg pending record for other smbd processes
1664 to throttle the number of duplicate print_queue_update msgs
1665 sent. */
1667 pdb = get_print_db_byname(sharename);
1668 if (!pdb) {
1669 SAFE_FREE(buffer);
1670 return;
1673 snprintf(key, sizeof(key), "MSG_PENDING/%s", sharename);
1675 if ( !tdb_store_uint32( pdb->tdb, key, time(NULL) ) ) {
1676 /* log a message but continue on */
1678 DEBUG(0,("print_queue_update: failed to store MSG_PENDING flag for [%s]!\n",
1679 sharename));
1682 release_print_db( pdb );
1684 /* finally send the message */
1686 send_to_bgqd(msg_ctx, MSG_PRINTER_UPDATE, (uint8_t *)buffer, len);
1688 SAFE_FREE( buffer );
1690 return;
1693 /****************************************************************************
1694 Create/Update an entry in the print tdb that will allow us to send notify
1695 updates only to interested smbd's.
1696 ****************************************************************************/
1698 bool print_notify_register_pid(int snum)
1700 TDB_DATA data;
1701 struct tdb_print_db *pdb = NULL;
1702 TDB_CONTEXT *tdb = NULL;
1703 const char *printername;
1704 uint32_t mypid = (uint32_t)getpid();
1705 bool ret = False;
1706 size_t i;
1708 /* if (snum == -1), then the change notify request was
1709 on a print server handle and we need to register on
1710 all print queus */
1712 if (snum == -1)
1714 int num_services = lp_numservices();
1715 int idx;
1717 for ( idx=0; idx<num_services; idx++ ) {
1718 if (lp_snum_ok(idx) && lp_printable(idx) )
1719 print_notify_register_pid(idx);
1722 return True;
1724 else /* register for a specific printer */
1726 printername = lp_const_servicename(snum);
1727 pdb = get_print_db_byname(printername);
1728 if (!pdb)
1729 return False;
1730 tdb = pdb->tdb;
1733 if (tdb_lock_bystring_with_timeout(tdb, NOTIFY_PID_LIST_KEY, 10) != 0) {
1734 DEBUG(0,("print_notify_register_pid: Failed to lock printer %s\n",
1735 printername));
1736 if (pdb)
1737 release_print_db(pdb);
1738 return False;
1741 data = get_printer_notify_pid_list( tdb, printername, True );
1743 /* Add ourselves and increase the refcount. */
1745 for (i = 0; i < data.dsize; i += 8) {
1746 if (IVAL(data.dptr,i) == mypid) {
1747 uint32_t new_refcount = IVAL(data.dptr, i+4) + 1;
1748 SIVAL(data.dptr, i+4, new_refcount);
1749 break;
1753 if (i == data.dsize) {
1754 /* We weren't in the list. Realloc. */
1755 data.dptr = (uint8_t *)SMB_REALLOC(data.dptr, data.dsize + 8);
1756 if (!data.dptr) {
1757 DEBUG(0,("print_notify_register_pid: Relloc fail for printer %s\n",
1758 printername));
1759 goto done;
1761 data.dsize += 8;
1762 SIVAL(data.dptr,data.dsize - 8,mypid);
1763 SIVAL(data.dptr,data.dsize - 4,1); /* Refcount. */
1766 /* Store back the record. */
1767 if (tdb_store_bystring(tdb, NOTIFY_PID_LIST_KEY, data, TDB_REPLACE) != 0) {
1768 DEBUG(0,("print_notify_register_pid: Failed to update pid \
1769 list for printer %s\n", printername));
1770 goto done;
1773 ret = True;
1775 done:
1777 tdb_unlock_bystring(tdb, NOTIFY_PID_LIST_KEY);
1778 if (pdb)
1779 release_print_db(pdb);
1780 SAFE_FREE(data.dptr);
1781 return ret;
1784 /****************************************************************************
1785 Update an entry in the print tdb that will allow us to send notify
1786 updates only to interested smbd's.
1787 ****************************************************************************/
1789 bool print_notify_deregister_pid(int snum)
1791 TDB_DATA data;
1792 struct tdb_print_db *pdb = NULL;
1793 TDB_CONTEXT *tdb = NULL;
1794 const char *printername;
1795 uint32_t mypid = (uint32_t)getpid();
1796 size_t i;
1797 bool ret = False;
1799 /* if ( snum == -1 ), we are deregister a print server handle
1800 which means to deregister on all print queues */
1802 if (snum == -1)
1804 int num_services = lp_numservices();
1805 int idx;
1807 for ( idx=0; idx<num_services; idx++ ) {
1808 if ( lp_snum_ok(idx) && lp_printable(idx) )
1809 print_notify_deregister_pid(idx);
1812 return True;
1814 else /* deregister a specific printer */
1816 printername = lp_const_servicename(snum);
1817 pdb = get_print_db_byname(printername);
1818 if (!pdb)
1819 return False;
1820 tdb = pdb->tdb;
1823 if (tdb_lock_bystring_with_timeout(tdb, NOTIFY_PID_LIST_KEY, 10) != 0) {
1824 DEBUG(0,("print_notify_register_pid: Failed to lock \
1825 printer %s database\n", printername));
1826 if (pdb)
1827 release_print_db(pdb);
1828 return False;
1831 data = get_printer_notify_pid_list( tdb, printername, True );
1833 /* Reduce refcount. Remove ourselves if zero. */
1835 for (i = 0; i < data.dsize; ) {
1836 if (IVAL(data.dptr,i) == mypid) {
1837 uint32_t refcount = IVAL(data.dptr, i+4);
1839 refcount--;
1841 if (refcount == 0) {
1842 if (data.dsize - i > 8)
1843 memmove( &data.dptr[i], &data.dptr[i+8], data.dsize - i - 8);
1844 data.dsize -= 8;
1845 continue;
1847 SIVAL(data.dptr, i+4, refcount);
1850 i += 8;
1853 if (data.dsize == 0)
1854 SAFE_FREE(data.dptr);
1856 /* Store back the record. */
1857 if (tdb_store_bystring(tdb, NOTIFY_PID_LIST_KEY, data, TDB_REPLACE) != 0) {
1858 DEBUG(0,("print_notify_register_pid: Failed to update pid \
1859 list for printer %s\n", printername));
1860 goto done;
1863 ret = True;
1865 done:
1867 tdb_unlock_bystring(tdb, NOTIFY_PID_LIST_KEY);
1868 if (pdb)
1869 release_print_db(pdb);
1870 SAFE_FREE(data.dptr);
1871 return ret;
1874 /****************************************************************************
1875 Check if a jobid is valid. It is valid if it exists in the database.
1876 ****************************************************************************/
1878 bool print_job_exists(const char* sharename, uint32_t jobid)
1880 struct tdb_print_db *pdb = get_print_db_byname(sharename);
1881 bool ret;
1882 uint32_t tmp;
1884 if (!pdb)
1885 return False;
1886 ret = tdb_exists(pdb->tdb, print_key(jobid, &tmp));
1887 release_print_db(pdb);
1888 return ret;
1891 /****************************************************************************
1892 Return the device mode asigned to a specific print job.
1893 Only valid for the process doing the spooling and when the job
1894 has not been spooled.
1895 ****************************************************************************/
1897 struct spoolss_DeviceMode *print_job_devmode(TALLOC_CTX *mem_ctx,
1898 const char *sharename,
1899 uint32_t jobid)
1901 struct printjob *pjob = print_job_find(mem_ctx, sharename, jobid);
1902 if (pjob == NULL) {
1903 return NULL;
1906 return pjob->devmode;
1909 /****************************************************************************
1910 Set the name of a job. Only possible for owner.
1911 ****************************************************************************/
1913 bool print_job_set_name(struct tevent_context *ev,
1914 struct messaging_context *msg_ctx,
1915 const char *sharename, uint32_t jobid, const char *name)
1917 struct printjob *pjob;
1918 bool ret;
1919 TALLOC_CTX *tmp_ctx = talloc_new(ev);
1920 if (tmp_ctx == NULL) {
1921 return false;
1924 pjob = print_job_find(tmp_ctx, sharename, jobid);
1925 if (!pjob || pjob->pid != getpid()) {
1926 ret = false;
1927 goto err_out;
1930 fstrcpy(pjob->jobname, name);
1931 ret = pjob_store(ev, msg_ctx, sharename, jobid, pjob);
1932 err_out:
1933 talloc_free(tmp_ctx);
1934 return ret;
1937 /****************************************************************************
1938 Get the name of a job. Only possible for owner.
1939 ****************************************************************************/
1941 bool print_job_get_name(TALLOC_CTX *mem_ctx, const char *sharename, uint32_t jobid, char **name)
1943 struct printjob *pjob;
1945 pjob = print_job_find(mem_ctx, sharename, jobid);
1946 if (!pjob || pjob->pid != getpid()) {
1947 return false;
1950 *name = pjob->jobname;
1951 return true;
1955 /***************************************************************************
1956 Remove a jobid from the 'jobs added' list.
1957 ***************************************************************************/
1959 static bool remove_from_jobs_added(const char* sharename, uint32_t jobid)
1961 bool ret = remove_from_jobs_list("INFO/jobs_added", sharename, jobid);
1962 return ret;
1965 /****************************************************************************
1966 Delete a print job - don't update queue.
1967 ****************************************************************************/
1969 static bool print_job_delete1(struct tevent_context *ev,
1970 struct messaging_context *msg_ctx,
1971 int snum, uint32_t jobid)
1973 const char* sharename = lp_const_servicename(snum);
1974 const struct loadparm_substitution *lp_sub =
1975 loadparm_s3_global_substitution();
1976 struct printjob *pjob;
1977 int result = 0;
1978 struct printif *current_printif = get_printer_fns( snum );
1979 bool ret;
1980 TALLOC_CTX *tmp_ctx = talloc_new(ev);
1981 if (tmp_ctx == NULL) {
1982 return false;
1985 pjob = print_job_find(tmp_ctx, sharename, jobid);
1986 if (!pjob) {
1987 ret = false;
1988 goto err_out;
1992 * If already deleting just return.
1995 if (pjob->status == LPQ_DELETING) {
1996 ret = true;
1997 goto err_out;
2000 /* Hrm - we need to be able to cope with deleting a job before it
2001 has reached the spooler. Just mark it as LPQ_DELETING and
2002 let the print_queue_update() code rmeove the record */
2005 if (pjob->sysjob == -1) {
2006 DEBUG(5, ("attempt to delete job %u not seen by lpr\n", (unsigned int)jobid));
2009 /* Set the tdb entry to be deleting. */
2011 pjob->status = LPQ_DELETING;
2012 pjob_store(ev, msg_ctx, sharename, jobid, pjob);
2014 if (pjob->spooled && pjob->sysjob != -1)
2016 result = (*(current_printif->job_delete))(
2017 lp_printername(talloc_tos(), lp_sub, snum),
2018 lp_lprm_command(snum),
2019 pjob);
2021 /* Delete the tdb entry if the delete succeeded or the job hasn't
2022 been spooled. */
2024 if (result == 0) {
2025 struct tdb_print_db *pdb = get_print_db_byname(sharename);
2026 int njobs = 1;
2028 if (!pdb) {
2029 ret = false;
2030 goto err_out;
2032 pjob_delete(ev, msg_ctx, sharename, jobid);
2033 /* Ensure we keep a rough count of the number of total jobs... */
2034 tdb_change_int32_atomic(pdb->tdb, "INFO/total_jobs", &njobs, -1);
2035 release_print_db(pdb);
2039 remove_from_jobs_added( sharename, jobid );
2041 ret = (result == 0);
2042 err_out:
2043 talloc_free(tmp_ctx);
2044 return ret;
2047 /****************************************************************************
2048 Return true if the current user owns the print job.
2049 ****************************************************************************/
2051 static bool is_owner(const struct auth_session_info *server_info,
2052 const char *servicename,
2053 uint32_t jobid)
2055 struct printjob *pjob;
2056 bool ret;
2057 TALLOC_CTX *tmp_ctx = talloc_new(server_info);
2058 if (tmp_ctx == NULL) {
2059 return false;
2062 pjob = print_job_find(tmp_ctx, servicename, jobid);
2063 if (!pjob || !server_info) {
2064 ret = false;
2065 goto err_out;
2068 ret = strequal(pjob->user, server_info->unix_info->sanitized_username);
2069 err_out:
2070 talloc_free(tmp_ctx);
2071 return ret;
2074 /****************************************************************************
2075 Delete a print job.
2076 ****************************************************************************/
2078 WERROR print_job_delete(const struct auth_session_info *server_info,
2079 struct messaging_context *msg_ctx,
2080 int snum, uint32_t jobid)
2082 const char* sharename = lp_const_servicename(snum);
2083 const struct loadparm_substitution *lp_sub =
2084 loadparm_s3_global_substitution();
2085 struct printjob *pjob;
2086 bool owner;
2087 WERROR werr;
2088 TALLOC_CTX *tmp_ctx = talloc_new(msg_ctx);
2089 if (tmp_ctx == NULL) {
2090 return WERR_NOT_ENOUGH_MEMORY;
2093 owner = is_owner(server_info, lp_const_servicename(snum), jobid);
2095 /* Check access against security descriptor or whether the user
2096 owns their job. */
2098 if (!owner &&
2099 !W_ERROR_IS_OK(print_access_check(server_info, msg_ctx, snum,
2100 JOB_ACCESS_ADMINISTER))) {
2101 DEBUG(0, ("print job delete denied."
2102 "User name: %s, Printer name: %s.",
2103 uidtoname(server_info->unix_token->uid),
2104 lp_printername(tmp_ctx, lp_sub, snum)));
2106 werr = WERR_ACCESS_DENIED;
2107 goto err_out;
2111 * get the spooled filename of the print job
2112 * if this works, then the file has not been spooled
2113 * to the underlying print system. Just delete the
2114 * spool file & return.
2117 pjob = print_job_find(tmp_ctx, sharename, jobid);
2118 if (!pjob || pjob->spooled || pjob->pid != getpid()) {
2119 DEBUG(10, ("Skipping spool file removal for job %u\n", jobid));
2120 } else {
2121 DEBUG(10, ("Removing spool file [%s]\n", pjob->filename));
2122 if (unlink(pjob->filename) == -1) {
2123 werr = map_werror_from_unix(errno);
2124 goto err_out;
2128 if (!print_job_delete1(global_event_context(), msg_ctx, snum, jobid)) {
2129 werr = WERR_ACCESS_DENIED;
2130 goto err_out;
2133 /* force update the database and say the delete failed if the
2134 job still exists */
2136 print_queue_update(msg_ctx, snum, True);
2138 pjob = print_job_find(tmp_ctx, sharename, jobid);
2139 if (pjob && (pjob->status != LPQ_DELETING)) {
2140 werr = WERR_ACCESS_DENIED;
2141 goto err_out;
2143 werr = WERR_PRINTER_HAS_JOBS_QUEUED;
2145 err_out:
2146 talloc_free(tmp_ctx);
2147 return werr;
2150 /****************************************************************************
2151 Pause a job.
2152 ****************************************************************************/
2154 WERROR print_job_pause(const struct auth_session_info *server_info,
2155 struct messaging_context *msg_ctx,
2156 int snum, uint32_t jobid)
2158 const char* sharename = lp_const_servicename(snum);
2159 const struct loadparm_substitution *lp_sub =
2160 loadparm_s3_global_substitution();
2161 struct printjob *pjob;
2162 int ret = -1;
2163 struct printif *current_printif = get_printer_fns( snum );
2164 WERROR werr;
2165 TALLOC_CTX *tmp_ctx = talloc_new(msg_ctx);
2166 if (tmp_ctx == NULL) {
2167 return WERR_NOT_ENOUGH_MEMORY;
2170 pjob = print_job_find(tmp_ctx, sharename, jobid);
2171 if (!pjob || !server_info) {
2172 DEBUG(10, ("print_job_pause: no pjob or user for jobid %u\n",
2173 (unsigned int)jobid ));
2174 werr = WERR_INVALID_PARAMETER;
2175 goto err_out;
2178 if (!pjob->spooled || pjob->sysjob == -1) {
2179 DEBUG(10, ("print_job_pause: not spooled or bad sysjob = %d for jobid %u\n",
2180 (int)pjob->sysjob, (unsigned int)jobid ));
2181 werr = WERR_INVALID_PARAMETER;
2182 goto err_out;
2185 if (!is_owner(server_info, lp_const_servicename(snum), jobid) &&
2186 !W_ERROR_IS_OK(print_access_check(server_info, msg_ctx, snum,
2187 JOB_ACCESS_ADMINISTER))) {
2188 DEBUG(0, ("print job pause denied."
2189 "User name: %s, Printer name: %s.",
2190 uidtoname(server_info->unix_token->uid),
2191 lp_printername(tmp_ctx, lp_sub, snum)));
2193 werr = WERR_ACCESS_DENIED;
2194 goto err_out;
2197 /* need to pause the spooled entry */
2198 ret = (*(current_printif->job_pause))(snum, pjob);
2200 if (ret != 0) {
2201 werr = WERR_INVALID_PARAMETER;
2202 goto err_out;
2205 /* force update the database */
2206 print_cache_flush(lp_const_servicename(snum));
2208 /* Send a printer notify message */
2210 notify_job_status(global_event_context(), msg_ctx, sharename, jobid,
2211 JOB_STATUS_PAUSED);
2213 /* how do we tell if this succeeded? */
2214 werr = WERR_OK;
2215 err_out:
2216 talloc_free(tmp_ctx);
2217 return werr;
2220 /****************************************************************************
2221 Resume a job.
2222 ****************************************************************************/
2224 WERROR print_job_resume(const struct auth_session_info *server_info,
2225 struct messaging_context *msg_ctx,
2226 int snum, uint32_t jobid)
2228 const char *sharename = lp_const_servicename(snum);
2229 const struct loadparm_substitution *lp_sub =
2230 loadparm_s3_global_substitution();
2231 struct printjob *pjob;
2232 int ret;
2233 struct printif *current_printif = get_printer_fns( snum );
2234 WERROR werr;
2235 TALLOC_CTX *tmp_ctx = talloc_new(msg_ctx);
2236 if (tmp_ctx == NULL)
2237 return WERR_NOT_ENOUGH_MEMORY;
2239 pjob = print_job_find(tmp_ctx, sharename, jobid);
2240 if (!pjob || !server_info) {
2241 DEBUG(10, ("print_job_resume: no pjob or user for jobid %u\n",
2242 (unsigned int)jobid ));
2243 werr = WERR_INVALID_PARAMETER;
2244 goto err_out;
2247 if (!pjob->spooled || pjob->sysjob == -1) {
2248 DEBUG(10, ("print_job_resume: not spooled or bad sysjob = %d for jobid %u\n",
2249 (int)pjob->sysjob, (unsigned int)jobid ));
2250 werr = WERR_INVALID_PARAMETER;
2251 goto err_out;
2254 if (!is_owner(server_info, lp_const_servicename(snum), jobid) &&
2255 !W_ERROR_IS_OK(print_access_check(server_info, msg_ctx, snum,
2256 JOB_ACCESS_ADMINISTER))) {
2257 DEBUG(0, ("print job resume denied."
2258 "User name: %s, Printer name: %s.",
2259 uidtoname(server_info->unix_token->uid),
2260 lp_printername(tmp_ctx, lp_sub, snum)));
2262 werr = WERR_ACCESS_DENIED;
2263 goto err_out;
2266 ret = (*(current_printif->job_resume))(snum, pjob);
2268 if (ret != 0) {
2269 werr = WERR_INVALID_PARAMETER;
2270 goto err_out;
2273 /* force update the database */
2274 print_cache_flush(lp_const_servicename(snum));
2276 /* Send a printer notify message */
2278 notify_job_status(global_event_context(), msg_ctx, sharename, jobid,
2279 JOB_STATUS_QUEUED);
2281 werr = WERR_OK;
2282 err_out:
2283 talloc_free(tmp_ctx);
2284 return werr;
2287 /****************************************************************************
2288 Write to a print file.
2289 ****************************************************************************/
2291 ssize_t print_job_write(struct tevent_context *ev,
2292 struct messaging_context *msg_ctx,
2293 int snum, uint32_t jobid, const char *buf, size_t size)
2295 const char* sharename = lp_const_servicename(snum);
2296 ssize_t return_code;
2297 struct printjob *pjob;
2298 TALLOC_CTX *tmp_ctx = talloc_new(ev);
2299 if (tmp_ctx == NULL) {
2300 return -1;
2303 pjob = print_job_find(tmp_ctx, sharename, jobid);
2304 if (!pjob) {
2305 return_code = -1;
2306 goto err_out;
2309 /* don't allow another process to get this info - it is meaningless */
2310 if (pjob->pid != getpid()) {
2311 return_code = -1;
2312 goto err_out;
2315 /* if SMBD is spooling this can't be allowed */
2316 if (pjob->status == PJOB_SMBD_SPOOLING) {
2317 return_code = -1;
2318 goto err_out;
2321 return_code = write_data(pjob->fd, buf, size);
2322 if (return_code > 0) {
2323 pjob->size += size;
2324 pjob_store(ev, msg_ctx, sharename, jobid, pjob);
2326 err_out:
2327 talloc_free(tmp_ctx);
2328 return return_code;
2331 /****************************************************************************
2332 Get the queue status - do not update if db is out of date.
2333 ****************************************************************************/
2335 static int get_queue_status(const char* sharename, print_status_struct *status)
2337 fstring keystr;
2338 TDB_DATA data;
2339 struct tdb_print_db *pdb = get_print_db_byname(sharename);
2340 int len;
2342 if (status) {
2343 ZERO_STRUCTP(status);
2346 if (!pdb)
2347 return 0;
2349 if (status) {
2350 fstr_sprintf(keystr, "STATUS/%s", sharename);
2351 data = tdb_fetch(pdb->tdb, string_tdb_data(keystr));
2352 if (data.dptr) {
2353 if (data.dsize == sizeof(print_status_struct))
2354 /* this memcpy is ok since the status struct was
2355 not packed before storing it in the tdb */
2356 memcpy(status, data.dptr, sizeof(print_status_struct));
2357 SAFE_FREE(data.dptr);
2360 len = tdb_fetch_int32(pdb->tdb, "INFO/total_jobs");
2361 release_print_db(pdb);
2362 return (len == -1 ? 0 : len);
2365 /****************************************************************************
2366 Determine the number of jobs in a queue.
2367 ****************************************************************************/
2369 int print_queue_length(struct messaging_context *msg_ctx, int snum,
2370 print_status_struct *pstatus)
2372 const char* sharename = lp_const_servicename( snum );
2373 print_status_struct status;
2374 int len;
2376 ZERO_STRUCT( status );
2378 /* make sure the database is up to date */
2379 if (print_cache_expired(lp_const_servicename(snum), True))
2380 print_queue_update(msg_ctx, snum, False);
2382 /* also fetch the queue status */
2383 memset(&status, 0, sizeof(status));
2384 len = get_queue_status(sharename, &status);
2386 if (pstatus)
2387 *pstatus = status;
2389 return len;
2392 /***************************************************************************
2393 Allocate a jobid. Hold the lock for as short a time as possible.
2394 ***************************************************************************/
2396 static WERROR allocate_print_jobid(struct tdb_print_db *pdb, int snum,
2397 const char *sharename, uint32_t *pjobid)
2399 int i;
2400 uint32_t jobid;
2401 enum TDB_ERROR terr;
2402 int ret;
2404 *pjobid = (uint32_t)-1;
2406 for (i = 0; i < 3; i++) {
2407 /* Lock the database - only wait 20 seconds. */
2408 ret = tdb_lock_bystring_with_timeout(pdb->tdb,
2409 "INFO/nextjob", 20);
2410 if (ret != 0) {
2411 DEBUG(0, ("allocate_print_jobid: "
2412 "Failed to lock printing database %s\n",
2413 sharename));
2414 terr = tdb_error(pdb->tdb);
2415 return ntstatus_to_werror(map_nt_error_from_tdb(terr));
2418 if (!tdb_fetch_uint32(pdb->tdb, "INFO/nextjob", &jobid)) {
2419 terr = tdb_error(pdb->tdb);
2420 if (terr != TDB_ERR_NOEXIST) {
2421 DEBUG(0, ("allocate_print_jobid: "
2422 "Failed to fetch INFO/nextjob "
2423 "for print queue %s\n", sharename));
2424 tdb_unlock_bystring(pdb->tdb, "INFO/nextjob");
2425 return ntstatus_to_werror(map_nt_error_from_tdb(terr));
2427 DEBUG(10, ("allocate_print_jobid: "
2428 "No existing jobid in %s\n", sharename));
2429 jobid = 0;
2432 DEBUG(10, ("allocate_print_jobid: "
2433 "Read jobid %u from %s\n", jobid, sharename));
2435 jobid = NEXT_JOBID(jobid);
2437 ret = tdb_store_int32(pdb->tdb, "INFO/nextjob", jobid);
2438 if (ret != 0) {
2439 terr = tdb_error(pdb->tdb);
2440 DEBUG(3, ("allocate_print_jobid: "
2441 "Failed to store INFO/nextjob.\n"));
2442 tdb_unlock_bystring(pdb->tdb, "INFO/nextjob");
2443 return ntstatus_to_werror(map_nt_error_from_tdb(terr));
2446 /* We've finished with the INFO/nextjob lock. */
2447 tdb_unlock_bystring(pdb->tdb, "INFO/nextjob");
2449 if (!print_job_exists(sharename, jobid)) {
2450 break;
2452 DEBUG(10, ("allocate_print_jobid: "
2453 "Found jobid %u in %s\n", jobid, sharename));
2456 if (i > 2) {
2457 DEBUG(0, ("allocate_print_jobid: "
2458 "Failed to allocate a print job for queue %s\n",
2459 sharename));
2460 /* Probably full... */
2461 return WERR_NO_SPOOL_SPACE;
2464 /* Store a dummy placeholder. */
2466 uint32_t tmp;
2467 TDB_DATA dum;
2468 dum.dptr = NULL;
2469 dum.dsize = 0;
2470 if (tdb_store(pdb->tdb, print_key(jobid, &tmp), dum,
2471 TDB_INSERT) != 0) {
2472 DEBUG(3, ("allocate_print_jobid: "
2473 "jobid (%d) failed to store placeholder.\n",
2474 jobid ));
2475 terr = tdb_error(pdb->tdb);
2476 return ntstatus_to_werror(map_nt_error_from_tdb(terr));
2480 *pjobid = jobid;
2481 return WERR_OK;
2484 /***************************************************************************
2485 Do all checks needed to determine if we can start a job.
2486 ***************************************************************************/
2488 static WERROR print_job_checks(const struct auth_session_info *server_info,
2489 struct messaging_context *msg_ctx,
2490 int snum, int *njobs)
2492 const char *sharename = lp_const_servicename(snum);
2493 const struct loadparm_substitution *lp_sub =
2494 loadparm_s3_global_substitution();
2495 uint64_t dspace, dsize;
2496 uint64_t minspace;
2497 int ret;
2499 if (!W_ERROR_IS_OK(print_access_check(server_info, msg_ctx, snum,
2500 PRINTER_ACCESS_USE))) {
2501 DEBUG(3, ("print_job_checks: "
2502 "job start denied by security descriptor\n"));
2503 return WERR_ACCESS_DENIED;
2506 if (!print_time_access_check(server_info, msg_ctx, sharename)) {
2507 DEBUG(3, ("print_job_checks: "
2508 "job start denied by time check\n"));
2509 return WERR_ACCESS_DENIED;
2512 /* see if we have sufficient disk space */
2513 if (lp_min_print_space(snum)) {
2514 minspace = lp_min_print_space(snum);
2515 ret = sys_fsusage(lp_path(talloc_tos(), lp_sub, snum), &dspace, &dsize);
2516 if (ret == 0 && dspace < 2*minspace) {
2517 DEBUG(3, ("print_job_checks: "
2518 "disk space check failed.\n"));
2519 return WERR_NO_SPOOL_SPACE;
2523 /* for autoloaded printers, check that the printcap entry still exists */
2524 if (lp_autoloaded(snum) &&
2525 !printer_list_printername_exists(sharename)) {
2526 DEBUG(3, ("print_job_checks: printer name %s check failed.\n",
2527 sharename));
2528 return WERR_ACCESS_DENIED;
2531 /* Insure the maximum queue size is not violated */
2532 *njobs = print_queue_length(msg_ctx, snum, NULL);
2533 if (*njobs > lp_maxprintjobs(snum)) {
2534 DEBUG(3, ("print_job_checks: Queue %s number of jobs (%d) "
2535 "larger than max printjobs per queue (%d).\n",
2536 sharename, *njobs, lp_maxprintjobs(snum)));
2537 return WERR_NO_SPOOL_SPACE;
2540 return WERR_OK;
2543 /***************************************************************************
2544 Create a job file.
2545 ***************************************************************************/
2547 static WERROR print_job_spool_file(int snum, uint32_t jobid,
2548 const char *output_file,
2549 struct printjob *pjob)
2551 const struct loadparm_substitution *lp_sub =
2552 loadparm_s3_global_substitution();
2553 WERROR werr;
2554 SMB_STRUCT_STAT st;
2555 const char *path;
2556 int len;
2557 mode_t mask;
2559 /* if this file is within the printer path, it means that smbd
2560 * is spooling it and will pass us control when it is finished.
2561 * Verify that the file name is ok, within path, and it is
2562 * already already there */
2563 if (output_file) {
2564 path = lp_path(talloc_tos(), lp_sub, snum);
2565 len = strlen(path);
2566 if (strncmp(output_file, path, len) == 0 &&
2567 (output_file[len - 1] == '/' || output_file[len] == '/')) {
2569 /* verify path is not too long */
2570 if (strlen(output_file) >= sizeof(pjob->filename)) {
2571 return WERR_INVALID_NAME;
2574 /* verify that the file exists */
2575 if (sys_stat(output_file, &st, false) != 0) {
2576 return WERR_INVALID_NAME;
2579 fstrcpy(pjob->filename, output_file);
2581 DEBUG(3, ("print_job_spool_file:"
2582 "External spooling activated\n"));
2584 /* we do not open the file until spooling is done */
2585 pjob->fd = -1;
2586 pjob->status = PJOB_SMBD_SPOOLING;
2588 return WERR_OK;
2592 slprintf(pjob->filename, sizeof(pjob->filename)-1,
2593 "%s/%sXXXXXX", lp_path(talloc_tos(), lp_sub, snum),
2594 PRINT_SPOOL_PREFIX);
2595 mask = umask(S_IRWXO | S_IRWXG);
2596 pjob->fd = mkstemp(pjob->filename);
2597 umask(mask);
2599 if (pjob->fd == -1) {
2600 werr = map_werror_from_unix(errno);
2601 if (W_ERROR_EQUAL(werr, WERR_ACCESS_DENIED)) {
2602 /* Common setup error, force a report. */
2603 DEBUG(0, ("print_job_spool_file: "
2604 "insufficient permissions to open spool "
2605 "file %s.\n", pjob->filename));
2606 } else {
2607 /* Normal case, report at level 3 and above. */
2608 DEBUG(3, ("print_job_spool_file: "
2609 "can't open spool file %s\n",
2610 pjob->filename));
2612 return werr;
2615 return WERR_OK;
2618 /***************************************************************************
2619 Start spooling a job - return the jobid.
2620 ***************************************************************************/
2622 WERROR print_job_start(const struct auth_session_info *server_info,
2623 struct messaging_context *msg_ctx,
2624 const char *clientmachine,
2625 int snum, const char *docname, const char *filename,
2626 struct spoolss_DeviceMode *devmode, uint32_t *_jobid)
2628 uint32_t jobid;
2629 char *path = NULL, *userstr = NULL;
2630 struct printjob pjob;
2631 const char *sharename = lp_const_servicename(snum);
2632 struct tdb_print_db *pdb = get_print_db_byname(sharename);
2633 const struct loadparm_substitution *lp_sub =
2634 loadparm_s3_global_substitution();
2635 int njobs;
2636 WERROR werr;
2638 if (!pdb) {
2639 return WERR_INTERNAL_DB_CORRUPTION;
2642 path = lp_path(talloc_tos(), lp_sub, snum);
2644 werr = print_job_checks(server_info, msg_ctx, snum, &njobs);
2645 if (!W_ERROR_IS_OK(werr)) {
2646 release_print_db(pdb);
2647 return werr;
2650 DEBUG(10, ("print_job_start: "
2651 "Queue %s number of jobs (%d), max printjobs = %d\n",
2652 sharename, njobs, lp_maxprintjobs(snum)));
2654 werr = allocate_print_jobid(pdb, snum, sharename, &jobid);
2655 if (!W_ERROR_IS_OK(werr)) {
2656 goto fail;
2659 /* create the database entry */
2661 ZERO_STRUCT(pjob);
2663 pjob.pid = getpid();
2664 pjob.jobid = jobid;
2665 pjob.sysjob = -1;
2666 pjob.fd = -1;
2667 pjob.starttime = time(NULL);
2668 pjob.status = LPQ_SPOOLING;
2669 pjob.size = 0;
2670 pjob.spooled = False;
2671 pjob.smbjob = True;
2672 pjob.devmode = devmode;
2674 fstrcpy(pjob.jobname, docname);
2676 fstrcpy(pjob.clientmachine, clientmachine);
2678 userstr = talloc_sub_full(talloc_tos(),
2679 sharename,
2680 server_info->unix_info->sanitized_username,
2681 path, server_info->unix_token->gid,
2682 server_info->unix_info->sanitized_username,
2683 server_info->info->domain_name,
2684 lp_printjob_username(snum));
2685 if (userstr == NULL) {
2686 werr = WERR_NOT_ENOUGH_MEMORY;
2687 goto fail;
2689 strlcpy(pjob.user, userstr, sizeof(pjob.user));
2690 TALLOC_FREE(userstr);
2692 fstrcpy(pjob.queuename, lp_const_servicename(snum));
2694 /* we have a job entry - now create the spool file */
2695 werr = print_job_spool_file(snum, jobid, filename, &pjob);
2696 if (!W_ERROR_IS_OK(werr)) {
2697 goto fail;
2700 pjob_store(global_event_context(), msg_ctx, sharename, jobid, &pjob);
2702 /* Update the 'jobs added' entry used by print_queue_status. */
2703 add_to_jobs_list(pdb, jobid, "INFO/jobs_added");
2705 /* Ensure we keep a rough count of the number of total jobs... */
2706 tdb_change_int32_atomic(pdb->tdb, "INFO/total_jobs", &njobs, 1);
2708 release_print_db(pdb);
2710 *_jobid = jobid;
2711 return WERR_OK;
2713 fail:
2714 if (jobid != -1) {
2715 pjob_delete(global_event_context(), msg_ctx, sharename, jobid);
2718 release_print_db(pdb);
2720 DEBUG(3, ("print_job_start: returning fail. "
2721 "Error = %s\n", win_errstr(werr)));
2722 return werr;
2725 /****************************************************************************
2726 Update the number of pages spooled to jobid
2727 ****************************************************************************/
2729 void print_job_endpage(struct messaging_context *msg_ctx,
2730 int snum, uint32_t jobid)
2732 const char* sharename = lp_const_servicename(snum);
2733 struct printjob *pjob;
2734 TALLOC_CTX *tmp_ctx = talloc_new(msg_ctx);
2735 if (tmp_ctx == NULL) {
2736 return;
2739 pjob = print_job_find(tmp_ctx, sharename, jobid);
2740 if (!pjob) {
2741 goto err_out;
2743 /* don't allow another process to get this info - it is meaningless */
2744 if (pjob->pid != getpid()) {
2745 goto err_out;
2748 pjob->page_count++;
2749 pjob_store(global_event_context(), msg_ctx, sharename, jobid, pjob);
2750 err_out:
2751 talloc_free(tmp_ctx);
2754 /****************************************************************************
2755 Print a file - called on closing the file. This spools the job.
2756 If normal close is false then we're tearing down the jobs - treat as an
2757 error.
2758 ****************************************************************************/
2760 NTSTATUS print_job_end(struct messaging_context *msg_ctx, int snum,
2761 uint32_t jobid, enum file_close_type close_type)
2763 const char* sharename = lp_const_servicename(snum);
2764 const struct loadparm_substitution *lp_sub =
2765 loadparm_s3_global_substitution();
2766 struct printjob *pjob;
2767 int ret;
2768 SMB_STRUCT_STAT sbuf;
2769 struct printif *current_printif = get_printer_fns(snum);
2770 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
2771 char *lpq_cmd;
2772 TALLOC_CTX *tmp_ctx = talloc_new(msg_ctx);
2773 if (tmp_ctx == NULL) {
2774 return NT_STATUS_NO_MEMORY;
2777 pjob = print_job_find(tmp_ctx, sharename, jobid);
2778 if (!pjob) {
2779 status = NT_STATUS_PRINT_CANCELLED;
2780 goto err_out;
2783 if (pjob->spooled || pjob->pid != getpid()) {
2784 status = NT_STATUS_ACCESS_DENIED;
2785 goto err_out;
2788 if (close_type == NORMAL_CLOSE || close_type == SHUTDOWN_CLOSE) {
2789 if (pjob->status == PJOB_SMBD_SPOOLING) {
2790 /* take over the file now, smbd is done */
2791 if (sys_stat(pjob->filename, &sbuf, false) != 0) {
2792 status = map_nt_error_from_unix(errno);
2793 DEBUG(3, ("print_job_end: "
2794 "stat file failed for jobid %d\n",
2795 jobid));
2796 goto fail;
2799 pjob->status = LPQ_SPOOLING;
2801 } else {
2803 if ((sys_fstat(pjob->fd, &sbuf, false) != 0)) {
2804 status = map_nt_error_from_unix(errno);
2805 close(pjob->fd);
2806 DEBUG(3, ("print_job_end: "
2807 "stat file failed for jobid %d\n",
2808 jobid));
2809 goto fail;
2812 close(pjob->fd);
2815 pjob->size = sbuf.st_ex_size;
2816 } else {
2819 * Not a normal close, something has gone wrong. Cleanup.
2821 if (pjob->fd != -1) {
2822 close(pjob->fd);
2824 goto fail;
2827 /* Technically, this is not quite right. If the printer has a separator
2828 * page turned on, the NT spooler prints the separator page even if the
2829 * print job is 0 bytes. 010215 JRR */
2830 if (pjob->size == 0 || pjob->status == LPQ_DELETING) {
2831 /* don't bother spooling empty files or something being deleted. */
2832 DEBUG(5,("print_job_end: canceling spool of %s (%s)\n",
2833 pjob->filename, pjob->size ? "deleted" : "zero length" ));
2834 unlink(pjob->filename);
2835 pjob_delete(global_event_context(), msg_ctx, sharename, jobid);
2836 return NT_STATUS_OK;
2839 /* don't strip out characters like '$' from the printername */
2840 lpq_cmd = talloc_string_sub2(tmp_ctx,
2841 lp_lpq_command(snum),
2842 "%p",
2843 lp_printername(talloc_tos(), lp_sub, snum),
2844 false, false, false);
2845 if (lpq_cmd == NULL) {
2846 status = NT_STATUS_PRINT_CANCELLED;
2847 goto fail;
2849 lpq_cmd = talloc_sub_full(tmp_ctx,
2850 lp_servicename(talloc_tos(), lp_sub, snum),
2851 current_user_info.unix_name,
2853 get_current_gid(NULL),
2854 get_current_username(),
2855 current_user_info.domain,
2856 lpq_cmd);
2857 if (lpq_cmd == NULL) {
2858 status = NT_STATUS_PRINT_CANCELLED;
2859 goto fail;
2862 ret = (*(current_printif->job_submit))(snum, pjob,
2863 current_printif->type, lpq_cmd);
2864 if (ret) {
2865 status = NT_STATUS_PRINT_CANCELLED;
2866 goto fail;
2869 /* The print job has been successfully handed over to the back-end */
2871 pjob->spooled = True;
2872 pjob->status = LPQ_QUEUED;
2873 pjob_store(global_event_context(), msg_ctx, sharename, jobid, pjob);
2875 /* make sure the database is up to date */
2876 if (print_cache_expired(lp_const_servicename(snum), True))
2877 print_queue_update(msg_ctx, snum, False);
2879 return NT_STATUS_OK;
2881 fail:
2883 /* The print job was not successfully started. Cleanup */
2884 /* Still need to add proper error return propagation! 010122:JRR */
2885 pjob->fd = -1;
2886 unlink(pjob->filename);
2887 pjob_delete(global_event_context(), msg_ctx, sharename, jobid);
2888 err_out:
2889 talloc_free(tmp_ctx);
2890 return status;
2893 /****************************************************************************
2894 Get a snapshot of jobs in the system without traversing.
2895 ****************************************************************************/
2897 static bool get_stored_queue_info(struct messaging_context *msg_ctx,
2898 struct tdb_print_db *pdb, int snum,
2899 int *pcount, print_queue_struct **ppqueue)
2901 const struct loadparm_substitution *lp_sub =
2902 loadparm_s3_global_substitution();
2903 TDB_DATA data, cgdata, jcdata;
2904 print_queue_struct *queue = NULL;
2905 uint32_t qcount = 0;
2906 uint32_t extra_count = 0;
2907 uint32_t changed_count = 0;
2908 int total_count = 0;
2909 size_t len = 0;
2910 uint32_t i;
2911 int max_reported_jobs = lp_max_reported_print_jobs(snum);
2912 bool ret = false;
2913 const char* sharename = lp_servicename(talloc_tos(), lp_sub, snum);
2914 TALLOC_CTX *tmp_ctx = talloc_new(msg_ctx);
2915 if (tmp_ctx == NULL) {
2916 return false;
2919 /* make sure the database is up to date */
2920 if (print_cache_expired(lp_const_servicename(snum), True))
2921 print_queue_update(msg_ctx, snum, False);
2923 *pcount = 0;
2924 *ppqueue = NULL;
2926 ZERO_STRUCT(data);
2927 ZERO_STRUCT(cgdata);
2929 /* Get the stored queue data. */
2930 data = tdb_fetch(pdb->tdb, string_tdb_data("INFO/linear_queue_array"));
2932 if (data.dptr && data.dsize >= sizeof(qcount))
2933 len += tdb_unpack(data.dptr + len, data.dsize - len, "d", &qcount);
2935 /* Get the added jobs list. */
2936 cgdata = tdb_fetch(pdb->tdb, string_tdb_data("INFO/jobs_added"));
2937 if (cgdata.dptr != NULL && (cgdata.dsize % 4 == 0))
2938 extra_count = cgdata.dsize/4;
2940 /* Get the changed jobs list. */
2941 jcdata = tdb_fetch(pdb->tdb, string_tdb_data("INFO/jobs_changed"));
2942 if (jcdata.dptr != NULL && (jcdata.dsize % 4 == 0))
2943 changed_count = jcdata.dsize / 4;
2945 DEBUG(5,("get_stored_queue_info: qcount = %u, extra_count = %u\n", (unsigned int)qcount, (unsigned int)extra_count));
2947 /* Allocate the queue size. */
2948 if (qcount == 0 && extra_count == 0)
2949 goto out;
2951 if ((queue = SMB_MALLOC_ARRAY(print_queue_struct, qcount + extra_count)) == NULL)
2952 goto out;
2954 /* Retrieve the linearised queue data. */
2956 for(i = 0; i < qcount; i++) {
2957 uint32_t qjob, qsize, qpage_count, qstatus, qpriority, qtime;
2958 len += tdb_unpack(data.dptr + len, data.dsize - len, "ddddddff",
2959 &qjob,
2960 &qsize,
2961 &qpage_count,
2962 &qstatus,
2963 &qpriority,
2964 &qtime,
2965 queue[i].fs_user,
2966 queue[i].fs_file);
2967 queue[i].sysjob = qjob;
2968 queue[i].size = qsize;
2969 queue[i].page_count = qpage_count;
2970 queue[i].status = qstatus;
2971 queue[i].priority = qpriority;
2972 queue[i].time = qtime;
2975 total_count = qcount;
2977 /* Add new jobids to the queue. */
2978 for (i = 0; i < extra_count; i++) {
2979 uint32_t jobid;
2980 struct printjob *pjob;
2982 jobid = IVAL(cgdata.dptr, i*4);
2983 DEBUG(5,("get_stored_queue_info: added job = %u\n", (unsigned int)jobid));
2984 pjob = print_job_find(tmp_ctx, lp_const_servicename(snum), jobid);
2985 if (!pjob) {
2986 DEBUG(5,("get_stored_queue_info: failed to find added job = %u\n", (unsigned int)jobid));
2987 remove_from_jobs_added(sharename, jobid);
2988 continue;
2991 queue[total_count].sysjob = pjob->sysjob;
2992 queue[total_count].size = pjob->size;
2993 queue[total_count].page_count = pjob->page_count;
2994 queue[total_count].status = pjob->status;
2995 queue[total_count].priority = 1;
2996 queue[total_count].time = pjob->starttime;
2997 fstrcpy(queue[total_count].fs_user, pjob->user);
2998 fstrcpy(queue[total_count].fs_file, pjob->jobname);
2999 total_count++;
3000 talloc_free(pjob);
3003 /* Update the changed jobids. */
3004 for (i = 0; i < changed_count; i++) {
3005 uint32_t jobid = IVAL(jcdata.dptr, i * 4);
3006 struct printjob *pjob;
3007 uint32_t j;
3008 bool found = false;
3010 pjob = print_job_find(tmp_ctx, sharename, jobid);
3011 if (pjob == NULL) {
3012 DEBUG(5,("get_stored_queue_info: failed to find "
3013 "changed job = %u\n",
3014 (unsigned int)jobid));
3015 remove_from_jobs_changed(sharename, jobid);
3016 continue;
3019 for (j = 0; j < total_count; j++) {
3020 if (queue[j].sysjob == pjob->sysjob) {
3021 found = true;
3022 break;
3026 if (found) {
3027 DEBUG(5,("get_stored_queue_info: changed job: %u\n",
3028 (unsigned int)jobid));
3030 queue[j].sysjob = pjob->sysjob;
3031 queue[j].size = pjob->size;
3032 queue[j].page_count = pjob->page_count;
3033 queue[j].status = pjob->status;
3034 queue[j].priority = 1;
3035 queue[j].time = pjob->starttime;
3036 fstrcpy(queue[j].fs_user, pjob->user);
3037 fstrcpy(queue[j].fs_file, pjob->jobname);
3038 talloc_free(pjob);
3040 DEBUG(5,("updated queue[%u], jobid: %u, sysjob: %u, "
3041 "jobname: %s\n",
3042 (unsigned int)j, (unsigned int)jobid,
3043 (unsigned int)queue[j].sysjob, pjob->jobname));
3046 remove_from_jobs_changed(sharename, jobid);
3049 /* Sort the queue by submission time otherwise they are displayed
3050 in hash order. */
3052 TYPESAFE_QSORT(queue, total_count, printjob_comp);
3054 DEBUG(5,("get_stored_queue_info: total_count = %u\n", (unsigned int)total_count));
3056 if (max_reported_jobs && total_count > max_reported_jobs)
3057 total_count = max_reported_jobs;
3059 *ppqueue = queue;
3060 *pcount = total_count;
3062 ret = true;
3064 out:
3066 SAFE_FREE(data.dptr);
3067 SAFE_FREE(cgdata.dptr);
3068 talloc_free(tmp_ctx);
3069 return ret;
3072 /****************************************************************************
3073 Get a printer queue listing.
3074 set queue = NULL and status = NULL if you just want to update the cache
3075 ****************************************************************************/
3077 int print_queue_status(struct messaging_context *msg_ctx, int snum,
3078 print_queue_struct **ppqueue,
3079 print_status_struct *status)
3081 fstring keystr;
3082 TDB_DATA data, key;
3083 const char *sharename;
3084 struct tdb_print_db *pdb;
3085 int count = 0;
3087 /* make sure the database is up to date */
3089 if (print_cache_expired(lp_const_servicename(snum), True))
3090 print_queue_update(msg_ctx, snum, False);
3092 /* return if we are done */
3093 if ( !ppqueue || !status )
3094 return 0;
3096 *ppqueue = NULL;
3097 sharename = lp_const_servicename(snum);
3098 pdb = get_print_db_byname(sharename);
3100 if (!pdb)
3101 return 0;
3104 * Fetch the queue status. We must do this first, as there may
3105 * be no jobs in the queue.
3108 ZERO_STRUCTP(status);
3109 slprintf(keystr, sizeof(keystr)-1, "STATUS/%s", sharename);
3110 key = string_tdb_data(keystr);
3112 data = tdb_fetch(pdb->tdb, key);
3113 if (data.dptr) {
3114 if (data.dsize == sizeof(*status)) {
3115 /* this memcpy is ok since the status struct was
3116 not packed before storing it in the tdb */
3117 memcpy(status, data.dptr, sizeof(*status));
3119 SAFE_FREE(data.dptr);
3123 * Now, fetch the print queue information. We first count the number
3124 * of entries, and then only retrieve the queue if necessary.
3127 if (!get_stored_queue_info(msg_ctx, pdb, snum, &count, ppqueue)) {
3128 release_print_db(pdb);
3129 return 0;
3132 release_print_db(pdb);
3133 return count;
3136 /****************************************************************************
3137 Pause a queue.
3138 ****************************************************************************/
3140 WERROR print_queue_pause(const struct auth_session_info *server_info,
3141 struct messaging_context *msg_ctx, int snum)
3143 int ret;
3144 struct printif *current_printif = get_printer_fns( snum );
3146 if (!W_ERROR_IS_OK(print_access_check(server_info, msg_ctx, snum,
3147 PRINTER_ACCESS_ADMINISTER))) {
3148 return WERR_ACCESS_DENIED;
3152 become_root();
3154 ret = (*(current_printif->queue_pause))(snum);
3156 unbecome_root();
3158 if (ret != 0) {
3159 return WERR_INVALID_PARAMETER;
3162 /* force update the database */
3163 print_cache_flush(lp_const_servicename(snum));
3165 /* Send a printer notify message */
3167 notify_printer_status(global_event_context(), msg_ctx, snum,
3168 PRINTER_STATUS_PAUSED);
3170 return WERR_OK;
3173 /****************************************************************************
3174 Resume a queue.
3175 ****************************************************************************/
3177 WERROR print_queue_resume(const struct auth_session_info *server_info,
3178 struct messaging_context *msg_ctx, int snum)
3180 int ret;
3181 struct printif *current_printif = get_printer_fns( snum );
3183 if (!W_ERROR_IS_OK(print_access_check(server_info, msg_ctx, snum,
3184 PRINTER_ACCESS_ADMINISTER))) {
3185 return WERR_ACCESS_DENIED;
3188 become_root();
3190 ret = (*(current_printif->queue_resume))(snum);
3192 unbecome_root();
3194 if (ret != 0) {
3195 return WERR_INVALID_PARAMETER;
3198 /* make sure the database is up to date */
3199 if (print_cache_expired(lp_const_servicename(snum), True))
3200 print_queue_update(msg_ctx, snum, True);
3202 /* Send a printer notify message */
3204 notify_printer_status(global_event_context(), msg_ctx, snum,
3205 PRINTER_STATUS_OK);
3207 return WERR_OK;
3210 /****************************************************************************
3211 Purge a queue - implemented by deleting all jobs that we can delete.
3212 ****************************************************************************/
3214 WERROR print_queue_purge(const struct auth_session_info *server_info,
3215 struct messaging_context *msg_ctx, int snum)
3217 print_queue_struct *queue;
3218 print_status_struct status;
3219 int njobs, i;
3220 bool can_job_admin;
3222 /* Force and update so the count is accurate (i.e. not a cached count) */
3223 print_queue_update(msg_ctx, snum, True);
3225 can_job_admin = W_ERROR_IS_OK(print_access_check(server_info,
3226 msg_ctx,
3227 snum,
3228 JOB_ACCESS_ADMINISTER));
3229 njobs = print_queue_status(msg_ctx, snum, &queue, &status);
3231 if ( can_job_admin )
3232 become_root();
3234 for (i = 0; i < njobs; i++) {
3235 struct tdb_print_db *pdb;
3236 int jobid;
3237 bool owner;
3238 pdb = get_print_db_byname(lp_const_servicename(snum));
3239 if (pdb == NULL) {
3240 DEBUG(1, ("failed to find printdb for %s\n",
3241 lp_const_servicename(snum)));
3242 continue;
3244 jobid = sysjob_to_jobid_pdb(pdb, queue[i].sysjob);
3245 if (jobid == (uint32_t)-1) {
3246 DEBUG(2, ("jobid for system job %d not found\n",
3247 queue[i].sysjob));
3248 continue; /* unix job */
3250 owner = is_owner(server_info, lp_const_servicename(snum),
3251 jobid);
3253 if (owner || can_job_admin) {
3254 print_job_delete1(global_event_context(), msg_ctx,
3255 snum, jobid);
3259 if ( can_job_admin )
3260 unbecome_root();
3262 /* update the cache */
3263 print_queue_update(msg_ctx, snum, True);
3265 SAFE_FREE(queue);
3267 return WERR_OK;