diff options
-rw-r--r-- | jim-aio.c | 49 | ||||
-rw-r--r-- | jim_tcl.txt | 36 | ||||
-rw-r--r-- | tests/aio.test | 30 |
3 files changed, 112 insertions, 3 deletions
@@ -1853,8 +1853,9 @@ static int JimAioOpenCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { const char *mode; - FILE *fh; + FILE *fh = NULL; const char *filename; + int fd = -1; if (argc != 2 && argc != 3) { Jim_WrongNumArgs(interp, 1, argv, "filename ?mode?"); @@ -1879,15 +1880,57 @@ static int JimAioOpenCommand(Jim_Interp *interp, int argc, } } #endif +#ifndef JIM_ANSIC + if (*mode == 'R' || *mode == 'W') { + /* POSIX flags */ + static const char * const modetypes[] = { + "RDONLY", "WRONLY", "RDWR", "APPEND", "BINARY", "CREAT", "EXCL", "NOCTTY", "TRUNC", NULL + }; + static const char * const simplemodes[] = { + "r", "w", "w+" + }; + static const int modeflags[] = { + O_RDONLY, O_WRONLY, O_RDWR, O_APPEND, 0, O_CREAT, O_EXCL, O_NOCTTY, O_TRUNC, + }; + int posixflags = 0; + int len = Jim_ListLength(interp, argv[2]); + int i; + int opt; - fh = fopen(filename, mode); + mode = NULL; + + for (i = 0; i < len; i++) { + Jim_Obj *objPtr = Jim_ListGetIndex(interp, argv[2], i); + if (Jim_GetEnum(interp, objPtr, modetypes, &opt, "access mode", JIM_ERRMSG) != JIM_OK) { + return JIM_ERR; + } + if (opt < 3) { + mode = simplemodes[opt]; + } + posixflags |= modeflags[opt]; + } + /* mode must be set here if it started with 'R' or 'W' and passed the enum check above */ + assert(mode); + fd = open(filename, posixflags, 0666); + if (fd >= 0) { + fh = fdopen(fd, mode); + if (fh == NULL) { + close(fd); + } + } + } + else +#endif + { + fh = fopen(filename, mode); + } if (fh == NULL) { JimAioSetError(interp, argv[1]); return JIM_ERR; } - return JimMakeChannel(interp, fh, -1, argv[1], "aio.handle%ld", 0, mode, 0) ? JIM_OK : JIM_ERR; + return JimMakeChannel(interp, fh, fd, argv[1], "aio.handle%ld", 0, mode, 0) ? JIM_OK : JIM_ERR; } #if defined(JIM_SSL) && !defined(JIM_BOOTSTRAP) diff --git a/jim_tcl.txt b/jim_tcl.txt index 1889ac9..88b62f5 100644 --- a/jim_tcl.txt +++ b/jim_tcl.txt @@ -64,6 +64,7 @@ Changes since 0.80 7. Add support for `lsearch -index` and `lsearch -stride`, the latter per TIP 351 8. `lsort -index` now supports multiple indices 9. Add support for `lsort -stride` +10. `open` now supports POSIX-style access arguments Changes between 0.79 and 0.80 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -3506,6 +3507,41 @@ It may have any of the following values: +'access'+ defaults to 'r'. +Additionally, if POSIX mode is supported by the underlying system, +then access may insted of consistent of a list of any of the following +flags, all of which have the standard POSIX meanings. In this case, +the first flag *must* be one of RDONLY, WRONLY or RDWR. + ++RDONLY+:: + Open the file for reading only. + ++WRONLY+:: + Open the file for writing only. + ++RDWR+:: + Open the file for both reading and writing. + ++APPEND+:: + Set the file pointer to the end of the file prior to each write. + ++BINARY+:: + Ignored. + ++CREAT+:: + Create the file if it does not already exist (without this flag + it is an error for the file not to exist). + ++EXCL+:: + If CREAT is also specified, an error is returned if the file + already exists. + ++NOCTTY+:: + If the file is a terminal device, this flag prevents the file + from becoming the controlling terminal of the process. + ++TRUNC+:: + If the file exists it is truncated to zero length. + If a file is opened for both reading and writing, then `seek` must be invoked between a read and a write, or vice versa. diff --git a/tests/aio.test b/tests/aio.test index 4b04dbd..12e41ab 100644 --- a/tests/aio.test +++ b/tests/aio.test @@ -2,6 +2,7 @@ source [file dirname [info script]]/testing.tcl needs constraint jim testCmdConstraints socket +testConstraint unix [expr {$tcl_platform(platform) eq {unix}}] # Create and open in binary mode for compatibility between Windows and Unix set f [open testdata.in wb] @@ -11,6 +12,7 @@ set f [open testdata.in rb] defer { $f close + file delete testdata.in } test aio-1.1 {seek usage} -body { @@ -126,4 +128,32 @@ test aio-8.1 {filename} { $f filename } testdata.in +test aio-9.1 {open: posix modes} -constraints unix -body { + set in [open testdata.in RDONLY] + set buf [$in gets] + $in close + set buf +} -result {test-data} + +test aio-9.2 {open: posix modes, bad modes} -constraints unix -body { + open testdata.in {CREAT TRUNC} +} -returnCodes error -result {testdata.in: Invalid argument} + +test aio-9.3 {open: posix modes, bad modes} -constraints unix -body { + open testdata.in {WRONG TRUNC} +} -returnCodes error -result {bad access mode "WRONG": must be APPEND, BINARY, CREAT, EXCL, NOCTTY, RDONLY, RDWR, TRUNC, or WRONLY} + +test aio-9.4 {open: posix modes} -constraints unix -cleanup { + file delete testdata.out +} -body { + set out [open testdata.out {WRONLY CREAT TRUNC}] + $out puts write-data + $out close + # Now open for readwrite without truncate + set io [open testdata.out {RDWR CREAT}] + set buf [$io gets] + $io close + set buf +} -result {write-data} + testreport |