diff --git a/doc/xml/release.xml b/doc/xml/release.xml
index 6d186e5c8..11c112d81 100644
--- a/doc/xml/release.xml
+++ b/doc/xml/release.xml
@@ -71,6 +71,10 @@
Resolve storage path expressions before passing to remote.
+
+ Expose handle (file descriptor) from IoRead
when applicable.
+
+
Add storageHelperFree()
to storage helper.
diff --git a/src/common/exec.c b/src/common/exec.c
index 31d3dc444..7995e9c9c 100644
--- a/src/common/exec.c
+++ b/src/common/exec.c
@@ -153,7 +153,9 @@ execOpen(Exec *this)
ioWriteOpen(this->ioWriteHandle);
// Create wrapper interfaces that check process state
- this->ioReadExec = ioReadNewP(this, .read = (IoReadInterfaceRead)execRead, .eof = (IoReadInterfaceEof)execEof);
+ this->ioReadExec = ioReadNewP(
+ this, .read = (IoReadInterfaceRead)execRead, .eof = (IoReadInterfaceEof)execEof,
+ .handle = (IoReadInterfaceHandle)execHandleRead);
ioReadOpen(this->ioReadExec);
this->ioWriteExec = ioWriteNewP(this, .write = (IoWriteInterfaceWrite)execWrite);
ioWriteOpen(this->ioWriteExec);
@@ -335,6 +337,21 @@ execMemContext(const Exec *this)
FUNCTION_TEST_RETURN(this->memContext);
}
+/***********************************************************************************************************************************
+Get the read handle
+***********************************************************************************************************************************/
+int
+execHandleRead(Exec *this)
+{
+ FUNCTION_TEST_BEGIN();
+ FUNCTION_TEST_PARAM(EXEC, this);
+ FUNCTION_TEST_END();
+
+ ASSERT(this != NULL);
+
+ FUNCTION_TEST_RETURN(this->handleRead);
+}
+
/***********************************************************************************************************************************
Free the object
***********************************************************************************************************************************/
diff --git a/src/common/exec.h b/src/common/exec.h
index 2064c284c..4cc21280c 100644
--- a/src/common/exec.h
+++ b/src/common/exec.h
@@ -38,6 +38,7 @@ bool execEof(Exec *this);
IoRead *execIoRead(const Exec *this);
IoWrite *execIoWrite(const Exec *this);
MemContext *execMemContext(const Exec *this);
+int execHandleRead(Exec *this);
/***********************************************************************************************************************************
Destructor
diff --git a/src/common/io/handleRead.c b/src/common/io/handleRead.c
index 06dcf8853..a42a7dc08 100644
--- a/src/common/io/handleRead.c
+++ b/src/common/io/handleRead.c
@@ -41,7 +41,9 @@ ioHandleReadNew(const String *name, int handle, TimeMSec timeout)
{
this = memNew(sizeof(IoHandleRead));
this->memContext = memContextCurrent();
- this->io = ioReadNewP(this, .eof = (IoReadInterfaceEof)ioHandleReadEof, .read = (IoReadInterfaceRead)ioHandleRead);
+ this->io = ioReadNewP(
+ this, .eof = (IoReadInterfaceEof)ioHandleReadEof, .handle = (IoReadInterfaceHandle)ioHandleReadHandle,
+ .read = (IoReadInterfaceRead)ioHandleRead);
this->name = strDup(name);
this->handle = handle;
this->timeout = timeout;
@@ -146,6 +148,21 @@ ioHandleReadEof(const IoHandleRead *this)
FUNCTION_LOG_RETURN(BOOL, this->eof);
}
+/***********************************************************************************************************************************
+Get handle (file descriptor)
+***********************************************************************************************************************************/
+int
+ioHandleReadHandle(const IoHandleRead *this)
+{
+ FUNCTION_TEST_BEGIN();
+ FUNCTION_TEST_PARAM(IO_HANDLE_READ, this);
+ FUNCTION_TEST_END();
+
+ ASSERT(this != NULL);
+
+ FUNCTION_TEST_RETURN(this->handle);
+}
+
/***********************************************************************************************************************************
Get io interface
***********************************************************************************************************************************/
diff --git a/src/common/io/handleRead.h b/src/common/io/handleRead.h
index cb5a854ef..dc9d21ae8 100644
--- a/src/common/io/handleRead.h
+++ b/src/common/io/handleRead.h
@@ -29,6 +29,7 @@ IoHandleRead *ioHandleReadMove(IoHandleRead *this, MemContext *parentNew);
Getters
***********************************************************************************************************************************/
bool ioHandleReadEof(const IoHandleRead *this);
+int ioHandleReadHandle(const IoHandleRead *this);
IoRead *ioHandleReadIo(const IoHandleRead *this);
/***********************************************************************************************************************************
diff --git a/src/common/io/read.c b/src/common/io/read.c
index 5009443c4..e877bf6f6 100644
--- a/src/common/io/read.c
+++ b/src/common/io/read.c
@@ -357,6 +357,23 @@ ioReadFilterGroupSet(IoRead *this, IoFilterGroup *filterGroup)
FUNCTION_LOG_RETURN_VOID();
}
+/***********************************************************************************************************************************
+Handle (file descriptor) for the read object
+
+No all read objects have a handle and -1 will be returned in that case.
+***********************************************************************************************************************************/
+int
+ioReadHandle(const IoRead *this)
+{
+ FUNCTION_LOG_BEGIN(logLevelTrace);
+ FUNCTION_LOG_PARAM(IO_READ, this);
+ FUNCTION_LOG_END();
+
+ ASSERT(this != NULL);
+
+ FUNCTION_LOG_RETURN(INT, this->interface.handle == NULL ? -1 : this->interface.handle(this->driver));
+}
+
/***********************************************************************************************************************************
Free the object
***********************************************************************************************************************************/
diff --git a/src/common/io/read.h b/src/common/io/read.h
index fb6a14eec..acad04edc 100644
--- a/src/common/io/read.h
+++ b/src/common/io/read.h
@@ -31,6 +31,7 @@ Getters/Setters
bool ioReadEof(const IoRead *this);
const IoFilterGroup *ioReadFilterGroup(const IoRead *this);
void ioReadFilterGroupSet(IoRead *this, IoFilterGroup *filterGroup);
+int ioReadHandle(const IoRead *this);
/***********************************************************************************************************************************
Destructor
diff --git a/src/common/io/read.intern.h b/src/common/io/read.intern.h
index 8feec24c6..1ef3918b7 100644
--- a/src/common/io/read.intern.h
+++ b/src/common/io/read.intern.h
@@ -12,12 +12,14 @@ Constructor
typedef bool (*IoReadInterfaceEof)(void *driver);
typedef void (*IoReadInterfaceClose)(void *driver);
typedef bool (*IoReadInterfaceOpen)(void *driver);
+typedef int (*IoReadInterfaceHandle)(void *driver);
typedef size_t (*IoReadInterfaceRead)(void *driver, Buffer *buffer, bool block);
typedef struct IoReadInterface
{
IoReadInterfaceEof eof;
IoReadInterfaceClose close;
+ IoReadInterfaceHandle handle;
IoReadInterfaceOpen open;
IoReadInterfaceRead read;
} IoReadInterface;
diff --git a/test/src/module/common/execTest.c b/test/src/module/common/execTest.c
index e246a1204..9cdf7d862 100644
--- a/test/src/module/common/execTest.c
+++ b/test/src/module/common/execTest.c
@@ -27,6 +27,7 @@ testRun(void)
// -------------------------------------------------------------------------------------------------------------------------
TEST_ASSIGN(exec, execNew(strNew("cat"), NULL, strNew("cat"), 1000), "new cat exec");
TEST_RESULT_PTR(execMemContext(exec), exec->memContext, "get mem context");
+ TEST_RESULT_INT(execHandleRead(exec), exec->handleRead, "check read handle");
TEST_RESULT_VOID(execOpen(exec), "open cat exec");
String *message = strNew("ACKBYACK");
diff --git a/test/src/module/common/ioTest.c b/test/src/module/common/ioTest.c
index 963fd7436..8735dd94c 100644
--- a/test/src/module/common/ioTest.c
+++ b/test/src/module/common/ioTest.c
@@ -519,6 +519,7 @@ testRun(void)
MEM_CONTEXT_TEMP_END();
ioReadOpen(ioHandleReadIo(read));
+ TEST_RESULT_INT(ioReadHandle(ioHandleReadIo(read)), read->handle, "check handle");
// Read a string
TEST_RESULT_STR(strPtr(ioReadLine(ioHandleReadIo(read))), "test string 1", "read test string");