r7829: fix unitialized printer status field that was breaking migration of print...
[Samba/gbeck.git] / source / printing / printing.c
blob0737cf00d1d07658897195d15d5176131980fa7a
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 struct print_queue_update_context {
47 char* sharename;
48 int printing_type;
49 char* lpqcommand;
53 static TDB_CONTEXT *rap_tdb;
54 static uint16 next_rap_jobid;
55 struct rap_jobid_key {
56 fstring sharename;
57 uint32 jobid;
60 /***************************************************************************
61 Nightmare. LANMAN jobid's are 16 bit numbers..... We must map them to 32
62 bit RPC jobids.... JRA.
63 ***************************************************************************/
65 uint16 pjobid_to_rap(const char* sharename, uint32 jobid)
67 uint16 rap_jobid;
68 TDB_DATA data, key;
69 struct rap_jobid_key jinfo;
70 uint8 buf[2];
72 DEBUG(10,("pjobid_to_rap: called.\n"));
74 if (!rap_tdb) {
75 /* Create the in-memory tdb. */
76 rap_tdb = tdb_open_log(NULL, 0, TDB_INTERNAL, (O_RDWR|O_CREAT), 0644);
77 if (!rap_tdb)
78 return 0;
81 ZERO_STRUCT( jinfo );
82 fstrcpy( jinfo.sharename, sharename );
83 jinfo.jobid = jobid;
84 key.dptr = (char*)&jinfo;
85 key.dsize = sizeof(jinfo);
87 data = tdb_fetch(rap_tdb, key);
88 if (data.dptr && data.dsize == sizeof(uint16)) {
89 rap_jobid = SVAL(data.dptr, 0);
90 SAFE_FREE(data.dptr);
91 DEBUG(10,("pjobid_to_rap: jobid %u maps to RAP jobid %u\n",
92 (unsigned int)jobid, (unsigned int)rap_jobid));
93 return rap_jobid;
95 SAFE_FREE(data.dptr);
96 /* Not found - create and store mapping. */
97 rap_jobid = ++next_rap_jobid;
98 if (rap_jobid == 0)
99 rap_jobid = ++next_rap_jobid;
100 SSVAL(buf,0,rap_jobid);
101 data.dptr = buf;
102 data.dsize = sizeof(rap_jobid);
103 tdb_store(rap_tdb, key, data, TDB_REPLACE);
104 tdb_store(rap_tdb, data, key, TDB_REPLACE);
106 DEBUG(10,("pjobid_to_rap: created jobid %u maps to RAP jobid %u\n",
107 (unsigned int)jobid, (unsigned int)rap_jobid));
108 return rap_jobid;
111 BOOL rap_to_pjobid(uint16 rap_jobid, fstring sharename, uint32 *pjobid)
113 TDB_DATA data, key;
114 uint8 buf[2];
116 DEBUG(10,("rap_to_pjobid called.\n"));
118 if (!rap_tdb)
119 return False;
121 SSVAL(buf,0,rap_jobid);
122 key.dptr = buf;
123 key.dsize = sizeof(rap_jobid);
124 data = tdb_fetch(rap_tdb, key);
125 if ( data.dptr && data.dsize == sizeof(struct rap_jobid_key) )
127 struct rap_jobid_key *jinfo = (struct rap_jobid_key*)data.dptr;
128 fstrcpy( sharename, jinfo->sharename );
129 *pjobid = jinfo->jobid;
130 DEBUG(10,("rap_to_pjobid: jobid %u maps to RAP jobid %u\n",
131 (unsigned int)*pjobid, (unsigned int)rap_jobid));
132 SAFE_FREE(data.dptr);
133 return True;
136 DEBUG(10,("rap_to_pjobid: Failed to lookup RAP jobid %u\n",
137 (unsigned int)rap_jobid));
138 SAFE_FREE(data.dptr);
139 return False;
142 static void rap_jobid_delete(const char* sharename, uint32 jobid)
144 TDB_DATA key, data;
145 uint16 rap_jobid;
146 struct rap_jobid_key jinfo;
147 uint8 buf[2];
149 DEBUG(10,("rap_jobid_delete: called.\n"));
151 if (!rap_tdb)
152 return;
154 ZERO_STRUCT( jinfo );
155 fstrcpy( jinfo.sharename, sharename );
156 jinfo.jobid = jobid;
157 key.dptr = (char*)&jinfo;
158 key.dsize = sizeof(jinfo);
160 data = tdb_fetch(rap_tdb, key);
161 if (!data.dptr || (data.dsize != sizeof(uint16))) {
162 DEBUG(10,("rap_jobid_delete: cannot find jobid %u\n",
163 (unsigned int)jobid ));
164 SAFE_FREE(data.dptr);
165 return;
168 DEBUG(10,("rap_jobid_delete: deleting jobid %u\n",
169 (unsigned int)jobid ));
171 rap_jobid = SVAL(data.dptr, 0);
172 SAFE_FREE(data.dptr);
173 SSVAL(buf,0,rap_jobid);
174 data.dptr=buf;
175 data.dsize = sizeof(rap_jobid);
176 tdb_delete(rap_tdb, key);
177 tdb_delete(rap_tdb, data);
180 static int get_queue_status(const char* sharename, print_status_struct *);
182 /****************************************************************************
183 Initialise the printing backend. Called once at startup before the fork().
184 ****************************************************************************/
186 BOOL print_backend_init(void)
188 const char *sversion = "INFO/version";
189 pstring printing_path;
190 int services = lp_numservices();
191 int snum;
193 unlink(lock_path("printing.tdb"));
194 pstrcpy(printing_path,lock_path("printing"));
195 mkdir(printing_path,0755);
197 /* handle a Samba upgrade */
199 for (snum = 0; snum < services; snum++) {
200 struct tdb_print_db *pdb;
201 if (!lp_print_ok(snum))
202 continue;
204 pdb = get_print_db_byname(lp_const_servicename(snum));
205 if (!pdb)
206 continue;
207 if (tdb_lock_bystring(pdb->tdb, sversion, 0) == -1) {
208 DEBUG(0,("print_backend_init: Failed to open printer %s database\n", lp_const_servicename(snum) ));
209 release_print_db(pdb);
210 return False;
212 if (tdb_fetch_int32(pdb->tdb, sversion) != PRINT_DATABASE_VERSION) {
213 tdb_traverse(pdb->tdb, tdb_traverse_delete_fn, NULL);
214 tdb_store_int32(pdb->tdb, sversion, PRINT_DATABASE_VERSION);
216 tdb_unlock_bystring(pdb->tdb, sversion);
217 release_print_db(pdb);
220 close_all_print_db(); /* Don't leave any open. */
222 /* do NT print initialization... */
223 return nt_printing_init();
226 /****************************************************************************
227 Shut down printing backend. Called once at shutdown to close the tdb.
228 ****************************************************************************/
230 void printing_end(void)
232 close_all_print_db(); /* Don't leave any open. */
235 /****************************************************************************
236 Retrieve the set of printing functions for a given service. This allows
237 us to set the printer function table based on the value of the 'printing'
238 service parameter.
240 Use the generic interface as the default and only use cups interface only
241 when asked for (and only when supported)
242 ****************************************************************************/
244 static struct printif *get_printer_fns_from_type( int type )
246 struct printif *printer_fns = &generic_printif;
248 #ifdef HAVE_CUPS
249 if ( type == PRINT_CUPS ) {
250 printer_fns = &cups_printif;
252 #endif /* HAVE_CUPS */
254 printer_fns->type = type;
256 return printer_fns;
259 static struct printif *get_printer_fns( int snum )
261 return get_printer_fns_from_type( lp_printing(snum) );
265 /****************************************************************************
266 Useful function to generate a tdb key.
267 ****************************************************************************/
269 static TDB_DATA print_key(uint32 jobid)
271 static uint32 j;
272 TDB_DATA ret;
274 SIVAL(&j, 0, jobid);
275 ret.dptr = (void *)&j;
276 ret.dsize = sizeof(j);
277 return ret;
280 /***********************************************************************
281 unpack a pjob from a tdb buffer
282 ***********************************************************************/
284 int unpack_pjob( char* buf, int buflen, struct printjob *pjob )
286 int len = 0;
287 int used;
288 uint32 pjpid, pjsysjob, pjfd, pjstarttime, pjstatus;
289 uint32 pjsize, pjpage_count, pjspooled, pjsmbjob;
291 if ( !buf || !pjob )
292 return -1;
294 len += tdb_unpack(buf+len, buflen-len, "dddddddddffff",
295 &pjpid,
296 &pjsysjob,
297 &pjfd,
298 &pjstarttime,
299 &pjstatus,
300 &pjsize,
301 &pjpage_count,
302 &pjspooled,
303 &pjsmbjob,
304 pjob->filename,
305 pjob->jobname,
306 pjob->user,
307 pjob->queuename);
309 if ( len == -1 )
310 return -1;
312 if ( (used = unpack_devicemode(&pjob->nt_devmode, buf+len, buflen-len)) == -1 )
313 return -1;
315 len += used;
317 pjob->pid = pjpid;
318 pjob->sysjob = pjsysjob;
319 pjob->fd = pjfd;
320 pjob->starttime = pjstarttime;
321 pjob->status = pjstatus;
322 pjob->size = pjsize;
323 pjob->page_count = pjpage_count;
324 pjob->spooled = pjspooled;
325 pjob->smbjob = pjsmbjob;
327 return len;
331 /****************************************************************************
332 Useful function to find a print job in the database.
333 ****************************************************************************/
335 static struct printjob *print_job_find(const char *sharename, uint32 jobid)
337 static struct printjob pjob;
338 TDB_DATA ret;
339 struct tdb_print_db *pdb = get_print_db_byname(sharename);
342 if (!pdb)
343 return NULL;
345 ret = tdb_fetch(pdb->tdb, print_key(jobid));
346 release_print_db(pdb);
348 if (!ret.dptr)
349 return NULL;
351 if ( pjob.nt_devmode )
352 free_nt_devicemode( &pjob.nt_devmode );
354 ZERO_STRUCT( pjob );
356 if ( unpack_pjob( ret.dptr, ret.dsize, &pjob ) == -1 ) {
357 SAFE_FREE(ret.dptr);
358 return NULL;
361 SAFE_FREE(ret.dptr);
362 return &pjob;
365 /* Convert a unix jobid to a smb jobid */
367 static uint32 sysjob_to_jobid_value;
369 static int unixjob_traverse_fn(TDB_CONTEXT *the_tdb, TDB_DATA key,
370 TDB_DATA data, void *state)
372 struct printjob *pjob;
373 int *sysjob = (int *)state;
375 if (!data.dptr || data.dsize == 0)
376 return 0;
378 pjob = (struct printjob *)data.dptr;
379 if (key.dsize != sizeof(uint32))
380 return 0;
382 if (*sysjob == pjob->sysjob) {
383 uint32 jobid = IVAL(key.dptr,0);
385 sysjob_to_jobid_value = jobid;
386 return 1;
389 return 0;
392 /****************************************************************************
393 This is a *horribly expensive call as we have to iterate through all the
394 current printer tdb's. Don't do this often ! JRA.
395 ****************************************************************************/
397 uint32 sysjob_to_jobid(int unix_jobid)
399 int services = lp_numservices();
400 int snum;
402 sysjob_to_jobid_value = (uint32)-1;
404 for (snum = 0; snum < services; snum++) {
405 struct tdb_print_db *pdb;
406 if (!lp_print_ok(snum))
407 continue;
408 pdb = get_print_db_byname(lp_const_servicename(snum));
409 if (pdb)
410 tdb_traverse(pdb->tdb, unixjob_traverse_fn, &unix_jobid);
411 release_print_db(pdb);
412 if (sysjob_to_jobid_value != (uint32)-1)
413 return sysjob_to_jobid_value;
415 return (uint32)-1;
418 /****************************************************************************
419 Send notifications based on what has changed after a pjob_store.
420 ****************************************************************************/
422 static struct {
423 uint32 lpq_status;
424 uint32 spoolss_status;
425 } lpq_to_spoolss_status_map[] = {
426 { LPQ_QUEUED, JOB_STATUS_QUEUED },
427 { LPQ_PAUSED, JOB_STATUS_PAUSED },
428 { LPQ_SPOOLING, JOB_STATUS_SPOOLING },
429 { LPQ_PRINTING, JOB_STATUS_PRINTING },
430 { LPQ_DELETING, JOB_STATUS_DELETING },
431 { LPQ_OFFLINE, JOB_STATUS_OFFLINE },
432 { LPQ_PAPEROUT, JOB_STATUS_PAPEROUT },
433 { LPQ_PRINTED, JOB_STATUS_PRINTED },
434 { LPQ_DELETED, JOB_STATUS_DELETED },
435 { LPQ_BLOCKED, JOB_STATUS_BLOCKED },
436 { LPQ_USER_INTERVENTION, JOB_STATUS_USER_INTERVENTION },
437 { -1, 0 }
440 /* Convert a lpq status value stored in printing.tdb into the
441 appropriate win32 API constant. */
443 static uint32 map_to_spoolss_status(uint32 lpq_status)
445 int i = 0;
447 while (lpq_to_spoolss_status_map[i].lpq_status != -1) {
448 if (lpq_to_spoolss_status_map[i].lpq_status == lpq_status)
449 return lpq_to_spoolss_status_map[i].spoolss_status;
450 i++;
453 return 0;
456 static void pjob_store_notify(const char* sharename, uint32 jobid, struct printjob *old_data,
457 struct printjob *new_data)
459 BOOL new_job = False;
461 if (!old_data)
462 new_job = True;
464 /* Job attributes that can't be changed. We only send
465 notification for these on a new job. */
467 /* ACHTUNG! Due to a bug in Samba's spoolss parsing of the
468 NOTIFY_INFO_DATA buffer, we *have* to send the job submission
469 time first or else we'll end up with potential alignment
470 errors. I don't think the systemtime should be spooled as
471 a string, but this gets us around that error.
472 --jerry (i'll feel dirty for this) */
474 if (new_job) {
475 notify_job_submitted(sharename, jobid, new_data->starttime);
476 notify_job_username(sharename, jobid, new_data->user);
479 if (new_job || !strequal(old_data->jobname, new_data->jobname))
480 notify_job_name(sharename, jobid, new_data->jobname);
482 /* Job attributes of a new job or attributes that can be
483 modified. */
485 if (new_job || !strequal(old_data->jobname, new_data->jobname))
486 notify_job_name(sharename, jobid, new_data->jobname);
488 if (new_job || old_data->status != new_data->status)
489 notify_job_status(sharename, jobid, map_to_spoolss_status(new_data->status));
491 if (new_job || old_data->size != new_data->size)
492 notify_job_total_bytes(sharename, jobid, new_data->size);
494 if (new_job || old_data->page_count != new_data->page_count)
495 notify_job_total_pages(sharename, jobid, new_data->page_count);
498 /****************************************************************************
499 Store a job structure back to the database.
500 ****************************************************************************/
502 static BOOL pjob_store(const char* sharename, uint32 jobid, struct printjob *pjob)
504 TDB_DATA old_data, new_data;
505 BOOL ret = False;
506 struct tdb_print_db *pdb = get_print_db_byname(sharename);
507 char *buf = NULL;
508 int len, newlen, buflen;
511 if (!pdb)
512 return False;
514 /* Get old data */
516 old_data = tdb_fetch(pdb->tdb, print_key(jobid));
518 /* Doh! Now we have to pack/unpack data since the NT_DEVICEMODE was added */
520 newlen = 0;
522 do {
523 len = 0;
524 buflen = newlen;
525 len += tdb_pack(buf+len, buflen-len, "dddddddddffff",
526 (uint32)pjob->pid,
527 (uint32)pjob->sysjob,
528 (uint32)pjob->fd,
529 (uint32)pjob->starttime,
530 (uint32)pjob->status,
531 (uint32)pjob->size,
532 (uint32)pjob->page_count,
533 (uint32)pjob->spooled,
534 (uint32)pjob->smbjob,
535 pjob->filename,
536 pjob->jobname,
537 pjob->user,
538 pjob->queuename);
540 len += pack_devicemode(pjob->nt_devmode, buf+len, buflen-len);
542 if (buflen != len) {
543 char *tb;
545 tb = (char *)SMB_REALLOC(buf, len);
546 if (!tb) {
547 DEBUG(0,("pjob_store: failed to enlarge buffer!\n"));
548 goto done;
550 else
551 buf = tb;
552 newlen = len;
554 } while ( buflen != len );
557 /* Store new data */
559 new_data.dptr = buf;
560 new_data.dsize = len;
561 ret = (tdb_store(pdb->tdb, print_key(jobid), new_data, TDB_REPLACE) == 0);
563 release_print_db(pdb);
565 /* Send notify updates for what has changed */
567 if ( ret ) {
568 struct printjob old_pjob;
570 if ( old_data.dsize )
572 if ( unpack_pjob( old_data.dptr, old_data.dsize, &old_pjob ) != -1 )
574 pjob_store_notify( sharename, jobid, &old_pjob , pjob );
575 free_nt_devicemode( &old_pjob.nt_devmode );
578 else {
579 /* new job */
580 pjob_store_notify( sharename, jobid, NULL, pjob );
584 done:
585 SAFE_FREE( old_data.dptr );
586 SAFE_FREE( buf );
588 return ret;
591 /****************************************************************************
592 Remove a job structure from the database.
593 ****************************************************************************/
595 void pjob_delete(const char* sharename, uint32 jobid)
597 struct printjob *pjob;
598 uint32 job_status = 0;
599 struct tdb_print_db *pdb;
601 pdb = get_print_db_byname( sharename );
603 if (!pdb)
604 return;
606 pjob = print_job_find( sharename, jobid );
608 if (!pjob) {
609 DEBUG(5, ("pjob_delete: we were asked to delete nonexistent job %u\n",
610 (unsigned int)jobid));
611 release_print_db(pdb);
612 return;
615 /* We must cycle through JOB_STATUS_DELETING and
616 JOB_STATUS_DELETED for the port monitor to delete the job
617 properly. */
619 job_status = JOB_STATUS_DELETING|JOB_STATUS_DELETED;
620 notify_job_status(sharename, jobid, job_status);
622 /* Remove from printing.tdb */
624 tdb_delete(pdb->tdb, print_key(jobid));
625 remove_from_jobs_changed(sharename, jobid);
626 release_print_db( pdb );
627 rap_jobid_delete(sharename, jobid);
630 /****************************************************************************
631 Parse a file name from the system spooler to generate a jobid.
632 ****************************************************************************/
634 static uint32 print_parse_jobid(char *fname)
636 int jobid;
638 if (strncmp(fname,PRINT_SPOOL_PREFIX,strlen(PRINT_SPOOL_PREFIX)) != 0)
639 return (uint32)-1;
640 fname += strlen(PRINT_SPOOL_PREFIX);
642 jobid = atoi(fname);
643 if (jobid <= 0)
644 return (uint32)-1;
646 return (uint32)jobid;
649 /****************************************************************************
650 List a unix job in the print database.
651 ****************************************************************************/
653 static void print_unix_job(const char *sharename, print_queue_struct *q, uint32 jobid)
655 struct printjob pj, *old_pj;
657 if (jobid == (uint32)-1)
658 jobid = q->job + UNIX_JOB_START;
660 /* Preserve the timestamp on an existing unix print job */
662 old_pj = print_job_find(sharename, jobid);
664 ZERO_STRUCT(pj);
666 pj.pid = (pid_t)-1;
667 pj.sysjob = q->job;
668 pj.fd = -1;
669 pj.starttime = old_pj ? old_pj->starttime : q->time;
670 pj.status = q->status;
671 pj.size = q->size;
672 pj.spooled = True;
673 fstrcpy(pj.filename, old_pj ? old_pj->filename : "");
674 if (jobid < UNIX_JOB_START) {
675 pj.smbjob = True;
676 fstrcpy(pj.jobname, old_pj ? old_pj->jobname : "Remote Downlevel Document");
677 } else {
678 pj.smbjob = False;
679 fstrcpy(pj.jobname, old_pj ? old_pj->jobname : q->fs_file);
681 fstrcpy(pj.user, old_pj ? old_pj->user : q->fs_user);
682 fstrcpy(pj.queuename, old_pj ? old_pj->queuename : sharename );
684 pjob_store(sharename, jobid, &pj);
688 struct traverse_struct {
689 print_queue_struct *queue;
690 int qcount, snum, maxcount, total_jobs;
691 const char *sharename;
692 time_t lpq_time;
695 /****************************************************************************
696 Utility fn to delete any jobs that are no longer active.
697 ****************************************************************************/
699 static int traverse_fn_delete(TDB_CONTEXT *t, TDB_DATA key, TDB_DATA data, void *state)
701 struct traverse_struct *ts = (struct traverse_struct *)state;
702 struct printjob pjob;
703 uint32 jobid;
704 int i = 0;
706 if ( key.dsize != sizeof(jobid) )
707 return 0;
709 jobid = IVAL(key.dptr, 0);
710 if ( unpack_pjob( data.dptr, data.dsize, &pjob ) == -1 )
711 return 0;
712 free_nt_devicemode( &pjob.nt_devmode );
715 if (!pjob.smbjob) {
716 /* remove a unix job if it isn't in the system queue any more */
718 for (i=0;i<ts->qcount;i++) {
719 uint32 u_jobid = (ts->queue[i].job + UNIX_JOB_START);
720 if (jobid == u_jobid)
721 break;
723 if (i == ts->qcount) {
724 DEBUG(10,("traverse_fn_delete: pjob %u deleted due to !smbjob\n",
725 (unsigned int)jobid ));
726 pjob_delete(ts->sharename, jobid);
727 return 0;
730 /* need to continue the the bottom of the function to
731 save the correct attributes */
734 /* maybe it hasn't been spooled yet */
735 if (!pjob.spooled) {
736 /* if a job is not spooled and the process doesn't
737 exist then kill it. This cleans up after smbd
738 deaths */
739 if (!process_exists(pjob.pid)) {
740 DEBUG(10,("traverse_fn_delete: pjob %u deleted due to !process_exists (%u)\n",
741 (unsigned int)jobid, (unsigned int)pjob.pid ));
742 pjob_delete(ts->sharename, jobid);
743 } else
744 ts->total_jobs++;
745 return 0;
748 /* this check only makes sense for jobs submitted from Windows clients */
750 if ( pjob.smbjob ) {
751 for (i=0;i<ts->qcount;i++) {
752 uint32 curr_jobid = print_parse_jobid(ts->queue[i].fs_file);
753 if (jobid == curr_jobid)
754 break;
758 /* The job isn't in the system queue - we have to assume it has
759 completed, so delete the database entry. */
761 if (i == ts->qcount) {
763 /* A race can occur between the time a job is spooled and
764 when it appears in the lpq output. This happens when
765 the job is added to printing.tdb when another smbd
766 running print_queue_update() has completed a lpq and
767 is currently traversing the printing tdb and deleting jobs.
768 Don't delete the job if it was submitted after the lpq_time. */
770 if (pjob.starttime < ts->lpq_time) {
771 DEBUG(10,("traverse_fn_delete: pjob %u deleted due to pjob.starttime (%u) < ts->lpq_time (%u)\n",
772 (unsigned int)jobid,
773 (unsigned int)pjob.starttime,
774 (unsigned int)ts->lpq_time ));
775 pjob_delete(ts->sharename, jobid);
776 } else
777 ts->total_jobs++;
778 return 0;
781 /* Save the pjob attributes we will store. */
782 /* FIXME!!! This is the only place where queue->job
783 represents the SMB jobid --jerry */
784 ts->queue[i].job = jobid;
785 ts->queue[i].size = pjob.size;
786 ts->queue[i].page_count = pjob.page_count;
787 ts->queue[i].status = pjob.status;
788 ts->queue[i].priority = 1;
789 ts->queue[i].time = pjob.starttime;
790 fstrcpy(ts->queue[i].fs_user, pjob.user);
791 fstrcpy(ts->queue[i].fs_file, pjob.jobname);
793 ts->total_jobs++;
795 return 0;
798 /****************************************************************************
799 Check if the print queue has been updated recently enough.
800 ****************************************************************************/
802 static void print_cache_flush(int snum)
804 fstring key;
805 const char *sharename = lp_const_servicename(snum);
806 struct tdb_print_db *pdb = get_print_db_byname(sharename);
808 if (!pdb)
809 return;
810 slprintf(key, sizeof(key)-1, "CACHE/%s", sharename);
811 tdb_store_int32(pdb->tdb, key, -1);
812 release_print_db(pdb);
815 /****************************************************************************
816 Check if someone already thinks they are doing the update.
817 ****************************************************************************/
819 static pid_t get_updating_pid(const char *sharename)
821 fstring keystr;
822 TDB_DATA data, key;
823 pid_t updating_pid;
824 struct tdb_print_db *pdb = get_print_db_byname(sharename);
826 if (!pdb)
827 return (pid_t)-1;
828 slprintf(keystr, sizeof(keystr)-1, "UPDATING/%s", sharename);
829 key.dptr = keystr;
830 key.dsize = strlen(keystr);
832 data = tdb_fetch(pdb->tdb, key);
833 release_print_db(pdb);
834 if (!data.dptr || data.dsize != sizeof(pid_t)) {
835 SAFE_FREE(data.dptr);
836 return (pid_t)-1;
839 updating_pid = IVAL(data.dptr, 0);
840 SAFE_FREE(data.dptr);
842 if (process_exists(updating_pid))
843 return updating_pid;
845 return (pid_t)-1;
848 /****************************************************************************
849 Set the fact that we're doing the update, or have finished doing the update
850 in the tdb.
851 ****************************************************************************/
853 static void set_updating_pid(const fstring sharename, BOOL updating)
855 fstring keystr;
856 TDB_DATA key;
857 TDB_DATA data;
858 pid_t updating_pid = sys_getpid();
859 uint8 buffer[4];
861 struct tdb_print_db *pdb = get_print_db_byname(sharename);
863 if (!pdb)
864 return;
866 slprintf(keystr, sizeof(keystr)-1, "UPDATING/%s", sharename);
867 key.dptr = keystr;
868 key.dsize = strlen(keystr);
870 DEBUG(5, ("set_updating_pid: %s updating lpq cache for print share %s\n",
871 updating ? "" : "not ",
872 sharename ));
874 if ( !updating ) {
875 tdb_delete(pdb->tdb, key);
876 release_print_db(pdb);
877 return;
880 SIVAL( buffer, 0, updating_pid);
881 data.dptr = (void *)buffer;
882 data.dsize = 4; /* we always assume this is a 4 byte value */
884 tdb_store(pdb->tdb, key, data, TDB_REPLACE);
885 release_print_db(pdb);
888 /****************************************************************************
889 Sort print jobs by submittal time.
890 ****************************************************************************/
892 static int printjob_comp(print_queue_struct *j1, print_queue_struct *j2)
894 /* Silly cases */
896 if (!j1 && !j2)
897 return 0;
898 if (!j1)
899 return -1;
900 if (!j2)
901 return 1;
903 /* Sort on job start time */
905 if (j1->time == j2->time)
906 return 0;
907 return (j1->time > j2->time) ? 1 : -1;
910 /****************************************************************************
911 Store the sorted queue representation for later portmon retrieval.
912 ****************************************************************************/
914 static void store_queue_struct(struct tdb_print_db *pdb, struct traverse_struct *pts)
916 TDB_DATA data;
917 int max_reported_jobs = lp_max_reported_jobs(pts->snum);
918 print_queue_struct *queue = pts->queue;
919 size_t len;
920 size_t i;
921 uint qcount;
923 if (max_reported_jobs && (max_reported_jobs < pts->qcount))
924 pts->qcount = max_reported_jobs;
925 qcount = pts->qcount;
927 /* Work out the size. */
928 data.dsize = 0;
929 data.dsize += tdb_pack(NULL, 0, "d", qcount);
931 for (i = 0; i < pts->qcount; i++) {
932 data.dsize += tdb_pack(NULL, 0, "ddddddff",
933 (uint32)queue[i].job,
934 (uint32)queue[i].size,
935 (uint32)queue[i].page_count,
936 (uint32)queue[i].status,
937 (uint32)queue[i].priority,
938 (uint32)queue[i].time,
939 queue[i].fs_user,
940 queue[i].fs_file);
943 if ((data.dptr = SMB_MALLOC(data.dsize)) == NULL)
944 return;
946 len = 0;
947 len += tdb_pack(data.dptr + len, data.dsize - len, "d", qcount);
948 for (i = 0; i < pts->qcount; i++) {
949 len += tdb_pack(data.dptr + len, data.dsize - len, "ddddddff",
950 (uint32)queue[i].job,
951 (uint32)queue[i].size,
952 (uint32)queue[i].page_count,
953 (uint32)queue[i].status,
954 (uint32)queue[i].priority,
955 (uint32)queue[i].time,
956 queue[i].fs_user,
957 queue[i].fs_file);
960 tdb_store(pdb->tdb, string_tdb_data("INFO/linear_queue_array"), data,
961 TDB_REPLACE);
962 SAFE_FREE(data.dptr);
963 return;
966 static TDB_DATA get_jobs_changed_data(struct tdb_print_db *pdb)
968 TDB_DATA data;
970 ZERO_STRUCT(data);
972 data = tdb_fetch(pdb->tdb, string_tdb_data("INFO/jobs_changed"));
973 if (data.dptr == NULL || data.dsize == 0 || (data.dsize % 4 != 0)) {
974 SAFE_FREE(data.dptr);
975 ZERO_STRUCT(data);
978 return data;
981 static void check_job_changed(const char *sharename, TDB_DATA data, uint32 jobid)
983 unsigned int i;
984 unsigned int job_count = data.dsize / 4;
986 for (i = 0; i < job_count; i++) {
987 uint32 ch_jobid;
989 ch_jobid = IVAL(data.dptr, i*4);
990 if (ch_jobid == jobid)
991 remove_from_jobs_changed(sharename, jobid);
995 /****************************************************************************
996 Check if the print queue has been updated recently enough.
997 ****************************************************************************/
999 static BOOL print_cache_expired(const char *sharename, BOOL check_pending)
1001 fstring key;
1002 time_t last_qscan_time, time_now = time(NULL);
1003 struct tdb_print_db *pdb = get_print_db_byname(sharename);
1004 BOOL result = False;
1006 if (!pdb)
1007 return False;
1009 snprintf(key, sizeof(key), "CACHE/%s", sharename);
1010 last_qscan_time = (time_t)tdb_fetch_int32(pdb->tdb, key);
1013 * Invalidate the queue for 3 reasons.
1014 * (1). last queue scan time == -1.
1015 * (2). Current time - last queue scan time > allowed cache time.
1016 * (3). last queue scan time > current time + MAX_CACHE_VALID_TIME (1 hour by default).
1017 * This last test picks up machines for which the clock has been moved
1018 * forward, an lpq scan done and then the clock moved back. Otherwise
1019 * that last lpq scan would stay around for a loooong loooong time... :-). JRA.
1022 if (last_qscan_time == ((time_t)-1)
1023 || (time_now - last_qscan_time) >= lp_lpqcachetime()
1024 || last_qscan_time > (time_now + MAX_CACHE_VALID_TIME))
1026 time_t msg_pending_time;
1028 DEBUG(4, ("print_cache_expired: cache expired for queue %s "
1029 "(last_qscan_time = %d, time now = %d, qcachetime = %d)\n",
1030 sharename, (int)last_qscan_time, (int)time_now,
1031 (int)lp_lpqcachetime() ));
1033 /* check if another smbd has already sent a message to update the
1034 queue. Give the pending message one minute to clear and
1035 then send another message anyways. Make sure to check for
1036 clocks that have been run forward and then back again. */
1038 snprintf(key, sizeof(key), "MSG_PENDING/%s", sharename);
1040 if ( check_pending
1041 && tdb_fetch_uint32( pdb->tdb, key, (uint32*)&msg_pending_time )
1042 && msg_pending_time > 0
1043 && msg_pending_time <= time_now
1044 && (time_now - msg_pending_time) < 60 )
1046 DEBUG(4,("print_cache_expired: message already pending for %s. Accepting cache\n",
1047 sharename));
1048 goto done;
1051 result = True;
1054 done:
1055 release_print_db(pdb);
1056 return result;
1059 /****************************************************************************
1060 main work for updating the lpq cahe for a printer queue
1061 ****************************************************************************/
1063 static void print_queue_update_internal( const char *sharename,
1064 struct printif *current_printif,
1065 char *lpq_command )
1067 int i, qcount;
1068 print_queue_struct *queue = NULL;
1069 print_status_struct status;
1070 print_status_struct old_status;
1071 struct printjob *pjob;
1072 struct traverse_struct tstruct;
1073 TDB_DATA data, key;
1074 TDB_DATA jcdata;
1075 fstring keystr, cachestr;
1076 struct tdb_print_db *pdb = get_print_db_byname(sharename);
1078 DEBUG(5,("print_queue_update_internal: printer = %s, type = %d, lpq command = [%s]\n",
1079 sharename, current_printif->type, lpq_command));
1082 * Update the cache time FIRST ! Stops others even
1083 * attempting to get the lock and doing this
1084 * if the lpq takes a long time.
1087 slprintf(cachestr, sizeof(cachestr)-1, "CACHE/%s", sharename);
1088 tdb_store_int32(pdb->tdb, cachestr, (int)time(NULL));
1090 /* get the current queue using the appropriate interface */
1091 ZERO_STRUCT(status);
1093 qcount = (*(current_printif->queue_get))(sharename,
1094 current_printif->type,
1095 lpq_command, &queue, &status);
1097 DEBUG(3, ("print_queue_update_internal: %d job%s in queue for %s\n",
1098 qcount, (qcount != 1) ? "s" : "", sharename));
1100 /* Sort the queue by submission time otherwise they are displayed
1101 in hash order. */
1103 qsort(queue, qcount, sizeof(print_queue_struct),
1104 QSORT_CAST(printjob_comp));
1107 any job in the internal database that is marked as spooled
1108 and doesn't exist in the system queue is considered finished
1109 and removed from the database
1111 any job in the system database but not in the internal database
1112 is added as a unix job
1114 fill in any system job numbers as we go
1117 jcdata = get_jobs_changed_data(pdb);
1119 for (i=0; i<qcount; i++) {
1120 uint32 jobid = print_parse_jobid(queue[i].fs_file);
1122 if (jobid == (uint32)-1) {
1123 /* assume its a unix print job */
1124 print_unix_job(sharename, &queue[i], jobid);
1125 continue;
1128 /* we have an active SMB print job - update its status */
1129 pjob = print_job_find(sharename, jobid);
1130 if (!pjob) {
1131 /* err, somethings wrong. Probably smbd was restarted
1132 with jobs in the queue. All we can do is treat them
1133 like unix jobs. Pity. */
1134 print_unix_job(sharename, &queue[i], jobid);
1135 continue;
1138 pjob->sysjob = queue[i].job;
1139 pjob->status = queue[i].status;
1140 pjob_store(sharename, jobid, pjob);
1141 check_job_changed(sharename, jcdata, jobid);
1144 SAFE_FREE(jcdata.dptr);
1146 /* now delete any queued entries that don't appear in the
1147 system queue */
1148 tstruct.queue = queue;
1149 tstruct.qcount = qcount;
1150 tstruct.snum = -1;
1151 tstruct.total_jobs = 0;
1152 tstruct.lpq_time = time(NULL);
1153 tstruct.sharename = sharename;
1155 tdb_traverse(pdb->tdb, traverse_fn_delete, (void *)&tstruct);
1157 /* Store the linearised queue, max jobs only. */
1158 store_queue_struct(pdb, &tstruct);
1160 SAFE_FREE(tstruct.queue);
1162 DEBUG(10,("print_queue_update_internal: printer %s INFO/total_jobs = %d\n",
1163 sharename, tstruct.total_jobs ));
1165 tdb_store_int32(pdb->tdb, "INFO/total_jobs", tstruct.total_jobs);
1167 get_queue_status(sharename, &old_status);
1168 if (old_status.qcount != qcount)
1169 DEBUG(10,("print_queue_update_internal: queue status change %d jobs -> %d jobs for printer %s\n",
1170 old_status.qcount, qcount, sharename));
1172 /* store the new queue status structure */
1173 slprintf(keystr, sizeof(keystr)-1, "STATUS/%s", sharename);
1174 key.dptr = keystr;
1175 key.dsize = strlen(keystr);
1177 status.qcount = qcount;
1178 data.dptr = (void *)&status;
1179 data.dsize = sizeof(status);
1180 tdb_store(pdb->tdb, key, data, TDB_REPLACE);
1183 * Update the cache time again. We want to do this call
1184 * as little as possible...
1187 slprintf(keystr, sizeof(keystr)-1, "CACHE/%s", sharename);
1188 tdb_store_int32(pdb->tdb, keystr, (int32)time(NULL));
1190 /* clear the msg pending record for this queue */
1192 snprintf(keystr, sizeof(keystr), "MSG_PENDING/%s", sharename);
1194 if ( !tdb_store_uint32( pdb->tdb, keystr, 0 ) ) {
1195 /* log a message but continue on */
1197 DEBUG(0,("print_queue_update: failed to store MSG_PENDING flag for [%s]!\n",
1198 sharename));
1201 release_print_db( pdb );
1203 return;
1206 /****************************************************************************
1207 Update the internal database from the system print queue for a queue.
1208 obtain a lock on the print queue before proceeding (needed when mutiple
1209 smbd processes maytry to update the lpq cache concurrently).
1210 ****************************************************************************/
1212 static void print_queue_update_with_lock( const char *sharename,
1213 struct printif *current_printif,
1214 char *lpq_command )
1216 fstring keystr;
1217 struct tdb_print_db *pdb;
1219 DEBUG(5,("print_queue_update_with_lock: printer share = %s\n", sharename));
1220 pdb = get_print_db_byname(sharename);
1221 if (!pdb)
1222 return;
1224 if ( !print_cache_expired(sharename, False) ) {
1225 DEBUG(5,("print_queue_update_with_lock: print cache for %s is still ok\n", sharename));
1226 release_print_db(pdb);
1227 return;
1231 * Check to see if someone else is doing this update.
1232 * This is essentially a mutex on the update.
1235 if (get_updating_pid(sharename) != -1) {
1236 release_print_db(pdb);
1237 return;
1240 /* Lock the queue for the database update */
1242 slprintf(keystr, sizeof(keystr) - 1, "LOCK/%s", sharename);
1243 /* Only wait 10 seconds for this. */
1244 if (tdb_lock_bystring(pdb->tdb, keystr, 10) == -1) {
1245 DEBUG(0,("print_queue_update_with_lock: Failed to lock printer %s database\n", sharename));
1246 release_print_db(pdb);
1247 return;
1251 * Ensure that no one else got in here.
1252 * If the updating pid is still -1 then we are
1253 * the winner.
1256 if (get_updating_pid(sharename) != -1) {
1258 * Someone else is doing the update, exit.
1260 tdb_unlock_bystring(pdb->tdb, keystr);
1261 release_print_db(pdb);
1262 return;
1266 * We're going to do the update ourselves.
1269 /* Tell others we're doing the update. */
1270 set_updating_pid(sharename, True);
1273 * Allow others to enter and notice we're doing
1274 * the update.
1277 tdb_unlock_bystring(pdb->tdb, keystr);
1279 /* do the main work now */
1281 print_queue_update_internal( sharename, current_printif, lpq_command );
1283 /* Delete our pid from the db. */
1284 set_updating_pid(sharename, False);
1285 release_print_db(pdb);
1288 /****************************************************************************
1289 this is the receive function of the background lpq updater
1290 ****************************************************************************/
1291 static void print_queue_receive(int msg_type, pid_t src, void *buf, size_t msglen)
1293 struct print_queue_update_context ctx;
1294 fstring sharename;
1295 pstring lpqcommand;
1296 size_t len;
1298 len = tdb_unpack( buf, msglen, "fdP",
1299 sharename,
1300 &ctx.printing_type,
1301 lpqcommand );
1303 if ( len == -1 ) {
1304 DEBUG(0,("print_queue_receive: Got invalid print queue update message\n"));
1305 return;
1308 ctx.sharename = sharename;
1309 ctx.lpqcommand = lpqcommand;
1311 print_queue_update_with_lock(ctx.sharename,
1312 get_printer_fns_from_type(ctx.printing_type),
1313 ctx.lpqcommand );
1315 return;
1318 static pid_t background_lpq_updater_pid = -1;
1320 /****************************************************************************
1321 main thread of the background lpq updater
1322 ****************************************************************************/
1323 void start_background_queue(void)
1325 DEBUG(3,("start_background_queue: Starting background LPQ thread\n"));
1326 background_lpq_updater_pid = sys_fork();
1328 if (background_lpq_updater_pid == -1) {
1329 DEBUG(5,("start_background_queue: background LPQ thread failed to start. %s\n", strerror(errno) ));
1330 exit(1);
1333 if(background_lpq_updater_pid == 0) {
1334 /* Child. */
1335 DEBUG(5,("start_background_queue: background LPQ thread started\n"));
1337 claim_connection( NULL, "smbd lpq backend", 0, False,
1338 FLAG_MSG_GENERAL|FLAG_MSG_SMBD|FLAG_MSG_PRINT_GENERAL);
1340 if (!locking_init(0)) {
1341 exit(1);
1344 message_register(MSG_PRINTER_UPDATE, print_queue_receive);
1346 DEBUG(5,("start_background_queue: background LPQ thread waiting for messages\n"));
1347 while (1) {
1348 pause();
1350 /* check for some essential signals first */
1352 if (got_sig_term) {
1353 exit_server("Caught TERM signal");
1356 if (reload_after_sighup) {
1357 change_to_root_user();
1358 DEBUG(1,("Reloading services after SIGHUP\n"));
1359 reload_services(False);
1360 reload_after_sighup = 0;
1363 /* now check for messages */
1365 DEBUG(10,("start_background_queue: background LPQ thread got a message\n"));
1366 message_dispatch();
1368 /* process any pending print change notify messages */
1370 print_notify_send_messages(0);
1375 /****************************************************************************
1376 update the internal database from the system print queue for a queue
1377 ****************************************************************************/
1379 static void print_queue_update(int snum, BOOL force)
1381 fstring key;
1382 fstring sharename;
1383 pstring lpqcommand;
1384 char *buffer = NULL;
1385 size_t len = 0;
1386 size_t newlen;
1387 struct tdb_print_db *pdb;
1388 int type;
1389 struct printif *current_printif;
1391 fstrcpy( sharename, lp_const_servicename(snum));
1393 pstrcpy( lpqcommand, lp_lpqcommand(snum));
1394 pstring_sub( lpqcommand, "%p", PRINTERNAME(snum) );
1395 standard_sub_snum( snum, lpqcommand, sizeof(lpqcommand) );
1398 * Make sure that the background queue process exists.
1399 * Otherwise just do the update ourselves
1402 if ( force || background_lpq_updater_pid == -1 ) {
1403 DEBUG(4,("print_queue_update: updating queue [%s] myself\n", sharename));
1404 current_printif = get_printer_fns( snum );
1405 print_queue_update_with_lock( sharename, current_printif, lpqcommand );
1407 return;
1410 type = lp_printing(snum);
1412 /* get the length */
1414 len = tdb_pack( buffer, len, "fdP",
1415 sharename,
1416 type,
1417 lpqcommand );
1419 buffer = SMB_XMALLOC_ARRAY( char, len );
1421 /* now pack the buffer */
1422 newlen = tdb_pack( buffer, len, "fdP",
1423 sharename,
1424 type,
1425 lpqcommand );
1427 SMB_ASSERT( newlen == len );
1429 DEBUG(10,("print_queue_update: Sending message -> printer = %s, "
1430 "type = %d, lpq command = [%s]\n", sharename, type, lpqcommand ));
1432 /* here we set a msg pending record for other smbd processes
1433 to throttle the number of duplicate print_queue_update msgs
1434 sent. */
1436 pdb = get_print_db_byname(sharename);
1437 snprintf(key, sizeof(key), "MSG_PENDING/%s", sharename);
1439 if ( !tdb_store_uint32( pdb->tdb, key, time(NULL) ) ) {
1440 /* log a message but continue on */
1442 DEBUG(0,("print_queue_update: failed to store MSG_PENDING flag for [%s]!\n",
1443 sharename));
1446 release_print_db( pdb );
1448 /* finally send the message */
1450 become_root();
1451 message_send_pid(background_lpq_updater_pid,
1452 MSG_PRINTER_UPDATE, buffer, len, False);
1453 unbecome_root();
1455 SAFE_FREE( buffer );
1457 return;
1460 /****************************************************************************
1461 Create/Update an entry in the print tdb that will allow us to send notify
1462 updates only to interested smbd's.
1463 ****************************************************************************/
1465 BOOL print_notify_register_pid(int snum)
1467 TDB_DATA data;
1468 struct tdb_print_db *pdb = NULL;
1469 TDB_CONTEXT *tdb = NULL;
1470 const char *printername;
1471 uint32 mypid = (uint32)sys_getpid();
1472 BOOL ret = False;
1473 size_t i;
1475 /* if (snum == -1), then the change notify request was
1476 on a print server handle and we need to register on
1477 all print queus */
1479 if (snum == -1)
1481 int num_services = lp_numservices();
1482 int idx;
1484 for ( idx=0; idx<num_services; idx++ ) {
1485 if (lp_snum_ok(idx) && lp_print_ok(idx) )
1486 print_notify_register_pid(idx);
1489 return True;
1491 else /* register for a specific printer */
1493 printername = lp_const_servicename(snum);
1494 pdb = get_print_db_byname(printername);
1495 if (!pdb)
1496 return False;
1497 tdb = pdb->tdb;
1500 if (tdb_lock_bystring(tdb, NOTIFY_PID_LIST_KEY, 10) == -1) {
1501 DEBUG(0,("print_notify_register_pid: Failed to lock printer %s\n",
1502 printername));
1503 if (pdb)
1504 release_print_db(pdb);
1505 return False;
1508 data = get_printer_notify_pid_list( tdb, printername, True );
1510 /* Add ourselves and increase the refcount. */
1512 for (i = 0; i < data.dsize; i += 8) {
1513 if (IVAL(data.dptr,i) == mypid) {
1514 uint32 new_refcount = IVAL(data.dptr, i+4) + 1;
1515 SIVAL(data.dptr, i+4, new_refcount);
1516 break;
1520 if (i == data.dsize) {
1521 /* We weren't in the list. Realloc. */
1522 data.dptr = SMB_REALLOC(data.dptr, data.dsize + 8);
1523 if (!data.dptr) {
1524 DEBUG(0,("print_notify_register_pid: Relloc fail for printer %s\n",
1525 printername));
1526 goto done;
1528 data.dsize += 8;
1529 SIVAL(data.dptr,data.dsize - 8,mypid);
1530 SIVAL(data.dptr,data.dsize - 4,1); /* Refcount. */
1533 /* Store back the record. */
1534 if (tdb_store_bystring(tdb, NOTIFY_PID_LIST_KEY, data, TDB_REPLACE) == -1) {
1535 DEBUG(0,("print_notify_register_pid: Failed to update pid \
1536 list for printer %s\n", printername));
1537 goto done;
1540 ret = True;
1542 done:
1544 tdb_unlock_bystring(tdb, NOTIFY_PID_LIST_KEY);
1545 if (pdb)
1546 release_print_db(pdb);
1547 SAFE_FREE(data.dptr);
1548 return ret;
1551 /****************************************************************************
1552 Update an entry in the print tdb that will allow us to send notify
1553 updates only to interested smbd's.
1554 ****************************************************************************/
1556 BOOL print_notify_deregister_pid(int snum)
1558 TDB_DATA data;
1559 struct tdb_print_db *pdb = NULL;
1560 TDB_CONTEXT *tdb = NULL;
1561 const char *printername;
1562 uint32 mypid = (uint32)sys_getpid();
1563 size_t i;
1564 BOOL ret = False;
1566 /* if ( snum == -1 ), we are deregister a print server handle
1567 which means to deregister on all print queues */
1569 if (snum == -1)
1571 int num_services = lp_numservices();
1572 int idx;
1574 for ( idx=0; idx<num_services; idx++ ) {
1575 if ( lp_snum_ok(idx) && lp_print_ok(idx) )
1576 print_notify_deregister_pid(idx);
1579 return True;
1581 else /* deregister a specific printer */
1583 printername = lp_const_servicename(snum);
1584 pdb = get_print_db_byname(printername);
1585 if (!pdb)
1586 return False;
1587 tdb = pdb->tdb;
1590 if (tdb_lock_bystring(tdb, NOTIFY_PID_LIST_KEY, 10) == -1) {
1591 DEBUG(0,("print_notify_register_pid: Failed to lock \
1592 printer %s database\n", printername));
1593 if (pdb)
1594 release_print_db(pdb);
1595 return False;
1598 data = get_printer_notify_pid_list( tdb, printername, True );
1600 /* Reduce refcount. Remove ourselves if zero. */
1602 for (i = 0; i < data.dsize; ) {
1603 if (IVAL(data.dptr,i) == mypid) {
1604 uint32 refcount = IVAL(data.dptr, i+4);
1606 refcount--;
1608 if (refcount == 0) {
1609 if (data.dsize - i > 8)
1610 memmove( &data.dptr[i], &data.dptr[i+8], data.dsize - i - 8);
1611 data.dsize -= 8;
1612 continue;
1614 SIVAL(data.dptr, i+4, refcount);
1617 i += 8;
1620 if (data.dsize == 0)
1621 SAFE_FREE(data.dptr);
1623 /* Store back the record. */
1624 if (tdb_store_bystring(tdb, NOTIFY_PID_LIST_KEY, data, TDB_REPLACE) == -1) {
1625 DEBUG(0,("print_notify_register_pid: Failed to update pid \
1626 list for printer %s\n", printername));
1627 goto done;
1630 ret = True;
1632 done:
1634 tdb_unlock_bystring(tdb, NOTIFY_PID_LIST_KEY);
1635 if (pdb)
1636 release_print_db(pdb);
1637 SAFE_FREE(data.dptr);
1638 return ret;
1641 /****************************************************************************
1642 Check if a jobid is valid. It is valid if it exists in the database.
1643 ****************************************************************************/
1645 BOOL print_job_exists(const char* sharename, uint32 jobid)
1647 struct tdb_print_db *pdb = get_print_db_byname(sharename);
1648 BOOL ret;
1650 if (!pdb)
1651 return False;
1652 ret = tdb_exists(pdb->tdb, print_key(jobid));
1653 release_print_db(pdb);
1654 return ret;
1657 /****************************************************************************
1658 Give the fd used for a jobid.
1659 ****************************************************************************/
1661 int print_job_fd(const char* sharename, uint32 jobid)
1663 struct printjob *pjob = print_job_find(sharename, jobid);
1664 if (!pjob)
1665 return -1;
1666 /* don't allow another process to get this info - it is meaningless */
1667 if (pjob->pid != sys_getpid())
1668 return -1;
1669 return pjob->fd;
1672 /****************************************************************************
1673 Give the filename used for a jobid.
1674 Only valid for the process doing the spooling and when the job
1675 has not been spooled.
1676 ****************************************************************************/
1678 char *print_job_fname(const char* sharename, uint32 jobid)
1680 struct printjob *pjob = print_job_find(sharename, jobid);
1681 if (!pjob || pjob->spooled || pjob->pid != sys_getpid())
1682 return NULL;
1683 return pjob->filename;
1687 /****************************************************************************
1688 Give the filename used for a jobid.
1689 Only valid for the process doing the spooling and when the job
1690 has not been spooled.
1691 ****************************************************************************/
1693 NT_DEVICEMODE *print_job_devmode(const char* sharename, uint32 jobid)
1695 struct printjob *pjob = print_job_find(sharename, jobid);
1697 if ( !pjob )
1698 return NULL;
1700 return pjob->nt_devmode;
1703 /****************************************************************************
1704 Set the place in the queue for a job.
1705 ****************************************************************************/
1707 BOOL print_job_set_place(int snum, uint32 jobid, int place)
1709 DEBUG(2,("print_job_set_place not implemented yet\n"));
1710 return False;
1713 /****************************************************************************
1714 Set the name of a job. Only possible for owner.
1715 ****************************************************************************/
1717 BOOL print_job_set_name(int snum, uint32 jobid, char *name)
1719 const char* sharename = lp_const_servicename(snum);
1720 struct printjob *pjob;
1722 pjob = print_job_find(sharename, jobid);
1723 if (!pjob || pjob->pid != sys_getpid())
1724 return False;
1726 fstrcpy(pjob->jobname, name);
1727 return pjob_store(sharename, jobid, pjob);
1730 /***************************************************************************
1731 Remove a jobid from the 'jobs changed' list.
1732 ***************************************************************************/
1734 static BOOL remove_from_jobs_changed(const char* sharename, uint32 jobid)
1736 struct tdb_print_db *pdb = get_print_db_byname(sharename);
1737 TDB_DATA data, key;
1738 size_t job_count, i;
1739 BOOL ret = False;
1740 BOOL gotlock = False;
1742 ZERO_STRUCT(data);
1744 key = string_tdb_data("INFO/jobs_changed");
1746 if (tdb_chainlock_with_timeout(pdb->tdb, key, 5) == -1)
1747 goto out;
1749 gotlock = True;
1751 data = tdb_fetch(pdb->tdb, key);
1753 if (data.dptr == NULL || data.dsize == 0 || (data.dsize % 4 != 0))
1754 goto out;
1756 job_count = data.dsize / 4;
1757 for (i = 0; i < job_count; i++) {
1758 uint32 ch_jobid;
1760 ch_jobid = IVAL(data.dptr, i*4);
1761 if (ch_jobid == jobid) {
1762 if (i < job_count -1 )
1763 memmove(data.dptr + (i*4), data.dptr + (i*4) + 4, (job_count - i - 1)*4 );
1764 data.dsize -= 4;
1765 if (tdb_store(pdb->tdb, key, data, TDB_REPLACE) == -1)
1766 goto out;
1767 break;
1771 ret = True;
1772 out:
1774 if (gotlock)
1775 tdb_chainunlock(pdb->tdb, key);
1776 SAFE_FREE(data.dptr);
1777 release_print_db(pdb);
1778 if (ret)
1779 DEBUG(10,("remove_from_jobs_changed: removed jobid %u\n", (unsigned int)jobid ));
1780 else
1781 DEBUG(10,("remove_from_jobs_changed: Failed to remove jobid %u\n", (unsigned int)jobid ));
1782 return ret;
1785 /****************************************************************************
1786 Delete a print job - don't update queue.
1787 ****************************************************************************/
1789 static BOOL print_job_delete1(int snum, uint32 jobid)
1791 const char* sharename = lp_const_servicename(snum);
1792 struct printjob *pjob = print_job_find(sharename, jobid);
1793 int result = 0;
1794 struct printif *current_printif = get_printer_fns( snum );
1796 pjob = print_job_find(sharename, jobid);
1798 if (!pjob)
1799 return False;
1802 * If already deleting just return.
1805 if (pjob->status == LPQ_DELETING)
1806 return True;
1808 /* Hrm - we need to be able to cope with deleting a job before it
1809 has reached the spooler. */
1811 if (pjob->sysjob == -1) {
1812 DEBUG(5, ("attempt to delete job %u not seen by lpr\n", (unsigned int)jobid));
1815 /* Set the tdb entry to be deleting. */
1817 pjob->status = LPQ_DELETING;
1818 pjob_store(sharename, jobid, pjob);
1820 if (pjob->spooled && pjob->sysjob != -1)
1821 result = (*(current_printif->job_delete))(snum, pjob);
1823 /* Delete the tdb entry if the delete succeeded or the job hasn't
1824 been spooled. */
1826 if (result == 0) {
1827 struct tdb_print_db *pdb = get_print_db_byname(sharename);
1828 int njobs = 1;
1830 if (!pdb)
1831 return False;
1832 pjob_delete(sharename, jobid);
1833 /* Ensure we keep a rough count of the number of total jobs... */
1834 tdb_change_int32_atomic(pdb->tdb, "INFO/total_jobs", &njobs, -1);
1835 release_print_db(pdb);
1838 return (result == 0);
1841 /****************************************************************************
1842 Return true if the current user owns the print job.
1843 ****************************************************************************/
1845 static BOOL is_owner(struct current_user *user, int snum, uint32 jobid)
1847 struct printjob *pjob = print_job_find(lp_const_servicename(snum), jobid);
1848 user_struct *vuser;
1850 if (!pjob || !user)
1851 return False;
1853 if ((vuser = get_valid_user_struct(user->vuid)) != NULL) {
1854 return strequal(pjob->user, vuser->user.smb_name);
1855 } else {
1856 return strequal(pjob->user, uidtoname(user->uid));
1860 /****************************************************************************
1861 Delete a print job.
1862 ****************************************************************************/
1864 BOOL print_job_delete(struct current_user *user, int snum, uint32 jobid, WERROR *errcode)
1866 const char* sharename = lp_const_servicename( snum );
1867 BOOL owner, deleted;
1868 char *fname;
1870 *errcode = WERR_OK;
1872 owner = is_owner(user, snum, jobid);
1874 /* Check access against security descriptor or whether the user
1875 owns their job. */
1877 if (!owner &&
1878 !print_access_check(user, snum, JOB_ACCESS_ADMINISTER)) {
1879 DEBUG(3, ("delete denied by security descriptor\n"));
1880 *errcode = WERR_ACCESS_DENIED;
1882 /* BEGIN_ADMIN_LOG */
1883 sys_adminlog( LOG_ERR,
1884 "Permission denied-- user not allowed to delete, \
1885 pause, or resume print job. User name: %s. Printer name: %s.",
1886 uidtoname(user->uid), PRINTERNAME(snum) );
1887 /* END_ADMIN_LOG */
1889 return False;
1893 * get the spooled filename of the print job
1894 * if this works, then the file has not been spooled
1895 * to the underlying print system. Just delete the
1896 * spool file & return.
1899 if ( (fname = print_job_fname( sharename, jobid )) != NULL )
1901 /* remove the spool file */
1902 DEBUG(10,("print_job_delete: Removing spool file [%s]\n", fname ));
1903 if ( unlink( fname ) == -1 ) {
1904 *errcode = map_werror_from_unix(errno);
1905 return False;
1909 if (!print_job_delete1(snum, jobid)) {
1910 *errcode = WERR_ACCESS_DENIED;
1911 return False;
1914 /* force update the database and say the delete failed if the
1915 job still exists */
1917 print_queue_update(snum, True);
1919 deleted = !print_job_exists(sharename, jobid);
1920 if ( !deleted )
1921 *errcode = WERR_ACCESS_DENIED;
1923 return deleted;
1926 /****************************************************************************
1927 Pause a job.
1928 ****************************************************************************/
1930 BOOL print_job_pause(struct current_user *user, int snum, uint32 jobid, WERROR *errcode)
1932 const char* sharename = lp_const_servicename(snum);
1933 struct printjob *pjob;
1934 int ret = -1;
1935 struct printif *current_printif = get_printer_fns( snum );
1937 pjob = print_job_find(sharename, jobid);
1939 if (!pjob || !user)
1940 return False;
1942 if (!pjob->spooled || pjob->sysjob == -1)
1943 return False;
1945 if (!is_owner(user, snum, jobid) &&
1946 !print_access_check(user, snum, JOB_ACCESS_ADMINISTER)) {
1947 DEBUG(3, ("pause denied by security descriptor\n"));
1949 /* BEGIN_ADMIN_LOG */
1950 sys_adminlog( LOG_ERR,
1951 "Permission denied-- user not allowed to delete, \
1952 pause, or resume print job. User name: %s. Printer name: %s.",
1953 uidtoname(user->uid), PRINTERNAME(snum) );
1954 /* END_ADMIN_LOG */
1956 *errcode = WERR_ACCESS_DENIED;
1957 return False;
1960 /* need to pause the spooled entry */
1961 ret = (*(current_printif->job_pause))(snum, pjob);
1963 if (ret != 0) {
1964 *errcode = WERR_INVALID_PARAM;
1965 return False;
1968 /* force update the database */
1969 print_cache_flush(snum);
1971 /* Send a printer notify message */
1973 notify_job_status(sharename, jobid, JOB_STATUS_PAUSED);
1975 /* how do we tell if this succeeded? */
1977 return True;
1980 /****************************************************************************
1981 Resume a job.
1982 ****************************************************************************/
1984 BOOL print_job_resume(struct current_user *user, int snum, uint32 jobid, WERROR *errcode)
1986 const char *sharename = lp_const_servicename(snum);
1987 struct printjob *pjob;
1988 int ret;
1989 struct printif *current_printif = get_printer_fns( snum );
1991 pjob = print_job_find(sharename, jobid);
1993 if (!pjob || !user)
1994 return False;
1996 if (!pjob->spooled || pjob->sysjob == -1)
1997 return False;
1999 if (!is_owner(user, snum, jobid) &&
2000 !print_access_check(user, snum, JOB_ACCESS_ADMINISTER)) {
2001 DEBUG(3, ("resume denied by security descriptor\n"));
2002 *errcode = WERR_ACCESS_DENIED;
2004 /* BEGIN_ADMIN_LOG */
2005 sys_adminlog( LOG_ERR,
2006 "Permission denied-- user not allowed to delete, \
2007 pause, or resume print job. User name: %s. Printer name: %s.",
2008 uidtoname(user->uid), PRINTERNAME(snum) );
2009 /* END_ADMIN_LOG */
2010 return False;
2013 ret = (*(current_printif->job_resume))(snum, pjob);
2015 if (ret != 0) {
2016 *errcode = WERR_INVALID_PARAM;
2017 return False;
2020 /* force update the database */
2021 print_cache_flush(snum);
2023 /* Send a printer notify message */
2025 notify_job_status(sharename, jobid, JOB_STATUS_QUEUED);
2027 return True;
2030 /****************************************************************************
2031 Write to a print file.
2032 ****************************************************************************/
2034 ssize_t print_job_write(int snum, uint32 jobid, const char *buf, SMB_OFF_T pos, size_t size)
2036 const char* sharename = lp_const_servicename(snum);
2037 int return_code;
2038 struct printjob *pjob;
2040 pjob = print_job_find(sharename, jobid);
2042 if (!pjob)
2043 return -1;
2044 /* don't allow another process to get this info - it is meaningless */
2045 if (pjob->pid != sys_getpid())
2046 return -1;
2048 return_code = write_data_at_offset(pjob->fd, buf, size, pos);
2050 if (return_code>0) {
2051 pjob->size += size;
2052 pjob_store(sharename, jobid, pjob);
2054 return return_code;
2057 /****************************************************************************
2058 Get the queue status - do not update if db is out of date.
2059 ****************************************************************************/
2061 static int get_queue_status(const char* sharename, print_status_struct *status)
2063 fstring keystr;
2064 TDB_DATA data;
2065 struct tdb_print_db *pdb = get_print_db_byname(sharename);
2066 int len;
2068 if (!pdb)
2069 return 0;
2071 if (status) {
2072 ZERO_STRUCTP(status);
2073 fstr_sprintf(keystr, "STATUS/%s", sharename);
2074 data = tdb_fetch(pdb->tdb, string_tdb_data(keystr));
2075 if (data.dptr) {
2076 if (data.dsize == sizeof(print_status_struct))
2077 /* this memcpy is ok since the status struct was
2078 not packed before storing it in the tdb */
2079 memcpy(status, data.dptr, sizeof(print_status_struct));
2080 SAFE_FREE(data.dptr);
2083 len = tdb_fetch_int32(pdb->tdb, "INFO/total_jobs");
2084 release_print_db(pdb);
2085 return (len == -1 ? 0 : len);
2088 /****************************************************************************
2089 Determine the number of jobs in a queue.
2090 ****************************************************************************/
2092 int print_queue_length(int snum, print_status_struct *pstatus)
2094 const char* sharename = lp_const_servicename( snum );
2095 print_status_struct status;
2096 int len;
2098 ZERO_STRUCT( status );
2100 /* make sure the database is up to date */
2101 if (print_cache_expired(lp_const_servicename(snum), True))
2102 print_queue_update(snum, False);
2104 /* also fetch the queue status */
2105 memset(&status, 0, sizeof(status));
2106 len = get_queue_status(sharename, &status);
2108 if (pstatus)
2109 *pstatus = status;
2111 return len;
2114 /***************************************************************************
2115 Allocate a jobid. Hold the lock for as short a time as possible.
2116 ***************************************************************************/
2118 static BOOL allocate_print_jobid(struct tdb_print_db *pdb, int snum, const char *sharename, uint32 *pjobid)
2120 int i;
2121 uint32 jobid;
2123 *pjobid = (uint32)-1;
2125 for (i = 0; i < 3; i++) {
2126 /* Lock the database - only wait 20 seconds. */
2127 if (tdb_lock_bystring(pdb->tdb, "INFO/nextjob", 20) == -1) {
2128 DEBUG(0,("allocate_print_jobid: failed to lock printing database %s\n", sharename));
2129 return False;
2132 if (!tdb_fetch_uint32(pdb->tdb, "INFO/nextjob", &jobid)) {
2133 if (tdb_error(pdb->tdb) != TDB_ERR_NOEXIST) {
2134 DEBUG(0, ("allocate_print_jobid: failed to fetch INFO/nextjob for print queue %s\n",
2135 sharename));
2136 return False;
2138 jobid = 0;
2141 jobid = NEXT_JOBID(jobid);
2143 if (tdb_store_int32(pdb->tdb, "INFO/nextjob", jobid)==-1) {
2144 DEBUG(3, ("allocate_print_jobid: failed to store INFO/nextjob.\n"));
2145 tdb_unlock_bystring(pdb->tdb, "INFO/nextjob");
2146 return False;
2149 /* We've finished with the INFO/nextjob lock. */
2150 tdb_unlock_bystring(pdb->tdb, "INFO/nextjob");
2152 if (!print_job_exists(sharename, jobid))
2153 break;
2156 if (i > 2) {
2157 DEBUG(0, ("allocate_print_jobid: failed to allocate a print job for queue %s\n",
2158 sharename));
2159 /* Probably full... */
2160 errno = ENOSPC;
2161 return False;
2164 /* Store a dummy placeholder. */
2166 TDB_DATA dum;
2167 dum.dptr = NULL;
2168 dum.dsize = 0;
2169 if (tdb_store(pdb->tdb, print_key(jobid), dum, TDB_INSERT) == -1) {
2170 DEBUG(3, ("allocate_print_jobid: jobid (%d) failed to store placeholder.\n",
2171 jobid ));
2172 return False;
2176 *pjobid = jobid;
2177 return True;
2180 /***************************************************************************
2181 Append a jobid to the 'jobs changed' list.
2182 ***************************************************************************/
2184 static BOOL add_to_jobs_changed(struct tdb_print_db *pdb, uint32 jobid)
2186 TDB_DATA data;
2187 uint32 store_jobid;
2189 SIVAL(&store_jobid, 0, jobid);
2190 data.dptr = (char *)&store_jobid;
2191 data.dsize = 4;
2193 DEBUG(10,("add_to_jobs_changed: Added jobid %u\n", (unsigned int)jobid ));
2195 return (tdb_append(pdb->tdb, string_tdb_data("INFO/jobs_changed"),
2196 data) == 0);
2199 /***************************************************************************
2200 Start spooling a job - return the jobid.
2201 ***************************************************************************/
2203 uint32 print_job_start(struct current_user *user, int snum, char *jobname, NT_DEVICEMODE *nt_devmode )
2205 uint32 jobid;
2206 char *path;
2207 struct printjob pjob;
2208 user_struct *vuser;
2209 const char *sharename = lp_const_servicename(snum);
2210 struct tdb_print_db *pdb = get_print_db_byname(sharename);
2211 int njobs;
2213 errno = 0;
2215 if (!pdb)
2216 return (uint32)-1;
2218 if (!print_access_check(user, snum, PRINTER_ACCESS_USE)) {
2219 DEBUG(3, ("print_job_start: job start denied by security descriptor\n"));
2220 release_print_db(pdb);
2221 return (uint32)-1;
2224 if (!print_time_access_check(snum)) {
2225 DEBUG(3, ("print_job_start: job start denied by time check\n"));
2226 release_print_db(pdb);
2227 return (uint32)-1;
2230 path = lp_pathname(snum);
2232 /* see if we have sufficient disk space */
2233 if (lp_minprintspace(snum)) {
2234 SMB_BIG_UINT dspace, dsize;
2235 if (sys_fsusage(path, &dspace, &dsize) == 0 &&
2236 dspace < 2*(SMB_BIG_UINT)lp_minprintspace(snum)) {
2237 DEBUG(3, ("print_job_start: disk space check failed.\n"));
2238 release_print_db(pdb);
2239 errno = ENOSPC;
2240 return (uint32)-1;
2244 /* for autoloaded printers, check that the printcap entry still exists */
2245 if (lp_autoloaded(snum) && !pcap_printername_ok(lp_const_servicename(snum))) {
2246 DEBUG(3, ("print_job_start: printer name %s check failed.\n", lp_const_servicename(snum) ));
2247 release_print_db(pdb);
2248 errno = ENOENT;
2249 return (uint32)-1;
2252 /* Insure the maximum queue size is not violated */
2253 if ((njobs = print_queue_length(snum,NULL)) > lp_maxprintjobs(snum)) {
2254 DEBUG(3, ("print_job_start: Queue %s number of jobs (%d) larger than max printjobs per queue (%d).\n",
2255 sharename, njobs, lp_maxprintjobs(snum) ));
2256 release_print_db(pdb);
2257 errno = ENOSPC;
2258 return (uint32)-1;
2261 DEBUG(10,("print_job_start: Queue %s number of jobs (%d), max printjobs = %d\n",
2262 sharename, njobs, lp_maxprintjobs(snum) ));
2264 if (!allocate_print_jobid(pdb, snum, sharename, &jobid))
2265 goto fail;
2267 /* create the database entry */
2269 ZERO_STRUCT(pjob);
2271 pjob.pid = sys_getpid();
2272 pjob.sysjob = -1;
2273 pjob.fd = -1;
2274 pjob.starttime = time(NULL);
2275 pjob.status = LPQ_SPOOLING;
2276 pjob.size = 0;
2277 pjob.spooled = False;
2278 pjob.smbjob = True;
2279 pjob.nt_devmode = nt_devmode;
2281 fstrcpy(pjob.jobname, jobname);
2283 if ((vuser = get_valid_user_struct(user->vuid)) != NULL) {
2284 fstrcpy(pjob.user, vuser->user.smb_name);
2285 } else {
2286 fstrcpy(pjob.user, uidtoname(user->uid));
2289 fstrcpy(pjob.queuename, lp_const_servicename(snum));
2291 /* we have a job entry - now create the spool file */
2292 slprintf(pjob.filename, sizeof(pjob.filename)-1, "%s/%s%.8u.XXXXXX",
2293 path, PRINT_SPOOL_PREFIX, (unsigned int)jobid);
2294 pjob.fd = smb_mkstemp(pjob.filename);
2296 if (pjob.fd == -1) {
2297 if (errno == EACCES) {
2298 /* Common setup error, force a report. */
2299 DEBUG(0, ("print_job_start: insufficient permissions \
2300 to open spool file %s.\n", pjob.filename));
2301 } else {
2302 /* Normal case, report at level 3 and above. */
2303 DEBUG(3, ("print_job_start: can't open spool file %s,\n", pjob.filename));
2304 DEBUGADD(3, ("errno = %d (%s).\n", errno, strerror(errno)));
2306 goto fail;
2309 pjob_store(sharename, jobid, &pjob);
2311 /* Update the 'jobs changed' entry used by print_queue_status. */
2312 add_to_jobs_changed(pdb, jobid);
2314 /* Ensure we keep a rough count of the number of total jobs... */
2315 tdb_change_int32_atomic(pdb->tdb, "INFO/total_jobs", &njobs, 1);
2317 release_print_db(pdb);
2319 return jobid;
2321 fail:
2322 if (jobid != -1)
2323 pjob_delete(sharename, jobid);
2325 release_print_db(pdb);
2327 DEBUG(3, ("print_job_start: returning fail. Error = %s\n", strerror(errno) ));
2328 return (uint32)-1;
2331 /****************************************************************************
2332 Update the number of pages spooled to jobid
2333 ****************************************************************************/
2335 void print_job_endpage(int snum, uint32 jobid)
2337 const char* sharename = lp_const_servicename(snum);
2338 struct printjob *pjob;
2340 pjob = print_job_find(sharename, jobid);
2341 if (!pjob)
2342 return;
2343 /* don't allow another process to get this info - it is meaningless */
2344 if (pjob->pid != sys_getpid())
2345 return;
2347 pjob->page_count++;
2348 pjob_store(sharename, jobid, pjob);
2351 /****************************************************************************
2352 Print a file - called on closing the file. This spools the job.
2353 If normal close is false then we're tearing down the jobs - treat as an
2354 error.
2355 ****************************************************************************/
2357 BOOL print_job_end(int snum, uint32 jobid, BOOL normal_close)
2359 const char* sharename = lp_const_servicename(snum);
2360 struct printjob *pjob;
2361 int ret;
2362 SMB_STRUCT_STAT sbuf;
2363 struct printif *current_printif = get_printer_fns( snum );
2365 pjob = print_job_find(sharename, jobid);
2367 if (!pjob)
2368 return False;
2370 if (pjob->spooled || pjob->pid != sys_getpid())
2371 return False;
2373 if (normal_close && (sys_fstat(pjob->fd, &sbuf) == 0)) {
2374 pjob->size = sbuf.st_size;
2375 close(pjob->fd);
2376 pjob->fd = -1;
2377 } else {
2380 * Not a normal close or we couldn't stat the job file,
2381 * so something has gone wrong. Cleanup.
2383 close(pjob->fd);
2384 pjob->fd = -1;
2385 DEBUG(3,("print_job_end: failed to stat file for jobid %d\n", jobid ));
2386 goto fail;
2389 /* Technically, this is not quite right. If the printer has a separator
2390 * page turned on, the NT spooler prints the separator page even if the
2391 * print job is 0 bytes. 010215 JRR */
2392 if (pjob->size == 0 || pjob->status == LPQ_DELETING) {
2393 /* don't bother spooling empty files or something being deleted. */
2394 DEBUG(5,("print_job_end: canceling spool of %s (%s)\n",
2395 pjob->filename, pjob->size ? "deleted" : "zero length" ));
2396 unlink(pjob->filename);
2397 pjob_delete(sharename, jobid);
2398 return True;
2401 pjob->smbjob = jobid;
2403 ret = (*(current_printif->job_submit))(snum, pjob);
2405 if (ret)
2406 goto fail;
2408 /* The print job has been sucessfully handed over to the back-end */
2410 pjob->spooled = True;
2411 pjob->status = LPQ_QUEUED;
2412 pjob_store(sharename, jobid, pjob);
2414 /* make sure the database is up to date */
2415 if (print_cache_expired(lp_const_servicename(snum), True))
2416 print_queue_update(snum, False);
2418 return True;
2420 fail:
2422 /* The print job was not succesfully started. Cleanup */
2423 /* Still need to add proper error return propagation! 010122:JRR */
2424 unlink(pjob->filename);
2425 pjob_delete(sharename, jobid);
2426 return False;
2429 /****************************************************************************
2430 Get a snapshot of jobs in the system without traversing.
2431 ****************************************************************************/
2433 static BOOL get_stored_queue_info(struct tdb_print_db *pdb, int snum, int *pcount, print_queue_struct **ppqueue)
2435 TDB_DATA data, cgdata;
2436 print_queue_struct *queue = NULL;
2437 uint32 qcount = 0;
2438 uint32 extra_count = 0;
2439 int total_count = 0;
2440 size_t len = 0;
2441 uint32 i;
2442 int max_reported_jobs = lp_max_reported_jobs(snum);
2443 BOOL ret = False;
2444 const char* sharename = lp_servicename(snum);
2446 /* make sure the database is up to date */
2447 if (print_cache_expired(lp_const_servicename(snum), True))
2448 print_queue_update(snum, False);
2450 *pcount = 0;
2451 *ppqueue = NULL;
2453 ZERO_STRUCT(data);
2454 ZERO_STRUCT(cgdata);
2456 /* Get the stored queue data. */
2457 data = tdb_fetch(pdb->tdb, string_tdb_data("INFO/linear_queue_array"));
2459 if (data.dptr && data.dsize >= sizeof(qcount))
2460 len += tdb_unpack(data.dptr + len, data.dsize - len, "d", &qcount);
2462 /* Get the changed jobs list. */
2463 cgdata = tdb_fetch(pdb->tdb, string_tdb_data("INFO/jobs_changed"));
2464 if (cgdata.dptr != NULL && (cgdata.dsize % 4 == 0))
2465 extra_count = cgdata.dsize/4;
2467 DEBUG(5,("get_stored_queue_info: qcount = %u, extra_count = %u\n", (unsigned int)qcount, (unsigned int)extra_count));
2469 /* Allocate the queue size. */
2470 if (qcount == 0 && extra_count == 0)
2471 goto out;
2473 if ((queue = SMB_MALLOC_ARRAY(print_queue_struct, qcount + extra_count)) == NULL)
2474 goto out;
2476 /* Retrieve the linearised queue data. */
2478 for( i = 0; i < qcount; i++) {
2479 uint32 qjob, qsize, qpage_count, qstatus, qpriority, qtime;
2480 len += tdb_unpack(data.dptr + len, data.dsize - len, "ddddddff",
2481 &qjob,
2482 &qsize,
2483 &qpage_count,
2484 &qstatus,
2485 &qpriority,
2486 &qtime,
2487 queue[i].fs_user,
2488 queue[i].fs_file);
2489 queue[i].job = qjob;
2490 queue[i].size = qsize;
2491 queue[i].page_count = qpage_count;
2492 queue[i].status = qstatus;
2493 queue[i].priority = qpriority;
2494 queue[i].time = qtime;
2497 total_count = qcount;
2499 /* Add in the changed jobids. */
2500 for( i = 0; i < extra_count; i++) {
2501 uint32 jobid;
2502 struct printjob *pjob;
2504 jobid = IVAL(cgdata.dptr, i*4);
2505 DEBUG(5,("get_stored_queue_info: changed job = %u\n", (unsigned int)jobid));
2506 pjob = print_job_find(lp_const_servicename(snum), jobid);
2507 if (!pjob) {
2508 DEBUG(5,("get_stored_queue_info: failed to find changed job = %u\n", (unsigned int)jobid));
2509 remove_from_jobs_changed(sharename, jobid);
2510 continue;
2513 queue[total_count].job = jobid;
2514 queue[total_count].size = pjob->size;
2515 queue[total_count].page_count = pjob->page_count;
2516 queue[total_count].status = pjob->status;
2517 queue[total_count].priority = 1;
2518 queue[total_count].time = pjob->starttime;
2519 fstrcpy(queue[total_count].fs_user, pjob->user);
2520 fstrcpy(queue[total_count].fs_file, pjob->jobname);
2521 total_count++;
2524 /* Sort the queue by submission time otherwise they are displayed
2525 in hash order. */
2527 qsort(queue, total_count, sizeof(print_queue_struct), QSORT_CAST(printjob_comp));
2529 DEBUG(5,("get_stored_queue_info: total_count = %u\n", (unsigned int)total_count));
2531 if (max_reported_jobs && total_count > max_reported_jobs)
2532 total_count = max_reported_jobs;
2534 *ppqueue = queue;
2535 *pcount = total_count;
2537 ret = True;
2539 out:
2541 SAFE_FREE(data.dptr);
2542 SAFE_FREE(cgdata.dptr);
2543 return ret;
2546 /****************************************************************************
2547 Get a printer queue listing.
2548 set queue = NULL and status = NULL if you just want to update the cache
2549 ****************************************************************************/
2551 int print_queue_status(int snum,
2552 print_queue_struct **ppqueue,
2553 print_status_struct *status)
2555 fstring keystr;
2556 TDB_DATA data, key;
2557 const char *sharename;
2558 struct tdb_print_db *pdb;
2559 int count = 0;
2561 /* make sure the database is up to date */
2563 if (print_cache_expired(lp_const_servicename(snum), True))
2564 print_queue_update(snum, False);
2566 /* return if we are done */
2567 if ( !ppqueue || !status )
2568 return 0;
2570 *ppqueue = NULL;
2571 sharename = lp_const_servicename(snum);
2572 pdb = get_print_db_byname(sharename);
2574 if (!pdb)
2575 return 0;
2578 * Fetch the queue status. We must do this first, as there may
2579 * be no jobs in the queue.
2582 ZERO_STRUCTP(status);
2583 slprintf(keystr, sizeof(keystr)-1, "STATUS/%s", sharename);
2584 key.dptr = keystr;
2585 key.dsize = strlen(keystr);
2586 data = tdb_fetch(pdb->tdb, key);
2587 if (data.dptr) {
2588 if (data.dsize == sizeof(*status)) {
2589 /* this memcpy is ok since the status struct was
2590 not packed before storing it in the tdb */
2591 memcpy(status, data.dptr, sizeof(*status));
2593 SAFE_FREE(data.dptr);
2597 * Now, fetch the print queue information. We first count the number
2598 * of entries, and then only retrieve the queue if necessary.
2601 if (!get_stored_queue_info(pdb, snum, &count, ppqueue)) {
2602 release_print_db(pdb);
2603 return 0;
2606 release_print_db(pdb);
2607 return count;
2610 /****************************************************************************
2611 Pause a queue.
2612 ****************************************************************************/
2614 BOOL print_queue_pause(struct current_user *user, int snum, WERROR *errcode)
2616 int ret;
2617 struct printif *current_printif = get_printer_fns( snum );
2619 if (!print_access_check(user, snum, PRINTER_ACCESS_ADMINISTER)) {
2620 *errcode = WERR_ACCESS_DENIED;
2621 return False;
2625 become_root();
2627 ret = (*(current_printif->queue_pause))(snum);
2629 unbecome_root();
2631 if (ret != 0) {
2632 *errcode = WERR_INVALID_PARAM;
2633 return False;
2636 /* force update the database */
2637 print_cache_flush(snum);
2639 /* Send a printer notify message */
2641 notify_printer_status(snum, PRINTER_STATUS_PAUSED);
2643 return True;
2646 /****************************************************************************
2647 Resume a queue.
2648 ****************************************************************************/
2650 BOOL print_queue_resume(struct current_user *user, int snum, WERROR *errcode)
2652 int ret;
2653 struct printif *current_printif = get_printer_fns( snum );
2655 if (!print_access_check(user, snum, PRINTER_ACCESS_ADMINISTER)) {
2656 *errcode = WERR_ACCESS_DENIED;
2657 return False;
2660 become_root();
2662 ret = (*(current_printif->queue_resume))(snum);
2664 unbecome_root();
2666 if (ret != 0) {
2667 *errcode = WERR_INVALID_PARAM;
2668 return False;
2671 /* make sure the database is up to date */
2672 if (print_cache_expired(lp_const_servicename(snum), True))
2673 print_queue_update(snum, True);
2675 /* Send a printer notify message */
2677 notify_printer_status(snum, PRINTER_STATUS_OK);
2679 return True;
2682 /****************************************************************************
2683 Purge a queue - implemented by deleting all jobs that we can delete.
2684 ****************************************************************************/
2686 BOOL print_queue_purge(struct current_user *user, int snum, WERROR *errcode)
2688 print_queue_struct *queue;
2689 print_status_struct status;
2690 int njobs, i;
2691 BOOL can_job_admin;
2693 /* Force and update so the count is accurate (i.e. not a cached count) */
2694 print_queue_update(snum, True);
2696 can_job_admin = print_access_check(user, snum, JOB_ACCESS_ADMINISTER);
2697 njobs = print_queue_status(snum, &queue, &status);
2699 if ( can_job_admin )
2700 become_root();
2702 for (i=0;i<njobs;i++) {
2703 BOOL owner = is_owner(user, snum, queue[i].job);
2705 if (owner || can_job_admin) {
2706 print_job_delete1(snum, queue[i].job);
2710 if ( can_job_admin )
2711 unbecome_root();
2713 /* update the cache */
2714 print_queue_update( snum, True );
2716 SAFE_FREE(queue);
2718 return True;