It came up in chat today that dump/rmt uses hardcoded integer values that are then passed as the flags argument of open. This is wrong for several reasons.
The following patch corrects it. The rmt part is untested (don't have a suitable setup to test it with) -- if someone who uses rmt could check it out that would be helpful. Based on discussion with mrg, the rmt patch accepts a bunch of open flags that dump doesn't send, because it's apparently useful to be able to use rmt to dump to remote regular files with a suitably patched dump. Getting the latter written and committed is for some future time :-) Question: should the defines go in a new <protocols/rmt.h> or is that overkill? Right now they're pasted in both programs, which is not ideal but not a huge issue either. Index: usr.sbin/rmt/rmt.c =================================================================== RCS file: /cvsroot/src/usr.sbin/rmt/rmt.c,v retrieving revision 1.17 diff -u -p -r1.17 rmt.c --- usr.sbin/rmt/rmt.c 23 Jan 2018 21:06:25 -0000 1.17 +++ usr.sbin/rmt/rmt.c 17 Mar 2021 19:18:13 -0000 @@ -59,6 +59,25 @@ __RCSID("$NetBSD: rmt.c,v 1.17 2018/01/2 #include <string.h> #include <unistd.h> +/* + * The wire protocol uses integer literals for the open mode, + * corresponding to the traditional O_RDONLY and O_RDWR values. + * Traditional dump sends only either O_RDONLY or O_RDWR, but + * since it's useful to use rmt to dump to remote regular files + * we also allow some other flags, using the NetBSD values + * (which are likely the historical ones, but I'm not sure). + */ +#define RMT_O_RDONLY 0 +#define RMT_O_RDWR 2 +#define RMT_O_ACCMODE 3 +#define RMT_O_APPEND 8 +#define RMT_O_NOFOLLOW 0x100 +#define RMT_O_CREAT 0x200 +#define RMT_O_TRUNC 0x400 +#define RMT_O_EXCL 0x800 +#define RMT_O_REGULAR 0x02000000 +#define RMT_O_FLAGS 0x02000f08 + int tape = -1; int maxrecsize = -1; @@ -77,6 +96,7 @@ FILE *debug; char *checkbuf(char *, int); void error(int); void getstring(char *, size_t); +static int decode_mode(const char *); int main(int argc, char *argv[]) @@ -85,6 +105,7 @@ main(int argc, char *argv[]) int rval; char c; int n, i, cc; + int openflags; argc--, argv++; if (argc > 0) { @@ -106,7 +127,12 @@ top: getstring(device, sizeof(device)); getstring(mode, sizeof(mode)); DEBUG2("rmtd: O %s %s\n", device, mode); - tape = open(device, atoi(mode), + openflags = decode_mode(mode); + if (openflags == -1) { + error(EINVAL); + goto top; + } + tape = open(device, openflags, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH); if (tape < 0) goto ioerror; @@ -246,3 +272,49 @@ error(int num) (void)snprintf(resp, sizeof(resp), "E%d\n%s\n", num, strerror(num)); (void)write(STDOUT_FILENO, resp, strlen(resp)); } + +static int +decode_mode(const char *buf) +{ + unsigned val; + int ret; + char *more; + + errno = 0; + val = strtol(buf, &more, 0); + if (errno != 0 || *more != '\0') { + return -1; + } + switch (val & RMT_O_ACCMODE) { + case RMT_O_RDONLY: + ret = O_RDONLY; + break; + case RMT_O_RDWR: + ret = O_RDWR; + break; + default: + return -1; + } + if ((val & RMT_O_FLAGS) != val) { + return -1; + } + if (val & RMT_O_APPEND) { + ret |= O_APPEND; + } + if (val & RMT_O_NOFOLLOW) { + ret |= O_NOFOLLOW; + } + if (val & RMT_O_CREAT) { + ret |= O_CREAT; + } + if (val & RMT_O_TRUNC) { + ret |= O_TRUNC; + } + if (val & RMT_O_EXCL) { + ret |= O_EXCL; + } + if (val & RMT_O_REGULAR) { + ret |= O_REGULAR; + } + return ret; +} Index: sbin/dump/dump.h =================================================================== RCS file: /cvsroot/src/sbin/dump/dump.h,v retrieving revision 1.59 diff -u -p -r1.59 dump.h --- sbin/dump/dump.h 3 Dec 2020 08:25:57 -0000 1.59 +++ sbin/dump/dump.h 17 Mar 2021 19:18:14 -0000 @@ -244,6 +244,8 @@ void lfs_wrap_go(void); #endif /* rdump routines */ +#define RMT_O_RDONLY 0 +#define RMT_O_RDWR 2 #if defined(RDUMP) || defined(RRESTORE) void rmtclose(void); int rmthost(const char *); Index: sbin/dump/tape.c =================================================================== RCS file: /cvsroot/src/sbin/dump/tape.c,v retrieving revision 1.55 diff -u -p -r1.55 tape.c --- sbin/dump/tape.c 1 Mar 2019 16:42:11 -0000 1.55 +++ sbin/dump/tape.c 17 Mar 2021 19:18:14 -0000 @@ -391,7 +391,7 @@ trewind(int eject) #ifdef RDUMP if (host) { rmtclose(); - while (rmtopen(tape, 0, 0) < 0) + while (rmtopen(tape, RMT_O_RDONLY, 0) < 0) sleep(10); if (eflag && eject) { msg("Ejecting %s\n", tape); @@ -431,7 +431,7 @@ close_rewind(void) if (lflag) { for (i = 0; i < lflag / 10; i++) { /* wait lflag seconds */ if (host) { - if (rmtopen(tape, 0, 0) >= 0) { + if (rmtopen(tape, RMT_O_RDONLY, 0) >= 0) { rmtclose(); return; } @@ -667,7 +667,7 @@ restore_check_point: msg("Dumping volume %d on %s\n", tapeno, tape); } #ifdef RDUMP - while ((tapefd = (host ? rmtopen(tape, 2, 1) : + while ((tapefd = (host ? rmtopen(tape, RMT_O_RDWR, 1) : pipeout ? 1 : open(tape, O_WRONLY|O_CREAT, 0666))) < 0) #else while ((tapefd = (pipeout ? 1 : -- David A. Holland dholl...@netbsd.org