]> git.wh0rd.org - dump.git/blob - common/dumprmt.c
Initial revision
[dump.git] / common / dumprmt.c
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
42 static 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
90 static int rmtstate = TS_CLOSED;
91 static int rmtape;
92 static char *rmtpeer;
93
94 static int okname __P((char *));
95 static int rmtcall __P((char *, char *));
96 static void rmtconnaborted __P((/* int, int */));
97 static int rmtgetb __P((void));
98 static void rmtgetconn __P((void));
99 static void rmtgets __P((char *, int));
100 static int rmtreply __P((char *));
101
102 extern int ntrec; /* blocking factor on tape */
103
104 int
105 rmthost(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
121 static void
122 rmtconnaborted()
123 {
124
125 errx(1, "Lost connection to remote host.");
126 }
127
128 void
129 rmtgetconn()
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
179 static int
180 okname(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
196 int
197 rmtopen(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
208 void
209 rmtclose()
210 {
211
212 if (rmtstate != TS_OPEN)
213 return;
214 rmtcall("close", "C\n");
215 rmtstate = TS_CLOSED;
216 }
217
218 int
219 rmtread(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
242 int
243 rmtwrite(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
255 void
256 rmtwrite0(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
265 void
266 rmtwrite1(buf, count)
267 char *buf;
268 int count;
269 {
270
271 write(rmtape, buf, count);
272 }
273
274 int
275 rmtwrite2()
276 {
277
278 return (rmtreply("write"));
279 }
280
281 int
282 rmtseek(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
291 struct mtget mts;
292
293 struct mtget *
294 rmtstatus()
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
307 int
308 rmtioctl(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
319 static int
320 rmtcall(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
329 static int
330 rmtreply(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
359 int
360 rmtgetb()
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). */
370 void
371 rmtgets(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 }