Skip to content

Instantly share code, notes, and snippets.

View jamesmcm's full-sized avatar

James McMurray jamesmcm

View GitHub Profile
@jamesmcm
jamesmcm / docker_in_netns.txt
Created June 23, 2025 21:15
Running docker in a network namespace
# After creating the network namespace e.g. vo_none_none
# See https://unix.stackexchange.com/questions/686155/how-can-i-use-a-bind-mount-in-a-network-namespace
# The trick is to bind mount sys, as otherwise ip netns exec will create a mount namespace without it
# Note that each invocation of ip netns exec has its own mount namespace!
$ (on host) sudo -E unshare -m sh -c 'mount --bind /sys /sys; exec ip netns exec vo_none_none sudo --user archie --preserve-env bash'
$ (in netns) sudo umount /sys
$ (in netns) sudo dockerd --host=unix:///var/run/docker-netns.sock --data-root=/var/lib/docker-netns --default-runtime=runc
$ (in netns) DOCKER_OPTS="--dns=YOURDNSHERE" DOCKER_HOST=unix:///var/run/docker-netns.sock sudo --user archie --preserve-env docker ... # your docker command here
@jamesmcm
jamesmcm / foo.conf
Created June 22, 2025 18:20
Wireguard self-hosted VPN config for both IPv4 and IPv6
# This is the client config, run on the client machine with:
# sudo wg-quick up ./foo.conf
# from wireguard-tools
[Interface]
Address = 10.200.200.2/32, fd42:42:42::2/128
PrivateKey = clientprivatekey # CHANGEME: Set client private key here
# Google DNS
DNS = 8.8.8.8
DNS = 2001:4860:4860::8888
@jamesmcm
jamesmcm / srt_sync.py
Created April 21, 2025 22:29
Python script to synchronize SRT subtitles
#!/bin/python
import re
import argparse
from datetime import datetime, timedelta
def parse_time(time_str):
"""Convert SRT timestamp to total seconds."""
hours, minutes, seconds = time_str.replace(',', '.').split(':')
return int(hours) * 3600 + int(minutes) * 60 + float(seconds)
@jamesmcm
jamesmcm / BattleCamera.gd
Created October 13, 2024 09:06
GDScript examples
extends Camera2D
# Camera that reacts to window resizing
@export var acceleration: float = 500
@export var max_speed: float = 1000
var resolution: Vector2 = Vector2(0, 0)
var velocity: Vector2 = Vector2(0, 0)
@jamesmcm
jamesmcm / strace_out.log
Created January 23, 2021 15:21
strace_out.log
77751 execve("./createns", ["./createns"], 0x7ffc4c85d930 /* 59 vars */) = 0
77751 brk(NULL) = 0x560705217000
77751 arch_prctl(0x3001 /* ARCH_??? */, 0x7ffd14a69e90) = -1 EINVAL (Invalid argument)
77751 access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory)
77751 openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
77751 fstat(3, {st_mode=S_IFREG|0644, st_size=324747, ...}) = 0
77751 mmap(NULL, 324747, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7fea6f996000
77751 close(3) = 0
77751 openat(AT_FDCWD, "/usr/lib/libgcc_s.so.1", O_RDONLY|O_CLOEXEC) = 3
77751 read(3, "\x7f\x45\x4c\x46\x02\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\x00\x3e\x00\x01\x00\x00\x00\x20\x30\x00\x00\x00\x00\x00\x00\x40\x00\x00\x00\x00\x00\x00\x00\x10\x0a\x09\x00\x00\x00\x00\x00\x00\x00\x00\x00\x40\x00\x38\x00\x0b\x00\x40\x00\x24\x00\x23\x00\x01\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x2
@jamesmcm
jamesmcm / coin_problem.rs
Created October 20, 2020 21:53
coin_problem.rs
// https://www.reddit.com/r/rust/comments/jeu7xj/faang_interview_question_in_rust/
// Given an MxN array of “boxes”, where each box contains some number of coins C[i][j],
// you want to maximize the number of coins you can take. You take coins by traversing
// row by row, taking all of the coins from ONE box in each row. However, any time you
// change the index of the box you take coins from, you must pay a “change fee” equal
// to ABS(x - y) where x and y are the previous and new row indices. Write a function
// that can determine the optimal set of boxes to take coins from in order to maximize
// your profit after change fees
@jamesmcm
jamesmcm / minimum_chars.rs
Created September 28, 2020 13:28
Minimum needed characters problem solved in Rust
use std::collections::HashMap;
fn main() {
println!("{:?}", word2chars("pear"));
println!("{:?}", needed_chars(&["apple", "pear"]));
}
fn needed_chars(words: &[&str]) -> HashMap<char, u32> {
words
.iter()
@jamesmcm
jamesmcm / tokio_synchronous.rs
Created May 4, 2020 20:53
tokio_synchronous.rs
use std::error::Error;
use std::time::{Duration, Instant};
use tokio::net::TcpStream;
use tokio::prelude::*;
#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
let now = Instant::now();
task("task1", &now).await?;
@jamesmcm
jamesmcm / maxsubarray.rs
Created April 26, 2020 15:01
maxsubarray.rs
// Cargo.toml
[package]
name = "maxsubarray"
version = "0.1.0"
edition = "2018"
[dependencies]
[dev-dependencies]
criterion = "0.3.1"
@jamesmcm
jamesmcm / Xorg.0.log
Created April 18, 2020 19:10
Xorg.0.log
[ 1090.825] (WW) Failed to open protocol names file lib/xorg/protocol.txt
[ 1090.826]
X.Org X Server 1.20.8
X Protocol Version 11, Revision 0
[ 1090.826] Build Operating System: Linux Alpine Linux
[ 1090.826] Current Operating System: Linux falco 3.4.113 #6-postmarketOS SMP PREEMPT Tue Nov 5 06:54:09 UTC 2019 armv7l
[ 1090.826] Kernel command line: androidboot.bootdevice=msm_sdcc.1 androidboot.hardware=qcom vmalloc=400M utags.blkdev=/dev/block/platform/msm_sdcc.1/by-name/utags buildvariant=userdebug androidboot.bootdevice=msm_sdcc.1 androidboot.hardware=qcom vmalloc=400M utags.blkdev=/dev/block/platform/msm_sdcc.1/by-name/utags buildvariant=userdebug androidboot.emmc=true androidboot.serialno=TA92903XW6 androidboot.baseband=msm androidboot.mode=normal androidboot.device=falcon androidboot.hwrev=0x83C0 androidboot.radio=0x1 androidboot.powerup_reason=0x00100000 bootreason=hardware_reset androidboot.write_protect=0 restart.download_mode=0 androidboot.fsg-id= androidboot.secure_hardware=1 androidboot.cid=0