...
1
2
3
4
5 package preallocate
6
7 import (
8 "fmt"
9 "io"
10 "io/ioutil"
11 "os"
12
13 "github.com/pkg/errors"
14 )
15
16
17
18 const NullBufferSize = 512 * 1024
19
20
21 func File(file *os.File, size int64) error {
22 if size < 0 {
23 return errors.New("invalid preallocation size")
24 } else if size == 0 {
25 return nil
26 }
27
28 return preallocFile(file, size)
29 }
30
31
32 func TempFile(dir string, pattern string, size int64) (*os.File, error) {
33 if size < 0 {
34 return nil, errors.New("invalid preallocation size")
35 }
36
37 tempFile, err := ioutil.TempFile(dir, pattern)
38 if err != nil {
39 return nil, errors.Wrap(err, "failed to create temporary file")
40 }
41
42 return tempFile, File(tempFile, size)
43 }
44
45
46 func WriteSeeker(w io.WriteSeeker, size int64) error {
47 if size < 0 {
48 return errors.New("invalid preallocation size")
49 }
50
51 var (
52 b []byte
53 remaining = size
54 wrote int
55 err error
56 )
57
58 _, err = w.Seek(0, 0)
59 if err != nil {
60 return err
61 }
62
63 if remaining > NullBufferSize {
64 b = make([]byte, NullBufferSize)
65 for {
66 wrote, err = w.Write(b)
67 if err != nil {
68 return err
69 } else if int64(wrote) != NullBufferSize {
70 return fmt.Errorf("failed to preallocate file: write operation interrupted at %d/%d bytes", wrote, NullBufferSize)
71 }
72
73 remaining -= NullBufferSize
74 if remaining < NullBufferSize {
75 break
76 }
77 }
78 }
79
80 if remaining > 0 {
81 if b != nil {
82 b = b[0:remaining]
83 } else {
84 b = make([]byte, remaining)
85 }
86
87 wrote, err = w.Write(b)
88 if err != nil {
89 return err
90 } else if int64(wrote) != remaining {
91 return fmt.Errorf("failed to preallocate file: write operation interrupted at %d/%d bytes", wrote, remaining)
92 }
93 }
94
95 _, err = w.Seek(0, 0)
96 return err
97 }
98
View as plain text