s3-docs: Fix several typos.
[Samba.git] / source3 / printing / printing.c
blobf15bd4f754a435928e4eecfd4a4921220a2e50b8
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 "serverid.h"
32 #include "smbd/smbd.h"
33 #include "auth.h"
34 #include "messages.h"
35 #include "util_tdb.h"
37 extern struct current_user current_user;
38 extern userdom_struct current_user_info;
40 /* Current printer interface */
41 static bool remove_from_jobs_added(const char* sharename, uint32 jobid);
44 the printing backend revolves around a tdb database that stores the
45 SMB view of the print queue
47 The key for this database is a jobid - a internally generated number that
48 uniquely identifies a print job
50 reading the print queue involves two steps:
51 - possibly running lpq and updating the internal database from that
52 - reading entries from the database
54 jobids are assigned when a job starts spooling.
57 static TDB_CONTEXT *rap_tdb;
58 static uint16 next_rap_jobid;
59 struct rap_jobid_key {
60 fstring sharename;
61 uint32 jobid;
64 /***************************************************************************
65 Nightmare. LANMAN jobid's are 16 bit numbers..... We must map them to 32
66 bit RPC jobids.... JRA.
67 ***************************************************************************/
69 uint16 pjobid_to_rap(const char* sharename, uint32 jobid)
71 uint16 rap_jobid;
72 TDB_DATA data, key;
73 struct rap_jobid_key jinfo;
74 uint8 buf[2];
76 DEBUG(10,("pjobid_to_rap: called.\n"));
78 if (!rap_tdb) {
79 /* Create the in-memory tdb. */
80 rap_tdb = tdb_open_log(NULL, 0, TDB_INTERNAL, (O_RDWR|O_CREAT), 0644);
81 if (!rap_tdb)
82 return 0;
85 ZERO_STRUCT( jinfo );
86 fstrcpy( jinfo.sharename, sharename );
87 jinfo.jobid = jobid;
88 key.dptr = (uint8 *)&jinfo;
89 key.dsize = sizeof(jinfo);
91 data = tdb_fetch(rap_tdb, key);
92 if (data.dptr && data.dsize == sizeof(uint16)) {
93 rap_jobid = SVAL(data.dptr, 0);
94 SAFE_FREE(data.dptr);
95 DEBUG(10,("pjobid_to_rap: jobid %u maps to RAP jobid %u\n",
96 (unsigned int)jobid, (unsigned int)rap_jobid));
97 return rap_jobid;
99 SAFE_FREE(data.dptr);
100 /* Not found - create and store mapping. */
101 rap_jobid = ++next_rap_jobid;
102 if (rap_jobid == 0)
103 rap_jobid = ++next_rap_jobid;
104 SSVAL(buf,0,rap_jobid);
105 data.dptr = buf;
106 data.dsize = sizeof(rap_jobid);
107 tdb_store(rap_tdb, key, data, TDB_REPLACE);
108 tdb_store(rap_tdb, data, key, TDB_REPLACE);
110 DEBUG(10,("pjobid_to_rap: created jobid %u maps to RAP jobid %u\n",
111 (unsigned int)jobid, (unsigned int)rap_jobid));
112 return rap_jobid;
115 bool rap_to_pjobid(uint16 rap_jobid, fstring sharename, uint32 *pjobid)
117 TDB_DATA data, key;
118 uint8 buf[2];
120 DEBUG(10,("rap_to_pjobid called.\n"));
122 if (!rap_tdb)
123 return False;
125 SSVAL(buf,0,rap_jobid);
126 key.dptr = buf;
127 key.dsize = sizeof(rap_jobid);
128 data = tdb_fetch(rap_tdb, key);
129 if ( data.dptr && data.dsize == sizeof(struct rap_jobid_key) )
131 struct rap_jobid_key *jinfo = (struct rap_jobid_key*)data.dptr;
132 if (sharename != NULL) {
133 fstrcpy( sharename, jinfo->sharename );
135 *pjobid = jinfo->jobid;
136 DEBUG(10,("rap_to_pjobid: jobid %u maps to RAP jobid %u\n",
137 (unsigned int)*pjobid, (unsigned int)rap_jobid));
138 SAFE_FREE(data.dptr);
139 return True;
142 DEBUG(10,("rap_to_pjobid: Failed to lookup RAP jobid %u\n",
143 (unsigned int)rap_jobid));
144 SAFE_FREE(data.dptr);
145 return False;
148 void rap_jobid_delete(const char* sharename, uint32 jobid)
150 TDB_DATA key, data;
151 uint16 rap_jobid;
152 struct rap_jobid_key jinfo;
153 uint8 buf[2];
155 DEBUG(10,("rap_jobid_delete: called.\n"));
157 if (!rap_tdb)
158 return;
160 ZERO_STRUCT( jinfo );
161 fstrcpy( jinfo.sharename, sharename );
162 jinfo.jobid = jobid;
163 key.dptr = (uint8 *)&jinfo;
164 key.dsize = sizeof(jinfo);
166 data = tdb_fetch(rap_tdb, key);
167 if (!data.dptr || (data.dsize != sizeof(uint16))) {
168 DEBUG(10,("rap_jobid_delete: cannot find jobid %u\n",
169 (unsigned int)jobid ));
170 SAFE_FREE(data.dptr);
171 return;
174 DEBUG(10,("rap_jobid_delete: deleting jobid %u\n",
175 (unsigned int)jobid ));
177 rap_jobid = SVAL(data.dptr, 0);
178 SAFE_FREE(data.dptr);
179 SSVAL(buf,0,rap_jobid);
180 data.dptr = buf;
181 data.dsize = sizeof(rap_jobid);
182 tdb_delete(rap_tdb, key);
183 tdb_delete(rap_tdb, data);
186 static int get_queue_status(const char* sharename, print_status_struct *);
188 /****************************************************************************
189 Initialise the printing backend. Called once at startup before the fork().
190 ****************************************************************************/
192 bool print_backend_init(struct messaging_context *msg_ctx)
194 const char *sversion = "INFO/version";
195 int services = lp_numservices();
196 int snum;
198 unlink(cache_path("printing.tdb"));
199 mkdir(cache_path("printing"),0755);
201 /* handle a Samba upgrade */
203 for (snum = 0; snum < services; snum++) {
204 struct tdb_print_db *pdb;
205 if (!lp_print_ok(snum))
206 continue;
208 pdb = get_print_db_byname(lp_const_servicename(snum));
209 if (!pdb)
210 continue;
211 if (tdb_lock_bystring(pdb->tdb, sversion) == -1) {
212 DEBUG(0,("print_backend_init: Failed to open printer %s database\n", lp_const_servicename(snum) ));
213 release_print_db(pdb);
214 return False;
216 if (tdb_fetch_int32(pdb->tdb, sversion) != PRINT_DATABASE_VERSION) {
217 tdb_wipe_all(pdb->tdb);
218 tdb_store_int32(pdb->tdb, sversion, PRINT_DATABASE_VERSION);
220 tdb_unlock_bystring(pdb->tdb, sversion);
221 release_print_db(pdb);
224 close_all_print_db(); /* Don't leave any open. */
226 /* do NT print initialization... */
227 return nt_printing_init(msg_ctx);
230 /****************************************************************************
231 Shut down printing backend. Called once at shutdown to close the tdb.
232 ****************************************************************************/
234 void printing_end(void)
236 close_all_print_db(); /* Don't leave any open. */
239 /****************************************************************************
240 Retrieve the set of printing functions for a given service. This allows
241 us to set the printer function table based on the value of the 'printing'
242 service parameter.
244 Use the generic interface as the default and only use cups interface only
245 when asked for (and only when supported)
246 ****************************************************************************/
248 static struct printif *get_printer_fns_from_type( enum printing_types type )
250 struct printif *printer_fns = &generic_printif;
252 #ifdef HAVE_CUPS
253 if ( type == PRINT_CUPS ) {
254 printer_fns = &cups_printif;
256 #endif /* HAVE_CUPS */
258 #ifdef HAVE_IPRINT
259 if ( type == PRINT_IPRINT ) {
260 printer_fns = &iprint_printif;
262 #endif /* HAVE_IPRINT */
264 printer_fns->type = type;
266 return printer_fns;
269 static struct printif *get_printer_fns( int snum )
271 return get_printer_fns_from_type( (enum printing_types)lp_printing(snum) );
275 /****************************************************************************
276 Useful function to generate a tdb key.
277 ****************************************************************************/
279 static TDB_DATA print_key(uint32 jobid, uint32 *tmp)
281 TDB_DATA ret;
283 SIVAL(tmp, 0, jobid);
284 ret.dptr = (uint8 *)tmp;
285 ret.dsize = sizeof(*tmp);
286 return ret;
289 /****************************************************************************
290 Pack the devicemode to store it in a tdb.
291 ****************************************************************************/
292 static int pack_devicemode(struct spoolss_DeviceMode *devmode, uint8 *buf, int buflen)
294 enum ndr_err_code ndr_err;
295 DATA_BLOB blob;
296 int len = 0;
298 if (devmode) {
299 ndr_err = ndr_push_struct_blob(&blob, talloc_tos(),
300 devmode,
301 (ndr_push_flags_fn_t)
302 ndr_push_spoolss_DeviceMode);
303 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
304 DEBUG(10, ("pack_devicemode: "
305 "error encoding spoolss_DeviceMode\n"));
306 goto done;
308 } else {
309 ZERO_STRUCT(blob);
312 len = tdb_pack(buf, buflen, "B", blob.length, blob.data);
314 if (devmode) {
315 DEBUG(8, ("Packed devicemode [%s]\n", devmode->formname));
318 done:
319 return len;
322 /****************************************************************************
323 Unpack the devicemode to store it in a tdb.
324 ****************************************************************************/
325 static int unpack_devicemode(TALLOC_CTX *mem_ctx,
326 const uint8 *buf, int buflen,
327 struct spoolss_DeviceMode **devmode)
329 struct spoolss_DeviceMode *dm;
330 enum ndr_err_code ndr_err;
331 char *data = NULL;
332 int data_len = 0;
333 DATA_BLOB blob;
334 int len = 0;
336 *devmode = NULL;
338 len = tdb_unpack(buf, buflen, "B", &data_len, &data);
339 if (!data) {
340 return len;
343 dm = talloc_zero(mem_ctx, struct spoolss_DeviceMode);
344 if (!dm) {
345 goto done;
348 blob = data_blob_const(data, data_len);
350 ndr_err = ndr_pull_struct_blob(&blob, dm, dm,
351 (ndr_pull_flags_fn_t)ndr_pull_spoolss_DeviceMode);
352 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
353 DEBUG(10, ("unpack_devicemode: "
354 "error parsing spoolss_DeviceMode\n"));
355 goto done;
358 DEBUG(8, ("Unpacked devicemode [%s](%s)\n",
359 dm->devicename, dm->formname));
360 if (dm->driverextra_data.data) {
361 DEBUG(8, ("with a private section of %d bytes\n",
362 dm->__driverextra_length));
365 *devmode = dm;
367 done:
368 SAFE_FREE(data);
369 return len;
372 /***********************************************************************
373 unpack a pjob from a tdb buffer
374 ***********************************************************************/
376 static int unpack_pjob( uint8 *buf, int buflen, struct printjob *pjob )
378 int len = 0;
379 int used;
380 uint32 pjpid, pjsysjob, pjfd, pjstarttime, pjstatus;
381 uint32 pjsize, pjpage_count, pjspooled, pjsmbjob;
383 if ( !buf || !pjob )
384 return -1;
386 len += tdb_unpack(buf+len, buflen-len, "dddddddddfffff",
387 &pjpid,
388 &pjsysjob,
389 &pjfd,
390 &pjstarttime,
391 &pjstatus,
392 &pjsize,
393 &pjpage_count,
394 &pjspooled,
395 &pjsmbjob,
396 pjob->filename,
397 pjob->jobname,
398 pjob->user,
399 pjob->clientmachine,
400 pjob->queuename);
402 if ( len == -1 )
403 return -1;
405 used = unpack_devicemode(NULL, buf+len, buflen-len, &pjob->devmode);
406 if (used == -1) {
407 return -1;
410 len += used;
412 pjob->pid = pjpid;
413 pjob->sysjob = pjsysjob;
414 pjob->fd = pjfd;
415 pjob->starttime = pjstarttime;
416 pjob->status = pjstatus;
417 pjob->size = pjsize;
418 pjob->page_count = pjpage_count;
419 pjob->spooled = pjspooled;
420 pjob->smbjob = pjsmbjob;
422 return len;
426 /****************************************************************************
427 Useful function to find a print job in the database.
428 ****************************************************************************/
430 static struct printjob *print_job_find(const char *sharename, uint32 jobid)
432 static struct printjob pjob;
433 uint32_t tmp;
434 TDB_DATA ret;
435 struct tdb_print_db *pdb = get_print_db_byname(sharename);
437 DEBUG(10,("print_job_find: looking up job %u for share %s\n",
438 (unsigned int)jobid, sharename ));
440 if (!pdb) {
441 return NULL;
444 ret = tdb_fetch(pdb->tdb, print_key(jobid, &tmp));
445 release_print_db(pdb);
447 if (!ret.dptr) {
448 DEBUG(10,("print_job_find: failed to find jobid %u.\n", (unsigned int)jobid ));
449 return NULL;
452 talloc_free(pjob.devmode);
454 ZERO_STRUCT( pjob );
456 if ( unpack_pjob( ret.dptr, ret.dsize, &pjob ) == -1 ) {
457 DEBUG(10,("print_job_find: failed to unpack jobid %u.\n", (unsigned int)jobid ));
458 SAFE_FREE(ret.dptr);
459 return NULL;
462 SAFE_FREE(ret.dptr);
464 DEBUG(10,("print_job_find: returning system job %d for jobid %u.\n",
465 (int)pjob.sysjob, (unsigned int)jobid ));
467 return &pjob;
470 /* Convert a unix jobid to a smb jobid */
472 struct unixjob_traverse_state {
473 int sysjob;
474 uint32 sysjob_to_jobid_value;
477 static int unixjob_traverse_fn(TDB_CONTEXT *the_tdb, TDB_DATA key,
478 TDB_DATA data, void *private_data)
480 struct printjob *pjob;
481 struct unixjob_traverse_state *state =
482 (struct unixjob_traverse_state *)private_data;
484 if (!data.dptr || data.dsize == 0)
485 return 0;
487 pjob = (struct printjob *)data.dptr;
488 if (key.dsize != sizeof(uint32))
489 return 0;
491 if (state->sysjob == pjob->sysjob) {
492 uint32 jobid = IVAL(key.dptr,0);
494 state->sysjob_to_jobid_value = jobid;
495 return 1;
498 return 0;
501 /****************************************************************************
502 This is a *horribly expensive call as we have to iterate through all the
503 current printer tdb's. Don't do this often ! JRA.
504 ****************************************************************************/
506 uint32 sysjob_to_jobid(int unix_jobid)
508 int services = lp_numservices();
509 int snum;
510 struct unixjob_traverse_state state;
512 state.sysjob = unix_jobid;
513 state.sysjob_to_jobid_value = (uint32)-1;
515 for (snum = 0; snum < services; snum++) {
516 struct tdb_print_db *pdb;
517 if (!lp_print_ok(snum))
518 continue;
519 pdb = get_print_db_byname(lp_const_servicename(snum));
520 if (!pdb) {
521 continue;
523 tdb_traverse(pdb->tdb, unixjob_traverse_fn, &state);
524 release_print_db(pdb);
525 if (state.sysjob_to_jobid_value != (uint32)-1)
526 return state.sysjob_to_jobid_value;
528 return (uint32)-1;
531 /****************************************************************************
532 Send notifications based on what has changed after a pjob_store.
533 ****************************************************************************/
535 static const struct {
536 uint32_t lpq_status;
537 uint32_t spoolss_status;
538 } lpq_to_spoolss_status_map[] = {
539 { LPQ_QUEUED, JOB_STATUS_QUEUED },
540 { LPQ_PAUSED, JOB_STATUS_PAUSED },
541 { LPQ_SPOOLING, JOB_STATUS_SPOOLING },
542 { LPQ_PRINTING, JOB_STATUS_PRINTING },
543 { LPQ_DELETING, JOB_STATUS_DELETING },
544 { LPQ_OFFLINE, JOB_STATUS_OFFLINE },
545 { LPQ_PAPEROUT, JOB_STATUS_PAPEROUT },
546 { LPQ_PRINTED, JOB_STATUS_PRINTED },
547 { LPQ_DELETED, JOB_STATUS_DELETED },
548 { LPQ_BLOCKED, JOB_STATUS_BLOCKED_DEVQ },
549 { LPQ_USER_INTERVENTION, JOB_STATUS_USER_INTERVENTION },
550 { (uint32_t)-1, 0 }
553 /* Convert a lpq status value stored in printing.tdb into the
554 appropriate win32 API constant. */
556 static uint32 map_to_spoolss_status(uint32 lpq_status)
558 int i = 0;
560 while (lpq_to_spoolss_status_map[i].lpq_status != -1) {
561 if (lpq_to_spoolss_status_map[i].lpq_status == lpq_status)
562 return lpq_to_spoolss_status_map[i].spoolss_status;
563 i++;
566 return 0;
569 /***************************************************************************
570 Append a jobid to the 'jobs changed' list.
571 ***************************************************************************/
573 static bool add_to_jobs_changed(struct tdb_print_db *pdb, uint32_t jobid)
575 TDB_DATA data;
576 uint32_t store_jobid;
578 SIVAL(&store_jobid, 0, jobid);
579 data.dptr = (uint8 *) &store_jobid;
580 data.dsize = 4;
582 DEBUG(10,("add_to_jobs_added: Added jobid %u\n", (unsigned int)jobid ));
584 return (tdb_append(pdb->tdb, string_tdb_data("INFO/jobs_changed"),
585 data) == 0);
588 /***************************************************************************
589 Remove a jobid from the 'jobs changed' list.
590 ***************************************************************************/
592 static bool remove_from_jobs_changed(const char* sharename, uint32_t jobid)
594 struct tdb_print_db *pdb = get_print_db_byname(sharename);
595 TDB_DATA data, key;
596 size_t job_count, i;
597 bool ret = False;
598 bool gotlock = False;
600 if (!pdb) {
601 return False;
604 ZERO_STRUCT(data);
606 key = string_tdb_data("INFO/jobs_changed");
608 if (tdb_chainlock_with_timeout(pdb->tdb, key, 5) == -1)
609 goto out;
611 gotlock = True;
613 data = tdb_fetch(pdb->tdb, key);
615 if (data.dptr == NULL || data.dsize == 0 || (data.dsize % 4 != 0))
616 goto out;
618 job_count = data.dsize / 4;
619 for (i = 0; i < job_count; i++) {
620 uint32 ch_jobid;
622 ch_jobid = IVAL(data.dptr, i*4);
623 if (ch_jobid == jobid) {
624 if (i < job_count -1 )
625 memmove(data.dptr + (i*4), data.dptr + (i*4) + 4, (job_count - i - 1)*4 );
626 data.dsize -= 4;
627 if (tdb_store(pdb->tdb, key, data, TDB_REPLACE) == -1)
628 goto out;
629 break;
633 ret = True;
634 out:
636 if (gotlock)
637 tdb_chainunlock(pdb->tdb, key);
638 SAFE_FREE(data.dptr);
639 release_print_db(pdb);
640 if (ret)
641 DEBUG(10,("remove_from_jobs_changed: removed jobid %u\n", (unsigned int)jobid ));
642 else
643 DEBUG(10,("remove_from_jobs_changed: Failed to remove jobid %u\n", (unsigned int)jobid ));
644 return ret;
647 static void pjob_store_notify(struct tevent_context *ev,
648 struct messaging_context *msg_ctx,
649 const char* sharename, uint32 jobid,
650 struct printjob *old_data,
651 struct printjob *new_data,
652 bool *pchanged)
654 bool new_job = false;
655 bool changed = false;
657 if (old_data == NULL) {
658 new_job = true;
661 /* ACHTUNG! Due to a bug in Samba's spoolss parsing of the
662 NOTIFY_INFO_DATA buffer, we *have* to send the job submission
663 time first or else we'll end up with potential alignment
664 errors. I don't think the systemtime should be spooled as
665 a string, but this gets us around that error.
666 --jerry (i'll feel dirty for this) */
668 if (new_job) {
669 notify_job_submitted(ev, msg_ctx,
670 sharename, jobid, new_data->starttime);
671 notify_job_username(ev, msg_ctx,
672 sharename, jobid, new_data->user);
673 notify_job_name(ev, msg_ctx,
674 sharename, jobid, new_data->jobname);
675 notify_job_status(ev, msg_ctx,
676 sharename, jobid, map_to_spoolss_status(new_data->status));
677 notify_job_total_bytes(ev, msg_ctx,
678 sharename, jobid, new_data->size);
679 notify_job_total_pages(ev, msg_ctx,
680 sharename, jobid, new_data->page_count);
681 } else {
682 if (!strequal(old_data->jobname, new_data->jobname)) {
683 notify_job_name(ev, msg_ctx, sharename,
684 jobid, new_data->jobname);
685 changed = true;
688 if (old_data->status != new_data->status) {
689 notify_job_status(ev, msg_ctx,
690 sharename, jobid,
691 map_to_spoolss_status(new_data->status));
694 if (old_data->size != new_data->size) {
695 notify_job_total_bytes(ev, msg_ctx,
696 sharename, jobid, new_data->size);
699 if (old_data->page_count != new_data->page_count) {
700 notify_job_total_pages(ev, msg_ctx,
701 sharename, jobid,
702 new_data->page_count);
706 *pchanged = changed;
709 /****************************************************************************
710 Store a job structure back to the database.
711 ****************************************************************************/
713 static bool pjob_store(struct tevent_context *ev,
714 struct messaging_context *msg_ctx,
715 const char* sharename, uint32 jobid,
716 struct printjob *pjob)
718 uint32_t tmp;
719 TDB_DATA old_data, new_data;
720 bool ret = False;
721 struct tdb_print_db *pdb = get_print_db_byname(sharename);
722 uint8 *buf = NULL;
723 int len, newlen, buflen;
726 if (!pdb)
727 return False;
729 /* Get old data */
731 old_data = tdb_fetch(pdb->tdb, print_key(jobid, &tmp));
733 /* Doh! Now we have to pack/unpack data since the NT_DEVICEMODE was added */
735 newlen = 0;
737 do {
738 len = 0;
739 buflen = newlen;
740 len += tdb_pack(buf+len, buflen-len, "dddddddddfffff",
741 (uint32)pjob->pid,
742 (uint32)pjob->sysjob,
743 (uint32)pjob->fd,
744 (uint32)pjob->starttime,
745 (uint32)pjob->status,
746 (uint32)pjob->size,
747 (uint32)pjob->page_count,
748 (uint32)pjob->spooled,
749 (uint32)pjob->smbjob,
750 pjob->filename,
751 pjob->jobname,
752 pjob->user,
753 pjob->clientmachine,
754 pjob->queuename);
756 len += pack_devicemode(pjob->devmode, buf+len, buflen-len);
758 if (buflen != len) {
759 buf = (uint8 *)SMB_REALLOC(buf, len);
760 if (!buf) {
761 DEBUG(0,("pjob_store: failed to enlarge buffer!\n"));
762 goto done;
764 newlen = len;
766 } while ( buflen != len );
769 /* Store new data */
771 new_data.dptr = buf;
772 new_data.dsize = len;
773 ret = (tdb_store(pdb->tdb, print_key(jobid, &tmp), new_data,
774 TDB_REPLACE) == 0);
776 /* Send notify updates for what has changed */
778 if ( ret ) {
779 bool changed = false;
780 struct printjob old_pjob;
782 if ( old_data.dsize )
784 if ( unpack_pjob( old_data.dptr, old_data.dsize, &old_pjob ) != -1 )
786 pjob_store_notify(server_event_context(),
787 msg_ctx,
788 sharename, jobid, &old_pjob,
789 pjob,
790 &changed);
791 talloc_free(old_pjob.devmode);
793 if (changed) {
794 add_to_jobs_changed(pdb, jobid);
799 else {
800 /* new job */
801 pjob_store_notify(server_event_context(), msg_ctx,
802 sharename, jobid, NULL, pjob,
803 &changed);
807 release_print_db(pdb);
808 done:
809 SAFE_FREE( old_data.dptr );
810 SAFE_FREE( buf );
812 return ret;
815 /****************************************************************************
816 Remove a job structure from the database.
817 ****************************************************************************/
819 static void pjob_delete(struct tevent_context *ev,
820 struct messaging_context *msg_ctx,
821 const char* sharename, uint32 jobid)
823 uint32_t tmp;
824 struct printjob *pjob;
825 uint32 job_status = 0;
826 struct tdb_print_db *pdb;
828 pdb = get_print_db_byname( sharename );
830 if (!pdb)
831 return;
833 pjob = print_job_find( sharename, jobid );
835 if (!pjob) {
836 DEBUG(5, ("pjob_delete: we were asked to delete nonexistent job %u\n",
837 (unsigned int)jobid));
838 release_print_db(pdb);
839 return;
842 /* We must cycle through JOB_STATUS_DELETING and
843 JOB_STATUS_DELETED for the port monitor to delete the job
844 properly. */
846 job_status = JOB_STATUS_DELETING|JOB_STATUS_DELETED;
847 notify_job_status(ev, msg_ctx, sharename, jobid, job_status);
849 /* Remove from printing.tdb */
851 tdb_delete(pdb->tdb, print_key(jobid, &tmp));
852 remove_from_jobs_added(sharename, jobid);
853 release_print_db( pdb );
854 rap_jobid_delete(sharename, jobid);
857 /****************************************************************************
858 List a unix job in the print database.
859 ****************************************************************************/
861 static void print_unix_job(struct tevent_context *ev,
862 struct messaging_context *msg_ctx,
863 const char *sharename, print_queue_struct *q,
864 uint32 jobid)
866 struct printjob pj, *old_pj;
868 if (jobid == (uint32)-1)
869 jobid = q->job + UNIX_JOB_START;
871 /* Preserve the timestamp on an existing unix print job */
873 old_pj = print_job_find(sharename, jobid);
875 ZERO_STRUCT(pj);
877 pj.pid = (pid_t)-1;
878 pj.sysjob = q->job;
879 pj.fd = -1;
880 pj.starttime = old_pj ? old_pj->starttime : q->time;
881 pj.status = q->status;
882 pj.size = q->size;
883 pj.spooled = True;
884 fstrcpy(pj.filename, old_pj ? old_pj->filename : "");
885 if (jobid < UNIX_JOB_START) {
886 pj.smbjob = True;
887 fstrcpy(pj.jobname, old_pj ? old_pj->jobname : "Remote Downlevel Document");
888 } else {
889 pj.smbjob = False;
890 fstrcpy(pj.jobname, old_pj ? old_pj->jobname : q->fs_file);
892 fstrcpy(pj.user, old_pj ? old_pj->user : q->fs_user);
893 fstrcpy(pj.queuename, old_pj ? old_pj->queuename : sharename );
895 pjob_store(ev, msg_ctx, sharename, jobid, &pj);
899 struct traverse_struct {
900 print_queue_struct *queue;
901 int qcount, snum, maxcount, total_jobs;
902 const char *sharename;
903 time_t lpq_time;
904 const char *lprm_command;
905 struct printif *print_if;
906 struct tevent_context *ev;
907 struct messaging_context *msg_ctx;
910 /****************************************************************************
911 Utility fn to delete any jobs that are no longer active.
912 ****************************************************************************/
914 static int traverse_fn_delete(TDB_CONTEXT *t, TDB_DATA key, TDB_DATA data, void *state)
916 struct traverse_struct *ts = (struct traverse_struct *)state;
917 struct printjob pjob;
918 uint32 jobid;
919 int i = 0;
921 if ( key.dsize != sizeof(jobid) )
922 return 0;
924 jobid = IVAL(key.dptr, 0);
925 if ( unpack_pjob( data.dptr, data.dsize, &pjob ) == -1 )
926 return 0;
927 talloc_free(pjob.devmode);
930 if (!pjob.smbjob) {
931 /* remove a unix job if it isn't in the system queue any more */
933 for (i=0;i<ts->qcount;i++) {
934 uint32 u_jobid = (ts->queue[i].job + UNIX_JOB_START);
935 if (jobid == u_jobid)
936 break;
938 if (i == ts->qcount) {
939 DEBUG(10,("traverse_fn_delete: pjob %u deleted due to !smbjob\n",
940 (unsigned int)jobid ));
941 pjob_delete(ts->ev, ts->msg_ctx,
942 ts->sharename, jobid);
943 return 0;
946 /* need to continue the the bottom of the function to
947 save the correct attributes */
950 /* maybe it hasn't been spooled yet */
951 if (!pjob.spooled) {
952 /* if a job is not spooled and the process doesn't
953 exist then kill it. This cleans up after smbd
954 deaths */
955 if (!process_exists_by_pid(pjob.pid)) {
956 DEBUG(10,("traverse_fn_delete: pjob %u deleted due to !process_exists (%u)\n",
957 (unsigned int)jobid, (unsigned int)pjob.pid ));
958 pjob_delete(ts->ev, ts->msg_ctx,
959 ts->sharename, jobid);
960 } else
961 ts->total_jobs++;
962 return 0;
965 /* this check only makes sense for jobs submitted from Windows clients */
967 if ( pjob.smbjob ) {
968 for (i=0;i<ts->qcount;i++) {
969 uint32 curr_jobid;
971 if ( pjob.status == LPQ_DELETED )
972 continue;
974 curr_jobid = print_parse_jobid(ts->queue[i].fs_file);
976 if (jobid == curr_jobid) {
978 /* try to clean up any jobs that need to be deleted */
980 if ( pjob.status == LPQ_DELETING ) {
981 int result;
983 result = (*(ts->print_if->job_delete))(
984 ts->sharename, ts->lprm_command, &pjob );
986 if ( result != 0 ) {
987 /* if we can't delete, then reset the job status */
988 pjob.status = LPQ_QUEUED;
989 pjob_store(ts->ev, ts->msg_ctx,
990 ts->sharename, jobid, &pjob);
992 else {
993 /* if we deleted the job, the remove the tdb record */
994 pjob_delete(ts->ev,
995 ts->msg_ctx,
996 ts->sharename, jobid);
997 pjob.status = LPQ_DELETED;
1002 break;
1007 /* The job isn't in the system queue - we have to assume it has
1008 completed, so delete the database entry. */
1010 if (i == ts->qcount) {
1012 /* A race can occur between the time a job is spooled and
1013 when it appears in the lpq output. This happens when
1014 the job is added to printing.tdb when another smbd
1015 running print_queue_update() has completed a lpq and
1016 is currently traversing the printing tdb and deleting jobs.
1017 Don't delete the job if it was submitted after the lpq_time. */
1019 if (pjob.starttime < ts->lpq_time) {
1020 DEBUG(10,("traverse_fn_delete: pjob %u deleted due to pjob.starttime (%u) < ts->lpq_time (%u)\n",
1021 (unsigned int)jobid,
1022 (unsigned int)pjob.starttime,
1023 (unsigned int)ts->lpq_time ));
1024 pjob_delete(ts->ev, ts->msg_ctx,
1025 ts->sharename, jobid);
1026 } else
1027 ts->total_jobs++;
1028 return 0;
1031 /* Save the pjob attributes we will store.
1032 FIXME!!! This is the only place where queue->job
1033 represents the SMB jobid --jerry */
1035 ts->queue[i].job = jobid;
1036 ts->queue[i].size = pjob.size;
1037 ts->queue[i].page_count = pjob.page_count;
1038 ts->queue[i].status = pjob.status;
1039 ts->queue[i].priority = 1;
1040 ts->queue[i].time = pjob.starttime;
1041 fstrcpy(ts->queue[i].fs_user, pjob.user);
1042 fstrcpy(ts->queue[i].fs_file, pjob.jobname);
1044 ts->total_jobs++;
1046 return 0;
1049 /****************************************************************************
1050 Check if the print queue has been updated recently enough.
1051 ****************************************************************************/
1053 static void print_cache_flush(const char *sharename)
1055 fstring key;
1056 struct tdb_print_db *pdb = get_print_db_byname(sharename);
1058 if (!pdb)
1059 return;
1060 slprintf(key, sizeof(key)-1, "CACHE/%s", sharename);
1061 tdb_store_int32(pdb->tdb, key, -1);
1062 release_print_db(pdb);
1065 /****************************************************************************
1066 Check if someone already thinks they are doing the update.
1067 ****************************************************************************/
1069 static pid_t get_updating_pid(const char *sharename)
1071 fstring keystr;
1072 TDB_DATA data, key;
1073 pid_t updating_pid;
1074 struct tdb_print_db *pdb = get_print_db_byname(sharename);
1076 if (!pdb)
1077 return (pid_t)-1;
1078 slprintf(keystr, sizeof(keystr)-1, "UPDATING/%s", sharename);
1079 key = string_tdb_data(keystr);
1081 data = tdb_fetch(pdb->tdb, key);
1082 release_print_db(pdb);
1083 if (!data.dptr || data.dsize != sizeof(pid_t)) {
1084 SAFE_FREE(data.dptr);
1085 return (pid_t)-1;
1088 updating_pid = IVAL(data.dptr, 0);
1089 SAFE_FREE(data.dptr);
1091 if (process_exists_by_pid(updating_pid))
1092 return updating_pid;
1094 return (pid_t)-1;
1097 /****************************************************************************
1098 Set the fact that we're doing the update, or have finished doing the update
1099 in the tdb.
1100 ****************************************************************************/
1102 static void set_updating_pid(const fstring sharename, bool updating)
1104 fstring keystr;
1105 TDB_DATA key;
1106 TDB_DATA data;
1107 pid_t updating_pid = sys_getpid();
1108 uint8 buffer[4];
1110 struct tdb_print_db *pdb = get_print_db_byname(sharename);
1112 if (!pdb)
1113 return;
1115 slprintf(keystr, sizeof(keystr)-1, "UPDATING/%s", sharename);
1116 key = string_tdb_data(keystr);
1118 DEBUG(5, ("set_updating_pid: %s updating lpq cache for print share %s\n",
1119 updating ? "" : "not ",
1120 sharename ));
1122 if ( !updating ) {
1123 tdb_delete(pdb->tdb, key);
1124 release_print_db(pdb);
1125 return;
1128 SIVAL( buffer, 0, updating_pid);
1129 data.dptr = buffer;
1130 data.dsize = 4; /* we always assume this is a 4 byte value */
1132 tdb_store(pdb->tdb, key, data, TDB_REPLACE);
1133 release_print_db(pdb);
1136 /****************************************************************************
1137 Sort print jobs by submittal time.
1138 ****************************************************************************/
1140 static int printjob_comp(print_queue_struct *j1, print_queue_struct *j2)
1142 /* Silly cases */
1144 if (!j1 && !j2)
1145 return 0;
1146 if (!j1)
1147 return -1;
1148 if (!j2)
1149 return 1;
1151 /* Sort on job start time */
1153 if (j1->time == j2->time)
1154 return 0;
1155 return (j1->time > j2->time) ? 1 : -1;
1158 /****************************************************************************
1159 Store the sorted queue representation for later portmon retrieval.
1160 Skip deleted jobs
1161 ****************************************************************************/
1163 static void store_queue_struct(struct tdb_print_db *pdb, struct traverse_struct *pts)
1165 TDB_DATA data;
1166 int max_reported_jobs = lp_max_reported_jobs(pts->snum);
1167 print_queue_struct *queue = pts->queue;
1168 size_t len;
1169 size_t i;
1170 unsigned int qcount;
1172 if (max_reported_jobs && (max_reported_jobs < pts->qcount))
1173 pts->qcount = max_reported_jobs;
1174 qcount = 0;
1176 /* Work out the size. */
1177 data.dsize = 0;
1178 data.dsize += tdb_pack(NULL, 0, "d", qcount);
1180 for (i = 0; i < pts->qcount; i++) {
1181 if ( queue[i].status == LPQ_DELETED )
1182 continue;
1184 qcount++;
1185 data.dsize += tdb_pack(NULL, 0, "ddddddff",
1186 (uint32)queue[i].job,
1187 (uint32)queue[i].size,
1188 (uint32)queue[i].page_count,
1189 (uint32)queue[i].status,
1190 (uint32)queue[i].priority,
1191 (uint32)queue[i].time,
1192 queue[i].fs_user,
1193 queue[i].fs_file);
1196 if ((data.dptr = (uint8 *)SMB_MALLOC(data.dsize)) == NULL)
1197 return;
1199 len = 0;
1200 len += tdb_pack(data.dptr + len, data.dsize - len, "d", qcount);
1201 for (i = 0; i < pts->qcount; i++) {
1202 if ( queue[i].status == LPQ_DELETED )
1203 continue;
1205 len += tdb_pack(data.dptr + len, data.dsize - len, "ddddddff",
1206 (uint32)queue[i].job,
1207 (uint32)queue[i].size,
1208 (uint32)queue[i].page_count,
1209 (uint32)queue[i].status,
1210 (uint32)queue[i].priority,
1211 (uint32)queue[i].time,
1212 queue[i].fs_user,
1213 queue[i].fs_file);
1216 tdb_store(pdb->tdb, string_tdb_data("INFO/linear_queue_array"), data,
1217 TDB_REPLACE);
1218 SAFE_FREE(data.dptr);
1219 return;
1222 static TDB_DATA get_jobs_added_data(struct tdb_print_db *pdb)
1224 TDB_DATA data;
1226 ZERO_STRUCT(data);
1228 data = tdb_fetch(pdb->tdb, string_tdb_data("INFO/jobs_added"));
1229 if (data.dptr == NULL || data.dsize == 0 || (data.dsize % 4 != 0)) {
1230 SAFE_FREE(data.dptr);
1231 ZERO_STRUCT(data);
1234 return data;
1237 static void check_job_added(const char *sharename, TDB_DATA data, uint32 jobid)
1239 unsigned int i;
1240 unsigned int job_count = data.dsize / 4;
1242 for (i = 0; i < job_count; i++) {
1243 uint32 ch_jobid;
1245 ch_jobid = IVAL(data.dptr, i*4);
1246 if (ch_jobid == jobid)
1247 remove_from_jobs_added(sharename, jobid);
1251 /****************************************************************************
1252 Check if the print queue has been updated recently enough.
1253 ****************************************************************************/
1255 static bool print_cache_expired(const char *sharename, bool check_pending)
1257 fstring key;
1258 time_t last_qscan_time, time_now = time(NULL);
1259 struct tdb_print_db *pdb = get_print_db_byname(sharename);
1260 bool result = False;
1262 if (!pdb)
1263 return False;
1265 snprintf(key, sizeof(key), "CACHE/%s", sharename);
1266 last_qscan_time = (time_t)tdb_fetch_int32(pdb->tdb, key);
1269 * Invalidate the queue for 3 reasons.
1270 * (1). last queue scan time == -1.
1271 * (2). Current time - last queue scan time > allowed cache time.
1272 * (3). last queue scan time > current time + MAX_CACHE_VALID_TIME (1 hour by default).
1273 * This last test picks up machines for which the clock has been moved
1274 * forward, an lpq scan done and then the clock moved back. Otherwise
1275 * that last lpq scan would stay around for a loooong loooong time... :-). JRA.
1278 if (last_qscan_time == ((time_t)-1)
1279 || (time_now - last_qscan_time) >= lp_lpqcachetime()
1280 || last_qscan_time > (time_now + MAX_CACHE_VALID_TIME))
1282 uint32 u;
1283 time_t msg_pending_time;
1285 DEBUG(4, ("print_cache_expired: cache expired for queue %s "
1286 "(last_qscan_time = %d, time now = %d, qcachetime = %d)\n",
1287 sharename, (int)last_qscan_time, (int)time_now,
1288 (int)lp_lpqcachetime() ));
1290 /* check if another smbd has already sent a message to update the
1291 queue. Give the pending message one minute to clear and
1292 then send another message anyways. Make sure to check for
1293 clocks that have been run forward and then back again. */
1295 snprintf(key, sizeof(key), "MSG_PENDING/%s", sharename);
1297 if ( check_pending
1298 && tdb_fetch_uint32( pdb->tdb, key, &u )
1299 && (msg_pending_time=u) > 0
1300 && msg_pending_time <= time_now
1301 && (time_now - msg_pending_time) < 60 )
1303 DEBUG(4,("print_cache_expired: message already pending for %s. Accepting cache\n",
1304 sharename));
1305 goto done;
1308 result = True;
1311 done:
1312 release_print_db(pdb);
1313 return result;
1316 /****************************************************************************
1317 main work for updating the lpq cache for a printer queue
1318 ****************************************************************************/
1320 static void print_queue_update_internal( struct tevent_context *ev,
1321 struct messaging_context *msg_ctx,
1322 const char *sharename,
1323 struct printif *current_printif,
1324 char *lpq_command, char *lprm_command )
1326 int i, qcount;
1327 print_queue_struct *queue = NULL;
1328 print_status_struct status;
1329 print_status_struct old_status;
1330 struct printjob *pjob;
1331 struct traverse_struct tstruct;
1332 TDB_DATA data, key;
1333 TDB_DATA jcdata;
1334 fstring keystr, cachestr;
1335 struct tdb_print_db *pdb = get_print_db_byname(sharename);
1337 if (!pdb) {
1338 return;
1341 DEBUG(5,("print_queue_update_internal: printer = %s, type = %d, lpq command = [%s]\n",
1342 sharename, current_printif->type, lpq_command));
1345 * Update the cache time FIRST ! Stops others even
1346 * attempting to get the lock and doing this
1347 * if the lpq takes a long time.
1350 slprintf(cachestr, sizeof(cachestr)-1, "CACHE/%s", sharename);
1351 tdb_store_int32(pdb->tdb, cachestr, (int)time(NULL));
1353 /* get the current queue using the appropriate interface */
1354 ZERO_STRUCT(status);
1356 qcount = (*(current_printif->queue_get))(sharename,
1357 current_printif->type,
1358 lpq_command, &queue, &status);
1360 DEBUG(3, ("print_queue_update_internal: %d job%s in queue for %s\n",
1361 qcount, (qcount != 1) ? "s" : "", sharename));
1363 /* Sort the queue by submission time otherwise they are displayed
1364 in hash order. */
1366 TYPESAFE_QSORT(queue, qcount, printjob_comp);
1369 any job in the internal database that is marked as spooled
1370 and doesn't exist in the system queue is considered finished
1371 and removed from the database
1373 any job in the system database but not in the internal database
1374 is added as a unix job
1376 fill in any system job numbers as we go
1379 jcdata = get_jobs_added_data(pdb);
1381 for (i=0; i<qcount; i++) {
1382 uint32 jobid = print_parse_jobid(queue[i].fs_file);
1384 if (jobid == (uint32)-1) {
1385 /* assume its a unix print job */
1386 print_unix_job(ev, msg_ctx,
1387 sharename, &queue[i], jobid);
1388 continue;
1391 /* we have an active SMB print job - update its status */
1392 pjob = print_job_find(sharename, jobid);
1393 if (!pjob) {
1394 /* err, somethings wrong. Probably smbd was restarted
1395 with jobs in the queue. All we can do is treat them
1396 like unix jobs. Pity. */
1397 print_unix_job(ev, msg_ctx,
1398 sharename, &queue[i], jobid);
1399 continue;
1402 pjob->sysjob = queue[i].job;
1404 /* don't reset the status on jobs to be deleted */
1406 if ( pjob->status != LPQ_DELETING )
1407 pjob->status = queue[i].status;
1409 pjob_store(ev, msg_ctx, sharename, jobid, pjob);
1411 check_job_added(sharename, jcdata, jobid);
1414 SAFE_FREE(jcdata.dptr);
1416 /* now delete any queued entries that don't appear in the
1417 system queue */
1418 tstruct.queue = queue;
1419 tstruct.qcount = qcount;
1420 tstruct.snum = -1;
1421 tstruct.total_jobs = 0;
1422 tstruct.lpq_time = time(NULL);
1423 tstruct.sharename = sharename;
1424 tstruct.lprm_command = lprm_command;
1425 tstruct.print_if = current_printif;
1426 tstruct.ev = ev;
1427 tstruct.msg_ctx = msg_ctx;
1429 tdb_traverse(pdb->tdb, traverse_fn_delete, (void *)&tstruct);
1431 /* Store the linearised queue, max jobs only. */
1432 store_queue_struct(pdb, &tstruct);
1434 SAFE_FREE(tstruct.queue);
1436 DEBUG(10,("print_queue_update_internal: printer %s INFO/total_jobs = %d\n",
1437 sharename, tstruct.total_jobs ));
1439 tdb_store_int32(pdb->tdb, "INFO/total_jobs", tstruct.total_jobs);
1441 get_queue_status(sharename, &old_status);
1442 if (old_status.qcount != qcount)
1443 DEBUG(10,("print_queue_update_internal: queue status change %d jobs -> %d jobs for printer %s\n",
1444 old_status.qcount, qcount, sharename));
1446 /* store the new queue status structure */
1447 slprintf(keystr, sizeof(keystr)-1, "STATUS/%s", sharename);
1448 key = string_tdb_data(keystr);
1450 status.qcount = qcount;
1451 data.dptr = (uint8 *)&status;
1452 data.dsize = sizeof(status);
1453 tdb_store(pdb->tdb, key, data, TDB_REPLACE);
1456 * Update the cache time again. We want to do this call
1457 * as little as possible...
1460 slprintf(keystr, sizeof(keystr)-1, "CACHE/%s", sharename);
1461 tdb_store_int32(pdb->tdb, keystr, (int32)time(NULL));
1463 /* clear the msg pending record for this queue */
1465 snprintf(keystr, sizeof(keystr), "MSG_PENDING/%s", sharename);
1467 if ( !tdb_store_uint32( pdb->tdb, keystr, 0 ) ) {
1468 /* log a message but continue on */
1470 DEBUG(0,("print_queue_update: failed to store MSG_PENDING flag for [%s]!\n",
1471 sharename));
1474 release_print_db( pdb );
1476 return;
1479 /****************************************************************************
1480 Update the internal database from the system print queue for a queue.
1481 obtain a lock on the print queue before proceeding (needed when mutiple
1482 smbd processes maytry to update the lpq cache concurrently).
1483 ****************************************************************************/
1485 static void print_queue_update_with_lock( struct tevent_context *ev,
1486 struct messaging_context *msg_ctx,
1487 const char *sharename,
1488 struct printif *current_printif,
1489 char *lpq_command, char *lprm_command )
1491 fstring keystr;
1492 struct tdb_print_db *pdb;
1494 DEBUG(5,("print_queue_update_with_lock: printer share = %s\n", sharename));
1495 pdb = get_print_db_byname(sharename);
1496 if (!pdb)
1497 return;
1499 if ( !print_cache_expired(sharename, False) ) {
1500 DEBUG(5,("print_queue_update_with_lock: print cache for %s is still ok\n", sharename));
1501 release_print_db(pdb);
1502 return;
1506 * Check to see if someone else is doing this update.
1507 * This is essentially a mutex on the update.
1510 if (get_updating_pid(sharename) != -1) {
1511 release_print_db(pdb);
1512 return;
1515 /* Lock the queue for the database update */
1517 slprintf(keystr, sizeof(keystr) - 1, "LOCK/%s", sharename);
1518 /* Only wait 10 seconds for this. */
1519 if (tdb_lock_bystring_with_timeout(pdb->tdb, keystr, 10) == -1) {
1520 DEBUG(0,("print_queue_update_with_lock: Failed to lock printer %s database\n", sharename));
1521 release_print_db(pdb);
1522 return;
1526 * Ensure that no one else got in here.
1527 * If the updating pid is still -1 then we are
1528 * the winner.
1531 if (get_updating_pid(sharename) != -1) {
1533 * Someone else is doing the update, exit.
1535 tdb_unlock_bystring(pdb->tdb, keystr);
1536 release_print_db(pdb);
1537 return;
1541 * We're going to do the update ourselves.
1544 /* Tell others we're doing the update. */
1545 set_updating_pid(sharename, True);
1548 * Allow others to enter and notice we're doing
1549 * the update.
1552 tdb_unlock_bystring(pdb->tdb, keystr);
1554 /* do the main work now */
1556 print_queue_update_internal(ev, msg_ctx,
1557 sharename, current_printif,
1558 lpq_command, lprm_command);
1560 /* Delete our pid from the db. */
1561 set_updating_pid(sharename, False);
1562 release_print_db(pdb);
1565 /****************************************************************************
1566 this is the receive function of the background lpq updater
1567 ****************************************************************************/
1568 void print_queue_receive(struct messaging_context *msg,
1569 void *private_data,
1570 uint32_t msg_type,
1571 struct server_id server_id,
1572 DATA_BLOB *data)
1574 fstring sharename;
1575 char *lpqcommand = NULL, *lprmcommand = NULL;
1576 int printing_type;
1577 size_t len;
1579 len = tdb_unpack( (uint8 *)data->data, data->length, "fdPP",
1580 sharename,
1581 &printing_type,
1582 &lpqcommand,
1583 &lprmcommand );
1585 if ( len == -1 ) {
1586 SAFE_FREE(lpqcommand);
1587 SAFE_FREE(lprmcommand);
1588 DEBUG(0,("print_queue_receive: Got invalid print queue update message\n"));
1589 return;
1592 print_queue_update_with_lock(server_event_context(), msg, sharename,
1593 get_printer_fns_from_type((enum printing_types)printing_type),
1594 lpqcommand, lprmcommand );
1596 SAFE_FREE(lpqcommand);
1597 SAFE_FREE(lprmcommand);
1598 return;
1601 static void printing_pause_fd_handler(struct tevent_context *ev,
1602 struct tevent_fd *fde,
1603 uint16_t flags,
1604 void *private_data)
1607 * If pause_pipe[1] is closed it means the parent smbd
1608 * and children exited or aborted.
1610 exit_server_cleanly(NULL);
1613 extern struct child_pid *children;
1614 extern int num_children;
1616 static void add_child_pid(pid_t pid)
1618 struct child_pid *child;
1620 child = SMB_MALLOC_P(struct child_pid);
1621 if (child == NULL) {
1622 DEBUG(0, ("Could not add child struct -- malloc failed\n"));
1623 return;
1625 child->pid = pid;
1626 DLIST_ADD(children, child);
1627 num_children += 1;
1630 static pid_t background_lpq_updater_pid = -1;
1632 /****************************************************************************
1633 main thread of the background lpq updater
1634 ****************************************************************************/
1635 void start_background_queue(struct tevent_context *ev,
1636 struct messaging_context *msg_ctx)
1638 /* Use local variables for this as we don't
1639 * need to save the parent side of this, just
1640 * ensure it closes when the process exits.
1642 int pause_pipe[2];
1644 DEBUG(3,("start_background_queue: Starting background LPQ thread\n"));
1646 if (pipe(pause_pipe) == -1) {
1647 DEBUG(5,("start_background_queue: cannot create pipe. %s\n", strerror(errno) ));
1648 exit(1);
1651 background_lpq_updater_pid = sys_fork();
1653 if (background_lpq_updater_pid == -1) {
1654 DEBUG(5,("start_background_queue: background LPQ thread failed to start. %s\n", strerror(errno) ));
1655 exit(1);
1658 /* Track the printing pid along with other smbd children */
1659 add_child_pid(background_lpq_updater_pid);
1661 if(background_lpq_updater_pid == 0) {
1662 struct tevent_fd *fde;
1663 int ret;
1664 NTSTATUS status;
1666 /* Child. */
1667 DEBUG(5,("start_background_queue: background LPQ thread started\n"));
1669 close(pause_pipe[0]);
1670 pause_pipe[0] = -1;
1672 status = reinit_after_fork(msg_ctx, ev, procid_self(), true);
1674 if (!NT_STATUS_IS_OK(status)) {
1675 DEBUG(0,("reinit_after_fork() failed\n"));
1676 smb_panic("reinit_after_fork() failed");
1679 smbd_setup_sig_term_handler();
1680 smbd_setup_sig_hup_handler(ev, msg_ctx);
1682 if (!serverid_register(procid_self(),
1683 FLAG_MSG_GENERAL|FLAG_MSG_SMBD
1684 |FLAG_MSG_PRINT_GENERAL)) {
1685 exit(1);
1688 if (!locking_init()) {
1689 exit(1);
1692 messaging_register(msg_ctx, NULL, MSG_PRINTER_UPDATE,
1693 print_queue_receive);
1695 fde = tevent_add_fd(ev, ev, pause_pipe[1], TEVENT_FD_READ,
1696 printing_pause_fd_handler,
1697 NULL);
1698 if (!fde) {
1699 DEBUG(0,("tevent_add_fd() failed for pause_pipe\n"));
1700 smb_panic("tevent_add_fd() failed for pause_pipe");
1703 DEBUG(5,("start_background_queue: background LPQ thread waiting for messages\n"));
1704 ret = tevent_loop_wait(ev);
1705 /* should not be reached */
1706 DEBUG(0,("background_queue: tevent_loop_wait() exited with %d - %s\n",
1707 ret, (ret == 0) ? "out of events" : strerror(errno)));
1708 exit(1);
1711 close(pause_pipe[1]);
1714 /****************************************************************************
1715 update the internal database from the system print queue for a queue
1716 ****************************************************************************/
1718 static void print_queue_update(struct messaging_context *msg_ctx,
1719 int snum, bool force)
1721 fstring key;
1722 fstring sharename;
1723 char *lpqcommand = NULL;
1724 char *lprmcommand = NULL;
1725 uint8 *buffer = NULL;
1726 size_t len = 0;
1727 size_t newlen;
1728 struct tdb_print_db *pdb;
1729 int type;
1730 struct printif *current_printif;
1731 TALLOC_CTX *ctx = talloc_tos();
1733 fstrcpy( sharename, lp_const_servicename(snum));
1735 /* don't strip out characters like '$' from the printername */
1737 lpqcommand = talloc_string_sub2(ctx,
1738 lp_lpqcommand(snum),
1739 "%p",
1740 lp_printername(snum),
1741 false, false, false);
1742 if (!lpqcommand) {
1743 return;
1745 lpqcommand = talloc_sub_advanced(ctx,
1746 lp_servicename(snum),
1747 current_user_info.unix_name,
1749 current_user.ut.gid,
1750 get_current_username(),
1751 current_user_info.domain,
1752 lpqcommand);
1753 if (!lpqcommand) {
1754 return;
1757 lprmcommand = talloc_string_sub2(ctx,
1758 lp_lprmcommand(snum),
1759 "%p",
1760 lp_printername(snum),
1761 false, false, false);
1762 if (!lprmcommand) {
1763 return;
1765 lprmcommand = talloc_sub_advanced(ctx,
1766 lp_servicename(snum),
1767 current_user_info.unix_name,
1769 current_user.ut.gid,
1770 get_current_username(),
1771 current_user_info.domain,
1772 lprmcommand);
1773 if (!lprmcommand) {
1774 return;
1778 * Make sure that the background queue process exists.
1779 * Otherwise just do the update ourselves
1782 if ( force || background_lpq_updater_pid == -1 ) {
1783 DEBUG(4,("print_queue_update: updating queue [%s] myself\n", sharename));
1784 current_printif = get_printer_fns( snum );
1785 print_queue_update_with_lock(server_event_context(), msg_ctx,
1786 sharename, current_printif,
1787 lpqcommand, lprmcommand);
1789 return;
1792 type = lp_printing(snum);
1794 /* get the length */
1796 len = tdb_pack( NULL, 0, "fdPP",
1797 sharename,
1798 type,
1799 lpqcommand,
1800 lprmcommand );
1802 buffer = SMB_XMALLOC_ARRAY( uint8, len );
1804 /* now pack the buffer */
1805 newlen = tdb_pack( buffer, len, "fdPP",
1806 sharename,
1807 type,
1808 lpqcommand,
1809 lprmcommand );
1811 SMB_ASSERT( newlen == len );
1813 DEBUG(10,("print_queue_update: Sending message -> printer = %s, "
1814 "type = %d, lpq command = [%s] lprm command = [%s]\n",
1815 sharename, type, lpqcommand, lprmcommand ));
1817 /* here we set a msg pending record for other smbd processes
1818 to throttle the number of duplicate print_queue_update msgs
1819 sent. */
1821 pdb = get_print_db_byname(sharename);
1822 if (!pdb) {
1823 SAFE_FREE(buffer);
1824 return;
1827 snprintf(key, sizeof(key), "MSG_PENDING/%s", sharename);
1829 if ( !tdb_store_uint32( pdb->tdb, key, time(NULL) ) ) {
1830 /* log a message but continue on */
1832 DEBUG(0,("print_queue_update: failed to store MSG_PENDING flag for [%s]!\n",
1833 sharename));
1836 release_print_db( pdb );
1838 /* finally send the message */
1840 messaging_send_buf(msg_ctx, pid_to_procid(background_lpq_updater_pid),
1841 MSG_PRINTER_UPDATE, (uint8 *)buffer, len);
1843 SAFE_FREE( buffer );
1845 return;
1848 /****************************************************************************
1849 Create/Update an entry in the print tdb that will allow us to send notify
1850 updates only to interested smbd's.
1851 ****************************************************************************/
1853 bool print_notify_register_pid(int snum)
1855 TDB_DATA data;
1856 struct tdb_print_db *pdb = NULL;
1857 TDB_CONTEXT *tdb = NULL;
1858 const char *printername;
1859 uint32 mypid = (uint32)sys_getpid();
1860 bool ret = False;
1861 size_t i;
1863 /* if (snum == -1), then the change notify request was
1864 on a print server handle and we need to register on
1865 all print queus */
1867 if (snum == -1)
1869 int num_services = lp_numservices();
1870 int idx;
1872 for ( idx=0; idx<num_services; idx++ ) {
1873 if (lp_snum_ok(idx) && lp_print_ok(idx) )
1874 print_notify_register_pid(idx);
1877 return True;
1879 else /* register for a specific printer */
1881 printername = lp_const_servicename(snum);
1882 pdb = get_print_db_byname(printername);
1883 if (!pdb)
1884 return False;
1885 tdb = pdb->tdb;
1888 if (tdb_lock_bystring_with_timeout(tdb, NOTIFY_PID_LIST_KEY, 10) == -1) {
1889 DEBUG(0,("print_notify_register_pid: Failed to lock printer %s\n",
1890 printername));
1891 if (pdb)
1892 release_print_db(pdb);
1893 return False;
1896 data = get_printer_notify_pid_list( tdb, printername, True );
1898 /* Add ourselves and increase the refcount. */
1900 for (i = 0; i < data.dsize; i += 8) {
1901 if (IVAL(data.dptr,i) == mypid) {
1902 uint32 new_refcount = IVAL(data.dptr, i+4) + 1;
1903 SIVAL(data.dptr, i+4, new_refcount);
1904 break;
1908 if (i == data.dsize) {
1909 /* We weren't in the list. Realloc. */
1910 data.dptr = (uint8 *)SMB_REALLOC(data.dptr, data.dsize + 8);
1911 if (!data.dptr) {
1912 DEBUG(0,("print_notify_register_pid: Relloc fail for printer %s\n",
1913 printername));
1914 goto done;
1916 data.dsize += 8;
1917 SIVAL(data.dptr,data.dsize - 8,mypid);
1918 SIVAL(data.dptr,data.dsize - 4,1); /* Refcount. */
1921 /* Store back the record. */
1922 if (tdb_store_bystring(tdb, NOTIFY_PID_LIST_KEY, data, TDB_REPLACE) == -1) {
1923 DEBUG(0,("print_notify_register_pid: Failed to update pid \
1924 list for printer %s\n", printername));
1925 goto done;
1928 ret = True;
1930 done:
1932 tdb_unlock_bystring(tdb, NOTIFY_PID_LIST_KEY);
1933 if (pdb)
1934 release_print_db(pdb);
1935 SAFE_FREE(data.dptr);
1936 return ret;
1939 /****************************************************************************
1940 Update an entry in the print tdb that will allow us to send notify
1941 updates only to interested smbd's.
1942 ****************************************************************************/
1944 bool print_notify_deregister_pid(int snum)
1946 TDB_DATA data;
1947 struct tdb_print_db *pdb = NULL;
1948 TDB_CONTEXT *tdb = NULL;
1949 const char *printername;
1950 uint32 mypid = (uint32)sys_getpid();
1951 size_t i;
1952 bool ret = False;
1954 /* if ( snum == -1 ), we are deregister a print server handle
1955 which means to deregister on all print queues */
1957 if (snum == -1)
1959 int num_services = lp_numservices();
1960 int idx;
1962 for ( idx=0; idx<num_services; idx++ ) {
1963 if ( lp_snum_ok(idx) && lp_print_ok(idx) )
1964 print_notify_deregister_pid(idx);
1967 return True;
1969 else /* deregister a specific printer */
1971 printername = lp_const_servicename(snum);
1972 pdb = get_print_db_byname(printername);
1973 if (!pdb)
1974 return False;
1975 tdb = pdb->tdb;
1978 if (tdb_lock_bystring_with_timeout(tdb, NOTIFY_PID_LIST_KEY, 10) == -1) {
1979 DEBUG(0,("print_notify_register_pid: Failed to lock \
1980 printer %s database\n", printername));
1981 if (pdb)
1982 release_print_db(pdb);
1983 return False;
1986 data = get_printer_notify_pid_list( tdb, printername, True );
1988 /* Reduce refcount. Remove ourselves if zero. */
1990 for (i = 0; i < data.dsize; ) {
1991 if (IVAL(data.dptr,i) == mypid) {
1992 uint32 refcount = IVAL(data.dptr, i+4);
1994 refcount--;
1996 if (refcount == 0) {
1997 if (data.dsize - i > 8)
1998 memmove( &data.dptr[i], &data.dptr[i+8], data.dsize - i - 8);
1999 data.dsize -= 8;
2000 continue;
2002 SIVAL(data.dptr, i+4, refcount);
2005 i += 8;
2008 if (data.dsize == 0)
2009 SAFE_FREE(data.dptr);
2011 /* Store back the record. */
2012 if (tdb_store_bystring(tdb, NOTIFY_PID_LIST_KEY, data, TDB_REPLACE) == -1) {
2013 DEBUG(0,("print_notify_register_pid: Failed to update pid \
2014 list for printer %s\n", printername));
2015 goto done;
2018 ret = True;
2020 done:
2022 tdb_unlock_bystring(tdb, NOTIFY_PID_LIST_KEY);
2023 if (pdb)
2024 release_print_db(pdb);
2025 SAFE_FREE(data.dptr);
2026 return ret;
2029 /****************************************************************************
2030 Check if a jobid is valid. It is valid if it exists in the database.
2031 ****************************************************************************/
2033 bool print_job_exists(const char* sharename, uint32 jobid)
2035 struct tdb_print_db *pdb = get_print_db_byname(sharename);
2036 bool ret;
2037 uint32_t tmp;
2039 if (!pdb)
2040 return False;
2041 ret = tdb_exists(pdb->tdb, print_key(jobid, &tmp));
2042 release_print_db(pdb);
2043 return ret;
2046 /****************************************************************************
2047 Give the filename used for a jobid.
2048 Only valid for the process doing the spooling and when the job
2049 has not been spooled.
2050 ****************************************************************************/
2052 char *print_job_fname(const char* sharename, uint32 jobid)
2054 struct printjob *pjob = print_job_find(sharename, jobid);
2055 if (!pjob || pjob->spooled || pjob->pid != sys_getpid())
2056 return NULL;
2057 return pjob->filename;
2061 /****************************************************************************
2062 Give the filename used for a jobid.
2063 Only valid for the process doing the spooling and when the job
2064 has not been spooled.
2065 ****************************************************************************/
2067 struct spoolss_DeviceMode *print_job_devmode(const char* sharename, uint32 jobid)
2069 struct printjob *pjob = print_job_find(sharename, jobid);
2071 if ( !pjob )
2072 return NULL;
2074 return pjob->devmode;
2077 /****************************************************************************
2078 Set the name of a job. Only possible for owner.
2079 ****************************************************************************/
2081 bool print_job_set_name(struct tevent_context *ev,
2082 struct messaging_context *msg_ctx,
2083 const char *sharename, uint32 jobid, const char *name)
2085 struct printjob *pjob;
2087 pjob = print_job_find(sharename, jobid);
2088 if (!pjob || pjob->pid != sys_getpid())
2089 return False;
2091 fstrcpy(pjob->jobname, name);
2092 return pjob_store(ev, msg_ctx, sharename, jobid, pjob);
2095 /****************************************************************************
2096 Get the name of a job. Only possible for owner.
2097 ****************************************************************************/
2099 bool print_job_get_name(TALLOC_CTX *mem_ctx, const char *sharename, uint32_t jobid, char **name)
2101 struct printjob *pjob;
2103 pjob = print_job_find(sharename, jobid);
2104 if (!pjob || pjob->pid != sys_getpid()) {
2105 return false;
2108 *name = talloc_strdup(mem_ctx, pjob->jobname);
2109 if (!*name) {
2110 return false;
2113 return true;
2117 /***************************************************************************
2118 Remove a jobid from the 'jobs added' list.
2119 ***************************************************************************/
2121 static bool remove_from_jobs_added(const char* sharename, uint32 jobid)
2123 struct tdb_print_db *pdb = get_print_db_byname(sharename);
2124 TDB_DATA data, key;
2125 size_t job_count, i;
2126 bool ret = False;
2127 bool gotlock = False;
2129 if (!pdb) {
2130 return False;
2133 ZERO_STRUCT(data);
2135 key = string_tdb_data("INFO/jobs_added");
2137 if (tdb_chainlock_with_timeout(pdb->tdb, key, 5) == -1)
2138 goto out;
2140 gotlock = True;
2142 data = tdb_fetch(pdb->tdb, key);
2144 if (data.dptr == NULL || data.dsize == 0 || (data.dsize % 4 != 0))
2145 goto out;
2147 job_count = data.dsize / 4;
2148 for (i = 0; i < job_count; i++) {
2149 uint32 ch_jobid;
2151 ch_jobid = IVAL(data.dptr, i*4);
2152 if (ch_jobid == jobid) {
2153 if (i < job_count -1 )
2154 memmove(data.dptr + (i*4), data.dptr + (i*4) + 4, (job_count - i - 1)*4 );
2155 data.dsize -= 4;
2156 if (tdb_store(pdb->tdb, key, data, TDB_REPLACE) == -1)
2157 goto out;
2158 break;
2162 ret = True;
2163 out:
2165 if (gotlock)
2166 tdb_chainunlock(pdb->tdb, key);
2167 SAFE_FREE(data.dptr);
2168 release_print_db(pdb);
2169 if (ret)
2170 DEBUG(10,("remove_from_jobs_added: removed jobid %u\n", (unsigned int)jobid ));
2171 else
2172 DEBUG(10,("remove_from_jobs_added: Failed to remove jobid %u\n", (unsigned int)jobid ));
2173 return ret;
2176 /****************************************************************************
2177 Delete a print job - don't update queue.
2178 ****************************************************************************/
2180 static bool print_job_delete1(struct tevent_context *ev,
2181 struct messaging_context *msg_ctx,
2182 int snum, uint32 jobid)
2184 const char* sharename = lp_const_servicename(snum);
2185 struct printjob *pjob = print_job_find(sharename, jobid);
2186 int result = 0;
2187 struct printif *current_printif = get_printer_fns( snum );
2189 if (!pjob)
2190 return False;
2193 * If already deleting just return.
2196 if (pjob->status == LPQ_DELETING)
2197 return True;
2199 /* Hrm - we need to be able to cope with deleting a job before it
2200 has reached the spooler. Just mark it as LPQ_DELETING and
2201 let the print_queue_update() code rmeove the record */
2204 if (pjob->sysjob == -1) {
2205 DEBUG(5, ("attempt to delete job %u not seen by lpr\n", (unsigned int)jobid));
2208 /* Set the tdb entry to be deleting. */
2210 pjob->status = LPQ_DELETING;
2211 pjob_store(ev, msg_ctx, sharename, jobid, pjob);
2213 if (pjob->spooled && pjob->sysjob != -1)
2215 result = (*(current_printif->job_delete))(
2216 lp_printername(snum),
2217 lp_lprmcommand(snum),
2218 pjob);
2220 /* Delete the tdb entry if the delete succeeded or the job hasn't
2221 been spooled. */
2223 if (result == 0) {
2224 struct tdb_print_db *pdb = get_print_db_byname(sharename);
2225 int njobs = 1;
2227 if (!pdb)
2228 return False;
2229 pjob_delete(ev, msg_ctx, sharename, jobid);
2230 /* Ensure we keep a rough count of the number of total jobs... */
2231 tdb_change_int32_atomic(pdb->tdb, "INFO/total_jobs", &njobs, -1);
2232 release_print_db(pdb);
2236 remove_from_jobs_added( sharename, jobid );
2238 return (result == 0);
2241 /****************************************************************************
2242 Return true if the current user owns the print job.
2243 ****************************************************************************/
2245 static bool is_owner(const struct auth_serversupplied_info *server_info,
2246 const char *servicename,
2247 uint32 jobid)
2249 struct printjob *pjob = print_job_find(servicename, jobid);
2251 if (!pjob || !server_info)
2252 return False;
2254 return strequal(pjob->user, server_info->sanitized_username);
2257 /****************************************************************************
2258 Delete a print job.
2259 ****************************************************************************/
2261 WERROR print_job_delete(const struct auth_serversupplied_info *server_info,
2262 struct messaging_context *msg_ctx,
2263 int snum, uint32_t jobid)
2265 const char* sharename = lp_const_servicename(snum);
2266 struct printjob *pjob;
2267 bool owner;
2268 char *fname;
2270 owner = is_owner(server_info, lp_const_servicename(snum), jobid);
2272 /* Check access against security descriptor or whether the user
2273 owns their job. */
2275 if (!owner &&
2276 !print_access_check(server_info, msg_ctx, snum,
2277 JOB_ACCESS_ADMINISTER)) {
2278 DEBUG(3, ("delete denied by security descriptor\n"));
2280 /* BEGIN_ADMIN_LOG */
2281 sys_adminlog( LOG_ERR,
2282 "Permission denied-- user not allowed to delete, \
2283 pause, or resume print job. User name: %s. Printer name: %s.",
2284 uidtoname(server_info->utok.uid),
2285 lp_printername(snum) );
2286 /* END_ADMIN_LOG */
2288 return WERR_ACCESS_DENIED;
2292 * get the spooled filename of the print job
2293 * if this works, then the file has not been spooled
2294 * to the underlying print system. Just delete the
2295 * spool file & return.
2298 fname = print_job_fname(sharename, jobid);
2299 if (fname != NULL) {
2300 /* remove the spool file */
2301 DEBUG(10, ("print_job_delete: "
2302 "Removing spool file [%s]\n", fname));
2303 if (unlink(fname) == -1) {
2304 return map_werror_from_unix(errno);
2308 if (!print_job_delete1(server_event_context(), msg_ctx, snum, jobid)) {
2309 return WERR_ACCESS_DENIED;
2312 /* force update the database and say the delete failed if the
2313 job still exists */
2315 print_queue_update(msg_ctx, snum, True);
2317 pjob = print_job_find(sharename, jobid);
2318 if (pjob && (pjob->status != LPQ_DELETING)) {
2319 return WERR_ACCESS_DENIED;
2322 return WERR_PRINTER_HAS_JOBS_QUEUED;
2325 /****************************************************************************
2326 Pause a job.
2327 ****************************************************************************/
2329 bool print_job_pause(const struct auth_serversupplied_info *server_info,
2330 struct messaging_context *msg_ctx,
2331 int snum, uint32 jobid, WERROR *errcode)
2333 const char* sharename = lp_const_servicename(snum);
2334 struct printjob *pjob;
2335 int ret = -1;
2336 struct printif *current_printif = get_printer_fns( snum );
2338 pjob = print_job_find(sharename, jobid);
2340 if (!pjob || !server_info) {
2341 DEBUG(10, ("print_job_pause: no pjob or user for jobid %u\n",
2342 (unsigned int)jobid ));
2343 return False;
2346 if (!pjob->spooled || pjob->sysjob == -1) {
2347 DEBUG(10, ("print_job_pause: not spooled or bad sysjob = %d for jobid %u\n",
2348 (int)pjob->sysjob, (unsigned int)jobid ));
2349 return False;
2352 if (!is_owner(server_info, lp_const_servicename(snum), jobid) &&
2353 !print_access_check(server_info, msg_ctx, snum,
2354 JOB_ACCESS_ADMINISTER)) {
2355 DEBUG(3, ("pause denied by security descriptor\n"));
2357 /* BEGIN_ADMIN_LOG */
2358 sys_adminlog( LOG_ERR,
2359 "Permission denied-- user not allowed to delete, \
2360 pause, or resume print job. User name: %s. Printer name: %s.",
2361 uidtoname(server_info->utok.uid),
2362 lp_printername(snum) );
2363 /* END_ADMIN_LOG */
2365 *errcode = WERR_ACCESS_DENIED;
2366 return False;
2369 /* need to pause the spooled entry */
2370 ret = (*(current_printif->job_pause))(snum, pjob);
2372 if (ret != 0) {
2373 *errcode = WERR_INVALID_PARAM;
2374 return False;
2377 /* force update the database */
2378 print_cache_flush(lp_const_servicename(snum));
2380 /* Send a printer notify message */
2382 notify_job_status(server_event_context(), msg_ctx, sharename, jobid,
2383 JOB_STATUS_PAUSED);
2385 /* how do we tell if this succeeded? */
2387 return True;
2390 /****************************************************************************
2391 Resume a job.
2392 ****************************************************************************/
2394 bool print_job_resume(const struct auth_serversupplied_info *server_info,
2395 struct messaging_context *msg_ctx,
2396 int snum, uint32 jobid, WERROR *errcode)
2398 const char *sharename = lp_const_servicename(snum);
2399 struct printjob *pjob;
2400 int ret;
2401 struct printif *current_printif = get_printer_fns( snum );
2403 pjob = print_job_find(sharename, jobid);
2405 if (!pjob || !server_info) {
2406 DEBUG(10, ("print_job_resume: no pjob or user for jobid %u\n",
2407 (unsigned int)jobid ));
2408 return False;
2411 if (!pjob->spooled || pjob->sysjob == -1) {
2412 DEBUG(10, ("print_job_resume: not spooled or bad sysjob = %d for jobid %u\n",
2413 (int)pjob->sysjob, (unsigned int)jobid ));
2414 return False;
2417 if (!is_owner(server_info, lp_const_servicename(snum), jobid) &&
2418 !print_access_check(server_info, msg_ctx, snum,
2419 JOB_ACCESS_ADMINISTER)) {
2420 DEBUG(3, ("resume denied by security descriptor\n"));
2421 *errcode = WERR_ACCESS_DENIED;
2423 /* BEGIN_ADMIN_LOG */
2424 sys_adminlog( LOG_ERR,
2425 "Permission denied-- user not allowed to delete, \
2426 pause, or resume print job. User name: %s. Printer name: %s.",
2427 uidtoname(server_info->utok.uid),
2428 lp_printername(snum) );
2429 /* END_ADMIN_LOG */
2430 return False;
2433 ret = (*(current_printif->job_resume))(snum, pjob);
2435 if (ret != 0) {
2436 *errcode = WERR_INVALID_PARAM;
2437 return False;
2440 /* force update the database */
2441 print_cache_flush(lp_const_servicename(snum));
2443 /* Send a printer notify message */
2445 notify_job_status(server_event_context(), msg_ctx, sharename, jobid,
2446 JOB_STATUS_QUEUED);
2448 return True;
2451 /****************************************************************************
2452 Write to a print file.
2453 ****************************************************************************/
2455 ssize_t print_job_write(struct tevent_context *ev,
2456 struct messaging_context *msg_ctx,
2457 int snum, uint32 jobid, const char *buf, size_t size)
2459 const char* sharename = lp_const_servicename(snum);
2460 ssize_t return_code;
2461 struct printjob *pjob;
2463 pjob = print_job_find(sharename, jobid);
2465 if (!pjob)
2466 return -1;
2467 /* don't allow another process to get this info - it is meaningless */
2468 if (pjob->pid != sys_getpid())
2469 return -1;
2471 /* if SMBD is spooling this can't be allowed */
2472 if (pjob->status == PJOB_SMBD_SPOOLING) {
2473 return -1;
2476 return_code = write_data(pjob->fd, buf, size);
2478 if (return_code>0) {
2479 pjob->size += size;
2480 pjob_store(ev, msg_ctx, sharename, jobid, pjob);
2482 return return_code;
2485 /****************************************************************************
2486 Get the queue status - do not update if db is out of date.
2487 ****************************************************************************/
2489 static int get_queue_status(const char* sharename, print_status_struct *status)
2491 fstring keystr;
2492 TDB_DATA data;
2493 struct tdb_print_db *pdb = get_print_db_byname(sharename);
2494 int len;
2496 if (status) {
2497 ZERO_STRUCTP(status);
2500 if (!pdb)
2501 return 0;
2503 if (status) {
2504 fstr_sprintf(keystr, "STATUS/%s", sharename);
2505 data = tdb_fetch(pdb->tdb, string_tdb_data(keystr));
2506 if (data.dptr) {
2507 if (data.dsize == sizeof(print_status_struct))
2508 /* this memcpy is ok since the status struct was
2509 not packed before storing it in the tdb */
2510 memcpy(status, data.dptr, sizeof(print_status_struct));
2511 SAFE_FREE(data.dptr);
2514 len = tdb_fetch_int32(pdb->tdb, "INFO/total_jobs");
2515 release_print_db(pdb);
2516 return (len == -1 ? 0 : len);
2519 /****************************************************************************
2520 Determine the number of jobs in a queue.
2521 ****************************************************************************/
2523 int print_queue_length(struct messaging_context *msg_ctx, int snum,
2524 print_status_struct *pstatus)
2526 const char* sharename = lp_const_servicename( snum );
2527 print_status_struct status;
2528 int len;
2530 ZERO_STRUCT( status );
2532 /* make sure the database is up to date */
2533 if (print_cache_expired(lp_const_servicename(snum), True))
2534 print_queue_update(msg_ctx, snum, False);
2536 /* also fetch the queue status */
2537 memset(&status, 0, sizeof(status));
2538 len = get_queue_status(sharename, &status);
2540 if (pstatus)
2541 *pstatus = status;
2543 return len;
2546 /***************************************************************************
2547 Allocate a jobid. Hold the lock for as short a time as possible.
2548 ***************************************************************************/
2550 static WERROR allocate_print_jobid(struct tdb_print_db *pdb, int snum,
2551 const char *sharename, uint32 *pjobid)
2553 int i;
2554 uint32 jobid;
2555 enum TDB_ERROR terr;
2556 int ret;
2558 *pjobid = (uint32)-1;
2560 for (i = 0; i < 3; i++) {
2561 /* Lock the database - only wait 20 seconds. */
2562 ret = tdb_lock_bystring_with_timeout(pdb->tdb,
2563 "INFO/nextjob", 20);
2564 if (ret == -1) {
2565 DEBUG(0, ("allocate_print_jobid: "
2566 "Failed to lock printing database %s\n",
2567 sharename));
2568 terr = tdb_error(pdb->tdb);
2569 return ntstatus_to_werror(map_nt_error_from_tdb(terr));
2572 if (!tdb_fetch_uint32(pdb->tdb, "INFO/nextjob", &jobid)) {
2573 terr = tdb_error(pdb->tdb);
2574 if (terr != TDB_ERR_NOEXIST) {
2575 DEBUG(0, ("allocate_print_jobid: "
2576 "Failed to fetch INFO/nextjob "
2577 "for print queue %s\n", sharename));
2578 tdb_unlock_bystring(pdb->tdb, "INFO/nextjob");
2579 return ntstatus_to_werror(map_nt_error_from_tdb(terr));
2581 DEBUG(10, ("allocate_print_jobid: "
2582 "No existing jobid in %s\n", sharename));
2583 jobid = 0;
2586 DEBUG(10, ("allocate_print_jobid: "
2587 "Read jobid %u from %s\n", jobid, sharename));
2589 jobid = NEXT_JOBID(jobid);
2591 ret = tdb_store_int32(pdb->tdb, "INFO/nextjob", jobid);
2592 if (ret == -1) {
2593 terr = tdb_error(pdb->tdb);
2594 DEBUG(3, ("allocate_print_jobid: "
2595 "Failed to store INFO/nextjob.\n"));
2596 tdb_unlock_bystring(pdb->tdb, "INFO/nextjob");
2597 return ntstatus_to_werror(map_nt_error_from_tdb(terr));
2600 /* We've finished with the INFO/nextjob lock. */
2601 tdb_unlock_bystring(pdb->tdb, "INFO/nextjob");
2603 if (!print_job_exists(sharename, jobid)) {
2604 break;
2606 DEBUG(10, ("allocate_print_jobid: "
2607 "Found jobid %u in %s\n", jobid, sharename));
2610 if (i > 2) {
2611 DEBUG(0, ("allocate_print_jobid: "
2612 "Failed to allocate a print job for queue %s\n",
2613 sharename));
2614 /* Probably full... */
2615 return WERR_NO_SPOOL_SPACE;
2618 /* Store a dummy placeholder. */
2620 uint32_t tmp;
2621 TDB_DATA dum;
2622 dum.dptr = NULL;
2623 dum.dsize = 0;
2624 if (tdb_store(pdb->tdb, print_key(jobid, &tmp), dum,
2625 TDB_INSERT) == -1) {
2626 DEBUG(3, ("allocate_print_jobid: "
2627 "jobid (%d) failed to store placeholder.\n",
2628 jobid ));
2629 terr = tdb_error(pdb->tdb);
2630 return ntstatus_to_werror(map_nt_error_from_tdb(terr));
2634 *pjobid = jobid;
2635 return WERR_OK;
2638 /***************************************************************************
2639 Append a jobid to the 'jobs added' list.
2640 ***************************************************************************/
2642 static bool add_to_jobs_added(struct tdb_print_db *pdb, uint32 jobid)
2644 TDB_DATA data;
2645 uint32 store_jobid;
2647 SIVAL(&store_jobid, 0, jobid);
2648 data.dptr = (uint8 *)&store_jobid;
2649 data.dsize = 4;
2651 DEBUG(10,("add_to_jobs_added: Added jobid %u\n", (unsigned int)jobid ));
2653 return (tdb_append(pdb->tdb, string_tdb_data("INFO/jobs_added"),
2654 data) == 0);
2658 /***************************************************************************
2659 Do all checks needed to determine if we can start a job.
2660 ***************************************************************************/
2662 static WERROR print_job_checks(const struct auth_serversupplied_info *server_info,
2663 struct messaging_context *msg_ctx,
2664 int snum, int *njobs)
2666 const char *sharename = lp_const_servicename(snum);
2667 uint64_t dspace, dsize;
2668 uint64_t minspace;
2669 int ret;
2671 if (!print_access_check(server_info, msg_ctx, snum,
2672 PRINTER_ACCESS_USE)) {
2673 DEBUG(3, ("print_job_checks: "
2674 "job start denied by security descriptor\n"));
2675 return WERR_ACCESS_DENIED;
2678 if (!print_time_access_check(server_info, msg_ctx, sharename)) {
2679 DEBUG(3, ("print_job_checks: "
2680 "job start denied by time check\n"));
2681 return WERR_ACCESS_DENIED;
2684 /* see if we have sufficient disk space */
2685 if (lp_minprintspace(snum)) {
2686 minspace = lp_minprintspace(snum);
2687 ret = sys_fsusage(lp_pathname(snum), &dspace, &dsize);
2688 if (ret == 0 && dspace < 2*minspace) {
2689 DEBUG(3, ("print_job_checks: "
2690 "disk space check failed.\n"));
2691 return WERR_NO_SPOOL_SPACE;
2695 /* for autoloaded printers, check that the printcap entry still exists */
2696 if (lp_autoloaded(snum) && !pcap_printername_ok(sharename)) {
2697 DEBUG(3, ("print_job_checks: printer name %s check failed.\n",
2698 sharename));
2699 return WERR_ACCESS_DENIED;
2702 /* Insure the maximum queue size is not violated */
2703 *njobs = print_queue_length(msg_ctx, snum, NULL);
2704 if (*njobs > lp_maxprintjobs(snum)) {
2705 DEBUG(3, ("print_job_checks: Queue %s number of jobs (%d) "
2706 "larger than max printjobs per queue (%d).\n",
2707 sharename, *njobs, lp_maxprintjobs(snum)));
2708 return WERR_NO_SPOOL_SPACE;
2711 return WERR_OK;
2714 /***************************************************************************
2715 Create a job file.
2716 ***************************************************************************/
2718 static WERROR print_job_spool_file(int snum, uint32_t jobid,
2719 const char *output_file,
2720 struct printjob *pjob)
2722 WERROR werr;
2723 SMB_STRUCT_STAT st;
2724 const char *path;
2725 int len;
2727 /* if this file is within the printer path, it means that smbd
2728 * is spooling it and will pass us control when it is finished.
2729 * Verify that the file name is ok, within path, and it is
2730 * already already there */
2731 if (output_file) {
2732 path = lp_pathname(snum);
2733 len = strlen(path);
2734 if (strncmp(output_file, path, len) == 0 &&
2735 (output_file[len - 1] == '/' || output_file[len] == '/')) {
2737 /* verify path is not too long */
2738 if (strlen(output_file) >= sizeof(pjob->filename)) {
2739 return WERR_INVALID_NAME;
2742 /* verify that the file exists */
2743 if (sys_stat(output_file, &st, false) != 0) {
2744 return WERR_INVALID_NAME;
2747 fstrcpy(pjob->filename, output_file);
2749 DEBUG(3, ("print_job_spool_file:"
2750 "External spooling activated"));
2752 /* we do not open the file until spooling is done */
2753 pjob->fd = -1;
2754 pjob->status = PJOB_SMBD_SPOOLING;
2756 return WERR_OK;
2760 slprintf(pjob->filename, sizeof(pjob->filename)-1,
2761 "%s/%s%.8u.XXXXXX", lp_pathname(snum),
2762 PRINT_SPOOL_PREFIX, (unsigned int)jobid);
2763 pjob->fd = mkstemp(pjob->filename);
2765 if (pjob->fd == -1) {
2766 werr = map_werror_from_unix(errno);
2767 if (W_ERROR_EQUAL(werr, WERR_ACCESS_DENIED)) {
2768 /* Common setup error, force a report. */
2769 DEBUG(0, ("print_job_spool_file: "
2770 "insufficient permissions to open spool "
2771 "file %s.\n", pjob->filename));
2772 } else {
2773 /* Normal case, report at level 3 and above. */
2774 DEBUG(3, ("print_job_spool_file: "
2775 "can't open spool file %s\n",
2776 pjob->filename));
2778 return werr;
2781 return WERR_OK;
2784 /***************************************************************************
2785 Start spooling a job - return the jobid.
2786 ***************************************************************************/
2788 WERROR print_job_start(const struct auth_serversupplied_info *server_info,
2789 struct messaging_context *msg_ctx,
2790 const char *clientmachine,
2791 int snum, const char *docname, const char *filename,
2792 struct spoolss_DeviceMode *devmode, uint32_t *_jobid)
2794 uint32_t jobid;
2795 char *path;
2796 struct printjob pjob;
2797 const char *sharename = lp_const_servicename(snum);
2798 struct tdb_print_db *pdb = get_print_db_byname(sharename);
2799 int njobs;
2800 WERROR werr;
2802 if (!pdb) {
2803 return WERR_INTERNAL_DB_CORRUPTION;
2806 path = lp_pathname(snum);
2808 werr = print_job_checks(server_info, msg_ctx, snum, &njobs);
2809 if (!W_ERROR_IS_OK(werr)) {
2810 release_print_db(pdb);
2811 return werr;
2814 DEBUG(10, ("print_job_start: "
2815 "Queue %s number of jobs (%d), max printjobs = %d\n",
2816 sharename, njobs, lp_maxprintjobs(snum)));
2818 werr = allocate_print_jobid(pdb, snum, sharename, &jobid);
2819 if (!W_ERROR_IS_OK(werr)) {
2820 goto fail;
2823 /* create the database entry */
2825 ZERO_STRUCT(pjob);
2827 pjob.pid = sys_getpid();
2828 pjob.sysjob = -1;
2829 pjob.fd = -1;
2830 pjob.starttime = time(NULL);
2831 pjob.status = LPQ_SPOOLING;
2832 pjob.size = 0;
2833 pjob.spooled = False;
2834 pjob.smbjob = True;
2835 pjob.devmode = devmode;
2837 fstrcpy(pjob.jobname, docname);
2839 fstrcpy(pjob.clientmachine, clientmachine);
2841 fstrcpy(pjob.user, lp_printjob_username(snum));
2842 standard_sub_advanced(sharename, server_info->sanitized_username,
2843 path, server_info->utok.gid,
2844 server_info->sanitized_username,
2845 server_info->info3->base.domain.string,
2846 pjob.user, sizeof(pjob.user)-1);
2847 /* ensure NULL termination */
2848 pjob.user[sizeof(pjob.user)-1] = '\0';
2850 fstrcpy(pjob.queuename, lp_const_servicename(snum));
2852 /* we have a job entry - now create the spool file */
2853 werr = print_job_spool_file(snum, jobid, filename, &pjob);
2854 if (!W_ERROR_IS_OK(werr)) {
2855 goto fail;
2858 pjob_store(server_event_context(), msg_ctx, sharename, jobid, &pjob);
2860 /* Update the 'jobs added' entry used by print_queue_status. */
2861 add_to_jobs_added(pdb, jobid);
2863 /* Ensure we keep a rough count of the number of total jobs... */
2864 tdb_change_int32_atomic(pdb->tdb, "INFO/total_jobs", &njobs, 1);
2866 release_print_db(pdb);
2868 *_jobid = jobid;
2869 return WERR_OK;
2871 fail:
2872 if (jobid != -1) {
2873 pjob_delete(server_event_context(), msg_ctx, sharename, jobid);
2876 release_print_db(pdb);
2878 DEBUG(3, ("print_job_start: returning fail. "
2879 "Error = %s\n", win_errstr(werr)));
2880 return werr;
2883 /****************************************************************************
2884 Update the number of pages spooled to jobid
2885 ****************************************************************************/
2887 void print_job_endpage(struct messaging_context *msg_ctx,
2888 int snum, uint32 jobid)
2890 const char* sharename = lp_const_servicename(snum);
2891 struct printjob *pjob;
2893 pjob = print_job_find(sharename, jobid);
2894 if (!pjob)
2895 return;
2896 /* don't allow another process to get this info - it is meaningless */
2897 if (pjob->pid != sys_getpid())
2898 return;
2900 pjob->page_count++;
2901 pjob_store(server_event_context(), msg_ctx, sharename, jobid, pjob);
2904 /****************************************************************************
2905 Print a file - called on closing the file. This spools the job.
2906 If normal close is false then we're tearing down the jobs - treat as an
2907 error.
2908 ****************************************************************************/
2910 NTSTATUS print_job_end(struct messaging_context *msg_ctx, int snum,
2911 uint32 jobid, enum file_close_type close_type)
2913 const char* sharename = lp_const_servicename(snum);
2914 struct printjob *pjob;
2915 int ret;
2916 SMB_STRUCT_STAT sbuf;
2917 struct printif *current_printif = get_printer_fns( snum );
2918 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
2920 pjob = print_job_find(sharename, jobid);
2922 if (!pjob) {
2923 return NT_STATUS_PRINT_CANCELLED;
2926 if (pjob->spooled || pjob->pid != sys_getpid()) {
2927 return NT_STATUS_ACCESS_DENIED;
2930 if (close_type == NORMAL_CLOSE || close_type == SHUTDOWN_CLOSE) {
2931 if (pjob->status == PJOB_SMBD_SPOOLING) {
2932 /* take over the file now, smbd is done */
2933 if (sys_stat(pjob->filename, &sbuf, false) != 0) {
2934 status = map_nt_error_from_unix(errno);
2935 DEBUG(3, ("print_job_end: "
2936 "stat file failed for jobid %d\n",
2937 jobid));
2938 goto fail;
2941 pjob->status = LPQ_SPOOLING;
2943 } else {
2945 if ((sys_fstat(pjob->fd, &sbuf, false) != 0)) {
2946 status = map_nt_error_from_unix(errno);
2947 close(pjob->fd);
2948 DEBUG(3, ("print_job_end: "
2949 "stat file failed for jobid %d\n",
2950 jobid));
2951 goto fail;
2954 close(pjob->fd);
2957 pjob->size = sbuf.st_ex_size;
2958 } else {
2961 * Not a normal close, something has gone wrong. Cleanup.
2963 if (pjob->fd != -1) {
2964 close(pjob->fd);
2966 goto fail;
2969 /* Technically, this is not quite right. If the printer has a separator
2970 * page turned on, the NT spooler prints the separator page even if the
2971 * print job is 0 bytes. 010215 JRR */
2972 if (pjob->size == 0 || pjob->status == LPQ_DELETING) {
2973 /* don't bother spooling empty files or something being deleted. */
2974 DEBUG(5,("print_job_end: canceling spool of %s (%s)\n",
2975 pjob->filename, pjob->size ? "deleted" : "zero length" ));
2976 unlink(pjob->filename);
2977 pjob_delete(server_event_context(), msg_ctx, sharename, jobid);
2978 return NT_STATUS_OK;
2981 ret = (*(current_printif->job_submit))(snum, pjob);
2983 if (ret) {
2984 status = NT_STATUS_PRINT_CANCELLED;
2985 goto fail;
2988 /* The print job has been successfully handed over to the back-end */
2990 pjob->spooled = True;
2991 pjob->status = LPQ_QUEUED;
2992 pjob_store(server_event_context(), msg_ctx, sharename, jobid, pjob);
2994 /* make sure the database is up to date */
2995 if (print_cache_expired(lp_const_servicename(snum), True))
2996 print_queue_update(msg_ctx, snum, False);
2998 return NT_STATUS_OK;
3000 fail:
3002 /* The print job was not successfully started. Cleanup */
3003 /* Still need to add proper error return propagation! 010122:JRR */
3004 pjob->fd = -1;
3005 unlink(pjob->filename);
3006 pjob_delete(server_event_context(), msg_ctx, sharename, jobid);
3007 return status;
3010 /****************************************************************************
3011 Get a snapshot of jobs in the system without traversing.
3012 ****************************************************************************/
3014 static bool get_stored_queue_info(struct messaging_context *msg_ctx,
3015 struct tdb_print_db *pdb, int snum,
3016 int *pcount, print_queue_struct **ppqueue)
3018 TDB_DATA data, cgdata, jcdata;
3019 print_queue_struct *queue = NULL;
3020 uint32 qcount = 0;
3021 uint32 extra_count = 0;
3022 uint32_t changed_count = 0;
3023 int total_count = 0;
3024 size_t len = 0;
3025 uint32 i;
3026 int max_reported_jobs = lp_max_reported_jobs(snum);
3027 bool ret = False;
3028 const char* sharename = lp_servicename(snum);
3030 /* make sure the database is up to date */
3031 if (print_cache_expired(lp_const_servicename(snum), True))
3032 print_queue_update(msg_ctx, snum, False);
3034 *pcount = 0;
3035 *ppqueue = NULL;
3037 ZERO_STRUCT(data);
3038 ZERO_STRUCT(cgdata);
3040 /* Get the stored queue data. */
3041 data = tdb_fetch(pdb->tdb, string_tdb_data("INFO/linear_queue_array"));
3043 if (data.dptr && data.dsize >= sizeof(qcount))
3044 len += tdb_unpack(data.dptr + len, data.dsize - len, "d", &qcount);
3046 /* Get the added jobs list. */
3047 cgdata = tdb_fetch(pdb->tdb, string_tdb_data("INFO/jobs_added"));
3048 if (cgdata.dptr != NULL && (cgdata.dsize % 4 == 0))
3049 extra_count = cgdata.dsize/4;
3051 /* Get the changed jobs list. */
3052 jcdata = tdb_fetch(pdb->tdb, string_tdb_data("INFO/jobs_changed"));
3053 if (jcdata.dptr != NULL && (jcdata.dsize % 4 == 0))
3054 changed_count = jcdata.dsize / 4;
3056 DEBUG(5,("get_stored_queue_info: qcount = %u, extra_count = %u\n", (unsigned int)qcount, (unsigned int)extra_count));
3058 /* Allocate the queue size. */
3059 if (qcount == 0 && extra_count == 0)
3060 goto out;
3062 if ((queue = SMB_MALLOC_ARRAY(print_queue_struct, qcount + extra_count)) == NULL)
3063 goto out;
3065 /* Retrieve the linearised queue data. */
3067 for( i = 0; i < qcount; i++) {
3068 uint32 qjob, qsize, qpage_count, qstatus, qpriority, qtime;
3069 len += tdb_unpack(data.dptr + len, data.dsize - len, "ddddddff",
3070 &qjob,
3071 &qsize,
3072 &qpage_count,
3073 &qstatus,
3074 &qpriority,
3075 &qtime,
3076 queue[i].fs_user,
3077 queue[i].fs_file);
3078 queue[i].job = qjob;
3079 queue[i].size = qsize;
3080 queue[i].page_count = qpage_count;
3081 queue[i].status = qstatus;
3082 queue[i].priority = qpriority;
3083 queue[i].time = qtime;
3086 total_count = qcount;
3088 /* Add new jobids to the queue. */
3089 for( i = 0; i < extra_count; i++) {
3090 uint32 jobid;
3091 struct printjob *pjob;
3093 jobid = IVAL(cgdata.dptr, i*4);
3094 DEBUG(5,("get_stored_queue_info: added job = %u\n", (unsigned int)jobid));
3095 pjob = print_job_find(lp_const_servicename(snum), jobid);
3096 if (!pjob) {
3097 DEBUG(5,("get_stored_queue_info: failed to find added job = %u\n", (unsigned int)jobid));
3098 remove_from_jobs_added(sharename, jobid);
3099 continue;
3102 queue[total_count].job = jobid;
3103 queue[total_count].size = pjob->size;
3104 queue[total_count].page_count = pjob->page_count;
3105 queue[total_count].status = pjob->status;
3106 queue[total_count].priority = 1;
3107 queue[total_count].time = pjob->starttime;
3108 fstrcpy(queue[total_count].fs_user, pjob->user);
3109 fstrcpy(queue[total_count].fs_file, pjob->jobname);
3110 total_count++;
3113 /* Update the changed jobids. */
3114 for (i = 0; i < changed_count; i++) {
3115 uint32_t jobid = IVAL(jcdata.dptr, i * 4);
3116 uint32_t j;
3117 bool found = false;
3119 for (j = 0; j < total_count; j++) {
3120 if (queue[j].job == jobid) {
3121 found = true;
3122 break;
3126 if (found) {
3127 struct printjob *pjob;
3129 DEBUG(5,("get_stored_queue_info: changed job: %u\n",
3130 (unsigned int) jobid));
3132 pjob = print_job_find(sharename, jobid);
3133 if (pjob == NULL) {
3134 DEBUG(5,("get_stored_queue_info: failed to find "
3135 "changed job = %u\n",
3136 (unsigned int) jobid));
3137 remove_from_jobs_changed(sharename, jobid);
3138 continue;
3141 queue[j].job = jobid;
3142 queue[j].size = pjob->size;
3143 queue[j].page_count = pjob->page_count;
3144 queue[j].status = pjob->status;
3145 queue[j].priority = 1;
3146 queue[j].time = pjob->starttime;
3147 fstrcpy(queue[j].fs_user, pjob->user);
3148 fstrcpy(queue[j].fs_file, pjob->jobname);
3150 DEBUG(5,("get_stored_queue_info: updated queue[%u], jobid: %u, jobname: %s\n",
3151 (unsigned int) j, (unsigned int) jobid, pjob->jobname));
3154 remove_from_jobs_changed(sharename, jobid);
3157 /* Sort the queue by submission time otherwise they are displayed
3158 in hash order. */
3160 TYPESAFE_QSORT(queue, total_count, printjob_comp);
3162 DEBUG(5,("get_stored_queue_info: total_count = %u\n", (unsigned int)total_count));
3164 if (max_reported_jobs && total_count > max_reported_jobs)
3165 total_count = max_reported_jobs;
3167 *ppqueue = queue;
3168 *pcount = total_count;
3170 ret = True;
3172 out:
3174 SAFE_FREE(data.dptr);
3175 SAFE_FREE(cgdata.dptr);
3176 return ret;
3179 /****************************************************************************
3180 Get a printer queue listing.
3181 set queue = NULL and status = NULL if you just want to update the cache
3182 ****************************************************************************/
3184 int print_queue_status(struct messaging_context *msg_ctx, int snum,
3185 print_queue_struct **ppqueue,
3186 print_status_struct *status)
3188 fstring keystr;
3189 TDB_DATA data, key;
3190 const char *sharename;
3191 struct tdb_print_db *pdb;
3192 int count = 0;
3194 /* make sure the database is up to date */
3196 if (print_cache_expired(lp_const_servicename(snum), True))
3197 print_queue_update(msg_ctx, snum, False);
3199 /* return if we are done */
3200 if ( !ppqueue || !status )
3201 return 0;
3203 *ppqueue = NULL;
3204 sharename = lp_const_servicename(snum);
3205 pdb = get_print_db_byname(sharename);
3207 if (!pdb)
3208 return 0;
3211 * Fetch the queue status. We must do this first, as there may
3212 * be no jobs in the queue.
3215 ZERO_STRUCTP(status);
3216 slprintf(keystr, sizeof(keystr)-1, "STATUS/%s", sharename);
3217 key = string_tdb_data(keystr);
3219 data = tdb_fetch(pdb->tdb, key);
3220 if (data.dptr) {
3221 if (data.dsize == sizeof(*status)) {
3222 /* this memcpy is ok since the status struct was
3223 not packed before storing it in the tdb */
3224 memcpy(status, data.dptr, sizeof(*status));
3226 SAFE_FREE(data.dptr);
3230 * Now, fetch the print queue information. We first count the number
3231 * of entries, and then only retrieve the queue if necessary.
3234 if (!get_stored_queue_info(msg_ctx, pdb, snum, &count, ppqueue)) {
3235 release_print_db(pdb);
3236 return 0;
3239 release_print_db(pdb);
3240 return count;
3243 /****************************************************************************
3244 Pause a queue.
3245 ****************************************************************************/
3247 WERROR print_queue_pause(const struct auth_serversupplied_info *server_info,
3248 struct messaging_context *msg_ctx, int snum)
3250 int ret;
3251 struct printif *current_printif = get_printer_fns( snum );
3253 if (!print_access_check(server_info, msg_ctx, snum,
3254 PRINTER_ACCESS_ADMINISTER)) {
3255 return WERR_ACCESS_DENIED;
3259 become_root();
3261 ret = (*(current_printif->queue_pause))(snum);
3263 unbecome_root();
3265 if (ret != 0) {
3266 return WERR_INVALID_PARAM;
3269 /* force update the database */
3270 print_cache_flush(lp_const_servicename(snum));
3272 /* Send a printer notify message */
3274 notify_printer_status(server_event_context(), msg_ctx, snum,
3275 PRINTER_STATUS_PAUSED);
3277 return WERR_OK;
3280 /****************************************************************************
3281 Resume a queue.
3282 ****************************************************************************/
3284 WERROR print_queue_resume(const struct auth_serversupplied_info *server_info,
3285 struct messaging_context *msg_ctx, int snum)
3287 int ret;
3288 struct printif *current_printif = get_printer_fns( snum );
3290 if (!print_access_check(server_info, msg_ctx, snum,
3291 PRINTER_ACCESS_ADMINISTER)) {
3292 return WERR_ACCESS_DENIED;
3295 become_root();
3297 ret = (*(current_printif->queue_resume))(snum);
3299 unbecome_root();
3301 if (ret != 0) {
3302 return WERR_INVALID_PARAM;
3305 /* make sure the database is up to date */
3306 if (print_cache_expired(lp_const_servicename(snum), True))
3307 print_queue_update(msg_ctx, snum, True);
3309 /* Send a printer notify message */
3311 notify_printer_status(server_event_context(), msg_ctx, snum,
3312 PRINTER_STATUS_OK);
3314 return WERR_OK;
3317 /****************************************************************************
3318 Purge a queue - implemented by deleting all jobs that we can delete.
3319 ****************************************************************************/
3321 WERROR print_queue_purge(const struct auth_serversupplied_info *server_info,
3322 struct messaging_context *msg_ctx, int snum)
3324 print_queue_struct *queue;
3325 print_status_struct status;
3326 int njobs, i;
3327 bool can_job_admin;
3329 /* Force and update so the count is accurate (i.e. not a cached count) */
3330 print_queue_update(msg_ctx, snum, True);
3332 can_job_admin = print_access_check(server_info,
3333 msg_ctx,
3334 snum,
3335 JOB_ACCESS_ADMINISTER);
3336 njobs = print_queue_status(msg_ctx, snum, &queue, &status);
3338 if ( can_job_admin )
3339 become_root();
3341 for (i=0;i<njobs;i++) {
3342 bool owner = is_owner(server_info, lp_const_servicename(snum),
3343 queue[i].job);
3345 if (owner || can_job_admin) {
3346 print_job_delete1(server_event_context(), msg_ctx,
3347 snum, queue[i].job);
3351 if ( can_job_admin )
3352 unbecome_root();
3354 /* update the cache */
3355 print_queue_update(msg_ctx, snum, True);
3357 SAFE_FREE(queue);
3359 return WERR_OK;