diff --git a/stew/io2.nim b/stew/io2.nim index ba5a5ba..86bb3c2 100644 --- a/stew/io2.nim +++ b/stew/io2.nim @@ -1356,6 +1356,49 @@ proc setFilePos*(handle: IoHandle, offset: int64, else: ok() +proc updateFilePos*(handle: IoHandle, offset: int64, + whence: SeekPosition): IoResult[int64] = + ## Procedure shall set the file offset for the open file associated with the + ## file descriptor ``handle``, as follows: + ## * If whence is ``SeekPosition.SeekBegin``, the file offset shall be set + ## to ``offset`` bytes. + ## * If whence is ``SeekPosition.SeekCur``, the file offset shall be set to + ## its current location plus ``offset``. + ## * If whence is ``SeekPosition.SeekEnd``, the file offset shall be set to + ## the size of the file plus ``offset``. + ## + ## Returns the resulting offset location as measured in bytes from the + ## beginning of the file. + when defined(windows): + var noffset = 0'i64 + let pos = + case whence + of SeekBegin: + FILE_BEGIN + of SeekCurrent: + FILE_CURRENT + of SeekEnd: + FILE_END + let res = setFilePointerEx(uint(handle), offset, addr noffset, pos) + if res == 0: + err(ioLastError()) + else: + ok(noffset) + else: + let pos = + case whence + of SeekBegin: + posix.SEEK_SET + of SeekCurrent: + posix.SEEK_CUR + of SeekEnd: + posix.SEEK_END + let res = int64(posix.lseek(cint(handle), Off(offset), pos)) + if res == -1'i64: + err(ioLastError()) + else: + ok(res) + proc truncate*(handle: IoHandle, length: int64): IoResult[void] = ## Procedure cause the regular file referenced by handle ``handle`` to be ## truncated to a size of precisely ``length`` bytes. diff --git a/tests/test_io2.nim b/tests/test_io2.nim index 83af09d..f1318f7 100644 --- a/tests/test_io2.nim +++ b/tests/test_io2.nim @@ -629,6 +629,31 @@ suite "OS Input/Output procedures test suite": positions[3] == 10'i64 positions[4] == 20'i64 + test "updateFilePos(handle) test": + proc performTest(path: string): IoResult[tuple[s0, s1, s2, s3, s4: int64]] = + let flags = {OpenFlags.Write, OpenFlags.Truncate, OpenFlags.Create} + let handle = ? openFile(path, flags) + let msg = "AAAAABBBBBCCCCCDDDDD" + discard ? io2.writeFile(handle, msg) + let + pos0 = ? updateFilePos(handle, 0'i64, SeekBegin) + pos1 = ? updateFilePos(handle, 5'i64, SeekCurrent) + pos2 = ? updateFilePos(handle, 5'i64, SeekCurrent) + pos3 = ? updateFilePos(handle, 0'i64, SeekEnd) + pos4 = ? updateFilePos(handle, -5'i64, SeekEnd) + ? closeFile(handle) + ? removeFile(path) + ok((pos0, pos1, pos2, pos3, pos4)) + let res = performTest("testblob4") + check res.isOk() + let positions = res.get() + check: + positions[0] == 0'i64 + positions[1] == 5'i64 + positions[2] == 10'i64 + positions[3] == 20'i64 + positions[4] == 15'i64 + test "lockFile(handle)/unlockFile(handle) test": type TestResult = object