Add truncate()/ftruncate() cross-platform implementation. (#225)
This commit is contained in:
parent
54cc67cbb8
commit
8e0e344f0f
41
stew/io2.nim
41
stew/io2.nim
|
@ -183,6 +183,8 @@ when defined(windows):
|
|||
lpNewFilePointer: ptr int64,
|
||||
dwMoveMethod: uint32): int32 {.
|
||||
importc: "SetFilePointerEx", dynlib: "kernel32", stdcall, sideEffect.}
|
||||
proc setEndOfFile(hFile: uint): int32 {.
|
||||
importc: "SetEndOfFile", dynlib: "kernel32", stdcall, sideEffect.}
|
||||
proc lockFileEx(hFile: uint, dwFlags, dwReserved: uint32,
|
||||
nNumberOfBytesToLockLow, nNumberOfBytesToLockHigh: uint32,
|
||||
lpOverlapped: pointer): uint32 {.
|
||||
|
@ -1341,6 +1343,45 @@ proc setFilePos*(handle: IoHandle, offset: int64,
|
|||
else:
|
||||
ok()
|
||||
|
||||
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.
|
||||
when defined(windows):
|
||||
let res1 = setFilePointerEx(uint(handle), length, nil, FILE_BEGIN)
|
||||
if res1 == 0:
|
||||
return err(ioLastError())
|
||||
let res2 = setEndOfFile(uint(handle))
|
||||
if res2 == 0:
|
||||
return err(ioLastError())
|
||||
ok()
|
||||
else:
|
||||
let res = posix.ftruncate(cint(handle), Off(length))
|
||||
if res == -1:
|
||||
err(ioLastError())
|
||||
else:
|
||||
ok()
|
||||
|
||||
proc truncate*(pathName: string, length: int64): IoResult[void] =
|
||||
## Procedure cause the regular file referenced by path ``pathName`` to be
|
||||
## truncated to a size of precisely ``length`` bytes.
|
||||
when defined(windows):
|
||||
let
|
||||
flags = {OpenFlags.Write}
|
||||
handle = openFile(pathName, flags).valueOr:
|
||||
return err(error)
|
||||
res = truncate(handle, length)
|
||||
if res.isErr():
|
||||
discard closeFile(handle)
|
||||
return err(res.error)
|
||||
? closeFile(handle)
|
||||
ok()
|
||||
else:
|
||||
let res = posix.truncate(pathName, Off(length))
|
||||
if res == -1:
|
||||
err(ioLastError())
|
||||
else:
|
||||
ok()
|
||||
|
||||
proc checkFileSize*(value: int64): IoResult[int] =
|
||||
## Checks if ``value`` fits into supported by Nim string/sequence indexing
|
||||
## mechanism.
|
||||
|
|
|
@ -792,3 +792,54 @@ suite "OS Input/Output procedures test suite":
|
|||
check:
|
||||
res.isOk()
|
||||
len(res.get()) > 0
|
||||
|
||||
test "truncate(IoHandle) test":
|
||||
let flags = {OpenFlags.Create, OpenFlags.Write}
|
||||
block:
|
||||
let fdres = openFile("testtruncate1", flags)
|
||||
check:
|
||||
fdres.isOk()
|
||||
truncate(fdres.get(), 100).isOk()
|
||||
closeFile(fdres.get()).isOk()
|
||||
|
||||
block:
|
||||
let res = getFileSize("testtruncate1")
|
||||
check:
|
||||
res.isOk()
|
||||
res.get() == 100
|
||||
|
||||
block:
|
||||
let fdres = openFile("testtruncate1", flags)
|
||||
check:
|
||||
fdres.isOk()
|
||||
truncate(fdres.get(), 0).isOk()
|
||||
closeFile(fdres.get()).isOk()
|
||||
|
||||
block:
|
||||
let res = getFileSize("testtruncate1")
|
||||
check:
|
||||
res.isOk()
|
||||
res.get() == 0
|
||||
|
||||
check removeFile("testtruncate1").isOk()
|
||||
|
||||
test "truncate(path) test":
|
||||
check:
|
||||
writeFile("testtruncate2", "TEST", 0o644).isOk()
|
||||
truncate("testtruncate2", 200).isOk()
|
||||
|
||||
block:
|
||||
let res = getFileSize("testtruncate2")
|
||||
check:
|
||||
res.isOk()
|
||||
res.get() == 200
|
||||
|
||||
check truncate("testtruncate2", 0).isOk()
|
||||
|
||||
block:
|
||||
let res = getFileSize("testtruncate2")
|
||||
check:
|
||||
res.isOk()
|
||||
res.get() == 0
|
||||
|
||||
check removeFile("testtruncate2").isOk()
|
||||
|
|
Loading…
Reference in New Issue