From 67c4ed071971b1428a3004806e58d334945f197d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Deuc=D0=B5?= <shurd@sasktel.net> Date: Thu, 4 Mar 2021 20:03:45 -0500 Subject: [PATCH] Implement POSIX requirements for FD/Stream interactions. Documented here: https://pubs.opengroup.org/onlinepubs/009695399/functions/xsh_chap02_05.html#tag_02_05_01 This provides the best chance at read_raw() reading from the right location and updating the file pointer as expected while avoiding behaviour which is explicitly undefined by POSIX. --- src/sbbs3/js_file.c | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/src/sbbs3/js_file.c b/src/sbbs3/js_file.c index bfc4a03924..9c395972dd 100644 --- a/src/sbbs3/js_file.c +++ b/src/sbbs3/js_file.c @@ -355,6 +355,8 @@ js_raw_read(JSContext *cx, uintN argc, jsval *arglist) JSString* str; private_t* p; jsrefcount rc; + int fd; + off_t pos; JS_SET_RVAL(cx, arglist, JSVAL_NULL); @@ -378,7 +380,43 @@ js_raw_read(JSContext *cx, uintN argc, jsval *arglist) return(JS_TRUE); rc=JS_SUSPENDREQUEST(cx); + // https://pubs.opengroup.org/onlinepubs/009695399/functions/xsh_chap02_05.html#tag_02_05_01 + /* For the first handle, the first applicable condition below applies. After the actions + * required below are taken, if the handle is still open, the application can close it. + * If it is a file descriptor, no action is required. + * If the only further action to be performed on any handle to this open file descriptor + * is to close it, no action need be taken. + * If it is a stream which is unbuffered, no action need be taken. + * If it is a stream which is line buffered, and the last byte written to the stream was a + * <newline> (that is, as if a: putc('\n') was the most recent operation on that stream), + * no action need be taken. + * If it is a stream which is open for writing or appending (but not also open for reading), + * the application shall either perform an fflush(), or the stream shall be closed. + * If the stream is open for reading and it is at the end of the file ( feof() is true), no + * action need be taken. + * If the stream is open with a mode that allows reading and the underlying open file + * description refers to a device that is capable of seeking, the application shall + * either perform an fflush(), or the stream shall be closed. + * Otherwise, the result is undefined. + * For the second handle: + * If any previous active handle has been used by a function that explicitly changed the file + * offset, except as required above for the first handle, the application shall perform an + * lseek() or fseek() (as appropriate to the type of handle) to an appropriate location. + */ + /* + * Since we don't want to overcomplicate this, it basically boils down to: + * Call fflush() on the stream, lseek() on the descriptor, diddle the descriptor, then fseek() the + * stream. + * + * The only option bit is the fflush() on the stream, but it never hurts and is sometimes + * required by POSIX. + */ + fflush(p->fp); + pos = ftell(p->fp); + fd = fileno(p->fp); + lseek(fd, pos, SEEK_SET); len = read(fileno(p->fp),buf,len); + fseek(p->fp, pos + (len >= 0 ? len : 0), SEEK_SET); dbprintf(FALSE, p, "read %u raw bytes",len); if(len<0) len=0; -- GitLab