s3-rpc_client: move rpc_cli_transport structs and protos to rpc_transport.h
[Samba/gbeck.git] / source3 / printing / printing.c
blob785e893d3a57d9aedb880971e0622711d23a5b22
1 /*
2 Unix SMB/Netbios implementation.
3 Version 3.0
4 printing backend routines
5 Copyright (C) Andrew Tridgell 1992-2000
6 Copyright (C) Jeremy Allison 2002
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include "includes.h"
23 #include "system/syslog.h"
24 #include "system/filesys.h"
25 #include "printing.h"
26 #include "../librpc/gen_ndr/ndr_spoolss.h"
27 #include "nt_printing.h"
28 #include "../librpc/gen_ndr/netlogon.h"
29 #include "printing/notify.h"
30 #include "printing/pcap.h"
31 #include "serverid.h"
32 #include "smbd/smbd.h"
33 #include "auth.h"
34 #include "messages.h"
36 extern struct current_user current_user;
37 extern userdom_struct current_user_info;
39 /* Current printer interface */
40 static bool remove_from_jobs_added(const char* sharename, uint32 jobid);
43 the printing backend revolves around a tdb database that stores the
44 SMB view of the print queue
46 The key for this database is a jobid - a internally generated number that
47 uniquely identifies a print job
49 reading the print queue involves two steps:
50 - possibly running lpq and updating the internal database from that
51 - reading entries from the database
53 jobids are assigned when a job starts spooling.
56 static TDB_CONTEXT *rap_tdb;
57 static uint16 next_rap_jobid;
58 struct rap_jobid_key {
59 fstring sharename;
60 uint32 jobid;
63 /***************************************************************************
64 Nightmare. LANMAN jobid's are 16 bit numbers..... We must map them to 32
65 bit RPC jobids.... JRA.
66 ***************************************************************************/
68 uint16 pjobid_to_rap(const char* sharename, uint32 jobid)
70 uint16 rap_jobid;
71 TDB_DATA data, key;
72 struct rap_jobid_key jinfo;
73 uint8 buf[2];
75 DEBUG(10,("pjobid_to_rap: called.\n"));
77 if (!rap_tdb) {
78 /* Create the in-memory tdb. */
79 rap_tdb = tdb_open_log(NULL, 0, TDB_INTERNAL, (O_RDWR|O_CREAT), 0644);
80 if (!rap_tdb)
81 return 0;
84 ZERO_STRUCT( jinfo );
85 fstrcpy( jinfo.sharename, sharename );
86 jinfo.jobid = jobid;
87 key.dptr = (uint8 *)&jinfo;
88 key.dsize = sizeof(jinfo);
90 data = tdb_fetch(rap_tdb, key);
91 if (data.dptr && data.dsize == sizeof(uint16)) {
92 rap_jobid = SVAL(data.dptr, 0);
93 SAFE_FREE(data.dptr);
94 DEBUG(10,("pjobid_to_rap: jobid %u maps to RAP jobid %u\n",
95 (unsigned int)jobid, (unsigned int)rap_jobid));
96 return rap_jobid;
98 SAFE_FREE(data.dptr);
99 /* Not found - create and store mapping. */
100 rap_jobid = ++next_rap_jobid;
101 if (rap_jobid == 0)
102 rap_jobid = ++next_rap_jobid;
103 SSVAL(buf,0,rap_jobid);
104 data.dptr = buf;
105 data.dsize = sizeof(rap_jobid);
106 tdb_store(rap_tdb, key, data, TDB_REPLACE);
107 tdb_store(rap_tdb, data, key, TDB_REPLACE);
109 DEBUG(10,("pjobid_to_rap: created jobid %u maps to RAP jobid %u\n",
110 (unsigned int)jobid, (unsigned int)rap_jobid));
111 return rap_jobid;
114 bool rap_to_pjobid(uint16 rap_jobid, fstring sharename, uint32 *pjobid)
116 TDB_DATA data, key;
117 uint8 buf[2];
119 DEBUG(10,("rap_to_pjobid called.\n"));
121 if (!rap_tdb)
122 return False;
124 SSVAL(buf,0,rap_jobid);
125 key.dptr = buf;
126 key.dsize = sizeof(rap_jobid);
127 data = tdb_fetch(rap_tdb, key);
128 if ( data.dptr && data.dsize == sizeof(struct rap_jobid_key) )
130 struct rap_jobid_key *jinfo = (struct rap_jobid_key*)data.dptr;
131 if (sharename != NULL) {
132 fstrcpy( sharename, jinfo->sharename );
134 *pjobid = jinfo->jobid;
135 DEBUG(10,("rap_to_pjobid: jobid %u maps to RAP jobid %u\n",
136 (unsigned int)*pjobid, (unsigned int)rap_jobid));
137 SAFE_FREE(data.dptr);
138 return True;
141 DEBUG(10,("rap_to_pjobid: Failed to lookup RAP jobid %u\n",
142 (unsigned int)rap_jobid));
143 SAFE_FREE(data.dptr);
144 return False;
147 void rap_jobid_delete(const char* sharename, uint32 jobid)
149 TDB_DATA key, data;
150 uint16 rap_jobid;
151 struct rap_jobid_key jinfo;
152 uint8 buf[2];
154 DEBUG(10,("rap_jobid_delete: called.\n"));
156 if (!rap_tdb)
157 return;
159 ZERO_STRUCT( jinfo );
160 fstrcpy( jinfo.sharename, sharename );
161 jinfo.jobid = jobid;
162 key.dptr = (uint8 *)&jinfo;
163 key.dsize = sizeof(jinfo);
165 data = tdb_fetch(rap_tdb, key);
166 if (!data.dptr || (data.dsize != sizeof(uint16))) {
167 DEBUG(10,("rap_jobid_delete: cannot find jobid %u\n",
168 (unsigned int)jobid ));
169 SAFE_FREE(data.dptr);
170 return;
173 DEBUG(10,("rap_jobid_delete: deleting jobid %u\n",
174 (unsigned int)jobid ));
176 rap_jobid = SVAL(data.dptr, 0);
177 SAFE_FREE(data.dptr);
178 SSVAL(buf,0,rap_jobid);
179 data.dptr = buf;
180 data.dsize = sizeof(rap_jobid);
181 tdb_delete(rap_tdb, key);
182 tdb_delete(rap_tdb, data);
185 static int get_queue_status(const char* sharename, print_status_struct *);
187 /****************************************************************************
188 Initialise the printing backend. Called once at startup before the fork().
189 ****************************************************************************/
191 bool print_backend_init(struct messaging_context *msg_ctx)
193 const char *sversion = "INFO/version";
194 int services = lp_numservices();
195 int snum;
197 unlink(cache_path("printing.tdb"));
198 mkdir(cache_path("printing"),0755);
200 /* handle a Samba upgrade */
202 for (snum = 0; snum < services; snum++) {
203 struct tdb_print_db *pdb;
204 if (!lp_print_ok(snum))
205 continue;
207 pdb = get_print_db_byname(lp_const_servicename(snum));
208 if (!pdb)
209 continue;
210 if (tdb_lock_bystring(pdb->tdb, sversion) == -1) {
211 DEBUG(0,("print_backend_init: Failed to open printer %s database\n", lp_const_servicename(snum) ));
212 release_print_db(pdb);
213 return False;
215 if (tdb_fetch_int32(pdb->tdb, sversion) != PRINT_DATABASE_VERSION) {
216 tdb_wipe_all(pdb->tdb);
217 tdb_store_int32(pdb->tdb, sversion, PRINT_DATABASE_VERSION);
219 tdb_unlock_bystring(pdb->tdb, sversion);
220 release_print_db(pdb);
223 close_all_print_db(); /* Don't leave any open. */
225 /* do NT print initialization... */
226 return nt_printing_init(msg_ctx);
229 /****************************************************************************
230 Shut down printing backend. Called once at shutdown to close the tdb.
231 ****************************************************************************/
233 void printing_end(void)
235 close_all_print_db(); /* Don't leave any open. */
238 /****************************************************************************
239 Retrieve the set of printing functions for a given service. This allows
240 us to set the printer function table based on the value of the 'printing'
241 service parameter.
243 Use the generic interface as the default and only use cups interface only
244 when asked for (and only when supported)
245 ****************************************************************************/
247 static struct printif *get_printer_fns_from_type( enum printing_types type )
249 struct printif *printer_fns = &generic_printif;
251 #ifdef HAVE_CUPS
252 if ( type == PRINT_CUPS ) {
253 printer_fns = &cups_printif;
255 #endif /* HAVE_CUPS */
257 #ifdef HAVE_IPRINT
258 if ( type == PRINT_IPRINT ) {
259 printer_fns = &iprint_printif;
261 #endif /* HAVE_IPRINT */
263 printer_fns->type = type;
265 return printer_fns;
268 static struct printif *get_printer_fns( int snum )
270 return get_printer_fns_from_type( (enum printing_types)lp_printing(snum) );
274 /****************************************************************************
275 Useful function to generate a tdb key.
276 ****************************************************************************/
278 static TDB_DATA print_key(uint32 jobid, uint32 *tmp)
280 TDB_DATA ret;
282 SIVAL(tmp, 0, jobid);
283 ret.dptr = (uint8 *)tmp;
284 ret.dsize = sizeof(*tmp);
285 return ret;
288 /****************************************************************************
289 Pack the devicemode to store it in a tdb.
290 ****************************************************************************/
291 static int pack_devicemode(struct spoolss_DeviceMode *devmode, uint8 *buf, int buflen)
293 enum ndr_err_code ndr_err;
294 DATA_BLOB blob;
295 int len = 0;
297 if (devmode) {
298 ndr_err = ndr_push_struct_blob(&blob, talloc_tos(),
299 devmode,
300 (ndr_push_flags_fn_t)
301 ndr_push_spoolss_DeviceMode);
302 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
303 DEBUG(10, ("pack_devicemode: "
304 "error encoding spoolss_DeviceMode\n"));
305 goto done;
307 } else {
308 ZERO_STRUCT(blob);
311 len = tdb_pack(buf, buflen, "B", blob.length, blob.data);
313 if (devmode) {
314 DEBUG(8, ("Packed devicemode [%s]\n", devmode->formname));
317 done:
318 return len;
321 /****************************************************************************
322 Unpack the devicemode to store it in a tdb.
323 ****************************************************************************/
324 static int unpack_devicemode(TALLOC_CTX *mem_ctx,
325 const uint8 *buf, int buflen,
326 struct spoolss_DeviceMode **devmode)
328 struct spoolss_DeviceMode *dm;
329 enum ndr_err_code ndr_err;
330 char *data = NULL;
331 int data_len = 0;
332 DATA_BLOB blob;
333 int len = 0;
335 *devmode = NULL;
337 len = tdb_unpack(buf, buflen, "B", &data_len, &data);
338 if (!data) {
339 return len;
342 dm = talloc_zero(mem_ctx, struct spoolss_DeviceMode);
343 if (!dm) {
344 goto done;
347 blob = data_blob_const(data, data_len);
349 ndr_err = ndr_pull_struct_blob(&blob, dm, dm,
350 (ndr_pull_flags_fn_t)ndr_pull_spoolss_DeviceMode);
351 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
352 DEBUG(10, ("unpack_devicemode: "
353 "error parsing spoolss_DeviceMode\n"));
354 goto done;
357 DEBUG(8, ("Unpacked devicemode [%s](%s)\n",
358 dm->devicename, dm->formname));
359 if (dm->driverextra_data.data) {
360 DEBUG(8, ("with a private section of %d bytes\n",
361 dm->__driverextra_length));
364 *devmode = dm;
366 done:
367 SAFE_FREE(data);
368 return len;
371 /***********************************************************************
372 unpack a pjob from a tdb buffer
373 ***********************************************************************/
375 static int unpack_pjob( uint8 *buf, int buflen, struct printjob *pjob )
377 int len = 0;
378 int used;
379 uint32 pjpid, pjsysjob, pjfd, pjstarttime, pjstatus;
380 uint32 pjsize, pjpage_count, pjspooled, pjsmbjob;
382 if ( !buf || !pjob )
383 return -1;
385 len += tdb_unpack(buf+len, buflen-len, "dddddddddfffff",
386 &pjpid,
387 &pjsysjob,
388 &pjfd,
389 &pjstarttime,
390 &pjstatus,
391 &pjsize,
392 &pjpage_count,
393 &pjspooled,
394 &pjsmbjob,
395 pjob->filename,
396 pjob->jobname,
397 pjob->user,
398 pjob->clientmachine,
399 pjob->queuename);
401 if ( len == -1 )
402 return -1;
404 used = unpack_devicemode(NULL, buf+len, buflen-len, &pjob->devmode);
405 if (used == -1) {
406 return -1;
409 len += used;
411 pjob->pid = pjpid;
412 pjob->sysjob = pjsysjob;
413 pjob->fd = pjfd;
414 pjob->starttime = pjstarttime;
415 pjob->status = pjstatus;
416 pjob->size = pjsize;
417 pjob->page_count = pjpage_count;
418 pjob->spooled = pjspooled;
419 pjob->smbjob = pjsmbjob;
421 return len;
425 /****************************************************************************
426 Useful function to find a print job in the database.
427 ****************************************************************************/
429 static struct printjob *print_job_find(const char *sharename, uint32 jobid)
431 static struct printjob pjob;
432 uint32_t tmp;
433 TDB_DATA ret;
434 struct tdb_print_db *pdb = get_print_db_byname(sharename);
436 DEBUG(10,("print_job_find: looking up job %u for share %s\n",
437 (unsigned int)jobid, sharename ));
439 if (!pdb) {
440 return NULL;
443 ret = tdb_fetch(pdb->tdb, print_key(jobid, &tmp));
444 release_print_db(pdb);
446 if (!ret.dptr) {
447 DEBUG(10,("print_job_find: failed to find jobid %u.\n", (unsigned int)jobid ));
448 return NULL;
451 talloc_free(pjob.devmode);
453 ZERO_STRUCT( pjob );
455 if ( unpack_pjob( ret.dptr, ret.dsize, &pjob ) == -1 ) {
456 DEBUG(10,("print_job_find: failed to unpack jobid %u.\n", (unsigned int)jobid ));
457 SAFE_FREE(ret.dptr);
458 return NULL;
461 SAFE_FREE(ret.dptr);
463 DEBUG(10,("print_job_find: returning system job %d for jobid %u.\n",
464 (int)pjob.sysjob, (unsigned int)jobid ));
466 return &pjob;
469 /* Convert a unix jobid to a smb jobid */
471 struct unixjob_traverse_state {
472 int sysjob;
473 uint32 sysjob_to_jobid_value;
476 static int unixjob_traverse_fn(TDB_CONTEXT *the_tdb, TDB_DATA key,
477 TDB_DATA data, void *private_data)
479 struct printjob *pjob;
480 struct unixjob_traverse_state *state =
481 (struct unixjob_traverse_state *)private_data;
483 if (!data.dptr || data.dsize == 0)
484 return 0;
486 pjob = (struct printjob *)data.dptr;
487 if (key.dsize != sizeof(uint32))
488 return 0;
490 if (state->sysjob == pjob->sysjob) {
491 uint32 jobid = IVAL(key.dptr,0);
493 state->sysjob_to_jobid_value = jobid;
494 return 1;
497 return 0;
500 /****************************************************************************
501 This is a *horribly expensive call as we have to iterate through all the
502 current printer tdb's. Don't do this often ! JRA.
503 ****************************************************************************/
505 uint32 sysjob_to_jobid(int unix_jobid)
507 int services = lp_numservices();
508 int snum;
509 struct unixjob_traverse_state state;
511 state.sysjob = unix_jobid;
512 state.sysjob_to_jobid_value = (uint32)-1;
514 for (snum = 0; snum < services; snum++) {
515 struct tdb_print_db *pdb;
516 if (!lp_print_ok(snum))
517 continue;
518 pdb = get_print_db_byname(lp_const_servicename(snum));
519 if (!pdb) {
520 continue;
522 tdb_traverse(pdb->tdb, unixjob_traverse_fn, &state);
523 release_print_db(pdb);
524 if (state.sysjob_to_jobid_value != (uint32)-1)
525 return state.sysjob_to_jobid_value;
527 return (uint32)-1;
530 /****************************************************************************
531 Send notifications based on what has changed after a pjob_store.
532 ****************************************************************************/
534 static const struct {
535 uint32_t lpq_status;
536 uint32_t spoolss_status;
537 } lpq_to_spoolss_status_map[] = {
538 { LPQ_QUEUED, JOB_STATUS_QUEUED },
539 { LPQ_PAUSED, JOB_STATUS_PAUSED },
540 { LPQ_SPOOLING, JOB_STATUS_SPOOLING },
541 { LPQ_PRINTING, JOB_STATUS_PRINTING },
542 { LPQ_DELETING, JOB_STATUS_DELETING },
543 { LPQ_OFFLINE, JOB_STATUS_OFFLINE },
544 { LPQ_PAPEROUT, JOB_STATUS_PAPEROUT },
545 { LPQ_PRINTED, JOB_STATUS_PRINTED },
546 { LPQ_DELETED, JOB_STATUS_DELETED },
547 { LPQ_BLOCKED, JOB_STATUS_BLOCKED_DEVQ },
548 { LPQ_USER_INTERVENTION, JOB_STATUS_USER_INTERVENTION },
549 { (uint32_t)-1, 0 }
552 /* Convert a lpq status value stored in printing.tdb into the
553 appropriate win32 API constant. */
555 static uint32 map_to_spoolss_status(uint32 lpq_status)
557 int i = 0;
559 while (lpq_to_spoolss_status_map[i].lpq_status != -1) {
560 if (lpq_to_spoolss_status_map[i].lpq_status == lpq_status)
561 return lpq_to_spoolss_status_map[i].spoolss_status;
562 i++;
565 return 0;
568 /***************************************************************************
569 Append a jobid to the 'jobs changed' list.
570 ***************************************************************************/
572 static bool add_to_jobs_changed(struct tdb_print_db *pdb, uint32_t jobid)
574 TDB_DATA data;
575 uint32_t store_jobid;
577 SIVAL(&store_jobid, 0, jobid);
578 data.dptr = (uint8 *) &store_jobid;
579 data.dsize = 4;
581 DEBUG(10,("add_to_jobs_added: Added jobid %u\n", (unsigned int)jobid ));
583 return (tdb_append(pdb->tdb, string_tdb_data("INFO/jobs_changed"),
584 data) == 0);
587 /***************************************************************************
588 Remove a jobid from the 'jobs changed' list.
589 ***************************************************************************/
591 static bool remove_from_jobs_changed(const char* sharename, uint32_t jobid)
593 struct tdb_print_db *pdb = get_print_db_byname(sharename);
594 TDB_DATA data, key;
595 size_t job_count, i;
596 bool ret = False;
597 bool gotlock = False;
599 if (!pdb) {
600 return False;
603 ZERO_STRUCT(data);
605 key = string_tdb_data("INFO/jobs_changed");
607 if (tdb_chainlock_with_timeout(pdb->tdb, key, 5) == -1)
608 goto out;
610 gotlock = True;
612 data = tdb_fetch(pdb->tdb, key);
614 if (data.dptr == NULL || data.dsize == 0 || (data.dsize % 4 != 0))
615 goto out;
617 job_count = data.dsize / 4;
618 for (i = 0; i < job_count; i++) {
619 uint32 ch_jobid;
621 ch_jobid = IVAL(data.dptr, i*4);
622 if (ch_jobid == jobid) {
623 if (i < job_count -1 )
624 memmove(data.dptr + (i*4), data.dptr + (i*4) + 4, (job_count - i - 1)*4 );
625 data.dsize -= 4;
626 if (tdb_store(pdb->tdb, key, data, TDB_REPLACE) == -1)
627 goto out;
628 break;
632 ret = True;
633 out:
635 if (gotlock)
636 tdb_chainunlock(pdb->tdb, key);
637 SAFE_FREE(data.dptr);
638 release_print_db(pdb);
639 if (ret)
640 DEBUG(10,("remove_from_jobs_changed: removed jobid %u\n", (unsigned int)jobid ));
641 else
642 DEBUG(10,("remove_from_jobs_changed: Failed to remove jobid %u\n", (unsigned int)jobid ));
643 return ret;
646 static void pjob_store_notify(struct tevent_context *ev,
647 struct messaging_context *msg_ctx,
648 const char* sharename, uint32 jobid,
649 struct printjob *old_data,
650 struct printjob *new_data,
651 bool *pchanged)
653 bool new_job = false;
654 bool changed = false;
656 if (old_data == NULL) {
657 new_job = true;
660 /* ACHTUNG! Due to a bug in Samba's spoolss parsing of the
661 NOTIFY_INFO_DATA buffer, we *have* to send the job submission
662 time first or else we'll end up with potential alignment
663 errors. I don't think the systemtime should be spooled as
664 a string, but this gets us around that error.
665 --jerry (i'll feel dirty for this) */
667 if (new_job) {
668 notify_job_submitted(ev, msg_ctx,
669 sharename, jobid, new_data->starttime);
670 notify_job_username(ev, msg_ctx,
671 sharename, jobid, new_data->user);
672 notify_job_name(ev, msg_ctx,
673 sharename, jobid, new_data->jobname);
674 notify_job_status(ev, msg_ctx,
675 sharename, jobid, map_to_spoolss_status(new_data->status));
676 notify_job_total_bytes(ev, msg_ctx,
677 sharename, jobid, new_data->size);
678 notify_job_total_pages(ev, msg_ctx,
679 sharename, jobid, new_data->page_count);
680 } else {
681 if (!strequal(old_data->jobname, new_data->jobname)) {
682 notify_job_name(ev, msg_ctx, sharename,
683 jobid, new_data->jobname);
684 changed = true;
687 if (old_data->status != new_data->status) {
688 notify_job_status(ev, msg_ctx,
689 sharename, jobid,
690 map_to_spoolss_status(new_data->status));
693 if (old_data->size != new_data->size) {
694 notify_job_total_bytes(ev, msg_ctx,
695 sharename, jobid, new_data->size);
698 if (old_data->page_count != new_data->page_count) {
699 notify_job_total_pages(ev, msg_ctx,
700 sharename, jobid,
701 new_data->page_count);
705 *pchanged = changed;
708 /****************************************************************************
709 Store a job structure back to the database.
710 ****************************************************************************/
712 static bool pjob_store(struct tevent_context *ev,
713 struct messaging_context *msg_ctx,
714 const char* sharename, uint32 jobid,
715 struct printjob *pjob)
717 uint32_t tmp;
718 TDB_DATA old_data, new_data;
719 bool ret = False;
720 struct tdb_print_db *pdb = get_print_db_byname(sharename);
721 uint8 *buf = NULL;
722 int len, newlen, buflen;
725 if (!pdb)
726 return False;
728 /* Get old data */
730 old_data = tdb_fetch(pdb->tdb, print_key(jobid, &tmp));
732 /* Doh! Now we have to pack/unpack data since the NT_DEVICEMODE was added */
734 newlen = 0;
736 do {
737 len = 0;
738 buflen = newlen;
739 len += tdb_pack(buf+len, buflen-len, "dddddddddfffff",
740 (uint32)pjob->pid,
741 (uint32)pjob->sysjob,
742 (uint32)pjob->fd,
743 (uint32)pjob->starttime,
744 (uint32)pjob->status,
745 (uint32)pjob->size,
746 (uint32)pjob->page_count,
747 (uint32)pjob->spooled,
748 (uint32)pjob->smbjob,
749 pjob->filename,
750 pjob->jobname,
751 pjob->user,
752 pjob->clientmachine,
753 pjob->queuename);
755 len += pack_devicemode(pjob->devmode, buf+len, buflen-len);
757 if (buflen != len) {
758 buf = (uint8 *)SMB_REALLOC(buf, len);
759 if (!buf) {
760 DEBUG(0,("pjob_store: failed to enlarge buffer!\n"));
761 goto done;
763 newlen = len;
765 } while ( buflen != len );
768 /* Store new data */
770 new_data.dptr = buf;
771 new_data.dsize = len;
772 ret = (tdb_store(pdb->tdb, print_key(jobid, &tmp), new_data,
773 TDB_REPLACE) == 0);
775 /* Send notify updates for what has changed */
777 if ( ret ) {
778 bool changed = false;
779 struct printjob old_pjob;
781 if ( old_data.dsize )
783 if ( unpack_pjob( old_data.dptr, old_data.dsize, &old_pjob ) != -1 )
785 pjob_store_notify(server_event_context(),
786 msg_ctx,
787 sharename, jobid, &old_pjob,
788 pjob,
789 &changed);
790 talloc_free(old_pjob.devmode);
792 if (changed) {
793 add_to_jobs_changed(pdb, jobid);
798 else {
799 /* new job */
800 pjob_store_notify(server_event_context(), msg_ctx,
801 sharename, jobid, NULL, pjob,
802 &changed);
806 release_print_db(pdb);
807 done:
808 SAFE_FREE( old_data.dptr );
809 SAFE_FREE( buf );
811 return ret;
814 /****************************************************************************
815 Remove a job structure from the database.
816 ****************************************************************************/
818 static void pjob_delete(struct tevent_context *ev,
819 struct messaging_context *msg_ctx,
820 const char* sharename, uint32 jobid)
822 uint32_t tmp;
823 struct printjob *pjob;
824 uint32 job_status = 0;
825 struct tdb_print_db *pdb;
827 pdb = get_print_db_byname( sharename );
829 if (!pdb)
830 return;
832 pjob = print_job_find( sharename, jobid );
834 if (!pjob) {
835 DEBUG(5, ("pjob_delete: we were asked to delete nonexistent job %u\n",
836 (unsigned int)jobid));
837 release_print_db(pdb);
838 return;
841 /* We must cycle through JOB_STATUS_DELETING and
842 JOB_STATUS_DELETED for the port monitor to delete the job
843 properly. */
845 job_status = JOB_STATUS_DELETING|JOB_STATUS_DELETED;
846 notify_job_status(ev, msg_ctx, sharename, jobid, job_status);
848 /* Remove from printing.tdb */
850 tdb_delete(pdb->tdb, print_key(jobid, &tmp));
851 remove_from_jobs_added(sharename, jobid);
852 release_print_db( pdb );
853 rap_jobid_delete(sharename, jobid);
856 /****************************************************************************
857 List a unix job in the print database.
858 ****************************************************************************/
860 static void print_unix_job(struct tevent_context *ev,
861 struct messaging_context *msg_ctx,
862 const char *sharename, print_queue_struct *q,
863 uint32 jobid)
865 struct printjob pj, *old_pj;
867 if (jobid == (uint32)-1)
868 jobid = q->job + UNIX_JOB_START;
870 /* Preserve the timestamp on an existing unix print job */
872 old_pj = print_job_find(sharename, jobid);
874 ZERO_STRUCT(pj);
876 pj.pid = (pid_t)-1;
877 pj.sysjob = q->job;
878 pj.fd = -1;
879 pj.starttime = old_pj ? old_pj->starttime : q->time;
880 pj.status = q->status;
881 pj.size = q->size;
882 pj.spooled = True;
883 fstrcpy(pj.filename, old_pj ? old_pj->filename : "");
884 if (jobid < UNIX_JOB_START) {
885 pj.smbjob = True;
886 fstrcpy(pj.jobname, old_pj ? old_pj->jobname : "Remote Downlevel Document");
887 } else {
888 pj.smbjob = False;
889 fstrcpy(pj.jobname, old_pj ? old_pj->jobname : q->fs_file);
891 fstrcpy(pj.user, old_pj ? old_pj->user : q->fs_user);
892 fstrcpy(pj.queuename, old_pj ? old_pj->queuename : sharename );
894 pjob_store(ev, msg_ctx, sharename, jobid, &pj);
898 struct traverse_struct {
899 print_queue_struct *queue;
900 int qcount, snum, maxcount, total_jobs;
901 const char *sharename;
902 time_t lpq_time;
903 const char *lprm_command;
904 struct printif *print_if;
905 struct tevent_context *ev;
906 struct messaging_context *msg_ctx;
909 /****************************************************************************
910 Utility fn to delete any jobs that are no longer active.
911 ****************************************************************************/
913 static int traverse_fn_delete(TDB_CONTEXT *t, TDB_DATA key, TDB_DATA data, void *state)
915 struct traverse_struct *ts = (struct traverse_struct *)state;
916 struct printjob pjob;
917 uint32 jobid;
918 int i = 0;
920 if ( key.dsize != sizeof(jobid) )
921 return 0;
923 jobid = IVAL(key.dptr, 0);
924 if ( unpack_pjob( data.dptr, data.dsize, &pjob ) == -1 )
925 return 0;
926 talloc_free(pjob.devmode);
929 if (!pjob.smbjob) {
930 /* remove a unix job if it isn't in the system queue any more */
932 for (i=0;i<ts->qcount;i++) {
933 uint32 u_jobid = (ts->queue[i].job + UNIX_JOB_START);
934 if (jobid == u_jobid)
935 break;
937 if (i == ts->qcount) {
938 DEBUG(10,("traverse_fn_delete: pjob %u deleted due to !smbjob\n",
939 (unsigned int)jobid ));
940 pjob_delete(ts->ev, ts->msg_ctx,
941 ts->sharename, jobid);
942 return 0;
945 /* need to continue the the bottom of the function to
946 save the correct attributes */
949 /* maybe it hasn't been spooled yet */
950 if (!pjob.spooled) {
951 /* if a job is not spooled and the process doesn't
952 exist then kill it. This cleans up after smbd
953 deaths */
954 if (!process_exists_by_pid(pjob.pid)) {
955 DEBUG(10,("traverse_fn_delete: pjob %u deleted due to !process_exists (%u)\n",
956 (unsigned int)jobid, (unsigned int)pjob.pid ));
957 pjob_delete(ts->ev, ts->msg_ctx,
958 ts->sharename, jobid);
959 } else
960 ts->total_jobs++;
961 return 0;
964 /* this check only makes sense for jobs submitted from Windows clients */
966 if ( pjob.smbjob ) {
967 for (i=0;i<ts->qcount;i++) {
968 uint32 curr_jobid;
970 if ( pjob.status == LPQ_DELETED )
971 continue;
973 curr_jobid = print_parse_jobid(ts->queue[i].fs_file);
975 if (jobid == curr_jobid) {
977 /* try to clean up any jobs that need to be deleted */
979 if ( pjob.status == LPQ_DELETING ) {
980 int result;
982 result = (*(ts->print_if->job_delete))(
983 ts->sharename, ts->lprm_command, &pjob );
985 if ( result != 0 ) {
986 /* if we can't delete, then reset the job status */
987 pjob.status = LPQ_QUEUED;
988 pjob_store(ts->ev, ts->msg_ctx,
989 ts->sharename, jobid, &pjob);
991 else {
992 /* if we deleted the job, the remove the tdb record */
993 pjob_delete(ts->ev,
994 ts->msg_ctx,
995 ts->sharename, jobid);
996 pjob.status = LPQ_DELETED;
1001 break;
1006 /* The job isn't in the system queue - we have to assume it has
1007 completed, so delete the database entry. */
1009 if (i == ts->qcount) {
1011 /* A race can occur between the time a job is spooled and
1012 when it appears in the lpq output. This happens when
1013 the job is added to printing.tdb when another smbd
1014 running print_queue_update() has completed a lpq and
1015 is currently traversing the printing tdb and deleting jobs.
1016 Don't delete the job if it was submitted after the lpq_time. */
1018 if (pjob.starttime < ts->lpq_time) {
1019 DEBUG(10,("traverse_fn_delete: pjob %u deleted due to pjob.starttime (%u) < ts->lpq_time (%u)\n",
1020 (unsigned int)jobid,
1021 (unsigned int)pjob.starttime,
1022 (unsigned int)ts->lpq_time ));
1023 pjob_delete(ts->ev, ts->msg_ctx,
1024 ts->sharename, jobid);
1025 } else
1026 ts->total_jobs++;
1027 return 0;
1030 /* Save the pjob attributes we will store.
1031 FIXME!!! This is the only place where queue->job
1032 represents the SMB jobid --jerry */
1034 ts->queue[i].job = jobid;
1035 ts->queue[i].size = pjob.size;
1036 ts->queue[i].page_count = pjob.page_count;
1037 ts->queue[i].status = pjob.status;
1038 ts->queue[i].priority = 1;
1039 ts->queue[i].time = pjob.starttime;
1040 fstrcpy(ts->queue[i].fs_user, pjob.user);
1041 fstrcpy(ts->queue[i].fs_file, pjob.jobname);
1043 ts->total_jobs++;
1045 return 0;
1048 /****************************************************************************
1049 Check if the print queue has been updated recently enough.
1050 ****************************************************************************/
1052 static void print_cache_flush(const char *sharename)
1054 fstring key;
1055 struct tdb_print_db *pdb = get_print_db_byname(sharename);
1057 if (!pdb)
1058 return;
1059 slprintf(key, sizeof(key)-1, "CACHE/%s", sharename);
1060 tdb_store_int32(pdb->tdb, key, -1);
1061 release_print_db(pdb);
1064 /****************************************************************************
1065 Check if someone already thinks they are doing the update.
1066 ****************************************************************************/
1068 static pid_t get_updating_pid(const char *sharename)
1070 fstring keystr;
1071 TDB_DATA data, key;
1072 pid_t updating_pid;
1073 struct tdb_print_db *pdb = get_print_db_byname(sharename);
1075 if (!pdb)
1076 return (pid_t)-1;
1077 slprintf(keystr, sizeof(keystr)-1, "UPDATING/%s", sharename);
1078 key = string_tdb_data(keystr);
1080 data = tdb_fetch(pdb->tdb, key);
1081 release_print_db(pdb);
1082 if (!data.dptr || data.dsize != sizeof(pid_t)) {
1083 SAFE_FREE(data.dptr);
1084 return (pid_t)-1;
1087 updating_pid = IVAL(data.dptr, 0);
1088 SAFE_FREE(data.dptr);
1090 if (process_exists_by_pid(updating_pid))
1091 return updating_pid;
1093 return (pid_t)-1;
1096 /****************************************************************************
1097 Set the fact that we're doing the update, or have finished doing the update
1098 in the tdb.
1099 ****************************************************************************/
1101 static void set_updating_pid(const fstring sharename, bool updating)
1103 fstring keystr;
1104 TDB_DATA key;
1105 TDB_DATA data;
1106 pid_t updating_pid = sys_getpid();
1107 uint8 buffer[4];
1109 struct tdb_print_db *pdb = get_print_db_byname(sharename);
1111 if (!pdb)
1112 return;
1114 slprintf(keystr, sizeof(keystr)-1, "UPDATING/%s", sharename);
1115 key = string_tdb_data(keystr);
1117 DEBUG(5, ("set_updating_pid: %s updating lpq cache for print share %s\n",
1118 updating ? "" : "not ",
1119 sharename ));
1121 if ( !updating ) {
1122 tdb_delete(pdb->tdb, key);
1123 release_print_db(pdb);
1124 return;
1127 SIVAL( buffer, 0, updating_pid);
1128 data.dptr = buffer;
1129 data.dsize = 4; /* we always assume this is a 4 byte value */
1131 tdb_store(pdb->tdb, key, data, TDB_REPLACE);
1132 release_print_db(pdb);
1135 /****************************************************************************
1136 Sort print jobs by submittal time.
1137 ****************************************************************************/
1139 static int printjob_comp(print_queue_struct *j1, print_queue_struct *j2)
1141 /* Silly cases */
1143 if (!j1 && !j2)
1144 return 0;
1145 if (!j1)
1146 return -1;
1147 if (!j2)
1148 return 1;
1150 /* Sort on job start time */
1152 if (j1->time == j2->time)
1153 return 0;
1154 return (j1->time > j2->time) ? 1 : -1;
1157 /****************************************************************************
1158 Store the sorted queue representation for later portmon retrieval.
1159 Skip deleted jobs
1160 ****************************************************************************/
1162 static void store_queue_struct(struct tdb_print_db *pdb, struct traverse_struct *pts)
1164 TDB_DATA data;
1165 int max_reported_jobs = lp_max_reported_jobs(pts->snum);
1166 print_queue_struct *queue = pts->queue;
1167 size_t len;
1168 size_t i;
1169 unsigned int qcount;
1171 if (max_reported_jobs && (max_reported_jobs < pts->qcount))
1172 pts->qcount = max_reported_jobs;
1173 qcount = 0;
1175 /* Work out the size. */
1176 data.dsize = 0;
1177 data.dsize += tdb_pack(NULL, 0, "d", qcount);
1179 for (i = 0; i < pts->qcount; i++) {
1180 if ( queue[i].status == LPQ_DELETED )
1181 continue;
1183 qcount++;
1184 data.dsize += tdb_pack(NULL, 0, "ddddddff",
1185 (uint32)queue[i].job,
1186 (uint32)queue[i].size,
1187 (uint32)queue[i].page_count,
1188 (uint32)queue[i].status,
1189 (uint32)queue[i].priority,
1190 (uint32)queue[i].time,
1191 queue[i].fs_user,
1192 queue[i].fs_file);
1195 if ((data.dptr = (uint8 *)SMB_MALLOC(data.dsize)) == NULL)
1196 return;
1198 len = 0;
1199 len += tdb_pack(data.dptr + len, data.dsize - len, "d", qcount);
1200 for (i = 0; i < pts->qcount; i++) {
1201 if ( queue[i].status == LPQ_DELETED )
1202 continue;
1204 len += tdb_pack(data.dptr + len, data.dsize - len, "ddddddff",
1205 (uint32)queue[i].job,
1206 (uint32)queue[i].size,
1207 (uint32)queue[i].page_count,
1208 (uint32)queue[i].status,
1209 (uint32)queue[i].priority,
1210 (uint32)queue[i].time,
1211 queue[i].fs_user,
1212 queue[i].fs_file);
1215 tdb_store(pdb->tdb, string_tdb_data("INFO/linear_queue_array"), data,
1216 TDB_REPLACE);
1217 SAFE_FREE(data.dptr);
1218 return;
1221 static TDB_DATA get_jobs_added_data(struct tdb_print_db *pdb)
1223 TDB_DATA data;
1225 ZERO_STRUCT(data);
1227 data = tdb_fetch(pdb->tdb, string_tdb_data("INFO/jobs_added"));
1228 if (data.dptr == NULL || data.dsize == 0 || (data.dsize % 4 != 0)) {
1229 SAFE_FREE(data.dptr);
1230 ZERO_STRUCT(data);
1233 return data;
1236 static void check_job_added(const char *sharename, TDB_DATA data, uint32 jobid)
1238 unsigned int i;
1239 unsigned int job_count = data.dsize / 4;
1241 for (i = 0; i < job_count; i++) {
1242 uint32 ch_jobid;
1244 ch_jobid = IVAL(data.dptr, i*4);
1245 if (ch_jobid == jobid)
1246 remove_from_jobs_added(sharename, jobid);
1250 /****************************************************************************
1251 Check if the print queue has been updated recently enough.
1252 ****************************************************************************/
1254 static bool print_cache_expired(const char *sharename, bool check_pending)
1256 fstring key;
1257 time_t last_qscan_time, time_now = time(NULL);
1258 struct tdb_print_db *pdb = get_print_db_byname(sharename);
1259 bool result = False;
1261 if (!pdb)
1262 return False;
1264 snprintf(key, sizeof(key), "CACHE/%s", sharename);
1265 last_qscan_time = (time_t)tdb_fetch_int32(pdb->tdb, key);
1268 * Invalidate the queue for 3 reasons.
1269 * (1). last queue scan time == -1.
1270 * (2). Current time - last queue scan time > allowed cache time.
1271 * (3). last queue scan time > current time + MAX_CACHE_VALID_TIME (1 hour by default).
1272 * This last test picks up machines for which the clock has been moved
1273 * forward, an lpq scan done and then the clock moved back. Otherwise
1274 * that last lpq scan would stay around for a loooong loooong time... :-). JRA.
1277 if (last_qscan_time == ((time_t)-1)
1278 || (time_now - last_qscan_time) >= lp_lpqcachetime()
1279 || last_qscan_time > (time_now + MAX_CACHE_VALID_TIME))
1281 uint32 u;
1282 time_t msg_pending_time;
1284 DEBUG(4, ("print_cache_expired: cache expired for queue %s "
1285 "(last_qscan_time = %d, time now = %d, qcachetime = %d)\n",
1286 sharename, (int)last_qscan_time, (int)time_now,
1287 (int)lp_lpqcachetime() ));
1289 /* check if another smbd has already sent a message to update the
1290 queue. Give the pending message one minute to clear and
1291 then send another message anyways. Make sure to check for
1292 clocks that have been run forward and then back again. */
1294 snprintf(key, sizeof(key), "MSG_PENDING/%s", sharename);
1296 if ( check_pending
1297 && tdb_fetch_uint32( pdb->tdb, key, &u )
1298 && (msg_pending_time=u) > 0
1299 && msg_pending_time <= time_now
1300 && (time_now - msg_pending_time) < 60 )
1302 DEBUG(4,("print_cache_expired: message already pending for %s. Accepting cache\n",
1303 sharename));
1304 goto done;
1307 result = True;
1310 done:
1311 release_print_db(pdb);
1312 return result;
1315 /****************************************************************************
1316 main work for updating the lpq cache for a printer queue
1317 ****************************************************************************/
1319 static void print_queue_update_internal( struct tevent_context *ev,
1320 struct messaging_context *msg_ctx,
1321 const char *sharename,
1322 struct printif *current_printif,
1323 char *lpq_command, char *lprm_command )
1325 int i, qcount;
1326 print_queue_struct *queue = NULL;
1327 print_status_struct status;
1328 print_status_struct old_status;
1329 struct printjob *pjob;
1330 struct traverse_struct tstruct;
1331 TDB_DATA data, key;
1332 TDB_DATA jcdata;
1333 fstring keystr, cachestr;
1334 struct tdb_print_db *pdb = get_print_db_byname(sharename);
1336 if (!pdb) {
1337 return;
1340 DEBUG(5,("print_queue_update_internal: printer = %s, type = %d, lpq command = [%s]\n",
1341 sharename, current_printif->type, lpq_command));
1344 * Update the cache time FIRST ! Stops others even
1345 * attempting to get the lock and doing this
1346 * if the lpq takes a long time.
1349 slprintf(cachestr, sizeof(cachestr)-1, "CACHE/%s", sharename);
1350 tdb_store_int32(pdb->tdb, cachestr, (int)time(NULL));
1352 /* get the current queue using the appropriate interface */
1353 ZERO_STRUCT(status);
1355 qcount = (*(current_printif->queue_get))(sharename,
1356 current_printif->type,
1357 lpq_command, &queue, &status);
1359 DEBUG(3, ("print_queue_update_internal: %d job%s in queue for %s\n",
1360 qcount, (qcount != 1) ? "s" : "", sharename));
1362 /* Sort the queue by submission time otherwise they are displayed
1363 in hash order. */
1365 TYPESAFE_QSORT(queue, qcount, printjob_comp);
1368 any job in the internal database that is marked as spooled
1369 and doesn't exist in the system queue is considered finished
1370 and removed from the database
1372 any job in the system database but not in the internal database
1373 is added as a unix job
1375 fill in any system job numbers as we go
1378 jcdata = get_jobs_added_data(pdb);
1380 for (i=0; i<qcount; i++) {
1381 uint32 jobid = print_parse_jobid(queue[i].fs_file);
1383 if (jobid == (uint32)-1) {
1384 /* assume its a unix print job */
1385 print_unix_job(ev, msg_ctx,
1386 sharename, &queue[i], jobid);
1387 continue;
1390 /* we have an active SMB print job - update its status */
1391 pjob = print_job_find(sharename, jobid);
1392 if (!pjob) {
1393 /* err, somethings wrong. Probably smbd was restarted
1394 with jobs in the queue. All we can do is treat them
1395 like unix jobs. Pity. */
1396 print_unix_job(ev, msg_ctx,
1397 sharename, &queue[i], jobid);
1398 continue;
1401 pjob->sysjob = queue[i].job;
1403 /* don't reset the status on jobs to be deleted */
1405 if ( pjob->status != LPQ_DELETING )
1406 pjob->status = queue[i].status;
1408 pjob_store(ev, msg_ctx, sharename, jobid, pjob);
1410 check_job_added(sharename, jcdata, jobid);
1413 SAFE_FREE(jcdata.dptr);
1415 /* now delete any queued entries that don't appear in the
1416 system queue */
1417 tstruct.queue = queue;
1418 tstruct.qcount = qcount;
1419 tstruct.snum = -1;
1420 tstruct.total_jobs = 0;
1421 tstruct.lpq_time = time(NULL);
1422 tstruct.sharename = sharename;
1423 tstruct.lprm_command = lprm_command;
1424 tstruct.print_if = current_printif;
1425 tstruct.ev = ev;
1426 tstruct.msg_ctx = msg_ctx;
1428 tdb_traverse(pdb->tdb, traverse_fn_delete, (void *)&tstruct);
1430 /* Store the linearised queue, max jobs only. */
1431 store_queue_struct(pdb, &tstruct);
1433 SAFE_FREE(tstruct.queue);
1435 DEBUG(10,("print_queue_update_internal: printer %s INFO/total_jobs = %d\n",
1436 sharename, tstruct.total_jobs ));
1438 tdb_store_int32(pdb->tdb, "INFO/total_jobs", tstruct.total_jobs);
1440 get_queue_status(sharename, &old_status);
1441 if (old_status.qcount != qcount)
1442 DEBUG(10,("print_queue_update_internal: queue status change %d jobs -> %d jobs for printer %s\n",
1443 old_status.qcount, qcount, sharename));
1445 /* store the new queue status structure */
1446 slprintf(keystr, sizeof(keystr)-1, "STATUS/%s", sharename);
1447 key = string_tdb_data(keystr);
1449 status.qcount = qcount;
1450 data.dptr = (uint8 *)&status;
1451 data.dsize = sizeof(status);
1452 tdb_store(pdb->tdb, key, data, TDB_REPLACE);
1455 * Update the cache time again. We want to do this call
1456 * as little as possible...
1459 slprintf(keystr, sizeof(keystr)-1, "CACHE/%s", sharename);
1460 tdb_store_int32(pdb->tdb, keystr, (int32)time(NULL));
1462 /* clear the msg pending record for this queue */
1464 snprintf(keystr, sizeof(keystr), "MSG_PENDING/%s", sharename);
1466 if ( !tdb_store_uint32( pdb->tdb, keystr, 0 ) ) {
1467 /* log a message but continue on */
1469 DEBUG(0,("print_queue_update: failed to store MSG_PENDING flag for [%s]!\n",
1470 sharename));
1473 release_print_db( pdb );
1475 return;
1478 /****************************************************************************
1479 Update the internal database from the system print queue for a queue.
1480 obtain a lock on the print queue before proceeding (needed when mutiple
1481 smbd processes maytry to update the lpq cache concurrently).
1482 ****************************************************************************/
1484 static void print_queue_update_with_lock( struct tevent_context *ev,
1485 struct messaging_context *msg_ctx,
1486 const char *sharename,
1487 struct printif *current_printif,
1488 char *lpq_command, char *lprm_command )
1490 fstring keystr;
1491 struct tdb_print_db *pdb;
1493 DEBUG(5,("print_queue_update_with_lock: printer share = %s\n", sharename));
1494 pdb = get_print_db_byname(sharename);
1495 if (!pdb)
1496 return;
1498 if ( !print_cache_expired(sharename, False) ) {
1499 DEBUG(5,("print_queue_update_with_lock: print cache for %s is still ok\n", sharename));
1500 release_print_db(pdb);
1501 return;
1505 * Check to see if someone else is doing this update.
1506 * This is essentially a mutex on the update.
1509 if (get_updating_pid(sharename) != -1) {
1510 release_print_db(pdb);
1511 return;
1514 /* Lock the queue for the database update */
1516 slprintf(keystr, sizeof(keystr) - 1, "LOCK/%s", sharename);
1517 /* Only wait 10 seconds for this. */
1518 if (tdb_lock_bystring_with_timeout(pdb->tdb, keystr, 10) == -1) {
1519 DEBUG(0,("print_queue_update_with_lock: Failed to lock printer %s database\n", sharename));
1520 release_print_db(pdb);
1521 return;
1525 * Ensure that no one else got in here.
1526 * If the updating pid is still -1 then we are
1527 * the winner.
1530 if (get_updating_pid(sharename) != -1) {
1532 * Someone else is doing the update, exit.
1534 tdb_unlock_bystring(pdb->tdb, keystr);
1535 release_print_db(pdb);
1536 return;
1540 * We're going to do the update ourselves.
1543 /* Tell others we're doing the update. */
1544 set_updating_pid(sharename, True);
1547 * Allow others to enter and notice we're doing
1548 * the update.
1551 tdb_unlock_bystring(pdb->tdb, keystr);
1553 /* do the main work now */
1555 print_queue_update_internal(ev, msg_ctx,
1556 sharename, current_printif,
1557 lpq_command, lprm_command);
1559 /* Delete our pid from the db. */
1560 set_updating_pid(sharename, False);
1561 release_print_db(pdb);
1564 /****************************************************************************
1565 this is the receive function of the background lpq updater
1566 ****************************************************************************/
1567 void print_queue_receive(struct messaging_context *msg,
1568 void *private_data,
1569 uint32_t msg_type,
1570 struct server_id server_id,
1571 DATA_BLOB *data)
1573 fstring sharename;
1574 char *lpqcommand = NULL, *lprmcommand = NULL;
1575 int printing_type;
1576 size_t len;
1578 len = tdb_unpack( (uint8 *)data->data, data->length, "fdPP",
1579 sharename,
1580 &printing_type,
1581 &lpqcommand,
1582 &lprmcommand );
1584 if ( len == -1 ) {
1585 SAFE_FREE(lpqcommand);
1586 SAFE_FREE(lprmcommand);
1587 DEBUG(0,("print_queue_receive: Got invalid print queue update message\n"));
1588 return;
1591 print_queue_update_with_lock(server_event_context(), msg, sharename,
1592 get_printer_fns_from_type((enum printing_types)printing_type),
1593 lpqcommand, lprmcommand );
1595 SAFE_FREE(lpqcommand);
1596 SAFE_FREE(lprmcommand);
1597 return;
1600 static void printing_pause_fd_handler(struct tevent_context *ev,
1601 struct tevent_fd *fde,
1602 uint16_t flags,
1603 void *private_data)
1606 * If pause_pipe[1] is closed it means the parent smbd
1607 * and children exited or aborted.
1609 exit_server_cleanly(NULL);
1612 extern struct child_pid *children;
1613 extern int num_children;
1615 static void add_child_pid(pid_t pid)
1617 struct child_pid *child;
1619 child = SMB_MALLOC_P(struct child_pid);
1620 if (child == NULL) {
1621 DEBUG(0, ("Could not add child struct -- malloc failed\n"));
1622 return;
1624 child->pid = pid;
1625 DLIST_ADD(children, child);
1626 num_children += 1;
1629 static pid_t background_lpq_updater_pid = -1;
1631 /****************************************************************************
1632 main thread of the background lpq updater
1633 ****************************************************************************/
1634 void start_background_queue(struct tevent_context *ev,
1635 struct messaging_context *msg_ctx)
1637 /* Use local variables for this as we don't
1638 * need to save the parent side of this, just
1639 * ensure it closes when the process exits.
1641 int pause_pipe[2];
1643 DEBUG(3,("start_background_queue: Starting background LPQ thread\n"));
1645 if (pipe(pause_pipe) == -1) {
1646 DEBUG(5,("start_background_queue: cannot create pipe. %s\n", strerror(errno) ));
1647 exit(1);
1650 background_lpq_updater_pid = sys_fork();
1652 if (background_lpq_updater_pid == -1) {
1653 DEBUG(5,("start_background_queue: background LPQ thread failed to start. %s\n", strerror(errno) ));
1654 exit(1);
1657 /* Track the printing pid along with other smbd children */
1658 add_child_pid(background_lpq_updater_pid);
1660 if(background_lpq_updater_pid == 0) {
1661 struct tevent_fd *fde;
1662 int ret;
1663 NTSTATUS status;
1665 /* Child. */
1666 DEBUG(5,("start_background_queue: background LPQ thread started\n"));
1668 close(pause_pipe[0]);
1669 pause_pipe[0] = -1;
1671 status = reinit_after_fork(msg_ctx, ev, procid_self(), true);
1673 if (!NT_STATUS_IS_OK(status)) {
1674 DEBUG(0,("reinit_after_fork() failed\n"));
1675 smb_panic("reinit_after_fork() failed");
1678 smbd_setup_sig_term_handler();
1679 smbd_setup_sig_hup_handler(ev, msg_ctx);
1681 if (!serverid_register(procid_self(),
1682 FLAG_MSG_GENERAL|FLAG_MSG_SMBD
1683 |FLAG_MSG_PRINT_GENERAL)) {
1684 exit(1);
1687 if (!locking_init()) {
1688 exit(1);
1691 messaging_register(msg_ctx, NULL, MSG_PRINTER_UPDATE,
1692 print_queue_receive);
1694 fde = tevent_add_fd(ev, ev, pause_pipe[1], TEVENT_FD_READ,
1695 printing_pause_fd_handler,
1696 NULL);
1697 if (!fde) {
1698 DEBUG(0,("tevent_add_fd() failed for pause_pipe\n"));
1699 smb_panic("tevent_add_fd() failed for pause_pipe");
1702 DEBUG(5,("start_background_queue: background LPQ thread waiting for messages\n"));
1703 ret = tevent_loop_wait(ev);
1704 /* should not be reached */
1705 DEBUG(0,("background_queue: tevent_loop_wait() exited with %d - %s\n",
1706 ret, (ret == 0) ? "out of events" : strerror(errno)));
1707 exit(1);
1710 close(pause_pipe[1]);
1713 /****************************************************************************
1714 update the internal database from the system print queue for a queue
1715 ****************************************************************************/
1717 static void print_queue_update(struct messaging_context *msg_ctx,
1718 int snum, bool force)
1720 fstring key;
1721 fstring sharename;
1722 char *lpqcommand = NULL;
1723 char *lprmcommand = NULL;
1724 uint8 *buffer = NULL;
1725 size_t len = 0;
1726 size_t newlen;
1727 struct tdb_print_db *pdb;
1728 int type;
1729 struct printif *current_printif;
1730 TALLOC_CTX *ctx = talloc_tos();
1732 fstrcpy( sharename, lp_const_servicename(snum));
1734 /* don't strip out characters like '$' from the printername */
1736 lpqcommand = talloc_string_sub2(ctx,
1737 lp_lpqcommand(snum),
1738 "%p",
1739 lp_printername(snum),
1740 false, false, false);
1741 if (!lpqcommand) {
1742 return;
1744 lpqcommand = talloc_sub_advanced(ctx,
1745 lp_servicename(snum),
1746 current_user_info.unix_name,
1748 current_user.ut.gid,
1749 get_current_username(),
1750 current_user_info.domain,
1751 lpqcommand);
1752 if (!lpqcommand) {
1753 return;
1756 lprmcommand = talloc_string_sub2(ctx,
1757 lp_lprmcommand(snum),
1758 "%p",
1759 lp_printername(snum),
1760 false, false, false);
1761 if (!lprmcommand) {
1762 return;
1764 lprmcommand = talloc_sub_advanced(ctx,
1765 lp_servicename(snum),
1766 current_user_info.unix_name,
1768 current_user.ut.gid,
1769 get_current_username(),
1770 current_user_info.domain,
1771 lprmcommand);
1772 if (!lprmcommand) {
1773 return;
1777 * Make sure that the background queue process exists.
1778 * Otherwise just do the update ourselves
1781 if ( force || background_lpq_updater_pid == -1 ) {
1782 DEBUG(4,("print_queue_update: updating queue [%s] myself\n", sharename));
1783 current_printif = get_printer_fns( snum );
1784 print_queue_update_with_lock(server_event_context(), msg_ctx,
1785 sharename, current_printif,
1786 lpqcommand, lprmcommand);
1788 return;
1791 type = lp_printing(snum);
1793 /* get the length */
1795 len = tdb_pack( NULL, 0, "fdPP",
1796 sharename,
1797 type,
1798 lpqcommand,
1799 lprmcommand );
1801 buffer = SMB_XMALLOC_ARRAY( uint8, len );
1803 /* now pack the buffer */
1804 newlen = tdb_pack( buffer, len, "fdPP",
1805 sharename,
1806 type,
1807 lpqcommand,
1808 lprmcommand );
1810 SMB_ASSERT( newlen == len );
1812 DEBUG(10,("print_queue_update: Sending message -> printer = %s, "
1813 "type = %d, lpq command = [%s] lprm command = [%s]\n",
1814 sharename, type, lpqcommand, lprmcommand ));
1816 /* here we set a msg pending record for other smbd processes
1817 to throttle the number of duplicate print_queue_update msgs
1818 sent. */
1820 pdb = get_print_db_byname(sharename);
1821 if (!pdb) {
1822 SAFE_FREE(buffer);
1823 return;
1826 snprintf(key, sizeof(key), "MSG_PENDING/%s", sharename);
1828 if ( !tdb_store_uint32( pdb->tdb, key, time(NULL) ) ) {
1829 /* log a message but continue on */
1831 DEBUG(0,("print_queue_update: failed to store MSG_PENDING flag for [%s]!\n",
1832 sharename));
1835 release_print_db( pdb );
1837 /* finally send the message */
1839 messaging_send_buf(msg_ctx, pid_to_procid(background_lpq_updater_pid),
1840 MSG_PRINTER_UPDATE, (uint8 *)buffer, len);
1842 SAFE_FREE( buffer );
1844 return;
1847 /****************************************************************************
1848 Create/Update an entry in the print tdb that will allow us to send notify
1849 updates only to interested smbd's.
1850 ****************************************************************************/
1852 bool print_notify_register_pid(int snum)
1854 TDB_DATA data;
1855 struct tdb_print_db *pdb = NULL;
1856 TDB_CONTEXT *tdb = NULL;
1857 const char *printername;
1858 uint32 mypid = (uint32)sys_getpid();
1859 bool ret = False;
1860 size_t i;
1862 /* if (snum == -1), then the change notify request was
1863 on a print server handle and we need to register on
1864 all print queus */
1866 if (snum == -1)
1868 int num_services = lp_numservices();
1869 int idx;
1871 for ( idx=0; idx<num_services; idx++ ) {
1872 if (lp_snum_ok(idx) && lp_print_ok(idx) )
1873 print_notify_register_pid(idx);
1876 return True;
1878 else /* register for a specific printer */
1880 printername = lp_const_servicename(snum);
1881 pdb = get_print_db_byname(printername);
1882 if (!pdb)
1883 return False;
1884 tdb = pdb->tdb;
1887 if (tdb_lock_bystring_with_timeout(tdb, NOTIFY_PID_LIST_KEY, 10) == -1) {
1888 DEBUG(0,("print_notify_register_pid: Failed to lock printer %s\n",
1889 printername));
1890 if (pdb)
1891 release_print_db(pdb);
1892 return False;
1895 data = get_printer_notify_pid_list( tdb, printername, True );
1897 /* Add ourselves and increase the refcount. */
1899 for (i = 0; i < data.dsize; i += 8) {
1900 if (IVAL(data.dptr,i) == mypid) {
1901 uint32 new_refcount = IVAL(data.dptr, i+4) + 1;
1902 SIVAL(data.dptr, i+4, new_refcount);
1903 break;
1907 if (i == data.dsize) {
1908 /* We weren't in the list. Realloc. */
1909 data.dptr = (uint8 *)SMB_REALLOC(data.dptr, data.dsize + 8);
1910 if (!data.dptr) {
1911 DEBUG(0,("print_notify_register_pid: Relloc fail for printer %s\n",
1912 printername));
1913 goto done;
1915 data.dsize += 8;
1916 SIVAL(data.dptr,data.dsize - 8,mypid);
1917 SIVAL(data.dptr,data.dsize - 4,1); /* Refcount. */
1920 /* Store back the record. */
1921 if (tdb_store_bystring(tdb, NOTIFY_PID_LIST_KEY, data, TDB_REPLACE) == -1) {
1922 DEBUG(0,("print_notify_register_pid: Failed to update pid \
1923 list for printer %s\n", printername));
1924 goto done;
1927 ret = True;
1929 done:
1931 tdb_unlock_bystring(tdb, NOTIFY_PID_LIST_KEY);
1932 if (pdb)
1933 release_print_db(pdb);
1934 SAFE_FREE(data.dptr);
1935 return ret;
1938 /****************************************************************************
1939 Update an entry in the print tdb that will allow us to send notify
1940 updates only to interested smbd's.
1941 ****************************************************************************/
1943 bool print_notify_deregister_pid(int snum)
1945 TDB_DATA data;
1946 struct tdb_print_db *pdb = NULL;
1947 TDB_CONTEXT *tdb = NULL;
1948 const char *printername;
1949 uint32 mypid = (uint32)sys_getpid();
1950 size_t i;
1951 bool ret = False;
1953 /* if ( snum == -1 ), we are deregister a print server handle
1954 which means to deregister on all print queues */
1956 if (snum == -1)
1958 int num_services = lp_numservices();
1959 int idx;
1961 for ( idx=0; idx<num_services; idx++ ) {
1962 if ( lp_snum_ok(idx) && lp_print_ok(idx) )
1963 print_notify_deregister_pid(idx);
1966 return True;
1968 else /* deregister a specific printer */
1970 printername = lp_const_servicename(snum);
1971 pdb = get_print_db_byname(printername);
1972 if (!pdb)
1973 return False;
1974 tdb = pdb->tdb;
1977 if (tdb_lock_bystring_with_timeout(tdb, NOTIFY_PID_LIST_KEY, 10) == -1) {
1978 DEBUG(0,("print_notify_register_pid: Failed to lock \
1979 printer %s database\n", printername));
1980 if (pdb)
1981 release_print_db(pdb);
1982 return False;
1985 data = get_printer_notify_pid_list( tdb, printername, True );
1987 /* Reduce refcount. Remove ourselves if zero. */
1989 for (i = 0; i < data.dsize; ) {
1990 if (IVAL(data.dptr,i) == mypid) {
1991 uint32 refcount = IVAL(data.dptr, i+4);
1993 refcount--;
1995 if (refcount == 0) {
1996 if (data.dsize - i > 8)
1997 memmove( &data.dptr[i], &data.dptr[i+8], data.dsize - i - 8);
1998 data.dsize -= 8;
1999 continue;
2001 SIVAL(data.dptr, i+4, refcount);
2004 i += 8;
2007 if (data.dsize == 0)
2008 SAFE_FREE(data.dptr);
2010 /* Store back the record. */
2011 if (tdb_store_bystring(tdb, NOTIFY_PID_LIST_KEY, data, TDB_REPLACE) == -1) {
2012 DEBUG(0,("print_notify_register_pid: Failed to update pid \
2013 list for printer %s\n", printername));
2014 goto done;
2017 ret = True;
2019 done:
2021 tdb_unlock_bystring(tdb, NOTIFY_PID_LIST_KEY);
2022 if (pdb)
2023 release_print_db(pdb);
2024 SAFE_FREE(data.dptr);
2025 return ret;
2028 /****************************************************************************
2029 Check if a jobid is valid. It is valid if it exists in the database.
2030 ****************************************************************************/
2032 bool print_job_exists(const char* sharename, uint32 jobid)
2034 struct tdb_print_db *pdb = get_print_db_byname(sharename);
2035 bool ret;
2036 uint32_t tmp;
2038 if (!pdb)
2039 return False;
2040 ret = tdb_exists(pdb->tdb, print_key(jobid, &tmp));
2041 release_print_db(pdb);
2042 return ret;
2045 /****************************************************************************
2046 Give the filename used for a jobid.
2047 Only valid for the process doing the spooling and when the job
2048 has not been spooled.
2049 ****************************************************************************/
2051 char *print_job_fname(const char* sharename, uint32 jobid)
2053 struct printjob *pjob = print_job_find(sharename, jobid);
2054 if (!pjob || pjob->spooled || pjob->pid != sys_getpid())
2055 return NULL;
2056 return pjob->filename;
2060 /****************************************************************************
2061 Give the filename used for a jobid.
2062 Only valid for the process doing the spooling and when the job
2063 has not been spooled.
2064 ****************************************************************************/
2066 struct spoolss_DeviceMode *print_job_devmode(const char* sharename, uint32 jobid)
2068 struct printjob *pjob = print_job_find(sharename, jobid);
2070 if ( !pjob )
2071 return NULL;
2073 return pjob->devmode;
2076 /****************************************************************************
2077 Set the name of a job. Only possible for owner.
2078 ****************************************************************************/
2080 bool print_job_set_name(struct tevent_context *ev,
2081 struct messaging_context *msg_ctx,
2082 const char *sharename, uint32 jobid, const char *name)
2084 struct printjob *pjob;
2086 pjob = print_job_find(sharename, jobid);
2087 if (!pjob || pjob->pid != sys_getpid())
2088 return False;
2090 fstrcpy(pjob->jobname, name);
2091 return pjob_store(ev, msg_ctx, sharename, jobid, pjob);
2094 /****************************************************************************
2095 Get the name of a job. Only possible for owner.
2096 ****************************************************************************/
2098 bool print_job_get_name(TALLOC_CTX *mem_ctx, const char *sharename, uint32_t jobid, char **name)
2100 struct printjob *pjob;
2102 pjob = print_job_find(sharename, jobid);
2103 if (!pjob || pjob->pid != sys_getpid()) {
2104 return false;
2107 *name = talloc_strdup(mem_ctx, pjob->jobname);
2108 if (!*name) {
2109 return false;
2112 return true;
2116 /***************************************************************************
2117 Remove a jobid from the 'jobs added' list.
2118 ***************************************************************************/
2120 static bool remove_from_jobs_added(const char* sharename, uint32 jobid)
2122 struct tdb_print_db *pdb = get_print_db_byname(sharename);
2123 TDB_DATA data, key;
2124 size_t job_count, i;
2125 bool ret = False;
2126 bool gotlock = False;
2128 if (!pdb) {
2129 return False;
2132 ZERO_STRUCT(data);
2134 key = string_tdb_data("INFO/jobs_added");
2136 if (tdb_chainlock_with_timeout(pdb->tdb, key, 5) == -1)
2137 goto out;
2139 gotlock = True;
2141 data = tdb_fetch(pdb->tdb, key);
2143 if (data.dptr == NULL || data.dsize == 0 || (data.dsize % 4 != 0))
2144 goto out;
2146 job_count = data.dsize / 4;
2147 for (i = 0; i < job_count; i++) {
2148 uint32 ch_jobid;
2150 ch_jobid = IVAL(data.dptr, i*4);
2151 if (ch_jobid == jobid) {
2152 if (i < job_count -1 )
2153 memmove(data.dptr + (i*4), data.dptr + (i*4) + 4, (job_count - i - 1)*4 );
2154 data.dsize -= 4;
2155 if (tdb_store(pdb->tdb, key, data, TDB_REPLACE) == -1)
2156 goto out;
2157 break;
2161 ret = True;
2162 out:
2164 if (gotlock)
2165 tdb_chainunlock(pdb->tdb, key);
2166 SAFE_FREE(data.dptr);
2167 release_print_db(pdb);
2168 if (ret)
2169 DEBUG(10,("remove_from_jobs_added: removed jobid %u\n", (unsigned int)jobid ));
2170 else
2171 DEBUG(10,("remove_from_jobs_added: Failed to remove jobid %u\n", (unsigned int)jobid ));
2172 return ret;
2175 /****************************************************************************
2176 Delete a print job - don't update queue.
2177 ****************************************************************************/
2179 static bool print_job_delete1(struct tevent_context *ev,
2180 struct messaging_context *msg_ctx,
2181 int snum, uint32 jobid)
2183 const char* sharename = lp_const_servicename(snum);
2184 struct printjob *pjob = print_job_find(sharename, jobid);
2185 int result = 0;
2186 struct printif *current_printif = get_printer_fns( snum );
2188 if (!pjob)
2189 return False;
2192 * If already deleting just return.
2195 if (pjob->status == LPQ_DELETING)
2196 return True;
2198 /* Hrm - we need to be able to cope with deleting a job before it
2199 has reached the spooler. Just mark it as LPQ_DELETING and
2200 let the print_queue_update() code rmeove the record */
2203 if (pjob->sysjob == -1) {
2204 DEBUG(5, ("attempt to delete job %u not seen by lpr\n", (unsigned int)jobid));
2207 /* Set the tdb entry to be deleting. */
2209 pjob->status = LPQ_DELETING;
2210 pjob_store(ev, msg_ctx, sharename, jobid, pjob);
2212 if (pjob->spooled && pjob->sysjob != -1)
2214 result = (*(current_printif->job_delete))(
2215 lp_printername(snum),
2216 lp_lprmcommand(snum),
2217 pjob);
2219 /* Delete the tdb entry if the delete succeeded or the job hasn't
2220 been spooled. */
2222 if (result == 0) {
2223 struct tdb_print_db *pdb = get_print_db_byname(sharename);
2224 int njobs = 1;
2226 if (!pdb)
2227 return False;
2228 pjob_delete(ev, msg_ctx, sharename, jobid);
2229 /* Ensure we keep a rough count of the number of total jobs... */
2230 tdb_change_int32_atomic(pdb->tdb, "INFO/total_jobs", &njobs, -1);
2231 release_print_db(pdb);
2235 remove_from_jobs_added( sharename, jobid );
2237 return (result == 0);
2240 /****************************************************************************
2241 Return true if the current user owns the print job.
2242 ****************************************************************************/
2244 static bool is_owner(const struct auth_serversupplied_info *server_info,
2245 const char *servicename,
2246 uint32 jobid)
2248 struct printjob *pjob = print_job_find(servicename, jobid);
2250 if (!pjob || !server_info)
2251 return False;
2253 return strequal(pjob->user, server_info->sanitized_username);
2256 /****************************************************************************
2257 Delete a print job.
2258 ****************************************************************************/
2260 WERROR print_job_delete(const struct auth_serversupplied_info *server_info,
2261 struct messaging_context *msg_ctx,
2262 int snum, uint32_t jobid)
2264 const char* sharename = lp_const_servicename(snum);
2265 struct printjob *pjob;
2266 bool owner;
2267 char *fname;
2269 owner = is_owner(server_info, lp_const_servicename(snum), jobid);
2271 /* Check access against security descriptor or whether the user
2272 owns their job. */
2274 if (!owner &&
2275 !print_access_check(server_info, msg_ctx, snum,
2276 JOB_ACCESS_ADMINISTER)) {
2277 DEBUG(3, ("delete denied by security descriptor\n"));
2279 /* BEGIN_ADMIN_LOG */
2280 sys_adminlog( LOG_ERR,
2281 "Permission denied-- user not allowed to delete, \
2282 pause, or resume print job. User name: %s. Printer name: %s.",
2283 uidtoname(server_info->utok.uid),
2284 lp_printername(snum) );
2285 /* END_ADMIN_LOG */
2287 return WERR_ACCESS_DENIED;
2291 * get the spooled filename of the print job
2292 * if this works, then the file has not been spooled
2293 * to the underlying print system. Just delete the
2294 * spool file & return.
2297 fname = print_job_fname(sharename, jobid);
2298 if (fname != NULL) {
2299 /* remove the spool file */
2300 DEBUG(10, ("print_job_delete: "
2301 "Removing spool file [%s]\n", fname));
2302 if (unlink(fname) == -1) {
2303 return map_werror_from_unix(errno);
2307 if (!print_job_delete1(server_event_context(), msg_ctx, snum, jobid)) {
2308 return WERR_ACCESS_DENIED;
2311 /* force update the database and say the delete failed if the
2312 job still exists */
2314 print_queue_update(msg_ctx, snum, True);
2316 pjob = print_job_find(sharename, jobid);
2317 if (pjob && (pjob->status != LPQ_DELETING)) {
2318 return WERR_ACCESS_DENIED;
2321 return WERR_PRINTER_HAS_JOBS_QUEUED;
2324 /****************************************************************************
2325 Pause a job.
2326 ****************************************************************************/
2328 bool print_job_pause(const struct auth_serversupplied_info *server_info,
2329 struct messaging_context *msg_ctx,
2330 int snum, uint32 jobid, WERROR *errcode)
2332 const char* sharename = lp_const_servicename(snum);
2333 struct printjob *pjob;
2334 int ret = -1;
2335 struct printif *current_printif = get_printer_fns( snum );
2337 pjob = print_job_find(sharename, jobid);
2339 if (!pjob || !server_info) {
2340 DEBUG(10, ("print_job_pause: no pjob or user for jobid %u\n",
2341 (unsigned int)jobid ));
2342 return False;
2345 if (!pjob->spooled || pjob->sysjob == -1) {
2346 DEBUG(10, ("print_job_pause: not spooled or bad sysjob = %d for jobid %u\n",
2347 (int)pjob->sysjob, (unsigned int)jobid ));
2348 return False;
2351 if (!is_owner(server_info, lp_const_servicename(snum), jobid) &&
2352 !print_access_check(server_info, msg_ctx, snum,
2353 JOB_ACCESS_ADMINISTER)) {
2354 DEBUG(3, ("pause denied by security descriptor\n"));
2356 /* BEGIN_ADMIN_LOG */
2357 sys_adminlog( LOG_ERR,
2358 "Permission denied-- user not allowed to delete, \
2359 pause, or resume print job. User name: %s. Printer name: %s.",
2360 uidtoname(server_info->utok.uid),
2361 lp_printername(snum) );
2362 /* END_ADMIN_LOG */
2364 *errcode = WERR_ACCESS_DENIED;
2365 return False;
2368 /* need to pause the spooled entry */
2369 ret = (*(current_printif->job_pause))(snum, pjob);
2371 if (ret != 0) {
2372 *errcode = WERR_INVALID_PARAM;
2373 return False;
2376 /* force update the database */
2377 print_cache_flush(lp_const_servicename(snum));
2379 /* Send a printer notify message */
2381 notify_job_status(server_event_context(), msg_ctx, sharename, jobid,
2382 JOB_STATUS_PAUSED);
2384 /* how do we tell if this succeeded? */
2386 return True;
2389 /****************************************************************************
2390 Resume a job.
2391 ****************************************************************************/
2393 bool print_job_resume(const struct auth_serversupplied_info *server_info,
2394 struct messaging_context *msg_ctx,
2395 int snum, uint32 jobid, WERROR *errcode)
2397 const char *sharename = lp_const_servicename(snum);
2398 struct printjob *pjob;
2399 int ret;
2400 struct printif *current_printif = get_printer_fns( snum );
2402 pjob = print_job_find(sharename, jobid);
2404 if (!pjob || !server_info) {
2405 DEBUG(10, ("print_job_resume: no pjob or user for jobid %u\n",
2406 (unsigned int)jobid ));
2407 return False;
2410 if (!pjob->spooled || pjob->sysjob == -1) {
2411 DEBUG(10, ("print_job_resume: not spooled or bad sysjob = %d for jobid %u\n",
2412 (int)pjob->sysjob, (unsigned int)jobid ));
2413 return False;
2416 if (!is_owner(server_info, lp_const_servicename(snum), jobid) &&
2417 !print_access_check(server_info, msg_ctx, snum,
2418 JOB_ACCESS_ADMINISTER)) {
2419 DEBUG(3, ("resume denied by security descriptor\n"));
2420 *errcode = WERR_ACCESS_DENIED;
2422 /* BEGIN_ADMIN_LOG */
2423 sys_adminlog( LOG_ERR,
2424 "Permission denied-- user not allowed to delete, \
2425 pause, or resume print job. User name: %s. Printer name: %s.",
2426 uidtoname(server_info->utok.uid),
2427 lp_printername(snum) );
2428 /* END_ADMIN_LOG */
2429 return False;
2432 ret = (*(current_printif->job_resume))(snum, pjob);
2434 if (ret != 0) {
2435 *errcode = WERR_INVALID_PARAM;
2436 return False;
2439 /* force update the database */
2440 print_cache_flush(lp_const_servicename(snum));
2442 /* Send a printer notify message */
2444 notify_job_status(server_event_context(), msg_ctx, sharename, jobid,
2445 JOB_STATUS_QUEUED);
2447 return True;
2450 /****************************************************************************
2451 Write to a print file.
2452 ****************************************************************************/
2454 ssize_t print_job_write(struct tevent_context *ev,
2455 struct messaging_context *msg_ctx,
2456 int snum, uint32 jobid, const char *buf, size_t size)
2458 const char* sharename = lp_const_servicename(snum);
2459 ssize_t return_code;
2460 struct printjob *pjob;
2462 pjob = print_job_find(sharename, jobid);
2464 if (!pjob)
2465 return -1;
2466 /* don't allow another process to get this info - it is meaningless */
2467 if (pjob->pid != sys_getpid())
2468 return -1;
2470 /* if SMBD is spooling this can't be allowed */
2471 if (pjob->status == PJOB_SMBD_SPOOLING) {
2472 return -1;
2475 return_code = write_data(pjob->fd, buf, size);
2477 if (return_code>0) {
2478 pjob->size += size;
2479 pjob_store(ev, msg_ctx, sharename, jobid, pjob);
2481 return return_code;
2484 /****************************************************************************
2485 Get the queue status - do not update if db is out of date.
2486 ****************************************************************************/
2488 static int get_queue_status(const char* sharename, print_status_struct *status)
2490 fstring keystr;
2491 TDB_DATA data;
2492 struct tdb_print_db *pdb = get_print_db_byname(sharename);
2493 int len;
2495 if (status) {
2496 ZERO_STRUCTP(status);
2499 if (!pdb)
2500 return 0;
2502 if (status) {
2503 fstr_sprintf(keystr, "STATUS/%s", sharename);
2504 data = tdb_fetch(pdb->tdb, string_tdb_data(keystr));
2505 if (data.dptr) {
2506 if (data.dsize == sizeof(print_status_struct))
2507 /* this memcpy is ok since the status struct was
2508 not packed before storing it in the tdb */
2509 memcpy(status, data.dptr, sizeof(print_status_struct));
2510 SAFE_FREE(data.dptr);
2513 len = tdb_fetch_int32(pdb->tdb, "INFO/total_jobs");
2514 release_print_db(pdb);
2515 return (len == -1 ? 0 : len);
2518 /****************************************************************************
2519 Determine the number of jobs in a queue.
2520 ****************************************************************************/
2522 int print_queue_length(struct messaging_context *msg_ctx, int snum,
2523 print_status_struct *pstatus)
2525 const char* sharename = lp_const_servicename( snum );
2526 print_status_struct status;
2527 int len;
2529 ZERO_STRUCT( status );
2531 /* make sure the database is up to date */
2532 if (print_cache_expired(lp_const_servicename(snum), True))
2533 print_queue_update(msg_ctx, snum, False);
2535 /* also fetch the queue status */
2536 memset(&status, 0, sizeof(status));
2537 len = get_queue_status(sharename, &status);
2539 if (pstatus)
2540 *pstatus = status;
2542 return len;
2545 /***************************************************************************
2546 Allocate a jobid. Hold the lock for as short a time as possible.
2547 ***************************************************************************/
2549 static WERROR allocate_print_jobid(struct tdb_print_db *pdb, int snum,
2550 const char *sharename, uint32 *pjobid)
2552 int i;
2553 uint32 jobid;
2554 enum TDB_ERROR terr;
2555 int ret;
2557 *pjobid = (uint32)-1;
2559 for (i = 0; i < 3; i++) {
2560 /* Lock the database - only wait 20 seconds. */
2561 ret = tdb_lock_bystring_with_timeout(pdb->tdb,
2562 "INFO/nextjob", 20);
2563 if (ret == -1) {
2564 DEBUG(0, ("allocate_print_jobid: "
2565 "Failed to lock printing database %s\n",
2566 sharename));
2567 terr = tdb_error(pdb->tdb);
2568 return ntstatus_to_werror(map_nt_error_from_tdb(terr));
2571 if (!tdb_fetch_uint32(pdb->tdb, "INFO/nextjob", &jobid)) {
2572 terr = tdb_error(pdb->tdb);
2573 if (terr != TDB_ERR_NOEXIST) {
2574 DEBUG(0, ("allocate_print_jobid: "
2575 "Failed to fetch INFO/nextjob "
2576 "for print queue %s\n", sharename));
2577 tdb_unlock_bystring(pdb->tdb, "INFO/nextjob");
2578 return ntstatus_to_werror(map_nt_error_from_tdb(terr));
2580 DEBUG(10, ("allocate_print_jobid: "
2581 "No existing jobid in %s\n", sharename));
2582 jobid = 0;
2585 DEBUG(10, ("allocate_print_jobid: "
2586 "Read jobid %u from %s\n", jobid, sharename));
2588 jobid = NEXT_JOBID(jobid);
2590 ret = tdb_store_int32(pdb->tdb, "INFO/nextjob", jobid);
2591 if (ret == -1) {
2592 terr = tdb_error(pdb->tdb);
2593 DEBUG(3, ("allocate_print_jobid: "
2594 "Failed to store INFO/nextjob.\n"));
2595 tdb_unlock_bystring(pdb->tdb, "INFO/nextjob");
2596 return ntstatus_to_werror(map_nt_error_from_tdb(terr));
2599 /* We've finished with the INFO/nextjob lock. */
2600 tdb_unlock_bystring(pdb->tdb, "INFO/nextjob");
2602 if (!print_job_exists(sharename, jobid)) {
2603 break;
2605 DEBUG(10, ("allocate_print_jobid: "
2606 "Found jobid %u in %s\n", jobid, sharename));
2609 if (i > 2) {
2610 DEBUG(0, ("allocate_print_jobid: "
2611 "Failed to allocate a print job for queue %s\n",
2612 sharename));
2613 /* Probably full... */
2614 return WERR_NO_SPOOL_SPACE;
2617 /* Store a dummy placeholder. */
2619 uint32_t tmp;
2620 TDB_DATA dum;
2621 dum.dptr = NULL;
2622 dum.dsize = 0;
2623 if (tdb_store(pdb->tdb, print_key(jobid, &tmp), dum,
2624 TDB_INSERT) == -1) {
2625 DEBUG(3, ("allocate_print_jobid: "
2626 "jobid (%d) failed to store placeholder.\n",
2627 jobid ));
2628 terr = tdb_error(pdb->tdb);
2629 return ntstatus_to_werror(map_nt_error_from_tdb(terr));
2633 *pjobid = jobid;
2634 return WERR_OK;
2637 /***************************************************************************
2638 Append a jobid to the 'jobs added' list.
2639 ***************************************************************************/
2641 static bool add_to_jobs_added(struct tdb_print_db *pdb, uint32 jobid)
2643 TDB_DATA data;
2644 uint32 store_jobid;
2646 SIVAL(&store_jobid, 0, jobid);
2647 data.dptr = (uint8 *)&store_jobid;
2648 data.dsize = 4;
2650 DEBUG(10,("add_to_jobs_added: Added jobid %u\n", (unsigned int)jobid ));
2652 return (tdb_append(pdb->tdb, string_tdb_data("INFO/jobs_added"),
2653 data) == 0);
2657 /***************************************************************************
2658 Do all checks needed to determine if we can start a job.
2659 ***************************************************************************/
2661 static WERROR print_job_checks(const struct auth_serversupplied_info *server_info,
2662 struct messaging_context *msg_ctx,
2663 int snum, int *njobs)
2665 const char *sharename = lp_const_servicename(snum);
2666 uint64_t dspace, dsize;
2667 uint64_t minspace;
2668 int ret;
2670 if (!print_access_check(server_info, msg_ctx, snum,
2671 PRINTER_ACCESS_USE)) {
2672 DEBUG(3, ("print_job_checks: "
2673 "job start denied by security descriptor\n"));
2674 return WERR_ACCESS_DENIED;
2677 if (!print_time_access_check(server_info, msg_ctx, sharename)) {
2678 DEBUG(3, ("print_job_checks: "
2679 "job start denied by time check\n"));
2680 return WERR_ACCESS_DENIED;
2683 /* see if we have sufficient disk space */
2684 if (lp_minprintspace(snum)) {
2685 minspace = lp_minprintspace(snum);
2686 ret = sys_fsusage(lp_pathname(snum), &dspace, &dsize);
2687 if (ret == 0 && dspace < 2*minspace) {
2688 DEBUG(3, ("print_job_checks: "
2689 "disk space check failed.\n"));
2690 return WERR_NO_SPOOL_SPACE;
2694 /* for autoloaded printers, check that the printcap entry still exists */
2695 if (lp_autoloaded(snum) && !pcap_printername_ok(sharename)) {
2696 DEBUG(3, ("print_job_checks: printer name %s check failed.\n",
2697 sharename));
2698 return WERR_ACCESS_DENIED;
2701 /* Insure the maximum queue size is not violated */
2702 *njobs = print_queue_length(msg_ctx, snum, NULL);
2703 if (*njobs > lp_maxprintjobs(snum)) {
2704 DEBUG(3, ("print_job_checks: Queue %s number of jobs (%d) "
2705 "larger than max printjobs per queue (%d).\n",
2706 sharename, *njobs, lp_maxprintjobs(snum)));
2707 return WERR_NO_SPOOL_SPACE;
2710 return WERR_OK;
2713 /***************************************************************************
2714 Create a job file.
2715 ***************************************************************************/
2717 static WERROR print_job_spool_file(int snum, uint32_t jobid,
2718 const char *output_file,
2719 struct printjob *pjob)
2721 WERROR werr;
2722 SMB_STRUCT_STAT st;
2723 const char *path;
2724 int len;
2726 /* if this file is within the printer path, it means that smbd
2727 * is spooling it and will pass us control when it is finished.
2728 * Verify that the file name is ok, within path, and it is
2729 * already already there */
2730 if (output_file) {
2731 path = lp_pathname(snum);
2732 len = strlen(path);
2733 if (strncmp(output_file, path, len) == 0 &&
2734 (output_file[len - 1] == '/' || output_file[len] == '/')) {
2736 /* verify path is not too long */
2737 if (strlen(output_file) >= sizeof(pjob->filename)) {
2738 return WERR_INVALID_NAME;
2741 /* verify that the file exists */
2742 if (sys_stat(output_file, &st, false) != 0) {
2743 return WERR_INVALID_NAME;
2746 fstrcpy(pjob->filename, output_file);
2748 DEBUG(3, ("print_job_spool_file:"
2749 "External spooling activated"));
2751 /* we do not open the file until spooling is done */
2752 pjob->fd = -1;
2753 pjob->status = PJOB_SMBD_SPOOLING;
2755 return WERR_OK;
2759 slprintf(pjob->filename, sizeof(pjob->filename)-1,
2760 "%s/%s%.8u.XXXXXX", lp_pathname(snum),
2761 PRINT_SPOOL_PREFIX, (unsigned int)jobid);
2762 pjob->fd = mkstemp(pjob->filename);
2764 if (pjob->fd == -1) {
2765 werr = map_werror_from_unix(errno);
2766 if (W_ERROR_EQUAL(werr, WERR_ACCESS_DENIED)) {
2767 /* Common setup error, force a report. */
2768 DEBUG(0, ("print_job_spool_file: "
2769 "insufficient permissions to open spool "
2770 "file %s.\n", pjob->filename));
2771 } else {
2772 /* Normal case, report at level 3 and above. */
2773 DEBUG(3, ("print_job_spool_file: "
2774 "can't open spool file %s\n",
2775 pjob->filename));
2777 return werr;
2780 return WERR_OK;
2783 /***************************************************************************
2784 Start spooling a job - return the jobid.
2785 ***************************************************************************/
2787 WERROR print_job_start(const struct auth_serversupplied_info *server_info,
2788 struct messaging_context *msg_ctx,
2789 const char *clientmachine,
2790 int snum, const char *docname, const char *filename,
2791 struct spoolss_DeviceMode *devmode, uint32_t *_jobid)
2793 uint32_t jobid;
2794 char *path;
2795 struct printjob pjob;
2796 const char *sharename = lp_const_servicename(snum);
2797 struct tdb_print_db *pdb = get_print_db_byname(sharename);
2798 int njobs;
2799 WERROR werr;
2801 if (!pdb) {
2802 return WERR_INTERNAL_DB_CORRUPTION;
2805 path = lp_pathname(snum);
2807 werr = print_job_checks(server_info, msg_ctx, snum, &njobs);
2808 if (!W_ERROR_IS_OK(werr)) {
2809 release_print_db(pdb);
2810 return werr;
2813 DEBUG(10, ("print_job_start: "
2814 "Queue %s number of jobs (%d), max printjobs = %d\n",
2815 sharename, njobs, lp_maxprintjobs(snum)));
2817 werr = allocate_print_jobid(pdb, snum, sharename, &jobid);
2818 if (!W_ERROR_IS_OK(werr)) {
2819 goto fail;
2822 /* create the database entry */
2824 ZERO_STRUCT(pjob);
2826 pjob.pid = sys_getpid();
2827 pjob.sysjob = -1;
2828 pjob.fd = -1;
2829 pjob.starttime = time(NULL);
2830 pjob.status = LPQ_SPOOLING;
2831 pjob.size = 0;
2832 pjob.spooled = False;
2833 pjob.smbjob = True;
2834 pjob.devmode = devmode;
2836 fstrcpy(pjob.jobname, docname);
2838 fstrcpy(pjob.clientmachine, clientmachine);
2840 fstrcpy(pjob.user, lp_printjob_username(snum));
2841 standard_sub_advanced(sharename, server_info->sanitized_username,
2842 path, server_info->utok.gid,
2843 server_info->sanitized_username,
2844 server_info->info3->base.domain.string,
2845 pjob.user, sizeof(pjob.user)-1);
2846 /* ensure NULL termination */
2847 pjob.user[sizeof(pjob.user)-1] = '\0';
2849 fstrcpy(pjob.queuename, lp_const_servicename(snum));
2851 /* we have a job entry - now create the spool file */
2852 werr = print_job_spool_file(snum, jobid, filename, &pjob);
2853 if (!W_ERROR_IS_OK(werr)) {
2854 goto fail;
2857 pjob_store(server_event_context(), msg_ctx, sharename, jobid, &pjob);
2859 /* Update the 'jobs added' entry used by print_queue_status. */
2860 add_to_jobs_added(pdb, jobid);
2862 /* Ensure we keep a rough count of the number of total jobs... */
2863 tdb_change_int32_atomic(pdb->tdb, "INFO/total_jobs", &njobs, 1);
2865 release_print_db(pdb);
2867 *_jobid = jobid;
2868 return WERR_OK;
2870 fail:
2871 if (jobid != -1) {
2872 pjob_delete(server_event_context(), msg_ctx, sharename, jobid);
2875 release_print_db(pdb);
2877 DEBUG(3, ("print_job_start: returning fail. "
2878 "Error = %s\n", win_errstr(werr)));
2879 return werr;
2882 /****************************************************************************
2883 Update the number of pages spooled to jobid
2884 ****************************************************************************/
2886 void print_job_endpage(struct messaging_context *msg_ctx,
2887 int snum, uint32 jobid)
2889 const char* sharename = lp_const_servicename(snum);
2890 struct printjob *pjob;
2892 pjob = print_job_find(sharename, jobid);
2893 if (!pjob)
2894 return;
2895 /* don't allow another process to get this info - it is meaningless */
2896 if (pjob->pid != sys_getpid())
2897 return;
2899 pjob->page_count++;
2900 pjob_store(server_event_context(), msg_ctx, sharename, jobid, pjob);
2903 /****************************************************************************
2904 Print a file - called on closing the file. This spools the job.
2905 If normal close is false then we're tearing down the jobs - treat as an
2906 error.
2907 ****************************************************************************/
2909 NTSTATUS print_job_end(struct messaging_context *msg_ctx, int snum,
2910 uint32 jobid, enum file_close_type close_type)
2912 const char* sharename = lp_const_servicename(snum);
2913 struct printjob *pjob;
2914 int ret;
2915 SMB_STRUCT_STAT sbuf;
2916 struct printif *current_printif = get_printer_fns( snum );
2917 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
2919 pjob = print_job_find(sharename, jobid);
2921 if (!pjob) {
2922 return NT_STATUS_PRINT_CANCELLED;
2925 if (pjob->spooled || pjob->pid != sys_getpid()) {
2926 return NT_STATUS_ACCESS_DENIED;
2929 if (close_type == NORMAL_CLOSE || close_type == SHUTDOWN_CLOSE) {
2930 if (pjob->status == PJOB_SMBD_SPOOLING) {
2931 /* take over the file now, smbd is done */
2932 if (sys_stat(pjob->filename, &sbuf, false) != 0) {
2933 status = map_nt_error_from_unix(errno);
2934 DEBUG(3, ("print_job_end: "
2935 "stat file failed for jobid %d\n",
2936 jobid));
2937 goto fail;
2940 pjob->status = LPQ_SPOOLING;
2942 } else {
2944 if ((sys_fstat(pjob->fd, &sbuf, false) != 0)) {
2945 status = map_nt_error_from_unix(errno);
2946 close(pjob->fd);
2947 DEBUG(3, ("print_job_end: "
2948 "stat file failed for jobid %d\n",
2949 jobid));
2950 goto fail;
2953 close(pjob->fd);
2956 pjob->size = sbuf.st_ex_size;
2957 } else {
2960 * Not a normal close, something has gone wrong. Cleanup.
2962 if (pjob->fd != -1) {
2963 close(pjob->fd);
2965 goto fail;
2968 /* Technically, this is not quite right. If the printer has a separator
2969 * page turned on, the NT spooler prints the separator page even if the
2970 * print job is 0 bytes. 010215 JRR */
2971 if (pjob->size == 0 || pjob->status == LPQ_DELETING) {
2972 /* don't bother spooling empty files or something being deleted. */
2973 DEBUG(5,("print_job_end: canceling spool of %s (%s)\n",
2974 pjob->filename, pjob->size ? "deleted" : "zero length" ));
2975 unlink(pjob->filename);
2976 pjob_delete(server_event_context(), msg_ctx, sharename, jobid);
2977 return NT_STATUS_OK;
2980 ret = (*(current_printif->job_submit))(snum, pjob);
2982 if (ret) {
2983 status = NT_STATUS_PRINT_CANCELLED;
2984 goto fail;
2987 /* The print job has been successfully handed over to the back-end */
2989 pjob->spooled = True;
2990 pjob->status = LPQ_QUEUED;
2991 pjob_store(server_event_context(), msg_ctx, sharename, jobid, pjob);
2993 /* make sure the database is up to date */
2994 if (print_cache_expired(lp_const_servicename(snum), True))
2995 print_queue_update(msg_ctx, snum, False);
2997 return NT_STATUS_OK;
2999 fail:
3001 /* The print job was not successfully started. Cleanup */
3002 /* Still need to add proper error return propagation! 010122:JRR */
3003 pjob->fd = -1;
3004 unlink(pjob->filename);
3005 pjob_delete(server_event_context(), msg_ctx, sharename, jobid);
3006 return status;
3009 /****************************************************************************
3010 Get a snapshot of jobs in the system without traversing.
3011 ****************************************************************************/
3013 static bool get_stored_queue_info(struct messaging_context *msg_ctx,
3014 struct tdb_print_db *pdb, int snum,
3015 int *pcount, print_queue_struct **ppqueue)
3017 TDB_DATA data, cgdata, jcdata;
3018 print_queue_struct *queue = NULL;
3019 uint32 qcount = 0;
3020 uint32 extra_count = 0;
3021 uint32_t changed_count = 0;
3022 int total_count = 0;
3023 size_t len = 0;
3024 uint32 i;
3025 int max_reported_jobs = lp_max_reported_jobs(snum);
3026 bool ret = False;
3027 const char* sharename = lp_servicename(snum);
3029 /* make sure the database is up to date */
3030 if (print_cache_expired(lp_const_servicename(snum), True))
3031 print_queue_update(msg_ctx, snum, False);
3033 *pcount = 0;
3034 *ppqueue = NULL;
3036 ZERO_STRUCT(data);
3037 ZERO_STRUCT(cgdata);
3039 /* Get the stored queue data. */
3040 data = tdb_fetch(pdb->tdb, string_tdb_data("INFO/linear_queue_array"));
3042 if (data.dptr && data.dsize >= sizeof(qcount))
3043 len += tdb_unpack(data.dptr + len, data.dsize - len, "d", &qcount);
3045 /* Get the added jobs list. */
3046 cgdata = tdb_fetch(pdb->tdb, string_tdb_data("INFO/jobs_added"));
3047 if (cgdata.dptr != NULL && (cgdata.dsize % 4 == 0))
3048 extra_count = cgdata.dsize/4;
3050 /* Get the changed jobs list. */
3051 jcdata = tdb_fetch(pdb->tdb, string_tdb_data("INFO/jobs_changed"));
3052 if (jcdata.dptr != NULL && (jcdata.dsize % 4 == 0))
3053 changed_count = jcdata.dsize / 4;
3055 DEBUG(5,("get_stored_queue_info: qcount = %u, extra_count = %u\n", (unsigned int)qcount, (unsigned int)extra_count));
3057 /* Allocate the queue size. */
3058 if (qcount == 0 && extra_count == 0)
3059 goto out;
3061 if ((queue = SMB_MALLOC_ARRAY(print_queue_struct, qcount + extra_count)) == NULL)
3062 goto out;
3064 /* Retrieve the linearised queue data. */
3066 for( i = 0; i < qcount; i++) {
3067 uint32 qjob, qsize, qpage_count, qstatus, qpriority, qtime;
3068 len += tdb_unpack(data.dptr + len, data.dsize - len, "ddddddff",
3069 &qjob,
3070 &qsize,
3071 &qpage_count,
3072 &qstatus,
3073 &qpriority,
3074 &qtime,
3075 queue[i].fs_user,
3076 queue[i].fs_file);
3077 queue[i].job = qjob;
3078 queue[i].size = qsize;
3079 queue[i].page_count = qpage_count;
3080 queue[i].status = qstatus;
3081 queue[i].priority = qpriority;
3082 queue[i].time = qtime;
3085 total_count = qcount;
3087 /* Add new jobids to the queue. */
3088 for( i = 0; i < extra_count; i++) {
3089 uint32 jobid;
3090 struct printjob *pjob;
3092 jobid = IVAL(cgdata.dptr, i*4);
3093 DEBUG(5,("get_stored_queue_info: added job = %u\n", (unsigned int)jobid));
3094 pjob = print_job_find(lp_const_servicename(snum), jobid);
3095 if (!pjob) {
3096 DEBUG(5,("get_stored_queue_info: failed to find added job = %u\n", (unsigned int)jobid));
3097 remove_from_jobs_added(sharename, jobid);
3098 continue;
3101 queue[total_count].job = jobid;
3102 queue[total_count].size = pjob->size;
3103 queue[total_count].page_count = pjob->page_count;
3104 queue[total_count].status = pjob->status;
3105 queue[total_count].priority = 1;
3106 queue[total_count].time = pjob->starttime;
3107 fstrcpy(queue[total_count].fs_user, pjob->user);
3108 fstrcpy(queue[total_count].fs_file, pjob->jobname);
3109 total_count++;
3112 /* Update the changed jobids. */
3113 for (i = 0; i < changed_count; i++) {
3114 uint32_t jobid = IVAL(jcdata.dptr, i * 4);
3115 uint32_t j;
3116 bool found = false;
3118 for (j = 0; j < total_count; j++) {
3119 if (queue[j].job == jobid) {
3120 found = true;
3121 break;
3125 if (found) {
3126 struct printjob *pjob;
3128 DEBUG(5,("get_stored_queue_info: changed job: %u\n",
3129 (unsigned int) jobid));
3131 pjob = print_job_find(sharename, jobid);
3132 if (pjob == NULL) {
3133 DEBUG(5,("get_stored_queue_info: failed to find "
3134 "changed job = %u\n",
3135 (unsigned int) jobid));
3136 remove_from_jobs_changed(sharename, jobid);
3137 continue;
3140 queue[j].job = jobid;
3141 queue[j].size = pjob->size;
3142 queue[j].page_count = pjob->page_count;
3143 queue[j].status = pjob->status;
3144 queue[j].priority = 1;
3145 queue[j].time = pjob->starttime;
3146 fstrcpy(queue[j].fs_user, pjob->user);
3147 fstrcpy(queue[j].fs_file, pjob->jobname);
3149 DEBUG(5,("get_stored_queue_info: updated queue[%u], jobid: %u, jobname: %s\n",
3150 (unsigned int) j, (unsigned int) jobid, pjob->jobname));
3153 remove_from_jobs_changed(sharename, jobid);
3156 /* Sort the queue by submission time otherwise they are displayed
3157 in hash order. */
3159 TYPESAFE_QSORT(queue, total_count, printjob_comp);
3161 DEBUG(5,("get_stored_queue_info: total_count = %u\n", (unsigned int)total_count));
3163 if (max_reported_jobs && total_count > max_reported_jobs)
3164 total_count = max_reported_jobs;
3166 *ppqueue = queue;
3167 *pcount = total_count;
3169 ret = True;
3171 out:
3173 SAFE_FREE(data.dptr);
3174 SAFE_FREE(cgdata.dptr);
3175 return ret;
3178 /****************************************************************************
3179 Get a printer queue listing.
3180 set queue = NULL and status = NULL if you just want to update the cache
3181 ****************************************************************************/
3183 int print_queue_status(struct messaging_context *msg_ctx, int snum,
3184 print_queue_struct **ppqueue,
3185 print_status_struct *status)
3187 fstring keystr;
3188 TDB_DATA data, key;
3189 const char *sharename;
3190 struct tdb_print_db *pdb;
3191 int count = 0;
3193 /* make sure the database is up to date */
3195 if (print_cache_expired(lp_const_servicename(snum), True))
3196 print_queue_update(msg_ctx, snum, False);
3198 /* return if we are done */
3199 if ( !ppqueue || !status )
3200 return 0;
3202 *ppqueue = NULL;
3203 sharename = lp_const_servicename(snum);
3204 pdb = get_print_db_byname(sharename);
3206 if (!pdb)
3207 return 0;
3210 * Fetch the queue status. We must do this first, as there may
3211 * be no jobs in the queue.
3214 ZERO_STRUCTP(status);
3215 slprintf(keystr, sizeof(keystr)-1, "STATUS/%s", sharename);
3216 key = string_tdb_data(keystr);
3218 data = tdb_fetch(pdb->tdb, key);
3219 if (data.dptr) {
3220 if (data.dsize == sizeof(*status)) {
3221 /* this memcpy is ok since the status struct was
3222 not packed before storing it in the tdb */
3223 memcpy(status, data.dptr, sizeof(*status));
3225 SAFE_FREE(data.dptr);
3229 * Now, fetch the print queue information. We first count the number
3230 * of entries, and then only retrieve the queue if necessary.
3233 if (!get_stored_queue_info(msg_ctx, pdb, snum, &count, ppqueue)) {
3234 release_print_db(pdb);
3235 return 0;
3238 release_print_db(pdb);
3239 return count;
3242 /****************************************************************************
3243 Pause a queue.
3244 ****************************************************************************/
3246 WERROR print_queue_pause(const struct auth_serversupplied_info *server_info,
3247 struct messaging_context *msg_ctx, int snum)
3249 int ret;
3250 struct printif *current_printif = get_printer_fns( snum );
3252 if (!print_access_check(server_info, msg_ctx, snum,
3253 PRINTER_ACCESS_ADMINISTER)) {
3254 return WERR_ACCESS_DENIED;
3258 become_root();
3260 ret = (*(current_printif->queue_pause))(snum);
3262 unbecome_root();
3264 if (ret != 0) {
3265 return WERR_INVALID_PARAM;
3268 /* force update the database */
3269 print_cache_flush(lp_const_servicename(snum));
3271 /* Send a printer notify message */
3273 notify_printer_status(server_event_context(), msg_ctx, snum,
3274 PRINTER_STATUS_PAUSED);
3276 return WERR_OK;
3279 /****************************************************************************
3280 Resume a queue.
3281 ****************************************************************************/
3283 WERROR print_queue_resume(const struct auth_serversupplied_info *server_info,
3284 struct messaging_context *msg_ctx, int snum)
3286 int ret;
3287 struct printif *current_printif = get_printer_fns( snum );
3289 if (!print_access_check(server_info, msg_ctx, snum,
3290 PRINTER_ACCESS_ADMINISTER)) {
3291 return WERR_ACCESS_DENIED;
3294 become_root();
3296 ret = (*(current_printif->queue_resume))(snum);
3298 unbecome_root();
3300 if (ret != 0) {
3301 return WERR_INVALID_PARAM;
3304 /* make sure the database is up to date */
3305 if (print_cache_expired(lp_const_servicename(snum), True))
3306 print_queue_update(msg_ctx, snum, True);
3308 /* Send a printer notify message */
3310 notify_printer_status(server_event_context(), msg_ctx, snum,
3311 PRINTER_STATUS_OK);
3313 return WERR_OK;
3316 /****************************************************************************
3317 Purge a queue - implemented by deleting all jobs that we can delete.
3318 ****************************************************************************/
3320 WERROR print_queue_purge(const struct auth_serversupplied_info *server_info,
3321 struct messaging_context *msg_ctx, int snum)
3323 print_queue_struct *queue;
3324 print_status_struct status;
3325 int njobs, i;
3326 bool can_job_admin;
3328 /* Force and update so the count is accurate (i.e. not a cached count) */
3329 print_queue_update(msg_ctx, snum, True);
3331 can_job_admin = print_access_check(server_info,
3332 msg_ctx,
3333 snum,
3334 JOB_ACCESS_ADMINISTER);
3335 njobs = print_queue_status(msg_ctx, snum, &queue, &status);
3337 if ( can_job_admin )
3338 become_root();
3340 for (i=0;i<njobs;i++) {
3341 bool owner = is_owner(server_info, lp_const_servicename(snum),
3342 queue[i].job);
3344 if (owner || can_job_admin) {
3345 print_job_delete1(server_event_context(), msg_ctx,
3346 snum, queue[i].job);
3350 if ( can_job_admin )
3351 unbecome_root();
3353 /* update the cache */
3354 print_queue_update(msg_ctx, snum, True);
3356 SAFE_FREE(queue);
3358 return WERR_OK;