]> git.e2factory.org Git - e2factory.git/commitdiff
Add new mkdir(), mkdir_recursive and parse_mode() functions
authorTobias Ulmer <tu@emlix.com>
Fri, 27 Sep 2013 14:49:05 +0000 (16:49 +0200)
committerTobias Ulmer <tu@emlix.com>
Wed, 16 Nov 2016 14:01:23 +0000 (15:01 +0100)
Replace all calls to the external mkdir tool with our own mkdir
code.

Signed-off-by: Tobias Ulmer <tu@emlix.com>
12 files changed:
generic/e2lib.lua
generic/generic_git.lua
generic/le2lib.c
generic/transport.lua
global/e2-create-project.lua
local/e2-cf.lua
local/e2build.lua
local/e2tool.lua
plugins/cvs.lua
plugins/files.lua
plugins/git.lua
plugins/svn.lua

index 4acf19670bcb597469eac41bdf1cb34ca79ec03f..9a616efce97a97d8e54afb6924bc0e48beb259f5 100644 (file)
@@ -50,6 +50,7 @@ package.loaded["e2lib"] = e2lib
 local buildconfig = require("buildconfig")
 local lock = require("lock")
 local err = require("err")
+local errno = require("errno")
 local plugin = require("plugin")
 local tools = require("tools")
 local cache = require("cache")
@@ -1761,20 +1762,76 @@ function e2lib.rmdir(dir)
     return true
 end
 
---- call the mkdir command
--- @param dir string: the directory name
--- @param flags string: flags to pass to mkdir
--- @return bool
--- @return the last line ouf captured output
-function e2lib.mkdir(dir, flags)
-    flags = flags or ""
-    assert(type(dir) == "string")
-    assert(string.len(dir) > 0)
-    assert(type(flags) == "string")
+--- Parse a mode string in the form ugo+rwx etc.
+-- @param modestring Mode string.
+-- @return Numeric mode or false on error.
+-- @return Error object on failure.
+function e2lib.parse_mode(modestring)
+    local rc, errstring = le2lib.parse_mode(modestring)
+
+    if not rc then
+        return false, err.new("cannot parse mode string '%s': %s", modestring,
+            errstring)
+    end
 
-    -- TODO: quote flags as well
-    local args = string.format("%s %s", flags, e2lib.shquote(dir))
-    return e2lib.call_tool("mkdir", args)
+    return rc
+end
+
+--- Create a single directory.
+-- @param dir Directory name (string).
+-- @param mode Numeric mode for directory creation (umask restrictions apply).
+-- @return True on success, false on error.
+-- @return Error object on failure.
+-- @return Errno (number) on failure.
+function e2lib.mkdir(dir, mode)
+    local re
+
+    if mode == nil then
+        mode, re = e2lib.parse_mode("a+rwx")
+        if not mode then
+            return false, re
+        end
+    end
+
+    local rc, errstring, errnum = le2lib.mkdir(dir, mode)
+
+    if not rc then
+        return false, err.new("cannot create directory %q: %s", dir,
+            errstring), errnum
+    end
+
+    return true
+end
+
+--- Create zero or more directories making up a path. Some or all directories
+-- in the path may already exist.
+-- @param path Path name (string).
+-- @param mode Numeric mode for directory creation (umask restrictions apply).
+-- @return True on success, false on error.
+-- @return Error object on failure.
+function e2lib.mkdir_recursive(path, mode)
+    local dirs = e2lib.parentdirs(path)
+    local rc, re, errnum, eexist
+
+    if mode == nil then
+        mode, re = e2lib.parse_mode("ugo+rwx")
+        if not mode then
+            return false, re
+        end
+    end
+
+    eexist = errno.def2errnum("EEXIST")
+
+    for _,dir in ipairs(dirs) do
+        rc, re, errnum = e2lib.mkdir(dir, mode)
+        if not rc then
+            if errnum ~= eexist then
+                return false, re
+            end
+        end
+    end
+
+    return true
 end
 
 --- call the patch command
@@ -2137,26 +2194,24 @@ function e2lib.uname_machine()
     return machine
 end
 
---- return a table of parent directories
+--- Return a table of parent directories going deeper one directory at a time.
+-- Example: "/foo/", "/foo/bar", ...
 -- @param path string: path
 -- @return a table of parent directories, including path.
 function e2lib.parentdirs(path)
-    local i = 2
+    local start = 2
+    local stop
     local t = {}
-    local stop = false
-    while true do
-        local px
-        local p = path:find("/", i)
-        if not p then
-            p = #path
-            stop = true
-        end
-        px = path:sub(1, p)
-        table.insert(t, px)
-        i = p + 1
-        if stop then
-            break
+    local parent
+
+    while stop ~= path:len() do
+        stop = path:find("/", start)
+        if not stop then
+            stop = path:len()
         end
+        start = stop + 1
+        parent = path:sub(1, stop)
+        table.insert(t, parent)
     end
     return t
 end
index e189eed204a7967e7b176618361785dc85cae29d..fed8980441958bf8d75d531c2f190da8fb12c0d7 100644 (file)
@@ -650,7 +650,7 @@ function generic_git.new_repository(c, lserver, llocation, rserver, rlocation, f
     if not lurl then
         return false, e:cat(re)
     end
-    local rc = e2lib.mkdir(string.format("/%s", lurl.path), "-p")
+    local rc = e2lib.mkdir_recursive(e2lib.join("/", lurl.path))
     if not rc then
         return false, e:cat("can't create path to local git repository")
     end
index e12a0a0482d1ee727c7d32bc0dd9e03fb269f918..46c0fec5a8c1b19b1f55eec5afbd739b12fc488c 100644 (file)
@@ -526,6 +526,167 @@ do_rmdir(lua_State *lua)
        return 1;
 }
 
+static unsigned calc_mode(unsigned, int, int, unsigned);
+enum { OWN_USER = 0x1, OWN_GROUP = 0x2, OWN_OTHER = 0x4 };
+
+static int
+do_parse_mode(lua_State *lua)
+{
+       const char *modestr = luaL_checkstring(lua, 1);
+       size_t len = strlen(modestr);
+       size_t pos;
+       enum { PARSE_OWNERS, PARSE_OP, PARSE_PERMS, PARSE_COMMA };
+
+       int state = PARSE_OWNERS;
+       int owners = 0;
+       char op = 0;
+
+       mode_t protection = 0;
+       mode_t mode = 0;
+
+
+       for (pos = 0; pos <= len; pos++) {
+               switch (state) {
+               case PARSE_OWNERS:
+                       switch (modestr[pos]) {
+                       case 'u': owners |= OWN_USER; break;
+                       case 'g': owners |= OWN_GROUP; break;
+                       case 'o': owners |= OWN_OTHER; break;
+                       case 'a': owners |= (OWN_USER|OWN_GROUP|OWN_OTHER);
+                               break;
+                       case 0:
+                                 lua_pushboolean(lua, 0);
+                                 lua_pushstring(lua, "unexpected end of mode string");
+                                 return 2;
+                       default:
+                                 state = PARSE_OP;
+                                 pos--;
+                                 break;
+                       }
+
+                       if (owners == 0)
+                               owners |= (OWN_USER|OWN_GROUP|OWN_OTHER);
+
+                       break;
+               case PARSE_OP:
+                       switch (modestr[pos]) {
+                       case '+':
+                       case '-':
+                       case '=':
+                               op = modestr[pos];
+                               state = PARSE_PERMS;
+                               break;
+                       case 0:
+                                 lua_pushboolean(lua, 0);
+                                 lua_pushstring(lua, "unexpected end of mode string");
+                                 return 2;
+                       default:
+                                 lua_pushboolean(lua, 0);
+                                 lua_pushstring(lua, "unknown operator");
+
+                                 return 2;
+                       }
+
+                       break;
+               case PARSE_PERMS:
+                       switch (modestr[pos]) {
+                       case 'r': protection |= S_IRUSR; break;
+                       case 'w': protection |= S_IWUSR; break;
+                       case 'x':
+                       case 'X':
+                                 protection |= S_IXUSR; break;
+                       /*case 's': break;
+                       case 't': break;
+                       case 'u': break;
+                       case 'g': break;
+                       case 'o': break;*/
+                       case ',':
+                                 state = PARSE_COMMA;
+                                 pos--;
+                                 break;
+                       case 0:
+                                 /* end of string, end of parse */
+                                 break;
+                       default:
+                                 lua_pushboolean(lua, 0);
+                                 lua_pushstring(lua, "unknown protection mode");
+
+                                 return 2;
+                       }
+
+                       break;
+               case PARSE_COMMA:
+                       mode = calc_mode(mode, owners, op, protection);
+                       state = PARSE_OWNERS;
+                       owners = op = protection = 0;
+
+                       break;
+               }
+       }
+
+       mode = calc_mode(mode, owners, op, protection);
+
+       lua_pushinteger(lua, mode);
+
+       return 1;
+}
+
+static mode_t
+calc_mode(mode_t mode, int owners, int op, mode_t protection)
+{
+       int i, shift;
+
+       /* Loop over all possible owners and calc shift */
+       for (i = OWN_USER; i <= OWN_OTHER ; i <<= 1) {
+               if (owners & i) {
+                       switch (i) {
+                       case OWN_USER: shift = 0; break;
+                       case OWN_GROUP: shift = 3; break;
+                       case OWN_OTHER: shift = 6; break;
+                       }
+               } else {
+                       continue;
+               }
+
+               switch (op) {
+               case '+':
+                       mode |= (protection>>shift);
+                       break;
+               case '-':
+                       mode &= ~(protection>>shift);
+                       break;
+               case '=':
+                       /* reset protection, leaving suid/sguid alone */
+                       mode = mode & ~0777;
+                       mode |= (protection>>shift);
+                       break;
+               }
+       }
+
+       return mode;
+}
+
+static int
+do_mkdir(lua_State *lua)
+{
+       const char *pathname = luaL_checkstring(lua, 1);
+       mode_t mode = 0777;
+
+       if (lua_gettop(lua) > 1)
+               mode = luaL_checkinteger(lua, 2);
+
+       if (mkdir(pathname, mode) != 0) {
+               lua_pushboolean(lua, 0);
+               lua_pushstring(lua, strerror(errno));
+               lua_pushinteger(lua, errno);
+
+               return 3;
+       }
+
+       lua_pushboolean(lua, 1);
+       return 1;
+}
+
 static int
 do_kill(lua_State *lua)
 {
@@ -610,6 +771,8 @@ static luaL_Reg lib[] = {
        { "getpid", do_getpid },
        { "hardlink", do_hardlink },
        { "kill", do_kill },
+       { "mkdir", do_mkdir },
+       { "parse_mode", do_parse_mode },
        { "poll", poll_fd },
        { "rmdir", do_rmdir },
        { "setenv", do_setenv },
index 31febbb97120f93cb8108c9d1a0f9f8d6fd34fe6..7fd5a078c264633d11a44532298f4fc6c3d5b460 100644 (file)
@@ -175,7 +175,7 @@ function transport.fetch_file(surl, location, destdir, destname)
         return false, e:cat(re)
     end
     -- create the destination directory
-    rc, re = e2lib.mkdir(destdir, "-p")
+    rc, re = e2lib.mkdir_recursive(destdir)
     if not rc then
         return false, e:cat(re)
     end
@@ -281,24 +281,25 @@ function transport.push_file(sourcefile, durl, location, push_permissions, try_h
     if u.transport == "file" then
         local destdir = string.format("/%s", e2lib.dirname(u.path))
         local destname = e2lib.basename(u.path)
-        -- split directories, to apply permissions to all newly
-        -- created parent directories, too.
-        local dirs = e2lib.parentdirs(destdir)
-        local mkdir_perm = ""
+        local mode = nil
+
+        if push_permissions then
+            mode, re = e2lib.parse_mode(push_permissions)
+            if not mode then
+                return false, e:cat(re)
+            end
+        end
+
+        rc, re = e2lib.mkdir_recursive(destdir, mode)
+        if not rc then
+            return false, e:cat(re)
+        end
+
         local rsync_argv = {}
         if push_permissions then
-            mkdir_perm = string.format("--mode \"%s\"", push_permissions)
             table.insert(rsync_argv, "--perms")
             table.insert(rsync_argv, "--chmod")
             table.insert(rsync_argv, push_permissions)
-
-        end
-        for _,d in ipairs(dirs) do
-            local mkdir_flags = string.format("-p %s", mkdir_perm)
-            rc, re = e2lib.mkdir(d, mkdir_flags)
-            if not rc then
-                return false, e:cat(re)
-            end
         end
         local done = false
         local dst = e2lib.join(destdir, destname)
index c39976906af3c0626ff284b6a73902fdf01837fb..6487b1c551814bfda25f7531def2a50e51b55f6c 100644 (file)
@@ -121,7 +121,7 @@ local function e2_create_project(arg)
     }
     for _,f in ipairs(files) do
         local dir = e2lib.dirname(f.filename)
-        rc, re = e2lib.mkdir(dir, "-p")
+        rc, re = e2lib.mkdir_recursive(dir)
         if not rc then
             return false, e:cat(re)
         end
@@ -209,7 +209,7 @@ local function e2_create_project(arg)
     }
     for _,f in ipairs(files) do
         local dir = e2lib.dirname(f.filename)
-        rc, re = e2lib.mkdir(dir, "-p")
+        rc, re = e2lib.mkdir_recursive(dir)
         if not rc then
             return false, e:cat(re)
         end
index d00f6e8a828348184902d006d86b684739117dd3..07eb787da482ddfb6ffc32f0202539fa787e0a03 100644 (file)
@@ -165,7 +165,7 @@ local function newsource(info, ...)
         return false, e:cat(re)
     end
 
-    local rc, re = e2lib.mkdir(cfdir, "-p")
+    local rc, re = e2lib.mkdir_recursive(cfdir)
     if not rc then
         return false, e:cat(re)
     end
@@ -253,7 +253,7 @@ local function newresult(info, ...)
         return false, e:cat(re)
     end
 
-    local rc, re = e2lib.mkdir(cfdir, "-p")
+    local rc, re = e2lib.mkdir_recursive(cfdir)
     if not rc then
         return false, e:cat(re)
     end
index 3f65fb1c508b0df67ac0adc08cc243657c26f69d..006a56cc5aed7896993ec4f27670dc81e47069b3 100644 (file)
@@ -68,7 +68,7 @@ local function linklast(info, r, return_flags)
     if not lnk then
         return false, e:cat(re)
     end
-    rc, re = e2lib.mkdir(e2lib.dirname(lnk), "-p")  -- create the directory
+    rc, re = e2lib.mkdir_recursive(e2lib.dirname(lnk))
     if not rc then
         return false, e:cat(re)
     end
@@ -256,7 +256,7 @@ local function chroot_lock(info, r, return_flags)
     local res = info.results[r]
     local rc, re
     local e = err.new("error locking chroot")
-    rc, re = e2lib.mkdir(res.build_config.c, "-p")
+    rc, re = e2lib.mkdir_recursive(res.build_config.c)
     if not rc then
         return false, e:cat(re)
     end
@@ -284,7 +284,7 @@ local function setup_chroot(info, r, return_flags)
     local e = err.new("error setting up chroot")
     -- create the chroot path and create the chroot marker file without root
     -- permissions. That makes sure we have write permissions here.
-    rc, re = e2lib.mkdir(res.build_config.c, "-p")
+    rc, re = e2lib.mkdir_recursive(res.build_config.c)
     if not rc then
         return false, e:cat(re)
     end
@@ -550,7 +550,7 @@ function e2build.unpack_result(info, r, dep, destdir)
     if not rc then
         return false, e:cat(re)
     end
-    rc, re = e2lib.mkdir(destdir, "-p")
+    rc, re = e2lib.mkdir_recursive(destdir)
     if not rc then
         return false, e:cat(re)
     end
@@ -676,7 +676,7 @@ local function sources(info, r, return_flags)
         local dirs = {"out", "init", "script", "build", "root", "env", "dep"}
         for _, v in pairs(dirs) do
             local d = e2lib.join(res.build_config.T, v)
-            local rc, re = e2lib.mkdir(d, "-p")
+            local rc, re = e2lib.mkdir_recursive(d)
             if not rc then
                 return false, e:cat(re)
             end
@@ -908,7 +908,7 @@ local function store_result(info, r, return_flags)
     if not rc then
         return false, e:cat(re)
     end
-    rc, re = e2lib.mkdir("result/files", "-p")
+    rc, re = e2lib.mkdir_recursive("result/files")
     if not rc then
         return false, e:cat(re)
     end
@@ -1079,7 +1079,7 @@ local function collect_project(info, r, return_flags)
     local e = err.new("providing project data to this build failed")
     -- project/proj/init/<files>
     local destdir = e2lib.join(res.build_config.T, "project/proj/init")
-    rc, re = e2lib.mkdir(destdir, "-p")
+    rc, re = e2lib.mkdir_recursive(destdir)
     if not rc then
         return false, e:cat(re)
     end
@@ -1117,7 +1117,7 @@ local function collect_project(info, r, return_flags)
     f:close()
     -- files from the project
     local destdir = e2lib.join(res.build_config.T, "project/.e2/bin")
-    rc, re = e2lib.mkdir(destdir, "-p")
+    rc, re = e2lib.mkdir_recursive(destdir)
     if not rc then
         return false, e:cat(re)
     end
@@ -1128,7 +1128,7 @@ local function collect_project(info, r, return_flags)
         e2lib.logf(3, "chroot group: %s", g)
         local grp = info.chroot.groups_byname[g]
         local destdir = e2lib.join( res.build_config.T, "project/chroot", g)
-        rc, re = e2lib.mkdir(destdir, "-p")
+        rc, re = e2lib.mkdir_recursive(destdir)
         if not rc then
             return false, e:cat(re)
         end
@@ -1175,7 +1175,7 @@ local function collect_project(info, r, return_flags)
         e2lib.logf(3, "licence: %s", l)
         local lic = info.licences[l]
         local destdir = e2lib.join(res.build_config.T, "project/licences", l)
-        rc, re = e2lib.mkdir(destdir, "-p")
+        rc, re = e2lib.mkdir_recursive(destdir)
         if not rc then
             return false, e:cat(re)
         end
@@ -1207,7 +1207,7 @@ local function collect_project(info, r, return_flags)
         end
         local destdir =
             e2lib.join(res.build_config.T, "project", e2tool.resultdir(n))
-        rc, re = e2lib.mkdir(destdir, "-p")
+        rc, re = e2lib.mkdir_recursive(destdir)
         if not rc then
             return false, e:cat(re)
         end
@@ -1261,7 +1261,7 @@ local function collect_project(info, r, return_flags)
         e2lib.logf(3, "source: %s", s)
         local destdir =
             e2lib.join(res.build_config.T, "project", e2tool.sourcedir(s))
-        rc, re = e2lib.mkdir(destdir, "-p")
+        rc, re = e2lib.mkdir_recursive(destdir)
         if not rc then
             return false, e:cat(re)
         end
index 3869de9b47b6261695d5c35776e7a114fa9c3ed9..ac844798b5ed789048c7379663e8645c94732081 100644 (file)
@@ -248,7 +248,7 @@ end
 
 --- Open debug logfile.
 local function opendebuglogfile(info)
-    local rc, re = e2lib.mkdir(info.root .. "/log", "-p")
+    local rc, re = e2lib.mkdir_recursive(e2lib.join(info.root, "log"))
     if not rc then
         local e = err.new("error making log directory")
         return false, e:cat(re)
index 89c89f5db878752a94b6f44e3e224144f067817c..c2cb0e3b9934b057f2aa556669b71b900a529883 100644 (file)
@@ -406,7 +406,7 @@ function cvs.toresult(info, sourcename, sourceset, directory)
     local sourcedir = string.format("%s/%s", directory, source)
     local archive = string.format("%s.tar.gz", sourcename)
     local fname  = string.format("%s/%s", directory, makefile)
-    rc, re = e2lib.mkdir(sourcedir, "-p")
+    rc, re = e2lib.mkdir_recursive(sourcedir)
     if not rc then
         return false, e:cat(re)
     end
@@ -441,7 +441,7 @@ function cvs.toresult(info, sourcename, sourceset, directory)
     local destdir = string.format("%s/licences", directory)
     local fname = string.format("%s/%s.licences", destdir, archive)
     local licence_list = table.concat(src.licences, "\n") .. "\n"
-    rc, re = e2lib.mkdir(destdir, "-p")
+    rc, re = e2lib.mkdir_recursive(destdir)
     if not rc then
         return false, e:cat(re)
     end
index 9f5a3a47e9406ac7bf592b1bfb284efe59c82d3b..59f77d33c11092bb7b68bbac1e3fe5e09f5835fd 100644 (file)
@@ -374,7 +374,7 @@ function files.prepare_source(info, sourcename, sourceset, buildpath)
         else
             if not symlink then
                 symlink = buildpath .. "/" .. sourcename
-                local rc, re = e2lib.mkdir(symlink, "-p")
+                rc, re = e2lib.mkdir_recursive(symlink)
                 if not rc then
                     return false, e:cat(re)
                 end
@@ -403,7 +403,7 @@ function files.prepare_source(info, sourcename, sourceset, buildpath)
                 destdir, destname = gen_dest_dir_name(buildpath, sourcename,
                     file.copy, file.location)
 
-                rc, re = e2lib.mkdir(destdir, "-p")
+                rc, re = e2lib.mkdir_recursive(destdir)
                 if not rc then
                     re = err.new("creating directory failed: %s", re)
                     return false, e:cat(re)
@@ -532,9 +532,13 @@ function files.toresult(info, sourcename, sourceset, directory)
         e2lib.logf(4, "export file: %s", file.location)
         local destdir = string.format("%s/%s", directory, source)
         local destname = nil
-        e2lib.mkdir(destdir, "-p")
-        local rc, re = info.cache:fetch_file(file.server,
-        file.location, destdir, destname, {})
+
+        rc, re = e2lib.mkdir_recursive(destdir)
+        if not rc then
+            return false, e:cat(re)
+        end
+        rc, re = info.cache:fetch_file(file.server, file.location, destdir,
+            destname, {})
         if not rc then
             return false, e:cat(re)
         end
@@ -621,7 +625,7 @@ function files.toresult(info, sourcename, sourceset, directory)
         local fname = string.format("%s/%s.licences", destdir,
         e2lib.basename(file.location))
         local licence_list = table.concat(file.licences, "\n") .. "\n"
-        rc, re = e2lib.mkdir(destdir, "-p")
+        rc, re = e2lib.mkdir_recursive(destdir)
         if not rc then
             return false, e:cat(re)
         end
index a915489891d83afef8a3b40b0ba1ab0738df6923..3236a58a7120eb9f34aab27d1fc12899e1430b61 100644 (file)
@@ -343,7 +343,7 @@ function git.prepare_source(info, sourcename, sourceset, buildpath)
             e2lib.warnf("WOTHER", "working copy seems empty")
         end
         local dir = string.format("%s/%s", buildpath, sourcename)
-        local rc, re = e2lib.mkdir(dir, "-p")
+        local rc, re = e2lib.mkdir_recursive(dir)
         if not rc then
             return false, re
         end
@@ -523,9 +523,14 @@ function git.toresult(info, sourcename, sourceset, directory)
     local makefile = "makefile"
     local source = "source"
     local sourcedir = string.format("%s/%s", directory, source)
-    e2lib.mkdir(sourcedir, "-p")
     local archive = string.format("%s.tar.gz", src.name)
     local cmd = nil
+
+    rc, re = e2lib.mkdir_recursive(sourcedir)
+    if not rc then
+        return false, e:cat(re)
+    end
+
     if sourceset == "tag" or sourceset == "branch" then
         local ref = generic_git.sourceset2ref(sourceset, src.branch, src.tag)
         -- git archive --format=tar <ref> | gzip > <tarball>
@@ -566,7 +571,7 @@ function git.toresult(info, sourcename, sourceset, directory)
     local destdir = string.format("%s/licences", directory)
     local fname = string.format("%s/%s.licences", destdir, archive)
     local licence_list = table.concat(src.licences, "\n") .. "\n"
-    rc, re = e2lib.mkdir(destdir, "-p")
+    rc, re = e2lib.mkdir_recursive(destdir)
     if not rc then
         return false, e:cat(re)
     end
index f2001e81b4efede3c822bf8bf30108d21c502d50..ac4385a68692ba3538e54b0eaf599a23aacd6a8f 100644 (file)
@@ -319,7 +319,7 @@ function svn.toresult(info, sourcename, sourceset, directory)
     local sourcedir = e2lib.join(directory, source)
     local archive = string.format("%s.tar.gz", sourcename)
     local fname  = e2lib.join(directory, makefile)
-    rc, re = e2lib.mkdir(sourcedir, "-p")
+    rc, re = e2lib.mkdir_recursive(sourcedir)
     if not rc then
         return false, e:cat(re)
     end
@@ -354,7 +354,7 @@ function svn.toresult(info, sourcename, sourceset, directory)
     local destdir = e2lib.join(directory, "licences")
     local fname = string.format("%s/%s.licences", destdir, archive)
     local licence_list = table.concat(src.licences, "\n") .. "\n"
-    rc, re = e2lib.mkdir(destdir, "-p")
+    rc, re = e2lib.mkdir_recursive(destdir)
     if not rc then
         return false, e:cat(re)
     end