s3-printing: pass a talloc ctx to unpack_pjob
[ddiss/samba.git] / source3 / printing / printing.c
index ac9e76809290fe9f887b9e88de4ef0e6ba220faf..69281846dfa09ed918d6e76a96970c1351ecaf98 100644 (file)
@@ -380,18 +380,21 @@ done:
  unpack a pjob from a tdb buffer
 ***********************************************************************/
 
-static int unpack_pjob( uint8 *buf, int buflen, struct printjob *pjob )
+static int unpack_pjob(TALLOC_CTX *mem_ctx, uint8 *buf, int buflen,
+                      struct printjob *pjob)
 {
        int     len = 0;
        int     used;
-       uint32 pjpid, pjsysjob, pjfd, pjstarttime, pjstatus;
+       uint32 pjpid, pjjobid, pjsysjob, pjfd, pjstarttime, pjstatus;
        uint32 pjsize, pjpage_count, pjspooled, pjsmbjob;
 
-       if ( !buf || !pjob )
+       if (!buf || !pjob) {
                return -1;
+       }
 
-       len += tdb_unpack(buf+len, buflen-len, "dddddddddfffff",
+       len += tdb_unpack(buf+len, buflen-len, "ddddddddddfffff",
                                &pjpid,
+                               &pjjobid,
                                &pjsysjob,
                                &pjfd,
                                &pjstarttime,
@@ -406,10 +409,11 @@ static int unpack_pjob( uint8 *buf, int buflen, struct printjob *pjob )
                                pjob->clientmachine,
                                pjob->queuename);
 
-       if ( len == -1 )
+       if (len == -1) {
                return -1;
+       }
 
-        used = unpack_devicemode(NULL, buf+len, buflen-len, &pjob->devmode);
+        used = unpack_devicemode(mem_ctx, buf+len, buflen-len, &pjob->devmode);
         if (used == -1) {
                return -1;
         }
@@ -417,6 +421,7 @@ static int unpack_pjob( uint8 *buf, int buflen, struct printjob *pjob )
        len += used;
 
        pjob->pid = pjpid;
+       pjob->jobid = pjjobid;
        pjob->sysjob = pjsysjob;
        pjob->fd = pjfd;
        pjob->starttime = pjstarttime;
@@ -434,9 +439,11 @@ static int unpack_pjob( uint8 *buf, int buflen, struct printjob *pjob )
  Useful function to find a print job in the database.
 ****************************************************************************/
 
-static struct printjob *print_job_find(const char *sharename, uint32 jobid)
+static struct printjob *print_job_find(TALLOC_CTX *mem_ctx,
+                                      const char *sharename,
+                                      uint32 jobid)
 {
-       static struct printjob  pjob;
+       struct printjob         *pjob;
        uint32_t tmp;
        TDB_DATA                ret;
        struct tdb_print_db     *pdb = get_print_db_byname(sharename);
@@ -452,26 +459,30 @@ static struct printjob *print_job_find(const char *sharename, uint32 jobid)
        release_print_db(pdb);
 
        if (!ret.dptr) {
-               DEBUG(10,("print_job_find: failed to find jobid %u.\n", (unsigned int)jobid ));
+               DEBUG(10, ("print_job_find: failed to find jobid %u.\n",
+                          jobid));
                return NULL;
        }
 
-       talloc_free(pjob.devmode);
-
-       ZERO_STRUCT( pjob );
-
-       if ( unpack_pjob( ret.dptr, ret.dsize, &pjob ) == -1 ) {
-               DEBUG(10,("print_job_find: failed to unpack jobid %u.\n", (unsigned int)jobid ));
-               SAFE_FREE(ret.dptr);
-               return NULL;
+       pjob = talloc_zero(mem_ctx, struct printjob);
+       if (pjob == NULL) {
+               goto err_out;
        }
 
-       SAFE_FREE(ret.dptr);
+       if (unpack_pjob(mem_ctx, ret.dptr, ret.dsize, pjob) == -1) {
+               DEBUG(10, ("failed to unpack jobid %u.\n", jobid));
+               talloc_free(pjob);
+               pjob = NULL;
+               goto err_out;
+       }
 
        DEBUG(10,("print_job_find: returning system job %d for jobid %u.\n",
-                       (int)pjob.sysjob, (unsigned int)jobid ));
+                 pjob->sysjob, jobid));
+       SMB_ASSERT(pjob->jobid == jobid);
 
-       return &pjob;
+err_out:
+       SAFE_FREE(ret.dptr);
+       return pjob;
 }
 
 /* Convert a unix jobid to a smb jobid */
@@ -496,15 +507,25 @@ static int unixjob_traverse_fn(TDB_CONTEXT *the_tdb, TDB_DATA key,
                return 0;
 
        if (state->sysjob == pjob->sysjob) {
-               uint32 jobid = IVAL(key.dptr,0);
-
-               state->sysjob_to_jobid_value = jobid;
+               state->sysjob_to_jobid_value = pjob->jobid;
                return 1;
        }
 
        return 0;
 }
 
+static uint32 sysjob_to_jobid_pdb(struct tdb_print_db *pdb, int sysjob)
+{
+       struct unixjob_traverse_state state;
+
+       state.sysjob = sysjob;
+       state.sysjob_to_jobid_value = (uint32)-1;
+
+       tdb_traverse(pdb->tdb, unixjob_traverse_fn, &state);
+
+       return state.sysjob_to_jobid_value;
+}
+
 /****************************************************************************
  This is a *horribly expensive call as we have to iterate through all the
  current printer tdb's. Don't do this often ! JRA.
@@ -744,8 +765,9 @@ static bool pjob_store(struct tevent_context *ev,
        do {
                len = 0;
                buflen = newlen;
-               len += tdb_pack(buf+len, buflen-len, "dddddddddfffff",
+               len += tdb_pack(buf+len, buflen-len, "ddddddddddfffff",
                                (uint32)pjob->pid,
+                               (uint32)pjob->jobid,
                                (uint32)pjob->sysjob,
                                (uint32)pjob->fd,
                                (uint32)pjob->starttime,
@@ -782,37 +804,39 @@ static bool pjob_store(struct tevent_context *ev,
 
        /* Send notify updates for what has changed */
 
-       if ( ret ) {
+       if (ret) {
                bool changed = false;
                struct printjob old_pjob;
 
-               if ( old_data.dsize )
-               {
-                       if ( unpack_pjob( old_data.dptr, old_data.dsize, &old_pjob ) != -1 )
-                       {
-                               pjob_store_notify(server_event_context(),
+               if (old_data.dsize) {
+                       TALLOC_CTX *tmp_ctx = talloc_new(ev);
+                       if (tmp_ctx == NULL)
+                               goto done;
+
+                       len = unpack_pjob(tmp_ctx, old_data.dptr,
+                                         old_data.dsize, &old_pjob);
+                       if (len != -1 ) {
+                               pjob_store_notify(ev,
                                                  msg_ctx,
                                                  sharename, jobid, &old_pjob,
                                                  pjob,
                                                  &changed);
-                               talloc_free(old_pjob.devmode);
-
                                if (changed) {
                                        add_to_jobs_changed(pdb, jobid);
                                }
                        }
+                       talloc_free(tmp_ctx);
 
-               }
-               else {
+               } else {
                        /* new job */
-                       pjob_store_notify(server_event_context(), msg_ctx,
+                       pjob_store_notify(ev, msg_ctx,
                                          sharename, jobid, NULL, pjob,
                                          &changed);
                }
        }
 
-       release_print_db(pdb);
 done:
+       release_print_db(pdb);
        SAFE_FREE( old_data.dptr );
        SAFE_FREE( buf );
 
@@ -831,19 +855,21 @@ static void pjob_delete(struct tevent_context *ev,
        struct printjob *pjob;
        uint32 job_status = 0;
        struct tdb_print_db *pdb;
-
-       pdb = get_print_db_byname( sharename );
-
-       if (!pdb)
+       TALLOC_CTX *tmp_ctx = talloc_new(ev);
+       if (tmp_ctx == NULL) {
                return;
+       }
 
-       pjob = print_job_find( sharename, jobid );
+       pdb = get_print_db_byname(sharename);
+       if (!pdb) {
+               goto err_out;
+       }
 
+       pjob = print_job_find(tmp_ctx, sharename, jobid);
        if (!pjob) {
-               DEBUG(5, ("pjob_delete: we were asked to delete nonexistent job %u\n",
-                                       (unsigned int)jobid));
-               release_print_db(pdb);
-               return;
+               DEBUG(5, ("we were asked to delete nonexistent job %u\n",
+                         jobid));
+               goto err_release;
        }
 
        /* We must cycle through JOB_STATUS_DELETING and
@@ -857,8 +883,11 @@ static void pjob_delete(struct tevent_context *ev,
 
        tdb_delete(pdb->tdb, print_key(jobid, &tmp));
        remove_from_jobs_added(sharename, jobid);
-       release_print_db( pdb );
        rap_jobid_delete(sharename, jobid);
+err_release:
+       release_print_db(pdb);
+err_out:
+       talloc_free(tmp_ctx);
 }
 
 /****************************************************************************
@@ -871,18 +900,24 @@ static void print_unix_job(struct tevent_context *ev,
                           uint32 jobid)
 {
        struct printjob pj, *old_pj;
+       TALLOC_CTX *tmp_ctx = talloc_new(ev);
+       if (tmp_ctx == NULL) {
+               return;
+       }
 
-       if (jobid == (uint32)-1)
-               jobid = q->job + UNIX_JOB_START;
+       if (jobid == (uint32)-1) {
+               jobid = q->sysjob + UNIX_JOB_START;
+       }
 
        /* Preserve the timestamp on an existing unix print job */
 
-       old_pj = print_job_find(sharename, jobid);
+       old_pj = print_job_find(tmp_ctx, sharename, jobid);
 
        ZERO_STRUCT(pj);
 
        pj.pid = (pid_t)-1;
-       pj.sysjob = q->job;
+       pj.jobid = jobid;
+       pj.sysjob = q->sysjob;
        pj.fd = -1;
        pj.starttime = old_pj ? old_pj->starttime : q->time;
        pj.status = q->status;
@@ -900,6 +935,7 @@ static void print_unix_job(struct tevent_context *ev,
        fstrcpy(pj.queuename, old_pj ? old_pj->queuename : sharename );
 
        pjob_store(ev, msg_ctx, sharename, jobid, &pj);
+       talloc_free(tmp_ctx);
 }
 
 
@@ -912,6 +948,7 @@ struct traverse_struct {
        struct printif *print_if;
        struct tevent_context *ev;
        struct messaging_context *msg_ctx;
+       TALLOC_CTX *mem_ctx;
 };
 
 /****************************************************************************
@@ -928,19 +965,17 @@ static int traverse_fn_delete(TDB_CONTEXT *t, TDB_DATA key, TDB_DATA data, void
        if (  key.dsize != sizeof(jobid) )
                return 0;
 
-       jobid = IVAL(key.dptr, 0);
-       if ( unpack_pjob( data.dptr, data.dsize, &pjob ) == -1 )
+       if (unpack_pjob(ts->mem_ctx, data.dptr, data.dsize, &pjob) == -1)
                return 0;
        talloc_free(pjob.devmode);
-
+       jobid = pjob.jobid;
 
        if (!pjob.smbjob) {
                /* remove a unix job if it isn't in the system queue any more */
-
                for (i=0;i<ts->qcount;i++) {
-                       uint32 u_jobid = (ts->queue[i].job + UNIX_JOB_START);
-                       if (jobid == u_jobid)
+                       if (ts->queue[i].sysjob == pjob.sysjob) {
                                break;
+                       }
                }
                if (i == ts->qcount) {
                        DEBUG(10,("traverse_fn_delete: pjob %u deleted due to !smbjob\n",
@@ -971,16 +1006,12 @@ static int traverse_fn_delete(TDB_CONTEXT *t, TDB_DATA key, TDB_DATA data, void
 
        /* this check only makes sense for jobs submitted from Windows clients */
 
-       if ( pjob.smbjob ) {
+       if (pjob.smbjob) {
                for (i=0;i<ts->qcount;i++) {
-                       uint32 curr_jobid;
-
                        if ( pjob.status == LPQ_DELETED )
                                continue;
 
-                       curr_jobid = print_parse_jobid(ts->queue[i].fs_file);
-
-                       if (jobid == curr_jobid) {
+                       if (ts->queue[i].sysjob == pjob.sysjob) {
 
                                /* try to clean up any jobs that need to be deleted */
 
@@ -1035,11 +1066,8 @@ static int traverse_fn_delete(TDB_CONTEXT *t, TDB_DATA key, TDB_DATA data, void
                return 0;
        }
 
-       /* Save the pjob attributes we will store.
-          FIXME!!! This is the only place where queue->job
-          represents the SMB jobid      --jerry */
-
-       ts->queue[i].job = jobid;
+       /* Save the pjob attributes we will store. */
+       ts->queue[i].sysjob = pjob.sysjob;
        ts->queue[i].size = pjob.size;
        ts->queue[i].page_count = pjob.page_count;
        ts->queue[i].status = pjob.status;
@@ -1111,7 +1139,7 @@ static void set_updating_pid(const fstring sharename, bool updating)
        fstring keystr;
        TDB_DATA key;
        TDB_DATA data;
-       pid_t updating_pid = sys_getpid();
+       pid_t updating_pid = getpid();
        uint8 buffer[4];
 
        struct tdb_print_db *pdb = get_print_db_byname(sharename);
@@ -1190,7 +1218,7 @@ static void store_queue_struct(struct tdb_print_db *pdb, struct traverse_struct
 
                qcount++;
                data.dsize += tdb_pack(NULL, 0, "ddddddff",
-                               (uint32)queue[i].job,
+                               (uint32)queue[i].sysjob,
                                (uint32)queue[i].size,
                                (uint32)queue[i].page_count,
                                (uint32)queue[i].status,
@@ -1210,7 +1238,7 @@ static void store_queue_struct(struct tdb_print_db *pdb, struct traverse_struct
                        continue;
 
                len += tdb_pack(data.dptr + len, data.dsize - len, "ddddddff",
-                               (uint32)queue[i].job,
+                               (uint32)queue[i].sysjob,
                                (uint32)queue[i].size,
                                (uint32)queue[i].page_count,
                                (uint32)queue[i].status,
@@ -1324,11 +1352,11 @@ done:
  main work for updating the lpq cache for a printer queue
 ****************************************************************************/
 
-static void print_queue_update_internal( struct tevent_context *ev,
-                                        struct messaging_context *msg_ctx,
-                                        const char *sharename,
-                                         struct printif *current_printif,
-                                         char *lpq_command, char *lprm_command )
+static void print_queue_update_internal(struct tevent_context *ev,
+                                       struct messaging_context *msg_ctx,
+                                       const char *sharename,
+                                        struct printif *current_printif,
+                                        char *lpq_command, char *lprm_command)
 {
        int i, qcount;
        print_queue_struct *queue = NULL;
@@ -1340,8 +1368,9 @@ static void print_queue_update_internal( struct tevent_context *ev,
        TDB_DATA jcdata;
        fstring keystr, cachestr;
        struct tdb_print_db *pdb = get_print_db_byname(sharename);
+       TALLOC_CTX *tmp_ctx = talloc_new(ev);
 
-       if (!pdb) {
+       if ((pdb == NULL) || (tmp_ctx == NULL)) {
                return;
        }
 
@@ -1382,12 +1411,10 @@ static void print_queue_update_internal( struct tevent_context *ev,
 
          fill in any system job numbers as we go
        */
-
        jcdata = get_jobs_added_data(pdb);
 
        for (i=0; i<qcount; i++) {
-               uint32 jobid = print_parse_jobid(queue[i].fs_file);
-
+               uint32 jobid = sysjob_to_jobid_pdb(pdb, queue[i].sysjob);
                if (jobid == (uint32)-1) {
                        /* assume its a unix print job */
                        print_unix_job(ev, msg_ctx,
@@ -1396,18 +1423,18 @@ static void print_queue_update_internal( struct tevent_context *ev,
                }
 
                /* we have an active SMB print job - update its status */
-               pjob = print_job_find(sharename, jobid);
+               pjob = print_job_find(tmp_ctx, sharename, jobid);
                if (!pjob) {
                        /* err, somethings wrong. Probably smbd was restarted
                           with jobs in the queue. All we can do is treat them
                           like unix jobs. Pity. */
+                       DEBUG(1, ("queued print job %d not found in jobs list, "
+                                 "assuming unix job\n", jobid));
                        print_unix_job(ev, msg_ctx,
                                       sharename, &queue[i], jobid);
                        continue;
                }
 
-               pjob->sysjob = queue[i].job;
-
                /* don't reset the status on jobs to be deleted */
 
                if ( pjob->status != LPQ_DELETING )
@@ -1432,6 +1459,7 @@ static void print_queue_update_internal( struct tevent_context *ev,
        tstruct.print_if = current_printif;
        tstruct.ev = ev;
        tstruct.msg_ctx = msg_ctx;
+       tstruct.mem_ctx = tmp_ctx;
 
        tdb_traverse(pdb->tdb, traverse_fn_delete, (void *)&tstruct);
 
@@ -1439,6 +1467,7 @@ static void print_queue_update_internal( struct tevent_context *ev,
        store_queue_struct(pdb, &tstruct);
 
        SAFE_FREE(tstruct.queue);
+       talloc_free(tmp_ctx);
 
        DEBUG(10,("print_queue_update_internal: printer %s INFO/total_jobs = %d\n",
                                sharename, tstruct.total_jobs ));
@@ -1609,6 +1638,8 @@ void print_queue_receive(struct messaging_context *msg,
 update the internal database from the system print queue for a queue
 ****************************************************************************/
 
+extern pid_t background_lpq_updater_pid;
+
 static void print_queue_update(struct messaging_context *msg_ctx,
                               int snum, bool force)
 {
@@ -1750,7 +1781,7 @@ bool print_notify_register_pid(int snum)
        struct tdb_print_db *pdb = NULL;
        TDB_CONTEXT *tdb = NULL;
        const char *printername;
-       uint32 mypid = (uint32)sys_getpid();
+       uint32_t mypid = (uint32_t)getpid();
        bool ret = False;
        size_t i;
 
@@ -1841,7 +1872,7 @@ bool print_notify_deregister_pid(int snum)
        struct tdb_print_db *pdb = NULL;
        TDB_CONTEXT *tdb = NULL;
        const char *printername;
-       uint32 mypid = (uint32)sys_getpid();
+       uint32_t mypid = (uint32_t)getpid();
        size_t i;
        bool ret = False;
 
@@ -1945,8 +1976,8 @@ bool print_job_exists(const char* sharename, uint32 jobid)
 
 char *print_job_fname(const char* sharename, uint32 jobid)
 {
-       struct printjob *pjob = print_job_find(sharename, jobid);
-       if (!pjob || pjob->spooled || pjob->pid != sys_getpid())
+       struct printjob *pjob = print_job_find(NULL, sharename, jobid);
+       if (!pjob || pjob->spooled || pjob->pid != getpid())
                return NULL;
        return pjob->filename;
 }
@@ -1958,12 +1989,14 @@ char *print_job_fname(const char* sharename, uint32 jobid)
  has not been spooled.
 ****************************************************************************/
 
-struct spoolss_DeviceMode *print_job_devmode(const char* sharename, uint32 jobid)
+struct spoolss_DeviceMode *print_job_devmode(TALLOC_CTX *mem_ctx,
+                                            const char *sharename,
+                                            uint32 jobid)
 {
-       struct printjob *pjob = print_job_find(sharename, jobid);
-
-       if ( !pjob )
+       struct printjob *pjob = print_job_find(mem_ctx, sharename, jobid);
+       if (pjob == NULL) {
                return NULL;
+       }
 
        return pjob->devmode;
 }
@@ -1977,13 +2010,23 @@ bool print_job_set_name(struct tevent_context *ev,
                        const char *sharename, uint32 jobid, const char *name)
 {
        struct printjob *pjob;
+       bool ret;
+       TALLOC_CTX *tmp_ctx = talloc_new(ev);
+       if (tmp_ctx == NULL) {
+               return false;
+       }
 
-       pjob = print_job_find(sharename, jobid);
-       if (!pjob || pjob->pid != sys_getpid())
-               return False;
+       pjob = print_job_find(tmp_ctx, sharename, jobid);
+       if (!pjob || pjob->pid != getpid()) {
+               ret = false;
+               goto err_out;
+       }
 
        fstrcpy(pjob->jobname, name);
-       return pjob_store(ev, msg_ctx, sharename, jobid, pjob);
+       ret = pjob_store(ev, msg_ctx, sharename, jobid, pjob);
+err_out:
+       talloc_free(tmp_ctx);
+       return ret;
 }
 
 /****************************************************************************
@@ -1994,17 +2037,12 @@ bool print_job_get_name(TALLOC_CTX *mem_ctx, const char *sharename, uint32_t job
 {
        struct printjob *pjob;
 
-       pjob = print_job_find(sharename, jobid);
-       if (!pjob || pjob->pid != sys_getpid()) {
-               return false;
-       }
-
-       *name = talloc_strdup(mem_ctx, pjob->jobname);
-       if (!*name) {
+       pjob = print_job_find(mem_ctx, sharename, jobid);
+       if (!pjob || pjob->pid != getpid()) {
                return false;
        }
 
-       return true;
+       return pjob->jobname;
 }
 
 
@@ -2076,19 +2114,29 @@ static bool print_job_delete1(struct tevent_context *ev,
                              int snum, uint32 jobid)
 {
        const char* sharename = lp_const_servicename(snum);
-       struct printjob *pjob = print_job_find(sharename, jobid);
+       struct printjob *pjob;
        int result = 0;
        struct printif *current_printif = get_printer_fns( snum );
+       bool ret;
+       TALLOC_CTX *tmp_ctx = talloc_new(ev);
+       if (tmp_ctx == NULL) {
+               return false;
+       }
 
-       if (!pjob)
-               return False;
+       pjob = print_job_find(tmp_ctx, sharename, jobid);
+       if (!pjob) {
+               ret = false;
+               goto err_out;
+       }
 
        /*
         * If already deleting just return.
         */
 
-       if (pjob->status == LPQ_DELETING)
-               return True;
+       if (pjob->status == LPQ_DELETING) {
+               ret = true;
+               goto err_out;
+       }
 
        /* Hrm - we need to be able to cope with deleting a job before it
           has reached the spooler.  Just mark it as LPQ_DELETING and
@@ -2118,8 +2166,10 @@ static bool print_job_delete1(struct tevent_context *ev,
                        struct tdb_print_db *pdb = get_print_db_byname(sharename);
                        int njobs = 1;
 
-                       if (!pdb)
-                               return False;
+                       if (!pdb) {
+                               ret = false;
+                               goto err_out;
+                       }
                        pjob_delete(ev, msg_ctx, sharename, jobid);
                        /* Ensure we keep a rough count of the number of total jobs... */
                        tdb_change_int32_atomic(pdb->tdb, "INFO/total_jobs", &njobs, -1);
@@ -2129,7 +2179,10 @@ static bool print_job_delete1(struct tevent_context *ev,
 
        remove_from_jobs_added( sharename, jobid );
 
-       return (result == 0);
+       ret = (result == 0);
+err_out:
+       talloc_free(tmp_ctx);
+       return ret;
 }
 
 /****************************************************************************
@@ -2140,12 +2193,23 @@ static bool is_owner(const struct auth_session_info *server_info,
                     const char *servicename,
                     uint32 jobid)
 {
-       struct printjob *pjob = print_job_find(servicename, jobid);
+       struct printjob *pjob;
+       bool ret;
+       TALLOC_CTX *tmp_ctx = talloc_new(server_info);
+       if (tmp_ctx == NULL) {
+               return false;
+       }
 
-       if (!pjob || !server_info)
-               return False;
+       pjob = print_job_find(tmp_ctx, servicename, jobid);
+       if (!pjob || !server_info) {
+               ret = false;
+               goto err_out;
+       }
 
-       return strequal(pjob->user, server_info->unix_info->sanitized_username);
+       ret = strequal(pjob->user, server_info->unix_info->sanitized_username);
+err_out:
+       talloc_free(tmp_ctx);
+       return ret;
 }
 
 /****************************************************************************
@@ -2159,7 +2223,11 @@ WERROR print_job_delete(const struct auth_session_info *server_info,
        const char* sharename = lp_const_servicename(snum);
        struct printjob *pjob;
        bool    owner;
-       char    *fname;
+       WERROR werr;
+       TALLOC_CTX *tmp_ctx = talloc_new(msg_ctx);
+       if (tmp_ctx == NULL) {
+               return WERR_NOT_ENOUGH_MEMORY;
+       }
 
        owner = is_owner(server_info, lp_const_servicename(snum), jobid);
 
@@ -2179,7 +2247,8 @@ pause, or resume print job. User name: %s. Printer name: %s.",
                              lp_printername(snum) );
                /* END_ADMIN_LOG */
 
-               return WERR_ACCESS_DENIED;
+               werr = WERR_ACCESS_DENIED;
+               goto err_out;
        }
 
        /*
@@ -2189,18 +2258,20 @@ pause, or resume print job. User name: %s. Printer name: %s.",
         * spool file & return.
         */
 
-       fname = print_job_fname(sharename, jobid);
-       if (fname != NULL) {
-               /* remove the spool file */
-               DEBUG(10, ("print_job_delete: "
-                          "Removing spool file [%s]\n", fname));
-               if (unlink(fname) == -1) {
-                       return map_werror_from_unix(errno);
+       pjob = print_job_find(tmp_ctx, sharename, jobid);
+       if (!pjob || pjob->spooled || pjob->pid != getpid()) {
+               DEBUG(10, ("Skipping spool file removal for job %u\n", jobid));
+       } else {
+               DEBUG(10, ("Removing spool file [%s]\n", pjob->filename));
+               if (unlink(pjob->filename) == -1) {
+                       werr = map_werror_from_unix(errno);
+                       goto err_out;
                }
        }
 
        if (!print_job_delete1(server_event_context(), msg_ctx, snum, jobid)) {
-               return WERR_ACCESS_DENIED;
+               werr = WERR_ACCESS_DENIED;
+               goto err_out;
        }
 
        /* force update the database and say the delete failed if the
@@ -2208,39 +2279,49 @@ pause, or resume print job. User name: %s. Printer name: %s.",
 
        print_queue_update(msg_ctx, snum, True);
 
-       pjob = print_job_find(sharename, jobid);
+       pjob = print_job_find(tmp_ctx, sharename, jobid);
        if (pjob && (pjob->status != LPQ_DELETING)) {
-               return WERR_ACCESS_DENIED;
+               werr = WERR_ACCESS_DENIED;
+               goto err_out;
        }
+       werr = WERR_PRINTER_HAS_JOBS_QUEUED;
 
-       return WERR_PRINTER_HAS_JOBS_QUEUED;
+err_out:
+       talloc_free(tmp_ctx);
+       return werr;
 }
 
 /****************************************************************************
  Pause a job.
 ****************************************************************************/
 
-bool print_job_pause(const struct auth_session_info *server_info,
+WERROR print_job_pause(const struct auth_session_info *server_info,
                     struct messaging_context *msg_ctx,
-                    int snum, uint32 jobid, WERROR *errcode)
+                    int snum, uint32 jobid)
 {
        const char* sharename = lp_const_servicename(snum);
        struct printjob *pjob;
        int ret = -1;
        struct printif *current_printif = get_printer_fns( snum );
+       WERROR werr;
+       TALLOC_CTX *tmp_ctx = talloc_new(msg_ctx);
+       if (tmp_ctx == NULL) {
+               return WERR_NOT_ENOUGH_MEMORY;
+       }
 
-       pjob = print_job_find(sharename, jobid);
-
+       pjob = print_job_find(tmp_ctx, sharename, jobid);
        if (!pjob || !server_info) {
                DEBUG(10, ("print_job_pause: no pjob or user for jobid %u\n",
                        (unsigned int)jobid ));
-               return False;
+               werr = WERR_INVALID_PARAM;
+               goto err_out;
        }
 
        if (!pjob->spooled || pjob->sysjob == -1) {
                DEBUG(10, ("print_job_pause: not spooled or bad sysjob = %d for jobid %u\n",
                        (int)pjob->sysjob, (unsigned int)jobid ));
-               return False;
+               werr = WERR_INVALID_PARAM;
+               goto err_out;
        }
 
        if (!is_owner(server_info, lp_const_servicename(snum), jobid) &&
@@ -2256,16 +2337,16 @@ pause, or resume print job. User name: %s. Printer name: %s.",
                              lp_printername(snum) );
                /* END_ADMIN_LOG */
 
-               *errcode = WERR_ACCESS_DENIED;
-               return False;
+               werr = WERR_ACCESS_DENIED;
+               goto err_out;
        }
 
        /* need to pause the spooled entry */
        ret = (*(current_printif->job_pause))(snum, pjob);
 
        if (ret != 0) {
-               *errcode = WERR_INVALID_PARAM;
-               return False;
+               werr = WERR_INVALID_PARAM;
+               goto err_out;
        }
 
        /* force update the database */
@@ -2277,42 +2358,48 @@ pause, or resume print job. User name: %s. Printer name: %s.",
                          JOB_STATUS_PAUSED);
 
        /* how do we tell if this succeeded? */
-
-       return True;
+       werr = WERR_OK;
+err_out:
+       talloc_free(tmp_ctx);
+       return werr;
 }
 
 /****************************************************************************
  Resume a job.
 ****************************************************************************/
 
-bool print_job_resume(const struct auth_session_info *server_info,
+WERROR print_job_resume(const struct auth_session_info *server_info,
                      struct messaging_context *msg_ctx,
-                     int snum, uint32 jobid, WERROR *errcode)
+                     int snum, uint32 jobid)
 {
        const char *sharename = lp_const_servicename(snum);
        struct printjob *pjob;
        int ret;
        struct printif *current_printif = get_printer_fns( snum );
+       WERROR werr;
+       TALLOC_CTX *tmp_ctx = talloc_new(msg_ctx);
+       if (tmp_ctx == NULL)
+               return WERR_NOT_ENOUGH_MEMORY;
 
-       pjob = print_job_find(sharename, jobid);
-
+       pjob = print_job_find(tmp_ctx, sharename, jobid);
        if (!pjob || !server_info) {
                DEBUG(10, ("print_job_resume: no pjob or user for jobid %u\n",
                        (unsigned int)jobid ));
-               return False;
+               werr = WERR_INVALID_PARAM;
+               goto err_out;
        }
 
        if (!pjob->spooled || pjob->sysjob == -1) {
                DEBUG(10, ("print_job_resume: not spooled or bad sysjob = %d for jobid %u\n",
                        (int)pjob->sysjob, (unsigned int)jobid ));
-               return False;
+               werr = WERR_INVALID_PARAM;
+               goto err_out;
        }
 
        if (!is_owner(server_info, lp_const_servicename(snum), jobid) &&
            !print_access_check(server_info, msg_ctx, snum,
                                JOB_ACCESS_ADMINISTER)) {
                DEBUG(3, ("resume denied by security descriptor\n"));
-               *errcode = WERR_ACCESS_DENIED;
 
                /* BEGIN_ADMIN_LOG */
                sys_adminlog( LOG_ERR,
@@ -2321,14 +2408,15 @@ pause, or resume print job. User name: %s. Printer name: %s.",
                              uidtoname(server_info->unix_token->uid),
                              lp_printername(snum) );
                /* END_ADMIN_LOG */
-               return False;
+               werr = WERR_ACCESS_DENIED;
+               goto err_out;
        }
 
        ret = (*(current_printif->job_resume))(snum, pjob);
 
        if (ret != 0) {
-               *errcode = WERR_INVALID_PARAM;
-               return False;
+               werr = WERR_INVALID_PARAM;
+               goto err_out;
        }
 
        /* force update the database */
@@ -2339,7 +2427,10 @@ pause, or resume print job. User name: %s. Printer name: %s.",
        notify_job_status(server_event_context(), msg_ctx, sharename, jobid,
                          JOB_STATUS_QUEUED);
 
-       return True;
+       werr = WERR_OK;
+err_out:
+       talloc_free(tmp_ctx);
+       return werr;
 }
 
 /****************************************************************************
@@ -2353,26 +2444,36 @@ ssize_t print_job_write(struct tevent_context *ev,
        const char* sharename = lp_const_servicename(snum);
        ssize_t return_code;
        struct printjob *pjob;
+       TALLOC_CTX *tmp_ctx = talloc_new(ev);
+       if (tmp_ctx == NULL) {
+               return -1;
+       }
 
-       pjob = print_job_find(sharename, jobid);
+       pjob = print_job_find(tmp_ctx, sharename, jobid);
+       if (!pjob) {
+               return_code = -1;
+               goto err_out;
+       }
 
-       if (!pjob)
-               return -1;
        /* don't allow another process to get this info - it is meaningless */
-       if (pjob->pid != sys_getpid())
-               return -1;
+       if (pjob->pid != getpid()) {
+               return_code = -1;
+               goto err_out;
+       }
 
        /* if SMBD is spooling this can't be allowed */
        if (pjob->status == PJOB_SMBD_SPOOLING) {
-               return -1;
+               return_code = -1;
+               goto err_out;
        }
 
        return_code = write_data(pjob->fd, buf, size);
-
-       if (return_code>0) {
+       if (return_code > 0) {
                pjob->size += size;
                pjob_store(ev, msg_ctx, sharename, jobid, pjob);
        }
+err_out:
+       talloc_free(tmp_ctx);
        return return_code;
 }
 
@@ -2718,7 +2819,8 @@ WERROR print_job_start(const struct auth_session_info *server_info,
 
        ZERO_STRUCT(pjob);
 
-       pjob.pid = sys_getpid();
+       pjob.pid = getpid();
+       pjob.jobid = jobid;
        pjob.sysjob = -1;
        pjob.fd = -1;
        pjob.starttime = time(NULL);
@@ -2737,9 +2839,7 @@ WERROR print_job_start(const struct auth_session_info *server_info,
                              path, server_info->unix_token->gid,
                              server_info->unix_info->sanitized_username,
                              server_info->info->domain_name,
-                             pjob.user, sizeof(pjob.user)-1);
-       /* ensure NULL termination */
-       pjob.user[sizeof(pjob.user)-1] = '\0';
+                             pjob.user, sizeof(pjob.user));
 
        fstrcpy(pjob.queuename, lp_const_servicename(snum));
 
@@ -2783,16 +2883,24 @@ void print_job_endpage(struct messaging_context *msg_ctx,
 {
        const char* sharename = lp_const_servicename(snum);
        struct printjob *pjob;
-
-       pjob = print_job_find(sharename, jobid);
-       if (!pjob)
+       TALLOC_CTX *tmp_ctx = talloc_new(msg_ctx);
+       if (tmp_ctx == NULL) {
                return;
+       }
+
+       pjob = print_job_find(tmp_ctx, sharename, jobid);
+       if (!pjob) {
+               goto err_out;
+       }
        /* don't allow another process to get this info - it is meaningless */
-       if (pjob->pid != sys_getpid())
-               return;
+       if (pjob->pid != getpid()) {
+               goto err_out;
+       }
 
        pjob->page_count++;
        pjob_store(server_event_context(), msg_ctx, sharename, jobid, pjob);
+err_out:
+       talloc_free(tmp_ctx);
 }
 
 /****************************************************************************
@@ -2808,17 +2916,22 @@ NTSTATUS print_job_end(struct messaging_context *msg_ctx, int snum,
        struct printjob *pjob;
        int ret;
        SMB_STRUCT_STAT sbuf;
-       struct printif *current_printif = get_printer_fns( snum );
+       struct printif *current_printif = get_printer_fns(snum);
        NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
+       TALLOC_CTX *tmp_ctx = talloc_new(msg_ctx);
+       if (tmp_ctx == NULL) {
+               return NT_STATUS_NO_MEMORY;
+       }
 
-       pjob = print_job_find(sharename, jobid);
-
+       pjob = print_job_find(tmp_ctx, sharename, jobid);
        if (!pjob) {
-               return NT_STATUS_PRINT_CANCELLED;
+               status = NT_STATUS_PRINT_CANCELLED;
+               goto err_out;
        }
 
-       if (pjob->spooled || pjob->pid != sys_getpid()) {
-               return NT_STATUS_ACCESS_DENIED;
+       if (pjob->spooled || pjob->pid != getpid()) {
+               status = NT_STATUS_ACCESS_DENIED;
+               goto err_out;
        }
 
        if (close_type == NORMAL_CLOSE || close_type == SHUTDOWN_CLOSE) {
@@ -2898,6 +3011,8 @@ fail:
        pjob->fd = -1;
        unlink(pjob->filename);
        pjob_delete(server_event_context(), msg_ctx, sharename, jobid);
+err_out:
+       talloc_free(tmp_ctx);
        return status;
 }
 
@@ -2920,6 +3035,10 @@ static bool get_stored_queue_info(struct messaging_context *msg_ctx,
        int max_reported_jobs = lp_max_reported_jobs(snum);
        bool ret = False;
        const char* sharename = lp_servicename(snum);
+       TALLOC_CTX *tmp_ctx = talloc_new(msg_ctx);
+       if (tmp_ctx == NULL) {
+               return false;
+       }
 
        /* make sure the database is up to date */
        if (print_cache_expired(lp_const_servicename(snum), True))
@@ -2969,7 +3088,7 @@ static bool get_stored_queue_info(struct messaging_context *msg_ctx,
                                &qtime,
                                queue[i].fs_user,
                                queue[i].fs_file);
-               queue[i].job = qjob;
+               queue[i].sysjob = qjob;
                queue[i].size = qsize;
                queue[i].page_count = qpage_count;
                queue[i].status = qstatus;
@@ -2986,14 +3105,14 @@ static bool get_stored_queue_info(struct messaging_context *msg_ctx,
 
                jobid = IVAL(cgdata.dptr, i*4);
                DEBUG(5,("get_stored_queue_info: added job = %u\n", (unsigned int)jobid));
-               pjob = print_job_find(lp_const_servicename(snum), jobid);
+               pjob = print_job_find(tmp_ctx, lp_const_servicename(snum), jobid);
                if (!pjob) {
                        DEBUG(5,("get_stored_queue_info: failed to find added job = %u\n", (unsigned int)jobid));
                        remove_from_jobs_added(sharename, jobid);
                        continue;
                }
 
-               queue[total_count].job = jobid;
+               queue[total_count].sysjob = jobid;
                queue[total_count].size = pjob->size;
                queue[total_count].page_count = pjob->page_count;
                queue[total_count].status = pjob->status;
@@ -3002,6 +3121,7 @@ static bool get_stored_queue_info(struct messaging_context *msg_ctx,
                fstrcpy(queue[total_count].fs_user, pjob->user);
                fstrcpy(queue[total_count].fs_file, pjob->jobname);
                total_count++;
+               talloc_free(pjob);
        }
 
        /* Update the changed jobids. */
@@ -3011,7 +3131,7 @@ static bool get_stored_queue_info(struct messaging_context *msg_ctx,
                bool found = false;
 
                for (j = 0; j < total_count; j++) {
-                       if (queue[j].job == jobid) {
+                       if (queue[j].sysjob == jobid) {
                                found = true;
                                break;
                        }
@@ -3023,7 +3143,7 @@ static bool get_stored_queue_info(struct messaging_context *msg_ctx,
                        DEBUG(5,("get_stored_queue_info: changed job: %u\n",
                                 (unsigned int) jobid));
 
-                       pjob = print_job_find(sharename, jobid);
+                       pjob = print_job_find(tmp_ctx, sharename, jobid);
                        if (pjob == NULL) {
                                DEBUG(5,("get_stored_queue_info: failed to find "
                                         "changed job = %u\n",
@@ -3032,7 +3152,7 @@ static bool get_stored_queue_info(struct messaging_context *msg_ctx,
                                continue;
                        }
 
-                       queue[j].job = jobid;
+                       queue[j].sysjob = jobid;
                        queue[j].size = pjob->size;
                        queue[j].page_count = pjob->page_count;
                        queue[j].status = pjob->status;
@@ -3040,6 +3160,7 @@ static bool get_stored_queue_info(struct messaging_context *msg_ctx,
                        queue[j].time = pjob->starttime;
                        fstrcpy(queue[j].fs_user, pjob->user);
                        fstrcpy(queue[j].fs_file, pjob->jobname);
+                       talloc_free(pjob);
 
                        DEBUG(5,("get_stored_queue_info: updated queue[%u], jobid: %u, jobname: %s\n",
                                 (unsigned int) j, (unsigned int) jobid, pjob->jobname));
@@ -3067,6 +3188,7 @@ static bool get_stored_queue_info(struct messaging_context *msg_ctx,
 
        SAFE_FREE(data.dptr);
        SAFE_FREE(cgdata.dptr);
+       talloc_free(tmp_ctx);
        return ret;
 }
 
@@ -3234,11 +3356,11 @@ WERROR print_queue_purge(const struct auth_session_info *server_info,
 
        for (i=0;i<njobs;i++) {
                bool owner = is_owner(server_info, lp_const_servicename(snum),
-                                     queue[i].job);
+                                     queue[i].sysjob);
 
                if (owner || can_job_admin) {
                        print_job_delete1(server_event_context(), msg_ctx,
-                                         snum, queue[i].job);
+                                         snum, queue[i].sysjob);
                }
        }