LEFT | RIGHT |
(no file at all) | |
1 // Copyright 2014 The Go Authors. All rights reserved. | 1 // Copyright 2014 The Go Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style | 2 // Use of this source code is governed by a BSD-style |
3 // license that can be found in the LICENSE file. | 3 // license that can be found in the LICENSE file. |
4 | 4 |
5 package webdav | 5 package webdav |
6 | 6 |
7 import ( | 7 import ( |
8 "io" | 8 "io" |
9 "net/http" | 9 "net/http" |
10 "os" | 10 "os" |
| 11 "path" |
| 12 "path/filepath" |
| 13 "strings" |
11 ) | 14 ) |
12 | 15 |
13 // TODO: comment that paths are always "/"-separated, even for Windows servers. | 16 // A FileSystem implements access to a collection of named files. The elements |
14 | 17 // in a file path are separated by slash ('/', U+002F) characters, regardless |
| 18 // of host operating system convention. |
| 19 // |
| 20 // Each method has the same semantics as the os package's function of the same |
| 21 // name. |
15 type FileSystem interface { | 22 type FileSystem interface { |
16 » Mkdir(path string, perm os.FileMode) error | 23 » Mkdir(name string, perm os.FileMode) error |
17 » OpenFile(path string, flag int, perm os.FileMode) (File, error) | 24 » OpenFile(name string, flag int, perm os.FileMode) (File, error) |
18 » RemoveAll(path string) error | 25 » RemoveAll(name string) error |
19 » Stat(path string) (os.FileInfo, error) | 26 » Stat(name string) (os.FileInfo, error) |
20 } | 27 } |
21 | 28 |
| 29 // A File is returned by a FileSystem's OpenFile method and can be served by a |
| 30 // Handler. |
22 type File interface { | 31 type File interface { |
23 http.File | 32 http.File |
24 io.Writer | 33 io.Writer |
25 } | 34 } |
26 | 35 |
| 36 // A Dir implements FileSystem using the native file system restricted to a |
| 37 // specific directory tree. |
| 38 // |
| 39 // While the FileSystem.OpenFile method takes '/'-separated paths, a Dir's |
| 40 // string value is a filename on the native file system, not a URL, so it is |
| 41 // separated by filepath.Separator, which isn't necessarily '/'. |
| 42 // |
| 43 // An empty Dir is treated as ".". |
| 44 type Dir string |
| 45 |
| 46 func (d Dir) resolve(name string) string { |
| 47 // This implementation is based on Dir.Open's code in the standard net/h
ttp package. |
| 48 if filepath.Separator != '/' && strings.IndexRune(name, filepath.Separat
or) >= 0 || |
| 49 strings.Contains(name, "\x00") { |
| 50 return "" |
| 51 } |
| 52 dir := string(d) |
| 53 if dir == "" { |
| 54 dir = "." |
| 55 } |
| 56 return filepath.Join(dir, filepath.FromSlash(path.Clean("/"+name))) |
| 57 } |
| 58 |
| 59 func (d Dir) Mkdir(name string, perm os.FileMode) error { |
| 60 if name = d.resolve(name); name == "" { |
| 61 return os.ErrNotExist |
| 62 } |
| 63 return os.Mkdir(name, perm) |
| 64 } |
| 65 |
| 66 func (d Dir) OpenFile(name string, flag int, perm os.FileMode) (File, error) { |
| 67 if name = d.resolve(name); name == "" { |
| 68 return nil, os.ErrNotExist |
| 69 } |
| 70 return os.OpenFile(name, flag, perm) |
| 71 } |
| 72 |
| 73 func (d Dir) RemoveAll(name string) error { |
| 74 if name = d.resolve(name); name == "" { |
| 75 return os.ErrNotExist |
| 76 } |
| 77 if name == filepath.Clean(string(d)) { |
| 78 // Prohibit removing the virtual root directory. |
| 79 return os.ErrInvalid |
| 80 } |
| 81 return os.RemoveAll(name) |
| 82 } |
| 83 |
| 84 func (d Dir) Stat(name string) (os.FileInfo, error) { |
| 85 if name = d.resolve(name); name == "" { |
| 86 return nil, os.ErrNotExist |
| 87 } |
| 88 return os.Stat(name) |
| 89 } |
| 90 |
27 // TODO: a MemFS implementation. | 91 // TODO: a MemFS implementation. |
28 // TODO: a RealFS implementation, backed by the real, OS-provided file system. | |
LEFT | RIGHT |