return true
end
---- Create a hash context.
--- @return Hash context object or false on error.
--- @return Error object on failure.
+--- Create a hash context. Throws error object on failure.
+-- @return Hash context object.
function hash.hash_start()
local errstring, hc
- hc = {}
+ hc = { _data = "" }
hc._ctx, errstring = lsha1.init()
if not hc._ctx then
- return false, err.new("initializing SHA1 context failed: %s", errstring)
+ error(err.new("initializing SHA1 context failed: %s", errstring))
end
- hc._data = ""
return strict.lock(hc)
end
---- Add data to hash context.
+--- Add data to hash context. Throws error object on failure.
-- @param hc the hash context
-- @param data string: data
--- @return True on success, false on error.
--- @return Error object on failure.
function hash.hash_append(hc, data)
+ assert(type(hc) == "table")
+ assert(type(data) == "string")
+ assert(hc._data and hc._ctx)
local rc, errstring
hc._data = hc._data .. data
if #hc._data >= 64*1024 then
rc, errstring = lsha1.update(hc._ctx, hc._data)
if not rc then
- return false, err.new("%s", re)
+ error(err.new("%s", re))
end
hc._data = ""
end
-
- return true
end
---- Hash a line.
+--- Hash data with a new-line character. Throws error object on failure.
-- @param hc the hash context
-- @param data string: data to hash, a newline is appended
--- @return True on success, false on error.
--- @return Error object on failure.
-- @see hash_append
function hash.hash_line(hc, data)
- return hash.hash_append(hc, data .. "\n")
+ hash.hash_append(hc, data .. "\n")
end
--- Hash a file.
-- @return True on success, false on error.
-- @return Error object on failure.
function hash.hash_file(hc, path)
- local f, rc, re, buf
+
+ local function _hash_file(hc, f)
+ local rc, re, buf
+
+ while true do
+ buf, re = eio.fread(f, 64*1024)
+ if not buf then
+ return false, re
+ elseif buf == "" then
+ break
+ end
+
+ hash.hash_append(hc, buf)
+ end
+
+ return true
+ end
+
+ local f, rc, re, ok
f, re = eio.fopen(path, "r")
if not f then
end
trace.disable()
+ ok, rc, re = e2lib.trycall(_hash_file, hc, f)
+ trace.enable()
- while true do
- buf, re = eio.fread(f, 64*1024)
- if not buf then
- trace.enable()
- eio.fclose(f)
- return false, re
- elseif buf == "" then
- break
- end
-
- rc, re = hash.hash_append(hc, buf)
- if not rc then
- trace.enable()
- eio.fclose(f)
- return false, re
- end
+ if not ok then
+ -- rc contains error object/message
+ re = rc
+ rc = false
end
- trace.enable()
+ if not rc then
+ eio.fclose(f)
+ return false, re
+ end
rc, re = eio.fclose(f)
if not rc then
return false, re
end
-
return true
end
return cs
end
- hc, re = hash.hash_start()
- if not hc then
- return false, re
- end
+ hc = hash.hash_start()
rc, re = hash.hash_file(hc, path)
if not rc then
return cs
end
---- Get checksum and release hash context.
+--- Get checksum and release hash context. Throws error object on failure.
-- @param hc the hash context
--- @return SHA1 Checksum, or false on error.
--- @return Error object on failure.
+-- @return SHA1 Checksum.
function hash.hash_finish(hc)
local rc, errstring, cs
rc, errstring = lsha1.update(hc._ctx, hc._data)
if not rc then
- return false, err.new("%s", errstring)
+ error(err.new("%s", errstring))
end
cs, errstring = lsha1.final(hc._ctx)
if not cs then
- return false, err.new("%s", errstring)
+ error(err.new("%s", errstring))
end
-- Destroy the hash context to catch errors