github.com/iDigitalFlame/xmt@v0.5.4/data/c_no_fs.go (about)

     1  //go:build !go1.16
     2  // +build !go1.16
     3  
     4  // Copyright (C) 2020 - 2023 iDigitalFlame
     5  //
     6  // This program is free software: you can redistribute it and/or modify
     7  // it under the terms of the GNU General Public License as published by
     8  // the Free Software Foundation, either version 3 of the License, or
     9  // any later version.
    10  //
    11  // This program is distributed in the hope that it will be useful,
    12  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    13  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    14  // GNU General Public License for more details.
    15  //
    16  // You should have received a copy of the GNU General Public License
    17  // along with this program.  If not, see <https://www.gnu.org/licenses/>.
    18  //
    19  
    20  package data
    21  
    22  import (
    23  	"os"
    24  	"sort"
    25  	"strings"
    26  	"syscall"
    27  
    28  	"github.com/iDigitalFlame/xmt/util"
    29  )
    30  
    31  type dirEntry struct {
    32  	os.FileInfo
    33  }
    34  
    35  // A DirEntry is an entry read from a directory
    36  // (using the ReadDir function or a ReadDirFile's ReadDir method).
    37  //
    38  // Copy of "fs.DirEntry" for go1.15 and below.
    39  //
    40  // This is a pre go1.16 compatibility helper.
    41  type DirEntry interface {
    42  	Name() string
    43  	IsDir() bool
    44  	Type() os.FileMode
    45  	Info() (os.FileInfo, error)
    46  }
    47  
    48  func (d dirEntry) Type() os.FileMode {
    49  	return d.Mode()
    50  }
    51  
    52  // ReadDir reads the named directory, returning all its directory entries sorted
    53  // by filename. If an error occurs reading the directory, ReadDir returns the
    54  // entries it was able to read before the error, along with the error.
    55  //
    56  // Alias of "os.ReadDir".
    57  //
    58  // This is a pre go1.16 compatibility helper.
    59  func ReadDir(n string) ([]DirEntry, error) {
    60  	f, err := os.OpenFile(n, 0, 0)
    61  	if err != nil {
    62  		return nil, err
    63  	}
    64  	d, err := f.Readdir(0)
    65  	f.Close()
    66  	sort.Slice(d, func(i, j int) bool {
    67  		return d[i].Name() < d[j].Name()
    68  	})
    69  	r := make([]DirEntry, len(d))
    70  	for i := range d {
    71  		r[i] = dirEntry{d[i]}
    72  	}
    73  	return r, nil
    74  }
    75  func (d dirEntry) Info() (os.FileInfo, error) {
    76  	return d.FileInfo, nil
    77  }
    78  
    79  // CreateTemp creates a new temporary file in the directory dir, opens the file
    80  // for reading and writing, and returns the resulting file.
    81  //
    82  // The filename is generated by taking pattern and adding a random string to the
    83  // end.
    84  //
    85  // If pattern includes a "*", the random string replaces the last "*".
    86  //
    87  // If dir is the empty string, CreateTemp uses the default directory for temporary
    88  // files, as returned by TempDir.
    89  //
    90  // Multiple programs or goroutines calling CreateTemp simultaneously will not choose
    91  // the same file.
    92  //
    93  // The caller can use the file's Name method to find the pathname of the file.
    94  // It is the caller's responsibility to remove the file when it is no longer needed.
    95  //
    96  // Alias of "os.CreateTemp".
    97  //
    98  // This is a pre go1.16 compatibility helper.
    99  func CreateTemp(d, p string) (*os.File, error) {
   100  	if len(d) == 0 {
   101  		d = os.TempDir()
   102  	}
   103  	s, e, err := prefixAndSuffix(p)
   104  	if err != nil {
   105  		return nil, err
   106  	}
   107  	if os.IsPathSeparator(d[len(d)-1]) {
   108  		s = d + s
   109  	} else {
   110  		s = d + string(os.PathSeparator) + s
   111  	}
   112  	for i := 0; ; {
   113  		// 0xC2 - os.O_RDWR | os.O_CREATE | os.O_EXCL
   114  		f, err := os.OpenFile(s+util.Uitoa(uint64(util.FastRand()))+e, 0xC2, 0600)
   115  		if err != nil && os.IsExist(err) {
   116  			if i++; i < 0x2710 {
   117  				continue
   118  			}
   119  			return nil, syscall.EAGAIN
   120  		}
   121  		return f, err
   122  	}
   123  }
   124  func prefixAndSuffix(v string) (string, string, error) {
   125  	for i := 0; i < len(v); i++ {
   126  		if os.IsPathSeparator(v[i]) {
   127  			return "", "", syscall.EBADF
   128  		}
   129  	}
   130  	if i := strings.LastIndexByte(v, '*'); i != -1 {
   131  		return v[:i], v[i+1:], nil
   132  	}
   133  	return v, "", nil
   134  }