Unwanted (VDI) present
Recently I was given a task to run a outdated piece of commercial software on a very outdated (in)famous operating system. Unlucky for me on the given VDI (VirtualBox disk image) the so-called “Guests Additions” that enabled “better” time synchronization were already installed.
Fighting VBox time
So, this is what I had to do to keep the old clock:
- turn off networking card in the virtual machine configuration, because we do not want the system to use NTP or other newt service to get the “new” time,
- disable getting the host’s clock time:
VBoxManage setextradata "WinXP"
"VBoxInternal/Devices/VMMDev/0/Config/GetHostTimeDisabled" 1,
- and… this magic:
VBoxManage modifyvm "WinXP"
--biossystemtimeoffset "-341597644449", this thing does the very weird thing of telling the virtual machine BIOS how much to set it back in time, the offset here is total milliseconds between some old date and current date.
Getting the old date
With the Python script snippet below you will get the milliseconds to set back the VirtualBox clock to 01.01.2012 01:00.
|
|
from datetime import datetime
round((datetime.strptime("01.01.2012 01:00", "%d.%m.%Y %H:%M")
- datetime.now()).total_seconds() * 1000)
|
Equality methods
By implementing a method for equality equal-to? and two extraction methods equal-hash-code-of and equal-secondary-hash-code-of we can define our own object comparison rules.
For more info see Object Equality and Hashing.
Consider the following example:
1
2
3
4
5
6
7
8
9
10
11
12
13
14 |
|
If we create a new integer% object we can notice that it is not transparent (we can not inspect values of any of it’s fields).
|
|
(new integer%)
;; => (object:integer% ...)
|
But if we compare two fresh integer% objects they will be equal.
Transparent class
A transparent cvlass is a class with the inspect expression valuye se to #false.
From Racket documentation Creating Classes:
Just as for structure types, an inspector controls access to the class’s fields, including private fields, and also affects comparisons using equal?.
Consider the following example:
If we create a new integer% object we can see it’s field values.
|
|
(new integer%)
;; => (object:integer% 0)
|
And if we compare two fresh integer% objects they will be equal.
I have moved my main Fediverse account from @xgqt@fosstodon.org to @xgqt@emacs.ch.
The new account’s RSS feed can be found at emacs.ch/users/xgqt.rss.
Config
First let’s prepare a suitable nginx configuration file.
This one is pretty bare but it works well for our case:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31 |
worker_processes 1;
daemon off;
pid ./nginx/temp/nginx.pid;
error_log /dev/stdout info;
events {
worker_connections 1024;
}
http {
client_body_temp_path ./nginx/temp/client 1 2;
proxy_temp_path ./nginx/temp/proxy;
fastcgi_temp_path ./nginx/temp/fastcgi;
uwsgi_temp_path ./nginx/temp/uwsgi;
scgi_temp_path ./nginx/temp/scgi;
server {
listen 127.0.0.1:8080;
server_name localhost;
access_log /dev/stdout;
error_log /dev/stdout info;
root ./;
location / {
autoindex on;
}
}
}
|
Server config is set up for serving all static files from the current directory.
Startup
Preparation
Based on how you want to store _temp_path files it might be necessary to create (or clean up) additional directories, for example:
|
|
rm -r ./nginx/temp
mkdir -p ./nginx/temp
|
Run in current directory
|
|
nginx -c ./nginx.conf -p ./
|
BTW, you may want to replace ./ with "$(pwd)" and occurrences in the config with static paths.
Bonus: other simple servers
Some of no-dependency-except-itself http servers it’s good to know about:
Python http.server
|
|
python3 -m http.server -b 127.0.0.1 8080
|
Busybox
|
|
busybox httpd -f -p 127.0.0.1:8080 -v
|
You can read more about configuring busybox’s httpd on OpenWRT docs.
System preparation
Qemu
Emerge qemu with static-user USE enabled and your wanted architectures.
|
|
app-emulation/qemu QEMU_SOFTMMU_TARGETS: aarch64 arm x86_64
app-emulation/qemu QEMU_USER_TARGETS: aarch64 arm x86_64
app-emulation/qemu static-user
dev-libs/glib static-libs
sys-apps/attr static-libs
sys-libs/zlib static-libs
dev-libs/libpcre2 static-libs
|
OpenRC
Enable qemu-binfmt:
|
|
rc-update add qemu-binfmt default
|
Start qemu-binfmt:
|
|
rc-service qemu-binfmt start
|
Chrooting
- select chroot location (eg
/chroots/gentoo-arm64-musl-stable)
- unpack the desired rootfs
- create needed directories
mkdir -p /chroots/gentoo-arm64-musl-stable/var/cache/distfiles
- execute
bwrap
- with last
ro-bind mount the qemu emulator binary (eg qemu-aarch64)
- execute the mounted emulator binary giving it a shell program (eg
bash)
Chroot with bwrap:
|
|
bwrap \
--bind /chroots/gentoo-arm64-musl-stable / \
--dev /dev \
--proc /proc \
--perms 1777 --tmpfs /dev/shm \
--tmpfs /run \
--ro-bind /etc/resolv.conf /etc/resolv.conf \
--bind /var/cache/distfiles /var/cache/distfiles \
--ro-bind /usr/bin/qemu-aarch64 /usr/bin/qemu-aarch64 \
/usr/bin/qemu-aarch64 /bin/bash -l
|