source: vendor/3.6.0/source3/printing/printing.c

Last change on this file was 740, checked in by Silvan Scherrer, 13 years ago

Samba Server: update vendor to 3.6.0

File size: 91.4 KB
Line 
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
7
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.
12
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.
17
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/>.
20*/
21
22#include "includes.h"
23#include "system/syslog.h"
24#include "system/filesys.h"
25#include "printing.h"
26#include "../librpc/gen_ndr/ndr_spoolss.h"
27#include "nt_printing.h"
28#include "../librpc/gen_ndr/netlogon.h"
29#include "printing/notify.h"
30#include "printing/pcap.h"
31#include "serverid.h"
32#include "smbd/smbd.h"
33#include "auth.h"
34#include "messages.h"
35#include "util_tdb.h"
36
37extern struct current_user current_user;
38extern userdom_struct current_user_info;
39
40/* Current printer interface */
41static bool remove_from_jobs_added(const char* sharename, uint32 jobid);
42
43/*
44 the printing backend revolves around a tdb database that stores the
45 SMB view of the print queue
46
47 The key for this database is a jobid - a internally generated number that
48 uniquely identifies a print job
49
50 reading the print queue involves two steps:
51 - possibly running lpq and updating the internal database from that
52 - reading entries from the database
53
54 jobids are assigned when a job starts spooling.
55*/
56
57static TDB_CONTEXT *rap_tdb;
58static uint16 next_rap_jobid;
59struct rap_jobid_key {
60 fstring sharename;
61 uint32 jobid;
62};
63
64/***************************************************************************
65 Nightmare. LANMAN jobid's are 16 bit numbers..... We must map them to 32
66 bit RPC jobids.... JRA.
67***************************************************************************/
68
69uint16 pjobid_to_rap(const char* sharename, uint32 jobid)
70{
71 uint16 rap_jobid;
72 TDB_DATA data, key;
73 struct rap_jobid_key jinfo;
74 uint8 buf[2];
75
76 DEBUG(10,("pjobid_to_rap: called.\n"));
77
78 if (!rap_tdb) {
79 /* Create the in-memory tdb. */
80 rap_tdb = tdb_open_log(NULL, 0, TDB_INTERNAL, (O_RDWR|O_CREAT), 0644);
81 if (!rap_tdb)
82 return 0;
83 }
84
85 ZERO_STRUCT( jinfo );
86 fstrcpy( jinfo.sharename, sharename );
87 jinfo.jobid = jobid;
88 key.dptr = (uint8 *)&jinfo;
89 key.dsize = sizeof(jinfo);
90
91 data = tdb_fetch(rap_tdb, key);
92 if (data.dptr && data.dsize == sizeof(uint16)) {
93 rap_jobid = SVAL(data.dptr, 0);
94 SAFE_FREE(data.dptr);
95 DEBUG(10,("pjobid_to_rap: jobid %u maps to RAP jobid %u\n",
96 (unsigned int)jobid, (unsigned int)rap_jobid));
97 return rap_jobid;
98 }
99 SAFE_FREE(data.dptr);
100 /* Not found - create and store mapping. */
101 rap_jobid = ++next_rap_jobid;
102 if (rap_jobid == 0)
103 rap_jobid = ++next_rap_jobid;
104 SSVAL(buf,0,rap_jobid);
105 data.dptr = buf;
106 data.dsize = sizeof(rap_jobid);
107 tdb_store(rap_tdb, key, data, TDB_REPLACE);
108 tdb_store(rap_tdb, data, key, TDB_REPLACE);
109
110 DEBUG(10,("pjobid_to_rap: created jobid %u maps to RAP jobid %u\n",
111 (unsigned int)jobid, (unsigned int)rap_jobid));
112 return rap_jobid;
113}
114
115bool rap_to_pjobid(uint16 rap_jobid, fstring sharename, uint32 *pjobid)
116{
117 TDB_DATA data, key;
118 uint8 buf[2];
119
120 DEBUG(10,("rap_to_pjobid called.\n"));
121
122 if (!rap_tdb)
123 return False;
124
125 SSVAL(buf,0,rap_jobid);
126 key.dptr = buf;
127 key.dsize = sizeof(rap_jobid);
128 data = tdb_fetch(rap_tdb, key);
129 if ( data.dptr && data.dsize == sizeof(struct rap_jobid_key) )
130 {
131 struct rap_jobid_key *jinfo = (struct rap_jobid_key*)data.dptr;
132 if (sharename != NULL) {
133 fstrcpy( sharename, jinfo->sharename );
134 }
135 *pjobid = jinfo->jobid;
136 DEBUG(10,("rap_to_pjobid: jobid %u maps to RAP jobid %u\n",
137 (unsigned int)*pjobid, (unsigned int)rap_jobid));
138 SAFE_FREE(data.dptr);
139 return True;
140 }
141
142 DEBUG(10,("rap_to_pjobid: Failed to lookup RAP jobid %u\n",
143 (unsigned int)rap_jobid));
144 SAFE_FREE(data.dptr);
145 return False;
146}
147
148void rap_jobid_delete(const char* sharename, uint32 jobid)
149{
150 TDB_DATA key, data;
151 uint16 rap_jobid;
152 struct rap_jobid_key jinfo;
153 uint8 buf[2];
154
155 DEBUG(10,("rap_jobid_delete: called.\n"));
156
157 if (!rap_tdb)
158 return;
159
160 ZERO_STRUCT( jinfo );
161 fstrcpy( jinfo.sharename, sharename );
162 jinfo.jobid = jobid;
163 key.dptr = (uint8 *)&jinfo;
164 key.dsize = sizeof(jinfo);
165
166 data = tdb_fetch(rap_tdb, key);
167 if (!data.dptr || (data.dsize != sizeof(uint16))) {
168 DEBUG(10,("rap_jobid_delete: cannot find jobid %u\n",
169 (unsigned int)jobid ));
170 SAFE_FREE(data.dptr);
171 return;
172 }
173
174 DEBUG(10,("rap_jobid_delete: deleting jobid %u\n",
175 (unsigned int)jobid ));
176
177 rap_jobid = SVAL(data.dptr, 0);
178 SAFE_FREE(data.dptr);
179 SSVAL(buf,0,rap_jobid);
180 data.dptr = buf;
181 data.dsize = sizeof(rap_jobid);
182 tdb_delete(rap_tdb, key);
183 tdb_delete(rap_tdb, data);
184}
185
186static int get_queue_status(const char* sharename, print_status_struct *);
187
188/****************************************************************************
189 Initialise the printing backend. Called once at startup before the fork().
190****************************************************************************/
191
192bool print_backend_init(struct messaging_context *msg_ctx)
193{
194 const char *sversion = "INFO/version";
195 int services = lp_numservices();
196 int snum;
197
198 unlink(cache_path("printing.tdb"));
199 mkdir(cache_path("printing"),0755);
200
201 /* handle a Samba upgrade */
202
203 for (snum = 0; snum < services; snum++) {
204 struct tdb_print_db *pdb;
205 if (!lp_print_ok(snum))
206 continue;
207
208 pdb = get_print_db_byname(lp_const_servicename(snum));
209 if (!pdb)
210 continue;
211 if (tdb_lock_bystring(pdb->tdb, sversion) == -1) {
212 DEBUG(0,("print_backend_init: Failed to open printer %s database\n", lp_const_servicename(snum) ));
213 release_print_db(pdb);
214 return False;
215 }
216 if (tdb_fetch_int32(pdb->tdb, sversion) != PRINT_DATABASE_VERSION) {
217 tdb_wipe_all(pdb->tdb);
218 tdb_store_int32(pdb->tdb, sversion, PRINT_DATABASE_VERSION);
219 }
220 tdb_unlock_bystring(pdb->tdb, sversion);
221 release_print_db(pdb);
222 }
223
224 close_all_print_db(); /* Don't leave any open. */
225
226 /* do NT print initialization... */
227 return nt_printing_init(msg_ctx);
228}
229
230/****************************************************************************
231 Shut down printing backend. Called once at shutdown to close the tdb.
232****************************************************************************/
233
234void printing_end(void)
235{
236 close_all_print_db(); /* Don't leave any open. */
237}
238
239/****************************************************************************
240 Retrieve the set of printing functions for a given service. This allows
241 us to set the printer function table based on the value of the 'printing'
242 service parameter.
243
244 Use the generic interface as the default and only use cups interface only
245 when asked for (and only when supported)
246****************************************************************************/
247
248static struct printif *get_printer_fns_from_type( enum printing_types type )
249{
250 struct printif *printer_fns = &generic_printif;
251
252#ifdef HAVE_CUPS
253 if ( type == PRINT_CUPS ) {
254 printer_fns = &cups_printif;
255 }
256#endif /* HAVE_CUPS */
257
258#ifdef HAVE_IPRINT
259 if ( type == PRINT_IPRINT ) {
260 printer_fns = &iprint_printif;
261 }
262#endif /* HAVE_IPRINT */
263
264 printer_fns->type = type;
265
266 return printer_fns;
267}
268
269static struct printif *get_printer_fns( int snum )
270{
271 return get_printer_fns_from_type( (enum printing_types)lp_printing(snum) );
272}
273
274
275/****************************************************************************
276 Useful function to generate a tdb key.
277****************************************************************************/
278
279static TDB_DATA print_key(uint32 jobid, uint32 *tmp)
280{
281 TDB_DATA ret;
282
283 SIVAL(tmp, 0, jobid);
284 ret.dptr = (uint8 *)tmp;
285 ret.dsize = sizeof(*tmp);
286 return ret;
287}
288
289/****************************************************************************
290 Pack the devicemode to store it in a tdb.
291****************************************************************************/
292static int pack_devicemode(struct spoolss_DeviceMode *devmode, uint8 *buf, int buflen)
293{
294 enum ndr_err_code ndr_err;
295 DATA_BLOB blob;
296 int len = 0;
297
298 if (devmode) {
299 ndr_err = ndr_push_struct_blob(&blob, talloc_tos(),
300 devmode,
301 (ndr_push_flags_fn_t)
302 ndr_push_spoolss_DeviceMode);
303 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
304 DEBUG(10, ("pack_devicemode: "
305 "error encoding spoolss_DeviceMode\n"));
306 goto done;
307 }
308 } else {
309 ZERO_STRUCT(blob);
310 }
311
312 len = tdb_pack(buf, buflen, "B", blob.length, blob.data);
313
314 if (devmode) {
315 DEBUG(8, ("Packed devicemode [%s]\n", devmode->formname));
316 }
317
318done:
319 return len;
320}
321
322/****************************************************************************
323 Unpack the devicemode to store it in a tdb.
324****************************************************************************/
325static int unpack_devicemode(TALLOC_CTX *mem_ctx,
326 const uint8 *buf, int buflen,
327 struct spoolss_DeviceMode **devmode)
328{
329 struct spoolss_DeviceMode *dm;
330 enum ndr_err_code ndr_err;
331 char *data = NULL;
332 int data_len = 0;
333 DATA_BLOB blob;
334 int len = 0;
335
336 *devmode = NULL;
337
338 len = tdb_unpack(buf, buflen, "B", &data_len, &data);
339 if (!data) {
340 return len;
341 }
342
343 dm = talloc_zero(mem_ctx, struct spoolss_DeviceMode);
344 if (!dm) {
345 goto done;
346 }
347
348 blob = data_blob_const(data, data_len);
349
350 ndr_err = ndr_pull_struct_blob(&blob, dm, dm,
351 (ndr_pull_flags_fn_t)ndr_pull_spoolss_DeviceMode);
352 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
353 DEBUG(10, ("unpack_devicemode: "
354 "error parsing spoolss_DeviceMode\n"));
355 goto done;
356 }
357
358 DEBUG(8, ("Unpacked devicemode [%s](%s)\n",
359 dm->devicename, dm->formname));
360 if (dm->driverextra_data.data) {
361 DEBUG(8, ("with a private section of %d bytes\n",
362 dm->__driverextra_length));
363 }
364
365 *devmode = dm;
366
367done:
368 SAFE_FREE(data);
369 return len;
370}
371
372/***********************************************************************
373 unpack a pjob from a tdb buffer
374***********************************************************************/
375
376static int unpack_pjob( uint8 *buf, int buflen, struct printjob *pjob )
377{
378 int len = 0;
379 int used;
380 uint32 pjpid, pjsysjob, pjfd, pjstarttime, pjstatus;
381 uint32 pjsize, pjpage_count, pjspooled, pjsmbjob;
382
383 if ( !buf || !pjob )
384 return -1;
385
386 len += tdb_unpack(buf+len, buflen-len, "dddddddddfffff",
387 &pjpid,
388 &pjsysjob,
389 &pjfd,
390 &pjstarttime,
391 &pjstatus,
392 &pjsize,
393 &pjpage_count,
394 &pjspooled,
395 &pjsmbjob,
396 pjob->filename,
397 pjob->jobname,
398 pjob->user,
399 pjob->clientmachine,
400 pjob->queuename);
401
402 if ( len == -1 )
403 return -1;
404
405 used = unpack_devicemode(NULL, buf+len, buflen-len, &pjob->devmode);
406 if (used == -1) {
407 return -1;
408 }
409
410 len += used;
411
412 pjob->pid = pjpid;
413 pjob->sysjob = pjsysjob;
414 pjob->fd = pjfd;
415 pjob->starttime = pjstarttime;
416 pjob->status = pjstatus;
417 pjob->size = pjsize;
418 pjob->page_count = pjpage_count;
419 pjob->spooled = pjspooled;
420 pjob->smbjob = pjsmbjob;
421
422 return len;
423
424}
425
426/****************************************************************************
427 Useful function to find a print job in the database.
428****************************************************************************/
429
430static struct printjob *print_job_find(const char *sharename, uint32 jobid)
431{
432 static struct printjob pjob;
433 uint32_t tmp;
434 TDB_DATA ret;
435 struct tdb_print_db *pdb = get_print_db_byname(sharename);
436
437 DEBUG(10,("print_job_find: looking up job %u for share %s\n",
438 (unsigned int)jobid, sharename ));
439
440 if (!pdb) {
441 return NULL;
442 }
443
444 ret = tdb_fetch(pdb->tdb, print_key(jobid, &tmp));
445 release_print_db(pdb);
446
447 if (!ret.dptr) {
448 DEBUG(10,("print_job_find: failed to find jobid %u.\n", (unsigned int)jobid ));
449 return NULL;
450 }
451
452 talloc_free(pjob.devmode);
453
454 ZERO_STRUCT( pjob );
455
456 if ( unpack_pjob( ret.dptr, ret.dsize, &pjob ) == -1 ) {
457 DEBUG(10,("print_job_find: failed to unpack jobid %u.\n", (unsigned int)jobid ));
458 SAFE_FREE(ret.dptr);
459 return NULL;
460 }
461
462 SAFE_FREE(ret.dptr);
463
464 DEBUG(10,("print_job_find: returning system job %d for jobid %u.\n",
465 (int)pjob.sysjob, (unsigned int)jobid ));
466
467 return &pjob;
468}
469
470/* Convert a unix jobid to a smb jobid */
471
472struct unixjob_traverse_state {
473 int sysjob;
474 uint32 sysjob_to_jobid_value;
475};
476
477static int unixjob_traverse_fn(TDB_CONTEXT *the_tdb, TDB_DATA key,
478 TDB_DATA data, void *private_data)
479{
480 struct printjob *pjob;
481 struct unixjob_traverse_state *state =
482 (struct unixjob_traverse_state *)private_data;
483
484 if (!data.dptr || data.dsize == 0)
485 return 0;
486
487 pjob = (struct printjob *)data.dptr;
488 if (key.dsize != sizeof(uint32))
489 return 0;
490
491 if (state->sysjob == pjob->sysjob) {
492 uint32 jobid = IVAL(key.dptr,0);
493
494 state->sysjob_to_jobid_value = jobid;
495 return 1;
496 }
497
498 return 0;
499}
500
501/****************************************************************************
502 This is a *horribly expensive call as we have to iterate through all the
503 current printer tdb's. Don't do this often ! JRA.
504****************************************************************************/
505
506uint32 sysjob_to_jobid(int unix_jobid)
507{
508 int services = lp_numservices();
509 int snum;
510 struct unixjob_traverse_state state;
511
512 state.sysjob = unix_jobid;
513 state.sysjob_to_jobid_value = (uint32)-1;
514
515 for (snum = 0; snum < services; snum++) {
516 struct tdb_print_db *pdb;
517 if (!lp_print_ok(snum))
518 continue;
519 pdb = get_print_db_byname(lp_const_servicename(snum));
520 if (!pdb) {
521 continue;
522 }
523 tdb_traverse(pdb->tdb, unixjob_traverse_fn, &state);
524 release_print_db(pdb);
525 if (state.sysjob_to_jobid_value != (uint32)-1)
526 return state.sysjob_to_jobid_value;
527 }
528 return (uint32)-1;
529}
530
531/****************************************************************************
532 Send notifications based on what has changed after a pjob_store.
533****************************************************************************/
534
535static const struct {
536 uint32_t lpq_status;
537 uint32_t spoolss_status;
538} lpq_to_spoolss_status_map[] = {
539 { LPQ_QUEUED, JOB_STATUS_QUEUED },
540 { LPQ_PAUSED, JOB_STATUS_PAUSED },
541 { LPQ_SPOOLING, JOB_STATUS_SPOOLING },
542 { LPQ_PRINTING, JOB_STATUS_PRINTING },
543 { LPQ_DELETING, JOB_STATUS_DELETING },
544 { LPQ_OFFLINE, JOB_STATUS_OFFLINE },
545 { LPQ_PAPEROUT, JOB_STATUS_PAPEROUT },
546 { LPQ_PRINTED, JOB_STATUS_PRINTED },
547 { LPQ_DELETED, JOB_STATUS_DELETED },
548 { LPQ_BLOCKED, JOB_STATUS_BLOCKED_DEVQ },
549 { LPQ_USER_INTERVENTION, JOB_STATUS_USER_INTERVENTION },
550 { (uint32_t)-1, 0 }
551};
552
553/* Convert a lpq status value stored in printing.tdb into the
554 appropriate win32 API constant. */
555
556static uint32 map_to_spoolss_status(uint32 lpq_status)
557{
558 int i = 0;
559
560 while (lpq_to_spoolss_status_map[i].lpq_status != -1) {
561 if (lpq_to_spoolss_status_map[i].lpq_status == lpq_status)
562 return lpq_to_spoolss_status_map[i].spoolss_status;
563 i++;
564 }
565
566 return 0;
567}
568
569/***************************************************************************
570 Append a jobid to the 'jobs changed' list.
571***************************************************************************/
572
573static bool add_to_jobs_changed(struct tdb_print_db *pdb, uint32_t jobid)
574{
575 TDB_DATA data;
576 uint32_t store_jobid;
577
578 SIVAL(&store_jobid, 0, jobid);
579 data.dptr = (uint8 *) &store_jobid;
580 data.dsize = 4;
581
582 DEBUG(10,("add_to_jobs_added: Added jobid %u\n", (unsigned int)jobid ));
583
584 return (tdb_append(pdb->tdb, string_tdb_data("INFO/jobs_changed"),
585 data) == 0);
586}
587
588/***************************************************************************
589 Remove a jobid from the 'jobs changed' list.
590***************************************************************************/
591
592static bool remove_from_jobs_changed(const char* sharename, uint32_t jobid)
593{
594 struct tdb_print_db *pdb = get_print_db_byname(sharename);
595 TDB_DATA data, key;
596 size_t job_count, i;
597 bool ret = False;
598 bool gotlock = False;
599
600 if (!pdb) {
601 return False;
602 }
603
604 ZERO_STRUCT(data);
605
606 key = string_tdb_data("INFO/jobs_changed");
607
608 if (tdb_chainlock_with_timeout(pdb->tdb, key, 5) == -1)
609 goto out;
610
611 gotlock = True;
612
613 data = tdb_fetch(pdb->tdb, key);
614
615 if (data.dptr == NULL || data.dsize == 0 || (data.dsize % 4 != 0))
616 goto out;
617
618 job_count = data.dsize / 4;
619 for (i = 0; i < job_count; i++) {
620 uint32 ch_jobid;
621
622 ch_jobid = IVAL(data.dptr, i*4);
623 if (ch_jobid == jobid) {
624 if (i < job_count -1 )
625 memmove(data.dptr + (i*4), data.dptr + (i*4) + 4, (job_count - i - 1)*4 );
626 data.dsize -= 4;
627 if (tdb_store(pdb->tdb, key, data, TDB_REPLACE) == -1)
628 goto out;
629 break;
630 }
631 }
632
633 ret = True;
634 out:
635
636 if (gotlock)
637 tdb_chainunlock(pdb->tdb, key);
638 SAFE_FREE(data.dptr);
639 release_print_db(pdb);
640 if (ret)
641 DEBUG(10,("remove_from_jobs_changed: removed jobid %u\n", (unsigned int)jobid ));
642 else
643 DEBUG(10,("remove_from_jobs_changed: Failed to remove jobid %u\n", (unsigned int)jobid ));
644 return ret;
645}
646
647static void pjob_store_notify(struct tevent_context *ev,
648 struct messaging_context *msg_ctx,
649 const char* sharename, uint32 jobid,
650 struct printjob *old_data,
651 struct printjob *new_data,
652 bool *pchanged)
653{
654 bool new_job = false;
655 bool changed = false;
656
657 if (old_data == NULL) {
658 new_job = true;
659 }
660
661 /* ACHTUNG! Due to a bug in Samba's spoolss parsing of the
662 NOTIFY_INFO_DATA buffer, we *have* to send the job submission
663 time first or else we'll end up with potential alignment
664 errors. I don't think the systemtime should be spooled as
665 a string, but this gets us around that error.
666 --jerry (i'll feel dirty for this) */
667
668 if (new_job) {
669 notify_job_submitted(ev, msg_ctx,
670 sharename, jobid, new_data->starttime);
671 notify_job_username(ev, msg_ctx,
672 sharename, jobid, new_data->user);
673 notify_job_name(ev, msg_ctx,
674 sharename, jobid, new_data->jobname);
675 notify_job_status(ev, msg_ctx,
676 sharename, jobid, map_to_spoolss_status(new_data->status));
677 notify_job_total_bytes(ev, msg_ctx,
678 sharename, jobid, new_data->size);
679 notify_job_total_pages(ev, msg_ctx,
680 sharename, jobid, new_data->page_count);
681 } else {
682 if (!strequal(old_data->jobname, new_data->jobname)) {
683 notify_job_name(ev, msg_ctx, sharename,
684 jobid, new_data->jobname);
685 changed = true;
686 }
687
688 if (old_data->status != new_data->status) {
689 notify_job_status(ev, msg_ctx,
690 sharename, jobid,
691 map_to_spoolss_status(new_data->status));
692 }
693
694 if (old_data->size != new_data->size) {
695 notify_job_total_bytes(ev, msg_ctx,
696 sharename, jobid, new_data->size);
697 }
698
699 if (old_data->page_count != new_data->page_count) {
700 notify_job_total_pages(ev, msg_ctx,
701 sharename, jobid,
702 new_data->page_count);
703 }
704 }
705
706 *pchanged = changed;
707}
708
709/****************************************************************************
710 Store a job structure back to the database.
711****************************************************************************/
712
713static bool pjob_store(struct tevent_context *ev,
714 struct messaging_context *msg_ctx,
715 const char* sharename, uint32 jobid,
716 struct printjob *pjob)
717{
718 uint32_t tmp;
719 TDB_DATA old_data, new_data;
720 bool ret = False;
721 struct tdb_print_db *pdb = get_print_db_byname(sharename);
722 uint8 *buf = NULL;
723 int len, newlen, buflen;
724
725
726 if (!pdb)
727 return False;
728
729 /* Get old data */
730
731 old_data = tdb_fetch(pdb->tdb, print_key(jobid, &tmp));
732
733 /* Doh! Now we have to pack/unpack data since the NT_DEVICEMODE was added */
734
735 newlen = 0;
736
737 do {
738 len = 0;
739 buflen = newlen;
740 len += tdb_pack(buf+len, buflen-len, "dddddddddfffff",
741 (uint32)pjob->pid,
742 (uint32)pjob->sysjob,
743 (uint32)pjob->fd,
744 (uint32)pjob->starttime,
745 (uint32)pjob->status,
746 (uint32)pjob->size,
747 (uint32)pjob->page_count,
748 (uint32)pjob->spooled,
749 (uint32)pjob->smbjob,
750 pjob->filename,
751 pjob->jobname,
752 pjob->user,
753 pjob->clientmachine,
754 pjob->queuename);
755
756 len += pack_devicemode(pjob->devmode, buf+len, buflen-len);
757
758 if (buflen != len) {
759 buf = (uint8 *)SMB_REALLOC(buf, len);
760 if (!buf) {
761 DEBUG(0,("pjob_store: failed to enlarge buffer!\n"));
762 goto done;
763 }
764 newlen = len;
765 }
766 } while ( buflen != len );
767
768
769 /* Store new data */
770
771 new_data.dptr = buf;
772 new_data.dsize = len;
773 ret = (tdb_store(pdb->tdb, print_key(jobid, &tmp), new_data,
774 TDB_REPLACE) == 0);
775
776 /* Send notify updates for what has changed */
777
778 if ( ret ) {
779 bool changed = false;
780 struct printjob old_pjob;
781
782 if ( old_data.dsize )
783 {
784 if ( unpack_pjob( old_data.dptr, old_data.dsize, &old_pjob ) != -1 )
785 {
786 pjob_store_notify(server_event_context(),
787 msg_ctx,
788 sharename, jobid, &old_pjob,
789 pjob,
790 &changed);
791 talloc_free(old_pjob.devmode);
792
793 if (changed) {
794 add_to_jobs_changed(pdb, jobid);
795 }
796 }
797
798 }
799 else {
800 /* new job */
801 pjob_store_notify(server_event_context(), msg_ctx,
802 sharename, jobid, NULL, pjob,
803 &changed);
804 }
805 }
806
807 release_print_db(pdb);
808done:
809 SAFE_FREE( old_data.dptr );
810 SAFE_FREE( buf );
811
812 return ret;
813}
814
815/****************************************************************************
816 Remove a job structure from the database.
817****************************************************************************/
818
819static void pjob_delete(struct tevent_context *ev,
820 struct messaging_context *msg_ctx,
821 const char* sharename, uint32 jobid)
822{
823 uint32_t tmp;
824 struct printjob *pjob;
825 uint32 job_status = 0;
826 struct tdb_print_db *pdb;
827
828 pdb = get_print_db_byname( sharename );
829
830 if (!pdb)
831 return;
832
833 pjob = print_job_find( sharename, jobid );
834
835 if (!pjob) {
836 DEBUG(5, ("pjob_delete: we were asked to delete nonexistent job %u\n",
837 (unsigned int)jobid));
838 release_print_db(pdb);
839 return;
840 }
841
842 /* We must cycle through JOB_STATUS_DELETING and
843 JOB_STATUS_DELETED for the port monitor to delete the job
844 properly. */
845
846 job_status = JOB_STATUS_DELETING|JOB_STATUS_DELETED;
847 notify_job_status(ev, msg_ctx, sharename, jobid, job_status);
848
849 /* Remove from printing.tdb */
850
851 tdb_delete(pdb->tdb, print_key(jobid, &tmp));
852 remove_from_jobs_added(sharename, jobid);
853 release_print_db( pdb );
854 rap_jobid_delete(sharename, jobid);
855}
856
857/****************************************************************************
858 List a unix job in the print database.
859****************************************************************************/
860
861static void print_unix_job(struct tevent_context *ev,
862 struct messaging_context *msg_ctx,
863 const char *sharename, print_queue_struct *q,
864 uint32 jobid)
865{
866 struct printjob pj, *old_pj;
867
868 if (jobid == (uint32)-1)
869 jobid = q->job + UNIX_JOB_START;
870
871 /* Preserve the timestamp on an existing unix print job */
872
873 old_pj = print_job_find(sharename, jobid);
874
875 ZERO_STRUCT(pj);
876
877 pj.pid = (pid_t)-1;
878 pj.sysjob = q->job;
879 pj.fd = -1;
880 pj.starttime = old_pj ? old_pj->starttime : q->time;
881 pj.status = q->status;
882 pj.size = q->size;
883 pj.spooled = True;
884 fstrcpy(pj.filename, old_pj ? old_pj->filename : "");
885 if (jobid < UNIX_JOB_START) {
886 pj.smbjob = True;
887 fstrcpy(pj.jobname, old_pj ? old_pj->jobname : "Remote Downlevel Document");
888 } else {
889 pj.smbjob = False;
890 fstrcpy(pj.jobname, old_pj ? old_pj->jobname : q->fs_file);
891 }
892 fstrcpy(pj.user, old_pj ? old_pj->user : q->fs_user);
893 fstrcpy(pj.queuename, old_pj ? old_pj->queuename : sharename );
894
895 pjob_store(ev, msg_ctx, sharename, jobid, &pj);
896}
897
898
899struct traverse_struct {
900 print_queue_struct *queue;
901 int qcount, snum, maxcount, total_jobs;
902 const char *sharename;
903 time_t lpq_time;
904 const char *lprm_command;
905 struct printif *print_if;
906 struct tevent_context *ev;
907 struct messaging_context *msg_ctx;
908};
909
910/****************************************************************************
911 Utility fn to delete any jobs that are no longer active.
912****************************************************************************/
913
914static int traverse_fn_delete(TDB_CONTEXT *t, TDB_DATA key, TDB_DATA data, void *state)
915{
916 struct traverse_struct *ts = (struct traverse_struct *)state;
917 struct printjob pjob;
918 uint32 jobid;
919 int i = 0;
920
921 if ( key.dsize != sizeof(jobid) )
922 return 0;
923
924 jobid = IVAL(key.dptr, 0);
925 if ( unpack_pjob( data.dptr, data.dsize, &pjob ) == -1 )
926 return 0;
927 talloc_free(pjob.devmode);
928
929
930 if (!pjob.smbjob) {
931 /* remove a unix job if it isn't in the system queue any more */
932
933 for (i=0;i<ts->qcount;i++) {
934 uint32 u_jobid = (ts->queue[i].job + UNIX_JOB_START);
935 if (jobid == u_jobid)
936 break;
937 }
938 if (i == ts->qcount) {
939 DEBUG(10,("traverse_fn_delete: pjob %u deleted due to !smbjob\n",
940 (unsigned int)jobid ));
941 pjob_delete(ts->ev, ts->msg_ctx,
942 ts->sharename, jobid);
943 return 0;
944 }
945
946 /* need to continue the the bottom of the function to
947 save the correct attributes */
948 }
949
950 /* maybe it hasn't been spooled yet */
951 if (!pjob.spooled) {
952 /* if a job is not spooled and the process doesn't
953 exist then kill it. This cleans up after smbd
954 deaths */
955 if (!process_exists_by_pid(pjob.pid)) {
956 DEBUG(10,("traverse_fn_delete: pjob %u deleted due to !process_exists (%u)\n",
957 (unsigned int)jobid, (unsigned int)pjob.pid ));
958 pjob_delete(ts->ev, ts->msg_ctx,
959 ts->sharename, jobid);
960 } else
961 ts->total_jobs++;
962 return 0;
963 }
964
965 /* this check only makes sense for jobs submitted from Windows clients */
966
967 if ( pjob.smbjob ) {
968 for (i=0;i<ts->qcount;i++) {
969 uint32 curr_jobid;
970
971 if ( pjob.status == LPQ_DELETED )
972 continue;
973
974 curr_jobid = print_parse_jobid(ts->queue[i].fs_file);
975
976 if (jobid == curr_jobid) {
977
978 /* try to clean up any jobs that need to be deleted */
979
980 if ( pjob.status == LPQ_DELETING ) {
981 int result;
982
983 result = (*(ts->print_if->job_delete))(
984 ts->sharename, ts->lprm_command, &pjob );
985
986 if ( result != 0 ) {
987 /* if we can't delete, then reset the job status */
988 pjob.status = LPQ_QUEUED;
989 pjob_store(ts->ev, ts->msg_ctx,
990 ts->sharename, jobid, &pjob);
991 }
992 else {
993 /* if we deleted the job, the remove the tdb record */
994 pjob_delete(ts->ev,
995 ts->msg_ctx,
996 ts->sharename, jobid);
997 pjob.status = LPQ_DELETED;
998 }
999
1000 }
1001
1002 break;
1003 }
1004 }
1005 }
1006
1007 /* The job isn't in the system queue - we have to assume it has
1008 completed, so delete the database entry. */
1009
1010 if (i == ts->qcount) {
1011
1012 /* A race can occur between the time a job is spooled and
1013 when it appears in the lpq output. This happens when
1014 the job is added to printing.tdb when another smbd
1015 running print_queue_update() has completed a lpq and
1016 is currently traversing the printing tdb and deleting jobs.
1017 Don't delete the job if it was submitted after the lpq_time. */
1018
1019 if (pjob.starttime < ts->lpq_time) {
1020 DEBUG(10,("traverse_fn_delete: pjob %u deleted due to pjob.starttime (%u) < ts->lpq_time (%u)\n",
1021 (unsigned int)jobid,
1022 (unsigned int)pjob.starttime,
1023 (unsigned int)ts->lpq_time ));
1024 pjob_delete(ts->ev, ts->msg_ctx,
1025 ts->sharename, jobid);
1026 } else
1027 ts->total_jobs++;
1028 return 0;
1029 }
1030
1031 /* Save the pjob attributes we will store.
1032 FIXME!!! This is the only place where queue->job
1033 represents the SMB jobid --jerry */
1034
1035 ts->queue[i].job = jobid;
1036 ts->queue[i].size = pjob.size;
1037 ts->queue[i].page_count = pjob.page_count;
1038 ts->queue[i].status = pjob.status;
1039 ts->queue[i].priority = 1;
1040 ts->queue[i].time = pjob.starttime;
1041 fstrcpy(ts->queue[i].fs_user, pjob.user);
1042 fstrcpy(ts->queue[i].fs_file, pjob.jobname);
1043
1044 ts->total_jobs++;
1045
1046 return 0;
1047}
1048
1049/****************************************************************************
1050 Check if the print queue has been updated recently enough.
1051****************************************************************************/
1052
1053static void print_cache_flush(const char *sharename)
1054{
1055 fstring key;
1056 struct tdb_print_db *pdb = get_print_db_byname(sharename);
1057
1058 if (!pdb)
1059 return;
1060 slprintf(key, sizeof(key)-1, "CACHE/%s", sharename);
1061 tdb_store_int32(pdb->tdb, key, -1);
1062 release_print_db(pdb);
1063}
1064
1065/****************************************************************************
1066 Check if someone already thinks they are doing the update.
1067****************************************************************************/
1068
1069static pid_t get_updating_pid(const char *sharename)
1070{
1071 fstring keystr;
1072 TDB_DATA data, key;
1073 pid_t updating_pid;
1074 struct tdb_print_db *pdb = get_print_db_byname(sharename);
1075
1076 if (!pdb)
1077 return (pid_t)-1;
1078 slprintf(keystr, sizeof(keystr)-1, "UPDATING/%s", sharename);
1079 key = string_tdb_data(keystr);
1080
1081 data = tdb_fetch(pdb->tdb, key);
1082 release_print_db(pdb);
1083 if (!data.dptr || data.dsize != sizeof(pid_t)) {
1084 SAFE_FREE(data.dptr);
1085 return (pid_t)-1;
1086 }
1087
1088 updating_pid = IVAL(data.dptr, 0);
1089 SAFE_FREE(data.dptr);
1090
1091 if (process_exists_by_pid(updating_pid))
1092 return updating_pid;
1093
1094 return (pid_t)-1;
1095}
1096
1097/****************************************************************************
1098 Set the fact that we're doing the update, or have finished doing the update
1099 in the tdb.
1100****************************************************************************/
1101
1102static void set_updating_pid(const fstring sharename, bool updating)
1103{
1104 fstring keystr;
1105 TDB_DATA key;
1106 TDB_DATA data;
1107 pid_t updating_pid = sys_getpid();
1108 uint8 buffer[4];
1109
1110 struct tdb_print_db *pdb = get_print_db_byname(sharename);
1111
1112 if (!pdb)
1113 return;
1114
1115 slprintf(keystr, sizeof(keystr)-1, "UPDATING/%s", sharename);
1116 key = string_tdb_data(keystr);
1117
1118 DEBUG(5, ("set_updating_pid: %s updating lpq cache for print share %s\n",
1119 updating ? "" : "not ",
1120 sharename ));
1121
1122 if ( !updating ) {
1123 tdb_delete(pdb->tdb, key);
1124 release_print_db(pdb);
1125 return;
1126 }
1127
1128 SIVAL( buffer, 0, updating_pid);
1129 data.dptr = buffer;
1130 data.dsize = 4; /* we always assume this is a 4 byte value */
1131
1132 tdb_store(pdb->tdb, key, data, TDB_REPLACE);
1133 release_print_db(pdb);
1134}
1135
1136/****************************************************************************
1137 Sort print jobs by submittal time.
1138****************************************************************************/
1139
1140static int printjob_comp(print_queue_struct *j1, print_queue_struct *j2)
1141{
1142 /* Silly cases */
1143
1144 if (!j1 && !j2)
1145 return 0;
1146 if (!j1)
1147 return -1;
1148 if (!j2)
1149 return 1;
1150
1151 /* Sort on job start time */
1152
1153 if (j1->time == j2->time)
1154 return 0;
1155 return (j1->time > j2->time) ? 1 : -1;
1156}
1157
1158/****************************************************************************
1159 Store the sorted queue representation for later portmon retrieval.
1160 Skip deleted jobs
1161****************************************************************************/
1162
1163static void store_queue_struct(struct tdb_print_db *pdb, struct traverse_struct *pts)
1164{
1165 TDB_DATA data;
1166 int max_reported_jobs = lp_max_reported_jobs(pts->snum);
1167 print_queue_struct *queue = pts->queue;
1168 size_t len;
1169 size_t i;
1170 unsigned int qcount;
1171
1172 if (max_reported_jobs && (max_reported_jobs < pts->qcount))
1173 pts->qcount = max_reported_jobs;
1174 qcount = 0;
1175
1176 /* Work out the size. */
1177 data.dsize = 0;
1178 data.dsize += tdb_pack(NULL, 0, "d", qcount);
1179
1180 for (i = 0; i < pts->qcount; i++) {
1181 if ( queue[i].status == LPQ_DELETED )
1182 continue;
1183
1184 qcount++;
1185 data.dsize += tdb_pack(NULL, 0, "ddddddff",
1186 (uint32)queue[i].job,
1187 (uint32)queue[i].size,
1188 (uint32)queue[i].page_count,
1189 (uint32)queue[i].status,
1190 (uint32)queue[i].priority,
1191 (uint32)queue[i].time,
1192 queue[i].fs_user,
1193 queue[i].fs_file);
1194 }
1195
1196 if ((data.dptr = (uint8 *)SMB_MALLOC(data.dsize)) == NULL)
1197 return;
1198
1199 len = 0;
1200 len += tdb_pack(data.dptr + len, data.dsize - len, "d", qcount);
1201 for (i = 0; i < pts->qcount; i++) {
1202 if ( queue[i].status == LPQ_DELETED )
1203 continue;
1204
1205 len += tdb_pack(data.dptr + len, data.dsize - len, "ddddddff",
1206 (uint32)queue[i].job,
1207 (uint32)queue[i].size,
1208 (uint32)queue[i].page_count,
1209 (uint32)queue[i].status,
1210 (uint32)queue[i].priority,
1211 (uint32)queue[i].time,
1212 queue[i].fs_user,
1213 queue[i].fs_file);
1214 }
1215
1216 tdb_store(pdb->tdb, string_tdb_data("INFO/linear_queue_array"), data,
1217 TDB_REPLACE);
1218 SAFE_FREE(data.dptr);
1219 return;
1220}
1221
1222static TDB_DATA get_jobs_added_data(struct tdb_print_db *pdb)
1223{
1224 TDB_DATA data;
1225
1226 ZERO_STRUCT(data);
1227
1228 data = tdb_fetch(pdb->tdb, string_tdb_data("INFO/jobs_added"));
1229 if (data.dptr == NULL || data.dsize == 0 || (data.dsize % 4 != 0)) {
1230 SAFE_FREE(data.dptr);
1231 ZERO_STRUCT(data);
1232 }
1233
1234 return data;
1235}
1236
1237static void check_job_added(const char *sharename, TDB_DATA data, uint32 jobid)
1238{
1239 unsigned int i;
1240 unsigned int job_count = data.dsize / 4;
1241
1242 for (i = 0; i < job_count; i++) {
1243 uint32 ch_jobid;
1244
1245 ch_jobid = IVAL(data.dptr, i*4);
1246 if (ch_jobid == jobid)
1247 remove_from_jobs_added(sharename, jobid);
1248 }
1249}
1250
1251/****************************************************************************
1252 Check if the print queue has been updated recently enough.
1253****************************************************************************/
1254
1255static bool print_cache_expired(const char *sharename, bool check_pending)
1256{
1257 fstring key;
1258 time_t last_qscan_time, time_now = time(NULL);
1259 struct tdb_print_db *pdb = get_print_db_byname(sharename);
1260 bool result = False;
1261
1262 if (!pdb)
1263 return False;
1264
1265 snprintf(key, sizeof(key), "CACHE/%s", sharename);
1266 last_qscan_time = (time_t)tdb_fetch_int32(pdb->tdb, key);
1267
1268 /*
1269 * Invalidate the queue for 3 reasons.
1270 * (1). last queue scan time == -1.
1271 * (2). Current time - last queue scan time > allowed cache time.
1272 * (3). last queue scan time > current time + MAX_CACHE_VALID_TIME (1 hour by default).
1273 * This last test picks up machines for which the clock has been moved
1274 * forward, an lpq scan done and then the clock moved back. Otherwise
1275 * that last lpq scan would stay around for a loooong loooong time... :-). JRA.
1276 */
1277
1278 if (last_qscan_time == ((time_t)-1)
1279 || (time_now - last_qscan_time) >= lp_lpqcachetime()
1280 || last_qscan_time > (time_now + MAX_CACHE_VALID_TIME))
1281 {
1282 uint32 u;
1283 time_t msg_pending_time;
1284
1285 DEBUG(4, ("print_cache_expired: cache expired for queue %s "
1286 "(last_qscan_time = %d, time now = %d, qcachetime = %d)\n",
1287 sharename, (int)last_qscan_time, (int)time_now,
1288 (int)lp_lpqcachetime() ));
1289
1290 /* check if another smbd has already sent a message to update the
1291 queue. Give the pending message one minute to clear and
1292 then send another message anyways. Make sure to check for
1293 clocks that have been run forward and then back again. */
1294
1295 snprintf(key, sizeof(key), "MSG_PENDING/%s", sharename);
1296
1297 if ( check_pending
1298 && tdb_fetch_uint32( pdb->tdb, key, &u )
1299 && (msg_pending_time=u) > 0
1300 && msg_pending_time <= time_now
1301 && (time_now - msg_pending_time) < 60 )
1302 {
1303 DEBUG(4,("print_cache_expired: message already pending for %s. Accepting cache\n",
1304 sharename));
1305 goto done;
1306 }
1307
1308 result = True;
1309 }
1310
1311done:
1312 release_print_db(pdb);
1313 return result;
1314}
1315
1316/****************************************************************************
1317 main work for updating the lpq cache for a printer queue
1318****************************************************************************/
1319
1320static void print_queue_update_internal( struct tevent_context *ev,
1321 struct messaging_context *msg_ctx,
1322 const char *sharename,
1323 struct printif *current_printif,
1324 char *lpq_command, char *lprm_command )
1325{
1326 int i, qcount;
1327 print_queue_struct *queue = NULL;
1328 print_status_struct status;
1329 print_status_struct old_status;
1330 struct printjob *pjob;
1331 struct traverse_struct tstruct;
1332 TDB_DATA data, key;
1333 TDB_DATA jcdata;
1334 fstring keystr, cachestr;
1335 struct tdb_print_db *pdb = get_print_db_byname(sharename);
1336
1337 if (!pdb) {
1338 return;
1339 }
1340
1341 DEBUG(5,("print_queue_update_internal: printer = %s, type = %d, lpq command = [%s]\n",
1342 sharename, current_printif->type, lpq_command));
1343
1344 /*
1345 * Update the cache time FIRST ! Stops others even
1346 * attempting to get the lock and doing this
1347 * if the lpq takes a long time.
1348 */
1349
1350 slprintf(cachestr, sizeof(cachestr)-1, "CACHE/%s", sharename);
1351 tdb_store_int32(pdb->tdb, cachestr, (int)time(NULL));
1352
1353 /* get the current queue using the appropriate interface */
1354 ZERO_STRUCT(status);
1355
1356 qcount = (*(current_printif->queue_get))(sharename,
1357 current_printif->type,
1358 lpq_command, &queue, &status);
1359
1360 DEBUG(3, ("print_queue_update_internal: %d job%s in queue for %s\n",
1361 qcount, (qcount != 1) ? "s" : "", sharename));
1362
1363 /* Sort the queue by submission time otherwise they are displayed
1364 in hash order. */
1365
1366 TYPESAFE_QSORT(queue, qcount, printjob_comp);
1367
1368 /*
1369 any job in the internal database that is marked as spooled
1370 and doesn't exist in the system queue is considered finished
1371 and removed from the database
1372
1373 any job in the system database but not in the internal database
1374 is added as a unix job
1375
1376 fill in any system job numbers as we go
1377 */
1378
1379 jcdata = get_jobs_added_data(pdb);
1380
1381 for (i=0; i<qcount; i++) {
1382 uint32 jobid = print_parse_jobid(queue[i].fs_file);
1383
1384 if (jobid == (uint32)-1) {
1385 /* assume its a unix print job */
1386 print_unix_job(ev, msg_ctx,
1387 sharename, &queue[i], jobid);
1388 continue;
1389 }
1390
1391 /* we have an active SMB print job - update its status */
1392 pjob = print_job_find(sharename, jobid);
1393 if (!pjob) {
1394 /* err, somethings wrong. Probably smbd was restarted
1395 with jobs in the queue. All we can do is treat them
1396 like unix jobs. Pity. */
1397 print_unix_job(ev, msg_ctx,
1398 sharename, &queue[i], jobid);
1399 continue;
1400 }
1401
1402 pjob->sysjob = queue[i].job;
1403
1404 /* don't reset the status on jobs to be deleted */
1405
1406 if ( pjob->status != LPQ_DELETING )
1407 pjob->status = queue[i].status;
1408
1409 pjob_store(ev, msg_ctx, sharename, jobid, pjob);
1410
1411 check_job_added(sharename, jcdata, jobid);
1412 }
1413
1414 SAFE_FREE(jcdata.dptr);
1415
1416 /* now delete any queued entries that don't appear in the
1417 system queue */
1418 tstruct.queue = queue;
1419 tstruct.qcount = qcount;
1420 tstruct.snum = -1;
1421 tstruct.total_jobs = 0;
1422 tstruct.lpq_time = time(NULL);
1423 tstruct.sharename = sharename;
1424 tstruct.lprm_command = lprm_command;
1425 tstruct.print_if = current_printif;
1426 tstruct.ev = ev;
1427 tstruct.msg_ctx = msg_ctx;
1428
1429 tdb_traverse(pdb->tdb, traverse_fn_delete, (void *)&tstruct);
1430
1431 /* Store the linearised queue, max jobs only. */
1432 store_queue_struct(pdb, &tstruct);
1433
1434 SAFE_FREE(tstruct.queue);
1435
1436 DEBUG(10,("print_queue_update_internal: printer %s INFO/total_jobs = %d\n",
1437 sharename, tstruct.total_jobs ));
1438
1439 tdb_store_int32(pdb->tdb, "INFO/total_jobs", tstruct.total_jobs);
1440
1441 get_queue_status(sharename, &old_status);
1442 if (old_status.qcount != qcount)
1443 DEBUG(10,("print_queue_update_internal: queue status change %d jobs -> %d jobs for printer %s\n",
1444 old_status.qcount, qcount, sharename));
1445
1446 /* store the new queue status structure */
1447 slprintf(keystr, sizeof(keystr)-1, "STATUS/%s", sharename);
1448 key = string_tdb_data(keystr);
1449
1450 status.qcount = qcount;
1451 data.dptr = (uint8 *)&status;
1452 data.dsize = sizeof(status);
1453 tdb_store(pdb->tdb, key, data, TDB_REPLACE);
1454
1455 /*
1456 * Update the cache time again. We want to do this call
1457 * as little as possible...
1458 */
1459
1460 slprintf(keystr, sizeof(keystr)-1, "CACHE/%s", sharename);
1461 tdb_store_int32(pdb->tdb, keystr, (int32)time(NULL));
1462
1463 /* clear the msg pending record for this queue */
1464
1465 snprintf(keystr, sizeof(keystr), "MSG_PENDING/%s", sharename);
1466
1467 if ( !tdb_store_uint32( pdb->tdb, keystr, 0 ) ) {
1468 /* log a message but continue on */
1469
1470 DEBUG(0,("print_queue_update: failed to store MSG_PENDING flag for [%s]!\n",
1471 sharename));
1472 }
1473
1474 release_print_db( pdb );
1475
1476 return;
1477}
1478
1479/****************************************************************************
1480 Update the internal database from the system print queue for a queue.
1481 obtain a lock on the print queue before proceeding (needed when mutiple
1482 smbd processes maytry to update the lpq cache concurrently).
1483****************************************************************************/
1484
1485static void print_queue_update_with_lock( struct tevent_context *ev,
1486 struct messaging_context *msg_ctx,
1487 const char *sharename,
1488 struct printif *current_printif,
1489 char *lpq_command, char *lprm_command )
1490{
1491 fstring keystr;
1492 struct tdb_print_db *pdb;
1493
1494 DEBUG(5,("print_queue_update_with_lock: printer share = %s\n", sharename));
1495 pdb = get_print_db_byname(sharename);
1496 if (!pdb)
1497 return;
1498
1499 if ( !print_cache_expired(sharename, False) ) {
1500 DEBUG(5,("print_queue_update_with_lock: print cache for %s is still ok\n", sharename));
1501 release_print_db(pdb);
1502 return;
1503 }
1504
1505 /*
1506 * Check to see if someone else is doing this update.
1507 * This is essentially a mutex on the update.
1508 */
1509
1510 if (get_updating_pid(sharename) != -1) {
1511 release_print_db(pdb);
1512 return;
1513 }
1514
1515 /* Lock the queue for the database update */
1516
1517 slprintf(keystr, sizeof(keystr) - 1, "LOCK/%s", sharename);
1518 /* Only wait 10 seconds for this. */
1519 if (tdb_lock_bystring_with_timeout(pdb->tdb, keystr, 10) == -1) {
1520 DEBUG(0,("print_queue_update_with_lock: Failed to lock printer %s database\n", sharename));
1521 release_print_db(pdb);
1522 return;
1523 }
1524
1525 /*
1526 * Ensure that no one else got in here.
1527 * If the updating pid is still -1 then we are
1528 * the winner.
1529 */
1530
1531 if (get_updating_pid(sharename) != -1) {
1532 /*
1533 * Someone else is doing the update, exit.
1534 */
1535 tdb_unlock_bystring(pdb->tdb, keystr);
1536 release_print_db(pdb);
1537 return;
1538 }
1539
1540 /*
1541 * We're going to do the update ourselves.
1542 */
1543
1544 /* Tell others we're doing the update. */
1545 set_updating_pid(sharename, True);
1546
1547 /*
1548 * Allow others to enter and notice we're doing
1549 * the update.
1550 */
1551
1552 tdb_unlock_bystring(pdb->tdb, keystr);
1553
1554 /* do the main work now */
1555
1556 print_queue_update_internal(ev, msg_ctx,
1557 sharename, current_printif,
1558 lpq_command, lprm_command);
1559
1560 /* Delete our pid from the db. */
1561 set_updating_pid(sharename, False);
1562 release_print_db(pdb);
1563}
1564
1565/****************************************************************************
1566this is the receive function of the background lpq updater
1567****************************************************************************/
1568void print_queue_receive(struct messaging_context *msg,
1569 void *private_data,
1570 uint32_t msg_type,
1571 struct server_id server_id,
1572 DATA_BLOB *data)
1573{
1574 fstring sharename;
1575 char *lpqcommand = NULL, *lprmcommand = NULL;
1576 int printing_type;
1577 size_t len;
1578
1579 len = tdb_unpack( (uint8 *)data->data, data->length, "fdPP",
1580 sharename,
1581 &printing_type,
1582 &lpqcommand,
1583 &lprmcommand );
1584
1585 if ( len == -1 ) {
1586 SAFE_FREE(lpqcommand);
1587 SAFE_FREE(lprmcommand);
1588 DEBUG(0,("print_queue_receive: Got invalid print queue update message\n"));
1589 return;
1590 }
1591
1592 print_queue_update_with_lock(server_event_context(), msg, sharename,
1593 get_printer_fns_from_type((enum printing_types)printing_type),
1594 lpqcommand, lprmcommand );
1595
1596 SAFE_FREE(lpqcommand);
1597 SAFE_FREE(lprmcommand);
1598 return;
1599}
1600
1601static void printing_pause_fd_handler(struct tevent_context *ev,
1602 struct tevent_fd *fde,
1603 uint16_t flags,
1604 void *private_data)
1605{
1606 /*
1607 * If pause_pipe[1] is closed it means the parent smbd
1608 * and children exited or aborted.
1609 */
1610 exit_server_cleanly(NULL);
1611}
1612
1613extern struct child_pid *children;
1614extern int num_children;
1615
1616static void add_child_pid(pid_t pid)
1617{
1618 struct child_pid *child;
1619
1620 child = SMB_MALLOC_P(struct child_pid);
1621 if (child == NULL) {
1622 DEBUG(0, ("Could not add child struct -- malloc failed\n"));
1623 return;
1624 }
1625 child->pid = pid;
1626 DLIST_ADD(children, child);
1627 num_children += 1;
1628}
1629
1630static pid_t background_lpq_updater_pid = -1;
1631
1632/****************************************************************************
1633main thread of the background lpq updater
1634****************************************************************************/
1635void start_background_queue(struct tevent_context *ev,
1636 struct messaging_context *msg_ctx)
1637{
1638 /* Use local variables for this as we don't
1639 * need to save the parent side of this, just
1640 * ensure it closes when the process exits.
1641 */
1642 int pause_pipe[2];
1643
1644 DEBUG(3,("start_background_queue: Starting background LPQ thread\n"));
1645
1646 if (pipe(pause_pipe) == -1) {
1647 DEBUG(5,("start_background_queue: cannot create pipe. %s\n", strerror(errno) ));
1648 exit(1);
1649 }
1650
1651 background_lpq_updater_pid = sys_fork();
1652
1653 if (background_lpq_updater_pid == -1) {
1654 DEBUG(5,("start_background_queue: background LPQ thread failed to start. %s\n", strerror(errno) ));
1655 exit(1);
1656 }
1657
1658 /* Track the printing pid along with other smbd children */
1659 add_child_pid(background_lpq_updater_pid);
1660
1661 if(background_lpq_updater_pid == 0) {
1662 struct tevent_fd *fde;
1663 int ret;
1664 NTSTATUS status;
1665
1666 /* Child. */
1667 DEBUG(5,("start_background_queue: background LPQ thread started\n"));
1668
1669 close(pause_pipe[0]);
1670 pause_pipe[0] = -1;
1671
1672 status = reinit_after_fork(msg_ctx, ev, procid_self(), true);
1673
1674 if (!NT_STATUS_IS_OK(status)) {
1675 DEBUG(0,("reinit_after_fork() failed\n"));
1676 smb_panic("reinit_after_fork() failed");
1677 }
1678
1679 smbd_setup_sig_term_handler();
1680 smbd_setup_sig_hup_handler(ev, msg_ctx);
1681
1682 if (!serverid_register(procid_self(),
1683 FLAG_MSG_GENERAL|FLAG_MSG_SMBD
1684 |FLAG_MSG_PRINT_GENERAL)) {
1685 exit(1);
1686 }
1687
1688 if (!locking_init()) {
1689 exit(1);
1690 }
1691
1692 messaging_register(msg_ctx, NULL, MSG_PRINTER_UPDATE,
1693 print_queue_receive);
1694
1695 fde = tevent_add_fd(ev, ev, pause_pipe[1], TEVENT_FD_READ,
1696 printing_pause_fd_handler,
1697 NULL);
1698 if (!fde) {
1699 DEBUG(0,("tevent_add_fd() failed for pause_pipe\n"));
1700 smb_panic("tevent_add_fd() failed for pause_pipe");
1701 }
1702
1703 DEBUG(5,("start_background_queue: background LPQ thread waiting for messages\n"));
1704 ret = tevent_loop_wait(ev);
1705 /* should not be reached */
1706 DEBUG(0,("background_queue: tevent_loop_wait() exited with %d - %s\n",
1707 ret, (ret == 0) ? "out of events" : strerror(errno)));
1708 exit(1);
1709 }
1710
1711 close(pause_pipe[1]);
1712}
1713
1714/****************************************************************************
1715update the internal database from the system print queue for a queue
1716****************************************************************************/
1717
1718static void print_queue_update(struct messaging_context *msg_ctx,
1719 int snum, bool force)
1720{
1721 fstring key;
1722 fstring sharename;
1723 char *lpqcommand = NULL;
1724 char *lprmcommand = NULL;
1725 uint8 *buffer = NULL;
1726 size_t len = 0;
1727 size_t newlen;
1728 struct tdb_print_db *pdb;
1729 int type;
1730 struct printif *current_printif;
1731 TALLOC_CTX *ctx = talloc_tos();
1732
1733 fstrcpy( sharename, lp_const_servicename(snum));
1734
1735 /* don't strip out characters like '$' from the printername */
1736
1737 lpqcommand = talloc_string_sub2(ctx,
1738 lp_lpqcommand(snum),
1739 "%p",
1740 lp_printername(snum),
1741 false, false, false);
1742 if (!lpqcommand) {
1743 return;
1744 }
1745 lpqcommand = talloc_sub_advanced(ctx,
1746 lp_servicename(snum),
1747 current_user_info.unix_name,
1748 "",
1749 current_user.ut.gid,
1750 get_current_username(),
1751 current_user_info.domain,
1752 lpqcommand);
1753 if (!lpqcommand) {
1754 return;
1755 }
1756
1757 lprmcommand = talloc_string_sub2(ctx,
1758 lp_lprmcommand(snum),
1759 "%p",
1760 lp_printername(snum),
1761 false, false, false);
1762 if (!lprmcommand) {
1763 return;
1764 }
1765 lprmcommand = talloc_sub_advanced(ctx,
1766 lp_servicename(snum),
1767 current_user_info.unix_name,
1768 "",
1769 current_user.ut.gid,
1770 get_current_username(),
1771 current_user_info.domain,
1772 lprmcommand);
1773 if (!lprmcommand) {
1774 return;
1775 }
1776
1777 /*
1778 * Make sure that the background queue process exists.
1779 * Otherwise just do the update ourselves
1780 */
1781
1782 if ( force || background_lpq_updater_pid == -1 ) {
1783 DEBUG(4,("print_queue_update: updating queue [%s] myself\n", sharename));
1784 current_printif = get_printer_fns( snum );
1785 print_queue_update_with_lock(server_event_context(), msg_ctx,
1786 sharename, current_printif,
1787 lpqcommand, lprmcommand);
1788
1789 return;
1790 }
1791
1792 type = lp_printing(snum);
1793
1794 /* get the length */
1795
1796 len = tdb_pack( NULL, 0, "fdPP",
1797 sharename,
1798 type,
1799 lpqcommand,
1800 lprmcommand );
1801
1802 buffer = SMB_XMALLOC_ARRAY( uint8, len );
1803
1804 /* now pack the buffer */
1805 newlen = tdb_pack( buffer, len, "fdPP",
1806 sharename,
1807 type,
1808 lpqcommand,
1809 lprmcommand );
1810
1811 SMB_ASSERT( newlen == len );
1812
1813 DEBUG(10,("print_queue_update: Sending message -> printer = %s, "
1814 "type = %d, lpq command = [%s] lprm command = [%s]\n",
1815 sharename, type, lpqcommand, lprmcommand ));
1816
1817 /* here we set a msg pending record for other smbd processes
1818 to throttle the number of duplicate print_queue_update msgs
1819 sent. */
1820
1821 pdb = get_print_db_byname(sharename);
1822 if (!pdb) {
1823 SAFE_FREE(buffer);
1824 return;
1825 }
1826
1827 snprintf(key, sizeof(key), "MSG_PENDING/%s", sharename);
1828
1829 if ( !tdb_store_uint32( pdb->tdb, key, time(NULL) ) ) {
1830 /* log a message but continue on */
1831
1832 DEBUG(0,("print_queue_update: failed to store MSG_PENDING flag for [%s]!\n",
1833 sharename));
1834 }
1835
1836 release_print_db( pdb );
1837
1838 /* finally send the message */
1839
1840 messaging_send_buf(msg_ctx, pid_to_procid(background_lpq_updater_pid),
1841 MSG_PRINTER_UPDATE, (uint8 *)buffer, len);
1842
1843 SAFE_FREE( buffer );
1844
1845 return;
1846}
1847
1848/****************************************************************************
1849 Create/Update an entry in the print tdb that will allow us to send notify
1850 updates only to interested smbd's.
1851****************************************************************************/
1852
1853bool print_notify_register_pid(int snum)
1854{
1855 TDB_DATA data;
1856 struct tdb_print_db *pdb = NULL;
1857 TDB_CONTEXT *tdb = NULL;
1858 const char *printername;
1859 uint32 mypid = (uint32)sys_getpid();
1860 bool ret = False;
1861 size_t i;
1862
1863 /* if (snum == -1), then the change notify request was
1864 on a print server handle and we need to register on
1865 all print queus */
1866
1867 if (snum == -1)
1868 {
1869 int num_services = lp_numservices();
1870 int idx;
1871
1872 for ( idx=0; idx<num_services; idx++ ) {
1873 if (lp_snum_ok(idx) && lp_print_ok(idx) )
1874 print_notify_register_pid(idx);
1875 }
1876
1877 return True;
1878 }
1879 else /* register for a specific printer */
1880 {
1881 printername = lp_const_servicename(snum);
1882 pdb = get_print_db_byname(printername);
1883 if (!pdb)
1884 return False;
1885 tdb = pdb->tdb;
1886 }
1887
1888 if (tdb_lock_bystring_with_timeout(tdb, NOTIFY_PID_LIST_KEY, 10) == -1) {
1889 DEBUG(0,("print_notify_register_pid: Failed to lock printer %s\n",
1890 printername));
1891 if (pdb)
1892 release_print_db(pdb);
1893 return False;
1894 }
1895
1896 data = get_printer_notify_pid_list( tdb, printername, True );
1897
1898 /* Add ourselves and increase the refcount. */
1899
1900 for (i = 0; i < data.dsize; i += 8) {
1901 if (IVAL(data.dptr,i) == mypid) {
1902 uint32 new_refcount = IVAL(data.dptr, i+4) + 1;
1903 SIVAL(data.dptr, i+4, new_refcount);
1904 break;
1905 }
1906 }
1907
1908 if (i == data.dsize) {
1909 /* We weren't in the list. Realloc. */
1910 data.dptr = (uint8 *)SMB_REALLOC(data.dptr, data.dsize + 8);
1911 if (!data.dptr) {
1912 DEBUG(0,("print_notify_register_pid: Relloc fail for printer %s\n",
1913 printername));
1914 goto done;
1915 }
1916 data.dsize += 8;
1917 SIVAL(data.dptr,data.dsize - 8,mypid);
1918 SIVAL(data.dptr,data.dsize - 4,1); /* Refcount. */
1919 }
1920
1921 /* Store back the record. */
1922 if (tdb_store_bystring(tdb, NOTIFY_PID_LIST_KEY, data, TDB_REPLACE) == -1) {
1923 DEBUG(0,("print_notify_register_pid: Failed to update pid \
1924list for printer %s\n", printername));
1925 goto done;
1926 }
1927
1928 ret = True;
1929
1930 done:
1931
1932 tdb_unlock_bystring(tdb, NOTIFY_PID_LIST_KEY);
1933 if (pdb)
1934 release_print_db(pdb);
1935 SAFE_FREE(data.dptr);
1936 return ret;
1937}
1938
1939/****************************************************************************
1940 Update an entry in the print tdb that will allow us to send notify
1941 updates only to interested smbd's.
1942****************************************************************************/
1943
1944bool print_notify_deregister_pid(int snum)
1945{
1946 TDB_DATA data;
1947 struct tdb_print_db *pdb = NULL;
1948 TDB_CONTEXT *tdb = NULL;
1949 const char *printername;
1950 uint32 mypid = (uint32)sys_getpid();
1951 size_t i;
1952 bool ret = False;
1953
1954 /* if ( snum == -1 ), we are deregister a print server handle
1955 which means to deregister on all print queues */
1956
1957 if (snum == -1)
1958 {
1959 int num_services = lp_numservices();
1960 int idx;
1961
1962 for ( idx=0; idx<num_services; idx++ ) {
1963 if ( lp_snum_ok(idx) && lp_print_ok(idx) )
1964 print_notify_deregister_pid(idx);
1965 }
1966
1967 return True;
1968 }
1969 else /* deregister a specific printer */
1970 {
1971 printername = lp_const_servicename(snum);
1972 pdb = get_print_db_byname(printername);
1973 if (!pdb)
1974 return False;
1975 tdb = pdb->tdb;
1976 }
1977
1978 if (tdb_lock_bystring_with_timeout(tdb, NOTIFY_PID_LIST_KEY, 10) == -1) {
1979 DEBUG(0,("print_notify_register_pid: Failed to lock \
1980printer %s database\n", printername));
1981 if (pdb)
1982 release_print_db(pdb);
1983 return False;
1984 }
1985
1986 data = get_printer_notify_pid_list( tdb, printername, True );
1987
1988 /* Reduce refcount. Remove ourselves if zero. */
1989
1990 for (i = 0; i < data.dsize; ) {
1991 if (IVAL(data.dptr,i) == mypid) {
1992 uint32 refcount = IVAL(data.dptr, i+4);
1993
1994 refcount--;
1995
1996 if (refcount == 0) {
1997 if (data.dsize - i > 8)
1998 memmove( &data.dptr[i], &data.dptr[i+8], data.dsize - i - 8);
1999 data.dsize -= 8;
2000 continue;
2001 }
2002 SIVAL(data.dptr, i+4, refcount);
2003 }
2004
2005 i += 8;
2006 }
2007
2008 if (data.dsize == 0)
2009 SAFE_FREE(data.dptr);
2010
2011 /* Store back the record. */
2012 if (tdb_store_bystring(tdb, NOTIFY_PID_LIST_KEY, data, TDB_REPLACE) == -1) {
2013 DEBUG(0,("print_notify_register_pid: Failed to update pid \
2014list for printer %s\n", printername));
2015 goto done;
2016 }
2017
2018 ret = True;
2019
2020 done:
2021
2022 tdb_unlock_bystring(tdb, NOTIFY_PID_LIST_KEY);
2023 if (pdb)
2024 release_print_db(pdb);
2025 SAFE_FREE(data.dptr);
2026 return ret;
2027}
2028
2029/****************************************************************************
2030 Check if a jobid is valid. It is valid if it exists in the database.
2031****************************************************************************/
2032
2033bool print_job_exists(const char* sharename, uint32 jobid)
2034{
2035 struct tdb_print_db *pdb = get_print_db_byname(sharename);
2036 bool ret;
2037 uint32_t tmp;
2038
2039 if (!pdb)
2040 return False;
2041 ret = tdb_exists(pdb->tdb, print_key(jobid, &tmp));
2042 release_print_db(pdb);
2043 return ret;
2044}
2045
2046/****************************************************************************
2047 Give the filename used for a jobid.
2048 Only valid for the process doing the spooling and when the job
2049 has not been spooled.
2050****************************************************************************/
2051
2052char *print_job_fname(const char* sharename, uint32 jobid)
2053{
2054 struct printjob *pjob = print_job_find(sharename, jobid);
2055 if (!pjob || pjob->spooled || pjob->pid != sys_getpid())
2056 return NULL;
2057 return pjob->filename;
2058}
2059
2060
2061/****************************************************************************
2062 Give the filename used for a jobid.
2063 Only valid for the process doing the spooling and when the job
2064 has not been spooled.
2065****************************************************************************/
2066
2067struct spoolss_DeviceMode *print_job_devmode(const char* sharename, uint32 jobid)
2068{
2069 struct printjob *pjob = print_job_find(sharename, jobid);
2070
2071 if ( !pjob )
2072 return NULL;
2073
2074 return pjob->devmode;
2075}
2076
2077/****************************************************************************
2078 Set the name of a job. Only possible for owner.
2079****************************************************************************/
2080
2081bool print_job_set_name(struct tevent_context *ev,
2082 struct messaging_context *msg_ctx,
2083 const char *sharename, uint32 jobid, const char *name)
2084{
2085 struct printjob *pjob;
2086
2087 pjob = print_job_find(sharename, jobid);
2088 if (!pjob || pjob->pid != sys_getpid())
2089 return False;
2090
2091 fstrcpy(pjob->jobname, name);
2092 return pjob_store(ev, msg_ctx, sharename, jobid, pjob);
2093}
2094
2095/****************************************************************************
2096 Get the name of a job. Only possible for owner.
2097****************************************************************************/
2098
2099bool print_job_get_name(TALLOC_CTX *mem_ctx, const char *sharename, uint32_t jobid, char **name)
2100{
2101 struct printjob *pjob;
2102
2103 pjob = print_job_find(sharename, jobid);
2104 if (!pjob || pjob->pid != sys_getpid()) {
2105 return false;
2106 }
2107
2108 *name = talloc_strdup(mem_ctx, pjob->jobname);
2109 if (!*name) {
2110 return false;
2111 }
2112
2113 return true;
2114}
2115
2116
2117/***************************************************************************
2118 Remove a jobid from the 'jobs added' list.
2119***************************************************************************/
2120
2121static bool remove_from_jobs_added(const char* sharename, uint32 jobid)
2122{
2123 struct tdb_print_db *pdb = get_print_db_byname(sharename);
2124 TDB_DATA data, key;
2125 size_t job_count, i;
2126 bool ret = False;
2127 bool gotlock = False;
2128
2129 if (!pdb) {
2130 return False;
2131 }
2132
2133 ZERO_STRUCT(data);
2134
2135 key = string_tdb_data("INFO/jobs_added");
2136
2137 if (tdb_chainlock_with_timeout(pdb->tdb, key, 5) == -1)
2138 goto out;
2139
2140 gotlock = True;
2141
2142 data = tdb_fetch(pdb->tdb, key);
2143
2144 if (data.dptr == NULL || data.dsize == 0 || (data.dsize % 4 != 0))
2145 goto out;
2146
2147 job_count = data.dsize / 4;
2148 for (i = 0; i < job_count; i++) {
2149 uint32 ch_jobid;
2150
2151 ch_jobid = IVAL(data.dptr, i*4);
2152 if (ch_jobid == jobid) {
2153 if (i < job_count -1 )
2154 memmove(data.dptr + (i*4), data.dptr + (i*4) + 4, (job_count - i - 1)*4 );
2155 data.dsize -= 4;
2156 if (tdb_store(pdb->tdb, key, data, TDB_REPLACE) == -1)
2157 goto out;
2158 break;
2159 }
2160 }
2161
2162 ret = True;
2163 out:
2164
2165 if (gotlock)
2166 tdb_chainunlock(pdb->tdb, key);
2167 SAFE_FREE(data.dptr);
2168 release_print_db(pdb);
2169 if (ret)
2170 DEBUG(10,("remove_from_jobs_added: removed jobid %u\n", (unsigned int)jobid ));
2171 else
2172 DEBUG(10,("remove_from_jobs_added: Failed to remove jobid %u\n", (unsigned int)jobid ));
2173 return ret;
2174}
2175
2176/****************************************************************************
2177 Delete a print job - don't update queue.
2178****************************************************************************/
2179
2180static bool print_job_delete1(struct tevent_context *ev,
2181 struct messaging_context *msg_ctx,
2182 int snum, uint32 jobid)
2183{
2184 const char* sharename = lp_const_servicename(snum);
2185 struct printjob *pjob = print_job_find(sharename, jobid);
2186 int result = 0;
2187 struct printif *current_printif = get_printer_fns( snum );
2188
2189 if (!pjob)
2190 return False;
2191
2192 /*
2193 * If already deleting just return.
2194 */
2195
2196 if (pjob->status == LPQ_DELETING)
2197 return True;
2198
2199 /* Hrm - we need to be able to cope with deleting a job before it
2200 has reached the spooler. Just mark it as LPQ_DELETING and
2201 let the print_queue_update() code rmeove the record */
2202
2203
2204 if (pjob->sysjob == -1) {
2205 DEBUG(5, ("attempt to delete job %u not seen by lpr\n", (unsigned int)jobid));
2206 }
2207
2208 /* Set the tdb entry to be deleting. */
2209
2210 pjob->status = LPQ_DELETING;
2211 pjob_store(ev, msg_ctx, sharename, jobid, pjob);
2212
2213 if (pjob->spooled && pjob->sysjob != -1)
2214 {
2215 result = (*(current_printif->job_delete))(
2216 lp_printername(snum),
2217 lp_lprmcommand(snum),
2218 pjob);
2219
2220 /* Delete the tdb entry if the delete succeeded or the job hasn't
2221 been spooled. */
2222
2223 if (result == 0) {
2224 struct tdb_print_db *pdb = get_print_db_byname(sharename);
2225 int njobs = 1;
2226
2227 if (!pdb)
2228 return False;
2229 pjob_delete(ev, msg_ctx, sharename, jobid);
2230 /* Ensure we keep a rough count of the number of total jobs... */
2231 tdb_change_int32_atomic(pdb->tdb, "INFO/total_jobs", &njobs, -1);
2232 release_print_db(pdb);
2233 }
2234 }
2235
2236 remove_from_jobs_added( sharename, jobid );
2237
2238 return (result == 0);
2239}
2240
2241/****************************************************************************
2242 Return true if the current user owns the print job.
2243****************************************************************************/
2244
2245static bool is_owner(const struct auth_serversupplied_info *server_info,
2246 const char *servicename,
2247 uint32 jobid)
2248{
2249 struct printjob *pjob = print_job_find(servicename, jobid);
2250
2251 if (!pjob || !server_info)
2252 return False;
2253
2254 return strequal(pjob->user, server_info->sanitized_username);
2255}
2256
2257/****************************************************************************
2258 Delete a print job.
2259****************************************************************************/
2260
2261WERROR print_job_delete(const struct auth_serversupplied_info *server_info,
2262 struct messaging_context *msg_ctx,
2263 int snum, uint32_t jobid)
2264{
2265 const char* sharename = lp_const_servicename(snum);
2266 struct printjob *pjob;
2267 bool owner;
2268 char *fname;
2269
2270 owner = is_owner(server_info, lp_const_servicename(snum), jobid);
2271
2272 /* Check access against security descriptor or whether the user
2273 owns their job. */
2274
2275 if (!owner &&
2276 !print_access_check(server_info, msg_ctx, snum,
2277 JOB_ACCESS_ADMINISTER)) {
2278 DEBUG(3, ("delete denied by security descriptor\n"));
2279
2280 /* BEGIN_ADMIN_LOG */
2281 sys_adminlog( LOG_ERR,
2282 "Permission denied-- user not allowed to delete, \
2283pause, or resume print job. User name: %s. Printer name: %s.",
2284 uidtoname(server_info->utok.uid),
2285 lp_printername(snum) );
2286 /* END_ADMIN_LOG */
2287
2288 return WERR_ACCESS_DENIED;
2289 }
2290
2291 /*
2292 * get the spooled filename of the print job
2293 * if this works, then the file has not been spooled
2294 * to the underlying print system. Just delete the
2295 * spool file & return.
2296 */
2297
2298 fname = print_job_fname(sharename, jobid);
2299 if (fname != NULL) {
2300 /* remove the spool file */
2301 DEBUG(10, ("print_job_delete: "
2302 "Removing spool file [%s]\n", fname));
2303 if (unlink(fname) == -1) {
2304 return map_werror_from_unix(errno);
2305 }
2306 }
2307
2308 if (!print_job_delete1(server_event_context(), msg_ctx, snum, jobid)) {
2309 return WERR_ACCESS_DENIED;
2310 }
2311
2312 /* force update the database and say the delete failed if the
2313 job still exists */
2314
2315 print_queue_update(msg_ctx, snum, True);
2316
2317 pjob = print_job_find(sharename, jobid);
2318 if (pjob && (pjob->status != LPQ_DELETING)) {
2319 return WERR_ACCESS_DENIED;
2320 }
2321
2322 return WERR_PRINTER_HAS_JOBS_QUEUED;
2323}
2324
2325/****************************************************************************
2326 Pause a job.
2327****************************************************************************/
2328
2329bool print_job_pause(const struct auth_serversupplied_info *server_info,
2330 struct messaging_context *msg_ctx,
2331 int snum, uint32 jobid, WERROR *errcode)
2332{
2333 const char* sharename = lp_const_servicename(snum);
2334 struct printjob *pjob;
2335 int ret = -1;
2336 struct printif *current_printif = get_printer_fns( snum );
2337
2338 pjob = print_job_find(sharename, jobid);
2339
2340 if (!pjob || !server_info) {
2341 DEBUG(10, ("print_job_pause: no pjob or user for jobid %u\n",
2342 (unsigned int)jobid ));
2343 return False;
2344 }
2345
2346 if (!pjob->spooled || pjob->sysjob == -1) {
2347 DEBUG(10, ("print_job_pause: not spooled or bad sysjob = %d for jobid %u\n",
2348 (int)pjob->sysjob, (unsigned int)jobid ));
2349 return False;
2350 }
2351
2352 if (!is_owner(server_info, lp_const_servicename(snum), jobid) &&
2353 !print_access_check(server_info, msg_ctx, snum,
2354 JOB_ACCESS_ADMINISTER)) {
2355 DEBUG(3, ("pause denied by security descriptor\n"));
2356
2357 /* BEGIN_ADMIN_LOG */
2358 sys_adminlog( LOG_ERR,
2359 "Permission denied-- user not allowed to delete, \
2360pause, or resume print job. User name: %s. Printer name: %s.",
2361 uidtoname(server_info->utok.uid),
2362 lp_printername(snum) );
2363 /* END_ADMIN_LOG */
2364
2365 *errcode = WERR_ACCESS_DENIED;
2366 return False;
2367 }
2368
2369 /* need to pause the spooled entry */
2370 ret = (*(current_printif->job_pause))(snum, pjob);
2371
2372 if (ret != 0) {
2373 *errcode = WERR_INVALID_PARAM;
2374 return False;
2375 }
2376
2377 /* force update the database */
2378 print_cache_flush(lp_const_servicename(snum));
2379
2380 /* Send a printer notify message */
2381
2382 notify_job_status(server_event_context(), msg_ctx, sharename, jobid,
2383 JOB_STATUS_PAUSED);
2384
2385 /* how do we tell if this succeeded? */
2386
2387 return True;
2388}
2389
2390/****************************************************************************
2391 Resume a job.
2392****************************************************************************/
2393
2394bool print_job_resume(const struct auth_serversupplied_info *server_info,
2395 struct messaging_context *msg_ctx,
2396 int snum, uint32 jobid, WERROR *errcode)
2397{
2398 const char *sharename = lp_const_servicename(snum);
2399 struct printjob *pjob;
2400 int ret;
2401 struct printif *current_printif = get_printer_fns( snum );
2402
2403 pjob = print_job_find(sharename, jobid);
2404
2405 if (!pjob || !server_info) {
2406 DEBUG(10, ("print_job_resume: no pjob or user for jobid %u\n",
2407 (unsigned int)jobid ));
2408 return False;
2409 }
2410
2411 if (!pjob->spooled || pjob->sysjob == -1) {
2412 DEBUG(10, ("print_job_resume: not spooled or bad sysjob = %d for jobid %u\n",
2413 (int)pjob->sysjob, (unsigned int)jobid ));
2414 return False;
2415 }
2416
2417 if (!is_owner(server_info, lp_const_servicename(snum), jobid) &&
2418 !print_access_check(server_info, msg_ctx, snum,
2419 JOB_ACCESS_ADMINISTER)) {
2420 DEBUG(3, ("resume denied by security descriptor\n"));
2421 *errcode = WERR_ACCESS_DENIED;
2422
2423 /* BEGIN_ADMIN_LOG */
2424 sys_adminlog( LOG_ERR,
2425 "Permission denied-- user not allowed to delete, \
2426pause, or resume print job. User name: %s. Printer name: %s.",
2427 uidtoname(server_info->utok.uid),
2428 lp_printername(snum) );
2429 /* END_ADMIN_LOG */
2430 return False;
2431 }
2432
2433 ret = (*(current_printif->job_resume))(snum, pjob);
2434
2435 if (ret != 0) {
2436 *errcode = WERR_INVALID_PARAM;
2437 return False;
2438 }
2439
2440 /* force update the database */
2441 print_cache_flush(lp_const_servicename(snum));
2442
2443 /* Send a printer notify message */
2444
2445 notify_job_status(server_event_context(), msg_ctx, sharename, jobid,
2446 JOB_STATUS_QUEUED);
2447
2448 return True;
2449}
2450
2451/****************************************************************************
2452 Write to a print file.
2453****************************************************************************/
2454
2455ssize_t print_job_write(struct tevent_context *ev,
2456 struct messaging_context *msg_ctx,
2457 int snum, uint32 jobid, const char *buf, size_t size)
2458{
2459 const char* sharename = lp_const_servicename(snum);
2460 ssize_t return_code;
2461 struct printjob *pjob;
2462
2463 pjob = print_job_find(sharename, jobid);
2464
2465 if (!pjob)
2466 return -1;
2467 /* don't allow another process to get this info - it is meaningless */
2468 if (pjob->pid != sys_getpid())
2469 return -1;
2470
2471 /* if SMBD is spooling this can't be allowed */
2472 if (pjob->status == PJOB_SMBD_SPOOLING) {
2473 return -1;
2474 }
2475
2476 return_code = write_data(pjob->fd, buf, size);
2477
2478 if (return_code>0) {
2479 pjob->size += size;
2480 pjob_store(ev, msg_ctx, sharename, jobid, pjob);
2481 }
2482 return return_code;
2483}
2484
2485/****************************************************************************
2486 Get the queue status - do not update if db is out of date.
2487****************************************************************************/
2488
2489static int get_queue_status(const char* sharename, print_status_struct *status)
2490{
2491 fstring keystr;
2492 TDB_DATA data;
2493 struct tdb_print_db *pdb = get_print_db_byname(sharename);
2494 int len;
2495
2496 if (status) {
2497 ZERO_STRUCTP(status);
2498 }
2499
2500 if (!pdb)
2501 return 0;
2502
2503 if (status) {
2504 fstr_sprintf(keystr, "STATUS/%s", sharename);
2505 data = tdb_fetch(pdb->tdb, string_tdb_data(keystr));
2506 if (data.dptr) {
2507 if (data.dsize == sizeof(print_status_struct))
2508 /* this memcpy is ok since the status struct was
2509 not packed before storing it in the tdb */
2510 memcpy(status, data.dptr, sizeof(print_status_struct));
2511 SAFE_FREE(data.dptr);
2512 }
2513 }
2514 len = tdb_fetch_int32(pdb->tdb, "INFO/total_jobs");
2515 release_print_db(pdb);
2516 return (len == -1 ? 0 : len);
2517}
2518
2519/****************************************************************************
2520 Determine the number of jobs in a queue.
2521****************************************************************************/
2522
2523int print_queue_length(struct messaging_context *msg_ctx, int snum,
2524 print_status_struct *pstatus)
2525{
2526 const char* sharename = lp_const_servicename( snum );
2527 print_status_struct status;
2528 int len;
2529
2530 ZERO_STRUCT( status );
2531
2532 /* make sure the database is up to date */
2533 if (print_cache_expired(lp_const_servicename(snum), True))
2534 print_queue_update(msg_ctx, snum, False);
2535
2536 /* also fetch the queue status */
2537 memset(&status, 0, sizeof(status));
2538 len = get_queue_status(sharename, &status);
2539
2540 if (pstatus)
2541 *pstatus = status;
2542
2543 return len;
2544}
2545
2546/***************************************************************************
2547 Allocate a jobid. Hold the lock for as short a time as possible.
2548***************************************************************************/
2549
2550static WERROR allocate_print_jobid(struct tdb_print_db *pdb, int snum,
2551 const char *sharename, uint32 *pjobid)
2552{
2553 int i;
2554 uint32 jobid;
2555 enum TDB_ERROR terr;
2556 int ret;
2557
2558 *pjobid = (uint32)-1;
2559
2560 for (i = 0; i < 3; i++) {
2561 /* Lock the database - only wait 20 seconds. */
2562 ret = tdb_lock_bystring_with_timeout(pdb->tdb,
2563 "INFO/nextjob", 20);
2564 if (ret == -1) {
2565 DEBUG(0, ("allocate_print_jobid: "
2566 "Failed to lock printing database %s\n",
2567 sharename));
2568 terr = tdb_error(pdb->tdb);
2569 return ntstatus_to_werror(map_nt_error_from_tdb(terr));
2570 }
2571
2572 if (!tdb_fetch_uint32(pdb->tdb, "INFO/nextjob", &jobid)) {
2573 terr = tdb_error(pdb->tdb);
2574 if (terr != TDB_ERR_NOEXIST) {
2575 DEBUG(0, ("allocate_print_jobid: "
2576 "Failed to fetch INFO/nextjob "
2577 "for print queue %s\n", sharename));
2578 tdb_unlock_bystring(pdb->tdb, "INFO/nextjob");
2579 return ntstatus_to_werror(map_nt_error_from_tdb(terr));
2580 }
2581 DEBUG(10, ("allocate_print_jobid: "
2582 "No existing jobid in %s\n", sharename));
2583 jobid = 0;
2584 }
2585
2586 DEBUG(10, ("allocate_print_jobid: "
2587 "Read jobid %u from %s\n", jobid, sharename));
2588
2589 jobid = NEXT_JOBID(jobid);
2590
2591 ret = tdb_store_int32(pdb->tdb, "INFO/nextjob", jobid);
2592 if (ret == -1) {
2593 terr = tdb_error(pdb->tdb);
2594 DEBUG(3, ("allocate_print_jobid: "
2595 "Failed to store INFO/nextjob.\n"));
2596 tdb_unlock_bystring(pdb->tdb, "INFO/nextjob");
2597 return ntstatus_to_werror(map_nt_error_from_tdb(terr));
2598 }
2599
2600 /* We've finished with the INFO/nextjob lock. */
2601 tdb_unlock_bystring(pdb->tdb, "INFO/nextjob");
2602
2603 if (!print_job_exists(sharename, jobid)) {
2604 break;
2605 }
2606 DEBUG(10, ("allocate_print_jobid: "
2607 "Found jobid %u in %s\n", jobid, sharename));
2608 }
2609
2610 if (i > 2) {
2611 DEBUG(0, ("allocate_print_jobid: "
2612 "Failed to allocate a print job for queue %s\n",
2613 sharename));
2614 /* Probably full... */
2615 return WERR_NO_SPOOL_SPACE;
2616 }
2617
2618 /* Store a dummy placeholder. */
2619 {
2620 uint32_t tmp;
2621 TDB_DATA dum;
2622 dum.dptr = NULL;
2623 dum.dsize = 0;
2624 if (tdb_store(pdb->tdb, print_key(jobid, &tmp), dum,
2625 TDB_INSERT) == -1) {
2626 DEBUG(3, ("allocate_print_jobid: "
2627 "jobid (%d) failed to store placeholder.\n",
2628 jobid ));
2629 terr = tdb_error(pdb->tdb);
2630 return ntstatus_to_werror(map_nt_error_from_tdb(terr));
2631 }
2632 }
2633
2634 *pjobid = jobid;
2635 return WERR_OK;
2636}
2637
2638/***************************************************************************
2639 Append a jobid to the 'jobs added' list.
2640***************************************************************************/
2641
2642static bool add_to_jobs_added(struct tdb_print_db *pdb, uint32 jobid)
2643{
2644 TDB_DATA data;
2645 uint32 store_jobid;
2646
2647 SIVAL(&store_jobid, 0, jobid);
2648 data.dptr = (uint8 *)&store_jobid;
2649 data.dsize = 4;
2650
2651 DEBUG(10,("add_to_jobs_added: Added jobid %u\n", (unsigned int)jobid ));
2652
2653 return (tdb_append(pdb->tdb, string_tdb_data("INFO/jobs_added"),
2654 data) == 0);
2655}
2656
2657
2658/***************************************************************************
2659 Do all checks needed to determine if we can start a job.
2660***************************************************************************/
2661
2662static WERROR print_job_checks(const struct auth_serversupplied_info *server_info,
2663 struct messaging_context *msg_ctx,
2664 int snum, int *njobs)
2665{
2666 const char *sharename = lp_const_servicename(snum);
2667 uint64_t dspace, dsize;
2668 uint64_t minspace;
2669 int ret;
2670
2671 if (!print_access_check(server_info, msg_ctx, snum,
2672 PRINTER_ACCESS_USE)) {
2673 DEBUG(3, ("print_job_checks: "
2674 "job start denied by security descriptor\n"));
2675 return WERR_ACCESS_DENIED;
2676 }
2677
2678 if (!print_time_access_check(server_info, msg_ctx, sharename)) {
2679 DEBUG(3, ("print_job_checks: "
2680 "job start denied by time check\n"));
2681 return WERR_ACCESS_DENIED;
2682 }
2683
2684 /* see if we have sufficient disk space */
2685 if (lp_minprintspace(snum)) {
2686 minspace = lp_minprintspace(snum);
2687 ret = sys_fsusage(lp_pathname(snum), &dspace, &dsize);
2688 if (ret == 0 && dspace < 2*minspace) {
2689 DEBUG(3, ("print_job_checks: "
2690 "disk space check failed.\n"));
2691 return WERR_NO_SPOOL_SPACE;
2692 }
2693 }
2694
2695 /* for autoloaded printers, check that the printcap entry still exists */
2696 if (lp_autoloaded(snum) && !pcap_printername_ok(sharename)) {
2697 DEBUG(3, ("print_job_checks: printer name %s check failed.\n",
2698 sharename));
2699 return WERR_ACCESS_DENIED;
2700 }
2701
2702 /* Insure the maximum queue size is not violated */
2703 *njobs = print_queue_length(msg_ctx, snum, NULL);
2704 if (*njobs > lp_maxprintjobs(snum)) {
2705 DEBUG(3, ("print_job_checks: Queue %s number of jobs (%d) "
2706 "larger than max printjobs per queue (%d).\n",
2707 sharename, *njobs, lp_maxprintjobs(snum)));
2708 return WERR_NO_SPOOL_SPACE;
2709 }
2710
2711 return WERR_OK;
2712}
2713
2714/***************************************************************************
2715 Create a job file.
2716***************************************************************************/
2717
2718static WERROR print_job_spool_file(int snum, uint32_t jobid,
2719 const char *output_file,
2720 struct printjob *pjob)
2721{
2722 WERROR werr;
2723 SMB_STRUCT_STAT st;
2724 const char *path;
2725 int len;
2726
2727 /* if this file is within the printer path, it means that smbd
2728 * is spooling it and will pass us control when it is finished.
2729 * Verify that the file name is ok, within path, and it is
2730 * already already there */
2731 if (output_file) {
2732 path = lp_pathname(snum);
2733 len = strlen(path);
2734 if (strncmp(output_file, path, len) == 0 &&
2735 (output_file[len - 1] == '/' || output_file[len] == '/')) {
2736
2737 /* verify path is not too long */
2738 if (strlen(output_file) >= sizeof(pjob->filename)) {
2739 return WERR_INVALID_NAME;
2740 }
2741
2742 /* verify that the file exists */
2743 if (sys_stat(output_file, &st, false) != 0) {
2744 return WERR_INVALID_NAME;
2745 }
2746
2747 fstrcpy(pjob->filename, output_file);
2748
2749 DEBUG(3, ("print_job_spool_file:"
2750 "External spooling activated"));
2751
2752 /* we do not open the file until spooling is done */
2753 pjob->fd = -1;
2754 pjob->status = PJOB_SMBD_SPOOLING;
2755
2756 return WERR_OK;
2757 }
2758 }
2759
2760 slprintf(pjob->filename, sizeof(pjob->filename)-1,
2761 "%s/%s%.8u.XXXXXX", lp_pathname(snum),
2762 PRINT_SPOOL_PREFIX, (unsigned int)jobid);
2763 pjob->fd = mkstemp(pjob->filename);
2764
2765 if (pjob->fd == -1) {
2766 werr = map_werror_from_unix(errno);
2767 if (W_ERROR_EQUAL(werr, WERR_ACCESS_DENIED)) {
2768 /* Common setup error, force a report. */
2769 DEBUG(0, ("print_job_spool_file: "
2770 "insufficient permissions to open spool "
2771 "file %s.\n", pjob->filename));
2772 } else {
2773 /* Normal case, report at level 3 and above. */
2774 DEBUG(3, ("print_job_spool_file: "
2775 "can't open spool file %s\n",
2776 pjob->filename));
2777 }
2778 return werr;
2779 }
2780
2781 return WERR_OK;
2782}
2783
2784/***************************************************************************
2785 Start spooling a job - return the jobid.
2786***************************************************************************/
2787
2788WERROR print_job_start(const struct auth_serversupplied_info *server_info,
2789 struct messaging_context *msg_ctx,
2790 const char *clientmachine,
2791 int snum, const char *docname, const char *filename,
2792 struct spoolss_DeviceMode *devmode, uint32_t *_jobid)
2793{
2794 uint32_t jobid;
2795 char *path;
2796 struct printjob pjob;
2797 const char *sharename = lp_const_servicename(snum);
2798 struct tdb_print_db *pdb = get_print_db_byname(sharename);
2799 int njobs;
2800 WERROR werr;
2801
2802 if (!pdb) {
2803 return WERR_INTERNAL_DB_CORRUPTION;
2804 }
2805
2806 path = lp_pathname(snum);
2807
2808 werr = print_job_checks(server_info, msg_ctx, snum, &njobs);
2809 if (!W_ERROR_IS_OK(werr)) {
2810 release_print_db(pdb);
2811 return werr;
2812 }
2813
2814 DEBUG(10, ("print_job_start: "
2815 "Queue %s number of jobs (%d), max printjobs = %d\n",
2816 sharename, njobs, lp_maxprintjobs(snum)));
2817
2818 werr = allocate_print_jobid(pdb, snum, sharename, &jobid);
2819 if (!W_ERROR_IS_OK(werr)) {
2820 goto fail;
2821 }
2822
2823 /* create the database entry */
2824
2825 ZERO_STRUCT(pjob);
2826
2827 pjob.pid = sys_getpid();
2828 pjob.sysjob = -1;
2829 pjob.fd = -1;
2830 pjob.starttime = time(NULL);
2831 pjob.status = LPQ_SPOOLING;
2832 pjob.size = 0;
2833 pjob.spooled = False;
2834 pjob.smbjob = True;
2835 pjob.devmode = devmode;
2836
2837 fstrcpy(pjob.jobname, docname);
2838
2839 fstrcpy(pjob.clientmachine, clientmachine);
2840
2841 fstrcpy(pjob.user, lp_printjob_username(snum));
2842 standard_sub_advanced(sharename, server_info->sanitized_username,
2843 path, server_info->utok.gid,
2844 server_info->sanitized_username,
2845 server_info->info3->base.domain.string,
2846 pjob.user, sizeof(pjob.user)-1);
2847 /* ensure NULL termination */
2848 pjob.user[sizeof(pjob.user)-1] = '\0';
2849
2850 fstrcpy(pjob.queuename, lp_const_servicename(snum));
2851
2852 /* we have a job entry - now create the spool file */
2853 werr = print_job_spool_file(snum, jobid, filename, &pjob);
2854 if (!W_ERROR_IS_OK(werr)) {
2855 goto fail;
2856 }
2857
2858 pjob_store(server_event_context(), msg_ctx, sharename, jobid, &pjob);
2859
2860 /* Update the 'jobs added' entry used by print_queue_status. */
2861 add_to_jobs_added(pdb, jobid);
2862
2863 /* Ensure we keep a rough count of the number of total jobs... */
2864 tdb_change_int32_atomic(pdb->tdb, "INFO/total_jobs", &njobs, 1);
2865
2866 release_print_db(pdb);
2867
2868 *_jobid = jobid;
2869 return WERR_OK;
2870
2871fail:
2872 if (jobid != -1) {
2873 pjob_delete(server_event_context(), msg_ctx, sharename, jobid);
2874 }
2875
2876 release_print_db(pdb);
2877
2878 DEBUG(3, ("print_job_start: returning fail. "
2879 "Error = %s\n", win_errstr(werr)));
2880 return werr;
2881}
2882
2883/****************************************************************************
2884 Update the number of pages spooled to jobid
2885****************************************************************************/
2886
2887void print_job_endpage(struct messaging_context *msg_ctx,
2888 int snum, uint32 jobid)
2889{
2890 const char* sharename = lp_const_servicename(snum);
2891 struct printjob *pjob;
2892
2893 pjob = print_job_find(sharename, jobid);
2894 if (!pjob)
2895 return;
2896 /* don't allow another process to get this info - it is meaningless */
2897 if (pjob->pid != sys_getpid())
2898 return;
2899
2900 pjob->page_count++;
2901 pjob_store(server_event_context(), msg_ctx, sharename, jobid, pjob);
2902}
2903
2904/****************************************************************************
2905 Print a file - called on closing the file. This spools the job.
2906 If normal close is false then we're tearing down the jobs - treat as an
2907 error.
2908****************************************************************************/
2909
2910NTSTATUS print_job_end(struct messaging_context *msg_ctx, int snum,
2911 uint32 jobid, enum file_close_type close_type)
2912{
2913 const char* sharename = lp_const_servicename(snum);
2914 struct printjob *pjob;
2915 int ret;
2916 SMB_STRUCT_STAT sbuf;
2917 struct printif *current_printif = get_printer_fns( snum );
2918 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
2919
2920 pjob = print_job_find(sharename, jobid);
2921
2922 if (!pjob) {
2923 return NT_STATUS_PRINT_CANCELLED;
2924 }
2925
2926 if (pjob->spooled || pjob->pid != sys_getpid()) {
2927 return NT_STATUS_ACCESS_DENIED;
2928 }
2929
2930 if (close_type == NORMAL_CLOSE || close_type == SHUTDOWN_CLOSE) {
2931 if (pjob->status == PJOB_SMBD_SPOOLING) {
2932 /* take over the file now, smbd is done */
2933 if (sys_stat(pjob->filename, &sbuf, false) != 0) {
2934 status = map_nt_error_from_unix(errno);
2935 DEBUG(3, ("print_job_end: "
2936 "stat file failed for jobid %d\n",
2937 jobid));
2938 goto fail;
2939 }
2940
2941 pjob->status = LPQ_SPOOLING;
2942
2943 } else {
2944
2945 if ((sys_fstat(pjob->fd, &sbuf, false) != 0)) {
2946 status = map_nt_error_from_unix(errno);
2947 close(pjob->fd);
2948 DEBUG(3, ("print_job_end: "
2949 "stat file failed for jobid %d\n",
2950 jobid));
2951 goto fail;
2952 }
2953
2954 close(pjob->fd);
2955 }
2956
2957 pjob->size = sbuf.st_ex_size;
2958 } else {
2959
2960 /*
2961 * Not a normal close, something has gone wrong. Cleanup.
2962 */
2963 if (pjob->fd != -1) {
2964 close(pjob->fd);
2965 }
2966 goto fail;
2967 }
2968
2969 /* Technically, this is not quite right. If the printer has a separator
2970 * page turned on, the NT spooler prints the separator page even if the
2971 * print job is 0 bytes. 010215 JRR */
2972 if (pjob->size == 0 || pjob->status == LPQ_DELETING) {
2973 /* don't bother spooling empty files or something being deleted. */
2974 DEBUG(5,("print_job_end: canceling spool of %s (%s)\n",
2975 pjob->filename, pjob->size ? "deleted" : "zero length" ));
2976 unlink(pjob->filename);
2977 pjob_delete(server_event_context(), msg_ctx, sharename, jobid);
2978 return NT_STATUS_OK;
2979 }
2980
2981 ret = (*(current_printif->job_submit))(snum, pjob);
2982
2983 if (ret) {
2984 status = NT_STATUS_PRINT_CANCELLED;
2985 goto fail;
2986 }
2987
2988 /* The print job has been successfully handed over to the back-end */
2989
2990 pjob->spooled = True;
2991 pjob->status = LPQ_QUEUED;
2992 pjob_store(server_event_context(), msg_ctx, sharename, jobid, pjob);
2993
2994 /* make sure the database is up to date */
2995 if (print_cache_expired(lp_const_servicename(snum), True))
2996 print_queue_update(msg_ctx, snum, False);
2997
2998 return NT_STATUS_OK;
2999
3000fail:
3001
3002 /* The print job was not successfully started. Cleanup */
3003 /* Still need to add proper error return propagation! 010122:JRR */
3004 pjob->fd = -1;
3005 unlink(pjob->filename);
3006 pjob_delete(server_event_context(), msg_ctx, sharename, jobid);
3007 return status;
3008}
3009
3010/****************************************************************************
3011 Get a snapshot of jobs in the system without traversing.
3012****************************************************************************/
3013
3014static bool get_stored_queue_info(struct messaging_context *msg_ctx,
3015 struct tdb_print_db *pdb, int snum,
3016 int *pcount, print_queue_struct **ppqueue)
3017{
3018 TDB_DATA data, cgdata, jcdata;
3019 print_queue_struct *queue = NULL;
3020 uint32 qcount = 0;
3021 uint32 extra_count = 0;
3022 uint32_t changed_count = 0;
3023 int total_count = 0;
3024 size_t len = 0;
3025 uint32 i;
3026 int max_reported_jobs = lp_max_reported_jobs(snum);
3027 bool ret = False;
3028 const char* sharename = lp_servicename(snum);
3029
3030 /* make sure the database is up to date */
3031 if (print_cache_expired(lp_const_servicename(snum), True))
3032 print_queue_update(msg_ctx, snum, False);
3033
3034 *pcount = 0;
3035 *ppqueue = NULL;
3036
3037 ZERO_STRUCT(data);
3038 ZERO_STRUCT(cgdata);
3039
3040 /* Get the stored queue data. */
3041 data = tdb_fetch(pdb->tdb, string_tdb_data("INFO/linear_queue_array"));
3042
3043 if (data.dptr && data.dsize >= sizeof(qcount))
3044 len += tdb_unpack(data.dptr + len, data.dsize - len, "d", &qcount);
3045
3046 /* Get the added jobs list. */
3047 cgdata = tdb_fetch(pdb->tdb, string_tdb_data("INFO/jobs_added"));
3048 if (cgdata.dptr != NULL && (cgdata.dsize % 4 == 0))
3049 extra_count = cgdata.dsize/4;
3050
3051 /* Get the changed jobs list. */
3052 jcdata = tdb_fetch(pdb->tdb, string_tdb_data("INFO/jobs_changed"));
3053 if (jcdata.dptr != NULL && (jcdata.dsize % 4 == 0))
3054 changed_count = jcdata.dsize / 4;
3055
3056 DEBUG(5,("get_stored_queue_info: qcount = %u, extra_count = %u\n", (unsigned int)qcount, (unsigned int)extra_count));
3057
3058 /* Allocate the queue size. */
3059 if (qcount == 0 && extra_count == 0)
3060 goto out;
3061
3062 if ((queue = SMB_MALLOC_ARRAY(print_queue_struct, qcount + extra_count)) == NULL)
3063 goto out;
3064
3065 /* Retrieve the linearised queue data. */
3066
3067 for( i = 0; i < qcount; i++) {
3068 uint32 qjob, qsize, qpage_count, qstatus, qpriority, qtime;
3069 len += tdb_unpack(data.dptr + len, data.dsize - len, "ddddddff",
3070 &qjob,
3071 &qsize,
3072 &qpage_count,
3073 &qstatus,
3074 &qpriority,
3075 &qtime,
3076 queue[i].fs_user,
3077 queue[i].fs_file);
3078 queue[i].job = qjob;
3079 queue[i].size = qsize;
3080 queue[i].page_count = qpage_count;
3081 queue[i].status = qstatus;
3082 queue[i].priority = qpriority;
3083 queue[i].time = qtime;
3084 }
3085
3086 total_count = qcount;
3087
3088 /* Add new jobids to the queue. */
3089 for( i = 0; i < extra_count; i++) {
3090 uint32 jobid;
3091 struct printjob *pjob;
3092
3093 jobid = IVAL(cgdata.dptr, i*4);
3094 DEBUG(5,("get_stored_queue_info: added job = %u\n", (unsigned int)jobid));
3095 pjob = print_job_find(lp_const_servicename(snum), jobid);
3096 if (!pjob) {
3097 DEBUG(5,("get_stored_queue_info: failed to find added job = %u\n", (unsigned int)jobid));
3098 remove_from_jobs_added(sharename, jobid);
3099 continue;
3100 }
3101
3102 queue[total_count].job = jobid;
3103 queue[total_count].size = pjob->size;
3104 queue[total_count].page_count = pjob->page_count;
3105 queue[total_count].status = pjob->status;
3106 queue[total_count].priority = 1;
3107 queue[total_count].time = pjob->starttime;
3108 fstrcpy(queue[total_count].fs_user, pjob->user);
3109 fstrcpy(queue[total_count].fs_file, pjob->jobname);
3110 total_count++;
3111 }
3112
3113 /* Update the changed jobids. */
3114 for (i = 0; i < changed_count; i++) {
3115 uint32_t jobid = IVAL(jcdata.dptr, i * 4);
3116 uint32_t j;
3117 bool found = false;
3118
3119 for (j = 0; j < total_count; j++) {
3120 if (queue[j].job == jobid) {
3121 found = true;
3122 break;
3123 }
3124 }
3125
3126 if (found) {
3127 struct printjob *pjob;
3128
3129 DEBUG(5,("get_stored_queue_info: changed job: %u\n",
3130 (unsigned int) jobid));
3131
3132 pjob = print_job_find(sharename, jobid);
3133 if (pjob == NULL) {
3134 DEBUG(5,("get_stored_queue_info: failed to find "
3135 "changed job = %u\n",
3136 (unsigned int) jobid));
3137 remove_from_jobs_changed(sharename, jobid);
3138 continue;
3139 }
3140
3141 queue[j].job = jobid;
3142 queue[j].size = pjob->size;
3143 queue[j].page_count = pjob->page_count;
3144 queue[j].status = pjob->status;
3145 queue[j].priority = 1;
3146 queue[j].time = pjob->starttime;
3147 fstrcpy(queue[j].fs_user, pjob->user);
3148 fstrcpy(queue[j].fs_file, pjob->jobname);
3149
3150 DEBUG(5,("get_stored_queue_info: updated queue[%u], jobid: %u, jobname: %s\n",
3151 (unsigned int) j, (unsigned int) jobid, pjob->jobname));
3152 }
3153
3154 remove_from_jobs_changed(sharename, jobid);
3155 }
3156
3157 /* Sort the queue by submission time otherwise they are displayed
3158 in hash order. */
3159
3160 TYPESAFE_QSORT(queue, total_count, printjob_comp);
3161
3162 DEBUG(5,("get_stored_queue_info: total_count = %u\n", (unsigned int)total_count));
3163
3164 if (max_reported_jobs && total_count > max_reported_jobs)
3165 total_count = max_reported_jobs;
3166
3167 *ppqueue = queue;
3168 *pcount = total_count;
3169
3170 ret = True;
3171
3172 out:
3173
3174 SAFE_FREE(data.dptr);
3175 SAFE_FREE(cgdata.dptr);
3176 return ret;
3177}
3178
3179/****************************************************************************
3180 Get a printer queue listing.
3181 set queue = NULL and status = NULL if you just want to update the cache
3182****************************************************************************/
3183
3184int print_queue_status(struct messaging_context *msg_ctx, int snum,
3185 print_queue_struct **ppqueue,
3186 print_status_struct *status)
3187{
3188 fstring keystr;
3189 TDB_DATA data, key;
3190 const char *sharename;
3191 struct tdb_print_db *pdb;
3192 int count = 0;
3193
3194 /* make sure the database is up to date */
3195
3196 if (print_cache_expired(lp_const_servicename(snum), True))
3197 print_queue_update(msg_ctx, snum, False);
3198
3199 /* return if we are done */
3200 if ( !ppqueue || !status )
3201 return 0;
3202
3203 *ppqueue = NULL;
3204 sharename = lp_const_servicename(snum);
3205 pdb = get_print_db_byname(sharename);
3206
3207 if (!pdb)
3208 return 0;
3209
3210 /*
3211 * Fetch the queue status. We must do this first, as there may
3212 * be no jobs in the queue.
3213 */
3214
3215 ZERO_STRUCTP(status);
3216 slprintf(keystr, sizeof(keystr)-1, "STATUS/%s", sharename);
3217 key = string_tdb_data(keystr);
3218
3219 data = tdb_fetch(pdb->tdb, key);
3220 if (data.dptr) {
3221 if (data.dsize == sizeof(*status)) {
3222 /* this memcpy is ok since the status struct was
3223 not packed before storing it in the tdb */
3224 memcpy(status, data.dptr, sizeof(*status));
3225 }
3226 SAFE_FREE(data.dptr);
3227 }
3228
3229 /*
3230 * Now, fetch the print queue information. We first count the number
3231 * of entries, and then only retrieve the queue if necessary.
3232 */
3233
3234 if (!get_stored_queue_info(msg_ctx, pdb, snum, &count, ppqueue)) {
3235 release_print_db(pdb);
3236 return 0;
3237 }
3238
3239 release_print_db(pdb);
3240 return count;
3241}
3242
3243/****************************************************************************
3244 Pause a queue.
3245****************************************************************************/
3246
3247WERROR print_queue_pause(const struct auth_serversupplied_info *server_info,
3248 struct messaging_context *msg_ctx, int snum)
3249{
3250 int ret;
3251 struct printif *current_printif = get_printer_fns( snum );
3252
3253 if (!print_access_check(server_info, msg_ctx, snum,
3254 PRINTER_ACCESS_ADMINISTER)) {
3255 return WERR_ACCESS_DENIED;
3256 }
3257
3258
3259 become_root();
3260
3261 ret = (*(current_printif->queue_pause))(snum);
3262
3263 unbecome_root();
3264
3265 if (ret != 0) {
3266 return WERR_INVALID_PARAM;
3267 }
3268
3269 /* force update the database */
3270 print_cache_flush(lp_const_servicename(snum));
3271
3272 /* Send a printer notify message */
3273
3274 notify_printer_status(server_event_context(), msg_ctx, snum,
3275 PRINTER_STATUS_PAUSED);
3276
3277 return WERR_OK;
3278}
3279
3280/****************************************************************************
3281 Resume a queue.
3282****************************************************************************/
3283
3284WERROR print_queue_resume(const struct auth_serversupplied_info *server_info,
3285 struct messaging_context *msg_ctx, int snum)
3286{
3287 int ret;
3288 struct printif *current_printif = get_printer_fns( snum );
3289
3290 if (!print_access_check(server_info, msg_ctx, snum,
3291 PRINTER_ACCESS_ADMINISTER)) {
3292 return WERR_ACCESS_DENIED;
3293 }
3294
3295 become_root();
3296
3297 ret = (*(current_printif->queue_resume))(snum);
3298
3299 unbecome_root();
3300
3301 if (ret != 0) {
3302 return WERR_INVALID_PARAM;
3303 }
3304
3305 /* make sure the database is up to date */
3306 if (print_cache_expired(lp_const_servicename(snum), True))
3307 print_queue_update(msg_ctx, snum, True);
3308
3309 /* Send a printer notify message */
3310
3311 notify_printer_status(server_event_context(), msg_ctx, snum,
3312 PRINTER_STATUS_OK);
3313
3314 return WERR_OK;
3315}
3316
3317/****************************************************************************
3318 Purge a queue - implemented by deleting all jobs that we can delete.
3319****************************************************************************/
3320
3321WERROR print_queue_purge(const struct auth_serversupplied_info *server_info,
3322 struct messaging_context *msg_ctx, int snum)
3323{
3324 print_queue_struct *queue;
3325 print_status_struct status;
3326 int njobs, i;
3327 bool can_job_admin;
3328
3329 /* Force and update so the count is accurate (i.e. not a cached count) */
3330 print_queue_update(msg_ctx, snum, True);
3331
3332 can_job_admin = print_access_check(server_info,
3333 msg_ctx,
3334 snum,
3335 JOB_ACCESS_ADMINISTER);
3336 njobs = print_queue_status(msg_ctx, snum, &queue, &status);
3337
3338 if ( can_job_admin )
3339 become_root();
3340
3341 for (i=0;i<njobs;i++) {
3342 bool owner = is_owner(server_info, lp_const_servicename(snum),
3343 queue[i].job);
3344
3345 if (owner || can_job_admin) {
3346 print_job_delete1(server_event_context(), msg_ctx,
3347 snum, queue[i].job);
3348 }
3349 }
3350
3351 if ( can_job_admin )
3352 unbecome_root();
3353
3354 /* update the cache */
3355 print_queue_update(msg_ctx, snum, True);
3356
3357 SAFE_FREE(queue);
3358
3359 return WERR_OK;
3360}
Note: See TracBrowser for help on using the repository browser.