ctdb-logging: Separate out syslog and file logging backends
[Samba.git] / source3 / printing / printing.c
blobd8b619162e9b3c45e0b39cddbd6cf2c0a10f3670
1 /*
2 Unix SMB/Netbios implementation.
3 Version 3.0
4 printing backend routines
5 Copyright (C) Andrew Tridgell 1992-2000
6 Copyright (C) Jeremy Allison 2002
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include "includes.h"
23 #include "system/syslog.h"
24 #include "system/filesys.h"
25 #include "printing.h"
26 #include "../librpc/gen_ndr/ndr_spoolss.h"
27 #include "nt_printing.h"
28 #include "../librpc/gen_ndr/netlogon.h"
29 #include "printing/notify.h"
30 #include "printing/pcap.h"
31 #include "printing/printer_list.h"
32 #include "printing/queue_process.h"
33 #include "serverid.h"
34 #include "smbd/smbd.h"
35 #include "auth.h"
36 #include "messages.h"
37 #include "util_tdb.h"
38 #include "lib/param/loadparm.h"
40 extern struct current_user current_user;
41 extern userdom_struct current_user_info;
43 /* Current printer interface */
44 static bool remove_from_jobs_added(const char* sharename, uint32 jobid);
47 the printing backend revolves around a tdb database that stores the
48 SMB view of the print queue
50 The key for this database is a jobid - a internally generated number that
51 uniquely identifies a print job
53 reading the print queue involves two steps:
54 - possibly running lpq and updating the internal database from that
55 - reading entries from the database
57 jobids are assigned when a job starts spooling.
60 static TDB_CONTEXT *rap_tdb;
61 static uint16 next_rap_jobid;
62 struct rap_jobid_key {
63 fstring sharename;
64 uint32 jobid;
67 /***************************************************************************
68 Nightmare. LANMAN jobid's are 16 bit numbers..... We must map them to 32
69 bit RPC jobids.... JRA.
70 ***************************************************************************/
72 uint16 pjobid_to_rap(const char* sharename, uint32 jobid)
74 uint16 rap_jobid;
75 TDB_DATA data, key;
76 struct rap_jobid_key jinfo;
77 uint8 buf[2];
79 DEBUG(10,("pjobid_to_rap: called.\n"));
81 if (!rap_tdb) {
82 /* Create the in-memory tdb. */
83 rap_tdb = tdb_open_log(NULL, 0, TDB_INTERNAL, (O_RDWR|O_CREAT), 0644);
84 if (!rap_tdb)
85 return 0;
88 ZERO_STRUCT( jinfo );
89 fstrcpy( jinfo.sharename, sharename );
90 jinfo.jobid = jobid;
91 key.dptr = (uint8 *)&jinfo;
92 key.dsize = sizeof(jinfo);
94 data = tdb_fetch_compat(rap_tdb, key);
95 if (data.dptr && data.dsize == sizeof(uint16)) {
96 rap_jobid = SVAL(data.dptr, 0);
97 SAFE_FREE(data.dptr);
98 DEBUG(10,("pjobid_to_rap: jobid %u maps to RAP jobid %u\n",
99 (unsigned int)jobid, (unsigned int)rap_jobid));
100 return rap_jobid;
102 SAFE_FREE(data.dptr);
103 /* Not found - create and store mapping. */
104 rap_jobid = ++next_rap_jobid;
105 if (rap_jobid == 0)
106 rap_jobid = ++next_rap_jobid;
107 SSVAL(buf,0,rap_jobid);
108 data.dptr = buf;
109 data.dsize = sizeof(rap_jobid);
110 tdb_store(rap_tdb, key, data, TDB_REPLACE);
111 tdb_store(rap_tdb, data, key, TDB_REPLACE);
113 DEBUG(10,("pjobid_to_rap: created jobid %u maps to RAP jobid %u\n",
114 (unsigned int)jobid, (unsigned int)rap_jobid));
115 return rap_jobid;
118 bool rap_to_pjobid(uint16 rap_jobid, fstring sharename, uint32 *pjobid)
120 TDB_DATA data, key;
121 uint8 buf[2];
123 DEBUG(10,("rap_to_pjobid called.\n"));
125 if (!rap_tdb)
126 return False;
128 SSVAL(buf,0,rap_jobid);
129 key.dptr = buf;
130 key.dsize = sizeof(rap_jobid);
131 data = tdb_fetch_compat(rap_tdb, key);
132 if ( data.dptr && data.dsize == sizeof(struct rap_jobid_key) )
134 struct rap_jobid_key *jinfo = (struct rap_jobid_key*)data.dptr;
135 if (sharename != NULL) {
136 fstrcpy( sharename, jinfo->sharename );
138 *pjobid = jinfo->jobid;
139 DEBUG(10,("rap_to_pjobid: jobid %u maps to RAP jobid %u\n",
140 (unsigned int)*pjobid, (unsigned int)rap_jobid));
141 SAFE_FREE(data.dptr);
142 return True;
145 DEBUG(10,("rap_to_pjobid: Failed to lookup RAP jobid %u\n",
146 (unsigned int)rap_jobid));
147 SAFE_FREE(data.dptr);
148 return False;
151 void rap_jobid_delete(const char* sharename, uint32 jobid)
153 TDB_DATA key, data;
154 uint16 rap_jobid;
155 struct rap_jobid_key jinfo;
156 uint8 buf[2];
158 DEBUG(10,("rap_jobid_delete: called.\n"));
160 if (!rap_tdb)
161 return;
163 ZERO_STRUCT( jinfo );
164 fstrcpy( jinfo.sharename, sharename );
165 jinfo.jobid = jobid;
166 key.dptr = (uint8 *)&jinfo;
167 key.dsize = sizeof(jinfo);
169 data = tdb_fetch_compat(rap_tdb, key);
170 if (!data.dptr || (data.dsize != sizeof(uint16))) {
171 DEBUG(10,("rap_jobid_delete: cannot find jobid %u\n",
172 (unsigned int)jobid ));
173 SAFE_FREE(data.dptr);
174 return;
177 DEBUG(10,("rap_jobid_delete: deleting jobid %u\n",
178 (unsigned int)jobid ));
180 rap_jobid = SVAL(data.dptr, 0);
181 SAFE_FREE(data.dptr);
182 SSVAL(buf,0,rap_jobid);
183 data.dptr = buf;
184 data.dsize = sizeof(rap_jobid);
185 tdb_delete(rap_tdb, key);
186 tdb_delete(rap_tdb, data);
189 static int get_queue_status(const char* sharename, print_status_struct *);
191 /****************************************************************************
192 Initialise the printing backend. Called once at startup before the fork().
193 ****************************************************************************/
195 bool print_backend_init(struct messaging_context *msg_ctx)
197 const char *sversion = "INFO/version";
198 int services = lp_numservices();
199 int snum;
200 bool ok;
201 char *print_cache_path;
203 if (!printer_list_parent_init()) {
204 return false;
207 print_cache_path = cache_path("printing");
208 if (print_cache_path == NULL) {
209 return false;
211 ok = directory_create_or_exist(print_cache_path, 0755);
212 TALLOC_FREE(print_cache_path);
213 if (!ok) {
214 return false;
217 print_cache_path = cache_path("printing.tdb");
218 if (print_cache_path == NULL) {
219 return false;
221 unlink(print_cache_path);
222 TALLOC_FREE(print_cache_path);
224 /* handle a Samba upgrade */
226 for (snum = 0; snum < services; snum++) {
227 struct tdb_print_db *pdb;
228 if (!lp_printable(snum))
229 continue;
231 pdb = get_print_db_byname(lp_const_servicename(snum));
232 if (!pdb)
233 continue;
234 if (tdb_lock_bystring(pdb->tdb, sversion) != 0) {
235 DEBUG(0,("print_backend_init: Failed to open printer %s database\n", lp_const_servicename(snum) ));
236 release_print_db(pdb);
237 return False;
239 if (tdb_fetch_int32(pdb->tdb, sversion) != PRINT_DATABASE_VERSION) {
240 tdb_wipe_all(pdb->tdb);
241 tdb_store_int32(pdb->tdb, sversion, PRINT_DATABASE_VERSION);
243 tdb_unlock_bystring(pdb->tdb, sversion);
244 release_print_db(pdb);
247 close_all_print_db(); /* Don't leave any open. */
249 /* do NT print initialization... */
250 return nt_printing_init(msg_ctx);
253 /****************************************************************************
254 Shut down printing backend. Called once at shutdown to close the tdb.
255 ****************************************************************************/
257 void printing_end(void)
259 close_all_print_db(); /* Don't leave any open. */
262 /****************************************************************************
263 Retrieve the set of printing functions for a given service. This allows
264 us to set the printer function table based on the value of the 'printing'
265 service parameter.
267 Use the generic interface as the default and only use cups interface only
268 when asked for (and only when supported)
269 ****************************************************************************/
271 static struct printif *get_printer_fns_from_type( enum printing_types type )
273 struct printif *printer_fns = &generic_printif;
275 #ifdef HAVE_CUPS
276 if ( type == PRINT_CUPS ) {
277 printer_fns = &cups_printif;
279 #endif /* HAVE_CUPS */
281 #ifdef HAVE_IPRINT
282 if ( type == PRINT_IPRINT ) {
283 printer_fns = &iprint_printif;
285 #endif /* HAVE_IPRINT */
287 printer_fns->type = type;
289 return printer_fns;
292 static struct printif *get_printer_fns( int snum )
294 return get_printer_fns_from_type( (enum printing_types)lp_printing(snum) );
298 /****************************************************************************
299 Useful function to generate a tdb key.
300 ****************************************************************************/
302 static TDB_DATA print_key(uint32 jobid, uint32 *tmp)
304 TDB_DATA ret;
306 SIVAL(tmp, 0, jobid);
307 ret.dptr = (uint8 *)tmp;
308 ret.dsize = sizeof(*tmp);
309 return ret;
312 /****************************************************************************
313 Pack the devicemode to store it in a tdb.
314 ****************************************************************************/
315 static int pack_devicemode(struct spoolss_DeviceMode *devmode, uint8 *buf, int buflen)
317 enum ndr_err_code ndr_err;
318 DATA_BLOB blob;
319 int len = 0;
321 if (devmode) {
322 ndr_err = ndr_push_struct_blob(&blob, talloc_tos(),
323 devmode,
324 (ndr_push_flags_fn_t)
325 ndr_push_spoolss_DeviceMode);
326 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
327 DEBUG(10, ("pack_devicemode: "
328 "error encoding spoolss_DeviceMode\n"));
329 goto done;
331 } else {
332 ZERO_STRUCT(blob);
335 len = tdb_pack(buf, buflen, "B", blob.length, blob.data);
337 if (devmode) {
338 DEBUG(8, ("Packed devicemode [%s]\n", devmode->formname));
341 done:
342 return len;
345 /****************************************************************************
346 Unpack the devicemode to store it in a tdb.
347 ****************************************************************************/
348 static int unpack_devicemode(TALLOC_CTX *mem_ctx,
349 const uint8 *buf, int buflen,
350 struct spoolss_DeviceMode **devmode)
352 struct spoolss_DeviceMode *dm;
353 enum ndr_err_code ndr_err;
354 char *data = NULL;
355 int data_len = 0;
356 DATA_BLOB blob;
357 int len = 0;
359 *devmode = NULL;
361 len = tdb_unpack(buf, buflen, "B", &data_len, &data);
362 if (!data) {
363 return len;
366 dm = talloc_zero(mem_ctx, struct spoolss_DeviceMode);
367 if (!dm) {
368 goto done;
371 blob = data_blob_const(data, data_len);
373 ndr_err = ndr_pull_struct_blob(&blob, dm, dm,
374 (ndr_pull_flags_fn_t)ndr_pull_spoolss_DeviceMode);
375 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
376 DEBUG(10, ("unpack_devicemode: "
377 "error parsing spoolss_DeviceMode\n"));
378 goto done;
381 DEBUG(8, ("Unpacked devicemode [%s](%s)\n",
382 dm->devicename, dm->formname));
383 if (dm->driverextra_data.data) {
384 DEBUG(8, ("with a private section of %d bytes\n",
385 dm->__driverextra_length));
388 *devmode = dm;
390 done:
391 SAFE_FREE(data);
392 return len;
395 /***********************************************************************
396 unpack a pjob from a tdb buffer
397 ***********************************************************************/
399 static int unpack_pjob(TALLOC_CTX *mem_ctx, uint8 *buf, int buflen,
400 struct printjob *pjob)
402 int len = 0;
403 int used;
404 uint32 pjpid, pjjobid, pjsysjob, pjfd, pjstarttime, pjstatus;
405 uint32 pjsize, pjpage_count, pjspooled, pjsmbjob;
407 if (!buf || !pjob) {
408 return -1;
411 len += tdb_unpack(buf+len, buflen-len, "ddddddddddfffff",
412 &pjpid,
413 &pjjobid,
414 &pjsysjob,
415 &pjfd,
416 &pjstarttime,
417 &pjstatus,
418 &pjsize,
419 &pjpage_count,
420 &pjspooled,
421 &pjsmbjob,
422 pjob->filename,
423 pjob->jobname,
424 pjob->user,
425 pjob->clientmachine,
426 pjob->queuename);
428 if (len == -1) {
429 return -1;
432 used = unpack_devicemode(mem_ctx, buf+len, buflen-len, &pjob->devmode);
433 if (used == -1) {
434 return -1;
437 len += used;
439 pjob->pid = pjpid;
440 pjob->jobid = pjjobid;
441 pjob->sysjob = pjsysjob;
442 pjob->fd = pjfd;
443 pjob->starttime = pjstarttime;
444 pjob->status = pjstatus;
445 pjob->size = pjsize;
446 pjob->page_count = pjpage_count;
447 pjob->spooled = pjspooled;
448 pjob->smbjob = pjsmbjob;
450 return len;
454 /****************************************************************************
455 Useful function to find a print job in the database.
456 ****************************************************************************/
458 static struct printjob *print_job_find(TALLOC_CTX *mem_ctx,
459 const char *sharename,
460 uint32 jobid)
462 struct printjob *pjob;
463 uint32_t tmp;
464 TDB_DATA ret;
465 struct tdb_print_db *pdb = get_print_db_byname(sharename);
467 DEBUG(10,("print_job_find: looking up job %u for share %s\n",
468 (unsigned int)jobid, sharename ));
470 if (!pdb) {
471 return NULL;
474 ret = tdb_fetch_compat(pdb->tdb, print_key(jobid, &tmp));
475 release_print_db(pdb);
477 if (!ret.dptr) {
478 DEBUG(10, ("print_job_find: failed to find jobid %u.\n",
479 jobid));
480 return NULL;
483 pjob = talloc_zero(mem_ctx, struct printjob);
484 if (pjob == NULL) {
485 goto err_out;
488 if (unpack_pjob(mem_ctx, ret.dptr, ret.dsize, pjob) == -1) {
489 DEBUG(10, ("failed to unpack jobid %u.\n", jobid));
490 talloc_free(pjob);
491 pjob = NULL;
492 goto err_out;
495 DEBUG(10,("print_job_find: returning system job %d for jobid %u.\n",
496 pjob->sysjob, jobid));
497 SMB_ASSERT(pjob->jobid == jobid);
499 err_out:
500 SAFE_FREE(ret.dptr);
501 return pjob;
504 /* Convert a unix jobid to a smb jobid */
506 struct unixjob_traverse_state {
507 int sysjob;
508 uint32 sysjob_to_jobid_value;
511 static int unixjob_traverse_fn(TDB_CONTEXT *the_tdb, TDB_DATA key,
512 TDB_DATA data, void *private_data)
514 struct printjob *pjob;
515 struct unixjob_traverse_state *state =
516 (struct unixjob_traverse_state *)private_data;
518 if (!data.dptr || data.dsize == 0)
519 return 0;
521 pjob = (struct printjob *)data.dptr;
522 if (key.dsize != sizeof(uint32))
523 return 0;
525 if (state->sysjob == pjob->sysjob) {
526 state->sysjob_to_jobid_value = pjob->jobid;
527 return 1;
530 return 0;
533 uint32 sysjob_to_jobid_pdb(struct tdb_print_db *pdb, int sysjob)
535 struct unixjob_traverse_state state;
537 state.sysjob = sysjob;
538 state.sysjob_to_jobid_value = (uint32)-1;
540 tdb_traverse(pdb->tdb, unixjob_traverse_fn, &state);
542 return state.sysjob_to_jobid_value;
545 /****************************************************************************
546 This is a *horribly expensive call as we have to iterate through all the
547 current printer tdb's. Don't do this often ! JRA.
548 ****************************************************************************/
550 uint32 sysjob_to_jobid(int unix_jobid)
552 int services = lp_numservices();
553 int snum;
554 struct unixjob_traverse_state state;
556 state.sysjob = unix_jobid;
557 state.sysjob_to_jobid_value = (uint32)-1;
559 for (snum = 0; snum < services; snum++) {
560 struct tdb_print_db *pdb;
561 if (!lp_printable(snum))
562 continue;
563 pdb = get_print_db_byname(lp_const_servicename(snum));
564 if (!pdb) {
565 continue;
567 tdb_traverse(pdb->tdb, unixjob_traverse_fn, &state);
568 release_print_db(pdb);
569 if (state.sysjob_to_jobid_value != (uint32)-1)
570 return state.sysjob_to_jobid_value;
572 return (uint32)-1;
575 /****************************************************************************
576 Send notifications based on what has changed after a pjob_store.
577 ****************************************************************************/
579 static const struct {
580 uint32_t lpq_status;
581 uint32_t spoolss_status;
582 } lpq_to_spoolss_status_map[] = {
583 { LPQ_QUEUED, JOB_STATUS_QUEUED },
584 { LPQ_PAUSED, JOB_STATUS_PAUSED },
585 { LPQ_SPOOLING, JOB_STATUS_SPOOLING },
586 { LPQ_PRINTING, JOB_STATUS_PRINTING },
587 { LPQ_DELETING, JOB_STATUS_DELETING },
588 { LPQ_OFFLINE, JOB_STATUS_OFFLINE },
589 { LPQ_PAPEROUT, JOB_STATUS_PAPEROUT },
590 { LPQ_PRINTED, JOB_STATUS_PRINTED },
591 { LPQ_DELETED, JOB_STATUS_DELETED },
592 { LPQ_BLOCKED, JOB_STATUS_BLOCKED_DEVQ },
593 { LPQ_USER_INTERVENTION, JOB_STATUS_USER_INTERVENTION },
594 { (uint32_t)-1, 0 }
597 /* Convert a lpq status value stored in printing.tdb into the
598 appropriate win32 API constant. */
600 static uint32 map_to_spoolss_status(uint32 lpq_status)
602 int i = 0;
604 while (lpq_to_spoolss_status_map[i].lpq_status != -1) {
605 if (lpq_to_spoolss_status_map[i].lpq_status == lpq_status)
606 return lpq_to_spoolss_status_map[i].spoolss_status;
607 i++;
610 return 0;
613 /***************************************************************************
614 Append a jobid to the 'jobs changed' list.
615 ***************************************************************************/
617 static bool add_to_jobs_changed(struct tdb_print_db *pdb, uint32_t jobid)
619 TDB_DATA data;
620 uint32_t store_jobid;
622 SIVAL(&store_jobid, 0, jobid);
623 data.dptr = (uint8 *) &store_jobid;
624 data.dsize = 4;
626 DEBUG(10,("add_to_jobs_added: Added jobid %u\n", (unsigned int)jobid ));
628 return (tdb_append(pdb->tdb, string_tdb_data("INFO/jobs_changed"),
629 data) == 0);
632 /***************************************************************************
633 Remove a jobid from the 'jobs changed' list.
634 ***************************************************************************/
636 static bool remove_from_jobs_changed(const char* sharename, uint32_t jobid)
638 struct tdb_print_db *pdb = get_print_db_byname(sharename);
639 TDB_DATA data, key;
640 size_t job_count, i;
641 bool ret = False;
642 bool gotlock = False;
644 if (!pdb) {
645 return False;
648 ZERO_STRUCT(data);
650 key = string_tdb_data("INFO/jobs_changed");
652 if (tdb_chainlock_with_timeout(pdb->tdb, key, 5) != 0)
653 goto out;
655 gotlock = True;
657 data = tdb_fetch_compat(pdb->tdb, key);
659 if (data.dptr == NULL || data.dsize == 0 || (data.dsize % 4 != 0))
660 goto out;
662 job_count = data.dsize / 4;
663 for (i = 0; i < job_count; i++) {
664 uint32 ch_jobid;
666 ch_jobid = IVAL(data.dptr, i*4);
667 if (ch_jobid == jobid) {
668 if (i < job_count -1 )
669 memmove(data.dptr + (i*4), data.dptr + (i*4) + 4, (job_count - i - 1)*4 );
670 data.dsize -= 4;
671 if (tdb_store(pdb->tdb, key, data, TDB_REPLACE) != 0)
672 goto out;
673 break;
677 ret = True;
678 out:
680 if (gotlock)
681 tdb_chainunlock(pdb->tdb, key);
682 SAFE_FREE(data.dptr);
683 release_print_db(pdb);
684 if (ret)
685 DEBUG(10,("remove_from_jobs_changed: removed jobid %u\n", (unsigned int)jobid ));
686 else
687 DEBUG(10,("remove_from_jobs_changed: Failed to remove jobid %u\n", (unsigned int)jobid ));
688 return ret;
691 static void pjob_store_notify(struct tevent_context *ev,
692 struct messaging_context *msg_ctx,
693 const char* sharename, uint32 jobid,
694 struct printjob *old_data,
695 struct printjob *new_data,
696 bool *pchanged)
698 bool new_job = false;
699 bool changed = false;
701 if (old_data == NULL) {
702 new_job = true;
705 /* ACHTUNG! Due to a bug in Samba's spoolss parsing of the
706 NOTIFY_INFO_DATA buffer, we *have* to send the job submission
707 time first or else we'll end up with potential alignment
708 errors. I don't think the systemtime should be spooled as
709 a string, but this gets us around that error.
710 --jerry (i'll feel dirty for this) */
712 if (new_job) {
713 notify_job_submitted(ev, msg_ctx,
714 sharename, jobid, new_data->starttime);
715 notify_job_username(ev, msg_ctx,
716 sharename, jobid, new_data->user);
717 notify_job_name(ev, msg_ctx,
718 sharename, jobid, new_data->jobname);
719 notify_job_status(ev, msg_ctx,
720 sharename, jobid, map_to_spoolss_status(new_data->status));
721 notify_job_total_bytes(ev, msg_ctx,
722 sharename, jobid, new_data->size);
723 notify_job_total_pages(ev, msg_ctx,
724 sharename, jobid, new_data->page_count);
725 } else {
726 if (!strequal(old_data->jobname, new_data->jobname)) {
727 notify_job_name(ev, msg_ctx, sharename,
728 jobid, new_data->jobname);
729 changed = true;
732 if (old_data->status != new_data->status) {
733 notify_job_status(ev, msg_ctx,
734 sharename, jobid,
735 map_to_spoolss_status(new_data->status));
738 if (old_data->size != new_data->size) {
739 notify_job_total_bytes(ev, msg_ctx,
740 sharename, jobid, new_data->size);
743 if (old_data->page_count != new_data->page_count) {
744 notify_job_total_pages(ev, msg_ctx,
745 sharename, jobid,
746 new_data->page_count);
750 *pchanged = changed;
753 /****************************************************************************
754 Store a job structure back to the database.
755 ****************************************************************************/
757 static bool pjob_store(struct tevent_context *ev,
758 struct messaging_context *msg_ctx,
759 const char* sharename, uint32 jobid,
760 struct printjob *pjob)
762 uint32_t tmp;
763 TDB_DATA old_data, new_data;
764 bool ret = False;
765 struct tdb_print_db *pdb = get_print_db_byname(sharename);
766 uint8 *buf = NULL;
767 int len, newlen, buflen;
770 if (!pdb)
771 return False;
773 /* Get old data */
775 old_data = tdb_fetch_compat(pdb->tdb, print_key(jobid, &tmp));
777 /* Doh! Now we have to pack/unpack data since the NT_DEVICEMODE was added */
779 newlen = 0;
781 do {
782 len = 0;
783 buflen = newlen;
784 len += tdb_pack(buf+len, buflen-len, "ddddddddddfffff",
785 (uint32)pjob->pid,
786 (uint32)pjob->jobid,
787 (uint32)pjob->sysjob,
788 (uint32)pjob->fd,
789 (uint32)pjob->starttime,
790 (uint32)pjob->status,
791 (uint32)pjob->size,
792 (uint32)pjob->page_count,
793 (uint32)pjob->spooled,
794 (uint32)pjob->smbjob,
795 pjob->filename,
796 pjob->jobname,
797 pjob->user,
798 pjob->clientmachine,
799 pjob->queuename);
801 len += pack_devicemode(pjob->devmode, buf+len, buflen-len);
803 if (buflen != len) {
804 buf = (uint8 *)SMB_REALLOC(buf, len);
805 if (!buf) {
806 DEBUG(0,("pjob_store: failed to enlarge buffer!\n"));
807 goto done;
809 newlen = len;
811 } while ( buflen != len );
814 /* Store new data */
816 new_data.dptr = buf;
817 new_data.dsize = len;
818 ret = (tdb_store(pdb->tdb, print_key(jobid, &tmp), new_data,
819 TDB_REPLACE) == 0);
821 /* Send notify updates for what has changed */
823 if (ret) {
824 bool changed = false;
825 struct printjob old_pjob;
827 if (old_data.dsize) {
828 TALLOC_CTX *tmp_ctx = talloc_new(ev);
829 if (tmp_ctx == NULL)
830 goto done;
832 len = unpack_pjob(tmp_ctx, old_data.dptr,
833 old_data.dsize, &old_pjob);
834 if (len != -1 ) {
835 pjob_store_notify(ev,
836 msg_ctx,
837 sharename, jobid, &old_pjob,
838 pjob,
839 &changed);
840 if (changed) {
841 add_to_jobs_changed(pdb, jobid);
844 talloc_free(tmp_ctx);
846 } else {
847 /* new job */
848 pjob_store_notify(ev, msg_ctx,
849 sharename, jobid, NULL, pjob,
850 &changed);
854 done:
855 release_print_db(pdb);
856 SAFE_FREE( old_data.dptr );
857 SAFE_FREE( buf );
859 return ret;
862 /****************************************************************************
863 Remove a job structure from the database.
864 ****************************************************************************/
866 static void pjob_delete(struct tevent_context *ev,
867 struct messaging_context *msg_ctx,
868 const char* sharename, uint32 jobid)
870 uint32_t tmp;
871 struct printjob *pjob;
872 uint32 job_status = 0;
873 struct tdb_print_db *pdb;
874 TALLOC_CTX *tmp_ctx = talloc_new(ev);
875 if (tmp_ctx == NULL) {
876 return;
879 pdb = get_print_db_byname(sharename);
880 if (!pdb) {
881 goto err_out;
884 pjob = print_job_find(tmp_ctx, sharename, jobid);
885 if (!pjob) {
886 DEBUG(5, ("we were asked to delete nonexistent job %u\n",
887 jobid));
888 goto err_release;
891 /* We must cycle through JOB_STATUS_DELETING and
892 JOB_STATUS_DELETED for the port monitor to delete the job
893 properly. */
895 job_status = JOB_STATUS_DELETING|JOB_STATUS_DELETED;
896 notify_job_status(ev, msg_ctx, sharename, jobid, job_status);
898 /* Remove from printing.tdb */
900 tdb_delete(pdb->tdb, print_key(jobid, &tmp));
901 remove_from_jobs_added(sharename, jobid);
902 rap_jobid_delete(sharename, jobid);
903 err_release:
904 release_print_db(pdb);
905 err_out:
906 talloc_free(tmp_ctx);
909 /****************************************************************************
910 List a unix job in the print database.
911 ****************************************************************************/
913 static void print_unix_job(struct tevent_context *ev,
914 struct messaging_context *msg_ctx,
915 const char *sharename, print_queue_struct *q,
916 uint32 jobid)
918 struct printjob pj, *old_pj;
919 TALLOC_CTX *tmp_ctx = talloc_new(ev);
920 if (tmp_ctx == NULL) {
921 return;
924 if (jobid == (uint32)-1) {
925 jobid = q->sysjob + UNIX_JOB_START;
928 /* Preserve the timestamp on an existing unix print job */
930 old_pj = print_job_find(tmp_ctx, sharename, jobid);
932 ZERO_STRUCT(pj);
934 pj.pid = (pid_t)-1;
935 pj.jobid = jobid;
936 pj.sysjob = q->sysjob;
937 pj.fd = -1;
938 pj.starttime = old_pj ? old_pj->starttime : q->time;
939 pj.status = q->status;
940 pj.size = q->size;
941 pj.spooled = True;
942 fstrcpy(pj.filename, old_pj ? old_pj->filename : "");
943 if (jobid < UNIX_JOB_START) {
944 pj.smbjob = True;
945 fstrcpy(pj.jobname, old_pj ? old_pj->jobname : "Remote Downlevel Document");
946 } else {
947 pj.smbjob = False;
948 fstrcpy(pj.jobname, old_pj ? old_pj->jobname : q->fs_file);
950 fstrcpy(pj.user, old_pj ? old_pj->user : q->fs_user);
951 fstrcpy(pj.queuename, old_pj ? old_pj->queuename : sharename );
953 pjob_store(ev, msg_ctx, sharename, jobid, &pj);
954 talloc_free(tmp_ctx);
958 struct traverse_struct {
959 print_queue_struct *queue;
960 int qcount, snum, maxcount, total_jobs;
961 const char *sharename;
962 time_t lpq_time;
963 const char *lprm_command;
964 struct printif *print_if;
965 struct tevent_context *ev;
966 struct messaging_context *msg_ctx;
967 TALLOC_CTX *mem_ctx;
970 /****************************************************************************
971 Utility fn to delete any jobs that are no longer active.
972 ****************************************************************************/
974 static int traverse_fn_delete(TDB_CONTEXT *t, TDB_DATA key, TDB_DATA data, void *state)
976 struct traverse_struct *ts = (struct traverse_struct *)state;
977 struct printjob pjob;
978 uint32 jobid;
979 int i = 0;
981 if ( key.dsize != sizeof(jobid) )
982 return 0;
984 if (unpack_pjob(ts->mem_ctx, data.dptr, data.dsize, &pjob) == -1)
985 return 0;
986 talloc_free(pjob.devmode);
987 jobid = pjob.jobid;
989 if (!pjob.smbjob) {
990 /* remove a unix job if it isn't in the system queue any more */
991 for (i=0;i<ts->qcount;i++) {
992 if (ts->queue[i].sysjob == pjob.sysjob) {
993 break;
996 if (i == ts->qcount) {
997 DEBUG(10,("traverse_fn_delete: pjob %u deleted due to !smbjob\n",
998 (unsigned int)jobid ));
999 pjob_delete(ts->ev, ts->msg_ctx,
1000 ts->sharename, jobid);
1001 return 0;
1004 /* need to continue the the bottom of the function to
1005 save the correct attributes */
1008 /* maybe it hasn't been spooled yet */
1009 if (!pjob.spooled) {
1010 /* if a job is not spooled and the process doesn't
1011 exist then kill it. This cleans up after smbd
1012 deaths */
1013 if (!process_exists_by_pid(pjob.pid)) {
1014 DEBUG(10,("traverse_fn_delete: pjob %u deleted due to !process_exists (%u)\n",
1015 (unsigned int)jobid, (unsigned int)pjob.pid ));
1016 pjob_delete(ts->ev, ts->msg_ctx,
1017 ts->sharename, jobid);
1018 } else
1019 ts->total_jobs++;
1020 return 0;
1023 /* this check only makes sense for jobs submitted from Windows clients */
1025 if (pjob.smbjob) {
1026 for (i=0;i<ts->qcount;i++) {
1027 if ( pjob.status == LPQ_DELETED )
1028 continue;
1030 if (ts->queue[i].sysjob == pjob.sysjob) {
1032 /* try to clean up any jobs that need to be deleted */
1034 if ( pjob.status == LPQ_DELETING ) {
1035 int result;
1037 result = (*(ts->print_if->job_delete))(
1038 ts->sharename, ts->lprm_command, &pjob );
1040 if ( result != 0 ) {
1041 /* if we can't delete, then reset the job status */
1042 pjob.status = LPQ_QUEUED;
1043 pjob_store(ts->ev, ts->msg_ctx,
1044 ts->sharename, jobid, &pjob);
1046 else {
1047 /* if we deleted the job, the remove the tdb record */
1048 pjob_delete(ts->ev,
1049 ts->msg_ctx,
1050 ts->sharename, jobid);
1051 pjob.status = LPQ_DELETED;
1056 break;
1061 /* The job isn't in the system queue - we have to assume it has
1062 completed, so delete the database entry. */
1064 if (i == ts->qcount) {
1066 /* A race can occur between the time a job is spooled and
1067 when it appears in the lpq output. This happens when
1068 the job is added to printing.tdb when another smbd
1069 running print_queue_update() has completed a lpq and
1070 is currently traversing the printing tdb and deleting jobs.
1071 Don't delete the job if it was submitted after the lpq_time. */
1073 if (pjob.starttime < ts->lpq_time) {
1074 DEBUG(10,("traverse_fn_delete: pjob %u deleted due to pjob.starttime (%u) < ts->lpq_time (%u)\n",
1075 (unsigned int)jobid,
1076 (unsigned int)pjob.starttime,
1077 (unsigned int)ts->lpq_time ));
1078 pjob_delete(ts->ev, ts->msg_ctx,
1079 ts->sharename, jobid);
1080 } else
1081 ts->total_jobs++;
1082 return 0;
1085 /* Save the pjob attributes we will store. */
1086 ts->queue[i].sysjob = pjob.sysjob;
1087 ts->queue[i].size = pjob.size;
1088 ts->queue[i].page_count = pjob.page_count;
1089 ts->queue[i].status = pjob.status;
1090 ts->queue[i].priority = 1;
1091 ts->queue[i].time = pjob.starttime;
1092 fstrcpy(ts->queue[i].fs_user, pjob.user);
1093 fstrcpy(ts->queue[i].fs_file, pjob.jobname);
1095 ts->total_jobs++;
1097 return 0;
1100 /****************************************************************************
1101 Check if the print queue has been updated recently enough.
1102 ****************************************************************************/
1104 static void print_cache_flush(const char *sharename)
1106 fstring key;
1107 struct tdb_print_db *pdb = get_print_db_byname(sharename);
1109 if (!pdb)
1110 return;
1111 slprintf(key, sizeof(key)-1, "CACHE/%s", sharename);
1112 tdb_store_int32(pdb->tdb, key, -1);
1113 release_print_db(pdb);
1116 /****************************************************************************
1117 Check if someone already thinks they are doing the update.
1118 ****************************************************************************/
1120 static pid_t get_updating_pid(const char *sharename)
1122 fstring keystr;
1123 TDB_DATA data, key;
1124 pid_t updating_pid;
1125 struct tdb_print_db *pdb = get_print_db_byname(sharename);
1127 if (!pdb)
1128 return (pid_t)-1;
1129 slprintf(keystr, sizeof(keystr)-1, "UPDATING/%s", sharename);
1130 key = string_tdb_data(keystr);
1132 data = tdb_fetch_compat(pdb->tdb, key);
1133 release_print_db(pdb);
1134 if (!data.dptr || data.dsize != sizeof(pid_t)) {
1135 SAFE_FREE(data.dptr);
1136 return (pid_t)-1;
1139 updating_pid = IVAL(data.dptr, 0);
1140 SAFE_FREE(data.dptr);
1142 if (process_exists_by_pid(updating_pid))
1143 return updating_pid;
1145 return (pid_t)-1;
1148 /****************************************************************************
1149 Set the fact that we're doing the update, or have finished doing the update
1150 in the tdb.
1151 ****************************************************************************/
1153 static void set_updating_pid(const fstring sharename, bool updating)
1155 fstring keystr;
1156 TDB_DATA key;
1157 TDB_DATA data;
1158 pid_t updating_pid = getpid();
1159 uint8 buffer[4];
1161 struct tdb_print_db *pdb = get_print_db_byname(sharename);
1163 if (!pdb)
1164 return;
1166 slprintf(keystr, sizeof(keystr)-1, "UPDATING/%s", sharename);
1167 key = string_tdb_data(keystr);
1169 DEBUG(5, ("set_updating_pid: %supdating lpq cache for print share %s\n",
1170 updating ? "" : "not ",
1171 sharename ));
1173 if ( !updating ) {
1174 tdb_delete(pdb->tdb, key);
1175 release_print_db(pdb);
1176 return;
1179 SIVAL( buffer, 0, updating_pid);
1180 data.dptr = buffer;
1181 data.dsize = 4; /* we always assume this is a 4 byte value */
1183 tdb_store(pdb->tdb, key, data, TDB_REPLACE);
1184 release_print_db(pdb);
1187 /****************************************************************************
1188 Sort print jobs by submittal time.
1189 ****************************************************************************/
1191 static int printjob_comp(print_queue_struct *j1, print_queue_struct *j2)
1193 /* Silly cases */
1195 if (!j1 && !j2)
1196 return 0;
1197 if (!j1)
1198 return -1;
1199 if (!j2)
1200 return 1;
1202 /* Sort on job start time */
1204 if (j1->time == j2->time)
1205 return 0;
1206 return (j1->time > j2->time) ? 1 : -1;
1209 /****************************************************************************
1210 Store the sorted queue representation for later portmon retrieval.
1211 Skip deleted jobs
1212 ****************************************************************************/
1214 static void store_queue_struct(struct tdb_print_db *pdb, struct traverse_struct *pts)
1216 TDB_DATA data;
1217 int max_reported_jobs = lp_max_reported_print_jobs(pts->snum);
1218 print_queue_struct *queue = pts->queue;
1219 size_t len;
1220 size_t i;
1221 unsigned int qcount;
1223 if (max_reported_jobs && (max_reported_jobs < pts->qcount))
1224 pts->qcount = max_reported_jobs;
1225 qcount = 0;
1227 /* Work out the size. */
1228 data.dsize = 0;
1229 data.dsize += tdb_pack(NULL, 0, "d", qcount);
1231 for (i = 0; i < pts->qcount; i++) {
1232 if ( queue[i].status == LPQ_DELETED )
1233 continue;
1235 qcount++;
1236 data.dsize += tdb_pack(NULL, 0, "ddddddff",
1237 (uint32)queue[i].sysjob,
1238 (uint32)queue[i].size,
1239 (uint32)queue[i].page_count,
1240 (uint32)queue[i].status,
1241 (uint32)queue[i].priority,
1242 (uint32)queue[i].time,
1243 queue[i].fs_user,
1244 queue[i].fs_file);
1247 if ((data.dptr = (uint8 *)SMB_MALLOC(data.dsize)) == NULL)
1248 return;
1250 len = 0;
1251 len += tdb_pack(data.dptr + len, data.dsize - len, "d", qcount);
1252 for (i = 0; i < pts->qcount; i++) {
1253 if ( queue[i].status == LPQ_DELETED )
1254 continue;
1256 len += tdb_pack(data.dptr + len, data.dsize - len, "ddddddff",
1257 (uint32)queue[i].sysjob,
1258 (uint32)queue[i].size,
1259 (uint32)queue[i].page_count,
1260 (uint32)queue[i].status,
1261 (uint32)queue[i].priority,
1262 (uint32)queue[i].time,
1263 queue[i].fs_user,
1264 queue[i].fs_file);
1267 tdb_store(pdb->tdb, string_tdb_data("INFO/linear_queue_array"), data,
1268 TDB_REPLACE);
1269 SAFE_FREE(data.dptr);
1270 return;
1273 static TDB_DATA get_jobs_added_data(struct tdb_print_db *pdb)
1275 TDB_DATA data;
1277 ZERO_STRUCT(data);
1279 data = tdb_fetch_compat(pdb->tdb, string_tdb_data("INFO/jobs_added"));
1280 if (data.dptr == NULL || data.dsize == 0 || (data.dsize % 4 != 0)) {
1281 SAFE_FREE(data.dptr);
1282 ZERO_STRUCT(data);
1285 return data;
1288 static void check_job_added(const char *sharename, TDB_DATA data, uint32 jobid)
1290 unsigned int i;
1291 unsigned int job_count = data.dsize / 4;
1293 for (i = 0; i < job_count; i++) {
1294 uint32 ch_jobid;
1296 ch_jobid = IVAL(data.dptr, i*4);
1297 if (ch_jobid == jobid)
1298 remove_from_jobs_added(sharename, jobid);
1302 /****************************************************************************
1303 Check if the print queue has been updated recently enough.
1304 ****************************************************************************/
1306 static bool print_cache_expired(const char *sharename, bool check_pending)
1308 fstring key;
1309 time_t last_qscan_time, time_now = time(NULL);
1310 struct tdb_print_db *pdb = get_print_db_byname(sharename);
1311 bool result = False;
1313 if (!pdb)
1314 return False;
1316 snprintf(key, sizeof(key), "CACHE/%s", sharename);
1317 last_qscan_time = (time_t)tdb_fetch_int32(pdb->tdb, key);
1320 * Invalidate the queue for 3 reasons.
1321 * (1). last queue scan time == -1.
1322 * (2). Current time - last queue scan time > allowed cache time.
1323 * (3). last queue scan time > current time + MAX_CACHE_VALID_TIME (1 hour by default).
1324 * This last test picks up machines for which the clock has been moved
1325 * forward, an lpq scan done and then the clock moved back. Otherwise
1326 * that last lpq scan would stay around for a loooong loooong time... :-). JRA.
1329 if (last_qscan_time == ((time_t)-1)
1330 || (time_now - last_qscan_time) >= lp_lpq_cache_time()
1331 || last_qscan_time > (time_now + MAX_CACHE_VALID_TIME))
1333 uint32 u;
1334 time_t msg_pending_time;
1336 DEBUG(4, ("print_cache_expired: cache expired for queue %s "
1337 "(last_qscan_time = %d, time now = %d, qcachetime = %d)\n",
1338 sharename, (int)last_qscan_time, (int)time_now,
1339 (int)lp_lpq_cache_time() ));
1341 /* check if another smbd has already sent a message to update the
1342 queue. Give the pending message one minute to clear and
1343 then send another message anyways. Make sure to check for
1344 clocks that have been run forward and then back again. */
1346 snprintf(key, sizeof(key), "MSG_PENDING/%s", sharename);
1348 if ( check_pending
1349 && tdb_fetch_uint32( pdb->tdb, key, &u )
1350 && (msg_pending_time=u) > 0
1351 && msg_pending_time <= time_now
1352 && (time_now - msg_pending_time) < 60 )
1354 DEBUG(4,("print_cache_expired: message already pending for %s. Accepting cache\n",
1355 sharename));
1356 goto done;
1359 result = True;
1362 done:
1363 release_print_db(pdb);
1364 return result;
1367 /****************************************************************************
1368 main work for updating the lpq cache for a printer queue
1369 ****************************************************************************/
1371 static void print_queue_update_internal(struct tevent_context *ev,
1372 struct messaging_context *msg_ctx,
1373 const char *sharename,
1374 struct printif *current_printif,
1375 char *lpq_command, char *lprm_command)
1377 int i, qcount;
1378 print_queue_struct *queue = NULL;
1379 print_status_struct status;
1380 print_status_struct old_status;
1381 struct printjob *pjob;
1382 struct traverse_struct tstruct;
1383 TDB_DATA data, key;
1384 TDB_DATA jcdata;
1385 fstring keystr, cachestr;
1386 struct tdb_print_db *pdb = get_print_db_byname(sharename);
1387 TALLOC_CTX *tmp_ctx = talloc_new(ev);
1389 if ((pdb == NULL) || (tmp_ctx == NULL)) {
1390 return;
1393 DEBUG(5,("print_queue_update_internal: printer = %s, type = %d, lpq command = [%s]\n",
1394 sharename, current_printif->type, lpq_command));
1397 * Update the cache time FIRST ! Stops others even
1398 * attempting to get the lock and doing this
1399 * if the lpq takes a long time.
1402 slprintf(cachestr, sizeof(cachestr)-1, "CACHE/%s", sharename);
1403 tdb_store_int32(pdb->tdb, cachestr, (int)time(NULL));
1405 /* get the current queue using the appropriate interface */
1406 ZERO_STRUCT(status);
1408 qcount = (*(current_printif->queue_get))(sharename,
1409 current_printif->type,
1410 lpq_command, &queue, &status);
1412 DEBUG(3, ("print_queue_update_internal: %d job%s in queue for %s\n",
1413 qcount, (qcount != 1) ? "s" : "", sharename));
1415 /* Sort the queue by submission time otherwise they are displayed
1416 in hash order. */
1418 TYPESAFE_QSORT(queue, qcount, printjob_comp);
1421 any job in the internal database that is marked as spooled
1422 and doesn't exist in the system queue is considered finished
1423 and removed from the database
1425 any job in the system database but not in the internal database
1426 is added as a unix job
1428 fill in any system job numbers as we go
1430 jcdata = get_jobs_added_data(pdb);
1432 for (i=0; i<qcount; i++) {
1433 uint32 jobid = sysjob_to_jobid_pdb(pdb, queue[i].sysjob);
1434 if (jobid == (uint32)-1) {
1435 /* assume its a unix print job */
1436 print_unix_job(ev, msg_ctx,
1437 sharename, &queue[i], jobid);
1438 continue;
1441 /* we have an active SMB print job - update its status */
1442 pjob = print_job_find(tmp_ctx, sharename, jobid);
1443 if (!pjob) {
1444 /* err, somethings wrong. Probably smbd was restarted
1445 with jobs in the queue. All we can do is treat them
1446 like unix jobs. Pity. */
1447 DEBUG(1, ("queued print job %d not found in jobs list, "
1448 "assuming unix job\n", jobid));
1449 print_unix_job(ev, msg_ctx,
1450 sharename, &queue[i], jobid);
1451 continue;
1454 /* don't reset the status on jobs to be deleted */
1456 if ( pjob->status != LPQ_DELETING )
1457 pjob->status = queue[i].status;
1459 pjob_store(ev, msg_ctx, sharename, jobid, pjob);
1461 check_job_added(sharename, jcdata, jobid);
1464 SAFE_FREE(jcdata.dptr);
1466 /* now delete any queued entries that don't appear in the
1467 system queue */
1468 tstruct.queue = queue;
1469 tstruct.qcount = qcount;
1470 tstruct.snum = -1;
1471 tstruct.total_jobs = 0;
1472 tstruct.lpq_time = time(NULL);
1473 tstruct.sharename = sharename;
1474 tstruct.lprm_command = lprm_command;
1475 tstruct.print_if = current_printif;
1476 tstruct.ev = ev;
1477 tstruct.msg_ctx = msg_ctx;
1478 tstruct.mem_ctx = tmp_ctx;
1480 tdb_traverse(pdb->tdb, traverse_fn_delete, (void *)&tstruct);
1482 /* Store the linearised queue, max jobs only. */
1483 store_queue_struct(pdb, &tstruct);
1485 SAFE_FREE(tstruct.queue);
1486 talloc_free(tmp_ctx);
1488 DEBUG(10,("print_queue_update_internal: printer %s INFO/total_jobs = %d\n",
1489 sharename, tstruct.total_jobs ));
1491 tdb_store_int32(pdb->tdb, "INFO/total_jobs", tstruct.total_jobs);
1493 get_queue_status(sharename, &old_status);
1494 if (old_status.qcount != qcount)
1495 DEBUG(10,("print_queue_update_internal: queue status change %d jobs -> %d jobs for printer %s\n",
1496 old_status.qcount, qcount, sharename));
1498 /* store the new queue status structure */
1499 slprintf(keystr, sizeof(keystr)-1, "STATUS/%s", sharename);
1500 key = string_tdb_data(keystr);
1502 status.qcount = qcount;
1503 data.dptr = (uint8 *)&status;
1504 data.dsize = sizeof(status);
1505 tdb_store(pdb->tdb, key, data, TDB_REPLACE);
1508 * Update the cache time again. We want to do this call
1509 * as little as possible...
1512 slprintf(keystr, sizeof(keystr)-1, "CACHE/%s", sharename);
1513 tdb_store_int32(pdb->tdb, keystr, (int32)time(NULL));
1515 /* clear the msg pending record for this queue */
1517 snprintf(keystr, sizeof(keystr), "MSG_PENDING/%s", sharename);
1519 if ( !tdb_store_uint32( pdb->tdb, keystr, 0 ) ) {
1520 /* log a message but continue on */
1522 DEBUG(0,("print_queue_update: failed to store MSG_PENDING flag for [%s]!\n",
1523 sharename));
1526 release_print_db( pdb );
1528 return;
1531 /****************************************************************************
1532 Update the internal database from the system print queue for a queue.
1533 obtain a lock on the print queue before proceeding (needed when mutiple
1534 smbd processes maytry to update the lpq cache concurrently).
1535 ****************************************************************************/
1537 static void print_queue_update_with_lock( struct tevent_context *ev,
1538 struct messaging_context *msg_ctx,
1539 const char *sharename,
1540 struct printif *current_printif,
1541 char *lpq_command, char *lprm_command )
1543 fstring keystr;
1544 struct tdb_print_db *pdb;
1546 DEBUG(5,("print_queue_update_with_lock: printer share = %s\n", sharename));
1547 pdb = get_print_db_byname(sharename);
1548 if (!pdb)
1549 return;
1551 if ( !print_cache_expired(sharename, False) ) {
1552 DEBUG(5,("print_queue_update_with_lock: print cache for %s is still ok\n", sharename));
1553 release_print_db(pdb);
1554 return;
1558 * Check to see if someone else is doing this update.
1559 * This is essentially a mutex on the update.
1562 if (get_updating_pid(sharename) != -1) {
1563 release_print_db(pdb);
1564 return;
1567 /* Lock the queue for the database update */
1569 slprintf(keystr, sizeof(keystr) - 1, "LOCK/%s", sharename);
1570 /* Only wait 10 seconds for this. */
1571 if (tdb_lock_bystring_with_timeout(pdb->tdb, keystr, 10) != 0) {
1572 DEBUG(0,("print_queue_update_with_lock: Failed to lock printer %s database\n", sharename));
1573 release_print_db(pdb);
1574 return;
1578 * Ensure that no one else got in here.
1579 * If the updating pid is still -1 then we are
1580 * the winner.
1583 if (get_updating_pid(sharename) != -1) {
1585 * Someone else is doing the update, exit.
1587 tdb_unlock_bystring(pdb->tdb, keystr);
1588 release_print_db(pdb);
1589 return;
1593 * We're going to do the update ourselves.
1596 /* Tell others we're doing the update. */
1597 set_updating_pid(sharename, True);
1600 * Allow others to enter and notice we're doing
1601 * the update.
1604 tdb_unlock_bystring(pdb->tdb, keystr);
1606 /* do the main work now */
1608 print_queue_update_internal(ev, msg_ctx,
1609 sharename, current_printif,
1610 lpq_command, lprm_command);
1612 /* Delete our pid from the db. */
1613 set_updating_pid(sharename, False);
1614 release_print_db(pdb);
1617 /****************************************************************************
1618 this is the receive function of the background lpq updater
1619 ****************************************************************************/
1620 void print_queue_receive(struct messaging_context *msg,
1621 void *private_data,
1622 uint32_t msg_type,
1623 struct server_id server_id,
1624 DATA_BLOB *data)
1626 fstring sharename;
1627 char *lpqcommand = NULL, *lprmcommand = NULL;
1628 int printing_type;
1629 size_t len;
1631 len = tdb_unpack( (uint8 *)data->data, data->length, "fdPP",
1632 sharename,
1633 &printing_type,
1634 &lpqcommand,
1635 &lprmcommand );
1637 if ( len == -1 ) {
1638 SAFE_FREE(lpqcommand);
1639 SAFE_FREE(lprmcommand);
1640 DEBUG(0,("print_queue_receive: Got invalid print queue update message\n"));
1641 return;
1644 print_queue_update_with_lock(server_event_context(), msg, sharename,
1645 get_printer_fns_from_type((enum printing_types)printing_type),
1646 lpqcommand, lprmcommand );
1648 SAFE_FREE(lpqcommand);
1649 SAFE_FREE(lprmcommand);
1650 return;
1653 /****************************************************************************
1654 update the internal database from the system print queue for a queue
1655 ****************************************************************************/
1657 extern pid_t background_lpq_updater_pid;
1659 static void print_queue_update(struct messaging_context *msg_ctx,
1660 int snum, bool force)
1662 fstring key;
1663 fstring sharename;
1664 char *lpqcommand = NULL;
1665 char *lprmcommand = NULL;
1666 uint8 *buffer = NULL;
1667 size_t len = 0;
1668 size_t newlen;
1669 struct tdb_print_db *pdb;
1670 int type;
1671 struct printif *current_printif;
1672 TALLOC_CTX *ctx = talloc_tos();
1674 fstrcpy( sharename, lp_const_servicename(snum));
1676 /* don't strip out characters like '$' from the printername */
1678 lpqcommand = talloc_string_sub2(ctx,
1679 lp_lpq_command(talloc_tos(), snum),
1680 "%p",
1681 lp_printername(talloc_tos(), snum),
1682 false, false, false);
1683 if (!lpqcommand) {
1684 return;
1686 lpqcommand = talloc_sub_advanced(ctx,
1687 lp_servicename(talloc_tos(), snum),
1688 current_user_info.unix_name,
1690 current_user.ut.gid,
1691 get_current_username(),
1692 current_user_info.domain,
1693 lpqcommand);
1694 if (!lpqcommand) {
1695 return;
1698 lprmcommand = talloc_string_sub2(ctx,
1699 lp_lprm_command(talloc_tos(), snum),
1700 "%p",
1701 lp_printername(talloc_tos(), snum),
1702 false, false, false);
1703 if (!lprmcommand) {
1704 return;
1706 lprmcommand = talloc_sub_advanced(ctx,
1707 lp_servicename(talloc_tos(), snum),
1708 current_user_info.unix_name,
1710 current_user.ut.gid,
1711 get_current_username(),
1712 current_user_info.domain,
1713 lprmcommand);
1714 if (!lprmcommand) {
1715 return;
1719 * Make sure that the background queue process exists.
1720 * Otherwise just do the update ourselves
1723 if ( force || background_lpq_updater_pid == -1 ) {
1724 DEBUG(4,("print_queue_update: updating queue [%s] myself\n", sharename));
1725 current_printif = get_printer_fns( snum );
1726 print_queue_update_with_lock(server_event_context(), msg_ctx,
1727 sharename, current_printif,
1728 lpqcommand, lprmcommand);
1730 return;
1733 type = lp_printing(snum);
1735 /* get the length */
1737 len = tdb_pack( NULL, 0, "fdPP",
1738 sharename,
1739 type,
1740 lpqcommand,
1741 lprmcommand );
1743 buffer = SMB_XMALLOC_ARRAY( uint8, len );
1745 /* now pack the buffer */
1746 newlen = tdb_pack( buffer, len, "fdPP",
1747 sharename,
1748 type,
1749 lpqcommand,
1750 lprmcommand );
1752 SMB_ASSERT( newlen == len );
1754 DEBUG(10,("print_queue_update: Sending message -> printer = %s, "
1755 "type = %d, lpq command = [%s] lprm command = [%s]\n",
1756 sharename, type, lpqcommand, lprmcommand ));
1758 /* here we set a msg pending record for other smbd processes
1759 to throttle the number of duplicate print_queue_update msgs
1760 sent. */
1762 pdb = get_print_db_byname(sharename);
1763 if (!pdb) {
1764 SAFE_FREE(buffer);
1765 return;
1768 snprintf(key, sizeof(key), "MSG_PENDING/%s", sharename);
1770 if ( !tdb_store_uint32( pdb->tdb, key, time(NULL) ) ) {
1771 /* log a message but continue on */
1773 DEBUG(0,("print_queue_update: failed to store MSG_PENDING flag for [%s]!\n",
1774 sharename));
1777 release_print_db( pdb );
1779 /* finally send the message */
1781 messaging_send_buf(msg_ctx, pid_to_procid(background_lpq_updater_pid),
1782 MSG_PRINTER_UPDATE, (uint8 *)buffer, len);
1784 SAFE_FREE( buffer );
1786 return;
1789 /****************************************************************************
1790 Create/Update an entry in the print tdb that will allow us to send notify
1791 updates only to interested smbd's.
1792 ****************************************************************************/
1794 bool print_notify_register_pid(int snum)
1796 TDB_DATA data;
1797 struct tdb_print_db *pdb = NULL;
1798 TDB_CONTEXT *tdb = NULL;
1799 const char *printername;
1800 uint32_t mypid = (uint32_t)getpid();
1801 bool ret = False;
1802 size_t i;
1804 /* if (snum == -1), then the change notify request was
1805 on a print server handle and we need to register on
1806 all print queus */
1808 if (snum == -1)
1810 int num_services = lp_numservices();
1811 int idx;
1813 for ( idx=0; idx<num_services; idx++ ) {
1814 if (lp_snum_ok(idx) && lp_printable(idx) )
1815 print_notify_register_pid(idx);
1818 return True;
1820 else /* register for a specific printer */
1822 printername = lp_const_servicename(snum);
1823 pdb = get_print_db_byname(printername);
1824 if (!pdb)
1825 return False;
1826 tdb = pdb->tdb;
1829 if (tdb_lock_bystring_with_timeout(tdb, NOTIFY_PID_LIST_KEY, 10) != 0) {
1830 DEBUG(0,("print_notify_register_pid: Failed to lock printer %s\n",
1831 printername));
1832 if (pdb)
1833 release_print_db(pdb);
1834 return False;
1837 data = get_printer_notify_pid_list( tdb, printername, True );
1839 /* Add ourselves and increase the refcount. */
1841 for (i = 0; i < data.dsize; i += 8) {
1842 if (IVAL(data.dptr,i) == mypid) {
1843 uint32 new_refcount = IVAL(data.dptr, i+4) + 1;
1844 SIVAL(data.dptr, i+4, new_refcount);
1845 break;
1849 if (i == data.dsize) {
1850 /* We weren't in the list. Realloc. */
1851 data.dptr = (uint8 *)SMB_REALLOC(data.dptr, data.dsize + 8);
1852 if (!data.dptr) {
1853 DEBUG(0,("print_notify_register_pid: Relloc fail for printer %s\n",
1854 printername));
1855 goto done;
1857 data.dsize += 8;
1858 SIVAL(data.dptr,data.dsize - 8,mypid);
1859 SIVAL(data.dptr,data.dsize - 4,1); /* Refcount. */
1862 /* Store back the record. */
1863 if (tdb_store_bystring(tdb, NOTIFY_PID_LIST_KEY, data, TDB_REPLACE) != 0) {
1864 DEBUG(0,("print_notify_register_pid: Failed to update pid \
1865 list for printer %s\n", printername));
1866 goto done;
1869 ret = True;
1871 done:
1873 tdb_unlock_bystring(tdb, NOTIFY_PID_LIST_KEY);
1874 if (pdb)
1875 release_print_db(pdb);
1876 SAFE_FREE(data.dptr);
1877 return ret;
1880 /****************************************************************************
1881 Update an entry in the print tdb that will allow us to send notify
1882 updates only to interested smbd's.
1883 ****************************************************************************/
1885 bool print_notify_deregister_pid(int snum)
1887 TDB_DATA data;
1888 struct tdb_print_db *pdb = NULL;
1889 TDB_CONTEXT *tdb = NULL;
1890 const char *printername;
1891 uint32_t mypid = (uint32_t)getpid();
1892 size_t i;
1893 bool ret = False;
1895 /* if ( snum == -1 ), we are deregister a print server handle
1896 which means to deregister on all print queues */
1898 if (snum == -1)
1900 int num_services = lp_numservices();
1901 int idx;
1903 for ( idx=0; idx<num_services; idx++ ) {
1904 if ( lp_snum_ok(idx) && lp_printable(idx) )
1905 print_notify_deregister_pid(idx);
1908 return True;
1910 else /* deregister a specific printer */
1912 printername = lp_const_servicename(snum);
1913 pdb = get_print_db_byname(printername);
1914 if (!pdb)
1915 return False;
1916 tdb = pdb->tdb;
1919 if (tdb_lock_bystring_with_timeout(tdb, NOTIFY_PID_LIST_KEY, 10) != 0) {
1920 DEBUG(0,("print_notify_register_pid: Failed to lock \
1921 printer %s database\n", printername));
1922 if (pdb)
1923 release_print_db(pdb);
1924 return False;
1927 data = get_printer_notify_pid_list( tdb, printername, True );
1929 /* Reduce refcount. Remove ourselves if zero. */
1931 for (i = 0; i < data.dsize; ) {
1932 if (IVAL(data.dptr,i) == mypid) {
1933 uint32 refcount = IVAL(data.dptr, i+4);
1935 refcount--;
1937 if (refcount == 0) {
1938 if (data.dsize - i > 8)
1939 memmove( &data.dptr[i], &data.dptr[i+8], data.dsize - i - 8);
1940 data.dsize -= 8;
1941 continue;
1943 SIVAL(data.dptr, i+4, refcount);
1946 i += 8;
1949 if (data.dsize == 0)
1950 SAFE_FREE(data.dptr);
1952 /* Store back the record. */
1953 if (tdb_store_bystring(tdb, NOTIFY_PID_LIST_KEY, data, TDB_REPLACE) != 0) {
1954 DEBUG(0,("print_notify_register_pid: Failed to update pid \
1955 list for printer %s\n", printername));
1956 goto done;
1959 ret = True;
1961 done:
1963 tdb_unlock_bystring(tdb, NOTIFY_PID_LIST_KEY);
1964 if (pdb)
1965 release_print_db(pdb);
1966 SAFE_FREE(data.dptr);
1967 return ret;
1970 /****************************************************************************
1971 Check if a jobid is valid. It is valid if it exists in the database.
1972 ****************************************************************************/
1974 bool print_job_exists(const char* sharename, uint32 jobid)
1976 struct tdb_print_db *pdb = get_print_db_byname(sharename);
1977 bool ret;
1978 uint32_t tmp;
1980 if (!pdb)
1981 return False;
1982 ret = tdb_exists(pdb->tdb, print_key(jobid, &tmp));
1983 release_print_db(pdb);
1984 return ret;
1987 /****************************************************************************
1988 Return the device mode asigned to a specific print job.
1989 Only valid for the process doing the spooling and when the job
1990 has not been spooled.
1991 ****************************************************************************/
1993 struct spoolss_DeviceMode *print_job_devmode(TALLOC_CTX *mem_ctx,
1994 const char *sharename,
1995 uint32 jobid)
1997 struct printjob *pjob = print_job_find(mem_ctx, sharename, jobid);
1998 if (pjob == NULL) {
1999 return NULL;
2002 return pjob->devmode;
2005 /****************************************************************************
2006 Set the name of a job. Only possible for owner.
2007 ****************************************************************************/
2009 bool print_job_set_name(struct tevent_context *ev,
2010 struct messaging_context *msg_ctx,
2011 const char *sharename, uint32 jobid, const char *name)
2013 struct printjob *pjob;
2014 bool ret;
2015 TALLOC_CTX *tmp_ctx = talloc_new(ev);
2016 if (tmp_ctx == NULL) {
2017 return false;
2020 pjob = print_job_find(tmp_ctx, sharename, jobid);
2021 if (!pjob || pjob->pid != getpid()) {
2022 ret = false;
2023 goto err_out;
2026 fstrcpy(pjob->jobname, name);
2027 ret = pjob_store(ev, msg_ctx, sharename, jobid, pjob);
2028 err_out:
2029 talloc_free(tmp_ctx);
2030 return ret;
2033 /****************************************************************************
2034 Get the name of a job. Only possible for owner.
2035 ****************************************************************************/
2037 bool print_job_get_name(TALLOC_CTX *mem_ctx, const char *sharename, uint32_t jobid, char **name)
2039 struct printjob *pjob;
2041 pjob = print_job_find(mem_ctx, sharename, jobid);
2042 if (!pjob || pjob->pid != getpid()) {
2043 return false;
2046 *name = pjob->jobname;
2047 return true;
2051 /***************************************************************************
2052 Remove a jobid from the 'jobs added' list.
2053 ***************************************************************************/
2055 static bool remove_from_jobs_added(const char* sharename, uint32 jobid)
2057 struct tdb_print_db *pdb = get_print_db_byname(sharename);
2058 TDB_DATA data, key;
2059 size_t job_count, i;
2060 bool ret = False;
2061 bool gotlock = False;
2063 if (!pdb) {
2064 return False;
2067 ZERO_STRUCT(data);
2069 key = string_tdb_data("INFO/jobs_added");
2071 if (tdb_chainlock_with_timeout(pdb->tdb, key, 5) != 0)
2072 goto out;
2074 gotlock = True;
2076 data = tdb_fetch_compat(pdb->tdb, key);
2078 if (data.dptr == NULL || data.dsize == 0 || (data.dsize % 4 != 0))
2079 goto out;
2081 job_count = data.dsize / 4;
2082 for (i = 0; i < job_count; i++) {
2083 uint32 ch_jobid;
2085 ch_jobid = IVAL(data.dptr, i*4);
2086 if (ch_jobid == jobid) {
2087 if (i < job_count -1 )
2088 memmove(data.dptr + (i*4), data.dptr + (i*4) + 4, (job_count - i - 1)*4 );
2089 data.dsize -= 4;
2090 if (tdb_store(pdb->tdb, key, data, TDB_REPLACE) != 0)
2091 goto out;
2092 break;
2096 ret = True;
2097 out:
2099 if (gotlock)
2100 tdb_chainunlock(pdb->tdb, key);
2101 SAFE_FREE(data.dptr);
2102 release_print_db(pdb);
2103 if (ret)
2104 DEBUG(10,("remove_from_jobs_added: removed jobid %u\n", (unsigned int)jobid ));
2105 else
2106 DEBUG(10,("remove_from_jobs_added: Failed to remove jobid %u\n", (unsigned int)jobid ));
2107 return ret;
2110 /****************************************************************************
2111 Delete a print job - don't update queue.
2112 ****************************************************************************/
2114 static bool print_job_delete1(struct tevent_context *ev,
2115 struct messaging_context *msg_ctx,
2116 int snum, uint32 jobid)
2118 const char* sharename = lp_const_servicename(snum);
2119 struct printjob *pjob;
2120 int result = 0;
2121 struct printif *current_printif = get_printer_fns( snum );
2122 bool ret;
2123 TALLOC_CTX *tmp_ctx = talloc_new(ev);
2124 if (tmp_ctx == NULL) {
2125 return false;
2128 pjob = print_job_find(tmp_ctx, sharename, jobid);
2129 if (!pjob) {
2130 ret = false;
2131 goto err_out;
2135 * If already deleting just return.
2138 if (pjob->status == LPQ_DELETING) {
2139 ret = true;
2140 goto err_out;
2143 /* Hrm - we need to be able to cope with deleting a job before it
2144 has reached the spooler. Just mark it as LPQ_DELETING and
2145 let the print_queue_update() code rmeove the record */
2148 if (pjob->sysjob == -1) {
2149 DEBUG(5, ("attempt to delete job %u not seen by lpr\n", (unsigned int)jobid));
2152 /* Set the tdb entry to be deleting. */
2154 pjob->status = LPQ_DELETING;
2155 pjob_store(ev, msg_ctx, sharename, jobid, pjob);
2157 if (pjob->spooled && pjob->sysjob != -1)
2159 result = (*(current_printif->job_delete))(
2160 lp_printername(talloc_tos(), snum),
2161 lp_lprm_command(talloc_tos(), snum),
2162 pjob);
2164 /* Delete the tdb entry if the delete succeeded or the job hasn't
2165 been spooled. */
2167 if (result == 0) {
2168 struct tdb_print_db *pdb = get_print_db_byname(sharename);
2169 int njobs = 1;
2171 if (!pdb) {
2172 ret = false;
2173 goto err_out;
2175 pjob_delete(ev, msg_ctx, sharename, jobid);
2176 /* Ensure we keep a rough count of the number of total jobs... */
2177 tdb_change_int32_atomic(pdb->tdb, "INFO/total_jobs", &njobs, -1);
2178 release_print_db(pdb);
2182 remove_from_jobs_added( sharename, jobid );
2184 ret = (result == 0);
2185 err_out:
2186 talloc_free(tmp_ctx);
2187 return ret;
2190 /****************************************************************************
2191 Return true if the current user owns the print job.
2192 ****************************************************************************/
2194 static bool is_owner(const struct auth_session_info *server_info,
2195 const char *servicename,
2196 uint32 jobid)
2198 struct printjob *pjob;
2199 bool ret;
2200 TALLOC_CTX *tmp_ctx = talloc_new(server_info);
2201 if (tmp_ctx == NULL) {
2202 return false;
2205 pjob = print_job_find(tmp_ctx, servicename, jobid);
2206 if (!pjob || !server_info) {
2207 ret = false;
2208 goto err_out;
2211 ret = strequal(pjob->user, server_info->unix_info->sanitized_username);
2212 err_out:
2213 talloc_free(tmp_ctx);
2214 return ret;
2217 /****************************************************************************
2218 Delete a print job.
2219 ****************************************************************************/
2221 WERROR print_job_delete(const struct auth_session_info *server_info,
2222 struct messaging_context *msg_ctx,
2223 int snum, uint32_t jobid)
2225 const char* sharename = lp_const_servicename(snum);
2226 struct printjob *pjob;
2227 bool owner;
2228 WERROR werr;
2229 TALLOC_CTX *tmp_ctx = talloc_new(msg_ctx);
2230 if (tmp_ctx == NULL) {
2231 return WERR_NOT_ENOUGH_MEMORY;
2234 owner = is_owner(server_info, lp_const_servicename(snum), jobid);
2236 /* Check access against security descriptor or whether the user
2237 owns their job. */
2239 if (!owner &&
2240 !W_ERROR_IS_OK(print_access_check(server_info, msg_ctx, snum,
2241 JOB_ACCESS_ADMINISTER))) {
2242 DEBUG(0, ("print job delete denied."
2243 "User name: %s, Printer name: %s.",
2244 uidtoname(server_info->unix_token->uid),
2245 lp_printername(tmp_ctx, snum)));
2247 werr = WERR_ACCESS_DENIED;
2248 goto err_out;
2252 * get the spooled filename of the print job
2253 * if this works, then the file has not been spooled
2254 * to the underlying print system. Just delete the
2255 * spool file & return.
2258 pjob = print_job_find(tmp_ctx, sharename, jobid);
2259 if (!pjob || pjob->spooled || pjob->pid != getpid()) {
2260 DEBUG(10, ("Skipping spool file removal for job %u\n", jobid));
2261 } else {
2262 DEBUG(10, ("Removing spool file [%s]\n", pjob->filename));
2263 if (unlink(pjob->filename) == -1) {
2264 werr = map_werror_from_unix(errno);
2265 goto err_out;
2269 if (!print_job_delete1(server_event_context(), msg_ctx, snum, jobid)) {
2270 werr = WERR_ACCESS_DENIED;
2271 goto err_out;
2274 /* force update the database and say the delete failed if the
2275 job still exists */
2277 print_queue_update(msg_ctx, snum, True);
2279 pjob = print_job_find(tmp_ctx, sharename, jobid);
2280 if (pjob && (pjob->status != LPQ_DELETING)) {
2281 werr = WERR_ACCESS_DENIED;
2282 goto err_out;
2284 werr = WERR_PRINTER_HAS_JOBS_QUEUED;
2286 err_out:
2287 talloc_free(tmp_ctx);
2288 return werr;
2291 /****************************************************************************
2292 Pause a job.
2293 ****************************************************************************/
2295 WERROR print_job_pause(const struct auth_session_info *server_info,
2296 struct messaging_context *msg_ctx,
2297 int snum, uint32 jobid)
2299 const char* sharename = lp_const_servicename(snum);
2300 struct printjob *pjob;
2301 int ret = -1;
2302 struct printif *current_printif = get_printer_fns( snum );
2303 WERROR werr;
2304 TALLOC_CTX *tmp_ctx = talloc_new(msg_ctx);
2305 if (tmp_ctx == NULL) {
2306 return WERR_NOT_ENOUGH_MEMORY;
2309 pjob = print_job_find(tmp_ctx, sharename, jobid);
2310 if (!pjob || !server_info) {
2311 DEBUG(10, ("print_job_pause: no pjob or user for jobid %u\n",
2312 (unsigned int)jobid ));
2313 werr = WERR_INVALID_PARAM;
2314 goto err_out;
2317 if (!pjob->spooled || pjob->sysjob == -1) {
2318 DEBUG(10, ("print_job_pause: not spooled or bad sysjob = %d for jobid %u\n",
2319 (int)pjob->sysjob, (unsigned int)jobid ));
2320 werr = WERR_INVALID_PARAM;
2321 goto err_out;
2324 if (!is_owner(server_info, lp_const_servicename(snum), jobid) &&
2325 !W_ERROR_IS_OK(print_access_check(server_info, msg_ctx, snum,
2326 JOB_ACCESS_ADMINISTER))) {
2327 DEBUG(0, ("print job pause denied."
2328 "User name: %s, Printer name: %s.",
2329 uidtoname(server_info->unix_token->uid),
2330 lp_printername(tmp_ctx, snum)));
2332 werr = WERR_ACCESS_DENIED;
2333 goto err_out;
2336 /* need to pause the spooled entry */
2337 ret = (*(current_printif->job_pause))(snum, pjob);
2339 if (ret != 0) {
2340 werr = WERR_INVALID_PARAM;
2341 goto err_out;
2344 /* force update the database */
2345 print_cache_flush(lp_const_servicename(snum));
2347 /* Send a printer notify message */
2349 notify_job_status(server_event_context(), msg_ctx, sharename, jobid,
2350 JOB_STATUS_PAUSED);
2352 /* how do we tell if this succeeded? */
2353 werr = WERR_OK;
2354 err_out:
2355 talloc_free(tmp_ctx);
2356 return werr;
2359 /****************************************************************************
2360 Resume a job.
2361 ****************************************************************************/
2363 WERROR print_job_resume(const struct auth_session_info *server_info,
2364 struct messaging_context *msg_ctx,
2365 int snum, uint32 jobid)
2367 const char *sharename = lp_const_servicename(snum);
2368 struct printjob *pjob;
2369 int ret;
2370 struct printif *current_printif = get_printer_fns( snum );
2371 WERROR werr;
2372 TALLOC_CTX *tmp_ctx = talloc_new(msg_ctx);
2373 if (tmp_ctx == NULL)
2374 return WERR_NOT_ENOUGH_MEMORY;
2376 pjob = print_job_find(tmp_ctx, sharename, jobid);
2377 if (!pjob || !server_info) {
2378 DEBUG(10, ("print_job_resume: no pjob or user for jobid %u\n",
2379 (unsigned int)jobid ));
2380 werr = WERR_INVALID_PARAM;
2381 goto err_out;
2384 if (!pjob->spooled || pjob->sysjob == -1) {
2385 DEBUG(10, ("print_job_resume: not spooled or bad sysjob = %d for jobid %u\n",
2386 (int)pjob->sysjob, (unsigned int)jobid ));
2387 werr = WERR_INVALID_PARAM;
2388 goto err_out;
2391 if (!is_owner(server_info, lp_const_servicename(snum), jobid) &&
2392 !W_ERROR_IS_OK(print_access_check(server_info, msg_ctx, snum,
2393 JOB_ACCESS_ADMINISTER))) {
2394 DEBUG(0, ("print job resume denied."
2395 "User name: %s, Printer name: %s.",
2396 uidtoname(server_info->unix_token->uid),
2397 lp_printername(tmp_ctx, snum)));
2399 werr = WERR_ACCESS_DENIED;
2400 goto err_out;
2403 ret = (*(current_printif->job_resume))(snum, pjob);
2405 if (ret != 0) {
2406 werr = WERR_INVALID_PARAM;
2407 goto err_out;
2410 /* force update the database */
2411 print_cache_flush(lp_const_servicename(snum));
2413 /* Send a printer notify message */
2415 notify_job_status(server_event_context(), msg_ctx, sharename, jobid,
2416 JOB_STATUS_QUEUED);
2418 werr = WERR_OK;
2419 err_out:
2420 talloc_free(tmp_ctx);
2421 return werr;
2424 /****************************************************************************
2425 Write to a print file.
2426 ****************************************************************************/
2428 ssize_t print_job_write(struct tevent_context *ev,
2429 struct messaging_context *msg_ctx,
2430 int snum, uint32 jobid, const char *buf, size_t size)
2432 const char* sharename = lp_const_servicename(snum);
2433 ssize_t return_code;
2434 struct printjob *pjob;
2435 TALLOC_CTX *tmp_ctx = talloc_new(ev);
2436 if (tmp_ctx == NULL) {
2437 return -1;
2440 pjob = print_job_find(tmp_ctx, sharename, jobid);
2441 if (!pjob) {
2442 return_code = -1;
2443 goto err_out;
2446 /* don't allow another process to get this info - it is meaningless */
2447 if (pjob->pid != getpid()) {
2448 return_code = -1;
2449 goto err_out;
2452 /* if SMBD is spooling this can't be allowed */
2453 if (pjob->status == PJOB_SMBD_SPOOLING) {
2454 return_code = -1;
2455 goto err_out;
2458 return_code = write_data(pjob->fd, buf, size);
2459 if (return_code > 0) {
2460 pjob->size += size;
2461 pjob_store(ev, msg_ctx, sharename, jobid, pjob);
2463 err_out:
2464 talloc_free(tmp_ctx);
2465 return return_code;
2468 /****************************************************************************
2469 Get the queue status - do not update if db is out of date.
2470 ****************************************************************************/
2472 static int get_queue_status(const char* sharename, print_status_struct *status)
2474 fstring keystr;
2475 TDB_DATA data;
2476 struct tdb_print_db *pdb = get_print_db_byname(sharename);
2477 int len;
2479 if (status) {
2480 ZERO_STRUCTP(status);
2483 if (!pdb)
2484 return 0;
2486 if (status) {
2487 fstr_sprintf(keystr, "STATUS/%s", sharename);
2488 data = tdb_fetch_compat(pdb->tdb, string_tdb_data(keystr));
2489 if (data.dptr) {
2490 if (data.dsize == sizeof(print_status_struct))
2491 /* this memcpy is ok since the status struct was
2492 not packed before storing it in the tdb */
2493 memcpy(status, data.dptr, sizeof(print_status_struct));
2494 SAFE_FREE(data.dptr);
2497 len = tdb_fetch_int32(pdb->tdb, "INFO/total_jobs");
2498 release_print_db(pdb);
2499 return (len == -1 ? 0 : len);
2502 /****************************************************************************
2503 Determine the number of jobs in a queue.
2504 ****************************************************************************/
2506 int print_queue_length(struct messaging_context *msg_ctx, int snum,
2507 print_status_struct *pstatus)
2509 const char* sharename = lp_const_servicename( snum );
2510 print_status_struct status;
2511 int len;
2513 ZERO_STRUCT( status );
2515 /* make sure the database is up to date */
2516 if (print_cache_expired(lp_const_servicename(snum), True))
2517 print_queue_update(msg_ctx, snum, False);
2519 /* also fetch the queue status */
2520 memset(&status, 0, sizeof(status));
2521 len = get_queue_status(sharename, &status);
2523 if (pstatus)
2524 *pstatus = status;
2526 return len;
2529 /***************************************************************************
2530 Allocate a jobid. Hold the lock for as short a time as possible.
2531 ***************************************************************************/
2533 static WERROR allocate_print_jobid(struct tdb_print_db *pdb, int snum,
2534 const char *sharename, uint32 *pjobid)
2536 int i;
2537 uint32 jobid;
2538 enum TDB_ERROR terr;
2539 int ret;
2541 *pjobid = (uint32)-1;
2543 for (i = 0; i < 3; i++) {
2544 /* Lock the database - only wait 20 seconds. */
2545 ret = tdb_lock_bystring_with_timeout(pdb->tdb,
2546 "INFO/nextjob", 20);
2547 if (ret != 0) {
2548 DEBUG(0, ("allocate_print_jobid: "
2549 "Failed to lock printing database %s\n",
2550 sharename));
2551 terr = tdb_error(pdb->tdb);
2552 return ntstatus_to_werror(map_nt_error_from_tdb(terr));
2555 if (!tdb_fetch_uint32(pdb->tdb, "INFO/nextjob", &jobid)) {
2556 terr = tdb_error(pdb->tdb);
2557 if (terr != TDB_ERR_NOEXIST) {
2558 DEBUG(0, ("allocate_print_jobid: "
2559 "Failed to fetch INFO/nextjob "
2560 "for print queue %s\n", sharename));
2561 tdb_unlock_bystring(pdb->tdb, "INFO/nextjob");
2562 return ntstatus_to_werror(map_nt_error_from_tdb(terr));
2564 DEBUG(10, ("allocate_print_jobid: "
2565 "No existing jobid in %s\n", sharename));
2566 jobid = 0;
2569 DEBUG(10, ("allocate_print_jobid: "
2570 "Read jobid %u from %s\n", jobid, sharename));
2572 jobid = NEXT_JOBID(jobid);
2574 ret = tdb_store_int32(pdb->tdb, "INFO/nextjob", jobid);
2575 if (ret != 0) {
2576 terr = tdb_error(pdb->tdb);
2577 DEBUG(3, ("allocate_print_jobid: "
2578 "Failed to store INFO/nextjob.\n"));
2579 tdb_unlock_bystring(pdb->tdb, "INFO/nextjob");
2580 return ntstatus_to_werror(map_nt_error_from_tdb(terr));
2583 /* We've finished with the INFO/nextjob lock. */
2584 tdb_unlock_bystring(pdb->tdb, "INFO/nextjob");
2586 if (!print_job_exists(sharename, jobid)) {
2587 break;
2589 DEBUG(10, ("allocate_print_jobid: "
2590 "Found jobid %u in %s\n", jobid, sharename));
2593 if (i > 2) {
2594 DEBUG(0, ("allocate_print_jobid: "
2595 "Failed to allocate a print job for queue %s\n",
2596 sharename));
2597 /* Probably full... */
2598 return WERR_NO_SPOOL_SPACE;
2601 /* Store a dummy placeholder. */
2603 uint32_t tmp;
2604 TDB_DATA dum;
2605 dum.dptr = NULL;
2606 dum.dsize = 0;
2607 if (tdb_store(pdb->tdb, print_key(jobid, &tmp), dum,
2608 TDB_INSERT) != 0) {
2609 DEBUG(3, ("allocate_print_jobid: "
2610 "jobid (%d) failed to store placeholder.\n",
2611 jobid ));
2612 terr = tdb_error(pdb->tdb);
2613 return ntstatus_to_werror(map_nt_error_from_tdb(terr));
2617 *pjobid = jobid;
2618 return WERR_OK;
2621 /***************************************************************************
2622 Append a jobid to the 'jobs added' list.
2623 ***************************************************************************/
2625 static bool add_to_jobs_added(struct tdb_print_db *pdb, uint32 jobid)
2627 TDB_DATA data;
2628 uint32 store_jobid;
2630 SIVAL(&store_jobid, 0, jobid);
2631 data.dptr = (uint8 *)&store_jobid;
2632 data.dsize = 4;
2634 DEBUG(10,("add_to_jobs_added: Added jobid %u\n", (unsigned int)jobid ));
2636 return (tdb_append(pdb->tdb, string_tdb_data("INFO/jobs_added"),
2637 data) == 0);
2641 /***************************************************************************
2642 Do all checks needed to determine if we can start a job.
2643 ***************************************************************************/
2645 static WERROR print_job_checks(const struct auth_session_info *server_info,
2646 struct messaging_context *msg_ctx,
2647 int snum, int *njobs)
2649 const char *sharename = lp_const_servicename(snum);
2650 uint64_t dspace, dsize;
2651 uint64_t minspace;
2652 int ret;
2654 if (!W_ERROR_IS_OK(print_access_check(server_info, msg_ctx, snum,
2655 PRINTER_ACCESS_USE))) {
2656 DEBUG(3, ("print_job_checks: "
2657 "job start denied by security descriptor\n"));
2658 return WERR_ACCESS_DENIED;
2661 if (!print_time_access_check(server_info, msg_ctx, sharename)) {
2662 DEBUG(3, ("print_job_checks: "
2663 "job start denied by time check\n"));
2664 return WERR_ACCESS_DENIED;
2667 /* see if we have sufficient disk space */
2668 if (lp_min_print_space(snum)) {
2669 minspace = lp_min_print_space(snum);
2670 ret = sys_fsusage(lp_path(talloc_tos(), snum), &dspace, &dsize);
2671 if (ret == 0 && dspace < 2*minspace) {
2672 DEBUG(3, ("print_job_checks: "
2673 "disk space check failed.\n"));
2674 return WERR_NO_SPOOL_SPACE;
2678 /* for autoloaded printers, check that the printcap entry still exists */
2679 if (lp_autoloaded(snum) && !pcap_printername_ok(sharename)) {
2680 DEBUG(3, ("print_job_checks: printer name %s check failed.\n",
2681 sharename));
2682 return WERR_ACCESS_DENIED;
2685 /* Insure the maximum queue size is not violated */
2686 *njobs = print_queue_length(msg_ctx, snum, NULL);
2687 if (*njobs > lp_maxprintjobs(snum)) {
2688 DEBUG(3, ("print_job_checks: Queue %s number of jobs (%d) "
2689 "larger than max printjobs per queue (%d).\n",
2690 sharename, *njobs, lp_maxprintjobs(snum)));
2691 return WERR_NO_SPOOL_SPACE;
2694 return WERR_OK;
2697 /***************************************************************************
2698 Create a job file.
2699 ***************************************************************************/
2701 static WERROR print_job_spool_file(int snum, uint32_t jobid,
2702 const char *output_file,
2703 struct printjob *pjob)
2705 WERROR werr;
2706 SMB_STRUCT_STAT st;
2707 const char *path;
2708 int len;
2709 mode_t mask;
2711 /* if this file is within the printer path, it means that smbd
2712 * is spooling it and will pass us control when it is finished.
2713 * Verify that the file name is ok, within path, and it is
2714 * already already there */
2715 if (output_file) {
2716 path = lp_path(talloc_tos(), snum);
2717 len = strlen(path);
2718 if (strncmp(output_file, path, len) == 0 &&
2719 (output_file[len - 1] == '/' || output_file[len] == '/')) {
2721 /* verify path is not too long */
2722 if (strlen(output_file) >= sizeof(pjob->filename)) {
2723 return WERR_INVALID_NAME;
2726 /* verify that the file exists */
2727 if (sys_stat(output_file, &st, false) != 0) {
2728 return WERR_INVALID_NAME;
2731 fstrcpy(pjob->filename, output_file);
2733 DEBUG(3, ("print_job_spool_file:"
2734 "External spooling activated\n"));
2736 /* we do not open the file until spooling is done */
2737 pjob->fd = -1;
2738 pjob->status = PJOB_SMBD_SPOOLING;
2740 return WERR_OK;
2744 slprintf(pjob->filename, sizeof(pjob->filename)-1,
2745 "%s/%sXXXXXX", lp_path(talloc_tos(), snum),
2746 PRINT_SPOOL_PREFIX);
2747 mask = umask(S_IRWXO | S_IRWXG);
2748 pjob->fd = mkstemp(pjob->filename);
2749 umask(mask);
2751 if (pjob->fd == -1) {
2752 werr = map_werror_from_unix(errno);
2753 if (W_ERROR_EQUAL(werr, WERR_ACCESS_DENIED)) {
2754 /* Common setup error, force a report. */
2755 DEBUG(0, ("print_job_spool_file: "
2756 "insufficient permissions to open spool "
2757 "file %s.\n", pjob->filename));
2758 } else {
2759 /* Normal case, report at level 3 and above. */
2760 DEBUG(3, ("print_job_spool_file: "
2761 "can't open spool file %s\n",
2762 pjob->filename));
2764 return werr;
2767 return WERR_OK;
2770 /***************************************************************************
2771 Start spooling a job - return the jobid.
2772 ***************************************************************************/
2774 WERROR print_job_start(const struct auth_session_info *server_info,
2775 struct messaging_context *msg_ctx,
2776 const char *clientmachine,
2777 int snum, const char *docname, const char *filename,
2778 struct spoolss_DeviceMode *devmode, uint32_t *_jobid)
2780 uint32_t jobid;
2781 char *path;
2782 struct printjob pjob;
2783 const char *sharename = lp_const_servicename(snum);
2784 struct tdb_print_db *pdb = get_print_db_byname(sharename);
2785 int njobs;
2786 WERROR werr;
2788 if (!pdb) {
2789 return WERR_INTERNAL_DB_CORRUPTION;
2792 path = lp_path(talloc_tos(), snum);
2794 werr = print_job_checks(server_info, msg_ctx, snum, &njobs);
2795 if (!W_ERROR_IS_OK(werr)) {
2796 release_print_db(pdb);
2797 return werr;
2800 DEBUG(10, ("print_job_start: "
2801 "Queue %s number of jobs (%d), max printjobs = %d\n",
2802 sharename, njobs, lp_maxprintjobs(snum)));
2804 werr = allocate_print_jobid(pdb, snum, sharename, &jobid);
2805 if (!W_ERROR_IS_OK(werr)) {
2806 goto fail;
2809 /* create the database entry */
2811 ZERO_STRUCT(pjob);
2813 pjob.pid = getpid();
2814 pjob.jobid = jobid;
2815 pjob.sysjob = -1;
2816 pjob.fd = -1;
2817 pjob.starttime = time(NULL);
2818 pjob.status = LPQ_SPOOLING;
2819 pjob.size = 0;
2820 pjob.spooled = False;
2821 pjob.smbjob = True;
2822 pjob.devmode = devmode;
2824 fstrcpy(pjob.jobname, docname);
2826 fstrcpy(pjob.clientmachine, clientmachine);
2828 fstrcpy(pjob.user, lp_printjob_username(snum));
2829 standard_sub_advanced(sharename, server_info->unix_info->sanitized_username,
2830 path, server_info->unix_token->gid,
2831 server_info->unix_info->sanitized_username,
2832 server_info->info->domain_name,
2833 pjob.user, sizeof(pjob.user));
2835 fstrcpy(pjob.queuename, lp_const_servicename(snum));
2837 /* we have a job entry - now create the spool file */
2838 werr = print_job_spool_file(snum, jobid, filename, &pjob);
2839 if (!W_ERROR_IS_OK(werr)) {
2840 goto fail;
2843 pjob_store(server_event_context(), msg_ctx, sharename, jobid, &pjob);
2845 /* Update the 'jobs added' entry used by print_queue_status. */
2846 add_to_jobs_added(pdb, jobid);
2848 /* Ensure we keep a rough count of the number of total jobs... */
2849 tdb_change_int32_atomic(pdb->tdb, "INFO/total_jobs", &njobs, 1);
2851 release_print_db(pdb);
2853 *_jobid = jobid;
2854 return WERR_OK;
2856 fail:
2857 if (jobid != -1) {
2858 pjob_delete(server_event_context(), msg_ctx, sharename, jobid);
2861 release_print_db(pdb);
2863 DEBUG(3, ("print_job_start: returning fail. "
2864 "Error = %s\n", win_errstr(werr)));
2865 return werr;
2868 /****************************************************************************
2869 Update the number of pages spooled to jobid
2870 ****************************************************************************/
2872 void print_job_endpage(struct messaging_context *msg_ctx,
2873 int snum, uint32 jobid)
2875 const char* sharename = lp_const_servicename(snum);
2876 struct printjob *pjob;
2877 TALLOC_CTX *tmp_ctx = talloc_new(msg_ctx);
2878 if (tmp_ctx == NULL) {
2879 return;
2882 pjob = print_job_find(tmp_ctx, sharename, jobid);
2883 if (!pjob) {
2884 goto err_out;
2886 /* don't allow another process to get this info - it is meaningless */
2887 if (pjob->pid != getpid()) {
2888 goto err_out;
2891 pjob->page_count++;
2892 pjob_store(server_event_context(), msg_ctx, sharename, jobid, pjob);
2893 err_out:
2894 talloc_free(tmp_ctx);
2897 /****************************************************************************
2898 Print a file - called on closing the file. This spools the job.
2899 If normal close is false then we're tearing down the jobs - treat as an
2900 error.
2901 ****************************************************************************/
2903 NTSTATUS print_job_end(struct messaging_context *msg_ctx, int snum,
2904 uint32 jobid, enum file_close_type close_type)
2906 const char* sharename = lp_const_servicename(snum);
2907 struct printjob *pjob;
2908 int ret;
2909 SMB_STRUCT_STAT sbuf;
2910 struct printif *current_printif = get_printer_fns(snum);
2911 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
2912 char *lpq_cmd;
2913 TALLOC_CTX *tmp_ctx = talloc_new(msg_ctx);
2914 if (tmp_ctx == NULL) {
2915 return NT_STATUS_NO_MEMORY;
2918 pjob = print_job_find(tmp_ctx, sharename, jobid);
2919 if (!pjob) {
2920 status = NT_STATUS_PRINT_CANCELLED;
2921 goto err_out;
2924 if (pjob->spooled || pjob->pid != getpid()) {
2925 status = NT_STATUS_ACCESS_DENIED;
2926 goto err_out;
2929 if (close_type == NORMAL_CLOSE || close_type == SHUTDOWN_CLOSE) {
2930 if (pjob->status == PJOB_SMBD_SPOOLING) {
2931 /* take over the file now, smbd is done */
2932 if (sys_stat(pjob->filename, &sbuf, false) != 0) {
2933 status = map_nt_error_from_unix(errno);
2934 DEBUG(3, ("print_job_end: "
2935 "stat file failed for jobid %d\n",
2936 jobid));
2937 goto fail;
2940 pjob->status = LPQ_SPOOLING;
2942 } else {
2944 if ((sys_fstat(pjob->fd, &sbuf, false) != 0)) {
2945 status = map_nt_error_from_unix(errno);
2946 close(pjob->fd);
2947 DEBUG(3, ("print_job_end: "
2948 "stat file failed for jobid %d\n",
2949 jobid));
2950 goto fail;
2953 close(pjob->fd);
2956 pjob->size = sbuf.st_ex_size;
2957 } else {
2960 * Not a normal close, something has gone wrong. Cleanup.
2962 if (pjob->fd != -1) {
2963 close(pjob->fd);
2965 goto fail;
2968 /* Technically, this is not quite right. If the printer has a separator
2969 * page turned on, the NT spooler prints the separator page even if the
2970 * print job is 0 bytes. 010215 JRR */
2971 if (pjob->size == 0 || pjob->status == LPQ_DELETING) {
2972 /* don't bother spooling empty files or something being deleted. */
2973 DEBUG(5,("print_job_end: canceling spool of %s (%s)\n",
2974 pjob->filename, pjob->size ? "deleted" : "zero length" ));
2975 unlink(pjob->filename);
2976 pjob_delete(server_event_context(), msg_ctx, sharename, jobid);
2977 return NT_STATUS_OK;
2980 /* don't strip out characters like '$' from the printername */
2981 lpq_cmd = talloc_string_sub2(tmp_ctx,
2982 lp_lpq_command(talloc_tos(), snum),
2983 "%p",
2984 lp_printername(talloc_tos(), snum),
2985 false, false, false);
2986 if (lpq_cmd == NULL) {
2987 status = NT_STATUS_PRINT_CANCELLED;
2988 goto fail;
2990 lpq_cmd = talloc_sub_advanced(tmp_ctx,
2991 lp_servicename(talloc_tos(), snum),
2992 current_user_info.unix_name,
2994 current_user.ut.gid,
2995 get_current_username(),
2996 current_user_info.domain,
2997 lpq_cmd);
2998 if (lpq_cmd == NULL) {
2999 status = NT_STATUS_PRINT_CANCELLED;
3000 goto fail;
3003 ret = (*(current_printif->job_submit))(snum, pjob,
3004 current_printif->type, lpq_cmd);
3005 if (ret) {
3006 status = NT_STATUS_PRINT_CANCELLED;
3007 goto fail;
3010 /* The print job has been successfully handed over to the back-end */
3012 pjob->spooled = True;
3013 pjob->status = LPQ_QUEUED;
3014 pjob_store(server_event_context(), msg_ctx, sharename, jobid, pjob);
3016 /* make sure the database is up to date */
3017 if (print_cache_expired(lp_const_servicename(snum), True))
3018 print_queue_update(msg_ctx, snum, False);
3020 return NT_STATUS_OK;
3022 fail:
3024 /* The print job was not successfully started. Cleanup */
3025 /* Still need to add proper error return propagation! 010122:JRR */
3026 pjob->fd = -1;
3027 unlink(pjob->filename);
3028 pjob_delete(server_event_context(), msg_ctx, sharename, jobid);
3029 err_out:
3030 talloc_free(tmp_ctx);
3031 return status;
3034 /****************************************************************************
3035 Get a snapshot of jobs in the system without traversing.
3036 ****************************************************************************/
3038 static bool get_stored_queue_info(struct messaging_context *msg_ctx,
3039 struct tdb_print_db *pdb, int snum,
3040 int *pcount, print_queue_struct **ppqueue)
3042 TDB_DATA data, cgdata, jcdata;
3043 print_queue_struct *queue = NULL;
3044 uint32 qcount = 0;
3045 uint32 extra_count = 0;
3046 uint32_t changed_count = 0;
3047 int total_count = 0;
3048 size_t len = 0;
3049 uint32 i;
3050 int max_reported_jobs = lp_max_reported_print_jobs(snum);
3051 bool ret = false;
3052 const char* sharename = lp_servicename(talloc_tos(), snum);
3053 TALLOC_CTX *tmp_ctx = talloc_new(msg_ctx);
3054 if (tmp_ctx == NULL) {
3055 return false;
3058 /* make sure the database is up to date */
3059 if (print_cache_expired(lp_const_servicename(snum), True))
3060 print_queue_update(msg_ctx, snum, False);
3062 *pcount = 0;
3063 *ppqueue = NULL;
3065 ZERO_STRUCT(data);
3066 ZERO_STRUCT(cgdata);
3068 /* Get the stored queue data. */
3069 data = tdb_fetch_compat(pdb->tdb, string_tdb_data("INFO/linear_queue_array"));
3071 if (data.dptr && data.dsize >= sizeof(qcount))
3072 len += tdb_unpack(data.dptr + len, data.dsize - len, "d", &qcount);
3074 /* Get the added jobs list. */
3075 cgdata = tdb_fetch_compat(pdb->tdb, string_tdb_data("INFO/jobs_added"));
3076 if (cgdata.dptr != NULL && (cgdata.dsize % 4 == 0))
3077 extra_count = cgdata.dsize/4;
3079 /* Get the changed jobs list. */
3080 jcdata = tdb_fetch_compat(pdb->tdb, string_tdb_data("INFO/jobs_changed"));
3081 if (jcdata.dptr != NULL && (jcdata.dsize % 4 == 0))
3082 changed_count = jcdata.dsize / 4;
3084 DEBUG(5,("get_stored_queue_info: qcount = %u, extra_count = %u\n", (unsigned int)qcount, (unsigned int)extra_count));
3086 /* Allocate the queue size. */
3087 if (qcount == 0 && extra_count == 0)
3088 goto out;
3090 if ((queue = SMB_MALLOC_ARRAY(print_queue_struct, qcount + extra_count)) == NULL)
3091 goto out;
3093 /* Retrieve the linearised queue data. */
3095 for(i = 0; i < qcount; i++) {
3096 uint32 qjob, qsize, qpage_count, qstatus, qpriority, qtime;
3097 len += tdb_unpack(data.dptr + len, data.dsize - len, "ddddddff",
3098 &qjob,
3099 &qsize,
3100 &qpage_count,
3101 &qstatus,
3102 &qpriority,
3103 &qtime,
3104 queue[i].fs_user,
3105 queue[i].fs_file);
3106 queue[i].sysjob = qjob;
3107 queue[i].size = qsize;
3108 queue[i].page_count = qpage_count;
3109 queue[i].status = qstatus;
3110 queue[i].priority = qpriority;
3111 queue[i].time = qtime;
3114 total_count = qcount;
3116 /* Add new jobids to the queue. */
3117 for (i = 0; i < extra_count; i++) {
3118 uint32 jobid;
3119 struct printjob *pjob;
3121 jobid = IVAL(cgdata.dptr, i*4);
3122 DEBUG(5,("get_stored_queue_info: added job = %u\n", (unsigned int)jobid));
3123 pjob = print_job_find(tmp_ctx, lp_const_servicename(snum), jobid);
3124 if (!pjob) {
3125 DEBUG(5,("get_stored_queue_info: failed to find added job = %u\n", (unsigned int)jobid));
3126 remove_from_jobs_added(sharename, jobid);
3127 continue;
3130 queue[total_count].sysjob = pjob->sysjob;
3131 queue[total_count].size = pjob->size;
3132 queue[total_count].page_count = pjob->page_count;
3133 queue[total_count].status = pjob->status;
3134 queue[total_count].priority = 1;
3135 queue[total_count].time = pjob->starttime;
3136 fstrcpy(queue[total_count].fs_user, pjob->user);
3137 fstrcpy(queue[total_count].fs_file, pjob->jobname);
3138 total_count++;
3139 talloc_free(pjob);
3142 /* Update the changed jobids. */
3143 for (i = 0; i < changed_count; i++) {
3144 uint32_t jobid = IVAL(jcdata.dptr, i * 4);
3145 struct printjob *pjob;
3146 uint32_t j;
3147 bool found = false;
3149 pjob = print_job_find(tmp_ctx, sharename, jobid);
3150 if (pjob == NULL) {
3151 DEBUG(5,("get_stored_queue_info: failed to find "
3152 "changed job = %u\n",
3153 (unsigned int)jobid));
3154 remove_from_jobs_changed(sharename, jobid);
3155 continue;
3158 for (j = 0; j < total_count; j++) {
3159 if (queue[j].sysjob == pjob->sysjob) {
3160 found = true;
3161 break;
3165 if (found) {
3166 DEBUG(5,("get_stored_queue_info: changed job: %u\n",
3167 (unsigned int)jobid));
3169 queue[j].sysjob = pjob->sysjob;
3170 queue[j].size = pjob->size;
3171 queue[j].page_count = pjob->page_count;
3172 queue[j].status = pjob->status;
3173 queue[j].priority = 1;
3174 queue[j].time = pjob->starttime;
3175 fstrcpy(queue[j].fs_user, pjob->user);
3176 fstrcpy(queue[j].fs_file, pjob->jobname);
3177 talloc_free(pjob);
3179 DEBUG(5,("updated queue[%u], jobid: %u, sysjob: %u, "
3180 "jobname: %s\n",
3181 (unsigned int)j, (unsigned int)jobid,
3182 (unsigned int)queue[j].sysjob, pjob->jobname));
3185 remove_from_jobs_changed(sharename, jobid);
3188 /* Sort the queue by submission time otherwise they are displayed
3189 in hash order. */
3191 TYPESAFE_QSORT(queue, total_count, printjob_comp);
3193 DEBUG(5,("get_stored_queue_info: total_count = %u\n", (unsigned int)total_count));
3195 if (max_reported_jobs && total_count > max_reported_jobs)
3196 total_count = max_reported_jobs;
3198 *ppqueue = queue;
3199 *pcount = total_count;
3201 ret = true;
3203 out:
3205 SAFE_FREE(data.dptr);
3206 SAFE_FREE(cgdata.dptr);
3207 talloc_free(tmp_ctx);
3208 return ret;
3211 /****************************************************************************
3212 Get a printer queue listing.
3213 set queue = NULL and status = NULL if you just want to update the cache
3214 ****************************************************************************/
3216 int print_queue_status(struct messaging_context *msg_ctx, int snum,
3217 print_queue_struct **ppqueue,
3218 print_status_struct *status)
3220 fstring keystr;
3221 TDB_DATA data, key;
3222 const char *sharename;
3223 struct tdb_print_db *pdb;
3224 int count = 0;
3226 /* make sure the database is up to date */
3228 if (print_cache_expired(lp_const_servicename(snum), True))
3229 print_queue_update(msg_ctx, snum, False);
3231 /* return if we are done */
3232 if ( !ppqueue || !status )
3233 return 0;
3235 *ppqueue = NULL;
3236 sharename = lp_const_servicename(snum);
3237 pdb = get_print_db_byname(sharename);
3239 if (!pdb)
3240 return 0;
3243 * Fetch the queue status. We must do this first, as there may
3244 * be no jobs in the queue.
3247 ZERO_STRUCTP(status);
3248 slprintf(keystr, sizeof(keystr)-1, "STATUS/%s", sharename);
3249 key = string_tdb_data(keystr);
3251 data = tdb_fetch_compat(pdb->tdb, key);
3252 if (data.dptr) {
3253 if (data.dsize == sizeof(*status)) {
3254 /* this memcpy is ok since the status struct was
3255 not packed before storing it in the tdb */
3256 memcpy(status, data.dptr, sizeof(*status));
3258 SAFE_FREE(data.dptr);
3262 * Now, fetch the print queue information. We first count the number
3263 * of entries, and then only retrieve the queue if necessary.
3266 if (!get_stored_queue_info(msg_ctx, pdb, snum, &count, ppqueue)) {
3267 release_print_db(pdb);
3268 return 0;
3271 release_print_db(pdb);
3272 return count;
3275 /****************************************************************************
3276 Pause a queue.
3277 ****************************************************************************/
3279 WERROR print_queue_pause(const struct auth_session_info *server_info,
3280 struct messaging_context *msg_ctx, int snum)
3282 int ret;
3283 struct printif *current_printif = get_printer_fns( snum );
3285 if (!W_ERROR_IS_OK(print_access_check(server_info, msg_ctx, snum,
3286 PRINTER_ACCESS_ADMINISTER))) {
3287 return WERR_ACCESS_DENIED;
3291 become_root();
3293 ret = (*(current_printif->queue_pause))(snum);
3295 unbecome_root();
3297 if (ret != 0) {
3298 return WERR_INVALID_PARAM;
3301 /* force update the database */
3302 print_cache_flush(lp_const_servicename(snum));
3304 /* Send a printer notify message */
3306 notify_printer_status(server_event_context(), msg_ctx, snum,
3307 PRINTER_STATUS_PAUSED);
3309 return WERR_OK;
3312 /****************************************************************************
3313 Resume a queue.
3314 ****************************************************************************/
3316 WERROR print_queue_resume(const struct auth_session_info *server_info,
3317 struct messaging_context *msg_ctx, int snum)
3319 int ret;
3320 struct printif *current_printif = get_printer_fns( snum );
3322 if (!W_ERROR_IS_OK(print_access_check(server_info, msg_ctx, snum,
3323 PRINTER_ACCESS_ADMINISTER))) {
3324 return WERR_ACCESS_DENIED;
3327 become_root();
3329 ret = (*(current_printif->queue_resume))(snum);
3331 unbecome_root();
3333 if (ret != 0) {
3334 return WERR_INVALID_PARAM;
3337 /* make sure the database is up to date */
3338 if (print_cache_expired(lp_const_servicename(snum), True))
3339 print_queue_update(msg_ctx, snum, True);
3341 /* Send a printer notify message */
3343 notify_printer_status(server_event_context(), msg_ctx, snum,
3344 PRINTER_STATUS_OK);
3346 return WERR_OK;
3349 /****************************************************************************
3350 Purge a queue - implemented by deleting all jobs that we can delete.
3351 ****************************************************************************/
3353 WERROR print_queue_purge(const struct auth_session_info *server_info,
3354 struct messaging_context *msg_ctx, int snum)
3356 print_queue_struct *queue;
3357 print_status_struct status;
3358 int njobs, i;
3359 bool can_job_admin;
3361 /* Force and update so the count is accurate (i.e. not a cached count) */
3362 print_queue_update(msg_ctx, snum, True);
3364 can_job_admin = W_ERROR_IS_OK(print_access_check(server_info,
3365 msg_ctx,
3366 snum,
3367 JOB_ACCESS_ADMINISTER));
3368 njobs = print_queue_status(msg_ctx, snum, &queue, &status);
3370 if ( can_job_admin )
3371 become_root();
3373 for (i = 0; i < njobs; i++) {
3374 struct tdb_print_db *pdb;
3375 int jobid;
3376 bool owner;
3377 pdb = get_print_db_byname(lp_const_servicename(snum));
3378 if (pdb == NULL) {
3379 DEBUG(1, ("failed to find printdb for %s\n",
3380 lp_const_servicename(snum)));
3381 continue;
3383 jobid = sysjob_to_jobid_pdb(pdb, queue[i].sysjob);
3384 if (jobid == (uint32_t)-1) {
3385 DEBUG(2, ("jobid for system job %d not found\n",
3386 queue[i].sysjob));
3387 continue; /* unix job */
3389 owner = is_owner(server_info, lp_const_servicename(snum),
3390 jobid);
3392 if (owner || can_job_admin) {
3393 print_job_delete1(server_event_context(), msg_ctx,
3394 snum, jobid);
3398 if ( can_job_admin )
3399 unbecome_root();
3401 /* update the cache */
3402 print_queue_update(msg_ctx, snum, True);
3404 SAFE_FREE(queue);
3406 return WERR_OK;