summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJeremy Allison <jra@samba.org>2001-02-22 01:31:55 +0000
committerJeremy Allison <jra@samba.org>2001-02-22 01:31:55 +0000
commit201753ddc623a18f4ddd0d9a19391ea0471d4c49 (patch)
treef8e52b7b06464d16b93522a8bf9abbb6c343be17
parent5fa7c79c336584b9eb868abaae69f8fb5950c43b (diff)
downloadsamba-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.c8
-rw-r--r--source3/printing/printing.c91
-rw-r--r--source3/smbd/trans2.c20
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));