diff --git a/extra/dist/tarantoolctl b/extra/dist/tarantoolctl index e79050ecba676c9bd08ee0d6ac70a46db2bdf882..0011525a0c02788d581887d80fc58f36fad962ac 100755 --- a/extra/dist/tarantoolctl +++ b/extra/dist/tarantoolctl @@ -106,29 +106,6 @@ local fiber = require 'fiber' ffi.cdef[[ int kill(int pid, int sig); ]] -local config_file -local usermode = true - -if os.getenv('HOME') then - config_file = os.getenv('HOME') .. '/.config/tarantool/tarantool' -end - -if not fio.stat(config_file) then - usermode = false - local config_list = { - '/etc/sysconfig/tarantool', - '/etc/default/tarantool', - '/usr/local/etc/tarantool/tarantool', - } - - for _, c in pairs(config_list) do - if fio.stat(c) then - config_file = c - break - end - end -end - local available_commands = { 'start', 'stop', @@ -139,14 +116,41 @@ local available_commands = { 'reload' } +-- +-- true if we're running in HOME directory of a user +-- +local usermode +-- +-- a file with system-wide settings +-- +local default_file +-- +-- instance name +-- +local instance_name +-- +-- +-- +local instance_path +-- +-- console socket +-- +local console_sock + +-- +-- print usage and exit +-- + local function usage() log.error("Usage: %s {%s} instance_name", arg[0], table.concat(available_commands, '|')) - log.error("Config file: %s", config_file) + log.error("Config file: %s", default_file) os.exit(1) end +-- -- shift argv to remove 'tarantoolctl' from arg[0] +-- local function shift_argv(arg, argno, argcount) for i = argno, 128 do arg[i] = arg[i + argcount] @@ -156,80 +160,123 @@ local function shift_argv(arg, argno, argcount) end end -local cmd = arg[1] - -local valid_cmd = false -for _, vcmd in pairs(available_commands) do - if cmd == vcmd then - valid_cmd = true - break +-- +-- Check if the requested action is among +-- supported ones, and return it in this case +-- Otherwise print help and exit. +-- +local function check_cmd(cmd) + for _, vcmd in pairs(available_commands) do + if cmd == vcmd then + return cmd + end end -end - -if not valid_cmd then usage() end -local instance -if arg[2] == nil then - local istat = fio.lstat(arg[0]) - if istat == nil then - log.error("Can't stat %s: %s", arg[0], errno.strerror()) - os.exit(1) +-- +-- Find if we're running under a user, and this +-- user has a default file in his home directory. +-- If present, use it. Otherwise assume a system- +-- wide default. If it's missing, it's OK as well. +-- +local function find_default_file() + if os.getenv('HOME') then + local c = os.getenv('HOME') .. '/.config/tarantool/tarantool' + if fio.stat(c) then + usermode = true + return c + end end - if not istat:is_link() then - usage() + -- + -- no user-level defaults, use a system-wide one + -- + usermode = false + local config_list = { + '/etc/sysconfig/tarantool', + '/etc/default/tarantool', + '/usr/local/etc/tarantool/tarantool', + } + for _, c in pairs(config_list) do + if fio.stat(c) then + return c + end end - instance = fio.basename(arg[0], '.lua') - arg[2] = instance -else - instance = fio.basename(arg[2], '.lua') + -- It's OK if there is no default file - + -- load_default_file() will assume some defaults + return nil end -shift_argv(arg, 0, 2) - -local instance_lua = nil - - -dofile(config_file) -if instance_dir then - instance_lua = fio.pathjoin(instance_dir, instance .. '.lua') - if fio.stat(instance_lua) then - log.info('Found %s.lua in %s', instance, instance_dir) +-- +-- System-wide default file may be missing, this is OK, +-- we'll assume built-in defaults +-- +function load_default_file(default_file) + if default_file then + dofile(default_file) + end + if default_cfg == nil then + default_cfg = {} + end + local d = default_cfg + + d.pid_file = d.pid_file and d.pid_file or "/var/run/tarantool" + d.wal_dir = d.wal_dir and d.wal_dir or "/var/lib/tarantool" + d.snap_dir = d.snap_dir and d.snap_dir or "/var/lib/tarantool" + d.logger = d.logger and d.logger or "/var/log/tarantool" + d.sophia_dir = d.sophia_dir and d.sophia_dir or "/var/lib/tarantool" + + d.pid_file = fio.pathjoin(d.pid_file, instance_name .. '.pid') + d.wal_dir = fio.pathjoin(d.wal_dir, instance_name) + d.snap_dir = fio.pathjoin(d.snap_dir, instance_name) + d.sophia_dir = fio.pathjoin(d.sophia_dir, instance_name) + d.logger = fio.pathjoin(d.logger, instance_name .. '.log') + + if not usermode then + -- change user name only if not running locally + d.username = d.username and d.username or "tarantool" + -- + -- instance_dir must be set in the defaults file, + -- but don't try to set it to the global instance dir + -- if the user-local defaults file is in use + -- + if not instance_dir then + instance_dir = '/etc/tarantool/instances.enabled' + end end -end -instance_dir = nil -instance_lua = nil -if default_cfg == nil then - default_cfg = {} -end + if instance_dir == nil then + log.error('Instance directory (instance_dir) is not set in %s', default_file) + os.exit(-1) + end -if instance_dir == nil then - instance_dir = '/etc/tarantool/instances.enabled' - instance_lua = fio.pathjoin(instance_dir, instance .. '.lua') + if not fio.stat(instance_dir) then + log.error('Instance directory %s does not exist', instance_dir) + os.exit(-1) + end end -default_cfg.pid_file = default_cfg.pid_file and default_cfg.pid_file or "/var/run/tarantool" -default_cfg.wal_dir = default_cfg.wal_dir and default_cfg.wal_dir or "/var/lib/tarantool" -default_cfg.snap_dir = default_cfg.snap_dir and default_cfg.snap_dir or "/var/lib/tarantool" -default_cfg.sophia_dir = default_cfg.sophia_dir and default_cfg.sophia_dir or "/var/lib/tarantool" -default_cfg.logger = default_cfg.logger and default_cfg.logger or "/var/log/tarantool" --- change user name only if not running locally -if not usermode then - default_cfg.username = default_cfg.username and default_cfg.username or "tarantool" +-- +-- In case there is no explicit instance name, +-- check whether arg[0] is a symlink. In that +-- case, the name of the symlink is the instance +-- name. +-- +local function find_instance_name(arg0, arg2) + if arg2 ~= nil then + return fio.basename(arg2, '.lua') + end + local istat = fio.lstat(arg0) + if istat == nil then + log.error("Can't stat %s: %s", arg0, errno.strerror()) + os.exit(1) + end + if not istat:is_link() then + usage() + end + return fio.basename(arg0, '.lua') end --- create a path to the control socket (admin console) -local console_sock = fio.pathjoin(default_cfg.pid_file, instance .. '.control') - -default_cfg.pid_file = fio.pathjoin(default_cfg.pid_file, instance .. '.pid') -default_cfg.wal_dir = fio.pathjoin(default_cfg.wal_dir, instance) -default_cfg.snap_dir = fio.pathjoin(default_cfg.snap_dir, instance) -default_cfg.sophia_dir = fio.pathjoin(default_cfg.sophia_dir, instance, 'sophia') -default_cfg.logger = fio.pathjoin(default_cfg.logger, instance .. '.log') - -local instance_lua = fio.pathjoin(instance_dir, instance .. '.lua') local function mkdir(dirname) log.info("mkdir %s", dirname) @@ -269,30 +316,26 @@ function mk_default_dirs(cfg) end end -local force_cfg = { - pid_file = default_cfg.pid_file, - username = default_cfg.username, - background = true, - custom_proc_title = instance -} - local orig_cfg = box.cfg -wrapper_cfg = function(cfg) - - for i, v in pairs(force_cfg) do - cfg[i] = v - end +local function wrapper_cfg(cfg) for i, v in pairs(default_cfg) do if cfg[i] == nil then cfg[i] = v end end + -- + -- force these startup options + -- + cfg.pid_file = default_cfg.pid_file + cfg.username = default_cfg.username + cfg.background = true + cfg.custom_proc_title = instance_name mk_default_dirs(cfg) local res = orig_cfg(cfg) - require('fiber').name(instance) + require('fiber').name(instance_name) log.info('Run console at %s', console_sock) console.listen(console_sock) @@ -301,15 +344,15 @@ end function stop() log.info("Stopping instance...") - if fio.stat(force_cfg.pid_file) == nil then - log.error("Process is not running (pid: %s)", force_cfg.pid_file) + local pid_file = default_cfg.pid_file + if fio.stat(pid_file) == nil then + log.error("Process is not running (pid: %s)", pid_file) return 0 end - local f = fio.open(force_cfg.pid_file, 'O_RDONLY') + local f = fio.open(pid_file, 'O_RDONLY') if f == nil then - log.error("Can't read pid file %s: %s", - force_cfg.pid_file, errno.strerror()) + log.error("Can't read pid file %s: %s", pid_file, errno.strerror()) return -1 end @@ -319,14 +362,14 @@ function stop() local pid = tonumber(str) if pid == nil or pid <= 0 then - log.error("Broken pid file %s", force_cfg.pid_file) - fio.unlink(force_cfg.pid_file) + log.error("Broken pid file %s", pid_file) + fio.unlink(pid_file) return -1 end if ffi.C.kill(pid, 15) < 0 then log.error("Can't kill process %d: %s", pid, errno.strerror()) - fio.unlink(force_cfg.pid_file) + fio.unlink(pid_file) return -1 end return 0 @@ -335,7 +378,7 @@ end function start() log.info("Starting instance...") box.cfg = wrapper_cfg - local success, data = pcall(dofile, instance_lua) + local success, data = pcall(dofile, instance_path) -- if load fails - show last 10 lines of the log file if not success then print('Start failed: ' .. data) @@ -345,6 +388,32 @@ function start() end end +default_file = find_default_file() + +instance_name = find_instance_name(arg[0], arg[2]) + +local cmd = check_cmd(arg[1]) + +load_default_file(default_file) + +-- +-- Pass the rest of command line arguments to the +-- instsance +-- +shift_argv(arg, 0, 2) + +instance_path = fio.pathjoin(instance_dir, instance_name .. '.lua') + +if not fio.stat(instance_path) then + log.error('Instance %s is not found in %s', instance_name, instance_dir) + os.exit(-1) +end + +log.info('Found %s.lua in %s', instance_name, instance_dir) + +-- create a path to the control socket (admin console) +console_sock = fio.pathjoin(fio.dirname(default_cfg.pid_file), + instance_name .. '.control') if cmd == 'start' then start() @@ -394,18 +463,18 @@ elseif cmd == 'enter' then console.start() os.exit(0) elseif cmd == 'status' then - if fio.stat(force_cfg.pid_file) == nil then + local pid_file = default_cfg.pid_file + if fio.stat(pid_file) == nil then if errno() == errno.ENOENT then - print(instance .. ' is stopped (pid file does not exist)') + print(instance_name .. ' is stopped (pid file does not exist)') os.exit(1) end - log.error("Cant access pidfile %s: %s", - force_cfg.pid_file, errno.strerror()) + log.error("Cant access pidfile %s: %s", pid_file, errno.strerror()) end if fio.stat(console_sock) == nil then if errno() == errno.ENOENT then - log.warn("pidfile is exists, but control socket (%s) isn't", + log.warn("pid file exists, but the control socket (%s) doesn't", console_sock) os.exit(2) end @@ -423,16 +492,20 @@ elseif cmd == 'status' then end s:close() - print(instance .. ' is running (pid:' .. force_cfg.pid_file .. ')') + print(instance_name .. ' is running (pid:' .. default_cfg.pid_file .. ')') os.exit(0) elseif cmd == 'reload' then - if fio.stat(arg[2]) == nil then + if arg[1] == nil then + log.error("Usage: tarantoolctl reload instance_name file.lua") + os.exit(1) + end + if fio.stat(arg[1]) == nil then if errno() == errno.ENOENT then - print(arg[2] .. ': file not found') + print(arg[1] .. ': file not found') os.exit(1) end end - dofile(arg[2]) + dofile(arg[1]) else log.error("Unknown command '%s'", cmd) os.exit(-1) diff --git a/src/lua/fio.cc b/src/lua/fio.cc index 28507687681f398f3c272a02a6619130d19cc12a..5dfb85b130d2e73e96fc5e843948c542b637a638 100644 --- a/src/lua/fio.cc +++ b/src/lua/fio.cc @@ -49,11 +49,18 @@ extern "C" { static int lbox_fio_open(struct lua_State *L) { - const char *path = lua_tostring(L, 1); + const char *pathname; + if (lua_gettop(L) < 1) { +usage: + luaL_error(L, "Usage: fio.open(path, flags, mode)"); + } + pathname = lua_tostring(L, 1); + if (pathname == NULL) + goto usage; int flags = lua_tointeger(L, 2); int mode = lua_tointeger(L, 3); - int fh = coeio_open(path, flags, mode); + int fh = coeio_open(pathname, flags, mode); lua_pushinteger(L, fh); return 1; } @@ -63,6 +70,8 @@ lbox_fio_pwrite(struct lua_State *L) { int fh = lua_tointeger(L, 1); const char *buf = lua_tostring(L, 2); + if (buf == NULL) + luaL_error(L, "fio.pwrite(): buffer is not a string"); size_t len = lua_tonumber(L, 3); size_t offset = lua_tonumber(L, 4); @@ -108,13 +117,18 @@ lbox_fio_pread(struct lua_State *L) static int lbox_fio_rename(struct lua_State *L) { - const char *oldpath, *newpath; - int top = lua_gettop(L); - if (top < 2 || !(oldpath = lua_tostring(L, 1)) || - !(newpath = lua_tostring(L, 2))) { + const char *oldpath; + const char *newpath; + if (lua_gettop(L) < 2) { +usage: luaL_error(L, "Usage: fio.rename(oldpath, newpath)"); - return 0; } + oldpath = lua_tostring(L, 1); + newpath = lua_tostring(L, 2); + + if (oldpath == NULL || newpath == NULL) + goto usage; + int res = coeio_rename(oldpath, newpath); lua_pushboolean(L, res == 0); return 1; @@ -123,14 +137,14 @@ lbox_fio_rename(struct lua_State *L) static int lbox_fio_unlink(struct lua_State *L) { - if (lua_gettop(L) < 1) + const char *pathname; + if (lua_gettop(L) < 1) { +usage: luaL_error(L, "Usage: fio.unlink(pathname)"); - const char *pathname = lua_tostring(L, 1); - if (!pathname) { - errno = EINVAL; - lua_pushboolean(L, 0); - return 1; } + pathname = lua_tostring(L, 1); + if (pathname == NULL) + goto usage; int res = coeio_unlink(pathname); lua_pushboolean(L, res == 0); return 1; @@ -149,16 +163,21 @@ lbox_fio_ftruncate(struct lua_State *L) static int lbox_fio_truncate(struct lua_State *L) { + const char *pathname; int top = lua_gettop(L); - if (top < 1) + if (top < 1) { +usage: luaL_error(L, "Usage: fio.truncate(pathname[, newlen])"); - const char *path = lua_tostring(L, 1); + } + pathname = lua_tostring(L, 1); + if (pathname == NULL) + goto usage; off_t length; if (top >= 2) length = lua_tonumber(L, 2); else length = 0; - int res = coeio_truncate(path, length); + int res = coeio_truncate(pathname, length); lua_pushboolean(L, res == 0); return 1; @@ -169,6 +188,9 @@ lbox_fio_write(struct lua_State *L) { int fh = lua_tointeger(L, 1); const char *buf = lua_tostring(L, 2); + if (buf == NULL) + luaL_error(L, "fio.write(): buffer is not a string"); + size_t len = lua_tonumber(L, 3); int res = coeio_write(fh, buf, len); lua_pushinteger(L, res); @@ -178,14 +200,22 @@ lbox_fio_write(struct lua_State *L) static int lbox_fio_chown(struct lua_State *L) { - if (lua_gettop(L) < 3) + const char *pathname; + if (lua_gettop(L) < 3) { +usage: luaL_error(L, "Usage: fio.chown(pathname, owner, group)"); - const char *path = lua_tostring(L, 1); + } + pathname = lua_tostring(L, 1); + if (pathname == NULL) + goto usage; + uid_t owner; if (lua_isnumber(L, 2)) { owner = lua_tointeger(L, 2); } else { const char *username = lua_tostring(L, 2); + if (username == NULL) + username = ""; struct passwd *entry = getpwnam(username); if (!entry) { errno = EINVAL; @@ -200,6 +230,8 @@ lbox_fio_chown(struct lua_State *L) group = lua_tointeger(L, 3); } else { const char *groupname = lua_tostring(L, 3); + if (groupname == NULL) + groupname = ""; struct group *entry = getgrnam(groupname); if (!entry) { errno = EINVAL; @@ -208,7 +240,7 @@ lbox_fio_chown(struct lua_State *L) } group = entry->gr_gid; } - int res = coeio_chown(path, owner, group); + int res = coeio_chown(pathname, owner, group); lua_pushboolean(L, res == 0); return 1; } @@ -216,11 +248,17 @@ lbox_fio_chown(struct lua_State *L) static int lbox_fio_chmod(struct lua_State *L) { - if (lua_gettop(L) < 2) + const char *pathname; + if (lua_gettop(L) < 2) { +usage: luaL_error(L, "Usage: fio.chmod(pathname, mode)"); - const char *path = lua_tostring(L, 1); + } + pathname = lua_tostring(L, 1); + if (pathname == NULL) + goto usage; + mode_t mode = lua_tointeger(L, 2); - lua_pushboolean(L, coeio_chmod(path, mode) == 0); + lua_pushboolean(L, coeio_chmod(pathname, mode) == 0); return 1; } @@ -375,9 +413,14 @@ lbox_fio_pushstat(struct lua_State *L, const struct stat *stat) static int lbox_fio_lstat(struct lua_State *L) { - if (lua_gettop(L) < 1) + const char *pathname; + if (lua_gettop(L) < 1) { +usage: luaL_error(L, "pathname is absent"); - const char *pathname = lua_tostring(L, 1); + } + pathname = lua_tostring(L, 1); + if (pathname == NULL) + goto usage; struct stat stat; int res = coeio_lstat(pathname, &stat); @@ -391,9 +434,14 @@ lbox_fio_lstat(struct lua_State *L) static int lbox_fio_stat(struct lua_State *L) { - if (lua_gettop(L) < 1) - luaL_error(L, "pathname is absent"); - const char *pathname = lua_tostring(L, 1); + const char *pathname; + if (lua_gettop(L) < 1) { +usage: + luaL_error(L, "Usage: fio.stat(pathname)"); + } + pathname = lua_tostring(L, 1); + if (pathname == NULL) + goto usage; struct stat stat; int res = coeio_stat(pathname, &stat); @@ -424,10 +472,13 @@ lbox_fio_mkdir(struct lua_State *L) const char *pathname; int top = lua_gettop(L); - if (top < 1 || !(pathname = lua_tostring(L, 1))) { + if (top < 1) { +usage: luaL_error(L, "Usage fio.mkdir(pathname[, mode])"); - return 0; } + pathname = lua_tostring(L, 1); + if (pathname == NULL) + goto usage; mode_t mode; @@ -443,10 +494,13 @@ static int lbox_fio_rmdir(struct lua_State *L) { const char *pathname; - if (lua_gettop(L) < 1 || !(pathname = lua_tostring(L, 1))) { + if (lua_gettop(L) < 1) { +usage: luaL_error(L, "Usage: fio.rmdir(pathname)"); - return 0; } + pathname = lua_tostring(L, 1); + if (pathname == NULL) + goto usage; lua_pushboolean(L, coeio_rmdir(pathname) == 0); return 1; @@ -455,10 +509,15 @@ lbox_fio_rmdir(struct lua_State *L) static int lbox_fio_glob(struct lua_State *L) { - if (lua_gettop(L) < 1) + const char *pattern; + if (lua_gettop(L) < 1) { +usage: luaL_error(L, "Usage: fio.glob(pattern)"); + } - const char *pattern = lua_tostring(L, 1); + pattern = lua_tostring(L, 1); + if (pattern == NULL) + goto usage; glob_t globbuf; switch (glob(pattern, GLOB_NOESCAPE, NULL, &globbuf)) { @@ -490,10 +549,16 @@ lbox_fio_glob(struct lua_State *L) static int lbox_fio_link(struct lua_State *L) { - if (lua_gettop(L) < 2) + const char *target; + const char *linkpath; + if (lua_gettop(L) < 2) { +usage: luaL_error(L, "Usage: fio.link(target, linkpath)"); - const char *target = lua_tostring(L, 1); - const char *linkpath = lua_tostring(L, 2); + } + target = lua_tostring(L, 1); + linkpath = lua_tostring(L, 2); + if (target == NULL || linkpath == NULL) + goto usage; lua_pushboolean(L, coeio_link(target, linkpath) == 0); return 1; } @@ -501,10 +566,16 @@ lbox_fio_link(struct lua_State *L) static int lbox_fio_symlink(struct lua_State *L) { - if (lua_gettop(L) < 2) + const char *target; + const char *linkpath; + if (lua_gettop(L) < 2) { +usage: luaL_error(L, "Usage: fio.symlink(target, linkpath)"); - const char *target = lua_tostring(L, 1); - const char *linkpath = lua_tostring(L, 2); + } + target = lua_tostring(L, 1); + linkpath = lua_tostring(L, 2); + if (target == NULL || linkpath == NULL) + goto usage; lua_pushboolean(L, coeio_symlink(target, linkpath) == 0); return 1; } @@ -512,11 +583,15 @@ lbox_fio_symlink(struct lua_State *L) static int lbox_fio_readlink(struct lua_State *L) { - if (lua_gettop(L) < 1) + const char *pathname; + if (lua_gettop(L) < 1) { +usage: luaL_error(L, "Usage: fio.readlink(pathname)"); - + } + pathname = lua_tostring(L, 1); + if (pathname == NULL) + goto usage; char *path = (char *)lua_newuserdata(L, PATH_MAX); - const char *pathname = lua_tostring(L, 1); int res = coeio_readlink(pathname, path, PATH_MAX); if (res < 0) { lua_pushnil(L); diff --git a/test/box/fio.result b/test/box/fio.result index bd6d8634676e95a38c095640dae3c1ff6bd6119a..afe3e6f67cad2e45b0609a5a7edec5c7f72abb95 100644 --- a/test/box/fio.result +++ b/test/box/fio.result @@ -14,6 +14,10 @@ fio.umask() - 0 ... -- pathjoin +fio.basename(nil, nil) +--- +- null +... fio.pathjoin('abc', 'cde') --- - abc/cde @@ -31,6 +35,10 @@ fio.pathjoin('/', '/cde') - /cde ... -- basename +fio.basename(nil) +--- +- null +... fio.basename('/') --- - @@ -67,6 +75,10 @@ file3 = fio.pathjoin(tmpdir, 'file.3') file4 = fio.pathjoin(tmpdir, 'file.4') --- ... +fio.open(nil) +--- +- null +... fh1 = fio.open(file1, { 'O_RDWR', 'O_TRUNC', 'O_CREAT' }, 0777) --- ... @@ -121,13 +133,17 @@ fh1:stat().size --- - 0 ... +fh1:write(nil) +--- +- true +... fh1:write("Hello, world") --- - true ... fh1:stat().size --- -- 133 +- 136 ... fh1:fsync() --- @@ -143,11 +159,11 @@ fio.sync() ... fh1:pread(512, 121) --- -- Hello, world +- nilHello, world ... fh1:pread(5, 121) --- -- Hello +- nilHe ... fh1:write("; Ehllo, again") --- @@ -159,15 +175,15 @@ fh1:seek(121) ... fh1:read(13) --- -- Hello, world; +- nilHello, wor ... fh1:read(512) --- -- ' Ehllo, again' +- ld; Ehllo, again ... fh1:pread(512, 14 + 121) --- -- Ehllo, again +- d; Ehllo, again ... fh1:pwrite("He", 14 + 121) --- @@ -175,12 +191,12 @@ fh1:pwrite("He", 14 + 121) ... fh1:pread(512, 14 + 121) --- -- Hello, again +- He Ehllo, again ... { fh1:stat().size, fio.stat(file1).size } --- -- - 147 - - 147 +- - 150 + - 150 ... fh1:seek(121) --- @@ -188,12 +204,20 @@ fh1:seek(121) ... fh1:read(512) --- -- Hello, world; Hello, again +- nilHello, worlHe Ehllo, again +... +fio.link(nil, nil) +--- +- error: 'Usage: fio.link(target, linkpath)' ... fio.link(file1, file2) --- - true ... +fio.glob(nil) +--- +- error: 'Usage: fio.glob(pattern)' +... glob = fio.glob(fio.pathjoin(tmpdir, '*')) --- ... @@ -229,14 +253,26 @@ fh3:write("abc") --- - true ... +fio.rename(nil, nil) +--- +- error: 'Usage: fio.rename(oldpath, newpath)' +... fio.rename(file3, file4) --- - true ... +fio.symlink(nil, nil) +--- +- error: 'Usage: fio.symlink(target, linkpath)' +... fio.symlink(file4, file3) --- - true ... +fio.stat(nil) +--- +- error: 'Usage: fio.stat(pathname)' +... fio.stat(file3).size --- - 3 @@ -257,6 +293,10 @@ bit.band(fio.stat(file4).mode, 0x1FF) == 0x1FD --- - true ... +fio.chmod(nil, 0x1F8) +--- +- error: 'Usage: fio.chmod(pathname, mode)' +... fio.chmod(file4, 0x1F8) -- 0x770 --- - true @@ -269,6 +309,10 @@ bit.band(fio.stat(file4).mode, 0x1FF) == 0x1F8 --- - true ... +fio.mkdir(nil) +--- +- error: Usage fio.mkdir(pathname[, mode]) +... fio.mkdir(fio.pathjoin(tmpdir, "dir")) --- - true @@ -286,6 +330,10 @@ fio.mkdir(fio.pathjoin(tmpdir, "dir")) - false - Bad file descriptor ... +fio.rmdir(nil) +--- +- error: 'Usage: fio.rmdir(pathname)' +... fio.rmdir(fio.pathjoin(tmpdir, "dir")) --- - true @@ -319,9 +367,13 @@ fio.unlink() ... fio.unlink(nil) --- -- false +- error: 'Usage: fio.unlink(pathname)' ... -- dirname +fio.dirname(nil) +--- +- null +... fio.dirname('abc') --- - . diff --git a/test/box/fio.test.lua b/test/box/fio.test.lua index 8d5b7b5c4e39828c3d2af3aa4a0b775d59086f47..9e72f55ee1d5233938b1fa4f72b35681fbea6de4 100644 --- a/test/box/fio.test.lua +++ b/test/box/fio.test.lua @@ -7,12 +7,14 @@ type(fio.umask(0)) fio.umask() -- pathjoin +fio.basename(nil, nil) fio.pathjoin('abc', 'cde') fio.pathjoin('/', 'abc') fio.pathjoin('abc/', '/cde') fio.pathjoin('/', '/cde') -- basename +fio.basename(nil) fio.basename('/') fio.basename('abc') fio.basename('abc.cde', '.cde') @@ -30,6 +32,7 @@ file3 = fio.pathjoin(tmpdir, 'file.3') file4 = fio.pathjoin(tmpdir, 'file.4') +fio.open(nil) fh1 = fio.open(file1, { 'O_RDWR', 'O_TRUNC', 'O_CREAT' }, 0777) fh1 ~= nil f1s = fh1:stat() @@ -46,6 +49,7 @@ f1s:is_blk() fh1:seek(121) fh1:stat().size +fh1:write(nil) fh1:write("Hello, world") fh1:stat().size fh1:fsync() @@ -66,8 +70,10 @@ fh1:pread(512, 14 + 121) fh1:seek(121) fh1:read(512) +fio.link(nil, nil) fio.link(file1, file2) +fio.glob(nil) glob = fio.glob(fio.pathjoin(tmpdir, '*')) #glob { string.match(glob[1], '^.*/(.*)'), string.match(glob[2], '^.*/(.*)') } @@ -80,25 +86,31 @@ bit.band(fh3:stat().mode, 0x1FF) == 0x1FD fh3:write("abc") +fio.rename(nil, nil) fio.rename(file3, file4) +fio.symlink(nil, nil) fio.symlink(file4, file3) +fio.stat(nil) fio.stat(file3).size fio.lstat(file3).size ~= fio.stat(file3).size fio.lstat(file3).mode ~= fio.stat(file3).mode fio.basename(fio.readlink(file3)) bit.band(fio.stat(file4).mode, 0x1FF) == 0x1FD +fio.chmod(nil, 0x1F8) fio.chmod(file4, 0x1F8) -- 0x770 bit.band(fh3:stat().mode, 0x1FF) == 0x1F8 bit.band(fio.stat(file4).mode, 0x1FF) == 0x1F8 +fio.mkdir(nil) fio.mkdir(fio.pathjoin(tmpdir, "dir")) -- cleanup directories { fh1:close(), fh3:close() } { fh1:close(), errno.strerror(), fh3:close(), errno.strerror() } +fio.rmdir(nil) fio.rmdir(fio.pathjoin(tmpdir, "dir")) { fio.unlink(file1), fio.unlink(file2), fio.unlink(file3), fio.unlink(file4) } @@ -111,6 +123,7 @@ fio.unlink(nil) -- dirname +fio.dirname(nil) fio.dirname('abc') fio.dirname('/abc') fio.dirname('/abc/cde')