Revert "buildtools: Rename perl vendorarch configure option."
[Samba.git] / source3 / printing / printing.c
blob3129e10edfb27aedfa02198fe8eac94ce30e444d
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"
40 extern struct current_user current_user;
41 extern userdom_struct current_user_info;
43 /* Current printer interface */
44 static bool remove_from_jobs_added(const char* sharename, uint32 jobid);
47 the printing backend revolves around a tdb database that stores the
48 SMB view of the print queue
50 The key for this database is a jobid - a internally generated number that
51 uniquely identifies a print job
53 reading the print queue involves two steps:
54 - possibly running lpq and updating the internal database from that
55 - reading entries from the database
57 jobids are assigned when a job starts spooling.
60 static TDB_CONTEXT *rap_tdb;
61 static uint16 next_rap_jobid;
62 struct rap_jobid_key {
63 fstring sharename;
64 uint32 jobid;
67 /***************************************************************************
68 Nightmare. LANMAN jobid's are 16 bit numbers..... We must map them to 32
69 bit RPC jobids.... JRA.
70 ***************************************************************************/
72 uint16 pjobid_to_rap(const char* sharename, uint32 jobid)
74 uint16 rap_jobid;
75 TDB_DATA data, key;
76 struct rap_jobid_key jinfo;
77 uint8 buf[2];
79 DEBUG(10,("pjobid_to_rap: called.\n"));
81 if (!rap_tdb) {
82 /* Create the in-memory tdb. */
83 rap_tdb = tdb_open_log(NULL, 0, TDB_INTERNAL, (O_RDWR|O_CREAT), 0644);
84 if (!rap_tdb)
85 return 0;
88 ZERO_STRUCT( jinfo );
89 fstrcpy( jinfo.sharename, sharename );
90 jinfo.jobid = jobid;
91 key.dptr = (uint8 *)&jinfo;
92 key.dsize = sizeof(jinfo);
94 data = tdb_fetch_compat(rap_tdb, key);
95 if (data.dptr && data.dsize == sizeof(uint16)) {
96 rap_jobid = SVAL(data.dptr, 0);
97 SAFE_FREE(data.dptr);
98 DEBUG(10,("pjobid_to_rap: jobid %u maps to RAP jobid %u\n",
99 (unsigned int)jobid, (unsigned int)rap_jobid));
100 return rap_jobid;
102 SAFE_FREE(data.dptr);
103 /* Not found - create and store mapping. */
104 rap_jobid = ++next_rap_jobid;
105 if (rap_jobid == 0)
106 rap_jobid = ++next_rap_jobid;
107 SSVAL(buf,0,rap_jobid);
108 data.dptr = buf;
109 data.dsize = sizeof(rap_jobid);
110 tdb_store(rap_tdb, key, data, TDB_REPLACE);
111 tdb_store(rap_tdb, data, key, TDB_REPLACE);
113 DEBUG(10,("pjobid_to_rap: created jobid %u maps to RAP jobid %u\n",
114 (unsigned int)jobid, (unsigned int)rap_jobid));
115 return rap_jobid;
118 bool rap_to_pjobid(uint16 rap_jobid, fstring sharename, uint32 *pjobid)
120 TDB_DATA data, key;
121 uint8 buf[2];
123 DEBUG(10,("rap_to_pjobid called.\n"));
125 if (!rap_tdb)
126 return False;
128 SSVAL(buf,0,rap_jobid);
129 key.dptr = buf;
130 key.dsize = sizeof(rap_jobid);
131 data = tdb_fetch_compat(rap_tdb, key);
132 if ( data.dptr && data.dsize == sizeof(struct rap_jobid_key) )
134 struct rap_jobid_key *jinfo = (struct rap_jobid_key*)data.dptr;
135 if (sharename != NULL) {
136 fstrcpy( sharename, jinfo->sharename );
138 *pjobid = jinfo->jobid;
139 DEBUG(10,("rap_to_pjobid: jobid %u maps to RAP jobid %u\n",
140 (unsigned int)*pjobid, (unsigned int)rap_jobid));
141 SAFE_FREE(data.dptr);
142 return True;
145 DEBUG(10,("rap_to_pjobid: Failed to lookup RAP jobid %u\n",
146 (unsigned int)rap_jobid));
147 SAFE_FREE(data.dptr);
148 return False;
151 void rap_jobid_delete(const char* sharename, uint32 jobid)
153 TDB_DATA key, data;
154 uint16 rap_jobid;
155 struct rap_jobid_key jinfo;
156 uint8 buf[2];
158 DEBUG(10,("rap_jobid_delete: called.\n"));
160 if (!rap_tdb)
161 return;
163 ZERO_STRUCT( jinfo );
164 fstrcpy( jinfo.sharename, sharename );
165 jinfo.jobid = jobid;
166 key.dptr = (uint8 *)&jinfo;
167 key.dsize = sizeof(jinfo);
169 data = tdb_fetch_compat(rap_tdb, key);
170 if (!data.dptr || (data.dsize != sizeof(uint16))) {
171 DEBUG(10,("rap_jobid_delete: cannot find jobid %u\n",
172 (unsigned int)jobid ));
173 SAFE_FREE(data.dptr);
174 return;
177 DEBUG(10,("rap_jobid_delete: deleting jobid %u\n",
178 (unsigned int)jobid ));
180 rap_jobid = SVAL(data.dptr, 0);
181 SAFE_FREE(data.dptr);
182 SSVAL(buf,0,rap_jobid);
183 data.dptr = buf;
184 data.dsize = sizeof(rap_jobid);
185 tdb_delete(rap_tdb, key);
186 tdb_delete(rap_tdb, data);
189 static int get_queue_status(const char* sharename, print_status_struct *);
191 /****************************************************************************
192 Initialise the printing backend. Called once at startup before the fork().
193 ****************************************************************************/
195 bool print_backend_init(struct messaging_context *msg_ctx)
197 const char *sversion = "INFO/version";
198 int services = lp_numservices();
199 int snum;
200 bool ok;
202 if (!printer_list_parent_init()) {
203 return false;
206 ok = directory_create_or_exist(cache_path("printing"), geteuid(), 0755);
207 if (!ok) {
208 return false;
211 unlink(cache_path("printing.tdb"));
213 /* handle a Samba upgrade */
215 for (snum = 0; snum < services; snum++) {
216 struct tdb_print_db *pdb;
217 if (!lp_print_ok(snum))
218 continue;
220 pdb = get_print_db_byname(lp_const_servicename(snum));
221 if (!pdb)
222 continue;
223 if (tdb_lock_bystring(pdb->tdb, sversion) != 0) {
224 DEBUG(0,("print_backend_init: Failed to open printer %s database\n", lp_const_servicename(snum) ));
225 release_print_db(pdb);
226 return False;
228 if (tdb_fetch_int32(pdb->tdb, sversion) != PRINT_DATABASE_VERSION) {
229 tdb_wipe_all(pdb->tdb);
230 tdb_store_int32(pdb->tdb, sversion, PRINT_DATABASE_VERSION);
232 tdb_unlock_bystring(pdb->tdb, sversion);
233 release_print_db(pdb);
236 close_all_print_db(); /* Don't leave any open. */
238 /* do NT print initialization... */
239 return nt_printing_init(msg_ctx);
242 /****************************************************************************
243 Shut down printing backend. Called once at shutdown to close the tdb.
244 ****************************************************************************/
246 void printing_end(void)
248 close_all_print_db(); /* Don't leave any open. */
251 /****************************************************************************
252 Retrieve the set of printing functions for a given service. This allows
253 us to set the printer function table based on the value of the 'printing'
254 service parameter.
256 Use the generic interface as the default and only use cups interface only
257 when asked for (and only when supported)
258 ****************************************************************************/
260 static struct printif *get_printer_fns_from_type( enum printing_types type )
262 struct printif *printer_fns = &generic_printif;
264 #ifdef HAVE_CUPS
265 if ( type == PRINT_CUPS ) {
266 printer_fns = &cups_printif;
268 #endif /* HAVE_CUPS */
270 #ifdef HAVE_IPRINT
271 if ( type == PRINT_IPRINT ) {
272 printer_fns = &iprint_printif;
274 #endif /* HAVE_IPRINT */
276 printer_fns->type = type;
278 return printer_fns;
281 static struct printif *get_printer_fns( int snum )
283 return get_printer_fns_from_type( (enum printing_types)lp_printing(snum) );
287 /****************************************************************************
288 Useful function to generate a tdb key.
289 ****************************************************************************/
291 static TDB_DATA print_key(uint32 jobid, uint32 *tmp)
293 TDB_DATA ret;
295 SIVAL(tmp, 0, jobid);
296 ret.dptr = (uint8 *)tmp;
297 ret.dsize = sizeof(*tmp);
298 return ret;
301 /****************************************************************************
302 Pack the devicemode to store it in a tdb.
303 ****************************************************************************/
304 static int pack_devicemode(struct spoolss_DeviceMode *devmode, uint8 *buf, int buflen)
306 enum ndr_err_code ndr_err;
307 DATA_BLOB blob;
308 int len = 0;
310 if (devmode) {
311 ndr_err = ndr_push_struct_blob(&blob, talloc_tos(),
312 devmode,
313 (ndr_push_flags_fn_t)
314 ndr_push_spoolss_DeviceMode);
315 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
316 DEBUG(10, ("pack_devicemode: "
317 "error encoding spoolss_DeviceMode\n"));
318 goto done;
320 } else {
321 ZERO_STRUCT(blob);
324 len = tdb_pack(buf, buflen, "B", blob.length, blob.data);
326 if (devmode) {
327 DEBUG(8, ("Packed devicemode [%s]\n", devmode->formname));
330 done:
331 return len;
334 /****************************************************************************
335 Unpack the devicemode to store it in a tdb.
336 ****************************************************************************/
337 static int unpack_devicemode(TALLOC_CTX *mem_ctx,
338 const uint8 *buf, int buflen,
339 struct spoolss_DeviceMode **devmode)
341 struct spoolss_DeviceMode *dm;
342 enum ndr_err_code ndr_err;
343 char *data = NULL;
344 int data_len = 0;
345 DATA_BLOB blob;
346 int len = 0;
348 *devmode = NULL;
350 len = tdb_unpack(buf, buflen, "B", &data_len, &data);
351 if (!data) {
352 return len;
355 dm = talloc_zero(mem_ctx, struct spoolss_DeviceMode);
356 if (!dm) {
357 goto done;
360 blob = data_blob_const(data, data_len);
362 ndr_err = ndr_pull_struct_blob(&blob, dm, dm,
363 (ndr_pull_flags_fn_t)ndr_pull_spoolss_DeviceMode);
364 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
365 DEBUG(10, ("unpack_devicemode: "
366 "error parsing spoolss_DeviceMode\n"));
367 goto done;
370 DEBUG(8, ("Unpacked devicemode [%s](%s)\n",
371 dm->devicename, dm->formname));
372 if (dm->driverextra_data.data) {
373 DEBUG(8, ("with a private section of %d bytes\n",
374 dm->__driverextra_length));
377 *devmode = dm;
379 done:
380 SAFE_FREE(data);
381 return len;
384 /***********************************************************************
385 unpack a pjob from a tdb buffer
386 ***********************************************************************/
388 static int unpack_pjob(TALLOC_CTX *mem_ctx, uint8 *buf, int buflen,
389 struct printjob *pjob)
391 int len = 0;
392 int used;
393 uint32 pjpid, pjjobid, pjsysjob, pjfd, pjstarttime, pjstatus;
394 uint32 pjsize, pjpage_count, pjspooled, pjsmbjob;
396 if (!buf || !pjob) {
397 return -1;
400 len += tdb_unpack(buf+len, buflen-len, "ddddddddddfffff",
401 &pjpid,
402 &pjjobid,
403 &pjsysjob,
404 &pjfd,
405 &pjstarttime,
406 &pjstatus,
407 &pjsize,
408 &pjpage_count,
409 &pjspooled,
410 &pjsmbjob,
411 pjob->filename,
412 pjob->jobname,
413 pjob->user,
414 pjob->clientmachine,
415 pjob->queuename);
417 if (len == -1) {
418 return -1;
421 used = unpack_devicemode(mem_ctx, buf+len, buflen-len, &pjob->devmode);
422 if (used == -1) {
423 return -1;
426 len += used;
428 pjob->pid = pjpid;
429 pjob->jobid = pjjobid;
430 pjob->sysjob = pjsysjob;
431 pjob->fd = pjfd;
432 pjob->starttime = pjstarttime;
433 pjob->status = pjstatus;
434 pjob->size = pjsize;
435 pjob->page_count = pjpage_count;
436 pjob->spooled = pjspooled;
437 pjob->smbjob = pjsmbjob;
439 return len;
443 /****************************************************************************
444 Useful function to find a print job in the database.
445 ****************************************************************************/
447 static struct printjob *print_job_find(TALLOC_CTX *mem_ctx,
448 const char *sharename,
449 uint32 jobid)
451 struct printjob *pjob;
452 uint32_t tmp;
453 TDB_DATA ret;
454 struct tdb_print_db *pdb = get_print_db_byname(sharename);
456 DEBUG(10,("print_job_find: looking up job %u for share %s\n",
457 (unsigned int)jobid, sharename ));
459 if (!pdb) {
460 return NULL;
463 ret = tdb_fetch_compat(pdb->tdb, print_key(jobid, &tmp));
464 release_print_db(pdb);
466 if (!ret.dptr) {
467 DEBUG(10, ("print_job_find: failed to find jobid %u.\n",
468 jobid));
469 return NULL;
472 pjob = talloc_zero(mem_ctx, struct printjob);
473 if (pjob == NULL) {
474 goto err_out;
477 if (unpack_pjob(mem_ctx, ret.dptr, ret.dsize, pjob) == -1) {
478 DEBUG(10, ("failed to unpack jobid %u.\n", jobid));
479 talloc_free(pjob);
480 pjob = NULL;
481 goto err_out;
484 DEBUG(10,("print_job_find: returning system job %d for jobid %u.\n",
485 pjob->sysjob, jobid));
486 SMB_ASSERT(pjob->jobid == jobid);
488 err_out:
489 SAFE_FREE(ret.dptr);
490 return pjob;
493 struct job_traverse_state {
494 int sysjob;
495 uint32_t jobid;
498 /* find spoolss jobid based on sysjob */
499 static int sysjob_to_jobid_traverse_fn(TDB_CONTEXT *the_tdb, TDB_DATA key,
500 TDB_DATA data, void *private_data)
502 struct printjob *pjob;
503 struct job_traverse_state *state =
504 (struct job_traverse_state *)private_data;
506 if (!data.dptr || data.dsize == 0)
507 return 0;
509 pjob = (struct printjob *)data.dptr;
510 if (key.dsize != sizeof(uint32))
511 return 0;
513 if (state->sysjob == pjob->sysjob) {
514 state->jobid = pjob->jobid;
515 return 1;
518 return 0;
521 uint32 sysjob_to_jobid_pdb(struct tdb_print_db *pdb, int sysjob)
523 struct job_traverse_state state;
525 state.sysjob = sysjob;
526 state.jobid = (uint32_t)-1;
528 tdb_traverse(pdb->tdb, sysjob_to_jobid_traverse_fn, &state);
530 return state.jobid;
533 /****************************************************************************
534 This is a *horribly expensive call as we have to iterate through all the
535 current printer tdb's. Don't do this often ! JRA.
536 ****************************************************************************/
538 uint32 sysjob_to_jobid(int unix_jobid)
540 int services = lp_numservices();
541 int snum;
542 struct job_traverse_state state;
544 state.sysjob = unix_jobid;
545 state.jobid = (uint32_t)-1;
547 for (snum = 0; snum < services; snum++) {
548 struct tdb_print_db *pdb;
549 if (!lp_print_ok(snum))
550 continue;
551 pdb = get_print_db_byname(lp_const_servicename(snum));
552 if (!pdb) {
553 continue;
555 tdb_traverse(pdb->tdb, sysjob_to_jobid_traverse_fn, &state);
556 release_print_db(pdb);
557 if (state.jobid != (uint32_t)-1)
558 return state.jobid;
560 return (uint32)-1;
563 /* find sysjob based on spoolss jobid */
564 static int jobid_to_sysjob_traverse_fn(TDB_CONTEXT *the_tdb, TDB_DATA key,
565 TDB_DATA data, void *private_data)
567 struct printjob *pjob;
568 struct job_traverse_state *state =
569 (struct job_traverse_state *)private_data;
571 if (!data.dptr || data.dsize == 0)
572 return 0;
574 pjob = (struct printjob *)data.dptr;
575 if (key.dsize != sizeof(uint32_t))
576 return 0;
578 if (state->jobid == pjob->jobid) {
579 state->sysjob = pjob->sysjob;
580 return 1;
583 return 0;
586 int jobid_to_sysjob_pdb(struct tdb_print_db *pdb, uint32_t jobid)
588 struct job_traverse_state state;
590 state.sysjob = -1;
591 state.jobid = jobid;
593 tdb_traverse(pdb->tdb, jobid_to_sysjob_traverse_fn, &state);
595 return state.sysjob;
598 /****************************************************************************
599 Send notifications based on what has changed after a pjob_store.
600 ****************************************************************************/
602 static const struct {
603 uint32_t lpq_status;
604 uint32_t spoolss_status;
605 } lpq_to_spoolss_status_map[] = {
606 { LPQ_QUEUED, JOB_STATUS_QUEUED },
607 { LPQ_PAUSED, JOB_STATUS_PAUSED },
608 { LPQ_SPOOLING, JOB_STATUS_SPOOLING },
609 { LPQ_PRINTING, JOB_STATUS_PRINTING },
610 { LPQ_DELETING, JOB_STATUS_DELETING },
611 { LPQ_OFFLINE, JOB_STATUS_OFFLINE },
612 { LPQ_PAPEROUT, JOB_STATUS_PAPEROUT },
613 { LPQ_PRINTED, JOB_STATUS_PRINTED },
614 { LPQ_DELETED, JOB_STATUS_DELETED },
615 { LPQ_BLOCKED, JOB_STATUS_BLOCKED_DEVQ },
616 { LPQ_USER_INTERVENTION, JOB_STATUS_USER_INTERVENTION },
617 { (uint32_t)-1, 0 }
620 /* Convert a lpq status value stored in printing.tdb into the
621 appropriate win32 API constant. */
623 static uint32 map_to_spoolss_status(uint32 lpq_status)
625 int i = 0;
627 while (lpq_to_spoolss_status_map[i].lpq_status != -1) {
628 if (lpq_to_spoolss_status_map[i].lpq_status == lpq_status)
629 return lpq_to_spoolss_status_map[i].spoolss_status;
630 i++;
633 return 0;
636 /***************************************************************************
637 Append a jobid to the 'jobs changed' list.
638 ***************************************************************************/
640 static bool add_to_jobs_changed(struct tdb_print_db *pdb, uint32_t jobid)
642 TDB_DATA data;
643 uint32_t store_jobid;
645 SIVAL(&store_jobid, 0, jobid);
646 data.dptr = (uint8 *) &store_jobid;
647 data.dsize = 4;
649 DEBUG(10,("add_to_jobs_added: Added jobid %u\n", (unsigned int)jobid ));
651 return (tdb_append(pdb->tdb, string_tdb_data("INFO/jobs_changed"),
652 data) == 0);
655 /***************************************************************************
656 Remove a jobid from the 'jobs changed' list.
657 ***************************************************************************/
659 static bool remove_from_jobs_changed(const char* sharename, uint32_t jobid)
661 struct tdb_print_db *pdb = get_print_db_byname(sharename);
662 TDB_DATA data, key;
663 size_t job_count, i;
664 bool ret = False;
665 bool gotlock = False;
667 if (!pdb) {
668 return False;
671 ZERO_STRUCT(data);
673 key = string_tdb_data("INFO/jobs_changed");
675 if (tdb_chainlock_with_timeout(pdb->tdb, key, 5) != 0)
676 goto out;
678 gotlock = True;
680 data = tdb_fetch_compat(pdb->tdb, key);
682 if (data.dptr == NULL || data.dsize == 0 || (data.dsize % 4 != 0))
683 goto out;
685 job_count = data.dsize / 4;
686 for (i = 0; i < job_count; i++) {
687 uint32 ch_jobid;
689 ch_jobid = IVAL(data.dptr, i*4);
690 if (ch_jobid == jobid) {
691 if (i < job_count -1 )
692 memmove(data.dptr + (i*4), data.dptr + (i*4) + 4, (job_count - i - 1)*4 );
693 data.dsize -= 4;
694 if (tdb_store(pdb->tdb, key, data, TDB_REPLACE) != 0)
695 goto out;
696 break;
700 ret = True;
701 out:
703 if (gotlock)
704 tdb_chainunlock(pdb->tdb, key);
705 SAFE_FREE(data.dptr);
706 release_print_db(pdb);
707 if (ret)
708 DEBUG(10,("remove_from_jobs_changed: removed jobid %u\n", (unsigned int)jobid ));
709 else
710 DEBUG(10,("remove_from_jobs_changed: Failed to remove jobid %u\n", (unsigned int)jobid ));
711 return ret;
714 static void pjob_store_notify(struct tevent_context *ev,
715 struct messaging_context *msg_ctx,
716 const char* sharename, uint32 jobid,
717 struct printjob *old_data,
718 struct printjob *new_data,
719 bool *pchanged)
721 bool new_job = false;
722 bool changed = false;
724 if (old_data == NULL) {
725 new_job = true;
728 /* ACHTUNG! Due to a bug in Samba's spoolss parsing of the
729 NOTIFY_INFO_DATA buffer, we *have* to send the job submission
730 time first or else we'll end up with potential alignment
731 errors. I don't think the systemtime should be spooled as
732 a string, but this gets us around that error.
733 --jerry (i'll feel dirty for this) */
735 if (new_job) {
736 notify_job_submitted(ev, msg_ctx,
737 sharename, jobid, new_data->starttime);
738 notify_job_username(ev, msg_ctx,
739 sharename, jobid, new_data->user);
740 notify_job_name(ev, msg_ctx,
741 sharename, jobid, new_data->jobname);
742 notify_job_status(ev, msg_ctx,
743 sharename, jobid, map_to_spoolss_status(new_data->status));
744 notify_job_total_bytes(ev, msg_ctx,
745 sharename, jobid, new_data->size);
746 notify_job_total_pages(ev, msg_ctx,
747 sharename, jobid, new_data->page_count);
748 } else {
749 if (!strequal(old_data->jobname, new_data->jobname)) {
750 notify_job_name(ev, msg_ctx, sharename,
751 jobid, new_data->jobname);
752 changed = true;
755 if (old_data->status != new_data->status) {
756 notify_job_status(ev, msg_ctx,
757 sharename, jobid,
758 map_to_spoolss_status(new_data->status));
761 if (old_data->size != new_data->size) {
762 notify_job_total_bytes(ev, msg_ctx,
763 sharename, jobid, new_data->size);
766 if (old_data->page_count != new_data->page_count) {
767 notify_job_total_pages(ev, msg_ctx,
768 sharename, jobid,
769 new_data->page_count);
773 *pchanged = changed;
776 /****************************************************************************
777 Store a job structure back to the database.
778 ****************************************************************************/
780 static bool pjob_store(struct tevent_context *ev,
781 struct messaging_context *msg_ctx,
782 const char* sharename, uint32 jobid,
783 struct printjob *pjob)
785 uint32_t tmp;
786 TDB_DATA old_data, new_data;
787 bool ret = False;
788 struct tdb_print_db *pdb = get_print_db_byname(sharename);
789 uint8 *buf = NULL;
790 int len, newlen, buflen;
793 if (!pdb)
794 return False;
796 /* Get old data */
798 old_data = tdb_fetch_compat(pdb->tdb, print_key(jobid, &tmp));
800 /* Doh! Now we have to pack/unpack data since the NT_DEVICEMODE was added */
802 newlen = 0;
804 do {
805 len = 0;
806 buflen = newlen;
807 len += tdb_pack(buf+len, buflen-len, "ddddddddddfffff",
808 (uint32)pjob->pid,
809 (uint32)pjob->jobid,
810 (uint32)pjob->sysjob,
811 (uint32)pjob->fd,
812 (uint32)pjob->starttime,
813 (uint32)pjob->status,
814 (uint32)pjob->size,
815 (uint32)pjob->page_count,
816 (uint32)pjob->spooled,
817 (uint32)pjob->smbjob,
818 pjob->filename,
819 pjob->jobname,
820 pjob->user,
821 pjob->clientmachine,
822 pjob->queuename);
824 len += pack_devicemode(pjob->devmode, buf+len, buflen-len);
826 if (buflen != len) {
827 buf = (uint8 *)SMB_REALLOC(buf, len);
828 if (!buf) {
829 DEBUG(0,("pjob_store: failed to enlarge buffer!\n"));
830 goto done;
832 newlen = len;
834 } while ( buflen != len );
837 /* Store new data */
839 new_data.dptr = buf;
840 new_data.dsize = len;
841 ret = (tdb_store(pdb->tdb, print_key(jobid, &tmp), new_data,
842 TDB_REPLACE) == 0);
844 /* Send notify updates for what has changed */
846 if (ret) {
847 bool changed = false;
848 struct printjob old_pjob;
850 if (old_data.dsize) {
851 TALLOC_CTX *tmp_ctx = talloc_new(ev);
852 if (tmp_ctx == NULL)
853 goto done;
855 len = unpack_pjob(tmp_ctx, old_data.dptr,
856 old_data.dsize, &old_pjob);
857 if (len != -1 ) {
858 pjob_store_notify(ev,
859 msg_ctx,
860 sharename, jobid, &old_pjob,
861 pjob,
862 &changed);
863 if (changed) {
864 add_to_jobs_changed(pdb, jobid);
867 talloc_free(tmp_ctx);
869 } else {
870 /* new job */
871 pjob_store_notify(ev, msg_ctx,
872 sharename, jobid, NULL, pjob,
873 &changed);
877 done:
878 release_print_db(pdb);
879 SAFE_FREE( old_data.dptr );
880 SAFE_FREE( buf );
882 return ret;
885 /****************************************************************************
886 Remove a job structure from the database.
887 ****************************************************************************/
889 static void pjob_delete(struct tevent_context *ev,
890 struct messaging_context *msg_ctx,
891 const char* sharename, uint32 jobid)
893 uint32_t tmp;
894 struct printjob *pjob;
895 uint32 job_status = 0;
896 struct tdb_print_db *pdb;
897 TALLOC_CTX *tmp_ctx = talloc_new(ev);
898 if (tmp_ctx == NULL) {
899 return;
902 pdb = get_print_db_byname(sharename);
903 if (!pdb) {
904 goto err_out;
907 pjob = print_job_find(tmp_ctx, sharename, jobid);
908 if (!pjob) {
909 DEBUG(5, ("we were asked to delete nonexistent job %u\n",
910 jobid));
911 goto err_release;
914 /* We must cycle through JOB_STATUS_DELETING and
915 JOB_STATUS_DELETED for the port monitor to delete the job
916 properly. */
918 job_status = JOB_STATUS_DELETING|JOB_STATUS_DELETED;
919 notify_job_status(ev, msg_ctx, sharename, jobid, job_status);
921 /* Remove from printing.tdb */
923 tdb_delete(pdb->tdb, print_key(jobid, &tmp));
924 remove_from_jobs_added(sharename, jobid);
925 rap_jobid_delete(sharename, jobid);
926 err_release:
927 release_print_db(pdb);
928 err_out:
929 talloc_free(tmp_ctx);
932 /****************************************************************************
933 List a unix job in the print database.
934 ****************************************************************************/
936 static void print_unix_job(struct tevent_context *ev,
937 struct messaging_context *msg_ctx,
938 const char *sharename, print_queue_struct *q,
939 uint32 jobid)
941 struct printjob pj, *old_pj;
942 TALLOC_CTX *tmp_ctx = talloc_new(ev);
943 if (tmp_ctx == NULL) {
944 return;
947 if (jobid == (uint32)-1) {
948 jobid = q->sysjob + UNIX_JOB_START;
951 /* Preserve the timestamp on an existing unix print job */
953 old_pj = print_job_find(tmp_ctx, sharename, jobid);
955 ZERO_STRUCT(pj);
957 pj.pid = (pid_t)-1;
958 pj.jobid = jobid;
959 pj.sysjob = q->sysjob;
960 pj.fd = -1;
961 pj.starttime = old_pj ? old_pj->starttime : q->time;
962 pj.status = q->status;
963 pj.size = q->size;
964 pj.spooled = True;
965 fstrcpy(pj.filename, old_pj ? old_pj->filename : "");
966 if (jobid < UNIX_JOB_START) {
967 pj.smbjob = True;
968 fstrcpy(pj.jobname, old_pj ? old_pj->jobname : "Remote Downlevel Document");
969 } else {
970 pj.smbjob = False;
971 fstrcpy(pj.jobname, old_pj ? old_pj->jobname : q->fs_file);
973 fstrcpy(pj.user, old_pj ? old_pj->user : q->fs_user);
974 fstrcpy(pj.queuename, old_pj ? old_pj->queuename : sharename );
976 pjob_store(ev, msg_ctx, sharename, jobid, &pj);
977 talloc_free(tmp_ctx);
981 struct traverse_struct {
982 print_queue_struct *queue;
983 int qcount, snum, maxcount, total_jobs;
984 const char *sharename;
985 time_t lpq_time;
986 const char *lprm_command;
987 struct printif *print_if;
988 struct tevent_context *ev;
989 struct messaging_context *msg_ctx;
990 TALLOC_CTX *mem_ctx;
993 /****************************************************************************
994 Utility fn to delete any jobs that are no longer active.
995 ****************************************************************************/
997 static int traverse_fn_delete(TDB_CONTEXT *t, TDB_DATA key, TDB_DATA data, void *state)
999 struct traverse_struct *ts = (struct traverse_struct *)state;
1000 struct printjob pjob;
1001 uint32 jobid;
1002 int i = 0;
1004 if ( key.dsize != sizeof(jobid) )
1005 return 0;
1007 if (unpack_pjob(ts->mem_ctx, data.dptr, data.dsize, &pjob) == -1)
1008 return 0;
1009 talloc_free(pjob.devmode);
1010 jobid = pjob.jobid;
1012 if (!pjob.smbjob) {
1013 /* remove a unix job if it isn't in the system queue any more */
1014 for (i=0;i<ts->qcount;i++) {
1015 if (ts->queue[i].sysjob == pjob.sysjob) {
1016 break;
1019 if (i == ts->qcount) {
1020 DEBUG(10,("traverse_fn_delete: pjob %u deleted due to !smbjob\n",
1021 (unsigned int)jobid ));
1022 pjob_delete(ts->ev, ts->msg_ctx,
1023 ts->sharename, jobid);
1024 return 0;
1027 /* need to continue the the bottom of the function to
1028 save the correct attributes */
1031 /* maybe it hasn't been spooled yet */
1032 if (!pjob.spooled) {
1033 /* if a job is not spooled and the process doesn't
1034 exist then kill it. This cleans up after smbd
1035 deaths */
1036 if (!process_exists_by_pid(pjob.pid)) {
1037 DEBUG(10,("traverse_fn_delete: pjob %u deleted due to !process_exists (%u)\n",
1038 (unsigned int)jobid, (unsigned int)pjob.pid ));
1039 pjob_delete(ts->ev, ts->msg_ctx,
1040 ts->sharename, jobid);
1041 } else
1042 ts->total_jobs++;
1043 return 0;
1046 /* this check only makes sense for jobs submitted from Windows clients */
1048 if (pjob.smbjob) {
1049 for (i=0;i<ts->qcount;i++) {
1050 if ( pjob.status == LPQ_DELETED )
1051 continue;
1053 if (ts->queue[i].sysjob == pjob.sysjob) {
1055 /* try to clean up any jobs that need to be deleted */
1057 if ( pjob.status == LPQ_DELETING ) {
1058 int result;
1060 result = (*(ts->print_if->job_delete))(
1061 ts->sharename, ts->lprm_command, &pjob );
1063 if ( result != 0 ) {
1064 /* if we can't delete, then reset the job status */
1065 pjob.status = LPQ_QUEUED;
1066 pjob_store(ts->ev, ts->msg_ctx,
1067 ts->sharename, jobid, &pjob);
1069 else {
1070 /* if we deleted the job, the remove the tdb record */
1071 pjob_delete(ts->ev,
1072 ts->msg_ctx,
1073 ts->sharename, jobid);
1074 pjob.status = LPQ_DELETED;
1079 break;
1084 /* The job isn't in the system queue - we have to assume it has
1085 completed, so delete the database entry. */
1087 if (i == ts->qcount) {
1089 /* A race can occur between the time a job is spooled and
1090 when it appears in the lpq output. This happens when
1091 the job is added to printing.tdb when another smbd
1092 running print_queue_update() has completed a lpq and
1093 is currently traversing the printing tdb and deleting jobs.
1094 Don't delete the job if it was submitted after the lpq_time. */
1096 if (pjob.starttime < ts->lpq_time) {
1097 DEBUG(10,("traverse_fn_delete: pjob %u deleted due to pjob.starttime (%u) < ts->lpq_time (%u)\n",
1098 (unsigned int)jobid,
1099 (unsigned int)pjob.starttime,
1100 (unsigned int)ts->lpq_time ));
1101 pjob_delete(ts->ev, ts->msg_ctx,
1102 ts->sharename, jobid);
1103 } else
1104 ts->total_jobs++;
1105 return 0;
1108 /* Save the pjob attributes we will store. */
1109 ts->queue[i].sysjob = pjob.sysjob;
1110 ts->queue[i].size = pjob.size;
1111 ts->queue[i].page_count = pjob.page_count;
1112 ts->queue[i].status = pjob.status;
1113 ts->queue[i].priority = 1;
1114 ts->queue[i].time = pjob.starttime;
1115 fstrcpy(ts->queue[i].fs_user, pjob.user);
1116 fstrcpy(ts->queue[i].fs_file, pjob.jobname);
1118 ts->total_jobs++;
1120 return 0;
1123 /****************************************************************************
1124 Check if the print queue has been updated recently enough.
1125 ****************************************************************************/
1127 static void print_cache_flush(const char *sharename)
1129 fstring key;
1130 struct tdb_print_db *pdb = get_print_db_byname(sharename);
1132 if (!pdb)
1133 return;
1134 slprintf(key, sizeof(key)-1, "CACHE/%s", sharename);
1135 tdb_store_int32(pdb->tdb, key, -1);
1136 release_print_db(pdb);
1139 /****************************************************************************
1140 Check if someone already thinks they are doing the update.
1141 ****************************************************************************/
1143 static pid_t get_updating_pid(const char *sharename)
1145 fstring keystr;
1146 TDB_DATA data, key;
1147 pid_t updating_pid;
1148 struct tdb_print_db *pdb = get_print_db_byname(sharename);
1150 if (!pdb)
1151 return (pid_t)-1;
1152 slprintf(keystr, sizeof(keystr)-1, "UPDATING/%s", sharename);
1153 key = string_tdb_data(keystr);
1155 data = tdb_fetch_compat(pdb->tdb, key);
1156 release_print_db(pdb);
1157 if (!data.dptr || data.dsize != sizeof(pid_t)) {
1158 SAFE_FREE(data.dptr);
1159 return (pid_t)-1;
1162 updating_pid = IVAL(data.dptr, 0);
1163 SAFE_FREE(data.dptr);
1165 if (process_exists_by_pid(updating_pid))
1166 return updating_pid;
1168 return (pid_t)-1;
1171 /****************************************************************************
1172 Set the fact that we're doing the update, or have finished doing the update
1173 in the tdb.
1174 ****************************************************************************/
1176 static void set_updating_pid(const fstring sharename, bool updating)
1178 fstring keystr;
1179 TDB_DATA key;
1180 TDB_DATA data;
1181 pid_t updating_pid = getpid();
1182 uint8 buffer[4];
1184 struct tdb_print_db *pdb = get_print_db_byname(sharename);
1186 if (!pdb)
1187 return;
1189 slprintf(keystr, sizeof(keystr)-1, "UPDATING/%s", sharename);
1190 key = string_tdb_data(keystr);
1192 DEBUG(5, ("set_updating_pid: %s updating lpq cache for print share %s\n",
1193 updating ? "" : "not ",
1194 sharename ));
1196 if ( !updating ) {
1197 tdb_delete(pdb->tdb, key);
1198 release_print_db(pdb);
1199 return;
1202 SIVAL( buffer, 0, updating_pid);
1203 data.dptr = buffer;
1204 data.dsize = 4; /* we always assume this is a 4 byte value */
1206 tdb_store(pdb->tdb, key, data, TDB_REPLACE);
1207 release_print_db(pdb);
1210 /****************************************************************************
1211 Sort print jobs by submittal time.
1212 ****************************************************************************/
1214 static int printjob_comp(print_queue_struct *j1, print_queue_struct *j2)
1216 /* Silly cases */
1218 if (!j1 && !j2)
1219 return 0;
1220 if (!j1)
1221 return -1;
1222 if (!j2)
1223 return 1;
1225 /* Sort on job start time */
1227 if (j1->time == j2->time)
1228 return 0;
1229 return (j1->time > j2->time) ? 1 : -1;
1232 /****************************************************************************
1233 Store the sorted queue representation for later portmon retrieval.
1234 Skip deleted jobs
1235 ****************************************************************************/
1237 static void store_queue_struct(struct tdb_print_db *pdb, struct traverse_struct *pts)
1239 TDB_DATA data;
1240 int max_reported_jobs = lp_max_reported_jobs(pts->snum);
1241 print_queue_struct *queue = pts->queue;
1242 size_t len;
1243 size_t i;
1244 unsigned int qcount;
1246 if (max_reported_jobs && (max_reported_jobs < pts->qcount))
1247 pts->qcount = max_reported_jobs;
1248 qcount = 0;
1250 /* Work out the size. */
1251 data.dsize = 0;
1252 data.dsize += tdb_pack(NULL, 0, "d", qcount);
1254 for (i = 0; i < pts->qcount; i++) {
1255 if ( queue[i].status == LPQ_DELETED )
1256 continue;
1258 qcount++;
1259 data.dsize += tdb_pack(NULL, 0, "ddddddff",
1260 (uint32)queue[i].sysjob,
1261 (uint32)queue[i].size,
1262 (uint32)queue[i].page_count,
1263 (uint32)queue[i].status,
1264 (uint32)queue[i].priority,
1265 (uint32)queue[i].time,
1266 queue[i].fs_user,
1267 queue[i].fs_file);
1270 if ((data.dptr = (uint8 *)SMB_MALLOC(data.dsize)) == NULL)
1271 return;
1273 len = 0;
1274 len += tdb_pack(data.dptr + len, data.dsize - len, "d", qcount);
1275 for (i = 0; i < pts->qcount; i++) {
1276 if ( queue[i].status == LPQ_DELETED )
1277 continue;
1279 len += tdb_pack(data.dptr + len, data.dsize - len, "ddddddff",
1280 (uint32)queue[i].sysjob,
1281 (uint32)queue[i].size,
1282 (uint32)queue[i].page_count,
1283 (uint32)queue[i].status,
1284 (uint32)queue[i].priority,
1285 (uint32)queue[i].time,
1286 queue[i].fs_user,
1287 queue[i].fs_file);
1290 tdb_store(pdb->tdb, string_tdb_data("INFO/linear_queue_array"), data,
1291 TDB_REPLACE);
1292 SAFE_FREE(data.dptr);
1293 return;
1296 static TDB_DATA get_jobs_added_data(struct tdb_print_db *pdb)
1298 TDB_DATA data;
1300 ZERO_STRUCT(data);
1302 data = tdb_fetch_compat(pdb->tdb, string_tdb_data("INFO/jobs_added"));
1303 if (data.dptr == NULL || data.dsize == 0 || (data.dsize % 4 != 0)) {
1304 SAFE_FREE(data.dptr);
1305 ZERO_STRUCT(data);
1308 return data;
1311 static void check_job_added(const char *sharename, TDB_DATA data, uint32 jobid)
1313 unsigned int i;
1314 unsigned int job_count = data.dsize / 4;
1316 for (i = 0; i < job_count; i++) {
1317 uint32 ch_jobid;
1319 ch_jobid = IVAL(data.dptr, i*4);
1320 if (ch_jobid == jobid)
1321 remove_from_jobs_added(sharename, jobid);
1325 /****************************************************************************
1326 Check if the print queue has been updated recently enough.
1327 ****************************************************************************/
1329 static bool print_cache_expired(const char *sharename, bool check_pending)
1331 fstring key;
1332 time_t last_qscan_time, time_now = time(NULL);
1333 struct tdb_print_db *pdb = get_print_db_byname(sharename);
1334 bool result = False;
1336 if (!pdb)
1337 return False;
1339 snprintf(key, sizeof(key), "CACHE/%s", sharename);
1340 last_qscan_time = (time_t)tdb_fetch_int32(pdb->tdb, key);
1343 * Invalidate the queue for 3 reasons.
1344 * (1). last queue scan time == -1.
1345 * (2). Current time - last queue scan time > allowed cache time.
1346 * (3). last queue scan time > current time + MAX_CACHE_VALID_TIME (1 hour by default).
1347 * This last test picks up machines for which the clock has been moved
1348 * forward, an lpq scan done and then the clock moved back. Otherwise
1349 * that last lpq scan would stay around for a loooong loooong time... :-). JRA.
1352 if (last_qscan_time == ((time_t)-1)
1353 || (time_now - last_qscan_time) >= lp_lpqcachetime()
1354 || last_qscan_time > (time_now + MAX_CACHE_VALID_TIME))
1356 uint32 u;
1357 time_t msg_pending_time;
1359 DEBUG(4, ("print_cache_expired: cache expired for queue %s "
1360 "(last_qscan_time = %d, time now = %d, qcachetime = %d)\n",
1361 sharename, (int)last_qscan_time, (int)time_now,
1362 (int)lp_lpqcachetime() ));
1364 /* check if another smbd has already sent a message to update the
1365 queue. Give the pending message one minute to clear and
1366 then send another message anyways. Make sure to check for
1367 clocks that have been run forward and then back again. */
1369 snprintf(key, sizeof(key), "MSG_PENDING/%s", sharename);
1371 if ( check_pending
1372 && tdb_fetch_uint32( pdb->tdb, key, &u )
1373 && (msg_pending_time=u) > 0
1374 && msg_pending_time <= time_now
1375 && (time_now - msg_pending_time) < 60 )
1377 DEBUG(4,("print_cache_expired: message already pending for %s. Accepting cache\n",
1378 sharename));
1379 goto done;
1382 result = True;
1385 done:
1386 release_print_db(pdb);
1387 return result;
1390 /****************************************************************************
1391 main work for updating the lpq cache for a printer queue
1392 ****************************************************************************/
1394 static void print_queue_update_internal(struct tevent_context *ev,
1395 struct messaging_context *msg_ctx,
1396 const char *sharename,
1397 struct printif *current_printif,
1398 char *lpq_command, char *lprm_command)
1400 int i, qcount;
1401 print_queue_struct *queue = NULL;
1402 print_status_struct status;
1403 print_status_struct old_status;
1404 struct printjob *pjob;
1405 struct traverse_struct tstruct;
1406 TDB_DATA data, key;
1407 TDB_DATA jcdata;
1408 fstring keystr, cachestr;
1409 struct tdb_print_db *pdb = get_print_db_byname(sharename);
1410 TALLOC_CTX *tmp_ctx = talloc_new(ev);
1412 if ((pdb == NULL) || (tmp_ctx == NULL)) {
1413 return;
1416 DEBUG(5,("print_queue_update_internal: printer = %s, type = %d, lpq command = [%s]\n",
1417 sharename, current_printif->type, lpq_command));
1420 * Update the cache time FIRST ! Stops others even
1421 * attempting to get the lock and doing this
1422 * if the lpq takes a long time.
1425 slprintf(cachestr, sizeof(cachestr)-1, "CACHE/%s", sharename);
1426 tdb_store_int32(pdb->tdb, cachestr, (int)time(NULL));
1428 /* get the current queue using the appropriate interface */
1429 ZERO_STRUCT(status);
1431 qcount = (*(current_printif->queue_get))(sharename,
1432 current_printif->type,
1433 lpq_command, &queue, &status);
1435 DEBUG(3, ("print_queue_update_internal: %d job%s in queue for %s\n",
1436 qcount, (qcount != 1) ? "s" : "", sharename));
1438 /* Sort the queue by submission time otherwise they are displayed
1439 in hash order. */
1441 TYPESAFE_QSORT(queue, qcount, printjob_comp);
1444 any job in the internal database that is marked as spooled
1445 and doesn't exist in the system queue is considered finished
1446 and removed from the database
1448 any job in the system database but not in the internal database
1449 is added as a unix job
1451 fill in any system job numbers as we go
1453 jcdata = get_jobs_added_data(pdb);
1455 for (i=0; i<qcount; i++) {
1456 uint32 jobid = sysjob_to_jobid_pdb(pdb, queue[i].sysjob);
1457 if (jobid == (uint32)-1) {
1458 /* assume its a unix print job */
1459 print_unix_job(ev, msg_ctx,
1460 sharename, &queue[i], jobid);
1461 continue;
1464 /* we have an active SMB print job - update its status */
1465 pjob = print_job_find(tmp_ctx, sharename, jobid);
1466 if (!pjob) {
1467 /* err, somethings wrong. Probably smbd was restarted
1468 with jobs in the queue. All we can do is treat them
1469 like unix jobs. Pity. */
1470 DEBUG(1, ("queued print job %d not found in jobs list, "
1471 "assuming unix job\n", jobid));
1472 print_unix_job(ev, msg_ctx,
1473 sharename, &queue[i], jobid);
1474 continue;
1477 /* don't reset the status on jobs to be deleted */
1479 if ( pjob->status != LPQ_DELETING )
1480 pjob->status = queue[i].status;
1482 pjob_store(ev, msg_ctx, sharename, jobid, pjob);
1484 check_job_added(sharename, jcdata, jobid);
1487 SAFE_FREE(jcdata.dptr);
1489 /* now delete any queued entries that don't appear in the
1490 system queue */
1491 tstruct.queue = queue;
1492 tstruct.qcount = qcount;
1493 tstruct.snum = -1;
1494 tstruct.total_jobs = 0;
1495 tstruct.lpq_time = time(NULL);
1496 tstruct.sharename = sharename;
1497 tstruct.lprm_command = lprm_command;
1498 tstruct.print_if = current_printif;
1499 tstruct.ev = ev;
1500 tstruct.msg_ctx = msg_ctx;
1501 tstruct.mem_ctx = tmp_ctx;
1503 tdb_traverse(pdb->tdb, traverse_fn_delete, (void *)&tstruct);
1505 /* Store the linearised queue, max jobs only. */
1506 store_queue_struct(pdb, &tstruct);
1508 SAFE_FREE(tstruct.queue);
1509 talloc_free(tmp_ctx);
1511 DEBUG(10,("print_queue_update_internal: printer %s INFO/total_jobs = %d\n",
1512 sharename, tstruct.total_jobs ));
1514 tdb_store_int32(pdb->tdb, "INFO/total_jobs", tstruct.total_jobs);
1516 get_queue_status(sharename, &old_status);
1517 if (old_status.qcount != qcount)
1518 DEBUG(10,("print_queue_update_internal: queue status change %d jobs -> %d jobs for printer %s\n",
1519 old_status.qcount, qcount, sharename));
1521 /* store the new queue status structure */
1522 slprintf(keystr, sizeof(keystr)-1, "STATUS/%s", sharename);
1523 key = string_tdb_data(keystr);
1525 status.qcount = qcount;
1526 data.dptr = (uint8 *)&status;
1527 data.dsize = sizeof(status);
1528 tdb_store(pdb->tdb, key, data, TDB_REPLACE);
1531 * Update the cache time again. We want to do this call
1532 * as little as possible...
1535 slprintf(keystr, sizeof(keystr)-1, "CACHE/%s", sharename);
1536 tdb_store_int32(pdb->tdb, keystr, (int32)time(NULL));
1538 /* clear the msg pending record for this queue */
1540 snprintf(keystr, sizeof(keystr), "MSG_PENDING/%s", sharename);
1542 if ( !tdb_store_uint32( pdb->tdb, keystr, 0 ) ) {
1543 /* log a message but continue on */
1545 DEBUG(0,("print_queue_update: failed to store MSG_PENDING flag for [%s]!\n",
1546 sharename));
1549 release_print_db( pdb );
1551 return;
1554 /****************************************************************************
1555 Update the internal database from the system print queue for a queue.
1556 obtain a lock on the print queue before proceeding (needed when mutiple
1557 smbd processes maytry to update the lpq cache concurrently).
1558 ****************************************************************************/
1560 static void print_queue_update_with_lock( struct tevent_context *ev,
1561 struct messaging_context *msg_ctx,
1562 const char *sharename,
1563 struct printif *current_printif,
1564 char *lpq_command, char *lprm_command )
1566 fstring keystr;
1567 struct tdb_print_db *pdb;
1569 DEBUG(5,("print_queue_update_with_lock: printer share = %s\n", sharename));
1570 pdb = get_print_db_byname(sharename);
1571 if (!pdb)
1572 return;
1574 if ( !print_cache_expired(sharename, False) ) {
1575 DEBUG(5,("print_queue_update_with_lock: print cache for %s is still ok\n", sharename));
1576 release_print_db(pdb);
1577 return;
1581 * Check to see if someone else is doing this update.
1582 * This is essentially a mutex on the update.
1585 if (get_updating_pid(sharename) != -1) {
1586 release_print_db(pdb);
1587 return;
1590 /* Lock the queue for the database update */
1592 slprintf(keystr, sizeof(keystr) - 1, "LOCK/%s", sharename);
1593 /* Only wait 10 seconds for this. */
1594 if (tdb_lock_bystring_with_timeout(pdb->tdb, keystr, 10) != 0) {
1595 DEBUG(0,("print_queue_update_with_lock: Failed to lock printer %s database\n", sharename));
1596 release_print_db(pdb);
1597 return;
1601 * Ensure that no one else got in here.
1602 * If the updating pid is still -1 then we are
1603 * the winner.
1606 if (get_updating_pid(sharename) != -1) {
1608 * Someone else is doing the update, exit.
1610 tdb_unlock_bystring(pdb->tdb, keystr);
1611 release_print_db(pdb);
1612 return;
1616 * We're going to do the update ourselves.
1619 /* Tell others we're doing the update. */
1620 set_updating_pid(sharename, True);
1623 * Allow others to enter and notice we're doing
1624 * the update.
1627 tdb_unlock_bystring(pdb->tdb, keystr);
1629 /* do the main work now */
1631 print_queue_update_internal(ev, msg_ctx,
1632 sharename, current_printif,
1633 lpq_command, lprm_command);
1635 /* Delete our pid from the db. */
1636 set_updating_pid(sharename, False);
1637 release_print_db(pdb);
1640 /****************************************************************************
1641 this is the receive function of the background lpq updater
1642 ****************************************************************************/
1643 void print_queue_receive(struct messaging_context *msg,
1644 void *private_data,
1645 uint32_t msg_type,
1646 struct server_id server_id,
1647 DATA_BLOB *data)
1649 fstring sharename;
1650 char *lpqcommand = NULL, *lprmcommand = NULL;
1651 int printing_type;
1652 size_t len;
1654 len = tdb_unpack( (uint8 *)data->data, data->length, "fdPP",
1655 sharename,
1656 &printing_type,
1657 &lpqcommand,
1658 &lprmcommand );
1660 if ( len == -1 ) {
1661 SAFE_FREE(lpqcommand);
1662 SAFE_FREE(lprmcommand);
1663 DEBUG(0,("print_queue_receive: Got invalid print queue update message\n"));
1664 return;
1667 print_queue_update_with_lock(server_event_context(), msg, sharename,
1668 get_printer_fns_from_type((enum printing_types)printing_type),
1669 lpqcommand, lprmcommand );
1671 SAFE_FREE(lpqcommand);
1672 SAFE_FREE(lprmcommand);
1673 return;
1676 /****************************************************************************
1677 update the internal database from the system print queue for a queue
1678 ****************************************************************************/
1680 extern pid_t background_lpq_updater_pid;
1682 static void print_queue_update(struct messaging_context *msg_ctx,
1683 int snum, bool force)
1685 fstring key;
1686 fstring sharename;
1687 char *lpqcommand = NULL;
1688 char *lprmcommand = NULL;
1689 uint8 *buffer = NULL;
1690 size_t len = 0;
1691 size_t newlen;
1692 struct tdb_print_db *pdb;
1693 int type;
1694 struct printif *current_printif;
1695 TALLOC_CTX *ctx = talloc_tos();
1697 fstrcpy( sharename, lp_const_servicename(snum));
1699 /* don't strip out characters like '$' from the printername */
1701 lpqcommand = talloc_string_sub2(ctx,
1702 lp_lpqcommand(talloc_tos(), snum),
1703 "%p",
1704 lp_printername(talloc_tos(), snum),
1705 false, false, false);
1706 if (!lpqcommand) {
1707 return;
1709 lpqcommand = talloc_sub_advanced(ctx,
1710 lp_servicename(talloc_tos(), snum),
1711 current_user_info.unix_name,
1713 current_user.ut.gid,
1714 get_current_username(),
1715 current_user_info.domain,
1716 lpqcommand);
1717 if (!lpqcommand) {
1718 return;
1721 lprmcommand = talloc_string_sub2(ctx,
1722 lp_lprmcommand(talloc_tos(), snum),
1723 "%p",
1724 lp_printername(talloc_tos(), snum),
1725 false, false, false);
1726 if (!lprmcommand) {
1727 return;
1729 lprmcommand = talloc_sub_advanced(ctx,
1730 lp_servicename(talloc_tos(), snum),
1731 current_user_info.unix_name,
1733 current_user.ut.gid,
1734 get_current_username(),
1735 current_user_info.domain,
1736 lprmcommand);
1737 if (!lprmcommand) {
1738 return;
1742 * Make sure that the background queue process exists.
1743 * Otherwise just do the update ourselves
1746 if ( force || background_lpq_updater_pid == -1 ) {
1747 DEBUG(4,("print_queue_update: updating queue [%s] myself\n", sharename));
1748 current_printif = get_printer_fns( snum );
1749 print_queue_update_with_lock(server_event_context(), msg_ctx,
1750 sharename, current_printif,
1751 lpqcommand, lprmcommand);
1753 return;
1756 type = lp_printing(snum);
1758 /* get the length */
1760 len = tdb_pack( NULL, 0, "fdPP",
1761 sharename,
1762 type,
1763 lpqcommand,
1764 lprmcommand );
1766 buffer = SMB_XMALLOC_ARRAY( uint8, len );
1768 /* now pack the buffer */
1769 newlen = tdb_pack( buffer, len, "fdPP",
1770 sharename,
1771 type,
1772 lpqcommand,
1773 lprmcommand );
1775 SMB_ASSERT( newlen == len );
1777 DEBUG(10,("print_queue_update: Sending message -> printer = %s, "
1778 "type = %d, lpq command = [%s] lprm command = [%s]\n",
1779 sharename, type, lpqcommand, lprmcommand ));
1781 /* here we set a msg pending record for other smbd processes
1782 to throttle the number of duplicate print_queue_update msgs
1783 sent. */
1785 pdb = get_print_db_byname(sharename);
1786 if (!pdb) {
1787 SAFE_FREE(buffer);
1788 return;
1791 snprintf(key, sizeof(key), "MSG_PENDING/%s", sharename);
1793 if ( !tdb_store_uint32( pdb->tdb, key, time(NULL) ) ) {
1794 /* log a message but continue on */
1796 DEBUG(0,("print_queue_update: failed to store MSG_PENDING flag for [%s]!\n",
1797 sharename));
1800 release_print_db( pdb );
1802 /* finally send the message */
1804 messaging_send_buf(msg_ctx, pid_to_procid(background_lpq_updater_pid),
1805 MSG_PRINTER_UPDATE, (uint8 *)buffer, len);
1807 SAFE_FREE( buffer );
1809 return;
1812 /****************************************************************************
1813 Create/Update an entry in the print tdb that will allow us to send notify
1814 updates only to interested smbd's.
1815 ****************************************************************************/
1817 bool print_notify_register_pid(int snum)
1819 TDB_DATA data;
1820 struct tdb_print_db *pdb = NULL;
1821 TDB_CONTEXT *tdb = NULL;
1822 const char *printername;
1823 uint32_t mypid = (uint32_t)getpid();
1824 bool ret = False;
1825 size_t i;
1827 /* if (snum == -1), then the change notify request was
1828 on a print server handle and we need to register on
1829 all print queus */
1831 if (snum == -1)
1833 int num_services = lp_numservices();
1834 int idx;
1836 for ( idx=0; idx<num_services; idx++ ) {
1837 if (lp_snum_ok(idx) && lp_print_ok(idx) )
1838 print_notify_register_pid(idx);
1841 return True;
1843 else /* register for a specific printer */
1845 printername = lp_const_servicename(snum);
1846 pdb = get_print_db_byname(printername);
1847 if (!pdb)
1848 return False;
1849 tdb = pdb->tdb;
1852 if (tdb_lock_bystring_with_timeout(tdb, NOTIFY_PID_LIST_KEY, 10) != 0) {
1853 DEBUG(0,("print_notify_register_pid: Failed to lock printer %s\n",
1854 printername));
1855 if (pdb)
1856 release_print_db(pdb);
1857 return False;
1860 data = get_printer_notify_pid_list( tdb, printername, True );
1862 /* Add ourselves and increase the refcount. */
1864 for (i = 0; i < data.dsize; i += 8) {
1865 if (IVAL(data.dptr,i) == mypid) {
1866 uint32 new_refcount = IVAL(data.dptr, i+4) + 1;
1867 SIVAL(data.dptr, i+4, new_refcount);
1868 break;
1872 if (i == data.dsize) {
1873 /* We weren't in the list. Realloc. */
1874 data.dptr = (uint8 *)SMB_REALLOC(data.dptr, data.dsize + 8);
1875 if (!data.dptr) {
1876 DEBUG(0,("print_notify_register_pid: Relloc fail for printer %s\n",
1877 printername));
1878 goto done;
1880 data.dsize += 8;
1881 SIVAL(data.dptr,data.dsize - 8,mypid);
1882 SIVAL(data.dptr,data.dsize - 4,1); /* Refcount. */
1885 /* Store back the record. */
1886 if (tdb_store_bystring(tdb, NOTIFY_PID_LIST_KEY, data, TDB_REPLACE) != 0) {
1887 DEBUG(0,("print_notify_register_pid: Failed to update pid \
1888 list for printer %s\n", printername));
1889 goto done;
1892 ret = True;
1894 done:
1896 tdb_unlock_bystring(tdb, NOTIFY_PID_LIST_KEY);
1897 if (pdb)
1898 release_print_db(pdb);
1899 SAFE_FREE(data.dptr);
1900 return ret;
1903 /****************************************************************************
1904 Update an entry in the print tdb that will allow us to send notify
1905 updates only to interested smbd's.
1906 ****************************************************************************/
1908 bool print_notify_deregister_pid(int snum)
1910 TDB_DATA data;
1911 struct tdb_print_db *pdb = NULL;
1912 TDB_CONTEXT *tdb = NULL;
1913 const char *printername;
1914 uint32_t mypid = (uint32_t)getpid();
1915 size_t i;
1916 bool ret = False;
1918 /* if ( snum == -1 ), we are deregister a print server handle
1919 which means to deregister on all print queues */
1921 if (snum == -1)
1923 int num_services = lp_numservices();
1924 int idx;
1926 for ( idx=0; idx<num_services; idx++ ) {
1927 if ( lp_snum_ok(idx) && lp_print_ok(idx) )
1928 print_notify_deregister_pid(idx);
1931 return True;
1933 else /* deregister a specific printer */
1935 printername = lp_const_servicename(snum);
1936 pdb = get_print_db_byname(printername);
1937 if (!pdb)
1938 return False;
1939 tdb = pdb->tdb;
1942 if (tdb_lock_bystring_with_timeout(tdb, NOTIFY_PID_LIST_KEY, 10) != 0) {
1943 DEBUG(0,("print_notify_register_pid: Failed to lock \
1944 printer %s database\n", printername));
1945 if (pdb)
1946 release_print_db(pdb);
1947 return False;
1950 data = get_printer_notify_pid_list( tdb, printername, True );
1952 /* Reduce refcount. Remove ourselves if zero. */
1954 for (i = 0; i < data.dsize; ) {
1955 if (IVAL(data.dptr,i) == mypid) {
1956 uint32 refcount = IVAL(data.dptr, i+4);
1958 refcount--;
1960 if (refcount == 0) {
1961 if (data.dsize - i > 8)
1962 memmove( &data.dptr[i], &data.dptr[i+8], data.dsize - i - 8);
1963 data.dsize -= 8;
1964 continue;
1966 SIVAL(data.dptr, i+4, refcount);
1969 i += 8;
1972 if (data.dsize == 0)
1973 SAFE_FREE(data.dptr);
1975 /* Store back the record. */
1976 if (tdb_store_bystring(tdb, NOTIFY_PID_LIST_KEY, data, TDB_REPLACE) != 0) {
1977 DEBUG(0,("print_notify_register_pid: Failed to update pid \
1978 list for printer %s\n", printername));
1979 goto done;
1982 ret = True;
1984 done:
1986 tdb_unlock_bystring(tdb, NOTIFY_PID_LIST_KEY);
1987 if (pdb)
1988 release_print_db(pdb);
1989 SAFE_FREE(data.dptr);
1990 return ret;
1993 /****************************************************************************
1994 Check if a jobid is valid. It is valid if it exists in the database.
1995 ****************************************************************************/
1997 bool print_job_exists(const char* sharename, uint32 jobid)
1999 struct tdb_print_db *pdb = get_print_db_byname(sharename);
2000 bool ret;
2001 uint32_t tmp;
2003 if (!pdb)
2004 return False;
2005 ret = tdb_exists(pdb->tdb, print_key(jobid, &tmp));
2006 release_print_db(pdb);
2007 return ret;
2010 /****************************************************************************
2011 Return the device mode asigned to a specific print job.
2012 Only valid for the process doing the spooling and when the job
2013 has not been spooled.
2014 ****************************************************************************/
2016 struct spoolss_DeviceMode *print_job_devmode(TALLOC_CTX *mem_ctx,
2017 const char *sharename,
2018 uint32 jobid)
2020 struct printjob *pjob = print_job_find(mem_ctx, sharename, jobid);
2021 if (pjob == NULL) {
2022 return NULL;
2025 return pjob->devmode;
2028 /****************************************************************************
2029 Set the name of a job. Only possible for owner.
2030 ****************************************************************************/
2032 bool print_job_set_name(struct tevent_context *ev,
2033 struct messaging_context *msg_ctx,
2034 const char *sharename, uint32 jobid, const char *name)
2036 struct printjob *pjob;
2037 bool ret;
2038 TALLOC_CTX *tmp_ctx = talloc_new(ev);
2039 if (tmp_ctx == NULL) {
2040 return false;
2043 pjob = print_job_find(tmp_ctx, sharename, jobid);
2044 if (!pjob || pjob->pid != getpid()) {
2045 ret = false;
2046 goto err_out;
2049 fstrcpy(pjob->jobname, name);
2050 ret = pjob_store(ev, msg_ctx, sharename, jobid, pjob);
2051 err_out:
2052 talloc_free(tmp_ctx);
2053 return ret;
2056 /****************************************************************************
2057 Get the name of a job. Only possible for owner.
2058 ****************************************************************************/
2060 bool print_job_get_name(TALLOC_CTX *mem_ctx, const char *sharename, uint32_t jobid, char **name)
2062 struct printjob *pjob;
2064 pjob = print_job_find(mem_ctx, sharename, jobid);
2065 if (!pjob || pjob->pid != getpid()) {
2066 return false;
2069 *name = pjob->jobname;
2070 return true;
2074 /***************************************************************************
2075 Remove a jobid from the 'jobs added' list.
2076 ***************************************************************************/
2078 static bool remove_from_jobs_added(const char* sharename, uint32 jobid)
2080 struct tdb_print_db *pdb = get_print_db_byname(sharename);
2081 TDB_DATA data, key;
2082 size_t job_count, i;
2083 bool ret = False;
2084 bool gotlock = False;
2086 if (!pdb) {
2087 return False;
2090 ZERO_STRUCT(data);
2092 key = string_tdb_data("INFO/jobs_added");
2094 if (tdb_chainlock_with_timeout(pdb->tdb, key, 5) != 0)
2095 goto out;
2097 gotlock = True;
2099 data = tdb_fetch_compat(pdb->tdb, key);
2101 if (data.dptr == NULL || data.dsize == 0 || (data.dsize % 4 != 0))
2102 goto out;
2104 job_count = data.dsize / 4;
2105 for (i = 0; i < job_count; i++) {
2106 uint32 ch_jobid;
2108 ch_jobid = IVAL(data.dptr, i*4);
2109 if (ch_jobid == jobid) {
2110 if (i < job_count -1 )
2111 memmove(data.dptr + (i*4), data.dptr + (i*4) + 4, (job_count - i - 1)*4 );
2112 data.dsize -= 4;
2113 if (tdb_store(pdb->tdb, key, data, TDB_REPLACE) != 0)
2114 goto out;
2115 break;
2119 ret = True;
2120 out:
2122 if (gotlock)
2123 tdb_chainunlock(pdb->tdb, key);
2124 SAFE_FREE(data.dptr);
2125 release_print_db(pdb);
2126 if (ret)
2127 DEBUG(10,("remove_from_jobs_added: removed jobid %u\n", (unsigned int)jobid ));
2128 else
2129 DEBUG(10,("remove_from_jobs_added: Failed to remove jobid %u\n", (unsigned int)jobid ));
2130 return ret;
2133 /****************************************************************************
2134 Delete a print job - don't update queue.
2135 ****************************************************************************/
2137 static bool print_job_delete1(struct tevent_context *ev,
2138 struct messaging_context *msg_ctx,
2139 int snum, uint32 jobid)
2141 const char* sharename = lp_const_servicename(snum);
2142 struct printjob *pjob;
2143 int result = 0;
2144 struct printif *current_printif = get_printer_fns( snum );
2145 bool ret;
2146 TALLOC_CTX *tmp_ctx = talloc_new(ev);
2147 if (tmp_ctx == NULL) {
2148 return false;
2151 pjob = print_job_find(tmp_ctx, sharename, jobid);
2152 if (!pjob) {
2153 ret = false;
2154 goto err_out;
2158 * If already deleting just return.
2161 if (pjob->status == LPQ_DELETING) {
2162 ret = true;
2163 goto err_out;
2166 /* Hrm - we need to be able to cope with deleting a job before it
2167 has reached the spooler. Just mark it as LPQ_DELETING and
2168 let the print_queue_update() code rmeove the record */
2171 if (pjob->sysjob == -1) {
2172 DEBUG(5, ("attempt to delete job %u not seen by lpr\n", (unsigned int)jobid));
2175 /* Set the tdb entry to be deleting. */
2177 pjob->status = LPQ_DELETING;
2178 pjob_store(ev, msg_ctx, sharename, jobid, pjob);
2180 if (pjob->spooled && pjob->sysjob != -1)
2182 result = (*(current_printif->job_delete))(
2183 lp_printername(talloc_tos(), snum),
2184 lp_lprmcommand(talloc_tos(), snum),
2185 pjob);
2187 /* Delete the tdb entry if the delete succeeded or the job hasn't
2188 been spooled. */
2190 if (result == 0) {
2191 struct tdb_print_db *pdb = get_print_db_byname(sharename);
2192 int njobs = 1;
2194 if (!pdb) {
2195 ret = false;
2196 goto err_out;
2198 pjob_delete(ev, msg_ctx, sharename, jobid);
2199 /* Ensure we keep a rough count of the number of total jobs... */
2200 tdb_change_int32_atomic(pdb->tdb, "INFO/total_jobs", &njobs, -1);
2201 release_print_db(pdb);
2205 remove_from_jobs_added( sharename, jobid );
2207 ret = (result == 0);
2208 err_out:
2209 talloc_free(tmp_ctx);
2210 return ret;
2213 /****************************************************************************
2214 Return true if the current user owns the print job.
2215 ****************************************************************************/
2217 static bool is_owner(const struct auth_session_info *server_info,
2218 const char *servicename,
2219 uint32 jobid)
2221 struct printjob *pjob;
2222 bool ret;
2223 TALLOC_CTX *tmp_ctx = talloc_new(server_info);
2224 if (tmp_ctx == NULL) {
2225 return false;
2228 pjob = print_job_find(tmp_ctx, servicename, jobid);
2229 if (!pjob || !server_info) {
2230 ret = false;
2231 goto err_out;
2234 ret = strequal(pjob->user, server_info->unix_info->sanitized_username);
2235 err_out:
2236 talloc_free(tmp_ctx);
2237 return ret;
2240 /****************************************************************************
2241 Delete a print job.
2242 ****************************************************************************/
2244 WERROR print_job_delete(const struct auth_session_info *server_info,
2245 struct messaging_context *msg_ctx,
2246 int snum, uint32_t jobid)
2248 const char* sharename = lp_const_servicename(snum);
2249 struct printjob *pjob;
2250 bool owner;
2251 WERROR werr;
2252 TALLOC_CTX *tmp_ctx = talloc_new(msg_ctx);
2253 if (tmp_ctx == NULL) {
2254 return WERR_NOT_ENOUGH_MEMORY;
2257 owner = is_owner(server_info, lp_const_servicename(snum), jobid);
2259 /* Check access against security descriptor or whether the user
2260 owns their job. */
2262 if (!owner &&
2263 !print_access_check(server_info, msg_ctx, snum,
2264 JOB_ACCESS_ADMINISTER)) {
2265 DEBUG(3, ("delete denied by security descriptor\n"));
2267 /* BEGIN_ADMIN_LOG */
2268 sys_adminlog( LOG_ERR,
2269 "Permission denied-- user not allowed to delete, \
2270 pause, or resume print job. User name: %s. Printer name: %s.",
2271 uidtoname(server_info->unix_token->uid),
2272 lp_printername(talloc_tos(), snum) );
2273 /* END_ADMIN_LOG */
2275 werr = WERR_ACCESS_DENIED;
2276 goto err_out;
2280 * get the spooled filename of the print job
2281 * if this works, then the file has not been spooled
2282 * to the underlying print system. Just delete the
2283 * spool file & return.
2286 pjob = print_job_find(tmp_ctx, sharename, jobid);
2287 if (!pjob || pjob->spooled || pjob->pid != getpid()) {
2288 DEBUG(10, ("Skipping spool file removal for job %u\n", jobid));
2289 } else {
2290 DEBUG(10, ("Removing spool file [%s]\n", pjob->filename));
2291 if (unlink(pjob->filename) == -1) {
2292 werr = map_werror_from_unix(errno);
2293 goto err_out;
2297 if (!print_job_delete1(server_event_context(), msg_ctx, snum, jobid)) {
2298 werr = WERR_ACCESS_DENIED;
2299 goto err_out;
2302 /* force update the database and say the delete failed if the
2303 job still exists */
2305 print_queue_update(msg_ctx, snum, True);
2307 pjob = print_job_find(tmp_ctx, sharename, jobid);
2308 if (pjob && (pjob->status != LPQ_DELETING)) {
2309 werr = WERR_ACCESS_DENIED;
2310 goto err_out;
2312 werr = WERR_PRINTER_HAS_JOBS_QUEUED;
2314 err_out:
2315 talloc_free(tmp_ctx);
2316 return werr;
2319 /****************************************************************************
2320 Pause a job.
2321 ****************************************************************************/
2323 WERROR print_job_pause(const struct auth_session_info *server_info,
2324 struct messaging_context *msg_ctx,
2325 int snum, uint32 jobid)
2327 const char* sharename = lp_const_servicename(snum);
2328 struct printjob *pjob;
2329 int ret = -1;
2330 struct printif *current_printif = get_printer_fns( snum );
2331 WERROR werr;
2332 TALLOC_CTX *tmp_ctx = talloc_new(msg_ctx);
2333 if (tmp_ctx == NULL) {
2334 return WERR_NOT_ENOUGH_MEMORY;
2337 pjob = print_job_find(tmp_ctx, sharename, jobid);
2338 if (!pjob || !server_info) {
2339 DEBUG(10, ("print_job_pause: no pjob or user for jobid %u\n",
2340 (unsigned int)jobid ));
2341 werr = WERR_INVALID_PARAM;
2342 goto err_out;
2345 if (!pjob->spooled || pjob->sysjob == -1) {
2346 DEBUG(10, ("print_job_pause: not spooled or bad sysjob = %d for jobid %u\n",
2347 (int)pjob->sysjob, (unsigned int)jobid ));
2348 werr = WERR_INVALID_PARAM;
2349 goto err_out;
2352 if (!is_owner(server_info, lp_const_servicename(snum), jobid) &&
2353 !print_access_check(server_info, msg_ctx, snum,
2354 JOB_ACCESS_ADMINISTER)) {
2355 DEBUG(3, ("pause denied by security descriptor\n"));
2357 /* BEGIN_ADMIN_LOG */
2358 sys_adminlog( LOG_ERR,
2359 "Permission denied-- user not allowed to delete, \
2360 pause, or resume print job. User name: %s. Printer name: %s.",
2361 uidtoname(server_info->unix_token->uid),
2362 lp_printername(talloc_tos(), snum) );
2363 /* END_ADMIN_LOG */
2365 werr = WERR_ACCESS_DENIED;
2366 goto err_out;
2369 /* need to pause the spooled entry */
2370 ret = (*(current_printif->job_pause))(snum, pjob);
2372 if (ret != 0) {
2373 werr = WERR_INVALID_PARAM;
2374 goto err_out;
2377 /* force update the database */
2378 print_cache_flush(lp_const_servicename(snum));
2380 /* Send a printer notify message */
2382 notify_job_status(server_event_context(), msg_ctx, sharename, jobid,
2383 JOB_STATUS_PAUSED);
2385 /* how do we tell if this succeeded? */
2386 werr = WERR_OK;
2387 err_out:
2388 talloc_free(tmp_ctx);
2389 return werr;
2392 /****************************************************************************
2393 Resume a job.
2394 ****************************************************************************/
2396 WERROR print_job_resume(const struct auth_session_info *server_info,
2397 struct messaging_context *msg_ctx,
2398 int snum, uint32 jobid)
2400 const char *sharename = lp_const_servicename(snum);
2401 struct printjob *pjob;
2402 int ret;
2403 struct printif *current_printif = get_printer_fns( snum );
2404 WERROR werr;
2405 TALLOC_CTX *tmp_ctx = talloc_new(msg_ctx);
2406 if (tmp_ctx == NULL)
2407 return WERR_NOT_ENOUGH_MEMORY;
2409 pjob = print_job_find(tmp_ctx, sharename, jobid);
2410 if (!pjob || !server_info) {
2411 DEBUG(10, ("print_job_resume: no pjob or user for jobid %u\n",
2412 (unsigned int)jobid ));
2413 werr = WERR_INVALID_PARAM;
2414 goto err_out;
2417 if (!pjob->spooled || pjob->sysjob == -1) {
2418 DEBUG(10, ("print_job_resume: not spooled or bad sysjob = %d for jobid %u\n",
2419 (int)pjob->sysjob, (unsigned int)jobid ));
2420 werr = WERR_INVALID_PARAM;
2421 goto err_out;
2424 if (!is_owner(server_info, lp_const_servicename(snum), jobid) &&
2425 !print_access_check(server_info, msg_ctx, snum,
2426 JOB_ACCESS_ADMINISTER)) {
2427 DEBUG(3, ("resume denied by security descriptor\n"));
2429 /* BEGIN_ADMIN_LOG */
2430 sys_adminlog( LOG_ERR,
2431 "Permission denied-- user not allowed to delete, \
2432 pause, or resume print job. User name: %s. Printer name: %s.",
2433 uidtoname(server_info->unix_token->uid),
2434 lp_printername(talloc_tos(), snum) );
2435 /* END_ADMIN_LOG */
2436 werr = WERR_ACCESS_DENIED;
2437 goto err_out;
2440 ret = (*(current_printif->job_resume))(snum, pjob);
2442 if (ret != 0) {
2443 werr = WERR_INVALID_PARAM;
2444 goto err_out;
2447 /* force update the database */
2448 print_cache_flush(lp_const_servicename(snum));
2450 /* Send a printer notify message */
2452 notify_job_status(server_event_context(), msg_ctx, sharename, jobid,
2453 JOB_STATUS_QUEUED);
2455 werr = WERR_OK;
2456 err_out:
2457 talloc_free(tmp_ctx);
2458 return werr;
2461 /****************************************************************************
2462 Write to a print file.
2463 ****************************************************************************/
2465 ssize_t print_job_write(struct tevent_context *ev,
2466 struct messaging_context *msg_ctx,
2467 int snum, uint32 jobid, const char *buf, size_t size)
2469 const char* sharename = lp_const_servicename(snum);
2470 ssize_t return_code;
2471 struct printjob *pjob;
2472 TALLOC_CTX *tmp_ctx = talloc_new(ev);
2473 if (tmp_ctx == NULL) {
2474 return -1;
2477 pjob = print_job_find(tmp_ctx, sharename, jobid);
2478 if (!pjob) {
2479 return_code = -1;
2480 goto err_out;
2483 /* don't allow another process to get this info - it is meaningless */
2484 if (pjob->pid != getpid()) {
2485 return_code = -1;
2486 goto err_out;
2489 /* if SMBD is spooling this can't be allowed */
2490 if (pjob->status == PJOB_SMBD_SPOOLING) {
2491 return_code = -1;
2492 goto err_out;
2495 return_code = write_data(pjob->fd, buf, size);
2496 if (return_code > 0) {
2497 pjob->size += size;
2498 pjob_store(ev, msg_ctx, sharename, jobid, pjob);
2500 err_out:
2501 talloc_free(tmp_ctx);
2502 return return_code;
2505 /****************************************************************************
2506 Get the queue status - do not update if db is out of date.
2507 ****************************************************************************/
2509 static int get_queue_status(const char* sharename, print_status_struct *status)
2511 fstring keystr;
2512 TDB_DATA data;
2513 struct tdb_print_db *pdb = get_print_db_byname(sharename);
2514 int len;
2516 if (status) {
2517 ZERO_STRUCTP(status);
2520 if (!pdb)
2521 return 0;
2523 if (status) {
2524 fstr_sprintf(keystr, "STATUS/%s", sharename);
2525 data = tdb_fetch_compat(pdb->tdb, string_tdb_data(keystr));
2526 if (data.dptr) {
2527 if (data.dsize == sizeof(print_status_struct))
2528 /* this memcpy is ok since the status struct was
2529 not packed before storing it in the tdb */
2530 memcpy(status, data.dptr, sizeof(print_status_struct));
2531 SAFE_FREE(data.dptr);
2534 len = tdb_fetch_int32(pdb->tdb, "INFO/total_jobs");
2535 release_print_db(pdb);
2536 return (len == -1 ? 0 : len);
2539 /****************************************************************************
2540 Determine the number of jobs in a queue.
2541 ****************************************************************************/
2543 int print_queue_length(struct messaging_context *msg_ctx, int snum,
2544 print_status_struct *pstatus)
2546 const char* sharename = lp_const_servicename( snum );
2547 print_status_struct status;
2548 int len;
2550 ZERO_STRUCT( status );
2552 /* make sure the database is up to date */
2553 if (print_cache_expired(lp_const_servicename(snum), True))
2554 print_queue_update(msg_ctx, snum, False);
2556 /* also fetch the queue status */
2557 memset(&status, 0, sizeof(status));
2558 len = get_queue_status(sharename, &status);
2560 if (pstatus)
2561 *pstatus = status;
2563 return len;
2566 /***************************************************************************
2567 Allocate a jobid. Hold the lock for as short a time as possible.
2568 ***************************************************************************/
2570 static WERROR allocate_print_jobid(struct tdb_print_db *pdb, int snum,
2571 const char *sharename, uint32 *pjobid)
2573 int i;
2574 uint32 jobid;
2575 enum TDB_ERROR terr;
2576 int ret;
2578 *pjobid = (uint32)-1;
2580 for (i = 0; i < 3; i++) {
2581 /* Lock the database - only wait 20 seconds. */
2582 ret = tdb_lock_bystring_with_timeout(pdb->tdb,
2583 "INFO/nextjob", 20);
2584 if (ret != 0) {
2585 DEBUG(0, ("allocate_print_jobid: "
2586 "Failed to lock printing database %s\n",
2587 sharename));
2588 terr = tdb_error(pdb->tdb);
2589 return ntstatus_to_werror(map_nt_error_from_tdb(terr));
2592 if (!tdb_fetch_uint32(pdb->tdb, "INFO/nextjob", &jobid)) {
2593 terr = tdb_error(pdb->tdb);
2594 if (terr != TDB_ERR_NOEXIST) {
2595 DEBUG(0, ("allocate_print_jobid: "
2596 "Failed to fetch INFO/nextjob "
2597 "for print queue %s\n", sharename));
2598 tdb_unlock_bystring(pdb->tdb, "INFO/nextjob");
2599 return ntstatus_to_werror(map_nt_error_from_tdb(terr));
2601 DEBUG(10, ("allocate_print_jobid: "
2602 "No existing jobid in %s\n", sharename));
2603 jobid = 0;
2606 DEBUG(10, ("allocate_print_jobid: "
2607 "Read jobid %u from %s\n", jobid, sharename));
2609 jobid = NEXT_JOBID(jobid);
2611 ret = tdb_store_int32(pdb->tdb, "INFO/nextjob", jobid);
2612 if (ret != 0) {
2613 terr = tdb_error(pdb->tdb);
2614 DEBUG(3, ("allocate_print_jobid: "
2615 "Failed to store INFO/nextjob.\n"));
2616 tdb_unlock_bystring(pdb->tdb, "INFO/nextjob");
2617 return ntstatus_to_werror(map_nt_error_from_tdb(terr));
2620 /* We've finished with the INFO/nextjob lock. */
2621 tdb_unlock_bystring(pdb->tdb, "INFO/nextjob");
2623 if (!print_job_exists(sharename, jobid)) {
2624 break;
2626 DEBUG(10, ("allocate_print_jobid: "
2627 "Found jobid %u in %s\n", jobid, sharename));
2630 if (i > 2) {
2631 DEBUG(0, ("allocate_print_jobid: "
2632 "Failed to allocate a print job for queue %s\n",
2633 sharename));
2634 /* Probably full... */
2635 return WERR_NO_SPOOL_SPACE;
2638 /* Store a dummy placeholder. */
2640 uint32_t tmp;
2641 TDB_DATA dum;
2642 dum.dptr = NULL;
2643 dum.dsize = 0;
2644 if (tdb_store(pdb->tdb, print_key(jobid, &tmp), dum,
2645 TDB_INSERT) != 0) {
2646 DEBUG(3, ("allocate_print_jobid: "
2647 "jobid (%d) failed to store placeholder.\n",
2648 jobid ));
2649 terr = tdb_error(pdb->tdb);
2650 return ntstatus_to_werror(map_nt_error_from_tdb(terr));
2654 *pjobid = jobid;
2655 return WERR_OK;
2658 /***************************************************************************
2659 Append a jobid to the 'jobs added' list.
2660 ***************************************************************************/
2662 static bool add_to_jobs_added(struct tdb_print_db *pdb, uint32 jobid)
2664 TDB_DATA data;
2665 uint32 store_jobid;
2667 SIVAL(&store_jobid, 0, jobid);
2668 data.dptr = (uint8 *)&store_jobid;
2669 data.dsize = 4;
2671 DEBUG(10,("add_to_jobs_added: Added jobid %u\n", (unsigned int)jobid ));
2673 return (tdb_append(pdb->tdb, string_tdb_data("INFO/jobs_added"),
2674 data) == 0);
2678 /***************************************************************************
2679 Do all checks needed to determine if we can start a job.
2680 ***************************************************************************/
2682 static WERROR print_job_checks(const struct auth_session_info *server_info,
2683 struct messaging_context *msg_ctx,
2684 int snum, int *njobs)
2686 const char *sharename = lp_const_servicename(snum);
2687 uint64_t dspace, dsize;
2688 uint64_t minspace;
2689 int ret;
2691 if (!print_access_check(server_info, msg_ctx, snum,
2692 PRINTER_ACCESS_USE)) {
2693 DEBUG(3, ("print_job_checks: "
2694 "job start denied by security descriptor\n"));
2695 return WERR_ACCESS_DENIED;
2698 if (!print_time_access_check(server_info, msg_ctx, sharename)) {
2699 DEBUG(3, ("print_job_checks: "
2700 "job start denied by time check\n"));
2701 return WERR_ACCESS_DENIED;
2704 /* see if we have sufficient disk space */
2705 if (lp_minprintspace(snum)) {
2706 minspace = lp_minprintspace(snum);
2707 ret = sys_fsusage(lp_pathname(talloc_tos(), snum), &dspace, &dsize);
2708 if (ret == 0 && dspace < 2*minspace) {
2709 DEBUG(3, ("print_job_checks: "
2710 "disk space check failed.\n"));
2711 return WERR_NO_SPOOL_SPACE;
2715 /* for autoloaded printers, check that the printcap entry still exists */
2716 if (lp_autoloaded(snum) && !pcap_printername_ok(sharename)) {
2717 DEBUG(3, ("print_job_checks: printer name %s check failed.\n",
2718 sharename));
2719 return WERR_ACCESS_DENIED;
2722 /* Insure the maximum queue size is not violated */
2723 *njobs = print_queue_length(msg_ctx, snum, NULL);
2724 if (*njobs > lp_maxprintjobs(snum)) {
2725 DEBUG(3, ("print_job_checks: Queue %s number of jobs (%d) "
2726 "larger than max printjobs per queue (%d).\n",
2727 sharename, *njobs, lp_maxprintjobs(snum)));
2728 return WERR_NO_SPOOL_SPACE;
2731 return WERR_OK;
2734 /***************************************************************************
2735 Create a job file.
2736 ***************************************************************************/
2738 static WERROR print_job_spool_file(int snum, uint32_t jobid,
2739 const char *output_file,
2740 struct printjob *pjob)
2742 WERROR werr;
2743 SMB_STRUCT_STAT st;
2744 const char *path;
2745 int len;
2746 mode_t mask;
2748 /* if this file is within the printer path, it means that smbd
2749 * is spooling it and will pass us control when it is finished.
2750 * Verify that the file name is ok, within path, and it is
2751 * already already there */
2752 if (output_file) {
2753 path = lp_pathname(talloc_tos(), snum);
2754 len = strlen(path);
2755 if (strncmp(output_file, path, len) == 0 &&
2756 (output_file[len - 1] == '/' || output_file[len] == '/')) {
2758 /* verify path is not too long */
2759 if (strlen(output_file) >= sizeof(pjob->filename)) {
2760 return WERR_INVALID_NAME;
2763 /* verify that the file exists */
2764 if (sys_stat(output_file, &st, false) != 0) {
2765 return WERR_INVALID_NAME;
2768 fstrcpy(pjob->filename, output_file);
2770 DEBUG(3, ("print_job_spool_file:"
2771 "External spooling activated\n"));
2773 /* we do not open the file until spooling is done */
2774 pjob->fd = -1;
2775 pjob->status = PJOB_SMBD_SPOOLING;
2777 return WERR_OK;
2781 slprintf(pjob->filename, sizeof(pjob->filename)-1,
2782 "%s/%sXXXXXX", lp_pathname(talloc_tos(), snum),
2783 PRINT_SPOOL_PREFIX);
2784 mask = umask(S_IRWXO | S_IRWXG);
2785 pjob->fd = mkstemp(pjob->filename);
2786 umask(mask);
2788 if (pjob->fd == -1) {
2789 werr = map_werror_from_unix(errno);
2790 if (W_ERROR_EQUAL(werr, WERR_ACCESS_DENIED)) {
2791 /* Common setup error, force a report. */
2792 DEBUG(0, ("print_job_spool_file: "
2793 "insufficient permissions to open spool "
2794 "file %s.\n", pjob->filename));
2795 } else {
2796 /* Normal case, report at level 3 and above. */
2797 DEBUG(3, ("print_job_spool_file: "
2798 "can't open spool file %s\n",
2799 pjob->filename));
2801 return werr;
2804 return WERR_OK;
2807 /***************************************************************************
2808 Start spooling a job - return the jobid.
2809 ***************************************************************************/
2811 WERROR print_job_start(const struct auth_session_info *server_info,
2812 struct messaging_context *msg_ctx,
2813 const char *clientmachine,
2814 int snum, const char *docname, const char *filename,
2815 struct spoolss_DeviceMode *devmode, uint32_t *_jobid)
2817 uint32_t jobid;
2818 char *path;
2819 struct printjob pjob;
2820 const char *sharename = lp_const_servicename(snum);
2821 struct tdb_print_db *pdb = get_print_db_byname(sharename);
2822 int njobs;
2823 WERROR werr;
2825 if (!pdb) {
2826 return WERR_INTERNAL_DB_CORRUPTION;
2829 path = lp_pathname(talloc_tos(), snum);
2831 werr = print_job_checks(server_info, msg_ctx, snum, &njobs);
2832 if (!W_ERROR_IS_OK(werr)) {
2833 release_print_db(pdb);
2834 return werr;
2837 DEBUG(10, ("print_job_start: "
2838 "Queue %s number of jobs (%d), max printjobs = %d\n",
2839 sharename, njobs, lp_maxprintjobs(snum)));
2841 werr = allocate_print_jobid(pdb, snum, sharename, &jobid);
2842 if (!W_ERROR_IS_OK(werr)) {
2843 goto fail;
2846 /* create the database entry */
2848 ZERO_STRUCT(pjob);
2850 pjob.pid = getpid();
2851 pjob.jobid = jobid;
2852 pjob.sysjob = -1;
2853 pjob.fd = -1;
2854 pjob.starttime = time(NULL);
2855 pjob.status = LPQ_SPOOLING;
2856 pjob.size = 0;
2857 pjob.spooled = False;
2858 pjob.smbjob = True;
2859 pjob.devmode = devmode;
2861 fstrcpy(pjob.jobname, docname);
2863 fstrcpy(pjob.clientmachine, clientmachine);
2865 fstrcpy(pjob.user, lp_printjob_username(snum));
2866 standard_sub_advanced(sharename, server_info->unix_info->sanitized_username,
2867 path, server_info->unix_token->gid,
2868 server_info->unix_info->sanitized_username,
2869 server_info->info->domain_name,
2870 pjob.user, sizeof(pjob.user));
2872 fstrcpy(pjob.queuename, lp_const_servicename(snum));
2874 /* we have a job entry - now create the spool file */
2875 werr = print_job_spool_file(snum, jobid, filename, &pjob);
2876 if (!W_ERROR_IS_OK(werr)) {
2877 goto fail;
2880 pjob_store(server_event_context(), msg_ctx, sharename, jobid, &pjob);
2882 /* Update the 'jobs added' entry used by print_queue_status. */
2883 add_to_jobs_added(pdb, jobid);
2885 /* Ensure we keep a rough count of the number of total jobs... */
2886 tdb_change_int32_atomic(pdb->tdb, "INFO/total_jobs", &njobs, 1);
2888 release_print_db(pdb);
2890 *_jobid = jobid;
2891 return WERR_OK;
2893 fail:
2894 if (jobid != -1) {
2895 pjob_delete(server_event_context(), msg_ctx, sharename, jobid);
2898 release_print_db(pdb);
2900 DEBUG(3, ("print_job_start: returning fail. "
2901 "Error = %s\n", win_errstr(werr)));
2902 return werr;
2905 /****************************************************************************
2906 Update the number of pages spooled to jobid
2907 ****************************************************************************/
2909 void print_job_endpage(struct messaging_context *msg_ctx,
2910 int snum, uint32 jobid)
2912 const char* sharename = lp_const_servicename(snum);
2913 struct printjob *pjob;
2914 TALLOC_CTX *tmp_ctx = talloc_new(msg_ctx);
2915 if (tmp_ctx == NULL) {
2916 return;
2919 pjob = print_job_find(tmp_ctx, sharename, jobid);
2920 if (!pjob) {
2921 goto err_out;
2923 /* don't allow another process to get this info - it is meaningless */
2924 if (pjob->pid != getpid()) {
2925 goto err_out;
2928 pjob->page_count++;
2929 pjob_store(server_event_context(), msg_ctx, sharename, jobid, pjob);
2930 err_out:
2931 talloc_free(tmp_ctx);
2934 /****************************************************************************
2935 Print a file - called on closing the file. This spools the job.
2936 If normal close is false then we're tearing down the jobs - treat as an
2937 error.
2938 ****************************************************************************/
2940 NTSTATUS print_job_end(struct messaging_context *msg_ctx, int snum,
2941 uint32 jobid, enum file_close_type close_type)
2943 const char* sharename = lp_const_servicename(snum);
2944 struct printjob *pjob;
2945 int ret;
2946 SMB_STRUCT_STAT sbuf;
2947 struct printif *current_printif = get_printer_fns(snum);
2948 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
2949 char *lpq_cmd;
2950 TALLOC_CTX *tmp_ctx = talloc_new(msg_ctx);
2951 if (tmp_ctx == NULL) {
2952 return NT_STATUS_NO_MEMORY;
2955 pjob = print_job_find(tmp_ctx, sharename, jobid);
2956 if (!pjob) {
2957 status = NT_STATUS_PRINT_CANCELLED;
2958 goto err_out;
2961 if (pjob->spooled || pjob->pid != getpid()) {
2962 status = NT_STATUS_ACCESS_DENIED;
2963 goto err_out;
2966 if (close_type == NORMAL_CLOSE || close_type == SHUTDOWN_CLOSE) {
2967 if (pjob->status == PJOB_SMBD_SPOOLING) {
2968 /* take over the file now, smbd is done */
2969 if (sys_stat(pjob->filename, &sbuf, false) != 0) {
2970 status = map_nt_error_from_unix(errno);
2971 DEBUG(3, ("print_job_end: "
2972 "stat file failed for jobid %d\n",
2973 jobid));
2974 goto fail;
2977 pjob->status = LPQ_SPOOLING;
2979 } else {
2981 if ((sys_fstat(pjob->fd, &sbuf, false) != 0)) {
2982 status = map_nt_error_from_unix(errno);
2983 close(pjob->fd);
2984 DEBUG(3, ("print_job_end: "
2985 "stat file failed for jobid %d\n",
2986 jobid));
2987 goto fail;
2990 close(pjob->fd);
2993 pjob->size = sbuf.st_ex_size;
2994 } else {
2997 * Not a normal close, something has gone wrong. Cleanup.
2999 if (pjob->fd != -1) {
3000 close(pjob->fd);
3002 goto fail;
3005 /* Technically, this is not quite right. If the printer has a separator
3006 * page turned on, the NT spooler prints the separator page even if the
3007 * print job is 0 bytes. 010215 JRR */
3008 if (pjob->size == 0 || pjob->status == LPQ_DELETING) {
3009 /* don't bother spooling empty files or something being deleted. */
3010 DEBUG(5,("print_job_end: canceling spool of %s (%s)\n",
3011 pjob->filename, pjob->size ? "deleted" : "zero length" ));
3012 unlink(pjob->filename);
3013 pjob_delete(server_event_context(), msg_ctx, sharename, jobid);
3014 return NT_STATUS_OK;
3017 /* don't strip out characters like '$' from the printername */
3018 lpq_cmd = talloc_string_sub2(tmp_ctx,
3019 lp_lpqcommand(talloc_tos(), snum),
3020 "%p",
3021 lp_printername(talloc_tos(), snum),
3022 false, false, false);
3023 if (lpq_cmd == NULL) {
3024 status = NT_STATUS_PRINT_CANCELLED;
3025 goto fail;
3027 lpq_cmd = talloc_sub_advanced(tmp_ctx,
3028 lp_servicename(talloc_tos(), snum),
3029 current_user_info.unix_name,
3031 current_user.ut.gid,
3032 get_current_username(),
3033 current_user_info.domain,
3034 lpq_cmd);
3035 if (lpq_cmd == NULL) {
3036 status = NT_STATUS_PRINT_CANCELLED;
3037 goto fail;
3040 ret = (*(current_printif->job_submit))(snum, pjob,
3041 current_printif->type, lpq_cmd);
3042 if (ret) {
3043 status = NT_STATUS_PRINT_CANCELLED;
3044 goto fail;
3047 /* The print job has been successfully handed over to the back-end */
3049 pjob->spooled = True;
3050 pjob->status = LPQ_QUEUED;
3051 pjob_store(server_event_context(), msg_ctx, sharename, jobid, pjob);
3053 /* make sure the database is up to date */
3054 if (print_cache_expired(lp_const_servicename(snum), True))
3055 print_queue_update(msg_ctx, snum, False);
3057 return NT_STATUS_OK;
3059 fail:
3061 /* The print job was not successfully started. Cleanup */
3062 /* Still need to add proper error return propagation! 010122:JRR */
3063 pjob->fd = -1;
3064 unlink(pjob->filename);
3065 pjob_delete(server_event_context(), msg_ctx, sharename, jobid);
3066 err_out:
3067 talloc_free(tmp_ctx);
3068 return status;
3071 /****************************************************************************
3072 Get a snapshot of jobs in the system without traversing.
3073 ****************************************************************************/
3075 static bool get_stored_queue_info(struct messaging_context *msg_ctx,
3076 struct tdb_print_db *pdb, int snum,
3077 int *pcount, print_queue_struct **ppqueue)
3079 TDB_DATA data, cgdata, jcdata;
3080 print_queue_struct *queue = NULL;
3081 uint32 qcount = 0;
3082 uint32 extra_count = 0;
3083 uint32_t changed_count = 0;
3084 int total_count = 0;
3085 size_t len = 0;
3086 uint32 i;
3087 int max_reported_jobs = lp_max_reported_jobs(snum);
3088 bool ret = false;
3089 const char* sharename = lp_servicename(talloc_tos(), snum);
3090 TALLOC_CTX *tmp_ctx = talloc_new(msg_ctx);
3091 if (tmp_ctx == NULL) {
3092 return false;
3095 /* make sure the database is up to date */
3096 if (print_cache_expired(lp_const_servicename(snum), True))
3097 print_queue_update(msg_ctx, snum, False);
3099 *pcount = 0;
3100 *ppqueue = NULL;
3102 ZERO_STRUCT(data);
3103 ZERO_STRUCT(cgdata);
3105 /* Get the stored queue data. */
3106 data = tdb_fetch_compat(pdb->tdb, string_tdb_data("INFO/linear_queue_array"));
3108 if (data.dptr && data.dsize >= sizeof(qcount))
3109 len += tdb_unpack(data.dptr + len, data.dsize - len, "d", &qcount);
3111 /* Get the added jobs list. */
3112 cgdata = tdb_fetch_compat(pdb->tdb, string_tdb_data("INFO/jobs_added"));
3113 if (cgdata.dptr != NULL && (cgdata.dsize % 4 == 0))
3114 extra_count = cgdata.dsize/4;
3116 /* Get the changed jobs list. */
3117 jcdata = tdb_fetch_compat(pdb->tdb, string_tdb_data("INFO/jobs_changed"));
3118 if (jcdata.dptr != NULL && (jcdata.dsize % 4 == 0))
3119 changed_count = jcdata.dsize / 4;
3121 DEBUG(5,("get_stored_queue_info: qcount = %u, extra_count = %u\n", (unsigned int)qcount, (unsigned int)extra_count));
3123 /* Allocate the queue size. */
3124 if (qcount == 0 && extra_count == 0)
3125 goto out;
3127 if ((queue = SMB_MALLOC_ARRAY(print_queue_struct, qcount + extra_count)) == NULL)
3128 goto out;
3130 /* Retrieve the linearised queue data. */
3132 for(i = 0; i < qcount; i++) {
3133 uint32 qjob, qsize, qpage_count, qstatus, qpriority, qtime;
3134 len += tdb_unpack(data.dptr + len, data.dsize - len, "ddddddff",
3135 &qjob,
3136 &qsize,
3137 &qpage_count,
3138 &qstatus,
3139 &qpriority,
3140 &qtime,
3141 queue[i].fs_user,
3142 queue[i].fs_file);
3143 queue[i].sysjob = qjob;
3144 queue[i].size = qsize;
3145 queue[i].page_count = qpage_count;
3146 queue[i].status = qstatus;
3147 queue[i].priority = qpriority;
3148 queue[i].time = qtime;
3151 total_count = qcount;
3153 /* Add new jobids to the queue. */
3154 for (i = 0; i < extra_count; i++) {
3155 uint32 jobid;
3156 struct printjob *pjob;
3158 jobid = IVAL(cgdata.dptr, i*4);
3159 DEBUG(5,("get_stored_queue_info: added job = %u\n", (unsigned int)jobid));
3160 pjob = print_job_find(tmp_ctx, lp_const_servicename(snum), jobid);
3161 if (!pjob) {
3162 DEBUG(5,("get_stored_queue_info: failed to find added job = %u\n", (unsigned int)jobid));
3163 remove_from_jobs_added(sharename, jobid);
3164 continue;
3167 queue[total_count].sysjob = pjob->sysjob;
3168 queue[total_count].size = pjob->size;
3169 queue[total_count].page_count = pjob->page_count;
3170 queue[total_count].status = pjob->status;
3171 queue[total_count].priority = 1;
3172 queue[total_count].time = pjob->starttime;
3173 fstrcpy(queue[total_count].fs_user, pjob->user);
3174 fstrcpy(queue[total_count].fs_file, pjob->jobname);
3175 total_count++;
3176 talloc_free(pjob);
3179 /* Update the changed jobids. */
3180 for (i = 0; i < changed_count; i++) {
3181 uint32_t jobid = IVAL(jcdata.dptr, i * 4);
3182 struct printjob *pjob;
3183 uint32_t j;
3184 bool found = false;
3186 pjob = print_job_find(tmp_ctx, sharename, jobid);
3187 if (pjob == NULL) {
3188 DEBUG(5,("get_stored_queue_info: failed to find "
3189 "changed job = %u\n",
3190 (unsigned int)jobid));
3191 remove_from_jobs_changed(sharename, jobid);
3192 continue;
3195 for (j = 0; j < total_count; j++) {
3196 if (queue[j].sysjob == pjob->sysjob) {
3197 found = true;
3198 break;
3202 if (found) {
3203 DEBUG(5,("get_stored_queue_info: changed job: %u\n",
3204 (unsigned int)jobid));
3206 queue[j].sysjob = pjob->sysjob;
3207 queue[j].size = pjob->size;
3208 queue[j].page_count = pjob->page_count;
3209 queue[j].status = pjob->status;
3210 queue[j].priority = 1;
3211 queue[j].time = pjob->starttime;
3212 fstrcpy(queue[j].fs_user, pjob->user);
3213 fstrcpy(queue[j].fs_file, pjob->jobname);
3214 talloc_free(pjob);
3216 DEBUG(5,("updated queue[%u], jobid: %u, sysjob: %u, "
3217 "jobname: %s\n",
3218 (unsigned int)j, (unsigned int)jobid,
3219 (unsigned int)queue[j].sysjob, pjob->jobname));
3222 remove_from_jobs_changed(sharename, jobid);
3225 /* Sort the queue by submission time otherwise they are displayed
3226 in hash order. */
3228 TYPESAFE_QSORT(queue, total_count, printjob_comp);
3230 DEBUG(5,("get_stored_queue_info: total_count = %u\n", (unsigned int)total_count));
3232 if (max_reported_jobs && total_count > max_reported_jobs)
3233 total_count = max_reported_jobs;
3235 *ppqueue = queue;
3236 *pcount = total_count;
3238 ret = true;
3240 out:
3242 SAFE_FREE(data.dptr);
3243 SAFE_FREE(cgdata.dptr);
3244 talloc_free(tmp_ctx);
3245 return ret;
3248 /****************************************************************************
3249 Get a printer queue listing.
3250 set queue = NULL and status = NULL if you just want to update the cache
3251 ****************************************************************************/
3253 int print_queue_status(struct messaging_context *msg_ctx, int snum,
3254 print_queue_struct **ppqueue,
3255 print_status_struct *status)
3257 fstring keystr;
3258 TDB_DATA data, key;
3259 const char *sharename;
3260 struct tdb_print_db *pdb;
3261 int count = 0;
3263 /* make sure the database is up to date */
3265 if (print_cache_expired(lp_const_servicename(snum), True))
3266 print_queue_update(msg_ctx, snum, False);
3268 /* return if we are done */
3269 if ( !ppqueue || !status )
3270 return 0;
3272 *ppqueue = NULL;
3273 sharename = lp_const_servicename(snum);
3274 pdb = get_print_db_byname(sharename);
3276 if (!pdb)
3277 return 0;
3280 * Fetch the queue status. We must do this first, as there may
3281 * be no jobs in the queue.
3284 ZERO_STRUCTP(status);
3285 slprintf(keystr, sizeof(keystr)-1, "STATUS/%s", sharename);
3286 key = string_tdb_data(keystr);
3288 data = tdb_fetch_compat(pdb->tdb, key);
3289 if (data.dptr) {
3290 if (data.dsize == sizeof(*status)) {
3291 /* this memcpy is ok since the status struct was
3292 not packed before storing it in the tdb */
3293 memcpy(status, data.dptr, sizeof(*status));
3295 SAFE_FREE(data.dptr);
3299 * Now, fetch the print queue information. We first count the number
3300 * of entries, and then only retrieve the queue if necessary.
3303 if (!get_stored_queue_info(msg_ctx, pdb, snum, &count, ppqueue)) {
3304 release_print_db(pdb);
3305 return 0;
3308 release_print_db(pdb);
3309 return count;
3312 /****************************************************************************
3313 Pause a queue.
3314 ****************************************************************************/
3316 WERROR print_queue_pause(const struct auth_session_info *server_info,
3317 struct messaging_context *msg_ctx, int snum)
3319 int ret;
3320 struct printif *current_printif = get_printer_fns( snum );
3322 if (!print_access_check(server_info, msg_ctx, snum,
3323 PRINTER_ACCESS_ADMINISTER)) {
3324 return WERR_ACCESS_DENIED;
3328 become_root();
3330 ret = (*(current_printif->queue_pause))(snum);
3332 unbecome_root();
3334 if (ret != 0) {
3335 return WERR_INVALID_PARAM;
3338 /* force update the database */
3339 print_cache_flush(lp_const_servicename(snum));
3341 /* Send a printer notify message */
3343 notify_printer_status(server_event_context(), msg_ctx, snum,
3344 PRINTER_STATUS_PAUSED);
3346 return WERR_OK;
3349 /****************************************************************************
3350 Resume a queue.
3351 ****************************************************************************/
3353 WERROR print_queue_resume(const struct auth_session_info *server_info,
3354 struct messaging_context *msg_ctx, int snum)
3356 int ret;
3357 struct printif *current_printif = get_printer_fns( snum );
3359 if (!print_access_check(server_info, msg_ctx, snum,
3360 PRINTER_ACCESS_ADMINISTER)) {
3361 return WERR_ACCESS_DENIED;
3364 become_root();
3366 ret = (*(current_printif->queue_resume))(snum);
3368 unbecome_root();
3370 if (ret != 0) {
3371 return WERR_INVALID_PARAM;
3374 /* make sure the database is up to date */
3375 if (print_cache_expired(lp_const_servicename(snum), True))
3376 print_queue_update(msg_ctx, snum, True);
3378 /* Send a printer notify message */
3380 notify_printer_status(server_event_context(), msg_ctx, snum,
3381 PRINTER_STATUS_OK);
3383 return WERR_OK;
3386 /****************************************************************************
3387 Purge a queue - implemented by deleting all jobs that we can delete.
3388 ****************************************************************************/
3390 WERROR print_queue_purge(const struct auth_session_info *server_info,
3391 struct messaging_context *msg_ctx, int snum)
3393 print_queue_struct *queue;
3394 print_status_struct status;
3395 int njobs, i;
3396 bool can_job_admin;
3398 /* Force and update so the count is accurate (i.e. not a cached count) */
3399 print_queue_update(msg_ctx, snum, True);
3401 can_job_admin = print_access_check(server_info,
3402 msg_ctx,
3403 snum,
3404 JOB_ACCESS_ADMINISTER);
3405 njobs = print_queue_status(msg_ctx, snum, &queue, &status);
3407 if ( can_job_admin )
3408 become_root();
3410 for (i = 0; i < njobs; i++) {
3411 struct tdb_print_db *pdb;
3412 int jobid;
3413 bool owner;
3414 pdb = get_print_db_byname(lp_const_servicename(snum));
3415 if (pdb == NULL) {
3416 DEBUG(1, ("failed to find printdb for %s\n",
3417 lp_const_servicename(snum)));
3418 continue;
3420 jobid = sysjob_to_jobid_pdb(pdb, queue[i].sysjob);
3421 if (jobid == (uint32_t)-1) {
3422 DEBUG(2, ("jobid for system job %d not found\n",
3423 queue[i].sysjob));
3424 continue; /* unix job */
3426 owner = is_owner(server_info, lp_const_servicename(snum),
3427 jobid);
3429 if (owner || can_job_admin) {
3430 print_job_delete1(server_event_context(), msg_ctx,
3431 snum, jobid);
3435 if ( can_job_admin )
3436 unbecome_root();
3438 /* update the cache */
3439 print_queue_update(msg_ctx, snum, True);
3441 SAFE_FREE(queue);
3443 return WERR_OK;