OSDN Git Service

new repo
[bytom/vapor.git] / vendor / github.com / rjeczalik / notify / util.go
1 // Copyright (c) 2014-2015 The Notify Authors. All rights reserved.
2 // Use of this source code is governed by the MIT license that can be
3 // found in the LICENSE file.
4
5 package notify
6
7 import (
8         "errors"
9         "os"
10         "path/filepath"
11         "strings"
12 )
13
14 const all = ^Event(0)
15 const sep = string(os.PathSeparator)
16
17 var errDepth = errors.New("exceeded allowed iteration count (circular symlink?)")
18
19 func min(i, j int) int {
20         if i > j {
21                 return j
22         }
23         return i
24 }
25
26 func max(i, j int) int {
27         if i < j {
28                 return j
29         }
30         return i
31 }
32
33 // must panics if err is non-nil.
34 func must(err error) {
35         if err != nil {
36                 panic(err)
37         }
38 }
39
40 // nonil gives first non-nil error from the given arguments.
41 func nonil(err ...error) error {
42         for _, err := range err {
43                 if err != nil {
44                         return err
45                 }
46         }
47         return nil
48 }
49
50 func cleanpath(path string) (realpath string, isrec bool, err error) {
51         if strings.HasSuffix(path, "...") {
52                 isrec = true
53                 path = path[:len(path)-3]
54         }
55         if path, err = filepath.Abs(path); err != nil {
56                 return "", false, err
57         }
58         if path, err = canonical(path); err != nil {
59                 return "", false, err
60         }
61         return path, isrec, nil
62 }
63
64 // canonical resolves any symlink in the given path and returns it in a clean form.
65 // It expects the path to be absolute. It fails to resolve circular symlinks by
66 // maintaining a simple iteration limit.
67 func canonical(p string) (string, error) {
68         p, err := filepath.Abs(p)
69         if err != nil {
70                 return "", err
71         }
72         for i, j, depth := 1, 0, 1; i < len(p); i, depth = i+1, depth+1 {
73                 if depth > 128 {
74                         return "", &os.PathError{Op: "canonical", Path: p, Err: errDepth}
75                 }
76                 if j = strings.IndexRune(p[i:], '/'); j == -1 {
77                         j, i = i, len(p)
78                 } else {
79                         j, i = i, i+j
80                 }
81                 fi, err := os.Lstat(p[:i])
82                 if err != nil {
83                         return "", err
84                 }
85                 if fi.Mode()&os.ModeSymlink == os.ModeSymlink {
86                         s, err := os.Readlink(p[:i])
87                         if err != nil {
88                                 return "", err
89                         }
90                         if filepath.IsAbs(s) {
91                                 p = "/" + s + p[i:]
92                         } else {
93                                 p = p[:j] + s + p[i:]
94                         }
95                         i = 1 // no guarantee s is canonical, start all over
96                 }
97         }
98         return filepath.Clean(p), nil
99 }
100
101 func joinevents(events []Event) (e Event) {
102         if len(events) == 0 {
103                 e = All
104         } else {
105                 for _, event := range events {
106                         e |= event
107                 }
108         }
109         return
110 }
111
112 func split(s string) (string, string) {
113         if i := lastIndexSep(s); i != -1 {
114                 return s[:i], s[i+1:]
115         }
116         return "", s
117 }
118
119 func base(s string) string {
120         if i := lastIndexSep(s); i != -1 {
121                 return s[i+1:]
122         }
123         return s
124 }
125
126 func indexbase(root, name string) int {
127         if n, m := len(root), len(name); m >= n && name[:n] == root &&
128                 (n == m || name[n] == os.PathSeparator) {
129                 return min(n+1, m)
130         }
131         return -1
132 }
133
134 func indexSep(s string) int {
135         for i := 0; i < len(s); i++ {
136                 if s[i] == os.PathSeparator {
137                         return i
138                 }
139         }
140         return -1
141 }
142
143 func lastIndexSep(s string) int {
144         for i := len(s) - 1; i >= 0; i-- {
145                 if s[i] == os.PathSeparator {
146                         return i
147                 }
148         }
149         return -1
150 }