diff options
author | Jeremy Allison <jra@samba.org> | 2001-02-22 01:31:55 +0000 |
---|---|---|
committer | Jeremy Allison <jra@samba.org> | 2001-02-22 01:31:55 +0000 |
commit | 201753ddc623a18f4ddd0d9a19391ea0471d4c49 (patch) | |
tree | f8e52b7b06464d16b93522a8bf9abbb6c343be17 | |
parent | 5fa7c79c336584b9eb868abaae69f8fb5950c43b (diff) | |
download | samba-201753ddc623a18f4ddd0d9a19391ea0471d4c49.tar.gz samba-201753ddc623a18f4ddd0d9a19391ea0471d4c49.tar.xz samba-201753ddc623a18f4ddd0d9a19391ea0471d4c49.zip |
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)
-rw-r--r-- | source3/printing/printfsp.c | 8 | ||||
-rw-r--r-- | source3/printing/printing.c | 91 | ||||
-rw-r--r-- | source3/smbd/trans2.c | 20 |
3 files changed, 64 insertions, 55 deletions
diff --git a/source3/printing/printfsp.c b/source3/printing/printfsp.c index f6ab69fd93e..c87fb9754f2 100644 --- a/source3/printing/printfsp.c +++ b/source3/printing/printfsp.c @@ -84,6 +84,14 @@ print a file - called on closing the file ****************************************************************************/ void print_fsp_end(files_struct *fsp, BOOL normal_close) { + if (fsp->share_mode == FILE_DELETE_ON_CLOSE) { + /* + * Truncate the job. print_job_end will take + * care of deleting it for us. JRA. + */ + sys_ftruncate(fsp->fd, 0); + } + print_job_end(fsp->print_jobid, normal_close); if (fsp->fsp_name) { diff --git a/source3/printing/printing.c b/source3/printing/printing.c index 9ed33bc6aea..49681d90409 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 */ diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 4e44d71369b..d94a7758462 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1594,9 +1594,6 @@ static int call_trans2setfilepathinfo(connection_struct *conn, BOOL bad_path = False; files_struct *fsp = NULL; - if (!CAN_WRITE(conn)) - return(ERROR(ERRSRV,ERRaccess)); - if (tran_call == TRANSACT2_SETFILEINFO) { fsp = file_fsp(params,0); info_level = SVAL(params,2); @@ -1618,6 +1615,20 @@ static int call_trans2setfilepathinfo(connection_struct *conn, } return(UNIXERROR(ERRDOS,ERRbadpath)); } + } else if (fsp->print_file) { + /* + * Doing a DELETE_ON_CLOSE should cancel a print job. + */ + if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) { + fsp->share_mode = FILE_DELETE_ON_CLOSE; + + DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", + fsp->fsp_name )); + + SSVAL(params,0,0); + send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0); + return(-1); + } } else { /* * Original code - this is an open file. @@ -1660,6 +1671,9 @@ static int call_trans2setfilepathinfo(connection_struct *conn, } } + if (!CAN_WRITE(conn)) + return(ERROR(ERRSRV,ERRaccess)); + DEBUG(3,("call_trans2setfilepathinfo(%d) %s info_level=%d totdata=%d\n", tran_call,fname,info_level,total_data)); |