#include #include #include #include #include typedef struct fpriv FPRIV; struct fpriv { FILE *inner; unsigned int flags; void *h; } ; static int base64_wrap_r_cb(void *fpv, void *data, int len) { int n; n = fread(data,1,len,((FPRIV *)fpv)->inner); return((n<0)?-1:n); } static int base64_wrap_w_cb(void *fpv, const void *data, int len) { int n; const char *dp; int left; dp = data; left = len; while (left > 0) { n = fwrite(dp,1,left,((FPRIV *)fpv)->inner); if (n < 0) return(-1); dp += n; left -= n; } return(len); } static int base64_wrap_r(void *cookie, char *data, int len) { return(base64_r(((FPRIV *)cookie)->h,data,len)); } static int base64_wrap_w(void *cookie, const char *data, int len) { const char *dp; int left; int n; dp = data; left = len; while (left > 0) { n = base64_w(((FPRIV *)cookie)->h,dp,left); if (n < 0) return(-1); dp += n; left -= n; } return(len); } static int base64_wrap_c(void *cookie) { FPRIV *fp; fp = cookie; base64_close(fp->h); if (fp->flags & BASE64_CLOSE) fclose(fp->inner); free(fp); return(0); } FILE *base64_fwrap(FILE *inner, unsigned int flags) { FPRIV *fp; FILE *f; int e; switch (flags & ~BASE64_CLOSE) { case BASE64_OP_E | BASE64_DIR_R: case BASE64_OP_E | BASE64_DIR_W: case BASE64_OP_D | BASE64_DIR_R: case BASE64_OP_D | BASE64_DIR_W: break; default: return(0); break; } fp = malloc(sizeof(FPRIV)); if (! fp) return(0); f = funopen(fp,&base64_wrap_r,&base64_wrap_w,0,&base64_wrap_c); if (! f) { e = errno; free(fp); errno = e; return(0); } fp->inner = inner; fp->flags = flags; switch (flags & (BASE64_OP_E|BASE64_OP_D|BASE64_DIR_R|BASE64_DIR_W)) { case BASE64_OP_E | BASE64_DIR_R: fp->h = base64_e_r_cb(fp,&base64_wrap_r_cb); break; case BASE64_OP_E | BASE64_DIR_W: fp->h = base64_e_w_cb(fp,&base64_wrap_w_cb); break; case BASE64_OP_D | BASE64_DIR_R: fp->h = base64_d_r_cb(fp,&base64_wrap_r_cb); break; case BASE64_OP_D | BASE64_DIR_W: fp->h = base64_d_w_cb(fp,&base64_wrap_w_cb); break; default: abort(); /* can't happen - we checked above */ break; } return(f); }