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")
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
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
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
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)
{
{ "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 },
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
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)
}
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
}
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
--- 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)
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
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
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
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)
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
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
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
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>
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
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
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