summary: stress test for the lsof profile
execute: |
  ###########
  ## SETUP ##
  ###########
  # Create character device (check it doesn't exist!!)
  [ -e /dev/mem ] || sudo mknod /dev/mem c 1 1  # major 1-> memory device; #minor 1-> DMA
  # make sure we can run lsof -d mem later
  sudo chmod 660 /dev/mem

  # Create loopback test device (check it doesn't exist either!)
  [ -e /dev/loop10 ] || sudo mknod /dev/loop10 b 7 10  # major 1 -> loopback device; #minor10 -> instance 10 of device driver; shouldn't be in use.
  dd if=/dev/zero of=/tmp/test.img bs=1M count=10  # Fill /tmp/test.img with 10MB of 0's
  sudo losetup /dev/loop10 /tmp/test.img  # mount /tmp/test.img on /dev/loop10 so it looks like a block device

  # Create character test device (check again!)
  [ -e /dev/char-test ] || sudo mknod /dev/char-test c 99 1  # this major shouldn't be defined, should be a useless device just for extra testing


  ###########
  ## TESTS ##
  ###########

  # List all open files attached to /, recursively
  # sudo lsof +D /
  # these 2 could be combined in one (-i -U) to list all UNIX sockets and network files
  sudo lsof -i
  sudo lsof -U
  # these 5 could be combined ( -d mem,mmap,txt,CHR,BLK) for mapped, memory-mapped, binaries, character & block devices)
  sudo lsof -d mem
  sudo lsof -d mmap
  sudo lsof -d txt
  sudo lsof -d CHR
  sudo lsof -d BLK

  #############################
  # Test Deleted but Open Files
  #############################
  # Create a test file and open it in the background
  echo "test data" > /tmp/deleted-file
  sleep 1
  tail -f /tmp/deleted-file &  # Keep file open in background
  TAIL_PID=$!
  sleep 2
  # Delete the file while it's in use
  rm /tmp/deleted-file

  # See if lsof still detects it
  sudo lsof | grep -F "/tmp/deleted-file (deleted)"

  # Cleanup
  kill $TAIL_PID


  ##############################
  # Start a temporary web server
  ##############################
  python3 -m http.server 8080 &
  PYTHON_PID=$!
  sleep 2
  # Check what process is using port 8080
  sudo lsof -i :8080

  # Cleanup
  kill $PYTHON_PID

  ####################
  # Test Named Pipe
  ####################
  # Open a named pipe
  mkfifo /tmp/testpipe
  # open the pipe for r/w so that it remains open
  exec 3<> /tmp/testpipe
  # Check lsof dislays open pipe
  sudo lsof +E | tee /tmp/lsof.log | grep /tmp/testpipe || grep FIFO /tmp/lsof.log
  # Cleanup
  exec 3<&-  # Close fd 3
  rm /tmp/testpipe


  #####################
  # Open network sockets
  #####################
  # Start a temporary web server
  python3 -m http.server 8080 &
  sleep 1
  PYTHON_PID=$!
  sleep 1
  # Check what process is using port 8080
  sudo lsof -i :8080
  sleep 1
  # Cleanup
  kill $PYTHON_PID

  # ###################################
  # Process deletes its own binary
  echo -e '#!/bin/bash\nrm -- "$0"\nsleep 60' > /tmp/self-delete.sh
  chmod +x /tmp/self-delete.sh

  # Run it in the background
  /tmp/self-delete.sh &  
  SCRIPT_PID=$!
  sleep 2
  # Check if `lsof` can still track it
  echo "Process PID: $SCRIPT_PID"
  sudo lsof -p $SCRIPT_PID

  # Cleanup
  kill $SCRIPT_PID 2>/dev/null


  #################
  # Zombie process
  #################
  # Create a process that turns into a zombie
  bash -c 'sleep 10 & wait $!' &
  PARENT_PID=$!

  # Wait a moment and check for zombies
  sleep 2
  ps -ef | grep defunct
  sudo lsof -p $PARENT_PID

  # Cleanup
  kill $PARENT_PID 2>/dev/null

  ###########################
  # Encrypted loopback device
  ###########################
  # Create an encrypted loopback device
  dd if=/dev/zero of=/tmp/encrypted.img bs=1M count=30
  sudo losetup /dev/loop20 /tmp/encrypted.img
  echo "securest passphrase" | sudo cryptsetup luksFormat /dev/loop20 --key-file=-
  echo "securest passphrase" | sudo cryptsetup luksOpen /dev/loop20 encdev --key-file=-

  # Mount it and check open files
  sudo mkfs.ext4 /dev/mapper/encdev
  mkdir -p /mnt/encrypted
  sudo mount /dev/mapper/encdev /mnt/encrypted
  sleep 2
  echo "test data" > /mnt/encrypted/testfile
  # Start tail in the background and capture the correct PID
  exec 3</mnt/encrypted/testfile  # Open file descriptor 3 for reading
  sleep 2
  sudo lsof /mnt/encrypted
  exec 3<&-  # Close file descriptor after lsof

  # Cleanup
  sudo umount /mnt/encrypted
  sudo cryptsetup luksClose encdev
  sudo losetup -d /dev/loop20
  rm /tmp/encrypted.img

  ########
  #Try SMB
  ########
  #Install SMB and Mount SMB share 
  sudo apt update && sudo apt install -y samba
  sleep 1
  sudo mkdir -p /srv/samba/share
  sudo chmod 777 /srv/samba/share  # Allow all users to access (for testing)
  # Inline the 'testshare' entry to the samba config file
  printf "\n[testshare]\npath = /srv/samba/share\nbrowseable = yes\nread only = no\nguest ok = yes\nforce user = nobody\n" | sudo tee -a /etc/samba/smb.conf

  sleep 1
  sudo systemctl restart smbd nmbd

  # sudo ss -tulnp | grep smbd  # uncomment if need to troubleshoot SMB.

  sudo modprobe cifs


  sleep 1
  sudo mkdir -p /mnt/smb
  sudo mount -t cifs //127.0.0.1/testshare /mnt/smb -o guest

  # Try open file from mounted share
  echo "test content" | sudo tee /srv/samba/share/testfile.txt
  sudo sync  # sync samba to update testfile.txt
  # Open shared file for reading and assign fd 3. Open for r/w can be tricky in smb, this does the trick.
  exec 3</mnt/smb/testfile.txt
  sleep 2
  #lsof on open share
  sudo lsof -c smbd

  # Cleanup
  exec 3<&-  # Close fd 3
  sudo umount /mnt/smb

  #########
  # Try NFS
  #########
  #mount NFS
  sudo apt install -y nfs-kernel-server
  sleep 1
  sudo mkdir -p /srv/nfs/share
  sudo chmod 777 /srv/nfs/share  # Allow all users for testing
  # Update nfs share config
  echo '/srv/nfs/share 127.0.0.1(rw,sync,no_subtree_check,no_root_squash)' | sudo tee -a /etc/exports
  sudo exportfs -a
  sudo systemctl restart nfs-kernel-server
  sudo mkdir -p /mnt/nfs
  sudo mount -t nfs 127.0.0.1:/srv/nfs/share /mnt/nfs
  sudo lsof -c nfsd

  sudo umount /mnt/nfs
