proc {file copy} {{force {}} source target} {
	try {
		if {$force ni {{} -force}} {
			error "bad option \"$force\": should be -force"
		}

		if {![file exists $source]} {
			error "source file does not exist."
		}

		if {$force eq "" && [file exists $target]} {
			error "error copying \"$source\" to \"$target\": file already exists"
		}
		exec /mod/bin/busybox/cp $source $target
	} on error {msg opts} {
		incr opts(-level)
		return {*}$opts $msg
	}
}

proc {file rename} {{force {}} source target} {
	try {
		if {$force ni {{} -force}} {
			error "bad option \"$force\": should be -force"
		}

		if {![file exists $source]} {
			error "source file does not exist."
		}

		if {$force eq "" && [file exists $target]} {
			error "error copying \"$source\" to \"$target\": file already exists"
		}
		exec /mod/bin/busybox/mv $source $target
	} on error {msg opts} {
		incr opts(-level)
		return {*}$opts $msg
	}
}

proc {file touch} {target {ref ""}} {
	try {
		if {$ref ne ""} {
			if {![file exists $ref]} {
				error "ref file does not exist."
			}
			exec /mod/bin/busybox/touch -r $ref $target
		} else {
			exec /mod/bin/busybox/touch $target
		}
	} on error {msg opts} {
		incr opts(-level)
		return {*}$opts $msg
	}
}

local proc file {cmd args} {
	switch $cmd {
	    "rename" { tailcall {file rename} {*}$args }
	    "copy" { tailcall {file copy} {*}$args }
	    "touch" { tailcall {file touch} {*}$args }
	    default { tailcall upcall file $cmd {*}$args }
	}
}