]> git.wh0rd.org - dump.git/blame - common/dumprmt.c
Initial revision
[dump.git] / common / dumprmt.c
CommitLineData
1227625a
SP
1/*
2 * Ported to Linux's Second Extended File System as part of the
3 * dump and restore backup suit
4 * Remy Card <card@Linux.EU.Org>, 1994, 1995, 1996
5 *
6 */
7
8/*-
9 * Copyright (c) 1980, 1993
10 * The Regents of the University of California. All rights reserved.
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions and the following disclaimer.
17 * 2. Redistributions in binary form must reproduce the above copyright
18 * notice, this list of conditions and the following disclaimer in the
19 * documentation and/or other materials provided with the distribution.
20 * 3. All advertising materials mentioning features or use of this software
21 * must display the following acknowledgement:
22 * This product includes software developed by the University of
23 * California, Berkeley and its contributors.
24 * 4. Neither the name of the University nor the names of its contributors
25 * may be used to endorse or promote products derived from this software
26 * without specific prior written permission.
27 *
28 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
29 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
30 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
31 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
32 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
36 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
37 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
38 * SUCH DAMAGE.
39 */
40
41#ifndef lint
42static char sccsid[] = "@(#)dumprmt.c 8.2 (Berkeley) 4/28/95";
43#endif /* not lint */
44
45#include <sys/param.h>
46#include <sys/mtio.h>
47#include <sys/ioctl.h>
48#include <sys/socket.h>
49#include <sys/time.h>
50#ifdef __linux__
51#include <linux/ext2_fs.h>
52#include <bsdcompat.h>
53#else
54#ifdef sunos
55#include <sys/vnode.h>
56
57#include <ufs/inode.h>
58#else
59#include <ufs/ufs/dinode.h>
60#endif
61#endif
62
63#include <netinet/in.h>
64#include <netinet/tcp.h>
65
66#include <protocols/dumprestore.h>
67
68#include <ctype.h>
69#include <err.h>
70#include <netdb.h>
71#include <pwd.h>
72#include <signal.h>
73#include <stdio.h>
74#ifdef __STDC__
75#include <stdlib.h>
76#include <string.h>
77#include <unistd.h>
78#endif
79
80#ifdef __linux__
81#include <ext2fs/ext2fs.h>
82#endif
83
84#include "pathnames.h"
85#include "dump.h"
86
87#define TS_CLOSED 0
88#define TS_OPEN 1
89
90static int rmtstate = TS_CLOSED;
91static int rmtape;
92static char *rmtpeer;
93
94static int okname __P((char *));
95static int rmtcall __P((char *, char *));
96static void rmtconnaborted __P((/* int, int */));
97static int rmtgetb __P((void));
98static void rmtgetconn __P((void));
99static void rmtgets __P((char *, int));
100static int rmtreply __P((char *));
101
102extern int ntrec; /* blocking factor on tape */
103
104int
105rmthost(host)
106 char *host;
107{
108
109 rmtpeer = malloc(strlen(host) + 1);
110 if (rmtpeer)
111 strcpy(rmtpeer, host);
112 else
113 rmtpeer = host;
114 signal(SIGPIPE, rmtconnaborted);
115 rmtgetconn();
116 if (rmtape < 0)
117 return (0);
118 return (1);
119}
120
121static void
122rmtconnaborted()
123{
124
125 errx(1, "Lost connection to remote host.");
126}
127
128void
129rmtgetconn()
130{
131 register char *cp;
132 static struct servent *sp = NULL;
133 static struct passwd *pwd = NULL;
134#ifdef notdef
135 static int on = 1;
136#endif
137 char *tuser;
138 int size;
139 int maxseg;
140
141 if (sp == NULL) {
142 sp = getservbyname("shell", "tcp");
143 if (sp == NULL)
144 errx(1, "shell/tcp: unknown service");
145 pwd = getpwuid(getuid());
146 if (pwd == NULL)
147 errx(1, "who are you?");
148 }
149 if ((cp = strchr(rmtpeer, '@')) != NULL) {
150 tuser = rmtpeer;
151 *cp = '\0';
152 if (!okname(tuser))
153 exit(1);
154 rmtpeer = ++cp;
155 } else
156 tuser = pwd->pw_name;
157 rmtape = rcmd(&rmtpeer, (u_short)sp->s_port, pwd->pw_name, tuser,
158 _PATH_RMT, (int *)0);
159 size = ntrec * TP_BSIZE;
160 if (size > 60 * 1024) /* XXX */
161 size = 60 * 1024;
162 /* Leave some space for rmt request/response protocol */
163 size += 2 * 1024;
164 while (size > TP_BSIZE &&
165 setsockopt(rmtape, SOL_SOCKET, SO_SNDBUF, &size, sizeof (size)) < 0)
166 size -= TP_BSIZE;
167 (void)setsockopt(rmtape, SOL_SOCKET, SO_RCVBUF, &size, sizeof (size));
168 maxseg = 1024;
169 if (setsockopt(rmtape, IPPROTO_TCP, TCP_MAXSEG,
170 &maxseg, sizeof (maxseg)) < 0)
171 perror("TCP_MAXSEG setsockopt");
172
173#ifdef notdef
174 if (setsockopt(rmtape, IPPROTO_TCP, TCP_NODELAY, &on, sizeof (on)) < 0)
175 perror("TCP_NODELAY setsockopt");
176#endif
177}
178
179static int
180okname(cp0)
181 char *cp0;
182{
183 register char *cp;
184 register int c;
185
186 for (cp = cp0; *cp; cp++) {
187 c = *cp;
188 if (!isascii(c) || !(isalnum(c) || c == '_' || c == '-')) {
189 warnx("invalid user name: %s", cp0);
190 return (0);
191 }
192 }
193 return (1);
194}
195
196int
197rmtopen(tape, mode)
198 char *tape;
199 int mode;
200{
201 char buf[256];
202
203 (void)sprintf(buf, "O%s\n%d\n", tape, mode);
204 rmtstate = TS_OPEN;
205 return (rmtcall(tape, buf));
206}
207
208void
209rmtclose()
210{
211
212 if (rmtstate != TS_OPEN)
213 return;
214 rmtcall("close", "C\n");
215 rmtstate = TS_CLOSED;
216}
217
218int
219rmtread(buf, count)
220 char *buf;
221 int count;
222{
223 char line[30];
224 int n, i, cc;
225 extern errno;
226
227 (void)sprintf(line, "R%d\n", count);
228 n = rmtcall("read", line);
229 if (n < 0) {
230 errno = n;
231 return (-1);
232 }
233 for (i = 0; i < n; i += cc) {
234 cc = read(rmtape, buf+i, n - i);
235 if (cc <= 0) {
236 rmtconnaborted();
237 }
238 }
239 return (n);
240}
241
242int
243rmtwrite(buf, count)
244 char *buf;
245 int count;
246{
247 char line[30];
248
249 (void)sprintf(line, "W%d\n", count);
250 write(rmtape, line, strlen(line));
251 write(rmtape, buf, count);
252 return (rmtreply("write"));
253}
254
255void
256rmtwrite0(count)
257 int count;
258{
259 char line[30];
260
261 (void)sprintf(line, "W%d\n", count);
262 write(rmtape, line, strlen(line));
263}
264
265void
266rmtwrite1(buf, count)
267 char *buf;
268 int count;
269{
270
271 write(rmtape, buf, count);
272}
273
274int
275rmtwrite2()
276{
277
278 return (rmtreply("write"));
279}
280
281int
282rmtseek(offset, pos)
283 int offset, pos;
284{
285 char line[80];
286
287 (void)sprintf(line, "L%d\n%d\n", offset, pos);
288 return (rmtcall("seek", line));
289}
290
291struct mtget mts;
292
293struct mtget *
294rmtstatus()
295{
296 register int i;
297 register char *cp;
298
299 if (rmtstate != TS_OPEN)
300 return (NULL);
301 rmtcall("status", "S\n");
302 for (i = 0, cp = (char *)&mts; i < sizeof(mts); i++)
303 *cp++ = rmtgetb();
304 return (&mts);
305}
306
307int
308rmtioctl(cmd, count)
309 int cmd, count;
310{
311 char buf[256];
312
313 if (count < 0)
314 return (-1);
315 (void)sprintf(buf, "I%d\n%d\n", cmd, count);
316 return (rmtcall("ioctl", buf));
317}
318
319static int
320rmtcall(cmd, buf)
321 char *cmd, *buf;
322{
323
324 if (write(rmtape, buf, strlen(buf)) != strlen(buf))
325 rmtconnaborted();
326 return (rmtreply(cmd));
327}
328
329static int
330rmtreply(cmd)
331 char *cmd;
332{
333 register char *cp;
334 char code[30], emsg[BUFSIZ];
335
336 rmtgets(code, sizeof (code));
337 if (*code == 'E' || *code == 'F') {
338 rmtgets(emsg, sizeof (emsg));
339 msg("%s: %s", cmd, emsg);
340 if (*code == 'F') {
341 rmtstate = TS_CLOSED;
342 return (-1);
343 }
344 return (-1);
345 }
346 if (*code != 'A') {
347 /* Kill trailing newline */
348 cp = code + strlen(code);
349 if (cp > code && *--cp == '\n')
350 *cp = '\0';
351
352 msg("Protocol to remote tape server botched (code \"%s\").\n",
353 code);
354 rmtconnaborted();
355 }
356 return (atoi(code + 1));
357}
358
359int
360rmtgetb()
361{
362 char c;
363
364 if (read(rmtape, &c, 1) != 1)
365 rmtconnaborted();
366 return (c);
367}
368
369/* Get a line (guaranteed to have a trailing newline). */
370void
371rmtgets(line, len)
372 char *line;
373 int len;
374{
375 register char *cp = line;
376
377 while (len > 1) {
378 *cp = rmtgetb();
379 if (*cp == '\n') {
380 cp[1] = '\0';
381 return;
382 }
383 cp++;
384 len--;
385 }
386 *cp = '\0';
387 msg("Protocol to remote tape server botched.\n");
388 msg("(rmtgets got \"%s\").\n", line);
389 rmtconnaborted();
390}