You should release resources acquired on exceptions, here you leave a file handle hanging. I'm pretty sure the error you get is related to that. Reworked code which should properly cleanup after itself
proc encryptFile(key, key_hash, input_file, output_file: string) =
#var buf: seq[uint8]
echo input_file
echo output_file
var bufSize: int = 1000
var source = newFileStream(input_file, fmRead)
var dest = newFileStream(output_file, fmWrite)
try:
dest.write(key_hash)
# encrypt 1st mb
#var buf_enc: seq[uint8] = @[]
var bytes_temp = source.readStr(1000000)
var bytes_enc = crypto_secretbox_easy(key, bytes_temp)
dest.write(bytes_enc)
# var iters = 1
# while source.atEnd == false or iters <= 1000:
# var bytes_temp = source.readStr(1000)
# dest.write(crypto_secretbox_easy(key, bytes_temp))
# iters = iters + 1
# copy the rest
#var buf: seq[uint8] = @[]
var buf: seq[uint8] = @[]
buf.setLen(bufSize)
while source.atEnd == false:
var bytes = source.readData(buf[0].addr, bufSize)
if bytes == 0:
break
dest.writeData(buf[0].addr, bytes)
except:
echo "Unknown exception!"
finally: # Always release resources
source.close
dest.close
Thanks. Error I get is:
D:\autorun.exe.cypher
Traceback (most recent call last)
crypto.nim(15) encryptFile
streams.nim(154) write
streams.nim(130) writeData
SIGSEGV: Illegal storage access. (Attempt to read from nil?)
Basically when I try to write unwritable file it throws error.
Illegal storage access, is equivalent to nil pointer dereference in Nim, it is not an exception.
Checking the code of writeData:
proc writeData*(s, unused: Stream, buffer: pointer,
bufLen: int) {.deprecated.} =
## low level proc that writes an untyped `buffer` of `bufLen` size
## to the stream `s`.
s.writeDataImpl(s, buffer, bufLen)
This means that buffer is a nil pointer.
Checking the code of newFileStream:
proc newFileStream*(filename: string, mode: FileMode = fmRead, bufSize: int = -1): FileStream =
## creates a new stream from the file named `filename` with the mode `mode`.
## If the file cannot be opened, nil is returned. See the `system
## <system.html>`_ module for a list of available FileMode enums.
var f: File
if open(f, filename, mode, bufSize): result = newFileStream(f)
--> Your file couldn't be opened so you have a nil pointer.
This is mentionned in the documentation of Streams. There is a very new proc called openFileStream that will properly raise an IOError, use it.
Alternatively test for nil:
if dest.isNil:
raise newException(IOError, "Couldn't open destination file")
nil pointer dereference in Nim, it is not an exception.
Maybe we should note that in the language manual -- for people with no experience in c++ or similar languages.
Serasar, you may read also
https://stackoverflow.com/questions/1823721/how-to-catch-the-null-pointer-exception
Microsoft Visual Studio seems to support it in some way...