r6890: Refactor printing interface to take offset into job. Fixes bug
authorJeremy Allison <jra@samba.org>
Wed, 18 May 2005 18:02:15 +0000 (18:02 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 15:56:56 +0000 (10:56 -0500)
where large print jobs can have out-of-order offsets. Bug found
by Arcady Chernyak <Arcady.Chernyak@efi.com>
Jeremy.
(This used to be commit 482f7e0e3706098b71aa0b31a134994acb1e9fcf)

source3/lib/util.c
source3/lib/util_sock.c
source3/printing/printing.c
source3/rpc_server/srv_spoolss_nt.c
source3/smbd/fileio.c

index f31bcef281adfa79f0ea701583ba50d2a92806bc..f92ffaedc02e3f69a45102cb0dab4cf78495c272 100644 (file)
@@ -640,6 +640,46 @@ void close_low_fds(BOOL stderr_too)
 #endif
 }
 
+/*******************************************************************
+ Write data into an fd at a given offset. Ignore seek errors.
+********************************************************************/
+
+ssize_t write_data_at_offset(int fd, const char *buffer, size_t N, SMB_OFF_T pos)
+{
+       size_t total=0;
+       ssize_t ret;
+
+       if (pos == (SMB_OFF_T)-1) {
+               return write_data(fd, buffer, N);
+       }
+#if defined(HAVE_PWRITE) || defined(HAVE_PRWITE64)
+       while (total < N) {
+               ret = sys_pwrite(fd,buffer + total,N - total, pos);
+               if (ret == -1 && errno == ESPIPE) {
+                       return write_data(fd, buffer + total,N - total);
+               }
+               if (ret == -1) {
+                       DEBUG(0,("write_data_at_offset: write failure. Error = %s\n", strerror(errno) ));
+                       return -1;
+               }
+               if (ret == 0) {
+                       return total;
+               }
+               total += ret;
+               pos += ret;
+       }
+       return (ssize_t)total;
+#else
+       /* Use lseek and write_data. */
+       if (sys_lseek(fd, pos, SEEK_SET) == -1) {
+               if (errno != ESPIPE) {
+                       return -1;
+               }
+       }
+       return write_data(fd, buffer, N);
+#endif
+}
+
 /****************************************************************************
  Set a fd into blocking/nonblocking mode. Uses POSIX O_NONBLOCK if available,
  else
index 4222c3c5ef523c2663118c02cbc2137d569f4d79..72837d73d92dc679ff97a86f04f2f68b2125b29a 100644 (file)
@@ -403,7 +403,7 @@ static ssize_t read_socket_data(int fd,char *buffer,size_t N)
  Write data to a fd.
 ****************************************************************************/
 
-ssize_t write_data(int fd,char *buffer,size_t N)
+ssize_t write_data(int fd, const char *buffer, size_t N)
 {
        size_t total=0;
        ssize_t ret;
@@ -427,7 +427,7 @@ ssize_t write_data(int fd,char *buffer,size_t N)
  Write data to a socket - use send rather than write.
 ****************************************************************************/
 
-static ssize_t write_socket_data(int fd,char *buffer,size_t N)
+static ssize_t write_socket_data(int fd, const char *buffer, size_t N)
 {
        size_t total=0;
        ssize_t ret;
@@ -451,7 +451,7 @@ static ssize_t write_socket_data(int fd,char *buffer,size_t N)
  Write to a socket.
 ****************************************************************************/
 
-ssize_t write_socket(int fd,char *buf,size_t len)
+ssize_t write_socket(int fd, const char *buf, size_t len)
 {
        ssize_t ret=0;
 
@@ -489,7 +489,7 @@ BOOL send_keepalive(int client)
  Timeout is in milliseconds.
 ****************************************************************************/
 
-static ssize_t read_smb_length_return_keepalive(int fd,char *inbuf,unsigned int timeout)
+static ssize_t read_smb_length_return_keepalive(int fd, char *inbuf, unsigned int timeout)
 {
        ssize_t len=0;
        int msg_type;
@@ -523,7 +523,7 @@ static ssize_t read_smb_length_return_keepalive(int fd,char *inbuf,unsigned int
  Timeout is in milliseconds.
 ****************************************************************************/
 
-ssize_t read_smb_length(int fd,char *inbuf,unsigned int timeout)
+ssize_t read_smb_length(int fd, char *inbuf, unsigned int timeout)
 {
        ssize_t len;
 
@@ -552,7 +552,7 @@ ssize_t read_smb_length(int fd,char *inbuf,unsigned int timeout)
  Doesn't check the MAC on signed packets.
 ****************************************************************************/
 
-BOOL receive_smb_raw(int fd,char *buffer, unsigned int timeout)
+BOOL receive_smb_raw(int fd, char *buffer, unsigned int timeout)
 {
        ssize_t len,ret;
 
@@ -617,7 +617,7 @@ BOOL receive_smb_raw(int fd,char *buffer, unsigned int timeout)
  Checks the MAC on signed packets.
 ****************************************************************************/
 
-BOOL receive_smb(int fd,char *buffer, unsigned int timeout)
+BOOL receive_smb(int fd, char *buffer, unsigned int timeout)
 {
        if (!receive_smb_raw(fd, buffer, timeout)) {
                return False;
@@ -638,7 +638,7 @@ BOOL receive_smb(int fd,char *buffer, unsigned int timeout)
  Send an smb to a fd.
 ****************************************************************************/
 
-BOOL send_smb(int fd,char *buffer)
+BOOL send_smb(int fd, char *buffer)
 {
        size_t len;
        size_t nwritten=0;
index 03bdb7d4212cad494c5a2139bd02253f5f0ce5d2..ab86db53f38ef6ffb593e42a7d0b2bceb5f8c1d2 100644 (file)
@@ -2031,7 +2031,7 @@ pause, or resume print job. User name: %s. Printer name: %s.",
  Write to a print file.
 ****************************************************************************/
 
-int print_job_write(int snum, uint32 jobid, const char *buf, int size)
+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;
@@ -2045,7 +2045,8 @@ int print_job_write(int snum, uint32 jobid, const char *buf, int size)
        if (pjob->pid != sys_getpid())
                return -1;
 
-       return_code = write(pjob->fd, buf, size);
+       return_code = write_data_at_offset(pjob->fd, buf, size, pos);
+
        if (return_code>0) {
                pjob->size += size;
                pjob_store(sharename, jobid, pjob);
index 7daf1630fe2e3545896b061a497d2dd0f7846826..b7091b2ade74f30fc8663d3a405e2668696d3433 100644 (file)
@@ -5798,8 +5798,9 @@ WERROR _spoolss_writeprinter(pipes_struct *p, SPOOL_Q_WRITEPRINTER *q_u, SPOOL_R
        if (!get_printer_snum(p, handle, &snum))
                return WERR_BADFID;
 
-       (*buffer_written) = print_job_write(snum, Printer->jobid, (char *)buffer, buffer_size);
-       if (*buffer_written == -1) {
+       (*buffer_written) = (uint32)print_job_write(snum, Printer->jobid, (const char *)buffer,
+                                       (SMB_OFF_T)-1, (size_t)buffer_size);
+       if (*buffer_written == (uint32)-1) {
                r_u->buffer_written = 0;
                if (errno == ENOSPC)
                        return WERR_NO_SPOOL_SPACE;
index 977988fde465eb46fa505ea85798f7a35628e397..9b39bf8fe1e6d81c98fe2ac08d6d509575844f9b 100644 (file)
@@ -117,7 +117,7 @@ static unsigned int allocated_write_caches;
  *Really* write to a file.
 ****************************************************************************/
 
-static ssize_t real_write_file(files_struct *fsp,char *data,SMB_OFF_T pos, size_t n)
+static ssize_t real_write_file(files_struct *fsp,const char *data, SMB_OFF_T pos, size_t n)
 {
        ssize_t ret;
 
@@ -192,7 +192,7 @@ static int wcp_file_size_change(files_struct *fsp)
  Write to a file.
 ****************************************************************************/
 
-ssize_t write_file(files_struct *fsp, char *data, SMB_OFF_T pos, size_t n)
+ssize_t write_file(files_struct *fsp, const char *data, SMB_OFF_T pos, size_t n)
 {
        write_cache *wcp = fsp->wcp;
        ssize_t total_written = 0;
@@ -209,7 +209,7 @@ ssize_t write_file(files_struct *fsp, char *data, SMB_OFF_T pos, size_t n)
                        return -1;
                }
 
-               return print_job_write(SNUM(fsp->conn), jobid, data, n);
+               return print_job_write(SNUM(fsp->conn), jobid, data, pos, n);
        }
 
        if (!fsp->can_write) {