Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>
| ... | ... |
@@ -102,6 +102,8 @@ google.golang.org/genproto d80a6e20e776b0b17a324d0ba1ab50a39c8e8944 |
| 102 | 102 |
# containerd |
| 103 | 103 |
github.com/containerd/containerd 3addd840653146c90a254301d6c3a663c7fd6429 |
| 104 | 104 |
github.com/tonistiigi/fifo 1405643975692217d6720f8b54aeee1bf2cd5cf4 |
| 105 |
+github.com/stevvooe/continuity cd7a8e21e2b6f84799f5dd4b65faf49c8d3ee02d |
|
| 106 |
+github.com/tonistiigi/fsutil 0ac4c11b053b9c5c7c47558f81f96c7100ce50fb |
|
| 105 | 107 |
|
| 106 | 108 |
# cluster |
| 107 | 109 |
github.com/docker/swarmkit a4bf0135f63fb60f0e76ae81579cde87f580db6e |
| 108 | 110 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,202 @@ |
| 0 |
+ Apache License |
|
| 1 |
+ Version 2.0, January 2004 |
|
| 2 |
+ http://www.apache.org/licenses/ |
|
| 3 |
+ |
|
| 4 |
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION |
|
| 5 |
+ |
|
| 6 |
+ 1. Definitions. |
|
| 7 |
+ |
|
| 8 |
+ "License" shall mean the terms and conditions for use, reproduction, |
|
| 9 |
+ and distribution as defined by Sections 1 through 9 of this document. |
|
| 10 |
+ |
|
| 11 |
+ "Licensor" shall mean the copyright owner or entity authorized by |
|
| 12 |
+ the copyright owner that is granting the License. |
|
| 13 |
+ |
|
| 14 |
+ "Legal Entity" shall mean the union of the acting entity and all |
|
| 15 |
+ other entities that control, are controlled by, or are under common |
|
| 16 |
+ control with that entity. For the purposes of this definition, |
|
| 17 |
+ "control" means (i) the power, direct or indirect, to cause the |
|
| 18 |
+ direction or management of such entity, whether by contract or |
|
| 19 |
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the |
|
| 20 |
+ outstanding shares, or (iii) beneficial ownership of such entity. |
|
| 21 |
+ |
|
| 22 |
+ "You" (or "Your") shall mean an individual or Legal Entity |
|
| 23 |
+ exercising permissions granted by this License. |
|
| 24 |
+ |
|
| 25 |
+ "Source" form shall mean the preferred form for making modifications, |
|
| 26 |
+ including but not limited to software source code, documentation |
|
| 27 |
+ source, and configuration files. |
|
| 28 |
+ |
|
| 29 |
+ "Object" form shall mean any form resulting from mechanical |
|
| 30 |
+ transformation or translation of a Source form, including but |
|
| 31 |
+ not limited to compiled object code, generated documentation, |
|
| 32 |
+ and conversions to other media types. |
|
| 33 |
+ |
|
| 34 |
+ "Work" shall mean the work of authorship, whether in Source or |
|
| 35 |
+ Object form, made available under the License, as indicated by a |
|
| 36 |
+ copyright notice that is included in or attached to the work |
|
| 37 |
+ (an example is provided in the Appendix below). |
|
| 38 |
+ |
|
| 39 |
+ "Derivative Works" shall mean any work, whether in Source or Object |
|
| 40 |
+ form, that is based on (or derived from) the Work and for which the |
|
| 41 |
+ editorial revisions, annotations, elaborations, or other modifications |
|
| 42 |
+ represent, as a whole, an original work of authorship. For the purposes |
|
| 43 |
+ of this License, Derivative Works shall not include works that remain |
|
| 44 |
+ separable from, or merely link (or bind by name) to the interfaces of, |
|
| 45 |
+ the Work and Derivative Works thereof. |
|
| 46 |
+ |
|
| 47 |
+ "Contribution" shall mean any work of authorship, including |
|
| 48 |
+ the original version of the Work and any modifications or additions |
|
| 49 |
+ to that Work or Derivative Works thereof, that is intentionally |
|
| 50 |
+ submitted to Licensor for inclusion in the Work by the copyright owner |
|
| 51 |
+ or by an individual or Legal Entity authorized to submit on behalf of |
|
| 52 |
+ the copyright owner. For the purposes of this definition, "submitted" |
|
| 53 |
+ means any form of electronic, verbal, or written communication sent |
|
| 54 |
+ to the Licensor or its representatives, including but not limited to |
|
| 55 |
+ communication on electronic mailing lists, source code control systems, |
|
| 56 |
+ and issue tracking systems that are managed by, or on behalf of, the |
|
| 57 |
+ Licensor for the purpose of discussing and improving the Work, but |
|
| 58 |
+ excluding communication that is conspicuously marked or otherwise |
|
| 59 |
+ designated in writing by the copyright owner as "Not a Contribution." |
|
| 60 |
+ |
|
| 61 |
+ "Contributor" shall mean Licensor and any individual or Legal Entity |
|
| 62 |
+ on behalf of whom a Contribution has been received by Licensor and |
|
| 63 |
+ subsequently incorporated within the Work. |
|
| 64 |
+ |
|
| 65 |
+ 2. Grant of Copyright License. Subject to the terms and conditions of |
|
| 66 |
+ this License, each Contributor hereby grants to You a perpetual, |
|
| 67 |
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable |
|
| 68 |
+ copyright license to reproduce, prepare Derivative Works of, |
|
| 69 |
+ publicly display, publicly perform, sublicense, and distribute the |
|
| 70 |
+ Work and such Derivative Works in Source or Object form. |
|
| 71 |
+ |
|
| 72 |
+ 3. Grant of Patent License. Subject to the terms and conditions of |
|
| 73 |
+ this License, each Contributor hereby grants to You a perpetual, |
|
| 74 |
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable |
|
| 75 |
+ (except as stated in this section) patent license to make, have made, |
|
| 76 |
+ use, offer to sell, sell, import, and otherwise transfer the Work, |
|
| 77 |
+ where such license applies only to those patent claims licensable |
|
| 78 |
+ by such Contributor that are necessarily infringed by their |
|
| 79 |
+ Contribution(s) alone or by combination of their Contribution(s) |
|
| 80 |
+ with the Work to which such Contribution(s) was submitted. If You |
|
| 81 |
+ institute patent litigation against any entity (including a |
|
| 82 |
+ cross-claim or counterclaim in a lawsuit) alleging that the Work |
|
| 83 |
+ or a Contribution incorporated within the Work constitutes direct |
|
| 84 |
+ or contributory patent infringement, then any patent licenses |
|
| 85 |
+ granted to You under this License for that Work shall terminate |
|
| 86 |
+ as of the date such litigation is filed. |
|
| 87 |
+ |
|
| 88 |
+ 4. Redistribution. You may reproduce and distribute copies of the |
|
| 89 |
+ Work or Derivative Works thereof in any medium, with or without |
|
| 90 |
+ modifications, and in Source or Object form, provided that You |
|
| 91 |
+ meet the following conditions: |
|
| 92 |
+ |
|
| 93 |
+ (a) You must give any other recipients of the Work or |
|
| 94 |
+ Derivative Works a copy of this License; and |
|
| 95 |
+ |
|
| 96 |
+ (b) You must cause any modified files to carry prominent notices |
|
| 97 |
+ stating that You changed the files; and |
|
| 98 |
+ |
|
| 99 |
+ (c) You must retain, in the Source form of any Derivative Works |
|
| 100 |
+ that You distribute, all copyright, patent, trademark, and |
|
| 101 |
+ attribution notices from the Source form of the Work, |
|
| 102 |
+ excluding those notices that do not pertain to any part of |
|
| 103 |
+ the Derivative Works; and |
|
| 104 |
+ |
|
| 105 |
+ (d) If the Work includes a "NOTICE" text file as part of its |
|
| 106 |
+ distribution, then any Derivative Works that You distribute must |
|
| 107 |
+ include a readable copy of the attribution notices contained |
|
| 108 |
+ within such NOTICE file, excluding those notices that do not |
|
| 109 |
+ pertain to any part of the Derivative Works, in at least one |
|
| 110 |
+ of the following places: within a NOTICE text file distributed |
|
| 111 |
+ as part of the Derivative Works; within the Source form or |
|
| 112 |
+ documentation, if provided along with the Derivative Works; or, |
|
| 113 |
+ within a display generated by the Derivative Works, if and |
|
| 114 |
+ wherever such third-party notices normally appear. The contents |
|
| 115 |
+ of the NOTICE file are for informational purposes only and |
|
| 116 |
+ do not modify the License. You may add Your own attribution |
|
| 117 |
+ notices within Derivative Works that You distribute, alongside |
|
| 118 |
+ or as an addendum to the NOTICE text from the Work, provided |
|
| 119 |
+ that such additional attribution notices cannot be construed |
|
| 120 |
+ as modifying the License. |
|
| 121 |
+ |
|
| 122 |
+ You may add Your own copyright statement to Your modifications and |
|
| 123 |
+ may provide additional or different license terms and conditions |
|
| 124 |
+ for use, reproduction, or distribution of Your modifications, or |
|
| 125 |
+ for any such Derivative Works as a whole, provided Your use, |
|
| 126 |
+ reproduction, and distribution of the Work otherwise complies with |
|
| 127 |
+ the conditions stated in this License. |
|
| 128 |
+ |
|
| 129 |
+ 5. Submission of Contributions. Unless You explicitly state otherwise, |
|
| 130 |
+ any Contribution intentionally submitted for inclusion in the Work |
|
| 131 |
+ by You to the Licensor shall be under the terms and conditions of |
|
| 132 |
+ this License, without any additional terms or conditions. |
|
| 133 |
+ Notwithstanding the above, nothing herein shall supersede or modify |
|
| 134 |
+ the terms of any separate license agreement you may have executed |
|
| 135 |
+ with Licensor regarding such Contributions. |
|
| 136 |
+ |
|
| 137 |
+ 6. Trademarks. This License does not grant permission to use the trade |
|
| 138 |
+ names, trademarks, service marks, or product names of the Licensor, |
|
| 139 |
+ except as required for reasonable and customary use in describing the |
|
| 140 |
+ origin of the Work and reproducing the content of the NOTICE file. |
|
| 141 |
+ |
|
| 142 |
+ 7. Disclaimer of Warranty. Unless required by applicable law or |
|
| 143 |
+ agreed to in writing, Licensor provides the Work (and each |
|
| 144 |
+ Contributor provides its Contributions) on an "AS IS" BASIS, |
|
| 145 |
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or |
|
| 146 |
+ implied, including, without limitation, any warranties or conditions |
|
| 147 |
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A |
|
| 148 |
+ PARTICULAR PURPOSE. You are solely responsible for determining the |
|
| 149 |
+ appropriateness of using or redistributing the Work and assume any |
|
| 150 |
+ risks associated with Your exercise of permissions under this License. |
|
| 151 |
+ |
|
| 152 |
+ 8. Limitation of Liability. In no event and under no legal theory, |
|
| 153 |
+ whether in tort (including negligence), contract, or otherwise, |
|
| 154 |
+ unless required by applicable law (such as deliberate and grossly |
|
| 155 |
+ negligent acts) or agreed to in writing, shall any Contributor be |
|
| 156 |
+ liable to You for damages, including any direct, indirect, special, |
|
| 157 |
+ incidental, or consequential damages of any character arising as a |
|
| 158 |
+ result of this License or out of the use or inability to use the |
|
| 159 |
+ Work (including but not limited to damages for loss of goodwill, |
|
| 160 |
+ work stoppage, computer failure or malfunction, or any and all |
|
| 161 |
+ other commercial damages or losses), even if such Contributor |
|
| 162 |
+ has been advised of the possibility of such damages. |
|
| 163 |
+ |
|
| 164 |
+ 9. Accepting Warranty or Additional Liability. While redistributing |
|
| 165 |
+ the Work or Derivative Works thereof, You may choose to offer, |
|
| 166 |
+ and charge a fee for, acceptance of support, warranty, indemnity, |
|
| 167 |
+ or other liability obligations and/or rights consistent with this |
|
| 168 |
+ License. However, in accepting such obligations, You may act only |
|
| 169 |
+ on Your own behalf and on Your sole responsibility, not on behalf |
|
| 170 |
+ of any other Contributor, and only if You agree to indemnify, |
|
| 171 |
+ defend, and hold each Contributor harmless for any liability |
|
| 172 |
+ incurred by, or claims asserted against, such Contributor by reason |
|
| 173 |
+ of your accepting any such warranty or additional liability. |
|
| 174 |
+ |
|
| 175 |
+ END OF TERMS AND CONDITIONS |
|
| 176 |
+ |
|
| 177 |
+ APPENDIX: How to apply the Apache License to your work. |
|
| 178 |
+ |
|
| 179 |
+ To apply the Apache License to your work, attach the following |
|
| 180 |
+ boilerplate notice, with the fields enclosed by brackets "{}"
|
|
| 181 |
+ replaced with your own identifying information. (Don't include |
|
| 182 |
+ the brackets!) The text should be enclosed in the appropriate |
|
| 183 |
+ comment syntax for the file format. We also recommend that a |
|
| 184 |
+ file or class name and description of purpose be included on the |
|
| 185 |
+ same "printed page" as the copyright notice for easier |
|
| 186 |
+ identification within third-party archives. |
|
| 187 |
+ |
|
| 188 |
+ Copyright {yyyy} {name of copyright owner}
|
|
| 189 |
+ |
|
| 190 |
+ Licensed under the Apache License, Version 2.0 (the "License"); |
|
| 191 |
+ you may not use this file except in compliance with the License. |
|
| 192 |
+ You may obtain a copy of the License at |
|
| 193 |
+ |
|
| 194 |
+ http://www.apache.org/licenses/LICENSE-2.0 |
|
| 195 |
+ |
|
| 196 |
+ Unless required by applicable law or agreed to in writing, software |
|
| 197 |
+ distributed under the License is distributed on an "AS IS" BASIS, |
|
| 198 |
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
| 199 |
+ See the License for the specific language governing permissions and |
|
| 200 |
+ limitations under the License. |
|
| 201 |
+ |
| 0 | 202 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,19 @@ |
| 0 |
+# continuity |
|
| 1 |
+ |
|
| 2 |
+[](https://godoc.org/github.com/containerd/continuity) |
|
| 3 |
+[](https://travis-ci.org/containerd/continuity) |
|
| 4 |
+ |
|
| 5 |
+A transport-agnostic, filesystem metadata manifest system |
|
| 6 |
+ |
|
| 7 |
+This project is a staging area for experiments in providing transport agnostic |
|
| 8 |
+metadata storage. |
|
| 9 |
+ |
|
| 10 |
+Please see https://github.com/opencontainers/specs/issues/11 for more details. |
|
| 11 |
+ |
|
| 12 |
+## Building Proto Package |
|
| 13 |
+ |
|
| 14 |
+If you change the proto file you will need to rebuild the generated Go with `go generate`. |
|
| 15 |
+ |
|
| 16 |
+``` |
|
| 17 |
+go generate ./proto |
|
| 18 |
+``` |
| 0 | 19 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,10 @@ |
| 0 |
+// Copyright 2014 The Go Authors. All rights reserved. |
|
| 1 |
+// Use of this source code is governed by a BSD-style |
|
| 2 |
+// license that can be found in the LICENSE file. |
|
| 3 |
+ |
|
| 4 |
+// +build !gccgo |
|
| 5 |
+ |
|
| 6 |
+#include "textflag.h" |
|
| 7 |
+ |
|
| 8 |
+TEXT ·use(SB),NOSPLIT,$0 |
|
| 9 |
+ RET |
| 0 | 10 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,18 @@ |
| 0 |
+package sysx |
|
| 1 |
+ |
|
| 2 |
+const ( |
|
| 3 |
+ // AtSymlinkNoFollow defined from AT_SYMLINK_NOFOLLOW in <sys/fcntl.h> |
|
| 4 |
+ AtSymlinkNofollow = 0x20 |
|
| 5 |
+) |
|
| 6 |
+ |
|
| 7 |
+const ( |
|
| 8 |
+ |
|
| 9 |
+ // SYS_FCHMODAT defined from golang.org/sys/unix |
|
| 10 |
+ SYS_FCHMODAT = 467 |
|
| 11 |
+) |
|
| 12 |
+ |
|
| 13 |
+// These functions will be generated by generate.sh |
|
| 14 |
+// $ GOOS=darwin GOARCH=386 ./generate.sh chmod |
|
| 15 |
+// $ GOOS=darwin GOARCH=amd64 ./generate.sh chmod |
|
| 16 |
+ |
|
| 17 |
+//sys Fchmodat(dirfd int, path string, mode uint32, flags int) (err error) |
| 0 | 18 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,25 @@ |
| 0 |
+// mksyscall.pl -l32 chmod_darwin.go |
|
| 1 |
+// MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT |
|
| 2 |
+ |
|
| 3 |
+package sysx |
|
| 4 |
+ |
|
| 5 |
+import ( |
|
| 6 |
+ "syscall" |
|
| 7 |
+ "unsafe" |
|
| 8 |
+) |
|
| 9 |
+ |
|
| 10 |
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT |
|
| 11 |
+ |
|
| 12 |
+func Fchmodat(dirfd int, path string, mode uint32, flags int) (err error) {
|
|
| 13 |
+ var _p0 *byte |
|
| 14 |
+ _p0, err = syscall.BytePtrFromString(path) |
|
| 15 |
+ if err != nil {
|
|
| 16 |
+ return |
|
| 17 |
+ } |
|
| 18 |
+ _, _, e1 := syscall.Syscall6(SYS_FCHMODAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(flags), 0, 0) |
|
| 19 |
+ use(unsafe.Pointer(_p0)) |
|
| 20 |
+ if e1 != 0 {
|
|
| 21 |
+ err = errnoErr(e1) |
|
| 22 |
+ } |
|
| 23 |
+ return |
|
| 24 |
+} |
| 0 | 25 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,25 @@ |
| 0 |
+// mksyscall.pl chmod_darwin.go |
|
| 1 |
+// MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT |
|
| 2 |
+ |
|
| 3 |
+package sysx |
|
| 4 |
+ |
|
| 5 |
+import ( |
|
| 6 |
+ "syscall" |
|
| 7 |
+ "unsafe" |
|
| 8 |
+) |
|
| 9 |
+ |
|
| 10 |
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT |
|
| 11 |
+ |
|
| 12 |
+func Fchmodat(dirfd int, path string, mode uint32, flags int) (err error) {
|
|
| 13 |
+ var _p0 *byte |
|
| 14 |
+ _p0, err = syscall.BytePtrFromString(path) |
|
| 15 |
+ if err != nil {
|
|
| 16 |
+ return |
|
| 17 |
+ } |
|
| 18 |
+ _, _, e1 := syscall.Syscall6(SYS_FCHMODAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(flags), 0, 0) |
|
| 19 |
+ use(unsafe.Pointer(_p0)) |
|
| 20 |
+ if e1 != 0 {
|
|
| 21 |
+ err = errnoErr(e1) |
|
| 22 |
+ } |
|
| 23 |
+ return |
|
| 24 |
+} |
| 0 | 25 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,17 @@ |
| 0 |
+package sysx |
|
| 1 |
+ |
|
| 2 |
+const ( |
|
| 3 |
+ // AtSymlinkNoFollow defined from AT_SYMLINK_NOFOLLOW in <sys/fcntl.h> |
|
| 4 |
+ AtSymlinkNofollow = 0x200 |
|
| 5 |
+) |
|
| 6 |
+ |
|
| 7 |
+const ( |
|
| 8 |
+ |
|
| 9 |
+ // SYS_FCHMODAT defined from golang.org/sys/unix |
|
| 10 |
+ SYS_FCHMODAT = 490 |
|
| 11 |
+) |
|
| 12 |
+ |
|
| 13 |
+// These functions will be generated by generate.sh |
|
| 14 |
+// $ GOOS=freebsd GOARCH=amd64 ./generate.sh chmod |
|
| 15 |
+ |
|
| 16 |
+//sys Fchmodat(dirfd int, path string, mode uint32, flags int) (err error) |
| 0 | 17 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,25 @@ |
| 0 |
+// mksyscall.pl chmod_freebsd.go |
|
| 1 |
+// MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT |
|
| 2 |
+ |
|
| 3 |
+package sysx |
|
| 4 |
+ |
|
| 5 |
+import ( |
|
| 6 |
+ "syscall" |
|
| 7 |
+ "unsafe" |
|
| 8 |
+) |
|
| 9 |
+ |
|
| 10 |
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT |
|
| 11 |
+ |
|
| 12 |
+func Fchmodat(dirfd int, path string, mode uint32, flags int) (err error) {
|
|
| 13 |
+ var _p0 *byte |
|
| 14 |
+ _p0, err = syscall.BytePtrFromString(path) |
|
| 15 |
+ if err != nil {
|
|
| 16 |
+ return |
|
| 17 |
+ } |
|
| 18 |
+ _, _, e1 := syscall.Syscall6(SYS_FCHMODAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(flags), 0, 0) |
|
| 19 |
+ use(unsafe.Pointer(_p0)) |
|
| 20 |
+ if e1 != 0 {
|
|
| 21 |
+ err = errnoErr(e1) |
|
| 22 |
+ } |
|
| 23 |
+ return |
|
| 24 |
+} |
| 0 | 25 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,12 @@ |
| 0 |
+package sysx |
|
| 1 |
+ |
|
| 2 |
+import "syscall" |
|
| 3 |
+ |
|
| 4 |
+const ( |
|
| 5 |
+ // AtSymlinkNoFollow defined from AT_SYMLINK_NOFOLLOW in /usr/include/linux/fcntl.h |
|
| 6 |
+ AtSymlinkNofollow = 0x100 |
|
| 7 |
+) |
|
| 8 |
+ |
|
| 9 |
+func Fchmodat(dirfd int, path string, mode uint32, flags int) error {
|
|
| 10 |
+ return syscall.Fchmodat(dirfd, path, mode, flags) |
|
| 11 |
+} |
| 0 | 12 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,9 @@ |
| 0 |
+package sysx |
|
| 1 |
+ |
|
| 2 |
+// These functions will be generated by generate.sh |
|
| 3 |
+// $ GOOS=linux GOARCH=386 ./generate.sh copy |
|
| 4 |
+// $ GOOS=linux GOARCH=amd64 ./generate.sh copy |
|
| 5 |
+// $ GOOS=linux GOARCH=arm ./generate.sh copy |
|
| 6 |
+// $ GOOS=linux GOARCH=arm64 ./generate.sh copy |
|
| 7 |
+ |
|
| 8 |
+//sys CopyFileRange(fdin uintptr, offin *int64, fdout uintptr, offout *int64, len int, flags int) (n int, err error) |
| 0 | 9 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,20 @@ |
| 0 |
+// mksyscall.pl -l32 copy_linux.go |
|
| 1 |
+// MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT |
|
| 2 |
+ |
|
| 3 |
+package sysx |
|
| 4 |
+ |
|
| 5 |
+import ( |
|
| 6 |
+ "syscall" |
|
| 7 |
+ "unsafe" |
|
| 8 |
+) |
|
| 9 |
+ |
|
| 10 |
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT |
|
| 11 |
+ |
|
| 12 |
+func CopyFileRange(fdin uintptr, offin *int64, fdout uintptr, offout *int64, len int, flags int) (n int, err error) {
|
|
| 13 |
+ r0, _, e1 := syscall.Syscall6(SYS_COPY_FILE_RANGE, uintptr(fdin), uintptr(unsafe.Pointer(offin)), uintptr(fdout), uintptr(unsafe.Pointer(offout)), uintptr(len), uintptr(flags)) |
|
| 14 |
+ n = int(r0) |
|
| 15 |
+ if e1 != 0 {
|
|
| 16 |
+ err = errnoErr(e1) |
|
| 17 |
+ } |
|
| 18 |
+ return |
|
| 19 |
+} |
| 0 | 20 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,20 @@ |
| 0 |
+// mksyscall.pl copy_linux.go |
|
| 1 |
+// MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT |
|
| 2 |
+ |
|
| 3 |
+package sysx |
|
| 4 |
+ |
|
| 5 |
+import ( |
|
| 6 |
+ "syscall" |
|
| 7 |
+ "unsafe" |
|
| 8 |
+) |
|
| 9 |
+ |
|
| 10 |
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT |
|
| 11 |
+ |
|
| 12 |
+func CopyFileRange(fdin uintptr, offin *int64, fdout uintptr, offout *int64, len int, flags int) (n int, err error) {
|
|
| 13 |
+ r0, _, e1 := syscall.Syscall6(SYS_COPY_FILE_RANGE, uintptr(fdin), uintptr(unsafe.Pointer(offin)), uintptr(fdout), uintptr(unsafe.Pointer(offout)), uintptr(len), uintptr(flags)) |
|
| 14 |
+ n = int(r0) |
|
| 15 |
+ if e1 != 0 {
|
|
| 16 |
+ err = errnoErr(e1) |
|
| 17 |
+ } |
|
| 18 |
+ return |
|
| 19 |
+} |
| 0 | 20 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,20 @@ |
| 0 |
+// mksyscall.pl -l32 copy_linux.go |
|
| 1 |
+// MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT |
|
| 2 |
+ |
|
| 3 |
+package sysx |
|
| 4 |
+ |
|
| 5 |
+import ( |
|
| 6 |
+ "syscall" |
|
| 7 |
+ "unsafe" |
|
| 8 |
+) |
|
| 9 |
+ |
|
| 10 |
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT |
|
| 11 |
+ |
|
| 12 |
+func CopyFileRange(fdin uintptr, offin *int64, fdout uintptr, offout *int64, len int, flags int) (n int, err error) {
|
|
| 13 |
+ r0, _, e1 := syscall.Syscall6(SYS_COPY_FILE_RANGE, uintptr(fdin), uintptr(unsafe.Pointer(offin)), uintptr(fdout), uintptr(unsafe.Pointer(offout)), uintptr(len), uintptr(flags)) |
|
| 14 |
+ n = int(r0) |
|
| 15 |
+ if e1 != 0 {
|
|
| 16 |
+ err = errnoErr(e1) |
|
| 17 |
+ } |
|
| 18 |
+ return |
|
| 19 |
+} |
| 0 | 20 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,20 @@ |
| 0 |
+// mksyscall.pl copy_linux.go |
|
| 1 |
+// MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT |
|
| 2 |
+ |
|
| 3 |
+package sysx |
|
| 4 |
+ |
|
| 5 |
+import ( |
|
| 6 |
+ "syscall" |
|
| 7 |
+ "unsafe" |
|
| 8 |
+) |
|
| 9 |
+ |
|
| 10 |
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT |
|
| 11 |
+ |
|
| 12 |
+func CopyFileRange(fdin uintptr, offin *int64, fdout uintptr, offout *int64, len int, flags int) (n int, err error) {
|
|
| 13 |
+ r0, _, e1 := syscall.Syscall6(SYS_COPY_FILE_RANGE, uintptr(fdin), uintptr(unsafe.Pointer(offin)), uintptr(fdout), uintptr(unsafe.Pointer(offout)), uintptr(len), uintptr(flags)) |
|
| 14 |
+ n = int(r0) |
|
| 15 |
+ if e1 != 0 {
|
|
| 16 |
+ err = errnoErr(e1) |
|
| 17 |
+ } |
|
| 18 |
+ return |
|
| 19 |
+} |
| 0 | 9 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,37 @@ |
| 0 |
+package sysx |
|
| 1 |
+ |
|
| 2 |
+import ( |
|
| 3 |
+ "syscall" |
|
| 4 |
+ "unsafe" |
|
| 5 |
+) |
|
| 6 |
+ |
|
| 7 |
+var _zero uintptr |
|
| 8 |
+ |
|
| 9 |
+// use is a no-op, but the compiler cannot see that it is. |
|
| 10 |
+// Calling use(p) ensures that p is kept live until that point. |
|
| 11 |
+//go:noescape |
|
| 12 |
+func use(p unsafe.Pointer) |
|
| 13 |
+ |
|
| 14 |
+// Do the interface allocations only once for common |
|
| 15 |
+// Errno values. |
|
| 16 |
+var ( |
|
| 17 |
+ errEAGAIN error = syscall.EAGAIN |
|
| 18 |
+ errEINVAL error = syscall.EINVAL |
|
| 19 |
+ errENOENT error = syscall.ENOENT |
|
| 20 |
+) |
|
| 21 |
+ |
|
| 22 |
+// errnoErr returns common boxed Errno values, to prevent |
|
| 23 |
+// allocations at runtime. |
|
| 24 |
+func errnoErr(e syscall.Errno) error {
|
|
| 25 |
+ switch e {
|
|
| 26 |
+ case 0: |
|
| 27 |
+ return nil |
|
| 28 |
+ case syscall.EAGAIN: |
|
| 29 |
+ return errEAGAIN |
|
| 30 |
+ case syscall.EINVAL: |
|
| 31 |
+ return errEINVAL |
|
| 32 |
+ case syscall.ENOENT: |
|
| 33 |
+ return errENOENT |
|
| 34 |
+ } |
|
| 35 |
+ return e |
|
| 36 |
+} |
| 0 | 7 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,67 @@ |
| 0 |
+package sysx |
|
| 1 |
+ |
|
| 2 |
+import ( |
|
| 3 |
+ "bytes" |
|
| 4 |
+ "fmt" |
|
| 5 |
+ "syscall" |
|
| 6 |
+) |
|
| 7 |
+ |
|
| 8 |
+const defaultXattrBufferSize = 5 |
|
| 9 |
+ |
|
| 10 |
+var ErrNotSupported = fmt.Errorf("not supported")
|
|
| 11 |
+ |
|
| 12 |
+type listxattrFunc func(path string, dest []byte) (int, error) |
|
| 13 |
+ |
|
| 14 |
+func listxattrAll(path string, listFunc listxattrFunc) ([]string, error) {
|
|
| 15 |
+ var p []byte // nil on first execution |
|
| 16 |
+ |
|
| 17 |
+ for {
|
|
| 18 |
+ n, err := listFunc(path, p) // first call gets buffer size. |
|
| 19 |
+ if err != nil {
|
|
| 20 |
+ return nil, err |
|
| 21 |
+ } |
|
| 22 |
+ |
|
| 23 |
+ if n > len(p) {
|
|
| 24 |
+ p = make([]byte, n) |
|
| 25 |
+ continue |
|
| 26 |
+ } |
|
| 27 |
+ |
|
| 28 |
+ p = p[:n] |
|
| 29 |
+ |
|
| 30 |
+ ps := bytes.Split(bytes.TrimSuffix(p, []byte{0}), []byte{0})
|
|
| 31 |
+ var entries []string |
|
| 32 |
+ for _, p := range ps {
|
|
| 33 |
+ s := string(p) |
|
| 34 |
+ if s != "" {
|
|
| 35 |
+ entries = append(entries, s) |
|
| 36 |
+ } |
|
| 37 |
+ } |
|
| 38 |
+ |
|
| 39 |
+ return entries, nil |
|
| 40 |
+ } |
|
| 41 |
+} |
|
| 42 |
+ |
|
| 43 |
+type getxattrFunc func(string, string, []byte) (int, error) |
|
| 44 |
+ |
|
| 45 |
+func getxattrAll(path, attr string, getFunc getxattrFunc) ([]byte, error) {
|
|
| 46 |
+ p := make([]byte, defaultXattrBufferSize) |
|
| 47 |
+ for {
|
|
| 48 |
+ n, err := getFunc(path, attr, p) |
|
| 49 |
+ if err != nil {
|
|
| 50 |
+ if errno, ok := err.(syscall.Errno); ok && errno == syscall.ERANGE {
|
|
| 51 |
+ p = make([]byte, len(p)*2) // this can't be ideal. |
|
| 52 |
+ continue // try again! |
|
| 53 |
+ } |
|
| 54 |
+ |
|
| 55 |
+ return nil, err |
|
| 56 |
+ } |
|
| 57 |
+ |
|
| 58 |
+ // realloc to correct size and repeat |
|
| 59 |
+ if n > len(p) {
|
|
| 60 |
+ p = make([]byte, n) |
|
| 61 |
+ continue |
|
| 62 |
+ } |
|
| 63 |
+ |
|
| 64 |
+ return p[:n], nil |
|
| 65 |
+ } |
|
| 66 |
+} |
| 0 | 67 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,71 @@ |
| 0 |
+package sysx |
|
| 1 |
+ |
|
| 2 |
+// These functions will be generated by generate.sh |
|
| 3 |
+// $ GOOS=darwin GOARCH=386 ./generate.sh xattr |
|
| 4 |
+// $ GOOS=darwin GOARCH=amd64 ./generate.sh xattr |
|
| 5 |
+ |
|
| 6 |
+//sys getxattr(path string, attr string, dest []byte, pos int, options int) (sz int, err error) |
|
| 7 |
+//sys setxattr(path string, attr string, data []byte, flags int) (err error) |
|
| 8 |
+//sys removexattr(path string, attr string, options int) (err error) |
|
| 9 |
+//sys listxattr(path string, dest []byte, options int) (sz int, err error) |
|
| 10 |
+//sys Fchmodat(dirfd int, path string, mode uint32, flags int) (err error) |
|
| 11 |
+ |
|
| 12 |
+const ( |
|
| 13 |
+ xattrNoFollow = 0x01 |
|
| 14 |
+) |
|
| 15 |
+ |
|
| 16 |
+func listxattrFollow(path string, dest []byte) (sz int, err error) {
|
|
| 17 |
+ return listxattr(path, dest, 0) |
|
| 18 |
+} |
|
| 19 |
+ |
|
| 20 |
+// Listxattr calls syscall getxattr |
|
| 21 |
+func Listxattr(path string) ([]string, error) {
|
|
| 22 |
+ return listxattrAll(path, listxattrFollow) |
|
| 23 |
+} |
|
| 24 |
+ |
|
| 25 |
+// Removexattr calls syscall getxattr |
|
| 26 |
+func Removexattr(path string, attr string) (err error) {
|
|
| 27 |
+ return removexattr(path, attr, 0) |
|
| 28 |
+} |
|
| 29 |
+ |
|
| 30 |
+// Setxattr calls syscall setxattr |
|
| 31 |
+func Setxattr(path string, attr string, data []byte, flags int) (err error) {
|
|
| 32 |
+ return setxattr(path, attr, data, flags) |
|
| 33 |
+} |
|
| 34 |
+ |
|
| 35 |
+func getxattrFollow(path, attr string, dest []byte) (sz int, err error) {
|
|
| 36 |
+ return getxattr(path, attr, dest, 0, 0) |
|
| 37 |
+} |
|
| 38 |
+ |
|
| 39 |
+// Getxattr calls syscall getxattr |
|
| 40 |
+func Getxattr(path, attr string) ([]byte, error) {
|
|
| 41 |
+ return getxattrAll(path, attr, getxattrFollow) |
|
| 42 |
+} |
|
| 43 |
+ |
|
| 44 |
+func listxattrNoFollow(path string, dest []byte) (sz int, err error) {
|
|
| 45 |
+ return listxattr(path, dest, xattrNoFollow) |
|
| 46 |
+} |
|
| 47 |
+ |
|
| 48 |
+// LListxattr calls syscall listxattr with XATTR_NOFOLLOW |
|
| 49 |
+func LListxattr(path string) ([]string, error) {
|
|
| 50 |
+ return listxattrAll(path, listxattrNoFollow) |
|
| 51 |
+} |
|
| 52 |
+ |
|
| 53 |
+// LRemovexattr calls syscall removexattr with XATTR_NOFOLLOW |
|
| 54 |
+func LRemovexattr(path string, attr string) (err error) {
|
|
| 55 |
+ return removexattr(path, attr, xattrNoFollow) |
|
| 56 |
+} |
|
| 57 |
+ |
|
| 58 |
+// Setxattr calls syscall setxattr with XATTR_NOFOLLOW |
|
| 59 |
+func LSetxattr(path string, attr string, data []byte, flags int) (err error) {
|
|
| 60 |
+ return setxattr(path, attr, data, flags|xattrNoFollow) |
|
| 61 |
+} |
|
| 62 |
+ |
|
| 63 |
+func getxattrNoFollow(path, attr string, dest []byte) (sz int, err error) {
|
|
| 64 |
+ return getxattr(path, attr, dest, 0, xattrNoFollow) |
|
| 65 |
+} |
|
| 66 |
+ |
|
| 67 |
+// LGetxattr calls syscall getxattr with XATTR_NOFOLLOW |
|
| 68 |
+func LGetxattr(path, attr string) ([]byte, error) {
|
|
| 69 |
+ return getxattrAll(path, attr, getxattrNoFollow) |
|
| 70 |
+} |
| 0 | 71 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,111 @@ |
| 0 |
+// mksyscall.pl -l32 xattr_darwin.go |
|
| 1 |
+// MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT |
|
| 2 |
+ |
|
| 3 |
+package sysx |
|
| 4 |
+ |
|
| 5 |
+import ( |
|
| 6 |
+ "syscall" |
|
| 7 |
+ "unsafe" |
|
| 8 |
+) |
|
| 9 |
+ |
|
| 10 |
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT |
|
| 11 |
+ |
|
| 12 |
+func getxattr(path string, attr string, dest []byte, pos int, options int) (sz int, err error) {
|
|
| 13 |
+ var _p0 *byte |
|
| 14 |
+ _p0, err = syscall.BytePtrFromString(path) |
|
| 15 |
+ if err != nil {
|
|
| 16 |
+ return |
|
| 17 |
+ } |
|
| 18 |
+ var _p1 *byte |
|
| 19 |
+ _p1, err = syscall.BytePtrFromString(attr) |
|
| 20 |
+ if err != nil {
|
|
| 21 |
+ return |
|
| 22 |
+ } |
|
| 23 |
+ var _p2 unsafe.Pointer |
|
| 24 |
+ if len(dest) > 0 {
|
|
| 25 |
+ _p2 = unsafe.Pointer(&dest[0]) |
|
| 26 |
+ } else {
|
|
| 27 |
+ _p2 = unsafe.Pointer(&_zero) |
|
| 28 |
+ } |
|
| 29 |
+ r0, _, e1 := syscall.Syscall6(syscall.SYS_GETXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(_p2), uintptr(len(dest)), uintptr(pos), uintptr(options)) |
|
| 30 |
+ use(unsafe.Pointer(_p0)) |
|
| 31 |
+ use(unsafe.Pointer(_p1)) |
|
| 32 |
+ sz = int(r0) |
|
| 33 |
+ if e1 != 0 {
|
|
| 34 |
+ err = errnoErr(e1) |
|
| 35 |
+ } |
|
| 36 |
+ return |
|
| 37 |
+} |
|
| 38 |
+ |
|
| 39 |
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT |
|
| 40 |
+ |
|
| 41 |
+func setxattr(path string, attr string, data []byte, flags int) (err error) {
|
|
| 42 |
+ var _p0 *byte |
|
| 43 |
+ _p0, err = syscall.BytePtrFromString(path) |
|
| 44 |
+ if err != nil {
|
|
| 45 |
+ return |
|
| 46 |
+ } |
|
| 47 |
+ var _p1 *byte |
|
| 48 |
+ _p1, err = syscall.BytePtrFromString(attr) |
|
| 49 |
+ if err != nil {
|
|
| 50 |
+ return |
|
| 51 |
+ } |
|
| 52 |
+ var _p2 unsafe.Pointer |
|
| 53 |
+ if len(data) > 0 {
|
|
| 54 |
+ _p2 = unsafe.Pointer(&data[0]) |
|
| 55 |
+ } else {
|
|
| 56 |
+ _p2 = unsafe.Pointer(&_zero) |
|
| 57 |
+ } |
|
| 58 |
+ _, _, e1 := syscall.Syscall6(syscall.SYS_SETXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(_p2), uintptr(len(data)), uintptr(flags), 0) |
|
| 59 |
+ use(unsafe.Pointer(_p0)) |
|
| 60 |
+ use(unsafe.Pointer(_p1)) |
|
| 61 |
+ if e1 != 0 {
|
|
| 62 |
+ err = errnoErr(e1) |
|
| 63 |
+ } |
|
| 64 |
+ return |
|
| 65 |
+} |
|
| 66 |
+ |
|
| 67 |
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT |
|
| 68 |
+ |
|
| 69 |
+func removexattr(path string, attr string, options int) (err error) {
|
|
| 70 |
+ var _p0 *byte |
|
| 71 |
+ _p0, err = syscall.BytePtrFromString(path) |
|
| 72 |
+ if err != nil {
|
|
| 73 |
+ return |
|
| 74 |
+ } |
|
| 75 |
+ var _p1 *byte |
|
| 76 |
+ _p1, err = syscall.BytePtrFromString(attr) |
|
| 77 |
+ if err != nil {
|
|
| 78 |
+ return |
|
| 79 |
+ } |
|
| 80 |
+ _, _, e1 := syscall.Syscall(syscall.SYS_REMOVEXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(options)) |
|
| 81 |
+ use(unsafe.Pointer(_p0)) |
|
| 82 |
+ use(unsafe.Pointer(_p1)) |
|
| 83 |
+ if e1 != 0 {
|
|
| 84 |
+ err = errnoErr(e1) |
|
| 85 |
+ } |
|
| 86 |
+ return |
|
| 87 |
+} |
|
| 88 |
+ |
|
| 89 |
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT |
|
| 90 |
+ |
|
| 91 |
+func listxattr(path string, dest []byte, options int) (sz int, err error) {
|
|
| 92 |
+ var _p0 *byte |
|
| 93 |
+ _p0, err = syscall.BytePtrFromString(path) |
|
| 94 |
+ if err != nil {
|
|
| 95 |
+ return |
|
| 96 |
+ } |
|
| 97 |
+ var _p1 unsafe.Pointer |
|
| 98 |
+ if len(dest) > 0 {
|
|
| 99 |
+ _p1 = unsafe.Pointer(&dest[0]) |
|
| 100 |
+ } else {
|
|
| 101 |
+ _p1 = unsafe.Pointer(&_zero) |
|
| 102 |
+ } |
|
| 103 |
+ r0, _, e1 := syscall.Syscall6(syscall.SYS_LISTXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(dest)), uintptr(options), 0, 0) |
|
| 104 |
+ use(unsafe.Pointer(_p0)) |
|
| 105 |
+ sz = int(r0) |
|
| 106 |
+ if e1 != 0 {
|
|
| 107 |
+ err = errnoErr(e1) |
|
| 108 |
+ } |
|
| 109 |
+ return |
|
| 110 |
+} |
| 0 | 111 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,111 @@ |
| 0 |
+// mksyscall.pl xattr_darwin.go |
|
| 1 |
+// MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT |
|
| 2 |
+ |
|
| 3 |
+package sysx |
|
| 4 |
+ |
|
| 5 |
+import ( |
|
| 6 |
+ "syscall" |
|
| 7 |
+ "unsafe" |
|
| 8 |
+) |
|
| 9 |
+ |
|
| 10 |
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT |
|
| 11 |
+ |
|
| 12 |
+func getxattr(path string, attr string, dest []byte, pos int, options int) (sz int, err error) {
|
|
| 13 |
+ var _p0 *byte |
|
| 14 |
+ _p0, err = syscall.BytePtrFromString(path) |
|
| 15 |
+ if err != nil {
|
|
| 16 |
+ return |
|
| 17 |
+ } |
|
| 18 |
+ var _p1 *byte |
|
| 19 |
+ _p1, err = syscall.BytePtrFromString(attr) |
|
| 20 |
+ if err != nil {
|
|
| 21 |
+ return |
|
| 22 |
+ } |
|
| 23 |
+ var _p2 unsafe.Pointer |
|
| 24 |
+ if len(dest) > 0 {
|
|
| 25 |
+ _p2 = unsafe.Pointer(&dest[0]) |
|
| 26 |
+ } else {
|
|
| 27 |
+ _p2 = unsafe.Pointer(&_zero) |
|
| 28 |
+ } |
|
| 29 |
+ r0, _, e1 := syscall.Syscall6(syscall.SYS_GETXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(_p2), uintptr(len(dest)), uintptr(pos), uintptr(options)) |
|
| 30 |
+ use(unsafe.Pointer(_p0)) |
|
| 31 |
+ use(unsafe.Pointer(_p1)) |
|
| 32 |
+ sz = int(r0) |
|
| 33 |
+ if e1 != 0 {
|
|
| 34 |
+ err = errnoErr(e1) |
|
| 35 |
+ } |
|
| 36 |
+ return |
|
| 37 |
+} |
|
| 38 |
+ |
|
| 39 |
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT |
|
| 40 |
+ |
|
| 41 |
+func setxattr(path string, attr string, data []byte, flags int) (err error) {
|
|
| 42 |
+ var _p0 *byte |
|
| 43 |
+ _p0, err = syscall.BytePtrFromString(path) |
|
| 44 |
+ if err != nil {
|
|
| 45 |
+ return |
|
| 46 |
+ } |
|
| 47 |
+ var _p1 *byte |
|
| 48 |
+ _p1, err = syscall.BytePtrFromString(attr) |
|
| 49 |
+ if err != nil {
|
|
| 50 |
+ return |
|
| 51 |
+ } |
|
| 52 |
+ var _p2 unsafe.Pointer |
|
| 53 |
+ if len(data) > 0 {
|
|
| 54 |
+ _p2 = unsafe.Pointer(&data[0]) |
|
| 55 |
+ } else {
|
|
| 56 |
+ _p2 = unsafe.Pointer(&_zero) |
|
| 57 |
+ } |
|
| 58 |
+ _, _, e1 := syscall.Syscall6(syscall.SYS_SETXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(_p2), uintptr(len(data)), uintptr(flags), 0) |
|
| 59 |
+ use(unsafe.Pointer(_p0)) |
|
| 60 |
+ use(unsafe.Pointer(_p1)) |
|
| 61 |
+ if e1 != 0 {
|
|
| 62 |
+ err = errnoErr(e1) |
|
| 63 |
+ } |
|
| 64 |
+ return |
|
| 65 |
+} |
|
| 66 |
+ |
|
| 67 |
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT |
|
| 68 |
+ |
|
| 69 |
+func removexattr(path string, attr string, options int) (err error) {
|
|
| 70 |
+ var _p0 *byte |
|
| 71 |
+ _p0, err = syscall.BytePtrFromString(path) |
|
| 72 |
+ if err != nil {
|
|
| 73 |
+ return |
|
| 74 |
+ } |
|
| 75 |
+ var _p1 *byte |
|
| 76 |
+ _p1, err = syscall.BytePtrFromString(attr) |
|
| 77 |
+ if err != nil {
|
|
| 78 |
+ return |
|
| 79 |
+ } |
|
| 80 |
+ _, _, e1 := syscall.Syscall(syscall.SYS_REMOVEXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(options)) |
|
| 81 |
+ use(unsafe.Pointer(_p0)) |
|
| 82 |
+ use(unsafe.Pointer(_p1)) |
|
| 83 |
+ if e1 != 0 {
|
|
| 84 |
+ err = errnoErr(e1) |
|
| 85 |
+ } |
|
| 86 |
+ return |
|
| 87 |
+} |
|
| 88 |
+ |
|
| 89 |
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT |
|
| 90 |
+ |
|
| 91 |
+func listxattr(path string, dest []byte, options int) (sz int, err error) {
|
|
| 92 |
+ var _p0 *byte |
|
| 93 |
+ _p0, err = syscall.BytePtrFromString(path) |
|
| 94 |
+ if err != nil {
|
|
| 95 |
+ return |
|
| 96 |
+ } |
|
| 97 |
+ var _p1 unsafe.Pointer |
|
| 98 |
+ if len(dest) > 0 {
|
|
| 99 |
+ _p1 = unsafe.Pointer(&dest[0]) |
|
| 100 |
+ } else {
|
|
| 101 |
+ _p1 = unsafe.Pointer(&_zero) |
|
| 102 |
+ } |
|
| 103 |
+ r0, _, e1 := syscall.Syscall6(syscall.SYS_LISTXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(dest)), uintptr(options), 0, 0) |
|
| 104 |
+ use(unsafe.Pointer(_p0)) |
|
| 105 |
+ sz = int(r0) |
|
| 106 |
+ if e1 != 0 {
|
|
| 107 |
+ err = errnoErr(e1) |
|
| 108 |
+ } |
|
| 109 |
+ return |
|
| 110 |
+} |
| 0 | 111 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,53 @@ |
| 0 |
+package sysx |
|
| 1 |
+ |
|
| 2 |
+import ( |
|
| 3 |
+ "errors" |
|
| 4 |
+) |
|
| 5 |
+ |
|
| 6 |
+// Initial stub version for FreeBSD. FreeBSD has a different |
|
| 7 |
+// syscall API from Darwin and Linux for extended attributes; |
|
| 8 |
+// it is also not widely used. It is not exposed at all by the |
|
| 9 |
+// Go syscall package, so we need to implement directly eventually. |
|
| 10 |
+ |
|
| 11 |
+var unsupported error = errors.New("extended attributes unsupported on FreeBSD")
|
|
| 12 |
+ |
|
| 13 |
+// Listxattr calls syscall listxattr and reads all content |
|
| 14 |
+// and returns a string array |
|
| 15 |
+func Listxattr(path string) ([]string, error) {
|
|
| 16 |
+ return []string{}, nil
|
|
| 17 |
+} |
|
| 18 |
+ |
|
| 19 |
+// Removexattr calls syscall removexattr |
|
| 20 |
+func Removexattr(path string, attr string) (err error) {
|
|
| 21 |
+ return unsupported |
|
| 22 |
+} |
|
| 23 |
+ |
|
| 24 |
+// Setxattr calls syscall setxattr |
|
| 25 |
+func Setxattr(path string, attr string, data []byte, flags int) (err error) {
|
|
| 26 |
+ return unsupported |
|
| 27 |
+} |
|
| 28 |
+ |
|
| 29 |
+// Getxattr calls syscall getxattr |
|
| 30 |
+func Getxattr(path, attr string) ([]byte, error) {
|
|
| 31 |
+ return []byte{}, nil
|
|
| 32 |
+} |
|
| 33 |
+ |
|
| 34 |
+// LListxattr lists xattrs, not following symlinks |
|
| 35 |
+func LListxattr(path string) ([]string, error) {
|
|
| 36 |
+ return []string{}, nil
|
|
| 37 |
+} |
|
| 38 |
+ |
|
| 39 |
+// LRemovexattr removes an xattr, not following symlinks |
|
| 40 |
+func LRemovexattr(path string, attr string) (err error) {
|
|
| 41 |
+ return unsupported |
|
| 42 |
+} |
|
| 43 |
+ |
|
| 44 |
+// LSetxattr sets an xattr, not following symlinks |
|
| 45 |
+func LSetxattr(path string, attr string, data []byte, flags int) (err error) {
|
|
| 46 |
+ return unsupported |
|
| 47 |
+} |
|
| 48 |
+ |
|
| 49 |
+// LGetxattr gets an xattr, not following symlinks |
|
| 50 |
+func LGetxattr(path, attr string) ([]byte, error) {
|
|
| 51 |
+ return []byte{}, nil
|
|
| 52 |
+} |
| 0 | 53 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,61 @@ |
| 0 |
+package sysx |
|
| 1 |
+ |
|
| 2 |
+import "syscall" |
|
| 3 |
+ |
|
| 4 |
+// These functions will be generated by generate.sh |
|
| 5 |
+// $ GOOS=linux GOARCH=386 ./generate.sh xattr |
|
| 6 |
+// $ GOOS=linux GOARCH=amd64 ./generate.sh xattr |
|
| 7 |
+// $ GOOS=linux GOARCH=arm ./generate.sh xattr |
|
| 8 |
+// $ GOOS=linux GOARCH=arm64 ./generate.sh xattr |
|
| 9 |
+// $ GOOS=linux GOARCH=ppc64 ./generate.sh xattr |
|
| 10 |
+// $ GOOS=linux GOARCH=ppc64le ./generate.sh xattr |
|
| 11 |
+// $ GOOS=linux GOARCH=s390x ./generate.sh xattr |
|
| 12 |
+ |
|
| 13 |
+// Listxattr calls syscall listxattr and reads all content |
|
| 14 |
+// and returns a string array |
|
| 15 |
+func Listxattr(path string) ([]string, error) {
|
|
| 16 |
+ return listxattrAll(path, syscall.Listxattr) |
|
| 17 |
+} |
|
| 18 |
+ |
|
| 19 |
+// Removexattr calls syscall removexattr |
|
| 20 |
+func Removexattr(path string, attr string) (err error) {
|
|
| 21 |
+ return syscall.Removexattr(path, attr) |
|
| 22 |
+} |
|
| 23 |
+ |
|
| 24 |
+// Setxattr calls syscall setxattr |
|
| 25 |
+func Setxattr(path string, attr string, data []byte, flags int) (err error) {
|
|
| 26 |
+ return syscall.Setxattr(path, attr, data, flags) |
|
| 27 |
+} |
|
| 28 |
+ |
|
| 29 |
+// Getxattr calls syscall getxattr |
|
| 30 |
+func Getxattr(path, attr string) ([]byte, error) {
|
|
| 31 |
+ return getxattrAll(path, attr, syscall.Getxattr) |
|
| 32 |
+} |
|
| 33 |
+ |
|
| 34 |
+//sys llistxattr(path string, dest []byte) (sz int, err error) |
|
| 35 |
+ |
|
| 36 |
+// LListxattr lists xattrs, not following symlinks |
|
| 37 |
+func LListxattr(path string) ([]string, error) {
|
|
| 38 |
+ return listxattrAll(path, llistxattr) |
|
| 39 |
+} |
|
| 40 |
+ |
|
| 41 |
+//sys lremovexattr(path string, attr string) (err error) |
|
| 42 |
+ |
|
| 43 |
+// LRemovexattr removes an xattr, not following symlinks |
|
| 44 |
+func LRemovexattr(path string, attr string) (err error) {
|
|
| 45 |
+ return lremovexattr(path, attr) |
|
| 46 |
+} |
|
| 47 |
+ |
|
| 48 |
+//sys lsetxattr(path string, attr string, data []byte, flags int) (err error) |
|
| 49 |
+ |
|
| 50 |
+// LSetxattr sets an xattr, not following symlinks |
|
| 51 |
+func LSetxattr(path string, attr string, data []byte, flags int) (err error) {
|
|
| 52 |
+ return lsetxattr(path, attr, data, flags) |
|
| 53 |
+} |
|
| 54 |
+ |
|
| 55 |
+//sys lgetxattr(path string, attr string, dest []byte) (sz int, err error) |
|
| 56 |
+ |
|
| 57 |
+// LGetxattr gets an xattr, not following symlinks |
|
| 58 |
+func LGetxattr(path, attr string) ([]byte, error) {
|
|
| 59 |
+ return getxattrAll(path, attr, lgetxattr) |
|
| 60 |
+} |
| 0 | 61 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,111 @@ |
| 0 |
+// mksyscall.pl -l32 xattr_linux.go |
|
| 1 |
+// MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT |
|
| 2 |
+ |
|
| 3 |
+package sysx |
|
| 4 |
+ |
|
| 5 |
+import ( |
|
| 6 |
+ "syscall" |
|
| 7 |
+ "unsafe" |
|
| 8 |
+) |
|
| 9 |
+ |
|
| 10 |
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT |
|
| 11 |
+ |
|
| 12 |
+func llistxattr(path string, dest []byte) (sz int, err error) {
|
|
| 13 |
+ var _p0 *byte |
|
| 14 |
+ _p0, err = syscall.BytePtrFromString(path) |
|
| 15 |
+ if err != nil {
|
|
| 16 |
+ return |
|
| 17 |
+ } |
|
| 18 |
+ var _p1 unsafe.Pointer |
|
| 19 |
+ if len(dest) > 0 {
|
|
| 20 |
+ _p1 = unsafe.Pointer(&dest[0]) |
|
| 21 |
+ } else {
|
|
| 22 |
+ _p1 = unsafe.Pointer(&_zero) |
|
| 23 |
+ } |
|
| 24 |
+ r0, _, e1 := syscall.Syscall(syscall.SYS_LLISTXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(dest))) |
|
| 25 |
+ use(unsafe.Pointer(_p0)) |
|
| 26 |
+ sz = int(r0) |
|
| 27 |
+ if e1 != 0 {
|
|
| 28 |
+ err = errnoErr(e1) |
|
| 29 |
+ } |
|
| 30 |
+ return |
|
| 31 |
+} |
|
| 32 |
+ |
|
| 33 |
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT |
|
| 34 |
+ |
|
| 35 |
+func lremovexattr(path string, attr string) (err error) {
|
|
| 36 |
+ var _p0 *byte |
|
| 37 |
+ _p0, err = syscall.BytePtrFromString(path) |
|
| 38 |
+ if err != nil {
|
|
| 39 |
+ return |
|
| 40 |
+ } |
|
| 41 |
+ var _p1 *byte |
|
| 42 |
+ _p1, err = syscall.BytePtrFromString(attr) |
|
| 43 |
+ if err != nil {
|
|
| 44 |
+ return |
|
| 45 |
+ } |
|
| 46 |
+ _, _, e1 := syscall.Syscall(syscall.SYS_LREMOVEXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0) |
|
| 47 |
+ use(unsafe.Pointer(_p0)) |
|
| 48 |
+ use(unsafe.Pointer(_p1)) |
|
| 49 |
+ if e1 != 0 {
|
|
| 50 |
+ err = errnoErr(e1) |
|
| 51 |
+ } |
|
| 52 |
+ return |
|
| 53 |
+} |
|
| 54 |
+ |
|
| 55 |
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT |
|
| 56 |
+ |
|
| 57 |
+func lsetxattr(path string, attr string, data []byte, flags int) (err error) {
|
|
| 58 |
+ var _p0 *byte |
|
| 59 |
+ _p0, err = syscall.BytePtrFromString(path) |
|
| 60 |
+ if err != nil {
|
|
| 61 |
+ return |
|
| 62 |
+ } |
|
| 63 |
+ var _p1 *byte |
|
| 64 |
+ _p1, err = syscall.BytePtrFromString(attr) |
|
| 65 |
+ if err != nil {
|
|
| 66 |
+ return |
|
| 67 |
+ } |
|
| 68 |
+ var _p2 unsafe.Pointer |
|
| 69 |
+ if len(data) > 0 {
|
|
| 70 |
+ _p2 = unsafe.Pointer(&data[0]) |
|
| 71 |
+ } else {
|
|
| 72 |
+ _p2 = unsafe.Pointer(&_zero) |
|
| 73 |
+ } |
|
| 74 |
+ _, _, e1 := syscall.Syscall6(syscall.SYS_LSETXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(_p2), uintptr(len(data)), uintptr(flags), 0) |
|
| 75 |
+ use(unsafe.Pointer(_p0)) |
|
| 76 |
+ use(unsafe.Pointer(_p1)) |
|
| 77 |
+ if e1 != 0 {
|
|
| 78 |
+ err = errnoErr(e1) |
|
| 79 |
+ } |
|
| 80 |
+ return |
|
| 81 |
+} |
|
| 82 |
+ |
|
| 83 |
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT |
|
| 84 |
+ |
|
| 85 |
+func lgetxattr(path string, attr string, dest []byte) (sz int, err error) {
|
|
| 86 |
+ var _p0 *byte |
|
| 87 |
+ _p0, err = syscall.BytePtrFromString(path) |
|
| 88 |
+ if err != nil {
|
|
| 89 |
+ return |
|
| 90 |
+ } |
|
| 91 |
+ var _p1 *byte |
|
| 92 |
+ _p1, err = syscall.BytePtrFromString(attr) |
|
| 93 |
+ if err != nil {
|
|
| 94 |
+ return |
|
| 95 |
+ } |
|
| 96 |
+ var _p2 unsafe.Pointer |
|
| 97 |
+ if len(dest) > 0 {
|
|
| 98 |
+ _p2 = unsafe.Pointer(&dest[0]) |
|
| 99 |
+ } else {
|
|
| 100 |
+ _p2 = unsafe.Pointer(&_zero) |
|
| 101 |
+ } |
|
| 102 |
+ r0, _, e1 := syscall.Syscall6(syscall.SYS_LGETXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(_p2), uintptr(len(dest)), 0, 0) |
|
| 103 |
+ use(unsafe.Pointer(_p0)) |
|
| 104 |
+ use(unsafe.Pointer(_p1)) |
|
| 105 |
+ sz = int(r0) |
|
| 106 |
+ if e1 != 0 {
|
|
| 107 |
+ err = errnoErr(e1) |
|
| 108 |
+ } |
|
| 109 |
+ return |
|
| 110 |
+} |
| 0 | 111 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,111 @@ |
| 0 |
+// mksyscall.pl xattr_linux.go |
|
| 1 |
+// MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT |
|
| 2 |
+ |
|
| 3 |
+package sysx |
|
| 4 |
+ |
|
| 5 |
+import ( |
|
| 6 |
+ "syscall" |
|
| 7 |
+ "unsafe" |
|
| 8 |
+) |
|
| 9 |
+ |
|
| 10 |
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT |
|
| 11 |
+ |
|
| 12 |
+func llistxattr(path string, dest []byte) (sz int, err error) {
|
|
| 13 |
+ var _p0 *byte |
|
| 14 |
+ _p0, err = syscall.BytePtrFromString(path) |
|
| 15 |
+ if err != nil {
|
|
| 16 |
+ return |
|
| 17 |
+ } |
|
| 18 |
+ var _p1 unsafe.Pointer |
|
| 19 |
+ if len(dest) > 0 {
|
|
| 20 |
+ _p1 = unsafe.Pointer(&dest[0]) |
|
| 21 |
+ } else {
|
|
| 22 |
+ _p1 = unsafe.Pointer(&_zero) |
|
| 23 |
+ } |
|
| 24 |
+ r0, _, e1 := syscall.Syscall(syscall.SYS_LLISTXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(dest))) |
|
| 25 |
+ use(unsafe.Pointer(_p0)) |
|
| 26 |
+ sz = int(r0) |
|
| 27 |
+ if e1 != 0 {
|
|
| 28 |
+ err = errnoErr(e1) |
|
| 29 |
+ } |
|
| 30 |
+ return |
|
| 31 |
+} |
|
| 32 |
+ |
|
| 33 |
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT |
|
| 34 |
+ |
|
| 35 |
+func lremovexattr(path string, attr string) (err error) {
|
|
| 36 |
+ var _p0 *byte |
|
| 37 |
+ _p0, err = syscall.BytePtrFromString(path) |
|
| 38 |
+ if err != nil {
|
|
| 39 |
+ return |
|
| 40 |
+ } |
|
| 41 |
+ var _p1 *byte |
|
| 42 |
+ _p1, err = syscall.BytePtrFromString(attr) |
|
| 43 |
+ if err != nil {
|
|
| 44 |
+ return |
|
| 45 |
+ } |
|
| 46 |
+ _, _, e1 := syscall.Syscall(syscall.SYS_LREMOVEXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0) |
|
| 47 |
+ use(unsafe.Pointer(_p0)) |
|
| 48 |
+ use(unsafe.Pointer(_p1)) |
|
| 49 |
+ if e1 != 0 {
|
|
| 50 |
+ err = errnoErr(e1) |
|
| 51 |
+ } |
|
| 52 |
+ return |
|
| 53 |
+} |
|
| 54 |
+ |
|
| 55 |
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT |
|
| 56 |
+ |
|
| 57 |
+func lsetxattr(path string, attr string, data []byte, flags int) (err error) {
|
|
| 58 |
+ var _p0 *byte |
|
| 59 |
+ _p0, err = syscall.BytePtrFromString(path) |
|
| 60 |
+ if err != nil {
|
|
| 61 |
+ return |
|
| 62 |
+ } |
|
| 63 |
+ var _p1 *byte |
|
| 64 |
+ _p1, err = syscall.BytePtrFromString(attr) |
|
| 65 |
+ if err != nil {
|
|
| 66 |
+ return |
|
| 67 |
+ } |
|
| 68 |
+ var _p2 unsafe.Pointer |
|
| 69 |
+ if len(data) > 0 {
|
|
| 70 |
+ _p2 = unsafe.Pointer(&data[0]) |
|
| 71 |
+ } else {
|
|
| 72 |
+ _p2 = unsafe.Pointer(&_zero) |
|
| 73 |
+ } |
|
| 74 |
+ _, _, e1 := syscall.Syscall6(syscall.SYS_LSETXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(_p2), uintptr(len(data)), uintptr(flags), 0) |
|
| 75 |
+ use(unsafe.Pointer(_p0)) |
|
| 76 |
+ use(unsafe.Pointer(_p1)) |
|
| 77 |
+ if e1 != 0 {
|
|
| 78 |
+ err = errnoErr(e1) |
|
| 79 |
+ } |
|
| 80 |
+ return |
|
| 81 |
+} |
|
| 82 |
+ |
|
| 83 |
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT |
|
| 84 |
+ |
|
| 85 |
+func lgetxattr(path string, attr string, dest []byte) (sz int, err error) {
|
|
| 86 |
+ var _p0 *byte |
|
| 87 |
+ _p0, err = syscall.BytePtrFromString(path) |
|
| 88 |
+ if err != nil {
|
|
| 89 |
+ return |
|
| 90 |
+ } |
|
| 91 |
+ var _p1 *byte |
|
| 92 |
+ _p1, err = syscall.BytePtrFromString(attr) |
|
| 93 |
+ if err != nil {
|
|
| 94 |
+ return |
|
| 95 |
+ } |
|
| 96 |
+ var _p2 unsafe.Pointer |
|
| 97 |
+ if len(dest) > 0 {
|
|
| 98 |
+ _p2 = unsafe.Pointer(&dest[0]) |
|
| 99 |
+ } else {
|
|
| 100 |
+ _p2 = unsafe.Pointer(&_zero) |
|
| 101 |
+ } |
|
| 102 |
+ r0, _, e1 := syscall.Syscall6(syscall.SYS_LGETXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(_p2), uintptr(len(dest)), 0, 0) |
|
| 103 |
+ use(unsafe.Pointer(_p0)) |
|
| 104 |
+ use(unsafe.Pointer(_p1)) |
|
| 105 |
+ sz = int(r0) |
|
| 106 |
+ if e1 != 0 {
|
|
| 107 |
+ err = errnoErr(e1) |
|
| 108 |
+ } |
|
| 109 |
+ return |
|
| 110 |
+} |
| 0 | 111 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,111 @@ |
| 0 |
+// mksyscall.pl -l32 xattr_linux.go |
|
| 1 |
+// MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT |
|
| 2 |
+ |
|
| 3 |
+package sysx |
|
| 4 |
+ |
|
| 5 |
+import ( |
|
| 6 |
+ "syscall" |
|
| 7 |
+ "unsafe" |
|
| 8 |
+) |
|
| 9 |
+ |
|
| 10 |
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT |
|
| 11 |
+ |
|
| 12 |
+func llistxattr(path string, dest []byte) (sz int, err error) {
|
|
| 13 |
+ var _p0 *byte |
|
| 14 |
+ _p0, err = syscall.BytePtrFromString(path) |
|
| 15 |
+ if err != nil {
|
|
| 16 |
+ return |
|
| 17 |
+ } |
|
| 18 |
+ var _p1 unsafe.Pointer |
|
| 19 |
+ if len(dest) > 0 {
|
|
| 20 |
+ _p1 = unsafe.Pointer(&dest[0]) |
|
| 21 |
+ } else {
|
|
| 22 |
+ _p1 = unsafe.Pointer(&_zero) |
|
| 23 |
+ } |
|
| 24 |
+ r0, _, e1 := syscall.Syscall(syscall.SYS_LLISTXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(dest))) |
|
| 25 |
+ use(unsafe.Pointer(_p0)) |
|
| 26 |
+ sz = int(r0) |
|
| 27 |
+ if e1 != 0 {
|
|
| 28 |
+ err = errnoErr(e1) |
|
| 29 |
+ } |
|
| 30 |
+ return |
|
| 31 |
+} |
|
| 32 |
+ |
|
| 33 |
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT |
|
| 34 |
+ |
|
| 35 |
+func lremovexattr(path string, attr string) (err error) {
|
|
| 36 |
+ var _p0 *byte |
|
| 37 |
+ _p0, err = syscall.BytePtrFromString(path) |
|
| 38 |
+ if err != nil {
|
|
| 39 |
+ return |
|
| 40 |
+ } |
|
| 41 |
+ var _p1 *byte |
|
| 42 |
+ _p1, err = syscall.BytePtrFromString(attr) |
|
| 43 |
+ if err != nil {
|
|
| 44 |
+ return |
|
| 45 |
+ } |
|
| 46 |
+ _, _, e1 := syscall.Syscall(syscall.SYS_LREMOVEXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0) |
|
| 47 |
+ use(unsafe.Pointer(_p0)) |
|
| 48 |
+ use(unsafe.Pointer(_p1)) |
|
| 49 |
+ if e1 != 0 {
|
|
| 50 |
+ err = errnoErr(e1) |
|
| 51 |
+ } |
|
| 52 |
+ return |
|
| 53 |
+} |
|
| 54 |
+ |
|
| 55 |
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT |
|
| 56 |
+ |
|
| 57 |
+func lsetxattr(path string, attr string, data []byte, flags int) (err error) {
|
|
| 58 |
+ var _p0 *byte |
|
| 59 |
+ _p0, err = syscall.BytePtrFromString(path) |
|
| 60 |
+ if err != nil {
|
|
| 61 |
+ return |
|
| 62 |
+ } |
|
| 63 |
+ var _p1 *byte |
|
| 64 |
+ _p1, err = syscall.BytePtrFromString(attr) |
|
| 65 |
+ if err != nil {
|
|
| 66 |
+ return |
|
| 67 |
+ } |
|
| 68 |
+ var _p2 unsafe.Pointer |
|
| 69 |
+ if len(data) > 0 {
|
|
| 70 |
+ _p2 = unsafe.Pointer(&data[0]) |
|
| 71 |
+ } else {
|
|
| 72 |
+ _p2 = unsafe.Pointer(&_zero) |
|
| 73 |
+ } |
|
| 74 |
+ _, _, e1 := syscall.Syscall6(syscall.SYS_LSETXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(_p2), uintptr(len(data)), uintptr(flags), 0) |
|
| 75 |
+ use(unsafe.Pointer(_p0)) |
|
| 76 |
+ use(unsafe.Pointer(_p1)) |
|
| 77 |
+ if e1 != 0 {
|
|
| 78 |
+ err = errnoErr(e1) |
|
| 79 |
+ } |
|
| 80 |
+ return |
|
| 81 |
+} |
|
| 82 |
+ |
|
| 83 |
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT |
|
| 84 |
+ |
|
| 85 |
+func lgetxattr(path string, attr string, dest []byte) (sz int, err error) {
|
|
| 86 |
+ var _p0 *byte |
|
| 87 |
+ _p0, err = syscall.BytePtrFromString(path) |
|
| 88 |
+ if err != nil {
|
|
| 89 |
+ return |
|
| 90 |
+ } |
|
| 91 |
+ var _p1 *byte |
|
| 92 |
+ _p1, err = syscall.BytePtrFromString(attr) |
|
| 93 |
+ if err != nil {
|
|
| 94 |
+ return |
|
| 95 |
+ } |
|
| 96 |
+ var _p2 unsafe.Pointer |
|
| 97 |
+ if len(dest) > 0 {
|
|
| 98 |
+ _p2 = unsafe.Pointer(&dest[0]) |
|
| 99 |
+ } else {
|
|
| 100 |
+ _p2 = unsafe.Pointer(&_zero) |
|
| 101 |
+ } |
|
| 102 |
+ r0, _, e1 := syscall.Syscall6(syscall.SYS_LGETXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(_p2), uintptr(len(dest)), 0, 0) |
|
| 103 |
+ use(unsafe.Pointer(_p0)) |
|
| 104 |
+ use(unsafe.Pointer(_p1)) |
|
| 105 |
+ sz = int(r0) |
|
| 106 |
+ if e1 != 0 {
|
|
| 107 |
+ err = errnoErr(e1) |
|
| 108 |
+ } |
|
| 109 |
+ return |
|
| 110 |
+} |
| 0 | 111 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,111 @@ |
| 0 |
+// mksyscall.pl xattr_linux.go |
|
| 1 |
+// MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT |
|
| 2 |
+ |
|
| 3 |
+package sysx |
|
| 4 |
+ |
|
| 5 |
+import ( |
|
| 6 |
+ "syscall" |
|
| 7 |
+ "unsafe" |
|
| 8 |
+) |
|
| 9 |
+ |
|
| 10 |
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT |
|
| 11 |
+ |
|
| 12 |
+func llistxattr(path string, dest []byte) (sz int, err error) {
|
|
| 13 |
+ var _p0 *byte |
|
| 14 |
+ _p0, err = syscall.BytePtrFromString(path) |
|
| 15 |
+ if err != nil {
|
|
| 16 |
+ return |
|
| 17 |
+ } |
|
| 18 |
+ var _p1 unsafe.Pointer |
|
| 19 |
+ if len(dest) > 0 {
|
|
| 20 |
+ _p1 = unsafe.Pointer(&dest[0]) |
|
| 21 |
+ } else {
|
|
| 22 |
+ _p1 = unsafe.Pointer(&_zero) |
|
| 23 |
+ } |
|
| 24 |
+ r0, _, e1 := syscall.Syscall(syscall.SYS_LLISTXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(dest))) |
|
| 25 |
+ use(unsafe.Pointer(_p0)) |
|
| 26 |
+ sz = int(r0) |
|
| 27 |
+ if e1 != 0 {
|
|
| 28 |
+ err = errnoErr(e1) |
|
| 29 |
+ } |
|
| 30 |
+ return |
|
| 31 |
+} |
|
| 32 |
+ |
|
| 33 |
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT |
|
| 34 |
+ |
|
| 35 |
+func lremovexattr(path string, attr string) (err error) {
|
|
| 36 |
+ var _p0 *byte |
|
| 37 |
+ _p0, err = syscall.BytePtrFromString(path) |
|
| 38 |
+ if err != nil {
|
|
| 39 |
+ return |
|
| 40 |
+ } |
|
| 41 |
+ var _p1 *byte |
|
| 42 |
+ _p1, err = syscall.BytePtrFromString(attr) |
|
| 43 |
+ if err != nil {
|
|
| 44 |
+ return |
|
| 45 |
+ } |
|
| 46 |
+ _, _, e1 := syscall.Syscall(syscall.SYS_LREMOVEXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0) |
|
| 47 |
+ use(unsafe.Pointer(_p0)) |
|
| 48 |
+ use(unsafe.Pointer(_p1)) |
|
| 49 |
+ if e1 != 0 {
|
|
| 50 |
+ err = errnoErr(e1) |
|
| 51 |
+ } |
|
| 52 |
+ return |
|
| 53 |
+} |
|
| 54 |
+ |
|
| 55 |
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT |
|
| 56 |
+ |
|
| 57 |
+func lsetxattr(path string, attr string, data []byte, flags int) (err error) {
|
|
| 58 |
+ var _p0 *byte |
|
| 59 |
+ _p0, err = syscall.BytePtrFromString(path) |
|
| 60 |
+ if err != nil {
|
|
| 61 |
+ return |
|
| 62 |
+ } |
|
| 63 |
+ var _p1 *byte |
|
| 64 |
+ _p1, err = syscall.BytePtrFromString(attr) |
|
| 65 |
+ if err != nil {
|
|
| 66 |
+ return |
|
| 67 |
+ } |
|
| 68 |
+ var _p2 unsafe.Pointer |
|
| 69 |
+ if len(data) > 0 {
|
|
| 70 |
+ _p2 = unsafe.Pointer(&data[0]) |
|
| 71 |
+ } else {
|
|
| 72 |
+ _p2 = unsafe.Pointer(&_zero) |
|
| 73 |
+ } |
|
| 74 |
+ _, _, e1 := syscall.Syscall6(syscall.SYS_LSETXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(_p2), uintptr(len(data)), uintptr(flags), 0) |
|
| 75 |
+ use(unsafe.Pointer(_p0)) |
|
| 76 |
+ use(unsafe.Pointer(_p1)) |
|
| 77 |
+ if e1 != 0 {
|
|
| 78 |
+ err = errnoErr(e1) |
|
| 79 |
+ } |
|
| 80 |
+ return |
|
| 81 |
+} |
|
| 82 |
+ |
|
| 83 |
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT |
|
| 84 |
+ |
|
| 85 |
+func lgetxattr(path string, attr string, dest []byte) (sz int, err error) {
|
|
| 86 |
+ var _p0 *byte |
|
| 87 |
+ _p0, err = syscall.BytePtrFromString(path) |
|
| 88 |
+ if err != nil {
|
|
| 89 |
+ return |
|
| 90 |
+ } |
|
| 91 |
+ var _p1 *byte |
|
| 92 |
+ _p1, err = syscall.BytePtrFromString(attr) |
|
| 93 |
+ if err != nil {
|
|
| 94 |
+ return |
|
| 95 |
+ } |
|
| 96 |
+ var _p2 unsafe.Pointer |
|
| 97 |
+ if len(dest) > 0 {
|
|
| 98 |
+ _p2 = unsafe.Pointer(&dest[0]) |
|
| 99 |
+ } else {
|
|
| 100 |
+ _p2 = unsafe.Pointer(&_zero) |
|
| 101 |
+ } |
|
| 102 |
+ r0, _, e1 := syscall.Syscall6(syscall.SYS_LGETXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(_p2), uintptr(len(dest)), 0, 0) |
|
| 103 |
+ use(unsafe.Pointer(_p0)) |
|
| 104 |
+ use(unsafe.Pointer(_p1)) |
|
| 105 |
+ sz = int(r0) |
|
| 106 |
+ if e1 != 0 {
|
|
| 107 |
+ err = errnoErr(e1) |
|
| 108 |
+ } |
|
| 109 |
+ return |
|
| 110 |
+} |
| 0 | 111 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,111 @@ |
| 0 |
+// mksyscall.pl xattr_linux.go |
|
| 1 |
+// MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT |
|
| 2 |
+ |
|
| 3 |
+package sysx |
|
| 4 |
+ |
|
| 5 |
+import ( |
|
| 6 |
+ "syscall" |
|
| 7 |
+ "unsafe" |
|
| 8 |
+) |
|
| 9 |
+ |
|
| 10 |
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT |
|
| 11 |
+ |
|
| 12 |
+func llistxattr(path string, dest []byte) (sz int, err error) {
|
|
| 13 |
+ var _p0 *byte |
|
| 14 |
+ _p0, err = syscall.BytePtrFromString(path) |
|
| 15 |
+ if err != nil {
|
|
| 16 |
+ return |
|
| 17 |
+ } |
|
| 18 |
+ var _p1 unsafe.Pointer |
|
| 19 |
+ if len(dest) > 0 {
|
|
| 20 |
+ _p1 = unsafe.Pointer(&dest[0]) |
|
| 21 |
+ } else {
|
|
| 22 |
+ _p1 = unsafe.Pointer(&_zero) |
|
| 23 |
+ } |
|
| 24 |
+ r0, _, e1 := syscall.Syscall(syscall.SYS_LLISTXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(dest))) |
|
| 25 |
+ use(unsafe.Pointer(_p0)) |
|
| 26 |
+ sz = int(r0) |
|
| 27 |
+ if e1 != 0 {
|
|
| 28 |
+ err = errnoErr(e1) |
|
| 29 |
+ } |
|
| 30 |
+ return |
|
| 31 |
+} |
|
| 32 |
+ |
|
| 33 |
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT |
|
| 34 |
+ |
|
| 35 |
+func lremovexattr(path string, attr string) (err error) {
|
|
| 36 |
+ var _p0 *byte |
|
| 37 |
+ _p0, err = syscall.BytePtrFromString(path) |
|
| 38 |
+ if err != nil {
|
|
| 39 |
+ return |
|
| 40 |
+ } |
|
| 41 |
+ var _p1 *byte |
|
| 42 |
+ _p1, err = syscall.BytePtrFromString(attr) |
|
| 43 |
+ if err != nil {
|
|
| 44 |
+ return |
|
| 45 |
+ } |
|
| 46 |
+ _, _, e1 := syscall.Syscall(syscall.SYS_LREMOVEXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0) |
|
| 47 |
+ use(unsafe.Pointer(_p0)) |
|
| 48 |
+ use(unsafe.Pointer(_p1)) |
|
| 49 |
+ if e1 != 0 {
|
|
| 50 |
+ err = errnoErr(e1) |
|
| 51 |
+ } |
|
| 52 |
+ return |
|
| 53 |
+} |
|
| 54 |
+ |
|
| 55 |
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT |
|
| 56 |
+ |
|
| 57 |
+func lsetxattr(path string, attr string, data []byte, flags int) (err error) {
|
|
| 58 |
+ var _p0 *byte |
|
| 59 |
+ _p0, err = syscall.BytePtrFromString(path) |
|
| 60 |
+ if err != nil {
|
|
| 61 |
+ return |
|
| 62 |
+ } |
|
| 63 |
+ var _p1 *byte |
|
| 64 |
+ _p1, err = syscall.BytePtrFromString(attr) |
|
| 65 |
+ if err != nil {
|
|
| 66 |
+ return |
|
| 67 |
+ } |
|
| 68 |
+ var _p2 unsafe.Pointer |
|
| 69 |
+ if len(data) > 0 {
|
|
| 70 |
+ _p2 = unsafe.Pointer(&data[0]) |
|
| 71 |
+ } else {
|
|
| 72 |
+ _p2 = unsafe.Pointer(&_zero) |
|
| 73 |
+ } |
|
| 74 |
+ _, _, e1 := syscall.Syscall6(syscall.SYS_LSETXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(_p2), uintptr(len(data)), uintptr(flags), 0) |
|
| 75 |
+ use(unsafe.Pointer(_p0)) |
|
| 76 |
+ use(unsafe.Pointer(_p1)) |
|
| 77 |
+ if e1 != 0 {
|
|
| 78 |
+ err = errnoErr(e1) |
|
| 79 |
+ } |
|
| 80 |
+ return |
|
| 81 |
+} |
|
| 82 |
+ |
|
| 83 |
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT |
|
| 84 |
+ |
|
| 85 |
+func lgetxattr(path string, attr string, dest []byte) (sz int, err error) {
|
|
| 86 |
+ var _p0 *byte |
|
| 87 |
+ _p0, err = syscall.BytePtrFromString(path) |
|
| 88 |
+ if err != nil {
|
|
| 89 |
+ return |
|
| 90 |
+ } |
|
| 91 |
+ var _p1 *byte |
|
| 92 |
+ _p1, err = syscall.BytePtrFromString(attr) |
|
| 93 |
+ if err != nil {
|
|
| 94 |
+ return |
|
| 95 |
+ } |
|
| 96 |
+ var _p2 unsafe.Pointer |
|
| 97 |
+ if len(dest) > 0 {
|
|
| 98 |
+ _p2 = unsafe.Pointer(&dest[0]) |
|
| 99 |
+ } else {
|
|
| 100 |
+ _p2 = unsafe.Pointer(&_zero) |
|
| 101 |
+ } |
|
| 102 |
+ r0, _, e1 := syscall.Syscall6(syscall.SYS_LGETXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(_p2), uintptr(len(dest)), 0, 0) |
|
| 103 |
+ use(unsafe.Pointer(_p0)) |
|
| 104 |
+ use(unsafe.Pointer(_p1)) |
|
| 105 |
+ sz = int(r0) |
|
| 106 |
+ if e1 != 0 {
|
|
| 107 |
+ err = errnoErr(e1) |
|
| 108 |
+ } |
|
| 109 |
+ return |
|
| 110 |
+} |
| 0 | 111 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,111 @@ |
| 0 |
+// mksyscall.pl xattr_linux.go |
|
| 1 |
+// MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT |
|
| 2 |
+ |
|
| 3 |
+package sysx |
|
| 4 |
+ |
|
| 5 |
+import ( |
|
| 6 |
+ "syscall" |
|
| 7 |
+ "unsafe" |
|
| 8 |
+) |
|
| 9 |
+ |
|
| 10 |
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT |
|
| 11 |
+ |
|
| 12 |
+func llistxattr(path string, dest []byte) (sz int, err error) {
|
|
| 13 |
+ var _p0 *byte |
|
| 14 |
+ _p0, err = syscall.BytePtrFromString(path) |
|
| 15 |
+ if err != nil {
|
|
| 16 |
+ return |
|
| 17 |
+ } |
|
| 18 |
+ var _p1 unsafe.Pointer |
|
| 19 |
+ if len(dest) > 0 {
|
|
| 20 |
+ _p1 = unsafe.Pointer(&dest[0]) |
|
| 21 |
+ } else {
|
|
| 22 |
+ _p1 = unsafe.Pointer(&_zero) |
|
| 23 |
+ } |
|
| 24 |
+ r0, _, e1 := syscall.Syscall(syscall.SYS_LLISTXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(dest))) |
|
| 25 |
+ use(unsafe.Pointer(_p0)) |
|
| 26 |
+ sz = int(r0) |
|
| 27 |
+ if e1 != 0 {
|
|
| 28 |
+ err = errnoErr(e1) |
|
| 29 |
+ } |
|
| 30 |
+ return |
|
| 31 |
+} |
|
| 32 |
+ |
|
| 33 |
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT |
|
| 34 |
+ |
|
| 35 |
+func lremovexattr(path string, attr string) (err error) {
|
|
| 36 |
+ var _p0 *byte |
|
| 37 |
+ _p0, err = syscall.BytePtrFromString(path) |
|
| 38 |
+ if err != nil {
|
|
| 39 |
+ return |
|
| 40 |
+ } |
|
| 41 |
+ var _p1 *byte |
|
| 42 |
+ _p1, err = syscall.BytePtrFromString(attr) |
|
| 43 |
+ if err != nil {
|
|
| 44 |
+ return |
|
| 45 |
+ } |
|
| 46 |
+ _, _, e1 := syscall.Syscall(syscall.SYS_LREMOVEXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0) |
|
| 47 |
+ use(unsafe.Pointer(_p0)) |
|
| 48 |
+ use(unsafe.Pointer(_p1)) |
|
| 49 |
+ if e1 != 0 {
|
|
| 50 |
+ err = errnoErr(e1) |
|
| 51 |
+ } |
|
| 52 |
+ return |
|
| 53 |
+} |
|
| 54 |
+ |
|
| 55 |
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT |
|
| 56 |
+ |
|
| 57 |
+func lsetxattr(path string, attr string, data []byte, flags int) (err error) {
|
|
| 58 |
+ var _p0 *byte |
|
| 59 |
+ _p0, err = syscall.BytePtrFromString(path) |
|
| 60 |
+ if err != nil {
|
|
| 61 |
+ return |
|
| 62 |
+ } |
|
| 63 |
+ var _p1 *byte |
|
| 64 |
+ _p1, err = syscall.BytePtrFromString(attr) |
|
| 65 |
+ if err != nil {
|
|
| 66 |
+ return |
|
| 67 |
+ } |
|
| 68 |
+ var _p2 unsafe.Pointer |
|
| 69 |
+ if len(data) > 0 {
|
|
| 70 |
+ _p2 = unsafe.Pointer(&data[0]) |
|
| 71 |
+ } else {
|
|
| 72 |
+ _p2 = unsafe.Pointer(&_zero) |
|
| 73 |
+ } |
|
| 74 |
+ _, _, e1 := syscall.Syscall6(syscall.SYS_LSETXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(_p2), uintptr(len(data)), uintptr(flags), 0) |
|
| 75 |
+ use(unsafe.Pointer(_p0)) |
|
| 76 |
+ use(unsafe.Pointer(_p1)) |
|
| 77 |
+ if e1 != 0 {
|
|
| 78 |
+ err = errnoErr(e1) |
|
| 79 |
+ } |
|
| 80 |
+ return |
|
| 81 |
+} |
|
| 82 |
+ |
|
| 83 |
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT |
|
| 84 |
+ |
|
| 85 |
+func lgetxattr(path string, attr string, dest []byte) (sz int, err error) {
|
|
| 86 |
+ var _p0 *byte |
|
| 87 |
+ _p0, err = syscall.BytePtrFromString(path) |
|
| 88 |
+ if err != nil {
|
|
| 89 |
+ return |
|
| 90 |
+ } |
|
| 91 |
+ var _p1 *byte |
|
| 92 |
+ _p1, err = syscall.BytePtrFromString(attr) |
|
| 93 |
+ if err != nil {
|
|
| 94 |
+ return |
|
| 95 |
+ } |
|
| 96 |
+ var _p2 unsafe.Pointer |
|
| 97 |
+ if len(dest) > 0 {
|
|
| 98 |
+ _p2 = unsafe.Pointer(&dest[0]) |
|
| 99 |
+ } else {
|
|
| 100 |
+ _p2 = unsafe.Pointer(&_zero) |
|
| 101 |
+ } |
|
| 102 |
+ r0, _, e1 := syscall.Syscall6(syscall.SYS_LGETXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(_p2), uintptr(len(dest)), 0, 0) |
|
| 103 |
+ use(unsafe.Pointer(_p0)) |
|
| 104 |
+ use(unsafe.Pointer(_p1)) |
|
| 105 |
+ sz = int(r0) |
|
| 106 |
+ if e1 != 0 {
|
|
| 107 |
+ err = errnoErr(e1) |
|
| 108 |
+ } |
|
| 109 |
+ return |
|
| 110 |
+} |
| 0 | 111 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,111 @@ |
| 0 |
+// mksyscall.pl xattr_linux.go |
|
| 1 |
+// MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT |
|
| 2 |
+ |
|
| 3 |
+package sysx |
|
| 4 |
+ |
|
| 5 |
+import ( |
|
| 6 |
+ "syscall" |
|
| 7 |
+ "unsafe" |
|
| 8 |
+) |
|
| 9 |
+ |
|
| 10 |
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT |
|
| 11 |
+ |
|
| 12 |
+func llistxattr(path string, dest []byte) (sz int, err error) {
|
|
| 13 |
+ var _p0 *byte |
|
| 14 |
+ _p0, err = syscall.BytePtrFromString(path) |
|
| 15 |
+ if err != nil {
|
|
| 16 |
+ return |
|
| 17 |
+ } |
|
| 18 |
+ var _p1 unsafe.Pointer |
|
| 19 |
+ if len(dest) > 0 {
|
|
| 20 |
+ _p1 = unsafe.Pointer(&dest[0]) |
|
| 21 |
+ } else {
|
|
| 22 |
+ _p1 = unsafe.Pointer(&_zero) |
|
| 23 |
+ } |
|
| 24 |
+ r0, _, e1 := syscall.Syscall(syscall.SYS_LLISTXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(dest))) |
|
| 25 |
+ use(unsafe.Pointer(_p0)) |
|
| 26 |
+ sz = int(r0) |
|
| 27 |
+ if e1 != 0 {
|
|
| 28 |
+ err = errnoErr(e1) |
|
| 29 |
+ } |
|
| 30 |
+ return |
|
| 31 |
+} |
|
| 32 |
+ |
|
| 33 |
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT |
|
| 34 |
+ |
|
| 35 |
+func lremovexattr(path string, attr string) (err error) {
|
|
| 36 |
+ var _p0 *byte |
|
| 37 |
+ _p0, err = syscall.BytePtrFromString(path) |
|
| 38 |
+ if err != nil {
|
|
| 39 |
+ return |
|
| 40 |
+ } |
|
| 41 |
+ var _p1 *byte |
|
| 42 |
+ _p1, err = syscall.BytePtrFromString(attr) |
|
| 43 |
+ if err != nil {
|
|
| 44 |
+ return |
|
| 45 |
+ } |
|
| 46 |
+ _, _, e1 := syscall.Syscall(syscall.SYS_LREMOVEXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0) |
|
| 47 |
+ use(unsafe.Pointer(_p0)) |
|
| 48 |
+ use(unsafe.Pointer(_p1)) |
|
| 49 |
+ if e1 != 0 {
|
|
| 50 |
+ err = errnoErr(e1) |
|
| 51 |
+ } |
|
| 52 |
+ return |
|
| 53 |
+} |
|
| 54 |
+ |
|
| 55 |
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT |
|
| 56 |
+ |
|
| 57 |
+func lsetxattr(path string, attr string, data []byte, flags int) (err error) {
|
|
| 58 |
+ var _p0 *byte |
|
| 59 |
+ _p0, err = syscall.BytePtrFromString(path) |
|
| 60 |
+ if err != nil {
|
|
| 61 |
+ return |
|
| 62 |
+ } |
|
| 63 |
+ var _p1 *byte |
|
| 64 |
+ _p1, err = syscall.BytePtrFromString(attr) |
|
| 65 |
+ if err != nil {
|
|
| 66 |
+ return |
|
| 67 |
+ } |
|
| 68 |
+ var _p2 unsafe.Pointer |
|
| 69 |
+ if len(data) > 0 {
|
|
| 70 |
+ _p2 = unsafe.Pointer(&data[0]) |
|
| 71 |
+ } else {
|
|
| 72 |
+ _p2 = unsafe.Pointer(&_zero) |
|
| 73 |
+ } |
|
| 74 |
+ _, _, e1 := syscall.Syscall6(syscall.SYS_LSETXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(_p2), uintptr(len(data)), uintptr(flags), 0) |
|
| 75 |
+ use(unsafe.Pointer(_p0)) |
|
| 76 |
+ use(unsafe.Pointer(_p1)) |
|
| 77 |
+ if e1 != 0 {
|
|
| 78 |
+ err = errnoErr(e1) |
|
| 79 |
+ } |
|
| 80 |
+ return |
|
| 81 |
+} |
|
| 82 |
+ |
|
| 83 |
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT |
|
| 84 |
+ |
|
| 85 |
+func lgetxattr(path string, attr string, dest []byte) (sz int, err error) {
|
|
| 86 |
+ var _p0 *byte |
|
| 87 |
+ _p0, err = syscall.BytePtrFromString(path) |
|
| 88 |
+ if err != nil {
|
|
| 89 |
+ return |
|
| 90 |
+ } |
|
| 91 |
+ var _p1 *byte |
|
| 92 |
+ _p1, err = syscall.BytePtrFromString(attr) |
|
| 93 |
+ if err != nil {
|
|
| 94 |
+ return |
|
| 95 |
+ } |
|
| 96 |
+ var _p2 unsafe.Pointer |
|
| 97 |
+ if len(dest) > 0 {
|
|
| 98 |
+ _p2 = unsafe.Pointer(&dest[0]) |
|
| 99 |
+ } else {
|
|
| 100 |
+ _p2 = unsafe.Pointer(&_zero) |
|
| 101 |
+ } |
|
| 102 |
+ r0, _, e1 := syscall.Syscall6(syscall.SYS_LGETXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(_p2), uintptr(len(dest)), 0, 0) |
|
| 103 |
+ use(unsafe.Pointer(_p0)) |
|
| 104 |
+ use(unsafe.Pointer(_p1)) |
|
| 105 |
+ sz = int(r0) |
|
| 106 |
+ if e1 != 0 {
|
|
| 107 |
+ err = errnoErr(e1) |
|
| 108 |
+ } |
|
| 109 |
+ return |
|
| 110 |
+} |
| 0 | 111 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,22 @@ |
| 0 |
+MIT |
|
| 1 |
+ |
|
| 2 |
+Copyright 2017 Tõnis Tiigi <tonistiigi@gmail.com> |
|
| 3 |
+ |
|
| 4 |
+Permission is hereby granted, free of charge, to any person obtaining |
|
| 5 |
+a copy of this software and associated documentation files (the |
|
| 6 |
+"Software"), to deal in the Software without restriction, including |
|
| 7 |
+without limitation the rights to use, copy, modify, merge, publish, |
|
| 8 |
+distribute, sublicense, and/or sell copies of the Software, and to |
|
| 9 |
+permit persons to whom the Software is furnished to do so, subject to |
|
| 10 |
+the following conditions: |
|
| 11 |
+ |
|
| 12 |
+The above copyright notice and this permission notice shall be |
|
| 13 |
+included in all copies or substantial portions of the Software. |
|
| 14 |
+ |
|
| 15 |
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
|
| 16 |
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
|
| 17 |
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
|
| 18 |
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE |
|
| 19 |
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION |
|
| 20 |
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION |
|
| 21 |
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
|
| 0 | 22 |
\ No newline at end of file |
| 1 | 23 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,37 @@ |
| 0 |
+package fsutil |
|
| 1 |
+ |
|
| 2 |
+import ( |
|
| 3 |
+ "os" |
|
| 4 |
+ |
|
| 5 |
+ "golang.org/x/net/context" |
|
| 6 |
+) |
|
| 7 |
+ |
|
| 8 |
+type walkerFn func(ctx context.Context, pathC chan<- *currentPath) error |
|
| 9 |
+ |
|
| 10 |
+func Changes(ctx context.Context, a, b walkerFn, changeFn ChangeFunc) error {
|
|
| 11 |
+ return nil |
|
| 12 |
+} |
|
| 13 |
+ |
|
| 14 |
+type HandleChangeFn func(ChangeKind, string, os.FileInfo, error) error |
|
| 15 |
+ |
|
| 16 |
+func GetWalkerFn(root string) walkerFn {
|
|
| 17 |
+ return func(ctx context.Context, pathC chan<- *currentPath) error {
|
|
| 18 |
+ return Walk(ctx, root, nil, func(path string, f os.FileInfo, err error) error {
|
|
| 19 |
+ if err != nil {
|
|
| 20 |
+ return err |
|
| 21 |
+ } |
|
| 22 |
+ |
|
| 23 |
+ p := ¤tPath{
|
|
| 24 |
+ path: path, |
|
| 25 |
+ f: f, |
|
| 26 |
+ } |
|
| 27 |
+ |
|
| 28 |
+ select {
|
|
| 29 |
+ case <-ctx.Done(): |
|
| 30 |
+ return ctx.Err() |
|
| 31 |
+ case pathC <- p: |
|
| 32 |
+ return nil |
|
| 33 |
+ } |
|
| 34 |
+ }) |
|
| 35 |
+ } |
|
| 36 |
+} |
| 0 | 37 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,199 @@ |
| 0 |
+package fsutil |
|
| 1 |
+ |
|
| 2 |
+import ( |
|
| 3 |
+ "os" |
|
| 4 |
+ "strings" |
|
| 5 |
+ |
|
| 6 |
+ "golang.org/x/net/context" |
|
| 7 |
+ "golang.org/x/sync/errgroup" |
|
| 8 |
+) |
|
| 9 |
+ |
|
| 10 |
+// Everything below is copied from containerd/fs. TODO: remove duplication @dmcgowan |
|
| 11 |
+ |
|
| 12 |
+// Const redefined because containerd/fs doesn't build on !linux |
|
| 13 |
+ |
|
| 14 |
+// ChangeKind is the type of modification that |
|
| 15 |
+// a change is making. |
|
| 16 |
+type ChangeKind int |
|
| 17 |
+ |
|
| 18 |
+const ( |
|
| 19 |
+ // ChangeKindAdd represents an addition of |
|
| 20 |
+ // a file |
|
| 21 |
+ ChangeKindAdd ChangeKind = iota |
|
| 22 |
+ |
|
| 23 |
+ // ChangeKindModify represents a change to |
|
| 24 |
+ // an existing file |
|
| 25 |
+ ChangeKindModify |
|
| 26 |
+ |
|
| 27 |
+ // ChangeKindDelete represents a delete of |
|
| 28 |
+ // a file |
|
| 29 |
+ ChangeKindDelete |
|
| 30 |
+) |
|
| 31 |
+ |
|
| 32 |
+// ChangeFunc is the type of function called for each change |
|
| 33 |
+// computed during a directory changes calculation. |
|
| 34 |
+type ChangeFunc func(ChangeKind, string, os.FileInfo, error) error |
|
| 35 |
+ |
|
| 36 |
+type currentPath struct {
|
|
| 37 |
+ path string |
|
| 38 |
+ f os.FileInfo |
|
| 39 |
+ // fullPath string |
|
| 40 |
+} |
|
| 41 |
+ |
|
| 42 |
+// doubleWalkDiff walks both directories to create a diff |
|
| 43 |
+func doubleWalkDiff(ctx context.Context, changeFn ChangeFunc, a, b walkerFn) (err error) {
|
|
| 44 |
+ g, ctx := errgroup.WithContext(ctx) |
|
| 45 |
+ |
|
| 46 |
+ var ( |
|
| 47 |
+ c1 = make(chan *currentPath, 128) |
|
| 48 |
+ c2 = make(chan *currentPath, 128) |
|
| 49 |
+ |
|
| 50 |
+ f1, f2 *currentPath |
|
| 51 |
+ rmdir string |
|
| 52 |
+ ) |
|
| 53 |
+ g.Go(func() error {
|
|
| 54 |
+ defer close(c1) |
|
| 55 |
+ return a(ctx, c1) |
|
| 56 |
+ }) |
|
| 57 |
+ g.Go(func() error {
|
|
| 58 |
+ defer close(c2) |
|
| 59 |
+ return b(ctx, c2) |
|
| 60 |
+ }) |
|
| 61 |
+ g.Go(func() error {
|
|
| 62 |
+ loop0: |
|
| 63 |
+ for c1 != nil || c2 != nil {
|
|
| 64 |
+ if f1 == nil && c1 != nil {
|
|
| 65 |
+ f1, err = nextPath(ctx, c1) |
|
| 66 |
+ if err != nil {
|
|
| 67 |
+ return err |
|
| 68 |
+ } |
|
| 69 |
+ if f1 == nil {
|
|
| 70 |
+ c1 = nil |
|
| 71 |
+ } |
|
| 72 |
+ } |
|
| 73 |
+ |
|
| 74 |
+ if f2 == nil && c2 != nil {
|
|
| 75 |
+ f2, err = nextPath(ctx, c2) |
|
| 76 |
+ if err != nil {
|
|
| 77 |
+ return err |
|
| 78 |
+ } |
|
| 79 |
+ if f2 == nil {
|
|
| 80 |
+ c2 = nil |
|
| 81 |
+ } |
|
| 82 |
+ } |
|
| 83 |
+ if f1 == nil && f2 == nil {
|
|
| 84 |
+ continue |
|
| 85 |
+ } |
|
| 86 |
+ |
|
| 87 |
+ var f os.FileInfo |
|
| 88 |
+ k, p := pathChange(f1, f2) |
|
| 89 |
+ switch k {
|
|
| 90 |
+ case ChangeKindAdd: |
|
| 91 |
+ if rmdir != "" {
|
|
| 92 |
+ rmdir = "" |
|
| 93 |
+ } |
|
| 94 |
+ f = f2.f |
|
| 95 |
+ f2 = nil |
|
| 96 |
+ case ChangeKindDelete: |
|
| 97 |
+ // Check if this file is already removed by being |
|
| 98 |
+ // under of a removed directory |
|
| 99 |
+ if rmdir != "" && strings.HasPrefix(f1.path, rmdir) {
|
|
| 100 |
+ f1 = nil |
|
| 101 |
+ continue |
|
| 102 |
+ } else if rmdir == "" && f1.f.IsDir() {
|
|
| 103 |
+ rmdir = f1.path + string(os.PathSeparator) |
|
| 104 |
+ } else if rmdir != "" {
|
|
| 105 |
+ rmdir = "" |
|
| 106 |
+ } |
|
| 107 |
+ f1 = nil |
|
| 108 |
+ case ChangeKindModify: |
|
| 109 |
+ same, err := sameFile(f1, f2) |
|
| 110 |
+ if err != nil {
|
|
| 111 |
+ return err |
|
| 112 |
+ } |
|
| 113 |
+ if f1.f.IsDir() && !f2.f.IsDir() {
|
|
| 114 |
+ rmdir = f1.path + string(os.PathSeparator) |
|
| 115 |
+ } else if rmdir != "" {
|
|
| 116 |
+ rmdir = "" |
|
| 117 |
+ } |
|
| 118 |
+ f = f2.f |
|
| 119 |
+ f1 = nil |
|
| 120 |
+ f2 = nil |
|
| 121 |
+ if same {
|
|
| 122 |
+ continue loop0 |
|
| 123 |
+ } |
|
| 124 |
+ } |
|
| 125 |
+ if err := changeFn(k, p, f, nil); err != nil {
|
|
| 126 |
+ return err |
|
| 127 |
+ } |
|
| 128 |
+ } |
|
| 129 |
+ return nil |
|
| 130 |
+ }) |
|
| 131 |
+ |
|
| 132 |
+ return g.Wait() |
|
| 133 |
+} |
|
| 134 |
+ |
|
| 135 |
+func pathChange(lower, upper *currentPath) (ChangeKind, string) {
|
|
| 136 |
+ if lower == nil {
|
|
| 137 |
+ if upper == nil {
|
|
| 138 |
+ panic("cannot compare nil paths")
|
|
| 139 |
+ } |
|
| 140 |
+ return ChangeKindAdd, upper.path |
|
| 141 |
+ } |
|
| 142 |
+ if upper == nil {
|
|
| 143 |
+ return ChangeKindDelete, lower.path |
|
| 144 |
+ } |
|
| 145 |
+ |
|
| 146 |
+ switch i := ComparePath(lower.path, upper.path); {
|
|
| 147 |
+ case i < 0: |
|
| 148 |
+ // File in lower that is not in upper |
|
| 149 |
+ return ChangeKindDelete, lower.path |
|
| 150 |
+ case i > 0: |
|
| 151 |
+ // File in upper that is not in lower |
|
| 152 |
+ return ChangeKindAdd, upper.path |
|
| 153 |
+ default: |
|
| 154 |
+ return ChangeKindModify, upper.path |
|
| 155 |
+ } |
|
| 156 |
+} |
|
| 157 |
+ |
|
| 158 |
+func sameFile(f1, f2 *currentPath) (same bool, retErr error) {
|
|
| 159 |
+ // If not a directory also check size, modtime, and content |
|
| 160 |
+ if !f1.f.IsDir() {
|
|
| 161 |
+ if f1.f.Size() != f2.f.Size() {
|
|
| 162 |
+ return false, nil |
|
| 163 |
+ } |
|
| 164 |
+ |
|
| 165 |
+ t1 := f1.f.ModTime() |
|
| 166 |
+ t2 := f2.f.ModTime() |
|
| 167 |
+ if t1.UnixNano() != t2.UnixNano() {
|
|
| 168 |
+ return false, nil |
|
| 169 |
+ } |
|
| 170 |
+ } |
|
| 171 |
+ |
|
| 172 |
+ ls1, ok := f1.f.Sys().(*Stat) |
|
| 173 |
+ if !ok {
|
|
| 174 |
+ return false, nil |
|
| 175 |
+ } |
|
| 176 |
+ ls2, ok := f1.f.Sys().(*Stat) |
|
| 177 |
+ if !ok {
|
|
| 178 |
+ return false, nil |
|
| 179 |
+ } |
|
| 180 |
+ |
|
| 181 |
+ return compareStat(ls1, ls2) |
|
| 182 |
+} |
|
| 183 |
+ |
|
| 184 |
+// compareStat returns whether the stats are equivalent, |
|
| 185 |
+// whether the files are considered the same file, and |
|
| 186 |
+// an error |
|
| 187 |
+func compareStat(ls1, ls2 *Stat) (bool, error) {
|
|
| 188 |
+ return ls1.Mode == ls2.Mode && ls1.Uid == ls2.Uid && ls1.Gid == ls2.Gid && ls1.Devmajor == ls2.Devmajor && ls1.Devminor == ls2.Devminor && ls1.Linkname == ls2.Linkname, nil |
|
| 189 |
+} |
|
| 190 |
+ |
|
| 191 |
+func nextPath(ctx context.Context, pathC <-chan *currentPath) (*currentPath, error) {
|
|
| 192 |
+ select {
|
|
| 193 |
+ case <-ctx.Done(): |
|
| 194 |
+ return nil, ctx.Err() |
|
| 195 |
+ case p := <-pathC: |
|
| 196 |
+ return p, nil |
|
| 197 |
+ } |
|
| 198 |
+} |
| 0 | 199 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,37 @@ |
| 0 |
+package fsutil |
|
| 1 |
+ |
|
| 2 |
+import ( |
|
| 3 |
+ "bytes" |
|
| 4 |
+ "syscall" |
|
| 5 |
+ |
|
| 6 |
+ "github.com/pkg/errors" |
|
| 7 |
+ "github.com/stevvooe/continuity/sysx" |
|
| 8 |
+) |
|
| 9 |
+ |
|
| 10 |
+// compareSysStat returns whether the stats are equivalent, |
|
| 11 |
+// whether the files are considered the same file, and |
|
| 12 |
+// an error |
|
| 13 |
+func compareSysStat(s1, s2 interface{}) (bool, error) {
|
|
| 14 |
+ ls1, ok := s1.(*syscall.Stat_t) |
|
| 15 |
+ if !ok {
|
|
| 16 |
+ return false, nil |
|
| 17 |
+ } |
|
| 18 |
+ ls2, ok := s2.(*syscall.Stat_t) |
|
| 19 |
+ if !ok {
|
|
| 20 |
+ return false, nil |
|
| 21 |
+ } |
|
| 22 |
+ |
|
| 23 |
+ return ls1.Mode == ls2.Mode && ls1.Uid == ls2.Uid && ls1.Gid == ls2.Gid && ls1.Rdev == ls2.Rdev, nil |
|
| 24 |
+} |
|
| 25 |
+ |
|
| 26 |
+func compareCapabilities(p1, p2 string) (bool, error) {
|
|
| 27 |
+ c1, err := sysx.LGetxattr(p1, "security.capability") |
|
| 28 |
+ if err != nil && err != syscall.ENODATA {
|
|
| 29 |
+ return false, errors.Wrapf(err, "failed to get xattr for %s", p1) |
|
| 30 |
+ } |
|
| 31 |
+ c2, err := sysx.LGetxattr(p2, "security.capability") |
|
| 32 |
+ if err != nil && err != syscall.ENODATA {
|
|
| 33 |
+ return false, errors.Wrapf(err, "failed to get xattr for %s", p2) |
|
| 34 |
+ } |
|
| 35 |
+ return bytes.Equal(c1, c2), nil |
|
| 36 |
+} |
| 0 | 37 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,353 @@ |
| 0 |
+// +build linux windows |
|
| 1 |
+ |
|
| 2 |
+package fsutil |
|
| 3 |
+ |
|
| 4 |
+import ( |
|
| 5 |
+ "archive/tar" |
|
| 6 |
+ "crypto/sha256" |
|
| 7 |
+ "encoding/hex" |
|
| 8 |
+ "hash" |
|
| 9 |
+ "io" |
|
| 10 |
+ "os" |
|
| 11 |
+ "path/filepath" |
|
| 12 |
+ "strconv" |
|
| 13 |
+ "sync" |
|
| 14 |
+ "time" |
|
| 15 |
+ |
|
| 16 |
+ "github.com/docker/docker/pkg/archive" |
|
| 17 |
+ "github.com/docker/docker/pkg/tarsum" |
|
| 18 |
+ "github.com/pkg/errors" |
|
| 19 |
+ "golang.org/x/net/context" |
|
| 20 |
+ "golang.org/x/sync/errgroup" |
|
| 21 |
+) |
|
| 22 |
+ |
|
| 23 |
+type WriteToFunc func(context.Context, string, io.WriteCloser) error |
|
| 24 |
+ |
|
| 25 |
+type DiskWriterOpt struct {
|
|
| 26 |
+ AsyncDataCb WriteToFunc |
|
| 27 |
+ SyncDataCb WriteToFunc |
|
| 28 |
+ NotifyCb func(ChangeKind, string, os.FileInfo, error) error |
|
| 29 |
+} |
|
| 30 |
+ |
|
| 31 |
+type DiskWriter struct {
|
|
| 32 |
+ opt DiskWriterOpt |
|
| 33 |
+ dest string |
|
| 34 |
+ |
|
| 35 |
+ wg sync.WaitGroup |
|
| 36 |
+ ctx context.Context |
|
| 37 |
+ cancel func() |
|
| 38 |
+ eg *errgroup.Group |
|
| 39 |
+} |
|
| 40 |
+ |
|
| 41 |
+func NewDiskWriter(ctx context.Context, dest string, opt DiskWriterOpt) (*DiskWriter, error) {
|
|
| 42 |
+ if opt.SyncDataCb == nil && opt.AsyncDataCb == nil {
|
|
| 43 |
+ return nil, errors.New("no data callback specified")
|
|
| 44 |
+ } |
|
| 45 |
+ if opt.SyncDataCb != nil && opt.AsyncDataCb != nil {
|
|
| 46 |
+ return nil, errors.New("can't specify both sync and async data callbacks")
|
|
| 47 |
+ } |
|
| 48 |
+ |
|
| 49 |
+ ctx, cancel := context.WithCancel(ctx) |
|
| 50 |
+ eg, ctx := errgroup.WithContext(ctx) |
|
| 51 |
+ |
|
| 52 |
+ return &DiskWriter{
|
|
| 53 |
+ opt: opt, |
|
| 54 |
+ dest: dest, |
|
| 55 |
+ eg: eg, |
|
| 56 |
+ ctx: ctx, |
|
| 57 |
+ cancel: cancel, |
|
| 58 |
+ }, nil |
|
| 59 |
+} |
|
| 60 |
+ |
|
| 61 |
+func (dw *DiskWriter) Wait(ctx context.Context) error {
|
|
| 62 |
+ return dw.eg.Wait() |
|
| 63 |
+} |
|
| 64 |
+ |
|
| 65 |
+func (dw *DiskWriter) HandleChange(kind ChangeKind, p string, fi os.FileInfo, err error) (retErr error) {
|
|
| 66 |
+ if err != nil {
|
|
| 67 |
+ return err |
|
| 68 |
+ } |
|
| 69 |
+ |
|
| 70 |
+ select {
|
|
| 71 |
+ case <-dw.ctx.Done(): |
|
| 72 |
+ return dw.ctx.Err() |
|
| 73 |
+ default: |
|
| 74 |
+ } |
|
| 75 |
+ |
|
| 76 |
+ defer func() {
|
|
| 77 |
+ if retErr != nil {
|
|
| 78 |
+ dw.cancel() |
|
| 79 |
+ } |
|
| 80 |
+ }() |
|
| 81 |
+ |
|
| 82 |
+ p = filepath.FromSlash(p) |
|
| 83 |
+ |
|
| 84 |
+ destPath := filepath.Join(dw.dest, p) |
|
| 85 |
+ |
|
| 86 |
+ if kind == ChangeKindDelete {
|
|
| 87 |
+ // todo: no need to validate if diff is trusted but is it always? |
|
| 88 |
+ if err := os.RemoveAll(destPath); err != nil {
|
|
| 89 |
+ return errors.Wrapf(err, "failed to remove: %s", destPath) |
|
| 90 |
+ } |
|
| 91 |
+ if dw.opt.NotifyCb != nil {
|
|
| 92 |
+ if err := dw.opt.NotifyCb(kind, p, nil, nil); err != nil {
|
|
| 93 |
+ return err |
|
| 94 |
+ } |
|
| 95 |
+ } |
|
| 96 |
+ return nil |
|
| 97 |
+ } |
|
| 98 |
+ |
|
| 99 |
+ stat, ok := fi.Sys().(*Stat) |
|
| 100 |
+ if !ok {
|
|
| 101 |
+ return errors.Errorf("%s invalid change without stat information", p)
|
|
| 102 |
+ } |
|
| 103 |
+ |
|
| 104 |
+ rename := true |
|
| 105 |
+ oldFi, err := os.Lstat(destPath) |
|
| 106 |
+ if err != nil {
|
|
| 107 |
+ if os.IsNotExist(err) {
|
|
| 108 |
+ if kind != ChangeKindAdd {
|
|
| 109 |
+ return errors.Wrapf(err, "invalid addition: %s", destPath) |
|
| 110 |
+ } |
|
| 111 |
+ rename = false |
|
| 112 |
+ } else {
|
|
| 113 |
+ return errors.Wrapf(err, "failed to stat %s", destPath) |
|
| 114 |
+ } |
|
| 115 |
+ } |
|
| 116 |
+ |
|
| 117 |
+ if oldFi != nil && fi.IsDir() && oldFi.IsDir() {
|
|
| 118 |
+ if err := rewriteMetadata(destPath, stat); err != nil {
|
|
| 119 |
+ return errors.Wrapf(err, "error setting dir metadata for %s", destPath) |
|
| 120 |
+ } |
|
| 121 |
+ return nil |
|
| 122 |
+ } |
|
| 123 |
+ |
|
| 124 |
+ newPath := destPath |
|
| 125 |
+ if rename {
|
|
| 126 |
+ newPath = filepath.Join(filepath.Dir(destPath), ".tmp."+nextSuffix()) |
|
| 127 |
+ } |
|
| 128 |
+ |
|
| 129 |
+ isRegularFile := false |
|
| 130 |
+ |
|
| 131 |
+ switch {
|
|
| 132 |
+ case fi.IsDir(): |
|
| 133 |
+ if err := os.Mkdir(newPath, fi.Mode()); err != nil {
|
|
| 134 |
+ return errors.Wrapf(err, "failed to create dir %s", newPath) |
|
| 135 |
+ } |
|
| 136 |
+ case fi.Mode()&os.ModeDevice != 0 || fi.Mode()&os.ModeNamedPipe != 0: |
|
| 137 |
+ if err := handleTarTypeBlockCharFifo(newPath, stat); err != nil {
|
|
| 138 |
+ return errors.Wrapf(err, "failed to create device %s", newPath) |
|
| 139 |
+ } |
|
| 140 |
+ case fi.Mode()&os.ModeSymlink != 0: |
|
| 141 |
+ if err := os.Symlink(stat.Linkname, newPath); err != nil {
|
|
| 142 |
+ return errors.Wrapf(err, "failed to symlink %s", newPath) |
|
| 143 |
+ } |
|
| 144 |
+ case stat.Linkname != "": |
|
| 145 |
+ if err := os.Link(filepath.Join(dw.dest, stat.Linkname), newPath); err != nil {
|
|
| 146 |
+ return errors.Wrapf(err, "failed to link %s to %s", newPath, stat.Linkname) |
|
| 147 |
+ } |
|
| 148 |
+ default: |
|
| 149 |
+ isRegularFile = true |
|
| 150 |
+ file, err := os.OpenFile(newPath, os.O_CREATE|os.O_WRONLY, fi.Mode()) //todo: windows |
|
| 151 |
+ if err != nil {
|
|
| 152 |
+ return errors.Wrapf(err, "failed to create %s", newPath) |
|
| 153 |
+ } |
|
| 154 |
+ if dw.opt.SyncDataCb != nil {
|
|
| 155 |
+ if err := dw.processChange(ChangeKindAdd, p, fi, file); err != nil {
|
|
| 156 |
+ file.Close() |
|
| 157 |
+ return err |
|
| 158 |
+ } |
|
| 159 |
+ break |
|
| 160 |
+ } |
|
| 161 |
+ if err := file.Close(); err != nil {
|
|
| 162 |
+ return errors.Wrapf(err, "failed to close %s", newPath) |
|
| 163 |
+ } |
|
| 164 |
+ } |
|
| 165 |
+ |
|
| 166 |
+ if err := rewriteMetadata(newPath, stat); err != nil {
|
|
| 167 |
+ return errors.Wrapf(err, "error setting metadata for %s", newPath) |
|
| 168 |
+ } |
|
| 169 |
+ |
|
| 170 |
+ if rename {
|
|
| 171 |
+ if err := os.Rename(newPath, destPath); err != nil {
|
|
| 172 |
+ return errors.Wrapf(err, "failed to rename %s to %s", newPath, destPath) |
|
| 173 |
+ } |
|
| 174 |
+ } |
|
| 175 |
+ |
|
| 176 |
+ if isRegularFile {
|
|
| 177 |
+ if dw.opt.AsyncDataCb != nil {
|
|
| 178 |
+ dw.requestAsyncFileData(p, destPath, fi) |
|
| 179 |
+ } |
|
| 180 |
+ } else {
|
|
| 181 |
+ return dw.processChange(kind, p, fi, nil) |
|
| 182 |
+ } |
|
| 183 |
+ |
|
| 184 |
+ return nil |
|
| 185 |
+} |
|
| 186 |
+ |
|
| 187 |
+func (dw *DiskWriter) requestAsyncFileData(p, dest string, fi os.FileInfo) {
|
|
| 188 |
+ // todo: limit worker threads |
|
| 189 |
+ dw.eg.Go(func() error {
|
|
| 190 |
+ if err := dw.processChange(ChangeKindAdd, p, fi, &lazyFileWriter{
|
|
| 191 |
+ dest: dest, |
|
| 192 |
+ }); err != nil {
|
|
| 193 |
+ return err |
|
| 194 |
+ } |
|
| 195 |
+ return chtimes(dest, fi.ModTime().UnixNano()) // TODO: parent dirs |
|
| 196 |
+ }) |
|
| 197 |
+} |
|
| 198 |
+ |
|
| 199 |
+func (dw *DiskWriter) processChange(kind ChangeKind, p string, fi os.FileInfo, w io.WriteCloser) error {
|
|
| 200 |
+ origw := w |
|
| 201 |
+ var hw *hashedWriter |
|
| 202 |
+ if dw.opt.NotifyCb != nil {
|
|
| 203 |
+ var err error |
|
| 204 |
+ if hw, err = newHashWriter(p, fi, w); err != nil {
|
|
| 205 |
+ return err |
|
| 206 |
+ } |
|
| 207 |
+ w = hw |
|
| 208 |
+ } |
|
| 209 |
+ if origw != nil {
|
|
| 210 |
+ fn := dw.opt.SyncDataCb |
|
| 211 |
+ if fn == nil && dw.opt.AsyncDataCb != nil {
|
|
| 212 |
+ fn = dw.opt.AsyncDataCb |
|
| 213 |
+ } |
|
| 214 |
+ if err := fn(dw.ctx, p, w); err != nil {
|
|
| 215 |
+ return err |
|
| 216 |
+ } |
|
| 217 |
+ } else {
|
|
| 218 |
+ if hw != nil {
|
|
| 219 |
+ hw.Close() |
|
| 220 |
+ } |
|
| 221 |
+ } |
|
| 222 |
+ if hw != nil {
|
|
| 223 |
+ return dw.opt.NotifyCb(kind, p, hw, nil) |
|
| 224 |
+ } |
|
| 225 |
+ return nil |
|
| 226 |
+} |
|
| 227 |
+ |
|
| 228 |
+type hashedWriter struct {
|
|
| 229 |
+ os.FileInfo |
|
| 230 |
+ io.Writer |
|
| 231 |
+ h hash.Hash |
|
| 232 |
+ w io.WriteCloser |
|
| 233 |
+ sum string |
|
| 234 |
+} |
|
| 235 |
+ |
|
| 236 |
+func newHashWriter(p string, fi os.FileInfo, w io.WriteCloser) (*hashedWriter, error) {
|
|
| 237 |
+ h, err := NewTarsumHash(p, fi) |
|
| 238 |
+ if err != nil {
|
|
| 239 |
+ return nil, err |
|
| 240 |
+ } |
|
| 241 |
+ hw := &hashedWriter{
|
|
| 242 |
+ FileInfo: fi, |
|
| 243 |
+ Writer: io.MultiWriter(w, h), |
|
| 244 |
+ h: h, |
|
| 245 |
+ w: w, |
|
| 246 |
+ } |
|
| 247 |
+ return hw, nil |
|
| 248 |
+} |
|
| 249 |
+ |
|
| 250 |
+func (hw *hashedWriter) Close() error {
|
|
| 251 |
+ hw.sum = string(hex.EncodeToString(hw.h.Sum(nil))) |
|
| 252 |
+ if hw.w != nil {
|
|
| 253 |
+ return hw.w.Close() |
|
| 254 |
+ } |
|
| 255 |
+ return nil |
|
| 256 |
+} |
|
| 257 |
+ |
|
| 258 |
+func (hw *hashedWriter) Hash() string {
|
|
| 259 |
+ return hw.sum |
|
| 260 |
+} |
|
| 261 |
+ |
|
| 262 |
+type lazyFileWriter struct {
|
|
| 263 |
+ dest string |
|
| 264 |
+ ctx context.Context |
|
| 265 |
+ f *os.File |
|
| 266 |
+} |
|
| 267 |
+ |
|
| 268 |
+func (lfw *lazyFileWriter) Write(dt []byte) (int, error) {
|
|
| 269 |
+ if lfw.f == nil {
|
|
| 270 |
+ file, err := os.OpenFile(lfw.dest, os.O_WRONLY, 0) //todo: windows |
|
| 271 |
+ if err != nil {
|
|
| 272 |
+ return 0, errors.Wrapf(err, "failed to open %s", lfw.dest) |
|
| 273 |
+ } |
|
| 274 |
+ lfw.f = file |
|
| 275 |
+ } |
|
| 276 |
+ return lfw.f.Write(dt) |
|
| 277 |
+} |
|
| 278 |
+ |
|
| 279 |
+func (lfw *lazyFileWriter) Close() error {
|
|
| 280 |
+ if lfw.f != nil {
|
|
| 281 |
+ return lfw.f.Close() |
|
| 282 |
+ } |
|
| 283 |
+ return nil |
|
| 284 |
+} |
|
| 285 |
+ |
|
| 286 |
+func mkdev(major int64, minor int64) uint32 {
|
|
| 287 |
+ return uint32(((minor & 0xfff00) << 12) | ((major & 0xfff) << 8) | (minor & 0xff)) |
|
| 288 |
+} |
|
| 289 |
+ |
|
| 290 |
+// Random number state. |
|
| 291 |
+// We generate random temporary file names so that there's a good |
|
| 292 |
+// chance the file doesn't exist yet - keeps the number of tries in |
|
| 293 |
+// TempFile to a minimum. |
|
| 294 |
+var rand uint32 |
|
| 295 |
+var randmu sync.Mutex |
|
| 296 |
+ |
|
| 297 |
+func reseed() uint32 {
|
|
| 298 |
+ return uint32(time.Now().UnixNano() + int64(os.Getpid())) |
|
| 299 |
+} |
|
| 300 |
+ |
|
| 301 |
+func nextSuffix() string {
|
|
| 302 |
+ randmu.Lock() |
|
| 303 |
+ r := rand |
|
| 304 |
+ if r == 0 {
|
|
| 305 |
+ r = reseed() |
|
| 306 |
+ } |
|
| 307 |
+ r = r*1664525 + 1013904223 // constants from Numerical Recipes |
|
| 308 |
+ rand = r |
|
| 309 |
+ randmu.Unlock() |
|
| 310 |
+ return strconv.Itoa(int(1e9 + r%1e9))[1:] |
|
| 311 |
+} |
|
| 312 |
+ |
|
| 313 |
+func NewTarsumHash(p string, fi os.FileInfo) (hash.Hash, error) {
|
|
| 314 |
+ stat, ok := fi.Sys().(*Stat) |
|
| 315 |
+ link := "" |
|
| 316 |
+ if ok {
|
|
| 317 |
+ link = stat.Linkname |
|
| 318 |
+ } |
|
| 319 |
+ if fi.IsDir() {
|
|
| 320 |
+ p += string(os.PathSeparator) |
|
| 321 |
+ } |
|
| 322 |
+ h, err := archive.FileInfoHeader(p, fi, link) |
|
| 323 |
+ if err != nil {
|
|
| 324 |
+ return nil, err |
|
| 325 |
+ } |
|
| 326 |
+ h.Name = p |
|
| 327 |
+ if ok {
|
|
| 328 |
+ h.Uid = int(stat.Uid) |
|
| 329 |
+ h.Gid = int(stat.Gid) |
|
| 330 |
+ h.Linkname = stat.Linkname |
|
| 331 |
+ if stat.Xattrs != nil {
|
|
| 332 |
+ h.Xattrs = make(map[string]string) |
|
| 333 |
+ for k, v := range stat.Xattrs {
|
|
| 334 |
+ h.Xattrs[k] = string(v) |
|
| 335 |
+ } |
|
| 336 |
+ } |
|
| 337 |
+ } |
|
| 338 |
+ tsh := &tarsumHash{h: h, Hash: sha256.New()}
|
|
| 339 |
+ tsh.Reset() |
|
| 340 |
+ return tsh, nil |
|
| 341 |
+} |
|
| 342 |
+ |
|
| 343 |
+// Reset resets the Hash to its initial state. |
|
| 344 |
+func (tsh *tarsumHash) Reset() {
|
|
| 345 |
+ tsh.Hash.Reset() |
|
| 346 |
+ tarsum.WriteV1Header(tsh.h, tsh.Hash) |
|
| 347 |
+} |
|
| 348 |
+ |
|
| 349 |
+type tarsumHash struct {
|
|
| 350 |
+ hash.Hash |
|
| 351 |
+ h *tar.Header |
|
| 352 |
+} |
| 0 | 353 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,64 @@ |
| 0 |
+// +build linux |
|
| 1 |
+ |
|
| 2 |
+package fsutil |
|
| 3 |
+ |
|
| 4 |
+import ( |
|
| 5 |
+ "os" |
|
| 6 |
+ "syscall" |
|
| 7 |
+ |
|
| 8 |
+ "github.com/pkg/errors" |
|
| 9 |
+ "github.com/stevvooe/continuity/sysx" |
|
| 10 |
+ "golang.org/x/sys/unix" |
|
| 11 |
+) |
|
| 12 |
+ |
|
| 13 |
+func rewriteMetadata(p string, stat *Stat) error {
|
|
| 14 |
+ for key, value := range stat.Xattrs {
|
|
| 15 |
+ sysx.Setxattr(p, key, value, 0) |
|
| 16 |
+ } |
|
| 17 |
+ |
|
| 18 |
+ if err := os.Lchown(p, int(stat.Uid), int(stat.Gid)); err != nil {
|
|
| 19 |
+ return errors.Wrapf(err, "failed to lchown %s", p) |
|
| 20 |
+ } |
|
| 21 |
+ |
|
| 22 |
+ if os.FileMode(stat.Mode)&os.ModeSymlink == 0 {
|
|
| 23 |
+ if err := os.Chmod(p, os.FileMode(stat.Mode)); err != nil {
|
|
| 24 |
+ return errors.Wrapf(err, "failed to chown %s", p) |
|
| 25 |
+ } |
|
| 26 |
+ } |
|
| 27 |
+ |
|
| 28 |
+ if err := chtimes(p, stat.ModTime); err != nil {
|
|
| 29 |
+ return errors.Wrapf(err, "failed to chtimes %s", p) |
|
| 30 |
+ } |
|
| 31 |
+ |
|
| 32 |
+ return nil |
|
| 33 |
+} |
|
| 34 |
+ |
|
| 35 |
+func chtimes(path string, un int64) error {
|
|
| 36 |
+ var utimes [2]unix.Timespec |
|
| 37 |
+ utimes[0] = unix.NsecToTimespec(un) |
|
| 38 |
+ utimes[1] = utimes[0] |
|
| 39 |
+ |
|
| 40 |
+ if err := unix.UtimesNanoAt(unix.AT_FDCWD, path, utimes[0:], unix.AT_SYMLINK_NOFOLLOW); err != nil {
|
|
| 41 |
+ return errors.Wrap(err, "failed call to UtimesNanoAt") |
|
| 42 |
+ } |
|
| 43 |
+ |
|
| 44 |
+ return nil |
|
| 45 |
+} |
|
| 46 |
+ |
|
| 47 |
+// handleTarTypeBlockCharFifo is an OS-specific helper function used by |
|
| 48 |
+// createTarFile to handle the following types of header: Block; Char; Fifo |
|
| 49 |
+func handleTarTypeBlockCharFifo(path string, stat *Stat) error {
|
|
| 50 |
+ mode := uint32(stat.Mode & 07777) |
|
| 51 |
+ if os.FileMode(stat.Mode)&os.ModeCharDevice != 0 {
|
|
| 52 |
+ mode |= syscall.S_IFCHR |
|
| 53 |
+ } else if os.FileMode(stat.Mode)&os.ModeNamedPipe != 0 {
|
|
| 54 |
+ mode |= syscall.S_IFIFO |
|
| 55 |
+ } else {
|
|
| 56 |
+ mode |= syscall.S_IFBLK |
|
| 57 |
+ } |
|
| 58 |
+ |
|
| 59 |
+ if err := syscall.Mknod(path, mode, int(mkdev(stat.Devmajor, stat.Devminor))); err != nil {
|
|
| 60 |
+ return err |
|
| 61 |
+ } |
|
| 62 |
+ return nil |
|
| 63 |
+} |
| 0 | 64 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,25 @@ |
| 0 |
+// +build windows |
|
| 1 |
+ |
|
| 2 |
+package fsutil |
|
| 3 |
+ |
|
| 4 |
+import ( |
|
| 5 |
+ "os" |
|
| 6 |
+ "time" |
|
| 7 |
+ |
|
| 8 |
+ "github.com/pkg/errors" |
|
| 9 |
+) |
|
| 10 |
+ |
|
| 11 |
+func rewriteMetadata(p string, stat *Stat) error {
|
|
| 12 |
+ return chtimes(p, stat.ModTime) |
|
| 13 |
+} |
|
| 14 |
+ |
|
| 15 |
+func chtimes(path string, un int64) error {
|
|
| 16 |
+ mtime := time.Unix(0, un) |
|
| 17 |
+ return os.Chtimes(path, mtime, mtime) |
|
| 18 |
+} |
|
| 19 |
+ |
|
| 20 |
+// handleTarTypeBlockCharFifo is an OS-specific helper function used by |
|
| 21 |
+// createTarFile to handle the following types of header: Block; Char; Fifo |
|
| 22 |
+func handleTarTypeBlockCharFifo(path string, stat *Stat) error {
|
|
| 23 |
+ return errors.New("Not implemented on windows")
|
|
| 24 |
+} |
| 0 | 3 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,46 @@ |
| 0 |
+package fsutil |
|
| 1 |
+ |
|
| 2 |
+import ( |
|
| 3 |
+ "os" |
|
| 4 |
+ |
|
| 5 |
+ "github.com/pkg/errors" |
|
| 6 |
+) |
|
| 7 |
+ |
|
| 8 |
+// Hardlinks validates that all targets for links were part of the changes |
|
| 9 |
+ |
|
| 10 |
+type Hardlinks struct {
|
|
| 11 |
+ seenFiles map[string]struct{}
|
|
| 12 |
+} |
|
| 13 |
+ |
|
| 14 |
+func (v *Hardlinks) HandleChange(kind ChangeKind, p string, fi os.FileInfo, err error) error {
|
|
| 15 |
+ if err != nil {
|
|
| 16 |
+ return err |
|
| 17 |
+ } |
|
| 18 |
+ |
|
| 19 |
+ if v.seenFiles == nil {
|
|
| 20 |
+ v.seenFiles = make(map[string]struct{})
|
|
| 21 |
+ } |
|
| 22 |
+ |
|
| 23 |
+ if kind == ChangeKindDelete {
|
|
| 24 |
+ return nil |
|
| 25 |
+ } |
|
| 26 |
+ |
|
| 27 |
+ stat, ok := fi.Sys().(*Stat) |
|
| 28 |
+ if !ok {
|
|
| 29 |
+ return errors.Errorf("invalid change without stat info: %s", p)
|
|
| 30 |
+ } |
|
| 31 |
+ |
|
| 32 |
+ if fi.IsDir() || fi.Mode()&os.ModeSymlink != 0 {
|
|
| 33 |
+ return nil |
|
| 34 |
+ } |
|
| 35 |
+ |
|
| 36 |
+ if len(stat.Linkname) > 0 {
|
|
| 37 |
+ if _, ok := v.seenFiles[stat.Linkname]; !ok {
|
|
| 38 |
+ return errors.Errorf("invalid link %s to unknown path: %q", p, stat.Linkname)
|
|
| 39 |
+ } |
|
| 40 |
+ } else {
|
|
| 41 |
+ v.seenFiles[p] = struct{}{}
|
|
| 42 |
+ } |
|
| 43 |
+ |
|
| 44 |
+ return nil |
|
| 45 |
+} |
| 0 | 46 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,45 @@ |
| 0 |
+Incremental file directory sync tools in golang. |
|
| 1 |
+ |
|
| 2 |
+``` |
|
| 3 |
+BENCH_FILE_SIZE=10000 ./bench.test --test.bench . |
|
| 4 |
+BenchmarkCopyWithTar10-4 2000 995242 ns/op |
|
| 5 |
+BenchmarkCopyWithTar50-4 300 4710021 ns/op |
|
| 6 |
+BenchmarkCopyWithTar200-4 100 16627260 ns/op |
|
| 7 |
+BenchmarkCopyWithTar1000-4 20 60031459 ns/op |
|
| 8 |
+BenchmarkCPA10-4 1000 1678367 ns/op |
|
| 9 |
+BenchmarkCPA50-4 500 3690306 ns/op |
|
| 10 |
+BenchmarkCPA200-4 200 9495066 ns/op |
|
| 11 |
+BenchmarkCPA1000-4 50 29769289 ns/op |
|
| 12 |
+BenchmarkDiffCopy10-4 2000 943889 ns/op |
|
| 13 |
+BenchmarkDiffCopy50-4 500 3285950 ns/op |
|
| 14 |
+BenchmarkDiffCopy200-4 200 8563792 ns/op |
|
| 15 |
+BenchmarkDiffCopy1000-4 50 29511340 ns/op |
|
| 16 |
+BenchmarkDiffCopyProto10-4 2000 944615 ns/op |
|
| 17 |
+BenchmarkDiffCopyProto50-4 500 3334940 ns/op |
|
| 18 |
+BenchmarkDiffCopyProto200-4 200 9420038 ns/op |
|
| 19 |
+BenchmarkDiffCopyProto1000-4 50 30632429 ns/op |
|
| 20 |
+BenchmarkIncrementalDiffCopy10-4 2000 691993 ns/op |
|
| 21 |
+BenchmarkIncrementalDiffCopy50-4 1000 1304253 ns/op |
|
| 22 |
+BenchmarkIncrementalDiffCopy200-4 500 3306519 ns/op |
|
| 23 |
+BenchmarkIncrementalDiffCopy1000-4 200 10211343 ns/op |
|
| 24 |
+BenchmarkIncrementalDiffCopy5000-4 20 55194427 ns/op |
|
| 25 |
+BenchmarkIncrementalDiffCopy10000-4 20 91759289 ns/op |
|
| 26 |
+BenchmarkIncrementalCopyWithTar10-4 2000 1020258 ns/op |
|
| 27 |
+BenchmarkIncrementalCopyWithTar50-4 300 5348786 ns/op |
|
| 28 |
+BenchmarkIncrementalCopyWithTar200-4 100 19495000 ns/op |
|
| 29 |
+BenchmarkIncrementalCopyWithTar1000-4 20 70338507 ns/op |
|
| 30 |
+BenchmarkIncrementalRsync10-4 30 45215754 ns/op |
|
| 31 |
+BenchmarkIncrementalRsync50-4 30 45837260 ns/op |
|
| 32 |
+BenchmarkIncrementalRsync200-4 30 48780614 ns/op |
|
| 33 |
+BenchmarkIncrementalRsync1000-4 20 54801892 ns/op |
|
| 34 |
+BenchmarkIncrementalRsync5000-4 20 84782542 ns/op |
|
| 35 |
+BenchmarkIncrementalRsync10000-4 10 103355108 ns/op |
|
| 36 |
+BenchmarkRsync10-4 30 46776470 ns/op |
|
| 37 |
+BenchmarkRsync50-4 30 48601555 ns/op |
|
| 38 |
+BenchmarkRsync200-4 20 59642691 ns/op |
|
| 39 |
+BenchmarkRsync1000-4 20 101343010 ns/op |
|
| 40 |
+BenchmarkGnuTar10-4 500 3171448 ns/op |
|
| 41 |
+BenchmarkGnuTar50-4 300 5030296 ns/op |
|
| 42 |
+BenchmarkGnuTar200-4 100 10464313 ns/op |
|
| 43 |
+BenchmarkGnuTar1000-4 50 30375257 ns/op |
|
| 44 |
+``` |
|
| 0 | 45 |
\ No newline at end of file |
| 1 | 46 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,210 @@ |
| 0 |
+// +build linux windows |
|
| 1 |
+ |
|
| 2 |
+package fsutil |
|
| 3 |
+ |
|
| 4 |
+import ( |
|
| 5 |
+ "io" |
|
| 6 |
+ "os" |
|
| 7 |
+ "sync" |
|
| 8 |
+ |
|
| 9 |
+ "github.com/pkg/errors" |
|
| 10 |
+ "golang.org/x/net/context" |
|
| 11 |
+ "golang.org/x/sync/errgroup" |
|
| 12 |
+) |
|
| 13 |
+ |
|
| 14 |
+func Receive(ctx context.Context, conn Stream, dest string, notifyHashed ChangeFunc) error {
|
|
| 15 |
+ ctx, cancel := context.WithCancel(context.Background()) |
|
| 16 |
+ defer cancel() |
|
| 17 |
+ |
|
| 18 |
+ r := &receiver{
|
|
| 19 |
+ conn: &syncStream{Stream: conn},
|
|
| 20 |
+ dest: dest, |
|
| 21 |
+ files: make(map[string]uint32), |
|
| 22 |
+ pipes: make(map[uint32]io.WriteCloser), |
|
| 23 |
+ notifyHashed: notifyHashed, |
|
| 24 |
+ } |
|
| 25 |
+ return r.run(ctx) |
|
| 26 |
+} |
|
| 27 |
+ |
|
| 28 |
+type receiver struct {
|
|
| 29 |
+ dest string |
|
| 30 |
+ conn Stream |
|
| 31 |
+ files map[string]uint32 |
|
| 32 |
+ pipes map[uint32]io.WriteCloser |
|
| 33 |
+ mu sync.RWMutex |
|
| 34 |
+ muPipes sync.RWMutex |
|
| 35 |
+ |
|
| 36 |
+ notifyHashed ChangeFunc |
|
| 37 |
+ orderValidator Validator |
|
| 38 |
+ hlValidator Hardlinks |
|
| 39 |
+} |
|
| 40 |
+ |
|
| 41 |
+type dynamicWalker struct {
|
|
| 42 |
+ walkChan chan *currentPath |
|
| 43 |
+ closed bool |
|
| 44 |
+} |
|
| 45 |
+ |
|
| 46 |
+func newDynamicWalker() *dynamicWalker {
|
|
| 47 |
+ return &dynamicWalker{
|
|
| 48 |
+ walkChan: make(chan *currentPath, 128), |
|
| 49 |
+ } |
|
| 50 |
+} |
|
| 51 |
+ |
|
| 52 |
+func (w *dynamicWalker) update(p *currentPath) error {
|
|
| 53 |
+ if w.closed {
|
|
| 54 |
+ return errors.New("walker is closed")
|
|
| 55 |
+ } |
|
| 56 |
+ if p == nil {
|
|
| 57 |
+ close(w.walkChan) |
|
| 58 |
+ return nil |
|
| 59 |
+ } |
|
| 60 |
+ w.walkChan <- p |
|
| 61 |
+ return nil |
|
| 62 |
+} |
|
| 63 |
+ |
|
| 64 |
+func (w *dynamicWalker) fill(ctx context.Context, pathC chan<- *currentPath) error {
|
|
| 65 |
+ for {
|
|
| 66 |
+ select {
|
|
| 67 |
+ case p, ok := <-w.walkChan: |
|
| 68 |
+ if !ok {
|
|
| 69 |
+ return nil |
|
| 70 |
+ } |
|
| 71 |
+ pathC <- p |
|
| 72 |
+ case <-ctx.Done(): |
|
| 73 |
+ return ctx.Err() |
|
| 74 |
+ } |
|
| 75 |
+ } |
|
| 76 |
+ return nil |
|
| 77 |
+} |
|
| 78 |
+ |
|
| 79 |
+func (r *receiver) run(ctx context.Context) error {
|
|
| 80 |
+ g, ctx := errgroup.WithContext(ctx) |
|
| 81 |
+ |
|
| 82 |
+ dw, err := NewDiskWriter(ctx, r.dest, DiskWriterOpt{
|
|
| 83 |
+ AsyncDataCb: r.asyncDataFunc, |
|
| 84 |
+ NotifyCb: r.notifyHashed, |
|
| 85 |
+ }) |
|
| 86 |
+ if err != nil {
|
|
| 87 |
+ return err |
|
| 88 |
+ } |
|
| 89 |
+ |
|
| 90 |
+ w := newDynamicWalker() |
|
| 91 |
+ |
|
| 92 |
+ g.Go(func() error {
|
|
| 93 |
+ err := doubleWalkDiff(ctx, dw.HandleChange, GetWalkerFn(r.dest), w.fill) |
|
| 94 |
+ if err != nil {
|
|
| 95 |
+ return err |
|
| 96 |
+ } |
|
| 97 |
+ if err := dw.Wait(ctx); err != nil {
|
|
| 98 |
+ return err |
|
| 99 |
+ } |
|
| 100 |
+ r.conn.SendMsg(&Packet{Type: PACKET_FIN})
|
|
| 101 |
+ return nil |
|
| 102 |
+ }) |
|
| 103 |
+ |
|
| 104 |
+ g.Go(func() error {
|
|
| 105 |
+ var i uint32 = 0 |
|
| 106 |
+ |
|
| 107 |
+ var p Packet |
|
| 108 |
+ for {
|
|
| 109 |
+ p = Packet{Data: p.Data[:0]}
|
|
| 110 |
+ if err := r.conn.RecvMsg(&p); err != nil {
|
|
| 111 |
+ return err |
|
| 112 |
+ } |
|
| 113 |
+ switch p.Type {
|
|
| 114 |
+ case PACKET_STAT: |
|
| 115 |
+ if p.Stat == nil {
|
|
| 116 |
+ if err := w.update(nil); err != nil {
|
|
| 117 |
+ return err |
|
| 118 |
+ } |
|
| 119 |
+ break |
|
| 120 |
+ } |
|
| 121 |
+ if fileCanRequestData(os.FileMode(p.Stat.Mode)) {
|
|
| 122 |
+ r.mu.Lock() |
|
| 123 |
+ r.files[p.Stat.Path] = i |
|
| 124 |
+ r.mu.Unlock() |
|
| 125 |
+ } |
|
| 126 |
+ i++ |
|
| 127 |
+ cp := ¤tPath{path: p.Stat.Path, f: &StatInfo{p.Stat}}
|
|
| 128 |
+ if err := r.orderValidator.HandleChange(ChangeKindAdd, cp.path, cp.f, nil); err != nil {
|
|
| 129 |
+ return err |
|
| 130 |
+ } |
|
| 131 |
+ if err := r.hlValidator.HandleChange(ChangeKindAdd, cp.path, cp.f, nil); err != nil {
|
|
| 132 |
+ return err |
|
| 133 |
+ } |
|
| 134 |
+ if err := w.update(cp); err != nil {
|
|
| 135 |
+ return err |
|
| 136 |
+ } |
|
| 137 |
+ case PACKET_DATA: |
|
| 138 |
+ r.muPipes.Lock() |
|
| 139 |
+ pw, ok := r.pipes[p.ID] |
|
| 140 |
+ r.muPipes.Unlock() |
|
| 141 |
+ if !ok {
|
|
| 142 |
+ return errors.Errorf("invalid file request %s", p.ID)
|
|
| 143 |
+ } |
|
| 144 |
+ if len(p.Data) == 0 {
|
|
| 145 |
+ if err := pw.Close(); err != nil {
|
|
| 146 |
+ return err |
|
| 147 |
+ } |
|
| 148 |
+ } else {
|
|
| 149 |
+ if _, err := pw.Write(p.Data); err != nil {
|
|
| 150 |
+ return err |
|
| 151 |
+ } |
|
| 152 |
+ } |
|
| 153 |
+ case PACKET_FIN: |
|
| 154 |
+ return nil |
|
| 155 |
+ } |
|
| 156 |
+ } |
|
| 157 |
+ }) |
|
| 158 |
+ return g.Wait() |
|
| 159 |
+} |
|
| 160 |
+ |
|
| 161 |
+func (r *receiver) asyncDataFunc(ctx context.Context, p string, wc io.WriteCloser) error {
|
|
| 162 |
+ r.mu.Lock() |
|
| 163 |
+ id, ok := r.files[p] |
|
| 164 |
+ if !ok {
|
|
| 165 |
+ r.mu.Unlock() |
|
| 166 |
+ return errors.Errorf("invalid file request %s", p)
|
|
| 167 |
+ } |
|
| 168 |
+ delete(r.files, p) |
|
| 169 |
+ r.mu.Unlock() |
|
| 170 |
+ |
|
| 171 |
+ wwc := newWrappedWriteCloser(wc) |
|
| 172 |
+ r.muPipes.Lock() |
|
| 173 |
+ r.pipes[id] = wwc |
|
| 174 |
+ r.muPipes.Unlock() |
|
| 175 |
+ if err := r.conn.SendMsg(&Packet{Type: PACKET_REQ, ID: id}); err != nil {
|
|
| 176 |
+ return err |
|
| 177 |
+ } |
|
| 178 |
+ err := wwc.Wait(ctx) |
|
| 179 |
+ r.muPipes.Lock() |
|
| 180 |
+ delete(r.pipes, id) |
|
| 181 |
+ r.muPipes.Unlock() |
|
| 182 |
+ return err |
|
| 183 |
+} |
|
| 184 |
+ |
|
| 185 |
+type wrappedWriteCloser struct {
|
|
| 186 |
+ io.WriteCloser |
|
| 187 |
+ err error |
|
| 188 |
+ once sync.Once |
|
| 189 |
+ done chan struct{}
|
|
| 190 |
+} |
|
| 191 |
+ |
|
| 192 |
+func newWrappedWriteCloser(wc io.WriteCloser) *wrappedWriteCloser {
|
|
| 193 |
+ return &wrappedWriteCloser{WriteCloser: wc, done: make(chan struct{})}
|
|
| 194 |
+} |
|
| 195 |
+ |
|
| 196 |
+func (w *wrappedWriteCloser) Close() error {
|
|
| 197 |
+ w.err = w.WriteCloser.Close() |
|
| 198 |
+ w.once.Do(func() { close(w.done) })
|
|
| 199 |
+ return w.err |
|
| 200 |
+} |
|
| 201 |
+ |
|
| 202 |
+func (w *wrappedWriteCloser) Wait(ctx context.Context) error {
|
|
| 203 |
+ select {
|
|
| 204 |
+ case <-ctx.Done(): |
|
| 205 |
+ return ctx.Err() |
|
| 206 |
+ case <-w.done: |
|
| 207 |
+ return w.err |
|
| 208 |
+ } |
|
| 209 |
+} |
| 0 | 210 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,14 @@ |
| 0 |
+// +build !linux,!windows |
|
| 1 |
+ |
|
| 2 |
+package fsutil |
|
| 3 |
+ |
|
| 4 |
+import ( |
|
| 5 |
+ "runtime" |
|
| 6 |
+ |
|
| 7 |
+ "github.com/pkg/errors" |
|
| 8 |
+ "golang.org/x/net/context" |
|
| 9 |
+) |
|
| 10 |
+ |
|
| 11 |
+func Receive(ctx context.Context, conn Stream, dest string, notifyHashed ChangeFunc) error {
|
|
| 12 |
+ return errors.Errorf("receive is unsupported in %s", runtime.GOOS)
|
|
| 13 |
+} |
| 0 | 14 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,201 @@ |
| 0 |
+package fsutil |
|
| 1 |
+ |
|
| 2 |
+import ( |
|
| 3 |
+ "io" |
|
| 4 |
+ "os" |
|
| 5 |
+ "path/filepath" |
|
| 6 |
+ "sync" |
|
| 7 |
+ |
|
| 8 |
+ "github.com/pkg/errors" |
|
| 9 |
+ "golang.org/x/net/context" |
|
| 10 |
+ "golang.org/x/sync/errgroup" |
|
| 11 |
+) |
|
| 12 |
+ |
|
| 13 |
+var bufPool = sync.Pool{
|
|
| 14 |
+ New: func() interface{} {
|
|
| 15 |
+ return make([]byte, 32*1<<10) |
|
| 16 |
+ }, |
|
| 17 |
+} |
|
| 18 |
+ |
|
| 19 |
+type Stream interface {
|
|
| 20 |
+ RecvMsg(interface{}) error
|
|
| 21 |
+ SendMsg(m interface{}) error
|
|
| 22 |
+ Context() context.Context |
|
| 23 |
+} |
|
| 24 |
+ |
|
| 25 |
+func Send(ctx context.Context, conn Stream, root string, opt *WalkOpt, progressCb func(int, bool)) error {
|
|
| 26 |
+ s := &sender{
|
|
| 27 |
+ conn: &syncStream{Stream: conn},
|
|
| 28 |
+ root: root, |
|
| 29 |
+ opt: opt, |
|
| 30 |
+ files: make(map[uint32]string), |
|
| 31 |
+ progressCb: progressCb, |
|
| 32 |
+ sendpipeline: make(chan *sendHandle, 128), |
|
| 33 |
+ } |
|
| 34 |
+ return s.run(ctx) |
|
| 35 |
+} |
|
| 36 |
+ |
|
| 37 |
+type sendHandle struct {
|
|
| 38 |
+ id uint32 |
|
| 39 |
+ path string |
|
| 40 |
+} |
|
| 41 |
+ |
|
| 42 |
+type sender struct {
|
|
| 43 |
+ conn Stream |
|
| 44 |
+ opt *WalkOpt |
|
| 45 |
+ root string |
|
| 46 |
+ files map[uint32]string |
|
| 47 |
+ mu sync.RWMutex |
|
| 48 |
+ progressCb func(int, bool) |
|
| 49 |
+ progressCurrent int |
|
| 50 |
+ sendpipeline chan *sendHandle |
|
| 51 |
+} |
|
| 52 |
+ |
|
| 53 |
+func (s *sender) run(ctx context.Context) error {
|
|
| 54 |
+ g, ctx := errgroup.WithContext(ctx) |
|
| 55 |
+ |
|
| 56 |
+ defer s.updateProgress(0, true) |
|
| 57 |
+ |
|
| 58 |
+ g.Go(func() error {
|
|
| 59 |
+ return s.walk(ctx) |
|
| 60 |
+ }) |
|
| 61 |
+ |
|
| 62 |
+ for i := 0; i < 4; i++ {
|
|
| 63 |
+ g.Go(func() error {
|
|
| 64 |
+ for h := range s.sendpipeline {
|
|
| 65 |
+ select {
|
|
| 66 |
+ case <-ctx.Done(): |
|
| 67 |
+ return ctx.Err() |
|
| 68 |
+ default: |
|
| 69 |
+ } |
|
| 70 |
+ if err := s.sendFile(h); err != nil {
|
|
| 71 |
+ return err |
|
| 72 |
+ } |
|
| 73 |
+ } |
|
| 74 |
+ return nil |
|
| 75 |
+ }) |
|
| 76 |
+ } |
|
| 77 |
+ |
|
| 78 |
+ g.Go(func() error {
|
|
| 79 |
+ defer close(s.sendpipeline) |
|
| 80 |
+ |
|
| 81 |
+ for {
|
|
| 82 |
+ select {
|
|
| 83 |
+ case <-ctx.Done(): |
|
| 84 |
+ return ctx.Err() |
|
| 85 |
+ default: |
|
| 86 |
+ } |
|
| 87 |
+ var p Packet |
|
| 88 |
+ if err := s.conn.RecvMsg(&p); err != nil {
|
|
| 89 |
+ return err |
|
| 90 |
+ } |
|
| 91 |
+ switch p.Type {
|
|
| 92 |
+ case PACKET_REQ: |
|
| 93 |
+ if err := s.queue(p.ID); err != nil {
|
|
| 94 |
+ return err |
|
| 95 |
+ } |
|
| 96 |
+ case PACKET_FIN: |
|
| 97 |
+ return s.conn.SendMsg(&Packet{Type: PACKET_FIN})
|
|
| 98 |
+ } |
|
| 99 |
+ } |
|
| 100 |
+ }) |
|
| 101 |
+ |
|
| 102 |
+ return g.Wait() |
|
| 103 |
+} |
|
| 104 |
+ |
|
| 105 |
+func (s *sender) updateProgress(size int, last bool) {
|
|
| 106 |
+ if s.progressCb != nil {
|
|
| 107 |
+ s.progressCurrent += size |
|
| 108 |
+ s.progressCb(s.progressCurrent, last) |
|
| 109 |
+ } |
|
| 110 |
+} |
|
| 111 |
+ |
|
| 112 |
+func (s *sender) queue(id uint32) error {
|
|
| 113 |
+ s.mu.Lock() |
|
| 114 |
+ p, ok := s.files[id] |
|
| 115 |
+ if !ok {
|
|
| 116 |
+ s.mu.Unlock() |
|
| 117 |
+ return errors.Errorf("invalid file id %d", id)
|
|
| 118 |
+ } |
|
| 119 |
+ delete(s.files, id) |
|
| 120 |
+ s.mu.Unlock() |
|
| 121 |
+ s.sendpipeline <- &sendHandle{id, p}
|
|
| 122 |
+ return nil |
|
| 123 |
+} |
|
| 124 |
+ |
|
| 125 |
+func (s *sender) sendFile(h *sendHandle) error {
|
|
| 126 |
+ f, err := os.Open(filepath.Join(s.root, h.path)) |
|
| 127 |
+ if err == nil {
|
|
| 128 |
+ buf := bufPool.Get().([]byte) |
|
| 129 |
+ defer bufPool.Put(buf) |
|
| 130 |
+ if _, err := io.CopyBuffer(&fileSender{sender: s, id: h.id}, f, buf); err != nil {
|
|
| 131 |
+ return err |
|
| 132 |
+ } |
|
| 133 |
+ } |
|
| 134 |
+ return s.conn.SendMsg(&Packet{ID: h.id, Type: PACKET_DATA})
|
|
| 135 |
+} |
|
| 136 |
+ |
|
| 137 |
+func (s *sender) walk(ctx context.Context) error {
|
|
| 138 |
+ var i uint32 = 0 |
|
| 139 |
+ err := Walk(ctx, s.root, s.opt, func(path string, fi os.FileInfo, err error) error {
|
|
| 140 |
+ if err != nil {
|
|
| 141 |
+ return err |
|
| 142 |
+ } |
|
| 143 |
+ stat, ok := fi.Sys().(*Stat) |
|
| 144 |
+ if !ok {
|
|
| 145 |
+ return errors.Wrapf(err, "invalid fileinfo without stat info: %s", path) |
|
| 146 |
+ } |
|
| 147 |
+ |
|
| 148 |
+ p := &Packet{
|
|
| 149 |
+ Type: PACKET_STAT, |
|
| 150 |
+ Stat: stat, |
|
| 151 |
+ } |
|
| 152 |
+ if fileCanRequestData(os.FileMode(stat.Mode)) {
|
|
| 153 |
+ s.mu.Lock() |
|
| 154 |
+ s.files[i] = stat.Path |
|
| 155 |
+ s.mu.Unlock() |
|
| 156 |
+ } |
|
| 157 |
+ i++ |
|
| 158 |
+ s.updateProgress(p.Size(), false) |
|
| 159 |
+ return errors.Wrapf(s.conn.SendMsg(p), "failed to send stat %s", path) |
|
| 160 |
+ }) |
|
| 161 |
+ if err != nil {
|
|
| 162 |
+ return err |
|
| 163 |
+ } |
|
| 164 |
+ return errors.Wrapf(s.conn.SendMsg(&Packet{Type: PACKET_STAT}), "failed to send last stat")
|
|
| 165 |
+} |
|
| 166 |
+ |
|
| 167 |
+func fileCanRequestData(m os.FileMode) bool {
|
|
| 168 |
+ // avoid updating this function as it needs to match between sender/receiver. |
|
| 169 |
+ // version if needed |
|
| 170 |
+ return m&os.ModeType == 0 |
|
| 171 |
+} |
|
| 172 |
+ |
|
| 173 |
+type fileSender struct {
|
|
| 174 |
+ sender *sender |
|
| 175 |
+ id uint32 |
|
| 176 |
+} |
|
| 177 |
+ |
|
| 178 |
+func (fs *fileSender) Write(dt []byte) (int, error) {
|
|
| 179 |
+ if len(dt) == 0 {
|
|
| 180 |
+ return 0, nil |
|
| 181 |
+ } |
|
| 182 |
+ p := &Packet{Type: PACKET_DATA, ID: fs.id, Data: dt}
|
|
| 183 |
+ if err := fs.sender.conn.SendMsg(p); err != nil {
|
|
| 184 |
+ return 0, err |
|
| 185 |
+ } |
|
| 186 |
+ fs.sender.updateProgress(p.Size(), false) |
|
| 187 |
+ return len(dt), nil |
|
| 188 |
+} |
|
| 189 |
+ |
|
| 190 |
+type syncStream struct {
|
|
| 191 |
+ Stream |
|
| 192 |
+ mu sync.Mutex |
|
| 193 |
+} |
|
| 194 |
+ |
|
| 195 |
+func (ss *syncStream) SendMsg(m interface{}) error {
|
|
| 196 |
+ ss.mu.Lock() |
|
| 197 |
+ err := ss.Stream.SendMsg(m) |
|
| 198 |
+ ss.mu.Unlock() |
|
| 199 |
+ return err |
|
| 200 |
+} |
| 0 | 201 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,931 @@ |
| 0 |
+// Code generated by protoc-gen-gogo. |
|
| 1 |
+// source: stat.proto |
|
| 2 |
+// DO NOT EDIT! |
|
| 3 |
+ |
|
| 4 |
+/* |
|
| 5 |
+ Package fsutil is a generated protocol buffer package. |
|
| 6 |
+ |
|
| 7 |
+ It is generated from these files: |
|
| 8 |
+ stat.proto |
|
| 9 |
+ wire.proto |
|
| 10 |
+ |
|
| 11 |
+ It has these top-level messages: |
|
| 12 |
+ Stat |
|
| 13 |
+ Packet |
|
| 14 |
+*/ |
|
| 15 |
+package fsutil |
|
| 16 |
+ |
|
| 17 |
+import proto "github.com/gogo/protobuf/proto" |
|
| 18 |
+import fmt "fmt" |
|
| 19 |
+import math "math" |
|
| 20 |
+ |
|
| 21 |
+import bytes "bytes" |
|
| 22 |
+ |
|
| 23 |
+import strings "strings" |
|
| 24 |
+import reflect "reflect" |
|
| 25 |
+import github_com_gogo_protobuf_sortkeys "github.com/gogo/protobuf/sortkeys" |
|
| 26 |
+ |
|
| 27 |
+import io "io" |
|
| 28 |
+ |
|
| 29 |
+// Reference imports to suppress errors if they are not otherwise used. |
|
| 30 |
+var _ = proto.Marshal |
|
| 31 |
+var _ = fmt.Errorf |
|
| 32 |
+var _ = math.Inf |
|
| 33 |
+ |
|
| 34 |
+// This is a compile-time assertion to ensure that this generated file |
|
| 35 |
+// is compatible with the proto package it is being compiled against. |
|
| 36 |
+// A compilation error at this line likely means your copy of the |
|
| 37 |
+// proto package needs to be updated. |
|
| 38 |
+const _ = proto.GoGoProtoPackageIsVersion2 // please upgrade the proto package |
|
| 39 |
+ |
|
| 40 |
+type Stat struct {
|
|
| 41 |
+ Path string `protobuf:"bytes,1,opt,name=path,proto3" json:"path,omitempty"` |
|
| 42 |
+ Mode uint32 `protobuf:"varint,2,opt,name=mode,proto3" json:"mode,omitempty"` |
|
| 43 |
+ Uid uint32 `protobuf:"varint,3,opt,name=uid,proto3" json:"uid,omitempty"` |
|
| 44 |
+ Gid uint32 `protobuf:"varint,4,opt,name=gid,proto3" json:"gid,omitempty"` |
|
| 45 |
+ Size_ int64 `protobuf:"varint,5,opt,name=size,proto3" json:"size,omitempty"` |
|
| 46 |
+ ModTime int64 `protobuf:"varint,6,opt,name=modTime,proto3" json:"modTime,omitempty"` |
|
| 47 |
+ // int32 typeflag = 7; |
|
| 48 |
+ Linkname string `protobuf:"bytes,7,opt,name=linkname,proto3" json:"linkname,omitempty"` |
|
| 49 |
+ Devmajor int64 `protobuf:"varint,8,opt,name=devmajor,proto3" json:"devmajor,omitempty"` |
|
| 50 |
+ Devminor int64 `protobuf:"varint,9,opt,name=devminor,proto3" json:"devminor,omitempty"` |
|
| 51 |
+ Xattrs map[string][]byte `protobuf:"bytes,10,rep,name=xattrs" json:"xattrs,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` |
|
| 52 |
+} |
|
| 53 |
+ |
|
| 54 |
+func (m *Stat) Reset() { *m = Stat{} }
|
|
| 55 |
+func (*Stat) ProtoMessage() {}
|
|
| 56 |
+func (*Stat) Descriptor() ([]byte, []int) { return fileDescriptorStat, []int{0} }
|
|
| 57 |
+ |
|
| 58 |
+func (m *Stat) GetPath() string {
|
|
| 59 |
+ if m != nil {
|
|
| 60 |
+ return m.Path |
|
| 61 |
+ } |
|
| 62 |
+ return "" |
|
| 63 |
+} |
|
| 64 |
+ |
|
| 65 |
+func (m *Stat) GetMode() uint32 {
|
|
| 66 |
+ if m != nil {
|
|
| 67 |
+ return m.Mode |
|
| 68 |
+ } |
|
| 69 |
+ return 0 |
|
| 70 |
+} |
|
| 71 |
+ |
|
| 72 |
+func (m *Stat) GetUid() uint32 {
|
|
| 73 |
+ if m != nil {
|
|
| 74 |
+ return m.Uid |
|
| 75 |
+ } |
|
| 76 |
+ return 0 |
|
| 77 |
+} |
|
| 78 |
+ |
|
| 79 |
+func (m *Stat) GetGid() uint32 {
|
|
| 80 |
+ if m != nil {
|
|
| 81 |
+ return m.Gid |
|
| 82 |
+ } |
|
| 83 |
+ return 0 |
|
| 84 |
+} |
|
| 85 |
+ |
|
| 86 |
+func (m *Stat) GetSize_() int64 {
|
|
| 87 |
+ if m != nil {
|
|
| 88 |
+ return m.Size_ |
|
| 89 |
+ } |
|
| 90 |
+ return 0 |
|
| 91 |
+} |
|
| 92 |
+ |
|
| 93 |
+func (m *Stat) GetModTime() int64 {
|
|
| 94 |
+ if m != nil {
|
|
| 95 |
+ return m.ModTime |
|
| 96 |
+ } |
|
| 97 |
+ return 0 |
|
| 98 |
+} |
|
| 99 |
+ |
|
| 100 |
+func (m *Stat) GetLinkname() string {
|
|
| 101 |
+ if m != nil {
|
|
| 102 |
+ return m.Linkname |
|
| 103 |
+ } |
|
| 104 |
+ return "" |
|
| 105 |
+} |
|
| 106 |
+ |
|
| 107 |
+func (m *Stat) GetDevmajor() int64 {
|
|
| 108 |
+ if m != nil {
|
|
| 109 |
+ return m.Devmajor |
|
| 110 |
+ } |
|
| 111 |
+ return 0 |
|
| 112 |
+} |
|
| 113 |
+ |
|
| 114 |
+func (m *Stat) GetDevminor() int64 {
|
|
| 115 |
+ if m != nil {
|
|
| 116 |
+ return m.Devminor |
|
| 117 |
+ } |
|
| 118 |
+ return 0 |
|
| 119 |
+} |
|
| 120 |
+ |
|
| 121 |
+func (m *Stat) GetXattrs() map[string][]byte {
|
|
| 122 |
+ if m != nil {
|
|
| 123 |
+ return m.Xattrs |
|
| 124 |
+ } |
|
| 125 |
+ return nil |
|
| 126 |
+} |
|
| 127 |
+ |
|
| 128 |
+func init() {
|
|
| 129 |
+ proto.RegisterType((*Stat)(nil), "fsutil.Stat") |
|
| 130 |
+} |
|
| 131 |
+func (this *Stat) Equal(that interface{}) bool {
|
|
| 132 |
+ if that == nil {
|
|
| 133 |
+ if this == nil {
|
|
| 134 |
+ return true |
|
| 135 |
+ } |
|
| 136 |
+ return false |
|
| 137 |
+ } |
|
| 138 |
+ |
|
| 139 |
+ that1, ok := that.(*Stat) |
|
| 140 |
+ if !ok {
|
|
| 141 |
+ that2, ok := that.(Stat) |
|
| 142 |
+ if ok {
|
|
| 143 |
+ that1 = &that2 |
|
| 144 |
+ } else {
|
|
| 145 |
+ return false |
|
| 146 |
+ } |
|
| 147 |
+ } |
|
| 148 |
+ if that1 == nil {
|
|
| 149 |
+ if this == nil {
|
|
| 150 |
+ return true |
|
| 151 |
+ } |
|
| 152 |
+ return false |
|
| 153 |
+ } else if this == nil {
|
|
| 154 |
+ return false |
|
| 155 |
+ } |
|
| 156 |
+ if this.Path != that1.Path {
|
|
| 157 |
+ return false |
|
| 158 |
+ } |
|
| 159 |
+ if this.Mode != that1.Mode {
|
|
| 160 |
+ return false |
|
| 161 |
+ } |
|
| 162 |
+ if this.Uid != that1.Uid {
|
|
| 163 |
+ return false |
|
| 164 |
+ } |
|
| 165 |
+ if this.Gid != that1.Gid {
|
|
| 166 |
+ return false |
|
| 167 |
+ } |
|
| 168 |
+ if this.Size_ != that1.Size_ {
|
|
| 169 |
+ return false |
|
| 170 |
+ } |
|
| 171 |
+ if this.ModTime != that1.ModTime {
|
|
| 172 |
+ return false |
|
| 173 |
+ } |
|
| 174 |
+ if this.Linkname != that1.Linkname {
|
|
| 175 |
+ return false |
|
| 176 |
+ } |
|
| 177 |
+ if this.Devmajor != that1.Devmajor {
|
|
| 178 |
+ return false |
|
| 179 |
+ } |
|
| 180 |
+ if this.Devminor != that1.Devminor {
|
|
| 181 |
+ return false |
|
| 182 |
+ } |
|
| 183 |
+ if len(this.Xattrs) != len(that1.Xattrs) {
|
|
| 184 |
+ return false |
|
| 185 |
+ } |
|
| 186 |
+ for i := range this.Xattrs {
|
|
| 187 |
+ if !bytes.Equal(this.Xattrs[i], that1.Xattrs[i]) {
|
|
| 188 |
+ return false |
|
| 189 |
+ } |
|
| 190 |
+ } |
|
| 191 |
+ return true |
|
| 192 |
+} |
|
| 193 |
+func (this *Stat) GoString() string {
|
|
| 194 |
+ if this == nil {
|
|
| 195 |
+ return "nil" |
|
| 196 |
+ } |
|
| 197 |
+ s := make([]string, 0, 14) |
|
| 198 |
+ s = append(s, "&fsutil.Stat{")
|
|
| 199 |
+ s = append(s, "Path: "+fmt.Sprintf("%#v", this.Path)+",\n")
|
|
| 200 |
+ s = append(s, "Mode: "+fmt.Sprintf("%#v", this.Mode)+",\n")
|
|
| 201 |
+ s = append(s, "Uid: "+fmt.Sprintf("%#v", this.Uid)+",\n")
|
|
| 202 |
+ s = append(s, "Gid: "+fmt.Sprintf("%#v", this.Gid)+",\n")
|
|
| 203 |
+ s = append(s, "Size_: "+fmt.Sprintf("%#v", this.Size_)+",\n")
|
|
| 204 |
+ s = append(s, "ModTime: "+fmt.Sprintf("%#v", this.ModTime)+",\n")
|
|
| 205 |
+ s = append(s, "Linkname: "+fmt.Sprintf("%#v", this.Linkname)+",\n")
|
|
| 206 |
+ s = append(s, "Devmajor: "+fmt.Sprintf("%#v", this.Devmajor)+",\n")
|
|
| 207 |
+ s = append(s, "Devminor: "+fmt.Sprintf("%#v", this.Devminor)+",\n")
|
|
| 208 |
+ keysForXattrs := make([]string, 0, len(this.Xattrs)) |
|
| 209 |
+ for k, _ := range this.Xattrs {
|
|
| 210 |
+ keysForXattrs = append(keysForXattrs, k) |
|
| 211 |
+ } |
|
| 212 |
+ github_com_gogo_protobuf_sortkeys.Strings(keysForXattrs) |
|
| 213 |
+ mapStringForXattrs := "map[string][]byte{"
|
|
| 214 |
+ for _, k := range keysForXattrs {
|
|
| 215 |
+ mapStringForXattrs += fmt.Sprintf("%#v: %#v,", k, this.Xattrs[k])
|
|
| 216 |
+ } |
|
| 217 |
+ mapStringForXattrs += "}" |
|
| 218 |
+ if this.Xattrs != nil {
|
|
| 219 |
+ s = append(s, "Xattrs: "+mapStringForXattrs+",\n") |
|
| 220 |
+ } |
|
| 221 |
+ s = append(s, "}") |
|
| 222 |
+ return strings.Join(s, "") |
|
| 223 |
+} |
|
| 224 |
+func valueToGoStringStat(v interface{}, typ string) string {
|
|
| 225 |
+ rv := reflect.ValueOf(v) |
|
| 226 |
+ if rv.IsNil() {
|
|
| 227 |
+ return "nil" |
|
| 228 |
+ } |
|
| 229 |
+ pv := reflect.Indirect(rv).Interface() |
|
| 230 |
+ return fmt.Sprintf("func(v %v) *%v { return &v } ( %#v )", typ, typ, pv)
|
|
| 231 |
+} |
|
| 232 |
+func (m *Stat) Marshal() (dAtA []byte, err error) {
|
|
| 233 |
+ size := m.Size() |
|
| 234 |
+ dAtA = make([]byte, size) |
|
| 235 |
+ n, err := m.MarshalTo(dAtA) |
|
| 236 |
+ if err != nil {
|
|
| 237 |
+ return nil, err |
|
| 238 |
+ } |
|
| 239 |
+ return dAtA[:n], nil |
|
| 240 |
+} |
|
| 241 |
+ |
|
| 242 |
+func (m *Stat) MarshalTo(dAtA []byte) (int, error) {
|
|
| 243 |
+ var i int |
|
| 244 |
+ _ = i |
|
| 245 |
+ var l int |
|
| 246 |
+ _ = l |
|
| 247 |
+ if len(m.Path) > 0 {
|
|
| 248 |
+ dAtA[i] = 0xa |
|
| 249 |
+ i++ |
|
| 250 |
+ i = encodeVarintStat(dAtA, i, uint64(len(m.Path))) |
|
| 251 |
+ i += copy(dAtA[i:], m.Path) |
|
| 252 |
+ } |
|
| 253 |
+ if m.Mode != 0 {
|
|
| 254 |
+ dAtA[i] = 0x10 |
|
| 255 |
+ i++ |
|
| 256 |
+ i = encodeVarintStat(dAtA, i, uint64(m.Mode)) |
|
| 257 |
+ } |
|
| 258 |
+ if m.Uid != 0 {
|
|
| 259 |
+ dAtA[i] = 0x18 |
|
| 260 |
+ i++ |
|
| 261 |
+ i = encodeVarintStat(dAtA, i, uint64(m.Uid)) |
|
| 262 |
+ } |
|
| 263 |
+ if m.Gid != 0 {
|
|
| 264 |
+ dAtA[i] = 0x20 |
|
| 265 |
+ i++ |
|
| 266 |
+ i = encodeVarintStat(dAtA, i, uint64(m.Gid)) |
|
| 267 |
+ } |
|
| 268 |
+ if m.Size_ != 0 {
|
|
| 269 |
+ dAtA[i] = 0x28 |
|
| 270 |
+ i++ |
|
| 271 |
+ i = encodeVarintStat(dAtA, i, uint64(m.Size_)) |
|
| 272 |
+ } |
|
| 273 |
+ if m.ModTime != 0 {
|
|
| 274 |
+ dAtA[i] = 0x30 |
|
| 275 |
+ i++ |
|
| 276 |
+ i = encodeVarintStat(dAtA, i, uint64(m.ModTime)) |
|
| 277 |
+ } |
|
| 278 |
+ if len(m.Linkname) > 0 {
|
|
| 279 |
+ dAtA[i] = 0x3a |
|
| 280 |
+ i++ |
|
| 281 |
+ i = encodeVarintStat(dAtA, i, uint64(len(m.Linkname))) |
|
| 282 |
+ i += copy(dAtA[i:], m.Linkname) |
|
| 283 |
+ } |
|
| 284 |
+ if m.Devmajor != 0 {
|
|
| 285 |
+ dAtA[i] = 0x40 |
|
| 286 |
+ i++ |
|
| 287 |
+ i = encodeVarintStat(dAtA, i, uint64(m.Devmajor)) |
|
| 288 |
+ } |
|
| 289 |
+ if m.Devminor != 0 {
|
|
| 290 |
+ dAtA[i] = 0x48 |
|
| 291 |
+ i++ |
|
| 292 |
+ i = encodeVarintStat(dAtA, i, uint64(m.Devminor)) |
|
| 293 |
+ } |
|
| 294 |
+ if len(m.Xattrs) > 0 {
|
|
| 295 |
+ for k, _ := range m.Xattrs {
|
|
| 296 |
+ dAtA[i] = 0x52 |
|
| 297 |
+ i++ |
|
| 298 |
+ v := m.Xattrs[k] |
|
| 299 |
+ byteSize := 0 |
|
| 300 |
+ if len(v) > 0 {
|
|
| 301 |
+ byteSize = 1 + len(v) + sovStat(uint64(len(v))) |
|
| 302 |
+ } |
|
| 303 |
+ mapSize := 1 + len(k) + sovStat(uint64(len(k))) + byteSize |
|
| 304 |
+ i = encodeVarintStat(dAtA, i, uint64(mapSize)) |
|
| 305 |
+ dAtA[i] = 0xa |
|
| 306 |
+ i++ |
|
| 307 |
+ i = encodeVarintStat(dAtA, i, uint64(len(k))) |
|
| 308 |
+ i += copy(dAtA[i:], k) |
|
| 309 |
+ if len(v) > 0 {
|
|
| 310 |
+ dAtA[i] = 0x12 |
|
| 311 |
+ i++ |
|
| 312 |
+ i = encodeVarintStat(dAtA, i, uint64(len(v))) |
|
| 313 |
+ i += copy(dAtA[i:], v) |
|
| 314 |
+ } |
|
| 315 |
+ } |
|
| 316 |
+ } |
|
| 317 |
+ return i, nil |
|
| 318 |
+} |
|
| 319 |
+ |
|
| 320 |
+func encodeFixed64Stat(dAtA []byte, offset int, v uint64) int {
|
|
| 321 |
+ dAtA[offset] = uint8(v) |
|
| 322 |
+ dAtA[offset+1] = uint8(v >> 8) |
|
| 323 |
+ dAtA[offset+2] = uint8(v >> 16) |
|
| 324 |
+ dAtA[offset+3] = uint8(v >> 24) |
|
| 325 |
+ dAtA[offset+4] = uint8(v >> 32) |
|
| 326 |
+ dAtA[offset+5] = uint8(v >> 40) |
|
| 327 |
+ dAtA[offset+6] = uint8(v >> 48) |
|
| 328 |
+ dAtA[offset+7] = uint8(v >> 56) |
|
| 329 |
+ return offset + 8 |
|
| 330 |
+} |
|
| 331 |
+func encodeFixed32Stat(dAtA []byte, offset int, v uint32) int {
|
|
| 332 |
+ dAtA[offset] = uint8(v) |
|
| 333 |
+ dAtA[offset+1] = uint8(v >> 8) |
|
| 334 |
+ dAtA[offset+2] = uint8(v >> 16) |
|
| 335 |
+ dAtA[offset+3] = uint8(v >> 24) |
|
| 336 |
+ return offset + 4 |
|
| 337 |
+} |
|
| 338 |
+func encodeVarintStat(dAtA []byte, offset int, v uint64) int {
|
|
| 339 |
+ for v >= 1<<7 {
|
|
| 340 |
+ dAtA[offset] = uint8(v&0x7f | 0x80) |
|
| 341 |
+ v >>= 7 |
|
| 342 |
+ offset++ |
|
| 343 |
+ } |
|
| 344 |
+ dAtA[offset] = uint8(v) |
|
| 345 |
+ return offset + 1 |
|
| 346 |
+} |
|
| 347 |
+func (m *Stat) Size() (n int) {
|
|
| 348 |
+ var l int |
|
| 349 |
+ _ = l |
|
| 350 |
+ l = len(m.Path) |
|
| 351 |
+ if l > 0 {
|
|
| 352 |
+ n += 1 + l + sovStat(uint64(l)) |
|
| 353 |
+ } |
|
| 354 |
+ if m.Mode != 0 {
|
|
| 355 |
+ n += 1 + sovStat(uint64(m.Mode)) |
|
| 356 |
+ } |
|
| 357 |
+ if m.Uid != 0 {
|
|
| 358 |
+ n += 1 + sovStat(uint64(m.Uid)) |
|
| 359 |
+ } |
|
| 360 |
+ if m.Gid != 0 {
|
|
| 361 |
+ n += 1 + sovStat(uint64(m.Gid)) |
|
| 362 |
+ } |
|
| 363 |
+ if m.Size_ != 0 {
|
|
| 364 |
+ n += 1 + sovStat(uint64(m.Size_)) |
|
| 365 |
+ } |
|
| 366 |
+ if m.ModTime != 0 {
|
|
| 367 |
+ n += 1 + sovStat(uint64(m.ModTime)) |
|
| 368 |
+ } |
|
| 369 |
+ l = len(m.Linkname) |
|
| 370 |
+ if l > 0 {
|
|
| 371 |
+ n += 1 + l + sovStat(uint64(l)) |
|
| 372 |
+ } |
|
| 373 |
+ if m.Devmajor != 0 {
|
|
| 374 |
+ n += 1 + sovStat(uint64(m.Devmajor)) |
|
| 375 |
+ } |
|
| 376 |
+ if m.Devminor != 0 {
|
|
| 377 |
+ n += 1 + sovStat(uint64(m.Devminor)) |
|
| 378 |
+ } |
|
| 379 |
+ if len(m.Xattrs) > 0 {
|
|
| 380 |
+ for k, v := range m.Xattrs {
|
|
| 381 |
+ _ = k |
|
| 382 |
+ _ = v |
|
| 383 |
+ l = 0 |
|
| 384 |
+ if len(v) > 0 {
|
|
| 385 |
+ l = 1 + len(v) + sovStat(uint64(len(v))) |
|
| 386 |
+ } |
|
| 387 |
+ mapEntrySize := 1 + len(k) + sovStat(uint64(len(k))) + l |
|
| 388 |
+ n += mapEntrySize + 1 + sovStat(uint64(mapEntrySize)) |
|
| 389 |
+ } |
|
| 390 |
+ } |
|
| 391 |
+ return n |
|
| 392 |
+} |
|
| 393 |
+ |
|
| 394 |
+func sovStat(x uint64) (n int) {
|
|
| 395 |
+ for {
|
|
| 396 |
+ n++ |
|
| 397 |
+ x >>= 7 |
|
| 398 |
+ if x == 0 {
|
|
| 399 |
+ break |
|
| 400 |
+ } |
|
| 401 |
+ } |
|
| 402 |
+ return n |
|
| 403 |
+} |
|
| 404 |
+func sozStat(x uint64) (n int) {
|
|
| 405 |
+ return sovStat(uint64((x << 1) ^ uint64((int64(x) >> 63)))) |
|
| 406 |
+} |
|
| 407 |
+func (this *Stat) String() string {
|
|
| 408 |
+ if this == nil {
|
|
| 409 |
+ return "nil" |
|
| 410 |
+ } |
|
| 411 |
+ keysForXattrs := make([]string, 0, len(this.Xattrs)) |
|
| 412 |
+ for k, _ := range this.Xattrs {
|
|
| 413 |
+ keysForXattrs = append(keysForXattrs, k) |
|
| 414 |
+ } |
|
| 415 |
+ github_com_gogo_protobuf_sortkeys.Strings(keysForXattrs) |
|
| 416 |
+ mapStringForXattrs := "map[string][]byte{"
|
|
| 417 |
+ for _, k := range keysForXattrs {
|
|
| 418 |
+ mapStringForXattrs += fmt.Sprintf("%v: %v,", k, this.Xattrs[k])
|
|
| 419 |
+ } |
|
| 420 |
+ mapStringForXattrs += "}" |
|
| 421 |
+ s := strings.Join([]string{`&Stat{`,
|
|
| 422 |
+ `Path:` + fmt.Sprintf("%v", this.Path) + `,`,
|
|
| 423 |
+ `Mode:` + fmt.Sprintf("%v", this.Mode) + `,`,
|
|
| 424 |
+ `Uid:` + fmt.Sprintf("%v", this.Uid) + `,`,
|
|
| 425 |
+ `Gid:` + fmt.Sprintf("%v", this.Gid) + `,`,
|
|
| 426 |
+ `Size_:` + fmt.Sprintf("%v", this.Size_) + `,`,
|
|
| 427 |
+ `ModTime:` + fmt.Sprintf("%v", this.ModTime) + `,`,
|
|
| 428 |
+ `Linkname:` + fmt.Sprintf("%v", this.Linkname) + `,`,
|
|
| 429 |
+ `Devmajor:` + fmt.Sprintf("%v", this.Devmajor) + `,`,
|
|
| 430 |
+ `Devminor:` + fmt.Sprintf("%v", this.Devminor) + `,`,
|
|
| 431 |
+ `Xattrs:` + mapStringForXattrs + `,`, |
|
| 432 |
+ `}`, |
|
| 433 |
+ }, "") |
|
| 434 |
+ return s |
|
| 435 |
+} |
|
| 436 |
+func valueToStringStat(v interface{}) string {
|
|
| 437 |
+ rv := reflect.ValueOf(v) |
|
| 438 |
+ if rv.IsNil() {
|
|
| 439 |
+ return "nil" |
|
| 440 |
+ } |
|
| 441 |
+ pv := reflect.Indirect(rv).Interface() |
|
| 442 |
+ return fmt.Sprintf("*%v", pv)
|
|
| 443 |
+} |
|
| 444 |
+func (m *Stat) Unmarshal(dAtA []byte) error {
|
|
| 445 |
+ l := len(dAtA) |
|
| 446 |
+ iNdEx := 0 |
|
| 447 |
+ for iNdEx < l {
|
|
| 448 |
+ preIndex := iNdEx |
|
| 449 |
+ var wire uint64 |
|
| 450 |
+ for shift := uint(0); ; shift += 7 {
|
|
| 451 |
+ if shift >= 64 {
|
|
| 452 |
+ return ErrIntOverflowStat |
|
| 453 |
+ } |
|
| 454 |
+ if iNdEx >= l {
|
|
| 455 |
+ return io.ErrUnexpectedEOF |
|
| 456 |
+ } |
|
| 457 |
+ b := dAtA[iNdEx] |
|
| 458 |
+ iNdEx++ |
|
| 459 |
+ wire |= (uint64(b) & 0x7F) << shift |
|
| 460 |
+ if b < 0x80 {
|
|
| 461 |
+ break |
|
| 462 |
+ } |
|
| 463 |
+ } |
|
| 464 |
+ fieldNum := int32(wire >> 3) |
|
| 465 |
+ wireType := int(wire & 0x7) |
|
| 466 |
+ if wireType == 4 {
|
|
| 467 |
+ return fmt.Errorf("proto: Stat: wiretype end group for non-group")
|
|
| 468 |
+ } |
|
| 469 |
+ if fieldNum <= 0 {
|
|
| 470 |
+ return fmt.Errorf("proto: Stat: illegal tag %d (wire type %d)", fieldNum, wire)
|
|
| 471 |
+ } |
|
| 472 |
+ switch fieldNum {
|
|
| 473 |
+ case 1: |
|
| 474 |
+ if wireType != 2 {
|
|
| 475 |
+ return fmt.Errorf("proto: wrong wireType = %d for field Path", wireType)
|
|
| 476 |
+ } |
|
| 477 |
+ var stringLen uint64 |
|
| 478 |
+ for shift := uint(0); ; shift += 7 {
|
|
| 479 |
+ if shift >= 64 {
|
|
| 480 |
+ return ErrIntOverflowStat |
|
| 481 |
+ } |
|
| 482 |
+ if iNdEx >= l {
|
|
| 483 |
+ return io.ErrUnexpectedEOF |
|
| 484 |
+ } |
|
| 485 |
+ b := dAtA[iNdEx] |
|
| 486 |
+ iNdEx++ |
|
| 487 |
+ stringLen |= (uint64(b) & 0x7F) << shift |
|
| 488 |
+ if b < 0x80 {
|
|
| 489 |
+ break |
|
| 490 |
+ } |
|
| 491 |
+ } |
|
| 492 |
+ intStringLen := int(stringLen) |
|
| 493 |
+ if intStringLen < 0 {
|
|
| 494 |
+ return ErrInvalidLengthStat |
|
| 495 |
+ } |
|
| 496 |
+ postIndex := iNdEx + intStringLen |
|
| 497 |
+ if postIndex > l {
|
|
| 498 |
+ return io.ErrUnexpectedEOF |
|
| 499 |
+ } |
|
| 500 |
+ m.Path = string(dAtA[iNdEx:postIndex]) |
|
| 501 |
+ iNdEx = postIndex |
|
| 502 |
+ case 2: |
|
| 503 |
+ if wireType != 0 {
|
|
| 504 |
+ return fmt.Errorf("proto: wrong wireType = %d for field Mode", wireType)
|
|
| 505 |
+ } |
|
| 506 |
+ m.Mode = 0 |
|
| 507 |
+ for shift := uint(0); ; shift += 7 {
|
|
| 508 |
+ if shift >= 64 {
|
|
| 509 |
+ return ErrIntOverflowStat |
|
| 510 |
+ } |
|
| 511 |
+ if iNdEx >= l {
|
|
| 512 |
+ return io.ErrUnexpectedEOF |
|
| 513 |
+ } |
|
| 514 |
+ b := dAtA[iNdEx] |
|
| 515 |
+ iNdEx++ |
|
| 516 |
+ m.Mode |= (uint32(b) & 0x7F) << shift |
|
| 517 |
+ if b < 0x80 {
|
|
| 518 |
+ break |
|
| 519 |
+ } |
|
| 520 |
+ } |
|
| 521 |
+ case 3: |
|
| 522 |
+ if wireType != 0 {
|
|
| 523 |
+ return fmt.Errorf("proto: wrong wireType = %d for field Uid", wireType)
|
|
| 524 |
+ } |
|
| 525 |
+ m.Uid = 0 |
|
| 526 |
+ for shift := uint(0); ; shift += 7 {
|
|
| 527 |
+ if shift >= 64 {
|
|
| 528 |
+ return ErrIntOverflowStat |
|
| 529 |
+ } |
|
| 530 |
+ if iNdEx >= l {
|
|
| 531 |
+ return io.ErrUnexpectedEOF |
|
| 532 |
+ } |
|
| 533 |
+ b := dAtA[iNdEx] |
|
| 534 |
+ iNdEx++ |
|
| 535 |
+ m.Uid |= (uint32(b) & 0x7F) << shift |
|
| 536 |
+ if b < 0x80 {
|
|
| 537 |
+ break |
|
| 538 |
+ } |
|
| 539 |
+ } |
|
| 540 |
+ case 4: |
|
| 541 |
+ if wireType != 0 {
|
|
| 542 |
+ return fmt.Errorf("proto: wrong wireType = %d for field Gid", wireType)
|
|
| 543 |
+ } |
|
| 544 |
+ m.Gid = 0 |
|
| 545 |
+ for shift := uint(0); ; shift += 7 {
|
|
| 546 |
+ if shift >= 64 {
|
|
| 547 |
+ return ErrIntOverflowStat |
|
| 548 |
+ } |
|
| 549 |
+ if iNdEx >= l {
|
|
| 550 |
+ return io.ErrUnexpectedEOF |
|
| 551 |
+ } |
|
| 552 |
+ b := dAtA[iNdEx] |
|
| 553 |
+ iNdEx++ |
|
| 554 |
+ m.Gid |= (uint32(b) & 0x7F) << shift |
|
| 555 |
+ if b < 0x80 {
|
|
| 556 |
+ break |
|
| 557 |
+ } |
|
| 558 |
+ } |
|
| 559 |
+ case 5: |
|
| 560 |
+ if wireType != 0 {
|
|
| 561 |
+ return fmt.Errorf("proto: wrong wireType = %d for field Size_", wireType)
|
|
| 562 |
+ } |
|
| 563 |
+ m.Size_ = 0 |
|
| 564 |
+ for shift := uint(0); ; shift += 7 {
|
|
| 565 |
+ if shift >= 64 {
|
|
| 566 |
+ return ErrIntOverflowStat |
|
| 567 |
+ } |
|
| 568 |
+ if iNdEx >= l {
|
|
| 569 |
+ return io.ErrUnexpectedEOF |
|
| 570 |
+ } |
|
| 571 |
+ b := dAtA[iNdEx] |
|
| 572 |
+ iNdEx++ |
|
| 573 |
+ m.Size_ |= (int64(b) & 0x7F) << shift |
|
| 574 |
+ if b < 0x80 {
|
|
| 575 |
+ break |
|
| 576 |
+ } |
|
| 577 |
+ } |
|
| 578 |
+ case 6: |
|
| 579 |
+ if wireType != 0 {
|
|
| 580 |
+ return fmt.Errorf("proto: wrong wireType = %d for field ModTime", wireType)
|
|
| 581 |
+ } |
|
| 582 |
+ m.ModTime = 0 |
|
| 583 |
+ for shift := uint(0); ; shift += 7 {
|
|
| 584 |
+ if shift >= 64 {
|
|
| 585 |
+ return ErrIntOverflowStat |
|
| 586 |
+ } |
|
| 587 |
+ if iNdEx >= l {
|
|
| 588 |
+ return io.ErrUnexpectedEOF |
|
| 589 |
+ } |
|
| 590 |
+ b := dAtA[iNdEx] |
|
| 591 |
+ iNdEx++ |
|
| 592 |
+ m.ModTime |= (int64(b) & 0x7F) << shift |
|
| 593 |
+ if b < 0x80 {
|
|
| 594 |
+ break |
|
| 595 |
+ } |
|
| 596 |
+ } |
|
| 597 |
+ case 7: |
|
| 598 |
+ if wireType != 2 {
|
|
| 599 |
+ return fmt.Errorf("proto: wrong wireType = %d for field Linkname", wireType)
|
|
| 600 |
+ } |
|
| 601 |
+ var stringLen uint64 |
|
| 602 |
+ for shift := uint(0); ; shift += 7 {
|
|
| 603 |
+ if shift >= 64 {
|
|
| 604 |
+ return ErrIntOverflowStat |
|
| 605 |
+ } |
|
| 606 |
+ if iNdEx >= l {
|
|
| 607 |
+ return io.ErrUnexpectedEOF |
|
| 608 |
+ } |
|
| 609 |
+ b := dAtA[iNdEx] |
|
| 610 |
+ iNdEx++ |
|
| 611 |
+ stringLen |= (uint64(b) & 0x7F) << shift |
|
| 612 |
+ if b < 0x80 {
|
|
| 613 |
+ break |
|
| 614 |
+ } |
|
| 615 |
+ } |
|
| 616 |
+ intStringLen := int(stringLen) |
|
| 617 |
+ if intStringLen < 0 {
|
|
| 618 |
+ return ErrInvalidLengthStat |
|
| 619 |
+ } |
|
| 620 |
+ postIndex := iNdEx + intStringLen |
|
| 621 |
+ if postIndex > l {
|
|
| 622 |
+ return io.ErrUnexpectedEOF |
|
| 623 |
+ } |
|
| 624 |
+ m.Linkname = string(dAtA[iNdEx:postIndex]) |
|
| 625 |
+ iNdEx = postIndex |
|
| 626 |
+ case 8: |
|
| 627 |
+ if wireType != 0 {
|
|
| 628 |
+ return fmt.Errorf("proto: wrong wireType = %d for field Devmajor", wireType)
|
|
| 629 |
+ } |
|
| 630 |
+ m.Devmajor = 0 |
|
| 631 |
+ for shift := uint(0); ; shift += 7 {
|
|
| 632 |
+ if shift >= 64 {
|
|
| 633 |
+ return ErrIntOverflowStat |
|
| 634 |
+ } |
|
| 635 |
+ if iNdEx >= l {
|
|
| 636 |
+ return io.ErrUnexpectedEOF |
|
| 637 |
+ } |
|
| 638 |
+ b := dAtA[iNdEx] |
|
| 639 |
+ iNdEx++ |
|
| 640 |
+ m.Devmajor |= (int64(b) & 0x7F) << shift |
|
| 641 |
+ if b < 0x80 {
|
|
| 642 |
+ break |
|
| 643 |
+ } |
|
| 644 |
+ } |
|
| 645 |
+ case 9: |
|
| 646 |
+ if wireType != 0 {
|
|
| 647 |
+ return fmt.Errorf("proto: wrong wireType = %d for field Devminor", wireType)
|
|
| 648 |
+ } |
|
| 649 |
+ m.Devminor = 0 |
|
| 650 |
+ for shift := uint(0); ; shift += 7 {
|
|
| 651 |
+ if shift >= 64 {
|
|
| 652 |
+ return ErrIntOverflowStat |
|
| 653 |
+ } |
|
| 654 |
+ if iNdEx >= l {
|
|
| 655 |
+ return io.ErrUnexpectedEOF |
|
| 656 |
+ } |
|
| 657 |
+ b := dAtA[iNdEx] |
|
| 658 |
+ iNdEx++ |
|
| 659 |
+ m.Devminor |= (int64(b) & 0x7F) << shift |
|
| 660 |
+ if b < 0x80 {
|
|
| 661 |
+ break |
|
| 662 |
+ } |
|
| 663 |
+ } |
|
| 664 |
+ case 10: |
|
| 665 |
+ if wireType != 2 {
|
|
| 666 |
+ return fmt.Errorf("proto: wrong wireType = %d for field Xattrs", wireType)
|
|
| 667 |
+ } |
|
| 668 |
+ var msglen int |
|
| 669 |
+ for shift := uint(0); ; shift += 7 {
|
|
| 670 |
+ if shift >= 64 {
|
|
| 671 |
+ return ErrIntOverflowStat |
|
| 672 |
+ } |
|
| 673 |
+ if iNdEx >= l {
|
|
| 674 |
+ return io.ErrUnexpectedEOF |
|
| 675 |
+ } |
|
| 676 |
+ b := dAtA[iNdEx] |
|
| 677 |
+ iNdEx++ |
|
| 678 |
+ msglen |= (int(b) & 0x7F) << shift |
|
| 679 |
+ if b < 0x80 {
|
|
| 680 |
+ break |
|
| 681 |
+ } |
|
| 682 |
+ } |
|
| 683 |
+ if msglen < 0 {
|
|
| 684 |
+ return ErrInvalidLengthStat |
|
| 685 |
+ } |
|
| 686 |
+ postIndex := iNdEx + msglen |
|
| 687 |
+ if postIndex > l {
|
|
| 688 |
+ return io.ErrUnexpectedEOF |
|
| 689 |
+ } |
|
| 690 |
+ var keykey uint64 |
|
| 691 |
+ for shift := uint(0); ; shift += 7 {
|
|
| 692 |
+ if shift >= 64 {
|
|
| 693 |
+ return ErrIntOverflowStat |
|
| 694 |
+ } |
|
| 695 |
+ if iNdEx >= l {
|
|
| 696 |
+ return io.ErrUnexpectedEOF |
|
| 697 |
+ } |
|
| 698 |
+ b := dAtA[iNdEx] |
|
| 699 |
+ iNdEx++ |
|
| 700 |
+ keykey |= (uint64(b) & 0x7F) << shift |
|
| 701 |
+ if b < 0x80 {
|
|
| 702 |
+ break |
|
| 703 |
+ } |
|
| 704 |
+ } |
|
| 705 |
+ var stringLenmapkey uint64 |
|
| 706 |
+ for shift := uint(0); ; shift += 7 {
|
|
| 707 |
+ if shift >= 64 {
|
|
| 708 |
+ return ErrIntOverflowStat |
|
| 709 |
+ } |
|
| 710 |
+ if iNdEx >= l {
|
|
| 711 |
+ return io.ErrUnexpectedEOF |
|
| 712 |
+ } |
|
| 713 |
+ b := dAtA[iNdEx] |
|
| 714 |
+ iNdEx++ |
|
| 715 |
+ stringLenmapkey |= (uint64(b) & 0x7F) << shift |
|
| 716 |
+ if b < 0x80 {
|
|
| 717 |
+ break |
|
| 718 |
+ } |
|
| 719 |
+ } |
|
| 720 |
+ intStringLenmapkey := int(stringLenmapkey) |
|
| 721 |
+ if intStringLenmapkey < 0 {
|
|
| 722 |
+ return ErrInvalidLengthStat |
|
| 723 |
+ } |
|
| 724 |
+ postStringIndexmapkey := iNdEx + intStringLenmapkey |
|
| 725 |
+ if postStringIndexmapkey > l {
|
|
| 726 |
+ return io.ErrUnexpectedEOF |
|
| 727 |
+ } |
|
| 728 |
+ mapkey := string(dAtA[iNdEx:postStringIndexmapkey]) |
|
| 729 |
+ iNdEx = postStringIndexmapkey |
|
| 730 |
+ if m.Xattrs == nil {
|
|
| 731 |
+ m.Xattrs = make(map[string][]byte) |
|
| 732 |
+ } |
|
| 733 |
+ if iNdEx < postIndex {
|
|
| 734 |
+ var valuekey uint64 |
|
| 735 |
+ for shift := uint(0); ; shift += 7 {
|
|
| 736 |
+ if shift >= 64 {
|
|
| 737 |
+ return ErrIntOverflowStat |
|
| 738 |
+ } |
|
| 739 |
+ if iNdEx >= l {
|
|
| 740 |
+ return io.ErrUnexpectedEOF |
|
| 741 |
+ } |
|
| 742 |
+ b := dAtA[iNdEx] |
|
| 743 |
+ iNdEx++ |
|
| 744 |
+ valuekey |= (uint64(b) & 0x7F) << shift |
|
| 745 |
+ if b < 0x80 {
|
|
| 746 |
+ break |
|
| 747 |
+ } |
|
| 748 |
+ } |
|
| 749 |
+ var mapbyteLen uint64 |
|
| 750 |
+ for shift := uint(0); ; shift += 7 {
|
|
| 751 |
+ if shift >= 64 {
|
|
| 752 |
+ return ErrIntOverflowStat |
|
| 753 |
+ } |
|
| 754 |
+ if iNdEx >= l {
|
|
| 755 |
+ return io.ErrUnexpectedEOF |
|
| 756 |
+ } |
|
| 757 |
+ b := dAtA[iNdEx] |
|
| 758 |
+ iNdEx++ |
|
| 759 |
+ mapbyteLen |= (uint64(b) & 0x7F) << shift |
|
| 760 |
+ if b < 0x80 {
|
|
| 761 |
+ break |
|
| 762 |
+ } |
|
| 763 |
+ } |
|
| 764 |
+ intMapbyteLen := int(mapbyteLen) |
|
| 765 |
+ if intMapbyteLen < 0 {
|
|
| 766 |
+ return ErrInvalidLengthStat |
|
| 767 |
+ } |
|
| 768 |
+ postbytesIndex := iNdEx + intMapbyteLen |
|
| 769 |
+ if postbytesIndex > l {
|
|
| 770 |
+ return io.ErrUnexpectedEOF |
|
| 771 |
+ } |
|
| 772 |
+ mapvalue := make([]byte, mapbyteLen) |
|
| 773 |
+ copy(mapvalue, dAtA[iNdEx:postbytesIndex]) |
|
| 774 |
+ iNdEx = postbytesIndex |
|
| 775 |
+ m.Xattrs[mapkey] = mapvalue |
|
| 776 |
+ } else {
|
|
| 777 |
+ var mapvalue []byte |
|
| 778 |
+ m.Xattrs[mapkey] = mapvalue |
|
| 779 |
+ } |
|
| 780 |
+ iNdEx = postIndex |
|
| 781 |
+ default: |
|
| 782 |
+ iNdEx = preIndex |
|
| 783 |
+ skippy, err := skipStat(dAtA[iNdEx:]) |
|
| 784 |
+ if err != nil {
|
|
| 785 |
+ return err |
|
| 786 |
+ } |
|
| 787 |
+ if skippy < 0 {
|
|
| 788 |
+ return ErrInvalidLengthStat |
|
| 789 |
+ } |
|
| 790 |
+ if (iNdEx + skippy) > l {
|
|
| 791 |
+ return io.ErrUnexpectedEOF |
|
| 792 |
+ } |
|
| 793 |
+ iNdEx += skippy |
|
| 794 |
+ } |
|
| 795 |
+ } |
|
| 796 |
+ |
|
| 797 |
+ if iNdEx > l {
|
|
| 798 |
+ return io.ErrUnexpectedEOF |
|
| 799 |
+ } |
|
| 800 |
+ return nil |
|
| 801 |
+} |
|
| 802 |
+func skipStat(dAtA []byte) (n int, err error) {
|
|
| 803 |
+ l := len(dAtA) |
|
| 804 |
+ iNdEx := 0 |
|
| 805 |
+ for iNdEx < l {
|
|
| 806 |
+ var wire uint64 |
|
| 807 |
+ for shift := uint(0); ; shift += 7 {
|
|
| 808 |
+ if shift >= 64 {
|
|
| 809 |
+ return 0, ErrIntOverflowStat |
|
| 810 |
+ } |
|
| 811 |
+ if iNdEx >= l {
|
|
| 812 |
+ return 0, io.ErrUnexpectedEOF |
|
| 813 |
+ } |
|
| 814 |
+ b := dAtA[iNdEx] |
|
| 815 |
+ iNdEx++ |
|
| 816 |
+ wire |= (uint64(b) & 0x7F) << shift |
|
| 817 |
+ if b < 0x80 {
|
|
| 818 |
+ break |
|
| 819 |
+ } |
|
| 820 |
+ } |
|
| 821 |
+ wireType := int(wire & 0x7) |
|
| 822 |
+ switch wireType {
|
|
| 823 |
+ case 0: |
|
| 824 |
+ for shift := uint(0); ; shift += 7 {
|
|
| 825 |
+ if shift >= 64 {
|
|
| 826 |
+ return 0, ErrIntOverflowStat |
|
| 827 |
+ } |
|
| 828 |
+ if iNdEx >= l {
|
|
| 829 |
+ return 0, io.ErrUnexpectedEOF |
|
| 830 |
+ } |
|
| 831 |
+ iNdEx++ |
|
| 832 |
+ if dAtA[iNdEx-1] < 0x80 {
|
|
| 833 |
+ break |
|
| 834 |
+ } |
|
| 835 |
+ } |
|
| 836 |
+ return iNdEx, nil |
|
| 837 |
+ case 1: |
|
| 838 |
+ iNdEx += 8 |
|
| 839 |
+ return iNdEx, nil |
|
| 840 |
+ case 2: |
|
| 841 |
+ var length int |
|
| 842 |
+ for shift := uint(0); ; shift += 7 {
|
|
| 843 |
+ if shift >= 64 {
|
|
| 844 |
+ return 0, ErrIntOverflowStat |
|
| 845 |
+ } |
|
| 846 |
+ if iNdEx >= l {
|
|
| 847 |
+ return 0, io.ErrUnexpectedEOF |
|
| 848 |
+ } |
|
| 849 |
+ b := dAtA[iNdEx] |
|
| 850 |
+ iNdEx++ |
|
| 851 |
+ length |= (int(b) & 0x7F) << shift |
|
| 852 |
+ if b < 0x80 {
|
|
| 853 |
+ break |
|
| 854 |
+ } |
|
| 855 |
+ } |
|
| 856 |
+ iNdEx += length |
|
| 857 |
+ if length < 0 {
|
|
| 858 |
+ return 0, ErrInvalidLengthStat |
|
| 859 |
+ } |
|
| 860 |
+ return iNdEx, nil |
|
| 861 |
+ case 3: |
|
| 862 |
+ for {
|
|
| 863 |
+ var innerWire uint64 |
|
| 864 |
+ var start int = iNdEx |
|
| 865 |
+ for shift := uint(0); ; shift += 7 {
|
|
| 866 |
+ if shift >= 64 {
|
|
| 867 |
+ return 0, ErrIntOverflowStat |
|
| 868 |
+ } |
|
| 869 |
+ if iNdEx >= l {
|
|
| 870 |
+ return 0, io.ErrUnexpectedEOF |
|
| 871 |
+ } |
|
| 872 |
+ b := dAtA[iNdEx] |
|
| 873 |
+ iNdEx++ |
|
| 874 |
+ innerWire |= (uint64(b) & 0x7F) << shift |
|
| 875 |
+ if b < 0x80 {
|
|
| 876 |
+ break |
|
| 877 |
+ } |
|
| 878 |
+ } |
|
| 879 |
+ innerWireType := int(innerWire & 0x7) |
|
| 880 |
+ if innerWireType == 4 {
|
|
| 881 |
+ break |
|
| 882 |
+ } |
|
| 883 |
+ next, err := skipStat(dAtA[start:]) |
|
| 884 |
+ if err != nil {
|
|
| 885 |
+ return 0, err |
|
| 886 |
+ } |
|
| 887 |
+ iNdEx = start + next |
|
| 888 |
+ } |
|
| 889 |
+ return iNdEx, nil |
|
| 890 |
+ case 4: |
|
| 891 |
+ return iNdEx, nil |
|
| 892 |
+ case 5: |
|
| 893 |
+ iNdEx += 4 |
|
| 894 |
+ return iNdEx, nil |
|
| 895 |
+ default: |
|
| 896 |
+ return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
|
|
| 897 |
+ } |
|
| 898 |
+ } |
|
| 899 |
+ panic("unreachable")
|
|
| 900 |
+} |
|
| 901 |
+ |
|
| 902 |
+var ( |
|
| 903 |
+ ErrInvalidLengthStat = fmt.Errorf("proto: negative length found during unmarshaling")
|
|
| 904 |
+ ErrIntOverflowStat = fmt.Errorf("proto: integer overflow")
|
|
| 905 |
+) |
|
| 906 |
+ |
|
| 907 |
+func init() { proto.RegisterFile("stat.proto", fileDescriptorStat) }
|
|
| 908 |
+ |
|
| 909 |
+var fileDescriptorStat = []byte{
|
|
| 910 |
+ // 303 bytes of a gzipped FileDescriptorProto |
|
| 911 |
+ 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x4c, 0x91, 0xb1, 0x4e, 0xf3, 0x30, |
|
| 912 |
+ 0x14, 0x85, 0x73, 0x9b, 0x36, 0x6d, 0xdd, 0xff, 0x97, 0x90, 0xc5, 0x70, 0xd5, 0xc1, 0x8a, 0x98, |
|
| 913 |
+ 0x32, 0xa0, 0x08, 0xc1, 0x02, 0x8c, 0x48, 0xbc, 0x40, 0x60, 0x60, 0x35, 0xb2, 0x29, 0xa6, 0x4d, |
|
| 914 |
+ 0x5c, 0x25, 0x4e, 0x45, 0x99, 0x78, 0x04, 0x1e, 0x83, 0xd7, 0x60, 0x63, 0xec, 0xc8, 0x48, 0xcc, |
|
| 915 |
+ 0xc2, 0xd8, 0x47, 0x40, 0x76, 0xda, 0xc2, 0x76, 0xce, 0x77, 0x7c, 0x65, 0x9d, 0x7b, 0x09, 0xa9, |
|
| 916 |
+ 0x0c, 0x37, 0xe9, 0xbc, 0xd4, 0x46, 0xd3, 0xe8, 0xae, 0xaa, 0x8d, 0x9a, 0x1d, 0xbc, 0x75, 0x48, |
|
| 917 |
+ 0xf7, 0xca, 0x70, 0x43, 0x29, 0xe9, 0xce, 0xb9, 0xb9, 0x47, 0x88, 0x21, 0x19, 0x66, 0x5e, 0x3b, |
|
| 918 |
+ 0x96, 0x6b, 0x21, 0xb1, 0x13, 0x43, 0xf2, 0x3f, 0xf3, 0x9a, 0xee, 0x91, 0xb0, 0x56, 0x02, 0x43, |
|
| 919 |
+ 0x8f, 0x9c, 0x74, 0x64, 0xa2, 0x04, 0x76, 0x5b, 0x32, 0x51, 0xc2, 0xcd, 0x55, 0xea, 0x49, 0x62, |
|
| 920 |
+ 0x2f, 0x86, 0x24, 0xcc, 0xbc, 0xa6, 0x48, 0xfa, 0xb9, 0x16, 0xd7, 0x2a, 0x97, 0x18, 0x79, 0xbc, |
|
| 921 |
+ 0xb5, 0x74, 0x4c, 0x06, 0x33, 0x55, 0x4c, 0x0b, 0x9e, 0x4b, 0xec, 0xfb, 0xdf, 0x77, 0xde, 0x65, |
|
| 922 |
+ 0x42, 0x2e, 0x72, 0xfe, 0xa0, 0x4b, 0x1c, 0xf8, 0xb1, 0x9d, 0xdf, 0x66, 0xaa, 0xd0, 0x25, 0x0e, |
|
| 923 |
+ 0x7f, 0x33, 0xe7, 0xe9, 0x11, 0x89, 0x1e, 0xb9, 0x31, 0x65, 0x85, 0x24, 0x0e, 0x93, 0xd1, 0x31, |
|
| 924 |
+ 0xa6, 0x6d, 0xdf, 0xd4, 0x75, 0x4d, 0x6f, 0x7c, 0x74, 0x59, 0x98, 0x72, 0x99, 0x6d, 0xde, 0x8d, |
|
| 925 |
+ 0xcf, 0xc8, 0xe8, 0x0f, 0x76, 0xa5, 0xa6, 0x72, 0xb9, 0xd9, 0x86, 0x93, 0x74, 0x9f, 0xf4, 0x16, |
|
| 926 |
+ 0x7c, 0x56, 0xb7, 0xdb, 0xf8, 0x97, 0xb5, 0xe6, 0xbc, 0x73, 0x0a, 0x17, 0x87, 0xab, 0x86, 0x05, |
|
| 927 |
+ 0x1f, 0x0d, 0x0b, 0xd6, 0x0d, 0x83, 0x67, 0xcb, 0xe0, 0xd5, 0x32, 0x78, 0xb7, 0x0c, 0x56, 0x96, |
|
| 928 |
+ 0xc1, 0xa7, 0x65, 0xf0, 0x6d, 0x59, 0xb0, 0xb6, 0x0c, 0x5e, 0xbe, 0x58, 0x70, 0x1b, 0xf9, 0x03, |
|
| 929 |
+ 0x9c, 0xfc, 0x04, 0x00, 0x00, 0xff, 0xff, 0x19, 0x97, 0x14, 0xf4, 0x8e, 0x01, 0x00, 0x00, |
|
| 930 |
+} |
| 0 | 931 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,17 @@ |
| 0 |
+syntax = "proto3"; |
|
| 1 |
+ |
|
| 2 |
+package fsutil; |
|
| 3 |
+ |
|
| 4 |
+message Stat {
|
|
| 5 |
+ string path = 1; |
|
| 6 |
+ uint32 mode = 2; |
|
| 7 |
+ uint32 uid = 3; |
|
| 8 |
+ uint32 gid = 4; |
|
| 9 |
+ int64 size = 5; |
|
| 10 |
+ int64 modTime = 6; |
|
| 11 |
+ // int32 typeflag = 7; |
|
| 12 |
+ string linkname = 7; |
|
| 13 |
+ int64 devmajor = 8; |
|
| 14 |
+ int64 devminor = 9; |
|
| 15 |
+ map<string, bytes> xattrs = 10; |
|
| 16 |
+} |
|
| 0 | 17 |
\ No newline at end of file |
| 1 | 18 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,88 @@ |
| 0 |
+package fsutil |
|
| 1 |
+ |
|
| 2 |
+import ( |
|
| 3 |
+ "os" |
|
| 4 |
+ "path/filepath" |
|
| 5 |
+ "sort" |
|
| 6 |
+ "strings" |
|
| 7 |
+ |
|
| 8 |
+ "github.com/pkg/errors" |
|
| 9 |
+) |
|
| 10 |
+ |
|
| 11 |
+type parent struct {
|
|
| 12 |
+ dir string |
|
| 13 |
+ last string |
|
| 14 |
+} |
|
| 15 |
+ |
|
| 16 |
+type Validator struct {
|
|
| 17 |
+ parentDirs []parent |
|
| 18 |
+} |
|
| 19 |
+ |
|
| 20 |
+func (v *Validator) HandleChange(kind ChangeKind, p string, fi os.FileInfo, err error) (retErr error) {
|
|
| 21 |
+ if err != nil {
|
|
| 22 |
+ return err |
|
| 23 |
+ } |
|
| 24 |
+ // test that all paths are in order and all parent dirs were present |
|
| 25 |
+ if v.parentDirs == nil {
|
|
| 26 |
+ v.parentDirs = make([]parent, 1, 10) |
|
| 27 |
+ } |
|
| 28 |
+ if p != filepath.Clean(p) {
|
|
| 29 |
+ return errors.Errorf("invalid unclean path %s", p)
|
|
| 30 |
+ } |
|
| 31 |
+ if filepath.IsAbs(p) {
|
|
| 32 |
+ return errors.Errorf("abolute path %s not allowed", p)
|
|
| 33 |
+ } |
|
| 34 |
+ dir := filepath.Dir(p) |
|
| 35 |
+ base := filepath.Base(p) |
|
| 36 |
+ if dir == "." {
|
|
| 37 |
+ dir = "" |
|
| 38 |
+ } |
|
| 39 |
+ if dir == ".." || strings.HasPrefix(p, "../") {
|
|
| 40 |
+ return errors.Errorf("invalid path: %s", p)
|
|
| 41 |
+ } |
|
| 42 |
+ |
|
| 43 |
+ // find a parent dir from saved records |
|
| 44 |
+ i := sort.Search(len(v.parentDirs), func(i int) bool {
|
|
| 45 |
+ return ComparePath(v.parentDirs[len(v.parentDirs)-1-i].dir, dir) <= 0 |
|
| 46 |
+ }) |
|
| 47 |
+ i = len(v.parentDirs) - 1 - i |
|
| 48 |
+ if i != len(v.parentDirs)-1 { // skipping back to grandparent
|
|
| 49 |
+ v.parentDirs = v.parentDirs[:i+1] |
|
| 50 |
+ } |
|
| 51 |
+ |
|
| 52 |
+ if dir != v.parentDirs[len(v.parentDirs)-1].dir || v.parentDirs[i].last >= base {
|
|
| 53 |
+ return errors.Errorf("changes out of order: %q %q", p, filepath.Join(v.parentDirs[i].dir, v.parentDirs[i].last))
|
|
| 54 |
+ } |
|
| 55 |
+ v.parentDirs[i].last = base |
|
| 56 |
+ if kind != ChangeKindDelete && fi.IsDir() {
|
|
| 57 |
+ v.parentDirs = append(v.parentDirs, parent{
|
|
| 58 |
+ dir: filepath.Join(dir, base), |
|
| 59 |
+ last: "", |
|
| 60 |
+ }) |
|
| 61 |
+ } |
|
| 62 |
+ // todo: validate invalid mode combinations |
|
| 63 |
+ return err |
|
| 64 |
+} |
|
| 65 |
+ |
|
| 66 |
+func ComparePath(p1, p2 string) int {
|
|
| 67 |
+ // byte-by-byte comparison to be compatible with str<>str |
|
| 68 |
+ min := min(len(p1), len(p2)) |
|
| 69 |
+ for i := 0; i < min; i++ {
|
|
| 70 |
+ switch {
|
|
| 71 |
+ case p1[i] == p2[i]: |
|
| 72 |
+ continue |
|
| 73 |
+ case p2[i] != '/' && p1[i] < p2[i] || p1[i] == '/': |
|
| 74 |
+ return -1 |
|
| 75 |
+ default: |
|
| 76 |
+ return 1 |
|
| 77 |
+ } |
|
| 78 |
+ } |
|
| 79 |
+ return len(p1) - len(p2) |
|
| 80 |
+} |
|
| 81 |
+ |
|
| 82 |
+func min(x, y int) int {
|
|
| 83 |
+ if x < y {
|
|
| 84 |
+ return x |
|
| 85 |
+ } |
|
| 86 |
+ return y |
|
| 87 |
+} |
| 0 | 88 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,170 @@ |
| 0 |
+package fsutil |
|
| 1 |
+ |
|
| 2 |
+import ( |
|
| 3 |
+ "os" |
|
| 4 |
+ "path/filepath" |
|
| 5 |
+ "runtime" |
|
| 6 |
+ "strings" |
|
| 7 |
+ "time" |
|
| 8 |
+ |
|
| 9 |
+ "github.com/docker/docker/pkg/fileutils" |
|
| 10 |
+ "github.com/pkg/errors" |
|
| 11 |
+ "golang.org/x/net/context" |
|
| 12 |
+) |
|
| 13 |
+ |
|
| 14 |
+type WalkOpt struct {
|
|
| 15 |
+ IncludePaths []string // todo: remove? |
|
| 16 |
+ ExcludePatterns []string |
|
| 17 |
+} |
|
| 18 |
+ |
|
| 19 |
+func Walk(ctx context.Context, p string, opt *WalkOpt, fn filepath.WalkFunc) error {
|
|
| 20 |
+ root, err := filepath.EvalSymlinks(p) |
|
| 21 |
+ if err != nil {
|
|
| 22 |
+ return errors.Wrapf(err, "failed to resolve %s", root) |
|
| 23 |
+ } |
|
| 24 |
+ fi, err := os.Stat(root) |
|
| 25 |
+ if err != nil {
|
|
| 26 |
+ return errors.Wrapf(err, "failed to stat: %s", root) |
|
| 27 |
+ } |
|
| 28 |
+ if !fi.IsDir() {
|
|
| 29 |
+ return errors.Errorf("%s is not a directory", root)
|
|
| 30 |
+ } |
|
| 31 |
+ |
|
| 32 |
+ var pm *fileutils.PatternMatcher |
|
| 33 |
+ if opt != nil && opt.ExcludePatterns != nil {
|
|
| 34 |
+ pm, err = fileutils.NewPatternMatcher(opt.ExcludePatterns) |
|
| 35 |
+ if err != nil {
|
|
| 36 |
+ return errors.Wrapf(err, "invalid excludepaths %s", opt.ExcludePatterns) |
|
| 37 |
+ } |
|
| 38 |
+ } |
|
| 39 |
+ |
|
| 40 |
+ seenFiles := make(map[uint64]string) |
|
| 41 |
+ return filepath.Walk(root, func(path string, fi os.FileInfo, err error) error {
|
|
| 42 |
+ if err != nil {
|
|
| 43 |
+ if os.IsNotExist(err) {
|
|
| 44 |
+ return filepath.SkipDir |
|
| 45 |
+ } |
|
| 46 |
+ return err |
|
| 47 |
+ } |
|
| 48 |
+ origpath := path |
|
| 49 |
+ path, err = filepath.Rel(root, path) |
|
| 50 |
+ if err != nil {
|
|
| 51 |
+ return err |
|
| 52 |
+ } |
|
| 53 |
+ // Skip root |
|
| 54 |
+ if path == "." {
|
|
| 55 |
+ return nil |
|
| 56 |
+ } |
|
| 57 |
+ |
|
| 58 |
+ if opt != nil {
|
|
| 59 |
+ if opt.IncludePaths != nil {
|
|
| 60 |
+ matched := false |
|
| 61 |
+ for _, p := range opt.IncludePaths {
|
|
| 62 |
+ if m, _ := filepath.Match(p, path); m {
|
|
| 63 |
+ matched = true |
|
| 64 |
+ break |
|
| 65 |
+ } |
|
| 66 |
+ } |
|
| 67 |
+ if !matched {
|
|
| 68 |
+ if fi.IsDir() {
|
|
| 69 |
+ return filepath.SkipDir |
|
| 70 |
+ } |
|
| 71 |
+ return nil |
|
| 72 |
+ } |
|
| 73 |
+ } |
|
| 74 |
+ if pm != nil {
|
|
| 75 |
+ m, err := pm.Matches(path) |
|
| 76 |
+ if err != nil {
|
|
| 77 |
+ return errors.Wrap(err, "failed to match excludepatterns") |
|
| 78 |
+ } |
|
| 79 |
+ |
|
| 80 |
+ if m {
|
|
| 81 |
+ if fi.IsDir() {
|
|
| 82 |
+ if !pm.Exclusions() {
|
|
| 83 |
+ return filepath.SkipDir |
|
| 84 |
+ } |
|
| 85 |
+ dirSlash := path + string(filepath.Separator) |
|
| 86 |
+ for _, pat := range pm.Patterns() {
|
|
| 87 |
+ if !pat.Exclusion() {
|
|
| 88 |
+ continue |
|
| 89 |
+ } |
|
| 90 |
+ patStr := pat.String() + string(filepath.Separator) |
|
| 91 |
+ if strings.HasPrefix(patStr, dirSlash) {
|
|
| 92 |
+ goto passedFilter |
|
| 93 |
+ } |
|
| 94 |
+ } |
|
| 95 |
+ return filepath.SkipDir |
|
| 96 |
+ } |
|
| 97 |
+ return nil |
|
| 98 |
+ } |
|
| 99 |
+ } |
|
| 100 |
+ } |
|
| 101 |
+ |
|
| 102 |
+ passedFilter: |
|
| 103 |
+ path = filepath.ToSlash(path) |
|
| 104 |
+ |
|
| 105 |
+ stat := &Stat{
|
|
| 106 |
+ Path: path, |
|
| 107 |
+ Mode: uint32(fi.Mode()), |
|
| 108 |
+ Size_: fi.Size(), |
|
| 109 |
+ ModTime: fi.ModTime().UnixNano(), |
|
| 110 |
+ } |
|
| 111 |
+ |
|
| 112 |
+ setUnixOpt(fi, stat, path, seenFiles) |
|
| 113 |
+ |
|
| 114 |
+ if !fi.IsDir() {
|
|
| 115 |
+ if fi.Mode()&os.ModeSymlink != 0 {
|
|
| 116 |
+ link, err := os.Readlink(origpath) |
|
| 117 |
+ if err != nil {
|
|
| 118 |
+ return errors.Wrapf(err, "failed to readlink %s", origpath) |
|
| 119 |
+ } |
|
| 120 |
+ stat.Linkname = link |
|
| 121 |
+ } |
|
| 122 |
+ } |
|
| 123 |
+ if err := loadXattr(origpath, stat); err != nil {
|
|
| 124 |
+ return errors.Wrapf(err, "failed to xattr %s", path) |
|
| 125 |
+ } |
|
| 126 |
+ |
|
| 127 |
+ if runtime.GOOS == "windows" {
|
|
| 128 |
+ permPart := stat.Mode & uint32(os.ModePerm) |
|
| 129 |
+ noPermPart := stat.Mode &^ uint32(os.ModePerm) |
|
| 130 |
+ // Add the x bit: make everything +x from windows |
|
| 131 |
+ permPart |= 0111 |
|
| 132 |
+ permPart &= 0755 |
|
| 133 |
+ stat.Mode = noPermPart | permPart |
|
| 134 |
+ } |
|
| 135 |
+ |
|
| 136 |
+ select {
|
|
| 137 |
+ case <-ctx.Done(): |
|
| 138 |
+ return ctx.Err() |
|
| 139 |
+ default: |
|
| 140 |
+ if err := fn(path, &StatInfo{stat}, nil); err != nil {
|
|
| 141 |
+ return err |
|
| 142 |
+ } |
|
| 143 |
+ } |
|
| 144 |
+ return nil |
|
| 145 |
+ }) |
|
| 146 |
+} |
|
| 147 |
+ |
|
| 148 |
+type StatInfo struct {
|
|
| 149 |
+ *Stat |
|
| 150 |
+} |
|
| 151 |
+ |
|
| 152 |
+func (s *StatInfo) Name() string {
|
|
| 153 |
+ return filepath.Base(s.Stat.Path) |
|
| 154 |
+} |
|
| 155 |
+func (s *StatInfo) Size() int64 {
|
|
| 156 |
+ return s.Stat.Size_ |
|
| 157 |
+} |
|
| 158 |
+func (s *StatInfo) Mode() os.FileMode {
|
|
| 159 |
+ return os.FileMode(s.Stat.Mode) |
|
| 160 |
+} |
|
| 161 |
+func (s *StatInfo) ModTime() time.Time {
|
|
| 162 |
+ return time.Unix(s.Stat.ModTime/1e9, s.Stat.ModTime%1e9) |
|
| 163 |
+} |
|
| 164 |
+func (s *StatInfo) IsDir() bool {
|
|
| 165 |
+ return s.Mode().IsDir() |
|
| 166 |
+} |
|
| 167 |
+func (s *StatInfo) Sys() interface{} {
|
|
| 168 |
+ return s.Stat |
|
| 169 |
+} |
| 0 | 170 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,61 @@ |
| 0 |
+// +build !windows |
|
| 1 |
+ |
|
| 2 |
+package fsutil |
|
| 3 |
+ |
|
| 4 |
+import ( |
|
| 5 |
+ "os" |
|
| 6 |
+ "syscall" |
|
| 7 |
+ |
|
| 8 |
+ "github.com/pkg/errors" |
|
| 9 |
+ "github.com/stevvooe/continuity/sysx" |
|
| 10 |
+) |
|
| 11 |
+ |
|
| 12 |
+func loadXattr(origpath string, stat *Stat) error {
|
|
| 13 |
+ xattrs, err := sysx.LListxattr(origpath) |
|
| 14 |
+ if err != nil {
|
|
| 15 |
+ return errors.Wrapf(err, "failed to xattr %s", origpath) |
|
| 16 |
+ } |
|
| 17 |
+ if len(xattrs) > 0 {
|
|
| 18 |
+ m := make(map[string][]byte) |
|
| 19 |
+ for _, key := range xattrs {
|
|
| 20 |
+ v, err := sysx.LGetxattr(origpath, key) |
|
| 21 |
+ if err == nil {
|
|
| 22 |
+ m[key] = v |
|
| 23 |
+ } |
|
| 24 |
+ } |
|
| 25 |
+ stat.Xattrs = m |
|
| 26 |
+ } |
|
| 27 |
+ return nil |
|
| 28 |
+} |
|
| 29 |
+ |
|
| 30 |
+func setUnixOpt(fi os.FileInfo, stat *Stat, path string, seenFiles map[uint64]string) {
|
|
| 31 |
+ s := fi.Sys().(*syscall.Stat_t) |
|
| 32 |
+ |
|
| 33 |
+ stat.Uid = s.Uid |
|
| 34 |
+ stat.Gid = s.Gid |
|
| 35 |
+ |
|
| 36 |
+ if !fi.IsDir() {
|
|
| 37 |
+ if s.Mode&syscall.S_IFBLK != 0 || |
|
| 38 |
+ s.Mode&syscall.S_IFCHR != 0 {
|
|
| 39 |
+ stat.Devmajor = int64(major(uint64(s.Rdev))) |
|
| 40 |
+ stat.Devminor = int64(minor(uint64(s.Rdev))) |
|
| 41 |
+ } |
|
| 42 |
+ |
|
| 43 |
+ ino := s.Ino |
|
| 44 |
+ if s.Nlink > 1 {
|
|
| 45 |
+ if oldpath, ok := seenFiles[ino]; ok {
|
|
| 46 |
+ stat.Linkname = oldpath |
|
| 47 |
+ stat.Size_ = 0 |
|
| 48 |
+ } |
|
| 49 |
+ } |
|
| 50 |
+ seenFiles[ino] = path |
|
| 51 |
+ } |
|
| 52 |
+} |
|
| 53 |
+ |
|
| 54 |
+func major(device uint64) uint64 {
|
|
| 55 |
+ return (device >> 8) & 0xfff |
|
| 56 |
+} |
|
| 57 |
+ |
|
| 58 |
+func minor(device uint64) uint64 {
|
|
| 59 |
+ return (device & 0xff) | ((device >> 12) & 0xfff00) |
|
| 60 |
+} |
| 0 | 14 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,563 @@ |
| 0 |
+// Code generated by protoc-gen-gogo. |
|
| 1 |
+// source: wire.proto |
|
| 2 |
+// DO NOT EDIT! |
|
| 3 |
+ |
|
| 4 |
+package fsutil |
|
| 5 |
+ |
|
| 6 |
+import proto "github.com/gogo/protobuf/proto" |
|
| 7 |
+import fmt "fmt" |
|
| 8 |
+import math "math" |
|
| 9 |
+ |
|
| 10 |
+import strconv "strconv" |
|
| 11 |
+ |
|
| 12 |
+import bytes "bytes" |
|
| 13 |
+ |
|
| 14 |
+import strings "strings" |
|
| 15 |
+import reflect "reflect" |
|
| 16 |
+ |
|
| 17 |
+import io "io" |
|
| 18 |
+ |
|
| 19 |
+// Reference imports to suppress errors if they are not otherwise used. |
|
| 20 |
+var _ = proto.Marshal |
|
| 21 |
+var _ = fmt.Errorf |
|
| 22 |
+var _ = math.Inf |
|
| 23 |
+ |
|
| 24 |
+type Packet_PacketType int32 |
|
| 25 |
+ |
|
| 26 |
+const ( |
|
| 27 |
+ PACKET_STAT Packet_PacketType = 0 |
|
| 28 |
+ PACKET_REQ Packet_PacketType = 1 |
|
| 29 |
+ PACKET_DATA Packet_PacketType = 2 |
|
| 30 |
+ PACKET_FIN Packet_PacketType = 3 |
|
| 31 |
+) |
|
| 32 |
+ |
|
| 33 |
+var Packet_PacketType_name = map[int32]string{
|
|
| 34 |
+ 0: "PACKET_STAT", |
|
| 35 |
+ 1: "PACKET_REQ", |
|
| 36 |
+ 2: "PACKET_DATA", |
|
| 37 |
+ 3: "PACKET_FIN", |
|
| 38 |
+} |
|
| 39 |
+var Packet_PacketType_value = map[string]int32{
|
|
| 40 |
+ "PACKET_STAT": 0, |
|
| 41 |
+ "PACKET_REQ": 1, |
|
| 42 |
+ "PACKET_DATA": 2, |
|
| 43 |
+ "PACKET_FIN": 3, |
|
| 44 |
+} |
|
| 45 |
+ |
|
| 46 |
+func (Packet_PacketType) EnumDescriptor() ([]byte, []int) { return fileDescriptorWire, []int{0, 0} }
|
|
| 47 |
+ |
|
| 48 |
+type Packet struct {
|
|
| 49 |
+ Type Packet_PacketType `protobuf:"varint,1,opt,name=type,proto3,enum=fsutil.Packet_PacketType" json:"type,omitempty"` |
|
| 50 |
+ Stat *Stat `protobuf:"bytes,2,opt,name=stat" json:"stat,omitempty"` |
|
| 51 |
+ ID uint32 `protobuf:"varint,3,opt,name=ID,proto3" json:"ID,omitempty"` |
|
| 52 |
+ Data []byte `protobuf:"bytes,4,opt,name=data,proto3" json:"data,omitempty"` |
|
| 53 |
+} |
|
| 54 |
+ |
|
| 55 |
+func (m *Packet) Reset() { *m = Packet{} }
|
|
| 56 |
+func (*Packet) ProtoMessage() {}
|
|
| 57 |
+func (*Packet) Descriptor() ([]byte, []int) { return fileDescriptorWire, []int{0} }
|
|
| 58 |
+ |
|
| 59 |
+func (m *Packet) GetType() Packet_PacketType {
|
|
| 60 |
+ if m != nil {
|
|
| 61 |
+ return m.Type |
|
| 62 |
+ } |
|
| 63 |
+ return PACKET_STAT |
|
| 64 |
+} |
|
| 65 |
+ |
|
| 66 |
+func (m *Packet) GetStat() *Stat {
|
|
| 67 |
+ if m != nil {
|
|
| 68 |
+ return m.Stat |
|
| 69 |
+ } |
|
| 70 |
+ return nil |
|
| 71 |
+} |
|
| 72 |
+ |
|
| 73 |
+func (m *Packet) GetID() uint32 {
|
|
| 74 |
+ if m != nil {
|
|
| 75 |
+ return m.ID |
|
| 76 |
+ } |
|
| 77 |
+ return 0 |
|
| 78 |
+} |
|
| 79 |
+ |
|
| 80 |
+func (m *Packet) GetData() []byte {
|
|
| 81 |
+ if m != nil {
|
|
| 82 |
+ return m.Data |
|
| 83 |
+ } |
|
| 84 |
+ return nil |
|
| 85 |
+} |
|
| 86 |
+ |
|
| 87 |
+func init() {
|
|
| 88 |
+ proto.RegisterType((*Packet)(nil), "fsutil.Packet") |
|
| 89 |
+ proto.RegisterEnum("fsutil.Packet_PacketType", Packet_PacketType_name, Packet_PacketType_value)
|
|
| 90 |
+} |
|
| 91 |
+func (x Packet_PacketType) String() string {
|
|
| 92 |
+ s, ok := Packet_PacketType_name[int32(x)] |
|
| 93 |
+ if ok {
|
|
| 94 |
+ return s |
|
| 95 |
+ } |
|
| 96 |
+ return strconv.Itoa(int(x)) |
|
| 97 |
+} |
|
| 98 |
+func (this *Packet) Equal(that interface{}) bool {
|
|
| 99 |
+ if that == nil {
|
|
| 100 |
+ if this == nil {
|
|
| 101 |
+ return true |
|
| 102 |
+ } |
|
| 103 |
+ return false |
|
| 104 |
+ } |
|
| 105 |
+ |
|
| 106 |
+ that1, ok := that.(*Packet) |
|
| 107 |
+ if !ok {
|
|
| 108 |
+ that2, ok := that.(Packet) |
|
| 109 |
+ if ok {
|
|
| 110 |
+ that1 = &that2 |
|
| 111 |
+ } else {
|
|
| 112 |
+ return false |
|
| 113 |
+ } |
|
| 114 |
+ } |
|
| 115 |
+ if that1 == nil {
|
|
| 116 |
+ if this == nil {
|
|
| 117 |
+ return true |
|
| 118 |
+ } |
|
| 119 |
+ return false |
|
| 120 |
+ } else if this == nil {
|
|
| 121 |
+ return false |
|
| 122 |
+ } |
|
| 123 |
+ if this.Type != that1.Type {
|
|
| 124 |
+ return false |
|
| 125 |
+ } |
|
| 126 |
+ if !this.Stat.Equal(that1.Stat) {
|
|
| 127 |
+ return false |
|
| 128 |
+ } |
|
| 129 |
+ if this.ID != that1.ID {
|
|
| 130 |
+ return false |
|
| 131 |
+ } |
|
| 132 |
+ if !bytes.Equal(this.Data, that1.Data) {
|
|
| 133 |
+ return false |
|
| 134 |
+ } |
|
| 135 |
+ return true |
|
| 136 |
+} |
|
| 137 |
+func (this *Packet) GoString() string {
|
|
| 138 |
+ if this == nil {
|
|
| 139 |
+ return "nil" |
|
| 140 |
+ } |
|
| 141 |
+ s := make([]string, 0, 8) |
|
| 142 |
+ s = append(s, "&fsutil.Packet{")
|
|
| 143 |
+ s = append(s, "Type: "+fmt.Sprintf("%#v", this.Type)+",\n")
|
|
| 144 |
+ if this.Stat != nil {
|
|
| 145 |
+ s = append(s, "Stat: "+fmt.Sprintf("%#v", this.Stat)+",\n")
|
|
| 146 |
+ } |
|
| 147 |
+ s = append(s, "ID: "+fmt.Sprintf("%#v", this.ID)+",\n")
|
|
| 148 |
+ s = append(s, "Data: "+fmt.Sprintf("%#v", this.Data)+",\n")
|
|
| 149 |
+ s = append(s, "}") |
|
| 150 |
+ return strings.Join(s, "") |
|
| 151 |
+} |
|
| 152 |
+func valueToGoStringWire(v interface{}, typ string) string {
|
|
| 153 |
+ rv := reflect.ValueOf(v) |
|
| 154 |
+ if rv.IsNil() {
|
|
| 155 |
+ return "nil" |
|
| 156 |
+ } |
|
| 157 |
+ pv := reflect.Indirect(rv).Interface() |
|
| 158 |
+ return fmt.Sprintf("func(v %v) *%v { return &v } ( %#v )", typ, typ, pv)
|
|
| 159 |
+} |
|
| 160 |
+func (m *Packet) Marshal() (dAtA []byte, err error) {
|
|
| 161 |
+ size := m.Size() |
|
| 162 |
+ dAtA = make([]byte, size) |
|
| 163 |
+ n, err := m.MarshalTo(dAtA) |
|
| 164 |
+ if err != nil {
|
|
| 165 |
+ return nil, err |
|
| 166 |
+ } |
|
| 167 |
+ return dAtA[:n], nil |
|
| 168 |
+} |
|
| 169 |
+ |
|
| 170 |
+func (m *Packet) MarshalTo(dAtA []byte) (int, error) {
|
|
| 171 |
+ var i int |
|
| 172 |
+ _ = i |
|
| 173 |
+ var l int |
|
| 174 |
+ _ = l |
|
| 175 |
+ if m.Type != 0 {
|
|
| 176 |
+ dAtA[i] = 0x8 |
|
| 177 |
+ i++ |
|
| 178 |
+ i = encodeVarintWire(dAtA, i, uint64(m.Type)) |
|
| 179 |
+ } |
|
| 180 |
+ if m.Stat != nil {
|
|
| 181 |
+ dAtA[i] = 0x12 |
|
| 182 |
+ i++ |
|
| 183 |
+ i = encodeVarintWire(dAtA, i, uint64(m.Stat.Size())) |
|
| 184 |
+ n1, err := m.Stat.MarshalTo(dAtA[i:]) |
|
| 185 |
+ if err != nil {
|
|
| 186 |
+ return 0, err |
|
| 187 |
+ } |
|
| 188 |
+ i += n1 |
|
| 189 |
+ } |
|
| 190 |
+ if m.ID != 0 {
|
|
| 191 |
+ dAtA[i] = 0x18 |
|
| 192 |
+ i++ |
|
| 193 |
+ i = encodeVarintWire(dAtA, i, uint64(m.ID)) |
|
| 194 |
+ } |
|
| 195 |
+ if len(m.Data) > 0 {
|
|
| 196 |
+ dAtA[i] = 0x22 |
|
| 197 |
+ i++ |
|
| 198 |
+ i = encodeVarintWire(dAtA, i, uint64(len(m.Data))) |
|
| 199 |
+ i += copy(dAtA[i:], m.Data) |
|
| 200 |
+ } |
|
| 201 |
+ return i, nil |
|
| 202 |
+} |
|
| 203 |
+ |
|
| 204 |
+func encodeFixed64Wire(dAtA []byte, offset int, v uint64) int {
|
|
| 205 |
+ dAtA[offset] = uint8(v) |
|
| 206 |
+ dAtA[offset+1] = uint8(v >> 8) |
|
| 207 |
+ dAtA[offset+2] = uint8(v >> 16) |
|
| 208 |
+ dAtA[offset+3] = uint8(v >> 24) |
|
| 209 |
+ dAtA[offset+4] = uint8(v >> 32) |
|
| 210 |
+ dAtA[offset+5] = uint8(v >> 40) |
|
| 211 |
+ dAtA[offset+6] = uint8(v >> 48) |
|
| 212 |
+ dAtA[offset+7] = uint8(v >> 56) |
|
| 213 |
+ return offset + 8 |
|
| 214 |
+} |
|
| 215 |
+func encodeFixed32Wire(dAtA []byte, offset int, v uint32) int {
|
|
| 216 |
+ dAtA[offset] = uint8(v) |
|
| 217 |
+ dAtA[offset+1] = uint8(v >> 8) |
|
| 218 |
+ dAtA[offset+2] = uint8(v >> 16) |
|
| 219 |
+ dAtA[offset+3] = uint8(v >> 24) |
|
| 220 |
+ return offset + 4 |
|
| 221 |
+} |
|
| 222 |
+func encodeVarintWire(dAtA []byte, offset int, v uint64) int {
|
|
| 223 |
+ for v >= 1<<7 {
|
|
| 224 |
+ dAtA[offset] = uint8(v&0x7f | 0x80) |
|
| 225 |
+ v >>= 7 |
|
| 226 |
+ offset++ |
|
| 227 |
+ } |
|
| 228 |
+ dAtA[offset] = uint8(v) |
|
| 229 |
+ return offset + 1 |
|
| 230 |
+} |
|
| 231 |
+func (m *Packet) Size() (n int) {
|
|
| 232 |
+ var l int |
|
| 233 |
+ _ = l |
|
| 234 |
+ if m.Type != 0 {
|
|
| 235 |
+ n += 1 + sovWire(uint64(m.Type)) |
|
| 236 |
+ } |
|
| 237 |
+ if m.Stat != nil {
|
|
| 238 |
+ l = m.Stat.Size() |
|
| 239 |
+ n += 1 + l + sovWire(uint64(l)) |
|
| 240 |
+ } |
|
| 241 |
+ if m.ID != 0 {
|
|
| 242 |
+ n += 1 + sovWire(uint64(m.ID)) |
|
| 243 |
+ } |
|
| 244 |
+ l = len(m.Data) |
|
| 245 |
+ if l > 0 {
|
|
| 246 |
+ n += 1 + l + sovWire(uint64(l)) |
|
| 247 |
+ } |
|
| 248 |
+ return n |
|
| 249 |
+} |
|
| 250 |
+ |
|
| 251 |
+func sovWire(x uint64) (n int) {
|
|
| 252 |
+ for {
|
|
| 253 |
+ n++ |
|
| 254 |
+ x >>= 7 |
|
| 255 |
+ if x == 0 {
|
|
| 256 |
+ break |
|
| 257 |
+ } |
|
| 258 |
+ } |
|
| 259 |
+ return n |
|
| 260 |
+} |
|
| 261 |
+func sozWire(x uint64) (n int) {
|
|
| 262 |
+ return sovWire(uint64((x << 1) ^ uint64((int64(x) >> 63)))) |
|
| 263 |
+} |
|
| 264 |
+func (this *Packet) String() string {
|
|
| 265 |
+ if this == nil {
|
|
| 266 |
+ return "nil" |
|
| 267 |
+ } |
|
| 268 |
+ s := strings.Join([]string{`&Packet{`,
|
|
| 269 |
+ `Type:` + fmt.Sprintf("%v", this.Type) + `,`,
|
|
| 270 |
+ `Stat:` + strings.Replace(fmt.Sprintf("%v", this.Stat), "Stat", "Stat", 1) + `,`,
|
|
| 271 |
+ `ID:` + fmt.Sprintf("%v", this.ID) + `,`,
|
|
| 272 |
+ `Data:` + fmt.Sprintf("%v", this.Data) + `,`,
|
|
| 273 |
+ `}`, |
|
| 274 |
+ }, "") |
|
| 275 |
+ return s |
|
| 276 |
+} |
|
| 277 |
+func valueToStringWire(v interface{}) string {
|
|
| 278 |
+ rv := reflect.ValueOf(v) |
|
| 279 |
+ if rv.IsNil() {
|
|
| 280 |
+ return "nil" |
|
| 281 |
+ } |
|
| 282 |
+ pv := reflect.Indirect(rv).Interface() |
|
| 283 |
+ return fmt.Sprintf("*%v", pv)
|
|
| 284 |
+} |
|
| 285 |
+func (m *Packet) Unmarshal(dAtA []byte) error {
|
|
| 286 |
+ l := len(dAtA) |
|
| 287 |
+ iNdEx := 0 |
|
| 288 |
+ for iNdEx < l {
|
|
| 289 |
+ preIndex := iNdEx |
|
| 290 |
+ var wire uint64 |
|
| 291 |
+ for shift := uint(0); ; shift += 7 {
|
|
| 292 |
+ if shift >= 64 {
|
|
| 293 |
+ return ErrIntOverflowWire |
|
| 294 |
+ } |
|
| 295 |
+ if iNdEx >= l {
|
|
| 296 |
+ return io.ErrUnexpectedEOF |
|
| 297 |
+ } |
|
| 298 |
+ b := dAtA[iNdEx] |
|
| 299 |
+ iNdEx++ |
|
| 300 |
+ wire |= (uint64(b) & 0x7F) << shift |
|
| 301 |
+ if b < 0x80 {
|
|
| 302 |
+ break |
|
| 303 |
+ } |
|
| 304 |
+ } |
|
| 305 |
+ fieldNum := int32(wire >> 3) |
|
| 306 |
+ wireType := int(wire & 0x7) |
|
| 307 |
+ if wireType == 4 {
|
|
| 308 |
+ return fmt.Errorf("proto: Packet: wiretype end group for non-group")
|
|
| 309 |
+ } |
|
| 310 |
+ if fieldNum <= 0 {
|
|
| 311 |
+ return fmt.Errorf("proto: Packet: illegal tag %d (wire type %d)", fieldNum, wire)
|
|
| 312 |
+ } |
|
| 313 |
+ switch fieldNum {
|
|
| 314 |
+ case 1: |
|
| 315 |
+ if wireType != 0 {
|
|
| 316 |
+ return fmt.Errorf("proto: wrong wireType = %d for field Type", wireType)
|
|
| 317 |
+ } |
|
| 318 |
+ m.Type = 0 |
|
| 319 |
+ for shift := uint(0); ; shift += 7 {
|
|
| 320 |
+ if shift >= 64 {
|
|
| 321 |
+ return ErrIntOverflowWire |
|
| 322 |
+ } |
|
| 323 |
+ if iNdEx >= l {
|
|
| 324 |
+ return io.ErrUnexpectedEOF |
|
| 325 |
+ } |
|
| 326 |
+ b := dAtA[iNdEx] |
|
| 327 |
+ iNdEx++ |
|
| 328 |
+ m.Type |= (Packet_PacketType(b) & 0x7F) << shift |
|
| 329 |
+ if b < 0x80 {
|
|
| 330 |
+ break |
|
| 331 |
+ } |
|
| 332 |
+ } |
|
| 333 |
+ case 2: |
|
| 334 |
+ if wireType != 2 {
|
|
| 335 |
+ return fmt.Errorf("proto: wrong wireType = %d for field Stat", wireType)
|
|
| 336 |
+ } |
|
| 337 |
+ var msglen int |
|
| 338 |
+ for shift := uint(0); ; shift += 7 {
|
|
| 339 |
+ if shift >= 64 {
|
|
| 340 |
+ return ErrIntOverflowWire |
|
| 341 |
+ } |
|
| 342 |
+ if iNdEx >= l {
|
|
| 343 |
+ return io.ErrUnexpectedEOF |
|
| 344 |
+ } |
|
| 345 |
+ b := dAtA[iNdEx] |
|
| 346 |
+ iNdEx++ |
|
| 347 |
+ msglen |= (int(b) & 0x7F) << shift |
|
| 348 |
+ if b < 0x80 {
|
|
| 349 |
+ break |
|
| 350 |
+ } |
|
| 351 |
+ } |
|
| 352 |
+ if msglen < 0 {
|
|
| 353 |
+ return ErrInvalidLengthWire |
|
| 354 |
+ } |
|
| 355 |
+ postIndex := iNdEx + msglen |
|
| 356 |
+ if postIndex > l {
|
|
| 357 |
+ return io.ErrUnexpectedEOF |
|
| 358 |
+ } |
|
| 359 |
+ if m.Stat == nil {
|
|
| 360 |
+ m.Stat = &Stat{}
|
|
| 361 |
+ } |
|
| 362 |
+ if err := m.Stat.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
|
|
| 363 |
+ return err |
|
| 364 |
+ } |
|
| 365 |
+ iNdEx = postIndex |
|
| 366 |
+ case 3: |
|
| 367 |
+ if wireType != 0 {
|
|
| 368 |
+ return fmt.Errorf("proto: wrong wireType = %d for field ID", wireType)
|
|
| 369 |
+ } |
|
| 370 |
+ m.ID = 0 |
|
| 371 |
+ for shift := uint(0); ; shift += 7 {
|
|
| 372 |
+ if shift >= 64 {
|
|
| 373 |
+ return ErrIntOverflowWire |
|
| 374 |
+ } |
|
| 375 |
+ if iNdEx >= l {
|
|
| 376 |
+ return io.ErrUnexpectedEOF |
|
| 377 |
+ } |
|
| 378 |
+ b := dAtA[iNdEx] |
|
| 379 |
+ iNdEx++ |
|
| 380 |
+ m.ID |= (uint32(b) & 0x7F) << shift |
|
| 381 |
+ if b < 0x80 {
|
|
| 382 |
+ break |
|
| 383 |
+ } |
|
| 384 |
+ } |
|
| 385 |
+ case 4: |
|
| 386 |
+ if wireType != 2 {
|
|
| 387 |
+ return fmt.Errorf("proto: wrong wireType = %d for field Data", wireType)
|
|
| 388 |
+ } |
|
| 389 |
+ var byteLen int |
|
| 390 |
+ for shift := uint(0); ; shift += 7 {
|
|
| 391 |
+ if shift >= 64 {
|
|
| 392 |
+ return ErrIntOverflowWire |
|
| 393 |
+ } |
|
| 394 |
+ if iNdEx >= l {
|
|
| 395 |
+ return io.ErrUnexpectedEOF |
|
| 396 |
+ } |
|
| 397 |
+ b := dAtA[iNdEx] |
|
| 398 |
+ iNdEx++ |
|
| 399 |
+ byteLen |= (int(b) & 0x7F) << shift |
|
| 400 |
+ if b < 0x80 {
|
|
| 401 |
+ break |
|
| 402 |
+ } |
|
| 403 |
+ } |
|
| 404 |
+ if byteLen < 0 {
|
|
| 405 |
+ return ErrInvalidLengthWire |
|
| 406 |
+ } |
|
| 407 |
+ postIndex := iNdEx + byteLen |
|
| 408 |
+ if postIndex > l {
|
|
| 409 |
+ return io.ErrUnexpectedEOF |
|
| 410 |
+ } |
|
| 411 |
+ m.Data = append(m.Data[:0], dAtA[iNdEx:postIndex]...) |
|
| 412 |
+ if m.Data == nil {
|
|
| 413 |
+ m.Data = []byte{}
|
|
| 414 |
+ } |
|
| 415 |
+ iNdEx = postIndex |
|
| 416 |
+ default: |
|
| 417 |
+ iNdEx = preIndex |
|
| 418 |
+ skippy, err := skipWire(dAtA[iNdEx:]) |
|
| 419 |
+ if err != nil {
|
|
| 420 |
+ return err |
|
| 421 |
+ } |
|
| 422 |
+ if skippy < 0 {
|
|
| 423 |
+ return ErrInvalidLengthWire |
|
| 424 |
+ } |
|
| 425 |
+ if (iNdEx + skippy) > l {
|
|
| 426 |
+ return io.ErrUnexpectedEOF |
|
| 427 |
+ } |
|
| 428 |
+ iNdEx += skippy |
|
| 429 |
+ } |
|
| 430 |
+ } |
|
| 431 |
+ |
|
| 432 |
+ if iNdEx > l {
|
|
| 433 |
+ return io.ErrUnexpectedEOF |
|
| 434 |
+ } |
|
| 435 |
+ return nil |
|
| 436 |
+} |
|
| 437 |
+func skipWire(dAtA []byte) (n int, err error) {
|
|
| 438 |
+ l := len(dAtA) |
|
| 439 |
+ iNdEx := 0 |
|
| 440 |
+ for iNdEx < l {
|
|
| 441 |
+ var wire uint64 |
|
| 442 |
+ for shift := uint(0); ; shift += 7 {
|
|
| 443 |
+ if shift >= 64 {
|
|
| 444 |
+ return 0, ErrIntOverflowWire |
|
| 445 |
+ } |
|
| 446 |
+ if iNdEx >= l {
|
|
| 447 |
+ return 0, io.ErrUnexpectedEOF |
|
| 448 |
+ } |
|
| 449 |
+ b := dAtA[iNdEx] |
|
| 450 |
+ iNdEx++ |
|
| 451 |
+ wire |= (uint64(b) & 0x7F) << shift |
|
| 452 |
+ if b < 0x80 {
|
|
| 453 |
+ break |
|
| 454 |
+ } |
|
| 455 |
+ } |
|
| 456 |
+ wireType := int(wire & 0x7) |
|
| 457 |
+ switch wireType {
|
|
| 458 |
+ case 0: |
|
| 459 |
+ for shift := uint(0); ; shift += 7 {
|
|
| 460 |
+ if shift >= 64 {
|
|
| 461 |
+ return 0, ErrIntOverflowWire |
|
| 462 |
+ } |
|
| 463 |
+ if iNdEx >= l {
|
|
| 464 |
+ return 0, io.ErrUnexpectedEOF |
|
| 465 |
+ } |
|
| 466 |
+ iNdEx++ |
|
| 467 |
+ if dAtA[iNdEx-1] < 0x80 {
|
|
| 468 |
+ break |
|
| 469 |
+ } |
|
| 470 |
+ } |
|
| 471 |
+ return iNdEx, nil |
|
| 472 |
+ case 1: |
|
| 473 |
+ iNdEx += 8 |
|
| 474 |
+ return iNdEx, nil |
|
| 475 |
+ case 2: |
|
| 476 |
+ var length int |
|
| 477 |
+ for shift := uint(0); ; shift += 7 {
|
|
| 478 |
+ if shift >= 64 {
|
|
| 479 |
+ return 0, ErrIntOverflowWire |
|
| 480 |
+ } |
|
| 481 |
+ if iNdEx >= l {
|
|
| 482 |
+ return 0, io.ErrUnexpectedEOF |
|
| 483 |
+ } |
|
| 484 |
+ b := dAtA[iNdEx] |
|
| 485 |
+ iNdEx++ |
|
| 486 |
+ length |= (int(b) & 0x7F) << shift |
|
| 487 |
+ if b < 0x80 {
|
|
| 488 |
+ break |
|
| 489 |
+ } |
|
| 490 |
+ } |
|
| 491 |
+ iNdEx += length |
|
| 492 |
+ if length < 0 {
|
|
| 493 |
+ return 0, ErrInvalidLengthWire |
|
| 494 |
+ } |
|
| 495 |
+ return iNdEx, nil |
|
| 496 |
+ case 3: |
|
| 497 |
+ for {
|
|
| 498 |
+ var innerWire uint64 |
|
| 499 |
+ var start int = iNdEx |
|
| 500 |
+ for shift := uint(0); ; shift += 7 {
|
|
| 501 |
+ if shift >= 64 {
|
|
| 502 |
+ return 0, ErrIntOverflowWire |
|
| 503 |
+ } |
|
| 504 |
+ if iNdEx >= l {
|
|
| 505 |
+ return 0, io.ErrUnexpectedEOF |
|
| 506 |
+ } |
|
| 507 |
+ b := dAtA[iNdEx] |
|
| 508 |
+ iNdEx++ |
|
| 509 |
+ innerWire |= (uint64(b) & 0x7F) << shift |
|
| 510 |
+ if b < 0x80 {
|
|
| 511 |
+ break |
|
| 512 |
+ } |
|
| 513 |
+ } |
|
| 514 |
+ innerWireType := int(innerWire & 0x7) |
|
| 515 |
+ if innerWireType == 4 {
|
|
| 516 |
+ break |
|
| 517 |
+ } |
|
| 518 |
+ next, err := skipWire(dAtA[start:]) |
|
| 519 |
+ if err != nil {
|
|
| 520 |
+ return 0, err |
|
| 521 |
+ } |
|
| 522 |
+ iNdEx = start + next |
|
| 523 |
+ } |
|
| 524 |
+ return iNdEx, nil |
|
| 525 |
+ case 4: |
|
| 526 |
+ return iNdEx, nil |
|
| 527 |
+ case 5: |
|
| 528 |
+ iNdEx += 4 |
|
| 529 |
+ return iNdEx, nil |
|
| 530 |
+ default: |
|
| 531 |
+ return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
|
|
| 532 |
+ } |
|
| 533 |
+ } |
|
| 534 |
+ panic("unreachable")
|
|
| 535 |
+} |
|
| 536 |
+ |
|
| 537 |
+var ( |
|
| 538 |
+ ErrInvalidLengthWire = fmt.Errorf("proto: negative length found during unmarshaling")
|
|
| 539 |
+ ErrIntOverflowWire = fmt.Errorf("proto: integer overflow")
|
|
| 540 |
+) |
|
| 541 |
+ |
|
| 542 |
+func init() { proto.RegisterFile("wire.proto", fileDescriptorWire) }
|
|
| 543 |
+ |
|
| 544 |
+var fileDescriptorWire = []byte{
|
|
| 545 |
+ // 253 bytes of a gzipped FileDescriptorProto |
|
| 546 |
+ 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xe2, 0xe2, 0x2a, 0xcf, 0x2c, 0x4a, |
|
| 547 |
+ 0xd5, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x62, 0x4b, 0x2b, 0x2e, 0x2d, 0xc9, 0xcc, 0x91, 0xe2, |
|
| 548 |
+ 0x2a, 0x2e, 0x49, 0x2c, 0x81, 0x88, 0x29, 0x9d, 0x65, 0xe4, 0x62, 0x0b, 0x48, 0x4c, 0xce, 0x4e, |
|
| 549 |
+ 0x2d, 0x11, 0xd2, 0xe5, 0x62, 0x29, 0xa9, 0x2c, 0x48, 0x95, 0x60, 0x54, 0x60, 0xd4, 0xe0, 0x33, |
|
| 550 |
+ 0x92, 0xd4, 0x83, 0xa8, 0xd6, 0x83, 0xc8, 0x42, 0xa9, 0x90, 0xca, 0x82, 0xd4, 0x20, 0xb0, 0x32, |
|
| 551 |
+ 0x21, 0x05, 0x2e, 0x16, 0x90, 0x39, 0x12, 0x4c, 0x0a, 0x8c, 0x1a, 0xdc, 0x46, 0x3c, 0x30, 0xe5, |
|
| 552 |
+ 0xc1, 0x25, 0x89, 0x25, 0x41, 0x60, 0x19, 0x21, 0x3e, 0x2e, 0x26, 0x4f, 0x17, 0x09, 0x66, 0x05, |
|
| 553 |
+ 0x46, 0x0d, 0xde, 0x20, 0x26, 0x4f, 0x17, 0x21, 0x21, 0x2e, 0x96, 0x94, 0xc4, 0x92, 0x44, 0x09, |
|
| 554 |
+ 0x16, 0x05, 0x46, 0x0d, 0x9e, 0x20, 0x30, 0x5b, 0xc9, 0x8f, 0x8b, 0x0b, 0x61, 0xb2, 0x10, 0x3f, |
|
| 555 |
+ 0x17, 0x77, 0x80, 0xa3, 0xb3, 0xb7, 0x6b, 0x48, 0x7c, 0x70, 0x88, 0x63, 0x88, 0x00, 0x83, 0x10, |
|
| 556 |
+ 0x1f, 0x17, 0x17, 0x54, 0x20, 0xc8, 0x35, 0x50, 0x80, 0x11, 0x49, 0x81, 0x8b, 0x63, 0x88, 0xa3, |
|
| 557 |
+ 0x00, 0x13, 0x92, 0x02, 0x37, 0x4f, 0x3f, 0x01, 0x66, 0x27, 0x9d, 0x0b, 0x0f, 0xe5, 0x18, 0x6e, |
|
| 558 |
+ 0x3c, 0x94, 0x63, 0xf8, 0xf0, 0x50, 0x8e, 0xb1, 0xe1, 0x91, 0x1c, 0xe3, 0x8a, 0x47, 0x72, 0x8c, |
|
| 559 |
+ 0x27, 0x1e, 0xc9, 0x31, 0x5e, 0x78, 0x24, 0xc7, 0xf8, 0xe0, 0x91, 0x1c, 0xe3, 0x8b, 0x47, 0x72, |
|
| 560 |
+ 0x0c, 0x1f, 0x1e, 0xc9, 0x31, 0x4e, 0x78, 0x2c, 0xc7, 0x90, 0xc4, 0x06, 0x0e, 0x04, 0x63, 0x40, |
|
| 561 |
+ 0x00, 0x00, 0x00, 0xff, 0xff, 0xda, 0x30, 0x43, 0x22, 0x26, 0x01, 0x00, 0x00, |
|
| 562 |
+} |
| 0 | 563 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,18 @@ |
| 0 |
+syntax = "proto3"; |
|
| 1 |
+ |
|
| 2 |
+package fsutil; |
|
| 3 |
+ |
|
| 4 |
+import "stat.proto"; |
|
| 5 |
+ |
|
| 6 |
+message Packet {
|
|
| 7 |
+ enum PacketType {
|
|
| 8 |
+ PACKET_STAT = 0; |
|
| 9 |
+ PACKET_REQ = 1; |
|
| 10 |
+ PACKET_DATA = 2; |
|
| 11 |
+ PACKET_FIN = 3; |
|
| 12 |
+ } |
|
| 13 |
+ PacketType type = 1; |
|
| 14 |
+ Stat stat = 2; |
|
| 15 |
+ uint32 ID = 3; |
|
| 16 |
+ bytes data = 4; |
|
| 17 |
+} |
| 0 | 18 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,67 @@ |
| 0 |
+// Copyright 2016 The Go Authors. All rights reserved. |
|
| 1 |
+// Use of this source code is governed by a BSD-style |
|
| 2 |
+// license that can be found in the LICENSE file. |
|
| 3 |
+ |
|
| 4 |
+// Package errgroup provides synchronization, error propagation, and Context |
|
| 5 |
+// cancelation for groups of goroutines working on subtasks of a common task. |
|
| 6 |
+package errgroup |
|
| 7 |
+ |
|
| 8 |
+import ( |
|
| 9 |
+ "sync" |
|
| 10 |
+ |
|
| 11 |
+ "golang.org/x/net/context" |
|
| 12 |
+) |
|
| 13 |
+ |
|
| 14 |
+// A Group is a collection of goroutines working on subtasks that are part of |
|
| 15 |
+// the same overall task. |
|
| 16 |
+// |
|
| 17 |
+// A zero Group is valid and does not cancel on error. |
|
| 18 |
+type Group struct {
|
|
| 19 |
+ cancel func() |
|
| 20 |
+ |
|
| 21 |
+ wg sync.WaitGroup |
|
| 22 |
+ |
|
| 23 |
+ errOnce sync.Once |
|
| 24 |
+ err error |
|
| 25 |
+} |
|
| 26 |
+ |
|
| 27 |
+// WithContext returns a new Group and an associated Context derived from ctx. |
|
| 28 |
+// |
|
| 29 |
+// The derived Context is canceled the first time a function passed to Go |
|
| 30 |
+// returns a non-nil error or the first time Wait returns, whichever occurs |
|
| 31 |
+// first. |
|
| 32 |
+func WithContext(ctx context.Context) (*Group, context.Context) {
|
|
| 33 |
+ ctx, cancel := context.WithCancel(ctx) |
|
| 34 |
+ return &Group{cancel: cancel}, ctx
|
|
| 35 |
+} |
|
| 36 |
+ |
|
| 37 |
+// Wait blocks until all function calls from the Go method have returned, then |
|
| 38 |
+// returns the first non-nil error (if any) from them. |
|
| 39 |
+func (g *Group) Wait() error {
|
|
| 40 |
+ g.wg.Wait() |
|
| 41 |
+ if g.cancel != nil {
|
|
| 42 |
+ g.cancel() |
|
| 43 |
+ } |
|
| 44 |
+ return g.err |
|
| 45 |
+} |
|
| 46 |
+ |
|
| 47 |
+// Go calls the given function in a new goroutine. |
|
| 48 |
+// |
|
| 49 |
+// The first call to return a non-nil error cancels the group; its error will be |
|
| 50 |
+// returned by Wait. |
|
| 51 |
+func (g *Group) Go(f func() error) {
|
|
| 52 |
+ g.wg.Add(1) |
|
| 53 |
+ |
|
| 54 |
+ go func() {
|
|
| 55 |
+ defer g.wg.Done() |
|
| 56 |
+ |
|
| 57 |
+ if err := f(); err != nil {
|
|
| 58 |
+ g.errOnce.Do(func() {
|
|
| 59 |
+ g.err = err |
|
| 60 |
+ if g.cancel != nil {
|
|
| 61 |
+ g.cancel() |
|
| 62 |
+ } |
|
| 63 |
+ }) |
|
| 64 |
+ } |
|
| 65 |
+ }() |
|
| 66 |
+} |
| 0 | 67 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,111 @@ |
| 0 |
+// Copyright 2013 The Go Authors. All rights reserved. |
|
| 1 |
+// Use of this source code is governed by a BSD-style |
|
| 2 |
+// license that can be found in the LICENSE file. |
|
| 3 |
+ |
|
| 4 |
+// Package singleflight provides a duplicate function call suppression |
|
| 5 |
+// mechanism. |
|
| 6 |
+package singleflight // import "golang.org/x/sync/singleflight" |
|
| 7 |
+ |
|
| 8 |
+import "sync" |
|
| 9 |
+ |
|
| 10 |
+// call is an in-flight or completed singleflight.Do call |
|
| 11 |
+type call struct {
|
|
| 12 |
+ wg sync.WaitGroup |
|
| 13 |
+ |
|
| 14 |
+ // These fields are written once before the WaitGroup is done |
|
| 15 |
+ // and are only read after the WaitGroup is done. |
|
| 16 |
+ val interface{}
|
|
| 17 |
+ err error |
|
| 18 |
+ |
|
| 19 |
+ // These fields are read and written with the singleflight |
|
| 20 |
+ // mutex held before the WaitGroup is done, and are read but |
|
| 21 |
+ // not written after the WaitGroup is done. |
|
| 22 |
+ dups int |
|
| 23 |
+ chans []chan<- Result |
|
| 24 |
+} |
|
| 25 |
+ |
|
| 26 |
+// Group represents a class of work and forms a namespace in |
|
| 27 |
+// which units of work can be executed with duplicate suppression. |
|
| 28 |
+type Group struct {
|
|
| 29 |
+ mu sync.Mutex // protects m |
|
| 30 |
+ m map[string]*call // lazily initialized |
|
| 31 |
+} |
|
| 32 |
+ |
|
| 33 |
+// Result holds the results of Do, so they can be passed |
|
| 34 |
+// on a channel. |
|
| 35 |
+type Result struct {
|
|
| 36 |
+ Val interface{}
|
|
| 37 |
+ Err error |
|
| 38 |
+ Shared bool |
|
| 39 |
+} |
|
| 40 |
+ |
|
| 41 |
+// Do executes and returns the results of the given function, making |
|
| 42 |
+// sure that only one execution is in-flight for a given key at a |
|
| 43 |
+// time. If a duplicate comes in, the duplicate caller waits for the |
|
| 44 |
+// original to complete and receives the same results. |
|
| 45 |
+// The return value shared indicates whether v was given to multiple callers. |
|
| 46 |
+func (g *Group) Do(key string, fn func() (interface{}, error)) (v interface{}, err error, shared bool) {
|
|
| 47 |
+ g.mu.Lock() |
|
| 48 |
+ if g.m == nil {
|
|
| 49 |
+ g.m = make(map[string]*call) |
|
| 50 |
+ } |
|
| 51 |
+ if c, ok := g.m[key]; ok {
|
|
| 52 |
+ c.dups++ |
|
| 53 |
+ g.mu.Unlock() |
|
| 54 |
+ c.wg.Wait() |
|
| 55 |
+ return c.val, c.err, true |
|
| 56 |
+ } |
|
| 57 |
+ c := new(call) |
|
| 58 |
+ c.wg.Add(1) |
|
| 59 |
+ g.m[key] = c |
|
| 60 |
+ g.mu.Unlock() |
|
| 61 |
+ |
|
| 62 |
+ g.doCall(c, key, fn) |
|
| 63 |
+ return c.val, c.err, c.dups > 0 |
|
| 64 |
+} |
|
| 65 |
+ |
|
| 66 |
+// DoChan is like Do but returns a channel that will receive the |
|
| 67 |
+// results when they are ready. |
|
| 68 |
+func (g *Group) DoChan(key string, fn func() (interface{}, error)) <-chan Result {
|
|
| 69 |
+ ch := make(chan Result, 1) |
|
| 70 |
+ g.mu.Lock() |
|
| 71 |
+ if g.m == nil {
|
|
| 72 |
+ g.m = make(map[string]*call) |
|
| 73 |
+ } |
|
| 74 |
+ if c, ok := g.m[key]; ok {
|
|
| 75 |
+ c.dups++ |
|
| 76 |
+ c.chans = append(c.chans, ch) |
|
| 77 |
+ g.mu.Unlock() |
|
| 78 |
+ return ch |
|
| 79 |
+ } |
|
| 80 |
+ c := &call{chans: []chan<- Result{ch}}
|
|
| 81 |
+ c.wg.Add(1) |
|
| 82 |
+ g.m[key] = c |
|
| 83 |
+ g.mu.Unlock() |
|
| 84 |
+ |
|
| 85 |
+ go g.doCall(c, key, fn) |
|
| 86 |
+ |
|
| 87 |
+ return ch |
|
| 88 |
+} |
|
| 89 |
+ |
|
| 90 |
+// doCall handles the single call for a key. |
|
| 91 |
+func (g *Group) doCall(c *call, key string, fn func() (interface{}, error)) {
|
|
| 92 |
+ c.val, c.err = fn() |
|
| 93 |
+ c.wg.Done() |
|
| 94 |
+ |
|
| 95 |
+ g.mu.Lock() |
|
| 96 |
+ delete(g.m, key) |
|
| 97 |
+ for _, ch := range c.chans {
|
|
| 98 |
+ ch <- Result{c.val, c.err, c.dups > 0}
|
|
| 99 |
+ } |
|
| 100 |
+ g.mu.Unlock() |
|
| 101 |
+} |
|
| 102 |
+ |
|
| 103 |
+// Forget tells the singleflight to forget about a key. Future calls |
|
| 104 |
+// to Do for this key will call the function rather than waiting for |
|
| 105 |
+// an earlier call to complete. |
|
| 106 |
+func (g *Group) Forget(key string) {
|
|
| 107 |
+ g.mu.Lock() |
|
| 108 |
+ delete(g.m, key) |
|
| 109 |
+ g.mu.Unlock() |
|
| 110 |
+} |