mirror of
https://github.com/status-im/nim-stew.git
synced 2025-01-09 11:45:42 +00:00
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,
|
lpNewFilePointer: ptr int64,
|
||||||
dwMoveMethod: uint32): int32 {.
|
dwMoveMethod: uint32): int32 {.
|
||||||
importc: "SetFilePointerEx", dynlib: "kernel32", stdcall, sideEffect.}
|
importc: "SetFilePointerEx", dynlib: "kernel32", stdcall, sideEffect.}
|
||||||
|
proc setEndOfFile(hFile: uint): int32 {.
|
||||||
|
importc: "SetEndOfFile", dynlib: "kernel32", stdcall, sideEffect.}
|
||||||
proc lockFileEx(hFile: uint, dwFlags, dwReserved: uint32,
|
proc lockFileEx(hFile: uint, dwFlags, dwReserved: uint32,
|
||||||
nNumberOfBytesToLockLow, nNumberOfBytesToLockHigh: uint32,
|
nNumberOfBytesToLockLow, nNumberOfBytesToLockHigh: uint32,
|
||||||
lpOverlapped: pointer): uint32 {.
|
lpOverlapped: pointer): uint32 {.
|
||||||
@ -1341,6 +1343,45 @@ proc setFilePos*(handle: IoHandle, offset: int64,
|
|||||||
else:
|
else:
|
||||||
ok()
|
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] =
|
proc checkFileSize*(value: int64): IoResult[int] =
|
||||||
## Checks if ``value`` fits into supported by Nim string/sequence indexing
|
## Checks if ``value`` fits into supported by Nim string/sequence indexing
|
||||||
## mechanism.
|
## mechanism.
|
||||||
|
@ -792,3 +792,54 @@ suite "OS Input/Output procedures test suite":
|
|||||||
check:
|
check:
|
||||||
res.isOk()
|
res.isOk()
|
||||||
len(res.get()) > 0
|
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…
x
Reference in New Issue
Block a user