lib: Transfer the responsibility of fopencookie bugs to the generic implementation.
[ashd.git] / lib / utils.c
index ed22b42..ad28086 100644 (file)
@@ -495,8 +495,22 @@ static ssize_t wrapread(void *pdata, char *buf, size_t len)
 static ssize_t wrapwrite(void *pdata, const char *buf, size_t len)
 {
     struct stdif *nf = pdata;
+    size_t off;
+    ssize_t ret;
     
-    return(nf->write(nf->pdata, buf, len));
+    /*
+     * XXX? In seeming violation of its own manual, glibc requires the
+     * cookie-write function to complete writing the entire buffer,
+     * rather than working like write(2).
+     */
+    off = 0;
+    while(off < len) {
+       ret = nf->write(nf->pdata, buf + off, len - off);
+       if(ret < 0)
+           return(off);
+       off += ret;
+    }
+    return(off);
 }
 
 static int wrapseek(void *pdata, off_t *pos, int whence)
@@ -518,6 +532,8 @@ static int wrapclose(void *pdata)
     
     if(nf->close != NULL)
        ret = nf->close(nf->pdata);
+    else
+       ret = 0;
     free(nf);
     return(ret);
 }
@@ -581,6 +597,8 @@ static int wrapclose(void *pdata)
     
     if(nf->close != NULL)
        ret = nf->close(nf->pdata);
+    else
+       ret = 0;
     free(nf);
     return(ret);
 }
@@ -594,7 +612,8 @@ FILE *funstdio(void *pdata,
     struct stdif *nf;
     
     omalloc(nf);
-    return(funopen(pdata, read?wrapread:NULL, write:wrapwrite:NULL, seek:wrapseek:NULL, wrapclose));
+    *nf = (struct stdif){.read = read, .write = write, .seek = seek, .close = close, .pdata = pdata};
+    return(funopen(nf, read?wrapread:NULL, write?wrapwrite:NULL, seek?wrapseek:NULL, wrapclose));
 }
 #else
 #error "No stdio implementation for this system"