nwqueue: implement change queue job entry
All checks were successful
Source release / source-package (push) Successful in 47s

Implement the Queue Change Job Entry endpoint for both the old NCP 17/6d
and newer NCP 17/7b variants.

Parse the queue job structure, look up the selected job by its job number,
and update the mutable job metadata fields while preserving server-managed
state such as client identity, entry time, job number, queue position, file
name/handle and servicing information.

Allow the job creator to update the standard user-changeable fields and allow
SUPERVISOR or Q_OPERATORS members to update the operator hold flag as well.
Return the documented queue/job/right/servicing completion codes for missing
queues, missing jobs, insufficient rights and jobs already being serviced.

This only updates NetWare queue metadata. It does not change the existing
Q_UNIX_PRINT/lp backend behavior and adds no CUPS dependency.
This commit is contained in:
Mario Fetka
2026-05-29 17:13:47 +02:00
parent 9f4f8fcbfe
commit 55be945c02
3 changed files with 99 additions and 6 deletions

View File

@@ -617,11 +617,101 @@ int nw_get_queue_job_file_size(uint32 q_id, int job_id)
return(result);
}
int nw_change_queue_job_entry(uint32 q_id, uint8 *qjstruct)
static int is_queue_operator(NWE_QUEUE *q, uint32 user_id)
{
/* TODO */
int result;
if (user_id == 1) /* SUPERVISOR */
return(1);
if (!q)
return(0);
result = nw_is_member_in_set(q->id, "Q_OPERATORS", user_id);
return(result == 0);
}
return(-0xfb);
static int change_queue_job_entry_old(INT_QUEUE_JOB *qj, QUEUE_JOB_OLD *job,
int operator)
{
int old_flags = qj->job_control_flags;
int new_flags = (old_flags & 0x20) | (job->job_control_flags & 0x58);
if (operator)
new_flags |= (job->job_control_flags & 0x80);
else
new_flags |= (old_flags & 0x80);
qj->target_id = GET_BE32(job->target_id);
qj->execute_time = get_time_field(job->target_execute_time);
qj->job_typ = GET_BE16(job->job_typ);
qj->job_control_flags = new_flags;
memcpy(qj->job_description, job->job_description,
sizeof(qj->job_description));
memcpy(qj->client_area, job->client_area, sizeof(qj->client_area));
return(old_flags);
}
static int change_queue_job_entry(INT_QUEUE_JOB *qj, QUEUE_JOB *job,
int operator)
{
int old_flags = qj->job_control_flags;
int request_flags = GET_16(job->job_control_flags);
int new_flags = (old_flags & 0x20) | (request_flags & 0x58);
if (operator)
new_flags |= (request_flags & 0x80);
else
new_flags |= (old_flags & 0x80);
qj->target_id = GET_BE32(job->target_id);
qj->execute_time = get_time_field(job->target_execute_time);
qj->job_typ = GET_BE16(job->job_typ);
qj->job_control_flags = new_flags;
memcpy(qj->job_description, job->job_description,
sizeof(qj->job_description));
memcpy(qj->client_area, job->client_area, sizeof(qj->client_area));
return(old_flags);
}
int nw_change_queue_job_entry(uint32 user_id, uint32 q_id,
uint8 *qjstruct, int old_call)
{
int result=-0xd1; /* no queue */
NWE_QUEUE *q=find_queue(q_id);
if (q) {
int job_id = old_call
? GET_BE16(((QUEUE_JOB_OLD*)qjstruct)->job_id)
: GET_BE16(((QUEUE_JOB*)qjstruct)->job_id);
INT_QUEUE_JOB *qj=find_queue_job(q, job_id);
result=-0xd5; /* no queue job */
if (qj) {
int operator = is_queue_operator(q, user_id);
int creator = (user_id == qj->client_id);
result=-0xd6; /* no job right */
if (operator || creator) {
int old_flags;
if (qj->server_station || qj->server_id)
return(-0xd7); /* queue servicing */
old_flags = old_call
? change_queue_job_entry_old(qj, (QUEUE_JOB_OLD*)qjstruct,
operator)
: change_queue_job_entry(qj, (QUEUE_JOB*)qjstruct,
operator);
q->changed++;
XDPRINTF((2, 0,
"Change Queue Job Entry q=0x%x, job=%d, user=0x%x, flags 0x%x->0x%x",
q_id, job_id, user_id, old_flags, qj->job_control_flags));
result=0;
}
}
}
return(result);
}
static int remove_queue_job_file(NWE_QUEUE *q, INT_QUEUE_JOB *qj)