From 201753ddc623a18f4ddd0d9a19391ea0471d4c49 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 22 Feb 2001 01:31:55 +0000 Subject: Fixed file descriptor leak in error processing of print jobs. NT sends "delete on close" to cancel a print job copied from the command line. Deal with this. Merged JohnR's fixes for print job errors. Jeremy. (This used to be commit 2060d74e48d62c99a1689ee02ac435b71918ddf0) --- source3/printing/printing.c | 91 +++++++++++++++++++-------------------------- 1 file changed, 39 insertions(+), 52 deletions(-) (limited to 'source3/printing/printing.c') diff --git a/source3/printing/printing.c b/source3/printing/printing.c index 9ed33bc6ae..49681d9040 100644 --- a/source3/printing/printing.c +++ b/source3/printing/printing.c @@ -38,6 +38,9 @@ extern int DEBUGLEVEL; jobids are assigned when a job starts spooling. */ +#define NEXT_JOBID(j) ((j+1) % PRINT_MAX_JOBID > 0 ? (j+1) % PRINT_MAX_JOBID : 1) + + struct printjob { pid_t pid; /* which process launched the job */ int sysjob; /* the system (lp) job number */ @@ -588,9 +591,11 @@ static BOOL is_owner(struct current_user *user, int jobid) if (!pjob || !user) return False; if ((vuser = get_valid_user_struct(user->vuid)) != NULL) { - return strequal(pjob->user, vuser->user.smb_name); + return strequal(pjob->user, + unix_to_dos(vuser->user.smb_name,False)); } else { - return strequal(pjob->user, uidtoname(user->uid)); + return strequal(pjob->user, + unix_to_dos(uidtoname(user->uid),False)); } } @@ -884,9 +889,9 @@ int print_job_start(struct current_user *user, int snum, char *jobname) fstrcpy(pjob.jobname, jobname); if ((vuser = get_valid_user_struct(user->vuid)) != NULL) { - fstrcpy(pjob.user, vuser->user.smb_name); + fstrcpy(pjob.user, unix_to_dos(vuser->user.smb_name,False)); } else { - fstrcpy(pjob.user, uidtoname(user->uid)); + fstrcpy(pjob.user, unix_to_dos(uidtoname(user->uid),False)); } fstrcpy(pjob.qname, lp_servicename(snum)); @@ -898,10 +903,8 @@ int print_job_start(struct current_user *user, int snum, char *jobname) next_jobid = tdb_fetch_int(tdb, "INFO/nextjob"); if (next_jobid == -1) next_jobid = 1; - for (jobid = next_jobid+1; jobid != next_jobid; ) { + for (jobid = NEXT_JOBID(next_jobid); jobid != next_jobid; jobid = NEXT_JOBID(jobid)) { if (!print_job_exists(jobid)) break; - jobid = (jobid + 1) % PRINT_MAX_JOBID; - if (jobid == 0) jobid = 1; } if (jobid == next_jobid || !print_job_store(jobid, &pjob)) { jobid = -1; @@ -922,23 +925,7 @@ int print_job_start(struct current_user *user, int snum, char *jobname) goto next_jobnum; } pjob.fd = sys_open(pjob.filename,O_WRONLY|O_CREAT|O_EXCL,0600); - 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; - } + if (pjob.fd == -1) goto fail; print_job_store(jobid, &pjob); @@ -1000,12 +987,14 @@ BOOL print_job_end(int jobid, BOOL normal_close) * Not a normal close or we couldn't stat the job file, * so something has gone wrong. Cleanup. */ - - unlink(pjob->filename); - tdb_delete(tdb, print_key(jobid)); - return False; + close(pjob->fd); + pjob->fd = -1; + goto fail; } - + + /* Technically, this is not quit right. If the printer has a separator + * page turned on, the NT spooler prints the separator page even if the + * print job is 0 bytes. 010215 JRR */ if (pjob->size == 0) { /* don't bother spooling empty files */ unlink(pjob->filename); @@ -1016,17 +1005,14 @@ BOOL print_job_end(int jobid, BOOL normal_close) /* we print from the directory path to give the best chance of parsing the lpq output */ wd = sys_getwd(current_directory); - if (!wd) - return False; + if (!wd) goto fail; pstrcpy(print_directory, pjob->filename); p = strrchr(print_directory,'/'); - if (!p) - return False; + if (!p) goto fail; *p++ = 0; - if (chdir(print_directory) != 0) - return False; + if (chdir(print_directory) != 0) goto fail; pstrcpy(jobname, pjob->jobname); pstring_sub(jobname, "'", "_"); @@ -1041,23 +1027,24 @@ BOOL print_job_end(int jobid, BOOL normal_close) chdir(wd); - if (ret == 0) { - /* The print job has been sucessfully handed over to the back-end */ - - pjob->spooled = True; - print_job_store(jobid, pjob); - - /* make sure the database is up to date */ - if (print_cache_expired(snum)) print_queue_update(snum); - - return True; - } else { - /* The print job was not succesfully started. Cleanup */ - /* Still need to add proper error return propagation! 010122:JRR */ - unlink(pjob->filename); - tdb_delete(tdb, print_key(jobid)); - return False; - } + if (ret) goto fail; + + /* The print job has been sucessfully handed over to the back-end */ + + pjob->spooled = True; + print_job_store(jobid, pjob); + + /* make sure the database is up to date */ + if (print_cache_expired(snum)) print_queue_update(snum); + + return True; + +fail: + /* The print job was not succesfully started. Cleanup */ + /* Still need to add proper error return propagation! 010122:JRR */ + unlink(pjob->filename); + tdb_delete(tdb, print_key(jobid)); + return False; } /* utility fn to enumerate the print queue */ -- cgit