atoo-studio 0.0.1 → 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.github.md +322 -0
- package/README.md +112 -0
- package/README.npm.md +112 -0
- package/bin/atoo-studio.js +90 -0
- package/dist/src/agents/claude-code-terminal/adapter.d.ts +42 -0
- package/dist/src/agents/claude-code-terminal/adapter.js +166 -0
- package/dist/src/agents/claude-code-terminal/index.d.ts +13 -0
- package/dist/src/agents/claude-code-terminal/index.js +45 -0
- package/dist/src/agents/claude-code-terminal/spawner.d.ts +9 -0
- package/dist/src/agents/claude-code-terminal/spawner.js +37 -0
- package/dist/src/agents/claude-code-terminal-chatro/adapter.d.ts +51 -0
- package/dist/src/agents/claude-code-terminal-chatro/adapter.js +301 -0
- package/dist/src/agents/claude-code-terminal-chatro/index.d.ts +13 -0
- package/dist/src/agents/claude-code-terminal-chatro/index.js +45 -0
- package/dist/src/agents/claude-code-terminal-chatro/jsonl-watcher.d.ts +67 -0
- package/dist/src/agents/claude-code-terminal-chatro/jsonl-watcher.js +431 -0
- package/dist/src/agents/claude-code-terminal-chatro/spawner.d.ts +9 -0
- package/dist/src/agents/claude-code-terminal-chatro/spawner.js +37 -0
- package/dist/src/agents/codex-terminal/adapter.d.ts +40 -0
- package/dist/src/agents/codex-terminal/adapter.js +160 -0
- package/dist/src/agents/codex-terminal/index.d.ts +13 -0
- package/dist/src/agents/codex-terminal/index.js +47 -0
- package/dist/src/agents/codex-terminal/spawner.d.ts +9 -0
- package/dist/src/agents/codex-terminal/spawner.js +56 -0
- package/dist/src/agents/codex-terminal-chatro/adapter.d.ts +58 -0
- package/dist/src/agents/codex-terminal-chatro/adapter.js +266 -0
- package/dist/src/agents/codex-terminal-chatro/index.d.ts +13 -0
- package/dist/src/agents/codex-terminal-chatro/index.js +50 -0
- package/dist/src/agents/codex-terminal-chatro/jsonl-watcher.d.ts +36 -0
- package/dist/src/agents/codex-terminal-chatro/jsonl-watcher.js +205 -0
- package/dist/src/agents/codex-terminal-chatro/spawner.d.ts +9 -0
- package/dist/src/agents/codex-terminal-chatro/spawner.js +57 -0
- package/dist/src/agents/lib/chain-builder.d.ts +21 -0
- package/dist/src/agents/lib/chain-builder.js +139 -0
- package/dist/src/agents/lib/claude/fs-sessions.d.ts +31 -0
- package/dist/src/agents/lib/claude/fs-sessions.js +329 -0
- package/dist/src/agents/lib/claude/jsonl-writer.d.ts +32 -0
- package/dist/src/agents/lib/claude/jsonl-writer.js +342 -0
- package/dist/src/agents/lib/claude/workspace-trust.d.ts +1 -0
- package/dist/src/agents/lib/claude/workspace-trust.js +29 -0
- package/dist/src/agents/lib/codex/fs-sessions.d.ts +34 -0
- package/dist/src/agents/lib/codex/fs-sessions.js +255 -0
- package/dist/src/agents/lib/codex/jsonl-mapper.d.ts +11 -0
- package/dist/src/agents/lib/codex/jsonl-mapper.js +154 -0
- package/dist/src/agents/lib/codex/jsonl-writer.d.ts +8 -0
- package/dist/src/agents/lib/codex/jsonl-writer.js +440 -0
- package/dist/src/agents/lib/fs-tracking.d.ts +36 -0
- package/dist/src/agents/lib/fs-tracking.js +109 -0
- package/dist/src/agents/lib/pty-activity-tracker.d.ts +37 -0
- package/dist/src/agents/lib/pty-activity-tracker.js +105 -0
- package/dist/src/agents/lib/session-id-utils.d.ts +46 -0
- package/dist/src/agents/lib/session-id-utils.js +147 -0
- package/dist/src/agents/lib/session-precreate.d.ts +17 -0
- package/dist/src/agents/lib/session-precreate.js +177 -0
- package/dist/src/agents/registry.d.ts +72 -0
- package/dist/src/agents/registry.js +337 -0
- package/dist/src/agents/types.d.ts +135 -0
- package/dist/src/agents/types.js +1 -0
- package/dist/src/auth/crypto-key.d.ts +6 -0
- package/dist/src/auth/crypto-key.js +45 -0
- package/dist/src/auth/middleware.d.ts +18 -0
- package/dist/src/auth/middleware.js +54 -0
- package/dist/src/auth/password.d.ts +2 -0
- package/dist/src/auth/password.js +12 -0
- package/dist/src/auth/session.d.ts +10 -0
- package/dist/src/auth/session.js +33 -0
- package/dist/src/auth/totp.d.ts +12 -0
- package/dist/src/auth/totp.js +61 -0
- package/dist/src/auth/webauthn.d.ts +6 -0
- package/dist/src/auth/webauthn.js +117 -0
- package/dist/src/config.d.ts +10 -0
- package/dist/src/config.js +16 -0
- package/dist/src/database/connection-manager.d.ts +25 -0
- package/dist/src/database/connection-manager.js +211 -0
- package/dist/src/database/discovery/container.d.ts +6 -0
- package/dist/src/database/discovery/container.js +226 -0
- package/dist/src/database/discovery/env-parser.d.ts +9 -0
- package/dist/src/database/discovery/env-parser.js +525 -0
- package/dist/src/database/discovery/local-files.d.ts +6 -0
- package/dist/src/database/discovery/local-files.js +58 -0
- package/dist/src/database/discovery/port-scan.d.ts +7 -0
- package/dist/src/database/discovery/port-scan.js +61 -0
- package/dist/src/database/drivers/cassandra.d.ts +12 -0
- package/dist/src/database/drivers/cassandra.js +91 -0
- package/dist/src/database/drivers/clickhouse.d.ts +11 -0
- package/dist/src/database/drivers/clickhouse.js +127 -0
- package/dist/src/database/drivers/elasticsearch.d.ts +12 -0
- package/dist/src/database/drivers/elasticsearch.js +169 -0
- package/dist/src/database/drivers/influxdb.d.ts +14 -0
- package/dist/src/database/drivers/influxdb.js +194 -0
- package/dist/src/database/drivers/memcached.d.ts +11 -0
- package/dist/src/database/drivers/memcached.js +117 -0
- package/dist/src/database/drivers/mongodb.d.ts +12 -0
- package/dist/src/database/drivers/mongodb.js +128 -0
- package/dist/src/database/drivers/mysql.d.ts +11 -0
- package/dist/src/database/drivers/mysql.js +112 -0
- package/dist/src/database/drivers/neo4j.d.ts +11 -0
- package/dist/src/database/drivers/neo4j.js +158 -0
- package/dist/src/database/drivers/postgresql.d.ts +11 -0
- package/dist/src/database/drivers/postgresql.js +133 -0
- package/dist/src/database/drivers/redis.d.ts +11 -0
- package/dist/src/database/drivers/redis.js +91 -0
- package/dist/src/database/drivers/sqlite.d.ts +10 -0
- package/dist/src/database/drivers/sqlite.js +100 -0
- package/dist/src/database/query-stream.d.ts +5 -0
- package/dist/src/database/query-stream.js +75 -0
- package/dist/src/database/types.d.ts +71 -0
- package/dist/src/database/types.js +1 -0
- package/dist/src/events/index.d.ts +3 -0
- package/dist/src/events/index.js +3 -0
- package/dist/src/events/types.d.ts +214 -0
- package/dist/src/events/types.js +22 -0
- package/dist/src/events/wire.d.ts +114 -0
- package/dist/src/events/wire.js +296 -0
- package/dist/src/fs-monitor-types.d.ts +24 -0
- package/dist/src/fs-monitor-types.js +1 -0
- package/dist/src/fs-monitor.d.ts +80 -0
- package/dist/src/fs-monitor.js +637 -0
- package/dist/src/handlers/auth.d.ts +1 -0
- package/dist/src/handlers/auth.js +170 -0
- package/dist/src/handlers/changes.d.ts +1 -0
- package/dist/src/handlers/changes.js +203 -0
- package/dist/src/handlers/containers.d.ts +12 -0
- package/dist/src/handlers/containers.js +379 -0
- package/dist/src/handlers/databases.d.ts +3 -0
- package/dist/src/handlers/databases.js +327 -0
- package/dist/src/handlers/environments.d.ts +3 -0
- package/dist/src/handlers/environments.js +286 -0
- package/dist/src/handlers/github.d.ts +1 -0
- package/dist/src/handlers/github.js +153 -0
- package/dist/src/handlers/projects.d.ts +1 -0
- package/dist/src/handlers/projects.js +895 -0
- package/dist/src/handlers/ssh.d.ts +1 -0
- package/dist/src/handlers/ssh.js +162 -0
- package/dist/src/handlers/users.d.ts +1 -0
- package/dist/src/handlers/users.js +195 -0
- package/dist/src/index.d.ts +1 -0
- package/dist/src/index.js +228 -0
- package/dist/src/mcp/config.d.ts +32 -0
- package/dist/src/mcp/config.js +227 -0
- package/dist/src/mcp/server.d.ts +1 -0
- package/dist/src/mcp/server.js +574 -0
- package/dist/src/serial/cuse-device.d.ts +19 -0
- package/dist/src/serial/cuse-device.js +260 -0
- package/dist/src/serial/manager.d.ts +63 -0
- package/dist/src/serial/manager.js +206 -0
- package/dist/src/serial/pty-pair.d.ts +16 -0
- package/dist/src/serial/pty-pair.js +68 -0
- package/dist/src/services/fs-browser.d.ts +14 -0
- package/dist/src/services/fs-browser.js +98 -0
- package/dist/src/services/git-ops.d.ts +78 -0
- package/dist/src/services/git-ops.js +288 -0
- package/dist/src/services/github-ops.d.ts +104 -0
- package/dist/src/services/github-ops.js +192 -0
- package/dist/src/services/obfuscation.d.ts +2 -0
- package/dist/src/services/obfuscation.js +16 -0
- package/dist/src/services/preview/headless-backend.d.ts +62 -0
- package/dist/src/services/preview/headless-backend.js +698 -0
- package/dist/src/services/preview/injected-scripts.d.ts +9 -0
- package/dist/src/services/preview/injected-scripts.js +232 -0
- package/dist/src/services/preview/preview-backend.d.ts +92 -0
- package/dist/src/services/preview/preview-backend.js +15 -0
- package/dist/src/services/preview/universal-setter.d.ts +7 -0
- package/dist/src/services/preview/universal-setter.js +46 -0
- package/dist/src/services/preview-manager.d.ts +50 -0
- package/dist/src/services/preview-manager.js +216 -0
- package/dist/src/services/project-watcher.d.ts +6 -0
- package/dist/src/services/project-watcher.js +307 -0
- package/dist/src/services/remote-fs-browser.d.ts +11 -0
- package/dist/src/services/remote-fs-browser.js +50 -0
- package/dist/src/services/remote-git-ops.d.ts +71 -0
- package/dist/src/services/remote-git-ops.js +215 -0
- package/dist/src/services/session-search.d.ts +56 -0
- package/dist/src/services/session-search.js +303 -0
- package/dist/src/services/ssh-manager.d.ts +44 -0
- package/dist/src/services/ssh-manager.js +359 -0
- package/dist/src/session-writer.d.ts +9 -0
- package/dist/src/session-writer.js +66 -0
- package/dist/src/spawner.d.ts +56 -0
- package/dist/src/spawner.js +135 -0
- package/dist/src/state/db.d.ts +214 -0
- package/dist/src/state/db.js +897 -0
- package/dist/src/state/store.d.ts +37 -0
- package/dist/src/state/store.js +108 -0
- package/dist/src/state/types.d.ts +13 -0
- package/dist/src/state/types.js +1 -0
- package/dist/src/web/devtools-proxy.d.ts +7 -0
- package/dist/src/web/devtools-proxy.js +176 -0
- package/dist/src/web/port-proxy.d.ts +15 -0
- package/dist/src/web/port-proxy.js +124 -0
- package/dist/src/web/preview-ws.d.ts +5 -0
- package/dist/src/web/preview-ws.js +207 -0
- package/dist/src/web/server.d.ts +6 -0
- package/dist/src/web/server.js +1694 -0
- package/dist/src/ws/agent-ws.d.ts +5 -0
- package/dist/src/ws/agent-ws.js +93 -0
- package/frontend/dist/assets/_basePickBy-B-LibQ4-.js +1 -0
- package/frontend/dist/assets/_baseUniq-CprifHap.js +1 -0
- package/frontend/dist/assets/_createAssigner-ByDUqGii.js +1 -0
- package/frontend/dist/assets/abap-DuT-3z4x.js +1 -0
- package/frontend/dist/assets/addon-fit-CxQet2ja.js +1 -0
- package/frontend/dist/assets/addon-web-links-D_jRkPIl.js +1 -0
- package/frontend/dist/assets/apex-B-em86xX.js +1 -0
- package/frontend/dist/assets/api-SUPuHhSY.js +2 -0
- package/frontend/dist/assets/arc-Z0_eVteO.js +1 -0
- package/frontend/dist/assets/architecture-PBZL5I3N-hvVXGhqd.js +1 -0
- package/frontend/dist/assets/architectureDiagram-2XIMDMQ5-DiHPxX4j.js +36 -0
- package/frontend/dist/assets/array-CwG8vNfn.js +1 -0
- package/frontend/dist/assets/auth-store-R7eW5SVu.js +1 -0
- package/frontend/dist/assets/azcli-Bg9wQloi.js +1 -0
- package/frontend/dist/assets/bat-BM46z99L.js +1 -0
- package/frontend/dist/assets/bicep-DcBsJUfh.js +2 -0
- package/frontend/dist/assets/blockDiagram-WCTKOSBZ-C40u_hLo.js +132 -0
- package/frontend/dist/assets/c4Diagram-IC4MRINW-Ct7LjWFQ.js +10 -0
- package/frontend/dist/assets/cameligo-zw7JTtim.js +1 -0
- package/frontend/dist/assets/channel-ClCsE6HN.js +1 -0
- package/frontend/dist/assets/chunk-4BX2VUAB-zZ6P90VO.js +1 -0
- package/frontend/dist/assets/chunk-55IACEB6-DXllTDQl.js +1 -0
- package/frontend/dist/assets/chunk-7E7YKBS2-7zRaOLjj.js +1 -0
- package/frontend/dist/assets/chunk-7R4GIKGN-Csst1274.js +80 -0
- package/frontend/dist/assets/chunk-C72U2L5F-_JbQPbLN.js +1 -0
- package/frontend/dist/assets/chunk-CFjPhJqf.js +1 -0
- package/frontend/dist/assets/chunk-EGIJ26TM-B--aFyPw.js +1 -0
- package/frontend/dist/assets/chunk-FMBD7UC4-DVR34RNb.js +15 -0
- package/frontend/dist/assets/chunk-GEFDOKGD-CnmN6cC8.js +2 -0
- package/frontend/dist/assets/chunk-JSJVCQXG-CWxHBzeJ.js +1 -0
- package/frontend/dist/assets/chunk-KX2RTZJC-DkRk56s7.js +1 -0
- package/frontend/dist/assets/chunk-KYZI473N-DCCsG2dK.js +53 -0
- package/frontend/dist/assets/chunk-L3YUKLVL-C-DkZTMr.js +1 -0
- package/frontend/dist/assets/chunk-MX3YWQON-OUdzv5sZ.js +1 -0
- package/frontend/dist/assets/chunk-NQ4KR5QH-Bpu9FsM7.js +220 -0
- package/frontend/dist/assets/chunk-O4XLMI2P-BMLK6_ib.js +7 -0
- package/frontend/dist/assets/chunk-OZEHJAEY-CNNiJtG0.js +1 -0
- package/frontend/dist/assets/chunk-PQ6SQG4A-evVHD3KM.js +1 -0
- package/frontend/dist/assets/chunk-PU5JKC2W-DPFTYuvl.js +70 -0
- package/frontend/dist/assets/chunk-QZHKN3VN-JRdddPvu.js +1 -0
- package/frontend/dist/assets/chunk-R5LLSJPH-CHQzVVOV.js +1 -0
- package/frontend/dist/assets/chunk-WL4C6EOR-BNFU6IIi.js +189 -0
- package/frontend/dist/assets/chunk-XIRO2GV7-98T93G85.js +1 -0
- package/frontend/dist/assets/chunk-XZSTWKYB-BcW3cyNp.js +94 -0
- package/frontend/dist/assets/chunk-YBOYWFTD-BgKO1qAJ.js +1 -0
- package/frontend/dist/assets/classDiagram-VBA2DB6C-DikXzgcD.js +1 -0
- package/frontend/dist/assets/classDiagram-v2-RAHNMMFH-D7E3tQUK.js +1 -0
- package/frontend/dist/assets/clojure-FspFoNNQ.js +1 -0
- package/frontend/dist/assets/clone-mOXuZa7C.js +1 -0
- package/frontend/dist/assets/codicon-ngg6Pgfi.ttf +0 -0
- package/frontend/dist/assets/coffee-13n8Bk2W.js +1 -0
- package/frontend/dist/assets/cose-bilkent-S5V4N54A-zUOWQqLe.js +1 -0
- package/frontend/dist/assets/cpp-BVm2xGEs.js +1 -0
- package/frontend/dist/assets/csharp-D2kAWmUm.js +1 -0
- package/frontend/dist/assets/csp-Ezvgpf0e.js +1 -0
- package/frontend/dist/assets/css-CYxRwcFy.js +3 -0
- package/frontend/dist/assets/css.worker-Cd5h-ZOL.js +89 -0
- package/frontend/dist/assets/cssMode-CrXej49V.js +1 -0
- package/frontend/dist/assets/cypher-jg3SGErc.js +1 -0
- package/frontend/dist/assets/cytoscape.esm-kyyvzxNV.js +321 -0
- package/frontend/dist/assets/dagre-DH4bgZO7.js +1 -0
- package/frontend/dist/assets/dagre-KLK3FWXG-DNSqDkwT.js +4 -0
- package/frontend/dist/assets/dart-179jqhK4.js +1 -0
- package/frontend/dist/assets/defaultLocale-Dda4OpKy.js +1 -0
- package/frontend/dist/assets/diagram-E7M64L7V-RqPNT5Vs.js +24 -0
- package/frontend/dist/assets/diagram-IFDJBPK2-B-5NRyaE.js +43 -0
- package/frontend/dist/assets/diagram-P4PSJMXO-BrP69Hk0.js +24 -0
- package/frontend/dist/assets/dist-CU_Nb1G5.js +1 -0
- package/frontend/dist/assets/dockerfile-CIAtSGxS.js +1 -0
- package/frontend/dist/assets/ecl-CGVKfDxD.js +1 -0
- package/frontend/dist/assets/editor-Br_kD0ds.css +1 -0
- package/frontend/dist/assets/editor.api2-YXkDn0Gm.js +872 -0
- package/frontend/dist/assets/editor.main-fBaXZjJ0.js +6 -0
- package/frontend/dist/assets/elixir-BZ-6w0y3.js +1 -0
- package/frontend/dist/assets/erDiagram-INFDFZHY-BYiB9NYg.js +70 -0
- package/frontend/dist/assets/flow9-CVuOjTMv.js +1 -0
- package/frontend/dist/assets/flowDiagram-PKNHOUZH-Cwq47rsR.js +162 -0
- package/frontend/dist/assets/freemarker2-DM-pztJU.js +3 -0
- package/frontend/dist/assets/fsharp-q0pGJYr6.js +1 -0
- package/frontend/dist/assets/ganttDiagram-A5KZAMGK-Dnx3szD9.js +292 -0
- package/frontend/dist/assets/gitGraph-HDMCJU4V-COlTQ7bA.js +1 -0
- package/frontend/dist/assets/gitGraphDiagram-K3NZZRJ6-BaUxboNc.js +65 -0
- package/frontend/dist/assets/go-dzSPfdEO.js +1 -0
- package/frontend/dist/assets/graphlib-kEFlkt3U.js +1 -0
- package/frontend/dist/assets/graphql-CG4OUoEV.js +1 -0
- package/frontend/dist/assets/handlebars-BbK53Vec.js +1 -0
- package/frontend/dist/assets/hcl-Cy14JPk3.js +1 -0
- package/frontend/dist/assets/html-DYtTQNOG.js +1 -0
- package/frontend/dist/assets/html.worker-BjVEKLoU.js +502 -0
- package/frontend/dist/assets/htmlMode-C6GTouth.js +1 -0
- package/frontend/dist/assets/index-DMLxes_u.js +157 -0
- package/frontend/dist/assets/index-DmzeqkB1.css +1 -0
- package/frontend/dist/assets/info-3K5VOQVL-DBtHyA4C.js +1 -0
- package/frontend/dist/assets/infoDiagram-LFFYTUFH-yBXLgMPI.js +2 -0
- package/frontend/dist/assets/ini-Pbg8HGVD.js +1 -0
- package/frontend/dist/assets/init-D6KNwrax.js +1 -0
- package/frontend/dist/assets/ishikawaDiagram-PHBUUO56-Bld4two_.js +70 -0
- package/frontend/dist/assets/java-BmVu6Qrl.js +1 -0
- package/frontend/dist/assets/javascript-PbfQEdcJ.js +1 -0
- package/frontend/dist/assets/journeyDiagram-4ABVD52K-4HyMd4R2.js +139 -0
- package/frontend/dist/assets/json.worker-DqU5Wxnl.js +58 -0
- package/frontend/dist/assets/jsonMode-CASsGppE.js +7 -0
- package/frontend/dist/assets/julia-3cGnieBq.js +1 -0
- package/frontend/dist/assets/kanban-definition-K7BYSVSG-DpgsZmpG.js +89 -0
- package/frontend/dist/assets/katex-CEw3x5bf.js +261 -0
- package/frontend/dist/assets/kotlin-BuWkVcfV.js +1 -0
- package/frontend/dist/assets/less-CJ_VPy2C.js +2 -0
- package/frontend/dist/assets/lexon-BygAuZPu.js +1 -0
- package/frontend/dist/assets/line-CA_wh_TY.js +1 -0
- package/frontend/dist/assets/linear-BAcLW45z.js +1 -0
- package/frontend/dist/assets/liquid-kz84dle6.js +1 -0
- package/frontend/dist/assets/lspLanguageFeatures-C7hAHFn1.js +4 -0
- package/frontend/dist/assets/lua-C8Xs3dCx.js +1 -0
- package/frontend/dist/assets/m3-DTJeKBk4.js +1 -0
- package/frontend/dist/assets/markdown-QCgx8JqZ.js +1 -0
- package/frontend/dist/assets/math-D0YcMJAn.js +1 -0
- package/frontend/dist/assets/mdx-yRw0ap-E.js +1 -0
- package/frontend/dist/assets/mermaid-parser.core-DAeTodBQ.js +4 -0
- package/frontend/dist/assets/mindmap-definition-YRQLILUH-CoNlFyVl.js +68 -0
- package/frontend/dist/assets/mips-DopWaYgE.js +1 -0
- package/frontend/dist/assets/monaco.contribution-DeY0Qei-.js +2 -0
- package/frontend/dist/assets/msdax-BDis4ARV.js +1 -0
- package/frontend/dist/assets/mysql-BV6MLsOI.js +1 -0
- package/frontend/dist/assets/objective-c-B1UuzKs6.js +1 -0
- package/frontend/dist/assets/ordinal-jM7S0YHN.js +1 -0
- package/frontend/dist/assets/packet-RMMSAZCW-FF6-Tmai.js +1 -0
- package/frontend/dist/assets/pascal-BkvESCrc.js +1 -0
- package/frontend/dist/assets/pascaligo-lTy0kZYr.js +1 -0
- package/frontend/dist/assets/path-DNPd7Py7.js +1 -0
- package/frontend/dist/assets/perl-CrtUPXLV.js +1 -0
- package/frontend/dist/assets/pgsql-B9IbNWx2.js +1 -0
- package/frontend/dist/assets/php-CXvQBY2p.js +1 -0
- package/frontend/dist/assets/pie-UPGHQEXC-CFvXY2o-.js +1 -0
- package/frontend/dist/assets/pieDiagram-SKSYHLDU-CM_hbCcn.js +30 -0
- package/frontend/dist/assets/pla-DxBxuqWu.js +1 -0
- package/frontend/dist/assets/postiats-OkEuT5YF.js +1 -0
- package/frontend/dist/assets/powerquery-CMx5Tq4K.js +1 -0
- package/frontend/dist/assets/powershell-CstRxrEc.js +1 -0
- package/frontend/dist/assets/preload-helper-D4M6sveU.js +1 -0
- package/frontend/dist/assets/protobuf-Bx0Z-uRj.js +2 -0
- package/frontend/dist/assets/pug--W8vanWl.js +1 -0
- package/frontend/dist/assets/python-DA0rnlw3.js +1 -0
- package/frontend/dist/assets/qsharp-CRtr0YbN.js +1 -0
- package/frontend/dist/assets/quadrantDiagram-337W2JSQ-B3n3IUhC.js +7 -0
- package/frontend/dist/assets/r-C6E1d6iv.js +1 -0
- package/frontend/dist/assets/radar-KQ55EAFF-MPZu7SdX.js +1 -0
- package/frontend/dist/assets/razor-yd73uata.js +1 -0
- package/frontend/dist/assets/redis-Dx13voP3.js +1 -0
- package/frontend/dist/assets/redshift-D66HwlyV.js +1 -0
- package/frontend/dist/assets/requirementDiagram-Z7DCOOCP-CorP7L7F.js +73 -0
- package/frontend/dist/assets/restructuredtext-DQT2NKJ2.js +1 -0
- package/frontend/dist/assets/rough.esm-DxAX5Vpo.js +1 -0
- package/frontend/dist/assets/ruby-iFXI8hwH.js +1 -0
- package/frontend/dist/assets/rust-CSKiei34.js +1 -0
- package/frontend/dist/assets/sankeyDiagram-WA2Y5GQK-RDx6Bd-B.js +10 -0
- package/frontend/dist/assets/sb-Bo3ttdP2.js +1 -0
- package/frontend/dist/assets/scala-BC1D-Nxp.js +1 -0
- package/frontend/dist/assets/scheme-Z4OAo4Lv.js +1 -0
- package/frontend/dist/assets/scss-BvrdPs6B.js +3 -0
- package/frontend/dist/assets/sequenceDiagram-2WXFIKYE-JMqJSFq6.js +145 -0
- package/frontend/dist/assets/shell-Bh_aCyF-.js +1 -0
- package/frontend/dist/assets/solidity-CWHj6tSe.js +1 -0
- package/frontend/dist/assets/sophia-raoNtKtm.js +1 -0
- package/frontend/dist/assets/sparql-XzmoGnue.js +1 -0
- package/frontend/dist/assets/sql-BD0i9Gvg.js +1 -0
- package/frontend/dist/assets/src-Bn-kKzs7.js +1 -0
- package/frontend/dist/assets/st-DtVKyms6.js +1 -0
- package/frontend/dist/assets/stateDiagram-RAJIS63D-CgFfENdy.js +1 -0
- package/frontend/dist/assets/stateDiagram-v2-FVOUBMTO-C4Hh2P-U.js +1 -0
- package/frontend/dist/assets/swift--UZs77wT.js +1 -0
- package/frontend/dist/assets/systemverilog-CDnBSWUd.js +1 -0
- package/frontend/dist/assets/tcl-DdCEuTHZ.js +1 -0
- package/frontend/dist/assets/timeline-definition-YZTLITO2-BnatPBR5.js +61 -0
- package/frontend/dist/assets/treemap-KZPCXAKY-qb1Pl9la.js +1 -0
- package/frontend/dist/assets/ts.worker-DyPAEIuH.js +67719 -0
- package/frontend/dist/assets/tsMode-iuvyEpyO.js +11 -0
- package/frontend/dist/assets/twig-SSL-Altf.js +1 -0
- package/frontend/dist/assets/typescript-17918Hud.js +1 -0
- package/frontend/dist/assets/typespec-BT7S0ETg.js +1 -0
- package/frontend/dist/assets/vb-CrIgucua.js +1 -0
- package/frontend/dist/assets/vennDiagram-LZ73GAT5-DygS4Zzd.js +34 -0
- package/frontend/dist/assets/wgsl-BeKc3oEp.js +298 -0
- package/frontend/dist/assets/workers-DTfwKVoM.js +1 -0
- package/frontend/dist/assets/xml-CBMr_Wbw.js +1 -0
- package/frontend/dist/assets/xterm-BrP-ENHg.css +1 -0
- package/frontend/dist/assets/xterm-CBX2m0YM.js +36 -0
- package/frontend/dist/assets/xychartDiagram-JWTSCODW-D6wY1Jwd.js +7 -0
- package/frontend/dist/assets/yaml-CTjCH7Bv.js +1 -0
- package/frontend/dist/fonts/inter-300.ttf +0 -0
- package/frontend/dist/fonts/inter-400.ttf +0 -0
- package/frontend/dist/fonts/inter-500.ttf +0 -0
- package/frontend/dist/fonts/inter-600.ttf +0 -0
- package/frontend/dist/fonts/inter-700.ttf +0 -0
- package/frontend/dist/index.html +49 -0
- package/frontend/dist/logo_192x192.png +0 -0
- package/frontend/dist/logo_32x32.png +0 -0
- package/frontend/dist/logo_512x512.png +0 -0
- package/frontend/dist/logo_64x64.png +0 -0
- package/frontend/dist/logobg_192x192.png +0 -0
- package/frontend/dist/logobg_512x512.png +0 -0
- package/frontend/dist/logobg_64x64.png +0 -0
- package/frontend/dist/manifest.json +25 -0
- package/frontend/dist/sw.js +22 -0
- package/package.json +74 -7
- package/preload/Makefile +12 -0
- package/preload/atoo-studio-preload.c +647 -0
- package/preload/atoo-studio-preload.so +0 -0
- package/setup-cuse.sh +260 -0
- package/setup.sh +81 -0
- package/src/serial/native/binding.gyp +10 -0
- package/src/serial/native/pty_pair.c +222 -0
|
@@ -0,0 +1,647 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* atoo-studio-preload.c — LD_PRELOAD shared library for Copy-on-Write filesystem monitoring.
|
|
3
|
+
*
|
|
4
|
+
* Intercepts libc file operations (open, rename, unlink, truncate) to:
|
|
5
|
+
* 1. Snapshot the original file before modification
|
|
6
|
+
* 2. Report the event to the TypeScript monitor via Unix socket
|
|
7
|
+
*
|
|
8
|
+
* Environment variables:
|
|
9
|
+
* ATOO_SESSION_ID — session/tracking identifier
|
|
10
|
+
* ATOO_SOCKET_PATH — path to Unix domain socket (default: ~/.atoo-studio/preload.sock)
|
|
11
|
+
* ATOO_PRELOAD_DEBUG — set to "1" to enable stderr debug logging
|
|
12
|
+
*
|
|
13
|
+
* Graceful degradation: if socket or env vars are unavailable, all intercepted
|
|
14
|
+
* functions pass through to real implementations with near-zero overhead.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
#include <dlfcn.h>
|
|
18
|
+
#include <errno.h>
|
|
19
|
+
#include <fcntl.h>
|
|
20
|
+
#include <limits.h>
|
|
21
|
+
#include <pthread.h>
|
|
22
|
+
#include <stdarg.h>
|
|
23
|
+
#include <stdint.h>
|
|
24
|
+
#include <stdio.h>
|
|
25
|
+
#include <stdlib.h>
|
|
26
|
+
#include <string.h>
|
|
27
|
+
#include <sys/socket.h>
|
|
28
|
+
#include <sys/stat.h>
|
|
29
|
+
#include <sys/un.h>
|
|
30
|
+
#include <time.h>
|
|
31
|
+
#include <unistd.h>
|
|
32
|
+
|
|
33
|
+
/* ── Real function pointers ─────────────────────────────────────────── */
|
|
34
|
+
|
|
35
|
+
static int (*real_open)(const char *, int, ...) = NULL;
|
|
36
|
+
static int (*real_open64)(const char *, int, ...) = NULL;
|
|
37
|
+
static int (*real_openat)(int, const char *, int, ...) = NULL;
|
|
38
|
+
static int (*real_openat64)(int, const char *, int, ...) = NULL;
|
|
39
|
+
static int (*real_creat)(const char *, mode_t) = NULL;
|
|
40
|
+
static int (*real_rename)(const char *, const char *) = NULL;
|
|
41
|
+
static int (*real_renameat)(int, const char *, int, const char *) = NULL;
|
|
42
|
+
static int (*real_renameat2)(int, const char *, int, const char *, unsigned int) = NULL;
|
|
43
|
+
static int (*real_unlink)(const char *) = NULL;
|
|
44
|
+
static int (*real_unlinkat)(int, const char *, int) = NULL;
|
|
45
|
+
static int (*real_truncate)(const char *, off_t) = NULL;
|
|
46
|
+
static int (*real_ftruncate)(int, off_t) = NULL;
|
|
47
|
+
|
|
48
|
+
/* ── Global state ───────────────────────────────────────────────────── */
|
|
49
|
+
|
|
50
|
+
static char g_session_id[256];
|
|
51
|
+
static char g_socket_path[PATH_MAX];
|
|
52
|
+
static char g_snapshot_dir[PATH_MAX];
|
|
53
|
+
static char g_atoo_dir[PATH_MAX]; /* ~/.atoo-studio/ for exclusion */
|
|
54
|
+
static int g_sock_fd = -1;
|
|
55
|
+
static int g_initialized = 0;
|
|
56
|
+
static uint64_t g_counter = 0;
|
|
57
|
+
static pthread_mutex_t g_mutex = PTHREAD_MUTEX_INITIALIZER;
|
|
58
|
+
|
|
59
|
+
/* Debug logging — only when ATOO_PRELOAD_DEBUG=1 */
|
|
60
|
+
static int g_debug = 0;
|
|
61
|
+
#define DBG(...) do { if (g_debug) fprintf(stderr, __VA_ARGS__); } while (0)
|
|
62
|
+
|
|
63
|
+
/* Per-thread re-entrancy guard */
|
|
64
|
+
static __thread int in_hook = 0;
|
|
65
|
+
|
|
66
|
+
/* ── Snapshot set (simple open-addressing hash map) ─────────────────── */
|
|
67
|
+
|
|
68
|
+
#define SET_INIT_CAP 256
|
|
69
|
+
|
|
70
|
+
typedef struct {
|
|
71
|
+
char **keys;
|
|
72
|
+
int cap;
|
|
73
|
+
int count;
|
|
74
|
+
} SnapSet;
|
|
75
|
+
|
|
76
|
+
static SnapSet g_snapped = { NULL, 0, 0 };
|
|
77
|
+
|
|
78
|
+
static unsigned int hash_str(const char *s) {
|
|
79
|
+
unsigned int h = 5381;
|
|
80
|
+
while (*s) h = h * 33 + (unsigned char)*s++;
|
|
81
|
+
return h;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
static int set_contains(SnapSet *set, const char *key) {
|
|
85
|
+
if (!set->keys || set->cap == 0) return 0;
|
|
86
|
+
unsigned int idx = hash_str(key) % (unsigned int)set->cap;
|
|
87
|
+
for (int i = 0; i < set->cap; i++) {
|
|
88
|
+
unsigned int pos = (idx + (unsigned int)i) % (unsigned int)set->cap;
|
|
89
|
+
if (!set->keys[pos]) return 0;
|
|
90
|
+
if (strcmp(set->keys[pos], key) == 0) return 1;
|
|
91
|
+
}
|
|
92
|
+
return 0;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
static void set_grow(SnapSet *set);
|
|
96
|
+
|
|
97
|
+
static void set_insert(SnapSet *set, const char *key) {
|
|
98
|
+
if (!set->keys) {
|
|
99
|
+
set->cap = SET_INIT_CAP;
|
|
100
|
+
set->keys = (char **)calloc((size_t)set->cap, sizeof(char *));
|
|
101
|
+
if (!set->keys) return;
|
|
102
|
+
}
|
|
103
|
+
if (set->count * 2 >= set->cap) {
|
|
104
|
+
set_grow(set);
|
|
105
|
+
}
|
|
106
|
+
unsigned int idx = hash_str(key) % (unsigned int)set->cap;
|
|
107
|
+
for (int i = 0; i < set->cap; i++) {
|
|
108
|
+
unsigned int pos = (idx + (unsigned int)i) % (unsigned int)set->cap;
|
|
109
|
+
if (!set->keys[pos]) {
|
|
110
|
+
set->keys[pos] = strdup(key);
|
|
111
|
+
set->count++;
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
if (strcmp(set->keys[pos], key) == 0) return; /* already present */
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
static void set_grow(SnapSet *set) {
|
|
119
|
+
int old_cap = set->cap;
|
|
120
|
+
char **old_keys = set->keys;
|
|
121
|
+
set->cap *= 2;
|
|
122
|
+
set->keys = (char **)calloc((size_t)set->cap, sizeof(char *));
|
|
123
|
+
set->count = 0;
|
|
124
|
+
if (!set->keys) {
|
|
125
|
+
set->keys = old_keys;
|
|
126
|
+
set->cap = old_cap;
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
for (int i = 0; i < old_cap; i++) {
|
|
130
|
+
if (old_keys[i]) {
|
|
131
|
+
set_insert(set, old_keys[i]);
|
|
132
|
+
free(old_keys[i]);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
free(old_keys);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/* ── Helpers ────────────────────────────────────────────────────────── */
|
|
139
|
+
|
|
140
|
+
static int connect_socket(void) {
|
|
141
|
+
int fd = socket(AF_UNIX, SOCK_STREAM, 0);
|
|
142
|
+
if (fd < 0) return -1;
|
|
143
|
+
|
|
144
|
+
struct sockaddr_un addr;
|
|
145
|
+
memset(&addr, 0, sizeof(addr));
|
|
146
|
+
addr.sun_family = AF_UNIX;
|
|
147
|
+
strncpy(addr.sun_path, g_socket_path, sizeof(addr.sun_path) - 1);
|
|
148
|
+
|
|
149
|
+
if (connect(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
|
|
150
|
+
close(fd);
|
|
151
|
+
return -1;
|
|
152
|
+
}
|
|
153
|
+
return fd;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
static int ensure_socket(void) {
|
|
157
|
+
if (g_sock_fd >= 0) return 0;
|
|
158
|
+
g_sock_fd = connect_socket();
|
|
159
|
+
return g_sock_fd >= 0 ? 0 : -1;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
static int is_excluded(const char *abspath) {
|
|
163
|
+
/* Skip our own snapshot/object directories */
|
|
164
|
+
if (strncmp(abspath, g_atoo_dir, strlen(g_atoo_dir)) == 0) return 1;
|
|
165
|
+
/* Skip virtual filesystems */
|
|
166
|
+
if (strncmp(abspath, "/proc/", 6) == 0) return 1;
|
|
167
|
+
if (strncmp(abspath, "/sys/", 5) == 0) return 1;
|
|
168
|
+
if (strncmp(abspath, "/dev/", 5) == 0) return 1;
|
|
169
|
+
if (strncmp(abspath, "/tmp/", 5) == 0) return 1;
|
|
170
|
+
return 0;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/* Resolve a dirfd + pathname to an absolute path.
|
|
174
|
+
* Returns 0 on success, -1 on failure. Result written to buf. */
|
|
175
|
+
static int resolve_path(int dirfd, const char *pathname, char *buf, size_t bufsz) {
|
|
176
|
+
if (!pathname || !pathname[0]) return -1;
|
|
177
|
+
|
|
178
|
+
if (pathname[0] == '/') {
|
|
179
|
+
/* Already absolute */
|
|
180
|
+
if (realpath(pathname, buf)) return 0;
|
|
181
|
+
/* realpath fails if file doesn't exist yet — use as-is */
|
|
182
|
+
strncpy(buf, pathname, bufsz - 1);
|
|
183
|
+
buf[bufsz - 1] = '\0';
|
|
184
|
+
return 0;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
if (dirfd == AT_FDCWD) {
|
|
188
|
+
/* Relative to CWD */
|
|
189
|
+
char cwd[PATH_MAX];
|
|
190
|
+
if (!getcwd(cwd, sizeof(cwd))) return -1;
|
|
191
|
+
snprintf(buf, bufsz, "%s/%s", cwd, pathname);
|
|
192
|
+
/* Try to canonicalize */
|
|
193
|
+
char resolved[PATH_MAX];
|
|
194
|
+
if (realpath(buf, resolved)) {
|
|
195
|
+
strncpy(buf, resolved, bufsz - 1);
|
|
196
|
+
buf[bufsz - 1] = '\0';
|
|
197
|
+
}
|
|
198
|
+
return 0;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
/* Relative to dirfd — read link from /proc/self/fd/<dirfd> */
|
|
202
|
+
char fdpath[64];
|
|
203
|
+
snprintf(fdpath, sizeof(fdpath), "/proc/self/fd/%d", dirfd);
|
|
204
|
+
char dirpath[PATH_MAX];
|
|
205
|
+
ssize_t n = readlink(fdpath, dirpath, sizeof(dirpath) - 1);
|
|
206
|
+
if (n < 0) return -1;
|
|
207
|
+
dirpath[n] = '\0';
|
|
208
|
+
snprintf(buf, bufsz, "%s/%s", dirpath, pathname);
|
|
209
|
+
char resolved[PATH_MAX];
|
|
210
|
+
if (realpath(buf, resolved)) {
|
|
211
|
+
strncpy(buf, resolved, bufsz - 1);
|
|
212
|
+
buf[bufsz - 1] = '\0';
|
|
213
|
+
}
|
|
214
|
+
return 0;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
/* Copy a file using real_open to avoid recursive interception. */
|
|
218
|
+
static int copy_file(const char *src, const char *dst) {
|
|
219
|
+
int sfd = real_open(src, O_RDONLY);
|
|
220
|
+
if (sfd < 0) return -1;
|
|
221
|
+
|
|
222
|
+
int dfd = real_open(dst, O_WRONLY | O_CREAT | O_TRUNC, 0600);
|
|
223
|
+
if (dfd < 0) {
|
|
224
|
+
close(sfd);
|
|
225
|
+
return -1;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
char iobuf[65536];
|
|
229
|
+
ssize_t nr;
|
|
230
|
+
while ((nr = read(sfd, iobuf, sizeof(iobuf))) > 0) {
|
|
231
|
+
ssize_t written = 0;
|
|
232
|
+
while (written < nr) {
|
|
233
|
+
ssize_t nw = write(dfd, iobuf + written, (size_t)(nr - written));
|
|
234
|
+
if (nw < 0) {
|
|
235
|
+
close(sfd);
|
|
236
|
+
close(dfd);
|
|
237
|
+
return -1;
|
|
238
|
+
}
|
|
239
|
+
written += nw;
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
close(sfd);
|
|
244
|
+
close(dfd);
|
|
245
|
+
return nr < 0 ? -1 : 0;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
/* Ensure parent directories exist for a given path. */
|
|
249
|
+
static void ensure_parent_dirs(const char *filepath) {
|
|
250
|
+
char tmp[PATH_MAX];
|
|
251
|
+
strncpy(tmp, filepath, sizeof(tmp) - 1);
|
|
252
|
+
tmp[sizeof(tmp) - 1] = '\0';
|
|
253
|
+
|
|
254
|
+
for (char *p = tmp + 1; *p; p++) {
|
|
255
|
+
if (*p == '/') {
|
|
256
|
+
*p = '\0';
|
|
257
|
+
mkdir(tmp, 0755);
|
|
258
|
+
*p = '/';
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
/* Get current timestamp as fractional seconds. */
|
|
264
|
+
static double now_ts(void) {
|
|
265
|
+
struct timespec ts;
|
|
266
|
+
clock_gettime(CLOCK_REALTIME, &ts);
|
|
267
|
+
return (double)ts.tv_sec + (double)ts.tv_nsec / 1e9;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
/* Escape a string for JSON (minimal: handle \, ", control chars). */
|
|
271
|
+
static int json_escape(const char *src, char *dst, size_t dstsz) {
|
|
272
|
+
size_t di = 0;
|
|
273
|
+
for (const char *s = src; *s && di < dstsz - 6; s++) {
|
|
274
|
+
switch (*s) {
|
|
275
|
+
case '\\': dst[di++] = '\\'; dst[di++] = '\\'; break;
|
|
276
|
+
case '"': dst[di++] = '\\'; dst[di++] = '"'; break;
|
|
277
|
+
case '\n': dst[di++] = '\\'; dst[di++] = 'n'; break;
|
|
278
|
+
case '\r': dst[di++] = '\\'; dst[di++] = 'r'; break;
|
|
279
|
+
case '\t': dst[di++] = '\\'; dst[di++] = 't'; break;
|
|
280
|
+
default:
|
|
281
|
+
if ((unsigned char)*s < 0x20) {
|
|
282
|
+
di += (size_t)snprintf(dst + di, dstsz - di, "\\u%04x", (unsigned char)*s);
|
|
283
|
+
} else {
|
|
284
|
+
dst[di++] = *s;
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
dst[di] = '\0';
|
|
289
|
+
return (int)di;
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
/* Snapshot a file and send event to the monitor.
|
|
293
|
+
* op: "write", "rename", "delete", "truncate"
|
|
294
|
+
* path: absolute path of the target file
|
|
295
|
+
* old_path: for rename, the source path (NULL otherwise)
|
|
296
|
+
*/
|
|
297
|
+
static void snapshot_and_report(const char *op, const char *abspath, const char *old_path) {
|
|
298
|
+
if (!g_initialized) {
|
|
299
|
+
DBG("[atoo-studio-preload] SKIP (not initialized): %s %s\n", op, abspath);
|
|
300
|
+
return;
|
|
301
|
+
}
|
|
302
|
+
if (is_excluded(abspath)) {
|
|
303
|
+
DBG("[atoo-studio-preload] SKIP (excluded): %s %s\n", op, abspath);
|
|
304
|
+
return;
|
|
305
|
+
}
|
|
306
|
+
/* Don't exclude based on old_path — atomic writes rename from /tmp/ to final path */
|
|
307
|
+
|
|
308
|
+
DBG("[atoo-studio-preload] EVENT: %s %s (old=%s)\n", op, abspath, old_path ? old_path : "none");
|
|
309
|
+
|
|
310
|
+
pthread_mutex_lock(&g_mutex);
|
|
311
|
+
|
|
312
|
+
/* Check if already snapshotted this path */
|
|
313
|
+
if (set_contains(&g_snapped, abspath)) {
|
|
314
|
+
DBG("[atoo-studio-preload] SKIP (already snapshotted): %s\n", abspath);
|
|
315
|
+
pthread_mutex_unlock(&g_mutex);
|
|
316
|
+
return;
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
/* Check if file exists before the operation */
|
|
320
|
+
struct stat st;
|
|
321
|
+
int file_existed = (stat(abspath, &st) == 0 && S_ISREG(st.st_mode));
|
|
322
|
+
|
|
323
|
+
/* Snapshot the original if it exists */
|
|
324
|
+
char snap_path[PATH_MAX];
|
|
325
|
+
snap_path[0] = '\0';
|
|
326
|
+
|
|
327
|
+
if (file_existed) {
|
|
328
|
+
uint64_t cnt = g_counter++;
|
|
329
|
+
snprintf(snap_path, sizeof(snap_path), "%s/%d_%lu",
|
|
330
|
+
g_snapshot_dir, (int)getpid(), (unsigned long)cnt);
|
|
331
|
+
ensure_parent_dirs(snap_path);
|
|
332
|
+
|
|
333
|
+
if (copy_file(abspath, snap_path) < 0) {
|
|
334
|
+
snap_path[0] = '\0'; /* failed to snapshot */
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
/* Mark as snapshotted */
|
|
339
|
+
set_insert(&g_snapped, abspath);
|
|
340
|
+
|
|
341
|
+
/* Build JSON event */
|
|
342
|
+
char epath[PATH_MAX * 2], eold[PATH_MAX * 2], esnap[PATH_MAX * 2];
|
|
343
|
+
json_escape(abspath, epath, sizeof(epath));
|
|
344
|
+
if (old_path) json_escape(old_path, eold, sizeof(eold));
|
|
345
|
+
if (snap_path[0]) json_escape(snap_path, esnap, sizeof(esnap));
|
|
346
|
+
|
|
347
|
+
char msg[PATH_MAX * 8];
|
|
348
|
+
int len = snprintf(msg, sizeof(msg),
|
|
349
|
+
"{\"session_id\":\"%s\",\"op\":\"%s\",\"path\":\"%s\"",
|
|
350
|
+
g_session_id, op, epath);
|
|
351
|
+
|
|
352
|
+
if (old_path) {
|
|
353
|
+
len += snprintf(msg + len, sizeof(msg) - (size_t)len,
|
|
354
|
+
",\"old_path\":\"%s\"", eold);
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
if (snap_path[0]) {
|
|
358
|
+
len += snprintf(msg + len, sizeof(msg) - (size_t)len,
|
|
359
|
+
",\"snapshot\":\"%s\"", esnap);
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
len += snprintf(msg + len, sizeof(msg) - (size_t)len,
|
|
363
|
+
",\"file_existed\":%s,\"ts\":%.3f}\n",
|
|
364
|
+
file_existed ? "true" : "false", now_ts());
|
|
365
|
+
|
|
366
|
+
/* Send to socket */
|
|
367
|
+
if (ensure_socket() == 0) {
|
|
368
|
+
ssize_t wr = write(g_sock_fd, msg, (size_t)len);
|
|
369
|
+
if (wr < 0) {
|
|
370
|
+
DBG("[atoo-studio-preload] SOCKET WRITE FAILED: %s\n", strerror(errno));
|
|
371
|
+
/* Connection lost, close and let next call retry */
|
|
372
|
+
close(g_sock_fd);
|
|
373
|
+
g_sock_fd = -1;
|
|
374
|
+
} else {
|
|
375
|
+
DBG("[atoo-studio-preload] SENT %zd bytes to socket\n", wr);
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
pthread_mutex_unlock(&g_mutex);
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
/* ── Constructor ────────────────────────────────────────────────────── */
|
|
383
|
+
|
|
384
|
+
__attribute__((constructor))
|
|
385
|
+
static void preload_init(void) {
|
|
386
|
+
/* Resolve real functions */
|
|
387
|
+
real_open = dlsym(RTLD_NEXT, "open");
|
|
388
|
+
real_open64 = dlsym(RTLD_NEXT, "open64");
|
|
389
|
+
real_openat = dlsym(RTLD_NEXT, "openat");
|
|
390
|
+
real_openat64 = dlsym(RTLD_NEXT, "openat64");
|
|
391
|
+
real_creat = dlsym(RTLD_NEXT, "creat");
|
|
392
|
+
real_rename = dlsym(RTLD_NEXT, "rename");
|
|
393
|
+
real_renameat = dlsym(RTLD_NEXT, "renameat");
|
|
394
|
+
real_renameat2 = dlsym(RTLD_NEXT, "renameat2");
|
|
395
|
+
real_unlink = dlsym(RTLD_NEXT, "unlink");
|
|
396
|
+
real_unlinkat = dlsym(RTLD_NEXT, "unlinkat");
|
|
397
|
+
real_truncate = dlsym(RTLD_NEXT, "truncate");
|
|
398
|
+
real_ftruncate = dlsym(RTLD_NEXT, "ftruncate");
|
|
399
|
+
|
|
400
|
+
/* Read config from environment */
|
|
401
|
+
const char *dbg = getenv("ATOO_PRELOAD_DEBUG");
|
|
402
|
+
g_debug = (dbg && dbg[0] == '1');
|
|
403
|
+
|
|
404
|
+
const char *sid = getenv("ATOO_SESSION_ID");
|
|
405
|
+
if (!sid || !sid[0]) return; /* Not configured — pass through */
|
|
406
|
+
|
|
407
|
+
strncpy(g_session_id, sid, sizeof(g_session_id) - 1);
|
|
408
|
+
|
|
409
|
+
const char *sock = getenv("ATOO_SOCKET_PATH");
|
|
410
|
+
if (sock && sock[0]) {
|
|
411
|
+
strncpy(g_socket_path, sock, sizeof(g_socket_path) - 1);
|
|
412
|
+
} else {
|
|
413
|
+
const char *home = getenv("HOME");
|
|
414
|
+
if (!home) return;
|
|
415
|
+
snprintf(g_socket_path, sizeof(g_socket_path), "%s/.atoo-studio/preload.sock", home);
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
/* Set up atoo-studio dir for exclusion */
|
|
419
|
+
const char *home = getenv("HOME");
|
|
420
|
+
if (home) {
|
|
421
|
+
snprintf(g_atoo_dir, sizeof(g_atoo_dir), "%s/.atoo-studio/", home);
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
/* Set up snapshot directory */
|
|
425
|
+
snprintf(g_snapshot_dir, sizeof(g_snapshot_dir), "%s/.atoo-studio/snapshots/%s",
|
|
426
|
+
home ? home : "/tmp", g_session_id);
|
|
427
|
+
|
|
428
|
+
/* Create snapshot directory (best effort) */
|
|
429
|
+
in_hook = 1;
|
|
430
|
+
ensure_parent_dirs(g_snapshot_dir);
|
|
431
|
+
mkdir(g_snapshot_dir, 0755);
|
|
432
|
+
in_hook = 0;
|
|
433
|
+
|
|
434
|
+
/* Try to connect (non-fatal if fails) */
|
|
435
|
+
g_sock_fd = connect_socket();
|
|
436
|
+
|
|
437
|
+
g_initialized = 1;
|
|
438
|
+
DBG("[atoo-studio-preload] INIT pid=%d session=%s socket=%s connected=%d\n",
|
|
439
|
+
(int)getpid(), g_session_id, g_socket_path, g_sock_fd >= 0);
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
/* ── Intercepted functions ──────────────────────────────────────────── */
|
|
443
|
+
|
|
444
|
+
int open(const char *pathname, int flags, ...) {
|
|
445
|
+
mode_t mode = 0;
|
|
446
|
+
if (flags & (O_CREAT | O_TMPFILE)) {
|
|
447
|
+
va_list ap;
|
|
448
|
+
va_start(ap, flags);
|
|
449
|
+
mode = (mode_t)va_arg(ap, int);
|
|
450
|
+
va_end(ap);
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
if (!in_hook && g_initialized && (flags & (O_WRONLY | O_RDWR | O_TRUNC | O_CREAT))) {
|
|
454
|
+
in_hook = 1;
|
|
455
|
+
char abspath[PATH_MAX];
|
|
456
|
+
if (pathname && resolve_path(AT_FDCWD, pathname, abspath, sizeof(abspath)) == 0) {
|
|
457
|
+
snapshot_and_report("write", abspath, NULL);
|
|
458
|
+
}
|
|
459
|
+
in_hook = 0;
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
return real_open(pathname, flags, mode);
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
int openat(int dirfd, const char *pathname, int flags, ...) {
|
|
466
|
+
mode_t mode = 0;
|
|
467
|
+
if (flags & (O_CREAT | O_TMPFILE)) {
|
|
468
|
+
va_list ap;
|
|
469
|
+
va_start(ap, flags);
|
|
470
|
+
mode = (mode_t)va_arg(ap, int);
|
|
471
|
+
va_end(ap);
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
if (!in_hook && g_initialized && (flags & (O_WRONLY | O_RDWR | O_TRUNC | O_CREAT))) {
|
|
475
|
+
in_hook = 1;
|
|
476
|
+
char abspath[PATH_MAX];
|
|
477
|
+
if (pathname && resolve_path(dirfd, pathname, abspath, sizeof(abspath)) == 0) {
|
|
478
|
+
snapshot_and_report("write", abspath, NULL);
|
|
479
|
+
}
|
|
480
|
+
in_hook = 0;
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
return real_openat(dirfd, pathname, flags, mode);
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
int open64(const char *pathname, int flags, ...) {
|
|
487
|
+
mode_t mode = 0;
|
|
488
|
+
if (flags & (O_CREAT | O_TMPFILE)) {
|
|
489
|
+
va_list ap;
|
|
490
|
+
va_start(ap, flags);
|
|
491
|
+
mode = (mode_t)va_arg(ap, int);
|
|
492
|
+
va_end(ap);
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
if (!in_hook && g_initialized && (flags & (O_WRONLY | O_RDWR | O_TRUNC | O_CREAT))) {
|
|
496
|
+
in_hook = 1;
|
|
497
|
+
char abspath[PATH_MAX];
|
|
498
|
+
if (resolve_path(AT_FDCWD, pathname, abspath, sizeof(abspath)) == 0) {
|
|
499
|
+
snapshot_and_report("write", abspath, NULL);
|
|
500
|
+
}
|
|
501
|
+
in_hook = 0;
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
return real_open64 ? real_open64(pathname, flags, mode) : real_open(pathname, flags, mode);
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
int openat64(int dirfd, const char *pathname, int flags, ...) {
|
|
508
|
+
mode_t mode = 0;
|
|
509
|
+
if (flags & (O_CREAT | O_TMPFILE)) {
|
|
510
|
+
va_list ap;
|
|
511
|
+
va_start(ap, flags);
|
|
512
|
+
mode = (mode_t)va_arg(ap, int);
|
|
513
|
+
va_end(ap);
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
if (!in_hook && g_initialized && (flags & (O_WRONLY | O_RDWR | O_TRUNC | O_CREAT))) {
|
|
517
|
+
in_hook = 1;
|
|
518
|
+
char abspath[PATH_MAX];
|
|
519
|
+
if (resolve_path(dirfd, pathname, abspath, sizeof(abspath)) == 0) {
|
|
520
|
+
snapshot_and_report("write", abspath, NULL);
|
|
521
|
+
}
|
|
522
|
+
in_hook = 0;
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
return real_openat64 ? real_openat64(dirfd, pathname, flags, mode) : real_openat(dirfd, pathname, flags, mode);
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
int creat(const char *pathname, mode_t mode) {
|
|
529
|
+
if (!in_hook && g_initialized) {
|
|
530
|
+
in_hook = 1;
|
|
531
|
+
char abspath[PATH_MAX];
|
|
532
|
+
if (pathname && resolve_path(AT_FDCWD, pathname, abspath, sizeof(abspath)) == 0) {
|
|
533
|
+
snapshot_and_report("write", abspath, NULL);
|
|
534
|
+
}
|
|
535
|
+
in_hook = 0;
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
return real_creat(pathname, mode);
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
int rename(const char *oldpath, const char *newpath) {
|
|
542
|
+
if (!in_hook && g_initialized) {
|
|
543
|
+
in_hook = 1;
|
|
544
|
+
char abs_new[PATH_MAX];
|
|
545
|
+
char abs_old[PATH_MAX];
|
|
546
|
+
int new_ok = newpath && resolve_path(AT_FDCWD, newpath, abs_new, sizeof(abs_new)) == 0;
|
|
547
|
+
int old_ok = oldpath && resolve_path(AT_FDCWD, oldpath, abs_old, sizeof(abs_old)) == 0;
|
|
548
|
+
if (new_ok) {
|
|
549
|
+
snapshot_and_report("rename", abs_new, old_ok ? abs_old : NULL);
|
|
550
|
+
}
|
|
551
|
+
in_hook = 0;
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
return real_rename(oldpath, newpath);
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
int renameat(int olddirfd, const char *oldpath, int newdirfd, const char *newpath) {
|
|
558
|
+
if (!in_hook && g_initialized) {
|
|
559
|
+
in_hook = 1;
|
|
560
|
+
char abs_new[PATH_MAX];
|
|
561
|
+
char abs_old[PATH_MAX];
|
|
562
|
+
int new_ok = newpath && resolve_path(newdirfd, newpath, abs_new, sizeof(abs_new)) == 0;
|
|
563
|
+
int old_ok = oldpath && resolve_path(olddirfd, oldpath, abs_old, sizeof(abs_old)) == 0;
|
|
564
|
+
if (new_ok) {
|
|
565
|
+
snapshot_and_report("rename", abs_new, old_ok ? abs_old : NULL);
|
|
566
|
+
}
|
|
567
|
+
in_hook = 0;
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
return real_renameat(olddirfd, oldpath, newdirfd, newpath);
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
int renameat2(int olddirfd, const char *oldpath, int newdirfd, const char *newpath, unsigned int flags) {
|
|
574
|
+
if (!in_hook && g_initialized && real_renameat2) {
|
|
575
|
+
in_hook = 1;
|
|
576
|
+
char abs_new[PATH_MAX];
|
|
577
|
+
char abs_old[PATH_MAX];
|
|
578
|
+
int new_ok = newpath && resolve_path(newdirfd, newpath, abs_new, sizeof(abs_new)) == 0;
|
|
579
|
+
int old_ok = oldpath && resolve_path(olddirfd, oldpath, abs_old, sizeof(abs_old)) == 0;
|
|
580
|
+
if (new_ok) {
|
|
581
|
+
snapshot_and_report("rename", abs_new, old_ok ? abs_old : NULL);
|
|
582
|
+
}
|
|
583
|
+
in_hook = 0;
|
|
584
|
+
}
|
|
585
|
+
|
|
586
|
+
if (real_renameat2) return real_renameat2(olddirfd, oldpath, newdirfd, newpath, flags);
|
|
587
|
+
/* Fallback if renameat2 not available */
|
|
588
|
+
errno = ENOSYS;
|
|
589
|
+
return -1;
|
|
590
|
+
}
|
|
591
|
+
|
|
592
|
+
int unlink(const char *pathname) {
|
|
593
|
+
if (!in_hook && g_initialized) {
|
|
594
|
+
in_hook = 1;
|
|
595
|
+
char abspath[PATH_MAX];
|
|
596
|
+
if (pathname && resolve_path(AT_FDCWD, pathname, abspath, sizeof(abspath)) == 0) {
|
|
597
|
+
snapshot_and_report("delete", abspath, NULL);
|
|
598
|
+
}
|
|
599
|
+
in_hook = 0;
|
|
600
|
+
}
|
|
601
|
+
|
|
602
|
+
return real_unlink(pathname);
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
int unlinkat(int dirfd, const char *pathname, int flags) {
|
|
606
|
+
if (!in_hook && g_initialized && !(flags & AT_REMOVEDIR)) {
|
|
607
|
+
in_hook = 1;
|
|
608
|
+
char abspath[PATH_MAX];
|
|
609
|
+
if (pathname && resolve_path(dirfd, pathname, abspath, sizeof(abspath)) == 0) {
|
|
610
|
+
snapshot_and_report("delete", abspath, NULL);
|
|
611
|
+
}
|
|
612
|
+
in_hook = 0;
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
return real_unlinkat(dirfd, pathname, flags);
|
|
616
|
+
}
|
|
617
|
+
|
|
618
|
+
int truncate(const char *path, off_t length) {
|
|
619
|
+
if (!in_hook && g_initialized) {
|
|
620
|
+
in_hook = 1;
|
|
621
|
+
char abspath[PATH_MAX];
|
|
622
|
+
if (path && resolve_path(AT_FDCWD, path, abspath, sizeof(abspath)) == 0) {
|
|
623
|
+
snapshot_and_report("truncate", abspath, NULL);
|
|
624
|
+
}
|
|
625
|
+
in_hook = 0;
|
|
626
|
+
}
|
|
627
|
+
|
|
628
|
+
return real_truncate(path, length);
|
|
629
|
+
}
|
|
630
|
+
|
|
631
|
+
int ftruncate(int fd, off_t length) {
|
|
632
|
+
if (!in_hook && g_initialized) {
|
|
633
|
+
in_hook = 1;
|
|
634
|
+
/* Resolve fd to path via /proc/self/fd/<fd> */
|
|
635
|
+
char fdlink[64];
|
|
636
|
+
char abspath[PATH_MAX];
|
|
637
|
+
snprintf(fdlink, sizeof(fdlink), "/proc/self/fd/%d", fd);
|
|
638
|
+
ssize_t n = readlink(fdlink, abspath, sizeof(abspath) - 1);
|
|
639
|
+
if (n > 0) {
|
|
640
|
+
abspath[n] = '\0';
|
|
641
|
+
snapshot_and_report("truncate", abspath, NULL);
|
|
642
|
+
}
|
|
643
|
+
in_hook = 0;
|
|
644
|
+
}
|
|
645
|
+
|
|
646
|
+
return real_ftruncate(fd, length);
|
|
647
|
+
}
|
|
Binary file
|