1 #include "burp.h"
2 #include "asfd.h"
3 #include "async.h"
4 #include "bfile.h"
5 #include "cmd.h"
6 #include "fzp.h"
7 #include "iobuf.h"
8 #include "log.h"
9 #include "msg.h"
10 
send_msg_fzp(struct fzp * fzp,enum cmd cmd,const char * buf,size_t s)11 int send_msg_fzp(struct fzp *fzp, enum cmd cmd, const char *buf, size_t s)
12 {
13 	if(fzp_printf(fzp, "%c%04X", cmd, (unsigned int)s)!=5
14 	  || fzp_write(fzp, buf, s)!=s
15 	  || fzp_printf(fzp, "\n")!=1)
16 	{
17 		logp("Unable to write message to file: %s\n", strerror(errno));
18 		return -1;
19 	}
20 	return 0;
21 }
22 
do_write(struct asfd * asfd,struct BFILE * bfd,uint8_t * out,size_t outlen,uint64_t * sent)23 static int do_write(struct asfd *asfd, struct BFILE *bfd,
24 	uint8_t *out, size_t outlen, uint64_t *sent)
25 {
26 	int ret=0;
27 	if((ret=bfd->write(bfd, out, outlen))<=0)
28 	{
29 		logp("%s: error when appending %lu: %d\n",
30 			__func__, (unsigned long)outlen, ret);
31 		asfd->write_str(asfd, CMD_ERROR, "write failed");
32 		return -1;
33 	}
34 	*sent+=outlen;
35 	return 0;
36 }
37 
do_inflate(struct asfd * asfd,z_stream * zstrm,struct BFILE * bfd,uint8_t * out,uint64_t * sent)38 static int do_inflate(struct asfd *asfd, z_stream *zstrm, struct BFILE *bfd,
39 	uint8_t *out, uint64_t *sent)
40 {
41 	int zret=Z_OK;
42 	unsigned have=0;
43 	struct iobuf *rbuf=asfd->rbuf;
44 
45 	zstrm->avail_in=rbuf->len;
46 	zstrm->next_in=(uint8_t *)rbuf->buf;
47 
48 	do
49 	{
50 		zstrm->avail_out=ZCHUNK;
51 		zstrm->next_out=out;
52 		zret=inflate(zstrm, Z_NO_FLUSH);
53 		switch(zret)
54 		{
55 			case Z_NEED_DICT:
56 				zret=Z_DATA_ERROR;
57 			case Z_DATA_ERROR:
58 			case Z_MEM_ERROR:
59 				logp("zstrm inflate error: %d\n", zret);
60 				return -1;
61 		}
62 		have=ZCHUNK-zstrm->avail_out;
63 		if(!have) continue;
64 
65 		if(do_write(asfd, bfd, out, have, sent))
66 			return -1;
67 	} while(!zstrm->avail_out);
68 	return 0;
69 }
70 
transfer_gzfile_in(struct asfd * asfd,struct BFILE * bfd,uint64_t * rcvd,uint64_t * sent)71 int transfer_gzfile_in(struct asfd *asfd, struct BFILE *bfd,
72 	uint64_t *rcvd, uint64_t *sent)
73 {
74 	int quit=0;
75 	int ret=-1;
76 	uint8_t out[ZCHUNK];
77 	struct iobuf *rbuf=asfd->rbuf;
78 	z_stream zstrm;
79 
80 	zstrm.zalloc=Z_NULL;
81 	zstrm.zfree=Z_NULL;
82 	zstrm.opaque=Z_NULL;
83 	zstrm.avail_in=0;
84 	zstrm.next_in=Z_NULL;
85 
86 	if(inflateInit2(&zstrm, (15+16)))
87 	{
88 		logp("unable to init inflate\n");
89 		goto end;
90 	}
91 
92 	while(!quit)
93 	{
94 		iobuf_free_content(rbuf);
95 		if(asfd->read(asfd)) goto end_inflate;
96 		(*rcvd)+=rbuf->len;
97 
98 		//logp("transfer in: %s\n", iobuf_to_printable(rbuf));
99 		switch(rbuf->cmd)
100 		{
101 			case CMD_APPEND: // append
102 				if(!bfd)
103 				{
104 					logp("given append, but no file to write to\n");
105 					asfd->write_str(asfd, CMD_ERROR,
106 						"append with no file");
107 					goto end_inflate;
108 				}
109 				else
110 				{
111 					if(do_inflate(asfd, &zstrm,
112 						bfd, out, sent))
113 							goto end_inflate;
114 				}
115 				break;
116 			case CMD_END_FILE: // finish up
117 				goto end_ok;
118 			case CMD_MESSAGE:
119 			case CMD_WARNING:
120 			{
121 				struct cntr *cntr=NULL;
122 				log_recvd(rbuf, cntr, 0);
123 				break;
124 			}
125 			default:
126 				iobuf_log_unexpected(rbuf, __func__);
127 				goto end_inflate;
128 		}
129 	}
130 
131 end_ok:
132 	ret=0;
133 end_inflate:
134 	inflateEnd(&zstrm);
135 end:
136 	if(ret) logp("transfer file returning: %d\n", ret);
137 	iobuf_free_content(rbuf);
138 	return ret;
139 }
140