Compare commits
56
Commits
jo-so/readme
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b20483dd9a | ||
|
|
8020dbd8fc | ||
|
|
b7e1c37e14 | ||
|
|
2f6547f873 | ||
|
|
48dbfaf34a | ||
|
|
b09e018894 | ||
|
|
3bc2b310a3 | ||
|
|
963e3511fe | ||
|
|
d5289cfd89 | ||
|
|
ddaa6b190f | ||
|
|
15020ec20a | ||
|
|
fcb15624db | ||
|
|
db43c7c9cf | ||
|
|
3e344b360f | ||
|
|
5527d390eb | ||
|
|
6f44d95070 | ||
|
|
32d21c8074 | ||
|
|
eb337a1351 | ||
|
|
48186df8af | ||
|
|
c14650010e | ||
|
|
2d3bd9432f | ||
|
|
1a2d3ad643 | ||
|
|
7cccf2b56d | ||
|
|
d31988a829 | ||
|
|
b12c06568c | ||
|
|
e0de64c047 | ||
|
|
bc3efd48c2 | ||
|
|
cd6239737a | ||
|
|
97293f3cc1 | ||
|
|
76caf7e1d7 | ||
|
|
3527282950 | ||
|
|
d2502086ed | ||
|
|
c5110830f7 | ||
|
|
d81b72fed7 | ||
|
|
bd8d53906a | ||
|
|
acbb764ac5 | ||
|
|
45602d27c8 | ||
|
|
6706f4b9d7 | ||
|
|
b1c88db1ce | ||
|
|
688c84fd58 | ||
|
|
367697d59e | ||
|
|
77e222fb16 | ||
|
|
821c7c0bc2 | ||
|
|
854b4b0a6c | ||
|
|
6d5af57ebc | ||
|
|
a80ff8e855 | ||
|
|
3e51f7f56e | ||
|
|
e1ee7f0b0c | ||
|
|
337d066eeb | ||
|
|
4db9bb3cba | ||
|
|
489159c5f9 | ||
|
|
9c2d8fcd83 | ||
|
|
098036cca9 | ||
|
|
212135d3c8 | ||
|
|
7b5c7f64c0 | ||
|
|
b80dcf171f |
@@ -105,4 +105,7 @@ venv.bak/
|
|||||||
# mypy
|
# mypy
|
||||||
.mypy_cache/
|
.mypy_cache/
|
||||||
|
|
||||||
|
# nix
|
||||||
|
result*
|
||||||
|
|
||||||
test.py
|
test.py
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
# Waydroid Extras Script
|
# Waydroid Extras Script
|
||||||
Script to add gapps and other stuff to waydroid !
|
|
||||||
|
Script to add GApps and other stuff to Waydroid!
|
||||||
|
|
||||||
# Installation/Usage
|
# Installation/Usage
|
||||||
|
|
||||||
@@ -8,8 +9,9 @@ Script to add gapps and other stuff to waydroid !
|
|||||||
```
|
```
|
||||||
git clone https://github.com/casualsnek/waydroid_script
|
git clone https://github.com/casualsnek/waydroid_script
|
||||||
cd waydroid_script
|
cd waydroid_script
|
||||||
sudo python3 -m pip install -r
|
python3 -m venv venv
|
||||||
sudo python main.py
|
venv/bin/pip install -r requirements.txt
|
||||||
|
sudo venv/bin/python3 main.py
|
||||||
```
|
```
|
||||||
|
|
||||||

|

|
||||||
@@ -22,17 +24,20 @@ sudo python main.py
|
|||||||
|
|
||||||
## Command Line
|
## Command Line
|
||||||
|
|
||||||
|
```bash
|
||||||
git clone https://github.com/casualsnek/waydroid_script
|
git clone https://github.com/casualsnek/waydroid_script
|
||||||
cd waydroid_script
|
cd waydroid_script
|
||||||
sudo python3 -m pip install -r requirements.txt
|
python3 -m venv venv
|
||||||
|
venv/bin/pip install -r requirements.txt
|
||||||
# install something
|
# install something
|
||||||
sudo python3 main.py install {gapps, magisk, libndk, libhoudini, nodataperm, smartdock, microg}
|
sudo venv/bin/python3 main.py install {gapps, magisk, libndk, libhoudini, nodataperm, smartdock, microg, mitm}
|
||||||
# uninstall something
|
# uninstall something
|
||||||
sudo python3 main.py uninstall {gapps, magisk, libndk, libhoudini, nodataperm, smartdock, microg}
|
sudo venv/bin/python3 main.py uninstall {gapps, magisk, libndk, libhoudini, nodataperm, smartdock, microg}
|
||||||
# get Android device ID
|
# get Android device ID
|
||||||
sudo python main.py certified
|
sudo venv/bin/python3 main.py certified
|
||||||
# some hacks
|
# some hacks
|
||||||
sudo python3 hack {nodataperm, hidestatusbar}
|
sudo venv/bin/python3 main.py hack {nodataperm, hidestatusbar}
|
||||||
|
```
|
||||||
|
|
||||||
## Dependencies
|
## Dependencies
|
||||||
|
|
||||||
@@ -50,18 +55,19 @@ sudo python main.py
|
|||||||
|
|
||||||

|

|
||||||
|
|
||||||
Open terminal and switch to directory where "main.py" is located then run:
|
Open terminal and switch to the directory where "main.py" is located then run:
|
||||||
|
|
||||||
sudo python3 main.py install gapps
|
sudo venv/bin/python3 main.py install gapps
|
||||||
|
|
||||||
Then launch waydroid with:
|
Then launch waydroid with:
|
||||||
|
|
||||||
waydroid show-full-ui
|
waydroid show-full-ui
|
||||||
|
|
||||||
After waydroid has finished booting open terminal and switch to directory where "main.py" is located then run:
|
After waydroid has finished booting, open terminal and switch to directory where "main.py" is located then run:
|
||||||
|
|
||||||
sudo python3 main.py google
|
sudo python3 main.py google
|
||||||
Copy the returned numeric ID open ["https://google.com/android/uncertified/?pli=1"](https://google.com/android/uncertified/?pli=1) enter the id and register it, you may need to wait upto 10-20 minutes for device to get registered, then clear Google Play Service's cache and try logging in !
|
Copy the returned numeric ID, then open ["https://google.com/android/uncertified/?pli=1"](https://google.com/android/uncertified/?pli=1). Enter the ID and register it. Wait 10-20 minutes for device to get registered. Then clear Google Play Service's cache and try logging in!
|
||||||
|
|
||||||
|
|
||||||
## Install Magisk
|
## Install Magisk
|
||||||
|
|
||||||
@@ -69,7 +75,7 @@ Copy the returned numeric ID open ["https://google.com/android/uncertified/?pli=
|
|||||||
|
|
||||||
Open terminal and switch to directory where "main.py" is located then run:
|
Open terminal and switch to directory where "main.py" is located then run:
|
||||||
|
|
||||||
sudo python3 main.py install magisk
|
sudo venv/bin/python3 main.py install magisk
|
||||||
|
|
||||||
Magisk will be installed on next boot!
|
Magisk will be installed on next boot!
|
||||||
|
|
||||||
@@ -87,7 +93,7 @@ libndk seems to have better performance than libhoudini on AMD.
|
|||||||
|
|
||||||
Open terminal and switch to directory where "main.py" is located then run:
|
Open terminal and switch to directory where "main.py" is located then run:
|
||||||
|
|
||||||
sudo python3 main.py install libndk
|
sudo venv/bin/python3 main.py install libndk
|
||||||
|
|
||||||
## Install libhoudini arm translation
|
## Install libhoudini arm translation
|
||||||
|
|
||||||
@@ -99,7 +105,7 @@ houdini64 version: 11.0.1b_z.38765.m
|
|||||||
|
|
||||||
Open terminal and switch to directory where "main.py" is located then run:
|
Open terminal and switch to directory where "main.py" is located then run:
|
||||||
|
|
||||||
sudo python3 main.py install libhoudini
|
sudo venv/bin/python3 main.py install libhoudini
|
||||||
|
|
||||||
## Integrate Widevine DRM (L3)
|
## Integrate Widevine DRM (L3)
|
||||||
|
|
||||||
@@ -107,7 +113,7 @@ Open terminal and switch to directory where "main.py" is located then run:
|
|||||||
|
|
||||||
Open terminal and switch to directory where "main.py" is located then run:
|
Open terminal and switch to directory where "main.py" is located then run:
|
||||||
|
|
||||||
sudo python3 main.py install widevine
|
sudo venv/bin/python3 main.py install widevine
|
||||||
|
|
||||||
## Install Smart Dock
|
## Install Smart Dock
|
||||||
|
|
||||||
@@ -116,7 +122,13 @@ Open terminal and switch to directory where "main.py" is located then run:
|
|||||||
|
|
||||||
Open terminal and switch to directory where "main.py" is located then run:
|
Open terminal and switch to directory where "main.py" is located then run:
|
||||||
|
|
||||||
sudo python3 main.py install smartdock
|
sudo venv/bin/python3 main.py install smartdock
|
||||||
|
|
||||||
|
## Install a self-signed CA certificate
|
||||||
|
|
||||||
|
Open terminal and switch to directory where "main.py" is located then run:
|
||||||
|
|
||||||
|
sudo venv/bin/python3 main.py install mitm --ca-cert mycert.pem
|
||||||
|
|
||||||
## Granting full permission for apps data (HACK)
|
## Granting full permission for apps data (HACK)
|
||||||
|
|
||||||
@@ -130,9 +142,9 @@ Arknights, PUNISHING: GRAY RAVEN and other games won't freeze on the black scree
|
|||||||
Open terminal and switch to directory where "main.py" is located then run:
|
Open terminal and switch to directory where "main.py" is located then run:
|
||||||
|
|
||||||
```
|
```
|
||||||
sudo python3 main.py hack nodataperm
|
sudo venv/bin/python3 main.py hack nodataperm
|
||||||
```
|
```
|
||||||
**WARNING**: Tested on `lineage-18.1-20230128-VANILLA-waydroid_x86_64.img`. This script will replace `/system/framework/service.jar`, which may prevent WayDroid from booting. If so, run `sudo python3 main.py uninstall nodataperm` to remove it.
|
**WARNING**: Tested on `lineage-18.1-20230128-VANILLA-waydroid_x86_64.img`. This script will replace `/system/framework/service.jar`, which may prevent WayDroid from booting. If so, run `sudo venv/bin/python3 main.py uninstall nodataperm` to remove it.
|
||||||
|
|
||||||
|
|
||||||
Or you can run the following commands directly in `sudo waydroid shell`. In this way, every time a new game is installed, you need to run it again, but it's much less risky.
|
Or you can run the following commands directly in `sudo waydroid shell`. In this way, every time a new game is installed, you need to run it again, but it's much less risky.
|
||||||
@@ -154,7 +166,7 @@ chmod 777 -R /mnt/*/*/*/*/Android/obb
|
|||||||

|

|
||||||
|
|
||||||
```
|
```
|
||||||
sudo python main.py install microg
|
sudo venv/bin/python3 main.py install microg
|
||||||
```
|
```
|
||||||
|
|
||||||
## Hide Status Bar
|
## Hide Status Bar
|
||||||
@@ -165,18 +177,18 @@ After
|
|||||||

|

|
||||||
|
|
||||||
```
|
```
|
||||||
sudo python3 main.py hack hidestatusbar
|
sudo venv/bin/python3 main.py hack hidestatusbar
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
## Get Android ID for device registration
|
## Get Android ID for device registration
|
||||||
|
|
||||||
You need to register you device with its it before being able to use gapps, this will print out your Android ID which you can use for device registration required for google apps:
|
You need to register you device with its it before being able to use gapps, this will print out your Android ID which you can use for device registration required for Google apps:
|
||||||
Open terminal and switch to directory where "main.py" is located then run:
|
Open terminal and switch to directory where "main.py" is located then run:
|
||||||
|
|
||||||
sudo python3 main.py google
|
sudo venv/bin/python3 main.py certified
|
||||||
|
|
||||||
Star this repository if you find this useful, if you encounter problem create a issue on github !
|
Star this repository if you find this useful, if you encounter problem create an issue on GitHub!
|
||||||
|
|
||||||
## Error handling
|
## Error handling
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,4 @@
|
|||||||
|
let
|
||||||
|
pkgs = import <nixpkgs> {};
|
||||||
|
in
|
||||||
|
pkgs.callPackage ./package.nix { }
|
||||||
Generated
+41
@@ -0,0 +1,41 @@
|
|||||||
|
{
|
||||||
|
"nodes": {
|
||||||
|
"nixpkgs": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1707650010,
|
||||||
|
"narHash": "sha256-dOhphIA4MGrH4ElNCy/OlwmN24MsnEqFjRR6+RY7jZw=",
|
||||||
|
"owner": "NixOS",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"rev": "809cca784b9f72a5ad4b991e0e7bcf8890f9c3a6",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"id": "nixpkgs",
|
||||||
|
"type": "indirect"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"root": {
|
||||||
|
"inputs": {
|
||||||
|
"nixpkgs": "nixpkgs",
|
||||||
|
"systems": "systems"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"systems": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1681028828,
|
||||||
|
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
||||||
|
"owner": "nix-systems",
|
||||||
|
"repo": "default",
|
||||||
|
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "nix-systems",
|
||||||
|
"repo": "default",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"root": "root",
|
||||||
|
"version": 7
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
{
|
||||||
|
description = "Waydroid Extras Script";
|
||||||
|
inputs = {
|
||||||
|
systems.url = "github:nix-systems/default";
|
||||||
|
};
|
||||||
|
outputs = { self, nixpkgs, systems }:
|
||||||
|
let
|
||||||
|
inherit (nixpkgs) lib;
|
||||||
|
eachSystem = lib.genAttrs (import systems);
|
||||||
|
mkApp = program: { type = "app"; inherit program; };
|
||||||
|
in {
|
||||||
|
packages = eachSystem (system: rec {
|
||||||
|
waydroid_script = nixpkgs.legacyPackages."${system}".callPackage ./package.nix { };
|
||||||
|
default = waydroid_script;
|
||||||
|
});
|
||||||
|
apps = eachSystem (system: rec {
|
||||||
|
waydroid_script = mkApp "${self.outputs.packages.${system}.waydroid_script}/bin/waydroid_script";
|
||||||
|
default = waydroid_script;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -12,10 +12,13 @@ from stuff.hidestatusbar import HideStatusBar
|
|||||||
from stuff.houdini import Houdini
|
from stuff.houdini import Houdini
|
||||||
from stuff.magisk import Magisk
|
from stuff.magisk import Magisk
|
||||||
from stuff.microg import MicroG
|
from stuff.microg import MicroG
|
||||||
|
from stuff.mitm import Mitm
|
||||||
from stuff.ndk import Ndk
|
from stuff.ndk import Ndk
|
||||||
from stuff.nodataperm import Nodataperm
|
from stuff.nodataperm import Nodataperm
|
||||||
from stuff.smartdock import Smartdock
|
from stuff.smartdock import Smartdock
|
||||||
from stuff.widevine import Widevine
|
from stuff.widevine import Widevine
|
||||||
|
from stuff.fdroidpriv import FDroidPriv
|
||||||
|
from stuff.device_spoof import DeviceSpoof, PROFILES
|
||||||
import tools.helper as helper
|
import tools.helper as helper
|
||||||
from tools import container
|
from tools import container
|
||||||
from tools import images
|
from tools import images
|
||||||
@@ -82,7 +85,13 @@ def install_app(args):
|
|||||||
if "smartdock" in app:
|
if "smartdock" in app:
|
||||||
install_list.append(Smartdock())
|
install_list.append(Smartdock())
|
||||||
if "microg" in app:
|
if "microg" in app:
|
||||||
install_list.append(MicroG(args.android_version))
|
install_list.append(MicroG(args.android_version, args.microg_variant))
|
||||||
|
if "mitm" in app:
|
||||||
|
install_list.append(Mitm(args.ca_cert_file))
|
||||||
|
if "fdroidpriv" in app:
|
||||||
|
install_list.append(FDroidPriv(args.android_version))
|
||||||
|
if "device_spoof" in app:
|
||||||
|
DeviceSpoof(getattr(args, "spoof_profile", "pixel6")).install()
|
||||||
|
|
||||||
if not container.use_overlayfs():
|
if not container.use_overlayfs():
|
||||||
copy_dir = "/tmp/waydroid"
|
copy_dir = "/tmp/waydroid"
|
||||||
@@ -130,6 +139,12 @@ def remove_app(args):
|
|||||||
remove_list.append(Smartdock())
|
remove_list.append(Smartdock())
|
||||||
if "microg" in app:
|
if "microg" in app:
|
||||||
remove_list.append(MicroG(args.android_version, args.microg_variant))
|
remove_list.append(MicroG(args.android_version, args.microg_variant))
|
||||||
|
if "mitm" in app:
|
||||||
|
remove_list.append(Mitm())
|
||||||
|
if "fdroidpriv" in app:
|
||||||
|
remove_list.append(FDroidPriv(args.android_version))
|
||||||
|
if "device_spoof" in app:
|
||||||
|
DeviceSpoof().uninstall()
|
||||||
if "nodataperm" in app:
|
if "nodataperm" in app:
|
||||||
remove_list.append(Nodataperm(args.android_version))
|
remove_list.append(Nodataperm(args.android_version))
|
||||||
if "hidestatusbar" in app:
|
if "hidestatusbar" in app:
|
||||||
@@ -200,7 +215,7 @@ def interact():
|
|||||||
Choice(name="Android 13", value="13"),
|
Choice(name="Android 13", value="13"),
|
||||||
Choice(name="Exit", value=None)
|
Choice(name="Exit", value=None)
|
||||||
],
|
],
|
||||||
default="11",
|
default="13",
|
||||||
).execute()
|
).execute()
|
||||||
if not android_version:
|
if not android_version:
|
||||||
exit()
|
exit()
|
||||||
@@ -219,10 +234,9 @@ def interact():
|
|||||||
if not action:
|
if not action:
|
||||||
exit()
|
exit()
|
||||||
|
|
||||||
install_choices = ["gapps", "microg", "libndk", "magisk", "smartdock",]
|
install_choices = ["gapps", "microg", "libndk", "libhoudini", "magisk", "smartdock", "fdroidpriv", "widevine", "device_spoof"]
|
||||||
hack_choices = []
|
hack_choices = []
|
||||||
if android_version=="11":
|
if android_version=="11":
|
||||||
install_choices.extend(["libhoudini", "widevine"])
|
|
||||||
hack_choices.extend(["nodataperm", "hidestatusbar"])
|
hack_choices.extend(["nodataperm", "hidestatusbar"])
|
||||||
|
|
||||||
if action == "Install":
|
if action == "Install":
|
||||||
@@ -235,13 +249,20 @@ def interact():
|
|||||||
).execute()
|
).execute()
|
||||||
microg_variants = ["Standard", "NoGoolag",
|
microg_variants = ["Standard", "NoGoolag",
|
||||||
"UNLP", "Minimal", "MinimalIAP"]
|
"UNLP", "Minimal", "MinimalIAP"]
|
||||||
if "MicroG" in apps:
|
if "microg" in apps:
|
||||||
microg_variant = inquirer.select(
|
microg_variant = inquirer.select(
|
||||||
message="Select MicroG variant",
|
message="Select MicroG variant",
|
||||||
choices=microg_variants,
|
choices=microg_variants,
|
||||||
default="Standard",
|
default="Standard",
|
||||||
).execute()
|
).execute()
|
||||||
args.microg_variant = microg_variant
|
args.microg_variant = microg_variant
|
||||||
|
if "device_spoof" in apps:
|
||||||
|
spoof_profile = inquirer.select(
|
||||||
|
message="Select device profile to spoof",
|
||||||
|
choices=list(PROFILES.keys()),
|
||||||
|
default="pixel6",
|
||||||
|
).execute()
|
||||||
|
args.spoof_profile = spoof_profile
|
||||||
args.app = apps
|
args.app = apps
|
||||||
install_app(args)
|
install_app(args)
|
||||||
elif action == "Remove":
|
elif action == "Remove":
|
||||||
@@ -278,7 +299,7 @@ def main():
|
|||||||
parser.add_argument('-a', '--android-version',
|
parser.add_argument('-a', '--android-version',
|
||||||
dest='android_version',
|
dest='android_version',
|
||||||
help='Specify the Android version',
|
help='Specify the Android version',
|
||||||
default="11",
|
default="13",
|
||||||
choices=["11", "13"])
|
choices=["11", "13"])
|
||||||
|
|
||||||
# android command
|
# android command
|
||||||
@@ -286,8 +307,8 @@ def main():
|
|||||||
'certified', help='Get device ID to obtain Play Store certification')
|
'certified', help='Get device ID to obtain Play Store certification')
|
||||||
certified.set_defaults(func=get_certified)
|
certified.set_defaults(func=get_certified)
|
||||||
|
|
||||||
install_choices = ["gapps", "microg", "libndk",
|
install_choices = ["gapps", "microg", "libndk", "libhoudini",
|
||||||
"libhoudini", "magisk", "smartdock", "widevine"]
|
"magisk", "mitm", "smartdock", "widevine", "device_spoof"]
|
||||||
hack_choices = ["nodataperm", "hidestatusbar"]
|
hack_choices = ["nodataperm", "hidestatusbar"]
|
||||||
micrg_variants = ["Standard", "NoGoolag", "UNLP", "Minimal", "MinimalIAP"]
|
micrg_variants = ["Standard", "NoGoolag", "UNLP", "Minimal", "MinimalIAP"]
|
||||||
remove_choices = install_choices
|
remove_choices = install_choices
|
||||||
@@ -305,6 +326,7 @@ microg: Add microG, Aurora Store and Aurora Droid to WayDriod
|
|||||||
libndk: Add libndk arm translation, better for AMD CPUs
|
libndk: Add libndk arm translation, better for AMD CPUs
|
||||||
libhoudini: Add libhoudini arm translation, better for Intel CPUs
|
libhoudini: Add libhoudini arm translation, better for Intel CPUs
|
||||||
magisk: Install Magisk Delta to WayDroid
|
magisk: Install Magisk Delta to WayDroid
|
||||||
|
mitm -c CA_CERT_FILE: Install root CA cert into system trust store
|
||||||
smartdock: A desktop mode launcher for Android
|
smartdock: A desktop mode launcher for Android
|
||||||
widevine: Add support for widevine DRM L3
|
widevine: Add support for widevine DRM L3
|
||||||
"""
|
"""
|
||||||
@@ -313,6 +335,15 @@ widevine: Add support for widevine DRM L3
|
|||||||
'install', formatter_class=argparse.RawTextHelpFormatter, help='Install an app')
|
'install', formatter_class=argparse.RawTextHelpFormatter, help='Install an app')
|
||||||
install_parser.add_argument(
|
install_parser.add_argument(
|
||||||
**arg_template, choices=install_choices, help=install_help)
|
**arg_template, choices=install_choices, help=install_help)
|
||||||
|
install_parser.add_argument('-c', '--ca-cert',
|
||||||
|
dest='ca_cert_file',
|
||||||
|
help='[for mitm only] The CA certificate file (*.pem) to install',
|
||||||
|
default=None)
|
||||||
|
install_parser.add_argument('-p', '--spoof-profile',
|
||||||
|
dest='spoof_profile',
|
||||||
|
help='[for device_spoof only] Device profile to spoof',
|
||||||
|
choices=list(PROFILES.keys()),
|
||||||
|
default="pixel6")
|
||||||
install_parser.set_defaults(func=install_app)
|
install_parser.set_defaults(func=install_app)
|
||||||
|
|
||||||
# remove and its aliases
|
# remove and its aliases
|
||||||
|
|||||||
+32
@@ -0,0 +1,32 @@
|
|||||||
|
{ lib,
|
||||||
|
stdenvNoCC,
|
||||||
|
lzip,
|
||||||
|
python3,
|
||||||
|
makeWrapper }:
|
||||||
|
let
|
||||||
|
wrappedPath = lib.makeBinPath [ lzip ];
|
||||||
|
in stdenvNoCC.mkDerivation {
|
||||||
|
name = "waydroid_script";
|
||||||
|
|
||||||
|
buildInputs = [
|
||||||
|
(python3.withPackages(ps: with ps; [ tqdm requests inquirerpy ]))
|
||||||
|
];
|
||||||
|
|
||||||
|
nativeBuildInputs = [
|
||||||
|
makeWrapper
|
||||||
|
];
|
||||||
|
|
||||||
|
src = ./.;
|
||||||
|
|
||||||
|
postPatch = ''
|
||||||
|
patchShebangs main.py
|
||||||
|
'';
|
||||||
|
|
||||||
|
installPhase = ''
|
||||||
|
mkdir -p $out/libexec
|
||||||
|
cp -r . $out/libexec/waydroid_script
|
||||||
|
mkdir -p $out/bin
|
||||||
|
makeShellWrapper $out/libexec/waydroid_script/main.py $out/bin/waydroid_script \
|
||||||
|
--prefix PATH : "${wrappedPath}"
|
||||||
|
'';
|
||||||
|
}
|
||||||
+1
-1
@@ -14,7 +14,7 @@ class AndroidId:
|
|||||||
except:
|
except:
|
||||||
return
|
return
|
||||||
else:
|
else:
|
||||||
Logger.error("WayDroid isn't running !")
|
Logger.error("Please make sure Waydroid is running and Gapps has been installed!")
|
||||||
return
|
return
|
||||||
print(queryout.replace("android_id|", "").strip())
|
print(queryout.replace("android_id|", "").strip())
|
||||||
print(" ^----- Open https://google.com/android/uncertified/?pli=1")
|
print(" ^----- Open https://google.com/android/uncertified/?pli=1")
|
||||||
|
|||||||
@@ -0,0 +1,71 @@
|
|||||||
|
import configparser
|
||||||
|
from tools.logger import Logger
|
||||||
|
|
||||||
|
|
||||||
|
PROFILES = {
|
||||||
|
"pixel6": {
|
||||||
|
"ro.product.brand": "google",
|
||||||
|
"ro.product.manufacturer": "Google",
|
||||||
|
"ro.product.model": "Pixel 6",
|
||||||
|
"ro.product.name": "oriole",
|
||||||
|
"ro.product.device": "oriole",
|
||||||
|
"ro.product.board": "oriole",
|
||||||
|
"ro.build.product": "oriole",
|
||||||
|
"ro.build.fingerprint": "google/oriole/oriole:13/TQ3A.230901.001/10750268:user/release-keys",
|
||||||
|
"ro.build.description": "oriole-user 13 TQ3A.230901.001 10750268 release-keys",
|
||||||
|
"ro.build.version.release": "13",
|
||||||
|
"ro.build.version.sdk": "33",
|
||||||
|
"ro.build.type": "user",
|
||||||
|
"ro.build.tags": "release-keys",
|
||||||
|
},
|
||||||
|
"samsung_s21": {
|
||||||
|
"ro.product.brand": "samsung",
|
||||||
|
"ro.product.manufacturer": "samsung",
|
||||||
|
"ro.product.model": "SM-G991B",
|
||||||
|
"ro.product.name": "o1sxeea",
|
||||||
|
"ro.product.device": "o1s",
|
||||||
|
"ro.product.board": "lahaina",
|
||||||
|
"ro.build.product": "o1s",
|
||||||
|
"ro.build.fingerprint": "samsung/o1sxeea/o1s:13/TP1A.220624.014/G991BXXU5EWCA:user/release-keys",
|
||||||
|
"ro.build.description": "o1sxeea-user 13 TP1A.220624.014 G991BXXU5EWCA release-keys",
|
||||||
|
"ro.build.version.release": "13",
|
||||||
|
"ro.build.version.sdk": "33",
|
||||||
|
"ro.build.type": "user",
|
||||||
|
"ro.build.tags": "release-keys",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
PROP_KEYS = list(next(iter(PROFILES.values())).keys())
|
||||||
|
|
||||||
|
|
||||||
|
class DeviceSpoof:
|
||||||
|
id = "device_spoof"
|
||||||
|
|
||||||
|
def __init__(self, profile_name="pixel6") -> None:
|
||||||
|
if profile_name not in PROFILES:
|
||||||
|
raise ValueError(f"Unknown profile '{profile_name}'. Choose from: {list(PROFILES.keys())}")
|
||||||
|
self.profile_name = profile_name
|
||||||
|
self.apply_props = PROFILES[profile_name]
|
||||||
|
|
||||||
|
def _read_cfg(self):
|
||||||
|
cfg = configparser.ConfigParser()
|
||||||
|
cfg.read("/var/lib/waydroid/waydroid.cfg")
|
||||||
|
if not cfg.has_section("properties"):
|
||||||
|
cfg.add_section("properties")
|
||||||
|
return cfg
|
||||||
|
|
||||||
|
def install(self):
|
||||||
|
cfg = self._read_cfg()
|
||||||
|
for key, value in self.apply_props.items():
|
||||||
|
cfg.set("properties", key, value)
|
||||||
|
with open("/var/lib/waydroid/waydroid.cfg", "w") as f:
|
||||||
|
cfg.write(f)
|
||||||
|
Logger.info(f"Device spoofed as '{self.profile_name}'. Restart Waydroid to apply.")
|
||||||
|
|
||||||
|
def uninstall(self):
|
||||||
|
cfg = self._read_cfg()
|
||||||
|
for key in PROP_KEYS:
|
||||||
|
cfg.remove_option("properties", key)
|
||||||
|
with open("/var/lib/waydroid/waydroid.cfg", "w") as f:
|
||||||
|
cfg.write(f)
|
||||||
|
Logger.info("Device spoof properties removed. Restart Waydroid to apply.")
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
import os
|
||||||
|
import shutil
|
||||||
|
from stuff.general import General
|
||||||
|
|
||||||
|
|
||||||
|
class FDroidPriv(General):
|
||||||
|
id = "fdroid priv"
|
||||||
|
dl_links = {"11": ["https://f-droid.org/repo/org.fdroid.fdroid.privileged.ota_2130.zip",
|
||||||
|
"6242cab56d197d80c598593a46da62e4"],
|
||||||
|
"13": ["https://f-droid.org/repo/org.fdroid.fdroid.privileged.ota_2130.zip",
|
||||||
|
"6242cab56d197d80c598593a46da62e4"]}
|
||||||
|
partition = "system"
|
||||||
|
dl_file_name = "org.fdroid.fdroid.privileged.ota_2130.zip"
|
||||||
|
dl_link = ...
|
||||||
|
act_md5 = ...
|
||||||
|
extract_to = "/tmp/fdroid_ota_2130"
|
||||||
|
files = [
|
||||||
|
"app/F-Droid.apk"
|
||||||
|
"app/F-Droid/F-Droid.apk"
|
||||||
|
"etc/permissions/permissions_org.fdroid.fdroid.privileged.xml"
|
||||||
|
"priv-app/F-DroidPrivilegedExtension.apk"
|
||||||
|
"priv-app/F-DroidPrivilegedExtension/F-DroidPrivilegedExtension.apk"
|
||||||
|
]
|
||||||
|
file_map = {
|
||||||
|
"permissions_org.fdroid.fdroid.privileged.xml": "etc/permissions/permissions_org.fdroid.fdroid.privileged.xml",
|
||||||
|
"F-Droid.apk": "app/F-Droid/F-Droid.apk",
|
||||||
|
"F-DroidPrivilegedExtension.apk": "priv-app/F-DroidPrivilegedExtension/F-DroidPrivilegedExtension.apk",
|
||||||
|
}
|
||||||
|
def __init__(self, android_version="11") -> None:
|
||||||
|
super().__init__()
|
||||||
|
self.dl_link = self.dl_links[android_version][0]
|
||||||
|
self.act_md5 = self.dl_links[android_version][1]
|
||||||
|
|
||||||
|
def copy(self):
|
||||||
|
for f, d in self.file_map.items():
|
||||||
|
rro_file = os.path.join(
|
||||||
|
self.copy_dir, self.partition, d)
|
||||||
|
rro_dir = os.path.dirname(rro_file)
|
||||||
|
if not os.path.exists(rro_dir):
|
||||||
|
os.makedirs(rro_dir)
|
||||||
|
shutil.copyfile(os.path.join(self.extract_to, f), rro_file)
|
||||||
|
|
||||||
+4
-4
@@ -15,10 +15,10 @@ class Gapps(General):
|
|||||||
"armeabi-v7a": ["https://sourceforge.net/projects/opengapps/files/arm/20220215/open_gapps-arm-11.0-pico-20220215.zip", "8719519fa32ae83a62621c6056d32814"]
|
"armeabi-v7a": ["https://sourceforge.net/projects/opengapps/files/arm/20220215/open_gapps-arm-11.0-pico-20220215.zip", "8719519fa32ae83a62621c6056d32814"]
|
||||||
},
|
},
|
||||||
"13": {
|
"13": {
|
||||||
"x86_64": ["https://github.com/Howard20181/MindTheGappsBuilder/releases/download/20230323/MindTheGapps-13.0.0-x86_64-20230323.zip", "aba427be1ddd0963121c87a4eda80299"],
|
"x86_64": ["https://github.com/s1204IT/MindTheGappsBuilder/releases/download/20231028/MindTheGapps-13.0.0-x86_64-20231028.zip", "63ccebbf93d45c384f58d7c40049d398"],
|
||||||
"x86": ["https://github.com/Howard20181/MindTheGappsBuilder/releases/download/20230323/MindTheGapps-13.0.0-x86-20230323.zip", "f02d2f1a3f0a084f13ab4c1b58ad7554"],
|
"x86": ["https://github.com/s1204IT/MindTheGappsBuilder/releases/download/20231028/MindTheGapps-13.0.0-x86-20231028.zip", "f12b6a8ed14eedbb4b5b3c932a865956"],
|
||||||
"arm64-v8a": ["https://github.com/Howard20181/MindTheGappsBuilder/releases/download/20230323/MindTheGapps-13.0.0-arm64-20230323.zip", "18484a5622eeccffcea2b43205655d8a"],
|
"arm64-v8a": ["https://github.com/s1204IT/MindTheGappsBuilder/releases/download/20231028/MindTheGapps-13.0.0-arm64-20231028.zip", "11180da0a5d9f2ed2863882c30a8d556"],
|
||||||
"armeabi-v7a": ["https://github.com/Howard20181/MindTheGappsBuilder/releases/download/20230323/MindTheGapps-13.0.0-arm-20230323.zip", "e4c00a7eb1e4dfca0fc6a3e447710264"]
|
"armeabi-v7a": ["https://github.com/s1204IT/MindTheGappsBuilder/releases/download/20231028/MindTheGapps-13.0.0-arm-20231028.zip", "d525c980bac427844aa4cb01628f8a8f"]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
android_version = ...
|
android_version = ...
|
||||||
|
|||||||
+2
-2
@@ -73,8 +73,8 @@ class General:
|
|||||||
if not os.path.isfile(os.path.join(bin_dir, "resetprop")):
|
if not os.path.isfile(os.path.join(bin_dir, "resetprop")):
|
||||||
if not os.path.exists(bin_dir):
|
if not os.path.exists(bin_dir):
|
||||||
os.makedirs(bin_dir)
|
os.makedirs(bin_dir)
|
||||||
shutil.copy(os.path.join(
|
shutil.copy(os.path.join(os.path.join(os.path.dirname(__file__), "..", "bin",
|
||||||
"./bin", self.arch[0], "resetprop"), bin_dir)
|
self.arch[0], "resetprop")), bin_dir)
|
||||||
os.chmod(os.path.join(bin_dir, "resetprop"), 0o755)
|
os.chmod(os.path.join(bin_dir, "resetprop"), 0o755)
|
||||||
if not os.path.isfile(os.path.join(bin_dir, "resetprop.sh")):
|
if not os.path.isfile(os.path.join(bin_dir, "resetprop.sh")):
|
||||||
with open(os.path.join(bin_dir, "resetprop.sh"), "w") as f:
|
with open(os.path.join(bin_dir, "resetprop.sh"), "w") as f:
|
||||||
|
|||||||
@@ -5,8 +5,8 @@ from stuff.general import General
|
|||||||
|
|
||||||
class HideStatusBar(General):
|
class HideStatusBar(General):
|
||||||
id = "hide status bar"
|
id = "hide status bar"
|
||||||
dl_links = {"11": ["https://github.com/ayasa520/hide-status-bar/releases/download/v0.0.1/app-release.apk",
|
dl_links = {"11": ["https://github.com/ayasa520/hide-status-bar/releases/download/v0.0.2/app-release.apk",
|
||||||
"ae6c4cc567d6f3de77068e54e43818e2"]}
|
"ff2fe63ddfb4b035e6720a1b195b2355"]}
|
||||||
partition = "system"
|
partition = "system"
|
||||||
dl_file_name = "hidestatusbar.apk"
|
dl_file_name = "hidestatusbar.apk"
|
||||||
dl_link = ...
|
dl_link = ...
|
||||||
|
|||||||
+2
-2
@@ -10,7 +10,7 @@ class Houdini(General):
|
|||||||
partition = "system"
|
partition = "system"
|
||||||
dl_links = {
|
dl_links = {
|
||||||
"11": ["https://github.com/supremegamers/vendor_intel_proprietary_houdini/archive/81f2a51ef539a35aead396ab7fce2adf89f46e88.zip", "fbff756612b4144797fbc99eadcb6653"],
|
"11": ["https://github.com/supremegamers/vendor_intel_proprietary_houdini/archive/81f2a51ef539a35aead396ab7fce2adf89f46e88.zip", "fbff756612b4144797fbc99eadcb6653"],
|
||||||
# "13": ["https://github.com/supremegamers/vendor_intel_proprietary_houdini/archive/978d8cba061a08837b7e520cd03b635af643ba08.zip", "1e139054c05034648fae58a1810573b4"]
|
"13": ["https://github.com/supremegamers/vendor_intel_proprietary_houdini/archive/2f8f088671182e17e67321e098e8411a3972a628.zip", "37fe0899f1e4da7f9a724cca1c1ab1ea"]
|
||||||
}
|
}
|
||||||
act_md5 = ...
|
act_md5 = ...
|
||||||
dl_link = ...
|
dl_link = ...
|
||||||
@@ -18,7 +18,7 @@ class Houdini(General):
|
|||||||
extract_to = "/tmp/houdiniunpack"
|
extract_to = "/tmp/houdiniunpack"
|
||||||
init_rc_component = """
|
init_rc_component = """
|
||||||
on early-init
|
on early-init
|
||||||
mount -t binfmt_misc binfmt_misc /proc/sys/fs/binfmt_misc
|
mount binfmt_misc binfmt_misc /proc/sys/fs/binfmt_misc
|
||||||
|
|
||||||
on property:ro.enable.native.bridge.exec=1
|
on property:ro.enable.native.bridge.exec=1
|
||||||
exec -- /system/bin/sh -c "echo ':arm_exe:M::\\\\x7f\\\\x45\\\\x4c\\\\x46\\\\x01\\\\x01\\\\x01\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x02\\\\x00\\\\x28::/system/bin/houdini:P' > /proc/sys/fs/binfmt_misc/register"
|
exec -- /system/bin/sh -c "echo ':arm_exe:M::\\\\x7f\\\\x45\\\\x4c\\\\x46\\\\x01\\\\x01\\\\x01\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x02\\\\x00\\\\x28::/system/bin/houdini:P' > /proc/sys/fs/binfmt_misc/register"
|
||||||
|
|||||||
+37
-18
@@ -10,7 +10,7 @@ from tools import container
|
|||||||
class Magisk(General):
|
class Magisk(General):
|
||||||
id = "magisk delta"
|
id = "magisk delta"
|
||||||
partition = "system"
|
partition = "system"
|
||||||
dl_link = "https://huskydg.github.io/magisk-files/app-debug.apk"
|
dl_link = "https://github.com/mistrmochov/magiskdeltaorig/raw/main/app-release.apk"
|
||||||
dl_file_name = "magisk.apk"
|
dl_file_name = "magisk.apk"
|
||||||
extract_to = "/tmp/magisk_unpack"
|
extract_to = "/tmp/magisk_unpack"
|
||||||
magisk_dir = os.path.join(partition, "etc", "init", "magisk")
|
magisk_dir = os.path.join(partition, "etc", "init", "magisk")
|
||||||
@@ -29,30 +29,28 @@ service bootanim /system/bin/bootanimation
|
|||||||
bootanim_component = f"""
|
bootanim_component = f"""
|
||||||
on post-fs-data
|
on post-fs-data
|
||||||
start logd
|
start logd
|
||||||
exec u:r:su:s0 root root -- /system/etc/init/magisk/magisk{host()[1]} --auto-selinux --setup-sbin /system/etc/init/magisk
|
exec u:r:su:s0 root root -- /system/etc/init/magisk/magiskpolicy --live --magisk
|
||||||
exec u:r:su:s0 root root -- /system/etc/init/magisk/magiskpolicy --live --magisk "allow * magisk_file lnk_file *"
|
exec u:r:magisk:s0 root root -- /system/etc/init/magisk/magiskpolicy --live --magisk
|
||||||
mkdir /sbin/.magisk 700
|
exec u:r:update_engine:s0 root root -- /system/etc/init/magisk/magiskpolicy --live --magisk
|
||||||
mkdir /sbin/.magisk/mirror 700
|
mkdir /dev/magisk_iqeoVo2mDrO 700
|
||||||
mkdir /sbin/.magisk/block 700
|
exec u:r:su:s0 root root -- /system/etc/init/magisk/magisk64 --auto-selinux --setup-sbin /system/etc/init/magisk /dev/magisk_iqeoVo2mDrO
|
||||||
copy /system/etc/init/magisk/config /sbin/.magisk/config
|
exec u:r:su:s0 root root -- /dev/magisk_iqeoVo2mDrO/magisk --auto-selinux --post-fs-data
|
||||||
rm /dev/.magisk_unblock
|
|
||||||
exec u:r:su:s0 root root -- /sbin/magisk --auto-selinux --post-fs-data
|
|
||||||
wait /dev/.magisk_unblock 40
|
|
||||||
rm /dev/.magisk_unblock
|
|
||||||
|
|
||||||
on zygote-start
|
on nonencrypted
|
||||||
exec u:r:su:s0 root root -- /sbin/magisk --auto-selinux --service
|
exec u:r:su:s0 root root -- /dev/magisk_iqeoVo2mDrO/magisk --auto-selinux --service
|
||||||
|
|
||||||
|
on property:vold.decrypt=trigger_restart_framework
|
||||||
|
exec u:r:su:s0 root root -- /dev/magisk_iqeoVo2mDrO/magisk --auto-selinux --service
|
||||||
|
|
||||||
on property:sys.boot_completed=1
|
on property:sys.boot_completed=1
|
||||||
mkdir /data/adb/magisk 755
|
mkdir /data/adb/magisk 755
|
||||||
exec u:r:su:s0 root root -- /sbin/magisk --auto-selinux --boot-complete
|
exec u:r:su:s0 root root -- /dev/magisk_iqeoVo2mDrO/magisk --auto-selinux --boot-complete
|
||||||
exec -- /system/bin/sh -c "if [ ! -e /data/data/io.github.huskydg.magisk ] ; then pm install /system/etc/init/magisk/magisk.apk ; fi"
|
|
||||||
|
|
||||||
on property:init.svc.zygote=restarting
|
on property:init.svc.zygote=restarting
|
||||||
exec u:r:su:s0 root root -- /sbin/magisk --auto-selinux --zygote-restart
|
exec u:r:su:s0 root root -- /dev/magisk_iqeoVo2mDrO/magisk --auto-selinux --zygote-restart
|
||||||
|
|
||||||
on property:init.svc.zygote=stopped
|
on property:init.svc.zygote=stopped
|
||||||
exec u:r:su:s0 root root -- /sbin/magisk --auto-selinux --zygote-restart
|
exec u:r:su:s0 root root -- /dev/magisk_iqeoVo2mDrO/magisk --auto-selinux --zygote-restart
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def download(self):
|
def download(self):
|
||||||
@@ -66,7 +64,28 @@ on property:init.svc.zygote=stopped
|
|||||||
Logger.info("Additional setup")
|
Logger.info("Additional setup")
|
||||||
magisk_absolute_dir = os.path.join(self.copy_dir, self.magisk_dir)
|
magisk_absolute_dir = os.path.join(self.copy_dir, self.magisk_dir)
|
||||||
data_dir = get_data_dir()
|
data_dir = get_data_dir()
|
||||||
shutil.copytree(magisk_absolute_dir, os.path.join(data_dir, "adb", "magisk"), dirs_exist_ok=True)
|
data_magisk_dir = os.path.join(data_dir, "adb", "magisk")
|
||||||
|
shutil.copytree(magisk_absolute_dir, data_magisk_dir, dirs_exist_ok=True)
|
||||||
|
|
||||||
|
# General.install() calls set_perm() only over self.files, which are paths
|
||||||
|
# under copy_dir (the overlay). This /data/adb copy is made here, before
|
||||||
|
# that runs, so it keeps the 0644 the binaries inherited from the apk
|
||||||
|
# extraction. A non-executable /data/adb/magisk/magisk64 makes magisk_env()
|
||||||
|
# abort at post-fs-data: root still works from the overlay copy, but Zygisk
|
||||||
|
# silently never initialises (Magisk reports "Zygisk: No" no matter what
|
||||||
|
# the zygisk setting says). Apply the same perms set_path_perm() gives
|
||||||
|
# magisk paths, to this copy too.
|
||||||
|
self.set_data_magisk_perm(data_magisk_dir)
|
||||||
|
|
||||||
|
def set_data_magisk_perm(self, data_magisk_dir):
|
||||||
|
if not os.path.isdir(data_magisk_dir):
|
||||||
|
return
|
||||||
|
os.chmod(data_magisk_dir, 0o755)
|
||||||
|
for root, dirnames, filenames in os.walk(data_magisk_dir):
|
||||||
|
for dirname in dirnames:
|
||||||
|
os.chmod(os.path.join(root, dirname), 0o755)
|
||||||
|
for filename in filenames:
|
||||||
|
os.chmod(os.path.join(root, filename), 0o755)
|
||||||
|
|
||||||
def copy(self):
|
def copy(self):
|
||||||
magisk_absolute_dir = os.path.join(self.copy_dir, self.magisk_dir)
|
magisk_absolute_dir = os.path.join(self.copy_dir, self.magisk_dir)
|
||||||
|
|||||||
+2
-2
@@ -36,11 +36,11 @@ class MicroG(General):
|
|||||||
"6136b383153c2a6797d14fb4d7ca3f97"
|
"6136b383153c2a6797d14fb4d7ca3f97"
|
||||||
],
|
],
|
||||||
"Minimal": [
|
"Minimal": [
|
||||||
"https://github.com/ayasa520/MinMicroG/releases/download/latest/MinMicroG-Minimal-2.11.1-20230429100521.zip"
|
"https://github.com/ayasa520/MinMicroG/releases/download/latest/MinMicroG-Minimal-2.11.1-20230429100521.zip",
|
||||||
"afb87eb64e7749cfd72c4760d85849da"
|
"afb87eb64e7749cfd72c4760d85849da"
|
||||||
],
|
],
|
||||||
"MinimalIAP": [
|
"MinimalIAP": [
|
||||||
"https://github.com/ayasa520/MinMicroG/releases/download/latest/MinMicroG-MinimalIAP-2.11.1-20230429100556.zip"
|
"https://github.com/ayasa520/MinMicroG/releases/download/latest/MinMicroG-MinimalIAP-2.11.1-20230429100556.zip",
|
||||||
"cc071f4f776cbc16c4c1f707aff1f7fa"
|
"cc071f4f776cbc16c4c1f707aff1f7fa"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,40 @@
|
|||||||
|
import os
|
||||||
|
import shutil
|
||||||
|
from stuff.general import General
|
||||||
|
from tools.helper import run
|
||||||
|
from tools.logger import Logger
|
||||||
|
|
||||||
|
class Mitm(General):
|
||||||
|
id = "mitm"
|
||||||
|
partition = "system"
|
||||||
|
|
||||||
|
def __init__(self, ca_cert_file: str=None) -> None:
|
||||||
|
super().__init__()
|
||||||
|
self.ca_cert_file = ca_cert_file
|
||||||
|
|
||||||
|
def download(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def skip_extract(self):
|
||||||
|
return True
|
||||||
|
|
||||||
|
def copy(self):
|
||||||
|
file_hash = run([
|
||||||
|
'openssl', 'x509', '-noout', '-subject_hash_old', '-in',
|
||||||
|
self.ca_cert_file,
|
||||||
|
]).stdout.decode("ascii").strip()
|
||||||
|
target_dir = os.path.join(
|
||||||
|
self.copy_dir, self.partition, "etc", "security", "cacerts")
|
||||||
|
Logger.info(f"Creating directory: {target_dir}")
|
||||||
|
os.makedirs(target_dir, exist_ok=True)
|
||||||
|
target_path = os.path.join(target_dir, f'{file_hash}.0')
|
||||||
|
Logger.info(f"Copying {self.ca_cert_file} to system trust store")
|
||||||
|
Logger.info(f"Target file: {target_path}")
|
||||||
|
shutil.copyfile(self.ca_cert_file, target_path)
|
||||||
|
os.chmod(target_path, 0o644)
|
||||||
|
|
||||||
|
def install(self):
|
||||||
|
if not self.ca_cert_file:
|
||||||
|
raise ValueError(
|
||||||
|
"This command requires the --ca-cert switch and a *.pem file")
|
||||||
|
super().install()
|
||||||
+2
-2
@@ -9,12 +9,12 @@ class Ndk(General):
|
|||||||
partition = "system"
|
partition = "system"
|
||||||
dl_links = {
|
dl_links = {
|
||||||
"11": ["https://github.com/supremegamers/vendor_google_proprietary_ndk_translation-prebuilt/archive/9324a8914b649b885dad6f2bfd14a67e5d1520bf.zip", "c9572672d1045594448068079b34c350"],
|
"11": ["https://github.com/supremegamers/vendor_google_proprietary_ndk_translation-prebuilt/archive/9324a8914b649b885dad6f2bfd14a67e5d1520bf.zip", "c9572672d1045594448068079b34c350"],
|
||||||
"13": ["https://github.com/supremegamers/vendor_google_proprietary_ndk_translation-prebuilt/archive/a090003c60df53a9eadb2df09bd4fd2fa86ea629.zip", "e6f0d9fc28ebc427b59a3942a9a4ffc0"]
|
"13": ["https://github.com/supremegamers/vendor_google_proprietary_ndk_translation-prebuilt/archive/68734c52556d3d7a6db34c603dd9276915c29f2f.zip", "0b2207c490fcb400aa5c87fcf0d52d38"]
|
||||||
}
|
}
|
||||||
dl_file_name = "libndktranslation.zip"
|
dl_file_name = "libndktranslation.zip"
|
||||||
extract_to = "/tmp/libndkunpack"
|
extract_to = "/tmp/libndkunpack"
|
||||||
apply_props = {
|
apply_props = {
|
||||||
"ro.product.cpu.abilist": "x86_64,x86,armeabi-v7a,armeabi,arm64-v8a",
|
"ro.product.cpu.abilist": "x86_64,x86,arm64-v8a,armeabi-v7a,armeabi",
|
||||||
"ro.product.cpu.abilist32": "x86,armeabi-v7a,armeabi",
|
"ro.product.cpu.abilist32": "x86,armeabi-v7a,armeabi",
|
||||||
"ro.product.cpu.abilist64": "x86_64,arm64-v8a",
|
"ro.product.cpu.abilist64": "x86_64,arm64-v8a",
|
||||||
"ro.dalvik.vm.native.bridge": "libndk_translation.so",
|
"ro.dalvik.vm.native.bridge": "libndk_translation.so",
|
||||||
|
|||||||
+45
-19
@@ -1,7 +1,8 @@
|
|||||||
import gzip
|
|
||||||
import os
|
import os
|
||||||
|
import re
|
||||||
import shutil
|
import shutil
|
||||||
from stuff.general import General
|
from stuff.general import General
|
||||||
|
from tools.helper import backup, restore
|
||||||
from tools.logger import Logger
|
from tools.logger import Logger
|
||||||
from tools import container
|
from tools import container
|
||||||
|
|
||||||
@@ -9,37 +10,59 @@ from tools import container
|
|||||||
class Nodataperm(General):
|
class Nodataperm(General):
|
||||||
id = "nodataperm"
|
id = "nodataperm"
|
||||||
dl_links = {
|
dl_links = {
|
||||||
"11": ["https://github.com/ayasa520/hack_full_data_permission/archive/refs/heads/main.zip",
|
"11": {
|
||||||
"eafd7b0986f3edaebaf1dd89f19d49bf"],
|
"x86_64": [
|
||||||
"13": ["", ""]
|
"https://github.com/ayasa520/hack_full_data_permission/archive/d4beab7780eb792059d33e77d865579c9ee41546.zip",
|
||||||
|
"b0e3908ffcf5df8ea62f4929aa680f1a"
|
||||||
|
],
|
||||||
|
},
|
||||||
|
"13": {
|
||||||
|
"x86_64": [
|
||||||
|
"https://github.com/ayasa520/hack_full_data_permission/archive/d4beab7780eb792059d33e77d865579c9ee41546.zip",
|
||||||
|
"b0e3908ffcf5df8ea62f4929aa680f1a"
|
||||||
|
],
|
||||||
|
},
|
||||||
}
|
}
|
||||||
dl_file_name = "nodataperm.zip"
|
dl_file_name = "nodataperm.zip"
|
||||||
extract_to = "/tmp/nodataperm"
|
extract_to = "/tmp/nodataperm"
|
||||||
dl_link = ...
|
dl_link = None
|
||||||
act_md5 = ...
|
act_md5 = None
|
||||||
partition = "system"
|
partition = "system"
|
||||||
files = [
|
files = [
|
||||||
"etc/nodataperm.sh",
|
"etc/nodataperm.sh",
|
||||||
"etc/init/nodataperm.rc",
|
"etc/init/nodataperm.rc",
|
||||||
"framework/services.jar"
|
"framework/services.jar",
|
||||||
|
"framework/services.jar.prof",
|
||||||
|
"framework/services.jar.bprof",
|
||||||
]
|
]
|
||||||
|
|
||||||
def __init__(self, android_version="11") -> None:
|
def __init__(self, android_version="11") -> None:
|
||||||
super().__init__()
|
super().__init__()
|
||||||
self.dl_link = self.dl_links[android_version][0]
|
print("ok")
|
||||||
self.act_md5 = self.dl_links[android_version][1]
|
arch = self.arch[0]
|
||||||
|
if android_version not in self.dl_links:
|
||||||
|
raise KeyError(f"No download links for Android version '{android_version}'")
|
||||||
|
if arch not in self.dl_links[android_version]:
|
||||||
|
raise KeyError(f"No download links for architecture '{arch}' in Android version '{android_version}'")
|
||||||
|
self.dl_link = self.dl_links[android_version][arch][0]
|
||||||
|
self.act_md5 = self.dl_links[android_version][arch][1]
|
||||||
|
|
||||||
def copy(self):
|
def copy(self):
|
||||||
|
name = re.findall(r"([a-zA-Z0-9]+)\.zip", self.dl_link)[0]
|
||||||
extract_path = os.path.join(
|
extract_path = os.path.join(
|
||||||
self.extract_to, "hack_full_data_permission-main")
|
self.extract_to, f"hack_full_data_permission-{name}")
|
||||||
if not container.use_overlayfs():
|
if not container.use_overlayfs():
|
||||||
services_jar = os.path.join(
|
services_jar = os.path.join(
|
||||||
self.copy_dir, self.partition, "framework", "services.jar")
|
self.copy_dir, self.partition, "framework", "services.jar")
|
||||||
gz_filename = services_jar+".gz"
|
services_jar_prof = os.path.join(
|
||||||
with gzip.open(gz_filename, 'wb') as f_gz:
|
self.copy_dir, self.partition, "framework", "services.jar.prof")
|
||||||
with open(services_jar, "rb") as f:
|
services_jar_bprof = os.path.join(
|
||||||
f_gz.write(f.read())
|
self.copy_dir, self.partition, "framework", "services.jar.bprof")
|
||||||
Logger.info("Copying widevine library files ...")
|
backup(services_jar)
|
||||||
|
backup(services_jar_prof)
|
||||||
|
backup(services_jar_bprof)
|
||||||
|
|
||||||
|
Logger.info(f"Copying {self.id} library files ...")
|
||||||
shutil.copytree(extract_path, os.path.join(
|
shutil.copytree(extract_path, os.path.join(
|
||||||
self.copy_dir, self.partition), dirs_exist_ok=True)
|
self.copy_dir, self.partition), dirs_exist_ok=True)
|
||||||
|
|
||||||
@@ -47,7 +70,10 @@ class Nodataperm(General):
|
|||||||
if not container.use_overlayfs():
|
if not container.use_overlayfs():
|
||||||
services_jar = os.path.join(
|
services_jar = os.path.join(
|
||||||
self.copy_dir, self.partition, "framework", "services.jar")
|
self.copy_dir, self.partition, "framework", "services.jar")
|
||||||
gz_filename = services_jar+".gz"
|
services_jar_prof = os.path.join(
|
||||||
with gzip.GzipFile(gz_filename) as f_gz:
|
self.copy_dir, self.partition, "framework", "services.jar.prof")
|
||||||
with open(services_jar, "wb") as f:
|
services_jar_bprof = os.path.join(
|
||||||
f.writelines(f_gz)
|
self.copy_dir, self.partition, "framework", "services.jar.bprof")
|
||||||
|
restore(services_jar)
|
||||||
|
restore(services_jar_prof)
|
||||||
|
restore(services_jar_bprof)
|
||||||
|
|||||||
+3
-2
@@ -4,10 +4,10 @@ from stuff.general import General
|
|||||||
|
|
||||||
class Smartdock(General):
|
class Smartdock(General):
|
||||||
id = "smartdock"
|
id = "smartdock"
|
||||||
dl_link = "https://f-droid.org/repo/cu.axel.smartdock_198.apk"
|
dl_link = "https://f-droid.org/repo/cu.axel.smartdock_1130.apk"
|
||||||
partition = "system"
|
partition = "system"
|
||||||
dl_file_name = "smartdock.apk"
|
dl_file_name = "smartdock.apk"
|
||||||
act_md5 = "a8ce0bca5e1772796404602e0fa250a4"
|
act_md5 = "6bfedb959ef5855c3782e8001cb67f86"
|
||||||
apply_props = { "qemu.hw.mainkeys" : "1" }
|
apply_props = { "qemu.hw.mainkeys" : "1" }
|
||||||
skip_extract = True
|
skip_extract = True
|
||||||
permissions = """<?xml version="1.0" encoding="utf-8"?>
|
permissions = """<?xml version="1.0" encoding="utf-8"?>
|
||||||
@@ -30,6 +30,7 @@ class Smartdock(General):
|
|||||||
<permission name="android.permission.ACCESS_SUPERUSER"/>
|
<permission name="android.permission.ACCESS_SUPERUSER"/>
|
||||||
<permission name="android.permission.PACKAGE_USAGE_STATS" />
|
<permission name="android.permission.PACKAGE_USAGE_STATS" />
|
||||||
<permission name="android.permission.QUERY_ALL_PACKAGES" />
|
<permission name="android.permission.QUERY_ALL_PACKAGES" />
|
||||||
|
<permission name="android.permission.WRITE_SECURE_SETTINGS" />
|
||||||
</privapp-permissions>
|
</privapp-permissions>
|
||||||
</permissions>
|
</permissions>
|
||||||
"""
|
"""
|
||||||
|
|||||||
+13
-2
@@ -13,8 +13,8 @@ class Widevine(General):
|
|||||||
"x86_64": {
|
"x86_64": {
|
||||||
"11": ["https://github.com/supremegamers/vendor_google_proprietary_widevine-prebuilt/archive/48d1076a570837be6cdce8252d5d143363e37cc1.zip",
|
"11": ["https://github.com/supremegamers/vendor_google_proprietary_widevine-prebuilt/archive/48d1076a570837be6cdce8252d5d143363e37cc1.zip",
|
||||||
"f587b8859f9071da4bca6cea1b9bed6a"],
|
"f587b8859f9071da4bca6cea1b9bed6a"],
|
||||||
"13": ["https://github.com/supremegamers/vendor_google_proprietary_widevine-prebuilt/archive/a8524d608431573ef1c9313822d271f78728f9a6.zip",
|
"13": ["https://github.com/WayDroid-ATV/vendor_google_proprietary_widevine-prebuilt/archive/679552343d8b2e8d7a19b6df61c7a03963d0c75b.zip",
|
||||||
"5c55df61da5c012b4e43746547ab730f"]
|
"80ab79ea85c7b2556baedb371a54e01c"]
|
||||||
},
|
},
|
||||||
# "armeabi-v7a": ["https://github.com/supremegamers/vendor_google_proprietary_widevine-prebuilt/archive/a1a19361d36311bee042da8cf4ced798d2c76d98.zip", "fed6898b5cfd2a908cb134df97802554"],
|
# "armeabi-v7a": ["https://github.com/supremegamers/vendor_google_proprietary_widevine-prebuilt/archive/a1a19361d36311bee042da8cf4ced798d2c76d98.zip", "fed6898b5cfd2a908cb134df97802554"],
|
||||||
"arm64-v8a": {
|
"arm64-v8a": {
|
||||||
@@ -30,7 +30,10 @@ class Widevine(General):
|
|||||||
"etc/init/*widevine.rc",
|
"etc/init/*widevine.rc",
|
||||||
"etc/vintf/manifest/*widevine.xml",
|
"etc/vintf/manifest/*widevine.xml",
|
||||||
"lib/libwvhidl.so",
|
"lib/libwvhidl.so",
|
||||||
|
"lib/libwvaidl.so",
|
||||||
"lib/mediadrm",
|
"lib/mediadrm",
|
||||||
|
"lib64/libwvhidl.so",
|
||||||
|
"lib64/libwvaidl.so",
|
||||||
"lib64/mediadrm"
|
"lib64/mediadrm"
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -38,9 +41,17 @@ class Widevine(General):
|
|||||||
super().__init__()
|
super().__init__()
|
||||||
self.dl_link = self.dl_links[self.arch[0]][android_version][0]
|
self.dl_link = self.dl_links[self.arch[0]][android_version][0]
|
||||||
self.act_md5 = self.dl_links[self.arch[0]][android_version][1]
|
self.act_md5 = self.dl_links[self.arch[0]][android_version][1]
|
||||||
|
self.android_version = android_version
|
||||||
|
self.libdir = "lib64" if self.arch[1] == 64 else "lib"
|
||||||
|
|
||||||
def copy(self):
|
def copy(self):
|
||||||
name = re.findall("([a-zA-Z0-9]+)\.zip", self.dl_link)[0]
|
name = re.findall("([a-zA-Z0-9]+)\.zip", self.dl_link)[0]
|
||||||
Logger.info("Copying widevine library files ...")
|
Logger.info("Copying widevine library files ...")
|
||||||
shutil.copytree(os.path.join(self.extract_to, "vendor_google_proprietary_widevine-prebuilt-"+name,
|
shutil.copytree(os.path.join(self.extract_to, "vendor_google_proprietary_widevine-prebuilt-"+name,
|
||||||
"prebuilts"), os.path.join(self.copy_dir, self.partition), dirs_exist_ok=True)
|
"prebuilts"), os.path.join(self.copy_dir, self.partition), dirs_exist_ok=True)
|
||||||
|
if self.android_version == "13":
|
||||||
|
try:
|
||||||
|
os.symlink("libprotobuf-cpp-lite-3.9.1.so",
|
||||||
|
os.path.join(self.copy_dir, self.partition, self.libdir, "libprotobuf-cpp-lite.so"))
|
||||||
|
except FileExistsError:
|
||||||
|
pass
|
||||||
|
|||||||
@@ -0,0 +1,179 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""Regression test for Magisk.setup() permissions on the /data/adb/magisk copy.
|
||||||
|
|
||||||
|
install() runs copy() -> extra1() -> set_perm(). set_perm() only walks self.files,
|
||||||
|
which are paths under copy_dir (the overlay), so the copy that setup() makes into
|
||||||
|
<data>/adb/magisk keeps the 0644 the binaries inherit from the apk extraction.
|
||||||
|
|
||||||
|
A non-executable /data/adb/magisk/magisk64 makes magisk_env() abort at post-fs-data.
|
||||||
|
Root still works (it runs from the overlay copy), but Zygisk never initialises and
|
||||||
|
the Magisk app reports "Zygisk: No" with no error explaining why.
|
||||||
|
|
||||||
|
Runs as an ordinary user, needs no Waydroid install and no extra dependencies:
|
||||||
|
|
||||||
|
python3 tests/test_magisk_setup_perms.py
|
||||||
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
import shutil
|
||||||
|
import stat
|
||||||
|
import sys
|
||||||
|
import tempfile
|
||||||
|
|
||||||
|
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
||||||
|
|
||||||
|
import stuff.magisk as magisk_module
|
||||||
|
from stuff.magisk import Magisk
|
||||||
|
|
||||||
|
MAGISK_BINARIES = [
|
||||||
|
"magisk64",
|
||||||
|
"magiskinit",
|
||||||
|
"magiskboot",
|
||||||
|
"magiskpolicy",
|
||||||
|
"busybox",
|
||||||
|
"util_functions.sh",
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def make_overlay(base):
|
||||||
|
"""Mimic the tree copy() leaves behind: binaries written 0644 by shutil.copyfile."""
|
||||||
|
magisk_dir = os.path.join(base, "system", "etc", "init", "magisk")
|
||||||
|
os.makedirs(os.path.join(magisk_dir, "chromeos"), exist_ok=True)
|
||||||
|
for name in MAGISK_BINARIES:
|
||||||
|
path = os.path.join(magisk_dir, name)
|
||||||
|
with open(path, "wb") as f:
|
||||||
|
f.write(b"\x7fELF placeholder")
|
||||||
|
os.chmod(path, 0o644)
|
||||||
|
nested = os.path.join(magisk_dir, "chromeos", "futility")
|
||||||
|
with open(nested, "wb") as f:
|
||||||
|
f.write(b"placeholder")
|
||||||
|
os.chmod(nested, 0o644)
|
||||||
|
return magisk_dir
|
||||||
|
|
||||||
|
|
||||||
|
def file_modes(root):
|
||||||
|
modes = {}
|
||||||
|
for dirpath, _dirnames, filenames in os.walk(root):
|
||||||
|
for name in filenames:
|
||||||
|
path = os.path.join(dirpath, name)
|
||||||
|
modes[os.path.relpath(path, root)] = stat.S_IMODE(os.stat(path).st_mode)
|
||||||
|
return modes
|
||||||
|
|
||||||
|
|
||||||
|
def test_plain_copytree_loses_exec_bit():
|
||||||
|
"""Document the original behaviour: a bare copytree leaves the binaries 0644."""
|
||||||
|
base = tempfile.mkdtemp()
|
||||||
|
try:
|
||||||
|
src = make_overlay(base)
|
||||||
|
dst = os.path.join(base, "data", "adb", "magisk")
|
||||||
|
os.makedirs(os.path.dirname(dst), exist_ok=True)
|
||||||
|
shutil.copytree(src, dst, dirs_exist_ok=True)
|
||||||
|
|
||||||
|
modes = file_modes(dst)
|
||||||
|
assert modes["magisk64"] == 0o644, (
|
||||||
|
"expected the pre-fix behaviour to reproduce, got %o" % modes["magisk64"]
|
||||||
|
)
|
||||||
|
finally:
|
||||||
|
shutil.rmtree(base, ignore_errors=True)
|
||||||
|
|
||||||
|
|
||||||
|
def test_setup_makes_data_copy_executable():
|
||||||
|
"""setup() must leave every file and dir in <data>/adb/magisk executable."""
|
||||||
|
base = tempfile.mkdtemp()
|
||||||
|
try:
|
||||||
|
make_overlay(base)
|
||||||
|
data_dir = os.path.join(base, "data")
|
||||||
|
os.makedirs(data_dir, exist_ok=True)
|
||||||
|
|
||||||
|
original_get_data_dir = magisk_module.get_data_dir
|
||||||
|
original_info = magisk_module.Logger.info
|
||||||
|
magisk_module.get_data_dir = lambda: data_dir
|
||||||
|
magisk_module.Logger.info = lambda *a, **k: None
|
||||||
|
|
||||||
|
class StubMagisk(Magisk):
|
||||||
|
@property
|
||||||
|
def copy_dir(self):
|
||||||
|
return base
|
||||||
|
|
||||||
|
try:
|
||||||
|
StubMagisk().setup()
|
||||||
|
finally:
|
||||||
|
magisk_module.get_data_dir = original_get_data_dir
|
||||||
|
magisk_module.Logger.info = original_info
|
||||||
|
|
||||||
|
dst = os.path.join(data_dir, "adb", "magisk")
|
||||||
|
modes = file_modes(dst)
|
||||||
|
assert modes, "setup() copied nothing"
|
||||||
|
|
||||||
|
not_executable = {n: oct(m) for n, m in modes.items() if m != 0o755}
|
||||||
|
assert not not_executable, "files left non-0755: %s" % not_executable
|
||||||
|
|
||||||
|
assert stat.S_IMODE(os.stat(dst).st_mode) == 0o755
|
||||||
|
nested = os.path.join(dst, "chromeos")
|
||||||
|
assert stat.S_IMODE(os.stat(nested).st_mode) == 0o755, "nested dir not fixed"
|
||||||
|
finally:
|
||||||
|
shutil.rmtree(base, ignore_errors=True)
|
||||||
|
|
||||||
|
|
||||||
|
def test_setup_is_idempotent():
|
||||||
|
base = tempfile.mkdtemp()
|
||||||
|
try:
|
||||||
|
make_overlay(base)
|
||||||
|
data_dir = os.path.join(base, "data")
|
||||||
|
os.makedirs(data_dir, exist_ok=True)
|
||||||
|
|
||||||
|
original_get_data_dir = magisk_module.get_data_dir
|
||||||
|
original_info = magisk_module.Logger.info
|
||||||
|
magisk_module.get_data_dir = lambda: data_dir
|
||||||
|
magisk_module.Logger.info = lambda *a, **k: None
|
||||||
|
|
||||||
|
class StubMagisk(Magisk):
|
||||||
|
@property
|
||||||
|
def copy_dir(self):
|
||||||
|
return base
|
||||||
|
|
||||||
|
try:
|
||||||
|
StubMagisk().setup()
|
||||||
|
StubMagisk().setup()
|
||||||
|
finally:
|
||||||
|
magisk_module.get_data_dir = original_get_data_dir
|
||||||
|
magisk_module.Logger.info = original_info
|
||||||
|
|
||||||
|
dst = os.path.join(data_dir, "adb", "magisk")
|
||||||
|
assert all(m == 0o755 for m in file_modes(dst).values())
|
||||||
|
finally:
|
||||||
|
shutil.rmtree(base, ignore_errors=True)
|
||||||
|
|
||||||
|
|
||||||
|
def test_perm_helper_tolerates_missing_dir():
|
||||||
|
Magisk().set_data_magisk_perm(os.path.join(tempfile.gettempdir(), "definitely-not-here"))
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
tests = [
|
||||||
|
test_plain_copytree_loses_exec_bit,
|
||||||
|
test_setup_makes_data_copy_executable,
|
||||||
|
test_setup_is_idempotent,
|
||||||
|
test_perm_helper_tolerates_missing_dir,
|
||||||
|
]
|
||||||
|
failed = 0
|
||||||
|
for test in tests:
|
||||||
|
try:
|
||||||
|
test()
|
||||||
|
except AssertionError as exc:
|
||||||
|
failed += 1
|
||||||
|
print("FAIL %s: %s" % (test.__name__, exc))
|
||||||
|
except Exception as exc: # noqa: BLE001 - surface anything unexpected
|
||||||
|
failed += 1
|
||||||
|
print("ERROR %s: %r" % (test.__name__, exc))
|
||||||
|
else:
|
||||||
|
print("ok %s" % test.__name__)
|
||||||
|
if failed:
|
||||||
|
print("\n%d test(s) failed" % failed)
|
||||||
|
return 1
|
||||||
|
print("\nall %d tests passed" % len(tests))
|
||||||
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
sys.exit(main())
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import gzip
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
import platform
|
import platform
|
||||||
@@ -131,3 +132,15 @@ def check_root():
|
|||||||
if os.geteuid() != 0:
|
if os.geteuid() != 0:
|
||||||
Logger.error("This script must be run as root. Aborting.")
|
Logger.error("This script must be run as root. Aborting.")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
|
def backup(path):
|
||||||
|
gz_filename = path+".gz"
|
||||||
|
with gzip.open(gz_filename, 'wb') as f_gz:
|
||||||
|
with open(path, "rb") as f:
|
||||||
|
f_gz.write(f.read())
|
||||||
|
|
||||||
|
def restore(path):
|
||||||
|
gz_filename = path+".gz"
|
||||||
|
with gzip.GzipFile(gz_filename) as f_gz:
|
||||||
|
with open(path, "wb") as f:
|
||||||
|
f.writelines(f_gz)
|
||||||
|
|||||||
Reference in New Issue
Block a user