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