#!/bin/sh -e

##########################################################################
#   Synopsis:
#       auto-add-swap path-to-swapfile size (mibibytes)
#
#   Description:
#       The auto-add-swap script creates a swap file, activates it, and
#       configures the system to automatically activate it at boot time.
#       The new swap file serves as additional swap space if a swap
#       partition is already present.
#
#       Note: On SunOS, "swapfile" should be stated as a relative
#       path under /dev/zvol/dsk/rpool.
#       
#   Arguments:
#       path-to-swapfile    Full pathname of the new swap file
#       size                Size of swap file in mibibytes
#       
#   Examples:
#       auto-add-swap /swapfile 4096    # Creates /swapfile
#
#       SunOS: auto-add-swap swap1 4096 # Creates /dev/zvol/dsk/rpool/swap1
#
#   Returns:
#       0 on success, non-zero on failure
#
#   Files:
#       /etc/fstab (FreeBSD, NetBSD)
#
#   See also:
#       swapon(8), mdconfig(8) (FreeBSD)
#       swapctl(8) (NetBSD)
#       
#   History:
#   Date        Name        Modification
#   2021-12-20  Jason Bacon Begin
#   2024-11-12  Jason Bacon Add man page template and usage
##########################################################################

usage()
{
    printf "Usage: $0 swap-file-path megabytes\n"
    printf "Example: $0 /swapfile 4096\n"
    exit 1
}


##########################################################################
#   Main
##########################################################################

if [ $# != 2 ]; then
    usage
fi

swapfile=$1
mbytes=$2

case $(auto-ostype) in
FreeBSD)
    dir=$(dirname $swapfile)
    fs_type=$(df -T $dir | fgrep -v Filesystem | awk '{ print $2 }')
    if [ $fs_type = zfsx ]; then
	printf "Swap file on ZFS is currently not supported.\n"
	printf "Please choose another location.\n"
	exit 1
	# Not certain if ZFS swap is stable yet
	#pool=$(df -T $dir | fgrep -v Filesystem | awk '{ split($1, a, "/"); print a[1]; }')
	#sbase=$(basename $swapfile)
	#zfs create -V ${mbytes}M -o org.freebsd:swap=on -o checksum=off \
	#    -o compression=off -o dedup=off -o sync=disabled \
	#    -o primarycache=none $pool/$sbase
	#service zvol restart
    else
	if grep -q "$swapfile" /etc/fstab; then
	    printf "Error: swapfile is already configured in /etc/fstab.\n"
	    exit 1
	else
	    # FIXME: Probably won't work with ZFS
	    if [ ! -e $swapfile ]; then
		printf "Creating $swapfile...\n"
		dd if=/dev/zero of=$swapfile bs=1m count=$mbytes
	    else
		printf "Using existing $swapfile...\n"
	    fi
	    chmod 600 $swapfile
	    # https://www.cyberciti.biz/faq/create-a-freebsd-swap-file/
	    # https://www.freebsdnews.com/2015/07/03/add-swap-file-freebsd-10-1/
	    # FIXME: "late" is a workaround for this bug:
	    # https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=195326
	    auto-append-line "md\tnone\tswap\tsw,file=$swapfile,late\t0\t0" \
		/etc/fstab $0
	    swapon -aL
	fi
    fi
    swapinfo
    ;;

NetBSD)
    if grep -q "$swapfile" /etc/fstab; then
	printf "Error: swapfile is already configured in /etc/fstab.\n"
	exit 1
    else
	# FIXME: Probably won't work with ZFS
	if [ ! -e $swapfile ]; then
	    printf "Creating $swapfile...\n"
	    dd if=/dev/zero of=$swapfile bs=1m count=$mbytes
	else
	    printf "Using existing $swapfile...\n"
	fi
	chmod 600 $swapfile
	auto-append-line "$swapfile\tnone\tswap\tsw" /etc/fstab $0
	swapctl -A
    fi
    swapinfo
    ;;

RHEL)
    # https://linuxize.com/post/create-a-linux-swap-file/
    if grep -q "$swapfile" /etc/fstab; then
	printf "Error: swapfile is already configured in /etc/fstab.\n"
	exit 1
    else
	# FIXME: Probably won't work with ZFS
	if [ ! -e $swapfile ]; then
	    printf "Creating $swapfile...\n"
	    fallocate -l ${mbytes}MiB $swapfile
	    dd if=/dev/zero of=$swapfile bs=1M count=$mbytes
	else
	    printf "Using existing $swapfile...\n"
	fi
	chmod 600 $swapfile
	mkswap $swapfile
	swapon $swapfile
	auto-append-line "$swapfile\tswap\tswap\tdefaults\t0\t0" /etc/fstab $0
	swapon --show
    fi
    ;;

SunOS)  # Tested on OpenIndiana
    # Create a new zvol
    swapfile=rpool/$swapfile
    zfs create -V ${mbytes}M -b $(getconf PAGESIZE) -o compression=zle \
	-o primarycache=metadata -o secondarycache=none \
	-o sync=always -o logbias=throughput \
	-o com.sun:auto-snapshot=false $swapfile
    
    # Enable swap file
    swap_path=/dev/zvol/dsk/$swapfile
    /usr/sbin/swap -a $swap_path
    
    # Make it permanent
    if ! fgrep $swap_path /etc/vfstab; then
	printf "$swap_path\t-\t-\tswap\t-\tno\t-\n" >> /etc/vfstab
    fi
    swap -lh
    ;;
    
*)
    auto-unsupported-os $0
    exit
    ;;

esac
