update
This commit is contained in:
@@ -10,6 +10,7 @@ const seederKernelBin = join(repoRoot, 'packages/bare-os-seeder/kernel/bin')
|
||||
const commands = [
|
||||
'basename',
|
||||
'cat',
|
||||
'chmod',
|
||||
'clear',
|
||||
'crontab',
|
||||
'date',
|
||||
|
||||
@@ -2,3 +2,60 @@
|
||||
function bareStdin(ctx) {
|
||||
return typeof ctx.shellStdin === 'string' ? ctx.shellStdin : ''
|
||||
}
|
||||
|
||||
/** @param {number} mode @param {'file' | 'directory' | 'symlink'} type */
|
||||
function bareFormatModeString(mode, type) {
|
||||
const typeChar =
|
||||
type === 'directory' ? 'd' : type === 'symlink' ? 'l' : '-'
|
||||
const perm = mode & 0o777
|
||||
const r = (bit) => (perm & bit ? 'r' : '-')
|
||||
const w = (bit) => (perm & bit ? 'w' : '-')
|
||||
const x = (bit) => (perm & bit ? 'x' : '-')
|
||||
return (
|
||||
typeChar +
|
||||
r(0o400) +
|
||||
w(0o200) +
|
||||
x(0o100) +
|
||||
r(0o040) +
|
||||
w(0o020) +
|
||||
x(0o010) +
|
||||
r(0o004) +
|
||||
w(0o002) +
|
||||
x(0o001)
|
||||
)
|
||||
}
|
||||
|
||||
/** @param {number} mtimeMs @param {number} [nowMs] */
|
||||
function bareFormatLsMtime(mtimeMs, nowMs) {
|
||||
const now = nowMs != null ? nowMs : Date.now()
|
||||
const d = new Date(mtimeMs)
|
||||
const months = [
|
||||
'Jan',
|
||||
'Feb',
|
||||
'Mar',
|
||||
'Apr',
|
||||
'May',
|
||||
'Jun',
|
||||
'Jul',
|
||||
'Aug',
|
||||
'Sep',
|
||||
'Oct',
|
||||
'Nov',
|
||||
'Dec'
|
||||
]
|
||||
const mon = months[d.getMonth()]
|
||||
const day = String(d.getDate()).padStart(2, ' ')
|
||||
const sixMo = 180 * 24 * 3600 * 1000
|
||||
if (Math.abs(now - mtimeMs) > sixMo) {
|
||||
const yr = String(d.getFullYear()).padStart(4, ' ')
|
||||
return mon + ' ' + day + ' ' + yr
|
||||
}
|
||||
const hh = String(d.getHours()).padStart(2, '0')
|
||||
const mm = String(d.getMinutes()).padStart(2, '0')
|
||||
return mon + ' ' + day + ' ' + hh + ':' + mm
|
||||
}
|
||||
|
||||
/** @param {number} size */
|
||||
function barePosixBlocks(size) {
|
||||
return Math.ceil(Number(size) / 512) || 0
|
||||
}
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
async function run(ctx, argv) {
|
||||
const modeStr = argv[1]
|
||||
const files = argv.slice(2)
|
||||
if (!modeStr || !files.length) {
|
||||
ctx.console.error('usage: chmod OCTAL_MODE FILE...')
|
||||
ctx.exitCode = 1
|
||||
return
|
||||
}
|
||||
const mode = Number.parseInt(String(modeStr), 8)
|
||||
if (!Number.isFinite(mode) || mode < 0) {
|
||||
ctx.console.error('chmod: invalid mode')
|
||||
ctx.exitCode = 1
|
||||
return
|
||||
}
|
||||
for (const f of files) {
|
||||
try {
|
||||
await ctx.vfs.chmod(f, mode)
|
||||
} catch (e) {
|
||||
ctx.console.error('chmod: ' + f + ': ' + (e.message || e))
|
||||
ctx.exitCode = 1
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
async function run(ctx, argv) {
|
||||
ctx.console.log(
|
||||
'Bare OS — default user: guest | builtins: alias, cd, export, exit, login, logout, unalias | /bin: basename cat clear crontab date dirname echo env exit false git grep head hdms help hostname id login logout ls nl pathchk printenv pwd rm savevault seq sleep sort tail test touch true tty uname wc which whoami'
|
||||
'Bare OS — default user: guest | builtins: alias, cd, export, exit, login, logout, unalias | /bin: basename cat chmod clear crontab date dirname echo env exit false git grep head hdms help hostname id login logout ls nl pathchk printenv pwd rm savevault seq sleep sort tail test touch true tty uname wc which whoami'
|
||||
)
|
||||
ctx.console.log(
|
||||
'Identity: login [--new] <passphrase> | logout [--save] | savevault (encrypt copy of personal drive under /.bare/vault/)'
|
||||
|
||||
@@ -25,23 +25,95 @@ async function run(ctx, argv) {
|
||||
for (const t of targets) {
|
||||
if (targets.length > 1) ctx.console.log(t + ':')
|
||||
let names
|
||||
/** @type {string | null} */
|
||||
let singleEntryPath = null
|
||||
try {
|
||||
names = await vfs.readdir(t)
|
||||
const stT = await vfs.lstat(t)
|
||||
if (stT && stT.type !== 'directory') {
|
||||
const leaf = t
|
||||
.replace(/\/+$/, '')
|
||||
.split('/')
|
||||
.filter(Boolean)
|
||||
.pop()
|
||||
names = [leaf || t]
|
||||
singleEntryPath = t
|
||||
} else {
|
||||
names = await vfs.readdir(t)
|
||||
}
|
||||
} catch (e) {
|
||||
ctx.console.error('ls: cannot access ' + t + ': ' + (e.message || e))
|
||||
continue
|
||||
}
|
||||
// POSIX: hide dotfiles unless -a (. and .. are dot-prefixed too).
|
||||
if (!showAll) names = names.filter((n) => !n.startsWith('.'))
|
||||
if (!longFmt) {
|
||||
ctx.console.log(names.join(' '))
|
||||
} else {
|
||||
let totalBlocks = 0
|
||||
const rows = []
|
||||
for (const n of names) {
|
||||
const sub = t === '.' || t === './' ? n : t.replace(/\/$/, '') + '/' + n
|
||||
const st = await vfs.stat(sub)
|
||||
const tag = st ? (st.type === 'directory' ? 'd' : '-') : '?'
|
||||
const sz = st && st.size != null ? String(st.size) : '0'
|
||||
ctx.console.log(tag + 'rwxr-xr-x 1 user user ' + sz + ' ' + n)
|
||||
const sub =
|
||||
singleEntryPath != null
|
||||
? singleEntryPath
|
||||
: t === '.' || t === './'
|
||||
? n
|
||||
: t.replace(/\/$/, '') + '/' + n
|
||||
const st = await vfs.lstat(sub)
|
||||
if (!st) {
|
||||
rows.push({
|
||||
modeStr: '?---------',
|
||||
nlink: '?',
|
||||
user: '?',
|
||||
group: '?',
|
||||
size: 0,
|
||||
mtimeStr: '?',
|
||||
name: n,
|
||||
arrow: ''
|
||||
})
|
||||
continue
|
||||
}
|
||||
const blocks = barePosixBlocks(st.size || 0)
|
||||
totalBlocks += blocks
|
||||
const modeStr = bareFormatModeString(st.mode, st.type)
|
||||
const nlink = st.nlink != null ? String(st.nlink) : '1'
|
||||
const user = st.user != null ? st.user : String(st.uid ?? 0)
|
||||
const group = st.group != null ? st.group : String(st.gid ?? 0)
|
||||
const size = st.size != null ? String(st.size) : '0'
|
||||
const mtimeStr = bareFormatLsMtime(
|
||||
typeof st.mtimeMs === 'number' ? st.mtimeMs : Date.now()
|
||||
)
|
||||
let arrow = ''
|
||||
if (st.type === 'symlink' && st.linkname != null) {
|
||||
arrow = ' -> ' + st.linkname
|
||||
}
|
||||
rows.push({
|
||||
modeStr,
|
||||
nlink,
|
||||
user,
|
||||
group,
|
||||
size,
|
||||
mtimeStr,
|
||||
name: n,
|
||||
arrow
|
||||
})
|
||||
}
|
||||
if (singleEntryPath == null) ctx.console.log('total ' + totalBlocks)
|
||||
for (const r of rows) {
|
||||
ctx.console.log(
|
||||
r.modeStr +
|
||||
' ' +
|
||||
r.nlink +
|
||||
' ' +
|
||||
r.user +
|
||||
' ' +
|
||||
r.group +
|
||||
' ' +
|
||||
r.size +
|
||||
' ' +
|
||||
r.mtimeStr +
|
||||
' ' +
|
||||
r.name +
|
||||
r.arrow
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user