Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-pages.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/karrick/godirwalk/readdir_unix.go')
-rw-r--r--vendor/github.com/karrick/godirwalk/readdir_unix.go116
1 files changed, 116 insertions, 0 deletions
diff --git a/vendor/github.com/karrick/godirwalk/readdir_unix.go b/vendor/github.com/karrick/godirwalk/readdir_unix.go
new file mode 100644
index 00000000..2d86434e
--- /dev/null
+++ b/vendor/github.com/karrick/godirwalk/readdir_unix.go
@@ -0,0 +1,116 @@
+// +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris
+
+package godirwalk
+
+import (
+ "os"
+ "path/filepath"
+ "syscall"
+ "unsafe"
+
+ "github.com/pkg/errors"
+)
+
+var defaultBufferSize, pageSize int
+
+func init() {
+ pageSize = os.Getpagesize()
+ defaultBufferSize = 2 * pageSize
+}
+
+func readdirents(osDirname string, scratchBuffer []byte) (Dirents, error) {
+ dh, err := os.Open(osDirname)
+ if err != nil {
+ return nil, errors.Wrap(err, "cannot Open")
+ }
+
+ var entries Dirents
+
+ fd := int(dh.Fd())
+
+ if len(scratchBuffer) < pageSize {
+ scratchBuffer = make([]byte, defaultBufferSize)
+ }
+
+ var de *syscall.Dirent
+
+ for {
+ n, err := syscall.ReadDirent(fd, scratchBuffer)
+ if err != nil {
+ _ = dh.Close() // ignore potential error returned by Close
+ return nil, errors.Wrap(err, "cannot ReadDirent")
+ }
+ if n <= 0 {
+ break // end of directory reached
+ }
+ // Loop over the bytes returned by reading the directory entries.
+ buf := scratchBuffer[:n]
+ for len(buf) > 0 {
+ de = (*syscall.Dirent)(unsafe.Pointer(&buf[0])) // point entry to first syscall.Dirent in buffer
+ buf = buf[de.Reclen:] // advance buffer
+
+ if de.Ino == 0 {
+ continue // this item has been deleted, but not yet removed from directory
+ }
+
+ nameSlice := nameFromDirent(de)
+ namlen := len(nameSlice)
+ if (namlen == 0) || (namlen == 1 && nameSlice[0] == '.') || (namlen == 2 && nameSlice[0] == '.' && nameSlice[1] == '.') {
+ continue // skip unimportant entries
+ }
+ osChildname := string(nameSlice)
+
+ // Convert syscall constant, which is in purview of OS, to a
+ // constant defined by Go, assumed by this project to be stable.
+ var mode os.FileMode
+ switch de.Type {
+ case syscall.DT_REG:
+ // regular file
+ case syscall.DT_DIR:
+ mode = os.ModeDir
+ case syscall.DT_LNK:
+ mode = os.ModeSymlink
+ case syscall.DT_CHR:
+ mode = os.ModeDevice | os.ModeCharDevice
+ case syscall.DT_BLK:
+ mode = os.ModeDevice
+ case syscall.DT_FIFO:
+ mode = os.ModeNamedPipe
+ case syscall.DT_SOCK:
+ mode = os.ModeSocket
+ default:
+ // If syscall returned unknown type (e.g., DT_UNKNOWN, DT_WHT),
+ // then resolve actual mode by getting stat.
+ fi, err := os.Stat(filepath.Join(osDirname, osChildname))
+ if err != nil {
+ _ = dh.Close() // ignore potential error returned by Close
+ return nil, errors.Wrap(err, "cannot Stat")
+ }
+ // We only care about the bits that identify the type of a file
+ // system node, and can ignore append, exclusive, temporary,
+ // setuid, setgid, permission bits, and sticky bits, which are
+ // coincident to the bits that declare type of the file system
+ // node.
+ mode = fi.Mode() & os.ModeType
+ }
+
+ entries = append(entries, &Dirent{name: osChildname, modeType: mode})
+ }
+ }
+ if err = dh.Close(); err != nil {
+ return nil, err
+ }
+ return entries, nil
+}
+
+func readdirnames(osDirname string, scratchBuffer []byte) ([]string, error) {
+ des, err := readdirents(osDirname, scratchBuffer)
+ if err != nil {
+ return nil, err
+ }
+ names := make([]string, len(des))
+ for i, v := range des {
+ names[i] = v.name
+ }
+ return names, nil
+}