extern userdom_struct current_user_info;
/* Current printer interface */
-static bool remove_from_jobs_changed(const char* sharename, uint32 jobid);
+static bool remove_from_jobs_added(const char* sharename, uint32 jobid);
/*
the printing backend revolves around a tdb database that stores the
unpack a pjob from a tdb buffer
***********************************************************************/
-int unpack_pjob( uint8 *buf, int buflen, struct printjob *pjob )
+static int unpack_pjob( uint8 *buf, int buflen, struct printjob *pjob )
{
int len = 0;
int used;
if ( !buf || !pjob )
return -1;
- len += tdb_unpack(buf+len, buflen-len, "dddddddddffff",
+ len += tdb_unpack(buf+len, buflen-len, "dddddddddfffff",
&pjpid,
&pjsysjob,
&pjfd,
pjob->filename,
pjob->jobname,
pjob->user,
+ pjob->clientmachine,
pjob->queuename);
if ( len == -1 )
return 0;
}
+/***************************************************************************
+ Append a jobid to the 'jobs changed' list.
+***************************************************************************/
+
+static bool add_to_jobs_changed(struct tdb_print_db *pdb, uint32_t jobid)
+{
+ TDB_DATA data;
+ uint32_t store_jobid;
+
+ SIVAL(&store_jobid, 0, jobid);
+ data.dptr = (uint8 *) &store_jobid;
+ data.dsize = 4;
+
+ DEBUG(10,("add_to_jobs_added: Added jobid %u\n", (unsigned int)jobid ));
+
+ return (tdb_append(pdb->tdb, string_tdb_data("INFO/jobs_changed"),
+ data) == 0);
+}
+
+/***************************************************************************
+ Remove a jobid from the 'jobs changed' list.
+***************************************************************************/
+
+static bool remove_from_jobs_changed(const char* sharename, uint32_t jobid)
+{
+ struct tdb_print_db *pdb = get_print_db_byname(sharename);
+ TDB_DATA data, key;
+ size_t job_count, i;
+ bool ret = False;
+ bool gotlock = False;
+
+ if (!pdb) {
+ return False;
+ }
+
+ ZERO_STRUCT(data);
+
+ key = string_tdb_data("INFO/jobs_changed");
+
+ if (tdb_chainlock_with_timeout(pdb->tdb, key, 5) == -1)
+ goto out;
+
+ gotlock = True;
+
+ data = tdb_fetch(pdb->tdb, key);
+
+ if (data.dptr == NULL || data.dsize == 0 || (data.dsize % 4 != 0))
+ goto out;
+
+ job_count = data.dsize / 4;
+ for (i = 0; i < job_count; i++) {
+ uint32 ch_jobid;
+
+ ch_jobid = IVAL(data.dptr, i*4);
+ if (ch_jobid == jobid) {
+ if (i < job_count -1 )
+ memmove(data.dptr + (i*4), data.dptr + (i*4) + 4, (job_count - i - 1)*4 );
+ data.dsize -= 4;
+ if (tdb_store(pdb->tdb, key, data, TDB_REPLACE) == -1)
+ goto out;
+ break;
+ }
+ }
+
+ ret = True;
+ out:
+
+ if (gotlock)
+ tdb_chainunlock(pdb->tdb, key);
+ SAFE_FREE(data.dptr);
+ release_print_db(pdb);
+ if (ret)
+ DEBUG(10,("remove_from_jobs_changed: removed jobid %u\n", (unsigned int)jobid ));
+ else
+ DEBUG(10,("remove_from_jobs_changed: Failed to remove jobid %u\n", (unsigned int)jobid ));
+ return ret;
+}
+
static void pjob_store_notify(struct tevent_context *ev,
struct messaging_context *msg_ctx,
const char* sharename, uint32 jobid,
struct printjob *old_data,
- struct printjob *new_data)
+ struct printjob *new_data,
+ bool *pchanged)
{
- bool new_job = False;
+ bool new_job = false;
+ bool changed = false;
- if (!old_data)
- new_job = True;
-
- /* Job attributes that can't be changed. We only send
- notification for these on a new job. */
+ if (old_data == NULL) {
+ new_job = true;
+ }
/* ACHTUNG! Due to a bug in Samba's spoolss parsing of the
NOTIFY_INFO_DATA buffer, we *have* to send the job submission
sharename, jobid, new_data->starttime);
notify_job_username(ev, msg_ctx,
sharename, jobid, new_data->user);
- }
-
- if (new_job || !strequal(old_data->jobname, new_data->jobname))
- notify_job_name(ev, msg_ctx,
- sharename, jobid, new_data->jobname);
-
- /* Job attributes of a new job or attributes that can be
- modified. */
-
- if (new_job || !strequal(old_data->jobname, new_data->jobname))
notify_job_name(ev, msg_ctx,
sharename, jobid, new_data->jobname);
-
- if (new_job || old_data->status != new_data->status)
notify_job_status(ev, msg_ctx,
- sharename, jobid,
- map_to_spoolss_status(new_data->status));
-
- if (new_job || old_data->size != new_data->size)
+ sharename, jobid, map_to_spoolss_status(new_data->status));
notify_job_total_bytes(ev, msg_ctx,
sharename, jobid, new_data->size);
-
- if (new_job || old_data->page_count != new_data->page_count)
notify_job_total_pages(ev, msg_ctx,
sharename, jobid, new_data->page_count);
+ } else {
+ if (!strequal(old_data->jobname, new_data->jobname)) {
+ notify_job_name(ev, msg_ctx, sharename,
+ jobid, new_data->jobname);
+ changed = true;
+ }
+
+ if (old_data->status != new_data->status) {
+ notify_job_status(ev, msg_ctx,
+ sharename, jobid,
+ map_to_spoolss_status(new_data->status));
+ }
+
+ if (old_data->size != new_data->size) {
+ notify_job_total_bytes(ev, msg_ctx,
+ sharename, jobid, new_data->size);
+ }
+
+ if (old_data->page_count != new_data->page_count) {
+ notify_job_total_pages(ev, msg_ctx,
+ sharename, jobid,
+ new_data->page_count);
+ }
+ }
+
+ *pchanged = changed;
}
/****************************************************************************
do {
len = 0;
buflen = newlen;
- len += tdb_pack(buf+len, buflen-len, "dddddddddffff",
+ len += tdb_pack(buf+len, buflen-len, "dddddddddfffff",
(uint32)pjob->pid,
(uint32)pjob->sysjob,
(uint32)pjob->fd,
pjob->filename,
pjob->jobname,
pjob->user,
+ pjob->clientmachine,
pjob->queuename);
len += pack_devicemode(pjob->devmode, buf+len, buflen-len);
ret = (tdb_store(pdb->tdb, print_key(jobid, &tmp), new_data,
TDB_REPLACE) == 0);
- release_print_db(pdb);
-
/* Send notify updates for what has changed */
if ( ret ) {
+ bool changed = false;
struct printjob old_pjob;
if ( old_data.dsize )
pjob_store_notify(server_event_context(),
msg_ctx,
sharename, jobid, &old_pjob,
- pjob);
+ pjob,
+ &changed);
talloc_free(old_pjob.devmode);
+
+ if (changed) {
+ add_to_jobs_changed(pdb, jobid);
+ }
}
+
}
else {
/* new job */
pjob_store_notify(server_event_context(), msg_ctx,
- sharename, jobid, NULL, pjob);
+ sharename, jobid, NULL, pjob,
+ &changed);
}
}
+ release_print_db(pdb);
done:
SAFE_FREE( old_data.dptr );
SAFE_FREE( buf );
/* Remove from printing.tdb */
tdb_delete(pdb->tdb, print_key(jobid, &tmp));
- remove_from_jobs_changed(sharename, jobid);
+ remove_from_jobs_added(sharename, jobid);
release_print_db( pdb );
rap_jobid_delete(sharename, jobid);
}
return;
}
-static TDB_DATA get_jobs_changed_data(struct tdb_print_db *pdb)
+static TDB_DATA get_jobs_added_data(struct tdb_print_db *pdb)
{
TDB_DATA data;
ZERO_STRUCT(data);
- data = tdb_fetch(pdb->tdb, string_tdb_data("INFO/jobs_changed"));
+ data = tdb_fetch(pdb->tdb, string_tdb_data("INFO/jobs_added"));
if (data.dptr == NULL || data.dsize == 0 || (data.dsize % 4 != 0)) {
SAFE_FREE(data.dptr);
ZERO_STRUCT(data);
return data;
}
-static void check_job_changed(const char *sharename, TDB_DATA data, uint32 jobid)
+static void check_job_added(const char *sharename, TDB_DATA data, uint32 jobid)
{
unsigned int i;
unsigned int job_count = data.dsize / 4;
ch_jobid = IVAL(data.dptr, i*4);
if (ch_jobid == jobid)
- remove_from_jobs_changed(sharename, jobid);
+ remove_from_jobs_added(sharename, jobid);
}
}
fill in any system job numbers as we go
*/
- jcdata = get_jobs_changed_data(pdb);
+ jcdata = get_jobs_added_data(pdb);
for (i=0; i<qcount; i++) {
uint32 jobid = print_parse_jobid(queue[i].fs_file);
pjob_store(ev, msg_ctx, sharename, jobid, pjob);
- check_job_changed(sharename, jcdata, jobid);
+ check_job_added(sharename, jcdata, jobid);
}
SAFE_FREE(jcdata.dptr);
Set the name of a job. Only possible for owner.
****************************************************************************/
-bool print_job_set_name(const char *sharename, uint32 jobid, const char *name)
+bool print_job_set_name(struct tevent_context *ev,
+ struct messaging_context *msg_ctx,
+ const char *sharename, uint32 jobid, const char *name)
{
struct printjob *pjob;
return False;
fstrcpy(pjob->jobname, name);
- return pjob_store(server_event_context(), server_messaging_context(),
- sharename, jobid, pjob);
+ return pjob_store(ev, msg_ctx, sharename, jobid, pjob);
}
/****************************************************************************
/***************************************************************************
- Remove a jobid from the 'jobs changed' list.
+ Remove a jobid from the 'jobs added' list.
***************************************************************************/
-static bool remove_from_jobs_changed(const char* sharename, uint32 jobid)
+static bool remove_from_jobs_added(const char* sharename, uint32 jobid)
{
struct tdb_print_db *pdb = get_print_db_byname(sharename);
TDB_DATA data, key;
ZERO_STRUCT(data);
- key = string_tdb_data("INFO/jobs_changed");
+ key = string_tdb_data("INFO/jobs_added");
if (tdb_chainlock_with_timeout(pdb->tdb, key, 5) == -1)
goto out;
SAFE_FREE(data.dptr);
release_print_db(pdb);
if (ret)
- DEBUG(10,("remove_from_jobs_changed: removed jobid %u\n", (unsigned int)jobid ));
+ DEBUG(10,("remove_from_jobs_added: removed jobid %u\n", (unsigned int)jobid ));
else
- DEBUG(10,("remove_from_jobs_changed: Failed to remove jobid %u\n", (unsigned int)jobid ));
+ DEBUG(10,("remove_from_jobs_added: Failed to remove jobid %u\n", (unsigned int)jobid ));
return ret;
}
Delete a print job - don't update queue.
****************************************************************************/
-static bool print_job_delete1(int snum, uint32 jobid)
+static bool print_job_delete1(struct tevent_context *ev,
+ struct messaging_context *msg_ctx,
+ int snum, uint32 jobid)
{
const char* sharename = lp_const_servicename(snum);
struct printjob *pjob = print_job_find(sharename, jobid);
/* Set the tdb entry to be deleting. */
pjob->status = LPQ_DELETING;
- pjob_store(server_event_context(), server_messaging_context(),
- sharename, jobid, pjob);
+ pjob_store(ev, msg_ctx, sharename, jobid, pjob);
if (pjob->spooled && pjob->sysjob != -1)
{
if (!pdb)
return False;
- pjob_delete(server_event_context(),
- server_messaging_context(),
- sharename, jobid);
+ 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);
release_print_db(pdb);
}
}
- remove_from_jobs_changed( sharename, jobid );
+ remove_from_jobs_added( sharename, jobid );
return (result == 0);
}
Return true if the current user owns the print job.
****************************************************************************/
-static bool is_owner(struct auth_serversupplied_info *server_info,
+static bool is_owner(const struct auth_serversupplied_info *server_info,
const char *servicename,
uint32 jobid)
{
Delete a print job.
****************************************************************************/
-WERROR print_job_delete(struct auth_serversupplied_info *server_info,
+WERROR print_job_delete(const struct auth_serversupplied_info *server_info,
struct messaging_context *msg_ctx,
int snum, uint32_t jobid)
{
}
}
- if (!print_job_delete1(snum, jobid)) {
+ if (!print_job_delete1(server_event_context(), msg_ctx, snum, jobid)) {
return WERR_ACCESS_DENIED;
}
Pause a job.
****************************************************************************/
-bool print_job_pause(struct auth_serversupplied_info *server_info,
+bool print_job_pause(const struct auth_serversupplied_info *server_info,
struct messaging_context *msg_ctx,
int snum, uint32 jobid, WERROR *errcode)
{
Resume a job.
****************************************************************************/
-bool print_job_resume(struct auth_serversupplied_info *server_info,
+bool print_job_resume(const struct auth_serversupplied_info *server_info,
struct messaging_context *msg_ctx,
int snum, uint32 jobid, WERROR *errcode)
{
Write to a print file.
****************************************************************************/
-ssize_t print_job_write(int snum, uint32 jobid, const char *buf, SMB_OFF_T pos, size_t size)
+ssize_t print_job_write(struct tevent_context *ev,
+ struct messaging_context *msg_ctx,
+ int snum, uint32 jobid, const char *buf, size_t size)
{
const char* sharename = lp_const_servicename(snum);
ssize_t return_code;
return -1;
}
- return_code = write_data_at_offset(pjob->fd, buf, size, pos);
+ return_code = write_data(pjob->fd, buf, size);
if (return_code>0) {
pjob->size += size;
- pjob_store(server_event_context(), server_messaging_context(),
- sharename, jobid, pjob);
+ pjob_store(ev, msg_ctx, sharename, jobid, pjob);
}
return return_code;
}
}
/***************************************************************************
- Append a jobid to the 'jobs changed' list.
+ Append a jobid to the 'jobs added' list.
***************************************************************************/
-static bool add_to_jobs_changed(struct tdb_print_db *pdb, uint32 jobid)
+static bool add_to_jobs_added(struct tdb_print_db *pdb, uint32 jobid)
{
TDB_DATA data;
uint32 store_jobid;
data.dptr = (uint8 *)&store_jobid;
data.dsize = 4;
- DEBUG(10,("add_to_jobs_changed: Added jobid %u\n", (unsigned int)jobid ));
+ DEBUG(10,("add_to_jobs_added: Added jobid %u\n", (unsigned int)jobid ));
- return (tdb_append(pdb->tdb, string_tdb_data("INFO/jobs_changed"),
+ return (tdb_append(pdb->tdb, string_tdb_data("INFO/jobs_added"),
data) == 0);
}
Do all checks needed to determine if we can start a job.
***************************************************************************/
-static WERROR print_job_checks(struct auth_serversupplied_info *server_info,
+static WERROR print_job_checks(const struct auth_serversupplied_info *server_info,
struct messaging_context *msg_ctx,
int snum, int *njobs)
{
Start spooling a job - return the jobid.
***************************************************************************/
-WERROR print_job_start(struct auth_serversupplied_info *server_info,
+WERROR print_job_start(const struct auth_serversupplied_info *server_info,
struct messaging_context *msg_ctx,
+ const char *clientmachine,
int snum, const char *docname, const char *filename,
struct spoolss_DeviceMode *devmode, uint32_t *_jobid)
{
fstrcpy(pjob.jobname, docname);
+ fstrcpy(pjob.clientmachine, clientmachine);
+
fstrcpy(pjob.user, lp_printjob_username(snum));
standard_sub_advanced(sharename, server_info->sanitized_username,
path, server_info->utok.gid,
pjob_store(server_event_context(), msg_ctx, sharename, jobid, &pjob);
- /* Update the 'jobs changed' entry used by print_queue_status. */
- add_to_jobs_changed(pdb, jobid);
+ /* Update the 'jobs added' entry used by print_queue_status. */
+ add_to_jobs_added(pdb, jobid);
/* Ensure we keep a rough count of the number of total jobs... */
tdb_change_int32_atomic(pdb->tdb, "INFO/total_jobs", &njobs, 1);
Update the number of pages spooled to jobid
****************************************************************************/
-void print_job_endpage(int snum, uint32 jobid)
+void print_job_endpage(struct messaging_context *msg_ctx,
+ int snum, uint32 jobid)
{
const char* sharename = lp_const_servicename(snum);
struct printjob *pjob;
return;
pjob->page_count++;
- pjob_store(server_event_context(), server_messaging_context(),
- sharename, jobid, pjob);
+ pjob_store(server_event_context(), msg_ctx, sharename, jobid, pjob);
}
/****************************************************************************
struct tdb_print_db *pdb, int snum,
int *pcount, print_queue_struct **ppqueue)
{
- TDB_DATA data, cgdata;
+ TDB_DATA data, cgdata, jcdata;
print_queue_struct *queue = NULL;
uint32 qcount = 0;
uint32 extra_count = 0;
+ uint32_t changed_count = 0;
int total_count = 0;
size_t len = 0;
uint32 i;
if (data.dptr && data.dsize >= sizeof(qcount))
len += tdb_unpack(data.dptr + len, data.dsize - len, "d", &qcount);
- /* Get the changed jobs list. */
- cgdata = tdb_fetch(pdb->tdb, string_tdb_data("INFO/jobs_changed"));
+ /* Get the added jobs list. */
+ cgdata = tdb_fetch(pdb->tdb, string_tdb_data("INFO/jobs_added"));
if (cgdata.dptr != NULL && (cgdata.dsize % 4 == 0))
extra_count = cgdata.dsize/4;
+ /* Get the changed jobs list. */
+ jcdata = tdb_fetch(pdb->tdb, string_tdb_data("INFO/jobs_changed"));
+ if (jcdata.dptr != NULL && (jcdata.dsize % 4 == 0))
+ changed_count = jcdata.dsize / 4;
+
DEBUG(5,("get_stored_queue_info: qcount = %u, extra_count = %u\n", (unsigned int)qcount, (unsigned int)extra_count));
/* Allocate the queue size. */
total_count = qcount;
- /* Add in the changed jobids. */
+ /* Add new jobids to the queue. */
for( i = 0; i < extra_count; i++) {
uint32 jobid;
struct printjob *pjob;
jobid = IVAL(cgdata.dptr, i*4);
- DEBUG(5,("get_stored_queue_info: changed job = %u\n", (unsigned int)jobid));
+ DEBUG(5,("get_stored_queue_info: added job = %u\n", (unsigned int)jobid));
pjob = print_job_find(lp_const_servicename(snum), jobid);
if (!pjob) {
- DEBUG(5,("get_stored_queue_info: failed to find changed job = %u\n", (unsigned int)jobid));
- remove_from_jobs_changed(sharename, jobid);
+ DEBUG(5,("get_stored_queue_info: failed to find added job = %u\n", (unsigned int)jobid));
+ remove_from_jobs_added(sharename, jobid);
continue;
}
total_count++;
}
+ /* Update the changed jobids. */
+ for (i = 0; i < changed_count; i++) {
+ uint32_t jobid = IVAL(jcdata.dptr, i * 4);
+ uint32_t j;
+ bool found = false;
+
+ for (j = 0; j < total_count; j++) {
+ if (queue[j].job == jobid) {
+ found = true;
+ break;
+ }
+ }
+
+ if (found) {
+ struct printjob *pjob;
+
+ DEBUG(5,("get_stored_queue_info: changed job: %u\n",
+ (unsigned int) jobid));
+
+ pjob = print_job_find(sharename, jobid);
+ if (pjob == NULL) {
+ DEBUG(5,("get_stored_queue_info: failed to find "
+ "changed job = %u\n",
+ (unsigned int) jobid));
+ remove_from_jobs_changed(sharename, jobid);
+ continue;
+ }
+
+ queue[j].job = jobid;
+ queue[j].size = pjob->size;
+ queue[j].page_count = pjob->page_count;
+ queue[j].status = pjob->status;
+ queue[j].priority = 1;
+ queue[j].time = pjob->starttime;
+ fstrcpy(queue[j].fs_user, pjob->user);
+ fstrcpy(queue[j].fs_file, pjob->jobname);
+
+ DEBUG(5,("get_stored_queue_info: updated queue[%u], jobid: %u, jobname: %s\n",
+ (unsigned int) j, (unsigned int) jobid, pjob->jobname));
+ }
+
+ remove_from_jobs_changed(sharename, jobid);
+ }
+
/* Sort the queue by submission time otherwise they are displayed
in hash order. */
Pause a queue.
****************************************************************************/
-WERROR print_queue_pause(struct auth_serversupplied_info *server_info,
+WERROR print_queue_pause(const struct auth_serversupplied_info *server_info,
struct messaging_context *msg_ctx, int snum)
{
int ret;
Resume a queue.
****************************************************************************/
-WERROR print_queue_resume(struct auth_serversupplied_info *server_info,
+WERROR print_queue_resume(const struct auth_serversupplied_info *server_info,
struct messaging_context *msg_ctx, int snum)
{
int ret;
Purge a queue - implemented by deleting all jobs that we can delete.
****************************************************************************/
-WERROR print_queue_purge(struct auth_serversupplied_info *server_info,
+WERROR print_queue_purge(const struct auth_serversupplied_info *server_info,
struct messaging_context *msg_ctx, int snum)
{
print_queue_struct *queue;
queue[i].job);
if (owner || can_job_admin) {
- print_job_delete1(snum, queue[i].job);
+ print_job_delete1(server_event_context(), msg_ctx,
+ snum, queue[i].job);
}
}