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;
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;
}
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);
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 ));
- SMB_ASSERT(pjob.jobid == 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 */
/* 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 );
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
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);
}
/****************************************************************************
uint32 jobid)
{
struct printjob pj, *old_pj;
+ TALLOC_CTX *tmp_ctx = talloc_new(ev);
+ if (tmp_ctx == NULL) {
+ return;
+ }
- if (jobid == (uint32)-1)
+ 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);
fstrcpy(pj.queuename, old_pj ? old_pj->queuename : sharename );
pjob_store(ev, msg_ctx, sharename, jobid, &pj);
+ talloc_free(tmp_ctx);
}
struct printif *print_if;
struct tevent_context *ev;
struct messaging_context *msg_ctx;
+ TALLOC_CTX *mem_ctx;
};
/****************************************************************************
if ( key.dsize != sizeof(jobid) )
return 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;
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;
}
fill in any system job numbers as we go
*/
-
jcdata = get_jobs_added_data(pdb);
for (i=0; i<qcount; i++) {
}
/* 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
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);
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 ));
}
/****************************************************************************
- Give the filename used for a jobid.
- Only valid for the process doing the spooling and when the job
- has not been spooled.
-****************************************************************************/
-
-char *print_job_fname(const char* sharename, uint32 jobid)
-{
- struct printjob *pjob = print_job_find(sharename, jobid);
- if (!pjob || pjob->spooled || pjob->pid != getpid())
- return NULL;
- return pjob->filename;
-}
-
-
-/****************************************************************************
- Give the filename used for a jobid.
+ Return the device mode asigned to a specific print job.
Only valid for the process doing the spooling and when the job
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;
}
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 != 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;
}
/****************************************************************************
{
struct printjob *pjob;
- pjob = print_job_find(sharename, jobid);
+ pjob = print_job_find(mem_ctx, sharename, jobid);
if (!pjob || pjob->pid != getpid()) {
return false;
}
- *name = talloc_strdup(mem_ctx, pjob->jobname);
- if (!*name) {
- return false;
- }
-
+ *name = pjob->jobname;
return true;
}
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
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);
remove_from_jobs_added( sharename, jobid );
- return (result == 0);
+ ret = (result == 0);
+err_out:
+ talloc_free(tmp_ctx);
+ return ret;
}
/****************************************************************************
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;
}
/****************************************************************************
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);
lp_printername(snum) );
/* END_ADMIN_LOG */
- return WERR_ACCESS_DENIED;
+ werr = WERR_ACCESS_DENIED;
+ goto err_out;
}
/*
* 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
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) &&
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 */
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,
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 */
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;
}
/****************************************************************************
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 != 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;
}
{
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 != 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);
}
/****************************************************************************
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;
+ char *lpq_cmd;
+ 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 != getpid()) {
- return NT_STATUS_ACCESS_DENIED;
+ status = NT_STATUS_ACCESS_DENIED;
+ goto err_out;
}
if (close_type == NORMAL_CLOSE || close_type == SHUTDOWN_CLOSE) {
return NT_STATUS_OK;
}
- ret = (*(current_printif->job_submit))(snum, pjob);
+ /* don't strip out characters like '$' from the printername */
+ lpq_cmd = talloc_string_sub2(tmp_ctx,
+ lp_lpqcommand(snum),
+ "%p",
+ lp_printername(snum),
+ false, false, false);
+ if (lpq_cmd == NULL) {
+ status = NT_STATUS_PRINT_CANCELLED;
+ goto fail;
+ }
+ lpq_cmd = talloc_sub_advanced(tmp_ctx,
+ lp_servicename(snum),
+ current_user_info.unix_name,
+ "",
+ current_user.ut.gid,
+ get_current_username(),
+ current_user_info.domain,
+ lpq_cmd);
+ if (lpq_cmd == NULL) {
+ status = NT_STATUS_PRINT_CANCELLED;
+ goto fail;
+ }
+ ret = (*(current_printif->job_submit))(snum, pjob,
+ current_printif->type, lpq_cmd);
if (ret) {
status = NT_STATUS_PRINT_CANCELLED;
goto fail;
pjob->fd = -1;
unlink(pjob->filename);
pjob_delete(server_event_context(), msg_ctx, sharename, jobid);
+err_out:
+ talloc_free(tmp_ctx);
return status;
}
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))
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);
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. */
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",
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));
SAFE_FREE(data.dptr);
SAFE_FREE(cgdata.dptr);
+ talloc_free(tmp_ctx);
return ret;
}