summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorDominik Picheta <dominikpicheta@googlemail.com>2017-04-08 12:24:21 +0200
committerGitHub <noreply@github.com>2017-04-08 12:24:21 +0200
commit27ede215041fb5269670fef98bb655c15a2724a8 (patch)
tree3ecb4a6b70c1c1e739c83f7cfa45f840c7ef0b7e
parentcdfcc12529d716786683c997f1f673bd423432b6 (diff)
parentbc5c2d8414f053281beeb1f3af9c4e03ac49184a (diff)
downloadNim-27ede215041fb5269670fef98bb655c15a2724a8.tar.gz
Merge pull request #5612 from ehmry/AsyncFile.setLen
asyncfile: setLen procedure for files
-rw-r--r--lib/pure/asyncfile.nim24
-rw-r--r--lib/system.nim3
-rw-r--r--lib/system/sysio.nim7
-rw-r--r--tests/async/tasyncfile.nim5
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)