github.com/zntrio/harp/v2@v2.0.9/pkg/bundle/fs/directory.go (about)

     1  // Licensed to Elasticsearch B.V. under one or more contributor
     2  // license agreements. See the NOTICE file distributed with
     3  // this work for additional information regarding copyright
     4  // ownership. Elasticsearch B.V. licenses this file to you under
     5  // the Apache License, Version 2.0 (the "License"); you may
     6  // not use this file except in compliance with the License.
     7  // You may obtain a copy of the License at
     8  //
     9  //     http://www.apache.org/licenses/LICENSE-2.0
    10  //
    11  // Unless required by applicable law or agreed to in writing,
    12  // software distributed under the License is distributed on an
    13  // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
    14  // KIND, either express or implied.  See the License for the
    15  // specific language governing permissions and limitations
    16  // under the License.
    17  
    18  //go:build go1.16
    19  // +build go1.16
    20  
    21  package fs
    22  
    23  import (
    24  	"errors"
    25  	"io"
    26  	"io/fs"
    27  	"os"
    28  	"sync"
    29  	"time"
    30  )
    31  
    32  type directory struct {
    33  	sync.RWMutex
    34  
    35  	name     string
    36  	perm     os.FileMode
    37  	modTime  time.Time
    38  	children map[string]interface{}
    39  }
    40  
    41  // Compile time type assertion.
    42  var _ fs.ReadDirFile = (*directory)(nil)
    43  
    44  // -----------------------------------------------------------------------------
    45  
    46  func (d *directory) Stat() (fs.FileInfo, error) {
    47  	return &fileInfo{
    48  		name:    d.name,
    49  		size:    1,
    50  		modTime: d.modTime,
    51  		mode:    d.perm | fs.ModeDir,
    52  	}, nil
    53  }
    54  
    55  func (d *directory) Read(b []byte) (int, error) {
    56  	return 0, errors.New("is a directory")
    57  }
    58  
    59  func (d *directory) Close() error {
    60  	return nil
    61  }
    62  
    63  func (d *directory) ReadDir(n int) ([]fs.DirEntry, error) {
    64  	// Lock for read
    65  	d.RLock()
    66  	defer d.RUnlock()
    67  
    68  	// Retrieve children entry count
    69  	childrenNames := []string{}
    70  	for entryName := range d.children {
    71  		childrenNames = append(childrenNames, entryName)
    72  	}
    73  
    74  	// Apply read limit
    75  	if n <= 0 {
    76  		n = len(childrenNames)
    77  	}
    78  
    79  	// Iterate on children entities
    80  	out := []fs.DirEntry{}
    81  	for i := 0; i < len(childrenNames) && i < n; i++ {
    82  		name := childrenNames[i]
    83  		h := d.children[name]
    84  
    85  		switch item := h.(type) {
    86  		case *directory:
    87  			out = append(out, &dirEntry{
    88  				fi: &fileInfo{
    89  					name: item.name,
    90  					size: 1,
    91  					mode: item.perm | os.ModeDir,
    92  				},
    93  			})
    94  		case *file:
    95  			out = append(out, &dirEntry{
    96  				fi: &fileInfo{
    97  					name:    item.name,
    98  					size:    item.size,
    99  					modTime: item.modTime,
   100  					mode:    item.mode,
   101  				},
   102  			})
   103  		default:
   104  			continue
   105  		}
   106  	}
   107  
   108  	// Check directory entry exhaustion
   109  	if n > len(childrenNames) {
   110  		return out, io.EOF
   111  	}
   112  
   113  	// Check empty response
   114  	if len(out) == 0 {
   115  		return out, errors.New("directory has no entry")
   116  	}
   117  
   118  	// Return result
   119  	return out, nil
   120  }