@@ -222,3 +222,53 @@ func getUnderlyingAndPath(fs billy.Basic, path string) (billy.Basic, string) {
222
222
223
223
return u .Underlying (), path
224
224
}
225
+
226
+ // ReadFile reads the named file and returns the contents from the given filesystem.
227
+ // A successful call returns err == nil, not err == EOF.
228
+ // Because ReadFile reads the whole file, it does not treat an EOF from Read
229
+ // as an error to be reported.
230
+ func ReadFile (fs billy.Basic , name string ) ([]byte , error ) {
231
+ f , err := fs .Open (name )
232
+ if err != nil {
233
+ return nil , err
234
+ }
235
+
236
+ defer f .Close ()
237
+
238
+ var size int
239
+ if info , err := fs .Stat (name ); err == nil {
240
+ size64 := info .Size ()
241
+ if int64 (int (size64 )) == size64 {
242
+ size = int (size64 )
243
+ }
244
+ }
245
+
246
+ size ++ // one byte for final read at EOF
247
+ // If a file claims a small size, read at least 512 bytes.
248
+ // In particular, files in Linux's /proc claim size 0 but
249
+ // then do not work right if read in small pieces,
250
+ // so an initial read of 1 byte would not work correctly.
251
+
252
+ if size < 512 {
253
+ size = 512
254
+ }
255
+
256
+ data := make ([]byte , 0 , size )
257
+ for {
258
+ if len (data ) >= cap (data ) {
259
+ d := append (data [:cap (data )], 0 )
260
+ data = d [:len (data )]
261
+ }
262
+
263
+ n , err := f .Read (data [len (data ):cap (data )])
264
+ data = data [:len (data )+ n ]
265
+
266
+ if err != nil {
267
+ if err == io .EOF {
268
+ err = nil
269
+ }
270
+
271
+ return data , err
272
+ }
273
+ }
274
+ }
0 commit comments