]> Dogcows Code - chaz/tar/blob - src/rmt.c
442a8310740aecc0de24d65cc33c52b25d4d4eb0
[chaz/tar] / src / rmt.c
1 /*
2 * Copyright (c) 1983 Regents of the University of California.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms are permitted
6 * provided that the above copyright notice and this paragraph are
7 * duplicated in all such forms and that any documentation,
8 * advertising materials, and other materials related to such
9 * distribution and use acknowledge that the software was developed
10 * by the University of California, Berkeley. The name of the
11 * University may not be used to endorse or promote products derived
12 * from this software without specific prior written permission.
13 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
16 */
17
18 #ifndef lint
19 char copyright[] =
20 "@(#) Copyright (c) 1983 Regents of the University of California.\n\
21 All rights reserved.\n";
22 #endif /* not lint */
23
24 /*
25 * rmt
26 */
27 #include <stdio.h>
28 #include <sgtty.h>
29 #include <sys/types.h>
30 #include <sys/socket.h>
31 #ifdef HAVE_SYS_GENTAPE_H /* e.g., ISC UNIX */
32 #include <sys/gentape.h>
33 #else
34 #include <sys/mtio.h>
35 #endif
36 #include <errno.h>
37
38 #if defined (_I386) && defined (_AIX)
39 #include <fcntl.h>
40 #endif
41
42 #ifdef HAVE_UNISTD_H
43 #include <unistd.h>
44 #else
45 long lseek ();
46 #endif
47
48 #ifdef STDC_HEADERS
49 #include <string.h>
50 #include <stdlib.h>
51 #else
52 extern char *malloc ();
53 #endif
54
55 int tape = -1;
56
57 char *record;
58 int maxrecsize = -1;
59 char *checkbuf ();
60 void getstring ();
61 void error ();
62
63 #define SSIZE 64
64 char device[SSIZE];
65 char count[SSIZE], mode[SSIZE], pos[SSIZE], op[SSIZE];
66
67 extern errno;
68 extern char *sys_errlist[];
69 char resp[BUFSIZ];
70
71 FILE *debug;
72 #define DEBUG(f) if (debug) fprintf(debug, f)
73 #define DEBUG1(f,a) if (debug) fprintf(debug, f, a)
74 #define DEBUG2(f,a1,a2) if (debug) fprintf(debug, f, a1, a2)
75
76 int
77 main (argc, argv)
78 int argc;
79 char **argv;
80 {
81 int rval;
82 char c;
83 int n, i, cc;
84
85 argc--, argv++;
86 if (argc > 0)
87 {
88 debug = fopen (*argv, "w");
89 if (debug == 0)
90 exit (1);
91 (void) setbuf (debug, (char *) 0);
92 }
93 top:
94 errno = 0;
95 rval = 0;
96 if (read (0, &c, 1) != 1)
97 exit (0);
98 switch (c)
99 {
100
101 case 'O':
102 if (tape >= 0)
103 (void) close (tape);
104 getstring (device);
105 getstring (mode);
106 DEBUG2 ("rmtd: O %s %s\n", device, mode);
107 #if defined (i386) && defined (AIX)
108 /* This is alleged to fix a byte ordering problem. */
109 /* I'm quite suspicious if it's right. -- mib */
110 {
111 int oflag = atoi (mode);
112 int nflag = 0;
113 if ((oflag & 3) == 0)
114 nflag |= O_RDONLY;
115 if (oflag & 1)
116 nflag |= O_WRONLY;
117 if (oflag & 2)
118 nflag |= O_RDWR;
119 if (oflag & 0x0008)
120 nflag |= O_APPEND;
121 if (oflag & 0x0200)
122 nflag |= O_CREAT;
123 if (oflag & 0x0400)
124 nflag |= O_TRUNC;
125 if (oflag & 0x0800)
126 nflag |= O_EXCL;
127 tape = open (device, nflag, 0666);
128 }
129 #else
130 tape = open (device, atoi (mode), 0666);
131 #endif
132 if (tape < 0)
133 goto ioerror;
134 goto respond;
135
136 case 'C':
137 DEBUG ("rmtd: C\n");
138 getstring (device); /* discard */
139 if (close (tape) < 0)
140 goto ioerror;
141 tape = -1;
142 goto respond;
143
144 case 'L':
145 getstring (count);
146 getstring (pos);
147 DEBUG2 ("rmtd: L %s %s\n", count, pos);
148 rval = lseek (tape, (long) atoi (count), atoi (pos));
149 if (rval < 0)
150 goto ioerror;
151 goto respond;
152
153 case 'W':
154 getstring (count);
155 n = atoi (count);
156 DEBUG1 ("rmtd: W %s\n", count);
157 record = checkbuf (record, n);
158 for (i = 0; i < n; i += cc)
159 {
160 cc = read (0, &record[i], n - i);
161 if (cc <= 0)
162 {
163 DEBUG ("rmtd: premature eof\n");
164 exit (2);
165 }
166 }
167 rval = write (tape, record, n);
168 if (rval < 0)
169 goto ioerror;
170 goto respond;
171
172 case 'R':
173 getstring (count);
174 DEBUG1 ("rmtd: R %s\n", count);
175 n = atoi (count);
176 record = checkbuf (record, n);
177 rval = read (tape, record, n);
178 if (rval < 0)
179 goto ioerror;
180 (void) sprintf (resp, "A%d\n", rval);
181 (void) write (1, resp, strlen (resp));
182 (void) write (1, record, rval);
183 goto top;
184
185 case 'I':
186 getstring (op);
187 getstring (count);
188 DEBUG2 ("rmtd: I %s %s\n", op, count);
189 #ifdef MTIOCTOP
190 {
191 struct mtop mtop;
192 mtop.mt_op = atoi (op);
193 mtop.mt_count = atoi (count);
194 if (ioctl (tape, MTIOCTOP, (char *) &mtop) < 0)
195 goto ioerror;
196 rval = mtop.mt_count;
197 }
198 #endif
199 goto respond;
200
201 case 'S': /* status */
202 DEBUG ("rmtd: S\n");
203 {
204 #ifdef MTIOCGET
205 struct mtget mtget;
206 if (ioctl (tape, MTIOCGET, (char *) &mtget) < 0)
207 goto ioerror;
208 rval = sizeof (mtget);
209 (void) sprintf (resp, "A%d\n", rval);
210 (void) write (1, resp, strlen (resp));
211 (void) write (1, (char *) &mtget, sizeof (mtget));
212 #endif
213 goto top;
214 }
215
216 default:
217 DEBUG1 ("rmtd: garbage command %c\n", c);
218 exit (3);
219 }
220 respond:
221 DEBUG1 ("rmtd: A %d\n", rval);
222 (void) sprintf (resp, "A%d\n", rval);
223 (void) write (1, resp, strlen (resp));
224 goto top;
225 ioerror:
226 error (errno);
227 goto top;
228 }
229
230 void
231 getstring (bp)
232 char *bp;
233 {
234 int i;
235 char *cp = bp;
236
237 for (i = 0; i < SSIZE; i++)
238 {
239 if (read (0, cp + i, 1) != 1)
240 exit (0);
241 if (cp[i] == '\n')
242 break;
243 }
244 cp[i] = '\0';
245 }
246
247 char *
248 checkbuf (record, size)
249 char *record;
250 int size;
251 {
252 if (size <= maxrecsize)
253 return (record);
254 if (record != 0)
255 free (record);
256 record = malloc (size);
257 if (record == 0)
258 {
259 DEBUG ("rmtd: cannot allocate buffer space\n");
260 exit (4);
261 }
262 maxrecsize = size;
263 #ifdef SO_RCVBUF
264 while (size > 1024 &&
265 setsockopt (0, SOL_SOCKET, SO_RCVBUF, (char *) &size, sizeof (size)) < 0)
266 size -= 1024;
267 #else
268 size = 1 + ((size - 1) % 1024);
269 #endif
270 return (record);
271 }
272
273 void
274 error (num)
275 int num;
276 {
277
278 DEBUG2 ("rmtd: E %d (%s)\n", num, sys_errlist[num]);
279 (void) sprintf (resp, "E%d\n%s\n", num, sys_errlist[num]);
280 (void) write (1, resp, strlen (resp));
281 }
This page took 0.048798 seconds and 4 git commands to generate.