+static int cproc_xfer(struct ftp *ftp, int code, const char *buf, void *cls)
+{
+ char *ptr;
+ struct ftp_transfer *xfer = cls;
+
+ if(code < 200) {
+ /* expect more */
+ if(code == 150 && (ptr = strchr(buf, '('))) {
+ /* update total size */
+ sscanf(ptr, "(%ld bytes)", &xfer->total);
+ }
+ return 1;
+ }
+
+ if(code >= 400) {
+ errmsg("failed to retrieve file\n");
+ }
+ return 0;
+}
+
+static void dproc_xfer(struct ftp *ftp, const char *buf, int sz, void *cls)
+{
+ struct ftp_transfer *xfer = cls;
+
+ if(xfer->op == FTP_RETR) {
+ if(sz == 0) {
+ /* EOF condition, got the whole file */
+ if(xfer->fp) {
+ fclose(xfer->fp);
+ xfer->fp = 0;
+ }
+
+ if(xfer->done) {
+ xfer->done(ftp, xfer);
+ }
+ return;
+ }
+
+ if(xfer->fp) {
+ ((char*)buf)[sz] = 0;
+ fwrite(buf, 1, sz, xfer->fp);
+
+ } else if(xfer->mem) {
+ int prevsz = darr_size(xfer->mem);
+ darr_resize(xfer->mem, prevsz + sz);
+ memcpy(xfer->mem + prevsz, buf, sz);
+ }
+
+ xfer->count += sz;
+ if(xfer->count > xfer->total) {
+ xfer->count = xfer->total;
+ }
+
+ } else { /* FTP_STOR */
+ /* TODO */
+ }
+}
+