s4:rootdse LDB module - remove unused variable
[Samba/gebeck_regimport.git] / source3 / printing / printing.c
blob1c2817dcc786cf927bc0371e144408e2d802c8a7
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 "printing.h"
24 #include "librpc/gen_ndr/messaging.h"
25 #include "../librpc/gen_ndr/ndr_spoolss.h"
26 #include "nt_printing.h"
27 #include "../librpc/gen_ndr/netlogon.h"
29 extern struct current_user current_user;
30 extern userdom_struct current_user_info;
32 /* Current printer interface */
33 static bool remove_from_jobs_added(const char* sharename, uint32 jobid);
36 the printing backend revolves around a tdb database that stores the
37 SMB view of the print queue
39 The key for this database is a jobid - a internally generated number that
40 uniquely identifies a print job
42 reading the print queue involves two steps:
43 - possibly running lpq and updating the internal database from that
44 - reading entries from the database
46 jobids are assigned when a job starts spooling.
49 static TDB_CONTEXT *rap_tdb;
50 static uint16 next_rap_jobid;
51 struct rap_jobid_key {
52 fstring sharename;
53 uint32 jobid;
56 /***************************************************************************
57 Nightmare. LANMAN jobid's are 16 bit numbers..... We must map them to 32
58 bit RPC jobids.... JRA.
59 ***************************************************************************/
61 uint16 pjobid_to_rap(const char* sharename, uint32 jobid)
63 uint16 rap_jobid;
64 TDB_DATA data, key;
65 struct rap_jobid_key jinfo;
66 uint8 buf[2];
68 DEBUG(10,("pjobid_to_rap: called.\n"));
70 if (!rap_tdb) {
71 /* Create the in-memory tdb. */
72 rap_tdb = tdb_open_log(NULL, 0, TDB_INTERNAL, (O_RDWR|O_CREAT), 0644);
73 if (!rap_tdb)
74 return 0;
77 ZERO_STRUCT( jinfo );
78 fstrcpy( jinfo.sharename, sharename );
79 jinfo.jobid = jobid;
80 key.dptr = (uint8 *)&jinfo;
81 key.dsize = sizeof(jinfo);
83 data = tdb_fetch(rap_tdb, key);
84 if (data.dptr && data.dsize == sizeof(uint16)) {
85 rap_jobid = SVAL(data.dptr, 0);
86 SAFE_FREE(data.dptr);
87 DEBUG(10,("pjobid_to_rap: jobid %u maps to RAP jobid %u\n",
88 (unsigned int)jobid, (unsigned int)rap_jobid));
89 return rap_jobid;
91 SAFE_FREE(data.dptr);
92 /* Not found - create and store mapping. */
93 rap_jobid = ++next_rap_jobid;
94 if (rap_jobid == 0)
95 rap_jobid = ++next_rap_jobid;
96 SSVAL(buf,0,rap_jobid);
97 data.dptr = buf;
98 data.dsize = sizeof(rap_jobid);
99 tdb_store(rap_tdb, key, data, TDB_REPLACE);
100 tdb_store(rap_tdb, data, key, TDB_REPLACE);
102 DEBUG(10,("pjobid_to_rap: created jobid %u maps to RAP jobid %u\n",
103 (unsigned int)jobid, (unsigned int)rap_jobid));
104 return rap_jobid;
107 bool rap_to_pjobid(uint16 rap_jobid, fstring sharename, uint32 *pjobid)
109 TDB_DATA data, key;
110 uint8 buf[2];
112 DEBUG(10,("rap_to_pjobid called.\n"));
114 if (!rap_tdb)
115 return False;
117 SSVAL(buf,0,rap_jobid);
118 key.dptr = buf;
119 key.dsize = sizeof(rap_jobid);
120 data = tdb_fetch(rap_tdb, key);
121 if ( data.dptr && data.dsize == sizeof(struct rap_jobid_key) )
123 struct rap_jobid_key *jinfo = (struct rap_jobid_key*)data.dptr;
124 if (sharename != NULL) {
125 fstrcpy( sharename, jinfo->sharename );
127 *pjobid = jinfo->jobid;
128 DEBUG(10,("rap_to_pjobid: jobid %u maps to RAP jobid %u\n",
129 (unsigned int)*pjobid, (unsigned int)rap_jobid));
130 SAFE_FREE(data.dptr);
131 return True;
134 DEBUG(10,("rap_to_pjobid: Failed to lookup RAP jobid %u\n",
135 (unsigned int)rap_jobid));
136 SAFE_FREE(data.dptr);
137 return False;
140 void rap_jobid_delete(const char* sharename, uint32 jobid)
142 TDB_DATA key, data;
143 uint16 rap_jobid;
144 struct rap_jobid_key jinfo;
145 uint8 buf[2];
147 DEBUG(10,("rap_jobid_delete: called.\n"));
149 if (!rap_tdb)
150 return;
152 ZERO_STRUCT( jinfo );
153 fstrcpy( jinfo.sharename, sharename );
154 jinfo.jobid = jobid;
155 key.dptr = (uint8 *)&jinfo;
156 key.dsize = sizeof(jinfo);
158 data = tdb_fetch(rap_tdb, key);
159 if (!data.dptr || (data.dsize != sizeof(uint16))) {
160 DEBUG(10,("rap_jobid_delete: cannot find jobid %u\n",
161 (unsigned int)jobid ));
162 SAFE_FREE(data.dptr);
163 return;
166 DEBUG(10,("rap_jobid_delete: deleting jobid %u\n",
167 (unsigned int)jobid ));
169 rap_jobid = SVAL(data.dptr, 0);
170 SAFE_FREE(data.dptr);
171 SSVAL(buf,0,rap_jobid);
172 data.dptr = buf;
173 data.dsize = sizeof(rap_jobid);
174 tdb_delete(rap_tdb, key);
175 tdb_delete(rap_tdb, data);
178 static int get_queue_status(const char* sharename, print_status_struct *);
180 /****************************************************************************
181 Initialise the printing backend. Called once at startup before the fork().
182 ****************************************************************************/
184 bool print_backend_init(struct messaging_context *msg_ctx)
186 const char *sversion = "INFO/version";
187 int services = lp_numservices();
188 int snum;
190 unlink(cache_path("printing.tdb"));
191 mkdir(cache_path("printing"),0755);
193 /* handle a Samba upgrade */
195 for (snum = 0; snum < services; snum++) {
196 struct tdb_print_db *pdb;
197 if (!lp_print_ok(snum))
198 continue;
200 pdb = get_print_db_byname(lp_const_servicename(snum));
201 if (!pdb)
202 continue;
203 if (tdb_lock_bystring(pdb->tdb, sversion) == -1) {
204 DEBUG(0,("print_backend_init: Failed to open printer %s database\n", lp_const_servicename(snum) ));
205 release_print_db(pdb);
206 return False;
208 if (tdb_fetch_int32(pdb->tdb, sversion) != PRINT_DATABASE_VERSION) {
209 tdb_wipe_all(pdb->tdb);
210 tdb_store_int32(pdb->tdb, sversion, PRINT_DATABASE_VERSION);
212 tdb_unlock_bystring(pdb->tdb, sversion);
213 release_print_db(pdb);
216 close_all_print_db(); /* Don't leave any open. */
218 /* do NT print initialization... */
219 return nt_printing_init(msg_ctx);
222 /****************************************************************************
223 Shut down printing backend. Called once at shutdown to close the tdb.
224 ****************************************************************************/
226 void printing_end(void)
228 close_all_print_db(); /* Don't leave any open. */
231 /****************************************************************************
232 Retrieve the set of printing functions for a given service. This allows
233 us to set the printer function table based on the value of the 'printing'
234 service parameter.
236 Use the generic interface as the default and only use cups interface only
237 when asked for (and only when supported)
238 ****************************************************************************/
240 static struct printif *get_printer_fns_from_type( enum printing_types type )
242 struct printif *printer_fns = &generic_printif;
244 #ifdef HAVE_CUPS
245 if ( type == PRINT_CUPS ) {
246 printer_fns = &cups_printif;
248 #endif /* HAVE_CUPS */
250 #ifdef HAVE_IPRINT
251 if ( type == PRINT_IPRINT ) {
252 printer_fns = &iprint_printif;
254 #endif /* HAVE_IPRINT */
256 printer_fns->type = type;
258 return printer_fns;
261 static struct printif *get_printer_fns( int snum )
263 return get_printer_fns_from_type( (enum printing_types)lp_printing(snum) );
267 /****************************************************************************
268 Useful function to generate a tdb key.
269 ****************************************************************************/
271 static TDB_DATA print_key(uint32 jobid, uint32 *tmp)
273 TDB_DATA ret;
275 SIVAL(tmp, 0, jobid);
276 ret.dptr = (uint8 *)tmp;
277 ret.dsize = sizeof(*tmp);
278 return ret;
281 /****************************************************************************
282 Pack the devicemode to store it in a tdb.
283 ****************************************************************************/
284 static int pack_devicemode(struct spoolss_DeviceMode *devmode, uint8 *buf, int buflen)
286 enum ndr_err_code ndr_err;
287 DATA_BLOB blob;
288 int len = 0;
290 if (devmode) {
291 ndr_err = ndr_push_struct_blob(&blob, talloc_tos(),
292 devmode,
293 (ndr_push_flags_fn_t)
294 ndr_push_spoolss_DeviceMode);
295 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
296 DEBUG(10, ("pack_devicemode: "
297 "error encoding spoolss_DeviceMode\n"));
298 goto done;
300 } else {
301 ZERO_STRUCT(blob);
304 len = tdb_pack(buf, buflen, "B", blob.length, blob.data);
306 if (devmode) {
307 DEBUG(8, ("Packed devicemode [%s]\n", devmode->formname));
310 done:
311 return len;
314 /****************************************************************************
315 Unpack the devicemode to store it in a tdb.
316 ****************************************************************************/
317 static int unpack_devicemode(TALLOC_CTX *mem_ctx,
318 const uint8 *buf, int buflen,
319 struct spoolss_DeviceMode **devmode)
321 struct spoolss_DeviceMode *dm;
322 enum ndr_err_code ndr_err;
323 char *data = NULL;
324 int data_len = 0;
325 DATA_BLOB blob;
326 int len = 0;
328 *devmode = NULL;
330 len = tdb_unpack(buf, buflen, "B", &data_len, &data);
331 if (!data) {
332 return len;
335 dm = talloc_zero(mem_ctx, struct spoolss_DeviceMode);
336 if (!dm) {
337 goto done;
340 blob = data_blob_const(data, data_len);
342 ndr_err = ndr_pull_struct_blob(&blob, dm, dm,
343 (ndr_pull_flags_fn_t)ndr_pull_spoolss_DeviceMode);
344 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
345 DEBUG(10, ("unpack_devicemode: "
346 "error parsing spoolss_DeviceMode\n"));
347 goto done;
350 DEBUG(8, ("Unpacked devicemode [%s](%s)\n",
351 dm->devicename, dm->formname));
352 if (dm->driverextra_data.data) {
353 DEBUG(8, ("with a private section of %d bytes\n",
354 dm->__driverextra_length));
357 *devmode = dm;
359 done:
360 SAFE_FREE(data);
361 return len;
364 /***********************************************************************
365 unpack a pjob from a tdb buffer
366 ***********************************************************************/
368 static int unpack_pjob( uint8 *buf, int buflen, struct printjob *pjob )
370 int len = 0;
371 int used;
372 uint32 pjpid, pjsysjob, pjfd, pjstarttime, pjstatus;
373 uint32 pjsize, pjpage_count, pjspooled, pjsmbjob;
375 if ( !buf || !pjob )
376 return -1;
378 len += tdb_unpack(buf+len, buflen-len, "dddddddddfffff",
379 &pjpid,
380 &pjsysjob,
381 &pjfd,
382 &pjstarttime,
383 &pjstatus,
384 &pjsize,
385 &pjpage_count,
386 &pjspooled,
387 &pjsmbjob,
388 pjob->filename,
389 pjob->jobname,
390 pjob->user,
391 pjob->clientmachine,
392 pjob->queuename);
394 if ( len == -1 )
395 return -1;
397 used = unpack_devicemode(NULL, buf+len, buflen-len, &pjob->devmode);
398 if (used == -1) {
399 return -1;
402 len += used;
404 pjob->pid = pjpid;
405 pjob->sysjob = pjsysjob;
406 pjob->fd = pjfd;
407 pjob->starttime = pjstarttime;
408 pjob->status = pjstatus;
409 pjob->size = pjsize;
410 pjob->page_count = pjpage_count;
411 pjob->spooled = pjspooled;
412 pjob->smbjob = pjsmbjob;
414 return len;
418 /****************************************************************************
419 Useful function to find a print job in the database.
420 ****************************************************************************/
422 static struct printjob *print_job_find(const char *sharename, uint32 jobid)
424 static struct printjob pjob;
425 uint32_t tmp;
426 TDB_DATA ret;
427 struct tdb_print_db *pdb = get_print_db_byname(sharename);
429 DEBUG(10,("print_job_find: looking up job %u for share %s\n",
430 (unsigned int)jobid, sharename ));
432 if (!pdb) {
433 return NULL;
436 ret = tdb_fetch(pdb->tdb, print_key(jobid, &tmp));
437 release_print_db(pdb);
439 if (!ret.dptr) {
440 DEBUG(10,("print_job_find: failed to find jobid %u.\n", (unsigned int)jobid ));
441 return NULL;
444 talloc_free(pjob.devmode);
446 ZERO_STRUCT( pjob );
448 if ( unpack_pjob( ret.dptr, ret.dsize, &pjob ) == -1 ) {
449 DEBUG(10,("print_job_find: failed to unpack jobid %u.\n", (unsigned int)jobid ));
450 SAFE_FREE(ret.dptr);
451 return NULL;
454 SAFE_FREE(ret.dptr);
456 DEBUG(10,("print_job_find: returning system job %d for jobid %u.\n",
457 (int)pjob.sysjob, (unsigned int)jobid ));
459 return &pjob;
462 /* Convert a unix jobid to a smb jobid */
464 struct unixjob_traverse_state {
465 int sysjob;
466 uint32 sysjob_to_jobid_value;
469 static int unixjob_traverse_fn(TDB_CONTEXT *the_tdb, TDB_DATA key,
470 TDB_DATA data, void *private_data)
472 struct printjob *pjob;
473 struct unixjob_traverse_state *state =
474 (struct unixjob_traverse_state *)private_data;
476 if (!data.dptr || data.dsize == 0)
477 return 0;
479 pjob = (struct printjob *)data.dptr;
480 if (key.dsize != sizeof(uint32))
481 return 0;
483 if (state->sysjob == pjob->sysjob) {
484 uint32 jobid = IVAL(key.dptr,0);
486 state->sysjob_to_jobid_value = jobid;
487 return 1;
490 return 0;
493 /****************************************************************************
494 This is a *horribly expensive call as we have to iterate through all the
495 current printer tdb's. Don't do this often ! JRA.
496 ****************************************************************************/
498 uint32 sysjob_to_jobid(int unix_jobid)
500 int services = lp_numservices();
501 int snum;
502 struct unixjob_traverse_state state;
504 state.sysjob = unix_jobid;
505 state.sysjob_to_jobid_value = (uint32)-1;
507 for (snum = 0; snum < services; snum++) {
508 struct tdb_print_db *pdb;
509 if (!lp_print_ok(snum))
510 continue;
511 pdb = get_print_db_byname(lp_const_servicename(snum));
512 if (!pdb) {
513 continue;
515 tdb_traverse(pdb->tdb, unixjob_traverse_fn, &state);
516 release_print_db(pdb);
517 if (state.sysjob_to_jobid_value != (uint32)-1)
518 return state.sysjob_to_jobid_value;
520 return (uint32)-1;
523 /****************************************************************************
524 Send notifications based on what has changed after a pjob_store.
525 ****************************************************************************/
527 static const struct {
528 uint32 lpq_status;
529 uint32 spoolss_status;
530 } lpq_to_spoolss_status_map[] = {
531 { LPQ_QUEUED, JOB_STATUS_QUEUED },
532 { LPQ_PAUSED, JOB_STATUS_PAUSED },
533 { LPQ_SPOOLING, JOB_STATUS_SPOOLING },
534 { LPQ_PRINTING, JOB_STATUS_PRINTING },
535 { LPQ_DELETING, JOB_STATUS_DELETING },
536 { LPQ_OFFLINE, JOB_STATUS_OFFLINE },
537 { LPQ_PAPEROUT, JOB_STATUS_PAPEROUT },
538 { LPQ_PRINTED, JOB_STATUS_PRINTED },
539 { LPQ_DELETED, JOB_STATUS_DELETED },
540 { LPQ_BLOCKED, JOB_STATUS_BLOCKED_DEVQ },
541 { LPQ_USER_INTERVENTION, JOB_STATUS_USER_INTERVENTION },
542 { -1, 0 }
545 /* Convert a lpq status value stored in printing.tdb into the
546 appropriate win32 API constant. */
548 static uint32 map_to_spoolss_status(uint32 lpq_status)
550 int i = 0;
552 while (lpq_to_spoolss_status_map[i].lpq_status != -1) {
553 if (lpq_to_spoolss_status_map[i].lpq_status == lpq_status)
554 return lpq_to_spoolss_status_map[i].spoolss_status;
555 i++;
558 return 0;
561 /***************************************************************************
562 Append a jobid to the 'jobs changed' list.
563 ***************************************************************************/
565 static bool add_to_jobs_changed(struct tdb_print_db *pdb, uint32_t jobid)
567 TDB_DATA data;
568 uint32_t store_jobid;
570 SIVAL(&store_jobid, 0, jobid);
571 data.dptr = (uint8 *) &store_jobid;
572 data.dsize = 4;
574 DEBUG(10,("add_to_jobs_added: Added jobid %u\n", (unsigned int)jobid ));
576 return (tdb_append(pdb->tdb, string_tdb_data("INFO/jobs_changed"),
577 data) == 0);
580 /***************************************************************************
581 Remove a jobid from the 'jobs changed' list.
582 ***************************************************************************/
584 static bool remove_from_jobs_changed(const char* sharename, uint32_t jobid)
586 struct tdb_print_db *pdb = get_print_db_byname(sharename);
587 TDB_DATA data, key;
588 size_t job_count, i;
589 bool ret = False;
590 bool gotlock = False;
592 if (!pdb) {
593 return False;
596 ZERO_STRUCT(data);
598 key = string_tdb_data("INFO/jobs_changed");
600 if (tdb_chainlock_with_timeout(pdb->tdb, key, 5) == -1)
601 goto out;
603 gotlock = True;
605 data = tdb_fetch(pdb->tdb, key);
607 if (data.dptr == NULL || data.dsize == 0 || (data.dsize % 4 != 0))
608 goto out;
610 job_count = data.dsize / 4;
611 for (i = 0; i < job_count; i++) {
612 uint32 ch_jobid;
614 ch_jobid = IVAL(data.dptr, i*4);
615 if (ch_jobid == jobid) {
616 if (i < job_count -1 )
617 memmove(data.dptr + (i*4), data.dptr + (i*4) + 4, (job_count - i - 1)*4 );
618 data.dsize -= 4;
619 if (tdb_store(pdb->tdb, key, data, TDB_REPLACE) == -1)
620 goto out;
621 break;
625 ret = True;
626 out:
628 if (gotlock)
629 tdb_chainunlock(pdb->tdb, key);
630 SAFE_FREE(data.dptr);
631 release_print_db(pdb);
632 if (ret)
633 DEBUG(10,("remove_from_jobs_changed: removed jobid %u\n", (unsigned int)jobid ));
634 else
635 DEBUG(10,("remove_from_jobs_changed: Failed to remove jobid %u\n", (unsigned int)jobid ));
636 return ret;
639 static void pjob_store_notify(struct tevent_context *ev,
640 struct messaging_context *msg_ctx,
641 const char* sharename, uint32 jobid,
642 struct printjob *old_data,
643 struct printjob *new_data,
644 bool *pchanged)
646 bool new_job = false;
647 bool changed = false;
649 if (old_data == NULL) {
650 new_job = true;
653 /* ACHTUNG! Due to a bug in Samba's spoolss parsing of the
654 NOTIFY_INFO_DATA buffer, we *have* to send the job submission
655 time first or else we'll end up with potential alignment
656 errors. I don't think the systemtime should be spooled as
657 a string, but this gets us around that error.
658 --jerry (i'll feel dirty for this) */
660 if (new_job) {
661 notify_job_submitted(ev, msg_ctx,
662 sharename, jobid, new_data->starttime);
663 notify_job_username(ev, msg_ctx,
664 sharename, jobid, new_data->user);
665 notify_job_name(ev, msg_ctx,
666 sharename, jobid, new_data->jobname);
667 notify_job_status(ev, msg_ctx,
668 sharename, jobid, map_to_spoolss_status(new_data->status));
669 notify_job_total_bytes(ev, msg_ctx,
670 sharename, jobid, new_data->size);
671 notify_job_total_pages(ev, msg_ctx,
672 sharename, jobid, new_data->page_count);
673 } else {
674 if (!strequal(old_data->jobname, new_data->jobname)) {
675 notify_job_name(ev, msg_ctx, sharename,
676 jobid, new_data->jobname);
677 changed = true;
680 if (old_data->status != new_data->status) {
681 notify_job_status(ev, msg_ctx,
682 sharename, jobid,
683 map_to_spoolss_status(new_data->status));
686 if (old_data->size != new_data->size) {
687 notify_job_total_bytes(ev, msg_ctx,
688 sharename, jobid, new_data->size);
691 if (old_data->page_count != new_data->page_count) {
692 notify_job_total_pages(ev, msg_ctx,
693 sharename, jobid,
694 new_data->page_count);
698 *pchanged = changed;
701 /****************************************************************************
702 Store a job structure back to the database.
703 ****************************************************************************/
705 static bool pjob_store(struct tevent_context *ev,
706 struct messaging_context *msg_ctx,
707 const char* sharename, uint32 jobid,
708 struct printjob *pjob)
710 uint32_t tmp;
711 TDB_DATA old_data, new_data;
712 bool ret = False;
713 struct tdb_print_db *pdb = get_print_db_byname(sharename);
714 uint8 *buf = NULL;
715 int len, newlen, buflen;
718 if (!pdb)
719 return False;
721 /* Get old data */
723 old_data = tdb_fetch(pdb->tdb, print_key(jobid, &tmp));
725 /* Doh! Now we have to pack/unpack data since the NT_DEVICEMODE was added */
727 newlen = 0;
729 do {
730 len = 0;
731 buflen = newlen;
732 len += tdb_pack(buf+len, buflen-len, "dddddddddfffff",
733 (uint32)pjob->pid,
734 (uint32)pjob->sysjob,
735 (uint32)pjob->fd,
736 (uint32)pjob->starttime,
737 (uint32)pjob->status,
738 (uint32)pjob->size,
739 (uint32)pjob->page_count,
740 (uint32)pjob->spooled,
741 (uint32)pjob->smbjob,
742 pjob->filename,
743 pjob->jobname,
744 pjob->user,
745 pjob->clientmachine,
746 pjob->queuename);
748 len += pack_devicemode(pjob->devmode, buf+len, buflen-len);
750 if (buflen != len) {
751 buf = (uint8 *)SMB_REALLOC(buf, len);
752 if (!buf) {
753 DEBUG(0,("pjob_store: failed to enlarge buffer!\n"));
754 goto done;
756 newlen = len;
758 } while ( buflen != len );
761 /* Store new data */
763 new_data.dptr = buf;
764 new_data.dsize = len;
765 ret = (tdb_store(pdb->tdb, print_key(jobid, &tmp), new_data,
766 TDB_REPLACE) == 0);
768 /* Send notify updates for what has changed */
770 if ( ret ) {
771 bool changed = false;
772 struct printjob old_pjob;
774 if ( old_data.dsize )
776 if ( unpack_pjob( old_data.dptr, old_data.dsize, &old_pjob ) != -1 )
778 pjob_store_notify(server_event_context(),
779 msg_ctx,
780 sharename, jobid, &old_pjob,
781 pjob,
782 &changed);
783 talloc_free(old_pjob.devmode);
785 if (changed) {
786 add_to_jobs_changed(pdb, jobid);
791 else {
792 /* new job */
793 pjob_store_notify(server_event_context(), msg_ctx,
794 sharename, jobid, NULL, pjob,
795 &changed);
799 release_print_db(pdb);
800 done:
801 SAFE_FREE( old_data.dptr );
802 SAFE_FREE( buf );
804 return ret;
807 /****************************************************************************
808 Remove a job structure from the database.
809 ****************************************************************************/
811 static void pjob_delete(struct tevent_context *ev,
812 struct messaging_context *msg_ctx,
813 const char* sharename, uint32 jobid)
815 uint32_t tmp;
816 struct printjob *pjob;
817 uint32 job_status = 0;
818 struct tdb_print_db *pdb;
820 pdb = get_print_db_byname( sharename );
822 if (!pdb)
823 return;
825 pjob = print_job_find( sharename, jobid );
827 if (!pjob) {
828 DEBUG(5, ("pjob_delete: we were asked to delete nonexistent job %u\n",
829 (unsigned int)jobid));
830 release_print_db(pdb);
831 return;
834 /* We must cycle through JOB_STATUS_DELETING and
835 JOB_STATUS_DELETED for the port monitor to delete the job
836 properly. */
838 job_status = JOB_STATUS_DELETING|JOB_STATUS_DELETED;
839 notify_job_status(ev, msg_ctx, sharename, jobid, job_status);
841 /* Remove from printing.tdb */
843 tdb_delete(pdb->tdb, print_key(jobid, &tmp));
844 remove_from_jobs_added(sharename, jobid);
845 release_print_db( pdb );
846 rap_jobid_delete(sharename, jobid);
849 /****************************************************************************
850 List a unix job in the print database.
851 ****************************************************************************/
853 static void print_unix_job(struct tevent_context *ev,
854 struct messaging_context *msg_ctx,
855 const char *sharename, print_queue_struct *q,
856 uint32 jobid)
858 struct printjob pj, *old_pj;
860 if (jobid == (uint32)-1)
861 jobid = q->job + UNIX_JOB_START;
863 /* Preserve the timestamp on an existing unix print job */
865 old_pj = print_job_find(sharename, jobid);
867 ZERO_STRUCT(pj);
869 pj.pid = (pid_t)-1;
870 pj.sysjob = q->job;
871 pj.fd = -1;
872 pj.starttime = old_pj ? old_pj->starttime : q->time;
873 pj.status = q->status;
874 pj.size = q->size;
875 pj.spooled = True;
876 fstrcpy(pj.filename, old_pj ? old_pj->filename : "");
877 if (jobid < UNIX_JOB_START) {
878 pj.smbjob = True;
879 fstrcpy(pj.jobname, old_pj ? old_pj->jobname : "Remote Downlevel Document");
880 } else {
881 pj.smbjob = False;
882 fstrcpy(pj.jobname, old_pj ? old_pj->jobname : q->fs_file);
884 fstrcpy(pj.user, old_pj ? old_pj->user : q->fs_user);
885 fstrcpy(pj.queuename, old_pj ? old_pj->queuename : sharename );
887 pjob_store(ev, msg_ctx, sharename, jobid, &pj);
891 struct traverse_struct {
892 print_queue_struct *queue;
893 int qcount, snum, maxcount, total_jobs;
894 const char *sharename;
895 time_t lpq_time;
896 const char *lprm_command;
897 struct printif *print_if;
898 struct tevent_context *ev;
899 struct messaging_context *msg_ctx;
902 /****************************************************************************
903 Utility fn to delete any jobs that are no longer active.
904 ****************************************************************************/
906 static int traverse_fn_delete(TDB_CONTEXT *t, TDB_DATA key, TDB_DATA data, void *state)
908 struct traverse_struct *ts = (struct traverse_struct *)state;
909 struct printjob pjob;
910 uint32 jobid;
911 int i = 0;
913 if ( key.dsize != sizeof(jobid) )
914 return 0;
916 jobid = IVAL(key.dptr, 0);
917 if ( unpack_pjob( data.dptr, data.dsize, &pjob ) == -1 )
918 return 0;
919 talloc_free(pjob.devmode);
922 if (!pjob.smbjob) {
923 /* remove a unix job if it isn't in the system queue any more */
925 for (i=0;i<ts->qcount;i++) {
926 uint32 u_jobid = (ts->queue[i].job + UNIX_JOB_START);
927 if (jobid == u_jobid)
928 break;
930 if (i == ts->qcount) {
931 DEBUG(10,("traverse_fn_delete: pjob %u deleted due to !smbjob\n",
932 (unsigned int)jobid ));
933 pjob_delete(ts->ev, ts->msg_ctx,
934 ts->sharename, jobid);
935 return 0;
938 /* need to continue the the bottom of the function to
939 save the correct attributes */
942 /* maybe it hasn't been spooled yet */
943 if (!pjob.spooled) {
944 /* if a job is not spooled and the process doesn't
945 exist then kill it. This cleans up after smbd
946 deaths */
947 if (!process_exists_by_pid(pjob.pid)) {
948 DEBUG(10,("traverse_fn_delete: pjob %u deleted due to !process_exists (%u)\n",
949 (unsigned int)jobid, (unsigned int)pjob.pid ));
950 pjob_delete(ts->ev, ts->msg_ctx,
951 ts->sharename, jobid);
952 } else
953 ts->total_jobs++;
954 return 0;
957 /* this check only makes sense for jobs submitted from Windows clients */
959 if ( pjob.smbjob ) {
960 for (i=0;i<ts->qcount;i++) {
961 uint32 curr_jobid;
963 if ( pjob.status == LPQ_DELETED )
964 continue;
966 curr_jobid = print_parse_jobid(ts->queue[i].fs_file);
968 if (jobid == curr_jobid) {
970 /* try to clean up any jobs that need to be deleted */
972 if ( pjob.status == LPQ_DELETING ) {
973 int result;
975 result = (*(ts->print_if->job_delete))(
976 ts->sharename, ts->lprm_command, &pjob );
978 if ( result != 0 ) {
979 /* if we can't delete, then reset the job status */
980 pjob.status = LPQ_QUEUED;
981 pjob_store(ts->ev, ts->msg_ctx,
982 ts->sharename, jobid, &pjob);
984 else {
985 /* if we deleted the job, the remove the tdb record */
986 pjob_delete(ts->ev,
987 ts->msg_ctx,
988 ts->sharename, jobid);
989 pjob.status = LPQ_DELETED;
994 break;
999 /* The job isn't in the system queue - we have to assume it has
1000 completed, so delete the database entry. */
1002 if (i == ts->qcount) {
1004 /* A race can occur between the time a job is spooled and
1005 when it appears in the lpq output. This happens when
1006 the job is added to printing.tdb when another smbd
1007 running print_queue_update() has completed a lpq and
1008 is currently traversing the printing tdb and deleting jobs.
1009 Don't delete the job if it was submitted after the lpq_time. */
1011 if (pjob.starttime < ts->lpq_time) {
1012 DEBUG(10,("traverse_fn_delete: pjob %u deleted due to pjob.starttime (%u) < ts->lpq_time (%u)\n",
1013 (unsigned int)jobid,
1014 (unsigned int)pjob.starttime,
1015 (unsigned int)ts->lpq_time ));
1016 pjob_delete(ts->ev, ts->msg_ctx,
1017 ts->sharename, jobid);
1018 } else
1019 ts->total_jobs++;
1020 return 0;
1023 /* Save the pjob attributes we will store.
1024 FIXME!!! This is the only place where queue->job
1025 represents the SMB jobid --jerry */
1027 ts->queue[i].job = jobid;
1028 ts->queue[i].size = pjob.size;
1029 ts->queue[i].page_count = pjob.page_count;
1030 ts->queue[i].status = pjob.status;
1031 ts->queue[i].priority = 1;
1032 ts->queue[i].time = pjob.starttime;
1033 fstrcpy(ts->queue[i].fs_user, pjob.user);
1034 fstrcpy(ts->queue[i].fs_file, pjob.jobname);
1036 ts->total_jobs++;
1038 return 0;
1041 /****************************************************************************
1042 Check if the print queue has been updated recently enough.
1043 ****************************************************************************/
1045 static void print_cache_flush(const char *sharename)
1047 fstring key;
1048 struct tdb_print_db *pdb = get_print_db_byname(sharename);
1050 if (!pdb)
1051 return;
1052 slprintf(key, sizeof(key)-1, "CACHE/%s", sharename);
1053 tdb_store_int32(pdb->tdb, key, -1);
1054 release_print_db(pdb);
1057 /****************************************************************************
1058 Check if someone already thinks they are doing the update.
1059 ****************************************************************************/
1061 static pid_t get_updating_pid(const char *sharename)
1063 fstring keystr;
1064 TDB_DATA data, key;
1065 pid_t updating_pid;
1066 struct tdb_print_db *pdb = get_print_db_byname(sharename);
1068 if (!pdb)
1069 return (pid_t)-1;
1070 slprintf(keystr, sizeof(keystr)-1, "UPDATING/%s", sharename);
1071 key = string_tdb_data(keystr);
1073 data = tdb_fetch(pdb->tdb, key);
1074 release_print_db(pdb);
1075 if (!data.dptr || data.dsize != sizeof(pid_t)) {
1076 SAFE_FREE(data.dptr);
1077 return (pid_t)-1;
1080 updating_pid = IVAL(data.dptr, 0);
1081 SAFE_FREE(data.dptr);
1083 if (process_exists_by_pid(updating_pid))
1084 return updating_pid;
1086 return (pid_t)-1;
1089 /****************************************************************************
1090 Set the fact that we're doing the update, or have finished doing the update
1091 in the tdb.
1092 ****************************************************************************/
1094 static void set_updating_pid(const fstring sharename, bool updating)
1096 fstring keystr;
1097 TDB_DATA key;
1098 TDB_DATA data;
1099 pid_t updating_pid = sys_getpid();
1100 uint8 buffer[4];
1102 struct tdb_print_db *pdb = get_print_db_byname(sharename);
1104 if (!pdb)
1105 return;
1107 slprintf(keystr, sizeof(keystr)-1, "UPDATING/%s", sharename);
1108 key = string_tdb_data(keystr);
1110 DEBUG(5, ("set_updating_pid: %s updating lpq cache for print share %s\n",
1111 updating ? "" : "not ",
1112 sharename ));
1114 if ( !updating ) {
1115 tdb_delete(pdb->tdb, key);
1116 release_print_db(pdb);
1117 return;
1120 SIVAL( buffer, 0, updating_pid);
1121 data.dptr = buffer;
1122 data.dsize = 4; /* we always assume this is a 4 byte value */
1124 tdb_store(pdb->tdb, key, data, TDB_REPLACE);
1125 release_print_db(pdb);
1128 /****************************************************************************
1129 Sort print jobs by submittal time.
1130 ****************************************************************************/
1132 static int printjob_comp(print_queue_struct *j1, print_queue_struct *j2)
1134 /* Silly cases */
1136 if (!j1 && !j2)
1137 return 0;
1138 if (!j1)
1139 return -1;
1140 if (!j2)
1141 return 1;
1143 /* Sort on job start time */
1145 if (j1->time == j2->time)
1146 return 0;
1147 return (j1->time > j2->time) ? 1 : -1;
1150 /****************************************************************************
1151 Store the sorted queue representation for later portmon retrieval.
1152 Skip deleted jobs
1153 ****************************************************************************/
1155 static void store_queue_struct(struct tdb_print_db *pdb, struct traverse_struct *pts)
1157 TDB_DATA data;
1158 int max_reported_jobs = lp_max_reported_jobs(pts->snum);
1159 print_queue_struct *queue = pts->queue;
1160 size_t len;
1161 size_t i;
1162 unsigned int qcount;
1164 if (max_reported_jobs && (max_reported_jobs < pts->qcount))
1165 pts->qcount = max_reported_jobs;
1166 qcount = 0;
1168 /* Work out the size. */
1169 data.dsize = 0;
1170 data.dsize += tdb_pack(NULL, 0, "d", qcount);
1172 for (i = 0; i < pts->qcount; i++) {
1173 if ( queue[i].status == LPQ_DELETED )
1174 continue;
1176 qcount++;
1177 data.dsize += tdb_pack(NULL, 0, "ddddddff",
1178 (uint32)queue[i].job,
1179 (uint32)queue[i].size,
1180 (uint32)queue[i].page_count,
1181 (uint32)queue[i].status,
1182 (uint32)queue[i].priority,
1183 (uint32)queue[i].time,
1184 queue[i].fs_user,
1185 queue[i].fs_file);
1188 if ((data.dptr = (uint8 *)SMB_MALLOC(data.dsize)) == NULL)
1189 return;
1191 len = 0;
1192 len += tdb_pack(data.dptr + len, data.dsize - len, "d", qcount);
1193 for (i = 0; i < pts->qcount; i++) {
1194 if ( queue[i].status == LPQ_DELETED )
1195 continue;
1197 len += tdb_pack(data.dptr + len, data.dsize - len, "ddddddff",
1198 (uint32)queue[i].job,
1199 (uint32)queue[i].size,
1200 (uint32)queue[i].page_count,
1201 (uint32)queue[i].status,
1202 (uint32)queue[i].priority,
1203 (uint32)queue[i].time,
1204 queue[i].fs_user,
1205 queue[i].fs_file);
1208 tdb_store(pdb->tdb, string_tdb_data("INFO/linear_queue_array"), data,
1209 TDB_REPLACE);
1210 SAFE_FREE(data.dptr);
1211 return;
1214 static TDB_DATA get_jobs_added_data(struct tdb_print_db *pdb)
1216 TDB_DATA data;
1218 ZERO_STRUCT(data);
1220 data = tdb_fetch(pdb->tdb, string_tdb_data("INFO/jobs_added"));
1221 if (data.dptr == NULL || data.dsize == 0 || (data.dsize % 4 != 0)) {
1222 SAFE_FREE(data.dptr);
1223 ZERO_STRUCT(data);
1226 return data;
1229 static void check_job_added(const char *sharename, TDB_DATA data, uint32 jobid)
1231 unsigned int i;
1232 unsigned int job_count = data.dsize / 4;
1234 for (i = 0; i < job_count; i++) {
1235 uint32 ch_jobid;
1237 ch_jobid = IVAL(data.dptr, i*4);
1238 if (ch_jobid == jobid)
1239 remove_from_jobs_added(sharename, jobid);
1243 /****************************************************************************
1244 Check if the print queue has been updated recently enough.
1245 ****************************************************************************/
1247 static bool print_cache_expired(const char *sharename, bool check_pending)
1249 fstring key;
1250 time_t last_qscan_time, time_now = time(NULL);
1251 struct tdb_print_db *pdb = get_print_db_byname(sharename);
1252 bool result = False;
1254 if (!pdb)
1255 return False;
1257 snprintf(key, sizeof(key), "CACHE/%s", sharename);
1258 last_qscan_time = (time_t)tdb_fetch_int32(pdb->tdb, key);
1261 * Invalidate the queue for 3 reasons.
1262 * (1). last queue scan time == -1.
1263 * (2). Current time - last queue scan time > allowed cache time.
1264 * (3). last queue scan time > current time + MAX_CACHE_VALID_TIME (1 hour by default).
1265 * This last test picks up machines for which the clock has been moved
1266 * forward, an lpq scan done and then the clock moved back. Otherwise
1267 * that last lpq scan would stay around for a loooong loooong time... :-). JRA.
1270 if (last_qscan_time == ((time_t)-1)
1271 || (time_now - last_qscan_time) >= lp_lpqcachetime()
1272 || last_qscan_time > (time_now + MAX_CACHE_VALID_TIME))
1274 uint32 u;
1275 time_t msg_pending_time;
1277 DEBUG(4, ("print_cache_expired: cache expired for queue %s "
1278 "(last_qscan_time = %d, time now = %d, qcachetime = %d)\n",
1279 sharename, (int)last_qscan_time, (int)time_now,
1280 (int)lp_lpqcachetime() ));
1282 /* check if another smbd has already sent a message to update the
1283 queue. Give the pending message one minute to clear and
1284 then send another message anyways. Make sure to check for
1285 clocks that have been run forward and then back again. */
1287 snprintf(key, sizeof(key), "MSG_PENDING/%s", sharename);
1289 if ( check_pending
1290 && tdb_fetch_uint32( pdb->tdb, key, &u )
1291 && (msg_pending_time=u) > 0
1292 && msg_pending_time <= time_now
1293 && (time_now - msg_pending_time) < 60 )
1295 DEBUG(4,("print_cache_expired: message already pending for %s. Accepting cache\n",
1296 sharename));
1297 goto done;
1300 result = True;
1303 done:
1304 release_print_db(pdb);
1305 return result;
1308 /****************************************************************************
1309 main work for updating the lpq cahe for a printer queue
1310 ****************************************************************************/
1312 static void print_queue_update_internal( struct tevent_context *ev,
1313 struct messaging_context *msg_ctx,
1314 const char *sharename,
1315 struct printif *current_printif,
1316 char *lpq_command, char *lprm_command )
1318 int i, qcount;
1319 print_queue_struct *queue = NULL;
1320 print_status_struct status;
1321 print_status_struct old_status;
1322 struct printjob *pjob;
1323 struct traverse_struct tstruct;
1324 TDB_DATA data, key;
1325 TDB_DATA jcdata;
1326 fstring keystr, cachestr;
1327 struct tdb_print_db *pdb = get_print_db_byname(sharename);
1329 if (!pdb) {
1330 return;
1333 DEBUG(5,("print_queue_update_internal: printer = %s, type = %d, lpq command = [%s]\n",
1334 sharename, current_printif->type, lpq_command));
1337 * Update the cache time FIRST ! Stops others even
1338 * attempting to get the lock and doing this
1339 * if the lpq takes a long time.
1342 slprintf(cachestr, sizeof(cachestr)-1, "CACHE/%s", sharename);
1343 tdb_store_int32(pdb->tdb, cachestr, (int)time(NULL));
1345 /* get the current queue using the appropriate interface */
1346 ZERO_STRUCT(status);
1348 qcount = (*(current_printif->queue_get))(sharename,
1349 current_printif->type,
1350 lpq_command, &queue, &status);
1352 DEBUG(3, ("print_queue_update_internal: %d job%s in queue for %s\n",
1353 qcount, (qcount != 1) ? "s" : "", sharename));
1355 /* Sort the queue by submission time otherwise they are displayed
1356 in hash order. */
1358 TYPESAFE_QSORT(queue, qcount, printjob_comp);
1361 any job in the internal database that is marked as spooled
1362 and doesn't exist in the system queue is considered finished
1363 and removed from the database
1365 any job in the system database but not in the internal database
1366 is added as a unix job
1368 fill in any system job numbers as we go
1371 jcdata = get_jobs_added_data(pdb);
1373 for (i=0; i<qcount; i++) {
1374 uint32 jobid = print_parse_jobid(queue[i].fs_file);
1376 if (jobid == (uint32)-1) {
1377 /* assume its a unix print job */
1378 print_unix_job(ev, msg_ctx,
1379 sharename, &queue[i], jobid);
1380 continue;
1383 /* we have an active SMB print job - update its status */
1384 pjob = print_job_find(sharename, jobid);
1385 if (!pjob) {
1386 /* err, somethings wrong. Probably smbd was restarted
1387 with jobs in the queue. All we can do is treat them
1388 like unix jobs. Pity. */
1389 print_unix_job(ev, msg_ctx,
1390 sharename, &queue[i], jobid);
1391 continue;
1394 pjob->sysjob = queue[i].job;
1396 /* don't reset the status on jobs to be deleted */
1398 if ( pjob->status != LPQ_DELETING )
1399 pjob->status = queue[i].status;
1401 pjob_store(ev, msg_ctx, sharename, jobid, pjob);
1403 check_job_added(sharename, jcdata, jobid);
1406 SAFE_FREE(jcdata.dptr);
1408 /* now delete any queued entries that don't appear in the
1409 system queue */
1410 tstruct.queue = queue;
1411 tstruct.qcount = qcount;
1412 tstruct.snum = -1;
1413 tstruct.total_jobs = 0;
1414 tstruct.lpq_time = time(NULL);
1415 tstruct.sharename = sharename;
1416 tstruct.lprm_command = lprm_command;
1417 tstruct.print_if = current_printif;
1418 tstruct.ev = ev;
1419 tstruct.msg_ctx = msg_ctx;
1421 tdb_traverse(pdb->tdb, traverse_fn_delete, (void *)&tstruct);
1423 /* Store the linearised queue, max jobs only. */
1424 store_queue_struct(pdb, &tstruct);
1426 SAFE_FREE(tstruct.queue);
1428 DEBUG(10,("print_queue_update_internal: printer %s INFO/total_jobs = %d\n",
1429 sharename, tstruct.total_jobs ));
1431 tdb_store_int32(pdb->tdb, "INFO/total_jobs", tstruct.total_jobs);
1433 get_queue_status(sharename, &old_status);
1434 if (old_status.qcount != qcount)
1435 DEBUG(10,("print_queue_update_internal: queue status change %d jobs -> %d jobs for printer %s\n",
1436 old_status.qcount, qcount, sharename));
1438 /* store the new queue status structure */
1439 slprintf(keystr, sizeof(keystr)-1, "STATUS/%s", sharename);
1440 key = string_tdb_data(keystr);
1442 status.qcount = qcount;
1443 data.dptr = (uint8 *)&status;
1444 data.dsize = sizeof(status);
1445 tdb_store(pdb->tdb, key, data, TDB_REPLACE);
1448 * Update the cache time again. We want to do this call
1449 * as little as possible...
1452 slprintf(keystr, sizeof(keystr)-1, "CACHE/%s", sharename);
1453 tdb_store_int32(pdb->tdb, keystr, (int32)time(NULL));
1455 /* clear the msg pending record for this queue */
1457 snprintf(keystr, sizeof(keystr), "MSG_PENDING/%s", sharename);
1459 if ( !tdb_store_uint32( pdb->tdb, keystr, 0 ) ) {
1460 /* log a message but continue on */
1462 DEBUG(0,("print_queue_update: failed to store MSG_PENDING flag for [%s]!\n",
1463 sharename));
1466 release_print_db( pdb );
1468 return;
1471 /****************************************************************************
1472 Update the internal database from the system print queue for a queue.
1473 obtain a lock on the print queue before proceeding (needed when mutiple
1474 smbd processes maytry to update the lpq cache concurrently).
1475 ****************************************************************************/
1477 static void print_queue_update_with_lock( struct tevent_context *ev,
1478 struct messaging_context *msg_ctx,
1479 const char *sharename,
1480 struct printif *current_printif,
1481 char *lpq_command, char *lprm_command )
1483 fstring keystr;
1484 struct tdb_print_db *pdb;
1486 DEBUG(5,("print_queue_update_with_lock: printer share = %s\n", sharename));
1487 pdb = get_print_db_byname(sharename);
1488 if (!pdb)
1489 return;
1491 if ( !print_cache_expired(sharename, False) ) {
1492 DEBUG(5,("print_queue_update_with_lock: print cache for %s is still ok\n", sharename));
1493 release_print_db(pdb);
1494 return;
1498 * Check to see if someone else is doing this update.
1499 * This is essentially a mutex on the update.
1502 if (get_updating_pid(sharename) != -1) {
1503 release_print_db(pdb);
1504 return;
1507 /* Lock the queue for the database update */
1509 slprintf(keystr, sizeof(keystr) - 1, "LOCK/%s", sharename);
1510 /* Only wait 10 seconds for this. */
1511 if (tdb_lock_bystring_with_timeout(pdb->tdb, keystr, 10) == -1) {
1512 DEBUG(0,("print_queue_update_with_lock: Failed to lock printer %s database\n", sharename));
1513 release_print_db(pdb);
1514 return;
1518 * Ensure that no one else got in here.
1519 * If the updating pid is still -1 then we are
1520 * the winner.
1523 if (get_updating_pid(sharename) != -1) {
1525 * Someone else is doing the update, exit.
1527 tdb_unlock_bystring(pdb->tdb, keystr);
1528 release_print_db(pdb);
1529 return;
1533 * We're going to do the update ourselves.
1536 /* Tell others we're doing the update. */
1537 set_updating_pid(sharename, True);
1540 * Allow others to enter and notice we're doing
1541 * the update.
1544 tdb_unlock_bystring(pdb->tdb, keystr);
1546 /* do the main work now */
1548 print_queue_update_internal(ev, msg_ctx,
1549 sharename, current_printif,
1550 lpq_command, lprm_command);
1552 /* Delete our pid from the db. */
1553 set_updating_pid(sharename, False);
1554 release_print_db(pdb);
1557 /****************************************************************************
1558 this is the receive function of the background lpq updater
1559 ****************************************************************************/
1560 static void print_queue_receive(struct messaging_context *msg,
1561 void *private_data,
1562 uint32_t msg_type,
1563 struct server_id server_id,
1564 DATA_BLOB *data)
1566 fstring sharename;
1567 char *lpqcommand = NULL, *lprmcommand = NULL;
1568 int printing_type;
1569 size_t len;
1571 len = tdb_unpack( (uint8 *)data->data, data->length, "fdPP",
1572 sharename,
1573 &printing_type,
1574 &lpqcommand,
1575 &lprmcommand );
1577 if ( len == -1 ) {
1578 SAFE_FREE(lpqcommand);
1579 SAFE_FREE(lprmcommand);
1580 DEBUG(0,("print_queue_receive: Got invalid print queue update message\n"));
1581 return;
1584 print_queue_update_with_lock(server_event_context(), msg, sharename,
1585 get_printer_fns_from_type((enum printing_types)printing_type),
1586 lpqcommand, lprmcommand );
1588 SAFE_FREE(lpqcommand);
1589 SAFE_FREE(lprmcommand);
1590 return;
1593 static void printing_pause_fd_handler(struct tevent_context *ev,
1594 struct tevent_fd *fde,
1595 uint16_t flags,
1596 void *private_data)
1599 * If pause_pipe[1] is closed it means the parent smbd
1600 * and children exited or aborted.
1602 exit_server_cleanly(NULL);
1605 extern struct child_pid *children;
1606 extern int num_children;
1608 static void add_child_pid(pid_t pid)
1610 struct child_pid *child;
1612 child = SMB_MALLOC_P(struct child_pid);
1613 if (child == NULL) {
1614 DEBUG(0, ("Could not add child struct -- malloc failed\n"));
1615 return;
1617 child->pid = pid;
1618 DLIST_ADD(children, child);
1619 num_children += 1;
1622 static pid_t background_lpq_updater_pid = -1;
1624 /****************************************************************************
1625 main thread of the background lpq updater
1626 ****************************************************************************/
1627 void start_background_queue(struct tevent_context *ev,
1628 struct messaging_context *msg_ctx)
1630 /* Use local variables for this as we don't
1631 * need to save the parent side of this, just
1632 * ensure it closes when the process exits.
1634 int pause_pipe[2];
1636 DEBUG(3,("start_background_queue: Starting background LPQ thread\n"));
1638 if (pipe(pause_pipe) == -1) {
1639 DEBUG(5,("start_background_queue: cannot create pipe. %s\n", strerror(errno) ));
1640 exit(1);
1643 background_lpq_updater_pid = sys_fork();
1645 if (background_lpq_updater_pid == -1) {
1646 DEBUG(5,("start_background_queue: background LPQ thread failed to start. %s\n", strerror(errno) ));
1647 exit(1);
1650 /* Track the printing pid along with other smbd children */
1651 add_child_pid(background_lpq_updater_pid);
1653 if(background_lpq_updater_pid == 0) {
1654 struct tevent_fd *fde;
1655 int ret;
1656 NTSTATUS status;
1658 /* Child. */
1659 DEBUG(5,("start_background_queue: background LPQ thread started\n"));
1661 close(pause_pipe[0]);
1662 pause_pipe[0] = -1;
1664 status = reinit_after_fork(msg_ctx, ev, procid_self(), true);
1666 if (!NT_STATUS_IS_OK(status)) {
1667 DEBUG(0,("reinit_after_fork() failed\n"));
1668 smb_panic("reinit_after_fork() failed");
1671 smbd_setup_sig_term_handler();
1672 smbd_setup_sig_hup_handler(ev, msg_ctx);
1674 if (!serverid_register(procid_self(),
1675 FLAG_MSG_GENERAL|FLAG_MSG_SMBD
1676 |FLAG_MSG_PRINT_GENERAL)) {
1677 exit(1);
1680 if (!locking_init()) {
1681 exit(1);
1684 messaging_register(msg_ctx, NULL, MSG_PRINTER_UPDATE,
1685 print_queue_receive);
1687 fde = tevent_add_fd(ev, ev, pause_pipe[1], TEVENT_FD_READ,
1688 printing_pause_fd_handler,
1689 NULL);
1690 if (!fde) {
1691 DEBUG(0,("tevent_add_fd() failed for pause_pipe\n"));
1692 smb_panic("tevent_add_fd() failed for pause_pipe");
1695 DEBUG(5,("start_background_queue: background LPQ thread waiting for messages\n"));
1696 ret = tevent_loop_wait(ev);
1697 /* should not be reached */
1698 DEBUG(0,("background_queue: tevent_loop_wait() exited with %d - %s\n",
1699 ret, (ret == 0) ? "out of events" : strerror(errno)));
1700 exit(1);
1703 close(pause_pipe[1]);
1706 /****************************************************************************
1707 update the internal database from the system print queue for a queue
1708 ****************************************************************************/
1710 static void print_queue_update(struct messaging_context *msg_ctx,
1711 int snum, bool force)
1713 fstring key;
1714 fstring sharename;
1715 char *lpqcommand = NULL;
1716 char *lprmcommand = NULL;
1717 uint8 *buffer = NULL;
1718 size_t len = 0;
1719 size_t newlen;
1720 struct tdb_print_db *pdb;
1721 int type;
1722 struct printif *current_printif;
1723 TALLOC_CTX *ctx = talloc_tos();
1725 fstrcpy( sharename, lp_const_servicename(snum));
1727 /* don't strip out characters like '$' from the printername */
1729 lpqcommand = talloc_string_sub2(ctx,
1730 lp_lpqcommand(snum),
1731 "%p",
1732 lp_printername(snum),
1733 false, false, false);
1734 if (!lpqcommand) {
1735 return;
1737 lpqcommand = talloc_sub_advanced(ctx,
1738 lp_servicename(snum),
1739 current_user_info.unix_name,
1741 current_user.ut.gid,
1742 get_current_username(),
1743 current_user_info.domain,
1744 lpqcommand);
1745 if (!lpqcommand) {
1746 return;
1749 lprmcommand = talloc_string_sub2(ctx,
1750 lp_lprmcommand(snum),
1751 "%p",
1752 lp_printername(snum),
1753 false, false, false);
1754 if (!lprmcommand) {
1755 return;
1757 lprmcommand = talloc_sub_advanced(ctx,
1758 lp_servicename(snum),
1759 current_user_info.unix_name,
1761 current_user.ut.gid,
1762 get_current_username(),
1763 current_user_info.domain,
1764 lprmcommand);
1765 if (!lprmcommand) {
1766 return;
1770 * Make sure that the background queue process exists.
1771 * Otherwise just do the update ourselves
1774 if ( force || background_lpq_updater_pid == -1 ) {
1775 DEBUG(4,("print_queue_update: updating queue [%s] myself\n", sharename));
1776 current_printif = get_printer_fns( snum );
1777 print_queue_update_with_lock(server_event_context(), msg_ctx,
1778 sharename, current_printif,
1779 lpqcommand, lprmcommand);
1781 return;
1784 type = lp_printing(snum);
1786 /* get the length */
1788 len = tdb_pack( NULL, 0, "fdPP",
1789 sharename,
1790 type,
1791 lpqcommand,
1792 lprmcommand );
1794 buffer = SMB_XMALLOC_ARRAY( uint8, len );
1796 /* now pack the buffer */
1797 newlen = tdb_pack( buffer, len, "fdPP",
1798 sharename,
1799 type,
1800 lpqcommand,
1801 lprmcommand );
1803 SMB_ASSERT( newlen == len );
1805 DEBUG(10,("print_queue_update: Sending message -> printer = %s, "
1806 "type = %d, lpq command = [%s] lprm command = [%s]\n",
1807 sharename, type, lpqcommand, lprmcommand ));
1809 /* here we set a msg pending record for other smbd processes
1810 to throttle the number of duplicate print_queue_update msgs
1811 sent. */
1813 pdb = get_print_db_byname(sharename);
1814 if (!pdb) {
1815 SAFE_FREE(buffer);
1816 return;
1819 snprintf(key, sizeof(key), "MSG_PENDING/%s", sharename);
1821 if ( !tdb_store_uint32( pdb->tdb, key, time(NULL) ) ) {
1822 /* log a message but continue on */
1824 DEBUG(0,("print_queue_update: failed to store MSG_PENDING flag for [%s]!\n",
1825 sharename));
1828 release_print_db( pdb );
1830 /* finally send the message */
1832 messaging_send_buf(msg_ctx, pid_to_procid(background_lpq_updater_pid),
1833 MSG_PRINTER_UPDATE, (uint8 *)buffer, len);
1835 SAFE_FREE( buffer );
1837 return;
1840 /****************************************************************************
1841 Create/Update an entry in the print tdb that will allow us to send notify
1842 updates only to interested smbd's.
1843 ****************************************************************************/
1845 bool print_notify_register_pid(int snum)
1847 TDB_DATA data;
1848 struct tdb_print_db *pdb = NULL;
1849 TDB_CONTEXT *tdb = NULL;
1850 const char *printername;
1851 uint32 mypid = (uint32)sys_getpid();
1852 bool ret = False;
1853 size_t i;
1855 /* if (snum == -1), then the change notify request was
1856 on a print server handle and we need to register on
1857 all print queus */
1859 if (snum == -1)
1861 int num_services = lp_numservices();
1862 int idx;
1864 for ( idx=0; idx<num_services; idx++ ) {
1865 if (lp_snum_ok(idx) && lp_print_ok(idx) )
1866 print_notify_register_pid(idx);
1869 return True;
1871 else /* register for a specific printer */
1873 printername = lp_const_servicename(snum);
1874 pdb = get_print_db_byname(printername);
1875 if (!pdb)
1876 return False;
1877 tdb = pdb->tdb;
1880 if (tdb_lock_bystring_with_timeout(tdb, NOTIFY_PID_LIST_KEY, 10) == -1) {
1881 DEBUG(0,("print_notify_register_pid: Failed to lock printer %s\n",
1882 printername));
1883 if (pdb)
1884 release_print_db(pdb);
1885 return False;
1888 data = get_printer_notify_pid_list( tdb, printername, True );
1890 /* Add ourselves and increase the refcount. */
1892 for (i = 0; i < data.dsize; i += 8) {
1893 if (IVAL(data.dptr,i) == mypid) {
1894 uint32 new_refcount = IVAL(data.dptr, i+4) + 1;
1895 SIVAL(data.dptr, i+4, new_refcount);
1896 break;
1900 if (i == data.dsize) {
1901 /* We weren't in the list. Realloc. */
1902 data.dptr = (uint8 *)SMB_REALLOC(data.dptr, data.dsize + 8);
1903 if (!data.dptr) {
1904 DEBUG(0,("print_notify_register_pid: Relloc fail for printer %s\n",
1905 printername));
1906 goto done;
1908 data.dsize += 8;
1909 SIVAL(data.dptr,data.dsize - 8,mypid);
1910 SIVAL(data.dptr,data.dsize - 4,1); /* Refcount. */
1913 /* Store back the record. */
1914 if (tdb_store_bystring(tdb, NOTIFY_PID_LIST_KEY, data, TDB_REPLACE) == -1) {
1915 DEBUG(0,("print_notify_register_pid: Failed to update pid \
1916 list for printer %s\n", printername));
1917 goto done;
1920 ret = True;
1922 done:
1924 tdb_unlock_bystring(tdb, NOTIFY_PID_LIST_KEY);
1925 if (pdb)
1926 release_print_db(pdb);
1927 SAFE_FREE(data.dptr);
1928 return ret;
1931 /****************************************************************************
1932 Update an entry in the print tdb that will allow us to send notify
1933 updates only to interested smbd's.
1934 ****************************************************************************/
1936 bool print_notify_deregister_pid(int snum)
1938 TDB_DATA data;
1939 struct tdb_print_db *pdb = NULL;
1940 TDB_CONTEXT *tdb = NULL;
1941 const char *printername;
1942 uint32 mypid = (uint32)sys_getpid();
1943 size_t i;
1944 bool ret = False;
1946 /* if ( snum == -1 ), we are deregister a print server handle
1947 which means to deregister on all print queues */
1949 if (snum == -1)
1951 int num_services = lp_numservices();
1952 int idx;
1954 for ( idx=0; idx<num_services; idx++ ) {
1955 if ( lp_snum_ok(idx) && lp_print_ok(idx) )
1956 print_notify_deregister_pid(idx);
1959 return True;
1961 else /* deregister a specific printer */
1963 printername = lp_const_servicename(snum);
1964 pdb = get_print_db_byname(printername);
1965 if (!pdb)
1966 return False;
1967 tdb = pdb->tdb;
1970 if (tdb_lock_bystring_with_timeout(tdb, NOTIFY_PID_LIST_KEY, 10) == -1) {
1971 DEBUG(0,("print_notify_register_pid: Failed to lock \
1972 printer %s database\n", printername));
1973 if (pdb)
1974 release_print_db(pdb);
1975 return False;
1978 data = get_printer_notify_pid_list( tdb, printername, True );
1980 /* Reduce refcount. Remove ourselves if zero. */
1982 for (i = 0; i < data.dsize; ) {
1983 if (IVAL(data.dptr,i) == mypid) {
1984 uint32 refcount = IVAL(data.dptr, i+4);
1986 refcount--;
1988 if (refcount == 0) {
1989 if (data.dsize - i > 8)
1990 memmove( &data.dptr[i], &data.dptr[i+8], data.dsize - i - 8);
1991 data.dsize -= 8;
1992 continue;
1994 SIVAL(data.dptr, i+4, refcount);
1997 i += 8;
2000 if (data.dsize == 0)
2001 SAFE_FREE(data.dptr);
2003 /* Store back the record. */
2004 if (tdb_store_bystring(tdb, NOTIFY_PID_LIST_KEY, data, TDB_REPLACE) == -1) {
2005 DEBUG(0,("print_notify_register_pid: Failed to update pid \
2006 list for printer %s\n", printername));
2007 goto done;
2010 ret = True;
2012 done:
2014 tdb_unlock_bystring(tdb, NOTIFY_PID_LIST_KEY);
2015 if (pdb)
2016 release_print_db(pdb);
2017 SAFE_FREE(data.dptr);
2018 return ret;
2021 /****************************************************************************
2022 Check if a jobid is valid. It is valid if it exists in the database.
2023 ****************************************************************************/
2025 bool print_job_exists(const char* sharename, uint32 jobid)
2027 struct tdb_print_db *pdb = get_print_db_byname(sharename);
2028 bool ret;
2029 uint32_t tmp;
2031 if (!pdb)
2032 return False;
2033 ret = tdb_exists(pdb->tdb, print_key(jobid, &tmp));
2034 release_print_db(pdb);
2035 return ret;
2038 /****************************************************************************
2039 Give the filename used for a jobid.
2040 Only valid for the process doing the spooling and when the job
2041 has not been spooled.
2042 ****************************************************************************/
2044 char *print_job_fname(const char* sharename, uint32 jobid)
2046 struct printjob *pjob = print_job_find(sharename, jobid);
2047 if (!pjob || pjob->spooled || pjob->pid != sys_getpid())
2048 return NULL;
2049 return pjob->filename;
2053 /****************************************************************************
2054 Give the filename used for a jobid.
2055 Only valid for the process doing the spooling and when the job
2056 has not been spooled.
2057 ****************************************************************************/
2059 struct spoolss_DeviceMode *print_job_devmode(const char* sharename, uint32 jobid)
2061 struct printjob *pjob = print_job_find(sharename, jobid);
2063 if ( !pjob )
2064 return NULL;
2066 return pjob->devmode;
2069 /****************************************************************************
2070 Set the name of a job. Only possible for owner.
2071 ****************************************************************************/
2073 bool print_job_set_name(struct tevent_context *ev,
2074 struct messaging_context *msg_ctx,
2075 const char *sharename, uint32 jobid, const char *name)
2077 struct printjob *pjob;
2079 pjob = print_job_find(sharename, jobid);
2080 if (!pjob || pjob->pid != sys_getpid())
2081 return False;
2083 fstrcpy(pjob->jobname, name);
2084 return pjob_store(ev, msg_ctx, sharename, jobid, pjob);
2087 /****************************************************************************
2088 Get the name of a job. Only possible for owner.
2089 ****************************************************************************/
2091 bool print_job_get_name(TALLOC_CTX *mem_ctx, const char *sharename, uint32_t jobid, char **name)
2093 struct printjob *pjob;
2095 pjob = print_job_find(sharename, jobid);
2096 if (!pjob || pjob->pid != sys_getpid()) {
2097 return false;
2100 *name = talloc_strdup(mem_ctx, pjob->jobname);
2101 if (!*name) {
2102 return false;
2105 return true;
2109 /***************************************************************************
2110 Remove a jobid from the 'jobs added' list.
2111 ***************************************************************************/
2113 static bool remove_from_jobs_added(const char* sharename, uint32 jobid)
2115 struct tdb_print_db *pdb = get_print_db_byname(sharename);
2116 TDB_DATA data, key;
2117 size_t job_count, i;
2118 bool ret = False;
2119 bool gotlock = False;
2121 if (!pdb) {
2122 return False;
2125 ZERO_STRUCT(data);
2127 key = string_tdb_data("INFO/jobs_added");
2129 if (tdb_chainlock_with_timeout(pdb->tdb, key, 5) == -1)
2130 goto out;
2132 gotlock = True;
2134 data = tdb_fetch(pdb->tdb, key);
2136 if (data.dptr == NULL || data.dsize == 0 || (data.dsize % 4 != 0))
2137 goto out;
2139 job_count = data.dsize / 4;
2140 for (i = 0; i < job_count; i++) {
2141 uint32 ch_jobid;
2143 ch_jobid = IVAL(data.dptr, i*4);
2144 if (ch_jobid == jobid) {
2145 if (i < job_count -1 )
2146 memmove(data.dptr + (i*4), data.dptr + (i*4) + 4, (job_count - i - 1)*4 );
2147 data.dsize -= 4;
2148 if (tdb_store(pdb->tdb, key, data, TDB_REPLACE) == -1)
2149 goto out;
2150 break;
2154 ret = True;
2155 out:
2157 if (gotlock)
2158 tdb_chainunlock(pdb->tdb, key);
2159 SAFE_FREE(data.dptr);
2160 release_print_db(pdb);
2161 if (ret)
2162 DEBUG(10,("remove_from_jobs_added: removed jobid %u\n", (unsigned int)jobid ));
2163 else
2164 DEBUG(10,("remove_from_jobs_added: Failed to remove jobid %u\n", (unsigned int)jobid ));
2165 return ret;
2168 /****************************************************************************
2169 Delete a print job - don't update queue.
2170 ****************************************************************************/
2172 static bool print_job_delete1(struct tevent_context *ev,
2173 struct messaging_context *msg_ctx,
2174 int snum, uint32 jobid)
2176 const char* sharename = lp_const_servicename(snum);
2177 struct printjob *pjob = print_job_find(sharename, jobid);
2178 int result = 0;
2179 struct printif *current_printif = get_printer_fns( snum );
2181 if (!pjob)
2182 return False;
2185 * If already deleting just return.
2188 if (pjob->status == LPQ_DELETING)
2189 return True;
2191 /* Hrm - we need to be able to cope with deleting a job before it
2192 has reached the spooler. Just mark it as LPQ_DELETING and
2193 let the print_queue_update() code rmeove the record */
2196 if (pjob->sysjob == -1) {
2197 DEBUG(5, ("attempt to delete job %u not seen by lpr\n", (unsigned int)jobid));
2200 /* Set the tdb entry to be deleting. */
2202 pjob->status = LPQ_DELETING;
2203 pjob_store(ev, msg_ctx, sharename, jobid, pjob);
2205 if (pjob->spooled && pjob->sysjob != -1)
2207 result = (*(current_printif->job_delete))(
2208 lp_printername(snum),
2209 lp_lprmcommand(snum),
2210 pjob);
2212 /* Delete the tdb entry if the delete succeeded or the job hasn't
2213 been spooled. */
2215 if (result == 0) {
2216 struct tdb_print_db *pdb = get_print_db_byname(sharename);
2217 int njobs = 1;
2219 if (!pdb)
2220 return False;
2221 pjob_delete(ev, msg_ctx, sharename, jobid);
2222 /* Ensure we keep a rough count of the number of total jobs... */
2223 tdb_change_int32_atomic(pdb->tdb, "INFO/total_jobs", &njobs, -1);
2224 release_print_db(pdb);
2228 remove_from_jobs_added( sharename, jobid );
2230 return (result == 0);
2233 /****************************************************************************
2234 Return true if the current user owns the print job.
2235 ****************************************************************************/
2237 static bool is_owner(const struct auth_serversupplied_info *server_info,
2238 const char *servicename,
2239 uint32 jobid)
2241 struct printjob *pjob = print_job_find(servicename, jobid);
2243 if (!pjob || !server_info)
2244 return False;
2246 return strequal(pjob->user, server_info->sanitized_username);
2249 /****************************************************************************
2250 Delete a print job.
2251 ****************************************************************************/
2253 WERROR print_job_delete(const struct auth_serversupplied_info *server_info,
2254 struct messaging_context *msg_ctx,
2255 int snum, uint32_t jobid)
2257 const char* sharename = lp_const_servicename(snum);
2258 struct printjob *pjob;
2259 bool owner;
2260 char *fname;
2262 owner = is_owner(server_info, lp_const_servicename(snum), jobid);
2264 /* Check access against security descriptor or whether the user
2265 owns their job. */
2267 if (!owner &&
2268 !print_access_check(server_info, msg_ctx, snum,
2269 JOB_ACCESS_ADMINISTER)) {
2270 DEBUG(3, ("delete denied by security descriptor\n"));
2272 /* BEGIN_ADMIN_LOG */
2273 sys_adminlog( LOG_ERR,
2274 "Permission denied-- user not allowed to delete, \
2275 pause, or resume print job. User name: %s. Printer name: %s.",
2276 uidtoname(server_info->utok.uid),
2277 lp_printername(snum) );
2278 /* END_ADMIN_LOG */
2280 return WERR_ACCESS_DENIED;
2284 * get the spooled filename of the print job
2285 * if this works, then the file has not been spooled
2286 * to the underlying print system. Just delete the
2287 * spool file & return.
2290 fname = print_job_fname(sharename, jobid);
2291 if (fname != NULL) {
2292 /* remove the spool file */
2293 DEBUG(10, ("print_job_delete: "
2294 "Removing spool file [%s]\n", fname));
2295 if (unlink(fname) == -1) {
2296 return map_werror_from_unix(errno);
2300 if (!print_job_delete1(server_event_context(), msg_ctx, snum, jobid)) {
2301 return WERR_ACCESS_DENIED;
2304 /* force update the database and say the delete failed if the
2305 job still exists */
2307 print_queue_update(msg_ctx, snum, True);
2309 pjob = print_job_find(sharename, jobid);
2310 if (pjob && (pjob->status != LPQ_DELETING)) {
2311 return WERR_ACCESS_DENIED;
2314 return WERR_PRINTER_HAS_JOBS_QUEUED;
2317 /****************************************************************************
2318 Pause a job.
2319 ****************************************************************************/
2321 bool print_job_pause(const struct auth_serversupplied_info *server_info,
2322 struct messaging_context *msg_ctx,
2323 int snum, uint32 jobid, WERROR *errcode)
2325 const char* sharename = lp_const_servicename(snum);
2326 struct printjob *pjob;
2327 int ret = -1;
2328 struct printif *current_printif = get_printer_fns( snum );
2330 pjob = print_job_find(sharename, jobid);
2332 if (!pjob || !server_info) {
2333 DEBUG(10, ("print_job_pause: no pjob or user for jobid %u\n",
2334 (unsigned int)jobid ));
2335 return False;
2338 if (!pjob->spooled || pjob->sysjob == -1) {
2339 DEBUG(10, ("print_job_pause: not spooled or bad sysjob = %d for jobid %u\n",
2340 (int)pjob->sysjob, (unsigned int)jobid ));
2341 return False;
2344 if (!is_owner(server_info, lp_const_servicename(snum), jobid) &&
2345 !print_access_check(server_info, msg_ctx, snum,
2346 JOB_ACCESS_ADMINISTER)) {
2347 DEBUG(3, ("pause denied by security descriptor\n"));
2349 /* BEGIN_ADMIN_LOG */
2350 sys_adminlog( LOG_ERR,
2351 "Permission denied-- user not allowed to delete, \
2352 pause, or resume print job. User name: %s. Printer name: %s.",
2353 uidtoname(server_info->utok.uid),
2354 lp_printername(snum) );
2355 /* END_ADMIN_LOG */
2357 *errcode = WERR_ACCESS_DENIED;
2358 return False;
2361 /* need to pause the spooled entry */
2362 ret = (*(current_printif->job_pause))(snum, pjob);
2364 if (ret != 0) {
2365 *errcode = WERR_INVALID_PARAM;
2366 return False;
2369 /* force update the database */
2370 print_cache_flush(lp_const_servicename(snum));
2372 /* Send a printer notify message */
2374 notify_job_status(server_event_context(), msg_ctx, sharename, jobid,
2375 JOB_STATUS_PAUSED);
2377 /* how do we tell if this succeeded? */
2379 return True;
2382 /****************************************************************************
2383 Resume a job.
2384 ****************************************************************************/
2386 bool print_job_resume(const struct auth_serversupplied_info *server_info,
2387 struct messaging_context *msg_ctx,
2388 int snum, uint32 jobid, WERROR *errcode)
2390 const char *sharename = lp_const_servicename(snum);
2391 struct printjob *pjob;
2392 int ret;
2393 struct printif *current_printif = get_printer_fns( snum );
2395 pjob = print_job_find(sharename, jobid);
2397 if (!pjob || !server_info) {
2398 DEBUG(10, ("print_job_resume: no pjob or user for jobid %u\n",
2399 (unsigned int)jobid ));
2400 return False;
2403 if (!pjob->spooled || pjob->sysjob == -1) {
2404 DEBUG(10, ("print_job_resume: not spooled or bad sysjob = %d for jobid %u\n",
2405 (int)pjob->sysjob, (unsigned int)jobid ));
2406 return False;
2409 if (!is_owner(server_info, lp_const_servicename(snum), jobid) &&
2410 !print_access_check(server_info, msg_ctx, snum,
2411 JOB_ACCESS_ADMINISTER)) {
2412 DEBUG(3, ("resume denied by security descriptor\n"));
2413 *errcode = WERR_ACCESS_DENIED;
2415 /* BEGIN_ADMIN_LOG */
2416 sys_adminlog( LOG_ERR,
2417 "Permission denied-- user not allowed to delete, \
2418 pause, or resume print job. User name: %s. Printer name: %s.",
2419 uidtoname(server_info->utok.uid),
2420 lp_printername(snum) );
2421 /* END_ADMIN_LOG */
2422 return False;
2425 ret = (*(current_printif->job_resume))(snum, pjob);
2427 if (ret != 0) {
2428 *errcode = WERR_INVALID_PARAM;
2429 return False;
2432 /* force update the database */
2433 print_cache_flush(lp_const_servicename(snum));
2435 /* Send a printer notify message */
2437 notify_job_status(server_event_context(), msg_ctx, sharename, jobid,
2438 JOB_STATUS_QUEUED);
2440 return True;
2443 /****************************************************************************
2444 Write to a print file.
2445 ****************************************************************************/
2447 ssize_t print_job_write(struct tevent_context *ev,
2448 struct messaging_context *msg_ctx,
2449 int snum, uint32 jobid, const char *buf, size_t size)
2451 const char* sharename = lp_const_servicename(snum);
2452 ssize_t return_code;
2453 struct printjob *pjob;
2455 pjob = print_job_find(sharename, jobid);
2457 if (!pjob)
2458 return -1;
2459 /* don't allow another process to get this info - it is meaningless */
2460 if (pjob->pid != sys_getpid())
2461 return -1;
2463 /* if SMBD is spooling this can't be allowed */
2464 if (pjob->status == PJOB_SMBD_SPOOLING) {
2465 return -1;
2468 return_code = write_data(pjob->fd, buf, size);
2470 if (return_code>0) {
2471 pjob->size += size;
2472 pjob_store(ev, msg_ctx, sharename, jobid, pjob);
2474 return return_code;
2477 /****************************************************************************
2478 Get the queue status - do not update if db is out of date.
2479 ****************************************************************************/
2481 static int get_queue_status(const char* sharename, print_status_struct *status)
2483 fstring keystr;
2484 TDB_DATA data;
2485 struct tdb_print_db *pdb = get_print_db_byname(sharename);
2486 int len;
2488 if (status) {
2489 ZERO_STRUCTP(status);
2492 if (!pdb)
2493 return 0;
2495 if (status) {
2496 fstr_sprintf(keystr, "STATUS/%s", sharename);
2497 data = tdb_fetch(pdb->tdb, string_tdb_data(keystr));
2498 if (data.dptr) {
2499 if (data.dsize == sizeof(print_status_struct))
2500 /* this memcpy is ok since the status struct was
2501 not packed before storing it in the tdb */
2502 memcpy(status, data.dptr, sizeof(print_status_struct));
2503 SAFE_FREE(data.dptr);
2506 len = tdb_fetch_int32(pdb->tdb, "INFO/total_jobs");
2507 release_print_db(pdb);
2508 return (len == -1 ? 0 : len);
2511 /****************************************************************************
2512 Determine the number of jobs in a queue.
2513 ****************************************************************************/
2515 int print_queue_length(struct messaging_context *msg_ctx, int snum,
2516 print_status_struct *pstatus)
2518 const char* sharename = lp_const_servicename( snum );
2519 print_status_struct status;
2520 int len;
2522 ZERO_STRUCT( status );
2524 /* make sure the database is up to date */
2525 if (print_cache_expired(lp_const_servicename(snum), True))
2526 print_queue_update(msg_ctx, snum, False);
2528 /* also fetch the queue status */
2529 memset(&status, 0, sizeof(status));
2530 len = get_queue_status(sharename, &status);
2532 if (pstatus)
2533 *pstatus = status;
2535 return len;
2538 /***************************************************************************
2539 Allocate a jobid. Hold the lock for as short a time as possible.
2540 ***************************************************************************/
2542 static WERROR allocate_print_jobid(struct tdb_print_db *pdb, int snum,
2543 const char *sharename, uint32 *pjobid)
2545 int i;
2546 uint32 jobid;
2547 enum TDB_ERROR terr;
2548 int ret;
2550 *pjobid = (uint32)-1;
2552 for (i = 0; i < 3; i++) {
2553 /* Lock the database - only wait 20 seconds. */
2554 ret = tdb_lock_bystring_with_timeout(pdb->tdb,
2555 "INFO/nextjob", 20);
2556 if (ret == -1) {
2557 DEBUG(0, ("allocate_print_jobid: "
2558 "Failed to lock printing database %s\n",
2559 sharename));
2560 terr = tdb_error(pdb->tdb);
2561 return ntstatus_to_werror(map_nt_error_from_tdb(terr));
2564 if (!tdb_fetch_uint32(pdb->tdb, "INFO/nextjob", &jobid)) {
2565 terr = tdb_error(pdb->tdb);
2566 if (terr != TDB_ERR_NOEXIST) {
2567 DEBUG(0, ("allocate_print_jobid: "
2568 "Failed to fetch INFO/nextjob "
2569 "for print queue %s\n", sharename));
2570 tdb_unlock_bystring(pdb->tdb, "INFO/nextjob");
2571 return ntstatus_to_werror(map_nt_error_from_tdb(terr));
2573 DEBUG(10, ("allocate_print_jobid: "
2574 "No existing jobid in %s\n", sharename));
2575 jobid = 0;
2578 DEBUG(10, ("allocate_print_jobid: "
2579 "Read jobid %u from %s\n", jobid, sharename));
2581 jobid = NEXT_JOBID(jobid);
2583 ret = tdb_store_int32(pdb->tdb, "INFO/nextjob", jobid);
2584 if (ret == -1) {
2585 terr = tdb_error(pdb->tdb);
2586 DEBUG(3, ("allocate_print_jobid: "
2587 "Failed to store INFO/nextjob.\n"));
2588 tdb_unlock_bystring(pdb->tdb, "INFO/nextjob");
2589 return ntstatus_to_werror(map_nt_error_from_tdb(terr));
2592 /* We've finished with the INFO/nextjob lock. */
2593 tdb_unlock_bystring(pdb->tdb, "INFO/nextjob");
2595 if (!print_job_exists(sharename, jobid)) {
2596 break;
2598 DEBUG(10, ("allocate_print_jobid: "
2599 "Found jobid %u in %s\n", jobid, sharename));
2602 if (i > 2) {
2603 DEBUG(0, ("allocate_print_jobid: "
2604 "Failed to allocate a print job for queue %s\n",
2605 sharename));
2606 /* Probably full... */
2607 return WERR_NO_SPOOL_SPACE;
2610 /* Store a dummy placeholder. */
2612 uint32_t tmp;
2613 TDB_DATA dum;
2614 dum.dptr = NULL;
2615 dum.dsize = 0;
2616 if (tdb_store(pdb->tdb, print_key(jobid, &tmp), dum,
2617 TDB_INSERT) == -1) {
2618 DEBUG(3, ("allocate_print_jobid: "
2619 "jobid (%d) failed to store placeholder.\n",
2620 jobid ));
2621 terr = tdb_error(pdb->tdb);
2622 return ntstatus_to_werror(map_nt_error_from_tdb(terr));
2626 *pjobid = jobid;
2627 return WERR_OK;
2630 /***************************************************************************
2631 Append a jobid to the 'jobs added' list.
2632 ***************************************************************************/
2634 static bool add_to_jobs_added(struct tdb_print_db *pdb, uint32 jobid)
2636 TDB_DATA data;
2637 uint32 store_jobid;
2639 SIVAL(&store_jobid, 0, jobid);
2640 data.dptr = (uint8 *)&store_jobid;
2641 data.dsize = 4;
2643 DEBUG(10,("add_to_jobs_added: Added jobid %u\n", (unsigned int)jobid ));
2645 return (tdb_append(pdb->tdb, string_tdb_data("INFO/jobs_added"),
2646 data) == 0);
2650 /***************************************************************************
2651 Do all checks needed to determine if we can start a job.
2652 ***************************************************************************/
2654 static WERROR print_job_checks(const struct auth_serversupplied_info *server_info,
2655 struct messaging_context *msg_ctx,
2656 int snum, int *njobs)
2658 const char *sharename = lp_const_servicename(snum);
2659 uint64_t dspace, dsize;
2660 uint64_t minspace;
2661 int ret;
2663 if (!print_access_check(server_info, msg_ctx, snum,
2664 PRINTER_ACCESS_USE)) {
2665 DEBUG(3, ("print_job_checks: "
2666 "job start denied by security descriptor\n"));
2667 return WERR_ACCESS_DENIED;
2670 if (!print_time_access_check(server_info, msg_ctx, sharename)) {
2671 DEBUG(3, ("print_job_checks: "
2672 "job start denied by time check\n"));
2673 return WERR_ACCESS_DENIED;
2676 /* see if we have sufficient disk space */
2677 if (lp_minprintspace(snum)) {
2678 minspace = lp_minprintspace(snum);
2679 ret = sys_fsusage(lp_pathname(snum), &dspace, &dsize);
2680 if (ret == 0 && dspace < 2*minspace) {
2681 DEBUG(3, ("print_job_checks: "
2682 "disk space check failed.\n"));
2683 return WERR_NO_SPOOL_SPACE;
2687 /* for autoloaded printers, check that the printcap entry still exists */
2688 if (lp_autoloaded(snum) && !pcap_printername_ok(sharename)) {
2689 DEBUG(3, ("print_job_checks: printer name %s check failed.\n",
2690 sharename));
2691 return WERR_ACCESS_DENIED;
2694 /* Insure the maximum queue size is not violated */
2695 *njobs = print_queue_length(msg_ctx, snum, NULL);
2696 if (*njobs > lp_maxprintjobs(snum)) {
2697 DEBUG(3, ("print_job_checks: Queue %s number of jobs (%d) "
2698 "larger than max printjobs per queue (%d).\n",
2699 sharename, *njobs, lp_maxprintjobs(snum)));
2700 return WERR_NO_SPOOL_SPACE;
2703 return WERR_OK;
2706 /***************************************************************************
2707 Create a job file.
2708 ***************************************************************************/
2710 static WERROR print_job_spool_file(int snum, uint32_t jobid,
2711 const char *output_file,
2712 struct printjob *pjob)
2714 WERROR werr;
2715 SMB_STRUCT_STAT st;
2716 const char *path;
2717 int len;
2719 /* if this file is within the printer path, it means that smbd
2720 * is spooling it and will pass us control when it is finished.
2721 * Verify that the file name is ok, within path, and it is
2722 * already already there */
2723 if (output_file) {
2724 path = lp_pathname(snum);
2725 len = strlen(path);
2726 if (strncmp(output_file, path, len) == 0 &&
2727 (output_file[len - 1] == '/' || output_file[len] == '/')) {
2729 /* verify path is not too long */
2730 if (strlen(output_file) >= sizeof(pjob->filename)) {
2731 return WERR_INVALID_NAME;
2734 /* verify that the file exists */
2735 if (sys_stat(output_file, &st, false) != 0) {
2736 return WERR_INVALID_NAME;
2739 fstrcpy(pjob->filename, output_file);
2741 DEBUG(3, ("print_job_spool_file:"
2742 "External spooling activated"));
2744 /* we do not open the file until spooling is done */
2745 pjob->fd = -1;
2746 pjob->status = PJOB_SMBD_SPOOLING;
2748 return WERR_OK;
2752 slprintf(pjob->filename, sizeof(pjob->filename)-1,
2753 "%s/%s%.8u.XXXXXX", lp_pathname(snum),
2754 PRINT_SPOOL_PREFIX, (unsigned int)jobid);
2755 pjob->fd = mkstemp(pjob->filename);
2757 if (pjob->fd == -1) {
2758 werr = map_werror_from_unix(errno);
2759 if (W_ERROR_EQUAL(werr, WERR_ACCESS_DENIED)) {
2760 /* Common setup error, force a report. */
2761 DEBUG(0, ("print_job_spool_file: "
2762 "insufficient permissions to open spool "
2763 "file %s.\n", pjob->filename));
2764 } else {
2765 /* Normal case, report at level 3 and above. */
2766 DEBUG(3, ("print_job_spool_file: "
2767 "can't open spool file %s\n",
2768 pjob->filename));
2770 return werr;
2773 return WERR_OK;
2776 /***************************************************************************
2777 Start spooling a job - return the jobid.
2778 ***************************************************************************/
2780 WERROR print_job_start(const struct auth_serversupplied_info *server_info,
2781 struct messaging_context *msg_ctx,
2782 const char *clientmachine,
2783 int snum, const char *docname, const char *filename,
2784 struct spoolss_DeviceMode *devmode, uint32_t *_jobid)
2786 uint32_t jobid;
2787 char *path;
2788 struct printjob pjob;
2789 const char *sharename = lp_const_servicename(snum);
2790 struct tdb_print_db *pdb = get_print_db_byname(sharename);
2791 int njobs;
2792 WERROR werr;
2794 if (!pdb) {
2795 return WERR_INTERNAL_DB_CORRUPTION;
2798 path = lp_pathname(snum);
2800 werr = print_job_checks(server_info, msg_ctx, snum, &njobs);
2801 if (!W_ERROR_IS_OK(werr)) {
2802 release_print_db(pdb);
2803 return werr;
2806 DEBUG(10, ("print_job_start: "
2807 "Queue %s number of jobs (%d), max printjobs = %d\n",
2808 sharename, njobs, lp_maxprintjobs(snum)));
2810 werr = allocate_print_jobid(pdb, snum, sharename, &jobid);
2811 if (!W_ERROR_IS_OK(werr)) {
2812 goto fail;
2815 /* create the database entry */
2817 ZERO_STRUCT(pjob);
2819 pjob.pid = sys_getpid();
2820 pjob.sysjob = -1;
2821 pjob.fd = -1;
2822 pjob.starttime = time(NULL);
2823 pjob.status = LPQ_SPOOLING;
2824 pjob.size = 0;
2825 pjob.spooled = False;
2826 pjob.smbjob = True;
2827 pjob.devmode = devmode;
2829 fstrcpy(pjob.jobname, docname);
2831 fstrcpy(pjob.clientmachine, clientmachine);
2833 fstrcpy(pjob.user, lp_printjob_username(snum));
2834 standard_sub_advanced(sharename, server_info->sanitized_username,
2835 path, server_info->utok.gid,
2836 server_info->sanitized_username,
2837 server_info->info3->base.domain.string,
2838 pjob.user, sizeof(pjob.user)-1);
2839 /* ensure NULL termination */
2840 pjob.user[sizeof(pjob.user)-1] = '\0';
2842 fstrcpy(pjob.queuename, lp_const_servicename(snum));
2844 /* we have a job entry - now create the spool file */
2845 werr = print_job_spool_file(snum, jobid, filename, &pjob);
2846 if (!W_ERROR_IS_OK(werr)) {
2847 goto fail;
2850 pjob_store(server_event_context(), msg_ctx, sharename, jobid, &pjob);
2852 /* Update the 'jobs added' entry used by print_queue_status. */
2853 add_to_jobs_added(pdb, jobid);
2855 /* Ensure we keep a rough count of the number of total jobs... */
2856 tdb_change_int32_atomic(pdb->tdb, "INFO/total_jobs", &njobs, 1);
2858 release_print_db(pdb);
2860 *_jobid = jobid;
2861 return WERR_OK;
2863 fail:
2864 if (jobid != -1) {
2865 pjob_delete(server_event_context(), msg_ctx, sharename, jobid);
2868 release_print_db(pdb);
2870 DEBUG(3, ("print_job_start: returning fail. "
2871 "Error = %s\n", win_errstr(werr)));
2872 return werr;
2875 /****************************************************************************
2876 Update the number of pages spooled to jobid
2877 ****************************************************************************/
2879 void print_job_endpage(struct messaging_context *msg_ctx,
2880 int snum, uint32 jobid)
2882 const char* sharename = lp_const_servicename(snum);
2883 struct printjob *pjob;
2885 pjob = print_job_find(sharename, jobid);
2886 if (!pjob)
2887 return;
2888 /* don't allow another process to get this info - it is meaningless */
2889 if (pjob->pid != sys_getpid())
2890 return;
2892 pjob->page_count++;
2893 pjob_store(server_event_context(), msg_ctx, sharename, jobid, pjob);
2896 /****************************************************************************
2897 Print a file - called on closing the file. This spools the job.
2898 If normal close is false then we're tearing down the jobs - treat as an
2899 error.
2900 ****************************************************************************/
2902 NTSTATUS print_job_end(struct messaging_context *msg_ctx, int snum,
2903 uint32 jobid, enum file_close_type close_type)
2905 const char* sharename = lp_const_servicename(snum);
2906 struct printjob *pjob;
2907 int ret;
2908 SMB_STRUCT_STAT sbuf;
2909 struct printif *current_printif = get_printer_fns( snum );
2910 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
2912 pjob = print_job_find(sharename, jobid);
2914 if (!pjob) {
2915 return NT_STATUS_PRINT_CANCELLED;
2918 if (pjob->spooled || pjob->pid != sys_getpid()) {
2919 return NT_STATUS_ACCESS_DENIED;
2922 if (close_type == NORMAL_CLOSE || close_type == SHUTDOWN_CLOSE) {
2923 if (pjob->status == PJOB_SMBD_SPOOLING) {
2924 /* take over the file now, smbd is done */
2925 if (sys_stat(pjob->filename, &sbuf, false) != 0) {
2926 status = map_nt_error_from_unix(errno);
2927 DEBUG(3, ("print_job_end: "
2928 "stat file failed for jobid %d\n",
2929 jobid));
2930 goto fail;
2933 pjob->status = LPQ_SPOOLING;
2935 } else {
2937 if ((sys_fstat(pjob->fd, &sbuf, false) != 0)) {
2938 status = map_nt_error_from_unix(errno);
2939 close(pjob->fd);
2940 DEBUG(3, ("print_job_end: "
2941 "stat file failed for jobid %d\n",
2942 jobid));
2943 goto fail;
2946 close(pjob->fd);
2949 pjob->size = sbuf.st_ex_size;
2950 } else {
2953 * Not a normal close, something has gone wrong. Cleanup.
2955 if (pjob->fd != -1) {
2956 close(pjob->fd);
2958 goto fail;
2961 /* Technically, this is not quite right. If the printer has a separator
2962 * page turned on, the NT spooler prints the separator page even if the
2963 * print job is 0 bytes. 010215 JRR */
2964 if (pjob->size == 0 || pjob->status == LPQ_DELETING) {
2965 /* don't bother spooling empty files or something being deleted. */
2966 DEBUG(5,("print_job_end: canceling spool of %s (%s)\n",
2967 pjob->filename, pjob->size ? "deleted" : "zero length" ));
2968 unlink(pjob->filename);
2969 pjob_delete(server_event_context(), msg_ctx, sharename, jobid);
2970 return NT_STATUS_OK;
2973 ret = (*(current_printif->job_submit))(snum, pjob);
2975 if (ret) {
2976 status = NT_STATUS_PRINT_CANCELLED;
2977 goto fail;
2980 /* The print job has been successfully handed over to the back-end */
2982 pjob->spooled = True;
2983 pjob->status = LPQ_QUEUED;
2984 pjob_store(server_event_context(), msg_ctx, sharename, jobid, pjob);
2986 /* make sure the database is up to date */
2987 if (print_cache_expired(lp_const_servicename(snum), True))
2988 print_queue_update(msg_ctx, snum, False);
2990 return NT_STATUS_OK;
2992 fail:
2994 /* The print job was not successfully started. Cleanup */
2995 /* Still need to add proper error return propagation! 010122:JRR */
2996 pjob->fd = -1;
2997 unlink(pjob->filename);
2998 pjob_delete(server_event_context(), msg_ctx, sharename, jobid);
2999 return status;
3002 /****************************************************************************
3003 Get a snapshot of jobs in the system without traversing.
3004 ****************************************************************************/
3006 static bool get_stored_queue_info(struct messaging_context *msg_ctx,
3007 struct tdb_print_db *pdb, int snum,
3008 int *pcount, print_queue_struct **ppqueue)
3010 TDB_DATA data, cgdata, jcdata;
3011 print_queue_struct *queue = NULL;
3012 uint32 qcount = 0;
3013 uint32 extra_count = 0;
3014 uint32_t changed_count = 0;
3015 int total_count = 0;
3016 size_t len = 0;
3017 uint32 i;
3018 int max_reported_jobs = lp_max_reported_jobs(snum);
3019 bool ret = False;
3020 const char* sharename = lp_servicename(snum);
3022 /* make sure the database is up to date */
3023 if (print_cache_expired(lp_const_servicename(snum), True))
3024 print_queue_update(msg_ctx, snum, False);
3026 *pcount = 0;
3027 *ppqueue = NULL;
3029 ZERO_STRUCT(data);
3030 ZERO_STRUCT(cgdata);
3032 /* Get the stored queue data. */
3033 data = tdb_fetch(pdb->tdb, string_tdb_data("INFO/linear_queue_array"));
3035 if (data.dptr && data.dsize >= sizeof(qcount))
3036 len += tdb_unpack(data.dptr + len, data.dsize - len, "d", &qcount);
3038 /* Get the added jobs list. */
3039 cgdata = tdb_fetch(pdb->tdb, string_tdb_data("INFO/jobs_added"));
3040 if (cgdata.dptr != NULL && (cgdata.dsize % 4 == 0))
3041 extra_count = cgdata.dsize/4;
3043 /* Get the changed jobs list. */
3044 jcdata = tdb_fetch(pdb->tdb, string_tdb_data("INFO/jobs_changed"));
3045 if (jcdata.dptr != NULL && (jcdata.dsize % 4 == 0))
3046 changed_count = jcdata.dsize / 4;
3048 DEBUG(5,("get_stored_queue_info: qcount = %u, extra_count = %u\n", (unsigned int)qcount, (unsigned int)extra_count));
3050 /* Allocate the queue size. */
3051 if (qcount == 0 && extra_count == 0)
3052 goto out;
3054 if ((queue = SMB_MALLOC_ARRAY(print_queue_struct, qcount + extra_count)) == NULL)
3055 goto out;
3057 /* Retrieve the linearised queue data. */
3059 for( i = 0; i < qcount; i++) {
3060 uint32 qjob, qsize, qpage_count, qstatus, qpriority, qtime;
3061 len += tdb_unpack(data.dptr + len, data.dsize - len, "ddddddff",
3062 &qjob,
3063 &qsize,
3064 &qpage_count,
3065 &qstatus,
3066 &qpriority,
3067 &qtime,
3068 queue[i].fs_user,
3069 queue[i].fs_file);
3070 queue[i].job = qjob;
3071 queue[i].size = qsize;
3072 queue[i].page_count = qpage_count;
3073 queue[i].status = qstatus;
3074 queue[i].priority = qpriority;
3075 queue[i].time = qtime;
3078 total_count = qcount;
3080 /* Add new jobids to the queue. */
3081 for( i = 0; i < extra_count; i++) {
3082 uint32 jobid;
3083 struct printjob *pjob;
3085 jobid = IVAL(cgdata.dptr, i*4);
3086 DEBUG(5,("get_stored_queue_info: added job = %u\n", (unsigned int)jobid));
3087 pjob = print_job_find(lp_const_servicename(snum), jobid);
3088 if (!pjob) {
3089 DEBUG(5,("get_stored_queue_info: failed to find added job = %u\n", (unsigned int)jobid));
3090 remove_from_jobs_added(sharename, jobid);
3091 continue;
3094 queue[total_count].job = jobid;
3095 queue[total_count].size = pjob->size;
3096 queue[total_count].page_count = pjob->page_count;
3097 queue[total_count].status = pjob->status;
3098 queue[total_count].priority = 1;
3099 queue[total_count].time = pjob->starttime;
3100 fstrcpy(queue[total_count].fs_user, pjob->user);
3101 fstrcpy(queue[total_count].fs_file, pjob->jobname);
3102 total_count++;
3105 /* Update the changed jobids. */
3106 for (i = 0; i < changed_count; i++) {
3107 uint32_t jobid = IVAL(jcdata.dptr, i * 4);
3108 uint32_t j;
3109 bool found = false;
3111 for (j = 0; j < total_count; j++) {
3112 if (queue[j].job == jobid) {
3113 found = true;
3114 break;
3118 if (found) {
3119 struct printjob *pjob;
3121 DEBUG(5,("get_stored_queue_info: changed job: %u\n",
3122 (unsigned int) jobid));
3124 pjob = print_job_find(sharename, jobid);
3125 if (pjob == NULL) {
3126 DEBUG(5,("get_stored_queue_info: failed to find "
3127 "changed job = %u\n",
3128 (unsigned int) jobid));
3129 remove_from_jobs_changed(sharename, jobid);
3130 continue;
3133 queue[j].job = jobid;
3134 queue[j].size = pjob->size;
3135 queue[j].page_count = pjob->page_count;
3136 queue[j].status = pjob->status;
3137 queue[j].priority = 1;
3138 queue[j].time = pjob->starttime;
3139 fstrcpy(queue[j].fs_user, pjob->user);
3140 fstrcpy(queue[j].fs_file, pjob->jobname);
3142 DEBUG(5,("get_stored_queue_info: updated queue[%u], jobid: %u, jobname: %s\n",
3143 (unsigned int) j, (unsigned int) jobid, pjob->jobname));
3146 remove_from_jobs_changed(sharename, jobid);
3149 /* Sort the queue by submission time otherwise they are displayed
3150 in hash order. */
3152 TYPESAFE_QSORT(queue, total_count, printjob_comp);
3154 DEBUG(5,("get_stored_queue_info: total_count = %u\n", (unsigned int)total_count));
3156 if (max_reported_jobs && total_count > max_reported_jobs)
3157 total_count = max_reported_jobs;
3159 *ppqueue = queue;
3160 *pcount = total_count;
3162 ret = True;
3164 out:
3166 SAFE_FREE(data.dptr);
3167 SAFE_FREE(cgdata.dptr);
3168 return ret;
3171 /****************************************************************************
3172 Get a printer queue listing.
3173 set queue = NULL and status = NULL if you just want to update the cache
3174 ****************************************************************************/
3176 int print_queue_status(struct messaging_context *msg_ctx, int snum,
3177 print_queue_struct **ppqueue,
3178 print_status_struct *status)
3180 fstring keystr;
3181 TDB_DATA data, key;
3182 const char *sharename;
3183 struct tdb_print_db *pdb;
3184 int count = 0;
3186 /* make sure the database is up to date */
3188 if (print_cache_expired(lp_const_servicename(snum), True))
3189 print_queue_update(msg_ctx, snum, False);
3191 /* return if we are done */
3192 if ( !ppqueue || !status )
3193 return 0;
3195 *ppqueue = NULL;
3196 sharename = lp_const_servicename(snum);
3197 pdb = get_print_db_byname(sharename);
3199 if (!pdb)
3200 return 0;
3203 * Fetch the queue status. We must do this first, as there may
3204 * be no jobs in the queue.
3207 ZERO_STRUCTP(status);
3208 slprintf(keystr, sizeof(keystr)-1, "STATUS/%s", sharename);
3209 key = string_tdb_data(keystr);
3211 data = tdb_fetch(pdb->tdb, key);
3212 if (data.dptr) {
3213 if (data.dsize == sizeof(*status)) {
3214 /* this memcpy is ok since the status struct was
3215 not packed before storing it in the tdb */
3216 memcpy(status, data.dptr, sizeof(*status));
3218 SAFE_FREE(data.dptr);
3222 * Now, fetch the print queue information. We first count the number
3223 * of entries, and then only retrieve the queue if necessary.
3226 if (!get_stored_queue_info(msg_ctx, pdb, snum, &count, ppqueue)) {
3227 release_print_db(pdb);
3228 return 0;
3231 release_print_db(pdb);
3232 return count;
3235 /****************************************************************************
3236 Pause a queue.
3237 ****************************************************************************/
3239 WERROR print_queue_pause(const struct auth_serversupplied_info *server_info,
3240 struct messaging_context *msg_ctx, int snum)
3242 int ret;
3243 struct printif *current_printif = get_printer_fns( snum );
3245 if (!print_access_check(server_info, msg_ctx, snum,
3246 PRINTER_ACCESS_ADMINISTER)) {
3247 return WERR_ACCESS_DENIED;
3251 become_root();
3253 ret = (*(current_printif->queue_pause))(snum);
3255 unbecome_root();
3257 if (ret != 0) {
3258 return WERR_INVALID_PARAM;
3261 /* force update the database */
3262 print_cache_flush(lp_const_servicename(snum));
3264 /* Send a printer notify message */
3266 notify_printer_status(server_event_context(), msg_ctx, snum,
3267 PRINTER_STATUS_PAUSED);
3269 return WERR_OK;
3272 /****************************************************************************
3273 Resume a queue.
3274 ****************************************************************************/
3276 WERROR print_queue_resume(const struct auth_serversupplied_info *server_info,
3277 struct messaging_context *msg_ctx, int snum)
3279 int ret;
3280 struct printif *current_printif = get_printer_fns( snum );
3282 if (!print_access_check(server_info, msg_ctx, snum,
3283 PRINTER_ACCESS_ADMINISTER)) {
3284 return WERR_ACCESS_DENIED;
3287 become_root();
3289 ret = (*(current_printif->queue_resume))(snum);
3291 unbecome_root();
3293 if (ret != 0) {
3294 return WERR_INVALID_PARAM;
3297 /* make sure the database is up to date */
3298 if (print_cache_expired(lp_const_servicename(snum), True))
3299 print_queue_update(msg_ctx, snum, True);
3301 /* Send a printer notify message */
3303 notify_printer_status(server_event_context(), msg_ctx, snum,
3304 PRINTER_STATUS_OK);
3306 return WERR_OK;
3309 /****************************************************************************
3310 Purge a queue - implemented by deleting all jobs that we can delete.
3311 ****************************************************************************/
3313 WERROR print_queue_purge(const struct auth_serversupplied_info *server_info,
3314 struct messaging_context *msg_ctx, int snum)
3316 print_queue_struct *queue;
3317 print_status_struct status;
3318 int njobs, i;
3319 bool can_job_admin;
3321 /* Force and update so the count is accurate (i.e. not a cached count) */
3322 print_queue_update(msg_ctx, snum, True);
3324 can_job_admin = print_access_check(server_info,
3325 msg_ctx,
3326 snum,
3327 JOB_ACCESS_ADMINISTER);
3328 njobs = print_queue_status(msg_ctx, snum, &queue, &status);
3330 if ( can_job_admin )
3331 become_root();
3333 for (i=0;i<njobs;i++) {
3334 bool owner = is_owner(server_info, lp_const_servicename(snum),
3335 queue[i].job);
3337 if (owner || can_job_admin) {
3338 print_job_delete1(server_event_context(), msg_ctx,
3339 snum, queue[i].job);
3343 if ( can_job_admin )
3344 unbecome_root();
3346 /* update the cache */
3347 print_queue_update(msg_ctx, snum, True);
3349 SAFE_FREE(queue);
3351 return WERR_OK;