libgpo: apply some const.
[Samba.git] / source3 / printing / printing.c
blobc6c42f3b0b134233318c5497221293ac36909b7d
1 /*
2 Unix SMB/Netbios implementation.
3 Version 3.0
4 printing backend routines
5 Copyright (C) Andrew Tridgell 1992-2000
6 Copyright (C) Jeremy Allison 2002
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include "includes.h"
23 #include "system/syslog.h"
24 #include "system/filesys.h"
25 #include "printing.h"
26 #include "../librpc/gen_ndr/ndr_spoolss.h"
27 #include "nt_printing.h"
28 #include "../librpc/gen_ndr/netlogon.h"
29 #include "printing/notify.h"
30 #include "printing/pcap.h"
31 #include "printing/printer_list.h"
32 #include "printing/queue_process.h"
33 #include "serverid.h"
34 #include "smbd/smbd.h"
35 #include "auth.h"
36 #include "messages.h"
37 #include "util_tdb.h"
38 #include "lib/param/loadparm.h"
39 #include "lib/util/sys_rw_data.h"
41 extern struct current_user current_user;
42 extern userdom_struct current_user_info;
44 /* Current printer interface */
45 static bool remove_from_jobs_added(const char* sharename, uint32_t jobid);
48 the printing backend revolves around a tdb database that stores the
49 SMB view of the print queue
51 The key for this database is a jobid - a internally generated number that
52 uniquely identifies a print job
54 reading the print queue involves two steps:
55 - possibly running lpq and updating the internal database from that
56 - reading entries from the database
58 jobids are assigned when a job starts spooling.
61 static TDB_CONTEXT *rap_tdb;
62 static uint16_t next_rap_jobid;
63 struct rap_jobid_key {
64 fstring sharename;
65 uint32_t jobid;
68 /***************************************************************************
69 Nightmare. LANMAN jobid's are 16 bit numbers..... We must map them to 32
70 bit RPC jobids.... JRA.
71 ***************************************************************************/
73 uint16_t pjobid_to_rap(const char* sharename, uint32_t jobid)
75 uint16_t rap_jobid;
76 TDB_DATA data, key;
77 struct rap_jobid_key jinfo;
78 uint8_t buf[2];
80 DEBUG(10,("pjobid_to_rap: called.\n"));
82 if (!rap_tdb) {
83 /* Create the in-memory tdb. */
84 rap_tdb = tdb_open_log(NULL, 0, TDB_INTERNAL, (O_RDWR|O_CREAT), 0644);
85 if (!rap_tdb)
86 return 0;
89 ZERO_STRUCT( jinfo );
90 fstrcpy( jinfo.sharename, sharename );
91 jinfo.jobid = jobid;
92 key.dptr = (uint8_t *)&jinfo;
93 key.dsize = sizeof(jinfo);
95 data = tdb_fetch(rap_tdb, key);
96 if (data.dptr && data.dsize == sizeof(uint16_t)) {
97 rap_jobid = SVAL(data.dptr, 0);
98 SAFE_FREE(data.dptr);
99 DEBUG(10,("pjobid_to_rap: jobid %u maps to RAP jobid %u\n",
100 (unsigned int)jobid, (unsigned int)rap_jobid));
101 return rap_jobid;
103 SAFE_FREE(data.dptr);
104 /* Not found - create and store mapping. */
105 rap_jobid = ++next_rap_jobid;
106 if (rap_jobid == 0)
107 rap_jobid = ++next_rap_jobid;
108 SSVAL(buf,0,rap_jobid);
109 data.dptr = buf;
110 data.dsize = sizeof(rap_jobid);
111 tdb_store(rap_tdb, key, data, TDB_REPLACE);
112 tdb_store(rap_tdb, data, key, TDB_REPLACE);
114 DEBUG(10,("pjobid_to_rap: created jobid %u maps to RAP jobid %u\n",
115 (unsigned int)jobid, (unsigned int)rap_jobid));
116 return rap_jobid;
119 bool rap_to_pjobid(uint16_t rap_jobid, fstring sharename, uint32_t *pjobid)
121 TDB_DATA data, key;
122 uint8_t buf[2];
124 DEBUG(10,("rap_to_pjobid called.\n"));
126 if (!rap_tdb)
127 return False;
129 SSVAL(buf,0,rap_jobid);
130 key.dptr = buf;
131 key.dsize = sizeof(rap_jobid);
132 data = tdb_fetch(rap_tdb, key);
133 if ( data.dptr && data.dsize == sizeof(struct rap_jobid_key) )
135 struct rap_jobid_key *jinfo = (struct rap_jobid_key*)data.dptr;
136 if (sharename != NULL) {
137 fstrcpy( sharename, jinfo->sharename );
139 *pjobid = jinfo->jobid;
140 DEBUG(10,("rap_to_pjobid: jobid %u maps to RAP jobid %u\n",
141 (unsigned int)*pjobid, (unsigned int)rap_jobid));
142 SAFE_FREE(data.dptr);
143 return True;
146 DEBUG(10,("rap_to_pjobid: Failed to lookup RAP jobid %u\n",
147 (unsigned int)rap_jobid));
148 SAFE_FREE(data.dptr);
149 return False;
152 void rap_jobid_delete(const char* sharename, uint32_t jobid)
154 TDB_DATA key, data;
155 uint16_t rap_jobid;
156 struct rap_jobid_key jinfo;
157 uint8_t buf[2];
159 DEBUG(10,("rap_jobid_delete: called.\n"));
161 if (!rap_tdb)
162 return;
164 ZERO_STRUCT( jinfo );
165 fstrcpy( jinfo.sharename, sharename );
166 jinfo.jobid = jobid;
167 key.dptr = (uint8_t *)&jinfo;
168 key.dsize = sizeof(jinfo);
170 data = tdb_fetch(rap_tdb, key);
171 if (!data.dptr || (data.dsize != sizeof(uint16_t))) {
172 DEBUG(10,("rap_jobid_delete: cannot find jobid %u\n",
173 (unsigned int)jobid ));
174 SAFE_FREE(data.dptr);
175 return;
178 DEBUG(10,("rap_jobid_delete: deleting jobid %u\n",
179 (unsigned int)jobid ));
181 rap_jobid = SVAL(data.dptr, 0);
182 SAFE_FREE(data.dptr);
183 SSVAL(buf,0,rap_jobid);
184 data.dptr = buf;
185 data.dsize = sizeof(rap_jobid);
186 tdb_delete(rap_tdb, key);
187 tdb_delete(rap_tdb, data);
190 static int get_queue_status(const char* sharename, print_status_struct *);
192 /****************************************************************************
193 Initialise the printing backend. Called once at startup before the fork().
194 ****************************************************************************/
196 bool print_backend_init(struct messaging_context *msg_ctx)
198 const char *sversion = "INFO/version";
199 int services = lp_numservices();
200 int snum;
201 bool ok;
202 char *print_cache_path;
204 if (!printer_list_parent_init()) {
205 return false;
208 print_cache_path = cache_path("printing");
209 if (print_cache_path == NULL) {
210 return false;
212 ok = directory_create_or_exist(print_cache_path, 0755);
213 TALLOC_FREE(print_cache_path);
214 if (!ok) {
215 return false;
218 print_cache_path = cache_path("printing.tdb");
219 if (print_cache_path == NULL) {
220 return false;
222 unlink(print_cache_path);
223 TALLOC_FREE(print_cache_path);
225 /* handle a Samba upgrade */
227 for (snum = 0; snum < services; snum++) {
228 struct tdb_print_db *pdb;
229 if (!lp_printable(snum))
230 continue;
232 pdb = get_print_db_byname(lp_const_servicename(snum));
233 if (!pdb)
234 continue;
235 if (tdb_lock_bystring(pdb->tdb, sversion) != 0) {
236 DEBUG(0,("print_backend_init: Failed to open printer %s database\n", lp_const_servicename(snum) ));
237 release_print_db(pdb);
238 return False;
240 if (tdb_fetch_int32(pdb->tdb, sversion) != PRINT_DATABASE_VERSION) {
241 tdb_wipe_all(pdb->tdb);
242 tdb_store_int32(pdb->tdb, sversion, PRINT_DATABASE_VERSION);
244 tdb_unlock_bystring(pdb->tdb, sversion);
245 release_print_db(pdb);
248 close_all_print_db(); /* Don't leave any open. */
250 /* do NT print initialization... */
251 return nt_printing_init(msg_ctx);
254 /****************************************************************************
255 Shut down printing backend. Called once at shutdown to close the tdb.
256 ****************************************************************************/
258 void printing_end(void)
260 close_all_print_db(); /* Don't leave any open. */
263 /****************************************************************************
264 Retrieve the set of printing functions for a given service. This allows
265 us to set the printer function table based on the value of the 'printing'
266 service parameter.
268 Use the generic interface as the default and only use cups interface only
269 when asked for (and only when supported)
270 ****************************************************************************/
272 static struct printif *get_printer_fns_from_type( enum printing_types type )
274 struct printif *printer_fns = &generic_printif;
276 #ifdef HAVE_CUPS
277 if ( type == PRINT_CUPS ) {
278 printer_fns = &cups_printif;
280 #endif /* HAVE_CUPS */
282 #ifdef HAVE_IPRINT
283 if ( type == PRINT_IPRINT ) {
284 printer_fns = &iprint_printif;
286 #endif /* HAVE_IPRINT */
288 printer_fns->type = type;
290 return printer_fns;
293 static struct printif *get_printer_fns( int snum )
295 return get_printer_fns_from_type( (enum printing_types)lp_printing(snum) );
299 /****************************************************************************
300 Useful function to generate a tdb key.
301 ****************************************************************************/
303 static TDB_DATA print_key(uint32_t jobid, uint32_t *tmp)
305 TDB_DATA ret;
307 SIVAL(tmp, 0, jobid);
308 ret.dptr = (uint8_t *)tmp;
309 ret.dsize = sizeof(*tmp);
310 return ret;
313 /****************************************************************************
314 Pack the devicemode to store it in a tdb.
315 ****************************************************************************/
316 static int pack_devicemode(struct spoolss_DeviceMode *devmode, uint8_t *buf, int buflen)
318 enum ndr_err_code ndr_err;
319 DATA_BLOB blob;
320 int len = 0;
322 if (devmode) {
323 ndr_err = ndr_push_struct_blob(&blob, talloc_tos(),
324 devmode,
325 (ndr_push_flags_fn_t)
326 ndr_push_spoolss_DeviceMode);
327 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
328 DEBUG(10, ("pack_devicemode: "
329 "error encoding spoolss_DeviceMode\n"));
330 goto done;
332 } else {
333 ZERO_STRUCT(blob);
336 len = tdb_pack(buf, buflen, "B", blob.length, blob.data);
338 if (devmode) {
339 DEBUG(8, ("Packed devicemode [%s]\n", devmode->formname));
342 done:
343 return len;
346 /****************************************************************************
347 Unpack the devicemode to store it in a tdb.
348 ****************************************************************************/
349 static int unpack_devicemode(TALLOC_CTX *mem_ctx,
350 const uint8_t *buf, int buflen,
351 struct spoolss_DeviceMode **devmode)
353 struct spoolss_DeviceMode *dm;
354 enum ndr_err_code ndr_err;
355 char *data = NULL;
356 int data_len = 0;
357 DATA_BLOB blob;
358 int len = 0;
360 *devmode = NULL;
362 len = tdb_unpack(buf, buflen, "B", &data_len, &data);
363 if (!data) {
364 return len;
367 dm = talloc_zero(mem_ctx, struct spoolss_DeviceMode);
368 if (!dm) {
369 goto done;
372 blob = data_blob_const(data, data_len);
374 ndr_err = ndr_pull_struct_blob(&blob, dm, dm,
375 (ndr_pull_flags_fn_t)ndr_pull_spoolss_DeviceMode);
376 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
377 DEBUG(10, ("unpack_devicemode: "
378 "error parsing spoolss_DeviceMode\n"));
379 goto done;
382 DEBUG(8, ("Unpacked devicemode [%s](%s)\n",
383 dm->devicename, dm->formname));
384 if (dm->driverextra_data.data) {
385 DEBUG(8, ("with a private section of %d bytes\n",
386 dm->__driverextra_length));
389 *devmode = dm;
391 done:
392 SAFE_FREE(data);
393 return len;
396 /***********************************************************************
397 unpack a pjob from a tdb buffer
398 ***********************************************************************/
400 static int unpack_pjob(TALLOC_CTX *mem_ctx, uint8_t *buf, int buflen,
401 struct printjob *pjob)
403 int len = 0;
404 int used;
405 uint32_t pjpid, pjjobid, pjsysjob, pjfd, pjstarttime, pjstatus;
406 uint32_t pjsize, pjpage_count, pjspooled, pjsmbjob;
408 if (!buf || !pjob) {
409 return -1;
412 len += tdb_unpack(buf+len, buflen-len, "ddddddddddfffff",
413 &pjpid,
414 &pjjobid,
415 &pjsysjob,
416 &pjfd,
417 &pjstarttime,
418 &pjstatus,
419 &pjsize,
420 &pjpage_count,
421 &pjspooled,
422 &pjsmbjob,
423 pjob->filename,
424 pjob->jobname,
425 pjob->user,
426 pjob->clientmachine,
427 pjob->queuename);
429 if (len == -1) {
430 return -1;
433 used = unpack_devicemode(mem_ctx, buf+len, buflen-len, &pjob->devmode);
434 if (used == -1) {
435 return -1;
438 len += used;
440 pjob->pid = pjpid;
441 pjob->jobid = pjjobid;
442 pjob->sysjob = pjsysjob;
443 pjob->fd = pjfd;
444 pjob->starttime = pjstarttime;
445 pjob->status = pjstatus;
446 pjob->size = pjsize;
447 pjob->page_count = pjpage_count;
448 pjob->spooled = pjspooled;
449 pjob->smbjob = pjsmbjob;
451 return len;
455 /****************************************************************************
456 Useful function to find a print job in the database.
457 ****************************************************************************/
459 static struct printjob *print_job_find(TALLOC_CTX *mem_ctx,
460 const char *sharename,
461 uint32_t jobid)
463 struct printjob *pjob;
464 uint32_t tmp;
465 TDB_DATA ret;
466 struct tdb_print_db *pdb = get_print_db_byname(sharename);
468 DEBUG(10,("print_job_find: looking up job %u for share %s\n",
469 (unsigned int)jobid, sharename ));
471 if (!pdb) {
472 return NULL;
475 ret = tdb_fetch(pdb->tdb, print_key(jobid, &tmp));
476 release_print_db(pdb);
478 if (!ret.dptr) {
479 DEBUG(10, ("print_job_find: failed to find jobid %u.\n",
480 jobid));
481 return NULL;
484 pjob = talloc_zero(mem_ctx, struct printjob);
485 if (pjob == NULL) {
486 goto err_out;
489 if (unpack_pjob(mem_ctx, ret.dptr, ret.dsize, pjob) == -1) {
490 DEBUG(10, ("failed to unpack jobid %u.\n", jobid));
491 talloc_free(pjob);
492 pjob = NULL;
493 goto err_out;
496 DEBUG(10,("print_job_find: returning system job %d for jobid %u.\n",
497 pjob->sysjob, jobid));
498 SMB_ASSERT(pjob->jobid == jobid);
500 err_out:
501 SAFE_FREE(ret.dptr);
502 return pjob;
505 struct job_traverse_state {
506 int sysjob;
507 uint32_t jobid;
510 /* find spoolss jobid based on sysjob */
511 static int sysjob_to_jobid_traverse_fn(TDB_CONTEXT *the_tdb, TDB_DATA key,
512 TDB_DATA data, void *private_data)
514 struct printjob *pjob;
515 struct job_traverse_state *state =
516 (struct job_traverse_state *)private_data;
518 if (!data.dptr || data.dsize == 0)
519 return 0;
521 pjob = (struct printjob *)data.dptr;
522 if (key.dsize != sizeof(uint32_t))
523 return 0;
525 if (state->sysjob == pjob->sysjob) {
526 state->jobid = pjob->jobid;
527 return 1;
530 return 0;
533 uint32_t sysjob_to_jobid_pdb(struct tdb_print_db *pdb, int sysjob)
535 struct job_traverse_state state;
537 state.sysjob = sysjob;
538 state.jobid = (uint32_t)-1;
540 tdb_traverse(pdb->tdb, sysjob_to_jobid_traverse_fn, &state);
542 return state.jobid;
545 /****************************************************************************
546 This is a *horribly expensive call as we have to iterate through all the
547 current printer tdb's. Don't do this often ! JRA.
548 ****************************************************************************/
550 uint32_t sysjob_to_jobid(int unix_jobid)
552 int services = lp_numservices();
553 int snum;
554 struct job_traverse_state state;
556 state.sysjob = unix_jobid;
557 state.jobid = (uint32_t)-1;
559 for (snum = 0; snum < services; snum++) {
560 struct tdb_print_db *pdb;
561 if (!lp_printable(snum))
562 continue;
563 pdb = get_print_db_byname(lp_const_servicename(snum));
564 if (!pdb) {
565 continue;
567 tdb_traverse(pdb->tdb, sysjob_to_jobid_traverse_fn, &state);
568 release_print_db(pdb);
569 if (state.jobid != (uint32_t)-1)
570 return state.jobid;
572 return (uint32_t)-1;
575 /* find sysjob based on spoolss jobid */
576 static int jobid_to_sysjob_traverse_fn(TDB_CONTEXT *the_tdb, TDB_DATA key,
577 TDB_DATA data, void *private_data)
579 struct printjob *pjob;
580 struct job_traverse_state *state =
581 (struct job_traverse_state *)private_data;
583 if (!data.dptr || data.dsize == 0)
584 return 0;
586 pjob = (struct printjob *)data.dptr;
587 if (key.dsize != sizeof(uint32_t))
588 return 0;
590 if (state->jobid == pjob->jobid) {
591 state->sysjob = pjob->sysjob;
592 return 1;
595 return 0;
598 int jobid_to_sysjob_pdb(struct tdb_print_db *pdb, uint32_t jobid)
600 struct job_traverse_state state;
602 state.sysjob = -1;
603 state.jobid = jobid;
605 tdb_traverse(pdb->tdb, jobid_to_sysjob_traverse_fn, &state);
607 return state.sysjob;
610 /****************************************************************************
611 Send notifications based on what has changed after a pjob_store.
612 ****************************************************************************/
614 static const struct {
615 uint32_t lpq_status;
616 uint32_t spoolss_status;
617 } lpq_to_spoolss_status_map[] = {
618 { LPQ_QUEUED, JOB_STATUS_QUEUED },
619 { LPQ_PAUSED, JOB_STATUS_PAUSED },
620 { LPQ_SPOOLING, JOB_STATUS_SPOOLING },
621 { LPQ_PRINTING, JOB_STATUS_PRINTING },
622 { LPQ_DELETING, JOB_STATUS_DELETING },
623 { LPQ_OFFLINE, JOB_STATUS_OFFLINE },
624 { LPQ_PAPEROUT, JOB_STATUS_PAPEROUT },
625 { LPQ_PRINTED, JOB_STATUS_PRINTED },
626 { LPQ_DELETED, JOB_STATUS_DELETED },
627 { LPQ_BLOCKED, JOB_STATUS_BLOCKED_DEVQ },
628 { LPQ_USER_INTERVENTION, JOB_STATUS_USER_INTERVENTION },
629 { (uint32_t)-1, 0 }
632 /* Convert a lpq status value stored in printing.tdb into the
633 appropriate win32 API constant. */
635 static uint32_t map_to_spoolss_status(uint32_t lpq_status)
637 int i = 0;
639 while (lpq_to_spoolss_status_map[i].lpq_status != -1) {
640 if (lpq_to_spoolss_status_map[i].lpq_status == lpq_status)
641 return lpq_to_spoolss_status_map[i].spoolss_status;
642 i++;
645 return 0;
648 /***************************************************************************
649 Append a jobid to the 'jobs changed' list.
650 ***************************************************************************/
652 static bool add_to_jobs_changed(struct tdb_print_db *pdb, uint32_t jobid)
654 TDB_DATA data;
655 uint32_t store_jobid;
657 SIVAL(&store_jobid, 0, jobid);
658 data.dptr = (uint8_t *) &store_jobid;
659 data.dsize = 4;
661 DEBUG(10,("add_to_jobs_added: Added jobid %u\n", (unsigned int)jobid ));
663 return (tdb_append(pdb->tdb, string_tdb_data("INFO/jobs_changed"),
664 data) == 0);
667 /***************************************************************************
668 Remove a jobid from the 'jobs changed' list.
669 ***************************************************************************/
671 static bool remove_from_jobs_changed(const char* sharename, uint32_t jobid)
673 struct tdb_print_db *pdb = get_print_db_byname(sharename);
674 TDB_DATA data, key;
675 size_t job_count, i;
676 bool ret = False;
677 bool gotlock = False;
679 if (!pdb) {
680 return False;
683 ZERO_STRUCT(data);
685 key = string_tdb_data("INFO/jobs_changed");
687 if (tdb_chainlock_with_timeout(pdb->tdb, key, 5) != 0)
688 goto out;
690 gotlock = True;
692 data = tdb_fetch(pdb->tdb, key);
694 if (data.dptr == NULL || data.dsize == 0 || (data.dsize % 4 != 0))
695 goto out;
697 job_count = data.dsize / 4;
698 for (i = 0; i < job_count; i++) {
699 uint32_t ch_jobid;
701 ch_jobid = IVAL(data.dptr, i*4);
702 if (ch_jobid == jobid) {
703 if (i < job_count -1 )
704 memmove(data.dptr + (i*4), data.dptr + (i*4) + 4, (job_count - i - 1)*4 );
705 data.dsize -= 4;
706 if (tdb_store(pdb->tdb, key, data, TDB_REPLACE) != 0)
707 goto out;
708 break;
712 ret = True;
713 out:
715 if (gotlock)
716 tdb_chainunlock(pdb->tdb, key);
717 SAFE_FREE(data.dptr);
718 release_print_db(pdb);
719 if (ret)
720 DEBUG(10,("remove_from_jobs_changed: removed jobid %u\n", (unsigned int)jobid ));
721 else
722 DEBUG(10,("remove_from_jobs_changed: Failed to remove jobid %u\n", (unsigned int)jobid ));
723 return ret;
726 static void pjob_store_notify(struct tevent_context *ev,
727 struct messaging_context *msg_ctx,
728 const char* sharename, uint32_t jobid,
729 struct printjob *old_data,
730 struct printjob *new_data,
731 bool *pchanged)
733 bool new_job = false;
734 bool changed = false;
736 if (old_data == NULL) {
737 new_job = true;
740 /* ACHTUNG! Due to a bug in Samba's spoolss parsing of the
741 NOTIFY_INFO_DATA buffer, we *have* to send the job submission
742 time first or else we'll end up with potential alignment
743 errors. I don't think the systemtime should be spooled as
744 a string, but this gets us around that error.
745 --jerry (i'll feel dirty for this) */
747 if (new_job) {
748 notify_job_submitted(ev, msg_ctx,
749 sharename, jobid, new_data->starttime);
750 notify_job_username(ev, msg_ctx,
751 sharename, jobid, new_data->user);
752 notify_job_name(ev, msg_ctx,
753 sharename, jobid, new_data->jobname);
754 notify_job_status(ev, msg_ctx,
755 sharename, jobid, map_to_spoolss_status(new_data->status));
756 notify_job_total_bytes(ev, msg_ctx,
757 sharename, jobid, new_data->size);
758 notify_job_total_pages(ev, msg_ctx,
759 sharename, jobid, new_data->page_count);
760 } else {
761 if (!strequal(old_data->jobname, new_data->jobname)) {
762 notify_job_name(ev, msg_ctx, sharename,
763 jobid, new_data->jobname);
764 changed = true;
767 if (old_data->status != new_data->status) {
768 notify_job_status(ev, msg_ctx,
769 sharename, jobid,
770 map_to_spoolss_status(new_data->status));
773 if (old_data->size != new_data->size) {
774 notify_job_total_bytes(ev, msg_ctx,
775 sharename, jobid, new_data->size);
778 if (old_data->page_count != new_data->page_count) {
779 notify_job_total_pages(ev, msg_ctx,
780 sharename, jobid,
781 new_data->page_count);
785 *pchanged = changed;
788 /****************************************************************************
789 Store a job structure back to the database.
790 ****************************************************************************/
792 static bool pjob_store(struct tevent_context *ev,
793 struct messaging_context *msg_ctx,
794 const char* sharename, uint32_t jobid,
795 struct printjob *pjob)
797 uint32_t tmp;
798 TDB_DATA old_data, new_data;
799 bool ret = False;
800 struct tdb_print_db *pdb = get_print_db_byname(sharename);
801 uint8_t *buf = NULL;
802 int len, newlen, buflen;
805 if (!pdb)
806 return False;
808 /* Get old data */
810 old_data = tdb_fetch(pdb->tdb, print_key(jobid, &tmp));
812 /* Doh! Now we have to pack/unpack data since the NT_DEVICEMODE was added */
814 newlen = 0;
816 do {
817 len = 0;
818 buflen = newlen;
819 len += tdb_pack(buf+len, buflen-len, "ddddddddddfffff",
820 (uint32_t)pjob->pid,
821 (uint32_t)pjob->jobid,
822 (uint32_t)pjob->sysjob,
823 (uint32_t)pjob->fd,
824 (uint32_t)pjob->starttime,
825 (uint32_t)pjob->status,
826 (uint32_t)pjob->size,
827 (uint32_t)pjob->page_count,
828 (uint32_t)pjob->spooled,
829 (uint32_t)pjob->smbjob,
830 pjob->filename,
831 pjob->jobname,
832 pjob->user,
833 pjob->clientmachine,
834 pjob->queuename);
836 len += pack_devicemode(pjob->devmode, buf+len, buflen-len);
838 if (buflen != len) {
839 buf = (uint8_t *)SMB_REALLOC(buf, len);
840 if (!buf) {
841 DEBUG(0,("pjob_store: failed to enlarge buffer!\n"));
842 goto done;
844 newlen = len;
846 } while ( buflen != len );
849 /* Store new data */
851 new_data.dptr = buf;
852 new_data.dsize = len;
853 ret = (tdb_store(pdb->tdb, print_key(jobid, &tmp), new_data,
854 TDB_REPLACE) == 0);
856 /* Send notify updates for what has changed */
858 if (ret) {
859 bool changed = false;
860 struct printjob old_pjob;
862 if (old_data.dsize) {
863 TALLOC_CTX *tmp_ctx = talloc_new(ev);
864 if (tmp_ctx == NULL)
865 goto done;
867 len = unpack_pjob(tmp_ctx, old_data.dptr,
868 old_data.dsize, &old_pjob);
869 if (len != -1 ) {
870 pjob_store_notify(ev,
871 msg_ctx,
872 sharename, jobid, &old_pjob,
873 pjob,
874 &changed);
875 if (changed) {
876 add_to_jobs_changed(pdb, jobid);
879 talloc_free(tmp_ctx);
881 } else {
882 /* new job */
883 pjob_store_notify(ev, msg_ctx,
884 sharename, jobid, NULL, pjob,
885 &changed);
889 done:
890 release_print_db(pdb);
891 SAFE_FREE( old_data.dptr );
892 SAFE_FREE( buf );
894 return ret;
897 /****************************************************************************
898 Remove a job structure from the database.
899 ****************************************************************************/
901 static void pjob_delete(struct tevent_context *ev,
902 struct messaging_context *msg_ctx,
903 const char* sharename, uint32_t jobid)
905 uint32_t tmp;
906 struct printjob *pjob;
907 uint32_t job_status = 0;
908 struct tdb_print_db *pdb;
909 TALLOC_CTX *tmp_ctx = talloc_new(ev);
910 if (tmp_ctx == NULL) {
911 return;
914 pdb = get_print_db_byname(sharename);
915 if (!pdb) {
916 goto err_out;
919 pjob = print_job_find(tmp_ctx, sharename, jobid);
920 if (!pjob) {
921 DEBUG(5, ("we were asked to delete nonexistent job %u\n",
922 jobid));
923 goto err_release;
926 /* We must cycle through JOB_STATUS_DELETING and
927 JOB_STATUS_DELETED for the port monitor to delete the job
928 properly. */
930 job_status = JOB_STATUS_DELETING|JOB_STATUS_DELETED;
931 notify_job_status(ev, msg_ctx, sharename, jobid, job_status);
933 /* Remove from printing.tdb */
935 tdb_delete(pdb->tdb, print_key(jobid, &tmp));
936 remove_from_jobs_added(sharename, jobid);
937 rap_jobid_delete(sharename, jobid);
938 err_release:
939 release_print_db(pdb);
940 err_out:
941 talloc_free(tmp_ctx);
944 /****************************************************************************
945 List a unix job in the print database.
946 ****************************************************************************/
948 static void print_unix_job(struct tevent_context *ev,
949 struct messaging_context *msg_ctx,
950 const char *sharename, print_queue_struct *q,
951 uint32_t jobid)
953 struct printjob pj, *old_pj;
954 TALLOC_CTX *tmp_ctx = talloc_new(ev);
955 if (tmp_ctx == NULL) {
956 return;
959 if (jobid == (uint32_t)-1) {
960 jobid = q->sysjob + UNIX_JOB_START;
963 /* Preserve the timestamp on an existing unix print job */
965 old_pj = print_job_find(tmp_ctx, sharename, jobid);
967 ZERO_STRUCT(pj);
969 pj.pid = (pid_t)-1;
970 pj.jobid = jobid;
971 pj.sysjob = q->sysjob;
972 pj.fd = -1;
973 pj.starttime = old_pj ? old_pj->starttime : q->time;
974 pj.status = q->status;
975 pj.size = q->size;
976 pj.spooled = True;
977 fstrcpy(pj.filename, old_pj ? old_pj->filename : "");
978 if (jobid < UNIX_JOB_START) {
979 pj.smbjob = True;
980 fstrcpy(pj.jobname, old_pj ? old_pj->jobname : "Remote Downlevel Document");
981 } else {
982 pj.smbjob = False;
983 fstrcpy(pj.jobname, old_pj ? old_pj->jobname : q->fs_file);
985 fstrcpy(pj.user, old_pj ? old_pj->user : q->fs_user);
986 fstrcpy(pj.queuename, old_pj ? old_pj->queuename : sharename );
988 pjob_store(ev, msg_ctx, sharename, jobid, &pj);
989 talloc_free(tmp_ctx);
993 struct traverse_struct {
994 print_queue_struct *queue;
995 int qcount, snum, maxcount, total_jobs;
996 const char *sharename;
997 time_t lpq_time;
998 const char *lprm_command;
999 struct printif *print_if;
1000 struct tevent_context *ev;
1001 struct messaging_context *msg_ctx;
1002 TALLOC_CTX *mem_ctx;
1005 /****************************************************************************
1006 Utility fn to delete any jobs that are no longer active.
1007 ****************************************************************************/
1009 static int traverse_fn_delete(TDB_CONTEXT *t, TDB_DATA key, TDB_DATA data, void *state)
1011 struct traverse_struct *ts = (struct traverse_struct *)state;
1012 struct printjob pjob;
1013 uint32_t jobid;
1014 int i = 0;
1016 if ( key.dsize != sizeof(jobid) )
1017 return 0;
1019 if (unpack_pjob(ts->mem_ctx, data.dptr, data.dsize, &pjob) == -1)
1020 return 0;
1021 talloc_free(pjob.devmode);
1022 jobid = pjob.jobid;
1024 if (!pjob.smbjob) {
1025 /* remove a unix job if it isn't in the system queue any more */
1026 for (i=0;i<ts->qcount;i++) {
1027 if (ts->queue[i].sysjob == pjob.sysjob) {
1028 break;
1031 if (i == ts->qcount) {
1032 DEBUG(10,("traverse_fn_delete: pjob %u deleted due to !smbjob\n",
1033 (unsigned int)jobid ));
1034 pjob_delete(ts->ev, ts->msg_ctx,
1035 ts->sharename, jobid);
1036 return 0;
1039 /* need to continue the the bottom of the function to
1040 save the correct attributes */
1043 /* maybe it hasn't been spooled yet */
1044 if (!pjob.spooled) {
1045 /* if a job is not spooled and the process doesn't
1046 exist then kill it. This cleans up after smbd
1047 deaths */
1048 if (!process_exists_by_pid(pjob.pid)) {
1049 DEBUG(10,("traverse_fn_delete: pjob %u deleted due to !process_exists (%u)\n",
1050 (unsigned int)jobid, (unsigned int)pjob.pid ));
1051 pjob_delete(ts->ev, ts->msg_ctx,
1052 ts->sharename, jobid);
1053 } else
1054 ts->total_jobs++;
1055 return 0;
1058 /* this check only makes sense for jobs submitted from Windows clients */
1060 if (pjob.smbjob) {
1061 for (i=0;i<ts->qcount;i++) {
1062 if ( pjob.status == LPQ_DELETED )
1063 continue;
1065 if (ts->queue[i].sysjob == pjob.sysjob) {
1067 /* try to clean up any jobs that need to be deleted */
1069 if ( pjob.status == LPQ_DELETING ) {
1070 int result;
1072 result = (*(ts->print_if->job_delete))(
1073 ts->sharename, ts->lprm_command, &pjob );
1075 if ( result != 0 ) {
1076 /* if we can't delete, then reset the job status */
1077 pjob.status = LPQ_QUEUED;
1078 pjob_store(ts->ev, ts->msg_ctx,
1079 ts->sharename, jobid, &pjob);
1081 else {
1082 /* if we deleted the job, the remove the tdb record */
1083 pjob_delete(ts->ev,
1084 ts->msg_ctx,
1085 ts->sharename, jobid);
1086 pjob.status = LPQ_DELETED;
1091 break;
1096 /* The job isn't in the system queue - we have to assume it has
1097 completed, so delete the database entry. */
1099 if (i == ts->qcount) {
1101 /* A race can occur between the time a job is spooled and
1102 when it appears in the lpq output. This happens when
1103 the job is added to printing.tdb when another smbd
1104 running print_queue_update() has completed a lpq and
1105 is currently traversing the printing tdb and deleting jobs.
1106 Don't delete the job if it was submitted after the lpq_time. */
1108 if (pjob.starttime < ts->lpq_time) {
1109 DEBUG(10,("traverse_fn_delete: pjob %u deleted due to pjob.starttime (%u) < ts->lpq_time (%u)\n",
1110 (unsigned int)jobid,
1111 (unsigned int)pjob.starttime,
1112 (unsigned int)ts->lpq_time ));
1113 pjob_delete(ts->ev, ts->msg_ctx,
1114 ts->sharename, jobid);
1115 } else
1116 ts->total_jobs++;
1117 return 0;
1120 /* Save the pjob attributes we will store. */
1121 ts->queue[i].sysjob = pjob.sysjob;
1122 ts->queue[i].size = pjob.size;
1123 ts->queue[i].page_count = pjob.page_count;
1124 ts->queue[i].status = pjob.status;
1125 ts->queue[i].priority = 1;
1126 ts->queue[i].time = pjob.starttime;
1127 fstrcpy(ts->queue[i].fs_user, pjob.user);
1128 fstrcpy(ts->queue[i].fs_file, pjob.jobname);
1130 ts->total_jobs++;
1132 return 0;
1135 /****************************************************************************
1136 Check if the print queue has been updated recently enough.
1137 ****************************************************************************/
1139 static void print_cache_flush(const char *sharename)
1141 fstring key;
1142 struct tdb_print_db *pdb = get_print_db_byname(sharename);
1144 if (!pdb)
1145 return;
1146 slprintf(key, sizeof(key)-1, "CACHE/%s", sharename);
1147 tdb_store_int32(pdb->tdb, key, -1);
1148 release_print_db(pdb);
1151 /****************************************************************************
1152 Check if someone already thinks they are doing the update.
1153 ****************************************************************************/
1155 static pid_t get_updating_pid(const char *sharename)
1157 fstring keystr;
1158 TDB_DATA data, key;
1159 pid_t updating_pid;
1160 struct tdb_print_db *pdb = get_print_db_byname(sharename);
1162 if (!pdb)
1163 return (pid_t)-1;
1164 slprintf(keystr, sizeof(keystr)-1, "UPDATING/%s", sharename);
1165 key = string_tdb_data(keystr);
1167 data = tdb_fetch(pdb->tdb, key);
1168 release_print_db(pdb);
1169 if (!data.dptr || data.dsize != sizeof(pid_t)) {
1170 SAFE_FREE(data.dptr);
1171 return (pid_t)-1;
1174 updating_pid = IVAL(data.dptr, 0);
1175 SAFE_FREE(data.dptr);
1177 if (process_exists_by_pid(updating_pid))
1178 return updating_pid;
1180 return (pid_t)-1;
1183 /****************************************************************************
1184 Set the fact that we're doing the update, or have finished doing the update
1185 in the tdb.
1186 ****************************************************************************/
1188 static void set_updating_pid(const fstring sharename, bool updating)
1190 fstring keystr;
1191 TDB_DATA key;
1192 TDB_DATA data;
1193 pid_t updating_pid = getpid();
1194 uint8_t buffer[4];
1196 struct tdb_print_db *pdb = get_print_db_byname(sharename);
1198 if (!pdb)
1199 return;
1201 slprintf(keystr, sizeof(keystr)-1, "UPDATING/%s", sharename);
1202 key = string_tdb_data(keystr);
1204 DEBUG(5, ("set_updating_pid: %supdating lpq cache for print share %s\n",
1205 updating ? "" : "not ",
1206 sharename ));
1208 if ( !updating ) {
1209 tdb_delete(pdb->tdb, key);
1210 release_print_db(pdb);
1211 return;
1214 SIVAL( buffer, 0, updating_pid);
1215 data.dptr = buffer;
1216 data.dsize = 4; /* we always assume this is a 4 byte value */
1218 tdb_store(pdb->tdb, key, data, TDB_REPLACE);
1219 release_print_db(pdb);
1222 /****************************************************************************
1223 Sort print jobs by submittal time.
1224 ****************************************************************************/
1226 static int printjob_comp(print_queue_struct *j1, print_queue_struct *j2)
1228 /* Silly cases */
1230 if (!j1 && !j2)
1231 return 0;
1232 if (!j1)
1233 return -1;
1234 if (!j2)
1235 return 1;
1237 /* Sort on job start time */
1239 if (j1->time == j2->time)
1240 return 0;
1241 return (j1->time > j2->time) ? 1 : -1;
1244 /****************************************************************************
1245 Store the sorted queue representation for later portmon retrieval.
1246 Skip deleted jobs
1247 ****************************************************************************/
1249 static void store_queue_struct(struct tdb_print_db *pdb, struct traverse_struct *pts)
1251 TDB_DATA data;
1252 int max_reported_jobs = lp_max_reported_print_jobs(pts->snum);
1253 print_queue_struct *queue = pts->queue;
1254 size_t len;
1255 size_t i;
1256 unsigned int qcount;
1258 if (max_reported_jobs && (max_reported_jobs < pts->qcount))
1259 pts->qcount = max_reported_jobs;
1260 qcount = 0;
1262 /* Work out the size. */
1263 data.dsize = 0;
1264 data.dsize += tdb_pack(NULL, 0, "d", qcount);
1266 for (i = 0; i < pts->qcount; i++) {
1267 if ( queue[i].status == LPQ_DELETED )
1268 continue;
1270 qcount++;
1271 data.dsize += tdb_pack(NULL, 0, "ddddddff",
1272 (uint32_t)queue[i].sysjob,
1273 (uint32_t)queue[i].size,
1274 (uint32_t)queue[i].page_count,
1275 (uint32_t)queue[i].status,
1276 (uint32_t)queue[i].priority,
1277 (uint32_t)queue[i].time,
1278 queue[i].fs_user,
1279 queue[i].fs_file);
1282 if ((data.dptr = (uint8_t *)SMB_MALLOC(data.dsize)) == NULL)
1283 return;
1285 len = 0;
1286 len += tdb_pack(data.dptr + len, data.dsize - len, "d", qcount);
1287 for (i = 0; i < pts->qcount; i++) {
1288 if ( queue[i].status == LPQ_DELETED )
1289 continue;
1291 len += tdb_pack(data.dptr + len, data.dsize - len, "ddddddff",
1292 (uint32_t)queue[i].sysjob,
1293 (uint32_t)queue[i].size,
1294 (uint32_t)queue[i].page_count,
1295 (uint32_t)queue[i].status,
1296 (uint32_t)queue[i].priority,
1297 (uint32_t)queue[i].time,
1298 queue[i].fs_user,
1299 queue[i].fs_file);
1302 tdb_store(pdb->tdb, string_tdb_data("INFO/linear_queue_array"), data,
1303 TDB_REPLACE);
1304 SAFE_FREE(data.dptr);
1305 return;
1308 static TDB_DATA get_jobs_added_data(struct tdb_print_db *pdb)
1310 TDB_DATA data;
1312 ZERO_STRUCT(data);
1314 data = tdb_fetch(pdb->tdb, string_tdb_data("INFO/jobs_added"));
1315 if (data.dptr == NULL || data.dsize == 0 || (data.dsize % 4 != 0)) {
1316 SAFE_FREE(data.dptr);
1317 ZERO_STRUCT(data);
1320 return data;
1323 static void check_job_added(const char *sharename, TDB_DATA data, uint32_t jobid)
1325 unsigned int i;
1326 unsigned int job_count = data.dsize / 4;
1328 for (i = 0; i < job_count; i++) {
1329 uint32_t ch_jobid;
1331 ch_jobid = IVAL(data.dptr, i*4);
1332 if (ch_jobid == jobid)
1333 remove_from_jobs_added(sharename, jobid);
1337 /****************************************************************************
1338 Check if the print queue has been updated recently enough.
1339 ****************************************************************************/
1341 static bool print_cache_expired(const char *sharename, bool check_pending)
1343 fstring key;
1344 time_t last_qscan_time, time_now = time(NULL);
1345 struct tdb_print_db *pdb = get_print_db_byname(sharename);
1346 bool result = False;
1348 if (!pdb)
1349 return False;
1351 snprintf(key, sizeof(key), "CACHE/%s", sharename);
1352 last_qscan_time = (time_t)tdb_fetch_int32(pdb->tdb, key);
1355 * Invalidate the queue for 3 reasons.
1356 * (1). last queue scan time == -1.
1357 * (2). Current time - last queue scan time > allowed cache time.
1358 * (3). last queue scan time > current time + MAX_CACHE_VALID_TIME (1 hour by default).
1359 * This last test picks up machines for which the clock has been moved
1360 * forward, an lpq scan done and then the clock moved back. Otherwise
1361 * that last lpq scan would stay around for a loooong loooong time... :-). JRA.
1364 if (last_qscan_time == ((time_t)-1)
1365 || (time_now - last_qscan_time) >= lp_lpq_cache_time()
1366 || last_qscan_time > (time_now + MAX_CACHE_VALID_TIME))
1368 uint32_t u;
1369 time_t msg_pending_time;
1371 DEBUG(4, ("print_cache_expired: cache expired for queue %s "
1372 "(last_qscan_time = %d, time now = %d, qcachetime = %d)\n",
1373 sharename, (int)last_qscan_time, (int)time_now,
1374 (int)lp_lpq_cache_time() ));
1376 /* check if another smbd has already sent a message to update the
1377 queue. Give the pending message one minute to clear and
1378 then send another message anyways. Make sure to check for
1379 clocks that have been run forward and then back again. */
1381 snprintf(key, sizeof(key), "MSG_PENDING/%s", sharename);
1383 if ( check_pending
1384 && tdb_fetch_uint32( pdb->tdb, key, &u )
1385 && (msg_pending_time=u) > 0
1386 && msg_pending_time <= time_now
1387 && (time_now - msg_pending_time) < 60 )
1389 DEBUG(4,("print_cache_expired: message already pending for %s. Accepting cache\n",
1390 sharename));
1391 goto done;
1394 result = True;
1397 done:
1398 release_print_db(pdb);
1399 return result;
1402 /****************************************************************************
1403 main work for updating the lpq cache for a printer queue
1404 ****************************************************************************/
1406 static void print_queue_update_internal(struct tevent_context *ev,
1407 struct messaging_context *msg_ctx,
1408 const char *sharename,
1409 struct printif *current_printif,
1410 char *lpq_command, char *lprm_command)
1412 int i, qcount;
1413 print_queue_struct *queue = NULL;
1414 print_status_struct status;
1415 print_status_struct old_status;
1416 struct printjob *pjob;
1417 struct traverse_struct tstruct;
1418 TDB_DATA data, key;
1419 TDB_DATA jcdata;
1420 fstring keystr, cachestr;
1421 struct tdb_print_db *pdb = get_print_db_byname(sharename);
1422 TALLOC_CTX *tmp_ctx = talloc_new(ev);
1424 if ((pdb == NULL) || (tmp_ctx == NULL)) {
1425 return;
1428 DEBUG(5,("print_queue_update_internal: printer = %s, type = %d, lpq command = [%s]\n",
1429 sharename, current_printif->type, lpq_command));
1432 * Update the cache time FIRST ! Stops others even
1433 * attempting to get the lock and doing this
1434 * if the lpq takes a long time.
1437 slprintf(cachestr, sizeof(cachestr)-1, "CACHE/%s", sharename);
1438 tdb_store_int32(pdb->tdb, cachestr, (int)time(NULL));
1440 /* get the current queue using the appropriate interface */
1441 ZERO_STRUCT(status);
1443 qcount = (*(current_printif->queue_get))(sharename,
1444 current_printif->type,
1445 lpq_command, &queue, &status);
1447 DEBUG(3, ("print_queue_update_internal: %d job%s in queue for %s\n",
1448 qcount, (qcount != 1) ? "s" : "", sharename));
1450 /* Sort the queue by submission time otherwise they are displayed
1451 in hash order. */
1453 TYPESAFE_QSORT(queue, qcount, printjob_comp);
1456 any job in the internal database that is marked as spooled
1457 and doesn't exist in the system queue is considered finished
1458 and removed from the database
1460 any job in the system database but not in the internal database
1461 is added as a unix job
1463 fill in any system job numbers as we go
1465 jcdata = get_jobs_added_data(pdb);
1467 for (i=0; i<qcount; i++) {
1468 uint32_t jobid = sysjob_to_jobid_pdb(pdb, queue[i].sysjob);
1469 if (jobid == (uint32_t)-1) {
1470 /* assume its a unix print job */
1471 print_unix_job(ev, msg_ctx,
1472 sharename, &queue[i], jobid);
1473 continue;
1476 /* we have an active SMB print job - update its status */
1477 pjob = print_job_find(tmp_ctx, sharename, jobid);
1478 if (!pjob) {
1479 /* err, somethings wrong. Probably smbd was restarted
1480 with jobs in the queue. All we can do is treat them
1481 like unix jobs. Pity. */
1482 DEBUG(1, ("queued print job %d not found in jobs list, "
1483 "assuming unix job\n", jobid));
1484 print_unix_job(ev, msg_ctx,
1485 sharename, &queue[i], jobid);
1486 continue;
1489 /* don't reset the status on jobs to be deleted */
1491 if ( pjob->status != LPQ_DELETING )
1492 pjob->status = queue[i].status;
1494 pjob_store(ev, msg_ctx, sharename, jobid, pjob);
1496 check_job_added(sharename, jcdata, jobid);
1499 SAFE_FREE(jcdata.dptr);
1501 /* now delete any queued entries that don't appear in the
1502 system queue */
1503 tstruct.queue = queue;
1504 tstruct.qcount = qcount;
1505 tstruct.snum = -1;
1506 tstruct.total_jobs = 0;
1507 tstruct.lpq_time = time(NULL);
1508 tstruct.sharename = sharename;
1509 tstruct.lprm_command = lprm_command;
1510 tstruct.print_if = current_printif;
1511 tstruct.ev = ev;
1512 tstruct.msg_ctx = msg_ctx;
1513 tstruct.mem_ctx = tmp_ctx;
1515 tdb_traverse(pdb->tdb, traverse_fn_delete, (void *)&tstruct);
1517 /* Store the linearised queue, max jobs only. */
1518 store_queue_struct(pdb, &tstruct);
1520 SAFE_FREE(tstruct.queue);
1521 talloc_free(tmp_ctx);
1523 DEBUG(10,("print_queue_update_internal: printer %s INFO/total_jobs = %d\n",
1524 sharename, tstruct.total_jobs ));
1526 tdb_store_int32(pdb->tdb, "INFO/total_jobs", tstruct.total_jobs);
1528 get_queue_status(sharename, &old_status);
1529 if (old_status.qcount != qcount)
1530 DEBUG(10,("print_queue_update_internal: queue status change %d jobs -> %d jobs for printer %s\n",
1531 old_status.qcount, qcount, sharename));
1533 /* store the new queue status structure */
1534 slprintf(keystr, sizeof(keystr)-1, "STATUS/%s", sharename);
1535 key = string_tdb_data(keystr);
1537 status.qcount = qcount;
1538 data.dptr = (uint8_t *)&status;
1539 data.dsize = sizeof(status);
1540 tdb_store(pdb->tdb, key, data, TDB_REPLACE);
1543 * Update the cache time again. We want to do this call
1544 * as little as possible...
1547 slprintf(keystr, sizeof(keystr)-1, "CACHE/%s", sharename);
1548 tdb_store_int32(pdb->tdb, keystr, (int32_t)time(NULL));
1550 /* clear the msg pending record for this queue */
1552 snprintf(keystr, sizeof(keystr), "MSG_PENDING/%s", sharename);
1554 if ( !tdb_store_uint32( pdb->tdb, keystr, 0 ) ) {
1555 /* log a message but continue on */
1557 DEBUG(0,("print_queue_update: failed to store MSG_PENDING flag for [%s]!\n",
1558 sharename));
1561 release_print_db( pdb );
1563 return;
1566 /****************************************************************************
1567 Update the internal database from the system print queue for a queue.
1568 obtain a lock on the print queue before proceeding (needed when mutiple
1569 smbd processes maytry to update the lpq cache concurrently).
1570 ****************************************************************************/
1572 static void print_queue_update_with_lock( struct tevent_context *ev,
1573 struct messaging_context *msg_ctx,
1574 const char *sharename,
1575 struct printif *current_printif,
1576 char *lpq_command, char *lprm_command )
1578 fstring keystr;
1579 struct tdb_print_db *pdb;
1581 DEBUG(5,("print_queue_update_with_lock: printer share = %s\n", sharename));
1582 pdb = get_print_db_byname(sharename);
1583 if (!pdb)
1584 return;
1586 if ( !print_cache_expired(sharename, False) ) {
1587 DEBUG(5,("print_queue_update_with_lock: print cache for %s is still ok\n", sharename));
1588 release_print_db(pdb);
1589 return;
1593 * Check to see if someone else is doing this update.
1594 * This is essentially a mutex on the update.
1597 if (get_updating_pid(sharename) != -1) {
1598 release_print_db(pdb);
1599 return;
1602 /* Lock the queue for the database update */
1604 slprintf(keystr, sizeof(keystr) - 1, "LOCK/%s", sharename);
1605 /* Only wait 10 seconds for this. */
1606 if (tdb_lock_bystring_with_timeout(pdb->tdb, keystr, 10) != 0) {
1607 DEBUG(0,("print_queue_update_with_lock: Failed to lock printer %s database\n", sharename));
1608 release_print_db(pdb);
1609 return;
1613 * Ensure that no one else got in here.
1614 * If the updating pid is still -1 then we are
1615 * the winner.
1618 if (get_updating_pid(sharename) != -1) {
1620 * Someone else is doing the update, exit.
1622 tdb_unlock_bystring(pdb->tdb, keystr);
1623 release_print_db(pdb);
1624 return;
1628 * We're going to do the update ourselves.
1631 /* Tell others we're doing the update. */
1632 set_updating_pid(sharename, True);
1635 * Allow others to enter and notice we're doing
1636 * the update.
1639 tdb_unlock_bystring(pdb->tdb, keystr);
1641 /* do the main work now */
1643 print_queue_update_internal(ev, msg_ctx,
1644 sharename, current_printif,
1645 lpq_command, lprm_command);
1647 /* Delete our pid from the db. */
1648 set_updating_pid(sharename, False);
1649 release_print_db(pdb);
1652 /****************************************************************************
1653 this is the receive function of the background lpq updater
1654 ****************************************************************************/
1655 void print_queue_receive(struct messaging_context *msg,
1656 void *private_data,
1657 uint32_t msg_type,
1658 struct server_id server_id,
1659 DATA_BLOB *data)
1661 fstring sharename;
1662 char *lpqcommand = NULL, *lprmcommand = NULL;
1663 int printing_type;
1664 size_t len;
1666 len = tdb_unpack( (uint8_t *)data->data, data->length, "fdPP",
1667 sharename,
1668 &printing_type,
1669 &lpqcommand,
1670 &lprmcommand );
1672 if ( len == -1 ) {
1673 SAFE_FREE(lpqcommand);
1674 SAFE_FREE(lprmcommand);
1675 DEBUG(0,("print_queue_receive: Got invalid print queue update message\n"));
1676 return;
1679 print_queue_update_with_lock(server_event_context(), msg, sharename,
1680 get_printer_fns_from_type((enum printing_types)printing_type),
1681 lpqcommand, lprmcommand );
1683 SAFE_FREE(lpqcommand);
1684 SAFE_FREE(lprmcommand);
1685 return;
1688 /****************************************************************************
1689 update the internal database from the system print queue for a queue
1690 ****************************************************************************/
1692 extern pid_t background_lpq_updater_pid;
1694 static void print_queue_update(struct messaging_context *msg_ctx,
1695 int snum, bool force)
1697 fstring key;
1698 fstring sharename;
1699 char *lpqcommand = NULL;
1700 char *lprmcommand = NULL;
1701 uint8_t *buffer = NULL;
1702 size_t len = 0;
1703 size_t newlen;
1704 struct tdb_print_db *pdb;
1705 int type;
1706 struct printif *current_printif;
1707 TALLOC_CTX *ctx = talloc_tos();
1709 fstrcpy( sharename, lp_const_servicename(snum));
1711 /* don't strip out characters like '$' from the printername */
1713 lpqcommand = talloc_string_sub2(ctx,
1714 lp_lpq_command(talloc_tos(), snum),
1715 "%p",
1716 lp_printername(talloc_tos(), snum),
1717 false, false, false);
1718 if (!lpqcommand) {
1719 return;
1721 lpqcommand = talloc_sub_advanced(ctx,
1722 lp_servicename(talloc_tos(), snum),
1723 current_user_info.unix_name,
1725 current_user.ut.gid,
1726 get_current_username(),
1727 current_user_info.domain,
1728 lpqcommand);
1729 if (!lpqcommand) {
1730 return;
1733 lprmcommand = talloc_string_sub2(ctx,
1734 lp_lprm_command(talloc_tos(), snum),
1735 "%p",
1736 lp_printername(talloc_tos(), snum),
1737 false, false, false);
1738 if (!lprmcommand) {
1739 return;
1741 lprmcommand = talloc_sub_advanced(ctx,
1742 lp_servicename(talloc_tos(), snum),
1743 current_user_info.unix_name,
1745 current_user.ut.gid,
1746 get_current_username(),
1747 current_user_info.domain,
1748 lprmcommand);
1749 if (!lprmcommand) {
1750 return;
1754 * Make sure that the background queue process exists.
1755 * Otherwise just do the update ourselves
1758 if ( force || background_lpq_updater_pid == -1 ) {
1759 DEBUG(4,("print_queue_update: updating queue [%s] myself\n", sharename));
1760 current_printif = get_printer_fns( snum );
1761 print_queue_update_with_lock(server_event_context(), msg_ctx,
1762 sharename, current_printif,
1763 lpqcommand, lprmcommand);
1765 return;
1768 type = lp_printing(snum);
1770 /* get the length */
1772 len = tdb_pack( NULL, 0, "fdPP",
1773 sharename,
1774 type,
1775 lpqcommand,
1776 lprmcommand );
1778 buffer = SMB_XMALLOC_ARRAY( uint8_t, len );
1780 /* now pack the buffer */
1781 newlen = tdb_pack( buffer, len, "fdPP",
1782 sharename,
1783 type,
1784 lpqcommand,
1785 lprmcommand );
1787 SMB_ASSERT( newlen == len );
1789 DEBUG(10,("print_queue_update: Sending message -> printer = %s, "
1790 "type = %d, lpq command = [%s] lprm command = [%s]\n",
1791 sharename, type, lpqcommand, lprmcommand ));
1793 /* here we set a msg pending record for other smbd processes
1794 to throttle the number of duplicate print_queue_update msgs
1795 sent. */
1797 pdb = get_print_db_byname(sharename);
1798 if (!pdb) {
1799 SAFE_FREE(buffer);
1800 return;
1803 snprintf(key, sizeof(key), "MSG_PENDING/%s", sharename);
1805 if ( !tdb_store_uint32( pdb->tdb, key, time(NULL) ) ) {
1806 /* log a message but continue on */
1808 DEBUG(0,("print_queue_update: failed to store MSG_PENDING flag for [%s]!\n",
1809 sharename));
1812 release_print_db( pdb );
1814 /* finally send the message */
1816 messaging_send_buf(msg_ctx, pid_to_procid(background_lpq_updater_pid),
1817 MSG_PRINTER_UPDATE, (uint8_t *)buffer, len);
1819 SAFE_FREE( buffer );
1821 return;
1824 /****************************************************************************
1825 Create/Update an entry in the print tdb that will allow us to send notify
1826 updates only to interested smbd's.
1827 ****************************************************************************/
1829 bool print_notify_register_pid(int snum)
1831 TDB_DATA data;
1832 struct tdb_print_db *pdb = NULL;
1833 TDB_CONTEXT *tdb = NULL;
1834 const char *printername;
1835 uint32_t mypid = (uint32_t)getpid();
1836 bool ret = False;
1837 size_t i;
1839 /* if (snum == -1), then the change notify request was
1840 on a print server handle and we need to register on
1841 all print queus */
1843 if (snum == -1)
1845 int num_services = lp_numservices();
1846 int idx;
1848 for ( idx=0; idx<num_services; idx++ ) {
1849 if (lp_snum_ok(idx) && lp_printable(idx) )
1850 print_notify_register_pid(idx);
1853 return True;
1855 else /* register for a specific printer */
1857 printername = lp_const_servicename(snum);
1858 pdb = get_print_db_byname(printername);
1859 if (!pdb)
1860 return False;
1861 tdb = pdb->tdb;
1864 if (tdb_lock_bystring_with_timeout(tdb, NOTIFY_PID_LIST_KEY, 10) != 0) {
1865 DEBUG(0,("print_notify_register_pid: Failed to lock printer %s\n",
1866 printername));
1867 if (pdb)
1868 release_print_db(pdb);
1869 return False;
1872 data = get_printer_notify_pid_list( tdb, printername, True );
1874 /* Add ourselves and increase the refcount. */
1876 for (i = 0; i < data.dsize; i += 8) {
1877 if (IVAL(data.dptr,i) == mypid) {
1878 uint32_t new_refcount = IVAL(data.dptr, i+4) + 1;
1879 SIVAL(data.dptr, i+4, new_refcount);
1880 break;
1884 if (i == data.dsize) {
1885 /* We weren't in the list. Realloc. */
1886 data.dptr = (uint8_t *)SMB_REALLOC(data.dptr, data.dsize + 8);
1887 if (!data.dptr) {
1888 DEBUG(0,("print_notify_register_pid: Relloc fail for printer %s\n",
1889 printername));
1890 goto done;
1892 data.dsize += 8;
1893 SIVAL(data.dptr,data.dsize - 8,mypid);
1894 SIVAL(data.dptr,data.dsize - 4,1); /* Refcount. */
1897 /* Store back the record. */
1898 if (tdb_store_bystring(tdb, NOTIFY_PID_LIST_KEY, data, TDB_REPLACE) != 0) {
1899 DEBUG(0,("print_notify_register_pid: Failed to update pid \
1900 list for printer %s\n", printername));
1901 goto done;
1904 ret = True;
1906 done:
1908 tdb_unlock_bystring(tdb, NOTIFY_PID_LIST_KEY);
1909 if (pdb)
1910 release_print_db(pdb);
1911 SAFE_FREE(data.dptr);
1912 return ret;
1915 /****************************************************************************
1916 Update an entry in the print tdb that will allow us to send notify
1917 updates only to interested smbd's.
1918 ****************************************************************************/
1920 bool print_notify_deregister_pid(int snum)
1922 TDB_DATA data;
1923 struct tdb_print_db *pdb = NULL;
1924 TDB_CONTEXT *tdb = NULL;
1925 const char *printername;
1926 uint32_t mypid = (uint32_t)getpid();
1927 size_t i;
1928 bool ret = False;
1930 /* if ( snum == -1 ), we are deregister a print server handle
1931 which means to deregister on all print queues */
1933 if (snum == -1)
1935 int num_services = lp_numservices();
1936 int idx;
1938 for ( idx=0; idx<num_services; idx++ ) {
1939 if ( lp_snum_ok(idx) && lp_printable(idx) )
1940 print_notify_deregister_pid(idx);
1943 return True;
1945 else /* deregister a specific printer */
1947 printername = lp_const_servicename(snum);
1948 pdb = get_print_db_byname(printername);
1949 if (!pdb)
1950 return False;
1951 tdb = pdb->tdb;
1954 if (tdb_lock_bystring_with_timeout(tdb, NOTIFY_PID_LIST_KEY, 10) != 0) {
1955 DEBUG(0,("print_notify_register_pid: Failed to lock \
1956 printer %s database\n", printername));
1957 if (pdb)
1958 release_print_db(pdb);
1959 return False;
1962 data = get_printer_notify_pid_list( tdb, printername, True );
1964 /* Reduce refcount. Remove ourselves if zero. */
1966 for (i = 0; i < data.dsize; ) {
1967 if (IVAL(data.dptr,i) == mypid) {
1968 uint32_t refcount = IVAL(data.dptr, i+4);
1970 refcount--;
1972 if (refcount == 0) {
1973 if (data.dsize - i > 8)
1974 memmove( &data.dptr[i], &data.dptr[i+8], data.dsize - i - 8);
1975 data.dsize -= 8;
1976 continue;
1978 SIVAL(data.dptr, i+4, refcount);
1981 i += 8;
1984 if (data.dsize == 0)
1985 SAFE_FREE(data.dptr);
1987 /* Store back the record. */
1988 if (tdb_store_bystring(tdb, NOTIFY_PID_LIST_KEY, data, TDB_REPLACE) != 0) {
1989 DEBUG(0,("print_notify_register_pid: Failed to update pid \
1990 list for printer %s\n", printername));
1991 goto done;
1994 ret = True;
1996 done:
1998 tdb_unlock_bystring(tdb, NOTIFY_PID_LIST_KEY);
1999 if (pdb)
2000 release_print_db(pdb);
2001 SAFE_FREE(data.dptr);
2002 return ret;
2005 /****************************************************************************
2006 Check if a jobid is valid. It is valid if it exists in the database.
2007 ****************************************************************************/
2009 bool print_job_exists(const char* sharename, uint32_t jobid)
2011 struct tdb_print_db *pdb = get_print_db_byname(sharename);
2012 bool ret;
2013 uint32_t tmp;
2015 if (!pdb)
2016 return False;
2017 ret = tdb_exists(pdb->tdb, print_key(jobid, &tmp));
2018 release_print_db(pdb);
2019 return ret;
2022 /****************************************************************************
2023 Return the device mode asigned to a specific print job.
2024 Only valid for the process doing the spooling and when the job
2025 has not been spooled.
2026 ****************************************************************************/
2028 struct spoolss_DeviceMode *print_job_devmode(TALLOC_CTX *mem_ctx,
2029 const char *sharename,
2030 uint32_t jobid)
2032 struct printjob *pjob = print_job_find(mem_ctx, sharename, jobid);
2033 if (pjob == NULL) {
2034 return NULL;
2037 return pjob->devmode;
2040 /****************************************************************************
2041 Set the name of a job. Only possible for owner.
2042 ****************************************************************************/
2044 bool print_job_set_name(struct tevent_context *ev,
2045 struct messaging_context *msg_ctx,
2046 const char *sharename, uint32_t jobid, const char *name)
2048 struct printjob *pjob;
2049 bool ret;
2050 TALLOC_CTX *tmp_ctx = talloc_new(ev);
2051 if (tmp_ctx == NULL) {
2052 return false;
2055 pjob = print_job_find(tmp_ctx, sharename, jobid);
2056 if (!pjob || pjob->pid != getpid()) {
2057 ret = false;
2058 goto err_out;
2061 fstrcpy(pjob->jobname, name);
2062 ret = pjob_store(ev, msg_ctx, sharename, jobid, pjob);
2063 err_out:
2064 talloc_free(tmp_ctx);
2065 return ret;
2068 /****************************************************************************
2069 Get the name of a job. Only possible for owner.
2070 ****************************************************************************/
2072 bool print_job_get_name(TALLOC_CTX *mem_ctx, const char *sharename, uint32_t jobid, char **name)
2074 struct printjob *pjob;
2076 pjob = print_job_find(mem_ctx, sharename, jobid);
2077 if (!pjob || pjob->pid != getpid()) {
2078 return false;
2081 *name = pjob->jobname;
2082 return true;
2086 /***************************************************************************
2087 Remove a jobid from the 'jobs added' list.
2088 ***************************************************************************/
2090 static bool remove_from_jobs_added(const char* sharename, uint32_t jobid)
2092 struct tdb_print_db *pdb = get_print_db_byname(sharename);
2093 TDB_DATA data, key;
2094 size_t job_count, i;
2095 bool ret = False;
2096 bool gotlock = False;
2098 if (!pdb) {
2099 return False;
2102 ZERO_STRUCT(data);
2104 key = string_tdb_data("INFO/jobs_added");
2106 if (tdb_chainlock_with_timeout(pdb->tdb, key, 5) != 0)
2107 goto out;
2109 gotlock = True;
2111 data = tdb_fetch(pdb->tdb, key);
2113 if (data.dptr == NULL || data.dsize == 0 || (data.dsize % 4 != 0))
2114 goto out;
2116 job_count = data.dsize / 4;
2117 for (i = 0; i < job_count; i++) {
2118 uint32_t ch_jobid;
2120 ch_jobid = IVAL(data.dptr, i*4);
2121 if (ch_jobid == jobid) {
2122 if (i < job_count -1 )
2123 memmove(data.dptr + (i*4), data.dptr + (i*4) + 4, (job_count - i - 1)*4 );
2124 data.dsize -= 4;
2125 if (tdb_store(pdb->tdb, key, data, TDB_REPLACE) != 0)
2126 goto out;
2127 break;
2131 ret = True;
2132 out:
2134 if (gotlock)
2135 tdb_chainunlock(pdb->tdb, key);
2136 SAFE_FREE(data.dptr);
2137 release_print_db(pdb);
2138 if (ret)
2139 DEBUG(10,("remove_from_jobs_added: removed jobid %u\n", (unsigned int)jobid ));
2140 else
2141 DEBUG(10,("remove_from_jobs_added: Failed to remove jobid %u\n", (unsigned int)jobid ));
2142 return ret;
2145 /****************************************************************************
2146 Delete a print job - don't update queue.
2147 ****************************************************************************/
2149 static bool print_job_delete1(struct tevent_context *ev,
2150 struct messaging_context *msg_ctx,
2151 int snum, uint32_t jobid)
2153 const char* sharename = lp_const_servicename(snum);
2154 struct printjob *pjob;
2155 int result = 0;
2156 struct printif *current_printif = get_printer_fns( snum );
2157 bool ret;
2158 TALLOC_CTX *tmp_ctx = talloc_new(ev);
2159 if (tmp_ctx == NULL) {
2160 return false;
2163 pjob = print_job_find(tmp_ctx, sharename, jobid);
2164 if (!pjob) {
2165 ret = false;
2166 goto err_out;
2170 * If already deleting just return.
2173 if (pjob->status == LPQ_DELETING) {
2174 ret = true;
2175 goto err_out;
2178 /* Hrm - we need to be able to cope with deleting a job before it
2179 has reached the spooler. Just mark it as LPQ_DELETING and
2180 let the print_queue_update() code rmeove the record */
2183 if (pjob->sysjob == -1) {
2184 DEBUG(5, ("attempt to delete job %u not seen by lpr\n", (unsigned int)jobid));
2187 /* Set the tdb entry to be deleting. */
2189 pjob->status = LPQ_DELETING;
2190 pjob_store(ev, msg_ctx, sharename, jobid, pjob);
2192 if (pjob->spooled && pjob->sysjob != -1)
2194 result = (*(current_printif->job_delete))(
2195 lp_printername(talloc_tos(), snum),
2196 lp_lprm_command(talloc_tos(), snum),
2197 pjob);
2199 /* Delete the tdb entry if the delete succeeded or the job hasn't
2200 been spooled. */
2202 if (result == 0) {
2203 struct tdb_print_db *pdb = get_print_db_byname(sharename);
2204 int njobs = 1;
2206 if (!pdb) {
2207 ret = false;
2208 goto err_out;
2210 pjob_delete(ev, msg_ctx, sharename, jobid);
2211 /* Ensure we keep a rough count of the number of total jobs... */
2212 tdb_change_int32_atomic(pdb->tdb, "INFO/total_jobs", &njobs, -1);
2213 release_print_db(pdb);
2217 remove_from_jobs_added( sharename, jobid );
2219 ret = (result == 0);
2220 err_out:
2221 talloc_free(tmp_ctx);
2222 return ret;
2225 /****************************************************************************
2226 Return true if the current user owns the print job.
2227 ****************************************************************************/
2229 static bool is_owner(const struct auth_session_info *server_info,
2230 const char *servicename,
2231 uint32_t jobid)
2233 struct printjob *pjob;
2234 bool ret;
2235 TALLOC_CTX *tmp_ctx = talloc_new(server_info);
2236 if (tmp_ctx == NULL) {
2237 return false;
2240 pjob = print_job_find(tmp_ctx, servicename, jobid);
2241 if (!pjob || !server_info) {
2242 ret = false;
2243 goto err_out;
2246 ret = strequal(pjob->user, server_info->unix_info->sanitized_username);
2247 err_out:
2248 talloc_free(tmp_ctx);
2249 return ret;
2252 /****************************************************************************
2253 Delete a print job.
2254 ****************************************************************************/
2256 WERROR print_job_delete(const struct auth_session_info *server_info,
2257 struct messaging_context *msg_ctx,
2258 int snum, uint32_t jobid)
2260 const char* sharename = lp_const_servicename(snum);
2261 struct printjob *pjob;
2262 bool owner;
2263 WERROR werr;
2264 TALLOC_CTX *tmp_ctx = talloc_new(msg_ctx);
2265 if (tmp_ctx == NULL) {
2266 return WERR_NOT_ENOUGH_MEMORY;
2269 owner = is_owner(server_info, lp_const_servicename(snum), jobid);
2271 /* Check access against security descriptor or whether the user
2272 owns their job. */
2274 if (!owner &&
2275 !W_ERROR_IS_OK(print_access_check(server_info, msg_ctx, snum,
2276 JOB_ACCESS_ADMINISTER))) {
2277 DEBUG(0, ("print job delete denied."
2278 "User name: %s, Printer name: %s.",
2279 uidtoname(server_info->unix_token->uid),
2280 lp_printername(tmp_ctx, snum)));
2282 werr = WERR_ACCESS_DENIED;
2283 goto err_out;
2287 * get the spooled filename of the print job
2288 * if this works, then the file has not been spooled
2289 * to the underlying print system. Just delete the
2290 * spool file & return.
2293 pjob = print_job_find(tmp_ctx, sharename, jobid);
2294 if (!pjob || pjob->spooled || pjob->pid != getpid()) {
2295 DEBUG(10, ("Skipping spool file removal for job %u\n", jobid));
2296 } else {
2297 DEBUG(10, ("Removing spool file [%s]\n", pjob->filename));
2298 if (unlink(pjob->filename) == -1) {
2299 werr = map_werror_from_unix(errno);
2300 goto err_out;
2304 if (!print_job_delete1(server_event_context(), msg_ctx, snum, jobid)) {
2305 werr = WERR_ACCESS_DENIED;
2306 goto err_out;
2309 /* force update the database and say the delete failed if the
2310 job still exists */
2312 print_queue_update(msg_ctx, snum, True);
2314 pjob = print_job_find(tmp_ctx, sharename, jobid);
2315 if (pjob && (pjob->status != LPQ_DELETING)) {
2316 werr = WERR_ACCESS_DENIED;
2317 goto err_out;
2319 werr = WERR_PRINTER_HAS_JOBS_QUEUED;
2321 err_out:
2322 talloc_free(tmp_ctx);
2323 return werr;
2326 /****************************************************************************
2327 Pause a job.
2328 ****************************************************************************/
2330 WERROR print_job_pause(const struct auth_session_info *server_info,
2331 struct messaging_context *msg_ctx,
2332 int snum, uint32_t jobid)
2334 const char* sharename = lp_const_servicename(snum);
2335 struct printjob *pjob;
2336 int ret = -1;
2337 struct printif *current_printif = get_printer_fns( snum );
2338 WERROR werr;
2339 TALLOC_CTX *tmp_ctx = talloc_new(msg_ctx);
2340 if (tmp_ctx == NULL) {
2341 return WERR_NOT_ENOUGH_MEMORY;
2344 pjob = print_job_find(tmp_ctx, sharename, jobid);
2345 if (!pjob || !server_info) {
2346 DEBUG(10, ("print_job_pause: no pjob or user for jobid %u\n",
2347 (unsigned int)jobid ));
2348 werr = WERR_INVALID_PARAMETER;
2349 goto err_out;
2352 if (!pjob->spooled || pjob->sysjob == -1) {
2353 DEBUG(10, ("print_job_pause: not spooled or bad sysjob = %d for jobid %u\n",
2354 (int)pjob->sysjob, (unsigned int)jobid ));
2355 werr = WERR_INVALID_PARAMETER;
2356 goto err_out;
2359 if (!is_owner(server_info, lp_const_servicename(snum), jobid) &&
2360 !W_ERROR_IS_OK(print_access_check(server_info, msg_ctx, snum,
2361 JOB_ACCESS_ADMINISTER))) {
2362 DEBUG(0, ("print job pause denied."
2363 "User name: %s, Printer name: %s.",
2364 uidtoname(server_info->unix_token->uid),
2365 lp_printername(tmp_ctx, snum)));
2367 werr = WERR_ACCESS_DENIED;
2368 goto err_out;
2371 /* need to pause the spooled entry */
2372 ret = (*(current_printif->job_pause))(snum, pjob);
2374 if (ret != 0) {
2375 werr = WERR_INVALID_PARAMETER;
2376 goto err_out;
2379 /* force update the database */
2380 print_cache_flush(lp_const_servicename(snum));
2382 /* Send a printer notify message */
2384 notify_job_status(server_event_context(), msg_ctx, sharename, jobid,
2385 JOB_STATUS_PAUSED);
2387 /* how do we tell if this succeeded? */
2388 werr = WERR_OK;
2389 err_out:
2390 talloc_free(tmp_ctx);
2391 return werr;
2394 /****************************************************************************
2395 Resume a job.
2396 ****************************************************************************/
2398 WERROR print_job_resume(const struct auth_session_info *server_info,
2399 struct messaging_context *msg_ctx,
2400 int snum, uint32_t jobid)
2402 const char *sharename = lp_const_servicename(snum);
2403 struct printjob *pjob;
2404 int ret;
2405 struct printif *current_printif = get_printer_fns( snum );
2406 WERROR werr;
2407 TALLOC_CTX *tmp_ctx = talloc_new(msg_ctx);
2408 if (tmp_ctx == NULL)
2409 return WERR_NOT_ENOUGH_MEMORY;
2411 pjob = print_job_find(tmp_ctx, sharename, jobid);
2412 if (!pjob || !server_info) {
2413 DEBUG(10, ("print_job_resume: no pjob or user for jobid %u\n",
2414 (unsigned int)jobid ));
2415 werr = WERR_INVALID_PARAMETER;
2416 goto err_out;
2419 if (!pjob->spooled || pjob->sysjob == -1) {
2420 DEBUG(10, ("print_job_resume: not spooled or bad sysjob = %d for jobid %u\n",
2421 (int)pjob->sysjob, (unsigned int)jobid ));
2422 werr = WERR_INVALID_PARAMETER;
2423 goto err_out;
2426 if (!is_owner(server_info, lp_const_servicename(snum), jobid) &&
2427 !W_ERROR_IS_OK(print_access_check(server_info, msg_ctx, snum,
2428 JOB_ACCESS_ADMINISTER))) {
2429 DEBUG(0, ("print job resume denied."
2430 "User name: %s, Printer name: %s.",
2431 uidtoname(server_info->unix_token->uid),
2432 lp_printername(tmp_ctx, snum)));
2434 werr = WERR_ACCESS_DENIED;
2435 goto err_out;
2438 ret = (*(current_printif->job_resume))(snum, pjob);
2440 if (ret != 0) {
2441 werr = WERR_INVALID_PARAMETER;
2442 goto err_out;
2445 /* force update the database */
2446 print_cache_flush(lp_const_servicename(snum));
2448 /* Send a printer notify message */
2450 notify_job_status(server_event_context(), msg_ctx, sharename, jobid,
2451 JOB_STATUS_QUEUED);
2453 werr = WERR_OK;
2454 err_out:
2455 talloc_free(tmp_ctx);
2456 return werr;
2459 /****************************************************************************
2460 Write to a print file.
2461 ****************************************************************************/
2463 ssize_t print_job_write(struct tevent_context *ev,
2464 struct messaging_context *msg_ctx,
2465 int snum, uint32_t jobid, const char *buf, size_t size)
2467 const char* sharename = lp_const_servicename(snum);
2468 ssize_t return_code;
2469 struct printjob *pjob;
2470 TALLOC_CTX *tmp_ctx = talloc_new(ev);
2471 if (tmp_ctx == NULL) {
2472 return -1;
2475 pjob = print_job_find(tmp_ctx, sharename, jobid);
2476 if (!pjob) {
2477 return_code = -1;
2478 goto err_out;
2481 /* don't allow another process to get this info - it is meaningless */
2482 if (pjob->pid != getpid()) {
2483 return_code = -1;
2484 goto err_out;
2487 /* if SMBD is spooling this can't be allowed */
2488 if (pjob->status == PJOB_SMBD_SPOOLING) {
2489 return_code = -1;
2490 goto err_out;
2493 return_code = write_data(pjob->fd, buf, size);
2494 if (return_code > 0) {
2495 pjob->size += size;
2496 pjob_store(ev, msg_ctx, sharename, jobid, pjob);
2498 err_out:
2499 talloc_free(tmp_ctx);
2500 return return_code;
2503 /****************************************************************************
2504 Get the queue status - do not update if db is out of date.
2505 ****************************************************************************/
2507 static int get_queue_status(const char* sharename, print_status_struct *status)
2509 fstring keystr;
2510 TDB_DATA data;
2511 struct tdb_print_db *pdb = get_print_db_byname(sharename);
2512 int len;
2514 if (status) {
2515 ZERO_STRUCTP(status);
2518 if (!pdb)
2519 return 0;
2521 if (status) {
2522 fstr_sprintf(keystr, "STATUS/%s", sharename);
2523 data = tdb_fetch(pdb->tdb, string_tdb_data(keystr));
2524 if (data.dptr) {
2525 if (data.dsize == sizeof(print_status_struct))
2526 /* this memcpy is ok since the status struct was
2527 not packed before storing it in the tdb */
2528 memcpy(status, data.dptr, sizeof(print_status_struct));
2529 SAFE_FREE(data.dptr);
2532 len = tdb_fetch_int32(pdb->tdb, "INFO/total_jobs");
2533 release_print_db(pdb);
2534 return (len == -1 ? 0 : len);
2537 /****************************************************************************
2538 Determine the number of jobs in a queue.
2539 ****************************************************************************/
2541 int print_queue_length(struct messaging_context *msg_ctx, int snum,
2542 print_status_struct *pstatus)
2544 const char* sharename = lp_const_servicename( snum );
2545 print_status_struct status;
2546 int len;
2548 ZERO_STRUCT( status );
2550 /* make sure the database is up to date */
2551 if (print_cache_expired(lp_const_servicename(snum), True))
2552 print_queue_update(msg_ctx, snum, False);
2554 /* also fetch the queue status */
2555 memset(&status, 0, sizeof(status));
2556 len = get_queue_status(sharename, &status);
2558 if (pstatus)
2559 *pstatus = status;
2561 return len;
2564 /***************************************************************************
2565 Allocate a jobid. Hold the lock for as short a time as possible.
2566 ***************************************************************************/
2568 static WERROR allocate_print_jobid(struct tdb_print_db *pdb, int snum,
2569 const char *sharename, uint32_t *pjobid)
2571 int i;
2572 uint32_t jobid;
2573 enum TDB_ERROR terr;
2574 int ret;
2576 *pjobid = (uint32_t)-1;
2578 for (i = 0; i < 3; i++) {
2579 /* Lock the database - only wait 20 seconds. */
2580 ret = tdb_lock_bystring_with_timeout(pdb->tdb,
2581 "INFO/nextjob", 20);
2582 if (ret != 0) {
2583 DEBUG(0, ("allocate_print_jobid: "
2584 "Failed to lock printing database %s\n",
2585 sharename));
2586 terr = tdb_error(pdb->tdb);
2587 return ntstatus_to_werror(map_nt_error_from_tdb(terr));
2590 if (!tdb_fetch_uint32(pdb->tdb, "INFO/nextjob", &jobid)) {
2591 terr = tdb_error(pdb->tdb);
2592 if (terr != TDB_ERR_NOEXIST) {
2593 DEBUG(0, ("allocate_print_jobid: "
2594 "Failed to fetch INFO/nextjob "
2595 "for print queue %s\n", sharename));
2596 tdb_unlock_bystring(pdb->tdb, "INFO/nextjob");
2597 return ntstatus_to_werror(map_nt_error_from_tdb(terr));
2599 DEBUG(10, ("allocate_print_jobid: "
2600 "No existing jobid in %s\n", sharename));
2601 jobid = 0;
2604 DEBUG(10, ("allocate_print_jobid: "
2605 "Read jobid %u from %s\n", jobid, sharename));
2607 jobid = NEXT_JOBID(jobid);
2609 ret = tdb_store_int32(pdb->tdb, "INFO/nextjob", jobid);
2610 if (ret != 0) {
2611 terr = tdb_error(pdb->tdb);
2612 DEBUG(3, ("allocate_print_jobid: "
2613 "Failed to store INFO/nextjob.\n"));
2614 tdb_unlock_bystring(pdb->tdb, "INFO/nextjob");
2615 return ntstatus_to_werror(map_nt_error_from_tdb(terr));
2618 /* We've finished with the INFO/nextjob lock. */
2619 tdb_unlock_bystring(pdb->tdb, "INFO/nextjob");
2621 if (!print_job_exists(sharename, jobid)) {
2622 break;
2624 DEBUG(10, ("allocate_print_jobid: "
2625 "Found jobid %u in %s\n", jobid, sharename));
2628 if (i > 2) {
2629 DEBUG(0, ("allocate_print_jobid: "
2630 "Failed to allocate a print job for queue %s\n",
2631 sharename));
2632 /* Probably full... */
2633 return WERR_NO_SPOOL_SPACE;
2636 /* Store a dummy placeholder. */
2638 uint32_t tmp;
2639 TDB_DATA dum;
2640 dum.dptr = NULL;
2641 dum.dsize = 0;
2642 if (tdb_store(pdb->tdb, print_key(jobid, &tmp), dum,
2643 TDB_INSERT) != 0) {
2644 DEBUG(3, ("allocate_print_jobid: "
2645 "jobid (%d) failed to store placeholder.\n",
2646 jobid ));
2647 terr = tdb_error(pdb->tdb);
2648 return ntstatus_to_werror(map_nt_error_from_tdb(terr));
2652 *pjobid = jobid;
2653 return WERR_OK;
2656 /***************************************************************************
2657 Append a jobid to the 'jobs added' list.
2658 ***************************************************************************/
2660 static bool add_to_jobs_added(struct tdb_print_db *pdb, uint32_t jobid)
2662 TDB_DATA data;
2663 uint32_t store_jobid;
2665 SIVAL(&store_jobid, 0, jobid);
2666 data.dptr = (uint8_t *)&store_jobid;
2667 data.dsize = 4;
2669 DEBUG(10,("add_to_jobs_added: Added jobid %u\n", (unsigned int)jobid ));
2671 return (tdb_append(pdb->tdb, string_tdb_data("INFO/jobs_added"),
2672 data) == 0);
2676 /***************************************************************************
2677 Do all checks needed to determine if we can start a job.
2678 ***************************************************************************/
2680 static WERROR print_job_checks(const struct auth_session_info *server_info,
2681 struct messaging_context *msg_ctx,
2682 int snum, int *njobs)
2684 const char *sharename = lp_const_servicename(snum);
2685 uint64_t dspace, dsize;
2686 uint64_t minspace;
2687 int ret;
2689 if (!W_ERROR_IS_OK(print_access_check(server_info, msg_ctx, snum,
2690 PRINTER_ACCESS_USE))) {
2691 DEBUG(3, ("print_job_checks: "
2692 "job start denied by security descriptor\n"));
2693 return WERR_ACCESS_DENIED;
2696 if (!print_time_access_check(server_info, msg_ctx, sharename)) {
2697 DEBUG(3, ("print_job_checks: "
2698 "job start denied by time check\n"));
2699 return WERR_ACCESS_DENIED;
2702 /* see if we have sufficient disk space */
2703 if (lp_min_print_space(snum)) {
2704 minspace = lp_min_print_space(snum);
2705 ret = sys_fsusage(lp_path(talloc_tos(), snum), &dspace, &dsize);
2706 if (ret == 0 && dspace < 2*minspace) {
2707 DEBUG(3, ("print_job_checks: "
2708 "disk space check failed.\n"));
2709 return WERR_NO_SPOOL_SPACE;
2713 /* for autoloaded printers, check that the printcap entry still exists */
2714 if (lp_autoloaded(snum) && !pcap_printername_ok(sharename)) {
2715 DEBUG(3, ("print_job_checks: printer name %s check failed.\n",
2716 sharename));
2717 return WERR_ACCESS_DENIED;
2720 /* Insure the maximum queue size is not violated */
2721 *njobs = print_queue_length(msg_ctx, snum, NULL);
2722 if (*njobs > lp_maxprintjobs(snum)) {
2723 DEBUG(3, ("print_job_checks: Queue %s number of jobs (%d) "
2724 "larger than max printjobs per queue (%d).\n",
2725 sharename, *njobs, lp_maxprintjobs(snum)));
2726 return WERR_NO_SPOOL_SPACE;
2729 return WERR_OK;
2732 /***************************************************************************
2733 Create a job file.
2734 ***************************************************************************/
2736 static WERROR print_job_spool_file(int snum, uint32_t jobid,
2737 const char *output_file,
2738 struct printjob *pjob)
2740 WERROR werr;
2741 SMB_STRUCT_STAT st;
2742 const char *path;
2743 int len;
2744 mode_t mask;
2746 /* if this file is within the printer path, it means that smbd
2747 * is spooling it and will pass us control when it is finished.
2748 * Verify that the file name is ok, within path, and it is
2749 * already already there */
2750 if (output_file) {
2751 path = lp_path(talloc_tos(), snum);
2752 len = strlen(path);
2753 if (strncmp(output_file, path, len) == 0 &&
2754 (output_file[len - 1] == '/' || output_file[len] == '/')) {
2756 /* verify path is not too long */
2757 if (strlen(output_file) >= sizeof(pjob->filename)) {
2758 return WERR_INVALID_NAME;
2761 /* verify that the file exists */
2762 if (sys_stat(output_file, &st, false) != 0) {
2763 return WERR_INVALID_NAME;
2766 fstrcpy(pjob->filename, output_file);
2768 DEBUG(3, ("print_job_spool_file:"
2769 "External spooling activated\n"));
2771 /* we do not open the file until spooling is done */
2772 pjob->fd = -1;
2773 pjob->status = PJOB_SMBD_SPOOLING;
2775 return WERR_OK;
2779 slprintf(pjob->filename, sizeof(pjob->filename)-1,
2780 "%s/%sXXXXXX", lp_path(talloc_tos(), snum),
2781 PRINT_SPOOL_PREFIX);
2782 mask = umask(S_IRWXO | S_IRWXG);
2783 pjob->fd = mkstemp(pjob->filename);
2784 umask(mask);
2786 if (pjob->fd == -1) {
2787 werr = map_werror_from_unix(errno);
2788 if (W_ERROR_EQUAL(werr, WERR_ACCESS_DENIED)) {
2789 /* Common setup error, force a report. */
2790 DEBUG(0, ("print_job_spool_file: "
2791 "insufficient permissions to open spool "
2792 "file %s.\n", pjob->filename));
2793 } else {
2794 /* Normal case, report at level 3 and above. */
2795 DEBUG(3, ("print_job_spool_file: "
2796 "can't open spool file %s\n",
2797 pjob->filename));
2799 return werr;
2802 return WERR_OK;
2805 /***************************************************************************
2806 Start spooling a job - return the jobid.
2807 ***************************************************************************/
2809 WERROR print_job_start(const struct auth_session_info *server_info,
2810 struct messaging_context *msg_ctx,
2811 const char *clientmachine,
2812 int snum, const char *docname, const char *filename,
2813 struct spoolss_DeviceMode *devmode, uint32_t *_jobid)
2815 uint32_t jobid;
2816 char *path;
2817 struct printjob pjob;
2818 const char *sharename = lp_const_servicename(snum);
2819 struct tdb_print_db *pdb = get_print_db_byname(sharename);
2820 int njobs;
2821 WERROR werr;
2823 if (!pdb) {
2824 return WERR_INTERNAL_DB_CORRUPTION;
2827 path = lp_path(talloc_tos(), snum);
2829 werr = print_job_checks(server_info, msg_ctx, snum, &njobs);
2830 if (!W_ERROR_IS_OK(werr)) {
2831 release_print_db(pdb);
2832 return werr;
2835 DEBUG(10, ("print_job_start: "
2836 "Queue %s number of jobs (%d), max printjobs = %d\n",
2837 sharename, njobs, lp_maxprintjobs(snum)));
2839 werr = allocate_print_jobid(pdb, snum, sharename, &jobid);
2840 if (!W_ERROR_IS_OK(werr)) {
2841 goto fail;
2844 /* create the database entry */
2846 ZERO_STRUCT(pjob);
2848 pjob.pid = getpid();
2849 pjob.jobid = jobid;
2850 pjob.sysjob = -1;
2851 pjob.fd = -1;
2852 pjob.starttime = time(NULL);
2853 pjob.status = LPQ_SPOOLING;
2854 pjob.size = 0;
2855 pjob.spooled = False;
2856 pjob.smbjob = True;
2857 pjob.devmode = devmode;
2859 fstrcpy(pjob.jobname, docname);
2861 fstrcpy(pjob.clientmachine, clientmachine);
2863 fstrcpy(pjob.user, lp_printjob_username(snum));
2864 standard_sub_advanced(sharename, server_info->unix_info->sanitized_username,
2865 path, server_info->unix_token->gid,
2866 server_info->unix_info->sanitized_username,
2867 server_info->info->domain_name,
2868 pjob.user, sizeof(pjob.user));
2870 fstrcpy(pjob.queuename, lp_const_servicename(snum));
2872 /* we have a job entry - now create the spool file */
2873 werr = print_job_spool_file(snum, jobid, filename, &pjob);
2874 if (!W_ERROR_IS_OK(werr)) {
2875 goto fail;
2878 pjob_store(server_event_context(), msg_ctx, sharename, jobid, &pjob);
2880 /* Update the 'jobs added' entry used by print_queue_status. */
2881 add_to_jobs_added(pdb, jobid);
2883 /* Ensure we keep a rough count of the number of total jobs... */
2884 tdb_change_int32_atomic(pdb->tdb, "INFO/total_jobs", &njobs, 1);
2886 release_print_db(pdb);
2888 *_jobid = jobid;
2889 return WERR_OK;
2891 fail:
2892 if (jobid != -1) {
2893 pjob_delete(server_event_context(), msg_ctx, sharename, jobid);
2896 release_print_db(pdb);
2898 DEBUG(3, ("print_job_start: returning fail. "
2899 "Error = %s\n", win_errstr(werr)));
2900 return werr;
2903 /****************************************************************************
2904 Update the number of pages spooled to jobid
2905 ****************************************************************************/
2907 void print_job_endpage(struct messaging_context *msg_ctx,
2908 int snum, uint32_t jobid)
2910 const char* sharename = lp_const_servicename(snum);
2911 struct printjob *pjob;
2912 TALLOC_CTX *tmp_ctx = talloc_new(msg_ctx);
2913 if (tmp_ctx == NULL) {
2914 return;
2917 pjob = print_job_find(tmp_ctx, sharename, jobid);
2918 if (!pjob) {
2919 goto err_out;
2921 /* don't allow another process to get this info - it is meaningless */
2922 if (pjob->pid != getpid()) {
2923 goto err_out;
2926 pjob->page_count++;
2927 pjob_store(server_event_context(), msg_ctx, sharename, jobid, pjob);
2928 err_out:
2929 talloc_free(tmp_ctx);
2932 /****************************************************************************
2933 Print a file - called on closing the file. This spools the job.
2934 If normal close is false then we're tearing down the jobs - treat as an
2935 error.
2936 ****************************************************************************/
2938 NTSTATUS print_job_end(struct messaging_context *msg_ctx, int snum,
2939 uint32_t jobid, enum file_close_type close_type)
2941 const char* sharename = lp_const_servicename(snum);
2942 struct printjob *pjob;
2943 int ret;
2944 SMB_STRUCT_STAT sbuf;
2945 struct printif *current_printif = get_printer_fns(snum);
2946 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
2947 char *lpq_cmd;
2948 TALLOC_CTX *tmp_ctx = talloc_new(msg_ctx);
2949 if (tmp_ctx == NULL) {
2950 return NT_STATUS_NO_MEMORY;
2953 pjob = print_job_find(tmp_ctx, sharename, jobid);
2954 if (!pjob) {
2955 status = NT_STATUS_PRINT_CANCELLED;
2956 goto err_out;
2959 if (pjob->spooled || pjob->pid != getpid()) {
2960 status = NT_STATUS_ACCESS_DENIED;
2961 goto err_out;
2964 if (close_type == NORMAL_CLOSE || close_type == SHUTDOWN_CLOSE) {
2965 if (pjob->status == PJOB_SMBD_SPOOLING) {
2966 /* take over the file now, smbd is done */
2967 if (sys_stat(pjob->filename, &sbuf, false) != 0) {
2968 status = map_nt_error_from_unix(errno);
2969 DEBUG(3, ("print_job_end: "
2970 "stat file failed for jobid %d\n",
2971 jobid));
2972 goto fail;
2975 pjob->status = LPQ_SPOOLING;
2977 } else {
2979 if ((sys_fstat(pjob->fd, &sbuf, false) != 0)) {
2980 status = map_nt_error_from_unix(errno);
2981 close(pjob->fd);
2982 DEBUG(3, ("print_job_end: "
2983 "stat file failed for jobid %d\n",
2984 jobid));
2985 goto fail;
2988 close(pjob->fd);
2991 pjob->size = sbuf.st_ex_size;
2992 } else {
2995 * Not a normal close, something has gone wrong. Cleanup.
2997 if (pjob->fd != -1) {
2998 close(pjob->fd);
3000 goto fail;
3003 /* Technically, this is not quite right. If the printer has a separator
3004 * page turned on, the NT spooler prints the separator page even if the
3005 * print job is 0 bytes. 010215 JRR */
3006 if (pjob->size == 0 || pjob->status == LPQ_DELETING) {
3007 /* don't bother spooling empty files or something being deleted. */
3008 DEBUG(5,("print_job_end: canceling spool of %s (%s)\n",
3009 pjob->filename, pjob->size ? "deleted" : "zero length" ));
3010 unlink(pjob->filename);
3011 pjob_delete(server_event_context(), msg_ctx, sharename, jobid);
3012 return NT_STATUS_OK;
3015 /* don't strip out characters like '$' from the printername */
3016 lpq_cmd = talloc_string_sub2(tmp_ctx,
3017 lp_lpq_command(talloc_tos(), snum),
3018 "%p",
3019 lp_printername(talloc_tos(), snum),
3020 false, false, false);
3021 if (lpq_cmd == NULL) {
3022 status = NT_STATUS_PRINT_CANCELLED;
3023 goto fail;
3025 lpq_cmd = talloc_sub_advanced(tmp_ctx,
3026 lp_servicename(talloc_tos(), snum),
3027 current_user_info.unix_name,
3029 current_user.ut.gid,
3030 get_current_username(),
3031 current_user_info.domain,
3032 lpq_cmd);
3033 if (lpq_cmd == NULL) {
3034 status = NT_STATUS_PRINT_CANCELLED;
3035 goto fail;
3038 ret = (*(current_printif->job_submit))(snum, pjob,
3039 current_printif->type, lpq_cmd);
3040 if (ret) {
3041 status = NT_STATUS_PRINT_CANCELLED;
3042 goto fail;
3045 /* The print job has been successfully handed over to the back-end */
3047 pjob->spooled = True;
3048 pjob->status = LPQ_QUEUED;
3049 pjob_store(server_event_context(), msg_ctx, sharename, jobid, pjob);
3051 /* make sure the database is up to date */
3052 if (print_cache_expired(lp_const_servicename(snum), True))
3053 print_queue_update(msg_ctx, snum, False);
3055 return NT_STATUS_OK;
3057 fail:
3059 /* The print job was not successfully started. Cleanup */
3060 /* Still need to add proper error return propagation! 010122:JRR */
3061 pjob->fd = -1;
3062 unlink(pjob->filename);
3063 pjob_delete(server_event_context(), msg_ctx, sharename, jobid);
3064 err_out:
3065 talloc_free(tmp_ctx);
3066 return status;
3069 /****************************************************************************
3070 Get a snapshot of jobs in the system without traversing.
3071 ****************************************************************************/
3073 static bool get_stored_queue_info(struct messaging_context *msg_ctx,
3074 struct tdb_print_db *pdb, int snum,
3075 int *pcount, print_queue_struct **ppqueue)
3077 TDB_DATA data, cgdata, jcdata;
3078 print_queue_struct *queue = NULL;
3079 uint32_t qcount = 0;
3080 uint32_t extra_count = 0;
3081 uint32_t changed_count = 0;
3082 int total_count = 0;
3083 size_t len = 0;
3084 uint32_t i;
3085 int max_reported_jobs = lp_max_reported_print_jobs(snum);
3086 bool ret = false;
3087 const char* sharename = lp_servicename(talloc_tos(), snum);
3088 TALLOC_CTX *tmp_ctx = talloc_new(msg_ctx);
3089 if (tmp_ctx == NULL) {
3090 return false;
3093 /* make sure the database is up to date */
3094 if (print_cache_expired(lp_const_servicename(snum), True))
3095 print_queue_update(msg_ctx, snum, False);
3097 *pcount = 0;
3098 *ppqueue = NULL;
3100 ZERO_STRUCT(data);
3101 ZERO_STRUCT(cgdata);
3103 /* Get the stored queue data. */
3104 data = tdb_fetch(pdb->tdb, string_tdb_data("INFO/linear_queue_array"));
3106 if (data.dptr && data.dsize >= sizeof(qcount))
3107 len += tdb_unpack(data.dptr + len, data.dsize - len, "d", &qcount);
3109 /* Get the added jobs list. */
3110 cgdata = tdb_fetch(pdb->tdb, string_tdb_data("INFO/jobs_added"));
3111 if (cgdata.dptr != NULL && (cgdata.dsize % 4 == 0))
3112 extra_count = cgdata.dsize/4;
3114 /* Get the changed jobs list. */
3115 jcdata = tdb_fetch(pdb->tdb, string_tdb_data("INFO/jobs_changed"));
3116 if (jcdata.dptr != NULL && (jcdata.dsize % 4 == 0))
3117 changed_count = jcdata.dsize / 4;
3119 DEBUG(5,("get_stored_queue_info: qcount = %u, extra_count = %u\n", (unsigned int)qcount, (unsigned int)extra_count));
3121 /* Allocate the queue size. */
3122 if (qcount == 0 && extra_count == 0)
3123 goto out;
3125 if ((queue = SMB_MALLOC_ARRAY(print_queue_struct, qcount + extra_count)) == NULL)
3126 goto out;
3128 /* Retrieve the linearised queue data. */
3130 for(i = 0; i < qcount; i++) {
3131 uint32_t qjob, qsize, qpage_count, qstatus, qpriority, qtime;
3132 len += tdb_unpack(data.dptr + len, data.dsize - len, "ddddddff",
3133 &qjob,
3134 &qsize,
3135 &qpage_count,
3136 &qstatus,
3137 &qpriority,
3138 &qtime,
3139 queue[i].fs_user,
3140 queue[i].fs_file);
3141 queue[i].sysjob = qjob;
3142 queue[i].size = qsize;
3143 queue[i].page_count = qpage_count;
3144 queue[i].status = qstatus;
3145 queue[i].priority = qpriority;
3146 queue[i].time = qtime;
3149 total_count = qcount;
3151 /* Add new jobids to the queue. */
3152 for (i = 0; i < extra_count; i++) {
3153 uint32_t jobid;
3154 struct printjob *pjob;
3156 jobid = IVAL(cgdata.dptr, i*4);
3157 DEBUG(5,("get_stored_queue_info: added job = %u\n", (unsigned int)jobid));
3158 pjob = print_job_find(tmp_ctx, lp_const_servicename(snum), jobid);
3159 if (!pjob) {
3160 DEBUG(5,("get_stored_queue_info: failed to find added job = %u\n", (unsigned int)jobid));
3161 remove_from_jobs_added(sharename, jobid);
3162 continue;
3165 queue[total_count].sysjob = pjob->sysjob;
3166 queue[total_count].size = pjob->size;
3167 queue[total_count].page_count = pjob->page_count;
3168 queue[total_count].status = pjob->status;
3169 queue[total_count].priority = 1;
3170 queue[total_count].time = pjob->starttime;
3171 fstrcpy(queue[total_count].fs_user, pjob->user);
3172 fstrcpy(queue[total_count].fs_file, pjob->jobname);
3173 total_count++;
3174 talloc_free(pjob);
3177 /* Update the changed jobids. */
3178 for (i = 0; i < changed_count; i++) {
3179 uint32_t jobid = IVAL(jcdata.dptr, i * 4);
3180 struct printjob *pjob;
3181 uint32_t j;
3182 bool found = false;
3184 pjob = print_job_find(tmp_ctx, sharename, jobid);
3185 if (pjob == NULL) {
3186 DEBUG(5,("get_stored_queue_info: failed to find "
3187 "changed job = %u\n",
3188 (unsigned int)jobid));
3189 remove_from_jobs_changed(sharename, jobid);
3190 continue;
3193 for (j = 0; j < total_count; j++) {
3194 if (queue[j].sysjob == pjob->sysjob) {
3195 found = true;
3196 break;
3200 if (found) {
3201 DEBUG(5,("get_stored_queue_info: changed job: %u\n",
3202 (unsigned int)jobid));
3204 queue[j].sysjob = pjob->sysjob;
3205 queue[j].size = pjob->size;
3206 queue[j].page_count = pjob->page_count;
3207 queue[j].status = pjob->status;
3208 queue[j].priority = 1;
3209 queue[j].time = pjob->starttime;
3210 fstrcpy(queue[j].fs_user, pjob->user);
3211 fstrcpy(queue[j].fs_file, pjob->jobname);
3212 talloc_free(pjob);
3214 DEBUG(5,("updated queue[%u], jobid: %u, sysjob: %u, "
3215 "jobname: %s\n",
3216 (unsigned int)j, (unsigned int)jobid,
3217 (unsigned int)queue[j].sysjob, pjob->jobname));
3220 remove_from_jobs_changed(sharename, jobid);
3223 /* Sort the queue by submission time otherwise they are displayed
3224 in hash order. */
3226 TYPESAFE_QSORT(queue, total_count, printjob_comp);
3228 DEBUG(5,("get_stored_queue_info: total_count = %u\n", (unsigned int)total_count));
3230 if (max_reported_jobs && total_count > max_reported_jobs)
3231 total_count = max_reported_jobs;
3233 *ppqueue = queue;
3234 *pcount = total_count;
3236 ret = true;
3238 out:
3240 SAFE_FREE(data.dptr);
3241 SAFE_FREE(cgdata.dptr);
3242 talloc_free(tmp_ctx);
3243 return ret;
3246 /****************************************************************************
3247 Get a printer queue listing.
3248 set queue = NULL and status = NULL if you just want to update the cache
3249 ****************************************************************************/
3251 int print_queue_status(struct messaging_context *msg_ctx, int snum,
3252 print_queue_struct **ppqueue,
3253 print_status_struct *status)
3255 fstring keystr;
3256 TDB_DATA data, key;
3257 const char *sharename;
3258 struct tdb_print_db *pdb;
3259 int count = 0;
3261 /* make sure the database is up to date */
3263 if (print_cache_expired(lp_const_servicename(snum), True))
3264 print_queue_update(msg_ctx, snum, False);
3266 /* return if we are done */
3267 if ( !ppqueue || !status )
3268 return 0;
3270 *ppqueue = NULL;
3271 sharename = lp_const_servicename(snum);
3272 pdb = get_print_db_byname(sharename);
3274 if (!pdb)
3275 return 0;
3278 * Fetch the queue status. We must do this first, as there may
3279 * be no jobs in the queue.
3282 ZERO_STRUCTP(status);
3283 slprintf(keystr, sizeof(keystr)-1, "STATUS/%s", sharename);
3284 key = string_tdb_data(keystr);
3286 data = tdb_fetch(pdb->tdb, key);
3287 if (data.dptr) {
3288 if (data.dsize == sizeof(*status)) {
3289 /* this memcpy is ok since the status struct was
3290 not packed before storing it in the tdb */
3291 memcpy(status, data.dptr, sizeof(*status));
3293 SAFE_FREE(data.dptr);
3297 * Now, fetch the print queue information. We first count the number
3298 * of entries, and then only retrieve the queue if necessary.
3301 if (!get_stored_queue_info(msg_ctx, pdb, snum, &count, ppqueue)) {
3302 release_print_db(pdb);
3303 return 0;
3306 release_print_db(pdb);
3307 return count;
3310 /****************************************************************************
3311 Pause a queue.
3312 ****************************************************************************/
3314 WERROR print_queue_pause(const struct auth_session_info *server_info,
3315 struct messaging_context *msg_ctx, int snum)
3317 int ret;
3318 struct printif *current_printif = get_printer_fns( snum );
3320 if (!W_ERROR_IS_OK(print_access_check(server_info, msg_ctx, snum,
3321 PRINTER_ACCESS_ADMINISTER))) {
3322 return WERR_ACCESS_DENIED;
3326 become_root();
3328 ret = (*(current_printif->queue_pause))(snum);
3330 unbecome_root();
3332 if (ret != 0) {
3333 return WERR_INVALID_PARAMETER;
3336 /* force update the database */
3337 print_cache_flush(lp_const_servicename(snum));
3339 /* Send a printer notify message */
3341 notify_printer_status(server_event_context(), msg_ctx, snum,
3342 PRINTER_STATUS_PAUSED);
3344 return WERR_OK;
3347 /****************************************************************************
3348 Resume a queue.
3349 ****************************************************************************/
3351 WERROR print_queue_resume(const struct auth_session_info *server_info,
3352 struct messaging_context *msg_ctx, int snum)
3354 int ret;
3355 struct printif *current_printif = get_printer_fns( snum );
3357 if (!W_ERROR_IS_OK(print_access_check(server_info, msg_ctx, snum,
3358 PRINTER_ACCESS_ADMINISTER))) {
3359 return WERR_ACCESS_DENIED;
3362 become_root();
3364 ret = (*(current_printif->queue_resume))(snum);
3366 unbecome_root();
3368 if (ret != 0) {
3369 return WERR_INVALID_PARAMETER;
3372 /* make sure the database is up to date */
3373 if (print_cache_expired(lp_const_servicename(snum), True))
3374 print_queue_update(msg_ctx, snum, True);
3376 /* Send a printer notify message */
3378 notify_printer_status(server_event_context(), msg_ctx, snum,
3379 PRINTER_STATUS_OK);
3381 return WERR_OK;
3384 /****************************************************************************
3385 Purge a queue - implemented by deleting all jobs that we can delete.
3386 ****************************************************************************/
3388 WERROR print_queue_purge(const struct auth_session_info *server_info,
3389 struct messaging_context *msg_ctx, int snum)
3391 print_queue_struct *queue;
3392 print_status_struct status;
3393 int njobs, i;
3394 bool can_job_admin;
3396 /* Force and update so the count is accurate (i.e. not a cached count) */
3397 print_queue_update(msg_ctx, snum, True);
3399 can_job_admin = W_ERROR_IS_OK(print_access_check(server_info,
3400 msg_ctx,
3401 snum,
3402 JOB_ACCESS_ADMINISTER));
3403 njobs = print_queue_status(msg_ctx, snum, &queue, &status);
3405 if ( can_job_admin )
3406 become_root();
3408 for (i = 0; i < njobs; i++) {
3409 struct tdb_print_db *pdb;
3410 int jobid;
3411 bool owner;
3412 pdb = get_print_db_byname(lp_const_servicename(snum));
3413 if (pdb == NULL) {
3414 DEBUG(1, ("failed to find printdb for %s\n",
3415 lp_const_servicename(snum)));
3416 continue;
3418 jobid = sysjob_to_jobid_pdb(pdb, queue[i].sysjob);
3419 if (jobid == (uint32_t)-1) {
3420 DEBUG(2, ("jobid for system job %d not found\n",
3421 queue[i].sysjob));
3422 continue; /* unix job */
3424 owner = is_owner(server_info, lp_const_servicename(snum),
3425 jobid);
3427 if (owner || can_job_admin) {
3428 print_job_delete1(server_event_context(), msg_ctx,
3429 snum, jobid);
3433 if ( can_job_admin )
3434 unbecome_root();
3436 /* update the cache */
3437 print_queue_update(msg_ctx, snum, True);
3439 SAFE_FREE(queue);
3441 return WERR_OK;