shithub: mc

ref: 8bc429fb93070938b8bc5d459da4f2664c00abae
dir: /lib/std/mktemp.myr/

View raw version
use "die.use"
use "alloc.use"
use "env.use"
use "errno.use"
use "fmt.use"
use "option.use"
use "pathjoin.use"
use "memops.use"
use "rand.use"
use "result.use"
use "sldup.use"
use "syswrap.use"
use "types.use"

pkg std =
	const mktemp	: (base : byte[:], opt : fdopt, mode : int64 -> std.result((fd, byte[:]), errno))
	const mktemppath	: (base : byte[:] -> byte[:])
;;

const Retries = 100

const mktemp = {base, opt, mode
	var tmpdir, path, uniq

	match std.getenv("TMPDIR")
	| `std.Some d:	tmpdir = d
	| `std.None:	tmpdir = std.sldup("/tmp")
	;;

	for var i = 0; i < Retries; i++
		uniq = randpath(tmpdir, base)
		path = pathcat(tmpdir, uniq)
		match std.openmode(path, opt | Ocreat, mode)
		| `Fail e:
			if e != Eexist
				std.slfree(uniq)
				std.slfree(tmpdir)
				-> `Fail e
			;;
		| `Ok fd:
			std.slfree(uniq)
			std.slfree(tmpdir)
			-> `Ok (fd, path)
		;;
		std.slfree(uniq)
		std.slfree(path)
	;;
	std.slfree(tmpdir)
	-> `Fail Eexist
}

const mktemppath = {base
	var tmpdir, path

	match std.getenv("TMPDIR")
	| `std.Some d:	tmpdir = d
	| `std.None:	tmpdir = std.sldup("/tmp")
	;;

	path = randpath(tmpdir, base)
	std.slfree(tmpdir)
	-> path
}

const randpath = {dir, base
	var f, p
	var v : uint64

	v = std.randnum()
	f = fmt("{}{}", base, v)
	p = pathcat(dir, f)
	std.slfree(f)
	-> p
}