* implement buffered IO for blob-reading, so you can continue siping from the blob...
authorWilfried Göesgens <willi@citadel.org>
Sun, 19 Apr 2009 15:05:55 +0000 (15:05 +0000)
committerWilfried Göesgens <willi@citadel.org>
Sun, 19 Apr 2009 15:05:55 +0000 (15:05 +0000)
libcitadel/lib/libcitadel.h
libcitadel/lib/stringbuf.c

index 4219792106a6316699cc91d2d1c70c80a85c1439..0f4f6e2d19e6f8ff2fe69d2ff4b7fcdc7c8b6727 100644 (file)
@@ -235,6 +235,13 @@ long StrBufPeek(StrBuf *Buf, const char* ptr, long nThChar, char PeekValue);
 
 int StrBufTCP_read_line(StrBuf *buf, int *fd, int append, const char **Error);
 int StrBufReadBLOB(StrBuf *Buf, int *fd, int append, long nBytes, const char **Error);
+int StrBufReadBLOBBuffered(StrBuf *Buf, 
+                          StrBuf *IOBuf, 
+                          const char **BufPos,
+                          int *fd, 
+                          int append, 
+                          long nBytes, 
+                          const char **Error);
 int StrBufTCP_read_buffered_line(StrBuf *Line, 
                                 StrBuf *buf, 
                                 int *fd, 
index d2b2f7d8af7e3134df8c1dc875c919835dad64ee..7db6017d600028d35fd366bb37272740f0bd2f31 100644 (file)
@@ -1508,6 +1508,93 @@ int StrBufReadBLOB(StrBuf *Buf, int *fd, int append, long nBytes, const char **E
        return nRead;
 }
 
+/**
+ * \brief Input binary data from socket
+ * flushes and closes the FD on error
+ * \param buf the buffer to get the input to
+ * \param fd pointer to the filedescriptor to read
+ * \param append Append to an existing string or replace?
+ * \param nBytes the maximal number of bytes to read
+ * \param Error strerror() on error 
+ * \returns numbers of chars read
+ */
+int StrBufReadBLOBBuffered(StrBuf *Buf, 
+                          StrBuf *IOBuf, 
+                          const char **BufPos,
+                          int *fd, 
+                          int append, 
+                          long nBytes, 
+                          const char **Error)
+{
+        fd_set wset;
+        int fdflags;
+       int len, rlen, slen;
+       int nRead;
+       char *ptr;
+
+       if ((Buf == NULL) || (*fd == -1) || (IOBuf == NULL))
+               return -1;
+       if (!append)
+               FlushStrBuf(Buf);
+       if (Buf->BufUsed + nBytes >= Buf->BufSize)
+               IncreaseBuf(Buf, 1, Buf->BufUsed + nBytes);
+
+
+       len = *BufPos - IOBuf->buf;
+       rlen = IOBuf->BufUsed - len;
+
+       if ((IOBuf->BufUsed > 0) && 
+           ((IOBuf->BufUsed - len > 0))) {
+               if (rlen <= nBytes) {
+                       memcpy(Buf->buf + Buf->BufUsed, *BufPos, rlen);
+                       Buf->BufUsed += rlen;
+                       Buf->buf[Buf->BufUsed] = '\0';
+                       *BufPos = NULL; FlushStrBuf(IOBuf);
+                       nRead = rlen;
+                       if (nRead == nBytes)
+                               return nBytes;
+               }
+               else {
+                       memcpy(Buf->buf + Buf->BufUsed, *BufPos, nBytes);
+                       Buf->BufUsed += nBytes;
+                       Buf->buf[Buf->BufUsed] = '\0';
+                       *BufPos += nBytes;
+                       return nBytes;
+               }
+       }
+
+       ptr = Buf->buf + Buf->BufUsed;
+
+       slen = len = Buf->BufUsed;
+
+       fdflags = fcntl(*fd, F_GETFL);
+
+       while (nRead < nBytes) {
+               if ((fdflags & O_NONBLOCK) == O_NONBLOCK) {
+                        FD_ZERO(&wset);
+                        FD_SET(*fd, &wset);
+                        if (select(*fd + 1, NULL, &wset, NULL, NULL) == -1) {
+                               *Error = strerror(errno);
+                                return -1;
+                        }
+                }
+
+                if ((rlen = read(*fd, 
+                                ptr,
+                                nBytes - nRead)) == -1) {
+                       close(*fd);
+                       *fd = -1;
+                       *Error = strerror(errno);
+                        return rlen;
+                }
+               nRead += rlen;
+               ptr += rlen;
+               Buf->BufUsed += rlen;
+       }
+       Buf->buf[Buf->BufUsed] = '\0';
+       return nRead;
+}
+
 /**
  * \brief Cut nChars from the start of the string
  * \param Buf Buffer to modify