summaryrefslogtreecommitdiffstats
path: root/runtime/stream.c
diff options
context:
space:
mode:
Diffstat (limited to 'runtime/stream.c')
-rw-r--r--runtime/stream.c111
1 files changed, 94 insertions, 17 deletions
diff --git a/runtime/stream.c b/runtime/stream.c
index 94fc0ca7..b35d6a11 100644
--- a/runtime/stream.c
+++ b/runtime/stream.c
@@ -256,7 +256,9 @@ doPhysOpen(strm_t *pThis)
if(pThis->cryprov != NULL) {
CHKiRet(pThis->cryprov->OnFileOpen(pThis->cryprovData,
- pThis->pszCurrFName, &pThis->cryprovFileData));
+ pThis->pszCurrFName, &pThis->cryprovFileData,
+ (pThis->tOperationsMode == STREAMMODE_READ) ? 'r' : 'w'));
+ pThis->cryprov->SetDeleteOnClose(pThis->cryprovFileData, pThis->bDeleteOnClose);
}
finalize_it:
RETiRet;
@@ -404,6 +406,12 @@ static rsRetVal strmCloseFile(strm_t *pThis)
}
}
+ /* if we have a signature provider, we must make sure that the crypto
+ * state files are opened and proper close processing happens. */
+ if(pThis->cryprov != NULL && pThis->fd == -1) {
+ strmOpenFile(pThis);
+ }
+
/* the file may already be closed (or never have opened), so guard
* against this. -- rgerhards, 2010-03-19
*/
@@ -550,11 +558,14 @@ finalize_it:
* rgerhards, 2008-02-13
*/
static rsRetVal
-strmReadBuf(strm_t *pThis)
+strmReadBuf(strm_t *pThis, int *padBytes)
{
DEFiRet;
int bRun;
long iLenRead;
+ size_t actualDataLen;
+ size_t toRead;
+ ssize_t bytesLeft;
ISOBJ_TYPE_assert(pThis, strm);
/* We need to try read at least twice because we may run into EOF and need to switch files. */
@@ -565,13 +576,35 @@ strmReadBuf(strm_t *pThis)
* rgerhards, 2008-02-13
*/
CHKiRet(strmOpenFile(pThis));
- iLenRead = read(pThis->fd, pThis->pIOBuf, pThis->sIOBufSize);
+ if(pThis->cryprov == NULL) {
+ toRead = pThis->sIOBufSize;
+ } else {
+ CHKiRet(pThis->cryprov->GetBytesLeftInBlock(pThis->cryprovFileData, &bytesLeft));
+ if(bytesLeft == -1 || bytesLeft > (ssize_t) pThis->sIOBufSize) {
+ toRead = pThis->sIOBufSize;
+ } else {
+ toRead = (size_t) bytesLeft;
+ }
+ }
+ iLenRead = read(pThis->fd, pThis->pIOBuf, toRead);
DBGOPRINT((obj_t*) pThis, "file %d read %ld bytes\n", pThis->fd, iLenRead);
+ /* end crypto */
if(iLenRead == 0) {
CHKiRet(strmHandleEOF(pThis));
} else if(iLenRead < 0)
ABORT_FINALIZE(RS_RET_IO_ERROR);
else { /* good read */
+ /* here we place our crypto interface */
+ if(pThis->cryprov != NULL) {
+ actualDataLen = iLenRead;
+ pThis->cryprov->Decrypt(pThis->cryprovFileData, pThis->pIOBuf, &actualDataLen);
+ *padBytes = iLenRead - actualDataLen;
+ iLenRead = actualDataLen;
+ DBGOPRINT((obj_t*) pThis, "encrypted file %d pad bytes %d, actual "
+ "data %ld\n", pThis->fd, *padBytes, iLenRead);
+ } else {
+ *padBytes = 0;
+ }
pThis->iBufPtrMax = iLenRead;
bRun = 0; /* exit loop */
}
@@ -593,6 +626,7 @@ finalize_it:
*/
static rsRetVal strmReadChar(strm_t *pThis, uchar *pC)
{
+ int padBytes = 0; /* in crypto mode, we may have some padding (non-data) bytes */
DEFiRet;
ASSERT(pThis != NULL);
@@ -608,8 +642,9 @@ static rsRetVal strmReadChar(strm_t *pThis, uchar *pC)
/* do we need to obtain a new buffer? */
if(pThis->iBufPtr >= pThis->iBufPtrMax) {
- CHKiRet(strmReadBuf(pThis));
+ CHKiRet(strmReadBuf(pThis, &padBytes));
}
+ pThis->iCurrOffs += padBytes;
/* if we reach this point, we have data available in the buffer */
@@ -645,7 +680,7 @@ static rsRetVal strmUnreadChar(strm_t *pThis, uchar c)
* destruction of the returned CStr object! -- dlang 2010-12-13
*/
static rsRetVal
-strmReadLine(strm_t *pThis, cstr_t **ppCStr, int mode)
+strmReadLine(strm_t *pThis, cstr_t **ppCStr, uint8_t mode, sbool bEscapeLF)
{
/* mode = 0 single line mode (equivalent to ReadLine)
* mode = 1 LFLF mode (paragraph, blank line between entries)
@@ -655,6 +690,7 @@ strmReadLine(strm_t *pThis, cstr_t **ppCStr, int mode)
uchar c;
uchar finished;
rsRetVal readCharRet;
+ sbool bPrevWasNL;
DEFiRet;
ASSERT(pThis != NULL);
@@ -680,18 +716,25 @@ strmReadLine(strm_t *pThis, cstr_t **ppCStr, int mode)
CHKiRet(cstrFinalize(*ppCStr));
} else if(mode == 1) {
finished=0;
+ bPrevWasNL = 0;
while(finished == 0){
if(c != '\n') {
CHKiRet(cstrAppendChar(*ppCStr, c));
CHKiRet(strmReadChar(pThis, &c));
+ bPrevWasNL = 0;
} else {
if ((((*ppCStr)->iStrLen) > 0) ){
- if ((*ppCStr)->pBuf[(*ppCStr)->iStrLen -1 ] == '\n'){
- rsCStrTruncate(*ppCStr,1); /* remove the prior newline */
+ if(bPrevWasNL) {
+ rsCStrTruncate(*ppCStr, (bEscapeLF) ? 4 : 1); /* remove the prior newline */
finished=1;
} else {
- CHKiRet(cstrAppendChar(*ppCStr, c));
+ if(bEscapeLF) {
+ CHKiRet(rsCStrAppendStrWithLen(*ppCStr, (uchar*)"#012", sizeof("#012")-1));
+ } else {
+ CHKiRet(cstrAppendChar(*ppCStr, c));
+ }
CHKiRet(strmReadChar(pThis, &c));
+ bPrevWasNL = 1;
}
} else {
finished=1; /* this is a blank line, a \n with nothing since the last complete record */
@@ -702,6 +745,7 @@ strmReadLine(strm_t *pThis, cstr_t **ppCStr, int mode)
} else if(mode == 2) {
/* indented follow-up lines */
finished=0;
+ bPrevWasNL = 0;
while(finished == 0){
if ((*ppCStr)->iStrLen == 0){
if(c != '\n') {
@@ -712,22 +756,31 @@ strmReadLine(strm_t *pThis, cstr_t **ppCStr, int mode)
finished=1; /* this is a blank line, a \n with nothing since the last complete record */
}
} else {
- if ((*ppCStr)->pBuf[(*ppCStr)->iStrLen -1 ] != '\n'){
- /* not the first character after a newline, add it to the buffer */
- CHKiRet(cstrAppendChar(*ppCStr, c));
- CHKiRet(strmReadChar(pThis, &c));
- } else {
+ if(bPrevWasNL) {
if ((c == ' ') || (c == '\t')){
CHKiRet(cstrAppendChar(*ppCStr, c));
CHKiRet(strmReadChar(pThis, &c));
+ bPrevWasNL = 0;
} else {
/* clean things up by putting the character we just read back into
* the input buffer and removing the LF character that is currently at the
* end of the output string */
CHKiRet(strmUnreadChar(pThis, c));
- rsCStrTruncate(*ppCStr,1);
+ rsCStrTruncate(*ppCStr, (bEscapeLF) ? 4 : 1);
finished=1;
}
+ } else { /* not the first character after a newline, add it to the buffer */
+ if(c == '\n') {
+ bPrevWasNL = 1;
+ if(bEscapeLF) {
+ CHKiRet(rsCStrAppendStrWithLen(*ppCStr, (uchar*)"#012", sizeof("#012")-1));
+ } else {
+ CHKiRet(cstrAppendChar(*ppCStr, c));
+ }
+ } else {
+ CHKiRet(cstrAppendChar(*ppCStr, c));
+ }
+ CHKiRet(strmReadChar(pThis, &c));
}
}
}
@@ -1454,6 +1507,8 @@ strmMultiFileSeek(strm_t *pThis, int FNum, off64_t offs, off64_t *bytesDel)
"deleting '%s' (%lld bytes)\n", pThis->iCurrFNum, FNum,
pThis->pszCurrFName, (long long) *bytesDel);
unlink((char*)pThis->pszCurrFName);
+ if(pThis->cryprov != NULL)
+ pThis->cryprov->DeleteStateFiles(pThis->pszCurrFName);
free(pThis->pszCurrFName);
pThis->pszCurrFName = NULL;
pThis->iCurrFNum = FNum;
@@ -1467,17 +1522,31 @@ finalize_it:
}
-
/* seek to current offset. This is primarily a helper to readjust the OS file
* pointer after a strm object has been deserialized.
*/
static rsRetVal strmSeekCurrOffs(strm_t *pThis)
{
+ off64_t targetOffs;
+ uchar c;
DEFiRet;
ISOBJ_TYPE_assert(pThis, strm);
- iRet = strmSeek(pThis, pThis->iCurrOffs);
+ if(pThis->cryprov == NULL || pThis->tOperationsMode != STREAMMODE_READ) {
+ iRet = strmSeek(pThis, pThis->iCurrOffs);
+ FINALIZE;
+ }
+
+ /* As the cryprov may use CBC or similiar things, we need to read skip data */
+ targetOffs = pThis->iCurrOffs;
+ pThis->iCurrOffs = 0;
+ DBGOPRINT((obj_t*) pThis, "encrypted, doing skip read of %lld bytes\n",
+ (long long) targetOffs);
+ while(targetOffs != pThis->iCurrOffs) {
+ CHKiRet(strmReadChar(pThis, &c));
+ }
+finalize_it:
RETiRet;
}
@@ -1604,7 +1673,6 @@ finalize_it:
/* property set methods */
/* simple ones first */
-DEFpropSetMeth(strm, bDeleteOnClose, int)
DEFpropSetMeth(strm, iMaxFileSize, int64)
DEFpropSetMeth(strm, iFileNumDigits, int)
DEFpropSetMeth(strm, tOperationsMode, int)
@@ -1620,6 +1688,15 @@ DEFpropSetMeth(strm, pszSizeLimitCmd, uchar*)
DEFpropSetMeth(strm, cryprov, cryprov_if_t*)
DEFpropSetMeth(strm, cryprovData, void*)
+static rsRetVal strmSetbDeleteOnClose(strm_t *pThis, int val)
+{
+ pThis->bDeleteOnClose = val;
+ if(pThis->cryprov != NULL) {
+ pThis->cryprov->SetDeleteOnClose(pThis->cryprovFileData, pThis->bDeleteOnClose);
+ }
+ return RS_RET_OK;
+}
+
static rsRetVal strmSetiMaxFiles(strm_t *pThis, int iNewVal)
{
pThis->iMaxFiles = iNewVal;