Compare commits
3 Commits
ksud-susfs
...
dev
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8304c54b8c | ||
|
|
8ddca5f310 | ||
|
|
d4d42cae0d |
65
.github/workflows/notify.yml
vendored
Normal file
65
.github/workflows/notify.yml
vendored
Normal file
@@ -0,0 +1,65 @@
|
||||
name: Notify
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
- 'release/**'
|
||||
paths-ignore:
|
||||
- 'docs/**'
|
||||
- '*.md'
|
||||
pull_request:
|
||||
types:
|
||||
- opened
|
||||
- reopened
|
||||
- synchronize
|
||||
branches:
|
||||
- main
|
||||
|
||||
defaults:
|
||||
run:
|
||||
working-directory: ts
|
||||
|
||||
jobs:
|
||||
notify:
|
||||
runs-on: ubuntu-latest
|
||||
concurrency:
|
||||
group: notify-telegram-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
steps:
|
||||
- name: Checkout repository with sparse-checkout
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
fetch-depth: 1
|
||||
sparse-checkout: |
|
||||
ts/**
|
||||
sparse-checkout-cone-mode: false
|
||||
|
||||
- name: Setup Bun runtime
|
||||
uses: oven-sh/setup-bun@v2
|
||||
with:
|
||||
bun-version: latest
|
||||
|
||||
- name: Cache Bun modules
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: |
|
||||
~/.bun
|
||||
ts/.node_modules
|
||||
key: ${{ runner.os }}-bun-${{ hashFiles('ts/bun.lock') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-bun-
|
||||
|
||||
- name: Install dependencies
|
||||
run: bun install --cache
|
||||
|
||||
- name: Run telegram bot script
|
||||
env:
|
||||
BOT_TOKEN: ${{ secrets.TELEGRAM_BOT_TOKEN }}
|
||||
TELEGRAM_GROUP_ID: ${{ secrets.TELEGRAM_GROUP_ID }}
|
||||
TELEGRAM_TOPIC_COMMITS: ${{ secrets.TELEGRAM_TOPIC_COMMITS }}
|
||||
TELEGRAM_TOPIC_PRS: ${{ secrets.TELEGRAM_TOPIC_PRS }}
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
GITHUB_EVENT_PATH: ${{ github.event_path }}
|
||||
run: bun run send.ts
|
||||
@@ -17,6 +17,7 @@ fun getBugreportFile(context: Context): File {
|
||||
val bugreportDir = File(context.cacheDir, "bugreport")
|
||||
bugreportDir.mkdirs()
|
||||
|
||||
val processFile = File(bugreportDir, "process.txt")
|
||||
val dmesgFile = File(bugreportDir, "dmesg.txt")
|
||||
val logcatFile = File(bugreportDir, "logcat.txt")
|
||||
val tombstonesFile = File(bugreportDir, "tombstones.tar.gz")
|
||||
@@ -40,8 +41,10 @@ fun getBugreportFile(context: Context): File {
|
||||
|
||||
val shell = getRootShell(true)
|
||||
|
||||
shell.newJob().add("dmesg > ${dmesgFile.absolutePath}").exec()
|
||||
shell.newJob().add("logcat -d > ${logcatFile.absolutePath}").exec()
|
||||
// busybox ps has very few features for embed devices
|
||||
shell.newJob().add("toybox ps -T -A -w -o PID,TID,UID,COMM,CMDLINE,CMD,LABEL,STAT,WCHAN > ${processFile.absolutePath}").exec()
|
||||
shell.newJob().add("dmesg -r > ${dmesgFile.absolutePath}").exec()
|
||||
shell.newJob().add("logcat -b all -v uid -d > ${logcatFile.absolutePath}").exec()
|
||||
shell.newJob().add("tar -czf ${tombstonesFile.absolutePath} -C /data/tombstones .").exec()
|
||||
shell.newJob().add("tar -czf ${dropboxFile.absolutePath} -C /data/system/dropbox .").exec()
|
||||
shell.newJob().add("tar -czf ${pstoreFile.absolutePath} -C /sys/fs/pstore .").exec()
|
||||
|
||||
34
ts/.gitignore
vendored
Normal file
34
ts/.gitignore
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
# dependencies (bun install)
|
||||
node_modules
|
||||
|
||||
# output
|
||||
out
|
||||
dist
|
||||
*.tgz
|
||||
|
||||
# code coverage
|
||||
coverage
|
||||
*.lcov
|
||||
|
||||
# logs
|
||||
logs
|
||||
_.log
|
||||
report.[0-9]_.[0-9]_.[0-9]_.[0-9]_.json
|
||||
|
||||
# dotenv environment variable files
|
||||
.env
|
||||
.env.development.local
|
||||
.env.test.local
|
||||
.env.production.local
|
||||
.env.local
|
||||
|
||||
# caches
|
||||
.eslintcache
|
||||
.cache
|
||||
*.tsbuildinfo
|
||||
|
||||
# IntelliJ based IDEs
|
||||
.idea
|
||||
|
||||
# Finder (MacOS) folder config
|
||||
.DS_Store
|
||||
13
ts/README.md
Normal file
13
ts/README.md
Normal file
@@ -0,0 +1,13 @@
|
||||
# ts
|
||||
|
||||
To install dependencies:
|
||||
|
||||
```bash
|
||||
bun install
|
||||
```
|
||||
|
||||
To run:
|
||||
|
||||
```bash
|
||||
bun run send.ts
|
||||
```
|
||||
52
ts/bun.lock
Normal file
52
ts/bun.lock
Normal file
@@ -0,0 +1,52 @@
|
||||
{
|
||||
"lockfileVersion": 1,
|
||||
"configVersion": 1,
|
||||
"workspaces": {
|
||||
"": {
|
||||
"name": "ts",
|
||||
"dependencies": {
|
||||
"grammy": "^1.38.4",
|
||||
"zod": "^4.1.12",
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/bun": "latest",
|
||||
},
|
||||
"peerDependencies": {
|
||||
"typescript": "^5",
|
||||
},
|
||||
},
|
||||
},
|
||||
"packages": {
|
||||
"@grammyjs/types": ["@grammyjs/types@3.22.2", "", {}, "sha512-uu7DX2ezhnBPozL3bXHmwhLvaFsh59E4QyviNH4Cij7EdVekYrs6mCzeXsa2pDk30l3uXo7DBahlZLzTPtpYZg=="],
|
||||
|
||||
"@types/bun": ["@types/bun@1.3.3", "", { "dependencies": { "bun-types": "1.3.3" } }, "sha512-ogrKbJ2X5N0kWLLFKeytG0eHDleBYtngtlbu9cyBKFtNL3cnpDZkNdQj8flVf6WTZUX5ulI9AY1oa7ljhSrp+g=="],
|
||||
|
||||
"@types/node": ["@types/node@24.10.1", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-GNWcUTRBgIRJD5zj+Tq0fKOJ5XZajIiBroOF0yvj2bSU1WvNdYS/dn9UxwsujGW4JX06dnHyjV2y9rRaybH0iQ=="],
|
||||
|
||||
"abort-controller": ["abort-controller@3.0.0", "", { "dependencies": { "event-target-shim": "^5.0.0" } }, "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg=="],
|
||||
|
||||
"bun-types": ["bun-types@1.3.3", "", { "dependencies": { "@types/node": "*" } }, "sha512-z3Xwlg7j2l9JY27x5Qn3Wlyos8YAp0kKRlrePAOjgjMGS5IG6E7Jnlx736vH9UVI4wUICwwhC9anYL++XeOgTQ=="],
|
||||
|
||||
"debug": ["debug@4.4.3", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="],
|
||||
|
||||
"event-target-shim": ["event-target-shim@5.0.1", "", {}, "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ=="],
|
||||
|
||||
"grammy": ["grammy@1.38.4", "", { "dependencies": { "@grammyjs/types": "3.22.2", "abort-controller": "^3.0.0", "debug": "^4.4.3", "node-fetch": "^2.7.0" } }, "sha512-z07Kin3HgRwMdy40KUs+c9fmNBvGlSxGwcqY8NAH0a8KULGFYEMQaFAo3ge0V5tvmgr02Jgubkf54KjHLAMCbw=="],
|
||||
|
||||
"ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="],
|
||||
|
||||
"node-fetch": ["node-fetch@2.7.0", "", { "dependencies": { "whatwg-url": "^5.0.0" }, "peerDependencies": { "encoding": "^0.1.0" }, "optionalPeers": ["encoding"] }, "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A=="],
|
||||
|
||||
"tr46": ["tr46@0.0.3", "", {}, "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw=="],
|
||||
|
||||
"typescript": ["typescript@5.9.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="],
|
||||
|
||||
"undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="],
|
||||
|
||||
"webidl-conversions": ["webidl-conversions@3.0.1", "", {}, "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ=="],
|
||||
|
||||
"whatwg-url": ["whatwg-url@5.0.0", "", { "dependencies": { "tr46": "~0.0.3", "webidl-conversions": "^3.0.0" } }, "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw=="],
|
||||
|
||||
"zod": ["zod@4.1.12", "", {}, "sha512-JInaHOamG8pt5+Ey8kGmdcAcg3OL9reK8ltczgHTAwNhMys/6ThXHityHxVV2p3fkw/c+MAvBHFVYHFZDmjMCQ=="],
|
||||
}
|
||||
}
|
||||
17
ts/package.json
Normal file
17
ts/package.json
Normal file
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"name": "ts",
|
||||
"module": "send.ts",
|
||||
"type": "module",
|
||||
"private": true,
|
||||
"author": "TypeFlu <TypeFlu@gmail.com> (https://Typeflu.me/)",
|
||||
"devDependencies": {
|
||||
"@types/bun": "latest"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"typescript": "^5"
|
||||
},
|
||||
"dependencies": {
|
||||
"grammy": "^1.38.4",
|
||||
"zod": "^4.1.12"
|
||||
}
|
||||
}
|
||||
197
ts/send.ts
Normal file
197
ts/send.ts
Normal file
@@ -0,0 +1,197 @@
|
||||
import { Bot, InlineKeyboard } from "grammy";
|
||||
import { z } from "zod";
|
||||
|
||||
const BOT_TOKEN = process.env.BOT_TOKEN!;
|
||||
const GROUP_ID = Number(process.env.TELEGRAM_GROUP_ID!);
|
||||
const TOPIC_COMMITS = Number(process.env.TELEGRAM_TOPIC_COMMITS!);
|
||||
const TOPIC_PRS = Number(process.env.TELEGRAM_TOPIC_PRS!);
|
||||
const GITHUB_TOKEN = process.env.GITHUB_TOKEN!;
|
||||
const EVENT_PATH = process.env.GITHUB_EVENT_PATH!;
|
||||
|
||||
const bot = new Bot(BOT_TOKEN);
|
||||
|
||||
const FileNode = z.object({ path: z.string() });
|
||||
|
||||
const PullRequestSchema = z.object({
|
||||
action: z.string(),
|
||||
number: z.number(),
|
||||
repository: z.object({
|
||||
full_name: z.string(),
|
||||
html_url: z.url(),
|
||||
}),
|
||||
pull_request: z.object({
|
||||
html_url: z.url().optional(),
|
||||
url: z.url().optional(),
|
||||
title: z.string(),
|
||||
body: z.string().nullable(),
|
||||
user: z.object({ login: z.string(), html_url: z.url() }),
|
||||
head: z.object({ ref: z.string() }),
|
||||
base: z.object({ ref: z.string() }),
|
||||
changed_files: z.number().optional().default(0),
|
||||
additions: z.number().optional().default(0),
|
||||
deletions: z.number().optional().default(0),
|
||||
}),
|
||||
});
|
||||
|
||||
const PushSchema = z.object({
|
||||
ref: z.string(),
|
||||
repository: z.object({
|
||||
full_name: z.string(),
|
||||
html_url: z.url(),
|
||||
}),
|
||||
head_commit: z
|
||||
.object({
|
||||
id: z.string(),
|
||||
url: z.url(),
|
||||
message: z.string(),
|
||||
author: z.object({ name: z.string(), email: z.email() }),
|
||||
added: z.array(z.string()).optional().default([]),
|
||||
modified: z.array(z.string()).optional().default([]),
|
||||
removed: z.array(z.string()).optional().default([]),
|
||||
})
|
||||
.nullable(),
|
||||
});
|
||||
|
||||
function detectLanguage(files: string[]): string {
|
||||
const ext = files.map((f) => (f.split(".").pop() || "").toLowerCase());
|
||||
if (ext.some((e) => e === "kt" || e === "kts")) return "Kotlin";
|
||||
if (ext.some((e) => e === "rs")) return "Rust";
|
||||
if (ext.some((e) => e === "c")) return "C";
|
||||
if (ext.some((e) => e === "sh")) return "Shell";
|
||||
if (ext.some((e) => e === "ts" || e === "tsx")) return "TypeScript";
|
||||
return "Other";
|
||||
}
|
||||
|
||||
async function fetchPrFiles(
|
||||
repoFullName: string,
|
||||
prNumber: number,
|
||||
): Promise<string[]> {
|
||||
const query = `
|
||||
query($owner:String!, $name:String!, $number:Int!) {
|
||||
repository(owner:$owner, name:$name) {
|
||||
pullRequest(number:$number) {
|
||||
files(first:100) {
|
||||
nodes {
|
||||
path
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}`;
|
||||
const [owner, name] = repoFullName.split("/");
|
||||
const resp = await fetch("https://api.github.com/graphql", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
Authorization: `bearer ${GITHUB_TOKEN}`,
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
query,
|
||||
variables: { owner, name, number: prNumber },
|
||||
}),
|
||||
});
|
||||
if (!resp.ok) {
|
||||
const body = await resp.text();
|
||||
throw new Error(`GitHub GraphQL API error: ${resp.status} ${body}`);
|
||||
}
|
||||
const json = (await resp.json()) as any;
|
||||
const nodes = json?.data?.repository?.pullRequest?.files?.nodes as
|
||||
| { path: string }[]
|
||||
| undefined;
|
||||
if (!nodes || !Array.isArray(nodes)) return [];
|
||||
return nodes.map((n) => n.path);
|
||||
}
|
||||
|
||||
function prUrlOf(pr: { html_url?: string; url?: string }) {
|
||||
return pr.html_url ?? pr.url ?? "";
|
||||
}
|
||||
|
||||
async function formatPrMessage(
|
||||
evt: z.infer<typeof PullRequestSchema>,
|
||||
): Promise<{ text: string; fileLink: string }> {
|
||||
const pr = evt.pull_request;
|
||||
const repo = evt.repository;
|
||||
const files = await fetchPrFiles(repo.full_name, evt.number);
|
||||
const lang = detectLanguage(files);
|
||||
const prUrl = prUrlOf(pr);
|
||||
const fileLink = prUrl ? `${prUrl}/files` : repo.html_url;
|
||||
const bodyText = pr.body ? pr.body : "_No description provided_";
|
||||
const text =
|
||||
`### Repository\n[${repo.full_name}](${repo.html_url})\n\n` +
|
||||
`**Pull Request #${evt.number}:** [${pr.title}](${prUrl || repo.html_url})\n\n` +
|
||||
`**Author:** [${pr.user.login}](${pr.user.html_url})\n` +
|
||||
`**Files Changed:** ${pr.changed_files}\n` +
|
||||
`**Additions / Deletions:** +${pr.additions} / -${pr.deletions}\n` +
|
||||
`**Language:** ${lang}\n\n` +
|
||||
`**Description:**\n\`\`\`\n${bodyText}\n\`\`\``;
|
||||
return { text, fileLink };
|
||||
}
|
||||
|
||||
function formatPushMessage(evt: z.infer<typeof PushSchema>): {
|
||||
text: string;
|
||||
fileLink: string;
|
||||
} {
|
||||
const repo = evt.repository;
|
||||
const c = evt.head_commit;
|
||||
if (!c) {
|
||||
const text = `### Repository\n[${repo.full_name}](${repo.html_url})\n\nPush event detected, but no head commit data available.`;
|
||||
return { text, fileLink: repo.html_url };
|
||||
}
|
||||
const added = c.added ?? [];
|
||||
const modified = c.modified ?? [];
|
||||
const removed = c.removed ?? [];
|
||||
const details = [
|
||||
added.length ? `➕ Added: ${added.join(", ")}` : "",
|
||||
modified.length ? `✏️ Modified: ${modified.join(", ")}` : "",
|
||||
removed.length ? `❌ Removed: ${removed.join(", ")}` : "",
|
||||
]
|
||||
.filter(Boolean)
|
||||
.join("\n");
|
||||
const lang = detectLanguage([...added, ...modified, ...removed]);
|
||||
const fileLink = c.url;
|
||||
const text =
|
||||
`### Repository\n[${repo.full_name}](${repo.html_url})\n\n` +
|
||||
`**Commit:** [${c.id}](${c.url})\n` +
|
||||
`**Author:** ${c.author.name} <${c.author.email}>\n` +
|
||||
`**Message:**\n\`\`\`\n${c.message}\n\`\`\`\n` +
|
||||
(details ? `**Changes:**\n${details}\n` : "") +
|
||||
`**Language:** ${lang}`;
|
||||
return { text, fileLink };
|
||||
}
|
||||
|
||||
async function main(): Promise<void> {
|
||||
const raw = await (
|
||||
await import("node:fs/promises")
|
||||
).readFile(EVENT_PATH, "utf-8");
|
||||
const parsed = JSON.parse(raw);
|
||||
let messageObj: { text: string; fileLink: string };
|
||||
let topic: number;
|
||||
if ("pull_request" in parsed) {
|
||||
const prEvt = PullRequestSchema.parse(parsed);
|
||||
messageObj = await formatPrMessage(prEvt);
|
||||
topic = TOPIC_PRS;
|
||||
} else {
|
||||
const pushEvt = PushSchema.parse(parsed);
|
||||
messageObj = formatPushMessage(pushEvt);
|
||||
topic = TOPIC_COMMITS;
|
||||
}
|
||||
const repoUrl =
|
||||
(parsed.repository &&
|
||||
(parsed.repository.html_url ?? parsed.repository.url)) ||
|
||||
"";
|
||||
const keyboard = new InlineKeyboard()
|
||||
.url("View on GitHub", repoUrl)
|
||||
.row()
|
||||
.url("View Files", messageObj.fileLink);
|
||||
await bot.api.sendMessage(GROUP_ID, messageObj.text, {
|
||||
parse_mode: "Markdown",
|
||||
message_thread_id: topic,
|
||||
reply_markup: keyboard,
|
||||
});
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
main().catch((err) => {
|
||||
console.error(err);
|
||||
process.exit(1);
|
||||
});
|
||||
29
ts/tsconfig.json
Normal file
29
ts/tsconfig.json
Normal file
@@ -0,0 +1,29 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
// Environment setup & latest features
|
||||
"lib": ["ESNext"],
|
||||
"target": "ESNext",
|
||||
"module": "Preserve",
|
||||
"moduleDetection": "force",
|
||||
"jsx": "react-jsx",
|
||||
"allowJs": true,
|
||||
|
||||
// Bundler mode
|
||||
"moduleResolution": "bundler",
|
||||
"allowImportingTsExtensions": true,
|
||||
"verbatimModuleSyntax": true,
|
||||
"noEmit": true,
|
||||
|
||||
// Best practices
|
||||
"strict": true,
|
||||
"skipLibCheck": true,
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
"noUncheckedIndexedAccess": true,
|
||||
"noImplicitOverride": true,
|
||||
|
||||
// Some stricter flags (disabled by default)
|
||||
"noUnusedLocals": false,
|
||||
"noUnusedParameters": false,
|
||||
"noPropertyAccessFromIndexSignature": false
|
||||
}
|
||||
}
|
||||
@@ -8,9 +8,7 @@ use android_logger::Config;
|
||||
use log::LevelFilter;
|
||||
|
||||
use crate::boot_patch::{BootPatchArgs, BootRestoreArgs};
|
||||
use crate::{
|
||||
apk_sign, assets, debug, defs, init_event, ksucalls, module, module_config, susfs, utils,
|
||||
};
|
||||
use crate::{apk_sign, assets, debug, defs, init_event, ksucalls, module, module_config, utils};
|
||||
|
||||
/// KernelSU userspace cli
|
||||
#[derive(Parser, Debug)]
|
||||
@@ -37,12 +35,6 @@ enum Commands {
|
||||
/// Trigger `boot-complete` event
|
||||
BootCompleted,
|
||||
|
||||
/// Susfs
|
||||
Susfs {
|
||||
#[command(subcommand)]
|
||||
command: Susfs,
|
||||
},
|
||||
|
||||
/// Install KernelSU userspace component to system
|
||||
Install {
|
||||
#[arg(long, default_value = None)]
|
||||
@@ -440,16 +432,6 @@ mod kpm_cmd {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(clap::Subcommand, Debug)]
|
||||
enum Susfs {
|
||||
/// Get SUSFS Status
|
||||
Status,
|
||||
/// Get SUSFS Version
|
||||
Version,
|
||||
/// Get SUSFS enable Features
|
||||
Features,
|
||||
}
|
||||
|
||||
#[derive(clap::Subcommand, Debug)]
|
||||
enum Umount {
|
||||
/// Add custom umount path
|
||||
@@ -514,16 +496,7 @@ pub fn run() -> Result<()> {
|
||||
init_event::on_boot_completed();
|
||||
Ok(())
|
||||
}
|
||||
Commands::Susfs { command } => {
|
||||
match command {
|
||||
Susfs::Version => println!("{}", susfs::get_susfs_version()),
|
||||
|
||||
Susfs::Status => println!("{}", susfs::get_susfs_status()),
|
||||
|
||||
Susfs::Features => println!("{}", susfs::get_susfs_features()),
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
Commands::Module { command } => {
|
||||
#[cfg(any(target_os = "linux", target_os = "android"))]
|
||||
{
|
||||
|
||||
@@ -21,9 +21,9 @@ pub fn on_post_data_fs() -> Result<()> {
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
let _ = catch_bootlog("logcat", &["logcat"]);
|
||||
let _ = catch_bootlog("logcat", &["logcat", "-b", "all"]);
|
||||
#[cfg(unix)]
|
||||
let _ = catch_bootlog("dmesg", &["dmesg", "-w"]);
|
||||
let _ = catch_bootlog("dmesg", &["dmesg", "-w", "-r"]);
|
||||
|
||||
if utils::has_magisk() {
|
||||
warn!("Magisk detected, skip post-fs-data!");
|
||||
|
||||
@@ -28,7 +28,6 @@ mod profile;
|
||||
mod restorecon;
|
||||
mod sepolicy;
|
||||
mod su;
|
||||
mod susfs;
|
||||
#[cfg(target_os = "android")]
|
||||
mod uid_scanner;
|
||||
mod umount_manager;
|
||||
|
||||
@@ -1,79 +0,0 @@
|
||||
#![allow(clippy::unreadable_literal)]
|
||||
use libc::SYS_reboot;
|
||||
|
||||
const SUSFS_MAX_VERSION_BUFSIZE: usize = 16;
|
||||
const SUSFS_ENABLED_FEATURES_SIZE: usize = 8192;
|
||||
const ERR_CMD_NOT_SUPPORTED: i32 = 126;
|
||||
const KSU_INSTALL_MAGIC1: u32 = 0xDEADBEEF;
|
||||
const CMD_SUSFS_SHOW_VERSION: u32 = 0x555e1;
|
||||
const CMD_SUSFS_SHOW_ENABLED_FEATURES: u32 = 0x555e2;
|
||||
const SUSFS_MAGIC: u32 = 0xFAFAFAFA;
|
||||
|
||||
#[repr(C)]
|
||||
struct SusfsVersion {
|
||||
susfs_version: [u8; SUSFS_MAX_VERSION_BUFSIZE],
|
||||
err: i32,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
struct SusfsFeatures {
|
||||
enabled_features: [u8; SUSFS_ENABLED_FEATURES_SIZE],
|
||||
err: i32,
|
||||
}
|
||||
|
||||
pub fn get_susfs_version() -> String {
|
||||
let mut cmd = SusfsVersion {
|
||||
susfs_version: [0; SUSFS_MAX_VERSION_BUFSIZE],
|
||||
err: ERR_CMD_NOT_SUPPORTED,
|
||||
};
|
||||
|
||||
let ret = unsafe {
|
||||
libc::syscall(
|
||||
SYS_reboot,
|
||||
KSU_INSTALL_MAGIC1,
|
||||
SUSFS_MAGIC,
|
||||
CMD_SUSFS_SHOW_VERSION,
|
||||
&mut cmd,
|
||||
)
|
||||
};
|
||||
|
||||
if ret < 0 {
|
||||
return "unsupport".to_string();
|
||||
}
|
||||
|
||||
let ver = cmd.susfs_version.iter().position(|&b| b == 0).unwrap_or(16);
|
||||
String::from_utf8(cmd.susfs_version[..ver].to_vec()).unwrap_or_else(|_| "<invalid>".to_string())
|
||||
}
|
||||
|
||||
pub fn get_susfs_status() -> bool {
|
||||
get_susfs_version() != "unsupport"
|
||||
}
|
||||
|
||||
pub fn get_susfs_features() -> String {
|
||||
let mut cmd = SusfsFeatures {
|
||||
enabled_features: [0; SUSFS_ENABLED_FEATURES_SIZE],
|
||||
err: ERR_CMD_NOT_SUPPORTED,
|
||||
};
|
||||
|
||||
let ret = unsafe {
|
||||
libc::syscall(
|
||||
SYS_reboot,
|
||||
KSU_INSTALL_MAGIC1,
|
||||
SUSFS_MAGIC,
|
||||
CMD_SUSFS_SHOW_ENABLED_FEATURES,
|
||||
&mut cmd,
|
||||
)
|
||||
};
|
||||
|
||||
if ret < 0 {
|
||||
return String::new();
|
||||
}
|
||||
|
||||
let features = cmd
|
||||
.enabled_features
|
||||
.iter()
|
||||
.position(|&b| b == 0)
|
||||
.unwrap_or(16);
|
||||
String::from_utf8(cmd.enabled_features[..features].to_vec())
|
||||
.unwrap_or_else(|_| "<invalid>".to_string())
|
||||
}
|
||||
Reference in New Issue
Block a user