]>
Dogcows Code - chaz/tar/blob - src/rmt.c
1 /* Remote connection server.
2 Copyright 1994, 1995, 1996, 1997, 1999 Free Software Foundation, Inc.
4 This program is free software; you can redistribute it and/or modify it
5 under the terms of the GNU General Public License as published by the
6 Free Software Foundation; either version 2, or (at your option) any later
9 This program is distributed in the hope that it will be useful, but
10 WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
12 Public License for more details.
14 You should have received a copy of the GNU General Public License along
15 with this program; if not, write to the Free Software Foundation, Inc.,
16 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
18 /* Copyright (C) 1983 Regents of the University of California.
21 Redistribution and use in source and binary forms are permitted provided
22 that the above copyright notice and this paragraph are duplicated in all
23 such forms and that any documentation, advertising materials, and other
24 materials related to such distribution and use acknowledge that the
25 software was developed by the University of California, Berkeley. The
26 name of the University may not be used to endorse or promote products
27 derived from this software without specific prior written permission.
28 THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
29 WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
30 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. */
33 #include "safe-read.h"
35 #include <sys/socket.h>
38 # define EXIT_FAILURE 1
41 # define EXIT_SUCCESS 0
44 /* Maximum size of a string from the requesting program. */
45 #define STRING_SIZE 64
47 /* Name of executing program. */
48 const char *program_name
;
50 /* File descriptor of the tape device, or negative if none open. */
53 /* Buffer containing transferred data, and its allocated size. */
54 static char *record_buffer
;
55 static size_t allocated_size
;
57 /* Buffer for constructing the reply. */
58 static char reply_buffer
[BUFSIZ
];
60 /* Debugging tools. */
62 static FILE *debug_file
;
65 if (debug_file) fprintf(debug_file, File)
67 #define DEBUG1(File, Arg) \
68 if (debug_file) fprintf(debug_file, File, Arg)
70 #define DEBUG2(File, Arg1, Arg2) \
71 if (debug_file) fprintf(debug_file, File, Arg1, Arg2)
73 /*------------------------------------------------.
74 | Return an error string, given an error number. |
75 `------------------------------------------------*/
83 private_strerror (int errnum
)
85 extern char *sys_errlist
[];
88 if (errnum
> 0 && errnum
<= sys_nerr
)
89 return _(sys_errlist
[errnum
]);
90 return _("Unknown system error");
92 # define strerror private_strerror
100 report_error_message (const char *string
)
102 DEBUG1 ("rmtd: E 0 (%s)\n", string
);
104 sprintf (reply_buffer
, "E0\n%s\n", string
);
105 full_write (STDOUT_FILENO
, reply_buffer
, strlen (reply_buffer
));
113 report_numbered_error (int num
)
115 DEBUG2 ("rmtd: E %d (%s)\n", num
, strerror (num
));
117 sprintf (reply_buffer
, "E%d\n%s\n", num
, strerror (num
));
118 full_write (STDOUT_FILENO
, reply_buffer
, strlen (reply_buffer
));
126 get_string (char *string
)
130 for (counter
= 0; counter
< STRING_SIZE
; counter
++)
132 if (safe_read (STDIN_FILENO
, string
+ counter
, 1) != 1)
135 if (string
[counter
] == '\n')
138 string
[counter
] = '\0';
146 prepare_record_buffer (size_t size
)
148 if (size
<= allocated_size
)
152 free (record_buffer
);
154 record_buffer
= malloc (size
);
158 DEBUG (_("rmtd: Cannot allocate buffer space\n"));
160 report_error_message (N_("Cannot allocate buffer space"));
161 exit (EXIT_FAILURE
); /* exit status used to be 4 */
164 allocated_size
= size
;
167 while (size
> 1024 &&
168 (setsockopt (STDIN_FILENO
, SOL_SOCKET
, SO_RCVBUF
,
169 (char *) &size
, sizeof size
)
173 /* FIXME: I do not see any purpose to the following line... Sigh! */
174 size
= 1 + ((size
- 1) % 1024);
178 /* Decode OFLAG_STRING, which represents the 2nd argument to `open'.
179 OFLAG_STRING should contain an optional integer, followed by an optional
180 symbolic representation of an open flag using only '|' to separate its
181 components (e.g. "O_WRONLY|O_CREAT|O_TRUNC"). Prefer the symbolic
182 representation if available, falling back on the numeric
183 representation, or to zero if both formats are absent.
185 This function should be the inverse of encode_oflag. The numeric
186 representation is not portable from one host to another, but it is
187 for backward compatibility with old-fashioned clients that do not
188 emit symbolic open flags. */
191 decode_oflag (char const *oflag_string
)
194 int numeric_oflag
= strtol (oflag_string
, &oflag_num_end
, 10);
195 int symbolic_oflag
= 0;
197 oflag_string
= oflag_num_end
;
198 while (ISSPACE ((unsigned char) *oflag_string
))
203 struct name_value_pair
{ char const *name
; int value
; };
204 static struct name_value_pair
const table
[] =
206 {"APPEND", O_APPEND
},
213 {"LARGEFILE", O_LARGEFILE
}, /* LFS extension for opening large files */
216 {"NOCTTY", O_NOCTTY
},
219 {"NONBLOCK", O_NONBLOCK
},
221 {"RDONLY", O_RDONLY
},
232 struct name_value_pair
const *t
;
235 if (*oflag_string
++ != 'O' || *oflag_string
++ != '_')
236 return numeric_oflag
;
239 (strncmp (oflag_string
, t
->name
, s
= strlen (t
->name
)) != 0
241 && strchr ("ABCDEFGHIJKLMNOPQRSTUVWXYZ_0123456789",
244 if (t
== table
+ sizeof table
/ sizeof *table
- 1)
245 return numeric_oflag
;
247 symbolic_oflag
|= t
->value
;
250 while (*oflag_string
++ == '|');
252 return symbolic_oflag
;
260 main (int argc
, char *const *argv
)
265 /* FIXME: Localization is meaningless, unless --help and --version are
266 locally used. Localization would be best accomplished by the calling
267 tar, on messages found within error packets. */
269 program_name
= argv
[0];
270 setlocale (LC_ALL
, "");
271 bindtextdomain (PACKAGE
, LOCALEDIR
);
272 textdomain (PACKAGE
);
274 /* FIXME: Implement --help and --version as for any other GNU program. */
279 debug_file
= fopen (*argv
, "w");
282 report_numbered_error (errno
);
285 setbuf (debug_file
, 0);
289 errno
= 0; /* FIXME: errno should be read-only */
291 if (safe_read (STDIN_FILENO
, &command
, 1) != 1)
296 /* FIXME: Maybe 'H' and 'V' for --help and --version output? */
300 char device_string
[STRING_SIZE
];
301 char oflag_string
[STRING_SIZE
];
303 get_string (device_string
);
304 get_string (oflag_string
);
305 DEBUG2 ("rmtd: O %s %s\n", device_string
, oflag_string
);
310 tape
= open (device_string
, decode_oflag (oflag_string
), MODE_RW
);
318 char device_string
[STRING_SIZE
];
320 get_string (device_string
); /* discard */
323 if (close (tape
) < 0)
331 char count_string
[STRING_SIZE
];
332 char position_string
[STRING_SIZE
];
338 get_string (count_string
);
339 get_string (position_string
);
340 DEBUG2 ("rmtd: L %s %s\n", count_string
, position_string
);
342 /* Parse count_string, taking care to check for overflow.
343 We can't use standard functions,
344 since off_t might be longer than long. */
346 for (p
= count_string
; *p
== ' ' || *p
== '\t'; p
++)
349 negative
= *p
== '-';
350 p
+= negative
|| *p
== '+';
354 int digit
= *p
++ - '0';
355 if (9 < (unsigned) digit
)
359 off_t c10
= 10 * count
;
360 off_t nc
= negative
? c10
- digit
: c10
+ digit
;
361 if (c10
/ 10 != count
|| (negative
? c10
< nc
: nc
< c10
))
363 report_error_message (N_("Seek offset out of range"));
370 switch (atoi (position_string
))
372 case 0: whence
= SEEK_SET
; break;
373 case 1: whence
= SEEK_CUR
; break;
374 case 2: whence
= SEEK_END
; break;
376 report_error_message (N_("Seek direction out of range"));
379 count
= lseek (tape
, count
, whence
);
383 /* Convert count back to string for reply.
384 We can't use sprintf, since off_t might be longer than long. */
385 p
= count_string
+ sizeof count_string
;
388 *--p
= '0' + (int) (count
% 10);
389 while ((count
/= 10) != 0);
391 DEBUG1 ("rmtd: A %s\n", p
);
393 sprintf (reply_buffer
, "A%s\n", p
);
394 full_write (STDOUT_FILENO
, reply_buffer
, strlen (reply_buffer
));
400 char count_string
[STRING_SIZE
];
404 get_string (count_string
);
405 size
= atol (count_string
);
406 DEBUG1 ("rmtd: W %s\n", count_string
);
408 prepare_record_buffer (size
);
409 for (counter
= 0; counter
< size
; counter
+= status
)
411 status
= safe_read (STDIN_FILENO
, &record_buffer
[counter
],
415 DEBUG (_("rmtd: Premature eof\n"));
417 report_error_message (N_("Premature end of file"));
418 exit (EXIT_FAILURE
); /* exit status used to be 2 */
421 status
= full_write (tape
, record_buffer
, size
);
429 char count_string
[STRING_SIZE
];
432 get_string (count_string
);
433 DEBUG1 ("rmtd: R %s\n", count_string
);
435 size
= atol (count_string
);
436 prepare_record_buffer (size
);
437 status
= safe_read (tape
, record_buffer
, size
);
440 sprintf (reply_buffer
, "A%ld\n", (long) status
);
441 full_write (STDOUT_FILENO
, reply_buffer
, strlen (reply_buffer
));
442 full_write (STDOUT_FILENO
, record_buffer
, status
);
448 char operation_string
[STRING_SIZE
];
449 char count_string
[STRING_SIZE
];
451 get_string (operation_string
);
452 get_string (count_string
);
453 DEBUG2 ("rmtd: I %s %s\n", operation_string
, count_string
);
462 /* Parse count_string, taking care to check for overflow.
463 We can't use standard functions,
464 since off_t might be longer than long. */
466 for (p
= count_string
; *p
== ' ' || *p
== '\t'; p
++)
469 negative
= *p
== '-';
470 p
+= negative
|| *p
== '+';
474 int digit
= *p
++ - '0';
475 if (9 < (unsigned) digit
)
479 off_t c10
= 10 * count
;
480 off_t nc
= negative
? c10
- digit
: c10
+ digit
;
481 if (c10
/ 10 != count
|| (negative
? c10
< nc
: nc
< c10
))
483 report_error_message (N_("Seek offset out of range"));
490 mtop
.mt_count
= count
;
491 if (mtop
.mt_count
!= count
)
493 report_error_message (N_("Seek offset out of range"));
496 mtop
.mt_op
= atoi (operation_string
);
498 if (ioctl (tape
, MTIOCTOP
, (char *) &mtop
) < 0)
505 case 'S': /* status */
511 struct mtget operation
;
513 if (ioctl (tape
, MTIOCGET
, (char *) &operation
) < 0)
515 status
= sizeof operation
;
516 sprintf (reply_buffer
, "A%ld\n", (long) status
);
517 full_write (STDOUT_FILENO
, reply_buffer
, strlen (reply_buffer
));
518 full_write (STDOUT_FILENO
, (char *) &operation
, sizeof operation
);
525 DEBUG1 (_("rmtd: Garbage command %c\n"), command
);
527 report_error_message (N_("Garbage command"));
528 exit (EXIT_FAILURE
); /* exit status used to be 3 */
532 DEBUG1 ("rmtd: A %ld\n", (long) status
);
534 sprintf (reply_buffer
, "A%ld\n", (long) status
);
535 full_write (STDOUT_FILENO
, reply_buffer
, strlen (reply_buffer
));
539 report_numbered_error (errno
);
This page took 0.057053 seconds and 4 git commands to generate.