[Git][ghc/ghc][master] JS: implement openat(AT_FDCWD...) (#23697)
Marge Bot (@marge-bot)
gitlab at gitlab.haskell.org
Thu Aug 17 11:54:32 UTC 2023
Marge Bot pushed to branch master at Glasgow Haskell Compiler / GHC
Commits:
e2b38115 by Sylvain Henry at 2023-08-17T07:54:06-04:00
JS: implement openat(AT_FDCWD...) (#23697)
Use `openSync` to implement `openat(AT_FDCWD...)`.
- - - - -
6 changed files:
- libraries/base/jsbits/base.js
- libraries/base/jsbits/errno.js
- libraries/base/tests/Makefile
- + libraries/base/tests/T23697.hsc
- + libraries/base/tests/T23697.stdout
- libraries/base/tests/all.T
Changes:
=====================================
libraries/base/jsbits/base.js
=====================================
@@ -39,7 +39,13 @@ function h$base_chmod(file, file_off, mode, c) {
}
function h$base_close(fd, c) {
- TRACE_IO("base_close fd: " + fd)
+ TRACE_IO("base_close fd: " + fd)
+ return h$close(fd,c);
+}
+
+function h$close(fd,c) {
+ if (c) {
+ //asynchronous
var fdo = h$base_fds[fd];
if(fdo) {
delete h$base_fds[fd];
@@ -59,6 +65,16 @@ function h$base_close(fd, c) {
h$errno = CONST_EINVAL;
c(-1);
}
+ } else {
+ //synchronous
+ try {
+ h$fs.closeSync(fd);
+ return 0;
+ } catch(err) {
+ h$setErrno(err);
+ return (-1);
+ }
+ }
}
function h$base_dup(fd, c) {
@@ -265,11 +281,25 @@ function h$rmdir(file, file_off) {
}
function h$base_open(file, file_off, how, mode, c) {
+ return h$open(file,file_off,how,mode,c);
+}
+
+function h$openat(dirfd, file, file_off, how, mode) {
+ if (dirfd != h$base_at_fdcwd) {
+ // we only support AT_FDWCD (open) until NodeJS provides "openat"
+ return h$unsupported(-1);
+ }
+ else {
+ return h$open(file,file_off,how,mode,undefined);
+ }
+}
+
+function h$open(file, file_off, how, mode,c) {
#ifndef GHCJS_BROWSER
if(h$isNode()) {
var flags, off;
var fp = h$decodeUtf8z(file, file_off);
- TRACE_IO("base_open: " + fp)
+ TRACE_IO("open: " + fp)
var acc = how & h$base_o_accmode;
// passing a number lets node.js use it directly as the flags (undocumented)
if(acc === h$base_o_rdonly) {
@@ -284,34 +314,64 @@ function h$base_open(file, file_off, how, mode, c) {
| ((how & h$base_o_creat) ? h$processConstants['fs']['O_CREAT'] : 0)
| ((how & h$base_o_excl) ? h$processConstants['fs']['O_EXCL'] : 0)
| ((how & h$base_o_append) ? h$processConstants['fs']['O_APPEND'] : 0);
- h$fs.open(fp, flags, mode, function(err, fd) {
- if(err) {
- h$handleErrnoC(err, -1, 0, c);
+ if (c) {
+ // asynchronous
+ h$fs.open(fp, flags, mode, function(err, fd) {
+ if(err) {
+ h$handleErrnoC(err, -1, 0, c);
+ } else {
+ var f = function(p) {
+ h$base_fds[fd] = { read: h$base_readFile
+ , write: h$base_writeFile
+ , close: h$base_closeFile
+ , fd: fd
+ , pos: p
+ , refs: 1
+ };
+ TRACE_IO("base_open: " + fp + " -> " + fd)
+ c(fd);
+ }
+ if(off === -1) {
+ h$fs.stat(fp, function(err, fs) {
+ if(err) h$handleErrnoC(err, -1, 0, c); else f(fs.size);
+ });
+ } else {
+ f(0);
+ }
+ }
+ });
+ }
+ else {
+ // synchronous
+ try {
+ var fd = h$fs.openSync(fp, flags, mode);
+ var f = function(p) {
+ h$base_fds[fd] = { read: h$base_readFile
+ , write: h$base_writeFile
+ , close: h$base_closeFile
+ , fd: fd
+ , pos: p
+ , refs: 1
+ };
+ TRACE_IO("open: " + fp + " -> " + fd)
+ }
+ if(off === -1) {
+ var fs = h$fs.statSync(fp);
+ f(fs.size);
} else {
- var f = function(p) {
- h$base_fds[fd] = { read: h$base_readFile
- , write: h$base_writeFile
- , close: h$base_closeFile
- , fd: fd
- , pos: p
- , refs: 1
- };
- TRACE_IO("base_open: " + fp + " -> " + fd)
- c(fd);
- }
- if(off === -1) {
- h$fs.stat(fp, function(err, fs) {
- if(err) h$handleErrnoC(err, -1, 0, c); else f(fs.size);
- });
- } else {
- f(0);
- }
+ f(0);
}
- });
+ return fd;
+ } catch(err) {
+ h$setErrno(err);
+ return -1;
+ }
+ }
} else
#endif
- h$unsupported(-1, c);
+ return h$unsupported(-1,c);
}
+
function h$base_read(fd, buf, buf_off, n, c) {
TRACE_IO("base_read: " + fd)
var fdo = h$base_fds[fd];
@@ -353,16 +413,30 @@ function h$base_write(fd, buf, buf_off, n, c) {
// buf_off: offset in the buffer
// n: number of bytes to write
// c: continuation
- TRACE_IO("base_write: " + fd)
+ TRACE_IO("base_write: " + fd)
+ return h$write(fd,buf,buf_off,n,c);
+}
- var fdo = h$base_fds[fd];
+function h$write(fd, buf, buf_off, n, c) {
- if(fdo && fdo.write) {
- fdo.write(fd, fdo, buf, buf_off, n, c);
+ if (c) {
+ var fdo = h$base_fds[fd];
+ // asynchronous
+ if(fdo && fdo.write) {
+ fdo.write(fd, fdo, buf, buf_off, n, c);
+ } else {
+ h$fs.write(fd, buf.u8, buf_off, n, function(err, bytesWritten, buf0) {
+ h$handleErrnoC(err, -1, bytesWritten, c);
+ });
+ }
} else {
- h$fs.write(fd, buf.u8, buf_off, n, function(err, bytesWritten, buf0) {
- h$handleErrnoC(err, -1, bytesWritten, c);
- });
+ //synchronous
+ try {
+ return h$fs.writeSync(fd, buf.u8, buf_off, n);
+ } catch(err) {
+ h$setErrno(err);
+ return (-1);
+ }
}
}
@@ -447,17 +521,19 @@ function h$base_utime(file, file_off, timbuf, timbuf_off, c) {
function h$base_waitpid(pid, stat, stat_off, options, c) {
throw "h$base_waitpid";
}
-/** @const */ var h$base_o_rdonly = 0x00000;
-/** @const */ var h$base_o_wronly = 0x00001;
-/** @const */ var h$base_o_rdwr = 0x00002;
-/** @const */ var h$base_o_accmode = 0x00003;
-/** @const */ var h$base_o_append = 0x00008;
-/** @const */ var h$base_o_creat = 0x00200;
-/** @const */ var h$base_o_trunc = 0x00400;
-/** @const */ var h$base_o_excl = 0x00800;
-/** @const */ var h$base_o_noctty = 0x20000;
-/** @const */ var h$base_o_nonblock = 0x00004;
-/** @const */ var h$base_o_binary = 0x00000;
+const h$base_o_rdonly = 0x00000;
+const h$base_o_wronly = 0x00001;
+const h$base_o_rdwr = 0x00002;
+const h$base_o_accmode = 0x00003;
+const h$base_o_append = 0x00008;
+const h$base_o_creat = 0x00200;
+const h$base_o_trunc = 0x00400;
+const h$base_o_excl = 0x00800;
+const h$base_o_noctty = 0x20000;
+const h$base_o_nonblock = 0x00004;
+const h$base_o_binary = 0x00000;
+const h$base_at_fdcwd = -100;
+
function h$base_stat_check_mode(mode,p) {
// inspired by Node's checkModeProperty
=====================================
libraries/base/jsbits/errno.js
=====================================
@@ -51,6 +51,7 @@ function h$setErrno(e) {
if(es.indexOf('ESPIPE') !== -1) return CONST_ESPIPE;
if(es.indexOf('EBADF') !== -1) return CONST_EBADF;
if(es.indexOf('ENOSPC') !== -1) return CONST_ENOSPC;
+ if(es.indexOf('EACCES') !== -1) return CONST_EACCES;
if(es.indexOf('Bad argument') !== -1) return CONST_ENOENT; // fixme?
throw ("setErrno not yet implemented for: " + e);
=====================================
libraries/base/tests/Makefile
=====================================
@@ -5,3 +5,9 @@
TOP=../../../testsuite
include $(TOP)/mk/boilerplate.mk
include $(TOP)/mk/test.mk
+
+.PHONY: T23697
+T23697:
+ '$(HSC2HS)' T23697.hsc
+ '$(TEST_HC)' $(TEST_HC_OPTS) $(WAY_FLAGS) -v0 T23697.hs
+ ./T23697
=====================================
libraries/base/tests/T23697.hsc
=====================================
@@ -0,0 +1,37 @@
+{-# LANGUAGE MagicHash #-}
+{-# LANGUAGE LambdaCase #-}
+{-# LANGUAGE NegativeLiterals #-}
+
+module Main (main) where
+
+import Foreign.C.Types
+import Foreign.C.String
+import Foreign.Ptr
+import GHC.Ptr
+import System.Posix.Internals
+import Data.Bits
+
+#include<fcntl.h>
+
+main :: IO ()
+main = do
+
+ let
+ checkErr :: (Num a, Eq a) => a -> a
+ checkErr = \case
+ (-1) -> error "Returned (-1)"
+ x -> x
+
+ fname = "foo"
+
+ -- test: openat(AT_FDCWD...), write, close
+ withCString fname $ \cstr -> do
+ fd <- checkErr <$> openat (#const AT_FDCWD) cstr (o_WRONLY .|. o_CREAT) 0o666
+ checkErr <$> write fd (Ptr "123456"##) 6
+ checkErr <$> close fd
+
+ putStrLn =<< readFile fname
+
+foreign import ccall openat :: CInt -> CString -> CInt -> CUInt -> IO CInt
+foreign import ccall write :: CInt -> Ptr () -> CSize -> IO CInt
+foreign import ccall close :: CInt -> IO CInt
=====================================
libraries/base/tests/T23697.stdout
=====================================
@@ -0,0 +1 @@
+123456
=====================================
libraries/base/tests/all.T
=====================================
@@ -313,3 +313,7 @@ test('AtomicModifyIORef', normal, compile_and_run, [''])
test('AtomicSwapIORef', normal, compile_and_run, [''])
test('T23454', normal, compile_fail, [''])
test('T23687', normal, compile_and_run, [''])
+test('T23697',
+ [ when(opsys('mingw32'), skip) # header not found
+ , when(opsys('darwin'), skip) # permission denied
+ ], makefile_test, ['T23697'])
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/e2b381154c0f89a4ee23190e2e7d7cae105587e6
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/e2b381154c0f89a4ee23190e2e7d7cae105587e6
You're receiving this email because of your account on gitlab.haskell.org.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.haskell.org/pipermail/ghc-commits/attachments/20230817/67cf8f87/attachment-0001.html>
More information about the ghc-commits
mailing list