cae.go 2.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. // Package cae implements PHP-like Compression and Archive Extensions.
  2. package cae
  3. import (
  4. "io"
  5. "os"
  6. "strings"
  7. )
  8. // A Streamer describes an streamable archive object.
  9. type Streamer interface {
  10. StreamFile(string, os.FileInfo, []byte) error
  11. StreamReader(string, os.FileInfo, io.Reader) error
  12. Close() error
  13. }
  14. // A HookFunc represents a middleware for packing and extracting archive.
  15. type HookFunc func(string, os.FileInfo) error
  16. // HasPrefix returns true if name has any string in given slice as prefix.
  17. func HasPrefix(name string, prefixes []string) bool {
  18. for _, prefix := range prefixes {
  19. if strings.HasPrefix(name, prefix) {
  20. return true
  21. }
  22. }
  23. return false
  24. }
  25. // IsEntry returns true if name equals to any string in given slice.
  26. func IsEntry(name string, entries []string) bool {
  27. for _, e := range entries {
  28. if e == name {
  29. return true
  30. }
  31. }
  32. return false
  33. }
  34. // IsFilter returns true if given name matches any of global filter rule.
  35. func IsFilter(name string) bool {
  36. if strings.Contains(name, ".DS_Store") {
  37. return true
  38. }
  39. return false
  40. }
  41. // IsExist returns true if given path is a file or directory.
  42. func IsExist(path string) bool {
  43. _, err := os.Stat(path)
  44. return err == nil || os.IsExist(err)
  45. }
  46. // Copy copies file from source to target path.
  47. func Copy(dest, src string) error {
  48. // Gather file information to set back later.
  49. si, err := os.Lstat(src)
  50. if err != nil {
  51. return err
  52. }
  53. // Handle symbolic link.
  54. if si.Mode()&os.ModeSymlink != 0 {
  55. target, err := os.Readlink(src)
  56. if err != nil {
  57. return err
  58. }
  59. // NOTE: os.Chmod and os.Chtimes don't recoganize symbolic link,
  60. // which will lead "no such file or directory" error.
  61. return os.Symlink(target, dest)
  62. }
  63. sr, err := os.Open(src)
  64. if err != nil {
  65. return err
  66. }
  67. defer sr.Close()
  68. dw, err := os.Create(dest)
  69. if err != nil {
  70. return err
  71. }
  72. defer dw.Close()
  73. if _, err = io.Copy(dw, sr); err != nil {
  74. return err
  75. }
  76. // Set back file information.
  77. if err = os.Chtimes(dest, si.ModTime(), si.ModTime()); err != nil {
  78. return err
  79. }
  80. return os.Chmod(dest, si.Mode())
  81. }