Fixed file descriptor leak in error processing of print jobs.
authorJeremy Allison <jra@samba.org>
Thu, 22 Feb 2001 01:31:55 +0000 (01:31 +0000)
committerJeremy Allison <jra@samba.org>
Thu, 22 Feb 2001 01:31:55 +0000 (01:31 +0000)
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/printfsp.c
source3/printing/printing.c
source3/smbd/trans2.c

index f6ab69fd93e2131a204ec6d6e25ef2cd08563887..c87fb9754f285580b97f92f475b432b1edcc5581 100644 (file)
@@ -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) {
index 9ed33bc6aead7808339325202e4578590ead07e3..49681d90409c1c00640039ac73ea7b0059b4924e 100644 (file)
@@ -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 */
index 4e44d71369b16e2c95b5b33b687a4ef78e343e8e..d94a7758462b6f4df1f4c05015f71da347dc073c 100644 (file)
@@ -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));