diff options
author | Dominik Picheta <dominikpicheta@googlemail.com> | 2017-04-08 12:24:21 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-04-08 12:24:21 +0200 |
commit | 27ede215041fb5269670fef98bb655c15a2724a8 (patch) | |
tree | 3ecb4a6b70c1c1e739c83f7cfa45f840c7ef0b7e | |
parent | cdfcc12529d716786683c997f1f673bd423432b6 (diff) | |
parent | bc5c2d8414f053281beeb1f3af9c4e03ac49184a (diff) | |
download | Nim-27ede215041fb5269670fef98bb655c15a2724a8.tar.gz |
Merge pull request #5612 from ehmry/AsyncFile.setLen
asyncfile: setLen procedure for files
-rw-r--r-- | lib/pure/asyncfile.nim | 24 | ||||
-rw-r--r-- | lib/system.nim | 3 | ||||
-rw-r--r-- | lib/system/sysio.nim | 7 | ||||
-rw-r--r-- | tests/async/tasyncfile.nim | 5 |
4 files changed, 34 insertions, 5 deletions
diff --git a/lib/pure/asyncfile.nim b/lib/pure/asyncfile.nim index c58e6c11b..86cd8d1be 100644 --- a/lib/pure/asyncfile.nim +++ b/lib/pure/asyncfile.nim @@ -70,14 +70,16 @@ else: result = O_RDWR result = result or O_NONBLOCK -proc getFileSize(f: AsyncFile): int64 = +proc getFileSize*(f: AsyncFile): int64 = ## Retrieves the specified file's size. when defined(windows) or defined(nimdoc): var high: DWord let low = getFileSize(f.fd.Handle, addr high) if low == INVALID_FILE_SIZE: raiseOSError(osLastError()) - return (high shl 32) or low + result = (high shl 32) or low + else: + result = lseek(f.fd.cint, 0, SEEK_END) proc openAsync*(filename: string, mode = fmRead): AsyncFile = ## Opens a file specified by the path in ``filename`` using @@ -466,6 +468,22 @@ proc write*(f: AsyncFile, data: string): Future[void] = addWrite(f.fd, cb) return retFuture +proc setFileSize*(f: AsyncFile, length: int64) = + ## Set a file length. + when defined(windows) or defined(nimdoc): + var + high = (length shr 32).Dword + let + low = (length and 0xffffffff).Dword + status = setFilePointer(f.fd.Handle, low, addr high, 0) + lastErr = osLastError() + if (status == INVALID_SET_FILE_POINTER and lastErr.int32 != NO_ERROR) or + (setEndOfFile(f.fd.Handle) == 0): + raiseOSError(osLastError()) + else: + if ftruncate(f.fd.cint, length) == -1: + raiseOSError(osLastError()) + proc close*(f: AsyncFile) = ## Closes the file specified. unregister(f.fd) @@ -498,4 +516,4 @@ proc readToStream*(f: AsyncFile, fs: FutureStream[string]) {.async.} = break await fs.write(data) - fs.complete() \ No newline at end of file + fs.complete() diff --git a/lib/system.nim b/lib/system.nim index 82d3bb7f7..1bc8eb7e1 100644 --- a/lib/system.nim +++ b/lib/system.nim @@ -2895,6 +2895,9 @@ when not defined(JS): #and not defined(nimscript): proc getFileSize*(f: File): int64 {.tags: [ReadIOEffect], benign.} ## retrieves the file size (in bytes) of `f`. + proc setFileSize*(f: File, size: int64) {.tags: [ReadIOEffect], benign.} + ## changes the size of file `f` (in bytes). + proc readBytes*(f: File, a: var openArray[int8|uint8], start, len: Natural): int {. tags: [ReadIOEffect], benign.} ## reads `len` bytes into the buffer `a` starting at ``a[start]``. Returns diff --git a/lib/system/sysio.nim b/lib/system/sysio.nim index 7444661e3..b199975a9 100644 --- a/lib/system/sysio.nim +++ b/lib/system/sysio.nim @@ -52,6 +52,8 @@ proc c_ferror(f: File): cint {. importc: "ferror", header: "<stdio.h>", tags: [].} proc c_setvbuf(f: File, buf: pointer, mode: cint, size: csize): cint {. importc: "setvbuf", header: "<stdio.h>", tags: [].} +proc c_ftruncate(f: FileHandle, len: clong): cint {. + importc: "ftruncate", header: "<unistd.h>".} proc raiseEIO(msg: string) {.noinline, noreturn.} = sysFatal(IOError, msg) @@ -373,6 +375,11 @@ proc getFileSize(f: File): int64 = result = getFilePos(f) setFilePos(f, oldPos) +proc setFileSize(f: File, size: int64) = + ## Set a file length. + if c_ftruncate(getFileHandle f, size.clong) == -1: + raiseEIO("cannot truncate file") + proc readFile(filename: string): TaintedString = var f: File if open(f, filename): diff --git a/tests/async/tasyncfile.nim b/tests/async/tasyncfile.nim index 26a9bb391..592f0ebd8 100644 --- a/tests/async/tasyncfile.nim +++ b/tests/async/tasyncfile.nim @@ -11,9 +11,10 @@ proc main() {.async.} = # Simple write/read test. block: var file = openAsync(fn, fmReadWrite) - await file.write("test") + await file.write("testing") file.setFilePos(0) await file.write("foo") + file.setFileSize(4) file.setFilePos(0) let data = await file.readAll() doAssert data == "foot" @@ -24,7 +25,7 @@ proc main() {.async.} = var file = openAsync(fn, fmAppend) await file.write("\ntest2") let errorTest = file.readAll() - echo await errorTest + yield errorTest doAssert errorTest.failed file.close() file = openAsync(fn, fmRead) |