📄 printing.c
字号:
}/**************************************************************************** Delete a print job.****************************************************************************/BOOL print_job_delete(struct current_user *user, int snum, uint32 jobid, WERROR *errcode){ const char* sharename = lp_const_servicename( snum ); struct printjob *pjob; BOOL owner; char *fname; *errcode = WERR_OK; owner = is_owner(user, snum, jobid); /* Check access against security descriptor or whether the user owns their job. */ if (!owner && !print_access_check(user, snum, JOB_ACCESS_ADMINISTER)) { DEBUG(3, ("delete denied by security descriptor\n")); *errcode = WERR_ACCESS_DENIED; /* BEGIN_ADMIN_LOG */ sys_adminlog( LOG_ERR, "Permission denied-- user not allowed to delete, \pause, or resume print job. User name: %s. Printer name: %s.", uidtoname(user->uid), PRINTERNAME(snum) ); /* END_ADMIN_LOG */ return False; } /* * get the spooled filename of the print job * if this works, then the file has not been spooled * to the underlying print system. Just delete the * spool file & return. */ if ( (fname = print_job_fname( sharename, jobid )) != NULL ) { /* remove the spool file */ DEBUG(10,("print_job_delete: Removing spool file [%s]\n", fname )); if ( unlink( fname ) == -1 ) { *errcode = map_werror_from_unix(errno); return False; } } if (!print_job_delete1(snum, jobid)) { *errcode = WERR_ACCESS_DENIED; return False; } /* force update the database and say the delete failed if the job still exists */ print_queue_update(snum, True); pjob = print_job_find(sharename, jobid); if ( pjob && (pjob->status != LPQ_DELETING) ) *errcode = WERR_ACCESS_DENIED; return (pjob == NULL );}/**************************************************************************** Pause a job.****************************************************************************/BOOL print_job_pause(struct current_user *user, int snum, uint32 jobid, WERROR *errcode){ const char* sharename = lp_const_servicename(snum); struct printjob *pjob; int ret = -1; struct printif *current_printif = get_printer_fns( snum ); pjob = print_job_find(sharename, jobid); if (!pjob || !user) return False; if (!pjob->spooled || pjob->sysjob == -1) return False; if (!is_owner(user, snum, jobid) && !print_access_check(user, snum, JOB_ACCESS_ADMINISTER)) { DEBUG(3, ("pause denied by security descriptor\n")); /* BEGIN_ADMIN_LOG */ sys_adminlog( LOG_ERR, "Permission denied-- user not allowed to delete, \pause, or resume print job. User name: %s. Printer name: %s.", uidtoname(user->uid), PRINTERNAME(snum) ); /* END_ADMIN_LOG */ *errcode = WERR_ACCESS_DENIED; return False; } /* need to pause the spooled entry */ ret = (*(current_printif->job_pause))(snum, pjob); if (ret != 0) { *errcode = WERR_INVALID_PARAM; return False; } /* force update the database */ print_cache_flush(snum); /* Send a printer notify message */ notify_job_status(sharename, jobid, JOB_STATUS_PAUSED); /* how do we tell if this succeeded? */ return True;}/**************************************************************************** Resume a job.****************************************************************************/BOOL print_job_resume(struct current_user *user, int snum, uint32 jobid, WERROR *errcode){ const char *sharename = lp_const_servicename(snum); struct printjob *pjob; int ret; struct printif *current_printif = get_printer_fns( snum ); pjob = print_job_find(sharename, jobid); if (!pjob || !user) return False; if (!pjob->spooled || pjob->sysjob == -1) return False; if (!is_owner(user, snum, jobid) && !print_access_check(user, snum, JOB_ACCESS_ADMINISTER)) { DEBUG(3, ("resume denied by security descriptor\n")); *errcode = WERR_ACCESS_DENIED; /* BEGIN_ADMIN_LOG */ sys_adminlog( LOG_ERR, "Permission denied-- user not allowed to delete, \pause, or resume print job. User name: %s. Printer name: %s.", uidtoname(user->uid), PRINTERNAME(snum) ); /* END_ADMIN_LOG */ return False; } ret = (*(current_printif->job_resume))(snum, pjob); if (ret != 0) { *errcode = WERR_INVALID_PARAM; return False; } /* force update the database */ print_cache_flush(snum); /* Send a printer notify message */ notify_job_status(sharename, jobid, JOB_STATUS_QUEUED); return True;}/**************************************************************************** Write to a print file.****************************************************************************/ssize_t print_job_write(int snum, uint32 jobid, const char *buf, SMB_OFF_T pos, size_t size){ const char* sharename = lp_const_servicename(snum); int return_code; struct printjob *pjob; pjob = print_job_find(sharename, jobid); if (!pjob) return -1; /* don't allow another process to get this info - it is meaningless */ if (pjob->pid != sys_getpid()) return -1; return_code = write_data_at_offset(pjob->fd, buf, size, pos); if (return_code>0) { pjob->size += size; pjob_store(sharename, jobid, pjob); } return return_code;}/**************************************************************************** Get the queue status - do not update if db is out of date.****************************************************************************/static int get_queue_status(const char* sharename, print_status_struct *status){ fstring keystr; TDB_DATA data; struct tdb_print_db *pdb = get_print_db_byname(sharename); int len; if (status) { ZERO_STRUCTP(status); } if (!pdb) return 0; if (status) { fstr_sprintf(keystr, "STATUS/%s", sharename); data = tdb_fetch(pdb->tdb, string_tdb_data(keystr)); if (data.dptr) { if (data.dsize == sizeof(print_status_struct)) /* this memcpy is ok since the status struct was not packed before storing it in the tdb */ memcpy(status, data.dptr, sizeof(print_status_struct)); SAFE_FREE(data.dptr); } } len = tdb_fetch_int32(pdb->tdb, "INFO/total_jobs"); release_print_db(pdb); return (len == -1 ? 0 : len);}/**************************************************************************** Determine the number of jobs in a queue.****************************************************************************/int print_queue_length(int snum, print_status_struct *pstatus){ const char* sharename = lp_const_servicename( snum ); print_status_struct status; int len; ZERO_STRUCT( status ); /* make sure the database is up to date */ if (print_cache_expired(lp_const_servicename(snum), True)) print_queue_update(snum, False); /* also fetch the queue status */ memset(&status, 0, sizeof(status)); len = get_queue_status(sharename, &status); if (pstatus) *pstatus = status; return len;}/*************************************************************************** Allocate a jobid. Hold the lock for as short a time as possible.***************************************************************************/static BOOL allocate_print_jobid(struct tdb_print_db *pdb, int snum, const char *sharename, uint32 *pjobid){ int i; uint32 jobid; *pjobid = (uint32)-1; for (i = 0; i < 3; i++) { /* Lock the database - only wait 20 seconds. */ if (tdb_lock_bystring(pdb->tdb, "INFO/nextjob", 20) == -1) { DEBUG(0,("allocate_print_jobid: failed to lock printing database %s\n", sharename)); return False; } if (!tdb_fetch_uint32(pdb->tdb, "INFO/nextjob", &jobid)) { if (tdb_error(pdb->tdb) != TDB_ERR_NOEXIST) { DEBUG(0, ("allocate_print_jobid: failed to fetch INFO/nextjob for print queue %s\n", sharename)); return False; } jobid = 0; } jobid = NEXT_JOBID(jobid); if (tdb_store_int32(pdb->tdb, "INFO/nextjob", jobid)==-1) { DEBUG(3, ("allocate_print_jobid: failed to store INFO/nextjob.\n")); tdb_unlock_bystring(pdb->tdb, "INFO/nextjob"); return False; } /* We've finished with the INFO/nextjob lock. */ tdb_unlock_bystring(pdb->tdb, "INFO/nextjob"); if (!print_job_exists(sharename, jobid)) break; } if (i > 2) { DEBUG(0, ("allocate_print_jobid: failed to allocate a print job for queue %s\n", sharename)); /* Probably full... */ errno = ENOSPC; return False; } /* Store a dummy placeholder. */ { TDB_DATA dum; dum.dptr = NULL; dum.dsize = 0; if (tdb_store(pdb->tdb, print_key(jobid), dum, TDB_INSERT) == -1) { DEBUG(3, ("allocate_print_jobid: jobid (%d) failed to store placeholder.\n", jobid )); return False; } } *pjobid = jobid; return True;}/*************************************************************************** Append a jobid to the 'jobs changed' list.***************************************************************************/static BOOL add_to_jobs_changed(struct tdb_print_db *pdb, uint32 jobid){ TDB_DATA data; uint32 store_jobid; SIVAL(&store_jobid, 0, jobid); data.dptr = (char *)&store_jobid; data.dsize = 4; DEBUG(10,("add_to_jobs_changed: Added jobid %u\n", (unsigned int)jobid )); return (tdb_append(pdb->tdb, string_tdb_data("INFO/jobs_changed"), data) == 0);}/*************************************************************************** Start spooling a job - return the jobid.***************************************************************************/uint32 print_job_start(struct current_user *user, int snum, char *jobname, NT_DEVICEMODE *nt_devmode ){ uint32 jobid; char *path; struct printjob pjob; user_struct *vuser; const char *sharename = lp_const_servicename(snum); struct tdb_print_db *pdb = get_print_db_byname(sharename); int njobs; errno = 0; if (!pdb) return (uint32)-1; if (!print_access_check(user, snum, PRINTER_ACCESS_USE)) { DEBUG(3, ("print_job_start: job start denied by security descriptor\n")); release_print_db(pdb); return (uint32)-1; } if (!print_time_access_check(snum)) { DEBUG(3, ("print_job_start: job start denied by time check\n")); release_print_db(pdb); return (uint32)-1; } path = lp_pathname(snum); /* see if we have sufficient disk space */ if (lp_minprintspace(snum)) { SMB_BIG_UINT dspace, dsize; if (sys_fsusage(path, &dspace, &dsize) == 0 && dspace < 2*(SMB_BIG_UINT)lp_minprintspace(snum)) { DEBUG(3, ("print_job_start: disk space check failed.\n")); release_print_db(pdb); errno = ENOSPC; return (uint32)-1; } } /* for autoloaded printers, check that the printcap entry still exists */ if (lp_autoloaded(snum) && !pcap_printername_ok(lp_const_servicename(snum))) { DEBUG(3, ("print_job_start: printer name %s check failed.\n", lp_const_servicename(snum) )); release_print_db(pdb); errno = ENOENT; return (uint32)-1; } /* Insure the maximum queue size is not violated */ if ((njobs = print_queue_length(snum,NULL)) > lp_maxprintjobs(snum)) { DEBUG(3, ("print_job_start: Queue %s number of jobs (%d) larger than max printjobs per queue (%d).\n", sharename, njobs, lp_maxprintjobs(snum) )); release_print_db(pdb); errno = ENOSPC; return (uint32)-1; } DEBUG(10,("print_job_start: Queue %s number of jobs (%d), max printjobs = %d\n", sharename, njobs, lp_maxprintjobs(snum) )); if (!allocate_print_jobid(pdb, snum, sharename, &jobid)) goto fail; /* create the database entry */ ZERO_STRUCT(pjob); pjob.pid = sys_getpid(); pjob.sysjob = -1; pjob.fd = -1; pjob.starttime = time(NULL); pjob.status = LPQ_SPOOLING; pjob.size = 0; pjob.spooled = False; pjob.smbjob = True; pjob.nt_devmode = nt_devmode; fstrcpy(pjob.jobname, jobname); if ((vuser = get_valid_user_struct(user->vuid)) != NULL) { fstrcpy(pjob.user, vuser->user.smb_name); } else { fstrcpy(pjob.user, uidtoname(user->uid)); } fstrcpy(pjob.queuename, lp_const_servicename(snum)); /* we have a job entry - now create the spool file */ slprintf(pjob.filename, sizeof(pjob.filename)-1, "%s/%s%.8u.XXXXXX", path, PRINT_SPOOL_PREFIX, (unsigned int)jobid); pjob.fd = smb_mkstemp(pjob.filename); if (pjob.fd == -1) { if (errno == EACCES) { /* Common setup error, force a report. */ DEBUG(0, ("print_job_start: insufficient permissions \to open spool file %s.\n", pjob.filename)); } else { /* Normal case, report at level 3 and above. */ DEBUG(3, ("print_job_start: can't open spool file %s,\n", pjob.filename)); DEBUGADD(3, ("errno = %d (%s).\n", errno, strerror(errno))); } goto fail; } pjob_store(sharename, jobid, &pjob); /* Update the 'jobs changed' entry used by print_queue_status. */ add_to_jobs_changed(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); release_print_db(pdb); return jobid; fail: if (jobid != -1) pjob_delete(sharename, jobid); release_print_db(pdb); DEBUG(3, ("print_job_start: returning fail. Error = %s\n", strerror(errno) )); return (uint32)-1;}/**************************************************************************** Update the number of pages spooled to jobid****************************************************************************/void print_job_endpage(int snum, uint32 jobid){ const char* s
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -