summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSaikari <[email protected]>2026-02-05 21:35:26 +0300
committerSaikari <[email protected]>2026-02-05 21:35:26 +0300
commit34a21b3d628b695491815da3f0c465a96e98fd30 (patch)
tree73667903553a54f2c4862184aebcb891982392cc
parent377a3e21381b4db9f05c81478189337e7713a18e (diff)
swap CRLF to LF?
-rw-r--r--xmake/core/sandbox/modules/os.lua1298
1 files changed, 649 insertions, 649 deletions
diff --git a/xmake/core/sandbox/modules/os.lua b/xmake/core/sandbox/modules/os.lua
index 58b1ed836..77c591451 100644
--- a/xmake/core/sandbox/modules/os.lua
+++ b/xmake/core/sandbox/modules/os.lua
@@ -1,649 +1,649 @@
---!A cross-platform build utility based on Lua
---
--- Licensed under the Apache License, Version 2.0 (the "License");
--- you may not use this file except in compliance with the License.
--- You may obtain a copy of the License at
---
--- http://www.apache.org/licenses/LICENSE-2.0
---
--- Unless required by applicable law or agreed to in writing, software
--- distributed under the License is distributed on an "AS IS" BASIS,
--- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
--- See the License for the specific language governing permissions and
--- limitations under the License.
---
--- Copyright (C) 2015-present, Xmake Open Source Community.
---
--- @author ruki
--- @file os.lua
---
-
--- load modules
-local io = require("base/io")
-local os = require("base/os")
-local path = require("base/path")
-local utils = require("base/utils")
-local xmake = require("base/xmake")
-local option = require("base/option")
-local semver = require("base/semver")
-local scheduler = require("base/scheduler")
-local sandbox = require("sandbox/sandbox")
-local vformat = require("sandbox/modules/vformat")
-
--- define module
-local sandbox_os = sandbox_os or {}
-
--- inherit some builtin interfaces
-sandbox_os.shell = os.shell
-sandbox_os.term = os.term
-sandbox_os.host = os.host
-sandbox_os.arch = os.arch
-sandbox_os.subhost = os.subhost
-sandbox_os.subarch = os.subarch
-sandbox_os.is_host = os.is_host
-sandbox_os.is_arch = os.is_arch
-sandbox_os.is_subhost = os.is_subhost
-sandbox_os.is_subarch = os.is_subarch
-sandbox_os.syserror = os.syserror
-sandbox_os.strerror = os.strerror
-sandbox_os.exit = os.exit
-sandbox_os.atexit = os.atexit
-sandbox_os.date = os.date
-sandbox_os.time = os.time
-sandbox_os.args = os.args
-sandbox_os.args = os.args
-sandbox_os.argv = os.argv
-sandbox_os.mtime = os.mtime
-sandbox_os.raise = os.raise
-sandbox_os.fscase = os.fscase
-sandbox_os.isroot = os.isroot
-sandbox_os.mclock = os.mclock
-sandbox_os.nuldev = os.nuldev
-sandbox_os.getenv = os.getenv
-sandbox_os.setenv = os.setenv
-sandbox_os.addenv = os.addenv
-sandbox_os.setenvp = os.setenvp
-sandbox_os.addenvp = os.addenvp
-sandbox_os.getenvs = os.getenvs
-sandbox_os.setenvs = os.setenvs
-sandbox_os.addenvs = os.addenvs
-sandbox_os.joinenvs = os.joinenvs
-sandbox_os.pbpaste = os.pbpaste
-sandbox_os.pbcopy = os.pbcopy
-sandbox_os.cpuinfo = os.cpuinfo
-sandbox_os.meminfo = os.meminfo
-sandbox_os.default_njob = os.default_njob
-sandbox_os.emptydir = os.emptydir
-sandbox_os.filesize = os.filesize
-sandbox_os.features = os.features
-sandbox_os.workingdir = os.workingdir
-sandbox_os.programdir = os.programdir
-sandbox_os.programfile = os.programfile
-sandbox_os.projectdir = os.projectdir
-sandbox_os.projectfile = os.projectfile
-sandbox_os.getwinsize = os.getwinsize
-sandbox_os.getpid = os.getpid
-
--- syserror code
-sandbox_os.SYSERR_UNKNOWN = os.SYSERR_UNKNOWN
-sandbox_os.SYSERR_NONE = os.SYSERR_NONE
-sandbox_os.SYSERR_NOT_PERM = os.SYSERR_NOT_PERM
-sandbox_os.SYSERR_NOT_FILEDIR = os.SYSERR_NOT_FILEDIR
-sandbox_os.SYSERR_NOT_ACCESS = os.SYSERR_NOT_ACCESS
-
--- copy file or directory
-function sandbox_os.cp(srcpath, dstpath, opt)
- assert(srcpath and dstpath)
- srcpath = tostring(srcpath)
- dstpath = tostring(dstpath)
- local ok, errors = os.cp(vformat(srcpath), vformat(dstpath), opt)
- if not ok then
- os.raise(errors)
- end
-end
-
--- move file or directory
-function sandbox_os.mv(srcpath, dstpath, opt)
- assert(srcpath and dstpath)
- srcpath = tostring(srcpath)
- dstpath = tostring(dstpath)
- local ok, errors = os.mv(vformat(srcpath), vformat(dstpath), opt)
- if not ok then
- os.raise(errors)
- end
-end
-
--- remove files or directories
-function sandbox_os.rm(filepath, opt)
- assert(filepath)
- filepath = tostring(filepath)
- local ok, errors = os.rm(vformat(filepath), opt)
- if not ok then
- os.raise(errors)
- end
-end
-
--- link file or directory to the new symfile
-function sandbox_os.ln(srcpath, dstpath, opt)
- assert(srcpath and dstpath)
- srcpath = tostring(srcpath)
- dstpath = tostring(dstpath)
- local ok, errors = os.ln(vformat(srcpath), vformat(dstpath), opt)
- if not ok then
- os.raise(errors)
- end
-end
-
--- copy file or directory with the verbose info
-function sandbox_os.vcp(srcpath, dstpath, opt)
- assert(srcpath and dstpath)
- if option.get("verbose") then
- utils.cprint("${dim}> copy %s to %s", srcpath, dstpath)
- end
- return sandbox_os.cp(srcpath, dstpath, opt)
-end
-
--- move file or directory with the verbose info
-function sandbox_os.vmv(srcpath, dstpath, opt)
- assert(srcpath and dstpath)
- if option.get("verbose") then
- utils.cprint("${dim}> move %s to %s", srcpath, dstpath)
- end
- return sandbox_os.mv(srcpath, dstpath, opt)
-end
-
--- remove file or directory with the verbose info
-function sandbox_os.vrm(filepath, opt)
- assert(filepath)
- if option.get("verbose") then
- utils.cprint("${dim}> remove %s", filepath)
- end
- return sandbox_os.rm(filepath, opt)
-end
-
--- link file or directory with the verbose info
-function sandbox_os.vln(srcpath, dstpath, opt)
- assert(srcpath and dstpath)
- if option.get("verbose") then
- utils.cprint("${dim}> link %s to %s", srcpath, dstpath)
- end
- return sandbox_os.ln(srcpath, dstpath, opt)
-end
-
--- try to copy file or directory
-function sandbox_os.trycp(srcpath, dstpath, opt)
- assert(srcpath and dstpath)
- return os.cp(vformat(srcpath), vformat(dstpath), opt)
-end
-
--- try to move file or directory
-function sandbox_os.trymv(srcpath, dstpath, opt)
- assert(srcpath and dstpath)
- return os.mv(vformat(srcpath), vformat(dstpath), opt)
-end
-
--- try to remove files or directories
-function sandbox_os.tryrm(filepath, opt)
- assert(filepath)
- return os.rm(vformat(filepath), opt)
-end
-
--- change to directory
-function sandbox_os.cd(dir)
-
- -- check
- assert(dir)
-
- -- format it first
- dir = vformat(dir)
-
- -- enter this directory
- local oldir, errors = os.cd(dir)
- if not oldir then
- os.raise(errors)
- end
-
- -- ok
- return oldir
-end
-
--- touch file or directory
-function sandbox_os.touch(filepath, opt)
- assert(filepath)
- local ok, errors = os.touch(vformat(filepath), opt)
- if not ok then
- os.raise(errors)
- end
-end
-
--- create directories
-function sandbox_os.mkdir(dir)
- assert(dir)
- local ok, errors = os.mkdir(vformat(dir))
- if not ok then
- os.raise(errors)
- end
-end
-
--- remove directories
-function sandbox_os.rmdir(dir, opt)
- assert(dir)
- local ok, errors = os.rmdir(vformat(dir), opt)
- if not ok then
- os.raise(errors)
- end
-end
-
--- get the current directory
-function sandbox_os.curdir()
- return assert(os.curdir())
-end
-
--- get the temporary directory
-function sandbox_os.tmpdir(opt)
- return assert(os.tmpdir(opt))
-end
-
--- get the temporary file
-function sandbox_os.tmpfile(key, opt)
- return assert(os.tmpfile(key, opt))
-end
-
--- get the script directory
-function sandbox_os.scriptdir()
- local instance = sandbox.instance()
- local rootdir = instance:rootdir()
- assert(rootdir)
- return rootdir
-end
-
--- quietly run command
-function sandbox_os.run(cmd, ...)
- cmd = vformat(cmd, ...)
- local ok, errors = os.run(cmd)
- if not ok then
- os.raise(errors)
- end
-end
-
--- quietly run command with arguments list
-function sandbox_os.runv(program, argv, opt)
- program = vformat(program)
- local ok, errors = os.runv(program, argv, opt)
- if not ok then
- os.raise(errors)
- end
-end
-
--- quietly run command and echo verbose info if [-v|--verbose] option is enabled
-function sandbox_os.vrun(cmd, ...)
- if option.get("verbose") then
- print(vformat(cmd, ...))
- end
- (option.get("verbose") and sandbox_os.exec or sandbox_os.run)(cmd, ...)
-end
-
--- quietly run command with arguments list and echo verbose info if [-v|--verbose] option is enabled
-function sandbox_os.vrunv(program, argv, opt)
- if option.get("verbose") then
- print(vformat(program) .. " " .. sandbox_os.args(argv or {}))
- end
- if not (opt and opt.dryrun) then
- (option.get("verbose") and sandbox_os.execv or sandbox_os.runv)(program, argv, opt)
- end
-end
-
--- run command and return output and error data
-function sandbox_os.iorun(cmd, ...)
- cmd = vformat(cmd, ...)
- local ok, outdata, errdata, errors = os.iorun(cmd)
- if not ok then
- if not errors then
- errors = errdata or ""
- if #errors:trim() == 0 then
- errors = outdata or ""
- end
- end
- os.raise({errors = errors, stderr = errdata, stdout = outdata})
- end
- return outdata, errdata
-end
-
--- run command and return output and error data
-function sandbox_os.iorunv(program, argv, opt)
- program = vformat(program)
- local ok, outdata, errdata, errors = os.iorunv(program, argv, opt)
- if not ok then
- if not errors then
- errors = errdata or ""
- if #errors:trim() == 0 then
- errors = outdata or ""
- end
- end
- os.raise({errors = errors, stderr = errdata, stdout = outdata})
- end
- return outdata, errdata
-end
-
--- execute command
-function sandbox_os.exec(cmd, ...)
- cmd = vformat(cmd, ...)
- local ok, errors = os.exec(cmd)
- if ok ~= 0 then
- if ok ~= nil then
- errors = string.format("exec(%s) failed(%d)", cmd, ok)
- else
- errors = string.format("cannot exec(%s), %s", cmd, errors and errors or "unknown reason")
- end
- os.raise(errors)
- end
-end
-
--- execute command with arguments list
--- get missing dlls
-local function _get_missing_dlls(program)
- local missing = {}
- local program_dir = path.directory(program)
- local pathenv = os.getenv("PATH") or ""
- local paths = path.splitenv(pathenv)
- table.insert(paths, 1, program_dir)
-
- local function _find_dll(name)
- for _, p in ipairs(paths) do
- if os.isfile(path.join(p, name)) then
- return true
- end
- end
- return false
- end
-
- local imports = {}
- local file = io.open(program, "rb")
- if file then
- local function read_uint16()
- local str = file:read(2)
- if not str then return 0 end
- local b1, b2 = string.byte(str, 1, 2)
- return b1 + b2 * 256
- end
- local function read_uint32()
- local str = file:read(4)
- if not str then return 0 end
- local b1, b2, b3, b4 = string.byte(str, 1, 4)
- return b1 + b2 * 256 + b3 * 65536 + b4 * 16777216
- end
-
- local mz = file:read(2)
- if mz == "MZ" then
- file:seek("set", 0x3C)
- local e_lfanew = read_uint32()
- file:seek("set", e_lfanew)
- if file:read(4) == "PE\0\0" then
- -- file header
- file:seek("cur", 2) -- Machine (2)
- local number_of_sections = read_uint16()
- file:seek("cur", 12) -- TimeDateStamp(4) + PointerToSymbolTable(4) + NumberOfSymbols(4)
- local size_of_optional_header = read_uint16()
- file:seek("cur", 2) -- Characteristics (2)
-
- -- optional header
- local magic = read_uint16()
- local is_pe64 = (magic == 0x20b)
-
- -- skip standard fields and some windows fields to reach DataDirectories
- -- Standard(24/22) + Windows(68/88)
- -- PE32: 24 + 68 = 92 bytes from magic to DataDirectories
- -- PE32+: 24 + 88 = 112 bytes from magic to DataDirectories
- -- Minus magic(2) that we just read
- local skip = (is_pe64 and (24 + 88 - 2) or (24 + 68 - 2))
- file:seek("cur", skip)
-
- -- Data Directories
- -- Export Table (8)
- file:seek("cur", 8)
-
- -- Import Table
- local import_rva = read_uint32()
- local import_size = read_uint32()
-
- if import_rva > 0 then
- -- Section Headers
- file:seek("set", e_lfanew + 4 + 20 + size_of_optional_header)
- local sections = {}
- for i = 1, number_of_sections do
- local s = {}
- file:seek("cur", 8) -- name
- s.vsize = read_uint32()
- s.vaddr = read_uint32()
- s.rawsize = read_uint32()
- s.rawaddr = read_uint32()
- file:seek("cur", 16)
- table.insert(sections, s)
- end
-
- local function rva_to_offset(rva)
- for _, s in ipairs(sections) do
- if rva >= s.vaddr and rva < s.vaddr + s.vsize then
- return s.rawaddr + (rva - s.vaddr)
- end
- end
- return nil
- end
-
- local import_offset = rva_to_offset(import_rva)
- if import_offset then
- file:seek("set", import_offset)
- while true do
- local original_ft = read_uint32() -- OriginalFirstThunk
- local time_date = read_uint32()
- local forwarder = read_uint32()
- local name_rva = read_uint32()
- local first_thunk = read_uint32()
-
- if original_ft == 0 and name_rva == 0 then break end
-
- if name_rva > 0 then
- local name_offset = rva_to_offset(name_rva)
- if name_offset then
- local save_pos = file:seek()
- file:seek("set", name_offset)
- local chars = {}
- while true do
- local b = string.byte(file:read(1))
- if b == 0 then break end
- table.insert(chars, string.char(b))
- end
- table.insert(imports, table.concat(chars))
- file:seek("set", save_pos)
- end
- end
- end
- end
- end
- end
- end
- file:close()
- end
-
- for _, dll in ipairs(imports) do
- if not _find_dll(dll) then
- table.insert(missing, dll)
- end
- end
- return missing
-end
-
-function sandbox_os.execv(program, argv, opt)
-
- -- make program
- program = vformat(program)
-
- -- flush io buffer first for fixing redirect io output order
- --
- -- e.g.
- --
- -- xmake run > /tmp/a
- -- print("xxx1")
- -- os.exec("echo xxx2")
- --
- -- cat /tmp/a
- -- xxx2
- -- xxx1
- --
- io.flush()
-
- -- run it
- opt = opt or {}
- local ok, errors = os.execv(program, argv, opt)
- if ok ~= 0 and not opt.try then
-
- -- get command
- local cmd = program
- if argv then
- cmd = cmd .. " " .. os.args(argv)
- end
-
- -- get errors
- if ok ~= nil then
- if ok == -1073741515 then -- 0xC0000135
- local missing_dlls = _get_missing_dlls(program)
- if #missing_dlls > 0 then
- errors = string.format("execv(%s) failed(%d): system error 0xC0000135 (STATUS_DLL_NOT_FOUND).\nThe application failed to start because the following DLLs were not found:\n - %s\nPlease check your PATH environment variable or copy the missing DLLs to the executable directory.", cmd, ok, table.concat(missing_dlls, "\n - "))
- else
- errors = string.format("execv(%s) failed(%d): system error 0xC0000135 (STATUS_DLL_NOT_FOUND).\nThe application failed to start because a dependent DLL was not found.\nPlease check your PATH environment variable or copy the missing DLL to the executable directory.", cmd, ok)
- end
- else
- errors = string.format("execv(%s) failed(%d)", cmd, ok)
- end
- else
- errors = string.format("cannot execv(%s), %s", cmd, errors and errors or "unknown reason")
- end
- os.raise(errors)
- end
-
- -- we need return results if opt.try is enabled
- return ok, errors
-end
-
--- execute command and echo verbose info if [-v|--verbose] option is enabled
-function sandbox_os.vexec(cmd, ...)
-
- -- echo command
- if option.get("verbose") then
- utils.cprint("${color.dump.string}" .. vformat(cmd, ...))
- end
-
- -- run it
- sandbox_os.exec(cmd, ...)
-end
-
--- execute command with arguments list and echo verbose info if [-v|--verbose] option is enabled
-function sandbox_os.vexecv(program, argv, opt)
-
- -- echo command
- if option.get("verbose") then
- utils.cprint("${color.dump.string}" .. vformat(program) .. " " .. sandbox_os.args(argv))
- end
-
- -- run it
- if not (opt and opt.dryrun) then
- return sandbox_os.execv(program, argv, opt)
- else
- return 0
- end
-end
-
--- match files or directories
-function sandbox_os.match(pattern, mode, opt)
- return os.match(vformat(tostring(pattern)), mode, opt)
-end
-
--- match directories
-function sandbox_os.dirs(pattern, opt)
- return os.dirs(vformat(tostring(pattern)), opt)
-end
-
--- match files
-function sandbox_os.files(pattern, opt)
- return os.files(vformat(tostring(pattern)), opt)
-end
-
--- match files and directories
-function sandbox_os.filedirs(pattern, opt)
- return os.filedirs(vformat(tostring(pattern)), opt)
-end
-
--- is directory?
-function sandbox_os.isdir(dirpath)
- assert(dirpath)
- dirpath = tostring(dirpath)
- return os.isdir(vformat(dirpath))
-end
-
--- is file?
-function sandbox_os.isfile(filepath)
- assert(filepath)
- filepath = tostring(filepath)
- return os.isfile(vformat(filepath))
-end
-
--- is symlink?
-function sandbox_os.islink(filepath)
- assert(filepath)
- filepath = tostring(filepath)
- return os.islink(vformat(filepath))
-end
-
--- is execute program?
-function sandbox_os.isexec(filepath)
- assert(filepath)
- filepath = tostring(filepath)
- return os.isexec(vformat(filepath))
-end
-
--- exists file or directory?
-function sandbox_os.exists(filedir)
- assert(filedir)
- filedir = tostring(filedir)
- return os.exists(vformat(filedir))
-end
-
--- read the content of symlink
-function sandbox_os.readlink(symlink)
- local result = os.readlink(tostring(symlink))
- if not result then
- os.raise("cannot read link(%s)", symlink)
- end
- return result
-end
-
--- sleep (support in coroutine)
-function sandbox_os.sleep(ms)
- if scheduler:co_running() then
- local ok, errors = scheduler:co_sleep(ms)
- if not ok then
- raise(errors)
- end
- else
- os.sleep(ms)
- end
-end
-
--- get xmake version
-function sandbox_os.xmakever()
-
- -- fill cache
- if sandbox_os._XMAKEVER == nil then
- -- get xmakever
- local xmakever = semver.new(xmake._VERSION_SHORT)
- -- save to cache
- sandbox_os._XMAKEVER = xmakever or false
- end
-
- -- done
- return sandbox_os._XMAKEVER or nil
-end
-
--- return module
-return sandbox_os
-
+--!A cross-platform build utility based on Lua
+--
+-- Licensed under the Apache License, Version 2.0 (the "License");
+-- you may not use this file except in compliance with the License.
+-- You may obtain a copy of the License at
+--
+-- http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+--
+-- Copyright (C) 2015-present, Xmake Open Source Community.
+--
+-- @author ruki
+-- @file os.lua
+--
+
+-- load modules
+local io = require("base/io")
+local os = require("base/os")
+local path = require("base/path")
+local utils = require("base/utils")
+local xmake = require("base/xmake")
+local option = require("base/option")
+local semver = require("base/semver")
+local scheduler = require("base/scheduler")
+local sandbox = require("sandbox/sandbox")
+local vformat = require("sandbox/modules/vformat")
+
+-- define module
+local sandbox_os = sandbox_os or {}
+
+-- inherit some builtin interfaces
+sandbox_os.shell = os.shell
+sandbox_os.term = os.term
+sandbox_os.host = os.host
+sandbox_os.arch = os.arch
+sandbox_os.subhost = os.subhost
+sandbox_os.subarch = os.subarch
+sandbox_os.is_host = os.is_host
+sandbox_os.is_arch = os.is_arch
+sandbox_os.is_subhost = os.is_subhost
+sandbox_os.is_subarch = os.is_subarch
+sandbox_os.syserror = os.syserror
+sandbox_os.strerror = os.strerror
+sandbox_os.exit = os.exit
+sandbox_os.atexit = os.atexit
+sandbox_os.date = os.date
+sandbox_os.time = os.time
+sandbox_os.args = os.args
+sandbox_os.args = os.args
+sandbox_os.argv = os.argv
+sandbox_os.mtime = os.mtime
+sandbox_os.raise = os.raise
+sandbox_os.fscase = os.fscase
+sandbox_os.isroot = os.isroot
+sandbox_os.mclock = os.mclock
+sandbox_os.nuldev = os.nuldev
+sandbox_os.getenv = os.getenv
+sandbox_os.setenv = os.setenv
+sandbox_os.addenv = os.addenv
+sandbox_os.setenvp = os.setenvp
+sandbox_os.addenvp = os.addenvp
+sandbox_os.getenvs = os.getenvs
+sandbox_os.setenvs = os.setenvs
+sandbox_os.addenvs = os.addenvs
+sandbox_os.joinenvs = os.joinenvs
+sandbox_os.pbpaste = os.pbpaste
+sandbox_os.pbcopy = os.pbcopy
+sandbox_os.cpuinfo = os.cpuinfo
+sandbox_os.meminfo = os.meminfo
+sandbox_os.default_njob = os.default_njob
+sandbox_os.emptydir = os.emptydir
+sandbox_os.filesize = os.filesize
+sandbox_os.features = os.features
+sandbox_os.workingdir = os.workingdir
+sandbox_os.programdir = os.programdir
+sandbox_os.programfile = os.programfile
+sandbox_os.projectdir = os.projectdir
+sandbox_os.projectfile = os.projectfile
+sandbox_os.getwinsize = os.getwinsize
+sandbox_os.getpid = os.getpid
+
+-- syserror code
+sandbox_os.SYSERR_UNKNOWN = os.SYSERR_UNKNOWN
+sandbox_os.SYSERR_NONE = os.SYSERR_NONE
+sandbox_os.SYSERR_NOT_PERM = os.SYSERR_NOT_PERM
+sandbox_os.SYSERR_NOT_FILEDIR = os.SYSERR_NOT_FILEDIR
+sandbox_os.SYSERR_NOT_ACCESS = os.SYSERR_NOT_ACCESS
+
+-- copy file or directory
+function sandbox_os.cp(srcpath, dstpath, opt)
+ assert(srcpath and dstpath)
+ srcpath = tostring(srcpath)
+ dstpath = tostring(dstpath)
+ local ok, errors = os.cp(vformat(srcpath), vformat(dstpath), opt)
+ if not ok then
+ os.raise(errors)
+ end
+end
+
+-- move file or directory
+function sandbox_os.mv(srcpath, dstpath, opt)
+ assert(srcpath and dstpath)
+ srcpath = tostring(srcpath)
+ dstpath = tostring(dstpath)
+ local ok, errors = os.mv(vformat(srcpath), vformat(dstpath), opt)
+ if not ok then
+ os.raise(errors)
+ end
+end
+
+-- remove files or directories
+function sandbox_os.rm(filepath, opt)
+ assert(filepath)
+ filepath = tostring(filepath)
+ local ok, errors = os.rm(vformat(filepath), opt)
+ if not ok then
+ os.raise(errors)
+ end
+end
+
+-- link file or directory to the new symfile
+function sandbox_os.ln(srcpath, dstpath, opt)
+ assert(srcpath and dstpath)
+ srcpath = tostring(srcpath)
+ dstpath = tostring(dstpath)
+ local ok, errors = os.ln(vformat(srcpath), vformat(dstpath), opt)
+ if not ok then
+ os.raise(errors)
+ end
+end
+
+-- copy file or directory with the verbose info
+function sandbox_os.vcp(srcpath, dstpath, opt)
+ assert(srcpath and dstpath)
+ if option.get("verbose") then
+ utils.cprint("${dim}> copy %s to %s", srcpath, dstpath)
+ end
+ return sandbox_os.cp(srcpath, dstpath, opt)
+end
+
+-- move file or directory with the verbose info
+function sandbox_os.vmv(srcpath, dstpath, opt)
+ assert(srcpath and dstpath)
+ if option.get("verbose") then
+ utils.cprint("${dim}> move %s to %s", srcpath, dstpath)
+ end
+ return sandbox_os.mv(srcpath, dstpath, opt)
+end
+
+-- remove file or directory with the verbose info
+function sandbox_os.vrm(filepath, opt)
+ assert(filepath)
+ if option.get("verbose") then
+ utils.cprint("${dim}> remove %s", filepath)
+ end
+ return sandbox_os.rm(filepath, opt)
+end
+
+-- link file or directory with the verbose info
+function sandbox_os.vln(srcpath, dstpath, opt)
+ assert(srcpath and dstpath)
+ if option.get("verbose") then
+ utils.cprint("${dim}> link %s to %s", srcpath, dstpath)
+ end
+ return sandbox_os.ln(srcpath, dstpath, opt)
+end
+
+-- try to copy file or directory
+function sandbox_os.trycp(srcpath, dstpath, opt)
+ assert(srcpath and dstpath)
+ return os.cp(vformat(srcpath), vformat(dstpath), opt)
+end
+
+-- try to move file or directory
+function sandbox_os.trymv(srcpath, dstpath, opt)
+ assert(srcpath and dstpath)
+ return os.mv(vformat(srcpath), vformat(dstpath), opt)
+end
+
+-- try to remove files or directories
+function sandbox_os.tryrm(filepath, opt)
+ assert(filepath)
+ return os.rm(vformat(filepath), opt)
+end
+
+-- change to directory
+function sandbox_os.cd(dir)
+
+ -- check
+ assert(dir)
+
+ -- format it first
+ dir = vformat(dir)
+
+ -- enter this directory
+ local oldir, errors = os.cd(dir)
+ if not oldir then
+ os.raise(errors)
+ end
+
+ -- ok
+ return oldir
+end
+
+-- touch file or directory
+function sandbox_os.touch(filepath, opt)
+ assert(filepath)
+ local ok, errors = os.touch(vformat(filepath), opt)
+ if not ok then
+ os.raise(errors)
+ end
+end
+
+-- create directories
+function sandbox_os.mkdir(dir)
+ assert(dir)
+ local ok, errors = os.mkdir(vformat(dir))
+ if not ok then
+ os.raise(errors)
+ end
+end
+
+-- remove directories
+function sandbox_os.rmdir(dir, opt)
+ assert(dir)
+ local ok, errors = os.rmdir(vformat(dir), opt)
+ if not ok then
+ os.raise(errors)
+ end
+end
+
+-- get the current directory
+function sandbox_os.curdir()
+ return assert(os.curdir())
+end
+
+-- get the temporary directory
+function sandbox_os.tmpdir(opt)
+ return assert(os.tmpdir(opt))
+end
+
+-- get the temporary file
+function sandbox_os.tmpfile(key, opt)
+ return assert(os.tmpfile(key, opt))
+end
+
+-- get the script directory
+function sandbox_os.scriptdir()
+ local instance = sandbox.instance()
+ local rootdir = instance:rootdir()
+ assert(rootdir)
+ return rootdir
+end
+
+-- quietly run command
+function sandbox_os.run(cmd, ...)
+ cmd = vformat(cmd, ...)
+ local ok, errors = os.run(cmd)
+ if not ok then
+ os.raise(errors)
+ end
+end
+
+-- quietly run command with arguments list
+function sandbox_os.runv(program, argv, opt)
+ program = vformat(program)
+ local ok, errors = os.runv(program, argv, opt)
+ if not ok then
+ os.raise(errors)
+ end
+end
+
+-- quietly run command and echo verbose info if [-v|--verbose] option is enabled
+function sandbox_os.vrun(cmd, ...)
+ if option.get("verbose") then
+ print(vformat(cmd, ...))
+ end
+ (option.get("verbose") and sandbox_os.exec or sandbox_os.run)(cmd, ...)
+end
+
+-- quietly run command with arguments list and echo verbose info if [-v|--verbose] option is enabled
+function sandbox_os.vrunv(program, argv, opt)
+ if option.get("verbose") then
+ print(vformat(program) .. " " .. sandbox_os.args(argv or {}))
+ end
+ if not (opt and opt.dryrun) then
+ (option.get("verbose") and sandbox_os.execv or sandbox_os.runv)(program, argv, opt)
+ end
+end
+
+-- run command and return output and error data
+function sandbox_os.iorun(cmd, ...)
+ cmd = vformat(cmd, ...)
+ local ok, outdata, errdata, errors = os.iorun(cmd)
+ if not ok then
+ if not errors then
+ errors = errdata or ""
+ if #errors:trim() == 0 then
+ errors = outdata or ""
+ end
+ end
+ os.raise({errors = errors, stderr = errdata, stdout = outdata})
+ end
+ return outdata, errdata
+end
+
+-- run command and return output and error data
+function sandbox_os.iorunv(program, argv, opt)
+ program = vformat(program)
+ local ok, outdata, errdata, errors = os.iorunv(program, argv, opt)
+ if not ok then
+ if not errors then
+ errors = errdata or ""
+ if #errors:trim() == 0 then
+ errors = outdata or ""
+ end
+ end
+ os.raise({errors = errors, stderr = errdata, stdout = outdata})
+ end
+ return outdata, errdata
+end
+
+-- execute command
+function sandbox_os.exec(cmd, ...)
+ cmd = vformat(cmd, ...)
+ local ok, errors = os.exec(cmd)
+ if ok ~= 0 then
+ if ok ~= nil then
+ errors = string.format("exec(%s) failed(%d)", cmd, ok)
+ else
+ errors = string.format("cannot exec(%s), %s", cmd, errors and errors or "unknown reason")
+ end
+ os.raise(errors)
+ end
+end
+
+-- execute command with arguments list
+-- get missing dlls
+local function _get_missing_dlls(program)
+ local missing = {}
+ local program_dir = path.directory(program)
+ local pathenv = os.getenv("PATH") or ""
+ local paths = path.splitenv(pathenv)
+ table.insert(paths, 1, program_dir)
+
+ local function _find_dll(name)
+ for _, p in ipairs(paths) do
+ if os.isfile(path.join(p, name)) then
+ return true
+ end
+ end
+ return false
+ end
+
+ local imports = {}
+ local file = io.open(program, "rb")
+ if file then
+ local function read_uint16()
+ local str = file:read(2)
+ if not str then return 0 end
+ local b1, b2 = string.byte(str, 1, 2)
+ return b1 + b2 * 256
+ end
+ local function read_uint32()
+ local str = file:read(4)
+ if not str then return 0 end
+ local b1, b2, b3, b4 = string.byte(str, 1, 4)
+ return b1 + b2 * 256 + b3 * 65536 + b4 * 16777216
+ end
+
+ local mz = file:read(2)
+ if mz == "MZ" then
+ file:seek("set", 0x3C)
+ local e_lfanew = read_uint32()
+ file:seek("set", e_lfanew)
+ if file:read(4) == "PE\0\0" then
+ -- file header
+ file:seek("cur", 2) -- Machine (2)
+ local number_of_sections = read_uint16()
+ file:seek("cur", 12) -- TimeDateStamp(4) + PointerToSymbolTable(4) + NumberOfSymbols(4)
+ local size_of_optional_header = read_uint16()
+ file:seek("cur", 2) -- Characteristics (2)
+
+ -- optional header
+ local magic = read_uint16()
+ local is_pe64 = (magic == 0x20b)
+
+ -- skip standard fields and some windows fields to reach DataDirectories
+ -- Standard(24/22) + Windows(68/88)
+ -- PE32: 24 + 68 = 92 bytes from magic to DataDirectories
+ -- PE32+: 24 + 88 = 112 bytes from magic to DataDirectories
+ -- Minus magic(2) that we just read
+ local skip = (is_pe64 and (24 + 88 - 2) or (24 + 68 - 2))
+ file:seek("cur", skip)
+
+ -- Data Directories
+ -- Export Table (8)
+ file:seek("cur", 8)
+
+ -- Import Table
+ local import_rva = read_uint32()
+ local import_size = read_uint32()
+
+ if import_rva > 0 then
+ -- Section Headers
+ file:seek("set", e_lfanew + 4 + 20 + size_of_optional_header)
+ local sections = {}
+ for i = 1, number_of_sections do
+ local s = {}
+ file:seek("cur", 8) -- name
+ s.vsize = read_uint32()
+ s.vaddr = read_uint32()
+ s.rawsize = read_uint32()
+ s.rawaddr = read_uint32()
+ file:seek("cur", 16)
+ table.insert(sections, s)
+ end
+
+ local function rva_to_offset(rva)
+ for _, s in ipairs(sections) do
+ if rva >= s.vaddr and rva < s.vaddr + s.vsize then
+ return s.rawaddr + (rva - s.vaddr)
+ end
+ end
+ return nil
+ end
+
+ local import_offset = rva_to_offset(import_rva)
+ if import_offset then
+ file:seek("set", import_offset)
+ while true do
+ local original_ft = read_uint32() -- OriginalFirstThunk
+ local time_date = read_uint32()
+ local forwarder = read_uint32()
+ local name_rva = read_uint32()
+ local first_thunk = read_uint32()
+
+ if original_ft == 0 and name_rva == 0 then break end
+
+ if name_rva > 0 then
+ local name_offset = rva_to_offset(name_rva)
+ if name_offset then
+ local save_pos = file:seek()
+ file:seek("set", name_offset)
+ local chars = {}
+ while true do
+ local b = string.byte(file:read(1))
+ if b == 0 then break end
+ table.insert(chars, string.char(b))
+ end
+ table.insert(imports, table.concat(chars))
+ file:seek("set", save_pos)
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+ file:close()
+ end
+
+ for _, dll in ipairs(imports) do
+ if not _find_dll(dll) then
+ table.insert(missing, dll)
+ end
+ end
+ return missing
+end
+
+function sandbox_os.execv(program, argv, opt)
+
+ -- make program
+ program = vformat(program)
+
+ -- flush io buffer first for fixing redirect io output order
+ --
+ -- e.g.
+ --
+ -- xmake run > /tmp/a
+ -- print("xxx1")
+ -- os.exec("echo xxx2")
+ --
+ -- cat /tmp/a
+ -- xxx2
+ -- xxx1
+ --
+ io.flush()
+
+ -- run it
+ opt = opt or {}
+ local ok, errors = os.execv(program, argv, opt)
+ if ok ~= 0 and not opt.try then
+
+ -- get command
+ local cmd = program
+ if argv then
+ cmd = cmd .. " " .. os.args(argv)
+ end
+
+ -- get errors
+ if ok ~= nil then
+ if ok == -1073741515 then -- 0xC0000135
+ local missing_dlls = _get_missing_dlls(program)
+ if #missing_dlls > 0 then
+ errors = string.format("execv(%s) failed(%d): system error 0xC0000135 (STATUS_DLL_NOT_FOUND).\nThe application failed to start because the following DLLs were not found:\n - %s\nPlease check your PATH environment variable or copy the missing DLLs to the executable directory.", cmd, ok, table.concat(missing_dlls, "\n - "))
+ else
+ errors = string.format("execv(%s) failed(%d): system error 0xC0000135 (STATUS_DLL_NOT_FOUND).\nThe application failed to start because a dependent DLL was not found.\nPlease check your PATH environment variable or copy the missing DLL to the executable directory.", cmd, ok)
+ end
+ else
+ errors = string.format("execv(%s) failed(%d)", cmd, ok)
+ end
+ else
+ errors = string.format("cannot execv(%s), %s", cmd, errors and errors or "unknown reason")
+ end
+ os.raise(errors)
+ end
+
+ -- we need return results if opt.try is enabled
+ return ok, errors
+end
+
+-- execute command and echo verbose info if [-v|--verbose] option is enabled
+function sandbox_os.vexec(cmd, ...)
+
+ -- echo command
+ if option.get("verbose") then
+ utils.cprint("${color.dump.string}" .. vformat(cmd, ...))
+ end
+
+ -- run it
+ sandbox_os.exec(cmd, ...)
+end
+
+-- execute command with arguments list and echo verbose info if [-v|--verbose] option is enabled
+function sandbox_os.vexecv(program, argv, opt)
+
+ -- echo command
+ if option.get("verbose") then
+ utils.cprint("${color.dump.string}" .. vformat(program) .. " " .. sandbox_os.args(argv))
+ end
+
+ -- run it
+ if not (opt and opt.dryrun) then
+ return sandbox_os.execv(program, argv, opt)
+ else
+ return 0
+ end
+end
+
+-- match files or directories
+function sandbox_os.match(pattern, mode, opt)
+ return os.match(vformat(tostring(pattern)), mode, opt)
+end
+
+-- match directories
+function sandbox_os.dirs(pattern, opt)
+ return os.dirs(vformat(tostring(pattern)), opt)
+end
+
+-- match files
+function sandbox_os.files(pattern, opt)
+ return os.files(vformat(tostring(pattern)), opt)
+end
+
+-- match files and directories
+function sandbox_os.filedirs(pattern, opt)
+ return os.filedirs(vformat(tostring(pattern)), opt)
+end
+
+-- is directory?
+function sandbox_os.isdir(dirpath)
+ assert(dirpath)
+ dirpath = tostring(dirpath)
+ return os.isdir(vformat(dirpath))
+end
+
+-- is file?
+function sandbox_os.isfile(filepath)
+ assert(filepath)
+ filepath = tostring(filepath)
+ return os.isfile(vformat(filepath))
+end
+
+-- is symlink?
+function sandbox_os.islink(filepath)
+ assert(filepath)
+ filepath = tostring(filepath)
+ return os.islink(vformat(filepath))
+end
+
+-- is execute program?
+function sandbox_os.isexec(filepath)
+ assert(filepath)
+ filepath = tostring(filepath)
+ return os.isexec(vformat(filepath))
+end
+
+-- exists file or directory?
+function sandbox_os.exists(filedir)
+ assert(filedir)
+ filedir = tostring(filedir)
+ return os.exists(vformat(filedir))
+end
+
+-- read the content of symlink
+function sandbox_os.readlink(symlink)
+ local result = os.readlink(tostring(symlink))
+ if not result then
+ os.raise("cannot read link(%s)", symlink)
+ end
+ return result
+end
+
+-- sleep (support in coroutine)
+function sandbox_os.sleep(ms)
+ if scheduler:co_running() then
+ local ok, errors = scheduler:co_sleep(ms)
+ if not ok then
+ raise(errors)
+ end
+ else
+ os.sleep(ms)
+ end
+end
+
+-- get xmake version
+function sandbox_os.xmakever()
+
+ -- fill cache
+ if sandbox_os._XMAKEVER == nil then
+ -- get xmakever
+ local xmakever = semver.new(xmake._VERSION_SHORT)
+ -- save to cache
+ sandbox_os._XMAKEVER = xmakever or false
+ end
+
+ -- done
+ return sandbox_os._XMAKEVER or nil
+end
+
+-- return module
+return sandbox_os
+