From fe0ce8dd8e18de6110404661f26db7a66ebac5ad Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 18 May 2005 18:02:15 +0000 Subject: r6890: Refactor printing interface to take offset into job. Fixes bug where large print jobs can have out-of-order offsets. Bug found by Arcady Chernyak Jeremy. (This used to be commit 482f7e0e3706098b71aa0b31a134994acb1e9fcf) --- source3/lib/util.c | 40 +++++++++++++++++++++++++++++++++++++ source3/lib/util_sock.c | 16 +++++++-------- source3/printing/printing.c | 5 +++-- source3/rpc_server/srv_spoolss_nt.c | 5 +++-- source3/smbd/fileio.c | 6 +++--- 5 files changed, 57 insertions(+), 15 deletions(-) diff --git a/source3/lib/util.c b/source3/lib/util.c index f31bcef281..f92ffaedc0 100644 --- a/source3/lib/util.c +++ b/source3/lib/util.c @@ -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 diff --git a/source3/lib/util_sock.c b/source3/lib/util_sock.c index 4222c3c5ef..72837d73d9 100644 --- a/source3/lib/util_sock.c +++ b/source3/lib/util_sock.c @@ -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; diff --git a/source3/printing/printing.c b/source3/printing/printing.c index 03bdb7d421..ab86db53f3 100644 --- a/source3/printing/printing.c +++ b/source3/printing/printing.c @@ -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); diff --git a/source3/rpc_server/srv_spoolss_nt.c b/source3/rpc_server/srv_spoolss_nt.c index 7daf1630fe..b7091b2ade 100644 --- a/source3/rpc_server/srv_spoolss_nt.c +++ b/source3/rpc_server/srv_spoolss_nt.c @@ -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; diff --git a/source3/smbd/fileio.c b/source3/smbd/fileio.c index 977988fde4..9b39bf8fe1 100644 --- a/source3/smbd/fileio.c +++ b/source3/smbd/fileio.c @@ -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) { -- cgit