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 }