⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 printing.c

📁 samba-3.0.22.tar.gz 编译smb服务器的源码
💻 C
📖 第 1 页 / 共 5 页
字号:
	if (new_job || !strequal(old_data->jobname, new_data->jobname))		notify_job_name(sharename, jobid, new_data->jobname);	if (new_job || old_data->status != new_data->status)		notify_job_status(sharename, jobid, map_to_spoolss_status(new_data->status));	if (new_job || old_data->size != new_data->size)		notify_job_total_bytes(sharename, jobid, new_data->size);	if (new_job || old_data->page_count != new_data->page_count)		notify_job_total_pages(sharename, jobid, new_data->page_count);}/**************************************************************************** Store a job structure back to the database.****************************************************************************/static BOOL pjob_store(const char* sharename, uint32 jobid, struct printjob *pjob){	TDB_DATA 		old_data, new_data;	BOOL 			ret = False;	struct tdb_print_db 	*pdb = get_print_db_byname(sharename);	char			*buf = NULL;	int			len, newlen, buflen;		if (!pdb)		return False;	/* Get old data */	old_data = tdb_fetch(pdb->tdb, print_key(jobid));	/* Doh!  Now we have to pack/unpack data since the NT_DEVICEMODE was added */	newlen = 0;		do {		len = 0;		buflen = newlen;		len += tdb_pack(buf+len, buflen-len, "dddddddddffff",				(uint32)pjob->pid,				(uint32)pjob->sysjob,				(uint32)pjob->fd,				(uint32)pjob->starttime,				(uint32)pjob->status,				(uint32)pjob->size,				(uint32)pjob->page_count,				(uint32)pjob->spooled,				(uint32)pjob->smbjob,				pjob->filename,				pjob->jobname,				pjob->user,				pjob->queuename);		len += pack_devicemode(pjob->nt_devmode, buf+len, buflen-len);			if (buflen != len) {			char *tb;			tb = (char *)SMB_REALLOC(buf, len);			if (!tb) {				DEBUG(0,("pjob_store: failed to enlarge buffer!\n"));				goto done;			}			else 				buf = tb;			newlen = len;		}	} while ( buflen != len );				/* Store new data */	new_data.dptr = buf;	new_data.dsize = len;	ret = (tdb_store(pdb->tdb, print_key(jobid), new_data, TDB_REPLACE) == 0);	release_print_db(pdb);	/* Send notify updates for what has changed */	if ( ret ) {		struct printjob old_pjob;		if ( old_data.dsize )		{			if ( unpack_pjob( old_data.dptr, old_data.dsize, &old_pjob ) != -1 )			{				pjob_store_notify( sharename, jobid, &old_pjob , pjob );				free_nt_devicemode( &old_pjob.nt_devmode );			}		}		else {			/* new job */			pjob_store_notify( sharename, jobid, NULL, pjob );		}	}done:	SAFE_FREE( old_data.dptr );	SAFE_FREE( buf );	return ret;}/**************************************************************************** Remove a job structure from the database.****************************************************************************/void pjob_delete(const char* sharename, uint32 jobid){	struct printjob *pjob;	uint32 job_status = 0;	struct tdb_print_db *pdb;	pdb = get_print_db_byname( sharename );	if (!pdb)		return;	pjob = print_job_find( 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;	}	/* We must cycle through JOB_STATUS_DELETING and           JOB_STATUS_DELETED for the port monitor to delete the job           properly. */		job_status = JOB_STATUS_DELETING|JOB_STATUS_DELETED;	notify_job_status(sharename, jobid, job_status);		/* Remove from printing.tdb */	tdb_delete(pdb->tdb, print_key(jobid));	remove_from_jobs_changed(sharename, jobid);	release_print_db( pdb );	rap_jobid_delete(sharename, jobid);}/**************************************************************************** Parse a file name from the system spooler to generate a jobid.****************************************************************************/static uint32 print_parse_jobid(char *fname){	int jobid;	if (strncmp(fname,PRINT_SPOOL_PREFIX,strlen(PRINT_SPOOL_PREFIX)) != 0)		return (uint32)-1;	fname += strlen(PRINT_SPOOL_PREFIX);	jobid = atoi(fname);	if (jobid <= 0)		return (uint32)-1;	return (uint32)jobid;}/**************************************************************************** List a unix job in the print database.****************************************************************************/static void print_unix_job(const char *sharename, print_queue_struct *q, uint32 jobid){	struct printjob pj, *old_pj;	if (jobid == (uint32)-1) 		jobid = q->job + UNIX_JOB_START;	/* Preserve the timestamp on an existing unix print job */	old_pj = print_job_find(sharename, jobid);	ZERO_STRUCT(pj);	pj.pid = (pid_t)-1;	pj.sysjob = q->job;	pj.fd = -1;	pj.starttime = old_pj ? old_pj->starttime : q->time;	pj.status = q->status;	pj.size = q->size;	pj.spooled = True;	fstrcpy(pj.filename, old_pj ? old_pj->filename : "");	if (jobid < UNIX_JOB_START) {		pj.smbjob = True;		fstrcpy(pj.jobname, old_pj ? old_pj->jobname : "Remote Downlevel Document");	} else {		pj.smbjob = False;		fstrcpy(pj.jobname, old_pj ? old_pj->jobname : q->fs_file);	}	fstrcpy(pj.user, old_pj ? old_pj->user : q->fs_user);	fstrcpy(pj.queuename, old_pj ? old_pj->queuename : sharename );	pjob_store(sharename, jobid, &pj);}struct traverse_struct {	print_queue_struct *queue;	int qcount, snum, maxcount, total_jobs;	const char *sharename;	time_t lpq_time;	const char *lprm_command;	struct printif *print_if;};/**************************************************************************** Utility fn to delete any jobs that are no longer active.****************************************************************************/static int traverse_fn_delete(TDB_CONTEXT *t, TDB_DATA key, TDB_DATA data, void *state){	struct traverse_struct *ts = (struct traverse_struct *)state;	struct printjob pjob;	uint32 jobid;	int i = 0;	if (  key.dsize != sizeof(jobid) )		return 0;			jobid = IVAL(key.dptr, 0);	if ( unpack_pjob( data.dptr, data.dsize, &pjob ) == -1 )		return 0;	free_nt_devicemode( &pjob.nt_devmode );	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)				break;		}		if (i == ts->qcount) {			DEBUG(10,("traverse_fn_delete: pjob %u deleted due to !smbjob\n",						(unsigned int)jobid ));			pjob_delete(ts->sharename, jobid);			return 0;		} 		/* need to continue the the bottom of the function to		   save the correct attributes */	}	/* maybe it hasn't been spooled yet */	if (!pjob.spooled) {		/* if a job is not spooled and the process doesn't                   exist then kill it. This cleans up after smbd                   deaths */		if (!process_exists_by_pid(pjob.pid)) {			DEBUG(10,("traverse_fn_delete: pjob %u deleted due to !process_exists (%u)\n",						(unsigned int)jobid, (unsigned int)pjob.pid ));			pjob_delete(ts->sharename, jobid);		} else			ts->total_jobs++;		return 0;	}	/* this check only makes sense for jobs submitted from Windows clients */		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) {				/* try to clean up any jobs that need to be deleted */				if ( pjob.status == LPQ_DELETING ) {					int result;					result = (*(ts->print_if->job_delete))( 						ts->sharename, ts->lprm_command, &pjob );					if ( result != 0 ) {						/* if we can't delete, then reset the job status */						pjob.status = LPQ_QUEUED;						pjob_store(ts->sharename, jobid, &pjob);					}					else {						/* if we deleted the job, the remove the tdb record */						pjob_delete(ts->sharename, jobid);						pjob.status = LPQ_DELETED;					}										}				break;			}		}	}		/* The job isn't in the system queue - we have to assume it has	   completed, so delete the database entry. */	if (i == ts->qcount) {		/* A race can occur between the time a job is spooled and		   when it appears in the lpq output.  This happens when		   the job is added to printing.tdb when another smbd		   running print_queue_update() has completed a lpq and		   is currently traversing the printing tdb and deleting jobs.		   Don't delete the job if it was submitted after the lpq_time. */		if (pjob.starttime < ts->lpq_time) {			DEBUG(10,("traverse_fn_delete: pjob %u deleted due to pjob.starttime (%u) < ts->lpq_time (%u)\n",						(unsigned int)jobid,						(unsigned int)pjob.starttime,						(unsigned int)ts->lpq_time ));			pjob_delete(ts->sharename, jobid);		} else			ts->total_jobs++;		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;			ts->queue[i].size = pjob.size;	ts->queue[i].page_count = pjob.page_count;	ts->queue[i].status = pjob.status;	ts->queue[i].priority = 1;	ts->queue[i].time = pjob.starttime;	fstrcpy(ts->queue[i].fs_user, pjob.user);	fstrcpy(ts->queue[i].fs_file, pjob.jobname);	ts->total_jobs++;	return 0;}/**************************************************************************** Check if the print queue has been updated recently enough.****************************************************************************/static void print_cache_flush(int snum){	fstring key;	const char *sharename = lp_const_servicename(snum);	struct tdb_print_db *pdb = get_print_db_byname(sharename);	if (!pdb)		return;	slprintf(key, sizeof(key)-1, "CACHE/%s", sharename);	tdb_store_int32(pdb->tdb, key, -1);	release_print_db(pdb);}/**************************************************************************** Check if someone already thinks they are doing the update.****************************************************************************/static pid_t get_updating_pid(const char *sharename){	fstring keystr;	TDB_DATA data, key;	pid_t updating_pid;	struct tdb_print_db *pdb = get_print_db_byname(sharename);	if (!pdb)		return (pid_t)-1;	slprintf(keystr, sizeof(keystr)-1, "UPDATING/%s", sharename);    	key.dptr = keystr;	key.dsize = strlen(keystr);	data = tdb_fetch(pdb->tdb, key);	release_print_db(pdb);	if (!data.dptr || data.dsize != sizeof(pid_t)) {		SAFE_FREE(data.dptr);		return (pid_t)-1;	}	updating_pid = IVAL(data.dptr, 0);	SAFE_FREE(data.dptr);	if (process_exists_by_pid(updating_pid))		return updating_pid;	return (pid_t)-1;}/**************************************************************************** Set the fact that we're doing the update, or have finished doing the update in the tdb.****************************************************************************/static void set_updating_pid(const fstring sharename, BOOL updating){	fstring keystr;	TDB_DATA key;	TDB_DATA data;	pid_t updating_pid = sys_getpid();	uint8 buffer[4];		struct tdb_print_db *pdb = get_print_db_byname(sharename);	if (!pdb)		return;	slprintf(keystr, sizeof(keystr)-1, "UPDATING/%s", sharename);    	key.dptr = keystr;	key.dsize = strlen(keystr);		DEBUG(5, ("set_updating_pid: %s updating lpq cache for print share %s\n", 		updating ? "" : "not ",		sharename ));	if ( !updating ) {		tdb_delete(pdb->tdb, key);		release_print_db(pdb);		return;	}		SIVAL( buffer, 0, updating_pid);	data.dptr = (void *)buffer;	data.dsize = 4;		/* we always assume this is a 4 byte value */	tdb_store(pdb->tdb, key, data, TDB_REPLACE);		release_print_db(pdb);}/**************************************************************************** Sort print jobs by submittal time.****************************************************************************/static int printjob_comp(print_queue_struct *j1, print_queue_struct *j2){	/* Silly cases */	if (!j1 && !j2)		return 0;	if (!j1)		return -1;	if (!j2)		return 1;	/* Sort on job start time */	if (j1->time == j2->time)		return 0;	return (j1->time > j2->time) ? 1 : -1;}/**************************************************************************** Store the sorted queue representation for later portmon retrieval. Skip deleted jobs****************************************************************************/static void store_queue_struct(struct tdb_print_db *pdb, struct traverse_struct *pts){	TDB_DATA data;	int max_reported_jobs = lp_max_reported_jobs(pts->snum);	print_queue_struct *queue = pts->queue;	size_t len;	size_t i;	uint qcount;	if (max_reported_jobs && (max_reported_jobs < pts->qcount))		pts->qcount = max_reported_jobs;	qcount = 0;	/* Work out the size. */	data.dsize = 0;	data.dsize += tdb_pack(NULL, 0, "d", qcount);	for (i = 0; i < pts->qcount; i++) {		if ( queue[i].status == LPQ_DELETED )			continue;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -