From 583e8ba2b3e0d3e919c136b6c167e41196fb5751 Mon Sep 17 00:00:00 2001 From: Ilya <markovilya197@gmail.com> Date: Tue, 31 Oct 2017 19:07:33 +0300 Subject: [PATCH] fio: new approach for error handling * Add golang-like approach to handle errors * Refactor some issues after review #2751 Closes #2757 --- src/lua/fio.c | 151 ++++++++++++++++++++++------------------ src/lua/fio.lua | 155 ++++++++++++++++++++++------------------- test/app/fio.result | 156 +++++++++++++++++++++++++++++++++++------- test/app/fio.test.lua | 53 ++++++++++---- 4 files changed, 341 insertions(+), 174 deletions(-) diff --git a/src/lua/fio.c b/src/lua/fio.c index ccbd9aaed5..4c9be183a9 100644 --- a/src/lua/fio.c +++ b/src/lua/fio.c @@ -47,6 +47,13 @@ #include "lua/utils.h" #include "coio_file.h" +static inline void +lbox_fio_pushsyserror(struct lua_State *L) +{ + diag_set(SystemError, "fio: %s", strerror(errno)); + luaT_pusherror(L, diag_get()->last); +} + static int lbox_fio_open(struct lua_State *L) { @@ -62,6 +69,11 @@ lbox_fio_open(struct lua_State *L) int mode = lua_tointeger(L, 3); int fh = coio_file_open(pathname, flags, mode); + if (fh < 0) { + lua_pushnil(L); + lbox_fio_pushsyserror(L); + return 2; + } lua_pushinteger(L, fh); return 1; } @@ -77,6 +89,11 @@ lbox_fio_pwrite(struct lua_State *L) size_t offset = lua_tonumber(L, 4); int res = coio_pwrite(fh, buf, len, offset); + if (res < 0) { + lua_pushnil(L); + lbox_fio_pushsyserror(L); + return 2; + } lua_pushinteger(L, res); return 1; } @@ -98,23 +115,34 @@ lbox_fio_pread(struct lua_State *L) if (!buf) { errno = ENOMEM; lua_pushnil(L); - return 1; + lbox_fio_pushsyserror(L); + return 2; } - int res = coio_pread(fh, buf, len, offset); - if (res < 0) { lua_pop(L, 1); lua_pushnil(L); - return 1; + lbox_fio_pushsyserror(L); + return 2; } lua_pushlstring(L, (char *)buf, res); lua_remove(L, -2); return 1; } +static inline int +lbox_fio_pushbool(struct lua_State *L, bool res) +{ + lua_pushboolean(L, res); + if (!res) { + lbox_fio_pushsyserror(L); + return 2; + } + return 1; +} + static int lbox_fio_rename(struct lua_State *L) { @@ -131,8 +159,7 @@ lbox_fio_rename(struct lua_State *L) goto usage; int res = coio_rename(oldpath, newpath); - lua_pushboolean(L, res == 0); - return 1; + return lbox_fio_pushbool(L, res == 0); } static int @@ -147,8 +174,7 @@ lbox_fio_unlink(struct lua_State *L) if (pathname == NULL) goto usage; int res = coio_unlink(pathname); - lua_pushboolean(L, res == 0); - return 1; + return lbox_fio_pushbool(L, res == 0); } static int @@ -157,8 +183,7 @@ lbox_fio_ftruncate(struct lua_State *L) int fd = lua_tointeger(L, 1); off_t length = lua_tonumber(L, 2); int res = coio_ftruncate(fd, length); - lua_pushboolean(L, res == 0); - return 1; + return lbox_fio_pushbool(L, res == 0); } static int @@ -180,8 +205,7 @@ lbox_fio_truncate(struct lua_State *L) length = 0; int res = coio_truncate(pathname, length); - lua_pushboolean(L, res == 0); - return 1; + return lbox_fio_pushbool(L, res == 0); } static int @@ -194,6 +218,11 @@ lbox_fio_write(struct lua_State *L) size_t len = lua_tonumber(L, 3); int res = coio_write(fh, buf, len); + if (res < 0) { + lua_pushnil(L); + lbox_fio_pushsyserror(L); + return 2; + } lua_pushinteger(L, res); return 1; } @@ -242,8 +271,7 @@ lbox_fio_chown(struct lua_State *L) group = entry->gr_gid; } int res = coio_chown(pathname, owner, group); - lua_pushboolean(L, res == 0); - return 1; + return lbox_fio_pushbool(L, res == 0); } static int @@ -259,8 +287,7 @@ lbox_fio_chmod(struct lua_State *L) goto usage; mode_t mode = lua_tointeger(L, 2); - lua_pushboolean(L, coio_chmod(pathname, mode) == 0); - return 1; + return lbox_fio_pushbool(L, coio_chmod(pathname, mode) == 0); } static int @@ -288,7 +315,8 @@ lbox_fio_read(struct lua_State *L) if (res < 0) { lua_pop(L, 1); lua_pushnil(L); - return 1; + lbox_fio_pushsyserror(L); + return 2; } lua_pushlstring(L, (char *)buf, res); lua_remove(L, -2); @@ -357,8 +385,13 @@ DEF_STAT_METHOD(is_sock, S_ISSOCK); #endif static int -lbox_fio_pushstat(struct lua_State *L, const struct stat *stat) +lbox_fio_pushstat(struct lua_State *L, int res, const struct stat *stat) { + if (res < 0) { + lua_pushnil(L); + lbox_fio_pushsyserror(L); + return 2; + } lua_newtable(L); PUSHTABLE("dev", lua_pushinteger, stat->st_dev); @@ -425,11 +458,7 @@ lbox_fio_lstat(struct lua_State *L) struct stat stat; int res = coio_lstat(pathname, &stat); - if (res < 0) { - lua_pushnil(L); - return 1; - } - return lbox_fio_pushstat(L, &stat); + return lbox_fio_pushstat(L, res, &stat); } static int @@ -446,11 +475,7 @@ lbox_fio_stat(struct lua_State *L) struct stat stat; int res = coio_stat(pathname, &stat); - if (res < 0) { - lua_pushnil(L); - return 1; - } - return lbox_fio_pushstat(L, &stat); + return lbox_fio_pushstat(L, res, &stat); } static int @@ -459,11 +484,7 @@ lbox_fio_fstat(struct lua_State *L) int fd = lua_tointeger(L, 1); struct stat stat; int res = coio_fstat(fd, &stat); - if (res < 0) { - lua_pushnil(L); - return 1; - } - return lbox_fio_pushstat(L, &stat); + return lbox_fio_pushstat(L, res, &stat); } @@ -483,12 +504,11 @@ lbox_fio_mkdir(struct lua_State *L) mode_t mode; - if (top >= 2) + if (top >= 2 && !lua_isnil(L, 2)) mode = lua_tointeger(L, 2); else mode = 0777; - lua_pushboolean(L, coio_mkdir(pathname, mode) == 0); - return 1; + return lbox_fio_pushbool(L, coio_mkdir(pathname, mode) == 0); } static int @@ -502,29 +522,28 @@ lbox_fio_rmdir(struct lua_State *L) pathname = lua_tostring(L, 1); if (pathname == NULL) goto usage; - - lua_pushboolean(L, coio_rmdir(pathname) == 0); - return 1; + return lbox_fio_pushbool(L, coio_rmdir(pathname) == 0); } static int -lbox_fio_listdir(struct lua_State *L) { +lbox_fio_listdir(struct lua_State *L) +{ const char *pathname; if (lua_gettop(L) < 1) { luaL_error(L, "Usage: fio.listdir(pathname)"); } pathname = lua_tostring(L, 1); char *buf; - if (coio_readdir(pathname, &buf) >= 0) { - lua_pushstring(L, buf); - free(buf); - } else { + if (coio_readdir(pathname, &buf) < 0) { lua_pushnil(L); + lbox_fio_pushsyserror(L); + return 2; } + lua_pushstring(L, buf); + free(buf); return 1; } - static int lbox_fio_glob(struct lua_State *L) { @@ -578,8 +597,7 @@ lbox_fio_link(struct lua_State *L) linkpath = lua_tostring(L, 2); if (target == NULL || linkpath == NULL) goto usage; - lua_pushboolean(L, coio_link(target, linkpath) == 0); - return 1; + return lbox_fio_pushbool(L, coio_link(target, linkpath) == 0); } static int @@ -595,8 +613,7 @@ lbox_fio_symlink(struct lua_State *L) linkpath = lua_tostring(L, 2); if (target == NULL || linkpath == NULL) goto usage; - lua_pushboolean(L, coio_symlink(target, linkpath) == 0); - return 1; + return lbox_fio_pushbool(L, coio_symlink(target, linkpath) == 0); } static int @@ -614,7 +631,8 @@ lbox_fio_readlink(struct lua_State *L) int res = coio_readlink(pathname, path, PATH_MAX); if (res < 0) { lua_pushnil(L); - return 1; + lbox_fio_pushsyserror(L); + return 2; } lua_pushlstring(L, path, res); lua_remove(L, -2); @@ -628,16 +646,17 @@ lbox_fio_tempdir(struct lua_State *L) if (!buf) { errno = ENOMEM; lua_pushnil(L); - return 1; + lbox_fio_pushsyserror(L); + return 2; } - - if (coio_tempdir(buf, PATH_MAX) == 0) { - lua_pushstring(L, buf); - lua_remove(L, -2); - } else { + if (coio_tempdir(buf, PATH_MAX) != 0) { lua_pushnil(L); + lbox_fio_pushsyserror(L); + return 2; } + lua_pushstring(L, buf); + lua_remove(L, -2); return 1; } @@ -648,7 +667,8 @@ lbox_fio_cwd(struct lua_State *L) if (!buf) { errno = ENOMEM; lua_pushnil(L); - return 1; + lbox_fio_pushsyserror(L); + return 2; } @@ -656,7 +676,9 @@ lbox_fio_cwd(struct lua_State *L) lua_pushstring(L, buf); lua_remove(L, -2); } else { + lbox_fio_pushsyserror(L); lua_pushnil(L); + return 2; } return 1; } @@ -665,31 +687,27 @@ static int lbox_fio_fsync(struct lua_State *L) { int fd = lua_tointeger(L, 1); - lua_pushboolean(L, coio_fsync(fd) == 0); - return 1; + return lbox_fio_pushbool(L, coio_fsync(fd) == 0); } static int lbox_fio_fdatasync(struct lua_State *L) { int fd = lua_tointeger(L, 1); - lua_pushboolean(L, coio_fdatasync(fd) == 0); - return 1; + return lbox_fio_pushbool(L, coio_fdatasync(fd) == 0); } static int lbox_fio_sync(struct lua_State *L) { - lua_pushboolean(L, coio_sync() == 0); - return 1; + return lbox_fio_pushbool(L, coio_sync() == 0); } static int lbox_fio_close(struct lua_State *L) { int fd = lua_tointeger(L, 1); - lua_pushboolean(L, coio_file_close(fd) == 0); - return 1; + return lbox_fio_pushbool(L, coio_file_close(fd) == 0); } static int @@ -698,8 +716,7 @@ lbox_fio_copyfile(struct lua_State *L) const char *source = lua_tostring(L, -2); const char *dest = lua_tostring(L, -1); assert(source != NULL && dest != NULL); - lua_pushboolean(L, coio_copyfile(source, dest) == 0); - return 1; + return lbox_fio_pushbool(L, coio_copyfile(source, dest) == 0); } diff --git a/src/lua/fio.lua b/src/lua/fio.lua index 15a178ab22..32f77a16b6 100644 --- a/src/lua/fio.lua +++ b/src/lua/fio.lua @@ -31,7 +31,10 @@ end fio_methods.write = function(self, data) data = tostring(data) - local res = internal.write(self.fh, data, #data) + local res, err = internal.write(self.fh, data, #data) + if err ~= nil then + return false, err + end return res >= 0 end @@ -48,7 +51,10 @@ fio_methods.pwrite = function(self, data, offset) offset = tonumber(offset) end - local res = internal.pwrite(self.fh, data, len, offset) + local res, err = internal.pwrite(self.fh, data, len, offset) + if err ~= nil then + return false, err + end return res >= 0 end @@ -63,7 +69,6 @@ fio_methods.pread = function(self, len, offset) return internal.pread(self.fh, tonumber(len), tonumber(offset)) end - fio_methods.truncate = function(self, length) if length == nil then length = 0 @@ -85,16 +90,15 @@ fio_methods.seek = function(self, offset, whence) end local res = internal.lseek(self.fh, tonumber(offset), whence) - - if res < 0 then - return nil - end return tonumber(res) end fio_methods.close = function(self) - local res = internal.close(self.fh) + local res, err = internal.close(self.fh) self.fh = -1 + if err ~= nil then + return false, err + end return res end @@ -106,7 +110,6 @@ fio_methods.fdatasync = function(self) return internal.fdatasync(self.fh) end - fio_methods.stat = function(self) return internal.fstat(self.fh) end @@ -117,12 +120,14 @@ local fio_mt = { __index = fio_methods } fio.open = function(path, flags, mode) local iflag = 0 local imode = 0 - + if type(path) ~= 'string' then + error("Usage open(path[, flags[, mode]])") + end if type(flags) ~= 'table' then flags = { flags } end if type(mode) ~= 'table' then - mode = { mode or 0x1FF } -- 0777 + mode = { mode or (bit.band(0x1FF, fio.umask())) } end @@ -148,9 +153,9 @@ fio.open = function(path, flags, mode) end end - local fh = internal.open(tostring(path), iflag, imode) - if fh < 0 then - return nil + local fh, err = internal.open(tostring(path), iflag, imode) + if err ~= nil then + return nil, err end fh = { fh = fh } @@ -190,8 +195,8 @@ fio.pathjoin = function(path, ...) end fio.basename = function(path, suffix) - if path == nil then - return nil + if type(path) ~= 'string' then + error("Usage fio.basename(path[, suffix])") end path = tostring(path) @@ -209,10 +214,9 @@ fio.basename = function(path, suffix) end fio.dirname = function(path) - if path == nil then - return nil + if type(path) ~= 'string' then + error("Usage fio.dirname(path)") end - path = tostring(path) path = ffi.new('char[?]', #path + 1, path) return ffi.string(ffi.C.dirname(path)) end @@ -235,9 +239,9 @@ fio.abspath = function(path) -- following established conventions of fio module: -- letting nil through and converting path to string if path == nil then - return nil + error("Usage fio.abspath(path)") end - path = tostring(path) + path = path local joined_path = '' local path_tab = {} if string.sub(path, 1, 1) == '/' then @@ -256,19 +260,19 @@ fio.abspath = function(path) end fio.chdir = function(path) - if path == nil or type(path)~='string' then - return false + if type(path)~='string' then + error("Usage: fio.chdir(path)") end return ffi.C.chdir(path) == 0 end fio.listdir = function(path) - if path == nil or type(path) ~= 'string' then - return nil + if type(path) ~= 'string' then + error("Usage: fio.listdir(path)") end - local str = internal.listdir(path) - if str == nil then - return nil + local str, err = internal.listdir(path) + if err ~= nil then + return nil, string.format("can't listdir %s: %s", path, err) end local t = {} if str == "" then @@ -282,34 +286,25 @@ fio.listdir = function(path) end fio.mktree = function(path, mode) - path = fio.abspath(path) - if path == nil then - return false + if type(path) ~= "string" then + error("Usage: fio.mktree(path[, mode])") end + path = fio.abspath(path) + local path = string.gsub(path, '^/', '') local dirs = string.split(path, "/") if #dirs == 1 then - if mode then - return fio.mkdir(path, mode) - else - return fio.mkdir(path) - end + return fio.mkdir(path, mode) end - + local st, err local current_dir = "/" for i, dir in ipairs(dirs) do current_dir = fio.pathjoin(current_dir, dir) if not fio.stat(current_dir) then - local res - if mode then - if not fio.mkdir(current_dir, mode) then - res = false - end - else - if not fio.mkdir(current_dir) then - res = false - end + st, err = fio.mkdir(current_dir, mode) + if err ~= nil then + return false, "Error create dir " .. current_dir .. err end end end @@ -317,22 +312,30 @@ fio.mktree = function(path, mode) end fio.rmtree = function(path) - if path == nil then - return false + if type(path) ~= 'string' then + error("Usage: fio.rmtree(path)") end - local path = tostring(path) + local status, err path = fio.abspath(path) - local ls = fio.listdir(path) - + local ls, err = fio.listdir(path) + if err ~= nil then + return nil, err + end for i, f in ipairs(ls) do local tmppath = fio.pathjoin(path, f) - if fio.stat(tmppath):is_dir() then - if not fio.rmtree(tmppath) then - return false + local st = fio.stat(tmppath) + if st and st:is_dir() then + st, err = fio.rmtree(tmppath) + if err ~= nil then + return nil, err end end end - return fio.rmdir(path) + status, err = fio.rmdir(path) + if err ~= nil then + return false, string.format("failed to remove %s: %s", path, err) + end + return true end fio.copyfile = function(from, to) @@ -343,7 +346,11 @@ fio.copyfile = function(from, to) if st and st:is_dir() then to = fio.pathjoin(to, fio.basename(from)) end - return internal.copyfile(from, to) + local _, err = internal.copyfile(from, to) + if err ~= nil then + return false, string.format("failed to copy %s to %s: %s", from, to, err) + end + return true end fio.copytree = function(from, to) @@ -351,43 +358,47 @@ fio.copytree = function(from, to) error('Usage: fio.copytree(from, to)') end local status, reason - from = fio.abspath(from) local st = fio.stat(from) - if st == nil or not st:is_dir() then + if not st then + return false, string.format("Directory %s does not exist", from) + end + if not st:is_dir() then return false, errno.strerror(errno.ENOTDIR) end - local ls = fio.listdir(from) - to = fio.abspath(to) + local ls, err = fio.listdir(from) + if err ~= nil then + return false, err + end -- create tree of destination - local status, reason = fio.mktree(to) - if not status then - return status, reason + status, reason = fio.mktree(to) + if reason ~= nil then + return false, reason end for i, f in ipairs(ls) do local ffrom = fio.pathjoin(from, f) local fto = fio.pathjoin(to, f) local st = fio.lstat(ffrom) - if st:is_dir() then + if st and st:is_dir() then status, reason = fio.copytree(ffrom, fto) - if not status then - return status, reason + if reason ~= nil then + return false, reason end end if st:is_reg() then status, reason = fio.copyfile(ffrom, fto) - if not status then - return status, reason + if reason ~= nil then + return false, reason end end if st:is_link() then local link_to, reason = fio.readlink(ffrom) - if not link_to then - return status, reason + if reason ~= nil then + return false, reason end status, reason = fio.symlink(link_to, fto) - if not status then - return nil, "can't create symlink in place of existing file "..fto + if reason ~= nil then + return false, "can't create symlink in place of existing file "..fto end end end diff --git a/test/app/fio.result b/test/app/fio.result index 4266f4fe7a..6dd3b414e5 100644 --- a/test/app/fio.result +++ b/test/app/fio.result @@ -14,9 +14,16 @@ fio.umask() - 0 ... -- pathjoin -fio.basename(nil, nil) +st, err = pcall(fio.basename, nil, nil) --- -- null +... +st +--- +- false +... +err:match("basename") ~= nil +--- +- true ... fio.pathjoin('abc', 'cde') --- @@ -35,9 +42,16 @@ fio.pathjoin('/', '/cde') - /cde ... -- basename -fio.basename(nil) +st, err = pcall(fio.basename, nil) --- -- null +... +st +--- +- false +... +err:match("basename") ~= nil +--- +- true ... fio.basename('/') --- @@ -75,9 +89,16 @@ file3 = fio.pathjoin(tmpdir, 'file.3') file4 = fio.pathjoin(tmpdir, 'file.4') --- ... -fio.open(nil) +st, err = pcall(fio.open, nil) --- -- null +... +st +--- +- false +... +err:match("open") ~= nil +--- +- true ... fh1 = fio.open(file1, { 'O_RDWR', 'O_TRUNC', 'O_CREAT' }, 0777) --- @@ -341,12 +362,15 @@ string.format('%04o', bit.band(fio.stat(dir2).mode, 0x1FF)) - - true - true ... -{ fh1:close(), errno.strerror(), fh3:close(), errno.strerror() } +fh1:close() --- -- - false - - Bad file descriptor - - false - - Bad file descriptor +- false +- 'fio: Bad file descriptor' +... +fh3:close() +--- +- false +- 'fio: Bad file descriptor' ... fio.rmdir(nil) --- @@ -373,15 +397,16 @@ fio.rmdir(dir2) - false - false - false + - 'fio: No such file or directory' ... fio.rmdir(tmpdir) --- - true ... -{ fio.rmdir(tmpdir), errno.strerror() } +fio.rmdir(tmpdir) --- -- - false - - No such file or directory +- false +- 'fio: No such file or directory' ... fio.unlink() --- @@ -395,9 +420,9 @@ fio.unlink(nil) fh4 = fio.open('newfile', {'O_RDWR','O_CREAT','O_EXCL'}) --- ... -string.format('%o', bit.band(fh4:stat().mode, 0x1FF)) +bit.band(fh4:stat().mode, 0x1FF) == bit.band(fio.umask(), 0x1ff) --- -- '777' +- true ... fh4:close() --- @@ -408,9 +433,16 @@ fio.unlink('newfile') - true ... -- dirname -fio.dirname(nil) +st, err = pcall(fio.dirname, nil) --- -- null +... +st +--- +- false +... +err:match("dirname") ~= nil +--- +- true ... fio.dirname('abc') --- @@ -433,9 +465,16 @@ fio.dirname('/') - / ... -- abspath -fio.abspath(nil) +st, err = pcall(fio.abspath, nil) --- -- null +... +st +--- +- false +... +err:match("abspath") ~= nil +--- +- true ... fio.abspath("/") --- @@ -477,14 +516,28 @@ type(string.find(fio.abspath("tmp"), "tmp")) old_cwd = fio.cwd() --- ... -fio.chdir(nil) +st, err = pcall(fio.chdir, nil) +--- +... +st --- - false ... -fio.chdir(42) +err:match("chdir") ~= nil +--- +- true +... +st, err = pcall(fio.chdir, 42) +--- +... +st --- - false ... +err:match("chdir") ~= nil +--- +- true +... fio.chdir('/no/such/file/or/directory') --- - false @@ -512,6 +565,17 @@ tmpdir = fio.tempdir() dir3 = fio.pathjoin(tmpdir, "dir3") --- ... +st, err = pcall(fio.mkdir, nil) +--- +... +st +--- +- false +... +err:match("mkdir") ~= nil +--- +- true +... fio.mkdir(dir3) --- - true @@ -528,6 +592,11 @@ fio.mkdir(fio.pathjoin(dir3, "3")) --- - true ... +fio.listdir("/no/such/directory/") +--- +- null +- 'can''t listdir /no/such/directory/: fio: No such file or directory' +... ls = fio.listdir(dir3) --- ... @@ -553,6 +622,17 @@ fio.stat(dir3) == nil --- - true ... +st, err = fio.rmtree(dir3) +--- +... +st +--- +- null +... +err:match("No such") ~= nil +--- +- true +... -- mktree tmp1 = fio.pathjoin(tmpdir, "1") --- @@ -563,6 +643,20 @@ tmp2 = fio.pathjoin(tmp1, "2") tree = fio.pathjoin(tmp2, "3") --- ... +tree2 = fio.pathjoin(tmpdir, "4") +--- +... +st, err = pcall(fio.mktree, nil) +--- +... +st +--- +- false +... +err:match("mktree") ~= nil +--- +- true +... fio.mktree(tree) --- - true @@ -575,6 +669,10 @@ fio.stat(tmp2) ~= nil --- - true ... +fio.mktree(tree2, 1) +--- +- true +... -- copy and copytree file1 = fio.pathjoin(tmp1, 'file.1') --- @@ -619,10 +717,17 @@ fio.stat(fio.pathjoin(tmp2, "file.1")) ~= nil --- - true ... -fio.copyfile(fio.pathjoin(tmp1, 'not_exists.txt'), tmp1) +res, err = fio.copyfile(fio.pathjoin(tmp1, 'not_exists.txt'), tmp1) +--- +... +res --- - false ... +err:match("failed to copy") ~= nil +--- +- true +... newdir = fio.pathjoin(tmpdir, "newdir") --- ... @@ -646,3 +751,8 @@ fio.readlink(fio.pathjoin(newdir, "2", "3", "file.3")) == file1 --- - true ... +fio.copytree("/no/such/dir", "/some/where") +--- +- false +- Directory /no/such/dir does not exist +... diff --git a/test/app/fio.test.lua b/test/app/fio.test.lua index 7826993131..d9d181fe69 100644 --- a/test/app/fio.test.lua +++ b/test/app/fio.test.lua @@ -7,14 +7,18 @@ type(fio.umask(0)) fio.umask() -- pathjoin -fio.basename(nil, nil) +st, err = pcall(fio.basename, nil, nil) +st +err:match("basename") ~= nil fio.pathjoin('abc', 'cde') fio.pathjoin('/', 'abc') fio.pathjoin('abc/', '/cde') fio.pathjoin('/', '/cde') -- basename -fio.basename(nil) +st, err = pcall(fio.basename, nil) +st +err:match("basename") ~= nil fio.basename('/') fio.basename('abc') fio.basename('abc.cde', '.cde') @@ -32,7 +36,9 @@ file3 = fio.pathjoin(tmpdir, 'file.3') file4 = fio.pathjoin(tmpdir, 'file.4') -fio.open(nil) +st, err = pcall(fio.open, nil) +st +err:match("open") ~= nil fh1 = fio.open(file1, { 'O_RDWR', 'O_TRUNC', 'O_CREAT' }, 0777) fh1 ~= nil f1s = fh1:stat() @@ -113,7 +119,8 @@ string.format('%04o', bit.band(fio.stat(dir2).mode, 0x1FF)) -- cleanup directories { fh1:close(), fh3:close() } -{ fh1:close(), errno.strerror(), fh3:close(), errno.strerror() } +fh1:close() +fh3:close() fio.rmdir(nil) fio.rmdir(dir1) @@ -122,20 +129,22 @@ fio.rmdir(dir2) { fio.unlink(file1), fio.unlink(file2), fio.unlink(file3), fio.unlink(file4) } { fio.unlink(file1), fio.unlink(file2), fio.unlink(file3), fio.unlink(file4) } fio.rmdir(tmpdir) -{ fio.rmdir(tmpdir), errno.strerror() } +fio.rmdir(tmpdir) fio.unlink() fio.unlink(nil) -- gh-1211 use 0777 if mode omitted in open fh4 = fio.open('newfile', {'O_RDWR','O_CREAT','O_EXCL'}) -string.format('%o', bit.band(fh4:stat().mode, 0x1FF)) +bit.band(fh4:stat().mode, 0x1FF) == bit.band(fio.umask(), 0x1ff) fh4:close() fio.unlink('newfile') -- dirname -fio.dirname(nil) +st, err = pcall(fio.dirname, nil) +st +err:match("dirname") ~= nil fio.dirname('abc') fio.dirname('/abc') fio.dirname('/abc/cde') @@ -143,7 +152,9 @@ fio.dirname('/abc/cde/') fio.dirname('/') -- abspath -fio.abspath(nil) +st, err = pcall(fio.abspath, nil) +st +err:match("abspath") ~= nil fio.abspath("/") fio.abspath("/tmp") fio.abspath("/tmp/test/../") @@ -156,8 +167,12 @@ type(string.find(fio.abspath("tmp"), "tmp")) -- chdir old_cwd = fio.cwd() -fio.chdir(nil) -fio.chdir(42) +st, err = pcall(fio.chdir, nil) +st +err:match("chdir") ~= nil +st, err = pcall(fio.chdir, 42) +st +err:match("chdir") ~= nil fio.chdir('/no/such/file/or/directory') fio.chdir('/') fio.cwd() @@ -167,10 +182,14 @@ fio.cwd() == old_cwd -- listdir tmpdir = fio.tempdir() dir3 = fio.pathjoin(tmpdir, "dir3") +st, err = pcall(fio.mkdir, nil) +st +err:match("mkdir") ~= nil fio.mkdir(dir3) fio.mkdir(fio.pathjoin(dir3, "1")) fio.mkdir(fio.pathjoin(dir3, "2")) fio.mkdir(fio.pathjoin(dir3, "3")) +fio.listdir("/no/such/directory/") ls = fio.listdir(dir3) table.sort(ls, function(a, b) return tonumber(a) < tonumber(b) end) ls @@ -179,15 +198,22 @@ ls fio.stat(dir3) ~= nil fio.rmtree(dir3) fio.stat(dir3) == nil +st, err = fio.rmtree(dir3) +st +err:match("No such") ~= nil -- mktree tmp1 = fio.pathjoin(tmpdir, "1") tmp2 = fio.pathjoin(tmp1, "2") tree = fio.pathjoin(tmp2, "3") +tree2 = fio.pathjoin(tmpdir, "4") +st, err = pcall(fio.mktree, nil) +st +err:match("mktree") ~= nil fio.mktree(tree) fio.stat(tree) ~= nil fio.stat(tmp2) ~= nil - +fio.mktree(tree2, 1) -- copy and copytree file1 = fio.pathjoin(tmp1, 'file.1') @@ -204,7 +230,9 @@ fio.symlink(file1, file3) fio.copyfile(file1, tmp2) fio.stat(fio.pathjoin(tmp2, "file.1")) ~= nil -fio.copyfile(fio.pathjoin(tmp1, 'not_exists.txt'), tmp1) +res, err = fio.copyfile(fio.pathjoin(tmp1, 'not_exists.txt'), tmp1) +res +err:match("failed to copy") ~= nil newdir = fio.pathjoin(tmpdir, "newdir") fio.copytree(fio.pathjoin(tmpdir, "1"), newdir) @@ -212,3 +240,4 @@ fio.stat(fio.pathjoin(newdir, "file.1")) ~= nil fio.stat(fio.pathjoin(newdir, "2", "file.2")) ~= nil fio.stat(fio.pathjoin(newdir, "2", "3", "file.3")) ~= nil fio.readlink(fio.pathjoin(newdir, "2", "3", "file.3")) == file1 +fio.copytree("/no/such/dir", "/some/where") \ No newline at end of file -- GitLab