r9268: bumping version to 3.0.20rc3
[Samba.git] / source / printing / printing.c
blob52a30704667fab5f43e648dcf2ee263103da8586
1 /*
2 Unix SMB/Netbios implementation.
3 Version 3.0
4 printing backend routines
5 Copyright (C) Andrew Tridgell 1992-2000
6 Copyright (C) Jeremy Allison 2002
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 #include "includes.h"
24 #include "printing.h"
26 extern SIG_ATOMIC_T got_sig_term;
27 extern SIG_ATOMIC_T reload_after_sighup;
29 /* Current printer interface */
30 static BOOL remove_from_jobs_changed(const char* sharename, uint32 jobid);
32 /*
33 the printing backend revolves around a tdb database that stores the
34 SMB view of the print queue
36 The key for this database is a jobid - a internally generated number that
37 uniquely identifies a print job
39 reading the print queue involves two steps:
40 - possibly running lpq and updating the internal database from that
41 - reading entries from the database
43 jobids are assigned when a job starts spooling.
46 static TDB_CONTEXT *rap_tdb;
47 static uint16 next_rap_jobid;
48 struct rap_jobid_key {
49 fstring sharename;
50 uint32 jobid;
53 /***************************************************************************
54 Nightmare. LANMAN jobid's are 16 bit numbers..... We must map them to 32
55 bit RPC jobids.... JRA.
56 ***************************************************************************/
58 uint16 pjobid_to_rap(const char* sharename, uint32 jobid)
60 uint16 rap_jobid;
61 TDB_DATA data, key;
62 struct rap_jobid_key jinfo;
63 uint8 buf[2];
65 DEBUG(10,("pjobid_to_rap: called.\n"));
67 if (!rap_tdb) {
68 /* Create the in-memory tdb. */
69 rap_tdb = tdb_open_log(NULL, 0, TDB_INTERNAL, (O_RDWR|O_CREAT), 0644);
70 if (!rap_tdb)
71 return 0;
74 ZERO_STRUCT( jinfo );
75 fstrcpy( jinfo.sharename, sharename );
76 jinfo.jobid = jobid;
77 key.dptr = (char*)&jinfo;
78 key.dsize = sizeof(jinfo);
80 data = tdb_fetch(rap_tdb, key);
81 if (data.dptr && data.dsize == sizeof(uint16)) {
82 rap_jobid = SVAL(data.dptr, 0);
83 SAFE_FREE(data.dptr);
84 DEBUG(10,("pjobid_to_rap: jobid %u maps to RAP jobid %u\n",
85 (unsigned int)jobid, (unsigned int)rap_jobid));
86 return rap_jobid;
88 SAFE_FREE(data.dptr);
89 /* Not found - create and store mapping. */
90 rap_jobid = ++next_rap_jobid;
91 if (rap_jobid == 0)
92 rap_jobid = ++next_rap_jobid;
93 SSVAL(buf,0,rap_jobid);
94 data.dptr = buf;
95 data.dsize = sizeof(rap_jobid);
96 tdb_store(rap_tdb, key, data, TDB_REPLACE);
97 tdb_store(rap_tdb, data, key, TDB_REPLACE);
99 DEBUG(10,("pjobid_to_rap: created jobid %u maps to RAP jobid %u\n",
100 (unsigned int)jobid, (unsigned int)rap_jobid));
101 return rap_jobid;
104 BOOL rap_to_pjobid(uint16 rap_jobid, fstring sharename, uint32 *pjobid)
106 TDB_DATA data, key;
107 uint8 buf[2];
109 DEBUG(10,("rap_to_pjobid called.\n"));
111 if (!rap_tdb)
112 return False;
114 SSVAL(buf,0,rap_jobid);
115 key.dptr = buf;
116 key.dsize = sizeof(rap_jobid);
117 data = tdb_fetch(rap_tdb, key);
118 if ( data.dptr && data.dsize == sizeof(struct rap_jobid_key) )
120 struct rap_jobid_key *jinfo = (struct rap_jobid_key*)data.dptr;
121 fstrcpy( sharename, jinfo->sharename );
122 *pjobid = jinfo->jobid;
123 DEBUG(10,("rap_to_pjobid: jobid %u maps to RAP jobid %u\n",
124 (unsigned int)*pjobid, (unsigned int)rap_jobid));
125 SAFE_FREE(data.dptr);
126 return True;
129 DEBUG(10,("rap_to_pjobid: Failed to lookup RAP jobid %u\n",
130 (unsigned int)rap_jobid));
131 SAFE_FREE(data.dptr);
132 return False;
135 static void rap_jobid_delete(const char* sharename, uint32 jobid)
137 TDB_DATA key, data;
138 uint16 rap_jobid;
139 struct rap_jobid_key jinfo;
140 uint8 buf[2];
142 DEBUG(10,("rap_jobid_delete: called.\n"));
144 if (!rap_tdb)
145 return;
147 ZERO_STRUCT( jinfo );
148 fstrcpy( jinfo.sharename, sharename );
149 jinfo.jobid = jobid;
150 key.dptr = (char*)&jinfo;
151 key.dsize = sizeof(jinfo);
153 data = tdb_fetch(rap_tdb, key);
154 if (!data.dptr || (data.dsize != sizeof(uint16))) {
155 DEBUG(10,("rap_jobid_delete: cannot find jobid %u\n",
156 (unsigned int)jobid ));
157 SAFE_FREE(data.dptr);
158 return;
161 DEBUG(10,("rap_jobid_delete: deleting jobid %u\n",
162 (unsigned int)jobid ));
164 rap_jobid = SVAL(data.dptr, 0);
165 SAFE_FREE(data.dptr);
166 SSVAL(buf,0,rap_jobid);
167 data.dptr=buf;
168 data.dsize = sizeof(rap_jobid);
169 tdb_delete(rap_tdb, key);
170 tdb_delete(rap_tdb, data);
173 static int get_queue_status(const char* sharename, print_status_struct *);
175 /****************************************************************************
176 Initialise the printing backend. Called once at startup before the fork().
177 ****************************************************************************/
179 BOOL print_backend_init(void)
181 const char *sversion = "INFO/version";
182 pstring printing_path;
183 int services = lp_numservices();
184 int snum;
186 unlink(lock_path("printing.tdb"));
187 pstrcpy(printing_path,lock_path("printing"));
188 mkdir(printing_path,0755);
190 /* handle a Samba upgrade */
192 for (snum = 0; snum < services; snum++) {
193 struct tdb_print_db *pdb;
194 if (!lp_print_ok(snum))
195 continue;
197 pdb = get_print_db_byname(lp_const_servicename(snum));
198 if (!pdb)
199 continue;
200 if (tdb_lock_bystring(pdb->tdb, sversion, 0) == -1) {
201 DEBUG(0,("print_backend_init: Failed to open printer %s database\n", lp_const_servicename(snum) ));
202 release_print_db(pdb);
203 return False;
205 if (tdb_fetch_int32(pdb->tdb, sversion) != PRINT_DATABASE_VERSION) {
206 tdb_traverse(pdb->tdb, tdb_traverse_delete_fn, NULL);
207 tdb_store_int32(pdb->tdb, sversion, PRINT_DATABASE_VERSION);
209 tdb_unlock_bystring(pdb->tdb, sversion);
210 release_print_db(pdb);
213 close_all_print_db(); /* Don't leave any open. */
215 /* do NT print initialization... */
216 return nt_printing_init();
219 /****************************************************************************
220 Shut down printing backend. Called once at shutdown to close the tdb.
221 ****************************************************************************/
223 void printing_end(void)
225 close_all_print_db(); /* Don't leave any open. */
228 /****************************************************************************
229 Retrieve the set of printing functions for a given service. This allows
230 us to set the printer function table based on the value of the 'printing'
231 service parameter.
233 Use the generic interface as the default and only use cups interface only
234 when asked for (and only when supported)
235 ****************************************************************************/
237 static struct printif *get_printer_fns_from_type( int type )
239 struct printif *printer_fns = &generic_printif;
241 #ifdef HAVE_CUPS
242 if ( type == PRINT_CUPS ) {
243 printer_fns = &cups_printif;
245 #endif /* HAVE_CUPS */
247 printer_fns->type = type;
249 return printer_fns;
252 static struct printif *get_printer_fns( int snum )
254 return get_printer_fns_from_type( lp_printing(snum) );
258 /****************************************************************************
259 Useful function to generate a tdb key.
260 ****************************************************************************/
262 static TDB_DATA print_key(uint32 jobid)
264 static uint32 j;
265 TDB_DATA ret;
267 SIVAL(&j, 0, jobid);
268 ret.dptr = (void *)&j;
269 ret.dsize = sizeof(j);
270 return ret;
273 /***********************************************************************
274 unpack a pjob from a tdb buffer
275 ***********************************************************************/
277 int unpack_pjob( char* buf, int buflen, struct printjob *pjob )
279 int len = 0;
280 int used;
281 uint32 pjpid, pjsysjob, pjfd, pjstarttime, pjstatus;
282 uint32 pjsize, pjpage_count, pjspooled, pjsmbjob;
284 if ( !buf || !pjob )
285 return -1;
287 len += tdb_unpack(buf+len, buflen-len, "dddddddddffff",
288 &pjpid,
289 &pjsysjob,
290 &pjfd,
291 &pjstarttime,
292 &pjstatus,
293 &pjsize,
294 &pjpage_count,
295 &pjspooled,
296 &pjsmbjob,
297 pjob->filename,
298 pjob->jobname,
299 pjob->user,
300 pjob->queuename);
302 if ( len == -1 )
303 return -1;
305 if ( (used = unpack_devicemode(&pjob->nt_devmode, buf+len, buflen-len)) == -1 )
306 return -1;
308 len += used;
310 pjob->pid = pjpid;
311 pjob->sysjob = pjsysjob;
312 pjob->fd = pjfd;
313 pjob->starttime = pjstarttime;
314 pjob->status = pjstatus;
315 pjob->size = pjsize;
316 pjob->page_count = pjpage_count;
317 pjob->spooled = pjspooled;
318 pjob->smbjob = pjsmbjob;
320 return len;
324 /****************************************************************************
325 Useful function to find a print job in the database.
326 ****************************************************************************/
328 static struct printjob *print_job_find(const char *sharename, uint32 jobid)
330 static struct printjob pjob;
331 TDB_DATA ret;
332 struct tdb_print_db *pdb = get_print_db_byname(sharename);
335 if (!pdb)
336 return NULL;
338 ret = tdb_fetch(pdb->tdb, print_key(jobid));
339 release_print_db(pdb);
341 if (!ret.dptr)
342 return NULL;
344 if ( pjob.nt_devmode )
345 free_nt_devicemode( &pjob.nt_devmode );
347 ZERO_STRUCT( pjob );
349 if ( unpack_pjob( ret.dptr, ret.dsize, &pjob ) == -1 ) {
350 SAFE_FREE(ret.dptr);
351 return NULL;
354 SAFE_FREE(ret.dptr);
355 return &pjob;
358 /* Convert a unix jobid to a smb jobid */
360 static uint32 sysjob_to_jobid_value;
362 static int unixjob_traverse_fn(TDB_CONTEXT *the_tdb, TDB_DATA key,
363 TDB_DATA data, void *state)
365 struct printjob *pjob;
366 int *sysjob = (int *)state;
368 if (!data.dptr || data.dsize == 0)
369 return 0;
371 pjob = (struct printjob *)data.dptr;
372 if (key.dsize != sizeof(uint32))
373 return 0;
375 if (*sysjob == pjob->sysjob) {
376 uint32 jobid = IVAL(key.dptr,0);
378 sysjob_to_jobid_value = jobid;
379 return 1;
382 return 0;
385 /****************************************************************************
386 This is a *horribly expensive call as we have to iterate through all the
387 current printer tdb's. Don't do this often ! JRA.
388 ****************************************************************************/
390 uint32 sysjob_to_jobid(int unix_jobid)
392 int services = lp_numservices();
393 int snum;
395 sysjob_to_jobid_value = (uint32)-1;
397 for (snum = 0; snum < services; snum++) {
398 struct tdb_print_db *pdb;
399 if (!lp_print_ok(snum))
400 continue;
401 pdb = get_print_db_byname(lp_const_servicename(snum));
402 if (!pdb) {
403 continue;
405 tdb_traverse(pdb->tdb, unixjob_traverse_fn, &unix_jobid);
406 release_print_db(pdb);
407 if (sysjob_to_jobid_value != (uint32)-1)
408 return sysjob_to_jobid_value;
410 return (uint32)-1;
413 /****************************************************************************
414 Send notifications based on what has changed after a pjob_store.
415 ****************************************************************************/
417 static struct {
418 uint32 lpq_status;
419 uint32 spoolss_status;
420 } lpq_to_spoolss_status_map[] = {
421 { LPQ_QUEUED, JOB_STATUS_QUEUED },
422 { LPQ_PAUSED, JOB_STATUS_PAUSED },
423 { LPQ_SPOOLING, JOB_STATUS_SPOOLING },
424 { LPQ_PRINTING, JOB_STATUS_PRINTING },
425 { LPQ_DELETING, JOB_STATUS_DELETING },
426 { LPQ_OFFLINE, JOB_STATUS_OFFLINE },
427 { LPQ_PAPEROUT, JOB_STATUS_PAPEROUT },
428 { LPQ_PRINTED, JOB_STATUS_PRINTED },
429 { LPQ_DELETED, JOB_STATUS_DELETED },
430 { LPQ_BLOCKED, JOB_STATUS_BLOCKED },
431 { LPQ_USER_INTERVENTION, JOB_STATUS_USER_INTERVENTION },
432 { -1, 0 }
435 /* Convert a lpq status value stored in printing.tdb into the
436 appropriate win32 API constant. */
438 static uint32 map_to_spoolss_status(uint32 lpq_status)
440 int i = 0;
442 while (lpq_to_spoolss_status_map[i].lpq_status != -1) {
443 if (lpq_to_spoolss_status_map[i].lpq_status == lpq_status)
444 return lpq_to_spoolss_status_map[i].spoolss_status;
445 i++;
448 return 0;
451 static void pjob_store_notify(const char* sharename, uint32 jobid, struct printjob *old_data,
452 struct printjob *new_data)
454 BOOL new_job = False;
456 if (!old_data)
457 new_job = True;
459 /* Job attributes that can't be changed. We only send
460 notification for these on a new job. */
462 /* ACHTUNG! Due to a bug in Samba's spoolss parsing of the
463 NOTIFY_INFO_DATA buffer, we *have* to send the job submission
464 time first or else we'll end up with potential alignment
465 errors. I don't think the systemtime should be spooled as
466 a string, but this gets us around that error.
467 --jerry (i'll feel dirty for this) */
469 if (new_job) {
470 notify_job_submitted(sharename, jobid, new_data->starttime);
471 notify_job_username(sharename, jobid, new_data->user);
474 if (new_job || !strequal(old_data->jobname, new_data->jobname))
475 notify_job_name(sharename, jobid, new_data->jobname);
477 /* Job attributes of a new job or attributes that can be
478 modified. */
480 if (new_job || !strequal(old_data->jobname, new_data->jobname))
481 notify_job_name(sharename, jobid, new_data->jobname);
483 if (new_job || old_data->status != new_data->status)
484 notify_job_status(sharename, jobid, map_to_spoolss_status(new_data->status));
486 if (new_job || old_data->size != new_data->size)
487 notify_job_total_bytes(sharename, jobid, new_data->size);
489 if (new_job || old_data->page_count != new_data->page_count)
490 notify_job_total_pages(sharename, jobid, new_data->page_count);
493 /****************************************************************************
494 Store a job structure back to the database.
495 ****************************************************************************/
497 static BOOL pjob_store(const char* sharename, uint32 jobid, struct printjob *pjob)
499 TDB_DATA old_data, new_data;
500 BOOL ret = False;
501 struct tdb_print_db *pdb = get_print_db_byname(sharename);
502 char *buf = NULL;
503 int len, newlen, buflen;
506 if (!pdb)
507 return False;
509 /* Get old data */
511 old_data = tdb_fetch(pdb->tdb, print_key(jobid));
513 /* Doh! Now we have to pack/unpack data since the NT_DEVICEMODE was added */
515 newlen = 0;
517 do {
518 len = 0;
519 buflen = newlen;
520 len += tdb_pack(buf+len, buflen-len, "dddddddddffff",
521 (uint32)pjob->pid,
522 (uint32)pjob->sysjob,
523 (uint32)pjob->fd,
524 (uint32)pjob->starttime,
525 (uint32)pjob->status,
526 (uint32)pjob->size,
527 (uint32)pjob->page_count,
528 (uint32)pjob->spooled,
529 (uint32)pjob->smbjob,
530 pjob->filename,
531 pjob->jobname,
532 pjob->user,
533 pjob->queuename);
535 len += pack_devicemode(pjob->nt_devmode, buf+len, buflen-len);
537 if (buflen != len) {
538 char *tb;
540 tb = (char *)SMB_REALLOC(buf, len);
541 if (!tb) {
542 DEBUG(0,("pjob_store: failed to enlarge buffer!\n"));
543 goto done;
545 else
546 buf = tb;
547 newlen = len;
549 } while ( buflen != len );
552 /* Store new data */
554 new_data.dptr = buf;
555 new_data.dsize = len;
556 ret = (tdb_store(pdb->tdb, print_key(jobid), new_data, TDB_REPLACE) == 0);
558 release_print_db(pdb);
560 /* Send notify updates for what has changed */
562 if ( ret ) {
563 struct printjob old_pjob;
565 if ( old_data.dsize )
567 if ( unpack_pjob( old_data.dptr, old_data.dsize, &old_pjob ) != -1 )
569 pjob_store_notify( sharename, jobid, &old_pjob , pjob );
570 free_nt_devicemode( &old_pjob.nt_devmode );
573 else {
574 /* new job */
575 pjob_store_notify( sharename, jobid, NULL, pjob );
579 done:
580 SAFE_FREE( old_data.dptr );
581 SAFE_FREE( buf );
583 return ret;
586 /****************************************************************************
587 Remove a job structure from the database.
588 ****************************************************************************/
590 void pjob_delete(const char* sharename, uint32 jobid)
592 struct printjob *pjob;
593 uint32 job_status = 0;
594 struct tdb_print_db *pdb;
596 pdb = get_print_db_byname( sharename );
598 if (!pdb)
599 return;
601 pjob = print_job_find( sharename, jobid );
603 if (!pjob) {
604 DEBUG(5, ("pjob_delete: we were asked to delete nonexistent job %u\n",
605 (unsigned int)jobid));
606 release_print_db(pdb);
607 return;
610 /* We must cycle through JOB_STATUS_DELETING and
611 JOB_STATUS_DELETED for the port monitor to delete the job
612 properly. */
614 job_status = JOB_STATUS_DELETING|JOB_STATUS_DELETED;
615 notify_job_status(sharename, jobid, job_status);
617 /* Remove from printing.tdb */
619 tdb_delete(pdb->tdb, print_key(jobid));
620 remove_from_jobs_changed(sharename, jobid);
621 release_print_db( pdb );
622 rap_jobid_delete(sharename, jobid);
625 /****************************************************************************
626 Parse a file name from the system spooler to generate a jobid.
627 ****************************************************************************/
629 static uint32 print_parse_jobid(char *fname)
631 int jobid;
633 if (strncmp(fname,PRINT_SPOOL_PREFIX,strlen(PRINT_SPOOL_PREFIX)) != 0)
634 return (uint32)-1;
635 fname += strlen(PRINT_SPOOL_PREFIX);
637 jobid = atoi(fname);
638 if (jobid <= 0)
639 return (uint32)-1;
641 return (uint32)jobid;
644 /****************************************************************************
645 List a unix job in the print database.
646 ****************************************************************************/
648 static void print_unix_job(const char *sharename, print_queue_struct *q, uint32 jobid)
650 struct printjob pj, *old_pj;
652 if (jobid == (uint32)-1)
653 jobid = q->job + UNIX_JOB_START;
655 /* Preserve the timestamp on an existing unix print job */
657 old_pj = print_job_find(sharename, jobid);
659 ZERO_STRUCT(pj);
661 pj.pid = (pid_t)-1;
662 pj.sysjob = q->job;
663 pj.fd = -1;
664 pj.starttime = old_pj ? old_pj->starttime : q->time;
665 pj.status = q->status;
666 pj.size = q->size;
667 pj.spooled = True;
668 fstrcpy(pj.filename, old_pj ? old_pj->filename : "");
669 if (jobid < UNIX_JOB_START) {
670 pj.smbjob = True;
671 fstrcpy(pj.jobname, old_pj ? old_pj->jobname : "Remote Downlevel Document");
672 } else {
673 pj.smbjob = False;
674 fstrcpy(pj.jobname, old_pj ? old_pj->jobname : q->fs_file);
676 fstrcpy(pj.user, old_pj ? old_pj->user : q->fs_user);
677 fstrcpy(pj.queuename, old_pj ? old_pj->queuename : sharename );
679 pjob_store(sharename, jobid, &pj);
683 struct traverse_struct {
684 print_queue_struct *queue;
685 int qcount, snum, maxcount, total_jobs;
686 const char *sharename;
687 time_t lpq_time;
690 /****************************************************************************
691 Utility fn to delete any jobs that are no longer active.
692 ****************************************************************************/
694 static int traverse_fn_delete(TDB_CONTEXT *t, TDB_DATA key, TDB_DATA data, void *state)
696 struct traverse_struct *ts = (struct traverse_struct *)state;
697 struct printjob pjob;
698 uint32 jobid;
699 int i = 0;
701 if ( key.dsize != sizeof(jobid) )
702 return 0;
704 jobid = IVAL(key.dptr, 0);
705 if ( unpack_pjob( data.dptr, data.dsize, &pjob ) == -1 )
706 return 0;
707 free_nt_devicemode( &pjob.nt_devmode );
710 if (!pjob.smbjob) {
711 /* remove a unix job if it isn't in the system queue any more */
713 for (i=0;i<ts->qcount;i++) {
714 uint32 u_jobid = (ts->queue[i].job + UNIX_JOB_START);
715 if (jobid == u_jobid)
716 break;
718 if (i == ts->qcount) {
719 DEBUG(10,("traverse_fn_delete: pjob %u deleted due to !smbjob\n",
720 (unsigned int)jobid ));
721 pjob_delete(ts->sharename, jobid);
722 return 0;
725 /* need to continue the the bottom of the function to
726 save the correct attributes */
729 /* maybe it hasn't been spooled yet */
730 if (!pjob.spooled) {
731 /* if a job is not spooled and the process doesn't
732 exist then kill it. This cleans up after smbd
733 deaths */
734 if (!process_exists(pjob.pid)) {
735 DEBUG(10,("traverse_fn_delete: pjob %u deleted due to !process_exists (%u)\n",
736 (unsigned int)jobid, (unsigned int)pjob.pid ));
737 pjob_delete(ts->sharename, jobid);
738 } else
739 ts->total_jobs++;
740 return 0;
743 /* this check only makes sense for jobs submitted from Windows clients */
745 if ( pjob.smbjob ) {
746 for (i=0;i<ts->qcount;i++) {
747 uint32 curr_jobid = print_parse_jobid(ts->queue[i].fs_file);
748 if (jobid == curr_jobid)
749 break;
753 /* The job isn't in the system queue - we have to assume it has
754 completed, so delete the database entry. */
756 if (i == ts->qcount) {
758 /* A race can occur between the time a job is spooled and
759 when it appears in the lpq output. This happens when
760 the job is added to printing.tdb when another smbd
761 running print_queue_update() has completed a lpq and
762 is currently traversing the printing tdb and deleting jobs.
763 Don't delete the job if it was submitted after the lpq_time. */
765 if (pjob.starttime < ts->lpq_time) {
766 DEBUG(10,("traverse_fn_delete: pjob %u deleted due to pjob.starttime (%u) < ts->lpq_time (%u)\n",
767 (unsigned int)jobid,
768 (unsigned int)pjob.starttime,
769 (unsigned int)ts->lpq_time ));
770 pjob_delete(ts->sharename, jobid);
771 } else
772 ts->total_jobs++;
773 return 0;
776 /* Save the pjob attributes we will store. */
777 /* FIXME!!! This is the only place where queue->job
778 represents the SMB jobid --jerry */
779 ts->queue[i].job = jobid;
780 ts->queue[i].size = pjob.size;
781 ts->queue[i].page_count = pjob.page_count;
782 ts->queue[i].status = pjob.status;
783 ts->queue[i].priority = 1;
784 ts->queue[i].time = pjob.starttime;
785 fstrcpy(ts->queue[i].fs_user, pjob.user);
786 fstrcpy(ts->queue[i].fs_file, pjob.jobname);
788 ts->total_jobs++;
790 return 0;
793 /****************************************************************************
794 Check if the print queue has been updated recently enough.
795 ****************************************************************************/
797 static void print_cache_flush(int snum)
799 fstring key;
800 const char *sharename = lp_const_servicename(snum);
801 struct tdb_print_db *pdb = get_print_db_byname(sharename);
803 if (!pdb)
804 return;
805 slprintf(key, sizeof(key)-1, "CACHE/%s", sharename);
806 tdb_store_int32(pdb->tdb, key, -1);
807 release_print_db(pdb);
810 /****************************************************************************
811 Check if someone already thinks they are doing the update.
812 ****************************************************************************/
814 static pid_t get_updating_pid(const char *sharename)
816 fstring keystr;
817 TDB_DATA data, key;
818 pid_t updating_pid;
819 struct tdb_print_db *pdb = get_print_db_byname(sharename);
821 if (!pdb)
822 return (pid_t)-1;
823 slprintf(keystr, sizeof(keystr)-1, "UPDATING/%s", sharename);
824 key.dptr = keystr;
825 key.dsize = strlen(keystr);
827 data = tdb_fetch(pdb->tdb, key);
828 release_print_db(pdb);
829 if (!data.dptr || data.dsize != sizeof(pid_t)) {
830 SAFE_FREE(data.dptr);
831 return (pid_t)-1;
834 updating_pid = IVAL(data.dptr, 0);
835 SAFE_FREE(data.dptr);
837 if (process_exists(updating_pid))
838 return updating_pid;
840 return (pid_t)-1;
843 /****************************************************************************
844 Set the fact that we're doing the update, or have finished doing the update
845 in the tdb.
846 ****************************************************************************/
848 static void set_updating_pid(const fstring sharename, BOOL updating)
850 fstring keystr;
851 TDB_DATA key;
852 TDB_DATA data;
853 pid_t updating_pid = sys_getpid();
854 uint8 buffer[4];
856 struct tdb_print_db *pdb = get_print_db_byname(sharename);
858 if (!pdb)
859 return;
861 slprintf(keystr, sizeof(keystr)-1, "UPDATING/%s", sharename);
862 key.dptr = keystr;
863 key.dsize = strlen(keystr);
865 DEBUG(5, ("set_updating_pid: %s updating lpq cache for print share %s\n",
866 updating ? "" : "not ",
867 sharename ));
869 if ( !updating ) {
870 tdb_delete(pdb->tdb, key);
871 release_print_db(pdb);
872 return;
875 SIVAL( buffer, 0, updating_pid);
876 data.dptr = (void *)buffer;
877 data.dsize = 4; /* we always assume this is a 4 byte value */
879 tdb_store(pdb->tdb, key, data, TDB_REPLACE);
880 release_print_db(pdb);
883 /****************************************************************************
884 Sort print jobs by submittal time.
885 ****************************************************************************/
887 static int printjob_comp(print_queue_struct *j1, print_queue_struct *j2)
889 /* Silly cases */
891 if (!j1 && !j2)
892 return 0;
893 if (!j1)
894 return -1;
895 if (!j2)
896 return 1;
898 /* Sort on job start time */
900 if (j1->time == j2->time)
901 return 0;
902 return (j1->time > j2->time) ? 1 : -1;
905 /****************************************************************************
906 Store the sorted queue representation for later portmon retrieval.
907 ****************************************************************************/
909 static void store_queue_struct(struct tdb_print_db *pdb, struct traverse_struct *pts)
911 TDB_DATA data;
912 int max_reported_jobs = lp_max_reported_jobs(pts->snum);
913 print_queue_struct *queue = pts->queue;
914 size_t len;
915 size_t i;
916 uint qcount;
918 if (max_reported_jobs && (max_reported_jobs < pts->qcount))
919 pts->qcount = max_reported_jobs;
920 qcount = pts->qcount;
922 /* Work out the size. */
923 data.dsize = 0;
924 data.dsize += tdb_pack(NULL, 0, "d", qcount);
926 for (i = 0; i < pts->qcount; i++) {
927 data.dsize += tdb_pack(NULL, 0, "ddddddff",
928 (uint32)queue[i].job,
929 (uint32)queue[i].size,
930 (uint32)queue[i].page_count,
931 (uint32)queue[i].status,
932 (uint32)queue[i].priority,
933 (uint32)queue[i].time,
934 queue[i].fs_user,
935 queue[i].fs_file);
938 if ((data.dptr = SMB_MALLOC(data.dsize)) == NULL)
939 return;
941 len = 0;
942 len += tdb_pack(data.dptr + len, data.dsize - len, "d", qcount);
943 for (i = 0; i < pts->qcount; i++) {
944 len += tdb_pack(data.dptr + len, data.dsize - len, "ddddddff",
945 (uint32)queue[i].job,
946 (uint32)queue[i].size,
947 (uint32)queue[i].page_count,
948 (uint32)queue[i].status,
949 (uint32)queue[i].priority,
950 (uint32)queue[i].time,
951 queue[i].fs_user,
952 queue[i].fs_file);
955 tdb_store(pdb->tdb, string_tdb_data("INFO/linear_queue_array"), data,
956 TDB_REPLACE);
957 SAFE_FREE(data.dptr);
958 return;
961 static TDB_DATA get_jobs_changed_data(struct tdb_print_db *pdb)
963 TDB_DATA data;
965 ZERO_STRUCT(data);
967 data = tdb_fetch(pdb->tdb, string_tdb_data("INFO/jobs_changed"));
968 if (data.dptr == NULL || data.dsize == 0 || (data.dsize % 4 != 0)) {
969 SAFE_FREE(data.dptr);
970 ZERO_STRUCT(data);
973 return data;
976 static void check_job_changed(const char *sharename, TDB_DATA data, uint32 jobid)
978 unsigned int i;
979 unsigned int job_count = data.dsize / 4;
981 for (i = 0; i < job_count; i++) {
982 uint32 ch_jobid;
984 ch_jobid = IVAL(data.dptr, i*4);
985 if (ch_jobid == jobid)
986 remove_from_jobs_changed(sharename, jobid);
990 /****************************************************************************
991 Check if the print queue has been updated recently enough.
992 ****************************************************************************/
994 static BOOL print_cache_expired(const char *sharename, BOOL check_pending)
996 fstring key;
997 time_t last_qscan_time, time_now = time(NULL);
998 struct tdb_print_db *pdb = get_print_db_byname(sharename);
999 BOOL result = False;
1001 if (!pdb)
1002 return False;
1004 snprintf(key, sizeof(key), "CACHE/%s", sharename);
1005 last_qscan_time = (time_t)tdb_fetch_int32(pdb->tdb, key);
1008 * Invalidate the queue for 3 reasons.
1009 * (1). last queue scan time == -1.
1010 * (2). Current time - last queue scan time > allowed cache time.
1011 * (3). last queue scan time > current time + MAX_CACHE_VALID_TIME (1 hour by default).
1012 * This last test picks up machines for which the clock has been moved
1013 * forward, an lpq scan done and then the clock moved back. Otherwise
1014 * that last lpq scan would stay around for a loooong loooong time... :-). JRA.
1017 if (last_qscan_time == ((time_t)-1)
1018 || (time_now - last_qscan_time) >= lp_lpqcachetime()
1019 || last_qscan_time > (time_now + MAX_CACHE_VALID_TIME))
1021 time_t msg_pending_time;
1023 DEBUG(4, ("print_cache_expired: cache expired for queue %s "
1024 "(last_qscan_time = %d, time now = %d, qcachetime = %d)\n",
1025 sharename, (int)last_qscan_time, (int)time_now,
1026 (int)lp_lpqcachetime() ));
1028 /* check if another smbd has already sent a message to update the
1029 queue. Give the pending message one minute to clear and
1030 then send another message anyways. Make sure to check for
1031 clocks that have been run forward and then back again. */
1033 snprintf(key, sizeof(key), "MSG_PENDING/%s", sharename);
1035 if ( check_pending
1036 && tdb_fetch_uint32( pdb->tdb, key, (uint32*)&msg_pending_time )
1037 && msg_pending_time > 0
1038 && msg_pending_time <= time_now
1039 && (time_now - msg_pending_time) < 60 )
1041 DEBUG(4,("print_cache_expired: message already pending for %s. Accepting cache\n",
1042 sharename));
1043 goto done;
1046 result = True;
1049 done:
1050 release_print_db(pdb);
1051 return result;
1054 /****************************************************************************
1055 main work for updating the lpq cahe for a printer queue
1056 ****************************************************************************/
1058 static void print_queue_update_internal( const char *sharename,
1059 struct printif *current_printif,
1060 char *lpq_command )
1062 int i, qcount;
1063 print_queue_struct *queue = NULL;
1064 print_status_struct status;
1065 print_status_struct old_status;
1066 struct printjob *pjob;
1067 struct traverse_struct tstruct;
1068 TDB_DATA data, key;
1069 TDB_DATA jcdata;
1070 fstring keystr, cachestr;
1071 struct tdb_print_db *pdb = get_print_db_byname(sharename);
1073 if (!pdb) {
1074 return;
1077 DEBUG(5,("print_queue_update_internal: printer = %s, type = %d, lpq command = [%s]\n",
1078 sharename, current_printif->type, lpq_command));
1081 * Update the cache time FIRST ! Stops others even
1082 * attempting to get the lock and doing this
1083 * if the lpq takes a long time.
1086 slprintf(cachestr, sizeof(cachestr)-1, "CACHE/%s", sharename);
1087 tdb_store_int32(pdb->tdb, cachestr, (int)time(NULL));
1089 /* get the current queue using the appropriate interface */
1090 ZERO_STRUCT(status);
1092 qcount = (*(current_printif->queue_get))(sharename,
1093 current_printif->type,
1094 lpq_command, &queue, &status);
1096 DEBUG(3, ("print_queue_update_internal: %d job%s in queue for %s\n",
1097 qcount, (qcount != 1) ? "s" : "", sharename));
1099 /* Sort the queue by submission time otherwise they are displayed
1100 in hash order. */
1102 qsort(queue, qcount, sizeof(print_queue_struct),
1103 QSORT_CAST(printjob_comp));
1106 any job in the internal database that is marked as spooled
1107 and doesn't exist in the system queue is considered finished
1108 and removed from the database
1110 any job in the system database but not in the internal database
1111 is added as a unix job
1113 fill in any system job numbers as we go
1116 jcdata = get_jobs_changed_data(pdb);
1118 for (i=0; i<qcount; i++) {
1119 uint32 jobid = print_parse_jobid(queue[i].fs_file);
1121 if (jobid == (uint32)-1) {
1122 /* assume its a unix print job */
1123 print_unix_job(sharename, &queue[i], jobid);
1124 continue;
1127 /* we have an active SMB print job - update its status */
1128 pjob = print_job_find(sharename, jobid);
1129 if (!pjob) {
1130 /* err, somethings wrong. Probably smbd was restarted
1131 with jobs in the queue. All we can do is treat them
1132 like unix jobs. Pity. */
1133 print_unix_job(sharename, &queue[i], jobid);
1134 continue;
1137 pjob->sysjob = queue[i].job;
1138 pjob->status = queue[i].status;
1139 pjob_store(sharename, jobid, pjob);
1140 check_job_changed(sharename, jcdata, jobid);
1143 SAFE_FREE(jcdata.dptr);
1145 /* now delete any queued entries that don't appear in the
1146 system queue */
1147 tstruct.queue = queue;
1148 tstruct.qcount = qcount;
1149 tstruct.snum = -1;
1150 tstruct.total_jobs = 0;
1151 tstruct.lpq_time = time(NULL);
1152 tstruct.sharename = sharename;
1154 tdb_traverse(pdb->tdb, traverse_fn_delete, (void *)&tstruct);
1156 /* Store the linearised queue, max jobs only. */
1157 store_queue_struct(pdb, &tstruct);
1159 SAFE_FREE(tstruct.queue);
1161 DEBUG(10,("print_queue_update_internal: printer %s INFO/total_jobs = %d\n",
1162 sharename, tstruct.total_jobs ));
1164 tdb_store_int32(pdb->tdb, "INFO/total_jobs", tstruct.total_jobs);
1166 get_queue_status(sharename, &old_status);
1167 if (old_status.qcount != qcount)
1168 DEBUG(10,("print_queue_update_internal: queue status change %d jobs -> %d jobs for printer %s\n",
1169 old_status.qcount, qcount, sharename));
1171 /* store the new queue status structure */
1172 slprintf(keystr, sizeof(keystr)-1, "STATUS/%s", sharename);
1173 key.dptr = keystr;
1174 key.dsize = strlen(keystr);
1176 status.qcount = qcount;
1177 data.dptr = (void *)&status;
1178 data.dsize = sizeof(status);
1179 tdb_store(pdb->tdb, key, data, TDB_REPLACE);
1182 * Update the cache time again. We want to do this call
1183 * as little as possible...
1186 slprintf(keystr, sizeof(keystr)-1, "CACHE/%s", sharename);
1187 tdb_store_int32(pdb->tdb, keystr, (int32)time(NULL));
1189 /* clear the msg pending record for this queue */
1191 snprintf(keystr, sizeof(keystr), "MSG_PENDING/%s", sharename);
1193 if ( !tdb_store_uint32( pdb->tdb, keystr, 0 ) ) {
1194 /* log a message but continue on */
1196 DEBUG(0,("print_queue_update: failed to store MSG_PENDING flag for [%s]!\n",
1197 sharename));
1200 release_print_db( pdb );
1202 return;
1205 /****************************************************************************
1206 Update the internal database from the system print queue for a queue.
1207 obtain a lock on the print queue before proceeding (needed when mutiple
1208 smbd processes maytry to update the lpq cache concurrently).
1209 ****************************************************************************/
1211 static void print_queue_update_with_lock( const char *sharename,
1212 struct printif *current_printif,
1213 char *lpq_command )
1215 fstring keystr;
1216 struct tdb_print_db *pdb;
1218 DEBUG(5,("print_queue_update_with_lock: printer share = %s\n", sharename));
1219 pdb = get_print_db_byname(sharename);
1220 if (!pdb)
1221 return;
1223 if ( !print_cache_expired(sharename, False) ) {
1224 DEBUG(5,("print_queue_update_with_lock: print cache for %s is still ok\n", sharename));
1225 release_print_db(pdb);
1226 return;
1230 * Check to see if someone else is doing this update.
1231 * This is essentially a mutex on the update.
1234 if (get_updating_pid(sharename) != -1) {
1235 release_print_db(pdb);
1236 return;
1239 /* Lock the queue for the database update */
1241 slprintf(keystr, sizeof(keystr) - 1, "LOCK/%s", sharename);
1242 /* Only wait 10 seconds for this. */
1243 if (tdb_lock_bystring(pdb->tdb, keystr, 10) == -1) {
1244 DEBUG(0,("print_queue_update_with_lock: Failed to lock printer %s database\n", sharename));
1245 release_print_db(pdb);
1246 return;
1250 * Ensure that no one else got in here.
1251 * If the updating pid is still -1 then we are
1252 * the winner.
1255 if (get_updating_pid(sharename) != -1) {
1257 * Someone else is doing the update, exit.
1259 tdb_unlock_bystring(pdb->tdb, keystr);
1260 release_print_db(pdb);
1261 return;
1265 * We're going to do the update ourselves.
1268 /* Tell others we're doing the update. */
1269 set_updating_pid(sharename, True);
1272 * Allow others to enter and notice we're doing
1273 * the update.
1276 tdb_unlock_bystring(pdb->tdb, keystr);
1278 /* do the main work now */
1280 print_queue_update_internal( sharename, current_printif, lpq_command );
1282 /* Delete our pid from the db. */
1283 set_updating_pid(sharename, False);
1284 release_print_db(pdb);
1287 /****************************************************************************
1288 this is the receive function of the background lpq updater
1289 ****************************************************************************/
1290 static void print_queue_receive(int msg_type, pid_t src, void *buf, size_t msglen)
1292 fstring sharename;
1293 pstring lpqcommand;
1294 int printing_type;
1295 size_t len;
1297 len = tdb_unpack( buf, msglen, "fdP",
1298 sharename,
1299 &printing_type,
1300 lpqcommand );
1302 if ( len == -1 ) {
1303 DEBUG(0,("print_queue_receive: Got invalid print queue update message\n"));
1304 return;
1307 print_queue_update_with_lock(sharename,
1308 get_printer_fns_from_type(printing_type),
1309 lpqcommand );
1311 return;
1314 static pid_t background_lpq_updater_pid = -1;
1316 /****************************************************************************
1317 main thread of the background lpq updater
1318 ****************************************************************************/
1319 void start_background_queue(void)
1321 DEBUG(3,("start_background_queue: Starting background LPQ thread\n"));
1322 background_lpq_updater_pid = sys_fork();
1324 if (background_lpq_updater_pid == -1) {
1325 DEBUG(5,("start_background_queue: background LPQ thread failed to start. %s\n", strerror(errno) ));
1326 exit(1);
1329 if(background_lpq_updater_pid == 0) {
1330 /* Child. */
1331 DEBUG(5,("start_background_queue: background LPQ thread started\n"));
1333 claim_connection( NULL, "smbd lpq backend", 0, False,
1334 FLAG_MSG_GENERAL|FLAG_MSG_SMBD|FLAG_MSG_PRINT_GENERAL);
1336 if (!locking_init(0)) {
1337 exit(1);
1340 message_register(MSG_PRINTER_UPDATE, print_queue_receive);
1342 DEBUG(5,("start_background_queue: background LPQ thread waiting for messages\n"));
1343 while (1) {
1344 pause();
1346 /* check for some essential signals first */
1348 if (got_sig_term) {
1349 exit_server("Caught TERM signal");
1352 if (reload_after_sighup) {
1353 change_to_root_user();
1354 DEBUG(1,("Reloading services after SIGHUP\n"));
1355 reload_services(False);
1356 reload_after_sighup = 0;
1359 /* now check for messages */
1361 DEBUG(10,("start_background_queue: background LPQ thread got a message\n"));
1362 message_dispatch();
1364 /* process any pending print change notify messages */
1366 print_notify_send_messages(0);
1371 /****************************************************************************
1372 update the internal database from the system print queue for a queue
1373 ****************************************************************************/
1375 static void print_queue_update(int snum, BOOL force)
1377 fstring key;
1378 fstring sharename;
1379 pstring lpqcommand;
1380 char *buffer = NULL;
1381 size_t len = 0;
1382 size_t newlen;
1383 struct tdb_print_db *pdb;
1384 int type;
1385 struct printif *current_printif;
1387 fstrcpy( sharename, lp_const_servicename(snum));
1389 /* don't strip out characters like '$' from the printername */
1391 pstrcpy( lpqcommand, lp_lpqcommand(snum));
1392 string_sub2( lpqcommand, "%p", PRINTERNAME(snum), sizeof(lpqcommand), False, False );
1393 standard_sub_snum( snum, lpqcommand, sizeof(lpqcommand) );
1396 * Make sure that the background queue process exists.
1397 * Otherwise just do the update ourselves
1400 if ( force || background_lpq_updater_pid == -1 ) {
1401 DEBUG(4,("print_queue_update: updating queue [%s] myself\n", sharename));
1402 current_printif = get_printer_fns( snum );
1403 print_queue_update_with_lock( sharename, current_printif, lpqcommand );
1405 return;
1408 type = lp_printing(snum);
1410 /* get the length */
1412 len = tdb_pack( buffer, len, "fdP",
1413 sharename,
1414 type,
1415 lpqcommand );
1417 buffer = SMB_XMALLOC_ARRAY( char, len );
1419 /* now pack the buffer */
1420 newlen = tdb_pack( buffer, len, "fdP",
1421 sharename,
1422 type,
1423 lpqcommand );
1425 SMB_ASSERT( newlen == len );
1427 DEBUG(10,("print_queue_update: Sending message -> printer = %s, "
1428 "type = %d, lpq command = [%s]\n", sharename, type, lpqcommand ));
1430 /* here we set a msg pending record for other smbd processes
1431 to throttle the number of duplicate print_queue_update msgs
1432 sent. */
1434 pdb = get_print_db_byname(sharename);
1435 if (!pdb) {
1436 SAFE_FREE(buffer);
1437 return;
1440 snprintf(key, sizeof(key), "MSG_PENDING/%s", sharename);
1442 if ( !tdb_store_uint32( pdb->tdb, key, time(NULL) ) ) {
1443 /* log a message but continue on */
1445 DEBUG(0,("print_queue_update: failed to store MSG_PENDING flag for [%s]!\n",
1446 sharename));
1449 release_print_db( pdb );
1451 /* finally send the message */
1453 become_root();
1454 message_send_pid(background_lpq_updater_pid,
1455 MSG_PRINTER_UPDATE, buffer, len, False);
1456 unbecome_root();
1458 SAFE_FREE( buffer );
1460 return;
1463 /****************************************************************************
1464 Create/Update an entry in the print tdb that will allow us to send notify
1465 updates only to interested smbd's.
1466 ****************************************************************************/
1468 BOOL print_notify_register_pid(int snum)
1470 TDB_DATA data;
1471 struct tdb_print_db *pdb = NULL;
1472 TDB_CONTEXT *tdb = NULL;
1473 const char *printername;
1474 uint32 mypid = (uint32)sys_getpid();
1475 BOOL ret = False;
1476 size_t i;
1478 /* if (snum == -1), then the change notify request was
1479 on a print server handle and we need to register on
1480 all print queus */
1482 if (snum == -1)
1484 int num_services = lp_numservices();
1485 int idx;
1487 for ( idx=0; idx<num_services; idx++ ) {
1488 if (lp_snum_ok(idx) && lp_print_ok(idx) )
1489 print_notify_register_pid(idx);
1492 return True;
1494 else /* register for a specific printer */
1496 printername = lp_const_servicename(snum);
1497 pdb = get_print_db_byname(printername);
1498 if (!pdb)
1499 return False;
1500 tdb = pdb->tdb;
1503 if (tdb_lock_bystring(tdb, NOTIFY_PID_LIST_KEY, 10) == -1) {
1504 DEBUG(0,("print_notify_register_pid: Failed to lock printer %s\n",
1505 printername));
1506 if (pdb)
1507 release_print_db(pdb);
1508 return False;
1511 data = get_printer_notify_pid_list( tdb, printername, True );
1513 /* Add ourselves and increase the refcount. */
1515 for (i = 0; i < data.dsize; i += 8) {
1516 if (IVAL(data.dptr,i) == mypid) {
1517 uint32 new_refcount = IVAL(data.dptr, i+4) + 1;
1518 SIVAL(data.dptr, i+4, new_refcount);
1519 break;
1523 if (i == data.dsize) {
1524 /* We weren't in the list. Realloc. */
1525 data.dptr = SMB_REALLOC(data.dptr, data.dsize + 8);
1526 if (!data.dptr) {
1527 DEBUG(0,("print_notify_register_pid: Relloc fail for printer %s\n",
1528 printername));
1529 goto done;
1531 data.dsize += 8;
1532 SIVAL(data.dptr,data.dsize - 8,mypid);
1533 SIVAL(data.dptr,data.dsize - 4,1); /* Refcount. */
1536 /* Store back the record. */
1537 if (tdb_store_bystring(tdb, NOTIFY_PID_LIST_KEY, data, TDB_REPLACE) == -1) {
1538 DEBUG(0,("print_notify_register_pid: Failed to update pid \
1539 list for printer %s\n", printername));
1540 goto done;
1543 ret = True;
1545 done:
1547 tdb_unlock_bystring(tdb, NOTIFY_PID_LIST_KEY);
1548 if (pdb)
1549 release_print_db(pdb);
1550 SAFE_FREE(data.dptr);
1551 return ret;
1554 /****************************************************************************
1555 Update an entry in the print tdb that will allow us to send notify
1556 updates only to interested smbd's.
1557 ****************************************************************************/
1559 BOOL print_notify_deregister_pid(int snum)
1561 TDB_DATA data;
1562 struct tdb_print_db *pdb = NULL;
1563 TDB_CONTEXT *tdb = NULL;
1564 const char *printername;
1565 uint32 mypid = (uint32)sys_getpid();
1566 size_t i;
1567 BOOL ret = False;
1569 /* if ( snum == -1 ), we are deregister a print server handle
1570 which means to deregister on all print queues */
1572 if (snum == -1)
1574 int num_services = lp_numservices();
1575 int idx;
1577 for ( idx=0; idx<num_services; idx++ ) {
1578 if ( lp_snum_ok(idx) && lp_print_ok(idx) )
1579 print_notify_deregister_pid(idx);
1582 return True;
1584 else /* deregister a specific printer */
1586 printername = lp_const_servicename(snum);
1587 pdb = get_print_db_byname(printername);
1588 if (!pdb)
1589 return False;
1590 tdb = pdb->tdb;
1593 if (tdb_lock_bystring(tdb, NOTIFY_PID_LIST_KEY, 10) == -1) {
1594 DEBUG(0,("print_notify_register_pid: Failed to lock \
1595 printer %s database\n", printername));
1596 if (pdb)
1597 release_print_db(pdb);
1598 return False;
1601 data = get_printer_notify_pid_list( tdb, printername, True );
1603 /* Reduce refcount. Remove ourselves if zero. */
1605 for (i = 0; i < data.dsize; ) {
1606 if (IVAL(data.dptr,i) == mypid) {
1607 uint32 refcount = IVAL(data.dptr, i+4);
1609 refcount--;
1611 if (refcount == 0) {
1612 if (data.dsize - i > 8)
1613 memmove( &data.dptr[i], &data.dptr[i+8], data.dsize - i - 8);
1614 data.dsize -= 8;
1615 continue;
1617 SIVAL(data.dptr, i+4, refcount);
1620 i += 8;
1623 if (data.dsize == 0)
1624 SAFE_FREE(data.dptr);
1626 /* Store back the record. */
1627 if (tdb_store_bystring(tdb, NOTIFY_PID_LIST_KEY, data, TDB_REPLACE) == -1) {
1628 DEBUG(0,("print_notify_register_pid: Failed to update pid \
1629 list for printer %s\n", printername));
1630 goto done;
1633 ret = True;
1635 done:
1637 tdb_unlock_bystring(tdb, NOTIFY_PID_LIST_KEY);
1638 if (pdb)
1639 release_print_db(pdb);
1640 SAFE_FREE(data.dptr);
1641 return ret;
1644 /****************************************************************************
1645 Check if a jobid is valid. It is valid if it exists in the database.
1646 ****************************************************************************/
1648 BOOL print_job_exists(const char* sharename, uint32 jobid)
1650 struct tdb_print_db *pdb = get_print_db_byname(sharename);
1651 BOOL ret;
1653 if (!pdb)
1654 return False;
1655 ret = tdb_exists(pdb->tdb, print_key(jobid));
1656 release_print_db(pdb);
1657 return ret;
1660 /****************************************************************************
1661 Give the fd used for a jobid.
1662 ****************************************************************************/
1664 int print_job_fd(const char* sharename, uint32 jobid)
1666 struct printjob *pjob = print_job_find(sharename, jobid);
1667 if (!pjob)
1668 return -1;
1669 /* don't allow another process to get this info - it is meaningless */
1670 if (pjob->pid != sys_getpid())
1671 return -1;
1672 return pjob->fd;
1675 /****************************************************************************
1676 Give the filename used for a jobid.
1677 Only valid for the process doing the spooling and when the job
1678 has not been spooled.
1679 ****************************************************************************/
1681 char *print_job_fname(const char* sharename, uint32 jobid)
1683 struct printjob *pjob = print_job_find(sharename, jobid);
1684 if (!pjob || pjob->spooled || pjob->pid != sys_getpid())
1685 return NULL;
1686 return pjob->filename;
1690 /****************************************************************************
1691 Give the filename used for a jobid.
1692 Only valid for the process doing the spooling and when the job
1693 has not been spooled.
1694 ****************************************************************************/
1696 NT_DEVICEMODE *print_job_devmode(const char* sharename, uint32 jobid)
1698 struct printjob *pjob = print_job_find(sharename, jobid);
1700 if ( !pjob )
1701 return NULL;
1703 return pjob->nt_devmode;
1706 /****************************************************************************
1707 Set the place in the queue for a job.
1708 ****************************************************************************/
1710 BOOL print_job_set_place(int snum, uint32 jobid, int place)
1712 DEBUG(2,("print_job_set_place not implemented yet\n"));
1713 return False;
1716 /****************************************************************************
1717 Set the name of a job. Only possible for owner.
1718 ****************************************************************************/
1720 BOOL print_job_set_name(int snum, uint32 jobid, char *name)
1722 const char* sharename = lp_const_servicename(snum);
1723 struct printjob *pjob;
1725 pjob = print_job_find(sharename, jobid);
1726 if (!pjob || pjob->pid != sys_getpid())
1727 return False;
1729 fstrcpy(pjob->jobname, name);
1730 return pjob_store(sharename, jobid, pjob);
1733 /***************************************************************************
1734 Remove a jobid from the 'jobs changed' list.
1735 ***************************************************************************/
1737 static BOOL remove_from_jobs_changed(const char* sharename, uint32 jobid)
1739 struct tdb_print_db *pdb = get_print_db_byname(sharename);
1740 TDB_DATA data, key;
1741 size_t job_count, i;
1742 BOOL ret = False;
1743 BOOL gotlock = False;
1745 if (!pdb) {
1746 return False;
1749 ZERO_STRUCT(data);
1751 key = string_tdb_data("INFO/jobs_changed");
1753 if (tdb_chainlock_with_timeout(pdb->tdb, key, 5) == -1)
1754 goto out;
1756 gotlock = True;
1758 data = tdb_fetch(pdb->tdb, key);
1760 if (data.dptr == NULL || data.dsize == 0 || (data.dsize % 4 != 0))
1761 goto out;
1763 job_count = data.dsize / 4;
1764 for (i = 0; i < job_count; i++) {
1765 uint32 ch_jobid;
1767 ch_jobid = IVAL(data.dptr, i*4);
1768 if (ch_jobid == jobid) {
1769 if (i < job_count -1 )
1770 memmove(data.dptr + (i*4), data.dptr + (i*4) + 4, (job_count - i - 1)*4 );
1771 data.dsize -= 4;
1772 if (tdb_store(pdb->tdb, key, data, TDB_REPLACE) == -1)
1773 goto out;
1774 break;
1778 ret = True;
1779 out:
1781 if (gotlock)
1782 tdb_chainunlock(pdb->tdb, key);
1783 SAFE_FREE(data.dptr);
1784 release_print_db(pdb);
1785 if (ret)
1786 DEBUG(10,("remove_from_jobs_changed: removed jobid %u\n", (unsigned int)jobid ));
1787 else
1788 DEBUG(10,("remove_from_jobs_changed: Failed to remove jobid %u\n", (unsigned int)jobid ));
1789 return ret;
1792 /****************************************************************************
1793 Delete a print job - don't update queue.
1794 ****************************************************************************/
1796 static BOOL print_job_delete1(int snum, uint32 jobid)
1798 const char* sharename = lp_const_servicename(snum);
1799 struct printjob *pjob = print_job_find(sharename, jobid);
1800 int result = 0;
1801 struct printif *current_printif = get_printer_fns( snum );
1803 pjob = print_job_find(sharename, jobid);
1805 if (!pjob)
1806 return False;
1809 * If already deleting just return.
1812 if (pjob->status == LPQ_DELETING)
1813 return True;
1815 /* Hrm - we need to be able to cope with deleting a job before it
1816 has reached the spooler. */
1818 if (pjob->sysjob == -1) {
1819 DEBUG(5, ("attempt to delete job %u not seen by lpr\n", (unsigned int)jobid));
1822 /* Set the tdb entry to be deleting. */
1824 pjob->status = LPQ_DELETING;
1825 pjob_store(sharename, jobid, pjob);
1827 if (pjob->spooled && pjob->sysjob != -1)
1828 result = (*(current_printif->job_delete))(snum, pjob);
1830 /* Delete the tdb entry if the delete succeeded or the job hasn't
1831 been spooled. */
1833 if (result == 0) {
1834 struct tdb_print_db *pdb = get_print_db_byname(sharename);
1835 int njobs = 1;
1837 if (!pdb)
1838 return False;
1839 pjob_delete(sharename, jobid);
1840 /* Ensure we keep a rough count of the number of total jobs... */
1841 tdb_change_int32_atomic(pdb->tdb, "INFO/total_jobs", &njobs, -1);
1842 release_print_db(pdb);
1845 return (result == 0);
1848 /****************************************************************************
1849 Return true if the current user owns the print job.
1850 ****************************************************************************/
1852 static BOOL is_owner(struct current_user *user, int snum, uint32 jobid)
1854 struct printjob *pjob = print_job_find(lp_const_servicename(snum), jobid);
1855 user_struct *vuser;
1857 if (!pjob || !user)
1858 return False;
1860 if ((vuser = get_valid_user_struct(user->vuid)) != NULL) {
1861 return strequal(pjob->user, vuser->user.smb_name);
1862 } else {
1863 return strequal(pjob->user, uidtoname(user->uid));
1867 /****************************************************************************
1868 Delete a print job.
1869 ****************************************************************************/
1871 BOOL print_job_delete(struct current_user *user, int snum, uint32 jobid, WERROR *errcode)
1873 const char* sharename = lp_const_servicename( snum );
1874 BOOL owner, deleted;
1875 char *fname;
1877 *errcode = WERR_OK;
1879 owner = is_owner(user, snum, jobid);
1881 /* Check access against security descriptor or whether the user
1882 owns their job. */
1884 if (!owner &&
1885 !print_access_check(user, snum, JOB_ACCESS_ADMINISTER)) {
1886 DEBUG(3, ("delete denied by security descriptor\n"));
1887 *errcode = WERR_ACCESS_DENIED;
1889 /* BEGIN_ADMIN_LOG */
1890 sys_adminlog( LOG_ERR,
1891 "Permission denied-- user not allowed to delete, \
1892 pause, or resume print job. User name: %s. Printer name: %s.",
1893 uidtoname(user->uid), PRINTERNAME(snum) );
1894 /* END_ADMIN_LOG */
1896 return False;
1900 * get the spooled filename of the print job
1901 * if this works, then the file has not been spooled
1902 * to the underlying print system. Just delete the
1903 * spool file & return.
1906 if ( (fname = print_job_fname( sharename, jobid )) != NULL )
1908 /* remove the spool file */
1909 DEBUG(10,("print_job_delete: Removing spool file [%s]\n", fname ));
1910 if ( unlink( fname ) == -1 ) {
1911 *errcode = map_werror_from_unix(errno);
1912 return False;
1916 if (!print_job_delete1(snum, jobid)) {
1917 *errcode = WERR_ACCESS_DENIED;
1918 return False;
1921 /* force update the database and say the delete failed if the
1922 job still exists */
1924 print_queue_update(snum, True);
1926 deleted = !print_job_exists(sharename, jobid);
1927 if ( !deleted )
1928 *errcode = WERR_ACCESS_DENIED;
1930 return deleted;
1933 /****************************************************************************
1934 Pause a job.
1935 ****************************************************************************/
1937 BOOL print_job_pause(struct current_user *user, int snum, uint32 jobid, WERROR *errcode)
1939 const char* sharename = lp_const_servicename(snum);
1940 struct printjob *pjob;
1941 int ret = -1;
1942 struct printif *current_printif = get_printer_fns( snum );
1944 pjob = print_job_find(sharename, jobid);
1946 if (!pjob || !user)
1947 return False;
1949 if (!pjob->spooled || pjob->sysjob == -1)
1950 return False;
1952 if (!is_owner(user, snum, jobid) &&
1953 !print_access_check(user, snum, JOB_ACCESS_ADMINISTER)) {
1954 DEBUG(3, ("pause denied by security descriptor\n"));
1956 /* BEGIN_ADMIN_LOG */
1957 sys_adminlog( LOG_ERR,
1958 "Permission denied-- user not allowed to delete, \
1959 pause, or resume print job. User name: %s. Printer name: %s.",
1960 uidtoname(user->uid), PRINTERNAME(snum) );
1961 /* END_ADMIN_LOG */
1963 *errcode = WERR_ACCESS_DENIED;
1964 return False;
1967 /* need to pause the spooled entry */
1968 ret = (*(current_printif->job_pause))(snum, pjob);
1970 if (ret != 0) {
1971 *errcode = WERR_INVALID_PARAM;
1972 return False;
1975 /* force update the database */
1976 print_cache_flush(snum);
1978 /* Send a printer notify message */
1980 notify_job_status(sharename, jobid, JOB_STATUS_PAUSED);
1982 /* how do we tell if this succeeded? */
1984 return True;
1987 /****************************************************************************
1988 Resume a job.
1989 ****************************************************************************/
1991 BOOL print_job_resume(struct current_user *user, int snum, uint32 jobid, WERROR *errcode)
1993 const char *sharename = lp_const_servicename(snum);
1994 struct printjob *pjob;
1995 int ret;
1996 struct printif *current_printif = get_printer_fns( snum );
1998 pjob = print_job_find(sharename, jobid);
2000 if (!pjob || !user)
2001 return False;
2003 if (!pjob->spooled || pjob->sysjob == -1)
2004 return False;
2006 if (!is_owner(user, snum, jobid) &&
2007 !print_access_check(user, snum, JOB_ACCESS_ADMINISTER)) {
2008 DEBUG(3, ("resume denied by security descriptor\n"));
2009 *errcode = WERR_ACCESS_DENIED;
2011 /* BEGIN_ADMIN_LOG */
2012 sys_adminlog( LOG_ERR,
2013 "Permission denied-- user not allowed to delete, \
2014 pause, or resume print job. User name: %s. Printer name: %s.",
2015 uidtoname(user->uid), PRINTERNAME(snum) );
2016 /* END_ADMIN_LOG */
2017 return False;
2020 ret = (*(current_printif->job_resume))(snum, pjob);
2022 if (ret != 0) {
2023 *errcode = WERR_INVALID_PARAM;
2024 return False;
2027 /* force update the database */
2028 print_cache_flush(snum);
2030 /* Send a printer notify message */
2032 notify_job_status(sharename, jobid, JOB_STATUS_QUEUED);
2034 return True;
2037 /****************************************************************************
2038 Write to a print file.
2039 ****************************************************************************/
2041 ssize_t print_job_write(int snum, uint32 jobid, const char *buf, SMB_OFF_T pos, size_t size)
2043 const char* sharename = lp_const_servicename(snum);
2044 int return_code;
2045 struct printjob *pjob;
2047 pjob = print_job_find(sharename, jobid);
2049 if (!pjob)
2050 return -1;
2051 /* don't allow another process to get this info - it is meaningless */
2052 if (pjob->pid != sys_getpid())
2053 return -1;
2055 return_code = write_data_at_offset(pjob->fd, buf, size, pos);
2057 if (return_code>0) {
2058 pjob->size += size;
2059 pjob_store(sharename, jobid, pjob);
2061 return return_code;
2064 /****************************************************************************
2065 Get the queue status - do not update if db is out of date.
2066 ****************************************************************************/
2068 static int get_queue_status(const char* sharename, print_status_struct *status)
2070 fstring keystr;
2071 TDB_DATA data;
2072 struct tdb_print_db *pdb = get_print_db_byname(sharename);
2073 int len;
2075 if (status) {
2076 ZERO_STRUCTP(status);
2079 if (!pdb)
2080 return 0;
2082 if (status) {
2083 fstr_sprintf(keystr, "STATUS/%s", sharename);
2084 data = tdb_fetch(pdb->tdb, string_tdb_data(keystr));
2085 if (data.dptr) {
2086 if (data.dsize == sizeof(print_status_struct))
2087 /* this memcpy is ok since the status struct was
2088 not packed before storing it in the tdb */
2089 memcpy(status, data.dptr, sizeof(print_status_struct));
2090 SAFE_FREE(data.dptr);
2093 len = tdb_fetch_int32(pdb->tdb, "INFO/total_jobs");
2094 release_print_db(pdb);
2095 return (len == -1 ? 0 : len);
2098 /****************************************************************************
2099 Determine the number of jobs in a queue.
2100 ****************************************************************************/
2102 int print_queue_length(int snum, print_status_struct *pstatus)
2104 const char* sharename = lp_const_servicename( snum );
2105 print_status_struct status;
2106 int len;
2108 ZERO_STRUCT( status );
2110 /* make sure the database is up to date */
2111 if (print_cache_expired(lp_const_servicename(snum), True))
2112 print_queue_update(snum, False);
2114 /* also fetch the queue status */
2115 memset(&status, 0, sizeof(status));
2116 len = get_queue_status(sharename, &status);
2118 if (pstatus)
2119 *pstatus = status;
2121 return len;
2124 /***************************************************************************
2125 Allocate a jobid. Hold the lock for as short a time as possible.
2126 ***************************************************************************/
2128 static BOOL allocate_print_jobid(struct tdb_print_db *pdb, int snum, const char *sharename, uint32 *pjobid)
2130 int i;
2131 uint32 jobid;
2133 *pjobid = (uint32)-1;
2135 for (i = 0; i < 3; i++) {
2136 /* Lock the database - only wait 20 seconds. */
2137 if (tdb_lock_bystring(pdb->tdb, "INFO/nextjob", 20) == -1) {
2138 DEBUG(0,("allocate_print_jobid: failed to lock printing database %s\n", sharename));
2139 return False;
2142 if (!tdb_fetch_uint32(pdb->tdb, "INFO/nextjob", &jobid)) {
2143 if (tdb_error(pdb->tdb) != TDB_ERR_NOEXIST) {
2144 DEBUG(0, ("allocate_print_jobid: failed to fetch INFO/nextjob for print queue %s\n",
2145 sharename));
2146 return False;
2148 jobid = 0;
2151 jobid = NEXT_JOBID(jobid);
2153 if (tdb_store_int32(pdb->tdb, "INFO/nextjob", jobid)==-1) {
2154 DEBUG(3, ("allocate_print_jobid: failed to store INFO/nextjob.\n"));
2155 tdb_unlock_bystring(pdb->tdb, "INFO/nextjob");
2156 return False;
2159 /* We've finished with the INFO/nextjob lock. */
2160 tdb_unlock_bystring(pdb->tdb, "INFO/nextjob");
2162 if (!print_job_exists(sharename, jobid))
2163 break;
2166 if (i > 2) {
2167 DEBUG(0, ("allocate_print_jobid: failed to allocate a print job for queue %s\n",
2168 sharename));
2169 /* Probably full... */
2170 errno = ENOSPC;
2171 return False;
2174 /* Store a dummy placeholder. */
2176 TDB_DATA dum;
2177 dum.dptr = NULL;
2178 dum.dsize = 0;
2179 if (tdb_store(pdb->tdb, print_key(jobid), dum, TDB_INSERT) == -1) {
2180 DEBUG(3, ("allocate_print_jobid: jobid (%d) failed to store placeholder.\n",
2181 jobid ));
2182 return False;
2186 *pjobid = jobid;
2187 return True;
2190 /***************************************************************************
2191 Append a jobid to the 'jobs changed' list.
2192 ***************************************************************************/
2194 static BOOL add_to_jobs_changed(struct tdb_print_db *pdb, uint32 jobid)
2196 TDB_DATA data;
2197 uint32 store_jobid;
2199 SIVAL(&store_jobid, 0, jobid);
2200 data.dptr = (char *)&store_jobid;
2201 data.dsize = 4;
2203 DEBUG(10,("add_to_jobs_changed: Added jobid %u\n", (unsigned int)jobid ));
2205 return (tdb_append(pdb->tdb, string_tdb_data("INFO/jobs_changed"),
2206 data) == 0);
2209 /***************************************************************************
2210 Start spooling a job - return the jobid.
2211 ***************************************************************************/
2213 uint32 print_job_start(struct current_user *user, int snum, char *jobname, NT_DEVICEMODE *nt_devmode )
2215 uint32 jobid;
2216 char *path;
2217 struct printjob pjob;
2218 user_struct *vuser;
2219 const char *sharename = lp_const_servicename(snum);
2220 struct tdb_print_db *pdb = get_print_db_byname(sharename);
2221 int njobs;
2223 errno = 0;
2225 if (!pdb)
2226 return (uint32)-1;
2228 if (!print_access_check(user, snum, PRINTER_ACCESS_USE)) {
2229 DEBUG(3, ("print_job_start: job start denied by security descriptor\n"));
2230 release_print_db(pdb);
2231 return (uint32)-1;
2234 if (!print_time_access_check(snum)) {
2235 DEBUG(3, ("print_job_start: job start denied by time check\n"));
2236 release_print_db(pdb);
2237 return (uint32)-1;
2240 path = lp_pathname(snum);
2242 /* see if we have sufficient disk space */
2243 if (lp_minprintspace(snum)) {
2244 SMB_BIG_UINT dspace, dsize;
2245 if (sys_fsusage(path, &dspace, &dsize) == 0 &&
2246 dspace < 2*(SMB_BIG_UINT)lp_minprintspace(snum)) {
2247 DEBUG(3, ("print_job_start: disk space check failed.\n"));
2248 release_print_db(pdb);
2249 errno = ENOSPC;
2250 return (uint32)-1;
2254 /* for autoloaded printers, check that the printcap entry still exists */
2255 if (lp_autoloaded(snum) && !pcap_printername_ok(lp_const_servicename(snum))) {
2256 DEBUG(3, ("print_job_start: printer name %s check failed.\n", lp_const_servicename(snum) ));
2257 release_print_db(pdb);
2258 errno = ENOENT;
2259 return (uint32)-1;
2262 /* Insure the maximum queue size is not violated */
2263 if ((njobs = print_queue_length(snum,NULL)) > lp_maxprintjobs(snum)) {
2264 DEBUG(3, ("print_job_start: Queue %s number of jobs (%d) larger than max printjobs per queue (%d).\n",
2265 sharename, njobs, lp_maxprintjobs(snum) ));
2266 release_print_db(pdb);
2267 errno = ENOSPC;
2268 return (uint32)-1;
2271 DEBUG(10,("print_job_start: Queue %s number of jobs (%d), max printjobs = %d\n",
2272 sharename, njobs, lp_maxprintjobs(snum) ));
2274 if (!allocate_print_jobid(pdb, snum, sharename, &jobid))
2275 goto fail;
2277 /* create the database entry */
2279 ZERO_STRUCT(pjob);
2281 pjob.pid = sys_getpid();
2282 pjob.sysjob = -1;
2283 pjob.fd = -1;
2284 pjob.starttime = time(NULL);
2285 pjob.status = LPQ_SPOOLING;
2286 pjob.size = 0;
2287 pjob.spooled = False;
2288 pjob.smbjob = True;
2289 pjob.nt_devmode = nt_devmode;
2291 fstrcpy(pjob.jobname, jobname);
2293 if ((vuser = get_valid_user_struct(user->vuid)) != NULL) {
2294 fstrcpy(pjob.user, vuser->user.smb_name);
2295 } else {
2296 fstrcpy(pjob.user, uidtoname(user->uid));
2299 fstrcpy(pjob.queuename, lp_const_servicename(snum));
2301 /* we have a job entry - now create the spool file */
2302 slprintf(pjob.filename, sizeof(pjob.filename)-1, "%s/%s%.8u.XXXXXX",
2303 path, PRINT_SPOOL_PREFIX, (unsigned int)jobid);
2304 pjob.fd = smb_mkstemp(pjob.filename);
2306 if (pjob.fd == -1) {
2307 if (errno == EACCES) {
2308 /* Common setup error, force a report. */
2309 DEBUG(0, ("print_job_start: insufficient permissions \
2310 to open spool file %s.\n", pjob.filename));
2311 } else {
2312 /* Normal case, report at level 3 and above. */
2313 DEBUG(3, ("print_job_start: can't open spool file %s,\n", pjob.filename));
2314 DEBUGADD(3, ("errno = %d (%s).\n", errno, strerror(errno)));
2316 goto fail;
2319 pjob_store(sharename, jobid, &pjob);
2321 /* Update the 'jobs changed' entry used by print_queue_status. */
2322 add_to_jobs_changed(pdb, jobid);
2324 /* Ensure we keep a rough count of the number of total jobs... */
2325 tdb_change_int32_atomic(pdb->tdb, "INFO/total_jobs", &njobs, 1);
2327 release_print_db(pdb);
2329 return jobid;
2331 fail:
2332 if (jobid != -1)
2333 pjob_delete(sharename, jobid);
2335 release_print_db(pdb);
2337 DEBUG(3, ("print_job_start: returning fail. Error = %s\n", strerror(errno) ));
2338 return (uint32)-1;
2341 /****************************************************************************
2342 Update the number of pages spooled to jobid
2343 ****************************************************************************/
2345 void print_job_endpage(int snum, uint32 jobid)
2347 const char* sharename = lp_const_servicename(snum);
2348 struct printjob *pjob;
2350 pjob = print_job_find(sharename, jobid);
2351 if (!pjob)
2352 return;
2353 /* don't allow another process to get this info - it is meaningless */
2354 if (pjob->pid != sys_getpid())
2355 return;
2357 pjob->page_count++;
2358 pjob_store(sharename, jobid, pjob);
2361 /****************************************************************************
2362 Print a file - called on closing the file. This spools the job.
2363 If normal close is false then we're tearing down the jobs - treat as an
2364 error.
2365 ****************************************************************************/
2367 BOOL print_job_end(int snum, uint32 jobid, BOOL normal_close)
2369 const char* sharename = lp_const_servicename(snum);
2370 struct printjob *pjob;
2371 int ret;
2372 SMB_STRUCT_STAT sbuf;
2373 struct printif *current_printif = get_printer_fns( snum );
2375 pjob = print_job_find(sharename, jobid);
2377 if (!pjob)
2378 return False;
2380 if (pjob->spooled || pjob->pid != sys_getpid())
2381 return False;
2383 if (normal_close && (sys_fstat(pjob->fd, &sbuf) == 0)) {
2384 pjob->size = sbuf.st_size;
2385 close(pjob->fd);
2386 pjob->fd = -1;
2387 } else {
2390 * Not a normal close or we couldn't stat the job file,
2391 * so something has gone wrong. Cleanup.
2393 close(pjob->fd);
2394 pjob->fd = -1;
2395 DEBUG(3,("print_job_end: failed to stat file for jobid %d\n", jobid ));
2396 goto fail;
2399 /* Technically, this is not quite right. If the printer has a separator
2400 * page turned on, the NT spooler prints the separator page even if the
2401 * print job is 0 bytes. 010215 JRR */
2402 if (pjob->size == 0 || pjob->status == LPQ_DELETING) {
2403 /* don't bother spooling empty files or something being deleted. */
2404 DEBUG(5,("print_job_end: canceling spool of %s (%s)\n",
2405 pjob->filename, pjob->size ? "deleted" : "zero length" ));
2406 unlink(pjob->filename);
2407 pjob_delete(sharename, jobid);
2408 return True;
2411 pjob->smbjob = jobid;
2413 ret = (*(current_printif->job_submit))(snum, pjob);
2415 if (ret)
2416 goto fail;
2418 /* The print job has been sucessfully handed over to the back-end */
2420 pjob->spooled = True;
2421 pjob->status = LPQ_QUEUED;
2422 pjob_store(sharename, jobid, pjob);
2424 /* make sure the database is up to date */
2425 if (print_cache_expired(lp_const_servicename(snum), True))
2426 print_queue_update(snum, False);
2428 return True;
2430 fail:
2432 /* The print job was not succesfully started. Cleanup */
2433 /* Still need to add proper error return propagation! 010122:JRR */
2434 unlink(pjob->filename);
2435 pjob_delete(sharename, jobid);
2436 return False;
2439 /****************************************************************************
2440 Get a snapshot of jobs in the system without traversing.
2441 ****************************************************************************/
2443 static BOOL get_stored_queue_info(struct tdb_print_db *pdb, int snum, int *pcount, print_queue_struct **ppqueue)
2445 TDB_DATA data, cgdata;
2446 print_queue_struct *queue = NULL;
2447 uint32 qcount = 0;
2448 uint32 extra_count = 0;
2449 int total_count = 0;
2450 size_t len = 0;
2451 uint32 i;
2452 int max_reported_jobs = lp_max_reported_jobs(snum);
2453 BOOL ret = False;
2454 const char* sharename = lp_servicename(snum);
2456 /* make sure the database is up to date */
2457 if (print_cache_expired(lp_const_servicename(snum), True))
2458 print_queue_update(snum, False);
2460 *pcount = 0;
2461 *ppqueue = NULL;
2463 ZERO_STRUCT(data);
2464 ZERO_STRUCT(cgdata);
2466 /* Get the stored queue data. */
2467 data = tdb_fetch(pdb->tdb, string_tdb_data("INFO/linear_queue_array"));
2469 if (data.dptr && data.dsize >= sizeof(qcount))
2470 len += tdb_unpack(data.dptr + len, data.dsize - len, "d", &qcount);
2472 /* Get the changed jobs list. */
2473 cgdata = tdb_fetch(pdb->tdb, string_tdb_data("INFO/jobs_changed"));
2474 if (cgdata.dptr != NULL && (cgdata.dsize % 4 == 0))
2475 extra_count = cgdata.dsize/4;
2477 DEBUG(5,("get_stored_queue_info: qcount = %u, extra_count = %u\n", (unsigned int)qcount, (unsigned int)extra_count));
2479 /* Allocate the queue size. */
2480 if (qcount == 0 && extra_count == 0)
2481 goto out;
2483 if ((queue = SMB_MALLOC_ARRAY(print_queue_struct, qcount + extra_count)) == NULL)
2484 goto out;
2486 /* Retrieve the linearised queue data. */
2488 for( i = 0; i < qcount; i++) {
2489 uint32 qjob, qsize, qpage_count, qstatus, qpriority, qtime;
2490 len += tdb_unpack(data.dptr + len, data.dsize - len, "ddddddff",
2491 &qjob,
2492 &qsize,
2493 &qpage_count,
2494 &qstatus,
2495 &qpriority,
2496 &qtime,
2497 queue[i].fs_user,
2498 queue[i].fs_file);
2499 queue[i].job = qjob;
2500 queue[i].size = qsize;
2501 queue[i].page_count = qpage_count;
2502 queue[i].status = qstatus;
2503 queue[i].priority = qpriority;
2504 queue[i].time = qtime;
2507 total_count = qcount;
2509 /* Add in the changed jobids. */
2510 for( i = 0; i < extra_count; i++) {
2511 uint32 jobid;
2512 struct printjob *pjob;
2514 jobid = IVAL(cgdata.dptr, i*4);
2515 DEBUG(5,("get_stored_queue_info: changed job = %u\n", (unsigned int)jobid));
2516 pjob = print_job_find(lp_const_servicename(snum), jobid);
2517 if (!pjob) {
2518 DEBUG(5,("get_stored_queue_info: failed to find changed job = %u\n", (unsigned int)jobid));
2519 remove_from_jobs_changed(sharename, jobid);
2520 continue;
2523 queue[total_count].job = jobid;
2524 queue[total_count].size = pjob->size;
2525 queue[total_count].page_count = pjob->page_count;
2526 queue[total_count].status = pjob->status;
2527 queue[total_count].priority = 1;
2528 queue[total_count].time = pjob->starttime;
2529 fstrcpy(queue[total_count].fs_user, pjob->user);
2530 fstrcpy(queue[total_count].fs_file, pjob->jobname);
2531 total_count++;
2534 /* Sort the queue by submission time otherwise they are displayed
2535 in hash order. */
2537 qsort(queue, total_count, sizeof(print_queue_struct), QSORT_CAST(printjob_comp));
2539 DEBUG(5,("get_stored_queue_info: total_count = %u\n", (unsigned int)total_count));
2541 if (max_reported_jobs && total_count > max_reported_jobs)
2542 total_count = max_reported_jobs;
2544 *ppqueue = queue;
2545 *pcount = total_count;
2547 ret = True;
2549 out:
2551 SAFE_FREE(data.dptr);
2552 SAFE_FREE(cgdata.dptr);
2553 return ret;
2556 /****************************************************************************
2557 Get a printer queue listing.
2558 set queue = NULL and status = NULL if you just want to update the cache
2559 ****************************************************************************/
2561 int print_queue_status(int snum,
2562 print_queue_struct **ppqueue,
2563 print_status_struct *status)
2565 fstring keystr;
2566 TDB_DATA data, key;
2567 const char *sharename;
2568 struct tdb_print_db *pdb;
2569 int count = 0;
2571 /* make sure the database is up to date */
2573 if (print_cache_expired(lp_const_servicename(snum), True))
2574 print_queue_update(snum, False);
2576 /* return if we are done */
2577 if ( !ppqueue || !status )
2578 return 0;
2580 *ppqueue = NULL;
2581 sharename = lp_const_servicename(snum);
2582 pdb = get_print_db_byname(sharename);
2584 if (!pdb)
2585 return 0;
2588 * Fetch the queue status. We must do this first, as there may
2589 * be no jobs in the queue.
2592 ZERO_STRUCTP(status);
2593 slprintf(keystr, sizeof(keystr)-1, "STATUS/%s", sharename);
2594 key.dptr = keystr;
2595 key.dsize = strlen(keystr);
2596 data = tdb_fetch(pdb->tdb, key);
2597 if (data.dptr) {
2598 if (data.dsize == sizeof(*status)) {
2599 /* this memcpy is ok since the status struct was
2600 not packed before storing it in the tdb */
2601 memcpy(status, data.dptr, sizeof(*status));
2603 SAFE_FREE(data.dptr);
2607 * Now, fetch the print queue information. We first count the number
2608 * of entries, and then only retrieve the queue if necessary.
2611 if (!get_stored_queue_info(pdb, snum, &count, ppqueue)) {
2612 release_print_db(pdb);
2613 return 0;
2616 release_print_db(pdb);
2617 return count;
2620 /****************************************************************************
2621 Pause a queue.
2622 ****************************************************************************/
2624 BOOL print_queue_pause(struct current_user *user, int snum, WERROR *errcode)
2626 int ret;
2627 struct printif *current_printif = get_printer_fns( snum );
2629 if (!print_access_check(user, snum, PRINTER_ACCESS_ADMINISTER)) {
2630 *errcode = WERR_ACCESS_DENIED;
2631 return False;
2635 become_root();
2637 ret = (*(current_printif->queue_pause))(snum);
2639 unbecome_root();
2641 if (ret != 0) {
2642 *errcode = WERR_INVALID_PARAM;
2643 return False;
2646 /* force update the database */
2647 print_cache_flush(snum);
2649 /* Send a printer notify message */
2651 notify_printer_status(snum, PRINTER_STATUS_PAUSED);
2653 return True;
2656 /****************************************************************************
2657 Resume a queue.
2658 ****************************************************************************/
2660 BOOL print_queue_resume(struct current_user *user, int snum, WERROR *errcode)
2662 int ret;
2663 struct printif *current_printif = get_printer_fns( snum );
2665 if (!print_access_check(user, snum, PRINTER_ACCESS_ADMINISTER)) {
2666 *errcode = WERR_ACCESS_DENIED;
2667 return False;
2670 become_root();
2672 ret = (*(current_printif->queue_resume))(snum);
2674 unbecome_root();
2676 if (ret != 0) {
2677 *errcode = WERR_INVALID_PARAM;
2678 return False;
2681 /* make sure the database is up to date */
2682 if (print_cache_expired(lp_const_servicename(snum), True))
2683 print_queue_update(snum, True);
2685 /* Send a printer notify message */
2687 notify_printer_status(snum, PRINTER_STATUS_OK);
2689 return True;
2692 /****************************************************************************
2693 Purge a queue - implemented by deleting all jobs that we can delete.
2694 ****************************************************************************/
2696 BOOL print_queue_purge(struct current_user *user, int snum, WERROR *errcode)
2698 print_queue_struct *queue;
2699 print_status_struct status;
2700 int njobs, i;
2701 BOOL can_job_admin;
2703 /* Force and update so the count is accurate (i.e. not a cached count) */
2704 print_queue_update(snum, True);
2706 can_job_admin = print_access_check(user, snum, JOB_ACCESS_ADMINISTER);
2707 njobs = print_queue_status(snum, &queue, &status);
2709 if ( can_job_admin )
2710 become_root();
2712 for (i=0;i<njobs;i++) {
2713 BOOL owner = is_owner(user, snum, queue[i].job);
2715 if (owner || can_job_admin) {
2716 print_job_delete1(snum, queue[i].job);
2720 if ( can_job_admin )
2721 unbecome_root();
2723 /* update the cache */
2724 print_queue_update( snum, True );
2726 SAFE_FREE(queue);
2728 return True;