github.com/blend/go-sdk@v1.20220411.3/fileutil/temp.go (about) 1 /* 2 3 Copyright (c) 2022 - Present. Blend Labs, Inc. All rights reserved 4 Use of this source code is governed by a MIT license that can be found in the LICENSE file. 5 6 */ 7 8 package fileutil 9 10 import ( 11 "os" 12 "sync" 13 14 "github.com/blend/go-sdk/ex" 15 ) 16 17 // NewTemp creates a new temp file with given contents. 18 func NewTemp(contents []byte) (*Temp, error) { 19 f, err := os.CreateTemp("", "") 20 if err != nil { 21 return nil, ex.New(err) 22 } 23 if _, err := f.Write(contents); err != nil { 24 return nil, ex.New(err) 25 } 26 return &Temp{ 27 file: f, 28 }, nil 29 } 30 31 // Temp is a file that deletes itself when closed. 32 // It does not hold a file handle open, so no 33 // guarantees are made around the file persisting for the lifetime of the object. 34 type Temp struct { 35 sync.Mutex 36 37 file *os.File 38 } 39 40 // Name returns the fully qualified file path. 41 func (tf *Temp) Name() string { 42 return tf.file.Name() 43 } 44 45 // Stat returns a FileInfo describing the named file. 46 // If there is an error, it will be of type *PathError. 47 func (tf *Temp) Stat() (os.FileInfo, error) { 48 tf.Lock() 49 defer tf.Unlock() 50 51 return tf.file.Stat() 52 } 53 54 // Read reads up to len(b) bytes from the File. 55 // It returns the number of bytes read and any error encountered. 56 // At end of file, Read returns 0, io.EOF. 57 func (tf *Temp) Read(buffer []byte) (int, error) { 58 tf.Lock() 59 defer tf.Unlock() 60 61 read, err := tf.file.Read(buffer) 62 return read, ex.New(err) 63 } 64 65 // ReadAt reads len(b) bytes from the File starting at byte offset off. 66 // It returns the number of bytes read and the error, if any. 67 // ReadAt always returns a non-nil error when n < len(b). 68 // At end of file, that error is io.EOF. 69 func (tf *Temp) ReadAt(buffer []byte, off int64) (int, error) { 70 tf.Lock() 71 defer tf.Unlock() 72 73 read, err := tf.file.ReadAt(buffer, off) 74 return read, ex.New(err) 75 } 76 77 // Write writes len(b) bytes to the File. 78 // It returns the number of bytes written and an error, if any. 79 // Write returns a non-nil error when n != len(b). 80 func (tf *Temp) Write(contents []byte) (int, error) { 81 tf.Lock() 82 defer tf.Unlock() 83 84 written, err := tf.file.Write(contents) 85 return written, ex.New(err) 86 } 87 88 // WriteAt writes len(b) bytes to the File starting at byte offset off. 89 // It returns the number of bytes written and an error, if any. 90 // WriteAt returns a non-nil error when n != len(b). 91 func (tf *Temp) WriteAt(contents []byte, off int64) (int, error) { 92 tf.Lock() 93 defer tf.Unlock() 94 95 written, err := tf.file.WriteAt(contents, off) 96 return written, ex.New(err) 97 } 98 99 // WriteString is like Write, but writes the contents of string s rather than 100 // a slice of bytes. 101 func (tf *Temp) WriteString(contents string) (int, error) { 102 tf.Lock() 103 defer tf.Unlock() 104 105 written, err := tf.file.WriteString(contents) 106 return written, ex.New(err) 107 } 108 109 // Close closes the file reference and deletes the file. 110 func (tf *Temp) Close() error { 111 tf.Lock() 112 defer tf.Unlock() 113 114 if err := tf.file.Close(); err != nil { 115 return ex.New(err) 116 } 117 if err := os.Remove(tf.file.Name()); err != nil { 118 return ex.New(err) 119 } 120 return nil 121 }