From d35120b506035595f50abdcbee3f5f28d11c5883 Mon Sep 17 00:00:00 2001 From: David Disseldorp Date: Thu, 30 Oct 2014 01:37:46 +0100 Subject: [PATCH 1/6] printing: add jobid_to_sysjob helper function Samba needs to deal with two types of print job identifiers, those allocated by the printing backend (sysjob ids), and those allocated by Samba's spoolss server (jobids). This change adds a helper function to map spoolss jobids to sysjob ids, to go alongside the corresponding sysjob to jobid mapping function. Signed-off-by: David Disseldorp Reviewed-by: Jeremy Allison (cherry picked from commit 77b5be1742ee7aa2733a25bfa6a3af369f5c9401) --- source3/include/printing.h | 1 + source3/printing/printing.c | 70 +++++++++++++++++++++++++++++++++------------ 2 files changed, 53 insertions(+), 18 deletions(-) diff --git a/source3/include/printing.h b/source3/include/printing.h index c511fa2..373bc54 100644 --- a/source3/include/printing.h +++ b/source3/include/printing.h @@ -194,6 +194,7 @@ void print_spool_terminate(struct connection_struct *conn, /* The following definitions come from printing/printing.c */ uint32 sysjob_to_jobid(int unix_jobid); +int jobid_to_sysjob_pdb(struct tdb_print_db *pdb, uint32_t jobid); bool print_notify_register_pid(int snum); bool print_notify_deregister_pid(int snum); bool print_job_exists(const char* sharename, uint32 jobid); diff --git a/source3/printing/printing.c b/source3/printing/printing.c index 16821ae..118d24c 100644 --- a/source3/printing/printing.c +++ b/source3/printing/printing.c @@ -478,19 +478,18 @@ err_out: return pjob; } -/* Convert a unix jobid to a smb jobid */ - -struct unixjob_traverse_state { +struct job_traverse_state { int sysjob; - uint32 sysjob_to_jobid_value; + uint32_t jobid; }; -static int unixjob_traverse_fn(TDB_CONTEXT *the_tdb, TDB_DATA key, - TDB_DATA data, void *private_data) +/* find spoolss jobid based on sysjob */ +static int sysjob_to_jobid_traverse_fn(TDB_CONTEXT *the_tdb, TDB_DATA key, + TDB_DATA data, void *private_data) { struct printjob *pjob; - struct unixjob_traverse_state *state = - (struct unixjob_traverse_state *)private_data; + struct job_traverse_state *state = + (struct job_traverse_state *)private_data; if (!data.dptr || data.dsize == 0) return 0; @@ -500,7 +499,7 @@ static int unixjob_traverse_fn(TDB_CONTEXT *the_tdb, TDB_DATA key, return 0; if (state->sysjob == pjob->sysjob) { - state->sysjob_to_jobid_value = pjob->jobid; + state->jobid = pjob->jobid; return 1; } @@ -509,14 +508,14 @@ static int unixjob_traverse_fn(TDB_CONTEXT *the_tdb, TDB_DATA key, static uint32 sysjob_to_jobid_pdb(struct tdb_print_db *pdb, int sysjob) { - struct unixjob_traverse_state state; + struct job_traverse_state state; state.sysjob = sysjob; - state.sysjob_to_jobid_value = (uint32)-1; + state.jobid = (uint32_t)-1; - tdb_traverse(pdb->tdb, unixjob_traverse_fn, &state); + tdb_traverse(pdb->tdb, sysjob_to_jobid_traverse_fn, &state); - return state.sysjob_to_jobid_value; + return state.jobid; } /**************************************************************************** @@ -528,10 +527,10 @@ uint32 sysjob_to_jobid(int unix_jobid) { int services = lp_numservices(); int snum; - struct unixjob_traverse_state state; + struct job_traverse_state state; state.sysjob = unix_jobid; - state.sysjob_to_jobid_value = (uint32)-1; + state.jobid = (uint32_t)-1; for (snum = 0; snum < services; snum++) { struct tdb_print_db *pdb; @@ -541,14 +540,49 @@ uint32 sysjob_to_jobid(int unix_jobid) if (!pdb) { continue; } - tdb_traverse(pdb->tdb, unixjob_traverse_fn, &state); + tdb_traverse(pdb->tdb, sysjob_to_jobid_traverse_fn, &state); release_print_db(pdb); - if (state.sysjob_to_jobid_value != (uint32)-1) - return state.sysjob_to_jobid_value; + if (state.jobid != (uint32_t)-1) + return state.jobid; } return (uint32)-1; } +/* find sysjob based on spoolss jobid */ +static int jobid_to_sysjob_traverse_fn(TDB_CONTEXT *the_tdb, TDB_DATA key, + TDB_DATA data, void *private_data) +{ + struct printjob *pjob; + struct job_traverse_state *state = + (struct job_traverse_state *)private_data; + + if (!data.dptr || data.dsize == 0) + return 0; + + pjob = (struct printjob *)data.dptr; + if (key.dsize != sizeof(uint32_t)) + return 0; + + if (state->jobid == pjob->jobid) { + state->sysjob = pjob->sysjob; + return 1; + } + + return 0; +} + +int jobid_to_sysjob_pdb(struct tdb_print_db *pdb, uint32_t jobid) +{ + struct job_traverse_state state; + + state.sysjob = -1; + state.jobid = jobid; + + tdb_traverse(pdb->tdb, jobid_to_sysjob_traverse_fn, &state); + + return state.sysjob; +} + /**************************************************************************** Send notifications based on what has changed after a pjob_store. ****************************************************************************/ -- 1.8.4.5 From dfcc90c702e185b9e668d29a74ec1aae5fbac959 Mon Sep 17 00:00:00 2001 From: David Disseldorp Date: Thu, 30 Oct 2014 01:37:47 +0100 Subject: [PATCH 2/6] spoolss: fix GetJob jobid lookups MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Clients issue GetJob requests using the jobid assigned by the spoolss server. The corresponding printing backend (sysjob) identifier needs to be resolved to locate the correct print queue entry. Bug: https://bugzilla.samba.org/show_bug.cgi?id=10905 Reported-by: Franz Pförtsch Signed-off-by: David Disseldorp Reviewed-by: Jeremy Allison (cherry picked from commit 3a28ae56977235d3c9e3abcd1f24b220e536c50d) --- source3/rpc_server/spoolss/srv_spoolss_nt.c | 37 +++++++++++++++++++++++++---- 1 file changed, 32 insertions(+), 5 deletions(-) diff --git a/source3/rpc_server/spoolss/srv_spoolss_nt.c b/source3/rpc_server/spoolss/srv_spoolss_nt.c index a8574e4..cc06e30 100644 --- a/source3/rpc_server/spoolss/srv_spoolss_nt.c +++ b/source3/rpc_server/spoolss/srv_spoolss_nt.c @@ -9077,13 +9077,14 @@ static WERROR getjob_level_1(TALLOC_CTX *mem_ctx, int count, int snum, struct spoolss_PrinterInfo2 *pinfo2, uint32_t jobid, + int sysjob, struct spoolss_JobInfo1 *r) { int i = 0; bool found = false; for (i=0; imem_ctx, get_session_info_system(), p->msg_ctx, - lp_const_servicename(snum), + svc_name, &pinfo2); if (!W_ERROR_IS_OK(result)) { return result; } + pdb = get_print_db_byname(svc_name); + if (pdb == NULL) { + DEBUG(3, ("failed to get print db for svc %s\n", svc_name)); + TALLOC_FREE(pinfo2); + return WERR_INVALID_PARAM; + } + + sysjob = jobid_to_sysjob_pdb(pdb, r->in.job_id); + release_print_db(pdb); + if (sysjob == -1) { + DEBUG(3, ("no sysjob for spoolss jobid %u\n", r->in.job_id)); + TALLOC_FREE(pinfo2); + return WERR_INVALID_PARAM; + } + count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status); DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n", @@ -9202,12 +9227,14 @@ WERROR _spoolss_GetJob(struct pipes_struct *p, case 1: result = getjob_level_1(p->mem_ctx, queue, count, snum, pinfo2, - r->in.job_id, &r->out.info->info1); + r->in.job_id, sysjob, + &r->out.info->info1); break; case 2: result = getjob_level_2(p->mem_ctx, queue, count, snum, pinfo2, - r->in.job_id, &r->out.info->info2); + r->in.job_id, sysjob, + &r->out.info->info2); break; default: result = WERR_UNKNOWN_LEVEL; -- 1.8.4.5 From d7af3dcd9100959212451349bf283f8ee10101e7 Mon Sep 17 00:00:00 2001 From: David Disseldorp Date: Thu, 30 Oct 2014 01:37:48 +0100 Subject: [PATCH 3/6] spoolss: fix jobid in level 1 GetJob and EnumJobs responses MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Until now, these responses have incorrectly carried the printing backend job identifier (sysjob), rather than the one allocated and returned by Samba on job submission. Bug: https://bugzilla.samba.org/show_bug.cgi?id=10905 Reported-by: Franz Pförtsch Signed-off-by: David Disseldorp Reviewed-by: Jeremy Allison (cherry picked from commit 4d7f5d2af6ef6960dccaccf89c6e88947e2591bf) [ddiss@samba.org: rebased for 3.6 with TALLOC_ARRAY] --- source3/rpc_server/spoolss/srv_spoolss_nt.c | 50 +++++++++++++++++++++-------- 1 file changed, 37 insertions(+), 13 deletions(-) diff --git a/source3/rpc_server/spoolss/srv_spoolss_nt.c b/source3/rpc_server/spoolss/srv_spoolss_nt.c index cc06e30..b5e66c9 100644 --- a/source3/rpc_server/spoolss/srv_spoolss_nt.c +++ b/source3/rpc_server/spoolss/srv_spoolss_nt.c @@ -6830,6 +6830,7 @@ fill_job_info1 static WERROR fill_job_info1(TALLOC_CTX *mem_ctx, struct spoolss_JobInfo1 *r, const print_queue_struct *queue, + uint32_t jobid, int position, int snum, struct spoolss_PrinterInfo2 *pinfo2) { @@ -6837,7 +6838,7 @@ static WERROR fill_job_info1(TALLOC_CTX *mem_ctx, t = gmtime(&queue->time); - r->job_id = queue->sysjob; + r->job_id = jobid; r->printer_name = talloc_strdup(mem_ctx, lp_servicename(snum)); W_ERROR_HAVE_NO_MEMORY(r->printer_name); @@ -6955,34 +6956,56 @@ static WERROR enumjobs_level1(TALLOC_CTX *mem_ctx, union spoolss_JobInfo *info; int i; WERROR result = WERR_OK; + uint32_t num_filled; + struct tdb_print_db *pdb; - info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues); - W_ERROR_HAVE_NO_MEMORY(info); + info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues); + if (info == NULL) { + result = WERR_NOMEM; + goto err_out; + } - *count = num_queues; + pdb = get_print_db_byname(pinfo2->sharename); + if (pdb == NULL) { + result = WERR_INVALID_PARAM; + goto err_info_free; + } + + num_filled = 0; + for (i = 0; i < num_queues; i++) { + uint32_t jobid = sysjob_to_jobid_pdb(pdb, queue[i].sysjob); + if (jobid == (uint32_t)-1) { + DEBUG(4, ("skipping sysjob %d\n", queue[i].sysjob)); + continue; + } - for (i=0; i<*count; i++) { result = fill_job_info1(info, - &info[i].info1, + &info[num_filled].info1, &queue[i], + jobid, i, snum, pinfo2); if (!W_ERROR_IS_OK(result)) { - goto out; + goto err_pdb_drop; } - } - out: - if (!W_ERROR_IS_OK(result)) { - TALLOC_FREE(info); - *count = 0; - return result; + num_filled++; } + release_print_db(pdb); *info_p = info; + *count = num_filled; return WERR_OK; + +err_pdb_drop: + release_print_db(pdb); +err_info_free: + TALLOC_FREE(info); +err_out: + *count = 0; + return result; } /**************************************************************************** @@ -9098,6 +9121,7 @@ static WERROR getjob_level_1(TALLOC_CTX *mem_ctx, return fill_job_info1(mem_ctx, r, &queue[i], + jobid, i, snum, pinfo2); -- 1.8.4.5 From 80408d87605726047addea971974f6a96d781a0d Mon Sep 17 00:00:00 2001 From: David Disseldorp Date: Thu, 30 Oct 2014 01:37:49 +0100 Subject: [PATCH 4/6] spoolss: fix jobid in level 2 GetJob and EnumJobs responses MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Until now, these responses have incorrectly carried the printing backend job identifier (sysjob), rather than the one allocated and returned by Samba on job submission. Bug: https://bugzilla.samba.org/show_bug.cgi?id=10905 Reported-by: Franz Pförtsch Signed-off-by: David Disseldorp Reviewed-by: Jeremy Allison (cherry picked from commit 45abaf81c67b62bab571df208931241afa660802) [ddiss@samba.org: rebased for 3.6 with TALLOC_ARRAY] --- source3/rpc_server/spoolss/srv_spoolss_nt.c | 52 ++++++++++++++++++++--------- 1 file changed, 37 insertions(+), 15 deletions(-) diff --git a/source3/rpc_server/spoolss/srv_spoolss_nt.c b/source3/rpc_server/spoolss/srv_spoolss_nt.c index b5e66c9..f0de790 100644 --- a/source3/rpc_server/spoolss/srv_spoolss_nt.c +++ b/source3/rpc_server/spoolss/srv_spoolss_nt.c @@ -6871,6 +6871,7 @@ fill_job_info2 static WERROR fill_job_info2(TALLOC_CTX *mem_ctx, struct spoolss_JobInfo2 *r, const print_queue_struct *queue, + uint32_t jobid, int position, int snum, struct spoolss_PrinterInfo2 *pinfo2, struct spoolss_DeviceMode *devmode) @@ -6879,7 +6880,7 @@ static WERROR fill_job_info2(TALLOC_CTX *mem_ctx, t = gmtime(&queue->time); - r->job_id = queue->sysjob; + r->job_id = jobid; r->printer_name = talloc_strdup(mem_ctx, lp_servicename(snum)); W_ERROR_HAVE_NO_MEMORY(r->printer_name); @@ -7022,45 +7023,65 @@ static WERROR enumjobs_level2(TALLOC_CTX *mem_ctx, union spoolss_JobInfo *info; int i; WERROR result = WERR_OK; + uint32_t num_filled; + struct tdb_print_db *pdb; - info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues); - W_ERROR_HAVE_NO_MEMORY(info); + info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues); + if (info == NULL) { + result = WERR_NOMEM; + goto err_out; + } - *count = num_queues; + pdb = get_print_db_byname(pinfo2->sharename); + if (pdb == NULL) { + result = WERR_INVALID_PARAM; + goto err_info_free; + } - for (i=0; i<*count; i++) { + num_filled = 0; + for (i = 0; i< num_queues; i++) { struct spoolss_DeviceMode *devmode; + uint32_t jobid = sysjob_to_jobid_pdb(pdb, queue[i].sysjob); + if (jobid == (uint32_t)-1) { + DEBUG(4, ("skipping sysjob %d\n", queue[i].sysjob)); + continue; + } result = spoolss_create_default_devmode(info, pinfo2->printername, &devmode); if (!W_ERROR_IS_OK(result)) { DEBUG(3, ("Can't proceed w/o a devmode!")); - goto out; + goto err_pdb_drop; } result = fill_job_info2(info, - &info[i].info2, + &info[num_filled].info2, &queue[i], + jobid, i, snum, pinfo2, devmode); if (!W_ERROR_IS_OK(result)) { - goto out; + goto err_pdb_drop; } + num_filled++; } - out: - if (!W_ERROR_IS_OK(result)) { - TALLOC_FREE(info); - *count = 0; - return result; - } - + release_print_db(pdb); *info_p = info; + *count = num_filled; return WERR_OK; + +err_pdb_drop: + release_print_db(pdb); +err_info_free: + TALLOC_FREE(info); +err_out: + *count = 0; + return result; } /**************************************************************************** @@ -9176,6 +9197,7 @@ static WERROR getjob_level_2(TALLOC_CTX *mem_ctx, return fill_job_info2(mem_ctx, r, &queue[i], + jobid, i, snum, pinfo2, -- 1.8.4.5 From 4f82122015e28f5bfb7f3282c925f58df800c012 Mon Sep 17 00:00:00 2001 From: David Disseldorp Date: Thu, 30 Oct 2014 01:37:50 +0100 Subject: [PATCH 5/6] spoolss: fix jobid in level 3 EnumJobs response MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Until now, these responses have incorrectly carried the printing backend job identifier (sysjob), rather than the one allocated and returned by Samba on job submission. Bug: https://bugzilla.samba.org/show_bug.cgi?id=10905 Reported-by: Franz Pförtsch Signed-off-by: David Disseldorp Reviewed-by: Jeremy Allison (cherry picked from commit 5e7ab3d2f4f7950099561eb22d6a9a1536297442) [ddiss@samba.org: rebased for 3.6 with TALLOC_ARRAY] --- source3/rpc_server/spoolss/srv_spoolss_nt.c | 58 +++++++++++++++++------------ 1 file changed, 34 insertions(+), 24 deletions(-) diff --git a/source3/rpc_server/spoolss/srv_spoolss_nt.c b/source3/rpc_server/spoolss/srv_spoolss_nt.c index f0de790..9a6f2d9 100644 --- a/source3/rpc_server/spoolss/srv_spoolss_nt.c +++ b/source3/rpc_server/spoolss/srv_spoolss_nt.c @@ -7098,41 +7098,51 @@ static WERROR enumjobs_level3(TALLOC_CTX *mem_ctx, union spoolss_JobInfo *info; int i; WERROR result = WERR_OK; + uint32_t num_filled; + struct tdb_print_db *pdb; - info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues); - W_ERROR_HAVE_NO_MEMORY(info); - - *count = num_queues; + info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues); + if (info == NULL) { + result = WERR_NOMEM; + goto err_out; + } - for (i=0; i<*count; i++) { - const print_queue_struct *next_queue = NULL; + pdb = get_print_db_byname(pinfo2->sharename); + if (pdb == NULL) { + result = WERR_INVALID_PARAM; + goto err_info_free; + } - if (i+1 < *count) { - next_queue = &queue[i+1]; + num_filled = 0; + for (i = 0; i < num_queues; i++) { + uint32_t jobid = sysjob_to_jobid_pdb(pdb, queue[i].sysjob); + if (jobid == (uint32_t)-1) { + DEBUG(4, ("skipping sysjob %d\n", queue[i].sysjob)); + continue; } - result = fill_job_info3(info, - &info[i].info3, - &queue[i], - next_queue, - i, - snum, - pinfo2); - if (!W_ERROR_IS_OK(result)) { - goto out; - } - } + info[num_filled].info3.job_id = jobid; + /* next_job_id is overwritten on next iteration */ + info[num_filled].info3.next_job_id = 0; + info[num_filled].info3.reserved = 0; - out: - if (!W_ERROR_IS_OK(result)) { - TALLOC_FREE(info); - *count = 0; - return result; + if (num_filled > 0) { + info[num_filled - 1].info3.next_job_id = jobid; + } + num_filled++; } + release_print_db(pdb); *info_p = info; + *count = num_filled; return WERR_OK; + +err_info_free: + TALLOC_FREE(info); +err_out: + *count = 0; + return result; } /**************************************************************** -- 1.8.4.5 From 73bea06d704f8dc91e78d84a8654ce168ec4dc86 Mon Sep 17 00:00:00 2001 From: David Disseldorp Date: Thu, 30 Oct 2014 01:37:51 +0100 Subject: [PATCH 6/6] spoolss: remove unused fill_job_info3() This logic has been moved into the previous EnumJobs(level=3) caller. The info3 structure only contains two fields that are used, so it doesn't make sense to have a separate helper for it. Signed-off-by: David Disseldorp Reviewed-by: Jeremy Allison (cherry picked from commit d772b98283f289917a6a8370808d4d0912899384) --- source3/rpc_server/spoolss/srv_spoolss_nt.c | 21 --------------------- 1 file changed, 21 deletions(-) diff --git a/source3/rpc_server/spoolss/srv_spoolss_nt.c b/source3/rpc_server/spoolss/srv_spoolss_nt.c index 9a6f2d9..f3b9eb3 100644 --- a/source3/rpc_server/spoolss/srv_spoolss_nt.c +++ b/source3/rpc_server/spoolss/srv_spoolss_nt.c @@ -6923,27 +6923,6 @@ static WERROR fill_job_info2(TALLOC_CTX *mem_ctx, } /**************************************************************************** -fill_job_info3 -****************************************************************************/ - -static WERROR fill_job_info3(TALLOC_CTX *mem_ctx, - struct spoolss_JobInfo3 *r, - const print_queue_struct *queue, - const print_queue_struct *next_queue, - int position, int snum, - struct spoolss_PrinterInfo2 *pinfo2) -{ - r->job_id = queue->sysjob; - r->next_job_id = 0; - if (next_queue) { - r->next_job_id = next_queue->sysjob; - } - r->reserved = 0; - - return WERR_OK; -} - -/**************************************************************************** Enumjobs at level 1. ****************************************************************************/ -- 1.8.4.5