package util

import (
	
	
	
	
	
	

	
)
RemoveAll removes path and any children it contains. It removes everything it can but returns the first error it encounters. If the path does not exist, RemoveAll returns nil (no error).
func ( billy.Basic,  string) error {
	,  = getUnderlyingAndPath(, )

	if ,  := .(removerAll);  {
		return .RemoveAll()
	}

	return removeAll(, )
}

type removerAll interface {
	RemoveAll(string) error
}

This implementation is adapted from os.RemoveAll.
Simple case: if Remove works, we're done.
	 := .Remove()
	if  == nil || os.IsNotExist() {
		return nil
	}
Otherwise, is this a directory we need to recurse into?
	,  := .Stat()
	if  != nil {
		if os.IsNotExist() {
			return nil
		}

		return 
	}

Not a directory; return the error from Remove.
		return 
	}

	,  := .(billy.Dir)
	if ! {
		return billy.ErrNotSupported
	}
Directory.
	,  := .ReadDir()
	if  != nil {
Race. It was deleted between the Lstat and Open. Return nil per RemoveAll's docs.
			return nil
		}

		return 
	}
Remove contents & return first error.
	 = nil
	for ,  := range  {
		 := .Join(, .Name())
		 := (, )
		if  == nil {
			 = 
		}
	}
Remove directory.
	 := .Remove()
	if  == nil || os.IsNotExist() {
		return nil
	}

	if  == nil {
		 = 
	}

	return 

}
WriteFile writes data to a file named by filename in the given filesystem. If the file does not exist, WriteFile creates it with permissions perm; otherwise WriteFile truncates it before writing.
func ( billy.Basic,  string,  []byte,  os.FileMode) error {
	,  := .OpenFile(, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, )
	if  != nil {
		return 
	}

	,  := .Write()
	if  == nil &&  < len() {
		 = io.ErrShortWrite
	}

	if  := .Close();  == nil {
		 = 
	}

	return 
}
Random number state. We generate random temporary file names so that there's a good chance the file doesn't exist yet - keeps the number of tries in TempFile to a minimum.
var rand uint32
var randmu sync.Mutex

func () uint32 {
	return uint32(time.Now().UnixNano() + int64(os.Getpid()))
}

func () string {
	randmu.Lock()
	 := rand
	if  == 0 {
		 = reseed()
	}
	 = *1664525 + 1013904223 // constants from Numerical Recipes
	rand = 
	randmu.Unlock()
	return strconv.Itoa(int(1e9 + %1e9))[1:]
}
TempFile creates a new temporary file in the directory dir with a name beginning with prefix, opens the file for reading and writing, and returns the resulting *os.File. If dir is the empty string, TempFile uses the default directory for temporary files (see os.TempDir). Multiple programs calling TempFile simultaneously will not choose the same file. The caller can use f.Name() to find the pathname of the file. It is the caller's responsibility to remove the file when no longer needed.
This implementation is based on stdlib ioutil.TempFile.

	if  == "" {
		 = os.TempDir()
	}

	 := 0
	for  := 0;  < 10000; ++ {
		 := filepath.Join(, +nextSuffix())
		,  = .OpenFile(, os.O_RDWR|os.O_CREATE|os.O_EXCL, 0600)
		if os.IsExist() {
			if ++;  > 10 {
				randmu.Lock()
				rand = reseed()
				randmu.Unlock()
			}
			continue
		}
		break
	}
	return
}
TempDir creates a new temporary directory in the directory dir with a name beginning with prefix and returns the path of the new directory. If dir is the empty string, TempDir uses the default directory for temporary files (see os.TempDir). Multiple programs calling TempDir simultaneously will not choose the same directory. It is the caller's responsibility to remove the directory when no longer needed.
This implementation is based on stdlib ioutil.TempDir

	if  == "" {
		 = os.TempDir()
	}

	 := 0
	for  := 0;  < 10000; ++ {
		 := filepath.Join(, +nextSuffix())
		 = .MkdirAll(, 0700)
		if os.IsExist() {
			if ++;  > 10 {
				randmu.Lock()
				rand = reseed()
				randmu.Unlock()
			}
			continue
		}
		if os.IsNotExist() {
			if ,  := os.Stat(); os.IsNotExist() {
				return "", 
			}
		}
		if  == nil {
			 = 
		}
		break
	}
	return
}

type underlying interface {
	Underlying() billy.Basic
}

func ( billy.Basic,  string) (billy.Basic, string) {
	,  := .(underlying)
	if ! {
		return , 
	}
	if ,  := .(billy.Chroot);  {
		 = .Join(.Root(), )
	}

	return .Underlying(),