]> git.e2factory.org Git - e2factory.git/commitdiff
Consolidate e2util into e2lib, add error reporting and new functions
authorTobias Ulmer <tu@emlix.com>
Thu, 29 Aug 2013 15:33:17 +0000 (17:33 +0200)
committerTobias Ulmer <tu@emlix.com>
Wed, 16 Nov 2016 14:01:23 +0000 (15:01 +0100)
Remove duplicate and unused functions. Add and verify error handling
on all call-sites of the new or renamed functions.

Signed-off-by: Tobias Ulmer <tu@emlix.com>
17 files changed:
doc/developer/config.ld
generic/Makefile
generic/e2lib.lua
generic/e2option.lua
generic/generic_git.lua
generic/le2lib.c [moved from generic/e2util.c with 55% similarity]
generic/plugin.lua
generic/transport.lua
global/e2-fetch-project.lua
global/e2-install-e2.lua
global/e2.lua
local/e2-new-source.lua
local/e2build.lua
local/e2tool.lua
plugins/cvs.lua
plugins/files.lua
plugins/git.lua

index 647ac1f2303933f368ad23002c1ac8d050b1c589..3b2fd439db5698a2f3e1c8875de59b802f498187 100644 (file)
@@ -9,7 +9,7 @@ file = { "../../generic",
                "../../generic/test_sha1.lua",
                "../../generic/luafile_ll.c",
                "../../generic/sha1.c",
-               "../../generic/e2util.c",
+               "../../generic/le2lib.c",
                "../../generic/lsha1.c",
                "../../global/e2-su-2.2.c",
                "../../local/linux32.c",
index d2ba8a8e4f2ce7323b703ea65a676f06964d89f3..ac4b2155266bb38cece575882ac7fb45f99e3d76 100644 (file)
@@ -32,48 +32,43 @@ include $(TOPLEVEL)/make.vars
 LUA_LIBS = strict.lua plugin.lua e2lib.lua
 LUA_LIBS += e2option.lua hash.lua tools.lua transport.lua cache.lua url.lua
 LUA_LIBS += generic_git.lua luafile.lua err.lua lock.lua
+SO_LIBS = sha1.so luafile_ll.so le2lib.so
 
 CLEAN_FILES = *~ *.o *.so
 
 
 .PHONY: all install uninstall local install-local clean
 
-all: sha1.so luafile_ll.so e2util.so
+all: $(SO_LIBS)
 
 sha1.so: sha1.o lsha1.o
 
 luafile_ll.so: luafile_ll.o
 
-e2util.so: e2util.o
+le2lib.so: le2lib.o
 
 install: all
        install -d $(DESTDIR)$(LIBDIR)
        install -m 644 $(LUA_LIBS) $(DESTDIR)$(LIBDIR)
-       install -m 644 sha1.so $(DESTDIR)$(LIBDIR)
-       install -m 644 luafile_ll.so $(DESTDIR)$(LIBDIR)
-       install -m 644 e2util.so $(DESTDIR)$(LIBDIR)
+       install -m 644 $(SO_LIBS) $(DESTDIR)$(LIBDIR)
 
 uninstall:
-       rm -f  $(DESTDIR)$(LIBDIR)/sha1.so
-       rm -f  $(DESTDIR)$(LIBDIR)/luafile_ll.so
-       rm -f  $(DESTDIR)$(LIBDIR)/e2util.so
-       set -e; for f in $(LUA_LIBS); do \
+       set -e; for f in $(LUA_LIBS) $(SO_LIBS); do \
                rm -f "$(DESTDIR)$(LIBDIR)/$$f"; \
        done
        rmdir -p $(DESTDIR)$(LIBDIR) || true
 
-local: sha1.so luafile_ll.so e2util.so
+local: $(SO_LIBS)
 
 install-local: local
        install -d $(LOCALLIBDIR)
-       install -m 644 sha1.so $(LOCALLIBDIR)
-       install -m 644 luafile_ll.so $(LOCALLIBDIR)
-       install -m 644 e2util.so $(LOCALLIBDIR)
+       install -m 644 $(LUA_LIBS) $(LOCALLIBDIR)
+       install -m 644 $(SO_LIBS) $(LOCALLIBDIR)
 
 uninstall-local:
-       rm -f  $(LOCALLIBDIR)/sha1.so
-       rm -f  $(LOCALLIBDIR)/luafile_ll.so
-       rm -f $(LOCALLIBDIR)/e2util.so
+       set -e; for f in $(LUA_LIBS) $(SO_LIBS); do \
+               rm -f "$(LOCALLIBDIR)/$$f"; \
+       done
        rmdir -p $(LOCALLIBDIR) || true
 
 doc:
index 20cb70677a0ea45a42db83e5f41c6bccc5daace1..66280e90dcb4d51e91bb3dd8a37184efd7490fc0 100644 (file)
@@ -48,13 +48,13 @@ local e2lib = {}
 package.loaded["e2lib"] = e2lib
 
 local buildconfig = require("buildconfig")
-require("e2util")
 local lock = require("lock")
 local err = require("err")
 local plugin = require("plugin")
 local tools = require("tools")
 local cache = require("cache")
 local luafile = require("luafile")
+local le2lib = require("le2lib")
 
 -- Module-level global variables
 --
@@ -116,9 +116,199 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.]],
     debuglogfilebuffer = {},
 }
 
+--- Get current working directory.
+-- @return Current working directory (string) or false on error.
+-- @return Error object on failure.
+function e2lib.cwd()
+    local path, errstring = le2lib.cwd()
+
+    if not path then
+        return false,
+            err.new("cannot get current working directory: %s", errstring)
+    end
+
+    return path
+end
+
+--- Dirent table, returned by @{stat}.
+-- @table dirent
+-- @field dev Device-id (number).
+-- @field ino Inode-number (number).
+-- @field mode Permissions and access mode (number).
+-- @field nlink Number of hard links (number).
+-- @field uid User ID (number).
+-- @field gid Group ID (number).
+-- @field rdev Device id for char of block special files (number).
+-- @field size File size (number).
+-- @field atime access time (number).
+-- @field mtime modification time (number).
+-- @field ctime change time (number).
+-- @field blksize block size (number).
+-- @field type One of the following strings: block-special, character-special,
+--             fifo-special, regular, directory, symbolic-link, socket, unknown.
+
+
+--- Get file status information.
+-- @param path Path to the file, including special files.
+-- @param followlinks Whether symlinks should be followed, or information
+--        about the link should be returned (boolean).
+-- @return Dirent table containing attributes (see @{dirent}), or false on error
+-- @return Error object on failure.
+function e2lib.stat(path, followlinks)
+    local dirent, errstring = le2lib.stat(path, followlinks)
+
+    if not dirent then
+        return false, err.new("stat failed: %s: %s", path, errstring)
+    end
+
+    return dirent
+end
+
+--- Checks if file exists.
+-- If executable is true, it also checks whether the file is executable.
+-- @param path Path to check.
+-- @param executable Check if executable (true) or not (false).
+-- @return True if file exists, false otherwise.
+function e2lib.exists(path, executable)
+    return le2lib.exists(path, executable)
+end
+
+--- Create a symlink.
+-- @param oldpath Path to point to (string).
+-- @param newpath New symlink path (string).
+-- @return True on success, false on error.
+-- @return Error object on failure.
+function e2lib.symlink(oldpath, newpath)
+    local rc, errstring = le2lib.symlink(oldpath, newpath)
+
+    if not rc then
+        return false, err.new("creating symlink failed: %s -> %s: %s",
+            newpath, oldpath, errstring)
+    end
+
+    return true
+end
+
+--- Create a hardlink.
+-- @param oldpath Path to existing file (string).
+-- @param newpath Path to new file (string).
+-- @return True on success, false on error.
+-- @return Error object on failure.
+function e2lib.hardlink(oldpath, newpath)
+    local rc, errstring = le2lib.hardlink(oldpath, newpath)
+
+    if not rc then
+        return false, err.new("creating hard link failed: %s -> %s: %s",
+            newpath, oldpath, errstring)
+    end
+
+    return true
+end
+
+--- Wait for process to terminate.
+-- @param pid Process ID, -1 to wait for any child.
+-- @return Exit status of process (WEXITSTATUS), or false on error.
+-- @return Process ID of the terminated child or error object on failure.
+function e2lib.wait(pid)
+    local rc, pid = le2lib.wait(pid)
+
+    if not rc then
+        local errstring = pid
+        return false, err.new("waiting for child %d failed: %s", pid, errstring)
+    end
+
+    return rc, pid
+end
+
+--- Poll input output multiplexing.
+-- Only indicates first selected file descriptor.
+-- @param timeout Timeout in milliseconds (number).
+-- @param fdvec Vector of file descriptors (table of numbers).
+-- @return Returns 0 on timeout, < 0 on error and > 0 to indicate which file
+--         descriptor triggered.
+-- @return True if it's a POLLIN event.
+-- @return True if it's a POLLOUT event.
+function e2lib.poll(timeout, fdvec)
+    return le2lib.poll(timeout, fdvec)
+end
+
+--- Set file descriptor in non-blocking mode.
+-- @param fd Open file descriptor.
+function e2lib.unblock(fd)
+    return le2lib.unblock(fd)
+end
+
+--- Creates a new process. Returns both in the parent and in the child.
+-- @return Process ID of the child or false on error in the parent process.
+--         Returns zero in the child process.
+-- @return Error object on failure.
+function e2lib.fork()
+    local pid, errstring = le2lib.fork()
+
+    if pid == false then
+        return false, err.new("failed to fork a new child: %s", errstring)
+    end
+
+    return pid
+end
+
+--- Set umask value.
+-- @param mask New umask value.
+-- @return Previous umask value.
+function e2lib.umask(mask)
+    return le2lib.umask(mask)
+end
+
+--- Set environment variable.
+-- @param var Variable name (string).
+-- @param val Variable content (string).
+-- @param overwrite True to overwrite existing variable of same name.
+-- @return True on success, false on error.
+function e2lib.setenv(var, val, overwrite)
+    -- used in only once, questionable
+    return le2lib.setenv(var, val, overwrite)
+end
+
+--- Reset signal handlers back to their default.
+-- @return True on success, false on error.
+-- @return Error object on failure.
+function e2lib.signal_reset()
+    local rc, errstring
+
+    rc, errstring = le2lib.signal_reset()
+    if not rc then
+        return false, err.new("resetting signal handlers: %s", errstring)
+    end
+
+    return true
+end
+
+--- Get current process id.
+-- @return Process ID (number)
+function e2lib.getpid()
+    -- used only for tempfile generation
+    return le2lib.getpid()
+end
+
+--- Send signal to process.
+-- @param pid Process ID to signal (number).
+-- @param sig Signal number.
+-- @return True on success, false on error.
+-- @return Error object on failure.
+function e2lib.kill(pid, sig)
+    local rc, errstring = le2lib.kill(pid, sig)
+
+    if not rc then
+        return false, err.new("sending signal %d to process %d failed: %s",
+            sig, pid, errstring)
+    end
+
+    return true
+end
+
 --- Interrupt handling.
 --
--- e2util sets up a SIGINT handler that calls back into this function.
+-- le2lib sets up a SIGINT handler that calls back into this function.
 function e2lib.interrupt_hook()
     e2lib.abort("*interrupted by user*")
 end
@@ -133,12 +323,12 @@ function e2lib.init()
     local traceflags = os.getenv("E2_TRACE") or "c"
     debug.sethook(e2lib.tracer, traceflags)
 
-    local rc, re = e2util.signal_reset()
+    local rc, re = e2lib.signal_reset()
     if not rc then
         e2lib.abort(re)
     end
 
-    e2util.closefrom(3)
+    e2lib.closefrom(3)
     -- ignore errors, no /proc should not prevent factory from working
 
     -- Overwrite io functions that create a file descriptor to set the
@@ -399,7 +589,7 @@ end
 --- Set E2_CONFIG in the environment to file. Also sets commandline option.
 -- @param file Config file name (string).
 function e2lib.sete2config(file)
-    e2util.setenv("E2_CONFIG", file, 1)
+    e2lib.setenv("E2_CONFIG", file, 1)
     e2lib.globals.osenv["E2_CONFIG"] = file
     e2lib.globals.cmdline["e2-config"] = file
 end
@@ -511,30 +701,16 @@ function e2lib.rotate_log(file)
     local rc, re
     local logdir = e2lib.dirname(file)
     local logfile = e2lib.basename(file)
-    local dir = e2util.directory(logdir, false)
-    if not dir then
-        return false, e:cat(string.format("%s: can't read directory", dir))
-    end
     local files = {}
-    local dst
-
-    if not e2util.stat(file) then
-        return true
-    end
 
     for f, re in e2lib.directory(logdir, false) do
-        local start, stop, extension
-
         if not f then
             return false, e:cat(re)
         end
 
-        start, stop = string.find(f, logfile, 1, true)
-        if start and start == 1 then
-            extension = string.sub(f, stop+1)
-            if string.find(extension, "^%.[0-9]+$") then
-                table.insert(files, f)
-            end
+        local match = f:match(string.format("%s.[0-9]+", logfile))
+        if match then
+            table.insert(files, 1, match)
         end
     end
 
@@ -548,22 +724,22 @@ function e2lib.rotate_log(file)
     table.sort(files, comp)
 
     for _,f in ipairs(files) do
-        local n, src, dst
-
-        src = e2lib.join(logdir, f)
-        n = f:match("%.([0-9]+)$")
-        assert(n, "could not match logfile number")
-        n = tonumber(n)
-        if n >= e2lib.globals.logrotate - 1 then
-            rc, re = e2lib.rm(src)
-            if not rc then
-                return false, e:cat(re)
-            end
-        else
-            dst = string.format("%s/%s.%d", logdir, logfile, n + 1)
-            rc, re = e2lib.mv(src, dst)
-            if not rc then
-                return false, e:cat(re)
+        local n = f:match(string.format("%s.([0-9]+)", logfile))
+        if n then
+            n = tonumber(n)
+            if n >= e2lib.globals.logrotate - 1 then
+                local del = string.format("%s/%s.%d", logdir, logfile, n)
+                rc, re = e2lib.unlink(del)
+                if not rc then
+                    return false, e:cat(re)
+                end
+            else
+                local src = string.format("%s/%s.%d", logdir, logfile, n)
+                local dst = string.format("%s/%s.%d", logdir, logfile, n + 1)
+                rc, re = e2lib.mv(src, dst)
+                if not rc then
+                    return false, e:cat(re)
+                end
             end
         end
     end
@@ -848,7 +1024,7 @@ function e2lib.read_global_config(e2_config_file)
             c.data = x
         end
         e2lib.logf(4, "reading global config file: %s", path)
-        local rc = e2util.exists(path)
+        local rc = e2lib.exists(path)
         if rc then
             e2lib.logf(3, "using global config file: %s", path)
             rc, re = e2lib.dofile2(path, c, true)
@@ -899,7 +1075,7 @@ end
 function e2lib.read_extension_config()
     local e = err.new("reading extension config file: %s",
     e2lib.globals.extension_config)
-    local rc = e2util.exists(e2lib.globals.extension_config)
+    local rc = e2lib.exists(e2lib.globals.extension_config)
     if not rc then
         return false, e:append("config file does not exist")
     end
@@ -939,7 +1115,7 @@ end
 --         or false and an err object on error. The iterator signals the
 --         end of the list by returning nil.
 function e2lib.directory(path, dotfiles, noerror)
-    local dir = e2util.directory(path, dotfiles)
+    local dir, errstring = le2lib.directory(path, dotfiles)
     if not dir then
         if noerror then
             dir = {}
@@ -950,7 +1126,8 @@ function e2lib.directory(path, dotfiles, noerror)
             return function ()
                 if not error_signaled then
                     error_signaled = true
-                    return false, err.new("directory `%s' does not exist", p)
+                    return false, err.new("reading directory `%s' failed: %s",
+                        path, errstring)
                 else
                     return nil
                 end
@@ -1024,6 +1201,7 @@ function e2lib.callcmd_pipe(cmds, infile, outfile)
     for cmdidx = 1, c do
         local pipein, output
         local errin, errout
+        local pid
 
         rc, errin, errout = luafile.pipe()
         if not rc then
@@ -1041,8 +1219,10 @@ function e2lib.callcmd_pipe(cmds, infile, outfile)
         end
 
         e2lib.logf(3, "+ %s", cmds[cmdidx])
-        local pid = e2util.fork()
-        if pid == 0 then
+        pid, re = e2lib.fork()
+        if not pid then
+            return false, e:cat(re)
+        elseif pid == 0 then
             if cmdidx < c then
                 -- everyone but the last
                 pipein:close()
@@ -1054,7 +1234,7 @@ function e2lib.callcmd_pipe(cmds, infile, outfile)
         end
 
         pids[pid] = cmdidx
-        e2util.unblock(errin:fileno())
+        e2lib.unblock(errin:fileno())
         ers[cmdidx] = errin
         errout:close()
 
@@ -1078,7 +1258,7 @@ function e2lib.callcmd_pipe(cmds, infile, outfile)
             table.insert(fds, n)
             ifd[n] = i
         end
-        local i, r = e2util.poll(-1, fds)
+        local i, r = e2lib.poll(-1, fds)
 
         if i <= 0 then
             return false, err.new("poll error: %s", tostring(i))
@@ -1106,9 +1286,10 @@ function e2lib.callcmd_pipe(cmds, infile, outfile)
     c = #cmds
     rc = true
     while c > 0 do
-        local status, pid = e2util.wait(-1)
+        local status, pid = e2lib.wait(-1)
         if not status then
-            return false, err.new("waiting for child to exit failed: %s", pid)
+            re = pid
+            return false, e:cat(re)
         end
 
         local cmdidx = pids[pid]
@@ -1136,9 +1317,10 @@ end
 -- captured via a pipe
 -- the capture function is called for every chunk of output that
 -- is captured from the pipe.
--- @return unknown
+-- @return Return status code of the command (number) or false on error.
+-- @return Error object on failure.
 function e2lib.callcmd_capture(cmd, capture)
-    local rc, oread, owrite, devnull, pid
+    local rc, re, oread, owrite, devnull, pid
 
     local function autocapture(msg)
         e2lib.log(3, msg)
@@ -1153,34 +1335,41 @@ function e2lib.callcmd_capture(cmd, capture)
         e2lib.abort("could not open /dev/null")
     end
     e2lib.logf(4, "+ %s", cmd)
-    pid = e2util.fork()
-    if pid == 0 then
+    pid, re = e2lib.fork()
+    if not pid then
+        return false, re
+    elseif pid == 0 then
         oread:close()
         rc = callcmd(devnull, owrite, owrite, cmd)
         os.exit(rc)
     else
         owrite:close()
-        --log("capturing...")
         while not oread:eof() do
             local x = oread:readline()
             if x then
-                --print("read: '" .. x .. "'")
                 capture(x)
             end
         end
         oread:close()
-        rc = e2util.wait(pid)
+        rc, re = e2lib.wait(pid)
+        if not rc then
+            luafile.close(devnull)
+            return false, re
+        end
+
         luafile.close(devnull)
-        --log("capturing done...")
-        --log("exit status was " .. rc)
     end
+
     return rc
 end
 
 --- Call a command, log its output and catch the last lines for error reporting.
 -- @param cmd string: the command
--- @return Return code of the command (number).
--- @return Error object containing command line and last lines of output.
+-- @return Return code of the command (number), or false on error.
+-- @return Error object containing command line and last lines of output. It's
+--         the callers responsibility to determine whether an error occured
+--         based on the return code. If the return code is false, an error
+--         within the function occured and a normal error object is returned.
 function e2lib.callcmd_log(cmd)
     local e = err.new("command %s failed:", cmd)
     local fifo = {}
@@ -1196,7 +1385,10 @@ function e2lib.callcmd_log(cmd)
         end
     end
 
-    local rc = e2lib.callcmd_capture(cmd, logto)
+    local rc, re = e2lib.callcmd_capture(cmd, logto)
+    if not rc then
+        return false, e:cat(e)
+    end
 
     if #fifo == 0 then
         table.insert(fifo, "command failed silently, no output captured")
@@ -1260,9 +1452,9 @@ end
 function e2lib.locate_project_root(path)
     local rc, re
     local e = err.new("checking for project directory failed")
-    local save_path = e2util.cwd()
+    local save_path, re = e2lib.cwd()
     if not save_path then
-        return false, e:append("cannot get current working directory")
+        return false, e:cat(re)
     end
     if path then
         rc = e2lib.chdir(path)
@@ -1271,14 +1463,14 @@ function e2lib.locate_project_root(path)
             return false, e:cat(re)
         end
     else
-        path = e2util.cwd()
+        path, re = e2lib.cwd()
         if not path then
             e2lib.chdir(save_path)
-            return false, e:append("cannot get current working directory")
+            return false, e:cat(re)
         end
     end
     while true do
-        if e2util.exists(".e2") then
+        if e2lib.exists(".e2") then
             e2lib.logf(3, "project is located in: %s", path)
             e2lib.chdir(save_path)
             return path
@@ -1291,10 +1483,10 @@ function e2lib.locate_project_root(path)
             e2lib.chdir(save_path)
             return false, e:cat(re)
         end
-        path = e2util.cwd()
+        path, re = e2lib.cwd()
         if not path then
             e2lib.chdir(save_path)
-            return false, e:append("cannot get current working directory")
+            return false, e:cat(re)
         end
     end
     e2lib.chdir(save_path)
@@ -1382,7 +1574,7 @@ end
 function e2lib.mktempfile(template)
     if not template then
         template = string.format("%s/e2tmp.%d.XXXXXXXX", e2lib.globals.tmpdir,
-            e2util.getpid())
+            e2lib.getpid())
     end
     local cmd = string.format("mktemp '%s'", template)
     local mktemp = io.popen(cmd, "r")
@@ -1404,11 +1596,18 @@ end
 -- temporary files.
 -- @param tmpfile File name to remove (string).
 function e2lib.rmtempfile(tmpfile)
+    local rc, re
+
     for i,v in ipairs(e2lib.globals.tmpfiles) do
         if v == tmpfile then
             table.remove(e2lib.globals.tmpfiles, i)
             e2lib.logf(4, "removing temporary file: %s", tmpfile)
-            e2lib.rm(tmpfile, "-f")
+            if e2lib.exists(tmpfile) then
+                rc, re = e2lib.unlink(tmpfile)
+                if not rc then
+                    e2lib.warnf(3, "could not remove tmpfile %q", tmpfile)
+                end
+            end
         end
     end
 end
@@ -1422,7 +1621,7 @@ end
 function e2lib.mktempdir(template)
     if not template then
         template = string.format("%s/e2tmp.%d.XXXXXXXX", e2lib.globals.tmpdir,
-        e2util.getpid())
+        e2lib.getpid())
     end
     local cmd = string.format("mktemp -d '%s'", template)
     local mktemp = io.popen(cmd, "r")
@@ -1444,11 +1643,18 @@ end
 -- list of temporary directories.
 -- @param tmpdir Directory name to remove (string).
 function e2lib.rmtempdir(tmpdir)
+    local rc, re
+
     for i,v in ipairs(e2lib.globals.tmpdirs) do
         if v == tmpdir then
             table.remove(e2lib.globals.tmpdirs, i)
             e2lib.logf(4, "removing temporary directory: %s", tmpdir)
-            e2lib.rm(tmpdir, "-fr")
+            if e2lib.exists(tmpdir) then
+                rc, re = e2lib.unlink_recursive(tmpdir)
+                if not rc then
+                    e2lib.warnf(3, "could not remove tmpdir %q", tmpdir)
+                end
+            end
         end
     end
 end
@@ -1472,19 +1678,6 @@ function e2lib.rmtempfiles()
     end
 end
 
---- call the rm tool with flags and filename
--- @param file string: the file parameter
--- @param flags string: flags to pass to rm (optional)
--- @return bool
--- @return an error object on failure
-function e2lib.rm(file, flags)
-    if not flags then
-        flags = ""
-    end
-    local args = string.format("%s %s", flags, file)
-    return e2lib.call_tool("rm", args)
-end
-
 --- call the touch tool with flags and filename
 -- @param file string: the file parameter
 -- @param flags string: flags to pass to touch (optional)
@@ -1497,17 +1690,75 @@ function e2lib.touch(file, flags)
     return e2lib.call_tool("touch", args)
 end
 
---- call the rmdir command
--- @param dir string: the directory name
--- @param flags string: flags to pass to rmdir
--- @return bool
--- @return the last line ouf captured output
-function e2lib.rmdir(dir, flags)
-    if not flags then
-        flags = ""
+--- Remove regular and special files, except dirs.
+-- @param pathname Path to file (string).
+-- @return True on success, false on error.
+-- @return Error object on failure.
+function e2lib.unlink(pathname)
+    local rc, errstring = le2lib.unlink(pathname)
+
+    if not rc then
+        return false, err.new("could not remove file %s: %s",
+            pathname, errstring)
     end
-    local args = string.format("%s %s", flags, dir)
-    return e2lib.call_tool("rmdir", args)
+
+    return true
+end
+
+--- Remove directories and files recursively.
+-- @param pathname Directory to delete.
+-- @return True on success, false on error.
+-- @return Error object on failure.
+function e2lib.unlink_recursive(pathname)
+    local de, rc, re
+    local filepath
+
+    for file, re in e2lib.directory(pathname, true) do
+        if not file then
+            return false, re
+        end
+
+        filepath = e2lib.join(pathname, file)
+
+        de, re = e2lib.stat(filepath)
+        if not de then
+            return false, re
+        end
+
+        if de.type == "directory" then
+            rc, re = e2lib.unlink_recursive(filepath)
+            if not rc then
+                return false, re
+            end
+        else
+            rc, re = e2lib.unlink(filepath)
+            if not rc then
+                return false, re
+            end
+        end
+    end
+
+    rc, re = e2lib.rmdir(pathname)
+    if not rc then
+        return false, re
+    end
+
+    return true
+end
+
+--- Remove single empty directory.
+-- @param dir Directory name (string).
+-- @return True on success, false on error.
+-- @return Error object on failure.
+function e2lib.rmdir(dir)
+    local rc, errstring = le2lib.rmdir(dir)
+
+    if not rc then
+        return false, err.new("could not remove directory %s: %s",
+            dir, errstring)
+    end
+
+    return true
 end
 
 --- call the mkdir command
@@ -1555,7 +1806,7 @@ function e2lib.call_tool(tool, args)
 
     call = string.format("%s %s %s", cmd, flags, args)
     rc, re = e2lib.callcmd_log(call)
-    if rc ~= 0 then
+    if not rc or rc ~= 0 then
         return false, re
     end
 
@@ -1589,7 +1840,7 @@ function e2lib.call_tool_argv(tool, argv)
     end
 
     rc, re = e2lib.callcmd_log(call)
-    if rc ~= 0 then
+    if not rc or rc ~= 0 then
         return false, re
     end
 
@@ -1657,7 +1908,7 @@ function e2lib.git(gitdir, subtool, args)
     call = string.format("GIT_DIR=%s %s %s %s",
         e2lib.shquote(gitdir), e2lib.shquote(git), e2lib.shquote(subtool), args)
     rc, re = e2lib.callcmd_log(call)
-    if rc ~= 0 then
+    if not rc or rc ~= 0 then
         return false, e:cat(re)
     end
 
@@ -1678,16 +1929,6 @@ function e2lib.svn(argv)
     return e2lib.call_tool_argv("svn", argv)
 end
 
---- call the ln command
--- @param dst string: destination name
--- @param link string: link name
--- @return bool
--- @return the last line of captured output
-function e2lib.symlink(dst, link)
-    local args = string.format("-s '%s' '%s'", dst, link)
-    return e2lib.call_tool("ln", args)
-end
-
 --- call the chmod command
 -- @param mode string: the new mode
 -- @param path string: path
@@ -1698,6 +1939,23 @@ function e2lib.chmod(mode, path)
     return e2lib.call_tool("chmod", args)
 end
 
+--- Close all file descriptors equal or larger than "fd".
+-- @param fd file descriptor (number)
+-- @return True on success, false on error
+-- @return Error object on failure.
+-- @raise Error on invalid input.
+function e2lib.closefrom(fd)
+    local rc, errstring
+
+    rc, errstring = le2lib.closefrom(fd)
+    if not rc then
+        return false, err.new("closefrom(%d) failed: %s",
+            tonumber(fd), errstring)
+    end
+
+    return true
+end
+
 --- call the mv command
 -- @param src string: source name
 -- @param dst string: destination name
@@ -1724,20 +1982,6 @@ function e2lib.cp(src, dst, flags)
     return e2lib.call_tool("cp", args)
 end
 
---- call the ln command
--- @param src string: source name
--- @param dst string: destination name
--- @param flags string: additional flags
--- @return bool
--- @return the last line ouf captured output
-function e2lib.ln(src, dst, flags)
-    if not flags then
-        flags = ""
-    end
-    local args = string.format("%s '%s' '%s'", flags, src, dst)
-    return e2lib.call_tool("ln", args)
-end
-
 --- call the curl command
 -- @param argv table: argument vector
 -- @return bool
@@ -1802,7 +2046,7 @@ end
 -- @param dir string: path
 -- @return bool
 function e2lib.isdir(dir)
-    local t = e2util.stat(dir, true)
+    local t = e2lib.stat(dir, true)
     if t and t.type == "directory" then
         return true
     end
@@ -1814,7 +2058,7 @@ end
 -- @param dir string: path
 -- @return bool
 function e2lib.isfile(path)
-    local t = e2util.stat(path, true)
+    local t = e2lib.stat(path, true)
     if t and t.type == "regular" then
         return true
     end
@@ -2076,7 +2320,7 @@ end
 -- @return an error object on failure
 function e2lib.chdir(path)
     local rc, re
-    rc, re = e2util.cd(path)
+    rc, re = le2lib.chdir(path)
     if not rc then
         return false, err.new("chdir %s failed: %s", path, re)
     end
index 93c77e16d63a2f57843fc6680e816972faaf81af..628c080fef801985e451049f6154872e86328c23 100644 (file)
@@ -37,7 +37,6 @@ local err = require("err")
 local strict = require("strict")
 local tools = require("tools")
 local buildconfig = require("buildconfig")
-require("e2util")
 
 local options = {}
 local aliases = {}
@@ -224,7 +223,7 @@ local function userdefaultoptions(opts)
     end
 
     local file = home .. "/.e2/e2rc"
-    if not e2util.exists(file) then
+    if not e2lib.exists(file) then
         return true
     end
 
index 1540b9fe6ee86ea45c391c3fb37d8726cce3f630..e189eed204a7967e7b176618361785dc85cae29d 100644 (file)
@@ -71,8 +71,8 @@ local function git_clone_url(surl, destdir, skip_checkout)
     local cmd = string.format("git clone %s --quiet %s %s", flags,
         e2lib.shquote(src), e2lib.shquote(destdir))
 
-    local rc, re = e2lib.callcmd_log(cmd)
-    if rc ~= 0 then
+    rc, re = e2lib.callcmd_log(cmd)
+    if not rc or rc ~= 0 then
         return false, e:cat(re)
     end
 
@@ -102,7 +102,7 @@ function generic_git.git_branch_new1(gitwc, track, branch, start_point)
         e2lib.shquote(gitwc), f_track, e2lib.shquote(branch),
         e2lib.shquote(start_point))
     rc, re = e2lib.callcmd_log(cmd)
-    if rc ~= 0 then
+    if not rc or rc ~= 0 then
         e = err.new("creating new branch failed")
         return false, e:cat(re)
     end
@@ -123,7 +123,7 @@ function generic_git.git_checkout1(gitwc, branch)
     cmd = string.format("cd %s && git checkout %s", e2lib.shquote(gitwc),
         e2lib.shquote(branch))
     rc, re = e2lib.callcmd_log(cmd)
-    if rc ~= 0 then
+    if not rc or rc ~= 0 then
         e = err.new("git checkout failed")
         return false, e:cat(re)
     end
@@ -209,7 +209,7 @@ function generic_git.git_init_db1(rurl)
     end
 
     rc, re = e2lib.callcmd_log(cmd)
-    if rc ~= 0 then
+    if not rc or rc ~= 0 then
         return false, e:cat(re)
     end
 
@@ -244,7 +244,7 @@ function generic_git.git_push1(gitdir, rurl, refspec)
     cmd = string.format("GIT_DIR=%s git push %s %s", e2lib.shquote(gitdir),
         e2lib.shquote(remote_git_url), e2lib.shquote(refspec))
     rc, re = e2lib.callcmd_log(cmd)
-    if rc ~= 0 then
+    if not rc or rc ~= 0 then
         return false, e:cat(re)
     end
 
@@ -284,7 +284,7 @@ function generic_git.git_remote_add1(lurl, rurl, name)
         e2lib.shquote("/"..lrepo.path), e2lib.shquote(name),
         e2lib.shquote(giturl))
     rc, re = e2lib.callcmd_log(cmd)
-    if rc ~= 0 then
+    if not rc or rc ~= 0 then
         return false, e:cat(re)
     end
 
@@ -411,9 +411,9 @@ function generic_git.git_config(gitdir, query)
     end
 
     local cmd = string.format("GIT_DIR=%s git config %s > %s",
-    e2lib.shquote(gitdir), e2lib.shquote(query), e2lib.shquote(tmpfile))
-    local rc, re = e2lib.callcmd_log(cmd)
-    if rc ~= 0 then
+        e2lib.shquote(gitdir), e2lib.shquote(query), e2lib.shquote(tmpfile))
+    rc, re = e2lib.callcmd_log(cmd)
+    if not rc or rc ~= 0 then
         e:append("git config failed")
         return nil, e
     end
@@ -438,8 +438,8 @@ function generic_git.git_add(gitdir, args)
     end
     local cmd = string.format("GIT_DIR=%s git add %s",
     e2lib.shquote(gitdir), e2lib.shquote(args))
-    local rc, re = e2lib.callcmd_log(cmd)
-    if rc ~= 0 then
+    rc, re = e2lib.callcmd_log(cmd)
+    if not rc or rc ~= 0 then
         return nil, e:cat(re)
     end
     return true, nil
similarity index 55%
rename from generic/e2util.c
rename to generic/le2lib.c
index 651cd8a69b1623a49c3a621071320f2afa24d326..c6f2242af8859f2b66d615b8409755b5fbd92323 100644 (file)
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
    */
 
-/*
-   Low-level file-system and process operations.
-   */
-
-
 #include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
 #include <lualib.h>
 #include <lauxlib.h>
 
-
 static char buffer[PATH_MAX + 1];
 
-
-/* e2util.fork() -> pid
-   | nil, ERRORMESSAGE
-
-   Forks a subprocess.
-   */
-
 static int
 lua_fork(lua_State *lua)
 {
@@ -65,7 +52,7 @@ lua_fork(lua_State *lua)
        rc = fork();
 
        if(rc < 0) {
-               lua_pushnil(lua);
+               lua_pushboolean(lua, 0);
                lua_pushstring(lua, strerror(errno));
                return 2;
        }
@@ -74,81 +61,23 @@ lua_fork(lua_State *lua)
        return 1;
 }
 
-
-/* e2util.cwd() -> STRING
-
-   Returns the current working directory.
-   */
-
 static int
 get_working_directory(lua_State *lua)
 {
        char *cwd = getcwd(buffer, sizeof(buffer));
 
-       if (cwd == NULL)
-               lua_pushnil(lua);
-       else
-               lua_pushstring(lua, buffer);
-
-       return 1;
-}
-
-
-/* e2util.realpath(PATH) -> PATH' | nil
-
-   If PATH names an existing object in the file-system, then this
-   function will return the absolute, canonical representation of PATH,
-   otherwise nil is returned.
-   */
+       if (cwd == NULL) {
+               lua_pushboolean(lua, 0);
+               lua_pushstring(lua, strerror(errno));
 
-static int
-get_realpath(lua_State *lua)
-{
-       const char *p = luaL_checkstring(lua, 1);
+               return 2;
+       }
 
-       if (realpath(p, buffer) == NULL)
-               lua_pushnil(lua);
-       else
-               lua_pushstring(lua, buffer);
+       lua_pushstring(lua, buffer);
 
        return 1;
 }
 
-
-/* e2util.stat(PATH, [FOLLOWLINKS?]) -> TABLE | nil
-
-   Returns stat(3) information for the file system object designated by PATH.
-   If FOLLOWLINKS? is not given or false, then the returned information will
-   apply to the actual symbolic link, if PATH designates one. Otherwise
-   the file pointed to by the link is taken. Returns a table with the
-   following entries:
-
-   dev           device-id (number)
-   ino           inode-number (number)
-   mode          permissions and access mode (number)
-   nlink         number of hard links (number)
-   uid           user id (number)
-   gid           group id (number)
-   rdev          device id for char of block special files (number)
-   size          file size (number)
-   atime         access time (number)
-   mtime         modification time (number)
-   ctime         change time (number)
-   blksize       block size (number)
-   blocks        number of blocks (number)
-
-   type          one of the following strings:
-
-   block-special
-   character-special
-   fifo-special
-   regular
-   directory
-   symbolic-link
-   socket
-   unknown
-   */
-
 static int
 get_file_statistics(lua_State *lua)
 {
@@ -164,7 +93,7 @@ get_file_statistics(lua_State *lua)
        }
 
        if (s < 0) {
-               lua_pushnil(lua);
+               lua_pushboolean(lua, 0);
                lua_pushstring(lua, strerror(errno));
                return 2;
        }
@@ -236,90 +165,58 @@ get_file_statistics(lua_State *lua)
        return 1;
 }
 
-
-/* e2util.readlink(PATH) -> PATH' | nil
-
-   Returns the path pointed to by the symbolic link PATH or nil, if the
-   link does not exist.
-   */
-
 static int
-read_symbolic_link(lua_State *lua)
+get_directory(lua_State *lua)
 {
        const char *p = luaL_checkstring(lua, 1);
-       int len;
-
-       len = readlink(p, buffer, sizeof(buffer));
+       int df = lua_gettop(lua) > 1 && lua_toboolean(lua, 2);
+       DIR *dir = opendir(p);
+       struct dirent *de;
+       int i = 1;
 
-       if (len > -1)
-               lua_pushlstring(lua, buffer, len);
-       else
-               lua_pushnil(lua);
+       if (dir == NULL) {
+               lua_pushboolean(lua, 0);
+               lua_pushstring(lua, strerror(errno));
 
-       return 1;
-}
+               return 2;
+       }
 
+       lua_newtable(lua);
 
-/* e2util.directory(PATH, [DOTFILES?]) -> TABLE | nil
+       for (;;) {
+               errno = 0;
+               de = readdir(dir);
 
-   Returns an array with the contents of the directory designated by PATH.
-   If DOTFILES? is given and true then files beginning with "." are also
-   included in the directory listing.
-   */
+               if (de == NULL) {
+                       if (errno) {
+                               lua_pop(lua, 1); /* remove table */
 
-static int
-get_directory(lua_State *lua)
-{
-       const char *p = luaL_checkstring(lua, 1);
-       int df = lua_gettop(lua) > 1 && lua_toboolean(lua, 2);
-       DIR *dir = opendir(p);
+                               lua_pushboolean(lua, 0);
+                               lua_pushstring(lua, strerror(errno));
 
-       if (dir == NULL)
-               lua_pushnil(lua);
-       else {
-               struct dirent *de;
-               int i = 1;
+                               closedir(dir);
 
-               lua_newtable(lua);
+                               return 2;
+                       }
 
-               for(;;) {
-                       de = readdir(dir);
+                       break;
+               }
 
-                       if(de == NULL) break;
+               if (strcmp(de->d_name, ".") == 0 ||
+                   strcmp(de->d_name, "..") == 0)
+                           continue;
 
-                       if(df || de->d_name[0] != '.') {
-                               lua_pushstring(lua, de->d_name);
-                               lua_rawseti(lua, -2, i++);
-                       }
+               if (df || de->d_name[0] != '.') {
+                       lua_pushstring(lua, de->d_name);
+                       lua_rawseti(lua, -2, i++);
                }
-
-               closedir(dir);
        }
 
-       return 1;
-}
-
+       closedir(dir);
 
-/* e2util.tempnam(DIR) -> PATH
-
-   Returns a random temporary pathname.
-   */
-
-static int
-create_temporary_filename(lua_State *lua)
-{
-       const char *dir = luaL_checkstring(lua, 1);
-       lua_pushstring(lua, tempnam(dir, "e2"));
        return 1;
 }
 
-
-/* e2util.exists(PATH, [EXECUTABLE?]) -> BOOL
-
-   Returns true if the file given in PATH exists. If EXECUTABLE? is given
-   and true, then it is also checked whether the file is executable.
-   */
-
 static int
 file_exists(lua_State *lua)
 {
@@ -333,12 +230,6 @@ file_exists(lua_State *lua)
        return 1;
 }
 
-
-/* e2util.cd(PATH)
-
-   Changes the current working directory to PATH.
-   */
-
 static int
 change_directory(lua_State *lua)
 {
@@ -350,127 +241,45 @@ change_directory(lua_State *lua)
                lua_pushstring(lua, strerror(errno));
                return 2;
        }
+
        lua_pushboolean(lua, 1);
-       lua_pushnil(lua);
-       return 2;
+       return 1;
 }
 
-/* e2util.symlink(OLDPATH, NEWPATH)
-
-   Creates a symbolic link named NEWPATH which contains the string OLDPATH.
-   */
-
 static int
 create_symlink(lua_State *lua)
 {
        const char *old = luaL_checkstring(lua, 1);
        const char *new = luaL_checkstring(lua, 2);
 
-       lua_pushboolean(lua, symlink(old, new) == 0);
-       return 1;
-}
-
+        if (symlink(old, new) != 0) {
+                lua_pushboolean(lua, 0);
+                lua_pushstring(lua, strerror(errno));
 
-/* e2util.pipe(COMMAND, [ARG...]) -> FDIN, FDOUT, FDERR, PID
-   |  nil, ERRORMESSAGE
+                return 2;
+        }
 
-   Invokes a subcommand and returns two file-descriptors for writing to stdin
-   and/or reading from stdout/stderr of the executing subprocess, respectively.
-   File-descriptors are named as viewn from the child process.
-   */
+       lua_pushboolean(lua, 1);
+       return 1;
+}
 
 static int
-run_pipe(lua_State *lua)
+do_hardlink(lua_State *lua)
 {
-       int in[2], out[2], err[2];
-       char **argv;
-       int n;
-
-       if(pipe(in) != 0)
-               return 0;
-
-       else if(pipe(out) != 0) {
-               close(in[0]);
-               close(in[1]);
-               return 0;
-       }
-       else if(pipe(err) != 0) {
-               close(out[0]);
-               close(out[1]);
-               close(in[0]);
-               close(in[1]);
-               return 0;
-       }
-       else {
-               fflush(0);
-               pid_t child = fork();
-
-               if (child < 0) {
-                       close(in[0]);
-                       close(in[1]);
-                       close(out[0]);
-                       close(out[1]);
-                       close(err[0]);
-                       close(err[1]);
-                       goto fail;
-               }
-               else if (child == 0) {
-                       close(in[1]);
-
-                       if(in[0] != STDIN_FILENO) {
-                               dup2(in[0], STDIN_FILENO);
-                               close(in[0]);
-                       }
-
-                       close(out[0]);
-
-                       if (out[1] != STDOUT_FILENO) {
-                               dup2(out[1], STDOUT_FILENO);
-                               close(out[1]);
-                       }
-
-                       close(err[0]);
+       const char *old = luaL_checkstring(lua, 1);
+       const char *new = luaL_checkstring(lua, 2);
 
-                       if (err[1] != STDERR_FILENO) {
-                               dup2(err[1], STDERR_FILENO);
-                               close(err[1]);
-                       }
+        if (link(old, new) != 0) {
+                lua_pushboolean(lua, 0);
+                lua_pushstring(lua, strerror(errno));
 
-                       n = lua_gettop(lua);
-                       argv = alloca(sizeof(*argv) * (n+1));
-                       argv[n] = NULL;
-                       while (n > 0) {
-                               argv[n-1] = (char *)luaL_checkstring(lua, n);
-                               n -= 1;
-                       }
-                       execvp(argv[0], argv);
-                       goto fail;
-               }
-               else {
-                       close(in[0]);
-                       close(out[1]);
-                       close(err[1]);
-                       lua_pushnumber(lua, in[1]);
-                       lua_pushnumber(lua, out[0]);
-                       lua_pushnumber(lua, err[0]);
-                       lua_pushnumber(lua, child);
-                       return 4;
-               }
-       }
+                return 2;
+        }
 
-fail:
-       lua_pushnil(lua);
-       lua_pushstring(lua, strerror(errno));
-       return 2;
+       lua_pushboolean(lua, 1);
+       return 1;
 }
 
-
-/* e2util.wait(PID) -> STATUS, PID
-   |  nil, ERRORMESSAGE
-
-   waits for process to terminate and returns exit code.
-   */
-
 static int
 process_wait(lua_State *lua)
 {
@@ -478,104 +287,17 @@ process_wait(lua_State *lua)
        int rc, status;
        rc = waitpid(pid, &status, 0);
        if (rc < 0) {
-               lua_pushnil(lua);
+               lua_pushboolean(lua, 0);
                lua_pushstring(lua, strerror(errno));
                return 2;
        }
+
        lua_pushnumber(lua, WEXITSTATUS(status));
        lua_pushnumber(lua, rc);
-       return 2;
-}
-
-
-/* e2util.read(FD, NUM) -> STRING
-   |  nil, ERRORMESSAGE
-
-   Reads characters from a file-descriptor.
-   */
-
-static int
-read_fd(lua_State *lua)
-{
-       int fd = luaL_checkinteger(lua, 1);
-       int n = luaL_checkinteger(lua, 2);
-       char *buf = (char *)malloc(n);
-       int m;
-
-       if(buf == NULL) return 0;
-
-       m = read(fd, buf, n);
-
-       if (m < 0) {
-               lua_pushnil(lua);
-               lua_pushstring(lua, strerror(errno));
-               free(buf);
-               return 2;
-       }
-       else
-               lua_pushlstring(lua, buf, m);
 
-       free(buf);
-       return 1;
-}
-
-
-/* e2util.write(FD, STRING, [NUM]) -> NUM'
-   |  nil, ERRORMESSAGE
-
-   Writes characters to a file-descriptor.
-   */
-
-static int
-write_fd(lua_State *lua)
-{
-       int fd = luaL_checkinteger(lua, 1);
-       size_t len;
-       const char *buf = luaL_checklstring(lua, 2, &len);
-       int n = lua_gettop(lua) > 2 ? luaL_checkinteger(lua, 3) : len;
-       int m;
-
-       m = write(fd, buf, n);
-
-       if (m < 0) {
-               lua_pushnil(lua);
-               lua_pushstring(lua, strerror(errno));
-               return 2;
-       }
-
-       lua_pushnumber(lua, m);
-       return 1;
-}
-
-
-/* e2util.close(FD) -> true
-   |  false, ERRORMESSAGE
-
-   Close file-descriptor, returning "false" if an error occurred or "true"
-   otherwise.
-   */
-
-static int
-close_fd(lua_State *lua)
-{
-       int fd = luaL_checkinteger(lua, 1);
-
-       if (close(fd) < 0) {
-               lua_pushnil(lua);
-               lua_pushstring(lua, strerror(errno));
-               return 2;
-       }
-
-       lua_pushboolean(lua, 1);
-       return 1;
+       return 2;
 }
 
-/* e2util.poll(TMO_MSEC, {FD...}) -> INDEX, POLLIN, POLLOUT
-   Returns 0 on timeout, <0 on error, otherwise indicates which FD triggered.
-   When muliple FDs triggered, only one is indicated.
-   With a FD given, two boolean values indicate read/writeability.
-   */
-
 static int
 poll_fd(lua_State *lua)
 {
@@ -616,10 +338,6 @@ poll_fd(lua_State *lua)
        return 1;
 }
 
-/* e2util.unblock(FD)
-   Set file to nonblocking mode
-   */
-
 static int
 unblock_fd(lua_State *lua)
 {
@@ -629,26 +347,6 @@ unblock_fd(lua_State *lua)
        return 0;
 }
 
-
-/* e2util.isatty(FD) -> BOOL
-
-   Returns true, if FD refers to a terminal device.
-   */
-
-static int
-is_terminal(lua_State *lua)
-{
-       int fd = luaL_checkinteger(lua, 1);
-       lua_pushboolean(lua, isatty(fd));
-       return 1;
-}
-
-/* e2util.umask(VAL)
-
-   Set the umask to VAL
-   Returns the previous value of umask
-   */
-
 static int
 set_umask(lua_State *lua)
 {
@@ -659,10 +357,6 @@ set_umask(lua_State *lua)
        return 1;
 }
 
-/* e2util.setenv(var, val, overwrite)
-
-*/
-
 static int
 do_setenv(lua_State *lua)
 {
@@ -676,10 +370,6 @@ do_setenv(lua_State *lua)
 
 }
 
-/* e2util.unsetenv(var)
-
-*/
-
 static int
 do_unsetenv(lua_State *lua)
 {
@@ -691,10 +381,6 @@ do_unsetenv(lua_State *lua)
        return 1;
 }
 
-/* e2util.exec()
-
-   call execvp() with the full argument list */
-
 static int
 do_exec(lua_State *lua)
 {
@@ -718,23 +404,30 @@ do_exec(lua_State *lua)
        return 1;
 }
 
-/* e2util.getpid()
-
-   get the pid of the current process */
-
 static int
 do_getpid(lua_State *lua) {
        pid_t pid = getpid();
-       if (pid < 0 )
-               lua_pushnil(lua);
-       else
-               lua_pushinteger(lua, pid);
+       lua_pushinteger(lua, pid);
        return 1;
 }
 
-/* e2util.signal_reset()
- * Reset all (possible) signals back to their default settings
- */
+static int
+do_unlink(lua_State *lua)
+{
+       const char *pathname = luaL_checkstring(lua, 1);
+
+       if (unlink(pathname) != 0) {
+               lua_pushboolean(lua, 0);
+               lua_pushstring(lua, strerror(errno));
+
+               return 2;
+       }
+
+       lua_pushboolean(lua, 1);
+       return 1;
+}
+
+/* Reset all (possible) signals back to their default settings */
 static int
 signal_reset(lua_State *L)
 {
@@ -761,7 +454,6 @@ signal_reset(lua_State *L)
                }
 
                if (sigaction(s, &act, NULL) < 0) {
-                       // fprintf(stderr, "%d is set to %p\n", s, (void *)act.sa_handler);
                        lua_pushboolean(L, 0);
                        lua_pushstring(L, strerror(errno));
                        return 2;
@@ -773,15 +465,7 @@ signal_reset(lua_State *L)
 }
 
 
-/*
- * e2util.closefrom() closes all file descriptors >= * fd_from.
- * closefrom() is commonly available on the BSDs, but on Linux we
- * have to use this crutch (which fails when /proc is not mounted).
- *
- * Lua:
- * e2util.closefrom(number) returns true OR false and an errno string.
- * May throw an exception.
- */
+/* closes all file descriptors >= fd */
 static int
 closefrom(lua_State *L)
 {
@@ -824,10 +508,44 @@ error:
        return 2;
 }
 
-/* e2util.catch_interrupt()
+static int
+do_rmdir(lua_State *lua)
+{
+       const char *pathname = luaL_checkstring(lua, 1);
+
+       if (rmdir(pathname) != 0) {
+               lua_pushboolean(lua, 0);
+               lua_pushstring(lua, strerror(errno));
+
+               return 2;
+       }
+
+       lua_pushboolean(lua, 1);
+       return 1;
+}
+
+static int
+do_kill(lua_State *lua)
+{
+       pid_t pid = luaL_checkinteger(lua, 1);
+       int sig = luaL_checkinteger(lua, 2);
+
+       if (kill(pid, sig) < 0) {
+               lua_pushboolean(lua, 0);
+               lua_pushstring(lua, strerror(errno));
+
+               return 2;
+       }
+
+       lua_pushboolean(lua, 1);
+       return 1;
+}
 
-   Establish signal handler for SIGINT that aborts. */
 
+/*
+ * Hook that gets called once an interrupt has been requested.
+ * Calls e2lib.interrupt_hook() to deal with any cleanup that might be required.
+ */
 static void
 lstop(lua_State *L, lua_Debug *ar) {
        lua_sethook(L, NULL, 0, 0);
@@ -850,6 +568,10 @@ lstop(lua_State *L, lua_Debug *ar) {
 static lua_State *globalL;
 
 
+/*
+ * Interrupt handler sets a hook to stop the interpreter from
+ * continuing normal execution at the next possible spot.
+ */
 static void
 laction(int i) {
        /* Ignore further signals because lstop() should
@@ -860,39 +582,42 @@ laction(int i) {
 
 
 static luaL_Reg lib[] = {
+       { "chdir", change_directory },
+       { "closefrom", closefrom },
        { "cwd", get_working_directory },
-       { "realpath", get_realpath },
-       { "stat", get_file_statistics },
-       { "readlink", read_symbolic_link },
        { "directory", get_directory },
-       { "tempnam", create_temporary_filename },
        { "exists", file_exists },
-       { "cd", change_directory },
-       { "symlink", create_symlink },
-       { "pipe", run_pipe },
-       { "wait", process_wait },
-       { "read", read_fd },
-       { "write", write_fd },
-       { "close", close_fd },
-       { "poll", poll_fd },
-       { "unblock", unblock_fd },
        { "fork", lua_fork },
-       { "isatty", is_terminal },
-       { "umask", set_umask },
-       { "setenv", do_setenv },
-       { "unsetenv", do_unsetenv },
-       { "exec", do_exec },
        { "getpid", do_getpid },
+       { "hardlink", do_hardlink },
+       { "kill", do_kill },
+       { "poll", poll_fd },
+       { "rmdir", do_rmdir },
+       { "setenv", do_setenv },
        { "signal_reset", signal_reset },
-       { "closefrom", closefrom },
+       { "stat", get_file_statistics },
+       { "symlink", create_symlink },
+       { "umask", set_umask },
+       { "unblock", unblock_fd },
+       { "unlink", do_unlink },
+       { "wait", process_wait },
        { NULL, NULL }
 };
 
 
-int luaopen_e2util(lua_State *lua)
+int luaopen_le2lib(lua_State *lua)
 {
-       luaL_register(lua, "e2util", lib);
+       luaL_Reg *next;
+
+       lua_newtable(lua);
+       for (next = &lib; next->name != NULL; next++) {
+               lua_pushcfunction(lua, next->func);
+               lua_setfield(lua, -2, next->name);
+       }
+
+       /* Establish signal handler catching SIGINT for orderly shutdown */
        globalL = lua;
        signal(SIGINT, laction);
+
        return 1;
 }
index 4a5b22cbc43abc25e542fe002d5f4bb1df185d65..40acc26185b4798171a8541150e4b3d89a567484 100644 (file)
@@ -113,7 +113,7 @@ local function load_plugin(dir, p, ctx)
                 e:append("a dependency of plugin %s is not a string", p)
             end
 
-            if not e2util.exists(string.format("%s/%s", dir, dep)) then
+            if not e2lib.exists(string.format("%s/%s", dir, dep)) then
                 e:append("dependency %s of plugin %s is not installed", dep, p)
             end
         end
index be7dc0782d45044c2a9cfb9d64ecabc6454a99ee..31febbb97120f93cb8108c9d1a0f9f8d6fd34fe6 100644 (file)
@@ -303,7 +303,11 @@ function transport.push_file(sourcefile, durl, location, push_permissions, try_h
         local done = false
         local dst = e2lib.join(destdir, destname)
         if (not push_permissions) and try_hardlink then
-            rc, re = e2lib.ln(sourcefile, dst, "--force")
+            local dst = e2lib.join(destdir, destname)
+            if e2lib.exists(dst) then
+                e2lib.unlink(dst) -- ignore error, hardlink will fail
+            end
+            rc, re = e2lib.hardlink(sourcefile, dst)
             if rc then
                 done = true
             else
index 0744cc23fe33a1642e35947d765594f1c627303e..783c82e71b909e8e148ddedb46cc7c2a14e10c5e 100644 (file)
@@ -195,7 +195,7 @@ local function e2_fetch_project(arg)
     local e2_install_e2 = string.format("%s %s/e2-install-e2",
     e2lib.shquote(buildconfig.LUA), e2lib.shquote(buildconfig.TOOLDIR))
     rc, re = e2lib.callcmd_log(e2_install_e2)
-    if rc ~= 0 then
+    if not rc or rc ~= 0 then
         local e = err.new("installing local e2 failed")
         return false, e:cat(re)
     end
index e794a0239509eb9ac3582226608a23d34840dc2d..71f71738fd17e95f02948b16d4327a6f35553cd2 100644 (file)
@@ -110,15 +110,19 @@ local function e2_install_e2(arg)
     -- version is 1 or 2
 
     -- remove the old e2 source, installation and plugins, if it exists
-    rc, re = e2lib.rm(".e2/e2 .e2/bin .e2/lib .e2/plugins", "-fr")
-    if not rc then
-        return false, e:cat(re)
+    for _,dir in ipairs({".e2/e2",  ".e2/bin", ".e2/lib", ".e2/plugins"}) do
+        if e2lib.exists(dir) then
+            rc, re = e2lib.unlink_recursive(dir)
+            if not rc then
+                return false, e:cat(re)
+            end
+        end
     end
 
     e2lib.logf(2, "installing local tools")
 
     local extensions
-    if e2util.exists(e2lib.globals.extension_config) then
+    if e2lib.exists(e2lib.globals.extension_config) then
         extensions, re = e2lib.read_extension_config()
         if not extensions then
             return false, e:cat(re)
@@ -185,12 +189,16 @@ local function e2_install_e2(arg)
         local server = config.site.e2_server
         local location = string.format("%s/%s.git", config.site.e2_base, ex.name)
         local destdir = ex.name
-        rc, re = e2lib.rm(destdir, "-fr")
-        if not rc then
-            return false, e:cat(re)
+
+        if e2lib.exists(destdir) then
+            rc, re = e2lib.unlink_recursive(destdir)
+            if not rc then
+                return false, e:cat(re)
+            end
         end
+
         rc, re = generic_git.git_clone_from_server(scache, server, location,
-        destdir, false)
+            destdir, false)
         if not rc then
             return false, e:cat(re)
         end
@@ -212,7 +220,7 @@ local function e2_install_e2(arg)
     local cmd = string.format("make PREFIX=%s BINDIR=%s local install-local",
     e2lib.shquote(buildconfig.PREFIX), e2lib.shquote(buildconfig.BINDIR))
     rc, re = e2lib.callcmd_log(cmd)
-    if rc ~= 0 then
+    if not rc or rc ~= 0 then
         return false, e:cat(re)
     end
 
index 8d148859fdf6c4220429e7620d7853b0f1128620..fa6f7f73c0adf4cebdd9c658740281376f9ed7d7 100644 (file)
@@ -32,7 +32,6 @@ local e2lib = require("e2lib")
 local e2option = require("e2option")
 local err = require("err")
 local buildconfig = require("buildconfig")
-require("e2util")
 
 local function e2(arg)
     local rc, re = e2lib.init()
@@ -81,7 +80,7 @@ local function e2(arg)
     end
 
     local env, cmd
-    if e2util.stat(e2call.globaltool) then
+    if e2lib.stat(e2call.globaltool) then
         e2call.tool = e2call.globaltool
         env = string.format("LUA_PATH='%s/?.lua' LUA_CPATH='%s/?.so'",
         buildconfig.LIBDIR, buildconfig.LIBDIR)
@@ -89,7 +88,7 @@ local function e2(arg)
         e2call.arg_string)
     elseif not root then
         return false, err.new("%s is not a global tool and we're not in a project environment", e2call.toolname)
-    elseif root and e2util.stat(e2call.localtool) then
+    elseif root and e2lib.stat(e2call.localtool) then
         e2call.tool = e2call.localtool
         -- Search for .lc files, the local e2 may be of an older version
         env = "LUA_PATH='" .. root .. "/.e2/lib/e2/?.lc;" ..
index 0c4fcda0cef5d01a79ab86449b2375a91e62e479..01b2a03b5524ba575cf66e27bbab8b8157d8e20d 100644 (file)
@@ -76,7 +76,7 @@ local function path_to_url(path)
         end
 
         local u = url.parse(path)
-        local cwd = e2util.cwd()
+        local cwd = e2lib.cwd()
         if not u and cwd then
             return "file://" .. e2lib.join(cwd, path)
         end
index 211b331d4bea67d6a423be2a47db71cfbab49de3..3f65fb1c508b0df67ac0adc08cc243657c26f69d 100644 (file)
@@ -72,10 +72,11 @@ local function linklast(info, r, return_flags)
     if not rc then
         return false, e:cat(re)
     end
-    rc, re = e2lib.rm(lnk, "-f")                       -- remove the old link
-    if not rc then
-        return false, e:cat(re)
+
+    if e2lib.exists(lnk) then
+        e2lib.unlink(lnk) -- ignore errors, symlink will catch it
     end
+
     rc, re = e2lib.symlink(dst, lnk)           -- create the new link
     if not rc then
         return false, e:cat(re)
@@ -434,7 +435,10 @@ local function runbuild(info, r, return_flags)
         out:flush()
     end
     e2tool.set_umask(info)
-    local rc = e2lib.callcmd_capture(cmd, logto)
+    rc, re = e2lib.callcmd_capture(cmd, logto)
+    if not rc then
+        return false, e:cat(re)
+    end
     e2tool.reset_umask(info)
     out:close()
     if rc ~= 0 then
@@ -454,14 +458,14 @@ local function chroot_remove(info, r, return_flags)
     if not rc then
         return e:cat(re)
     end
-    rc, re = e2lib.rm(res.build_config.chroot_marker)
+    rc, re = e2lib.unlink(res.build_config.chroot_marker)
     if not rc then
         return false, e:cat(re)
     end
     local f = e2lib.join(info.root, "playground")
-    local s = e2util.stat(f)
+    local s = e2lib.stat(f)
     if s and s.type == "symbolic-link" then
-        local rc, e = e2lib.rm(f, "-f")
+        rc, re = e2lib.unlink(f)
         if not rc then
             return false, e:cat(re)
         end
@@ -913,7 +917,7 @@ local function store_result(info, r, return_flags)
         e2lib.logf(3, "result file: %s", f)
         local s = e2lib.join(rfilesdir, f)
         local d = "result/files"
-        rc, re = e2lib.ln(s, d)
+        rc, re = e2lib.hardlink(s, d)
         if not rc then
             -- There are three reasons this might fail
             -- a) Legitimate IO etc. errors.
@@ -1080,14 +1084,17 @@ local function collect_project(info, r, return_flags)
         return false, e:cat(re)
     end
 
-    local init_files = e2util.directory(e2lib.join(info.root, "/proj/init"))
-    for _,f in ipairs(init_files) do
+    for f, re in e2lib.directory(e2lib.join(info.root, "proj/init"), false) do
+        if not f then
+            return false, e:cat(re)
+        end
+
         e2lib.logf(3, "init file: %s", f)
         local server = "."
         local location = e2lib.join("proj/init", f)
         local cache_flags = {}
         rc, re = info.cache:fetch_file(server, location,
-        destdir, nil, cache_flags)
+            destdir, nil, cache_flags)
         if not rc then
             return false, e:cat(re)
         end
index 0975efad5d1b908770db85f0cd25582b1c9d0f37..3869de9b47b6261695d5c35776e7a114fa9c3ed9 100644 (file)
@@ -37,7 +37,6 @@ local environment = require("environment")
 local plugin = require("plugin")
 local url = require("url")
 local hash = require("hash")
-require("e2util")
 local e2option = require("e2option")
 local generic_git = require("generic_git")
 local policy = require("policy")
@@ -277,7 +276,7 @@ local function load_user_config(info, path, dest, index, var)
     local rc, re
     local e = err.new("loading configuration failed")
     e2lib.logf(3, "loading %s", path)
-    if not e2util.exists(path) then
+    if not e2lib.exists(path) then
         return false, e:append("file does not exist: %s", path)
     end
 
@@ -609,14 +608,14 @@ end
 -- @param info
 function e2tool.set_umask(info)
     e2lib.logf(4, "setting umask to %04o", info.chroot_umask)
-    e2util.umask(info.chroot_umask)
+    e2lib.umask(info.chroot_umask)
 end
 
 -- set umask back to the value used on the host
 -- @param info
 function e2tool.reset_umask(info)
     e2lib.logf(4, "setting umask to %04o", info.host_umask)
-    e2util.umask(info.host_umask)
+    e2lib.umask(info.host_umask)
 end
 
 -- initialize the umask set/reset mechanism (i.e. store the host umask)
@@ -626,7 +625,7 @@ local function init_umask(info)
     info.chroot_umask = 18   -- 022 octal
 
     -- save the umask value we run with
-    info.host_umask = e2util.umask(info.chroot_umask)
+    info.host_umask = e2lib.umask(info.chroot_umask)
 
     -- restore the previous umask value again
     e2tool.reset_umask(info)
@@ -643,7 +642,12 @@ function e2tool.local_init(path, tool)
     local info = {}
 
     info.current_tool = tool
-    info.startup_cwd = e2util.cwd()
+
+    rc, re = e2lib.cwd()
+    if not rc then
+        return false, e:cat(re)
+    end
+    info.startup_cwd = rc
 
     init_umask(info)
 
@@ -920,9 +924,9 @@ local function gather_source_paths(info, basedir, sources)
         end
 
         local fullentry = e2lib.join(info.root, e2tool.sourcedir(entry))
-        local s = e2util.stat(fullentry, false)
+        local s = e2lib.stat(fullentry, false)
         if s.type == "directory" then
-            if e2util.exists(e2tool.sourceconfig(entry)) then
+            if e2lib.exists(e2tool.sourceconfig(entry)) then
                 table.insert(sources, entry)
             else
                 -- try subfolder
@@ -1110,9 +1114,9 @@ local function gather_result_paths(info, basedir, results)
         end
 
         local fullentry = e2lib.join(info.root, e2tool.resultdir(entry))
-        local s = e2util.stat(fullentry, false)
+        local s = e2lib.stat(fullentry, false)
         if s.type == "directory" then
-            if e2util.exists(e2tool.resultconfig(entry)) then
+            if e2lib.exists(e2tool.resultconfig(entry)) then
                 table.insert(results, entry)
             else
                 -- try subfolder
@@ -1464,7 +1468,7 @@ function e2tool.collect_project_info(info, skip_load_config)
     }
     for _,f in ipairs(deprecated_files) do
         local path = e2lib.join(info.root, f)
-        if e2util.exists(path) then
+        if e2lib.exists(path) then
             e2lib.warnf("WDEPRECATED", "File exists but is no longer used: `%s'", f)
         end
     end
@@ -1970,10 +1974,9 @@ local function hashcache(info, file)
     if not p then
         return nil, e:cat(re)
     end
-
-    local s, msg = e2util.stat(p)
+    local s, re = e2lib.stat(p)
     if not s then
-        return nil, err.new("%s: %s", p, msg)
+        return nil, e:cat(re)
     end
 
     local id = string.format("%s:%s", file.server, file.location)
index 669fff1912325b5abab6d1b98c9f684d69495d83..89c89f5db878752a94b6f44e3e224144f067817c 100644 (file)
@@ -197,7 +197,7 @@ function cvs.fetch_source(info, sourcename)
     e2lib.shquote(cvstool), cvsflags, e2lib.shquote(cvsroot),
     rev, e2lib.shquote(base), e2lib.shquote(src.module))
     local rc, re = e2lib.callcmd_log(cmd)
-    if rc ~= 0 then
+    if not rc or rc ~= 0 then
         return false, e:cat(re)
     end
     return true, nil
@@ -254,8 +254,8 @@ function cvs.prepare_source(info, sourcename, source_set, buildpath)
     else
         return false, err.new("invalid build mode")
     end
-    local rc, re = e2lib.callcmd_log(cmd)
-    if rc ~= 0 then
+    rc, re = e2lib.callcmd_log(cmd)
+    if not rc or rc ~= 0 then
         return false, e:cat(re)
     end
     return true, nil
@@ -282,13 +282,13 @@ function cvs.update(info, sourcename)
         return false, e:cat(re)
     end
     local cmd = string.format("cd %s && CVS_RSH=%s %s %s update -R",
-    e2lib.shquote(working), e2lib.shquote(rsh), e2lib.shquote(cvstool),
-    cvsflags)
-    local rc, re = e2lib.callcmd_log(cmd)
-    if rc ~= 0 then
-        e:cat(re)
-        return false, e
+        e2lib.shquote(working), e2lib.shquote(rsh), e2lib.shquote(cvstool),
+        cvsflags)
+    rc, re = e2lib.callcmd_log(cmd)
+    if not rc or rc ~= 0 then
+        return false, e:cat(re)
     end
+
     return true, nil
 end
 
index 5b0837451bb0126cf04997c719c357527312fb5e..9f5a3a47e9406ac7bf592b1bfb284efe59c82d3b 100644 (file)
@@ -365,9 +365,9 @@ function files.prepare_source(info, sourcename, sourceset, buildpath)
             if not symlink then
                 symlink = buildpath .. "/" .. sourcename
                 if file.unpack ~= sourcename then
-                    if not e2util.symlink(file.unpack, symlink) then
-                        return false, e:append("cannot create symlink: %s -> %s", symlink,
-                        file.unpack)
+                    rc, re = e2lib.symlink(file.unpack, symlink)
+                    if not rc then
+                        return false, e:cat(re)
                     end
                 end
             end
index 9053b59e7b39cf77797baccef4dd4227be39dc94..a915489891d83afef8a3b40b0ba1ab0738df6923 100644 (file)
@@ -329,8 +329,16 @@ function git.prepare_source(info, sourcename, sourceset, buildpath)
     elseif sourceset == "working-copy" then
         -- warn for empty working-copy
         local working = string.format("%s/%s", info.root, src.working)
-        local d = e2util.directory(working, false)
-        if #d == 0 then
+        local empty = true
+        for f, re in e2lib.directory(working, false) do
+            if not f then
+                return false, e:cat(re)
+            end
+
+            empty = false
+            break
+        end
+        if empty then
             e2lib.warnf("WOTHER", "in result: %s", src.name)
             e2lib.warnf("WOTHER", "working copy seems empty")
         end
@@ -539,8 +547,8 @@ function git.toresult(info, sourcename, sourceset, directory)
         return false, e:append("sourceset not supported: %s",
         sourceset)
     end
-    local rc, re = e2lib.callcmd_log(cmd)
-    if rc ~= 0 then
+    rc, re = e2lib.callcmd_log(cmd)
+    if not rc or rc ~= 0 then
         return false, e:cat(re)
     end
     local fname  = string.format("%s/%s", directory, makefile)