VERSION: Bump version up to 4.0.25.
[Samba.git] / source3 / printing / printing.c
blob2b07e8865190dc387ac6702a1e0f9af6d6958a9c
1 /*
2 Unix SMB/Netbios implementation.
3 Version 3.0
4 printing backend routines
5 Copyright (C) Andrew Tridgell 1992-2000
6 Copyright (C) Jeremy Allison 2002
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include "includes.h"
23 #include "system/syslog.h"
24 #include "system/filesys.h"
25 #include "printing.h"
26 #include "../librpc/gen_ndr/ndr_spoolss.h"
27 #include "nt_printing.h"
28 #include "../librpc/gen_ndr/netlogon.h"
29 #include "printing/notify.h"
30 #include "printing/pcap.h"
31 #include "printing/printer_list.h"
32 #include "printing/queue_process.h"
33 #include "serverid.h"
34 #include "smbd/smbd.h"
35 #include "auth.h"
36 #include "messages.h"
37 #include "util_tdb.h"
38 #include "lib/param/loadparm.h"
40 extern struct current_user current_user;
41 extern userdom_struct current_user_info;
43 /* Current printer interface */
44 static bool remove_from_jobs_added(const char* sharename, uint32 jobid);
47 the printing backend revolves around a tdb database that stores the
48 SMB view of the print queue
50 The key for this database is a jobid - a internally generated number that
51 uniquely identifies a print job
53 reading the print queue involves two steps:
54 - possibly running lpq and updating the internal database from that
55 - reading entries from the database
57 jobids are assigned when a job starts spooling.
60 static TDB_CONTEXT *rap_tdb;
61 static uint16 next_rap_jobid;
62 struct rap_jobid_key {
63 fstring sharename;
64 uint32 jobid;
67 /***************************************************************************
68 Nightmare. LANMAN jobid's are 16 bit numbers..... We must map them to 32
69 bit RPC jobids.... JRA.
70 ***************************************************************************/
72 uint16 pjobid_to_rap(const char* sharename, uint32 jobid)
74 uint16 rap_jobid;
75 TDB_DATA data, key;
76 struct rap_jobid_key jinfo;
77 uint8 buf[2];
79 DEBUG(10,("pjobid_to_rap: called.\n"));
81 if (!rap_tdb) {
82 /* Create the in-memory tdb. */
83 rap_tdb = tdb_open_log(NULL, 0, TDB_INTERNAL, (O_RDWR|O_CREAT), 0644);
84 if (!rap_tdb)
85 return 0;
88 ZERO_STRUCT( jinfo );
89 fstrcpy( jinfo.sharename, sharename );
90 jinfo.jobid = jobid;
91 key.dptr = (uint8 *)&jinfo;
92 key.dsize = sizeof(jinfo);
94 data = tdb_fetch_compat(rap_tdb, key);
95 if (data.dptr && data.dsize == sizeof(uint16)) {
96 rap_jobid = SVAL(data.dptr, 0);
97 SAFE_FREE(data.dptr);
98 DEBUG(10,("pjobid_to_rap: jobid %u maps to RAP jobid %u\n",
99 (unsigned int)jobid, (unsigned int)rap_jobid));
100 return rap_jobid;
102 SAFE_FREE(data.dptr);
103 /* Not found - create and store mapping. */
104 rap_jobid = ++next_rap_jobid;
105 if (rap_jobid == 0)
106 rap_jobid = ++next_rap_jobid;
107 SSVAL(buf,0,rap_jobid);
108 data.dptr = buf;
109 data.dsize = sizeof(rap_jobid);
110 tdb_store(rap_tdb, key, data, TDB_REPLACE);
111 tdb_store(rap_tdb, data, key, TDB_REPLACE);
113 DEBUG(10,("pjobid_to_rap: created jobid %u maps to RAP jobid %u\n",
114 (unsigned int)jobid, (unsigned int)rap_jobid));
115 return rap_jobid;
118 bool rap_to_pjobid(uint16 rap_jobid, fstring sharename, uint32 *pjobid)
120 TDB_DATA data, key;
121 uint8 buf[2];
123 DEBUG(10,("rap_to_pjobid called.\n"));
125 if (!rap_tdb)
126 return False;
128 SSVAL(buf,0,rap_jobid);
129 key.dptr = buf;
130 key.dsize = sizeof(rap_jobid);
131 data = tdb_fetch_compat(rap_tdb, key);
132 if ( data.dptr && data.dsize == sizeof(struct rap_jobid_key) )
134 struct rap_jobid_key *jinfo = (struct rap_jobid_key*)data.dptr;
135 if (sharename != NULL) {
136 fstrcpy( sharename, jinfo->sharename );
138 *pjobid = jinfo->jobid;
139 DEBUG(10,("rap_to_pjobid: jobid %u maps to RAP jobid %u\n",
140 (unsigned int)*pjobid, (unsigned int)rap_jobid));
141 SAFE_FREE(data.dptr);
142 return True;
145 DEBUG(10,("rap_to_pjobid: Failed to lookup RAP jobid %u\n",
146 (unsigned int)rap_jobid));
147 SAFE_FREE(data.dptr);
148 return False;
151 void rap_jobid_delete(const char* sharename, uint32 jobid)
153 TDB_DATA key, data;
154 uint16 rap_jobid;
155 struct rap_jobid_key jinfo;
156 uint8 buf[2];
158 DEBUG(10,("rap_jobid_delete: called.\n"));
160 if (!rap_tdb)
161 return;
163 ZERO_STRUCT( jinfo );
164 fstrcpy( jinfo.sharename, sharename );
165 jinfo.jobid = jobid;
166 key.dptr = (uint8 *)&jinfo;
167 key.dsize = sizeof(jinfo);
169 data = tdb_fetch_compat(rap_tdb, key);
170 if (!data.dptr || (data.dsize != sizeof(uint16))) {
171 DEBUG(10,("rap_jobid_delete: cannot find jobid %u\n",
172 (unsigned int)jobid ));
173 SAFE_FREE(data.dptr);
174 return;
177 DEBUG(10,("rap_jobid_delete: deleting jobid %u\n",
178 (unsigned int)jobid ));
180 rap_jobid = SVAL(data.dptr, 0);
181 SAFE_FREE(data.dptr);
182 SSVAL(buf,0,rap_jobid);
183 data.dptr = buf;
184 data.dsize = sizeof(rap_jobid);
185 tdb_delete(rap_tdb, key);
186 tdb_delete(rap_tdb, data);
189 static int get_queue_status(const char* sharename, print_status_struct *);
191 /****************************************************************************
192 Initialise the printing backend. Called once at startup before the fork().
193 ****************************************************************************/
195 bool print_backend_init(struct messaging_context *msg_ctx)
197 const char *sversion = "INFO/version";
198 int services = lp_numservices();
199 int snum;
201 if (!printer_list_parent_init()) {
202 return false;
205 unlink(cache_path("printing.tdb"));
206 mkdir(cache_path("printing"),0755);
208 /* handle a Samba upgrade */
210 for (snum = 0; snum < services; snum++) {
211 struct tdb_print_db *pdb;
212 if (!lp_print_ok(snum))
213 continue;
215 pdb = get_print_db_byname(lp_const_servicename(snum));
216 if (!pdb)
217 continue;
218 if (tdb_lock_bystring(pdb->tdb, sversion) != 0) {
219 DEBUG(0,("print_backend_init: Failed to open printer %s database\n", lp_const_servicename(snum) ));
220 release_print_db(pdb);
221 return False;
223 if (tdb_fetch_int32(pdb->tdb, sversion) != PRINT_DATABASE_VERSION) {
224 tdb_wipe_all(pdb->tdb);
225 tdb_store_int32(pdb->tdb, sversion, PRINT_DATABASE_VERSION);
227 tdb_unlock_bystring(pdb->tdb, sversion);
228 release_print_db(pdb);
231 close_all_print_db(); /* Don't leave any open. */
233 /* do NT print initialization... */
234 return nt_printing_init(msg_ctx);
237 /****************************************************************************
238 Shut down printing backend. Called once at shutdown to close the tdb.
239 ****************************************************************************/
241 void printing_end(void)
243 close_all_print_db(); /* Don't leave any open. */
246 /****************************************************************************
247 Retrieve the set of printing functions for a given service. This allows
248 us to set the printer function table based on the value of the 'printing'
249 service parameter.
251 Use the generic interface as the default and only use cups interface only
252 when asked for (and only when supported)
253 ****************************************************************************/
255 static struct printif *get_printer_fns_from_type( enum printing_types type )
257 struct printif *printer_fns = &generic_printif;
259 #ifdef HAVE_CUPS
260 if ( type == PRINT_CUPS ) {
261 printer_fns = &cups_printif;
263 #endif /* HAVE_CUPS */
265 #ifdef HAVE_IPRINT
266 if ( type == PRINT_IPRINT ) {
267 printer_fns = &iprint_printif;
269 #endif /* HAVE_IPRINT */
271 printer_fns->type = type;
273 return printer_fns;
276 static struct printif *get_printer_fns( int snum )
278 return get_printer_fns_from_type( (enum printing_types)lp_printing(snum) );
282 /****************************************************************************
283 Useful function to generate a tdb key.
284 ****************************************************************************/
286 static TDB_DATA print_key(uint32 jobid, uint32 *tmp)
288 TDB_DATA ret;
290 SIVAL(tmp, 0, jobid);
291 ret.dptr = (uint8 *)tmp;
292 ret.dsize = sizeof(*tmp);
293 return ret;
296 /****************************************************************************
297 Pack the devicemode to store it in a tdb.
298 ****************************************************************************/
299 static int pack_devicemode(struct spoolss_DeviceMode *devmode, uint8 *buf, int buflen)
301 enum ndr_err_code ndr_err;
302 DATA_BLOB blob;
303 int len = 0;
305 if (devmode) {
306 ndr_err = ndr_push_struct_blob(&blob, talloc_tos(),
307 devmode,
308 (ndr_push_flags_fn_t)
309 ndr_push_spoolss_DeviceMode);
310 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
311 DEBUG(10, ("pack_devicemode: "
312 "error encoding spoolss_DeviceMode\n"));
313 goto done;
315 } else {
316 ZERO_STRUCT(blob);
319 len = tdb_pack(buf, buflen, "B", blob.length, blob.data);
321 if (devmode) {
322 DEBUG(8, ("Packed devicemode [%s]\n", devmode->formname));
325 done:
326 return len;
329 /****************************************************************************
330 Unpack the devicemode to store it in a tdb.
331 ****************************************************************************/
332 static int unpack_devicemode(TALLOC_CTX *mem_ctx,
333 const uint8 *buf, int buflen,
334 struct spoolss_DeviceMode **devmode)
336 struct spoolss_DeviceMode *dm;
337 enum ndr_err_code ndr_err;
338 char *data = NULL;
339 int data_len = 0;
340 DATA_BLOB blob;
341 int len = 0;
343 *devmode = NULL;
345 len = tdb_unpack(buf, buflen, "B", &data_len, &data);
346 if (!data) {
347 return len;
350 dm = talloc_zero(mem_ctx, struct spoolss_DeviceMode);
351 if (!dm) {
352 goto done;
355 blob = data_blob_const(data, data_len);
357 ndr_err = ndr_pull_struct_blob(&blob, dm, dm,
358 (ndr_pull_flags_fn_t)ndr_pull_spoolss_DeviceMode);
359 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
360 DEBUG(10, ("unpack_devicemode: "
361 "error parsing spoolss_DeviceMode\n"));
362 goto done;
365 DEBUG(8, ("Unpacked devicemode [%s](%s)\n",
366 dm->devicename, dm->formname));
367 if (dm->driverextra_data.data) {
368 DEBUG(8, ("with a private section of %d bytes\n",
369 dm->__driverextra_length));
372 *devmode = dm;
374 done:
375 SAFE_FREE(data);
376 return len;
379 /***********************************************************************
380 unpack a pjob from a tdb buffer
381 ***********************************************************************/
383 static int unpack_pjob(TALLOC_CTX *mem_ctx, uint8 *buf, int buflen,
384 struct printjob *pjob)
386 int len = 0;
387 int used;
388 uint32 pjpid, pjjobid, pjsysjob, pjfd, pjstarttime, pjstatus;
389 uint32 pjsize, pjpage_count, pjspooled, pjsmbjob;
391 if (!buf || !pjob) {
392 return -1;
395 len += tdb_unpack(buf+len, buflen-len, "ddddddddddfffff",
396 &pjpid,
397 &pjjobid,
398 &pjsysjob,
399 &pjfd,
400 &pjstarttime,
401 &pjstatus,
402 &pjsize,
403 &pjpage_count,
404 &pjspooled,
405 &pjsmbjob,
406 pjob->filename,
407 pjob->jobname,
408 pjob->user,
409 pjob->clientmachine,
410 pjob->queuename);
412 if (len == -1) {
413 return -1;
416 used = unpack_devicemode(mem_ctx, buf+len, buflen-len, &pjob->devmode);
417 if (used == -1) {
418 return -1;
421 len += used;
423 pjob->pid = pjpid;
424 pjob->jobid = pjjobid;
425 pjob->sysjob = pjsysjob;
426 pjob->fd = pjfd;
427 pjob->starttime = pjstarttime;
428 pjob->status = pjstatus;
429 pjob->size = pjsize;
430 pjob->page_count = pjpage_count;
431 pjob->spooled = pjspooled;
432 pjob->smbjob = pjsmbjob;
434 return len;
438 /****************************************************************************
439 Useful function to find a print job in the database.
440 ****************************************************************************/
442 static struct printjob *print_job_find(TALLOC_CTX *mem_ctx,
443 const char *sharename,
444 uint32 jobid)
446 struct printjob *pjob;
447 uint32_t tmp;
448 TDB_DATA ret;
449 struct tdb_print_db *pdb = get_print_db_byname(sharename);
451 DEBUG(10,("print_job_find: looking up job %u for share %s\n",
452 (unsigned int)jobid, sharename ));
454 if (!pdb) {
455 return NULL;
458 ret = tdb_fetch_compat(pdb->tdb, print_key(jobid, &tmp));
459 release_print_db(pdb);
461 if (!ret.dptr) {
462 DEBUG(10, ("print_job_find: failed to find jobid %u.\n",
463 jobid));
464 return NULL;
467 pjob = talloc_zero(mem_ctx, struct printjob);
468 if (pjob == NULL) {
469 goto err_out;
472 if (unpack_pjob(mem_ctx, ret.dptr, ret.dsize, pjob) == -1) {
473 DEBUG(10, ("failed to unpack jobid %u.\n", jobid));
474 talloc_free(pjob);
475 pjob = NULL;
476 goto err_out;
479 DEBUG(10,("print_job_find: returning system job %d for jobid %u.\n",
480 pjob->sysjob, jobid));
481 SMB_ASSERT(pjob->jobid == jobid);
483 err_out:
484 SAFE_FREE(ret.dptr);
485 return pjob;
488 struct job_traverse_state {
489 int sysjob;
490 uint32_t jobid;
493 /* find spoolss jobid based on sysjob */
494 static int sysjob_to_jobid_traverse_fn(TDB_CONTEXT *the_tdb, TDB_DATA key,
495 TDB_DATA data, void *private_data)
497 struct printjob *pjob;
498 struct job_traverse_state *state =
499 (struct job_traverse_state *)private_data;
501 if (!data.dptr || data.dsize == 0)
502 return 0;
504 pjob = (struct printjob *)data.dptr;
505 if (key.dsize != sizeof(uint32))
506 return 0;
508 if (state->sysjob == pjob->sysjob) {
509 state->jobid = pjob->jobid;
510 return 1;
513 return 0;
516 uint32 sysjob_to_jobid_pdb(struct tdb_print_db *pdb, int sysjob)
518 struct job_traverse_state state;
520 state.sysjob = sysjob;
521 state.jobid = (uint32_t)-1;
523 tdb_traverse(pdb->tdb, sysjob_to_jobid_traverse_fn, &state);
525 return state.jobid;
528 /****************************************************************************
529 This is a *horribly expensive call as we have to iterate through all the
530 current printer tdb's. Don't do this often ! JRA.
531 ****************************************************************************/
533 uint32 sysjob_to_jobid(int unix_jobid)
535 int services = lp_numservices();
536 int snum;
537 struct job_traverse_state state;
539 state.sysjob = unix_jobid;
540 state.jobid = (uint32_t)-1;
542 for (snum = 0; snum < services; snum++) {
543 struct tdb_print_db *pdb;
544 if (!lp_print_ok(snum))
545 continue;
546 pdb = get_print_db_byname(lp_const_servicename(snum));
547 if (!pdb) {
548 continue;
550 tdb_traverse(pdb->tdb, sysjob_to_jobid_traverse_fn, &state);
551 release_print_db(pdb);
552 if (state.jobid != (uint32_t)-1)
553 return state.jobid;
555 return (uint32)-1;
558 /* find sysjob based on spoolss jobid */
559 static int jobid_to_sysjob_traverse_fn(TDB_CONTEXT *the_tdb, TDB_DATA key,
560 TDB_DATA data, void *private_data)
562 struct printjob *pjob;
563 struct job_traverse_state *state =
564 (struct job_traverse_state *)private_data;
566 if (!data.dptr || data.dsize == 0)
567 return 0;
569 pjob = (struct printjob *)data.dptr;
570 if (key.dsize != sizeof(uint32_t))
571 return 0;
573 if (state->jobid == pjob->jobid) {
574 state->sysjob = pjob->sysjob;
575 return 1;
578 return 0;
581 int jobid_to_sysjob_pdb(struct tdb_print_db *pdb, uint32_t jobid)
583 struct job_traverse_state state;
585 state.sysjob = -1;
586 state.jobid = jobid;
588 tdb_traverse(pdb->tdb, jobid_to_sysjob_traverse_fn, &state);
590 return state.sysjob;
593 /****************************************************************************
594 Send notifications based on what has changed after a pjob_store.
595 ****************************************************************************/
597 static const struct {
598 uint32_t lpq_status;
599 uint32_t spoolss_status;
600 } lpq_to_spoolss_status_map[] = {
601 { LPQ_QUEUED, JOB_STATUS_QUEUED },
602 { LPQ_PAUSED, JOB_STATUS_PAUSED },
603 { LPQ_SPOOLING, JOB_STATUS_SPOOLING },
604 { LPQ_PRINTING, JOB_STATUS_PRINTING },
605 { LPQ_DELETING, JOB_STATUS_DELETING },
606 { LPQ_OFFLINE, JOB_STATUS_OFFLINE },
607 { LPQ_PAPEROUT, JOB_STATUS_PAPEROUT },
608 { LPQ_PRINTED, JOB_STATUS_PRINTED },
609 { LPQ_DELETED, JOB_STATUS_DELETED },
610 { LPQ_BLOCKED, JOB_STATUS_BLOCKED_DEVQ },
611 { LPQ_USER_INTERVENTION, JOB_STATUS_USER_INTERVENTION },
612 { (uint32_t)-1, 0 }
615 /* Convert a lpq status value stored in printing.tdb into the
616 appropriate win32 API constant. */
618 static uint32 map_to_spoolss_status(uint32 lpq_status)
620 int i = 0;
622 while (lpq_to_spoolss_status_map[i].lpq_status != -1) {
623 if (lpq_to_spoolss_status_map[i].lpq_status == lpq_status)
624 return lpq_to_spoolss_status_map[i].spoolss_status;
625 i++;
628 return 0;
631 /***************************************************************************
632 Append a jobid to the 'jobs changed' list.
633 ***************************************************************************/
635 static bool add_to_jobs_changed(struct tdb_print_db *pdb, uint32_t jobid)
637 TDB_DATA data;
638 uint32_t store_jobid;
640 SIVAL(&store_jobid, 0, jobid);
641 data.dptr = (uint8 *) &store_jobid;
642 data.dsize = 4;
644 DEBUG(10,("add_to_jobs_added: Added jobid %u\n", (unsigned int)jobid ));
646 return (tdb_append(pdb->tdb, string_tdb_data("INFO/jobs_changed"),
647 data) == 0);
650 /***************************************************************************
651 Remove a jobid from the 'jobs changed' list.
652 ***************************************************************************/
654 static bool remove_from_jobs_changed(const char* sharename, uint32_t jobid)
656 struct tdb_print_db *pdb = get_print_db_byname(sharename);
657 TDB_DATA data, key;
658 size_t job_count, i;
659 bool ret = False;
660 bool gotlock = False;
662 if (!pdb) {
663 return False;
666 ZERO_STRUCT(data);
668 key = string_tdb_data("INFO/jobs_changed");
670 if (tdb_chainlock_with_timeout(pdb->tdb, key, 5) != 0)
671 goto out;
673 gotlock = True;
675 data = tdb_fetch_compat(pdb->tdb, key);
677 if (data.dptr == NULL || data.dsize == 0 || (data.dsize % 4 != 0))
678 goto out;
680 job_count = data.dsize / 4;
681 for (i = 0; i < job_count; i++) {
682 uint32 ch_jobid;
684 ch_jobid = IVAL(data.dptr, i*4);
685 if (ch_jobid == jobid) {
686 if (i < job_count -1 )
687 memmove(data.dptr + (i*4), data.dptr + (i*4) + 4, (job_count - i - 1)*4 );
688 data.dsize -= 4;
689 if (tdb_store(pdb->tdb, key, data, TDB_REPLACE) != 0)
690 goto out;
691 break;
695 ret = True;
696 out:
698 if (gotlock)
699 tdb_chainunlock(pdb->tdb, key);
700 SAFE_FREE(data.dptr);
701 release_print_db(pdb);
702 if (ret)
703 DEBUG(10,("remove_from_jobs_changed: removed jobid %u\n", (unsigned int)jobid ));
704 else
705 DEBUG(10,("remove_from_jobs_changed: Failed to remove jobid %u\n", (unsigned int)jobid ));
706 return ret;
709 static void pjob_store_notify(struct tevent_context *ev,
710 struct messaging_context *msg_ctx,
711 const char* sharename, uint32 jobid,
712 struct printjob *old_data,
713 struct printjob *new_data,
714 bool *pchanged)
716 bool new_job = false;
717 bool changed = false;
719 if (old_data == NULL) {
720 new_job = true;
723 /* ACHTUNG! Due to a bug in Samba's spoolss parsing of the
724 NOTIFY_INFO_DATA buffer, we *have* to send the job submission
725 time first or else we'll end up with potential alignment
726 errors. I don't think the systemtime should be spooled as
727 a string, but this gets us around that error.
728 --jerry (i'll feel dirty for this) */
730 if (new_job) {
731 notify_job_submitted(ev, msg_ctx,
732 sharename, jobid, new_data->starttime);
733 notify_job_username(ev, msg_ctx,
734 sharename, jobid, new_data->user);
735 notify_job_name(ev, msg_ctx,
736 sharename, jobid, new_data->jobname);
737 notify_job_status(ev, msg_ctx,
738 sharename, jobid, map_to_spoolss_status(new_data->status));
739 notify_job_total_bytes(ev, msg_ctx,
740 sharename, jobid, new_data->size);
741 notify_job_total_pages(ev, msg_ctx,
742 sharename, jobid, new_data->page_count);
743 } else {
744 if (!strequal(old_data->jobname, new_data->jobname)) {
745 notify_job_name(ev, msg_ctx, sharename,
746 jobid, new_data->jobname);
747 changed = true;
750 if (old_data->status != new_data->status) {
751 notify_job_status(ev, msg_ctx,
752 sharename, jobid,
753 map_to_spoolss_status(new_data->status));
756 if (old_data->size != new_data->size) {
757 notify_job_total_bytes(ev, msg_ctx,
758 sharename, jobid, new_data->size);
761 if (old_data->page_count != new_data->page_count) {
762 notify_job_total_pages(ev, msg_ctx,
763 sharename, jobid,
764 new_data->page_count);
768 *pchanged = changed;
771 /****************************************************************************
772 Store a job structure back to the database.
773 ****************************************************************************/
775 static bool pjob_store(struct tevent_context *ev,
776 struct messaging_context *msg_ctx,
777 const char* sharename, uint32 jobid,
778 struct printjob *pjob)
780 uint32_t tmp;
781 TDB_DATA old_data, new_data;
782 bool ret = False;
783 struct tdb_print_db *pdb = get_print_db_byname(sharename);
784 uint8 *buf = NULL;
785 int len, newlen, buflen;
788 if (!pdb)
789 return False;
791 /* Get old data */
793 old_data = tdb_fetch_compat(pdb->tdb, print_key(jobid, &tmp));
795 /* Doh! Now we have to pack/unpack data since the NT_DEVICEMODE was added */
797 newlen = 0;
799 do {
800 len = 0;
801 buflen = newlen;
802 len += tdb_pack(buf+len, buflen-len, "ddddddddddfffff",
803 (uint32)pjob->pid,
804 (uint32)pjob->jobid,
805 (uint32)pjob->sysjob,
806 (uint32)pjob->fd,
807 (uint32)pjob->starttime,
808 (uint32)pjob->status,
809 (uint32)pjob->size,
810 (uint32)pjob->page_count,
811 (uint32)pjob->spooled,
812 (uint32)pjob->smbjob,
813 pjob->filename,
814 pjob->jobname,
815 pjob->user,
816 pjob->clientmachine,
817 pjob->queuename);
819 len += pack_devicemode(pjob->devmode, buf+len, buflen-len);
821 if (buflen != len) {
822 buf = (uint8 *)SMB_REALLOC(buf, len);
823 if (!buf) {
824 DEBUG(0,("pjob_store: failed to enlarge buffer!\n"));
825 goto done;
827 newlen = len;
829 } while ( buflen != len );
832 /* Store new data */
834 new_data.dptr = buf;
835 new_data.dsize = len;
836 ret = (tdb_store(pdb->tdb, print_key(jobid, &tmp), new_data,
837 TDB_REPLACE) == 0);
839 /* Send notify updates for what has changed */
841 if (ret) {
842 bool changed = false;
843 struct printjob old_pjob;
845 if (old_data.dsize) {
846 TALLOC_CTX *tmp_ctx = talloc_new(ev);
847 if (tmp_ctx == NULL)
848 goto done;
850 len = unpack_pjob(tmp_ctx, old_data.dptr,
851 old_data.dsize, &old_pjob);
852 if (len != -1 ) {
853 pjob_store_notify(ev,
854 msg_ctx,
855 sharename, jobid, &old_pjob,
856 pjob,
857 &changed);
858 if (changed) {
859 add_to_jobs_changed(pdb, jobid);
862 talloc_free(tmp_ctx);
864 } else {
865 /* new job */
866 pjob_store_notify(ev, msg_ctx,
867 sharename, jobid, NULL, pjob,
868 &changed);
872 done:
873 release_print_db(pdb);
874 SAFE_FREE( old_data.dptr );
875 SAFE_FREE( buf );
877 return ret;
880 /****************************************************************************
881 Remove a job structure from the database.
882 ****************************************************************************/
884 static void pjob_delete(struct tevent_context *ev,
885 struct messaging_context *msg_ctx,
886 const char* sharename, uint32 jobid)
888 uint32_t tmp;
889 struct printjob *pjob;
890 uint32 job_status = 0;
891 struct tdb_print_db *pdb;
892 TALLOC_CTX *tmp_ctx = talloc_new(ev);
893 if (tmp_ctx == NULL) {
894 return;
897 pdb = get_print_db_byname(sharename);
898 if (!pdb) {
899 goto err_out;
902 pjob = print_job_find(tmp_ctx, sharename, jobid);
903 if (!pjob) {
904 DEBUG(5, ("we were asked to delete nonexistent job %u\n",
905 jobid));
906 goto err_release;
909 /* We must cycle through JOB_STATUS_DELETING and
910 JOB_STATUS_DELETED for the port monitor to delete the job
911 properly. */
913 job_status = JOB_STATUS_DELETING|JOB_STATUS_DELETED;
914 notify_job_status(ev, msg_ctx, sharename, jobid, job_status);
916 /* Remove from printing.tdb */
918 tdb_delete(pdb->tdb, print_key(jobid, &tmp));
919 remove_from_jobs_added(sharename, jobid);
920 rap_jobid_delete(sharename, jobid);
921 err_release:
922 release_print_db(pdb);
923 err_out:
924 talloc_free(tmp_ctx);
927 /****************************************************************************
928 List a unix job in the print database.
929 ****************************************************************************/
931 static void print_unix_job(struct tevent_context *ev,
932 struct messaging_context *msg_ctx,
933 const char *sharename, print_queue_struct *q,
934 uint32 jobid)
936 struct printjob pj, *old_pj;
937 TALLOC_CTX *tmp_ctx = talloc_new(ev);
938 if (tmp_ctx == NULL) {
939 return;
942 if (jobid == (uint32)-1) {
943 jobid = q->sysjob + UNIX_JOB_START;
946 /* Preserve the timestamp on an existing unix print job */
948 old_pj = print_job_find(tmp_ctx, sharename, jobid);
950 ZERO_STRUCT(pj);
952 pj.pid = (pid_t)-1;
953 pj.jobid = jobid;
954 pj.sysjob = q->sysjob;
955 pj.fd = -1;
956 pj.starttime = old_pj ? old_pj->starttime : q->time;
957 pj.status = q->status;
958 pj.size = q->size;
959 pj.spooled = True;
960 fstrcpy(pj.filename, old_pj ? old_pj->filename : "");
961 if (jobid < UNIX_JOB_START) {
962 pj.smbjob = True;
963 fstrcpy(pj.jobname, old_pj ? old_pj->jobname : "Remote Downlevel Document");
964 } else {
965 pj.smbjob = False;
966 fstrcpy(pj.jobname, old_pj ? old_pj->jobname : q->fs_file);
968 fstrcpy(pj.user, old_pj ? old_pj->user : q->fs_user);
969 fstrcpy(pj.queuename, old_pj ? old_pj->queuename : sharename );
971 pjob_store(ev, msg_ctx, sharename, jobid, &pj);
972 talloc_free(tmp_ctx);
976 struct traverse_struct {
977 print_queue_struct *queue;
978 int qcount, snum, maxcount, total_jobs;
979 const char *sharename;
980 time_t lpq_time;
981 const char *lprm_command;
982 struct printif *print_if;
983 struct tevent_context *ev;
984 struct messaging_context *msg_ctx;
985 TALLOC_CTX *mem_ctx;
988 /****************************************************************************
989 Utility fn to delete any jobs that are no longer active.
990 ****************************************************************************/
992 static int traverse_fn_delete(TDB_CONTEXT *t, TDB_DATA key, TDB_DATA data, void *state)
994 struct traverse_struct *ts = (struct traverse_struct *)state;
995 struct printjob pjob;
996 uint32 jobid;
997 int i = 0;
999 if ( key.dsize != sizeof(jobid) )
1000 return 0;
1002 if (unpack_pjob(ts->mem_ctx, data.dptr, data.dsize, &pjob) == -1)
1003 return 0;
1004 talloc_free(pjob.devmode);
1005 jobid = pjob.jobid;
1007 if (!pjob.smbjob) {
1008 /* remove a unix job if it isn't in the system queue any more */
1009 for (i=0;i<ts->qcount;i++) {
1010 if (ts->queue[i].sysjob == pjob.sysjob) {
1011 break;
1014 if (i == ts->qcount) {
1015 DEBUG(10,("traverse_fn_delete: pjob %u deleted due to !smbjob\n",
1016 (unsigned int)jobid ));
1017 pjob_delete(ts->ev, ts->msg_ctx,
1018 ts->sharename, jobid);
1019 return 0;
1022 /* need to continue the the bottom of the function to
1023 save the correct attributes */
1026 /* maybe it hasn't been spooled yet */
1027 if (!pjob.spooled) {
1028 /* if a job is not spooled and the process doesn't
1029 exist then kill it. This cleans up after smbd
1030 deaths */
1031 if (!process_exists_by_pid(pjob.pid)) {
1032 DEBUG(10,("traverse_fn_delete: pjob %u deleted due to !process_exists (%u)\n",
1033 (unsigned int)jobid, (unsigned int)pjob.pid ));
1034 pjob_delete(ts->ev, ts->msg_ctx,
1035 ts->sharename, jobid);
1036 } else
1037 ts->total_jobs++;
1038 return 0;
1041 /* this check only makes sense for jobs submitted from Windows clients */
1043 if (pjob.smbjob) {
1044 for (i=0;i<ts->qcount;i++) {
1045 if ( pjob.status == LPQ_DELETED )
1046 continue;
1048 if (ts->queue[i].sysjob == pjob.sysjob) {
1050 /* try to clean up any jobs that need to be deleted */
1052 if ( pjob.status == LPQ_DELETING ) {
1053 int result;
1055 result = (*(ts->print_if->job_delete))(
1056 ts->sharename, ts->lprm_command, &pjob );
1058 if ( result != 0 ) {
1059 /* if we can't delete, then reset the job status */
1060 pjob.status = LPQ_QUEUED;
1061 pjob_store(ts->ev, ts->msg_ctx,
1062 ts->sharename, jobid, &pjob);
1064 else {
1065 /* if we deleted the job, the remove the tdb record */
1066 pjob_delete(ts->ev,
1067 ts->msg_ctx,
1068 ts->sharename, jobid);
1069 pjob.status = LPQ_DELETED;
1074 break;
1079 /* The job isn't in the system queue - we have to assume it has
1080 completed, so delete the database entry. */
1082 if (i == ts->qcount) {
1084 /* A race can occur between the time a job is spooled and
1085 when it appears in the lpq output. This happens when
1086 the job is added to printing.tdb when another smbd
1087 running print_queue_update() has completed a lpq and
1088 is currently traversing the printing tdb and deleting jobs.
1089 Don't delete the job if it was submitted after the lpq_time. */
1091 if (pjob.starttime < ts->lpq_time) {
1092 DEBUG(10,("traverse_fn_delete: pjob %u deleted due to pjob.starttime (%u) < ts->lpq_time (%u)\n",
1093 (unsigned int)jobid,
1094 (unsigned int)pjob.starttime,
1095 (unsigned int)ts->lpq_time ));
1096 pjob_delete(ts->ev, ts->msg_ctx,
1097 ts->sharename, jobid);
1098 } else
1099 ts->total_jobs++;
1100 return 0;
1103 /* Save the pjob attributes we will store. */
1104 ts->queue[i].sysjob = pjob.sysjob;
1105 ts->queue[i].size = pjob.size;
1106 ts->queue[i].page_count = pjob.page_count;
1107 ts->queue[i].status = pjob.status;
1108 ts->queue[i].priority = 1;
1109 ts->queue[i].time = pjob.starttime;
1110 fstrcpy(ts->queue[i].fs_user, pjob.user);
1111 fstrcpy(ts->queue[i].fs_file, pjob.jobname);
1113 ts->total_jobs++;
1115 return 0;
1118 /****************************************************************************
1119 Check if the print queue has been updated recently enough.
1120 ****************************************************************************/
1122 static void print_cache_flush(const char *sharename)
1124 fstring key;
1125 struct tdb_print_db *pdb = get_print_db_byname(sharename);
1127 if (!pdb)
1128 return;
1129 slprintf(key, sizeof(key)-1, "CACHE/%s", sharename);
1130 tdb_store_int32(pdb->tdb, key, -1);
1131 release_print_db(pdb);
1134 /****************************************************************************
1135 Check if someone already thinks they are doing the update.
1136 ****************************************************************************/
1138 static pid_t get_updating_pid(const char *sharename)
1140 fstring keystr;
1141 TDB_DATA data, key;
1142 pid_t updating_pid;
1143 struct tdb_print_db *pdb = get_print_db_byname(sharename);
1145 if (!pdb)
1146 return (pid_t)-1;
1147 slprintf(keystr, sizeof(keystr)-1, "UPDATING/%s", sharename);
1148 key = string_tdb_data(keystr);
1150 data = tdb_fetch_compat(pdb->tdb, key);
1151 release_print_db(pdb);
1152 if (!data.dptr || data.dsize != sizeof(pid_t)) {
1153 SAFE_FREE(data.dptr);
1154 return (pid_t)-1;
1157 updating_pid = IVAL(data.dptr, 0);
1158 SAFE_FREE(data.dptr);
1160 if (process_exists_by_pid(updating_pid))
1161 return updating_pid;
1163 return (pid_t)-1;
1166 /****************************************************************************
1167 Set the fact that we're doing the update, or have finished doing the update
1168 in the tdb.
1169 ****************************************************************************/
1171 static void set_updating_pid(const fstring sharename, bool updating)
1173 fstring keystr;
1174 TDB_DATA key;
1175 TDB_DATA data;
1176 pid_t updating_pid = getpid();
1177 uint8 buffer[4];
1179 struct tdb_print_db *pdb = get_print_db_byname(sharename);
1181 if (!pdb)
1182 return;
1184 slprintf(keystr, sizeof(keystr)-1, "UPDATING/%s", sharename);
1185 key = string_tdb_data(keystr);
1187 DEBUG(5, ("set_updating_pid: %s updating lpq cache for print share %s\n",
1188 updating ? "" : "not ",
1189 sharename ));
1191 if ( !updating ) {
1192 tdb_delete(pdb->tdb, key);
1193 release_print_db(pdb);
1194 return;
1197 SIVAL( buffer, 0, updating_pid);
1198 data.dptr = buffer;
1199 data.dsize = 4; /* we always assume this is a 4 byte value */
1201 tdb_store(pdb->tdb, key, data, TDB_REPLACE);
1202 release_print_db(pdb);
1205 /****************************************************************************
1206 Sort print jobs by submittal time.
1207 ****************************************************************************/
1209 static int printjob_comp(print_queue_struct *j1, print_queue_struct *j2)
1211 /* Silly cases */
1213 if (!j1 && !j2)
1214 return 0;
1215 if (!j1)
1216 return -1;
1217 if (!j2)
1218 return 1;
1220 /* Sort on job start time */
1222 if (j1->time == j2->time)
1223 return 0;
1224 return (j1->time > j2->time) ? 1 : -1;
1227 /****************************************************************************
1228 Store the sorted queue representation for later portmon retrieval.
1229 Skip deleted jobs
1230 ****************************************************************************/
1232 static void store_queue_struct(struct tdb_print_db *pdb, struct traverse_struct *pts)
1234 TDB_DATA data;
1235 int max_reported_jobs = lp_max_reported_jobs(pts->snum);
1236 print_queue_struct *queue = pts->queue;
1237 size_t len;
1238 size_t i;
1239 unsigned int qcount;
1241 if (max_reported_jobs && (max_reported_jobs < pts->qcount))
1242 pts->qcount = max_reported_jobs;
1243 qcount = 0;
1245 /* Work out the size. */
1246 data.dsize = 0;
1247 data.dsize += tdb_pack(NULL, 0, "d", qcount);
1249 for (i = 0; i < pts->qcount; i++) {
1250 if ( queue[i].status == LPQ_DELETED )
1251 continue;
1253 qcount++;
1254 data.dsize += tdb_pack(NULL, 0, "ddddddff",
1255 (uint32)queue[i].sysjob,
1256 (uint32)queue[i].size,
1257 (uint32)queue[i].page_count,
1258 (uint32)queue[i].status,
1259 (uint32)queue[i].priority,
1260 (uint32)queue[i].time,
1261 queue[i].fs_user,
1262 queue[i].fs_file);
1265 if ((data.dptr = (uint8 *)SMB_MALLOC(data.dsize)) == NULL)
1266 return;
1268 len = 0;
1269 len += tdb_pack(data.dptr + len, data.dsize - len, "d", qcount);
1270 for (i = 0; i < pts->qcount; i++) {
1271 if ( queue[i].status == LPQ_DELETED )
1272 continue;
1274 len += tdb_pack(data.dptr + len, data.dsize - len, "ddddddff",
1275 (uint32)queue[i].sysjob,
1276 (uint32)queue[i].size,
1277 (uint32)queue[i].page_count,
1278 (uint32)queue[i].status,
1279 (uint32)queue[i].priority,
1280 (uint32)queue[i].time,
1281 queue[i].fs_user,
1282 queue[i].fs_file);
1285 tdb_store(pdb->tdb, string_tdb_data("INFO/linear_queue_array"), data,
1286 TDB_REPLACE);
1287 SAFE_FREE(data.dptr);
1288 return;
1291 static TDB_DATA get_jobs_added_data(struct tdb_print_db *pdb)
1293 TDB_DATA data;
1295 ZERO_STRUCT(data);
1297 data = tdb_fetch_compat(pdb->tdb, string_tdb_data("INFO/jobs_added"));
1298 if (data.dptr == NULL || data.dsize == 0 || (data.dsize % 4 != 0)) {
1299 SAFE_FREE(data.dptr);
1300 ZERO_STRUCT(data);
1303 return data;
1306 static void check_job_added(const char *sharename, TDB_DATA data, uint32 jobid)
1308 unsigned int i;
1309 unsigned int job_count = data.dsize / 4;
1311 for (i = 0; i < job_count; i++) {
1312 uint32 ch_jobid;
1314 ch_jobid = IVAL(data.dptr, i*4);
1315 if (ch_jobid == jobid)
1316 remove_from_jobs_added(sharename, jobid);
1320 /****************************************************************************
1321 Check if the print queue has been updated recently enough.
1322 ****************************************************************************/
1324 static bool print_cache_expired(const char *sharename, bool check_pending)
1326 fstring key;
1327 time_t last_qscan_time, time_now = time(NULL);
1328 struct tdb_print_db *pdb = get_print_db_byname(sharename);
1329 bool result = False;
1331 if (!pdb)
1332 return False;
1334 snprintf(key, sizeof(key), "CACHE/%s", sharename);
1335 last_qscan_time = (time_t)tdb_fetch_int32(pdb->tdb, key);
1338 * Invalidate the queue for 3 reasons.
1339 * (1). last queue scan time == -1.
1340 * (2). Current time - last queue scan time > allowed cache time.
1341 * (3). last queue scan time > current time + MAX_CACHE_VALID_TIME (1 hour by default).
1342 * This last test picks up machines for which the clock has been moved
1343 * forward, an lpq scan done and then the clock moved back. Otherwise
1344 * that last lpq scan would stay around for a loooong loooong time... :-). JRA.
1347 if (last_qscan_time == ((time_t)-1)
1348 || (time_now - last_qscan_time) >= lp_lpqcachetime()
1349 || last_qscan_time > (time_now + MAX_CACHE_VALID_TIME))
1351 uint32 u;
1352 time_t msg_pending_time;
1354 DEBUG(4, ("print_cache_expired: cache expired for queue %s "
1355 "(last_qscan_time = %d, time now = %d, qcachetime = %d)\n",
1356 sharename, (int)last_qscan_time, (int)time_now,
1357 (int)lp_lpqcachetime() ));
1359 /* check if another smbd has already sent a message to update the
1360 queue. Give the pending message one minute to clear and
1361 then send another message anyways. Make sure to check for
1362 clocks that have been run forward and then back again. */
1364 snprintf(key, sizeof(key), "MSG_PENDING/%s", sharename);
1366 if ( check_pending
1367 && tdb_fetch_uint32( pdb->tdb, key, &u )
1368 && (msg_pending_time=u) > 0
1369 && msg_pending_time <= time_now
1370 && (time_now - msg_pending_time) < 60 )
1372 DEBUG(4,("print_cache_expired: message already pending for %s. Accepting cache\n",
1373 sharename));
1374 goto done;
1377 result = True;
1380 done:
1381 release_print_db(pdb);
1382 return result;
1385 /****************************************************************************
1386 main work for updating the lpq cache for a printer queue
1387 ****************************************************************************/
1389 static void print_queue_update_internal(struct tevent_context *ev,
1390 struct messaging_context *msg_ctx,
1391 const char *sharename,
1392 struct printif *current_printif,
1393 char *lpq_command, char *lprm_command)
1395 int i, qcount;
1396 print_queue_struct *queue = NULL;
1397 print_status_struct status;
1398 print_status_struct old_status;
1399 struct printjob *pjob;
1400 struct traverse_struct tstruct;
1401 TDB_DATA data, key;
1402 TDB_DATA jcdata;
1403 fstring keystr, cachestr;
1404 struct tdb_print_db *pdb = get_print_db_byname(sharename);
1405 TALLOC_CTX *tmp_ctx = talloc_new(ev);
1407 if ((pdb == NULL) || (tmp_ctx == NULL)) {
1408 return;
1411 DEBUG(5,("print_queue_update_internal: printer = %s, type = %d, lpq command = [%s]\n",
1412 sharename, current_printif->type, lpq_command));
1415 * Update the cache time FIRST ! Stops others even
1416 * attempting to get the lock and doing this
1417 * if the lpq takes a long time.
1420 slprintf(cachestr, sizeof(cachestr)-1, "CACHE/%s", sharename);
1421 tdb_store_int32(pdb->tdb, cachestr, (int)time(NULL));
1423 /* get the current queue using the appropriate interface */
1424 ZERO_STRUCT(status);
1426 qcount = (*(current_printif->queue_get))(sharename,
1427 current_printif->type,
1428 lpq_command, &queue, &status);
1430 DEBUG(3, ("print_queue_update_internal: %d job%s in queue for %s\n",
1431 qcount, (qcount != 1) ? "s" : "", sharename));
1433 /* Sort the queue by submission time otherwise they are displayed
1434 in hash order. */
1436 TYPESAFE_QSORT(queue, qcount, printjob_comp);
1439 any job in the internal database that is marked as spooled
1440 and doesn't exist in the system queue is considered finished
1441 and removed from the database
1443 any job in the system database but not in the internal database
1444 is added as a unix job
1446 fill in any system job numbers as we go
1448 jcdata = get_jobs_added_data(pdb);
1450 for (i=0; i<qcount; i++) {
1451 uint32 jobid = sysjob_to_jobid_pdb(pdb, queue[i].sysjob);
1452 if (jobid == (uint32)-1) {
1453 /* assume its a unix print job */
1454 print_unix_job(ev, msg_ctx,
1455 sharename, &queue[i], jobid);
1456 continue;
1459 /* we have an active SMB print job - update its status */
1460 pjob = print_job_find(tmp_ctx, sharename, jobid);
1461 if (!pjob) {
1462 /* err, somethings wrong. Probably smbd was restarted
1463 with jobs in the queue. All we can do is treat them
1464 like unix jobs. Pity. */
1465 DEBUG(1, ("queued print job %d not found in jobs list, "
1466 "assuming unix job\n", jobid));
1467 print_unix_job(ev, msg_ctx,
1468 sharename, &queue[i], jobid);
1469 continue;
1472 /* don't reset the status on jobs to be deleted */
1474 if ( pjob->status != LPQ_DELETING )
1475 pjob->status = queue[i].status;
1477 pjob_store(ev, msg_ctx, sharename, jobid, pjob);
1479 check_job_added(sharename, jcdata, jobid);
1482 SAFE_FREE(jcdata.dptr);
1484 /* now delete any queued entries that don't appear in the
1485 system queue */
1486 tstruct.queue = queue;
1487 tstruct.qcount = qcount;
1488 tstruct.snum = -1;
1489 tstruct.total_jobs = 0;
1490 tstruct.lpq_time = time(NULL);
1491 tstruct.sharename = sharename;
1492 tstruct.lprm_command = lprm_command;
1493 tstruct.print_if = current_printif;
1494 tstruct.ev = ev;
1495 tstruct.msg_ctx = msg_ctx;
1496 tstruct.mem_ctx = tmp_ctx;
1498 tdb_traverse(pdb->tdb, traverse_fn_delete, (void *)&tstruct);
1500 /* Store the linearised queue, max jobs only. */
1501 store_queue_struct(pdb, &tstruct);
1503 SAFE_FREE(tstruct.queue);
1504 talloc_free(tmp_ctx);
1506 DEBUG(10,("print_queue_update_internal: printer %s INFO/total_jobs = %d\n",
1507 sharename, tstruct.total_jobs ));
1509 tdb_store_int32(pdb->tdb, "INFO/total_jobs", tstruct.total_jobs);
1511 get_queue_status(sharename, &old_status);
1512 if (old_status.qcount != qcount)
1513 DEBUG(10,("print_queue_update_internal: queue status change %d jobs -> %d jobs for printer %s\n",
1514 old_status.qcount, qcount, sharename));
1516 /* store the new queue status structure */
1517 slprintf(keystr, sizeof(keystr)-1, "STATUS/%s", sharename);
1518 key = string_tdb_data(keystr);
1520 status.qcount = qcount;
1521 data.dptr = (uint8 *)&status;
1522 data.dsize = sizeof(status);
1523 tdb_store(pdb->tdb, key, data, TDB_REPLACE);
1526 * Update the cache time again. We want to do this call
1527 * as little as possible...
1530 slprintf(keystr, sizeof(keystr)-1, "CACHE/%s", sharename);
1531 tdb_store_int32(pdb->tdb, keystr, (int32)time(NULL));
1533 /* clear the msg pending record for this queue */
1535 snprintf(keystr, sizeof(keystr), "MSG_PENDING/%s", sharename);
1537 if ( !tdb_store_uint32( pdb->tdb, keystr, 0 ) ) {
1538 /* log a message but continue on */
1540 DEBUG(0,("print_queue_update: failed to store MSG_PENDING flag for [%s]!\n",
1541 sharename));
1544 release_print_db( pdb );
1546 return;
1549 /****************************************************************************
1550 Update the internal database from the system print queue for a queue.
1551 obtain a lock on the print queue before proceeding (needed when mutiple
1552 smbd processes maytry to update the lpq cache concurrently).
1553 ****************************************************************************/
1555 static void print_queue_update_with_lock( struct tevent_context *ev,
1556 struct messaging_context *msg_ctx,
1557 const char *sharename,
1558 struct printif *current_printif,
1559 char *lpq_command, char *lprm_command )
1561 fstring keystr;
1562 struct tdb_print_db *pdb;
1564 DEBUG(5,("print_queue_update_with_lock: printer share = %s\n", sharename));
1565 pdb = get_print_db_byname(sharename);
1566 if (!pdb)
1567 return;
1569 if ( !print_cache_expired(sharename, False) ) {
1570 DEBUG(5,("print_queue_update_with_lock: print cache for %s is still ok\n", sharename));
1571 release_print_db(pdb);
1572 return;
1576 * Check to see if someone else is doing this update.
1577 * This is essentially a mutex on the update.
1580 if (get_updating_pid(sharename) != -1) {
1581 release_print_db(pdb);
1582 return;
1585 /* Lock the queue for the database update */
1587 slprintf(keystr, sizeof(keystr) - 1, "LOCK/%s", sharename);
1588 /* Only wait 10 seconds for this. */
1589 if (tdb_lock_bystring_with_timeout(pdb->tdb, keystr, 10) != 0) {
1590 DEBUG(0,("print_queue_update_with_lock: Failed to lock printer %s database\n", sharename));
1591 release_print_db(pdb);
1592 return;
1596 * Ensure that no one else got in here.
1597 * If the updating pid is still -1 then we are
1598 * the winner.
1601 if (get_updating_pid(sharename) != -1) {
1603 * Someone else is doing the update, exit.
1605 tdb_unlock_bystring(pdb->tdb, keystr);
1606 release_print_db(pdb);
1607 return;
1611 * We're going to do the update ourselves.
1614 /* Tell others we're doing the update. */
1615 set_updating_pid(sharename, True);
1618 * Allow others to enter and notice we're doing
1619 * the update.
1622 tdb_unlock_bystring(pdb->tdb, keystr);
1624 /* do the main work now */
1626 print_queue_update_internal(ev, msg_ctx,
1627 sharename, current_printif,
1628 lpq_command, lprm_command);
1630 /* Delete our pid from the db. */
1631 set_updating_pid(sharename, False);
1632 release_print_db(pdb);
1635 /****************************************************************************
1636 this is the receive function of the background lpq updater
1637 ****************************************************************************/
1638 void print_queue_receive(struct messaging_context *msg,
1639 void *private_data,
1640 uint32_t msg_type,
1641 struct server_id server_id,
1642 DATA_BLOB *data)
1644 fstring sharename;
1645 char *lpqcommand = NULL, *lprmcommand = NULL;
1646 int printing_type;
1647 size_t len;
1649 len = tdb_unpack( (uint8 *)data->data, data->length, "fdPP",
1650 sharename,
1651 &printing_type,
1652 &lpqcommand,
1653 &lprmcommand );
1655 if ( len == -1 ) {
1656 SAFE_FREE(lpqcommand);
1657 SAFE_FREE(lprmcommand);
1658 DEBUG(0,("print_queue_receive: Got invalid print queue update message\n"));
1659 return;
1662 print_queue_update_with_lock(server_event_context(), msg, sharename,
1663 get_printer_fns_from_type((enum printing_types)printing_type),
1664 lpqcommand, lprmcommand );
1666 SAFE_FREE(lpqcommand);
1667 SAFE_FREE(lprmcommand);
1668 return;
1671 /****************************************************************************
1672 update the internal database from the system print queue for a queue
1673 ****************************************************************************/
1675 extern pid_t background_lpq_updater_pid;
1677 static void print_queue_update(struct messaging_context *msg_ctx,
1678 int snum, bool force)
1680 fstring key;
1681 fstring sharename;
1682 char *lpqcommand = NULL;
1683 char *lprmcommand = NULL;
1684 uint8 *buffer = NULL;
1685 size_t len = 0;
1686 size_t newlen;
1687 struct tdb_print_db *pdb;
1688 int type;
1689 struct printif *current_printif;
1690 TALLOC_CTX *ctx = talloc_tos();
1692 fstrcpy( sharename, lp_const_servicename(snum));
1694 /* don't strip out characters like '$' from the printername */
1696 lpqcommand = talloc_string_sub2(ctx,
1697 lp_lpqcommand(talloc_tos(), snum),
1698 "%p",
1699 lp_printername(talloc_tos(), snum),
1700 false, false, false);
1701 if (!lpqcommand) {
1702 return;
1704 lpqcommand = talloc_sub_advanced(ctx,
1705 lp_servicename(talloc_tos(), snum),
1706 current_user_info.unix_name,
1708 current_user.ut.gid,
1709 get_current_username(),
1710 current_user_info.domain,
1711 lpqcommand);
1712 if (!lpqcommand) {
1713 return;
1716 lprmcommand = talloc_string_sub2(ctx,
1717 lp_lprmcommand(talloc_tos(), snum),
1718 "%p",
1719 lp_printername(talloc_tos(), snum),
1720 false, false, false);
1721 if (!lprmcommand) {
1722 return;
1724 lprmcommand = talloc_sub_advanced(ctx,
1725 lp_servicename(talloc_tos(), snum),
1726 current_user_info.unix_name,
1728 current_user.ut.gid,
1729 get_current_username(),
1730 current_user_info.domain,
1731 lprmcommand);
1732 if (!lprmcommand) {
1733 return;
1737 * Make sure that the background queue process exists.
1738 * Otherwise just do the update ourselves
1741 if ( force || background_lpq_updater_pid == -1 ) {
1742 DEBUG(4,("print_queue_update: updating queue [%s] myself\n", sharename));
1743 current_printif = get_printer_fns( snum );
1744 print_queue_update_with_lock(server_event_context(), msg_ctx,
1745 sharename, current_printif,
1746 lpqcommand, lprmcommand);
1748 return;
1751 type = lp_printing(snum);
1753 /* get the length */
1755 len = tdb_pack( NULL, 0, "fdPP",
1756 sharename,
1757 type,
1758 lpqcommand,
1759 lprmcommand );
1761 buffer = SMB_XMALLOC_ARRAY( uint8, len );
1763 /* now pack the buffer */
1764 newlen = tdb_pack( buffer, len, "fdPP",
1765 sharename,
1766 type,
1767 lpqcommand,
1768 lprmcommand );
1770 SMB_ASSERT( newlen == len );
1772 DEBUG(10,("print_queue_update: Sending message -> printer = %s, "
1773 "type = %d, lpq command = [%s] lprm command = [%s]\n",
1774 sharename, type, lpqcommand, lprmcommand ));
1776 /* here we set a msg pending record for other smbd processes
1777 to throttle the number of duplicate print_queue_update msgs
1778 sent. */
1780 pdb = get_print_db_byname(sharename);
1781 if (!pdb) {
1782 SAFE_FREE(buffer);
1783 return;
1786 snprintf(key, sizeof(key), "MSG_PENDING/%s", sharename);
1788 if ( !tdb_store_uint32( pdb->tdb, key, time(NULL) ) ) {
1789 /* log a message but continue on */
1791 DEBUG(0,("print_queue_update: failed to store MSG_PENDING flag for [%s]!\n",
1792 sharename));
1795 release_print_db( pdb );
1797 /* finally send the message */
1799 messaging_send_buf(msg_ctx, pid_to_procid(background_lpq_updater_pid),
1800 MSG_PRINTER_UPDATE, (uint8 *)buffer, len);
1802 SAFE_FREE( buffer );
1804 return;
1807 /****************************************************************************
1808 Create/Update an entry in the print tdb that will allow us to send notify
1809 updates only to interested smbd's.
1810 ****************************************************************************/
1812 bool print_notify_register_pid(int snum)
1814 TDB_DATA data;
1815 struct tdb_print_db *pdb = NULL;
1816 TDB_CONTEXT *tdb = NULL;
1817 const char *printername;
1818 uint32_t mypid = (uint32_t)getpid();
1819 bool ret = False;
1820 size_t i;
1822 /* if (snum == -1), then the change notify request was
1823 on a print server handle and we need to register on
1824 all print queus */
1826 if (snum == -1)
1828 int num_services = lp_numservices();
1829 int idx;
1831 for ( idx=0; idx<num_services; idx++ ) {
1832 if (lp_snum_ok(idx) && lp_print_ok(idx) )
1833 print_notify_register_pid(idx);
1836 return True;
1838 else /* register for a specific printer */
1840 printername = lp_const_servicename(snum);
1841 pdb = get_print_db_byname(printername);
1842 if (!pdb)
1843 return False;
1844 tdb = pdb->tdb;
1847 if (tdb_lock_bystring_with_timeout(tdb, NOTIFY_PID_LIST_KEY, 10) != 0) {
1848 DEBUG(0,("print_notify_register_pid: Failed to lock printer %s\n",
1849 printername));
1850 if (pdb)
1851 release_print_db(pdb);
1852 return False;
1855 data = get_printer_notify_pid_list( tdb, printername, True );
1857 /* Add ourselves and increase the refcount. */
1859 for (i = 0; i < data.dsize; i += 8) {
1860 if (IVAL(data.dptr,i) == mypid) {
1861 uint32 new_refcount = IVAL(data.dptr, i+4) + 1;
1862 SIVAL(data.dptr, i+4, new_refcount);
1863 break;
1867 if (i == data.dsize) {
1868 /* We weren't in the list. Realloc. */
1869 data.dptr = (uint8 *)SMB_REALLOC(data.dptr, data.dsize + 8);
1870 if (!data.dptr) {
1871 DEBUG(0,("print_notify_register_pid: Relloc fail for printer %s\n",
1872 printername));
1873 goto done;
1875 data.dsize += 8;
1876 SIVAL(data.dptr,data.dsize - 8,mypid);
1877 SIVAL(data.dptr,data.dsize - 4,1); /* Refcount. */
1880 /* Store back the record. */
1881 if (tdb_store_bystring(tdb, NOTIFY_PID_LIST_KEY, data, TDB_REPLACE) != 0) {
1882 DEBUG(0,("print_notify_register_pid: Failed to update pid \
1883 list for printer %s\n", printername));
1884 goto done;
1887 ret = True;
1889 done:
1891 tdb_unlock_bystring(tdb, NOTIFY_PID_LIST_KEY);
1892 if (pdb)
1893 release_print_db(pdb);
1894 SAFE_FREE(data.dptr);
1895 return ret;
1898 /****************************************************************************
1899 Update an entry in the print tdb that will allow us to send notify
1900 updates only to interested smbd's.
1901 ****************************************************************************/
1903 bool print_notify_deregister_pid(int snum)
1905 TDB_DATA data;
1906 struct tdb_print_db *pdb = NULL;
1907 TDB_CONTEXT *tdb = NULL;
1908 const char *printername;
1909 uint32_t mypid = (uint32_t)getpid();
1910 size_t i;
1911 bool ret = False;
1913 /* if ( snum == -1 ), we are deregister a print server handle
1914 which means to deregister on all print queues */
1916 if (snum == -1)
1918 int num_services = lp_numservices();
1919 int idx;
1921 for ( idx=0; idx<num_services; idx++ ) {
1922 if ( lp_snum_ok(idx) && lp_print_ok(idx) )
1923 print_notify_deregister_pid(idx);
1926 return True;
1928 else /* deregister a specific printer */
1930 printername = lp_const_servicename(snum);
1931 pdb = get_print_db_byname(printername);
1932 if (!pdb)
1933 return False;
1934 tdb = pdb->tdb;
1937 if (tdb_lock_bystring_with_timeout(tdb, NOTIFY_PID_LIST_KEY, 10) != 0) {
1938 DEBUG(0,("print_notify_register_pid: Failed to lock \
1939 printer %s database\n", printername));
1940 if (pdb)
1941 release_print_db(pdb);
1942 return False;
1945 data = get_printer_notify_pid_list( tdb, printername, True );
1947 /* Reduce refcount. Remove ourselves if zero. */
1949 for (i = 0; i < data.dsize; ) {
1950 if (IVAL(data.dptr,i) == mypid) {
1951 uint32 refcount = IVAL(data.dptr, i+4);
1953 refcount--;
1955 if (refcount == 0) {
1956 if (data.dsize - i > 8)
1957 memmove( &data.dptr[i], &data.dptr[i+8], data.dsize - i - 8);
1958 data.dsize -= 8;
1959 continue;
1961 SIVAL(data.dptr, i+4, refcount);
1964 i += 8;
1967 if (data.dsize == 0)
1968 SAFE_FREE(data.dptr);
1970 /* Store back the record. */
1971 if (tdb_store_bystring(tdb, NOTIFY_PID_LIST_KEY, data, TDB_REPLACE) != 0) {
1972 DEBUG(0,("print_notify_register_pid: Failed to update pid \
1973 list for printer %s\n", printername));
1974 goto done;
1977 ret = True;
1979 done:
1981 tdb_unlock_bystring(tdb, NOTIFY_PID_LIST_KEY);
1982 if (pdb)
1983 release_print_db(pdb);
1984 SAFE_FREE(data.dptr);
1985 return ret;
1988 /****************************************************************************
1989 Check if a jobid is valid. It is valid if it exists in the database.
1990 ****************************************************************************/
1992 bool print_job_exists(const char* sharename, uint32 jobid)
1994 struct tdb_print_db *pdb = get_print_db_byname(sharename);
1995 bool ret;
1996 uint32_t tmp;
1998 if (!pdb)
1999 return False;
2000 ret = tdb_exists(pdb->tdb, print_key(jobid, &tmp));
2001 release_print_db(pdb);
2002 return ret;
2005 /****************************************************************************
2006 Return the device mode asigned to a specific print job.
2007 Only valid for the process doing the spooling and when the job
2008 has not been spooled.
2009 ****************************************************************************/
2011 struct spoolss_DeviceMode *print_job_devmode(TALLOC_CTX *mem_ctx,
2012 const char *sharename,
2013 uint32 jobid)
2015 struct printjob *pjob = print_job_find(mem_ctx, sharename, jobid);
2016 if (pjob == NULL) {
2017 return NULL;
2020 return pjob->devmode;
2023 /****************************************************************************
2024 Set the name of a job. Only possible for owner.
2025 ****************************************************************************/
2027 bool print_job_set_name(struct tevent_context *ev,
2028 struct messaging_context *msg_ctx,
2029 const char *sharename, uint32 jobid, const char *name)
2031 struct printjob *pjob;
2032 bool ret;
2033 TALLOC_CTX *tmp_ctx = talloc_new(ev);
2034 if (tmp_ctx == NULL) {
2035 return false;
2038 pjob = print_job_find(tmp_ctx, sharename, jobid);
2039 if (!pjob || pjob->pid != getpid()) {
2040 ret = false;
2041 goto err_out;
2044 fstrcpy(pjob->jobname, name);
2045 ret = pjob_store(ev, msg_ctx, sharename, jobid, pjob);
2046 err_out:
2047 talloc_free(tmp_ctx);
2048 return ret;
2051 /****************************************************************************
2052 Get the name of a job. Only possible for owner.
2053 ****************************************************************************/
2055 bool print_job_get_name(TALLOC_CTX *mem_ctx, const char *sharename, uint32_t jobid, char **name)
2057 struct printjob *pjob;
2059 pjob = print_job_find(mem_ctx, sharename, jobid);
2060 if (!pjob || pjob->pid != getpid()) {
2061 return false;
2064 *name = pjob->jobname;
2065 return true;
2069 /***************************************************************************
2070 Remove a jobid from the 'jobs added' list.
2071 ***************************************************************************/
2073 static bool remove_from_jobs_added(const char* sharename, uint32 jobid)
2075 struct tdb_print_db *pdb = get_print_db_byname(sharename);
2076 TDB_DATA data, key;
2077 size_t job_count, i;
2078 bool ret = False;
2079 bool gotlock = False;
2081 if (!pdb) {
2082 return False;
2085 ZERO_STRUCT(data);
2087 key = string_tdb_data("INFO/jobs_added");
2089 if (tdb_chainlock_with_timeout(pdb->tdb, key, 5) != 0)
2090 goto out;
2092 gotlock = True;
2094 data = tdb_fetch_compat(pdb->tdb, key);
2096 if (data.dptr == NULL || data.dsize == 0 || (data.dsize % 4 != 0))
2097 goto out;
2099 job_count = data.dsize / 4;
2100 for (i = 0; i < job_count; i++) {
2101 uint32 ch_jobid;
2103 ch_jobid = IVAL(data.dptr, i*4);
2104 if (ch_jobid == jobid) {
2105 if (i < job_count -1 )
2106 memmove(data.dptr + (i*4), data.dptr + (i*4) + 4, (job_count - i - 1)*4 );
2107 data.dsize -= 4;
2108 if (tdb_store(pdb->tdb, key, data, TDB_REPLACE) != 0)
2109 goto out;
2110 break;
2114 ret = True;
2115 out:
2117 if (gotlock)
2118 tdb_chainunlock(pdb->tdb, key);
2119 SAFE_FREE(data.dptr);
2120 release_print_db(pdb);
2121 if (ret)
2122 DEBUG(10,("remove_from_jobs_added: removed jobid %u\n", (unsigned int)jobid ));
2123 else
2124 DEBUG(10,("remove_from_jobs_added: Failed to remove jobid %u\n", (unsigned int)jobid ));
2125 return ret;
2128 /****************************************************************************
2129 Delete a print job - don't update queue.
2130 ****************************************************************************/
2132 static bool print_job_delete1(struct tevent_context *ev,
2133 struct messaging_context *msg_ctx,
2134 int snum, uint32 jobid)
2136 const char* sharename = lp_const_servicename(snum);
2137 struct printjob *pjob;
2138 int result = 0;
2139 struct printif *current_printif = get_printer_fns( snum );
2140 bool ret;
2141 TALLOC_CTX *tmp_ctx = talloc_new(ev);
2142 if (tmp_ctx == NULL) {
2143 return false;
2146 pjob = print_job_find(tmp_ctx, sharename, jobid);
2147 if (!pjob) {
2148 ret = false;
2149 goto err_out;
2153 * If already deleting just return.
2156 if (pjob->status == LPQ_DELETING) {
2157 ret = true;
2158 goto err_out;
2161 /* Hrm - we need to be able to cope with deleting a job before it
2162 has reached the spooler. Just mark it as LPQ_DELETING and
2163 let the print_queue_update() code rmeove the record */
2166 if (pjob->sysjob == -1) {
2167 DEBUG(5, ("attempt to delete job %u not seen by lpr\n", (unsigned int)jobid));
2170 /* Set the tdb entry to be deleting. */
2172 pjob->status = LPQ_DELETING;
2173 pjob_store(ev, msg_ctx, sharename, jobid, pjob);
2175 if (pjob->spooled && pjob->sysjob != -1)
2177 result = (*(current_printif->job_delete))(
2178 lp_printername(talloc_tos(), snum),
2179 lp_lprmcommand(talloc_tos(), snum),
2180 pjob);
2182 /* Delete the tdb entry if the delete succeeded or the job hasn't
2183 been spooled. */
2185 if (result == 0) {
2186 struct tdb_print_db *pdb = get_print_db_byname(sharename);
2187 int njobs = 1;
2189 if (!pdb) {
2190 ret = false;
2191 goto err_out;
2193 pjob_delete(ev, msg_ctx, sharename, jobid);
2194 /* Ensure we keep a rough count of the number of total jobs... */
2195 tdb_change_int32_atomic(pdb->tdb, "INFO/total_jobs", &njobs, -1);
2196 release_print_db(pdb);
2200 remove_from_jobs_added( sharename, jobid );
2202 ret = (result == 0);
2203 err_out:
2204 talloc_free(tmp_ctx);
2205 return ret;
2208 /****************************************************************************
2209 Return true if the current user owns the print job.
2210 ****************************************************************************/
2212 static bool is_owner(const struct auth_session_info *server_info,
2213 const char *servicename,
2214 uint32 jobid)
2216 struct printjob *pjob;
2217 bool ret;
2218 TALLOC_CTX *tmp_ctx = talloc_new(server_info);
2219 if (tmp_ctx == NULL) {
2220 return false;
2223 pjob = print_job_find(tmp_ctx, servicename, jobid);
2224 if (!pjob || !server_info) {
2225 ret = false;
2226 goto err_out;
2229 ret = strequal(pjob->user, server_info->unix_info->sanitized_username);
2230 err_out:
2231 talloc_free(tmp_ctx);
2232 return ret;
2235 /****************************************************************************
2236 Delete a print job.
2237 ****************************************************************************/
2239 WERROR print_job_delete(const struct auth_session_info *server_info,
2240 struct messaging_context *msg_ctx,
2241 int snum, uint32_t jobid)
2243 const char* sharename = lp_const_servicename(snum);
2244 struct printjob *pjob;
2245 bool owner;
2246 WERROR werr;
2247 TALLOC_CTX *tmp_ctx = talloc_new(msg_ctx);
2248 if (tmp_ctx == NULL) {
2249 return WERR_NOT_ENOUGH_MEMORY;
2252 owner = is_owner(server_info, lp_const_servicename(snum), jobid);
2254 /* Check access against security descriptor or whether the user
2255 owns their job. */
2257 if (!owner &&
2258 !print_access_check(server_info, msg_ctx, snum,
2259 JOB_ACCESS_ADMINISTER)) {
2260 DEBUG(3, ("delete denied by security descriptor\n"));
2262 /* BEGIN_ADMIN_LOG */
2263 sys_adminlog( LOG_ERR,
2264 "Permission denied-- user not allowed to delete, \
2265 pause, or resume print job. User name: %s. Printer name: %s.",
2266 uidtoname(server_info->unix_token->uid),
2267 lp_printername(talloc_tos(), snum) );
2268 /* END_ADMIN_LOG */
2270 werr = WERR_ACCESS_DENIED;
2271 goto err_out;
2275 * get the spooled filename of the print job
2276 * if this works, then the file has not been spooled
2277 * to the underlying print system. Just delete the
2278 * spool file & return.
2281 pjob = print_job_find(tmp_ctx, sharename, jobid);
2282 if (!pjob || pjob->spooled || pjob->pid != getpid()) {
2283 DEBUG(10, ("Skipping spool file removal for job %u\n", jobid));
2284 } else {
2285 DEBUG(10, ("Removing spool file [%s]\n", pjob->filename));
2286 if (unlink(pjob->filename) == -1) {
2287 werr = map_werror_from_unix(errno);
2288 goto err_out;
2292 if (!print_job_delete1(server_event_context(), msg_ctx, snum, jobid)) {
2293 werr = WERR_ACCESS_DENIED;
2294 goto err_out;
2297 /* force update the database and say the delete failed if the
2298 job still exists */
2300 print_queue_update(msg_ctx, snum, True);
2302 pjob = print_job_find(tmp_ctx, sharename, jobid);
2303 if (pjob && (pjob->status != LPQ_DELETING)) {
2304 werr = WERR_ACCESS_DENIED;
2305 goto err_out;
2307 werr = WERR_PRINTER_HAS_JOBS_QUEUED;
2309 err_out:
2310 talloc_free(tmp_ctx);
2311 return werr;
2314 /****************************************************************************
2315 Pause a job.
2316 ****************************************************************************/
2318 WERROR print_job_pause(const struct auth_session_info *server_info,
2319 struct messaging_context *msg_ctx,
2320 int snum, uint32 jobid)
2322 const char* sharename = lp_const_servicename(snum);
2323 struct printjob *pjob;
2324 int ret = -1;
2325 struct printif *current_printif = get_printer_fns( snum );
2326 WERROR werr;
2327 TALLOC_CTX *tmp_ctx = talloc_new(msg_ctx);
2328 if (tmp_ctx == NULL) {
2329 return WERR_NOT_ENOUGH_MEMORY;
2332 pjob = print_job_find(tmp_ctx, sharename, jobid);
2333 if (!pjob || !server_info) {
2334 DEBUG(10, ("print_job_pause: no pjob or user for jobid %u\n",
2335 (unsigned int)jobid ));
2336 werr = WERR_INVALID_PARAM;
2337 goto err_out;
2340 if (!pjob->spooled || pjob->sysjob == -1) {
2341 DEBUG(10, ("print_job_pause: not spooled or bad sysjob = %d for jobid %u\n",
2342 (int)pjob->sysjob, (unsigned int)jobid ));
2343 werr = WERR_INVALID_PARAM;
2344 goto err_out;
2347 if (!is_owner(server_info, lp_const_servicename(snum), jobid) &&
2348 !print_access_check(server_info, msg_ctx, snum,
2349 JOB_ACCESS_ADMINISTER)) {
2350 DEBUG(3, ("pause denied by security descriptor\n"));
2352 /* BEGIN_ADMIN_LOG */
2353 sys_adminlog( LOG_ERR,
2354 "Permission denied-- user not allowed to delete, \
2355 pause, or resume print job. User name: %s. Printer name: %s.",
2356 uidtoname(server_info->unix_token->uid),
2357 lp_printername(talloc_tos(), snum) );
2358 /* END_ADMIN_LOG */
2360 werr = WERR_ACCESS_DENIED;
2361 goto err_out;
2364 /* need to pause the spooled entry */
2365 ret = (*(current_printif->job_pause))(snum, pjob);
2367 if (ret != 0) {
2368 werr = WERR_INVALID_PARAM;
2369 goto err_out;
2372 /* force update the database */
2373 print_cache_flush(lp_const_servicename(snum));
2375 /* Send a printer notify message */
2377 notify_job_status(server_event_context(), msg_ctx, sharename, jobid,
2378 JOB_STATUS_PAUSED);
2380 /* how do we tell if this succeeded? */
2381 werr = WERR_OK;
2382 err_out:
2383 talloc_free(tmp_ctx);
2384 return werr;
2387 /****************************************************************************
2388 Resume a job.
2389 ****************************************************************************/
2391 WERROR print_job_resume(const struct auth_session_info *server_info,
2392 struct messaging_context *msg_ctx,
2393 int snum, uint32 jobid)
2395 const char *sharename = lp_const_servicename(snum);
2396 struct printjob *pjob;
2397 int ret;
2398 struct printif *current_printif = get_printer_fns( snum );
2399 WERROR werr;
2400 TALLOC_CTX *tmp_ctx = talloc_new(msg_ctx);
2401 if (tmp_ctx == NULL)
2402 return WERR_NOT_ENOUGH_MEMORY;
2404 pjob = print_job_find(tmp_ctx, sharename, jobid);
2405 if (!pjob || !server_info) {
2406 DEBUG(10, ("print_job_resume: no pjob or user for jobid %u\n",
2407 (unsigned int)jobid ));
2408 werr = WERR_INVALID_PARAM;
2409 goto err_out;
2412 if (!pjob->spooled || pjob->sysjob == -1) {
2413 DEBUG(10, ("print_job_resume: not spooled or bad sysjob = %d for jobid %u\n",
2414 (int)pjob->sysjob, (unsigned int)jobid ));
2415 werr = WERR_INVALID_PARAM;
2416 goto err_out;
2419 if (!is_owner(server_info, lp_const_servicename(snum), jobid) &&
2420 !print_access_check(server_info, msg_ctx, snum,
2421 JOB_ACCESS_ADMINISTER)) {
2422 DEBUG(3, ("resume denied by security descriptor\n"));
2424 /* BEGIN_ADMIN_LOG */
2425 sys_adminlog( LOG_ERR,
2426 "Permission denied-- user not allowed to delete, \
2427 pause, or resume print job. User name: %s. Printer name: %s.",
2428 uidtoname(server_info->unix_token->uid),
2429 lp_printername(talloc_tos(), snum) );
2430 /* END_ADMIN_LOG */
2431 werr = WERR_ACCESS_DENIED;
2432 goto err_out;
2435 ret = (*(current_printif->job_resume))(snum, pjob);
2437 if (ret != 0) {
2438 werr = WERR_INVALID_PARAM;
2439 goto err_out;
2442 /* force update the database */
2443 print_cache_flush(lp_const_servicename(snum));
2445 /* Send a printer notify message */
2447 notify_job_status(server_event_context(), msg_ctx, sharename, jobid,
2448 JOB_STATUS_QUEUED);
2450 werr = WERR_OK;
2451 err_out:
2452 talloc_free(tmp_ctx);
2453 return werr;
2456 /****************************************************************************
2457 Write to a print file.
2458 ****************************************************************************/
2460 ssize_t print_job_write(struct tevent_context *ev,
2461 struct messaging_context *msg_ctx,
2462 int snum, uint32 jobid, const char *buf, size_t size)
2464 const char* sharename = lp_const_servicename(snum);
2465 ssize_t return_code;
2466 struct printjob *pjob;
2467 TALLOC_CTX *tmp_ctx = talloc_new(ev);
2468 if (tmp_ctx == NULL) {
2469 return -1;
2472 pjob = print_job_find(tmp_ctx, sharename, jobid);
2473 if (!pjob) {
2474 return_code = -1;
2475 goto err_out;
2478 /* don't allow another process to get this info - it is meaningless */
2479 if (pjob->pid != getpid()) {
2480 return_code = -1;
2481 goto err_out;
2484 /* if SMBD is spooling this can't be allowed */
2485 if (pjob->status == PJOB_SMBD_SPOOLING) {
2486 return_code = -1;
2487 goto err_out;
2490 return_code = write_data(pjob->fd, buf, size);
2491 if (return_code > 0) {
2492 pjob->size += size;
2493 pjob_store(ev, msg_ctx, sharename, jobid, pjob);
2495 err_out:
2496 talloc_free(tmp_ctx);
2497 return return_code;
2500 /****************************************************************************
2501 Get the queue status - do not update if db is out of date.
2502 ****************************************************************************/
2504 static int get_queue_status(const char* sharename, print_status_struct *status)
2506 fstring keystr;
2507 TDB_DATA data;
2508 struct tdb_print_db *pdb = get_print_db_byname(sharename);
2509 int len;
2511 if (status) {
2512 ZERO_STRUCTP(status);
2515 if (!pdb)
2516 return 0;
2518 if (status) {
2519 fstr_sprintf(keystr, "STATUS/%s", sharename);
2520 data = tdb_fetch_compat(pdb->tdb, string_tdb_data(keystr));
2521 if (data.dptr) {
2522 if (data.dsize == sizeof(print_status_struct))
2523 /* this memcpy is ok since the status struct was
2524 not packed before storing it in the tdb */
2525 memcpy(status, data.dptr, sizeof(print_status_struct));
2526 SAFE_FREE(data.dptr);
2529 len = tdb_fetch_int32(pdb->tdb, "INFO/total_jobs");
2530 release_print_db(pdb);
2531 return (len == -1 ? 0 : len);
2534 /****************************************************************************
2535 Determine the number of jobs in a queue.
2536 ****************************************************************************/
2538 int print_queue_length(struct messaging_context *msg_ctx, int snum,
2539 print_status_struct *pstatus)
2541 const char* sharename = lp_const_servicename( snum );
2542 print_status_struct status;
2543 int len;
2545 ZERO_STRUCT( status );
2547 /* make sure the database is up to date */
2548 if (print_cache_expired(lp_const_servicename(snum), True))
2549 print_queue_update(msg_ctx, snum, False);
2551 /* also fetch the queue status */
2552 memset(&status, 0, sizeof(status));
2553 len = get_queue_status(sharename, &status);
2555 if (pstatus)
2556 *pstatus = status;
2558 return len;
2561 /***************************************************************************
2562 Allocate a jobid. Hold the lock for as short a time as possible.
2563 ***************************************************************************/
2565 static WERROR allocate_print_jobid(struct tdb_print_db *pdb, int snum,
2566 const char *sharename, uint32 *pjobid)
2568 int i;
2569 uint32 jobid;
2570 enum TDB_ERROR terr;
2571 int ret;
2573 *pjobid = (uint32)-1;
2575 for (i = 0; i < 3; i++) {
2576 /* Lock the database - only wait 20 seconds. */
2577 ret = tdb_lock_bystring_with_timeout(pdb->tdb,
2578 "INFO/nextjob", 20);
2579 if (ret != 0) {
2580 DEBUG(0, ("allocate_print_jobid: "
2581 "Failed to lock printing database %s\n",
2582 sharename));
2583 terr = tdb_error(pdb->tdb);
2584 return ntstatus_to_werror(map_nt_error_from_tdb(terr));
2587 if (!tdb_fetch_uint32(pdb->tdb, "INFO/nextjob", &jobid)) {
2588 terr = tdb_error(pdb->tdb);
2589 if (terr != TDB_ERR_NOEXIST) {
2590 DEBUG(0, ("allocate_print_jobid: "
2591 "Failed to fetch INFO/nextjob "
2592 "for print queue %s\n", sharename));
2593 tdb_unlock_bystring(pdb->tdb, "INFO/nextjob");
2594 return ntstatus_to_werror(map_nt_error_from_tdb(terr));
2596 DEBUG(10, ("allocate_print_jobid: "
2597 "No existing jobid in %s\n", sharename));
2598 jobid = 0;
2601 DEBUG(10, ("allocate_print_jobid: "
2602 "Read jobid %u from %s\n", jobid, sharename));
2604 jobid = NEXT_JOBID(jobid);
2606 ret = tdb_store_int32(pdb->tdb, "INFO/nextjob", jobid);
2607 if (ret != 0) {
2608 terr = tdb_error(pdb->tdb);
2609 DEBUG(3, ("allocate_print_jobid: "
2610 "Failed to store INFO/nextjob.\n"));
2611 tdb_unlock_bystring(pdb->tdb, "INFO/nextjob");
2612 return ntstatus_to_werror(map_nt_error_from_tdb(terr));
2615 /* We've finished with the INFO/nextjob lock. */
2616 tdb_unlock_bystring(pdb->tdb, "INFO/nextjob");
2618 if (!print_job_exists(sharename, jobid)) {
2619 break;
2621 DEBUG(10, ("allocate_print_jobid: "
2622 "Found jobid %u in %s\n", jobid, sharename));
2625 if (i > 2) {
2626 DEBUG(0, ("allocate_print_jobid: "
2627 "Failed to allocate a print job for queue %s\n",
2628 sharename));
2629 /* Probably full... */
2630 return WERR_NO_SPOOL_SPACE;
2633 /* Store a dummy placeholder. */
2635 uint32_t tmp;
2636 TDB_DATA dum;
2637 dum.dptr = NULL;
2638 dum.dsize = 0;
2639 if (tdb_store(pdb->tdb, print_key(jobid, &tmp), dum,
2640 TDB_INSERT) != 0) {
2641 DEBUG(3, ("allocate_print_jobid: "
2642 "jobid (%d) failed to store placeholder.\n",
2643 jobid ));
2644 terr = tdb_error(pdb->tdb);
2645 return ntstatus_to_werror(map_nt_error_from_tdb(terr));
2649 *pjobid = jobid;
2650 return WERR_OK;
2653 /***************************************************************************
2654 Append a jobid to the 'jobs added' list.
2655 ***************************************************************************/
2657 static bool add_to_jobs_added(struct tdb_print_db *pdb, uint32 jobid)
2659 TDB_DATA data;
2660 uint32 store_jobid;
2662 SIVAL(&store_jobid, 0, jobid);
2663 data.dptr = (uint8 *)&store_jobid;
2664 data.dsize = 4;
2666 DEBUG(10,("add_to_jobs_added: Added jobid %u\n", (unsigned int)jobid ));
2668 return (tdb_append(pdb->tdb, string_tdb_data("INFO/jobs_added"),
2669 data) == 0);
2673 /***************************************************************************
2674 Do all checks needed to determine if we can start a job.
2675 ***************************************************************************/
2677 static WERROR print_job_checks(const struct auth_session_info *server_info,
2678 struct messaging_context *msg_ctx,
2679 int snum, int *njobs)
2681 const char *sharename = lp_const_servicename(snum);
2682 uint64_t dspace, dsize;
2683 uint64_t minspace;
2684 int ret;
2686 if (!print_access_check(server_info, msg_ctx, snum,
2687 PRINTER_ACCESS_USE)) {
2688 DEBUG(3, ("print_job_checks: "
2689 "job start denied by security descriptor\n"));
2690 return WERR_ACCESS_DENIED;
2693 if (!print_time_access_check(server_info, msg_ctx, sharename)) {
2694 DEBUG(3, ("print_job_checks: "
2695 "job start denied by time check\n"));
2696 return WERR_ACCESS_DENIED;
2699 /* see if we have sufficient disk space */
2700 if (lp_minprintspace(snum)) {
2701 minspace = lp_minprintspace(snum);
2702 ret = sys_fsusage(lp_pathname(talloc_tos(), snum), &dspace, &dsize);
2703 if (ret == 0 && dspace < 2*minspace) {
2704 DEBUG(3, ("print_job_checks: "
2705 "disk space check failed.\n"));
2706 return WERR_NO_SPOOL_SPACE;
2710 /* for autoloaded printers, check that the printcap entry still exists */
2711 if (lp_autoloaded(snum) && !pcap_printername_ok(sharename)) {
2712 DEBUG(3, ("print_job_checks: printer name %s check failed.\n",
2713 sharename));
2714 return WERR_ACCESS_DENIED;
2717 /* Insure the maximum queue size is not violated */
2718 *njobs = print_queue_length(msg_ctx, snum, NULL);
2719 if (*njobs > lp_maxprintjobs(snum)) {
2720 DEBUG(3, ("print_job_checks: Queue %s number of jobs (%d) "
2721 "larger than max printjobs per queue (%d).\n",
2722 sharename, *njobs, lp_maxprintjobs(snum)));
2723 return WERR_NO_SPOOL_SPACE;
2726 return WERR_OK;
2729 /***************************************************************************
2730 Create a job file.
2731 ***************************************************************************/
2733 static WERROR print_job_spool_file(int snum, uint32_t jobid,
2734 const char *output_file,
2735 struct printjob *pjob)
2737 WERROR werr;
2738 SMB_STRUCT_STAT st;
2739 const char *path;
2740 int len;
2742 /* if this file is within the printer path, it means that smbd
2743 * is spooling it and will pass us control when it is finished.
2744 * Verify that the file name is ok, within path, and it is
2745 * already already there */
2746 if (output_file) {
2747 path = lp_pathname(talloc_tos(), snum);
2748 len = strlen(path);
2749 if (strncmp(output_file, path, len) == 0 &&
2750 (output_file[len - 1] == '/' || output_file[len] == '/')) {
2752 /* verify path is not too long */
2753 if (strlen(output_file) >= sizeof(pjob->filename)) {
2754 return WERR_INVALID_NAME;
2757 /* verify that the file exists */
2758 if (sys_stat(output_file, &st, false) != 0) {
2759 return WERR_INVALID_NAME;
2762 fstrcpy(pjob->filename, output_file);
2764 DEBUG(3, ("print_job_spool_file:"
2765 "External spooling activated"));
2767 /* we do not open the file until spooling is done */
2768 pjob->fd = -1;
2769 pjob->status = PJOB_SMBD_SPOOLING;
2771 return WERR_OK;
2775 slprintf(pjob->filename, sizeof(pjob->filename)-1,
2776 "%s/%sXXXXXX", lp_pathname(talloc_tos(), snum),
2777 PRINT_SPOOL_PREFIX);
2778 pjob->fd = mkstemp(pjob->filename);
2780 if (pjob->fd == -1) {
2781 werr = map_werror_from_unix(errno);
2782 if (W_ERROR_EQUAL(werr, WERR_ACCESS_DENIED)) {
2783 /* Common setup error, force a report. */
2784 DEBUG(0, ("print_job_spool_file: "
2785 "insufficient permissions to open spool "
2786 "file %s.\n", pjob->filename));
2787 } else {
2788 /* Normal case, report at level 3 and above. */
2789 DEBUG(3, ("print_job_spool_file: "
2790 "can't open spool file %s\n",
2791 pjob->filename));
2793 return werr;
2796 return WERR_OK;
2799 /***************************************************************************
2800 Start spooling a job - return the jobid.
2801 ***************************************************************************/
2803 WERROR print_job_start(const struct auth_session_info *server_info,
2804 struct messaging_context *msg_ctx,
2805 const char *clientmachine,
2806 int snum, const char *docname, const char *filename,
2807 struct spoolss_DeviceMode *devmode, uint32_t *_jobid)
2809 uint32_t jobid;
2810 char *path;
2811 struct printjob pjob;
2812 const char *sharename = lp_const_servicename(snum);
2813 struct tdb_print_db *pdb = get_print_db_byname(sharename);
2814 int njobs;
2815 WERROR werr;
2817 if (!pdb) {
2818 return WERR_INTERNAL_DB_CORRUPTION;
2821 path = lp_pathname(talloc_tos(), snum);
2823 werr = print_job_checks(server_info, msg_ctx, snum, &njobs);
2824 if (!W_ERROR_IS_OK(werr)) {
2825 release_print_db(pdb);
2826 return werr;
2829 DEBUG(10, ("print_job_start: "
2830 "Queue %s number of jobs (%d), max printjobs = %d\n",
2831 sharename, njobs, lp_maxprintjobs(snum)));
2833 werr = allocate_print_jobid(pdb, snum, sharename, &jobid);
2834 if (!W_ERROR_IS_OK(werr)) {
2835 goto fail;
2838 /* create the database entry */
2840 ZERO_STRUCT(pjob);
2842 pjob.pid = getpid();
2843 pjob.jobid = jobid;
2844 pjob.sysjob = -1;
2845 pjob.fd = -1;
2846 pjob.starttime = time(NULL);
2847 pjob.status = LPQ_SPOOLING;
2848 pjob.size = 0;
2849 pjob.spooled = False;
2850 pjob.smbjob = True;
2851 pjob.devmode = devmode;
2853 fstrcpy(pjob.jobname, docname);
2855 fstrcpy(pjob.clientmachine, clientmachine);
2857 fstrcpy(pjob.user, lp_printjob_username(snum));
2858 standard_sub_advanced(sharename, server_info->unix_info->sanitized_username,
2859 path, server_info->unix_token->gid,
2860 server_info->unix_info->sanitized_username,
2861 server_info->info->domain_name,
2862 pjob.user, sizeof(pjob.user));
2864 fstrcpy(pjob.queuename, lp_const_servicename(snum));
2866 /* we have a job entry - now create the spool file */
2867 werr = print_job_spool_file(snum, jobid, filename, &pjob);
2868 if (!W_ERROR_IS_OK(werr)) {
2869 goto fail;
2872 pjob_store(server_event_context(), msg_ctx, sharename, jobid, &pjob);
2874 /* Update the 'jobs added' entry used by print_queue_status. */
2875 add_to_jobs_added(pdb, jobid);
2877 /* Ensure we keep a rough count of the number of total jobs... */
2878 tdb_change_int32_atomic(pdb->tdb, "INFO/total_jobs", &njobs, 1);
2880 release_print_db(pdb);
2882 *_jobid = jobid;
2883 return WERR_OK;
2885 fail:
2886 if (jobid != -1) {
2887 pjob_delete(server_event_context(), msg_ctx, sharename, jobid);
2890 release_print_db(pdb);
2892 DEBUG(3, ("print_job_start: returning fail. "
2893 "Error = %s\n", win_errstr(werr)));
2894 return werr;
2897 /****************************************************************************
2898 Update the number of pages spooled to jobid
2899 ****************************************************************************/
2901 void print_job_endpage(struct messaging_context *msg_ctx,
2902 int snum, uint32 jobid)
2904 const char* sharename = lp_const_servicename(snum);
2905 struct printjob *pjob;
2906 TALLOC_CTX *tmp_ctx = talloc_new(msg_ctx);
2907 if (tmp_ctx == NULL) {
2908 return;
2911 pjob = print_job_find(tmp_ctx, sharename, jobid);
2912 if (!pjob) {
2913 goto err_out;
2915 /* don't allow another process to get this info - it is meaningless */
2916 if (pjob->pid != getpid()) {
2917 goto err_out;
2920 pjob->page_count++;
2921 pjob_store(server_event_context(), msg_ctx, sharename, jobid, pjob);
2922 err_out:
2923 talloc_free(tmp_ctx);
2926 /****************************************************************************
2927 Print a file - called on closing the file. This spools the job.
2928 If normal close is false then we're tearing down the jobs - treat as an
2929 error.
2930 ****************************************************************************/
2932 NTSTATUS print_job_end(struct messaging_context *msg_ctx, int snum,
2933 uint32 jobid, enum file_close_type close_type)
2935 const char* sharename = lp_const_servicename(snum);
2936 struct printjob *pjob;
2937 int ret;
2938 SMB_STRUCT_STAT sbuf;
2939 struct printif *current_printif = get_printer_fns(snum);
2940 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
2941 char *lpq_cmd;
2942 TALLOC_CTX *tmp_ctx = talloc_new(msg_ctx);
2943 if (tmp_ctx == NULL) {
2944 return NT_STATUS_NO_MEMORY;
2947 pjob = print_job_find(tmp_ctx, sharename, jobid);
2948 if (!pjob) {
2949 status = NT_STATUS_PRINT_CANCELLED;
2950 goto err_out;
2953 if (pjob->spooled || pjob->pid != getpid()) {
2954 status = NT_STATUS_ACCESS_DENIED;
2955 goto err_out;
2958 if (close_type == NORMAL_CLOSE || close_type == SHUTDOWN_CLOSE) {
2959 if (pjob->status == PJOB_SMBD_SPOOLING) {
2960 /* take over the file now, smbd is done */
2961 if (sys_stat(pjob->filename, &sbuf, false) != 0) {
2962 status = map_nt_error_from_unix(errno);
2963 DEBUG(3, ("print_job_end: "
2964 "stat file failed for jobid %d\n",
2965 jobid));
2966 goto fail;
2969 pjob->status = LPQ_SPOOLING;
2971 } else {
2973 if ((sys_fstat(pjob->fd, &sbuf, false) != 0)) {
2974 status = map_nt_error_from_unix(errno);
2975 close(pjob->fd);
2976 DEBUG(3, ("print_job_end: "
2977 "stat file failed for jobid %d\n",
2978 jobid));
2979 goto fail;
2982 close(pjob->fd);
2985 pjob->size = sbuf.st_ex_size;
2986 } else {
2989 * Not a normal close, something has gone wrong. Cleanup.
2991 if (pjob->fd != -1) {
2992 close(pjob->fd);
2994 goto fail;
2997 /* Technically, this is not quite right. If the printer has a separator
2998 * page turned on, the NT spooler prints the separator page even if the
2999 * print job is 0 bytes. 010215 JRR */
3000 if (pjob->size == 0 || pjob->status == LPQ_DELETING) {
3001 /* don't bother spooling empty files or something being deleted. */
3002 DEBUG(5,("print_job_end: canceling spool of %s (%s)\n",
3003 pjob->filename, pjob->size ? "deleted" : "zero length" ));
3004 unlink(pjob->filename);
3005 pjob_delete(server_event_context(), msg_ctx, sharename, jobid);
3006 return NT_STATUS_OK;
3009 /* don't strip out characters like '$' from the printername */
3010 lpq_cmd = talloc_string_sub2(tmp_ctx,
3011 lp_lpqcommand(talloc_tos(), snum),
3012 "%p",
3013 lp_printername(talloc_tos(), snum),
3014 false, false, false);
3015 if (lpq_cmd == NULL) {
3016 status = NT_STATUS_PRINT_CANCELLED;
3017 goto fail;
3019 lpq_cmd = talloc_sub_advanced(tmp_ctx,
3020 lp_servicename(talloc_tos(), snum),
3021 current_user_info.unix_name,
3023 current_user.ut.gid,
3024 get_current_username(),
3025 current_user_info.domain,
3026 lpq_cmd);
3027 if (lpq_cmd == NULL) {
3028 status = NT_STATUS_PRINT_CANCELLED;
3029 goto fail;
3032 ret = (*(current_printif->job_submit))(snum, pjob,
3033 current_printif->type, lpq_cmd);
3034 if (ret) {
3035 status = NT_STATUS_PRINT_CANCELLED;
3036 goto fail;
3039 /* The print job has been successfully handed over to the back-end */
3041 pjob->spooled = True;
3042 pjob->status = LPQ_QUEUED;
3043 pjob_store(server_event_context(), msg_ctx, sharename, jobid, pjob);
3045 /* make sure the database is up to date */
3046 if (print_cache_expired(lp_const_servicename(snum), True))
3047 print_queue_update(msg_ctx, snum, False);
3049 return NT_STATUS_OK;
3051 fail:
3053 /* The print job was not successfully started. Cleanup */
3054 /* Still need to add proper error return propagation! 010122:JRR */
3055 pjob->fd = -1;
3056 unlink(pjob->filename);
3057 pjob_delete(server_event_context(), msg_ctx, sharename, jobid);
3058 err_out:
3059 talloc_free(tmp_ctx);
3060 return status;
3063 /****************************************************************************
3064 Get a snapshot of jobs in the system without traversing.
3065 ****************************************************************************/
3067 static bool get_stored_queue_info(struct messaging_context *msg_ctx,
3068 struct tdb_print_db *pdb, int snum,
3069 int *pcount, print_queue_struct **ppqueue)
3071 TDB_DATA data, cgdata, jcdata;
3072 print_queue_struct *queue = NULL;
3073 uint32 qcount = 0;
3074 uint32 extra_count = 0;
3075 uint32_t changed_count = 0;
3076 int total_count = 0;
3077 size_t len = 0;
3078 uint32 i;
3079 int max_reported_jobs = lp_max_reported_jobs(snum);
3080 bool ret = false;
3081 const char* sharename = lp_servicename(talloc_tos(), snum);
3082 TALLOC_CTX *tmp_ctx = talloc_new(msg_ctx);
3083 if (tmp_ctx == NULL) {
3084 return false;
3087 /* make sure the database is up to date */
3088 if (print_cache_expired(lp_const_servicename(snum), True))
3089 print_queue_update(msg_ctx, snum, False);
3091 *pcount = 0;
3092 *ppqueue = NULL;
3094 ZERO_STRUCT(data);
3095 ZERO_STRUCT(cgdata);
3097 /* Get the stored queue data. */
3098 data = tdb_fetch_compat(pdb->tdb, string_tdb_data("INFO/linear_queue_array"));
3100 if (data.dptr && data.dsize >= sizeof(qcount))
3101 len += tdb_unpack(data.dptr + len, data.dsize - len, "d", &qcount);
3103 /* Get the added jobs list. */
3104 cgdata = tdb_fetch_compat(pdb->tdb, string_tdb_data("INFO/jobs_added"));
3105 if (cgdata.dptr != NULL && (cgdata.dsize % 4 == 0))
3106 extra_count = cgdata.dsize/4;
3108 /* Get the changed jobs list. */
3109 jcdata = tdb_fetch_compat(pdb->tdb, string_tdb_data("INFO/jobs_changed"));
3110 if (jcdata.dptr != NULL && (jcdata.dsize % 4 == 0))
3111 changed_count = jcdata.dsize / 4;
3113 DEBUG(5,("get_stored_queue_info: qcount = %u, extra_count = %u\n", (unsigned int)qcount, (unsigned int)extra_count));
3115 /* Allocate the queue size. */
3116 if (qcount == 0 && extra_count == 0)
3117 goto out;
3119 if ((queue = SMB_MALLOC_ARRAY(print_queue_struct, qcount + extra_count)) == NULL)
3120 goto out;
3122 /* Retrieve the linearised queue data. */
3124 for(i = 0; i < qcount; i++) {
3125 uint32 qjob, qsize, qpage_count, qstatus, qpriority, qtime;
3126 len += tdb_unpack(data.dptr + len, data.dsize - len, "ddddddff",
3127 &qjob,
3128 &qsize,
3129 &qpage_count,
3130 &qstatus,
3131 &qpriority,
3132 &qtime,
3133 queue[i].fs_user,
3134 queue[i].fs_file);
3135 queue[i].sysjob = qjob;
3136 queue[i].size = qsize;
3137 queue[i].page_count = qpage_count;
3138 queue[i].status = qstatus;
3139 queue[i].priority = qpriority;
3140 queue[i].time = qtime;
3143 total_count = qcount;
3145 /* Add new jobids to the queue. */
3146 for (i = 0; i < extra_count; i++) {
3147 uint32 jobid;
3148 struct printjob *pjob;
3150 jobid = IVAL(cgdata.dptr, i*4);
3151 DEBUG(5,("get_stored_queue_info: added job = %u\n", (unsigned int)jobid));
3152 pjob = print_job_find(tmp_ctx, lp_const_servicename(snum), jobid);
3153 if (!pjob) {
3154 DEBUG(5,("get_stored_queue_info: failed to find added job = %u\n", (unsigned int)jobid));
3155 remove_from_jobs_added(sharename, jobid);
3156 continue;
3159 queue[total_count].sysjob = pjob->sysjob;
3160 queue[total_count].size = pjob->size;
3161 queue[total_count].page_count = pjob->page_count;
3162 queue[total_count].status = pjob->status;
3163 queue[total_count].priority = 1;
3164 queue[total_count].time = pjob->starttime;
3165 fstrcpy(queue[total_count].fs_user, pjob->user);
3166 fstrcpy(queue[total_count].fs_file, pjob->jobname);
3167 total_count++;
3168 talloc_free(pjob);
3171 /* Update the changed jobids. */
3172 for (i = 0; i < changed_count; i++) {
3173 uint32_t jobid = IVAL(jcdata.dptr, i * 4);
3174 struct printjob *pjob;
3175 uint32_t j;
3176 bool found = false;
3178 pjob = print_job_find(tmp_ctx, sharename, jobid);
3179 if (pjob == NULL) {
3180 DEBUG(5,("get_stored_queue_info: failed to find "
3181 "changed job = %u\n",
3182 (unsigned int)jobid));
3183 remove_from_jobs_changed(sharename, jobid);
3184 continue;
3187 for (j = 0; j < total_count; j++) {
3188 if (queue[j].sysjob == pjob->sysjob) {
3189 found = true;
3190 break;
3194 if (found) {
3195 DEBUG(5,("get_stored_queue_info: changed job: %u\n",
3196 (unsigned int)jobid));
3198 queue[j].sysjob = pjob->sysjob;
3199 queue[j].size = pjob->size;
3200 queue[j].page_count = pjob->page_count;
3201 queue[j].status = pjob->status;
3202 queue[j].priority = 1;
3203 queue[j].time = pjob->starttime;
3204 fstrcpy(queue[j].fs_user, pjob->user);
3205 fstrcpy(queue[j].fs_file, pjob->jobname);
3206 talloc_free(pjob);
3208 DEBUG(5,("updated queue[%u], jobid: %u, sysjob: %u, "
3209 "jobname: %s\n",
3210 (unsigned int)j, (unsigned int)jobid,
3211 (unsigned int)queue[j].sysjob, pjob->jobname));
3214 remove_from_jobs_changed(sharename, jobid);
3217 /* Sort the queue by submission time otherwise they are displayed
3218 in hash order. */
3220 TYPESAFE_QSORT(queue, total_count, printjob_comp);
3222 DEBUG(5,("get_stored_queue_info: total_count = %u\n", (unsigned int)total_count));
3224 if (max_reported_jobs && total_count > max_reported_jobs)
3225 total_count = max_reported_jobs;
3227 *ppqueue = queue;
3228 *pcount = total_count;
3230 ret = true;
3232 out:
3234 SAFE_FREE(data.dptr);
3235 SAFE_FREE(cgdata.dptr);
3236 talloc_free(tmp_ctx);
3237 return ret;
3240 /****************************************************************************
3241 Get a printer queue listing.
3242 set queue = NULL and status = NULL if you just want to update the cache
3243 ****************************************************************************/
3245 int print_queue_status(struct messaging_context *msg_ctx, int snum,
3246 print_queue_struct **ppqueue,
3247 print_status_struct *status)
3249 fstring keystr;
3250 TDB_DATA data, key;
3251 const char *sharename;
3252 struct tdb_print_db *pdb;
3253 int count = 0;
3255 /* make sure the database is up to date */
3257 if (print_cache_expired(lp_const_servicename(snum), True))
3258 print_queue_update(msg_ctx, snum, False);
3260 /* return if we are done */
3261 if ( !ppqueue || !status )
3262 return 0;
3264 *ppqueue = NULL;
3265 sharename = lp_const_servicename(snum);
3266 pdb = get_print_db_byname(sharename);
3268 if (!pdb)
3269 return 0;
3272 * Fetch the queue status. We must do this first, as there may
3273 * be no jobs in the queue.
3276 ZERO_STRUCTP(status);
3277 slprintf(keystr, sizeof(keystr)-1, "STATUS/%s", sharename);
3278 key = string_tdb_data(keystr);
3280 data = tdb_fetch_compat(pdb->tdb, key);
3281 if (data.dptr) {
3282 if (data.dsize == sizeof(*status)) {
3283 /* this memcpy is ok since the status struct was
3284 not packed before storing it in the tdb */
3285 memcpy(status, data.dptr, sizeof(*status));
3287 SAFE_FREE(data.dptr);
3291 * Now, fetch the print queue information. We first count the number
3292 * of entries, and then only retrieve the queue if necessary.
3295 if (!get_stored_queue_info(msg_ctx, pdb, snum, &count, ppqueue)) {
3296 release_print_db(pdb);
3297 return 0;
3300 release_print_db(pdb);
3301 return count;
3304 /****************************************************************************
3305 Pause a queue.
3306 ****************************************************************************/
3308 WERROR print_queue_pause(const struct auth_session_info *server_info,
3309 struct messaging_context *msg_ctx, int snum)
3311 int ret;
3312 struct printif *current_printif = get_printer_fns( snum );
3314 if (!print_access_check(server_info, msg_ctx, snum,
3315 PRINTER_ACCESS_ADMINISTER)) {
3316 return WERR_ACCESS_DENIED;
3320 become_root();
3322 ret = (*(current_printif->queue_pause))(snum);
3324 unbecome_root();
3326 if (ret != 0) {
3327 return WERR_INVALID_PARAM;
3330 /* force update the database */
3331 print_cache_flush(lp_const_servicename(snum));
3333 /* Send a printer notify message */
3335 notify_printer_status(server_event_context(), msg_ctx, snum,
3336 PRINTER_STATUS_PAUSED);
3338 return WERR_OK;
3341 /****************************************************************************
3342 Resume a queue.
3343 ****************************************************************************/
3345 WERROR print_queue_resume(const struct auth_session_info *server_info,
3346 struct messaging_context *msg_ctx, int snum)
3348 int ret;
3349 struct printif *current_printif = get_printer_fns( snum );
3351 if (!print_access_check(server_info, msg_ctx, snum,
3352 PRINTER_ACCESS_ADMINISTER)) {
3353 return WERR_ACCESS_DENIED;
3356 become_root();
3358 ret = (*(current_printif->queue_resume))(snum);
3360 unbecome_root();
3362 if (ret != 0) {
3363 return WERR_INVALID_PARAM;
3366 /* make sure the database is up to date */
3367 if (print_cache_expired(lp_const_servicename(snum), True))
3368 print_queue_update(msg_ctx, snum, True);
3370 /* Send a printer notify message */
3372 notify_printer_status(server_event_context(), msg_ctx, snum,
3373 PRINTER_STATUS_OK);
3375 return WERR_OK;
3378 /****************************************************************************
3379 Purge a queue - implemented by deleting all jobs that we can delete.
3380 ****************************************************************************/
3382 WERROR print_queue_purge(const struct auth_session_info *server_info,
3383 struct messaging_context *msg_ctx, int snum)
3385 print_queue_struct *queue;
3386 print_status_struct status;
3387 int njobs, i;
3388 bool can_job_admin;
3390 /* Force and update so the count is accurate (i.e. not a cached count) */
3391 print_queue_update(msg_ctx, snum, True);
3393 can_job_admin = print_access_check(server_info,
3394 msg_ctx,
3395 snum,
3396 JOB_ACCESS_ADMINISTER);
3397 njobs = print_queue_status(msg_ctx, snum, &queue, &status);
3399 if ( can_job_admin )
3400 become_root();
3402 for (i = 0; i < njobs; i++) {
3403 struct tdb_print_db *pdb;
3404 int jobid;
3405 bool owner;
3406 pdb = get_print_db_byname(lp_const_servicename(snum));
3407 if (pdb == NULL) {
3408 DEBUG(1, ("failed to find printdb for %s\n",
3409 lp_const_servicename(snum)));
3410 continue;
3412 jobid = sysjob_to_jobid_pdb(pdb, queue[i].sysjob);
3413 if (jobid == (uint32_t)-1) {
3414 DEBUG(2, ("jobid for system job %d not found\n",
3415 queue[i].sysjob));
3416 continue; /* unix job */
3418 owner = is_owner(server_info, lp_const_servicename(snum),
3419 jobid);
3421 if (owner || can_job_admin) {
3422 print_job_delete1(server_event_context(), msg_ctx,
3423 snum, jobid);
3427 if ( can_job_admin )
3428 unbecome_root();
3430 /* update the cache */
3431 print_queue_update(msg_ctx, snum, True);
3433 SAFE_FREE(queue);
3435 return WERR_OK;