xref: /openbsd-src/usr.bin/rsync/session.c (revision 99fd087599a8791921855f21bd7e36130f39aadc)
1 /*	$Id: session.c,v 1.7 2019/05/08 20:00:25 benno Exp $ */
2 /*
3  * Copyright (c) 2019 Kristaps Dzonsons <kristaps@bsd.lv>
4  *
5  * Permission to use, copy, modify, and distribute this software for any
6  * purpose with or without fee is hereby granted, provided that the above
7  * copyright notice and this permission notice appear in all copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16  */
17 #include <sys/param.h>
18 
19 #include <assert.h>
20 #include <stdint.h>
21 #include <stdlib.h>
22 #include <unistd.h>
23 
24 #include "extern.h"
25 
26 /*
27  * Accept how much we've read, written, and file-size, and print them in
28  * a human-readable fashion (with GB, MB, etc. prefixes).
29  * This only prints as the client.
30  */
31 static void
32 stats_log(struct sess *sess,
33 	uint64_t tread, uint64_t twrite, uint64_t tsize)
34 {
35 	double		 tr, tw, ts;
36 	const char	*tru = "B", *twu = "B", *tsu = "B";
37 	int		 trsz = 0, twsz = 0, tssz = 0;
38 
39 	assert(verbose);
40 	if (sess->opts->server)
41 		return;
42 
43 	if (tread >= 1024 * 1024 * 1024) {
44 		tr = tread / (1024.0 * 1024.0 * 1024.0);
45 		tru = "GB";
46 		trsz = 3;
47 	} else if (tread >= 1024 * 1024) {
48 		tr = tread / (1024.0 * 1024.0);
49 		tru = "MB";
50 		trsz = 2;
51 	} else if (tread >= 1024) {
52 		tr = tread / 1024.0;
53 		tru = "KB";
54 		trsz = 1;
55 	} else
56 		tr = tread;
57 
58 	if (twrite >= 1024 * 1024 * 1024) {
59 		tw = twrite / (1024.0 * 1024.0 * 1024.0);
60 		twu = "GB";
61 		twsz = 3;
62 	} else if (twrite >= 1024 * 1024) {
63 		tw = twrite / (1024.0 * 1024.0);
64 		twu = "MB";
65 		twsz = 2;
66 	} else if (twrite >= 1024) {
67 		tw = twrite / 1024.0;
68 		twu = "KB";
69 		twsz = 1;
70 	} else
71 		tw = twrite;
72 
73 	if (tsize >= 1024 * 1024 * 1024) {
74 		ts = tsize / (1024.0 * 1024.0 * 1024.0);
75 		tsu = "GB";
76 		tssz = 3;
77 	} else if (tsize >= 1024 * 1024) {
78 		ts = tsize / (1024.0 * 1024.0);
79 		tsu = "MB";
80 		tssz = 2;
81 	} else if (tsize >= 1024) {
82 		ts = tsize / 1024.0;
83 		tsu = "KB";
84 		tssz = 1;
85 	} else
86 		ts = tsize;
87 
88 	LOG1("Transfer complete: "
89 	    "%.*lf %s sent, %.*lf %s read, %.*lf %s file size",
90 	    trsz, tr, tru,
91 	    twsz, tw, twu,
92 	    tssz, ts, tsu);
93 }
94 
95 /*
96  * At the end of transmission, we write our statistics if we're the
97  * server, then log only if we're not the server.
98  * Either way, only do this if we're in verbose mode.
99  * Returns zero on failure, non-zero on success.
100  */
101 int
102 sess_stats_send(struct sess *sess, int fd)
103 {
104 	uint64_t tw, tr, ts;
105 
106 	if (verbose == 0)
107 		return 1;
108 
109 	tw = sess->total_write;
110 	tr = sess->total_read;
111 	ts = sess->total_size;
112 
113 	if (sess->opts->server) {
114 		if (!io_write_ulong(sess, fd, tr)) {
115 			ERRX1("io_write_ulong");
116 			return 0;
117 		} else if (!io_write_ulong(sess, fd, tw)) {
118 			ERRX1("io_write_ulong");
119 			return 0;
120 		} else if (!io_write_ulong(sess, fd, ts)) {
121 			ERRX1("io_write_ulong");
122 			return 0;
123 		}
124 	}
125 
126 	stats_log(sess, tr, tw, ts);
127 	return 1;
128 }
129 
130 /*
131  * At the end of the transmission, we have some statistics to read.
132  * Only do this (1) if we're in verbose mode and (2) if we're the
133  * server.
134  * Then log the findings.
135  * Return zero on failure, non-zero on success.
136  */
137 int
138 sess_stats_recv(struct sess *sess, int fd)
139 {
140 	uint64_t tr, tw, ts;
141 
142 	if (sess->opts->server || verbose == 0)
143 		return 1;
144 
145 	if (!io_read_ulong(sess, fd, &tw)) {
146 		ERRX1("io_read_ulong");
147 		return 0;
148 	} else if (!io_read_ulong(sess, fd, &tr)) {
149 		ERRX1("io_read_ulong");
150 		return 0;
151 	} else if (!io_read_ulong(sess, fd, &ts)) {
152 		ERRX1("io_read_ulong");
153 		return 0;
154 	}
155 
156 	stats_log(sess, tr, tw, ts);
157 	return 1;
158 }
159