diff options
-rw-r--r-- | Makefile | 14 | ||||
-rw-r--r-- | common.c | 53 | ||||
-rw-r--r-- | common.h | 34 | ||||
-rw-r--r-- | copier.c | 46 | ||||
-rw-r--r-- | editasroot.c | 56 |
5 files changed, 117 insertions, 86 deletions
@@ -5,19 +5,23 @@ include $(CONFIGFILE) OBJ =\ editasroot.o\ + common.o\ copier.o +HDR =\ + common.h + all: editasroot copier -$(OBJ): $(@:.o=.c) +$(OBJ): $(HDR) .c.o: $(CC) -c -o $@ $< $(CFLAGS) $(CPPFLAGS) -editasroot: editasroot.o - $(CC) -o $@ $@.o $(LDFLAGS) +editasroot: editasroot.o common.o + $(CC) -o $@ $@.o common.o $(LDFLAGS) -copier: copier.o - $(CC) -o $@ $@.o $(LDFLAGS) +copier: copier.o common.o + $(CC) -o $@ $@.o common.o $(LDFLAGS) install: editasroot copier mkdir -p -- "$(DESTDIR)$(PREFIX)/bin" diff --git a/common.c b/common.c new file mode 100644 index 0000000..5379f89 --- /dev/null +++ b/common.c @@ -0,0 +1,53 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + + +void +copy_file(int destfd, const char *destfname, int srcfd, const char *srcfname, int *okp) +{ + char buf[BUFSIZ]; + ssize_t r, w, p, ok_off; + size_t read_off; + + if (okp) { + *okp = 0; + ok_off = 1; + read_off = 0; + } else { + ok_off = 0; + read_off = 1; + buf[0] = 0; + } + + for (;;) { + r = read(srcfd, &buf[read_off], sizeof(buf) - read_off); + if (r <= 0) { + if (!r) + break; + fprintf(stderr, "%s: read %s: %s", argv0, srcfname, strerror(errno)); + exit(1); + } + + if (r == ok_off) { /* Only possible if okp != NULL */ + *okp = 1; + break; + } + + r += (ssize_t)read_off; + for (p = ok_off; p < r; p += w) { + w = write(destfd, buf, (size_t)(r - p)); + if (r <= 0) { + fprintf(stderr, "%s: write %s: %s", argv0, destfname, strerror(errno)); + exit(1); + } + } + } + + if (!okp) { + w = write(destfd, buf, 1); + if (r <= 0) { + fprintf(stderr, "%s: write %s: %s", argv0, destfname, strerror(errno)); + exit(1); + } + } +} diff --git a/common.h b/common.h new file mode 100644 index 0000000..ac73c43 --- /dev/null +++ b/common.h @@ -0,0 +1,34 @@ +/* See LICENSE file for copyright and license details. */ +#include <sys/prctl.h> +#include <sys/socket.h> +#include <sys/wait.h> +#include <errno.h> +#include <fcntl.h> +#include <paths.h> +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <termios.h> +#include <unistd.h> + +/* We need at least 2 bytes we are sending 1 addition byte in each chunk */ +#if BUFSIZ < 2 +# undef BUFSIZ +# define BUFSIZ 2 +#endif + +/* We impose a limit because PF_UNIX/SOCK_SEQPACKET can block if sending + * too much (I don't know the exact limit and it can change), without + * first setting up a socket options, which is overkill for this application, + * and there is also a hard limit just above 210000B for each EMSGSIZE will + * be thrown. */ +#if BUFSIZ > (8 << 10) +# undef BUFSIZ +# define BUFSIZ (8 << 10) +#endif + + +extern const char *argv0; + +void copy_file(int destfd, const char *destfname, int srcfd, const char *srcfname, int *okp); @@ -1,46 +1,14 @@ /* See LICENSE file for copyright and license details. */ -#include <sys/socket.h> -#include <errno.h> -#include <fcntl.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> +#include "common.h" -static const char *argv0 = "editasroot/copier"; - - -static void -copy_file(int destfd, const char *destfname, int srcfd, const char *srcfname) -{ - char buf[BUFSIZ]; - ssize_t r, w, p; - - for (;;) { - r = read(srcfd, buf, sizeof(buf)); - if (r <= 0) { - if (!r) - break; - fprintf(stderr, "%s: read %s: %s", argv0, srcfname, strerror(errno)); - exit(1); - } - - for (p = 0; p < r; p += w) { - w = write(destfd, buf, (size_t)(r - p)); - if (r <= 0) { - fprintf(stderr, "%s: write %s: %s", argv0, destfname, strerror(errno)); - exit(1); - } - } - } -} +const char *argv0 = "editasroot/copier"; int main(int argc, char *argv[]) { - int filefd, parentfd; + int filefd, parentfd, ok; const char *path; ssize_t r; char b; @@ -59,7 +27,7 @@ main(int argc, char *argv[]) fprintf(stderr, "%s: open %s O_RDWR: %s\n", argv0, path, strerror(errno)); exit(1); } - copy_file(parentfd, "<socket to parent>", filefd, path); + copy_file(parentfd, "<socket to parent>", filefd, path, NULL); if (close(filefd)) { fprintf(stderr, "%s: read %s: %s\n", argv0, path, strerror(errno)); exit(1); @@ -81,7 +49,7 @@ main(int argc, char *argv[]) fprintf(stderr, "%s: open %s O_WRONLY|O_TRUNC: %s\n", argv0, path, strerror(errno)); exit(1); } - copy_file(filefd, path, parentfd, "<socket to parent>"); + copy_file(filefd, path, parentfd, "<socket to parent>", &ok); if (close(filefd)) { fprintf(stderr, "%s: write %s: %s\n", argv0, path, strerror(errno)); exit(1); @@ -90,6 +58,10 @@ main(int argc, char *argv[]) fprintf(stderr, "%s: read <socket to parent>: %s\n", argv0, strerror(errno)); exit(1); } + if (!ok) { + fprintf(stderr, "%s: parent exited before sending file termination message, file may be truncated\n", argv0); + exit(1); + } return 0; } diff --git a/editasroot.c b/editasroot.c index c6ce396..09479f8 100644 --- a/editasroot.c +++ b/editasroot.c @@ -1,21 +1,11 @@ /* See LICENSE file for copyright and license details. */ -#include <sys/prctl.h> -#include <sys/socket.h> -#include <sys/wait.h> -#include <errno.h> -#include <fcntl.h> -#include <paths.h> -#include <signal.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <termios.h> -#include <unistd.h> +#include "common.h" #define TEMPFILEPATTERN "tmpXXXXXX" -static const char *argv0 = "editasroot"; +const char *argv0 = "editasroot"; + static const char *unlink_this = NULL; static int ttyfd = -1; static int tcattrs_fetched = 0; @@ -101,32 +91,6 @@ get_tmpfile_pattern(void) } -static void -copy_file(int destfd, const char *destfname, int srcfd, const char *srcfname) -{ - char buf[BUFSIZ]; - ssize_t r, w, p; - - for (;;) { - r = read(srcfd, buf, sizeof(buf)); - if (r <= 0) { - if (!r) - break; - fprintf(stderr, "%s: read %s: %s", argv0, srcfname, strerror(errno)); - exit(1); - } - - for (p = 0; p < r; p += w) { - w = write(destfd, buf, (size_t)(r - p)); - if (r <= 0) { - fprintf(stderr, "%s: write %s: %s", argv0, destfname, strerror(errno)); - exit(1); - } - } - } -} - - static pid_t run_child(const char *file, int fd, int close_this) { @@ -191,7 +155,7 @@ main(int argc, char *argv[]) { const char *editor; char *path; - int fd, fds[2], status, i; + int fd, fds[2], status, i, ok; pid_t pid; if (!argc) @@ -226,8 +190,8 @@ main(int argc, char *argv[]) editor = get_editor(); /* Start copier, with a bidirectional channel to it for copying the file */ - if (socketpair(PF_LOCAL, SOCK_STREAM, 0, fds)) { - fprintf(stderr, "%s: socketpair PF_LOCAL SOCK_STREAM 0: %s", argv0, strerror(errno)); + if (socketpair(PF_LOCAL, SOCK_SEQPACKET, 0, fds)) { + fprintf(stderr, "%s: socketpair PF_LOCAL SOCK_SEQPACKET 0: %s", argv0, strerror(errno)); exit(1); } pid = run_child(argv[0], fds[1], fds[0]); @@ -246,7 +210,7 @@ main(int argc, char *argv[]) exit(1); } unlink_this = path; - copy_file(fd, path, fds[0], "<socket to child>"); + copy_file(fd, path, fds[0], "<socket to child>", &ok); if (close(fd)) { fprintf(stderr, "%s: write %s: %s", argv0, path, strerror(errno)); exit(1); @@ -255,6 +219,10 @@ main(int argc, char *argv[]) fprintf(stderr, "%s: shutdown <socket to child> SHUT_RD: %s\n", argv0, strerror(errno)); exit(1); } + if (!ok) { + fprintf(stderr, "%s: child exited before sending file termination message\n", argv0); + exit(1); + } /* Don't need to restore terminal attributes, if we got here, asroot as not interrupted */ close(ttyfd); @@ -274,7 +242,7 @@ main(int argc, char *argv[]) fprintf(stderr, "%s: open %s O_RDONLY: %s", argv0, path, strerror(errno)); exit(1); } - copy_file(fds[0], "<socket to child>", fd, path); + copy_file(fds[0], "<socket to child>", fd, path, NULL); if (close(fd)) { fprintf(stderr, "%s: read %s: %s", argv0, path, strerror(errno)); exit(1); |