GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: sbin/restore/../dump/dumprmt.c Lines: 0 113 0.0 %
Date: 2017-11-13 Branches: 0 62 0.0 %

Line Branch Exec Source
1
/*	$OpenBSD: dumprmt.c,v 1.29 2015/01/16 06:39:57 deraadt Exp $	*/
2
/*	$NetBSD: dumprmt.c,v 1.17 1997/06/05 16:10:47 mrg Exp $	*/
3
4
/*-
5
 * Copyright (c) 1980, 1993
6
 *	The Regents of the University of California.  All rights reserved.
7
 *
8
 * Redistribution and use in source and binary forms, with or without
9
 * modification, are permitted provided that the following conditions
10
 * are met:
11
 * 1. Redistributions of source code must retain the above copyright
12
 *    notice, this list of conditions and the following disclaimer.
13
 * 2. Redistributions in binary form must reproduce the above copyright
14
 *    notice, this list of conditions and the following disclaimer in the
15
 *    documentation and/or other materials provided with the distribution.
16
 * 3. Neither the name of the University nor the names of its contributors
17
 *    may be used to endorse or promote products derived from this software
18
 *    without specific prior written permission.
19
 *
20
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30
 * SUCH DAMAGE.
31
 */
32
33
#include <sys/param.h>	/* MAXBSIZE */
34
#include <sys/mtio.h>
35
#include <sys/ioctl.h>
36
#include <sys/socket.h>
37
#include <sys/time.h>
38
#include <ufs/ufs/dinode.h>
39
40
#include <netinet/in.h>
41
#include <netinet/tcp.h>
42
43
#include <protocols/dumprestore.h>
44
45
#include <ctype.h>
46
#include <err.h>
47
#include <netdb.h>
48
#include <errno.h>
49
#include <pwd.h>
50
#include <signal.h>
51
#include <stdio.h>
52
#include <stdlib.h>
53
#include <string.h>
54
#include <unistd.h>
55
#include <limits.h>
56
57
#include "pathnames.h"
58
#include "dump.h"
59
60
#define	TS_CLOSED	0
61
#define	TS_OPEN		1
62
63
static	int rmtstate = TS_CLOSED;
64
static	int rmtape;
65
static	char *rmtpeer;
66
67
static	int okname(char *);
68
static	int rmtcall(char *, char *);
69
static	void rmtconnaborted(int);
70
static	int rmtgetb(void);
71
static	void rmtgetconn(void);
72
static	void rmtgets(char *, int);
73
static	int rmtreply(char *);
74
75
int	rmthost(char *host);
76
int	rmtopen(char *tape, int mode);
77
int	rmtread(char *buf, int count);
78
int	rmtwrite(char *buf, int count);
79
int	rmtseek(int offset, int pos);
80
int	rmtioctl(int cmd, int count);
81
void	rmtclose(void);
82
83
extern	int ntrec;		/* blocking factor on tape */
84
85
int
86
rmthost(char *host)
87
{
88
	int len = strlen(host) + 1;
89
90
	rmtpeer = malloc(len);
91
	if (rmtpeer)
92
		strlcpy(rmtpeer, host, len);
93
	else
94
		rmtpeer = host;
95
	signal(SIGPIPE, rmtconnaborted);
96
	rmtgetconn();
97
	if (rmtape < 0)
98
		return (0);
99
	return (1);
100
}
101
102
/* ARGSUSED */
103
static void
104
rmtconnaborted(int signo)
105
{
106
	/* XXX signal race */
107
	errx(X_ABORT, "Lost connection to remote host.");
108
}
109
110
void
111
rmtgetconn(void)
112
{
113
	char *cp;
114
	static struct servent *sp = NULL;
115
	static struct passwd *pwd = NULL;
116
	static int on = 1;
117
	char *tuser, *name;
118
	int size;
119
	int maxseg;
120
121
	if (sp == NULL) {
122
		sp = getservbyname("shell", "tcp");
123
		if (sp == NULL)
124
			errx(X_STARTUP, "shell/tcp: unknown service");
125
		pwd = getpwuid(getuid());
126
		if (pwd == NULL)
127
			errx(X_STARTUP, "who are you?");
128
	}
129
	if ((name = strdup(pwd->pw_name)) == NULL)
130
		err(X_STARTUP, "malloc");
131
	if ((cp = strchr(rmtpeer, '@')) != NULL) {
132
		tuser = rmtpeer;
133
		*cp = '\0';
134
		if (!okname(tuser))
135
			exit(X_STARTUP);
136
		rmtpeer = ++cp;
137
	} else
138
		tuser = name;
139
140
	rmtape = rcmd(&rmtpeer, sp->s_port, name, tuser, _PATH_RMT, NULL);
141
	(void)free(name);
142
	if (rmtape < 0)
143
		return;
144
145
	size = ntrec * TP_BSIZE;
146
	if (size > 60 * 1024)		/* XXX */
147
		size = 60 * 1024;
148
	/* Leave some space for rmt request/response protocol */
149
	size += 2 * 1024;
150
	while (size > TP_BSIZE &&
151
	    setsockopt(rmtape, SOL_SOCKET, SO_SNDBUF, &size, sizeof(size)) < 0)
152
		    size -= TP_BSIZE;
153
	(void)setsockopt(rmtape, SOL_SOCKET, SO_RCVBUF, &size, sizeof(size));
154
155
	maxseg = 1024;
156
	(void)setsockopt(rmtape, IPPROTO_TCP, TCP_MAXSEG, &maxseg,
157
		sizeof(maxseg));
158
159
	(void) setsockopt(rmtape, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on));
160
}
161
162
static int
163
okname(char *cp0)
164
{
165
	char *cp;
166
	unsigned char c;
167
168
	for (cp = cp0; *cp; cp++) {
169
		c = *cp;
170
		if (!isascii(c) || !(isalnum(c) || c == '_' || c == '-')) {
171
			warnx("invalid user name: %s", cp0);
172
			return (0);
173
		}
174
	}
175
	return (1);
176
}
177
178
int
179
rmtopen(char *tape, int mode)
180
{
181
	char buf[256];
182
183
	(void)snprintf(buf, sizeof(buf), "O%s\n%d\n", tape, mode);
184
	rmtstate = TS_OPEN;
185
	return (rmtcall(tape, buf));
186
}
187
188
void
189
rmtclose(void)
190
{
191
192
	if (rmtstate != TS_OPEN)
193
		return;
194
	rmtcall("close", "C\n");
195
	rmtstate = TS_CLOSED;
196
}
197
198
int
199
rmtread(char *buf, int count)
200
{
201
	char line[30];
202
	int n, i, cc;
203
204
	(void)snprintf(line, sizeof(line), "R%d\n", count);
205
	n = rmtcall("read", line);
206
	if (n < 0) {
207
		errno = n;
208
		return (-1);
209
	}
210
	for (i = 0; i < n; i += cc) {
211
		cc = read(rmtape, buf+i, n - i);
212
		if (cc <= 0) {
213
			rmtconnaborted(0);
214
		}
215
	}
216
	return (n);
217
}
218
219
int
220
rmtwrite(char *buf, int count)
221
{
222
	char line[30];
223
224
	(void)snprintf(line, sizeof(line), "W%d\n", count);
225
	write(rmtape, line, strlen(line));
226
	write(rmtape, buf, count);
227
	return (rmtreply("write"));
228
}
229
230
int
231
rmtseek(int offset, int pos)
232
{
233
	char line[80];
234
235
	(void)snprintf(line, sizeof(line), "L%d\n%d\n", offset, pos);
236
	return (rmtcall("seek", line));
237
}
238
239
int
240
rmtioctl(int cmd, int count)
241
{
242
	char buf[256];
243
244
	if (count < 0)
245
		return (-1);
246
	(void)snprintf(buf, sizeof(buf), "I%d\n%d\n", cmd, count);
247
	return (rmtcall("ioctl", buf));
248
}
249
250
static int
251
rmtcall(char *cmd, char *buf)
252
{
253
254
	if (write(rmtape, buf, strlen(buf)) != strlen(buf))
255
		rmtconnaborted(0);
256
	return (rmtreply(cmd));
257
}
258
259
static int
260
rmtreply(char *cmd)
261
{
262
	char *cp;
263
	char code[30], emsg[BUFSIZ];
264
265
	rmtgets(code, sizeof(code));
266
	if (*code == 'E' || *code == 'F') {
267
		rmtgets(emsg, sizeof(emsg));
268
		msg("%s: %s", cmd, emsg);
269
		errno = atoi(&code[1]);
270
		if (*code == 'F')
271
			rmtstate = TS_CLOSED;
272
		return (-1);
273
	}
274
	if (*code != 'A') {
275
		/* Kill trailing newline */
276
		cp = code + strlen(code);
277
		if (cp > code && *--cp == '\n')
278
			*cp = '\0';
279
280
		msg("Protocol to remote tape server botched (code \"%s\").\n",
281
		    code);
282
		rmtconnaborted(0);
283
	}
284
	return (atoi(code + 1));
285
}
286
287
int
288
rmtgetb(void)
289
{
290
	char c;
291
292
	if (read(rmtape, &c, 1) != 1)
293
		rmtconnaborted(0);
294
	return (c);
295
}
296
297
/* Get a line (guaranteed to have a trailing newline). */
298
void
299
rmtgets(char *line, int len)
300
{
301
	char *cp = line;
302
303
	while (len > 1) {
304
		*cp = rmtgetb();
305
		if (*cp == '\n') {
306
			cp[1] = '\0';
307
			return;
308
		}
309
		cp++;
310
		len--;
311
	}
312
	*cp = '\0';
313
	msg("Protocol to remote tape server botched.\n");
314
	msg("(rmtgets got \"%s\").\n", line);
315
	rmtconnaborted(0);
316
}