LCOV - code coverage report
Current view: top level - source3/printing - printing.c (source / functions) Hit Total Coverage
Test: coverage report for vadcx-master-patch-75612 fe003de8 Lines: 1104 1555 71.0 %
Date: 2024-02-29 22:57:05 Functions: 58 61 95.1 %

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

Generated by: LCOV version 1.14