Browse code

vendor: update containerd to a15b6e2097

Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>

Tonis Tiigi authored on 2019/03/15 16:16:41
Showing 110 changed files
... ...
@@ -14,7 +14,7 @@ github.com/sirupsen/logrus v1.0.6
14 14
 github.com/tchap/go-patricia v2.2.6
15 15
 github.com/vdemeester/shakers 24d7f1d6a71aa5d9cbe7390e4afb66b7eef9e1b3
16 16
 golang.org/x/net a680a1efc54dd51c040b3b5ce4939ea3cf2ea0d1
17
-golang.org/x/sys 41f3e6584952bb034a481797859f6ab34b6803bd
17
+golang.org/x/sys d455e41777fca6e8a5a79e34a14b8368bc11d9ba
18 18
 github.com/docker/go-units 47565b4f722fb6ceae66b95f853feed578a4a51c # v0.3.3
19 19
 github.com/docker/go-connections 7395e3f8aa162843a74ed6d48e79627d9792ac55 # v0.4.0
20 20
 golang.org/x/text f21a4dfb5e38f5895301dc265a8def02365cc3d0 # v0.3.0
... ...
@@ -119,14 +119,14 @@ github.com/googleapis/gax-go v2.0.0
119 119
 google.golang.org/genproto 694d95ba50e67b2e363f3483057db5d4910c18f9
120 120
 
121 121
 # containerd
122
-github.com/containerd/containerd bb71b10fd8f58240ca47fbb579b9d1028eea7c84 # v1.2.5
122
+github.com/containerd/containerd a15b6e2097c48b632dbdc63254bad4c62b69e709
123 123
 github.com/containerd/fifo 3d5202aec260678c48179c56f40e6f38a095738c
124 124
 github.com/containerd/continuity 004b46473808b3e7a4a3049c20e4376c91eb966d
125 125
 github.com/containerd/cgroups dbea6f2bd41658b84b00417ceefa416b979cbf10
126 126
 github.com/containerd/console c12b1e7919c14469339a5d38f2f8ed9b64a9de23
127 127
 github.com/containerd/go-runc 5a6d9f37cfa36b15efba46dc7ea349fa9b7143c3
128 128
 github.com/containerd/typeurl a93fcdb778cd272c6e9b3028b2f42d813e785d40
129
-github.com/containerd/ttrpc 2a805f71863501300ae1976d29f0454ae003e85a
129
+github.com/containerd/ttrpc f02858b1457c5ca3aaec3a0803eb0d59f96e41d6
130 130
 github.com/gogo/googleapis 08a7655d27152912db7aaf4f983275eaf8d128ef
131 131
 
132 132
 # cluster
... ...
@@ -172,11 +172,9 @@ checkpoint, err := task.Checkpoint(context)
172 172
 err := client.Push(context, "myregistry/checkpoints/redis:master", checkpoint)
173 173
 
174 174
 // on a new machine pull the checkpoint and restore the redis container
175
-image, err := client.Pull(context, "myregistry/checkpoints/redis:master")
175
+checkpoint, err := client.Pull(context, "myregistry/checkpoints/redis:master")
176 176
 
177
-checkpoint := image.Target()
178
-
179
-redis, err = client.NewContainer(context, "redis-master", containerd.WithCheckpoint(checkpoint, "redis-rootfs"))
177
+redis, err = client.NewContainer(context, "redis-master", containerd.WithNewSnapshot("redis-rootfs", checkpoint))
180 178
 defer container.Delete(context)
181 179
 
182 180
 task, err = redis.NewTask(context, cio.Stdio, containerd.WithTaskCheckpoint(checkpoint))
... ...
@@ -212,11 +210,6 @@ See [PLUGINS.md](PLUGINS.md) for how to create plugins
212 212
 Please see [RELEASES.md](RELEASES.md) for details on versioning and stability
213 213
 of containerd components.
214 214
 
215
-### Development reports.
216
-
217
-Weekly summary on the progress and what is being worked on.
218
-https://github.com/containerd/containerd/tree/master/reports
219
-
220 215
 ### Communication
221 216
 
222 217
 For async communication and long running discussions please use issues and pull requests on the github repo.
... ...
@@ -224,7 +217,12 @@ This will be the best place to discuss design and implementation.
224 224
 
225 225
 For sync communication we have a community slack with a #containerd channel that everyone is welcome to join and chat about development.
226 226
 
227
-**Slack:** https://join.slack.com/t/dockercommunity/shared_invite/enQtNDM4NjAwNDMyOTUwLWZlMDZmYWRjZjk4Zjc5ZGQ5NWZkOWI1Yjk2NGE3ZWVlYjYxM2VhYjczOWIyZDFhZTE3NTUwZWQzMjhmNGYyZTg
227
+**Slack:** Catch us in the #containerd and #containerd-dev channels on dockercommunity.slack.com.
228
+[Click here for an invite to docker community slack.](https://join.slack.com/t/dockercommunity/shared_invite/enQtNDY4MDc1Mzc0MzIwLTgxZDBlMmM4ZGEyNDc1N2FkMzlhODJkYmE1YTVkYjM1MDE3ZjAwZjBkOGFlOTJkZjRmZGYzNjYyY2M3ZTUxYzQ)
229
+
230
+### Security audit
231
+
232
+A third party security audit was performed by Cure53 in 4Q2018; the [full report](docs/SECURITY_AUDIT.pdf) is available in our docs/ directory.
228 233
 
229 234
 ### Reporting security issues
230 235
 
... ...
@@ -249,3 +247,8 @@ Please find all these core project documents, including the:
249 249
  * and [Contributing guidelines](https://github.com/containerd/project/blob/master/CONTRIBUTING.md)
250 250
 
251 251
 information in our [`containerd/project`](https://github.com/containerd/project) repository.
252
+
253
+## Adoption
254
+
255
+Interested to see who is using containerd? Are you using containerd in a project?
256
+Please add yourself via pull request to our [ADOPTERS.md](./ADOPTERS.md) file.
... ...
@@ -55,6 +55,9 @@ type TaskDelete struct {
55 55
 	Pid         uint32    `protobuf:"varint,2,opt,name=pid,proto3" json:"pid,omitempty"`
56 56
 	ExitStatus  uint32    `protobuf:"varint,3,opt,name=exit_status,json=exitStatus,proto3" json:"exit_status,omitempty"`
57 57
 	ExitedAt    time.Time `protobuf:"bytes,4,opt,name=exited_at,json=exitedAt,stdtime" json:"exited_at"`
58
+	// id is the specific exec. By default if omitted will be `""` thus matches
59
+	// the init exec of the task matching `container_id`.
60
+	ID string `protobuf:"bytes,5,opt,name=id,proto3" json:"id,omitempty"`
58 61
 }
59 62
 
60 63
 func (m *TaskDelete) Reset()                    { *m = TaskDelete{} }
... ...
@@ -210,6 +213,8 @@ func (m *TaskDelete) Field(fieldpath []string) (string, bool) {
210 210
 	// unhandled: exited_at
211 211
 	case "container_id":
212 212
 		return string(m.ContainerID), len(m.ContainerID) > 0
213
+	case "id":
214
+		return string(m.ID), len(m.ID) > 0
213 215
 	}
214 216
 	return "", false
215 217
 }
... ...
@@ -474,6 +479,12 @@ func (m *TaskDelete) MarshalTo(dAtA []byte) (int, error) {
474 474
 		return 0, err
475 475
 	}
476 476
 	i += n2
477
+	if len(m.ID) > 0 {
478
+		dAtA[i] = 0x2a
479
+		i++
480
+		i = encodeVarintTask(dAtA, i, uint64(len(m.ID)))
481
+		i += copy(dAtA[i:], m.ID)
482
+	}
477 483
 	return i, nil
478 484
 }
479 485
 
... ...
@@ -806,6 +817,10 @@ func (m *TaskDelete) Size() (n int) {
806 806
 	}
807 807
 	l = types.SizeOfStdTime(m.ExitedAt)
808 808
 	n += 1 + l + sovTask(uint64(l))
809
+	l = len(m.ID)
810
+	if l > 0 {
811
+		n += 1 + l + sovTask(uint64(l))
812
+	}
809 813
 	return n
810 814
 }
811 815
 
... ...
@@ -975,6 +990,7 @@ func (this *TaskDelete) String() string {
975 975
 		`Pid:` + fmt.Sprintf("%v", this.Pid) + `,`,
976 976
 		`ExitStatus:` + fmt.Sprintf("%v", this.ExitStatus) + `,`,
977 977
 		`ExitedAt:` + strings.Replace(strings.Replace(this.ExitedAt.String(), "Timestamp", "google_protobuf2.Timestamp", 1), `&`, ``, 1) + `,`,
978
+		`ID:` + fmt.Sprintf("%v", this.ID) + `,`,
978 979
 		`}`,
979 980
 	}, "")
980 981
 	return s
... ...
@@ -1522,6 +1538,35 @@ func (m *TaskDelete) Unmarshal(dAtA []byte) error {
1522 1522
 				return err
1523 1523
 			}
1524 1524
 			iNdEx = postIndex
1525
+		case 5:
1526
+			if wireType != 2 {
1527
+				return fmt.Errorf("proto: wrong wireType = %d for field ID", wireType)
1528
+			}
1529
+			var stringLen uint64
1530
+			for shift := uint(0); ; shift += 7 {
1531
+				if shift >= 64 {
1532
+					return ErrIntOverflowTask
1533
+				}
1534
+				if iNdEx >= l {
1535
+					return io.ErrUnexpectedEOF
1536
+				}
1537
+				b := dAtA[iNdEx]
1538
+				iNdEx++
1539
+				stringLen |= (uint64(b) & 0x7F) << shift
1540
+				if b < 0x80 {
1541
+					break
1542
+				}
1543
+			}
1544
+			intStringLen := int(stringLen)
1545
+			if intStringLen < 0 {
1546
+				return ErrInvalidLengthTask
1547
+			}
1548
+			postIndex := iNdEx + intStringLen
1549
+			if postIndex > l {
1550
+				return io.ErrUnexpectedEOF
1551
+			}
1552
+			m.ID = string(dAtA[iNdEx:postIndex])
1553
+			iNdEx = postIndex
1525 1554
 		default:
1526 1555
 			iNdEx = preIndex
1527 1556
 			skippy, err := skipTask(dAtA[iNdEx:])
... ...
@@ -2566,45 +2611,46 @@ func init() {
2566 2566
 }
2567 2567
 
2568 2568
 var fileDescriptorTask = []byte{
2569
-	// 637 bytes of a gzipped FileDescriptorProto
2569
+	// 644 bytes of a gzipped FileDescriptorProto
2570 2570
 	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x95, 0xcd, 0x6e, 0xd3, 0x40,
2571
-	0x10, 0xc7, 0x63, 0xa7, 0x75, 0x93, 0x09, 0x55, 0x8b, 0x55, 0x41, 0xc8, 0xc1, 0x8e, 0xcc, 0x25,
2572
-	0x27, 0x5b, 0x04, 0x89, 0x0b, 0x42, 0x6a, 0xd2, 0x70, 0xc8, 0xa1, 0x4a, 0x71, 0x7b, 0xa8, 0xb8,
2573
-	0x44, 0x4e, 0x76, 0x93, 0x2c, 0x8d, 0xbd, 0x96, 0x3d, 0x46, 0x45, 0xe2, 0xc0, 0x23, 0xf0, 0x08,
2574
-	0x3c, 0x05, 0xcf, 0xd0, 0x03, 0x07, 0x8e, 0x9c, 0x02, 0xf5, 0x03, 0x70, 0xe2, 0x01, 0xd0, 0x7a,
2575
-	0x1d, 0xb7, 0x50, 0xf1, 0x65, 0x89, 0x53, 0x76, 0x66, 0x67, 0xff, 0x33, 0xf3, 0xdb, 0xc9, 0x1a,
2576
-	0x1e, 0xcd, 0x19, 0x2e, 0x92, 0x89, 0x3d, 0xe5, 0xbe, 0x33, 0xe5, 0x01, 0x7a, 0x2c, 0xa0, 0x11,
2577
-	0xb9, 0xbe, 0xf4, 0x42, 0xe6, 0xd0, 0x97, 0x34, 0xc0, 0xd8, 0x41, 0x2f, 0x3e, 0xb3, 0xc3, 0x88,
2578
-	0x23, 0xd7, 0x6f, 0x5f, 0x45, 0xd8, 0x72, 0xb7, 0xb5, 0x37, 0xe7, 0x73, 0x9e, 0xed, 0x3a, 0x62,
2579
-	0x25, 0x03, 0x5b, 0xe6, 0x9c, 0xf3, 0xf9, 0x92, 0x3a, 0x99, 0x35, 0x49, 0x66, 0x0e, 0x32, 0x9f,
2580
-	0xc6, 0xe8, 0xf9, 0x61, 0x1e, 0xf0, 0x77, 0x15, 0xe0, 0xab, 0x90, 0xc6, 0x8e, 0xcf, 0x93, 0x00,
2581
-	0xf3, 0x73, 0xfb, 0x7f, 0x3c, 0x57, 0xa4, 0x0c, 0x97, 0xc9, 0x9c, 0x05, 0xce, 0x8c, 0xd1, 0x25,
2582
-	0x09, 0x3d, 0x5c, 0x48, 0x05, 0xeb, 0xab, 0x02, 0x70, 0xe2, 0xc5, 0x67, 0x07, 0x11, 0xf5, 0x90,
2583
-	0xea, 0x5d, 0xb8, 0x55, 0x1c, 0x1e, 0x33, 0xd2, 0x54, 0xda, 0x4a, 0xa7, 0xde, 0xdf, 0x49, 0x57,
2584
-	0x66, 0xe3, 0x60, 0xed, 0x1f, 0x0e, 0xdc, 0x46, 0x11, 0x34, 0x24, 0xfa, 0x1d, 0xd0, 0x26, 0x49,
2585
-	0x40, 0x96, 0xb4, 0xa9, 0x8a, 0x68, 0x37, 0xb7, 0x74, 0x07, 0xb4, 0x88, 0x73, 0x9c, 0xc5, 0xcd,
2586
-	0x6a, 0xbb, 0xda, 0x69, 0x74, 0xef, 0xda, 0xd7, 0x78, 0x65, 0xbd, 0xd8, 0x87, 0xa2, 0x17, 0x37,
2587
-	0x0f, 0xd3, 0x1f, 0x80, 0xca, 0x78, 0x73, 0xa3, 0xad, 0x74, 0x1a, 0xdd, 0x7b, 0xf6, 0x0d, 0xb8,
2588
-	0xb6, 0xa8, 0x73, 0x38, 0xea, 0x6b, 0xe9, 0xca, 0x54, 0x87, 0x23, 0x57, 0x65, 0x5c, 0x37, 0x00,
2589
-	0xa6, 0x0b, 0x3a, 0x3d, 0x0b, 0x39, 0x0b, 0xb0, 0xb9, 0x99, 0xe5, 0xbf, 0xe6, 0xd1, 0x77, 0xa1,
2590
-	0x1a, 0x32, 0xd2, 0xd4, 0xda, 0x4a, 0x67, 0xdb, 0x15, 0x4b, 0xeb, 0x19, 0xd4, 0x85, 0xce, 0x31,
2591
-	0x7a, 0x11, 0x96, 0x6a, 0x37, 0x97, 0x54, 0xaf, 0x24, 0xdf, 0xe7, 0x0c, 0x07, 0x74, 0x49, 0x4b,
2592
-	0x32, 0xbc, 0x21, 0xaa, 0x9b, 0xd0, 0xa0, 0xe7, 0x0c, 0xc7, 0x31, 0x7a, 0x98, 0x08, 0x84, 0x62,
2593
-	0x07, 0x84, 0xeb, 0x38, 0xf3, 0xe8, 0x3d, 0xa8, 0x0b, 0x8b, 0x92, 0xb1, 0x87, 0x39, 0xb4, 0x96,
2594
-	0x2d, 0x07, 0xcd, 0x5e, 0xdf, 0xba, 0x7d, 0xb2, 0x1e, 0xb4, 0x7e, 0xed, 0x62, 0x65, 0x56, 0xde,
2595
-	0x7e, 0x36, 0x15, 0xb7, 0x26, 0x8f, 0xf5, 0xd0, 0x7a, 0x01, 0x9a, 0x64, 0xaa, 0xef, 0xc1, 0x66,
2596
-	0x8c, 0x84, 0x05, 0xb2, 0x58, 0x57, 0x1a, 0xe2, 0x66, 0x63, 0x24, 0x3c, 0xc1, 0xf5, 0xcd, 0x4a,
2597
-	0x2b, 0xf7, 0xd3, 0x28, 0xca, 0xca, 0x92, 0x7e, 0x1a, 0x45, 0x7a, 0x0b, 0x6a, 0x48, 0x23, 0x9f,
2598
-	0x05, 0xde, 0x32, 0xab, 0xa8, 0xe6, 0x16, 0xb6, 0xf5, 0x41, 0x81, 0x9a, 0x48, 0xf6, 0xf4, 0x9c,
2599
-	0x61, 0xc9, 0x31, 0x53, 0x73, 0x42, 0xf5, 0x7c, 0x04, 0x06, 0xae, 0xca, 0x0a, 0x74, 0xd5, 0x5f,
2600
-	0xa2, 0xdb, 0xf8, 0x3d, 0xba, 0xcd, 0x52, 0xe8, 0x9e, 0xc0, 0x96, 0xe8, 0x66, 0x34, 0x3a, 0x2c,
2601
-	0xd3, 0x8c, 0xb5, 0x80, 0x6d, 0x09, 0x83, 0x4e, 0x7b, 0x84, 0x50, 0x52, 0x8a, 0xc8, 0x7d, 0xd8,
2602
-	0xa2, 0xe7, 0x74, 0x3a, 0x2e, 0xb0, 0x40, 0xba, 0x32, 0x35, 0xa1, 0x39, 0x1c, 0xb8, 0x9a, 0xd8,
2603
-	0x1a, 0x12, 0xeb, 0x35, 0xec, 0xac, 0x33, 0x65, 0x33, 0xff, 0x1f, 0x73, 0xdd, 0xbc, 0x0a, 0x6b,
2604
-	0x5f, 0xfe, 0x33, 0x8e, 0xbc, 0x24, 0x2e, 0x97, 0xd8, 0xea, 0x41, 0x43, 0x28, 0xb8, 0x34, 0x4e,
2605
-	0xfc, 0x92, 0x12, 0x33, 0xd8, 0xcd, 0x9e, 0xb8, 0xe2, 0x59, 0x28, 0xc9, 0xe0, 0xc7, 0xc7, 0x46,
2606
-	0xfd, 0xf9, 0xb1, 0xe9, 0x1f, 0x5d, 0x5c, 0x1a, 0x95, 0x4f, 0x97, 0x46, 0xe5, 0x4d, 0x6a, 0x28,
2607
-	0x17, 0xa9, 0xa1, 0x7c, 0x4c, 0x0d, 0xe5, 0x4b, 0x6a, 0x28, 0xef, 0xbe, 0x19, 0xca, 0xf3, 0xee,
2608
-	0x3f, 0x7c, 0x65, 0x1e, 0xcb, 0x9f, 0xd3, 0xca, 0x69, 0x75, 0xa2, 0x65, 0x13, 0xf9, 0xf0, 0x7b,
2609
-	0x00, 0x00, 0x00, 0xff, 0xff, 0x07, 0x69, 0x62, 0x9d, 0xa6, 0x06, 0x00, 0x00,
2571
+	0x10, 0xc7, 0x63, 0xa7, 0x75, 0xd3, 0x09, 0x55, 0x8b, 0x55, 0x95, 0x90, 0x83, 0x1d, 0x99, 0x4b,
2572
+	0x4e, 0xb6, 0x08, 0x12, 0x17, 0x84, 0xd4, 0xa4, 0xe1, 0x90, 0x43, 0x95, 0xe2, 0xf6, 0x50, 0x71,
2573
+	0x89, 0x36, 0xd9, 0x4d, 0xb2, 0x34, 0xf1, 0x5a, 0xf6, 0x18, 0x15, 0x89, 0x03, 0x8f, 0xc0, 0x23,
2574
+	0xf0, 0x38, 0x3d, 0x20, 0xc4, 0x91, 0x53, 0xa0, 0x7e, 0x00, 0x4e, 0x3c, 0x00, 0x5a, 0xaf, 0x93,
2575
+	0xb6, 0x54, 0x7c, 0x59, 0xe2, 0x94, 0x9d, 0xd9, 0xd9, 0xff, 0xec, 0xfc, 0x76, 0x3c, 0x81, 0xc7,
2576
+	0x13, 0x8e, 0xd3, 0x64, 0xe8, 0x8e, 0xc4, 0xdc, 0x1b, 0x89, 0x00, 0x09, 0x0f, 0x58, 0x44, 0xaf,
2577
+	0x2f, 0x49, 0xc8, 0x3d, 0xf6, 0x8a, 0x05, 0x18, 0x7b, 0x48, 0xe2, 0x33, 0x37, 0x8c, 0x04, 0x0a,
2578
+	0xf3, 0xee, 0x55, 0x84, 0xab, 0x76, 0xeb, 0xbb, 0x13, 0x31, 0x11, 0xd9, 0xae, 0x27, 0x57, 0x2a,
2579
+	0xb0, 0x6e, 0x4f, 0x84, 0x98, 0xcc, 0x98, 0x97, 0x59, 0xc3, 0x64, 0xec, 0x21, 0x9f, 0xb3, 0x18,
2580
+	0xc9, 0x3c, 0xcc, 0x03, 0xfe, 0xee, 0x06, 0xf8, 0x3a, 0x64, 0xb1, 0x37, 0x17, 0x49, 0x80, 0xf9,
2581
+	0xb9, 0xfd, 0x3f, 0x9e, 0x5b, 0xa5, 0x0c, 0x67, 0xc9, 0x84, 0x07, 0xde, 0x98, 0xb3, 0x19, 0x0d,
2582
+	0x09, 0x4e, 0x95, 0x82, 0xf3, 0x4d, 0x03, 0x38, 0x21, 0xf1, 0xd9, 0x41, 0xc4, 0x08, 0x32, 0xb3,
2583
+	0x05, 0x77, 0x56, 0x87, 0x07, 0x9c, 0xd6, 0xb4, 0x86, 0xd6, 0xdc, 0xec, 0x6c, 0xa7, 0x0b, 0xbb,
2584
+	0x7a, 0xb0, 0xf4, 0xf7, 0xba, 0x7e, 0x75, 0x15, 0xd4, 0xa3, 0xe6, 0x1e, 0x18, 0xc3, 0x24, 0xa0,
2585
+	0x33, 0x56, 0xd3, 0x65, 0xb4, 0x9f, 0x5b, 0xa6, 0x07, 0x46, 0x24, 0x04, 0x8e, 0xe3, 0x5a, 0xb9,
2586
+	0x51, 0x6e, 0x56, 0x5b, 0xf7, 0xdc, 0x6b, 0xbc, 0xb2, 0x5a, 0xdc, 0x43, 0x59, 0x8b, 0x9f, 0x87,
2587
+	0x99, 0x0f, 0x41, 0xe7, 0xa2, 0xb6, 0xd6, 0xd0, 0x9a, 0xd5, 0xd6, 0x7d, 0xf7, 0x16, 0x5c, 0x57,
2588
+	0xde, 0xb3, 0xd7, 0xef, 0x18, 0xe9, 0xc2, 0xd6, 0x7b, 0x7d, 0x5f, 0xe7, 0xc2, 0xb4, 0x00, 0x46,
2589
+	0x53, 0x36, 0x3a, 0x0b, 0x05, 0x0f, 0xb0, 0xb6, 0x9e, 0xe5, 0xbf, 0xe6, 0x31, 0x77, 0xa0, 0x1c,
2590
+	0x72, 0x5a, 0x33, 0x1a, 0x5a, 0x73, 0xcb, 0x97, 0x4b, 0xe7, 0x39, 0x6c, 0x4a, 0x9d, 0x63, 0x24,
2591
+	0x11, 0x16, 0x2a, 0x37, 0x97, 0xd4, 0xaf, 0x24, 0x3f, 0xe6, 0x0c, 0xbb, 0x6c, 0xc6, 0x0a, 0x32,
2592
+	0xbc, 0x25, 0x6a, 0xda, 0x50, 0x65, 0xe7, 0x1c, 0x07, 0x31, 0x12, 0x4c, 0x24, 0x42, 0xb9, 0x03,
2593
+	0xd2, 0x75, 0x9c, 0x79, 0xcc, 0x36, 0x6c, 0x4a, 0x8b, 0xd1, 0x01, 0xc1, 0x1c, 0x5a, 0xdd, 0x55,
2594
+	0x8d, 0xe6, 0x2e, 0x5f, 0xdd, 0x3d, 0x59, 0x36, 0x5a, 0xa7, 0x72, 0xb1, 0xb0, 0x4b, 0xef, 0xbe,
2595
+	0xd8, 0x9a, 0x5f, 0x51, 0xc7, 0xda, 0x68, 0xee, 0x81, 0xce, 0xa9, 0xa2, 0x96, 0x53, 0xed, 0xfa,
2596
+	0x3a, 0xa7, 0xce, 0x4b, 0x30, 0x14, 0x6b, 0x73, 0x17, 0xd6, 0x63, 0xa4, 0x3c, 0x50, 0x45, 0xf8,
2597
+	0xca, 0x90, 0x2f, 0x1e, 0x23, 0x15, 0x09, 0x2e, 0x5f, 0x5c, 0x59, 0xb9, 0x9f, 0x45, 0x51, 0x76,
2598
+	0x5d, 0xe5, 0x67, 0x51, 0x64, 0xd6, 0xa1, 0x82, 0x2c, 0x9a, 0xf3, 0x80, 0xcc, 0xb2, 0x9b, 0x56,
2599
+	0xfc, 0x95, 0xed, 0x7c, 0xd0, 0xa0, 0x22, 0x93, 0x3d, 0x3b, 0xe7, 0x58, 0xb0, 0xfd, 0xf4, 0x9c,
2600
+	0xdc, 0x8d, 0x22, 0x96, 0x48, 0xcb, 0xbf, 0x44, 0xba, 0xf6, 0x7b, 0xa4, 0xeb, 0x45, 0x90, 0x3a,
2601
+	0x4f, 0x61, 0x43, 0x56, 0xd3, 0xef, 0x1f, 0x16, 0x29, 0xc6, 0x99, 0xc2, 0x96, 0x82, 0xc1, 0x46,
2602
+	0x6d, 0x4a, 0x19, 0x2d, 0x44, 0xe4, 0x01, 0x6c, 0xb0, 0x73, 0x36, 0x1a, 0xac, 0xb0, 0x40, 0xba,
2603
+	0xb0, 0x0d, 0xa9, 0xd9, 0xeb, 0xfa, 0x86, 0xdc, 0xea, 0x51, 0xe7, 0x0d, 0x6c, 0x2f, 0x33, 0x65,
2604
+	0xdf, 0xc2, 0x7f, 0xcc, 0x75, 0xfb, 0x29, 0x9c, 0x7d, 0xf5, 0xc5, 0x1c, 0x91, 0x24, 0x2e, 0x96,
2605
+	0xd8, 0x69, 0x43, 0x55, 0x2a, 0xf8, 0x2c, 0x4e, 0xe6, 0x05, 0x25, 0xc6, 0xb0, 0x93, 0x8d, 0xbe,
2606
+	0xd5, 0xb8, 0x28, 0xc8, 0xe0, 0xe6, 0x10, 0xd2, 0x7f, 0x1e, 0x42, 0x9d, 0xa3, 0x8b, 0x4b, 0xab,
2607
+	0xf4, 0xf9, 0xd2, 0x2a, 0xbd, 0x4d, 0x2d, 0xed, 0x22, 0xb5, 0xb4, 0x4f, 0xa9, 0xa5, 0x7d, 0x4d,
2608
+	0x2d, 0xed, 0xfd, 0x77, 0x4b, 0x7b, 0xd1, 0xfa, 0x87, 0x7f, 0x9f, 0x27, 0xea, 0xe7, 0xb4, 0x74,
2609
+	0x5a, 0x1e, 0x1a, 0x59, 0x47, 0x3e, 0xfa, 0x11, 0x00, 0x00, 0xff, 0xff, 0xc5, 0x58, 0x0f, 0xec,
2610
+	0xbe, 0x06, 0x00, 0x00,
2610 2611
 }
... ...
@@ -29,6 +29,9 @@ message TaskDelete {
29 29
 	uint32 pid = 2;
30 30
 	uint32 exit_status = 3;
31 31
 	google.protobuf.Timestamp exited_at = 4 [(gogoproto.stdtime) = true, (gogoproto.nullable) = false];
32
+	// id is the specific exec. By default if omitted will be `""` thus matches
33
+	// the init exec of the task matching `container_id`.
34
+	string id = 5;
32 35
 }
33 36
 
34 37
 message TaskIO {
35 38
deleted file mode 100644
... ...
@@ -1,30 +0,0 @@
1
-/*
2
-   Copyright The containerd Authors.
3
-
4
-   Licensed under the Apache License, Version 2.0 (the "License");
5
-   you may not use this file except in compliance with the License.
6
-   You may obtain a copy of the License at
7
-
8
-       http://www.apache.org/licenses/LICENSE-2.0
9
-
10
-   Unless required by applicable law or agreed to in writing, software
11
-   distributed under the License is distributed on an "AS IS" BASIS,
12
-   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
-   See the License for the specific language governing permissions and
14
-   limitations under the License.
15
-*/
16
-
17
-package archive
18
-
19
-import (
20
-	"time"
21
-
22
-	"github.com/pkg/errors"
23
-)
24
-
25
-// as at MacOS 10.12 there is apparently no way to set timestamps
26
-// with nanosecond precision. We could fall back to utimes/lutimes
27
-// and lose the precision as a temporary workaround.
28
-func chtimes(path string, atime, mtime time.Time) error {
29
-	return errors.New("OSX missing UtimesNanoAt")
30
-}
... ...
@@ -1,4 +1,4 @@
1
-// +build freebsd linux openbsd solaris
1
+// +build !windows
2 2
 
3 3
 /*
4 4
    Copyright The containerd Authors.
... ...
@@ -31,11 +31,15 @@ const pipeRoot = `\\.\pipe`
31 31
 
32 32
 // NewFIFOSetInDir returns a new set of fifos for the task
33 33
 func NewFIFOSetInDir(_, id string, terminal bool) (*FIFOSet, error) {
34
+	stderrPipe := ""
35
+	if !terminal {
36
+		stderrPipe = fmt.Sprintf(`%s\ctr-%s-stderr`, pipeRoot, id)
37
+	}
34 38
 	return NewFIFOSet(Config{
35 39
 		Terminal: terminal,
36 40
 		Stdin:    fmt.Sprintf(`%s\ctr-%s-stdin`, pipeRoot, id),
37 41
 		Stdout:   fmt.Sprintf(`%s\ctr-%s-stdout`, pipeRoot, id),
38
-		Stderr:   fmt.Sprintf(`%s\ctr-%s-stderr`, pipeRoot, id),
42
+		Stderr:   stderrPipe,
39 43
 	}, nil), nil
40 44
 }
41 45
 
... ...
@@ -17,11 +17,14 @@
17 17
 package containerd
18 18
 
19 19
 import (
20
+	"bytes"
20 21
 	"context"
22
+	"encoding/json"
21 23
 	"fmt"
22 24
 	"net/http"
23 25
 	"runtime"
24 26
 	"strconv"
27
+	"strings"
25 28
 	"sync"
26 29
 	"time"
27 30
 
... ...
@@ -40,7 +43,6 @@ import (
40 40
 	"github.com/containerd/containerd/content"
41 41
 	contentproxy "github.com/containerd/containerd/content/proxy"
42 42
 	"github.com/containerd/containerd/defaults"
43
-	"github.com/containerd/containerd/errdefs"
44 43
 	"github.com/containerd/containerd/events"
45 44
 	"github.com/containerd/containerd/images"
46 45
 	"github.com/containerd/containerd/leases"
... ...
@@ -51,7 +53,6 @@ import (
51 51
 	"github.com/containerd/containerd/plugin"
52 52
 	"github.com/containerd/containerd/remotes"
53 53
 	"github.com/containerd/containerd/remotes/docker"
54
-	"github.com/containerd/containerd/remotes/docker/schema1"
55 54
 	"github.com/containerd/containerd/snapshots"
56 55
 	snproxy "github.com/containerd/containerd/snapshots/proxy"
57 56
 	"github.com/containerd/typeurl"
... ...
@@ -280,6 +281,12 @@ type RemoteContext struct {
280 280
 	// handlers.
281 281
 	BaseHandlers []images.Handler
282 282
 
283
+	// HandlerWrapper wraps the handler which gets sent to dispatch.
284
+	// Unlike BaseHandlers, this can run before and after the built
285
+	// in handlers, allowing operations to run on the descriptor
286
+	// after it has completed transferring.
287
+	HandlerWrapper func(images.Handler) images.Handler
288
+
283 289
 	// ConvertSchema1 is whether to convert Docker registry schema 1
284 290
 	// manifests. If this option is false then any image which resolves
285 291
 	// to schema 1 will return an error since schema 1 is not supported.
... ...
@@ -290,6 +297,9 @@ type RemoteContext struct {
290 290
 	// platforms will be used to create a PlatformMatcher with no ordering
291 291
 	// preference.
292 292
 	Platforms []string
293
+
294
+	// MaxConcurrentDownloads is the max concurrent content downloads for each pull.
295
+	MaxConcurrentDownloads int
293 296
 }
294 297
 
295 298
 func defaultRemoteContext() *RemoteContext {
... ...
@@ -341,157 +351,6 @@ func (c *Client) Fetch(ctx context.Context, ref string, opts ...RemoteOpt) (imag
341 341
 	return c.fetch(ctx, fetchCtx, ref, 0)
342 342
 }
343 343
 
344
-// Pull downloads the provided content into containerd's content store
345
-// and returns a platform specific image object
346
-func (c *Client) Pull(ctx context.Context, ref string, opts ...RemoteOpt) (Image, error) {
347
-	pullCtx := defaultRemoteContext()
348
-	for _, o := range opts {
349
-		if err := o(c, pullCtx); err != nil {
350
-			return nil, err
351
-		}
352
-	}
353
-
354
-	if pullCtx.PlatformMatcher == nil {
355
-		if len(pullCtx.Platforms) > 1 {
356
-			return nil, errors.New("cannot pull multiplatform image locally, try Fetch")
357
-		} else if len(pullCtx.Platforms) == 0 {
358
-			pullCtx.PlatformMatcher = platforms.Default()
359
-		} else {
360
-			p, err := platforms.Parse(pullCtx.Platforms[0])
361
-			if err != nil {
362
-				return nil, errors.Wrapf(err, "invalid platform %s", pullCtx.Platforms[0])
363
-			}
364
-
365
-			pullCtx.PlatformMatcher = platforms.Only(p)
366
-		}
367
-	}
368
-
369
-	ctx, done, err := c.WithLease(ctx)
370
-	if err != nil {
371
-		return nil, err
372
-	}
373
-	defer done(ctx)
374
-
375
-	img, err := c.fetch(ctx, pullCtx, ref, 1)
376
-	if err != nil {
377
-		return nil, err
378
-	}
379
-
380
-	i := NewImageWithPlatform(c, img, pullCtx.PlatformMatcher)
381
-
382
-	if pullCtx.Unpack {
383
-		if err := i.Unpack(ctx, pullCtx.Snapshotter); err != nil {
384
-			return nil, errors.Wrapf(err, "failed to unpack image on snapshotter %s", pullCtx.Snapshotter)
385
-		}
386
-	}
387
-
388
-	return i, nil
389
-}
390
-
391
-func (c *Client) fetch(ctx context.Context, rCtx *RemoteContext, ref string, limit int) (images.Image, error) {
392
-	store := c.ContentStore()
393
-	name, desc, err := rCtx.Resolver.Resolve(ctx, ref)
394
-	if err != nil {
395
-		return images.Image{}, errors.Wrapf(err, "failed to resolve reference %q", ref)
396
-	}
397
-
398
-	fetcher, err := rCtx.Resolver.Fetcher(ctx, name)
399
-	if err != nil {
400
-		return images.Image{}, errors.Wrapf(err, "failed to get fetcher for %q", name)
401
-	}
402
-
403
-	var (
404
-		handler images.Handler
405
-
406
-		isConvertible bool
407
-		converterFunc func(context.Context, ocispec.Descriptor) (ocispec.Descriptor, error)
408
-	)
409
-
410
-	if desc.MediaType == images.MediaTypeDockerSchema1Manifest && rCtx.ConvertSchema1 {
411
-		schema1Converter := schema1.NewConverter(store, fetcher)
412
-
413
-		handler = images.Handlers(append(rCtx.BaseHandlers, schema1Converter)...)
414
-
415
-		isConvertible = true
416
-
417
-		converterFunc = func(ctx context.Context, _ ocispec.Descriptor) (ocispec.Descriptor, error) {
418
-			return schema1Converter.Convert(ctx)
419
-		}
420
-	} else {
421
-		// Get all the children for a descriptor
422
-		childrenHandler := images.ChildrenHandler(store)
423
-		// Set any children labels for that content
424
-		childrenHandler = images.SetChildrenLabels(store, childrenHandler)
425
-		// Filter children by platforms
426
-		childrenHandler = images.FilterPlatforms(childrenHandler, rCtx.PlatformMatcher)
427
-		// Sort and limit manifests if a finite number is needed
428
-		if limit > 0 {
429
-			childrenHandler = images.LimitManifests(childrenHandler, rCtx.PlatformMatcher, limit)
430
-		}
431
-
432
-		// set isConvertible to true if there is application/octet-stream media type
433
-		convertibleHandler := images.HandlerFunc(
434
-			func(_ context.Context, desc ocispec.Descriptor) ([]ocispec.Descriptor, error) {
435
-				if desc.MediaType == docker.LegacyConfigMediaType {
436
-					isConvertible = true
437
-				}
438
-
439
-				return []ocispec.Descriptor{}, nil
440
-			},
441
-		)
442
-
443
-		handler = images.Handlers(append(rCtx.BaseHandlers,
444
-			remotes.FetchHandler(store, fetcher),
445
-			convertibleHandler,
446
-			childrenHandler,
447
-		)...)
448
-
449
-		converterFunc = func(ctx context.Context, desc ocispec.Descriptor) (ocispec.Descriptor, error) {
450
-			return docker.ConvertManifest(ctx, store, desc)
451
-		}
452
-	}
453
-
454
-	if err := images.Dispatch(ctx, handler, desc); err != nil {
455
-		return images.Image{}, err
456
-	}
457
-
458
-	if isConvertible {
459
-		if desc, err = converterFunc(ctx, desc); err != nil {
460
-			return images.Image{}, err
461
-		}
462
-	}
463
-
464
-	img := images.Image{
465
-		Name:   name,
466
-		Target: desc,
467
-		Labels: rCtx.Labels,
468
-	}
469
-
470
-	is := c.ImageService()
471
-	for {
472
-		if created, err := is.Create(ctx, img); err != nil {
473
-			if !errdefs.IsAlreadyExists(err) {
474
-				return images.Image{}, err
475
-			}
476
-
477
-			updated, err := is.Update(ctx, img)
478
-			if err != nil {
479
-				// if image was removed, try create again
480
-				if errdefs.IsNotFound(err) {
481
-					continue
482
-				}
483
-				return images.Image{}, err
484
-			}
485
-
486
-			img = updated
487
-		} else {
488
-			img = created
489
-		}
490
-
491
-		return img, nil
492
-	}
493
-}
494
-
495 344
 // Push uploads the provided content to a remote resource
496 345
 func (c *Client) Push(ctx context.Context, ref string, desc ocispec.Descriptor, opts ...RemoteOpt) error {
497 346
 	pushCtx := defaultRemoteContext()
... ...
@@ -521,7 +380,21 @@ func (c *Client) Push(ctx context.Context, ref string, desc ocispec.Descriptor,
521 521
 		return err
522 522
 	}
523 523
 
524
-	return remotes.PushContent(ctx, pusher, desc, c.ContentStore(), pushCtx.PlatformMatcher, pushCtx.BaseHandlers...)
524
+	var wrapper func(images.Handler) images.Handler
525
+
526
+	if len(pushCtx.BaseHandlers) > 0 {
527
+		wrapper = func(h images.Handler) images.Handler {
528
+			h = images.Handlers(append(pushCtx.BaseHandlers, h)...)
529
+			if pushCtx.HandlerWrapper != nil {
530
+				h = pushCtx.HandlerWrapper(h)
531
+			}
532
+			return h
533
+		}
534
+	} else if pushCtx.HandlerWrapper != nil {
535
+		wrapper = pushCtx.HandlerWrapper
536
+	}
537
+
538
+	return remotes.PushContent(ctx, pusher, desc, c.ContentStore(), pushCtx.PlatformMatcher, wrapper)
525 539
 }
526 540
 
527 541
 // GetImage returns an existing image
... ...
@@ -546,6 +419,45 @@ func (c *Client) ListImages(ctx context.Context, filters ...string) ([]Image, er
546 546
 	return images, nil
547 547
 }
548 548
 
549
+// Restore restores a container from a checkpoint
550
+func (c *Client) Restore(ctx context.Context, id string, checkpoint Image, opts ...RestoreOpts) (Container, error) {
551
+	store := c.ContentStore()
552
+	index, err := decodeIndex(ctx, store, checkpoint.Target())
553
+	if err != nil {
554
+		return nil, err
555
+	}
556
+
557
+	ctx, done, err := c.WithLease(ctx)
558
+	if err != nil {
559
+		return nil, err
560
+	}
561
+	defer done(ctx)
562
+
563
+	copts := []NewContainerOpts{}
564
+	for _, o := range opts {
565
+		copts = append(copts, o(ctx, id, c, checkpoint, index))
566
+	}
567
+
568
+	ctr, err := c.NewContainer(ctx, id, copts...)
569
+	if err != nil {
570
+		return nil, err
571
+	}
572
+
573
+	return ctr, nil
574
+}
575
+
576
+func writeIndex(ctx context.Context, index *ocispec.Index, client *Client, ref string) (d ocispec.Descriptor, err error) {
577
+	labels := map[string]string{}
578
+	for i, m := range index.Manifests {
579
+		labels[fmt.Sprintf("containerd.io/gc.ref.content.%d", i)] = m.Digest.String()
580
+	}
581
+	data, err := json.Marshal(index)
582
+	if err != nil {
583
+		return ocispec.Descriptor{}, err
584
+	}
585
+	return writeContent(ctx, client.ContentStore(), ocispec.MediaTypeImageIndex, ref, bytes.NewReader(data), content.WithLabels(labels))
586
+}
587
+
549 588
 // Subscribe to events that match one or more of the provided filters.
550 589
 //
551 590
 // Callers should listen on both the envelope and errs channels. If the errs
... ...
@@ -703,3 +615,20 @@ func (c *Client) Version(ctx context.Context) (Version, error) {
703 703
 		Revision: response.Revision,
704 704
 	}, nil
705 705
 }
706
+
707
+// CheckRuntime returns true if the current runtime matches the expected
708
+// runtime. Providing various parts of the runtime schema will match those
709
+// parts of the expected runtime
710
+func CheckRuntime(current, expected string) bool {
711
+	cp := strings.Split(current, ".")
712
+	l := len(cp)
713
+	for i, p := range strings.Split(expected, ".") {
714
+		if i > l {
715
+			return false
716
+		}
717
+		if p != cp[i] {
718
+			return false
719
+		}
720
+	}
721
+	return true
722
+}
... ...
@@ -178,3 +178,19 @@ func WithImageHandler(h images.Handler) RemoteOpt {
178 178
 		return nil
179 179
 	}
180 180
 }
181
+
182
+// WithImageHandlerWrapper wraps the handlers to be called on dispatch.
183
+func WithImageHandlerWrapper(w func(images.Handler) images.Handler) RemoteOpt {
184
+	return func(client *Client, c *RemoteContext) error {
185
+		c.HandlerWrapper = w
186
+		return nil
187
+	}
188
+}
189
+
190
+// WithMaxConcurrentDownloads sets max concurrent download limit.
191
+func WithMaxConcurrentDownloads(max int) RemoteOpt {
192
+	return func(client *Client, c *RemoteContext) error {
193
+		c.MaxConcurrentDownloads = max
194
+		return nil
195
+	}
196
+}
... ...
@@ -28,12 +28,22 @@ import (
28 28
 	"github.com/containerd/containerd/cio"
29 29
 	"github.com/containerd/containerd/containers"
30 30
 	"github.com/containerd/containerd/errdefs"
31
+	"github.com/containerd/containerd/images"
31 32
 	"github.com/containerd/containerd/oci"
33
+	"github.com/containerd/containerd/runtime/v2/runc/options"
32 34
 	"github.com/containerd/typeurl"
33 35
 	prototypes "github.com/gogo/protobuf/types"
36
+	ver "github.com/opencontainers/image-spec/specs-go"
37
+	ocispec "github.com/opencontainers/image-spec/specs-go/v1"
34 38
 	"github.com/pkg/errors"
35 39
 )
36 40
 
41
+const (
42
+	checkpointImageNameLabel       = "org.opencontainers.image.ref.name"
43
+	checkpointRuntimeNameLabel     = "io.containerd.checkpoint.runtime"
44
+	checkpointSnapshotterNameLabel = "io.containerd.checkpoint.snapshotter"
45
+)
46
+
37 47
 // Container is a metadata object for container resources and task creation
38 48
 type Container interface {
39 49
 	// ID identifies the container
... ...
@@ -64,6 +74,8 @@ type Container interface {
64 64
 	Extensions(context.Context) (map[string]prototypes.Any, error)
65 65
 	// Update a container
66 66
 	Update(context.Context, ...UpdateContainerOpts) error
67
+	// Checkpoint creates a checkpoint image of the current container
68
+	Checkpoint(context.Context, string, ...CheckpointOpts) (Image, error)
67 69
 }
68 70
 
69 71
 func containerFromRecord(client *Client, c containers.Container) *container {
... ...
@@ -217,7 +229,9 @@ func (c *container) NewTask(ctx context.Context, ioCreate cio.Creator, opts ...N
217 217
 			})
218 218
 		}
219 219
 	}
220
-	var info TaskInfo
220
+	info := TaskInfo{
221
+		runtime: r.Runtime.Name,
222
+	}
221 223
 	for _, o := range opts {
222 224
 		if err := o(ctx, c.client, &info); err != nil {
223 225
 			return nil, err
... ...
@@ -272,6 +286,70 @@ func (c *container) Update(ctx context.Context, opts ...UpdateContainerOpts) err
272 272
 	return nil
273 273
 }
274 274
 
275
+func (c *container) Checkpoint(ctx context.Context, ref string, opts ...CheckpointOpts) (Image, error) {
276
+	index := &ocispec.Index{
277
+		Versioned: ver.Versioned{
278
+			SchemaVersion: 2,
279
+		},
280
+		Annotations: make(map[string]string),
281
+	}
282
+	copts := &options.CheckpointOptions{
283
+		Exit:                false,
284
+		OpenTcp:             false,
285
+		ExternalUnixSockets: false,
286
+		Terminal:            false,
287
+		FileLocks:           true,
288
+		EmptyNamespaces:     nil,
289
+	}
290
+	info, err := c.Info(ctx)
291
+	if err != nil {
292
+		return nil, err
293
+	}
294
+
295
+	img, err := c.Image(ctx)
296
+	if err != nil {
297
+		return nil, err
298
+	}
299
+
300
+	ctx, done, err := c.client.WithLease(ctx)
301
+	if err != nil {
302
+		return nil, err
303
+	}
304
+	defer done(ctx)
305
+
306
+	// add image name to manifest
307
+	index.Annotations[checkpointImageNameLabel] = img.Name()
308
+	// add runtime info to index
309
+	index.Annotations[checkpointRuntimeNameLabel] = info.Runtime.Name
310
+	// add snapshotter info to index
311
+	index.Annotations[checkpointSnapshotterNameLabel] = info.Snapshotter
312
+
313
+	// process remaining opts
314
+	for _, o := range opts {
315
+		if err := o(ctx, c.client, &info, index, copts); err != nil {
316
+			err = errdefs.FromGRPC(err)
317
+			if !errdefs.IsAlreadyExists(err) {
318
+				return nil, err
319
+			}
320
+		}
321
+	}
322
+
323
+	desc, err := writeIndex(ctx, index, c.client, c.ID()+"index")
324
+	if err != nil {
325
+		return nil, err
326
+	}
327
+	i := images.Image{
328
+		Name:   ref,
329
+		Target: desc,
330
+	}
331
+	checkpoint, err := c.client.ImageService().Create(ctx, i)
332
+	if err != nil {
333
+		return nil, err
334
+	}
335
+
336
+	return NewImage(c.client, checkpoint), nil
337
+}
338
+
275 339
 func (c *container) loadTask(ctx context.Context, ioAttach cio.Attach) (Task, error) {
276 340
 	response, err := c.client.TaskService().Get(ctx, &tasks.GetRequest{
277 341
 		ContainerID: c.id,
278 342
new file mode 100644
... ...
@@ -0,0 +1,155 @@
0
+/*
1
+   Copyright The containerd Authors.
2
+
3
+   Licensed under the Apache License, Version 2.0 (the "License");
4
+   you may not use this file except in compliance with the License.
5
+   You may obtain a copy of the License at
6
+
7
+       http://www.apache.org/licenses/LICENSE-2.0
8
+
9
+   Unless required by applicable law or agreed to in writing, software
10
+   distributed under the License is distributed on an "AS IS" BASIS,
11
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+   See the License for the specific language governing permissions and
13
+   limitations under the License.
14
+*/
15
+
16
+package containerd
17
+
18
+import (
19
+	"bytes"
20
+	"context"
21
+	"fmt"
22
+	"runtime"
23
+
24
+	tasks "github.com/containerd/containerd/api/services/tasks/v1"
25
+	"github.com/containerd/containerd/containers"
26
+	"github.com/containerd/containerd/diff"
27
+	"github.com/containerd/containerd/images"
28
+	"github.com/containerd/containerd/platforms"
29
+	"github.com/containerd/containerd/rootfs"
30
+	"github.com/containerd/containerd/runtime/v2/runc/options"
31
+	"github.com/containerd/typeurl"
32
+	imagespec "github.com/opencontainers/image-spec/specs-go/v1"
33
+	"github.com/pkg/errors"
34
+)
35
+
36
+var (
37
+	// ErrCheckpointRWUnsupported is returned if the container runtime does not support checkpoint
38
+	ErrCheckpointRWUnsupported = errors.New("rw checkpoint is only supported on v2 runtimes")
39
+	// ErrMediaTypeNotFound returns an error when a media type in the manifest is unknown
40
+	ErrMediaTypeNotFound = errors.New("media type not found")
41
+)
42
+
43
+// CheckpointOpts are options to manage the checkpoint operation
44
+type CheckpointOpts func(context.Context, *Client, *containers.Container, *imagespec.Index, *options.CheckpointOptions) error
45
+
46
+// WithCheckpointImage includes the container image in the checkpoint
47
+func WithCheckpointImage(ctx context.Context, client *Client, c *containers.Container, index *imagespec.Index, copts *options.CheckpointOptions) error {
48
+	ir, err := client.ImageService().Get(ctx, c.Image)
49
+	if err != nil {
50
+		return err
51
+	}
52
+	index.Manifests = append(index.Manifests, ir.Target)
53
+	return nil
54
+}
55
+
56
+// WithCheckpointTask includes the running task
57
+func WithCheckpointTask(ctx context.Context, client *Client, c *containers.Container, index *imagespec.Index, copts *options.CheckpointOptions) error {
58
+	any, err := typeurl.MarshalAny(copts)
59
+	if err != nil {
60
+		return nil
61
+	}
62
+	task, err := client.TaskService().Checkpoint(ctx, &tasks.CheckpointTaskRequest{
63
+		ContainerID: c.ID,
64
+		Options:     any,
65
+	})
66
+	if err != nil {
67
+		return err
68
+	}
69
+	for _, d := range task.Descriptors {
70
+		platformSpec := platforms.DefaultSpec()
71
+		index.Manifests = append(index.Manifests, imagespec.Descriptor{
72
+			MediaType: d.MediaType,
73
+			Size:      d.Size_,
74
+			Digest:    d.Digest,
75
+			Platform:  &platformSpec,
76
+		})
77
+	}
78
+	// save copts
79
+	data, err := any.Marshal()
80
+	if err != nil {
81
+		return err
82
+	}
83
+	r := bytes.NewReader(data)
84
+	desc, err := writeContent(ctx, client.ContentStore(), images.MediaTypeContainerd1CheckpointOptions, c.ID+"-checkpoint-options", r)
85
+	if err != nil {
86
+		return err
87
+	}
88
+	desc.Platform = &imagespec.Platform{
89
+		OS:           runtime.GOOS,
90
+		Architecture: runtime.GOARCH,
91
+	}
92
+	index.Manifests = append(index.Manifests, desc)
93
+	return nil
94
+}
95
+
96
+// WithCheckpointRuntime includes the container runtime info
97
+func WithCheckpointRuntime(ctx context.Context, client *Client, c *containers.Container, index *imagespec.Index, copts *options.CheckpointOptions) error {
98
+	if c.Runtime.Options != nil {
99
+		data, err := c.Runtime.Options.Marshal()
100
+		if err != nil {
101
+			return err
102
+		}
103
+		r := bytes.NewReader(data)
104
+		desc, err := writeContent(ctx, client.ContentStore(), images.MediaTypeContainerd1CheckpointRuntimeOptions, c.ID+"-runtime-options", r)
105
+		if err != nil {
106
+			return err
107
+		}
108
+		desc.Platform = &imagespec.Platform{
109
+			OS:           runtime.GOOS,
110
+			Architecture: runtime.GOARCH,
111
+		}
112
+		index.Manifests = append(index.Manifests, desc)
113
+	}
114
+	return nil
115
+}
116
+
117
+// WithCheckpointRW includes the rw in the checkpoint
118
+func WithCheckpointRW(ctx context.Context, client *Client, c *containers.Container, index *imagespec.Index, copts *options.CheckpointOptions) error {
119
+	diffOpts := []diff.Opt{
120
+		diff.WithReference(fmt.Sprintf("checkpoint-rw-%s", c.SnapshotKey)),
121
+	}
122
+	rw, err := rootfs.CreateDiff(ctx,
123
+		c.SnapshotKey,
124
+		client.SnapshotService(c.Snapshotter),
125
+		client.DiffService(),
126
+		diffOpts...,
127
+	)
128
+	if err != nil {
129
+		return err
130
+
131
+	}
132
+	rw.Platform = &imagespec.Platform{
133
+		OS:           runtime.GOOS,
134
+		Architecture: runtime.GOARCH,
135
+	}
136
+	index.Manifests = append(index.Manifests, rw)
137
+	return nil
138
+}
139
+
140
+// WithCheckpointTaskExit causes the task to exit after checkpoint
141
+func WithCheckpointTaskExit(ctx context.Context, client *Client, c *containers.Container, index *imagespec.Index, copts *options.CheckpointOptions) error {
142
+	copts.Exit = true
143
+	return nil
144
+}
145
+
146
+// GetIndexByMediaType returns the index in a manifest for the specified media type
147
+func GetIndexByMediaType(index *imagespec.Index, mt string) (*imagespec.Descriptor, error) {
148
+	for _, d := range index.Manifests {
149
+		if d.MediaType == mt {
150
+			return &d, nil
151
+		}
152
+	}
153
+	return nil, ErrMediaTypeNotFound
154
+}
... ...
@@ -23,6 +23,7 @@ import (
23 23
 	"github.com/containerd/containerd/errdefs"
24 24
 	"github.com/containerd/containerd/oci"
25 25
 	"github.com/containerd/containerd/platforms"
26
+	"github.com/containerd/containerd/snapshots"
26 27
 	"github.com/containerd/typeurl"
27 28
 	"github.com/gogo/protobuf/types"
28 29
 	"github.com/opencontainers/image-spec/identity"
... ...
@@ -118,7 +119,7 @@ func WithSnapshot(id string) NewContainerOpts {
118 118
 
119 119
 // WithNewSnapshot allocates a new snapshot to be used by the container as the
120 120
 // root filesystem in read-write mode
121
-func WithNewSnapshot(id string, i Image) NewContainerOpts {
121
+func WithNewSnapshot(id string, i Image, opts ...snapshots.Opt) NewContainerOpts {
122 122
 	return func(ctx context.Context, client *Client, c *containers.Container) error {
123 123
 		diffIDs, err := i.(*image).i.RootFS(ctx, client.ContentStore(), platforms.Default())
124 124
 		if err != nil {
... ...
@@ -126,7 +127,7 @@ func WithNewSnapshot(id string, i Image) NewContainerOpts {
126 126
 		}
127 127
 		setSnapshotterIfEmpty(c)
128 128
 		parent := identity.ChainID(diffIDs).String()
129
-		if _, err := client.SnapshotService(c.Snapshotter).Prepare(ctx, id, parent); err != nil {
129
+		if _, err := client.SnapshotService(c.Snapshotter).Prepare(ctx, id, parent, opts...); err != nil {
130 130
 			return err
131 131
 		}
132 132
 		c.SnapshotKey = id
... ...
@@ -148,7 +149,7 @@ func WithSnapshotCleanup(ctx context.Context, client *Client, c containers.Conta
148 148
 
149 149
 // WithNewSnapshotView allocates a new snapshot to be used by the container as the
150 150
 // root filesystem in read-only mode
151
-func WithNewSnapshotView(id string, i Image) NewContainerOpts {
151
+func WithNewSnapshotView(id string, i Image, opts ...snapshots.Opt) NewContainerOpts {
152 152
 	return func(ctx context.Context, client *Client, c *containers.Container) error {
153 153
 		diffIDs, err := i.(*image).i.RootFS(ctx, client.ContentStore(), platforms.Default())
154 154
 		if err != nil {
... ...
@@ -156,7 +157,7 @@ func WithNewSnapshotView(id string, i Image) NewContainerOpts {
156 156
 		}
157 157
 		setSnapshotterIfEmpty(c)
158 158
 		parent := identity.ChainID(diffIDs).String()
159
-		if _, err := client.SnapshotService(c.Snapshotter).View(ctx, id, parent); err != nil {
159
+		if _, err := client.SnapshotService(c.Snapshotter).View(ctx, id, parent, opts...); err != nil {
160 160
 			return err
161 161
 		}
162 162
 		c.SnapshotKey = id
... ...
@@ -26,81 +26,12 @@ import (
26 26
 	"syscall"
27 27
 
28 28
 	"github.com/containerd/containerd/containers"
29
-	"github.com/containerd/containerd/content"
30 29
 	"github.com/containerd/containerd/errdefs"
31
-	"github.com/containerd/containerd/images"
32 30
 	"github.com/containerd/containerd/mount"
33 31
 	"github.com/containerd/containerd/platforms"
34
-	"github.com/gogo/protobuf/proto"
35
-	protobuf "github.com/gogo/protobuf/types"
36 32
 	"github.com/opencontainers/image-spec/identity"
37
-	"github.com/opencontainers/image-spec/specs-go/v1"
38
-	"github.com/pkg/errors"
39 33
 )
40 34
 
41
-// WithCheckpoint allows a container to be created from the checkpointed information
42
-// provided by the descriptor. The image, snapshot, and runtime specifications are
43
-// restored on the container
44
-func WithCheckpoint(im Image, snapshotKey string) NewContainerOpts {
45
-	// set image and rw, and spec
46
-	return func(ctx context.Context, client *Client, c *containers.Container) error {
47
-		var (
48
-			desc  = im.Target()
49
-			store = client.ContentStore()
50
-		)
51
-		index, err := decodeIndex(ctx, store, desc)
52
-		if err != nil {
53
-			return err
54
-		}
55
-		var rw *v1.Descriptor
56
-		for _, m := range index.Manifests {
57
-			switch m.MediaType {
58
-			case v1.MediaTypeImageLayer:
59
-				fk := m
60
-				rw = &fk
61
-			case images.MediaTypeDockerSchema2Manifest, images.MediaTypeDockerSchema2ManifestList:
62
-				config, err := images.Config(ctx, store, m, platforms.Default())
63
-				if err != nil {
64
-					return errors.Wrap(err, "unable to resolve image config")
65
-				}
66
-				diffIDs, err := images.RootFS(ctx, store, config)
67
-				if err != nil {
68
-					return errors.Wrap(err, "unable to get rootfs")
69
-				}
70
-				setSnapshotterIfEmpty(c)
71
-				if _, err := client.SnapshotService(c.Snapshotter).Prepare(ctx, snapshotKey, identity.ChainID(diffIDs).String()); err != nil {
72
-					if !errdefs.IsAlreadyExists(err) {
73
-						return err
74
-					}
75
-				}
76
-				c.Image = index.Annotations["image.name"]
77
-			case images.MediaTypeContainerd1CheckpointConfig:
78
-				data, err := content.ReadBlob(ctx, store, m)
79
-				if err != nil {
80
-					return errors.Wrap(err, "unable to read checkpoint config")
81
-				}
82
-				var any protobuf.Any
83
-				if err := proto.Unmarshal(data, &any); err != nil {
84
-					return err
85
-				}
86
-				c.Spec = &any
87
-			}
88
-		}
89
-		if rw != nil {
90
-			// apply the rw snapshot to the new rw layer
91
-			mounts, err := client.SnapshotService(c.Snapshotter).Mounts(ctx, snapshotKey)
92
-			if err != nil {
93
-				return errors.Wrapf(err, "unable to get mounts for %s", snapshotKey)
94
-			}
95
-			if _, err := client.DiffService().Apply(ctx, *rw, mounts); err != nil {
96
-				return errors.Wrap(err, "unable to apply rw diff")
97
-			}
98
-		}
99
-		c.SnapshotKey = snapshotKey
100
-		return nil
101
-	}
102
-}
103
-
104 35
 // WithRemappedSnapshot creates a new snapshot and remaps the uid/gid for the
105 36
 // filesystem to be used by a container with user namespaces
106 37
 func WithRemappedSnapshot(id string, i Image, uid, gid uint32) NewContainerOpts {
107 38
new file mode 100644
... ...
@@ -0,0 +1,150 @@
0
+/*
1
+   Copyright The containerd Authors.
2
+
3
+   Licensed under the Apache License, Version 2.0 (the "License");
4
+   you may not use this file except in compliance with the License.
5
+   You may obtain a copy of the License at
6
+
7
+       http://www.apache.org/licenses/LICENSE-2.0
8
+
9
+   Unless required by applicable law or agreed to in writing, software
10
+   distributed under the License is distributed on an "AS IS" BASIS,
11
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+   See the License for the specific language governing permissions and
13
+   limitations under the License.
14
+*/
15
+
16
+package containerd
17
+
18
+import (
19
+	"context"
20
+
21
+	"github.com/containerd/containerd/containers"
22
+	"github.com/containerd/containerd/content"
23
+	"github.com/containerd/containerd/images"
24
+	"github.com/containerd/containerd/platforms"
25
+	"github.com/gogo/protobuf/proto"
26
+	ptypes "github.com/gogo/protobuf/types"
27
+	"github.com/opencontainers/image-spec/identity"
28
+	imagespec "github.com/opencontainers/image-spec/specs-go/v1"
29
+	"github.com/pkg/errors"
30
+)
31
+
32
+var (
33
+	// ErrImageNameNotFoundInIndex is returned when the image name is not found in the index
34
+	ErrImageNameNotFoundInIndex = errors.New("image name not found in index")
35
+	// ErrRuntimeNameNotFoundInIndex is returned when the runtime is not found in the index
36
+	ErrRuntimeNameNotFoundInIndex = errors.New("runtime not found in index")
37
+	// ErrSnapshotterNameNotFoundInIndex is returned when the snapshotter is not found in the index
38
+	ErrSnapshotterNameNotFoundInIndex = errors.New("snapshotter not found in index")
39
+)
40
+
41
+// RestoreOpts are options to manage the restore operation
42
+type RestoreOpts func(context.Context, string, *Client, Image, *imagespec.Index) NewContainerOpts
43
+
44
+// WithRestoreImage restores the image for the container
45
+func WithRestoreImage(ctx context.Context, id string, client *Client, checkpoint Image, index *imagespec.Index) NewContainerOpts {
46
+	return func(ctx context.Context, client *Client, c *containers.Container) error {
47
+		name, ok := index.Annotations[checkpointImageNameLabel]
48
+		if !ok || name == "" {
49
+			return ErrRuntimeNameNotFoundInIndex
50
+		}
51
+		snapshotter, ok := index.Annotations[checkpointSnapshotterNameLabel]
52
+		if !ok || name == "" {
53
+			return ErrSnapshotterNameNotFoundInIndex
54
+		}
55
+		i, err := client.GetImage(ctx, name)
56
+		if err != nil {
57
+			return err
58
+		}
59
+
60
+		diffIDs, err := i.(*image).i.RootFS(ctx, client.ContentStore(), platforms.Default())
61
+		if err != nil {
62
+			return err
63
+		}
64
+		parent := identity.ChainID(diffIDs).String()
65
+		if _, err := client.SnapshotService(snapshotter).Prepare(ctx, id, parent); err != nil {
66
+			return err
67
+		}
68
+		c.Image = i.Name()
69
+		c.SnapshotKey = id
70
+		c.Snapshotter = snapshotter
71
+		return nil
72
+	}
73
+}
74
+
75
+// WithRestoreRuntime restores the runtime for the container
76
+func WithRestoreRuntime(ctx context.Context, id string, client *Client, checkpoint Image, index *imagespec.Index) NewContainerOpts {
77
+	return func(ctx context.Context, client *Client, c *containers.Container) error {
78
+		name, ok := index.Annotations[checkpointRuntimeNameLabel]
79
+		if !ok {
80
+			return ErrRuntimeNameNotFoundInIndex
81
+		}
82
+
83
+		// restore options if present
84
+		m, err := GetIndexByMediaType(index, images.MediaTypeContainerd1CheckpointRuntimeOptions)
85
+		if err != nil {
86
+			if err != ErrMediaTypeNotFound {
87
+				return err
88
+			}
89
+		}
90
+		var options *ptypes.Any
91
+		if m != nil {
92
+			store := client.ContentStore()
93
+			data, err := content.ReadBlob(ctx, store, *m)
94
+			if err != nil {
95
+				return errors.Wrap(err, "unable to read checkpoint runtime")
96
+			}
97
+			if err := proto.Unmarshal(data, options); err != nil {
98
+				return err
99
+			}
100
+		}
101
+
102
+		c.Runtime = containers.RuntimeInfo{
103
+			Name:    name,
104
+			Options: options,
105
+		}
106
+		return nil
107
+	}
108
+}
109
+
110
+// WithRestoreSpec restores the spec from the checkpoint for the container
111
+func WithRestoreSpec(ctx context.Context, id string, client *Client, checkpoint Image, index *imagespec.Index) NewContainerOpts {
112
+	return func(ctx context.Context, client *Client, c *containers.Container) error {
113
+		m, err := GetIndexByMediaType(index, images.MediaTypeContainerd1CheckpointConfig)
114
+		if err != nil {
115
+			return err
116
+		}
117
+		store := client.ContentStore()
118
+		data, err := content.ReadBlob(ctx, store, *m)
119
+		if err != nil {
120
+			return errors.Wrap(err, "unable to read checkpoint config")
121
+		}
122
+		var any ptypes.Any
123
+		if err := proto.Unmarshal(data, &any); err != nil {
124
+			return err
125
+		}
126
+		c.Spec = &any
127
+		return nil
128
+	}
129
+}
130
+
131
+// WithRestoreRW restores the rw layer from the checkpoint for the container
132
+func WithRestoreRW(ctx context.Context, id string, client *Client, checkpoint Image, index *imagespec.Index) NewContainerOpts {
133
+	return func(ctx context.Context, client *Client, c *containers.Container) error {
134
+		// apply rw layer
135
+		rw, err := GetIndexByMediaType(index, imagespec.MediaTypeImageLayerGzip)
136
+		if err != nil {
137
+			return err
138
+		}
139
+		mounts, err := client.SnapshotService(c.Snapshotter).Mounts(ctx, c.SnapshotKey)
140
+		if err != nil {
141
+			return err
142
+		}
143
+
144
+		if _, err := client.DiffService().Apply(ctx, *rw, mounts); err != nil {
145
+			return err
146
+		}
147
+		return nil
148
+	}
149
+}
... ...
@@ -86,6 +86,10 @@ type RuntimeInfo struct {
86 86
 
87 87
 // Store interacts with the underlying container storage
88 88
 type Store interface {
89
+	// Get a container using the id.
90
+	//
91
+	// Container object is returned on success. If the id is not known to the
92
+	// store, an error will be returned.
89 93
 	Get(ctx context.Context, id string) (Container, error)
90 94
 
91 95
 	// List returns containers that match one or more of the provided filters.
... ...
@@ -95,7 +95,7 @@ func FromGRPC(err error) error {
95 95
 
96 96
 	msg := rebaseMessage(cls, err)
97 97
 	if msg != "" {
98
-		err = errors.Wrapf(cls, msg)
98
+		err = errors.Wrap(cls, msg)
99 99
 	} else {
100 100
 		err = errors.WithStack(cls)
101 101
 	}
... ...
@@ -138,10 +138,10 @@ func (e *Exchange) Subscribe(ctx context.Context, fs ...string) (ch <-chan *even
138 138
 	)
139 139
 
140 140
 	closeAll := func() {
141
-		defer close(errq)
142
-		defer e.broadcaster.Remove(dst)
143
-		defer queue.Close()
144
-		defer channel.Close()
141
+		channel.Close()
142
+		queue.Close()
143
+		e.broadcaster.Remove(dst)
144
+		close(errq)
145 145
 	}
146 146
 
147 147
 	ch = evch
... ...
@@ -20,36 +20,23 @@ import (
20 20
 	"context"
21 21
 	"io"
22 22
 
23
-	"github.com/containerd/containerd/images"
23
+	"github.com/containerd/containerd/images/oci"
24
+
24 25
 	ocispec "github.com/opencontainers/image-spec/specs-go/v1"
25 26
 	"github.com/pkg/errors"
26 27
 )
27 28
 
28
-type exportOpts struct {
29
-}
30
-
31
-// ExportOpt allows the caller to specify export-specific options
32
-type ExportOpt func(c *exportOpts) error
33
-
34
-func resolveExportOpt(opts ...ExportOpt) (exportOpts, error) {
35
-	var eopts exportOpts
36
-	for _, o := range opts {
37
-		if err := o(&eopts); err != nil {
38
-			return eopts, err
39
-		}
40
-	}
41
-	return eopts, nil
42
-}
43
-
44 29
 // Export exports an image to a Tar stream.
45 30
 // OCI format is used by default.
46 31
 // It is up to caller to put "org.opencontainers.image.ref.name" annotation to desc.
47 32
 // TODO(AkihiroSuda): support exporting multiple descriptors at once to a single archive stream.
48
-func (c *Client) Export(ctx context.Context, exporter images.Exporter, desc ocispec.Descriptor, opts ...ExportOpt) (io.ReadCloser, error) {
49
-	_, err := resolveExportOpt(opts...) // unused now
33
+func (c *Client) Export(ctx context.Context, desc ocispec.Descriptor, opts ...oci.V1ExporterOpt) (io.ReadCloser, error) {
34
+
35
+	exporter, err := oci.ResolveV1ExportOpt(opts...)
50 36
 	if err != nil {
51 37
 		return nil, err
52 38
 	}
39
+
53 40
 	pr, pw := io.Pipe()
54 41
 	go func() {
55 42
 		pw.CloseWithError(errors.Wrap(exporter.Export(ctx, c.ContentStore(), desc, pw), "export failed"))
... ...
@@ -71,7 +71,7 @@ func ParseAll(ss ...string) (Filter, error) {
71 71
 	for _, s := range ss {
72 72
 		f, err := Parse(s)
73 73
 		if err != nil {
74
-			return nil, errors.Wrapf(errdefs.ErrInvalidArgument, err.Error())
74
+			return nil, errors.Wrap(errdefs.ErrInvalidArgument, err.Error())
75 75
 		}
76 76
 
77 77
 		fs = append(fs, f)
... ...
@@ -45,7 +45,7 @@ var (
45 45
 // Validate return nil if the string s is a valid identifier.
46 46
 //
47 47
 // identifiers must be valid domain names according to RFC 1035, section 2.3.1.  To
48
-// enforce case insensitvity, all characters must be lower case.
48
+// enforce case insensitivity, all characters must be lower case.
49 49
 //
50 50
 // In general, identifiers that pass this validation, should be safe for use as
51 51
 // a domain names or filesystem path component.
... ...
@@ -26,6 +26,7 @@ import (
26 26
 	ocispec "github.com/opencontainers/image-spec/specs-go/v1"
27 27
 	"github.com/pkg/errors"
28 28
 	"golang.org/x/sync/errgroup"
29
+	"golang.org/x/sync/semaphore"
29 30
 )
30 31
 
31 32
 var (
... ...
@@ -108,19 +109,30 @@ func Walk(ctx context.Context, handler Handler, descs ...ocispec.Descriptor) err
108 108
 // handler may return `ErrSkipDesc` to signal to the dispatcher to not traverse
109 109
 // any children.
110 110
 //
111
+// A concurrency limiter can be passed in to limit the number of concurrent
112
+// handlers running. When limiter is nil, there is no limit.
113
+//
111 114
 // Typically, this function will be used with `FetchHandler`, often composed
112 115
 // with other handlers.
113 116
 //
114 117
 // If any handler returns an error, the dispatch session will be canceled.
115
-func Dispatch(ctx context.Context, handler Handler, descs ...ocispec.Descriptor) error {
118
+func Dispatch(ctx context.Context, handler Handler, limiter *semaphore.Weighted, descs ...ocispec.Descriptor) error {
116 119
 	eg, ctx := errgroup.WithContext(ctx)
117 120
 	for _, desc := range descs {
118 121
 		desc := desc
119 122
 
123
+		if limiter != nil {
124
+			if err := limiter.Acquire(ctx, 1); err != nil {
125
+				return err
126
+			}
127
+		}
120 128
 		eg.Go(func() error {
121 129
 			desc := desc
122 130
 
123 131
 			children, err := handler.Handle(ctx, desc)
132
+			if limiter != nil {
133
+				limiter.Release(1)
134
+			}
124 135
 			if err != nil {
125 136
 				if errors.Cause(err) == ErrSkipDesc {
126 137
 					return nil // don't traverse the children.
... ...
@@ -129,7 +141,7 @@ func Dispatch(ctx context.Context, handler Handler, descs ...ocispec.Descriptor)
129 129
 			}
130 130
 
131 131
 			if len(children) > 0 {
132
-				return Dispatch(ctx, handler, children...)
132
+				return Dispatch(ctx, handler, limiter, children...)
133 133
 			}
134 134
 
135 135
 			return nil
... ...
@@ -29,11 +29,14 @@ const (
29 29
 	MediaTypeDockerSchema2Manifest         = "application/vnd.docker.distribution.manifest.v2+json"
30 30
 	MediaTypeDockerSchema2ManifestList     = "application/vnd.docker.distribution.manifest.list.v2+json"
31 31
 	// Checkpoint/Restore Media Types
32
-	MediaTypeContainerd1Checkpoint        = "application/vnd.containerd.container.criu.checkpoint.criu.tar"
33
-	MediaTypeContainerd1CheckpointPreDump = "application/vnd.containerd.container.criu.checkpoint.predump.tar"
34
-	MediaTypeContainerd1Resource          = "application/vnd.containerd.container.resource.tar"
35
-	MediaTypeContainerd1RW                = "application/vnd.containerd.container.rw.tar"
36
-	MediaTypeContainerd1CheckpointConfig  = "application/vnd.containerd.container.checkpoint.config.v1+proto"
32
+	MediaTypeContainerd1Checkpoint               = "application/vnd.containerd.container.criu.checkpoint.criu.tar"
33
+	MediaTypeContainerd1CheckpointPreDump        = "application/vnd.containerd.container.criu.checkpoint.predump.tar"
34
+	MediaTypeContainerd1Resource                 = "application/vnd.containerd.container.resource.tar"
35
+	MediaTypeContainerd1RW                       = "application/vnd.containerd.container.rw.tar"
36
+	MediaTypeContainerd1CheckpointConfig         = "application/vnd.containerd.container.checkpoint.config.v1+proto"
37
+	MediaTypeContainerd1CheckpointOptions        = "application/vnd.containerd.container.checkpoint.options.v1+proto"
38
+	MediaTypeContainerd1CheckpointRuntimeName    = "application/vnd.containerd.container.checkpoint.runtime.name"
39
+	MediaTypeContainerd1CheckpointRuntimeOptions = "application/vnd.containerd.container.checkpoint.runtime.options+proto"
37 40
 	// Legacy Docker schema1 manifest
38 41
 	MediaTypeDockerSchema1Manifest = "application/vnd.docker.distribution.manifest.v1+prettyjws"
39 42
 )
40 43
new file mode 100644
... ...
@@ -0,0 +1,241 @@
0
+/*
1
+   Copyright The containerd Authors.
2
+
3
+   Licensed under the Apache License, Version 2.0 (the "License");
4
+   you may not use this file except in compliance with the License.
5
+   You may obtain a copy of the License at
6
+
7
+       http://www.apache.org/licenses/LICENSE-2.0
8
+
9
+   Unless required by applicable law or agreed to in writing, software
10
+   distributed under the License is distributed on an "AS IS" BASIS,
11
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+   See the License for the specific language governing permissions and
13
+   limitations under the License.
14
+*/
15
+
16
+package oci
17
+
18
+import (
19
+	"archive/tar"
20
+	"context"
21
+	"encoding/json"
22
+	"io"
23
+	"sort"
24
+
25
+	"github.com/containerd/containerd/content"
26
+	"github.com/containerd/containerd/images"
27
+	"github.com/containerd/containerd/platforms"
28
+	ocispecs "github.com/opencontainers/image-spec/specs-go"
29
+	ocispec "github.com/opencontainers/image-spec/specs-go/v1"
30
+	"github.com/pkg/errors"
31
+)
32
+
33
+// V1Exporter implements OCI Image Spec v1.
34
+// It is up to caller to put "org.opencontainers.image.ref.name" annotation to desc.
35
+//
36
+// TODO(AkihiroSuda): add V1Exporter{TranslateMediaTypes: true} that transforms media types,
37
+//                    e.g. application/vnd.docker.image.rootfs.diff.tar.gzip
38
+//                         -> application/vnd.oci.image.layer.v1.tar+gzip
39
+type V1Exporter struct {
40
+	AllPlatforms bool
41
+}
42
+
43
+// V1ExporterOpt allows the caller to set additional options to a new V1Exporter
44
+type V1ExporterOpt func(c *V1Exporter) error
45
+
46
+// DefaultV1Exporter return a default V1Exporter pointer
47
+func DefaultV1Exporter() *V1Exporter {
48
+	return &V1Exporter{
49
+		AllPlatforms: false,
50
+	}
51
+}
52
+
53
+// ResolveV1ExportOpt return a new V1Exporter with V1ExporterOpt
54
+func ResolveV1ExportOpt(opts ...V1ExporterOpt) (*V1Exporter, error) {
55
+	exporter := DefaultV1Exporter()
56
+	for _, o := range opts {
57
+		if err := o(exporter); err != nil {
58
+			return exporter, err
59
+		}
60
+	}
61
+	return exporter, nil
62
+}
63
+
64
+// WithAllPlatforms set V1Exporter`s AllPlatforms option
65
+func WithAllPlatforms(allPlatforms bool) V1ExporterOpt {
66
+	return func(c *V1Exporter) error {
67
+		c.AllPlatforms = allPlatforms
68
+		return nil
69
+	}
70
+}
71
+
72
+// Export implements Exporter.
73
+func (oe *V1Exporter) Export(ctx context.Context, store content.Provider, desc ocispec.Descriptor, writer io.Writer) error {
74
+	tw := tar.NewWriter(writer)
75
+	defer tw.Close()
76
+
77
+	records := []tarRecord{
78
+		ociLayoutFile(""),
79
+		ociIndexRecord(desc),
80
+	}
81
+
82
+	algorithms := map[string]struct{}{}
83
+	exportHandler := func(ctx context.Context, desc ocispec.Descriptor) ([]ocispec.Descriptor, error) {
84
+		records = append(records, blobRecord(store, desc))
85
+		algorithms[desc.Digest.Algorithm().String()] = struct{}{}
86
+		return nil, nil
87
+	}
88
+
89
+	childrenHandler := images.ChildrenHandler(store)
90
+
91
+	if !oe.AllPlatforms {
92
+		// get local default platform to fetch image manifest
93
+		childrenHandler = images.FilterPlatforms(childrenHandler, platforms.Any(platforms.DefaultSpec()))
94
+	}
95
+
96
+	handlers := images.Handlers(
97
+		childrenHandler,
98
+		images.HandlerFunc(exportHandler),
99
+	)
100
+
101
+	// Walk sequentially since the number of fetchs is likely one and doing in
102
+	// parallel requires locking the export handler
103
+	if err := images.Walk(ctx, handlers, desc); err != nil {
104
+		return err
105
+	}
106
+
107
+	if len(algorithms) > 0 {
108
+		records = append(records, directoryRecord("blobs/", 0755))
109
+		for alg := range algorithms {
110
+			records = append(records, directoryRecord("blobs/"+alg+"/", 0755))
111
+		}
112
+	}
113
+
114
+	return writeTar(ctx, tw, records)
115
+}
116
+
117
+type tarRecord struct {
118
+	Header *tar.Header
119
+	CopyTo func(context.Context, io.Writer) (int64, error)
120
+}
121
+
122
+func blobRecord(cs content.Provider, desc ocispec.Descriptor) tarRecord {
123
+	path := "blobs/" + desc.Digest.Algorithm().String() + "/" + desc.Digest.Hex()
124
+	return tarRecord{
125
+		Header: &tar.Header{
126
+			Name:     path,
127
+			Mode:     0444,
128
+			Size:     desc.Size,
129
+			Typeflag: tar.TypeReg,
130
+		},
131
+		CopyTo: func(ctx context.Context, w io.Writer) (int64, error) {
132
+			r, err := cs.ReaderAt(ctx, desc)
133
+			if err != nil {
134
+				return 0, errors.Wrap(err, "failed to get reader")
135
+			}
136
+			defer r.Close()
137
+
138
+			// Verify digest
139
+			dgstr := desc.Digest.Algorithm().Digester()
140
+
141
+			n, err := io.Copy(io.MultiWriter(w, dgstr.Hash()), content.NewReader(r))
142
+			if err != nil {
143
+				return 0, errors.Wrap(err, "failed to copy to tar")
144
+			}
145
+			if dgstr.Digest() != desc.Digest {
146
+				return 0, errors.Errorf("unexpected digest %s copied", dgstr.Digest())
147
+			}
148
+			return n, nil
149
+		},
150
+	}
151
+}
152
+
153
+func directoryRecord(name string, mode int64) tarRecord {
154
+	return tarRecord{
155
+		Header: &tar.Header{
156
+			Name:     name,
157
+			Mode:     mode,
158
+			Typeflag: tar.TypeDir,
159
+		},
160
+	}
161
+}
162
+
163
+func ociLayoutFile(version string) tarRecord {
164
+	if version == "" {
165
+		version = ocispec.ImageLayoutVersion
166
+	}
167
+	layout := ocispec.ImageLayout{
168
+		Version: version,
169
+	}
170
+
171
+	b, err := json.Marshal(layout)
172
+	if err != nil {
173
+		panic(err)
174
+	}
175
+
176
+	return tarRecord{
177
+		Header: &tar.Header{
178
+			Name:     ocispec.ImageLayoutFile,
179
+			Mode:     0444,
180
+			Size:     int64(len(b)),
181
+			Typeflag: tar.TypeReg,
182
+		},
183
+		CopyTo: func(ctx context.Context, w io.Writer) (int64, error) {
184
+			n, err := w.Write(b)
185
+			return int64(n), err
186
+		},
187
+	}
188
+
189
+}
190
+
191
+func ociIndexRecord(manifests ...ocispec.Descriptor) tarRecord {
192
+	index := ocispec.Index{
193
+		Versioned: ocispecs.Versioned{
194
+			SchemaVersion: 2,
195
+		},
196
+		Manifests: manifests,
197
+	}
198
+
199
+	b, err := json.Marshal(index)
200
+	if err != nil {
201
+		panic(err)
202
+	}
203
+
204
+	return tarRecord{
205
+		Header: &tar.Header{
206
+			Name:     "index.json",
207
+			Mode:     0644,
208
+			Size:     int64(len(b)),
209
+			Typeflag: tar.TypeReg,
210
+		},
211
+		CopyTo: func(ctx context.Context, w io.Writer) (int64, error) {
212
+			n, err := w.Write(b)
213
+			return int64(n), err
214
+		},
215
+	}
216
+}
217
+
218
+func writeTar(ctx context.Context, tw *tar.Writer, records []tarRecord) error {
219
+	sort.Slice(records, func(i, j int) bool {
220
+		return records[i].Header.Name < records[j].Header.Name
221
+	})
222
+
223
+	for _, record := range records {
224
+		if err := tw.WriteHeader(record.Header); err != nil {
225
+			return err
226
+		}
227
+		if record.CopyTo != nil {
228
+			n, err := record.CopyTo(ctx, tw)
229
+			if err != nil {
230
+				return err
231
+			}
232
+			if n != record.Header.Size {
233
+				return errors.Errorf("unexpected copy size for %s", record.Header.Name)
234
+			}
235
+		} else if record.Header.Size > 0 {
236
+			return errors.Errorf("no content to write to record with non-zero size for %s", record.Header.Name)
237
+		}
238
+	}
239
+	return nil
240
+}
... ...
@@ -59,7 +59,6 @@ func (c *Client) Install(ctx context.Context, image Image, opts ...InstallOpts)
59 59
 		if err != nil {
60 60
 			return err
61 61
 		}
62
-		defer r.Close()
63 62
 		if _, err := archive.Apply(ctx, path, r, archive.WithFilter(func(hdr *tar.Header) (bool, error) {
64 63
 			d := filepath.Dir(hdr.Name)
65 64
 			result := d == "bin"
... ...
@@ -73,8 +72,10 @@ func (c *Client) Install(ctx context.Context, image Image, opts ...InstallOpts)
73 73
 			}
74 74
 			return result, nil
75 75
 		})); err != nil {
76
+			r.Close()
76 77
 			return err
77 78
 		}
79
+		r.Close()
78 80
 	}
79 81
 	return nil
80 82
 }
... ...
@@ -14,13 +14,11 @@
14 14
    limitations under the License.
15 15
 */
16 16
 
17
-package metadata
18
-
19
-import (
20
-	digest "github.com/opencontainers/go-digest"
21
-	bolt "go.etcd.io/bbolt"
22
-)
23
-
17
+// Package metadata stores all labels and object specific metadata by namespace.
18
+// This package also contains the main garbage collection logic  for cleaning up
19
+// resources consistently and atomically. Resources used by backends will be
20
+// tracked in the metadata store to be exposed to consumers of this package.
21
+//
24 22
 // The layout where a "/" delineates a bucket is described in the following
25 23
 // section. Please try to follow this as closely as possible when adding
26 24
 // functionality. We can bolster this with helpers and more structure if that
... ...
@@ -43,6 +41,84 @@ import (
43 43
 //
44 44
 // key: object-specific key identifying the storage bucket for the objects
45 45
 // contents.
46
+//
47
+// Below is the current database schema. This should be updated each time
48
+// the structure is changed in addition to adding a migration and incrementing
49
+// the database version. Note that `╘══*...*` refers to maps with arbitrary
50
+// keys.
51
+//  ├──version : <varint>                        - Latest version, see migrations
52
+//  └──v1                                        - Schema version bucket
53
+//     ╘══*namespace*
54
+//        ├──labels
55
+//        │  ╘══*key* : <string>                 - Label value
56
+//        ├──image
57
+//        │  ╘══*image name*
58
+//        │     ├──createdat : <binary time>     - Created at
59
+//        │     ├──updatedat : <binary time>     - Updated at
60
+//        │     ├──target
61
+//        │     │  ├──digest : <digest>          - Descriptor digest
62
+//        │     │  ├──mediatype : <string>       - Descriptor media type
63
+//        │     │  └──size : <varint>            - Descriptor size
64
+//        │     └──labels
65
+//        │        ╘══*key* : <string>           - Label value
66
+//        ├──containers
67
+//        │  ╘══*container id*
68
+//        │     ├──createdat : <binary time>     - Created at
69
+//        │     ├──updatedat : <binary time>     - Updated at
70
+//        │     ├──spec : <binary>               - Proto marshaled spec
71
+//        │     ├──image : <string>              - Image name
72
+//        │     ├──snapshotter : <string>        - Snapshotter name
73
+//        │     ├──snapshotKey : <string>        - Snapshot key
74
+//        │     ├──runtime
75
+//        │     │  ├──name : <string>            - Runtime name
76
+//        │     │  ├──extensions
77
+//        │     │  │  ╘══*name* : <binary>       - Proto marshaled extension
78
+//        │     │  └──options : <binary>         - Proto marshaled options
79
+//        │     └──labels
80
+//        │        ╘══*key* : <string>           - Label value
81
+//        ├──snapshots
82
+//        │  ╘══*snapshotter*
83
+//        │     ╘══*snapshot key*
84
+//        │        ├──name : <string>            - Snapshot name in backend
85
+//        │        ├──createdat : <binary time>  - Created at
86
+//        │        ├──updatedat : <binary time>  - Updated at
87
+//        │        ├──parent : <string>          - Parent snapshot name
88
+//        │        ├──children
89
+//        │        │  ╘══*snapshot key* : <nil>  - Child snapshot reference
90
+//        │        └──labels
91
+//        │           ╘══*key* : <string>        - Label value
92
+//        ├──content
93
+//        │  ├──blob
94
+//        │  │  ╘══*blob digest*
95
+//        │  │     ├──createdat : <binary time>  - Created at
96
+//        │  │     ├──updatedat : <binary time>  - Updated at
97
+//        │  │     ├──size : <varint>            - Blob size
98
+//        │  │     └──labels
99
+//        │  │        ╘══*key* : <string>        - Label value
100
+//        │  └──ingests
101
+//        │     ╘══*ingest reference*
102
+//        │        ├──ref : <string>             - Ingest reference in backend
103
+//        │        ├──expireat : <binary time>   - Time to expire ingest
104
+//        │        └──expected : <digest>        - Expected commit digest
105
+//        └──leases
106
+//           ╘══*lease id*
107
+//              ├──createdat : <binary time>     - Created at
108
+//              ├──labels
109
+//              │  ╘══*key* : <string>           - Label value
110
+//              ├──snapshots
111
+//              │  ╘══*snapshotter*
112
+//              │     ╘══*snapshot key* : <nil>  - Snapshot reference
113
+//              ├──content
114
+//              │  ╘══*blob digest* : <nil>      - Content blob reference
115
+//              └──ingests
116
+//                 ╘══*ingest reference* : <nil> - Content ingest reference
117
+package metadata
118
+
119
+import (
120
+	digest "github.com/opencontainers/go-digest"
121
+	bolt "go.etcd.io/bbolt"
122
+)
123
+
46 124
 var (
47 125
 	bucketKeyVersion          = []byte(schemaVersion)
48 126
 	bucketKeyDBVersion        = []byte("version")    // stores the version of the schema
... ...
@@ -72,7 +72,7 @@ func (s *containerStore) List(ctx context.Context, fs ...string) ([]containers.C
72 72
 
73 73
 	filter, err := filters.ParseAll(fs...)
74 74
 	if err != nil {
75
-		return nil, errors.Wrapf(errdefs.ErrInvalidArgument, err.Error())
75
+		return nil, errors.Wrap(errdefs.ErrInvalidArgument, err.Error())
76 76
 	}
77 77
 
78 78
 	bkt := getContainersBucket(s.tx, namespace)
... ...
@@ -38,16 +38,31 @@ import (
38 38
 
39 39
 type contentStore struct {
40 40
 	content.Store
41
-	db *DB
42
-	l  sync.RWMutex
41
+	db     *DB
42
+	shared bool
43
+	l      sync.RWMutex
43 44
 }
44 45
 
45 46
 // newContentStore returns a namespaced content store using an existing
46 47
 // content store interface.
47
-func newContentStore(db *DB, cs content.Store) *contentStore {
48
+// policy defines the sharing behavior for content between namespaces. Both
49
+// modes will result in shared storage in the backend for committed. Choose
50
+// "shared" to prevent separate namespaces from having to pull the same content
51
+// twice.  Choose "isolated" if the content must not be shared between
52
+// namespaces.
53
+//
54
+// If the policy is "shared", writes will try to resolve the "expected" digest
55
+// against the backend, allowing imports of content from other namespaces. In
56
+// "isolated" mode, the client must prove they have the content by providing
57
+// the entire blob before the content can be added to another namespace.
58
+//
59
+// Since we have only two policies right now, it's simpler using bool to
60
+// represent it internally.
61
+func newContentStore(db *DB, shared bool, cs content.Store) *contentStore {
48 62
 	return &contentStore{
49
-		Store: cs,
50
-		db:    db,
63
+		Store:  cs,
64
+		db:     db,
65
+		shared: shared,
51 66
 	}
52 67
 }
53 68
 
... ...
@@ -383,13 +398,15 @@ func (cs *contentStore) Writer(ctx context.Context, opts ...content.WriterOpt) (
383 383
 				return nil
384 384
 			}
385 385
 
386
-			if st, err := cs.Store.Info(ctx, wOpts.Desc.Digest); err == nil {
387
-				// Ensure the expected size is the same, it is likely
388
-				// an error if the size is mismatched but the caller
389
-				// must resolve this on commit
390
-				if wOpts.Desc.Size == 0 || wOpts.Desc.Size == st.Size {
391
-					shared = true
392
-					wOpts.Desc.Size = st.Size
386
+			if cs.shared {
387
+				if st, err := cs.Store.Info(ctx, wOpts.Desc.Digest); err == nil {
388
+					// Ensure the expected size is the same, it is likely
389
+					// an error if the size is mismatched but the caller
390
+					// must resolve this on commit
391
+					if wOpts.Desc.Size == 0 || wOpts.Desc.Size == st.Size {
392
+						shared = true
393
+						wOpts.Desc.Size = st.Size
394
+					}
393 395
 				}
394 396
 			}
395 397
 		}
... ...
@@ -46,6 +46,19 @@ const (
46 46
 	dbVersion = 3
47 47
 )
48 48
 
49
+// DBOpt configures how we set up the DB
50
+type DBOpt func(*dbOptions)
51
+
52
+// WithPolicyIsolated isolates contents between namespaces
53
+func WithPolicyIsolated(o *dbOptions) {
54
+	o.shared = false
55
+}
56
+
57
+// dbOptions configure db options.
58
+type dbOptions struct {
59
+	shared bool
60
+}
61
+
49 62
 // DB represents a metadata database backed by a bolt
50 63
 // database. The database is fully namespaced and stores
51 64
 // image, container, namespace, snapshot, and content data
... ...
@@ -72,19 +85,28 @@ type DB struct {
72 72
 	// mutationCallbacks are called after each mutation with the flag
73 73
 	// set indicating whether any dirty flags are set
74 74
 	mutationCallbacks []func(bool)
75
+
76
+	dbopts dbOptions
75 77
 }
76 78
 
77 79
 // NewDB creates a new metadata database using the provided
78 80
 // bolt database, content store, and snapshotters.
79
-func NewDB(db *bolt.DB, cs content.Store, ss map[string]snapshots.Snapshotter) *DB {
81
+func NewDB(db *bolt.DB, cs content.Store, ss map[string]snapshots.Snapshotter, opts ...DBOpt) *DB {
80 82
 	m := &DB{
81 83
 		db:      db,
82 84
 		ss:      make(map[string]*snapshotter, len(ss)),
83 85
 		dirtySS: map[string]struct{}{},
86
+		dbopts: dbOptions{
87
+			shared: true,
88
+		},
89
+	}
90
+
91
+	for _, opt := range opts {
92
+		opt(&m.dbopts)
84 93
 	}
85 94
 
86 95
 	// Initialize data stores
87
-	m.cs = newContentStore(m, cs)
96
+	m.cs = newContentStore(m, m.dbopts.shared, cs)
88 97
 	for name, sn := range ss {
89 98
 		m.ss[name] = newSnapshotter(m, name, sn)
90 99
 	}
... ...
@@ -84,7 +84,7 @@ func (s *imageStore) List(ctx context.Context, fs ...string) ([]images.Image, er
84 84
 
85 85
 	filter, err := filters.ParseAll(fs...)
86 86
 	if err != nil {
87
-		return nil, errors.Wrapf(errdefs.ErrInvalidArgument, err.Error())
87
+		return nil, errors.Wrap(errdefs.ErrInvalidArgument, err.Error())
88 88
 	}
89 89
 
90 90
 	var m []images.Image
... ...
@@ -122,7 +122,7 @@ func (lm *LeaseManager) List(ctx context.Context, fs ...string) ([]leases.Lease,
122 122
 
123 123
 	filter, err := filters.ParseAll(fs...)
124 124
 	if err != nil {
125
-		return nil, errors.Wrapf(errdefs.ErrInvalidArgument, err.Error())
125
+		return nil, errors.Wrap(errdefs.ErrInvalidArgument, err.Error())
126 126
 	}
127 127
 
128 128
 	var ll []leases.Lease
... ...
@@ -232,7 +232,7 @@ func overlayInfo(info, overlay snapshots.Info) snapshots.Info {
232 232
 		info.Labels = overlay.Labels
233 233
 	} else {
234 234
 		for k, v := range overlay.Labels {
235
-			overlay.Labels[k] = v
235
+			info.Labels[k] = v
236 236
 		}
237 237
 	}
238 238
 	return info
... ...
@@ -247,17 +247,8 @@ func populateDefaultWindowsSpec(ctx context.Context, s *Spec, id string) error {
247 247
 		Root:    &specs.Root{},
248 248
 		Process: &specs.Process{
249 249
 			Cwd: `C:\`,
250
-			ConsoleSize: &specs.Box{
251
-				Width:  80,
252
-				Height: 20,
253
-			},
254
-		},
255
-		Windows: &specs.Windows{
256
-			IgnoreFlushesDuringBoot: true,
257
-			Network: &specs.WindowsNetwork{
258
-				AllowUnqualifiedDNSQuery: true,
259
-			},
260 250
 		},
251
+		Windows: &specs.Windows{},
261 252
 	}
262 253
 	return nil
263 254
 }
... ...
@@ -141,8 +141,10 @@ func WithEnv(environmentVariables []string) SpecOpts {
141 141
 // replaced by env key or appended to the list
142 142
 func replaceOrAppendEnvValues(defaults, overrides []string) []string {
143 143
 	cache := make(map[string]int, len(defaults))
144
+	results := make([]string, 0, len(defaults))
144 145
 	for i, e := range defaults {
145 146
 		parts := strings.SplitN(e, "=", 2)
147
+		results = append(results, e)
146 148
 		cache[parts[0]] = i
147 149
 	}
148 150
 
... ...
@@ -150,7 +152,7 @@ func replaceOrAppendEnvValues(defaults, overrides []string) []string {
150 150
 		// Values w/o = means they want this env to be removed/unset.
151 151
 		if !strings.Contains(value, "=") {
152 152
 			if i, exists := cache[value]; exists {
153
-				defaults[i] = "" // Used to indicate it should be removed
153
+				results[i] = "" // Used to indicate it should be removed
154 154
 			}
155 155
 			continue
156 156
 		}
... ...
@@ -158,21 +160,21 @@ func replaceOrAppendEnvValues(defaults, overrides []string) []string {
158 158
 		// Just do a normal set/update
159 159
 		parts := strings.SplitN(value, "=", 2)
160 160
 		if i, exists := cache[parts[0]]; exists {
161
-			defaults[i] = value
161
+			results[i] = value
162 162
 		} else {
163
-			defaults = append(defaults, value)
163
+			results = append(results, value)
164 164
 		}
165 165
 	}
166 166
 
167 167
 	// Now remove all entries that we want to "unset"
168
-	for i := 0; i < len(defaults); i++ {
169
-		if defaults[i] == "" {
170
-			defaults = append(defaults[:i], defaults[i+1:]...)
168
+	for i := 0; i < len(results); i++ {
169
+		if results[i] == "" {
170
+			results = append(results[:i], results[i+1:]...)
171 171
 			i--
172 172
 		}
173 173
 	}
174 174
 
175
-	return defaults
175
+	return results
176 176
 }
177 177
 
178 178
 // WithProcessArgs replaces the args on the generated spec
... ...
@@ -310,7 +312,7 @@ func WithImageConfigArgs(image Image, args []string) SpecOpts {
310 310
 
311 311
 		setProcess(s)
312 312
 		if s.Linux != nil {
313
-			s.Process.Env = append(s.Process.Env, config.Env...)
313
+			s.Process.Env = replaceOrAppendEnvValues(s.Process.Env, config.Env)
314 314
 			cmd := config.Cmd
315 315
 			if len(args) > 0 {
316 316
 				cmd = args
... ...
@@ -332,8 +334,14 @@ func WithImageConfigArgs(image Image, args []string) SpecOpts {
332 332
 			// even if there is no specified user in the image config
333 333
 			return WithAdditionalGIDs("root")(ctx, client, c, s)
334 334
 		} else if s.Windows != nil {
335
-			s.Process.Env = config.Env
336
-			s.Process.Args = append(config.Entrypoint, config.Cmd...)
335
+			s.Process.Env = replaceOrAppendEnvValues(s.Process.Env, config.Env)
336
+			cmd := config.Cmd
337
+			if len(args) > 0 {
338
+				cmd = args
339
+			}
340
+			s.Process.Args = append(config.Entrypoint, cmd...)
341
+
342
+			s.Process.Cwd = config.WorkingDir
337 343
 			s.Process.User = specs.User{
338 344
 				Username: config.User,
339 345
 			}
... ...
@@ -1026,3 +1034,46 @@ func WithWindowsHyperV(_ context.Context, _ Client, _ *containers.Container, s *
1026 1026
 	}
1027 1027
 	return nil
1028 1028
 }
1029
+
1030
+// WithMemoryLimit sets the `Linux.LinuxResources.Memory.Limit` section to the
1031
+// `limit` specified if the `Linux` section is not `nil`. Additionally sets the
1032
+// `Windows.WindowsResources.Memory.Limit` section if the `Windows` section is
1033
+// not `nil`.
1034
+func WithMemoryLimit(limit uint64) SpecOpts {
1035
+	return func(_ context.Context, _ Client, _ *containers.Container, s *Spec) error {
1036
+		if s.Linux != nil {
1037
+			if s.Linux.Resources == nil {
1038
+				s.Linux.Resources = &specs.LinuxResources{}
1039
+			}
1040
+			if s.Linux.Resources.Memory == nil {
1041
+				s.Linux.Resources.Memory = &specs.LinuxMemory{}
1042
+			}
1043
+			l := int64(limit)
1044
+			s.Linux.Resources.Memory.Limit = &l
1045
+		}
1046
+		if s.Windows != nil {
1047
+			if s.Windows.Resources == nil {
1048
+				s.Windows.Resources = &specs.WindowsResources{}
1049
+			}
1050
+			if s.Windows.Resources.Memory == nil {
1051
+				s.Windows.Resources.Memory = &specs.WindowsMemoryResources{}
1052
+			}
1053
+			s.Windows.Resources.Memory.Limit = &limit
1054
+		}
1055
+		return nil
1056
+	}
1057
+}
1058
+
1059
+// WithAnnotations appends or replaces the annotations on the spec with the
1060
+// provided annotations
1061
+func WithAnnotations(annotations map[string]string) SpecOpts {
1062
+	return func(_ context.Context, _ Client, _ *containers.Container, s *Spec) error {
1063
+		if s.Annotations == nil {
1064
+			s.Annotations = make(map[string]string)
1065
+		}
1066
+		for k, v := range annotations {
1067
+			s.Annotations[k] = v
1068
+		}
1069
+		return nil
1070
+	}
1071
+}
1029 1072
new file mode 100644
... ...
@@ -0,0 +1,67 @@
0
+// +build windows
1
+
2
+/*
3
+   Copyright The containerd Authors.
4
+
5
+   Licensed under the Apache License, Version 2.0 (the "License");
6
+   you may not use this file except in compliance with the License.
7
+   You may obtain a copy of the License at
8
+
9
+       http://www.apache.org/licenses/LICENSE-2.0
10
+
11
+   Unless required by applicable law or agreed to in writing, software
12
+   distributed under the License is distributed on an "AS IS" BASIS,
13
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+   See the License for the specific language governing permissions and
15
+   limitations under the License.
16
+*/
17
+
18
+package oci
19
+
20
+import (
21
+	"context"
22
+
23
+	"github.com/containerd/containerd/containers"
24
+	specs "github.com/opencontainers/runtime-spec/specs-go"
25
+)
26
+
27
+// WithWindowsCPUCount sets the `Windows.Resources.CPU.Count` section to the
28
+// `count` specified.
29
+func WithWindowsCPUCount(count uint64) SpecOpts {
30
+	return func(_ context.Context, _ Client, _ *containers.Container, s *Spec) error {
31
+		if s.Windows.Resources == nil {
32
+			s.Windows.Resources = &specs.WindowsResources{}
33
+		}
34
+		if s.Windows.Resources.CPU == nil {
35
+			s.Windows.Resources.CPU = &specs.WindowsCPUResources{}
36
+		}
37
+		s.Windows.Resources.CPU.Count = &count
38
+		return nil
39
+	}
40
+}
41
+
42
+// WithWindowsIgnoreFlushesDuringBoot sets `Windows.IgnoreFlushesDuringBoot`.
43
+func WithWindowsIgnoreFlushesDuringBoot() SpecOpts {
44
+	return func(_ context.Context, _ Client, _ *containers.Container, s *Spec) error {
45
+		if s.Windows == nil {
46
+			s.Windows = &specs.Windows{}
47
+		}
48
+		s.Windows.IgnoreFlushesDuringBoot = true
49
+		return nil
50
+	}
51
+}
52
+
53
+// WithWindowNetworksAllowUnqualifiedDNSQuery sets `Windows.IgnoreFlushesDuringBoot`.
54
+func WithWindowNetworksAllowUnqualifiedDNSQuery() SpecOpts {
55
+	return func(_ context.Context, _ Client, _ *containers.Container, s *Spec) error {
56
+		if s.Windows == nil {
57
+			s.Windows = &specs.Windows{}
58
+		}
59
+		if s.Windows.Network == nil {
60
+			s.Windows.Network = &specs.WindowsNetwork{}
61
+		}
62
+
63
+		s.Windows.Network.AllowUnqualifiedDNSQuery = true
64
+		return nil
65
+	}
66
+}
... ...
@@ -75,6 +75,15 @@ const (
75 75
 	GCPlugin Type = "io.containerd.gc.v1"
76 76
 )
77 77
 
78
+const (
79
+	// RuntimeLinuxV1 is the legacy linux runtime
80
+	RuntimeLinuxV1 = "io.containerd.runtime.v1.linux"
81
+	// RuntimeRuncV1 is the runc runtime that supports a single container
82
+	RuntimeRuncV1 = "io.containerd.runc.v1"
83
+	// RuntimeRuncV2 is the runc runtime that supports multiple containers per shim
84
+	RuntimeRuncV2 = "io.containerd.runc.v2"
85
+)
86
+
78 87
 // Registration contains information for registering a plugin
79 88
 type Registration struct {
80 89
 	// Type of the plugin
81 90
new file mode 100644
... ...
@@ -0,0 +1,190 @@
0
+/*
1
+   Copyright The containerd Authors.
2
+
3
+   Licensed under the Apache License, Version 2.0 (the "License");
4
+   you may not use this file except in compliance with the License.
5
+   You may obtain a copy of the License at
6
+
7
+       http://www.apache.org/licenses/LICENSE-2.0
8
+
9
+   Unless required by applicable law or agreed to in writing, software
10
+   distributed under the License is distributed on an "AS IS" BASIS,
11
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+   See the License for the specific language governing permissions and
13
+   limitations under the License.
14
+*/
15
+
16
+package containerd
17
+
18
+import (
19
+	"context"
20
+
21
+	"github.com/containerd/containerd/errdefs"
22
+	"github.com/containerd/containerd/images"
23
+	"github.com/containerd/containerd/platforms"
24
+	"github.com/containerd/containerd/remotes"
25
+	"github.com/containerd/containerd/remotes/docker"
26
+	"github.com/containerd/containerd/remotes/docker/schema1"
27
+	ocispec "github.com/opencontainers/image-spec/specs-go/v1"
28
+	"github.com/pkg/errors"
29
+	"golang.org/x/sync/semaphore"
30
+)
31
+
32
+// Pull downloads the provided content into containerd's content store
33
+// and returns a platform specific image object
34
+func (c *Client) Pull(ctx context.Context, ref string, opts ...RemoteOpt) (Image, error) {
35
+	pullCtx := defaultRemoteContext()
36
+	for _, o := range opts {
37
+		if err := o(c, pullCtx); err != nil {
38
+			return nil, err
39
+		}
40
+	}
41
+
42
+	if pullCtx.PlatformMatcher == nil {
43
+		if len(pullCtx.Platforms) > 1 {
44
+			return nil, errors.New("cannot pull multiplatform image locally, try Fetch")
45
+		} else if len(pullCtx.Platforms) == 0 {
46
+			pullCtx.PlatformMatcher = platforms.Default()
47
+		} else {
48
+			p, err := platforms.Parse(pullCtx.Platforms[0])
49
+			if err != nil {
50
+				return nil, errors.Wrapf(err, "invalid platform %s", pullCtx.Platforms[0])
51
+			}
52
+
53
+			pullCtx.PlatformMatcher = platforms.Only(p)
54
+		}
55
+	}
56
+
57
+	ctx, done, err := c.WithLease(ctx)
58
+	if err != nil {
59
+		return nil, err
60
+	}
61
+	defer done(ctx)
62
+
63
+	img, err := c.fetch(ctx, pullCtx, ref, 1)
64
+	if err != nil {
65
+		return nil, err
66
+	}
67
+
68
+	i := NewImageWithPlatform(c, img, pullCtx.PlatformMatcher)
69
+
70
+	if pullCtx.Unpack {
71
+		if err := i.Unpack(ctx, pullCtx.Snapshotter); err != nil {
72
+			return nil, errors.Wrapf(err, "failed to unpack image on snapshotter %s", pullCtx.Snapshotter)
73
+		}
74
+	}
75
+
76
+	return i, nil
77
+}
78
+
79
+func (c *Client) fetch(ctx context.Context, rCtx *RemoteContext, ref string, limit int) (images.Image, error) {
80
+	store := c.ContentStore()
81
+	name, desc, err := rCtx.Resolver.Resolve(ctx, ref)
82
+	if err != nil {
83
+		return images.Image{}, errors.Wrapf(err, "failed to resolve reference %q", ref)
84
+	}
85
+
86
+	fetcher, err := rCtx.Resolver.Fetcher(ctx, name)
87
+	if err != nil {
88
+		return images.Image{}, errors.Wrapf(err, "failed to get fetcher for %q", name)
89
+	}
90
+
91
+	var (
92
+		handler images.Handler
93
+
94
+		isConvertible bool
95
+		converterFunc func(context.Context, ocispec.Descriptor) (ocispec.Descriptor, error)
96
+		limiter       *semaphore.Weighted
97
+	)
98
+
99
+	if desc.MediaType == images.MediaTypeDockerSchema1Manifest && rCtx.ConvertSchema1 {
100
+		schema1Converter := schema1.NewConverter(store, fetcher)
101
+
102
+		handler = images.Handlers(append(rCtx.BaseHandlers, schema1Converter)...)
103
+
104
+		isConvertible = true
105
+
106
+		converterFunc = func(ctx context.Context, _ ocispec.Descriptor) (ocispec.Descriptor, error) {
107
+			return schema1Converter.Convert(ctx)
108
+		}
109
+	} else {
110
+		// Get all the children for a descriptor
111
+		childrenHandler := images.ChildrenHandler(store)
112
+		// Set any children labels for that content
113
+		childrenHandler = images.SetChildrenLabels(store, childrenHandler)
114
+		// Filter children by platforms
115
+		childrenHandler = images.FilterPlatforms(childrenHandler, rCtx.PlatformMatcher)
116
+		// Sort and limit manifests if a finite number is needed
117
+		if limit > 0 {
118
+			childrenHandler = images.LimitManifests(childrenHandler, rCtx.PlatformMatcher, limit)
119
+		}
120
+
121
+		// set isConvertible to true if there is application/octet-stream media type
122
+		convertibleHandler := images.HandlerFunc(
123
+			func(_ context.Context, desc ocispec.Descriptor) ([]ocispec.Descriptor, error) {
124
+				if desc.MediaType == docker.LegacyConfigMediaType {
125
+					isConvertible = true
126
+				}
127
+
128
+				return []ocispec.Descriptor{}, nil
129
+			},
130
+		)
131
+
132
+		handler = images.Handlers(append(rCtx.BaseHandlers,
133
+			remotes.FetchHandler(store, fetcher),
134
+			convertibleHandler,
135
+			childrenHandler,
136
+		)...)
137
+
138
+		converterFunc = func(ctx context.Context, desc ocispec.Descriptor) (ocispec.Descriptor, error) {
139
+			return docker.ConvertManifest(ctx, store, desc)
140
+		}
141
+	}
142
+
143
+	if rCtx.HandlerWrapper != nil {
144
+		handler = rCtx.HandlerWrapper(handler)
145
+	}
146
+
147
+	if rCtx.MaxConcurrentDownloads > 0 {
148
+		limiter = semaphore.NewWeighted(int64(rCtx.MaxConcurrentDownloads))
149
+	}
150
+	if err := images.Dispatch(ctx, handler, limiter, desc); err != nil {
151
+		return images.Image{}, err
152
+	}
153
+
154
+	if isConvertible {
155
+		if desc, err = converterFunc(ctx, desc); err != nil {
156
+			return images.Image{}, err
157
+		}
158
+	}
159
+
160
+	img := images.Image{
161
+		Name:   name,
162
+		Target: desc,
163
+		Labels: rCtx.Labels,
164
+	}
165
+
166
+	is := c.ImageService()
167
+	for {
168
+		if created, err := is.Create(ctx, img); err != nil {
169
+			if !errdefs.IsAlreadyExists(err) {
170
+				return images.Image{}, err
171
+			}
172
+
173
+			updated, err := is.Update(ctx, img)
174
+			if err != nil {
175
+				// if image was removed, try create again
176
+				if errdefs.IsNotFound(err) {
177
+					continue
178
+				}
179
+				return images.Image{}, err
180
+			}
181
+
182
+			img = updated
183
+		} else {
184
+			img = created
185
+		}
186
+
187
+		return img, nil
188
+	}
189
+}
... ...
@@ -81,7 +81,7 @@ func (a *dockerAuthorizer) AddResponses(ctx context.Context, responses []*http.R
81 81
 			// TODO(dmcg): Store challenge, not token
82 82
 			// Move token fetching to authorize
83 83
 			return a.setTokenAuth(ctx, host, c.parameters)
84
-		} else if c.scheme == basicAuth {
84
+		} else if c.scheme == basicAuth && a.credentials != nil {
85 85
 			// TODO: Resolve credentials on authorize
86 86
 			username, secret, err := a.credentials(host)
87 87
 			if err != nil {
... ...
@@ -194,7 +194,11 @@ func (a *dockerAuthorizer) fetchTokenWithOAuth(ctx context.Context, to tokenOpti
194 194
 		form.Set("password", to.secret)
195 195
 	}
196 196
 
197
-	resp, err := ctxhttp.PostForm(ctx, a.client, to.realm, form)
197
+	resp, err := ctxhttp.Post(
198
+		ctx, a.client, to.realm,
199
+		"application/x-www-form-urlencoded; charset=utf-8",
200
+		strings.NewReader(form.Encode()),
201
+	)
198 202
 	if err != nil {
199 203
 		return "", err
200 204
 	}
... ...
@@ -29,6 +29,7 @@ import (
29 29
 	"github.com/containerd/containerd/log"
30 30
 	"github.com/containerd/containerd/reference"
31 31
 	"github.com/containerd/containerd/remotes"
32
+	"github.com/containerd/containerd/version"
32 33
 	digest "github.com/opencontainers/go-digest"
33 34
 	ocispec "github.com/opencontainers/image-spec/specs-go/v1"
34 35
 	"github.com/pkg/errors"
... ...
@@ -75,13 +76,16 @@ type ResolverOptions struct {
75 75
 
76 76
 	// Credentials provides username and secret given a host.
77 77
 	// If username is empty but a secret is given, that secret
78
-	// is interpretted as a long lived token.
78
+	// is interpreted as a long lived token.
79 79
 	// Deprecated: use Authorizer
80 80
 	Credentials func(string) (string, string, error)
81 81
 
82 82
 	// Host provides the hostname given a namespace.
83 83
 	Host func(string) (string, error)
84 84
 
85
+	// Headers are the HTTP request header fields sent by the resolver
86
+	Headers http.Header
87
+
85 88
 	// PlainHTTP specifies to use plain http and not https
86 89
 	PlainHTTP bool
87 90
 
... ...
@@ -105,6 +109,7 @@ func DefaultHost(ns string) (string, error) {
105 105
 type dockerResolver struct {
106 106
 	auth      Authorizer
107 107
 	host      func(string) (string, error)
108
+	headers   http.Header
108 109
 	plainHTTP bool
109 110
 	client    *http.Client
110 111
 	tracker   StatusTracker
... ...
@@ -118,12 +123,27 @@ func NewResolver(options ResolverOptions) remotes.Resolver {
118 118
 	if options.Host == nil {
119 119
 		options.Host = DefaultHost
120 120
 	}
121
+	if options.Headers == nil {
122
+		options.Headers = make(http.Header)
123
+	}
124
+	if _, ok := options.Headers["Accept"]; !ok {
125
+		// set headers for all the types we support for resolution.
126
+		options.Headers.Set("Accept", strings.Join([]string{
127
+			images.MediaTypeDockerSchema2Manifest,
128
+			images.MediaTypeDockerSchema2ManifestList,
129
+			ocispec.MediaTypeImageManifest,
130
+			ocispec.MediaTypeImageIndex, "*"}, ", "))
131
+	}
132
+	if _, ok := options.Headers["User-Agent"]; !ok {
133
+		options.Headers.Set("User-Agent", "containerd/"+version.Version)
134
+	}
121 135
 	if options.Authorizer == nil {
122 136
 		options.Authorizer = NewAuthorizer(options.Client, options.Credentials)
123 137
 	}
124 138
 	return &dockerResolver{
125 139
 		auth:      options.Authorizer,
126 140
 		host:      options.Host,
141
+		headers:   options.Headers,
127 142
 		plainHTTP: options.PlainHTTP,
128 143
 		client:    options.Client,
129 144
 		tracker:   options.Tracker,
... ...
@@ -182,12 +202,7 @@ func (r *dockerResolver) Resolve(ctx context.Context, ref string) (string, ocisp
182 182
 			return "", ocispec.Descriptor{}, err
183 183
 		}
184 184
 
185
-		// set headers for all the types we support for resolution.
186
-		req.Header.Set("Accept", strings.Join([]string{
187
-			images.MediaTypeDockerSchema2Manifest,
188
-			images.MediaTypeDockerSchema2ManifestList,
189
-			ocispec.MediaTypeImageManifest,
190
-			ocispec.MediaTypeImageIndex, "*"}, ", "))
185
+		req.Header = r.headers
191 186
 
192 187
 		log.G(ctx).Debug("resolving")
193 188
 		resp, err := fetcher.doRequestWithRetries(ctx, req, nil)
... ...
@@ -156,7 +156,7 @@ func push(ctx context.Context, provider content.Provider, pusher Pusher, desc oc
156 156
 //
157 157
 // Base handlers can be provided which will be called before any push specific
158 158
 // handlers.
159
-func PushContent(ctx context.Context, pusher Pusher, desc ocispec.Descriptor, provider content.Provider, platform platforms.MatchComparer, baseHandlers ...images.Handler) error {
159
+func PushContent(ctx context.Context, pusher Pusher, desc ocispec.Descriptor, provider content.Provider, platform platforms.MatchComparer, wrapper func(h images.Handler) images.Handler) error {
160 160
 	var m sync.Mutex
161 161
 	manifestStack := []ocispec.Descriptor{}
162 162
 
... ...
@@ -175,13 +175,16 @@ func PushContent(ctx context.Context, pusher Pusher, desc ocispec.Descriptor, pr
175 175
 
176 176
 	pushHandler := PushHandler(pusher, provider)
177 177
 
178
-	handlers := append(baseHandlers,
178
+	var handler images.Handler = images.Handlers(
179 179
 		images.FilterPlatforms(images.ChildrenHandler(provider), platform),
180 180
 		filterHandler,
181 181
 		pushHandler,
182 182
 	)
183
+	if wrapper != nil {
184
+		handler = wrapper(handler)
185
+	}
183 186
 
184
-	if err := images.Dispatch(ctx, images.Handlers(handlers...), desc); err != nil {
187
+	if err := images.Dispatch(ctx, handler, nil, desc); err != nil {
185 188
 		return err
186 189
 	}
187 190
 
... ...
@@ -60,6 +60,8 @@ type CreateOptions struct {
60 60
 	ShimCgroup          string   `protobuf:"bytes,9,opt,name=shim_cgroup,json=shimCgroup,proto3" json:"shim_cgroup,omitempty"`
61 61
 	IoUid               uint32   `protobuf:"varint,10,opt,name=io_uid,json=ioUid,proto3" json:"io_uid,omitempty"`
62 62
 	IoGid               uint32   `protobuf:"varint,11,opt,name=io_gid,json=ioGid,proto3" json:"io_gid,omitempty"`
63
+	CriuWorkPath        string   `protobuf:"bytes,12,opt,name=criu_work_path,json=criuWorkPath,proto3" json:"criu_work_path,omitempty"`
64
+	CriuImagePath       string   `protobuf:"bytes,13,opt,name=criu_image_path,json=criuImagePath,proto3" json:"criu_image_path,omitempty"`
63 65
 }
64 66
 
65 67
 func (m *CreateOptions) Reset()                    { *m = CreateOptions{} }
... ...
@@ -74,6 +76,8 @@ type CheckpointOptions struct {
74 74
 	FileLocks           bool     `protobuf:"varint,5,opt,name=file_locks,json=fileLocks,proto3" json:"file_locks,omitempty"`
75 75
 	EmptyNamespaces     []string `protobuf:"bytes,6,rep,name=empty_namespaces,json=emptyNamespaces" json:"empty_namespaces,omitempty"`
76 76
 	CgroupsMode         string   `protobuf:"bytes,7,opt,name=cgroups_mode,json=cgroupsMode,proto3" json:"cgroups_mode,omitempty"`
77
+	WorkPath            string   `protobuf:"bytes,8,opt,name=work_path,json=workPath,proto3" json:"work_path,omitempty"`
78
+	ImagePath           string   `protobuf:"bytes,9,opt,name=image_path,json=imagePath,proto3" json:"image_path,omitempty"`
77 79
 }
78 80
 
79 81
 func (m *CheckpointOptions) Reset()                    { *m = CheckpointOptions{} }
... ...
@@ -252,6 +256,18 @@ func (m *CreateOptions) MarshalTo(dAtA []byte) (int, error) {
252 252
 		i++
253 253
 		i = encodeVarintRunc(dAtA, i, uint64(m.IoGid))
254 254
 	}
255
+	if len(m.CriuWorkPath) > 0 {
256
+		dAtA[i] = 0x62
257
+		i++
258
+		i = encodeVarintRunc(dAtA, i, uint64(len(m.CriuWorkPath)))
259
+		i += copy(dAtA[i:], m.CriuWorkPath)
260
+	}
261
+	if len(m.CriuImagePath) > 0 {
262
+		dAtA[i] = 0x6a
263
+		i++
264
+		i = encodeVarintRunc(dAtA, i, uint64(len(m.CriuImagePath)))
265
+		i += copy(dAtA[i:], m.CriuImagePath)
266
+	}
255 267
 	return i, nil
256 268
 }
257 269
 
... ...
@@ -341,6 +357,18 @@ func (m *CheckpointOptions) MarshalTo(dAtA []byte) (int, error) {
341 341
 		i = encodeVarintRunc(dAtA, i, uint64(len(m.CgroupsMode)))
342 342
 		i += copy(dAtA[i:], m.CgroupsMode)
343 343
 	}
344
+	if len(m.WorkPath) > 0 {
345
+		dAtA[i] = 0x42
346
+		i++
347
+		i = encodeVarintRunc(dAtA, i, uint64(len(m.WorkPath)))
348
+		i += copy(dAtA[i:], m.WorkPath)
349
+	}
350
+	if len(m.ImagePath) > 0 {
351
+		dAtA[i] = 0x4a
352
+		i++
353
+		i = encodeVarintRunc(dAtA, i, uint64(len(m.ImagePath)))
354
+		i += copy(dAtA[i:], m.ImagePath)
355
+	}
344 356
 	return i, nil
345 357
 }
346 358
 
... ...
@@ -439,6 +467,14 @@ func (m *CreateOptions) Size() (n int) {
439 439
 	if m.IoGid != 0 {
440 440
 		n += 1 + sovRunc(uint64(m.IoGid))
441 441
 	}
442
+	l = len(m.CriuWorkPath)
443
+	if l > 0 {
444
+		n += 1 + l + sovRunc(uint64(l))
445
+	}
446
+	l = len(m.CriuImagePath)
447
+	if l > 0 {
448
+		n += 1 + l + sovRunc(uint64(l))
449
+	}
442 450
 	return n
443 451
 }
444 452
 
... ...
@@ -470,6 +506,14 @@ func (m *CheckpointOptions) Size() (n int) {
470 470
 	if l > 0 {
471 471
 		n += 1 + l + sovRunc(uint64(l))
472 472
 	}
473
+	l = len(m.WorkPath)
474
+	if l > 0 {
475
+		n += 1 + l + sovRunc(uint64(l))
476
+	}
477
+	l = len(m.ImagePath)
478
+	if l > 0 {
479
+		n += 1 + l + sovRunc(uint64(l))
480
+	}
473 481
 	return n
474 482
 }
475 483
 
... ...
@@ -525,6 +569,8 @@ func (this *CreateOptions) String() string {
525 525
 		`ShimCgroup:` + fmt.Sprintf("%v", this.ShimCgroup) + `,`,
526 526
 		`IoUid:` + fmt.Sprintf("%v", this.IoUid) + `,`,
527 527
 		`IoGid:` + fmt.Sprintf("%v", this.IoGid) + `,`,
528
+		`CriuWorkPath:` + fmt.Sprintf("%v", this.CriuWorkPath) + `,`,
529
+		`CriuImagePath:` + fmt.Sprintf("%v", this.CriuImagePath) + `,`,
528 530
 		`}`,
529 531
 	}, "")
530 532
 	return s
... ...
@@ -541,6 +587,8 @@ func (this *CheckpointOptions) String() string {
541 541
 		`FileLocks:` + fmt.Sprintf("%v", this.FileLocks) + `,`,
542 542
 		`EmptyNamespaces:` + fmt.Sprintf("%v", this.EmptyNamespaces) + `,`,
543 543
 		`CgroupsMode:` + fmt.Sprintf("%v", this.CgroupsMode) + `,`,
544
+		`WorkPath:` + fmt.Sprintf("%v", this.WorkPath) + `,`,
545
+		`ImagePath:` + fmt.Sprintf("%v", this.ImagePath) + `,`,
544 546
 		`}`,
545 547
 	}, "")
546 548
 	return s
... ...
@@ -994,6 +1042,64 @@ func (m *CreateOptions) Unmarshal(dAtA []byte) error {
994 994
 					break
995 995
 				}
996 996
 			}
997
+		case 12:
998
+			if wireType != 2 {
999
+				return fmt.Errorf("proto: wrong wireType = %d for field CriuWorkPath", wireType)
1000
+			}
1001
+			var stringLen uint64
1002
+			for shift := uint(0); ; shift += 7 {
1003
+				if shift >= 64 {
1004
+					return ErrIntOverflowRunc
1005
+				}
1006
+				if iNdEx >= l {
1007
+					return io.ErrUnexpectedEOF
1008
+				}
1009
+				b := dAtA[iNdEx]
1010
+				iNdEx++
1011
+				stringLen |= (uint64(b) & 0x7F) << shift
1012
+				if b < 0x80 {
1013
+					break
1014
+				}
1015
+			}
1016
+			intStringLen := int(stringLen)
1017
+			if intStringLen < 0 {
1018
+				return ErrInvalidLengthRunc
1019
+			}
1020
+			postIndex := iNdEx + intStringLen
1021
+			if postIndex > l {
1022
+				return io.ErrUnexpectedEOF
1023
+			}
1024
+			m.CriuWorkPath = string(dAtA[iNdEx:postIndex])
1025
+			iNdEx = postIndex
1026
+		case 13:
1027
+			if wireType != 2 {
1028
+				return fmt.Errorf("proto: wrong wireType = %d for field CriuImagePath", wireType)
1029
+			}
1030
+			var stringLen uint64
1031
+			for shift := uint(0); ; shift += 7 {
1032
+				if shift >= 64 {
1033
+					return ErrIntOverflowRunc
1034
+				}
1035
+				if iNdEx >= l {
1036
+					return io.ErrUnexpectedEOF
1037
+				}
1038
+				b := dAtA[iNdEx]
1039
+				iNdEx++
1040
+				stringLen |= (uint64(b) & 0x7F) << shift
1041
+				if b < 0x80 {
1042
+					break
1043
+				}
1044
+			}
1045
+			intStringLen := int(stringLen)
1046
+			if intStringLen < 0 {
1047
+				return ErrInvalidLengthRunc
1048
+			}
1049
+			postIndex := iNdEx + intStringLen
1050
+			if postIndex > l {
1051
+				return io.ErrUnexpectedEOF
1052
+			}
1053
+			m.CriuImagePath = string(dAtA[iNdEx:postIndex])
1054
+			iNdEx = postIndex
997 1055
 		default:
998 1056
 			iNdEx = preIndex
999 1057
 			skippy, err := skipRunc(dAtA[iNdEx:])
... ...
@@ -1202,6 +1308,64 @@ func (m *CheckpointOptions) Unmarshal(dAtA []byte) error {
1202 1202
 			}
1203 1203
 			m.CgroupsMode = string(dAtA[iNdEx:postIndex])
1204 1204
 			iNdEx = postIndex
1205
+		case 8:
1206
+			if wireType != 2 {
1207
+				return fmt.Errorf("proto: wrong wireType = %d for field WorkPath", wireType)
1208
+			}
1209
+			var stringLen uint64
1210
+			for shift := uint(0); ; shift += 7 {
1211
+				if shift >= 64 {
1212
+					return ErrIntOverflowRunc
1213
+				}
1214
+				if iNdEx >= l {
1215
+					return io.ErrUnexpectedEOF
1216
+				}
1217
+				b := dAtA[iNdEx]
1218
+				iNdEx++
1219
+				stringLen |= (uint64(b) & 0x7F) << shift
1220
+				if b < 0x80 {
1221
+					break
1222
+				}
1223
+			}
1224
+			intStringLen := int(stringLen)
1225
+			if intStringLen < 0 {
1226
+				return ErrInvalidLengthRunc
1227
+			}
1228
+			postIndex := iNdEx + intStringLen
1229
+			if postIndex > l {
1230
+				return io.ErrUnexpectedEOF
1231
+			}
1232
+			m.WorkPath = string(dAtA[iNdEx:postIndex])
1233
+			iNdEx = postIndex
1234
+		case 9:
1235
+			if wireType != 2 {
1236
+				return fmt.Errorf("proto: wrong wireType = %d for field ImagePath", wireType)
1237
+			}
1238
+			var stringLen uint64
1239
+			for shift := uint(0); ; shift += 7 {
1240
+				if shift >= 64 {
1241
+					return ErrIntOverflowRunc
1242
+				}
1243
+				if iNdEx >= l {
1244
+					return io.ErrUnexpectedEOF
1245
+				}
1246
+				b := dAtA[iNdEx]
1247
+				iNdEx++
1248
+				stringLen |= (uint64(b) & 0x7F) << shift
1249
+				if b < 0x80 {
1250
+					break
1251
+				}
1252
+			}
1253
+			intStringLen := int(stringLen)
1254
+			if intStringLen < 0 {
1255
+				return ErrInvalidLengthRunc
1256
+			}
1257
+			postIndex := iNdEx + intStringLen
1258
+			if postIndex > l {
1259
+				return io.ErrUnexpectedEOF
1260
+			}
1261
+			m.ImagePath = string(dAtA[iNdEx:postIndex])
1262
+			iNdEx = postIndex
1205 1263
 		default:
1206 1264
 			iNdEx = preIndex
1207 1265
 			skippy, err := skipRunc(dAtA[iNdEx:])
... ...
@@ -1412,39 +1576,43 @@ func init() {
1412 1412
 }
1413 1413
 
1414 1414
 var fileDescriptorRunc = []byte{
1415
-	// 541 bytes of a gzipped FileDescriptorProto
1416
-	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xdc, 0x93, 0xc1, 0x6e, 0xd3, 0x40,
1417
-	0x10, 0x86, 0x6b, 0xda, 0x26, 0xce, 0xa4, 0x29, 0xb0, 0x50, 0xc9, 0x14, 0x91, 0x86, 0x00, 0x52,
1418
-	0xb8, 0xa4, 0x12, 0x88, 0x13, 0xb7, 0xa6, 0x08, 0x55, 0x40, 0xa9, 0x0c, 0x95, 0x10, 0x42, 0x5a,
1419
-	0xb9, 0xeb, 0x21, 0x59, 0xc5, 0xde, 0x59, 0x79, 0xd7, 0xd4, 0xb9, 0xf5, 0x09, 0x78, 0xae, 0x1e,
1420
-	0x39, 0x72, 0x42, 0x34, 0x2f, 0x02, 0xf2, 0xda, 0x0e, 0x9c, 0x39, 0x72, 0xfb, 0xe7, 0xfb, 0xc7,
1421
-	0x9e, 0xd1, 0xbf, 0x1a, 0x98, 0x4c, 0xa5, 0x9d, 0xe5, 0x67, 0x63, 0x41, 0xe9, 0xbe, 0x20, 0x65,
1422
-	0x23, 0xa9, 0x30, 0x8b, 0xff, 0x96, 0x59, 0xae, 0xac, 0x4c, 0x71, 0x3f, 0x91, 0x2a, 0x2f, 0xca,
1423
-	0x4a, 0xd8, 0x85, 0x46, 0xe3, 0xd4, 0x58, 0x67, 0x64, 0x89, 0xed, 0xfc, 0x69, 0x1f, 0xbb, 0xb6,
1424
-	0x71, 0x69, 0xee, 0xde, 0x9e, 0xd2, 0x94, 0x5c, 0xc7, 0x7e, 0xa9, 0xaa, 0xe6, 0xe1, 0x57, 0x0f,
1425
-	0xba, 0x61, 0xae, 0xc4, 0x5b, 0x6d, 0x25, 0x29, 0xc3, 0x02, 0x68, 0xd7, 0x23, 0x02, 0x6f, 0xe0,
1426
-	0x8d, 0x3a, 0x61, 0x53, 0xb2, 0xfb, 0xb0, 0x55, 0x4b, 0x9e, 0x11, 0xd9, 0xe0, 0x9a, 0xb3, 0xbb,
1427
-	0x35, 0x0b, 0x89, 0x2c, 0xbb, 0x0b, 0x1d, 0x91, 0xc9, 0x9c, 0xeb, 0xc8, 0xce, 0x82, 0x75, 0xe7,
1428
-	0xfb, 0x25, 0x38, 0x89, 0xec, 0x8c, 0x3d, 0x82, 0x6d, 0xb3, 0x30, 0x16, 0xd3, 0x98, 0x8b, 0x69,
1429
-	0x46, 0xb9, 0x0e, 0x36, 0x06, 0xde, 0xc8, 0x0f, 0x7b, 0x35, 0x9d, 0x38, 0x38, 0xbc, 0x58, 0x87,
1430
-	0xde, 0x24, 0xc3, 0xc8, 0x62, 0xb3, 0xd2, 0x10, 0x7a, 0x8a, 0xb8, 0x96, 0x5f, 0xc8, 0x56, 0x93,
1431
-	0x3d, 0xf7, 0x5d, 0x57, 0xd1, 0x49, 0xc9, 0xdc, 0xe4, 0x3b, 0xe0, 0x93, 0x46, 0xc5, 0xad, 0xd0,
1432
-	0x6e, 0x31, 0x3f, 0x6c, 0x97, 0xf5, 0x7b, 0xa1, 0xd9, 0x13, 0xd8, 0xc1, 0xc2, 0x62, 0xa6, 0xa2,
1433
-	0x84, 0xe7, 0x4a, 0x16, 0xdc, 0x90, 0x98, 0xa3, 0x35, 0x6e, 0x41, 0x3f, 0xbc, 0xd5, 0x98, 0xa7,
1434
-	0x4a, 0x16, 0xef, 0x2a, 0x8b, 0xed, 0x82, 0x6f, 0x31, 0x4b, 0xa5, 0x8a, 0x92, 0x7a, 0xcb, 0x55,
1435
-	0xcd, 0xee, 0x01, 0x7c, 0x96, 0x09, 0xf2, 0x84, 0xc4, 0xdc, 0x04, 0x9b, 0xce, 0xed, 0x94, 0xe4,
1436
-	0x75, 0x09, 0xd8, 0x63, 0xb8, 0x81, 0xa9, 0xb6, 0x0b, 0xae, 0xa2, 0x14, 0x8d, 0x8e, 0x04, 0x9a,
1437
-	0xa0, 0x35, 0x58, 0x1f, 0x75, 0xc2, 0xeb, 0x8e, 0x1f, 0xaf, 0x70, 0x99, 0x68, 0x95, 0x84, 0xe1,
1438
-	0x29, 0xc5, 0x18, 0xb4, 0xab, 0x44, 0x6b, 0xf6, 0x86, 0x62, 0x64, 0x0f, 0x61, 0x5b, 0x11, 0x57,
1439
-	0x78, 0xce, 0xe7, 0xb8, 0xc8, 0xa4, 0x9a, 0x06, 0xbe, 0x1b, 0xb8, 0xa5, 0xe8, 0x18, 0xcf, 0x5f,
1440
-	0x55, 0x8c, 0xed, 0x41, 0xd7, 0xcc, 0x64, 0xda, 0xe4, 0xda, 0x71, 0xff, 0x81, 0x12, 0x55, 0xa1,
1441
-	0xb2, 0x1d, 0x68, 0x49, 0xe2, 0xb9, 0x8c, 0x03, 0x18, 0x78, 0xa3, 0x5e, 0xb8, 0x29, 0xe9, 0x54,
1442
-	0xc6, 0x35, 0x9e, 0xca, 0x38, 0xe8, 0x36, 0xf8, 0xa5, 0x8c, 0x87, 0xbf, 0x3c, 0xb8, 0x39, 0x99,
1443
-	0xa1, 0x98, 0x6b, 0x92, 0xca, 0x36, 0xcf, 0xc0, 0x60, 0x03, 0x0b, 0xd9, 0xa4, 0xef, 0xf4, 0xff,
1444
-	0x1a, 0xfb, 0xf0, 0x19, 0x6c, 0x9f, 0x64, 0x24, 0xd0, 0x98, 0x43, 0xb4, 0x91, 0x4c, 0x0c, 0x7b,
1445
-	0x00, 0x6d, 0x2c, 0x50, 0x70, 0x19, 0x57, 0x77, 0x71, 0x00, 0xcb, 0x1f, 0x7b, 0xad, 0x17, 0x05,
1446
-	0x8a, 0xa3, 0xc3, 0xb0, 0x55, 0x5a, 0x47, 0xf1, 0xc1, 0xa7, 0xcb, 0xab, 0xfe, 0xda, 0xf7, 0xab,
1447
-	0xfe, 0xda, 0xc5, 0xb2, 0xef, 0x5d, 0x2e, 0xfb, 0xde, 0xb7, 0x65, 0xdf, 0xfb, 0xb9, 0xec, 0x7b,
1448
-	0x1f, 0x0f, 0xfe, 0xf5, 0xb0, 0x9f, 0xaf, 0xd4, 0x87, 0xb5, 0xb3, 0x96, 0xbb, 0xd9, 0xa7, 0xbf,
1449
-	0x03, 0x00, 0x00, 0xff, 0xff, 0x18, 0xa1, 0x4b, 0x5b, 0x27, 0x04, 0x00, 0x00,
1415
+	// 604 bytes of a gzipped FileDescriptorProto
1416
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xdc, 0x94, 0xcf, 0x6e, 0xd3, 0x40,
1417
+	0x10, 0xc6, 0xeb, 0xfe, 0x49, 0x9c, 0x49, 0xd2, 0xc2, 0x42, 0x25, 0xd3, 0xaa, 0x69, 0x08, 0x7f,
1418
+	0x14, 0x2e, 0xa9, 0x04, 0xe2, 0xc4, 0xad, 0x29, 0x42, 0x15, 0x50, 0x2a, 0x43, 0x05, 0x42, 0x48,
1419
+	0x2b, 0x77, 0x3d, 0x24, 0xab, 0xc4, 0x3b, 0x96, 0x77, 0x4d, 0x92, 0x1b, 0x4f, 0xc0, 0x0b, 0xf1,
1420
+	0x02, 0x3d, 0x21, 0x8e, 0x9c, 0x10, 0xcd, 0x93, 0xa0, 0x5d, 0xc7, 0x69, 0xcf, 0x1c, 0xb9, 0xcd,
1421
+	0xfc, 0xe6, 0xb3, 0x67, 0xf4, 0x7d, 0xb2, 0xa1, 0x3f, 0x90, 0x66, 0x98, 0x9f, 0xf7, 0x04, 0x25,
1422
+	0x07, 0x82, 0x94, 0x89, 0xa4, 0xc2, 0x2c, 0xbe, 0x5e, 0x66, 0xb9, 0x32, 0x32, 0xc1, 0x83, 0xb1,
1423
+	0x54, 0xf9, 0xd4, 0x76, 0xc2, 0xcc, 0x52, 0xd4, 0xae, 0xea, 0xa5, 0x19, 0x19, 0x62, 0xdb, 0x57,
1424
+	0xf2, 0x9e, 0x93, 0xf5, 0xec, 0x70, 0xe7, 0xf6, 0x80, 0x06, 0xe4, 0x14, 0x07, 0xb6, 0x2a, 0xc4,
1425
+	0x9d, 0x6f, 0x1e, 0xd4, 0xc3, 0x5c, 0x89, 0x37, 0xa9, 0x91, 0xa4, 0x34, 0x0b, 0xa0, 0xba, 0x58,
1426
+	0x11, 0x78, 0x6d, 0xaf, 0x5b, 0x0b, 0xcb, 0x96, 0xdd, 0x85, 0xc6, 0xa2, 0xe4, 0x19, 0x91, 0x09,
1427
+	0x56, 0xdd, 0xb8, 0xbe, 0x60, 0x21, 0x91, 0x61, 0xbb, 0x50, 0x13, 0x99, 0xcc, 0x79, 0x1a, 0x99,
1428
+	0x61, 0xb0, 0xe6, 0xe6, 0xbe, 0x05, 0xa7, 0x91, 0x19, 0xb2, 0x07, 0xb0, 0xa9, 0x67, 0xda, 0x60,
1429
+	0x12, 0x73, 0x31, 0xc8, 0x28, 0x4f, 0x83, 0xf5, 0xb6, 0xd7, 0xf5, 0xc3, 0xe6, 0x82, 0xf6, 0x1d,
1430
+	0xec, 0xfc, 0x58, 0x83, 0x66, 0x3f, 0xc3, 0xc8, 0x60, 0x79, 0x52, 0x07, 0x9a, 0x8a, 0x78, 0x2a,
1431
+	0xbf, 0x90, 0x29, 0x36, 0x7b, 0xee, 0xb9, 0xba, 0xa2, 0x53, 0xcb, 0xdc, 0xe6, 0x3b, 0xe0, 0x53,
1432
+	0x8a, 0x8a, 0x1b, 0x91, 0xba, 0xc3, 0xfc, 0xb0, 0x6a, 0xfb, 0x77, 0x22, 0x65, 0x8f, 0x61, 0x1b,
1433
+	0xa7, 0x06, 0x33, 0x15, 0x8d, 0x79, 0xae, 0xe4, 0x94, 0x6b, 0x12, 0x23, 0x34, 0xda, 0x1d, 0xe8,
1434
+	0x87, 0xb7, 0xca, 0xe1, 0x99, 0x92, 0xd3, 0xb7, 0xc5, 0x88, 0xed, 0x80, 0x6f, 0x30, 0x4b, 0xa4,
1435
+	0x8a, 0xc6, 0x8b, 0x2b, 0x97, 0x3d, 0xdb, 0x03, 0xf8, 0x2c, 0xc7, 0xc8, 0xc7, 0x24, 0x46, 0x3a,
1436
+	0xd8, 0x70, 0xd3, 0x9a, 0x25, 0xaf, 0x2c, 0x60, 0x8f, 0xe0, 0x06, 0x26, 0xa9, 0x99, 0x71, 0x15,
1437
+	0x25, 0xa8, 0xd3, 0x48, 0xa0, 0x0e, 0x2a, 0xed, 0xb5, 0x6e, 0x2d, 0xdc, 0x72, 0xfc, 0x64, 0x89,
1438
+	0xad, 0xa3, 0x85, 0x13, 0x9a, 0x27, 0x14, 0x63, 0x50, 0x2d, 0x1c, 0x5d, 0xb0, 0xd7, 0x14, 0x23,
1439
+	0xbb, 0x0f, 0x9b, 0x8a, 0xb8, 0xc2, 0x09, 0x1f, 0xe1, 0x2c, 0x93, 0x6a, 0x10, 0xf8, 0x6e, 0x61,
1440
+	0x43, 0xd1, 0x09, 0x4e, 0x5e, 0x16, 0x8c, 0xed, 0x43, 0x5d, 0x0f, 0x65, 0x52, 0xfa, 0x5a, 0x73,
1441
+	0xef, 0x01, 0x8b, 0x0a, 0x53, 0xd9, 0x36, 0x54, 0x24, 0xf1, 0x5c, 0xc6, 0x01, 0xb4, 0xbd, 0x6e,
1442
+	0x33, 0xdc, 0x90, 0x74, 0x26, 0xe3, 0x05, 0x1e, 0xc8, 0x38, 0xa8, 0x97, 0xf8, 0x85, 0x8c, 0xed,
1443
+	0x52, 0x17, 0xe3, 0x84, 0xb2, 0x51, 0x91, 0x65, 0xc3, 0xbd, 0xb1, 0x61, 0xe9, 0x7b, 0xca, 0x46,
1444
+	0x2e, 0xcf, 0x87, 0xb0, 0xe5, 0x54, 0x32, 0x89, 0x06, 0x58, 0xc8, 0x9a, 0x4e, 0xd6, 0xb4, 0xf8,
1445
+	0xd8, 0x52, 0xab, 0xeb, 0x7c, 0x5f, 0x85, 0x9b, 0xfd, 0x21, 0x8a, 0x51, 0x4a, 0x52, 0x99, 0x32,
1446
+	0x54, 0x06, 0xeb, 0x38, 0x95, 0x65, 0x96, 0xae, 0xfe, 0x6f, 0x43, 0xdc, 0x85, 0xda, 0x95, 0x95,
1447
+	0x7e, 0xf1, 0x59, 0x4c, 0x4a, 0x1b, 0xf7, 0x00, 0xae, 0x39, 0x58, 0x44, 0x57, 0x93, 0x4b, 0xf7,
1448
+	0x9e, 0xc2, 0xe6, 0x69, 0x46, 0x02, 0xb5, 0x3e, 0x42, 0x13, 0xc9, 0xb1, 0x66, 0xf7, 0xa0, 0x8a,
1449
+	0x53, 0x14, 0x5c, 0xc6, 0xc5, 0x17, 0x7a, 0x08, 0xf3, 0xdf, 0xfb, 0x95, 0xe7, 0x53, 0x14, 0xc7,
1450
+	0x47, 0x61, 0xc5, 0x8e, 0x8e, 0xe3, 0xc3, 0x4f, 0x17, 0x97, 0xad, 0x95, 0x5f, 0x97, 0xad, 0x95,
1451
+	0xaf, 0xf3, 0x96, 0x77, 0x31, 0x6f, 0x79, 0x3f, 0xe7, 0x2d, 0xef, 0xcf, 0xbc, 0xe5, 0x7d, 0x3c,
1452
+	0xfc, 0xd7, 0x5f, 0xcc, 0xb3, 0x65, 0xf5, 0x61, 0xe5, 0xbc, 0xe2, 0xfe, 0x1e, 0x4f, 0xfe, 0x06,
1453
+	0x00, 0x00, 0xff, 0xff, 0x7f, 0x24, 0x6f, 0x2e, 0xb1, 0x04, 0x00, 0x00,
1450 1454
 }
... ...
@@ -25,6 +25,8 @@ message CreateOptions {
25 25
 	string shim_cgroup = 9;
26 26
 	uint32 io_uid = 10;
27 27
 	uint32 io_gid = 11;
28
+	string criu_work_path = 12;
29
+	string criu_image_path = 13;
28 30
 }
29 31
 
30 32
 message CheckpointOptions {
... ...
@@ -35,6 +37,8 @@ message CheckpointOptions {
35 35
 	bool file_locks = 5;
36 36
 	repeated string empty_namespaces = 6;
37 37
 	string cgroups_mode = 7;
38
+	string work_path = 8;
39
+	string image_path = 9;
38 40
 }
39 41
 
40 42
 message ProcessDetails {
... ...
@@ -20,6 +20,7 @@ package linux
20 20
 
21 21
 import (
22 22
 	"context"
23
+	"fmt"
23 24
 	"io/ioutil"
24 25
 	"os"
25 26
 	"path/filepath"
... ...
@@ -114,12 +115,12 @@ func (b *bundle) NewShimClient(ctx context.Context, namespace string, getClientO
114 114
 
115 115
 // Delete deletes the bundle from disk
116 116
 func (b *bundle) Delete() error {
117
-	err := os.RemoveAll(b.path)
117
+	err := atomicDelete(b.path)
118 118
 	if err == nil {
119
-		return os.RemoveAll(b.workDir)
119
+		return atomicDelete(b.workDir)
120 120
 	}
121 121
 	// error removing the bundle path; still attempt removing work dir
122
-	err2 := os.RemoveAll(b.workDir)
122
+	err2 := atomicDelete(b.workDir)
123 123
 	if err2 == nil {
124 124
 		return err
125 125
 	}
... ...
@@ -152,3 +153,13 @@ func (b *bundle) shimConfig(namespace string, c *Config, runcOptions *runctypes.
152 152
 		SystemdCgroup: systemdCgroup,
153 153
 	}
154 154
 }
155
+
156
+// atomicDelete renames the path to a hidden file before removal
157
+func atomicDelete(path string) error {
158
+	// create a hidden dir for an atomic removal
159
+	atomicPath := filepath.Join(filepath.Dir(path), fmt.Sprintf(".%s", filepath.Base(path)))
160
+	if err := os.Rename(path, atomicPath); err != nil {
161
+		return err
162
+	}
163
+	return os.RemoveAll(atomicPath)
164
+}
... ...
@@ -76,6 +76,7 @@ type Init struct {
76 76
 	IoGID        int
77 77
 	NoPivotRoot  bool
78 78
 	NoNewKeyring bool
79
+	CriuWorkPath string
79 80
 }
80 81
 
81 82
 // NewRunc returns a new runc instance for a process
... ...
@@ -132,7 +133,7 @@ func (p *Init) Create(ctx context.Context, r *CreateConfig) error {
132 132
 		opts := &runc.RestoreOpts{
133 133
 			CheckpointOpts: runc.CheckpointOpts{
134 134
 				ImagePath:  r.Checkpoint,
135
-				WorkDir:    p.WorkDir,
135
+				WorkDir:    p.CriuWorkPath,
136 136
 				ParentPath: r.ParentCheckpoint,
137 137
 			},
138 138
 			PidFile:     pidFile,
... ...
@@ -425,8 +426,12 @@ func (p *Init) checkpoint(ctx context.Context, r *CheckpointConfig) error {
425 425
 	if !r.Exit {
426 426
 		actions = append(actions, runc.LeaveRunning)
427 427
 	}
428
-	work := filepath.Join(p.WorkDir, "criu-work")
429
-	defer os.RemoveAll(work)
428
+	// keep criu work directory if criu work dir is set
429
+	work := r.WorkDir
430
+	if work == "" {
431
+		work = filepath.Join(p.WorkDir, "criu-work")
432
+		defer os.RemoveAll(work)
433
+	}
430 434
 	if err := p.runtime.Checkpoint(ctx, p.id, &runc.CheckpointOpts{
431 435
 		WorkDir:                  work,
432 436
 		ImagePath:                r.Path,
... ...
@@ -55,6 +55,7 @@ type ExecConfig struct {
55 55
 
56 56
 // CheckpointConfig holds task checkpoint configuration
57 57
 type CheckpointConfig struct {
58
+	WorkDir                  string
58 59
 	Path                     string
59 60
 	Exit                     bool
60 61
 	AllowOpenTCP             bool
... ...
@@ -21,6 +21,7 @@ package linux
21 21
 import (
22 22
 	"context"
23 23
 	"fmt"
24
+	"io"
24 25
 	"io/ioutil"
25 26
 	"os"
26 27
 	"path/filepath"
... ...
@@ -40,6 +41,7 @@ import (
40 40
 	"github.com/containerd/containerd/plugin"
41 41
 	"github.com/containerd/containerd/runtime"
42 42
 	"github.com/containerd/containerd/runtime/linux/runctypes"
43
+	"github.com/containerd/containerd/runtime/v1"
43 44
 	"github.com/containerd/containerd/runtime/v1/linux/proc"
44 45
 	shim "github.com/containerd/containerd/runtime/v1/shim/v1"
45 46
 	runc "github.com/containerd/go-runc"
... ...
@@ -288,6 +290,10 @@ func (r *Runtime) restoreTasks(ctx context.Context) ([]*Task, error) {
288 288
 			continue
289 289
 		}
290 290
 		name := namespace.Name()
291
+		// skip hidden directories
292
+		if len(name) > 0 && name[0] == '.' {
293
+			continue
294
+		}
291 295
 		log.G(ctx).WithField("namespace", name).Debug("loading tasks in namespace")
292 296
 		tasks, err := r.loadTasks(ctx, name)
293 297
 		if err != nil {
... ...
@@ -351,6 +357,30 @@ func (r *Runtime) loadTasks(ctx context.Context, ns string) ([]*Task, error) {
351 351
 			continue
352 352
 		}
353 353
 
354
+		logDirPath := filepath.Join(r.root, ns, id)
355
+
356
+		shimStdoutLog, err := v1.OpenShimStdoutLog(ctx, logDirPath)
357
+		if err != nil {
358
+			log.G(ctx).WithError(err).WithFields(logrus.Fields{
359
+				"id":         id,
360
+				"namespace":  ns,
361
+				"logDirPath": logDirPath,
362
+			}).Error("opening shim stdout log pipe")
363
+			continue
364
+		}
365
+		go io.Copy(os.Stdout, shimStdoutLog)
366
+
367
+		shimStderrLog, err := v1.OpenShimStderrLog(ctx, logDirPath)
368
+		if err != nil {
369
+			log.G(ctx).WithError(err).WithFields(logrus.Fields{
370
+				"id":         id,
371
+				"namespace":  ns,
372
+				"logDirPath": logDirPath,
373
+			}).Error("opening shim stderr log pipe")
374
+			continue
375
+		}
376
+		go io.Copy(os.Stderr, shimStderrLog)
377
+
354 378
 		t, err := newTask(id, ns, pid, s, r.events, r.tasks, bundle)
355 379
 		if err != nil {
356 380
 			log.G(ctx).WithError(err).Error("loading task type")
357 381
new file mode 100644
... ...
@@ -0,0 +1,38 @@
0
+// +build !windows
1
+
2
+/*
3
+   Copyright The containerd Authors.
4
+
5
+   Licensed under the Apache License, Version 2.0 (the "License");
6
+   you may not use this file except in compliance with the License.
7
+   You may obtain a copy of the License at
8
+
9
+       http://www.apache.org/licenses/LICENSE-2.0
10
+
11
+   Unless required by applicable law or agreed to in writing, software
12
+   distributed under the License is distributed on an "AS IS" BASIS,
13
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+   See the License for the specific language governing permissions and
15
+   limitations under the License.
16
+*/
17
+
18
+package v1
19
+
20
+import (
21
+	"context"
22
+	"io"
23
+	"path/filepath"
24
+
25
+	"github.com/containerd/fifo"
26
+	"golang.org/x/sys/unix"
27
+)
28
+
29
+// OpenShimStdoutLog opens the shim log for reading
30
+func OpenShimStdoutLog(ctx context.Context, logDirPath string) (io.ReadWriteCloser, error) {
31
+	return fifo.OpenFifo(ctx, filepath.Join(logDirPath, "shim.stdout.log"), unix.O_RDWR|unix.O_CREAT, 0700)
32
+}
33
+
34
+// OpenShimStderrLog opens the shim log
35
+func OpenShimStderrLog(ctx context.Context, logDirPath string) (io.ReadWriteCloser, error) {
36
+	return fifo.OpenFifo(ctx, filepath.Join(logDirPath, "shim.stderr.log"), unix.O_RDWR|unix.O_CREAT, 0700)
37
+}
... ...
@@ -37,6 +37,7 @@ import (
37 37
 
38 38
 	"github.com/containerd/containerd/events"
39 39
 	"github.com/containerd/containerd/log"
40
+	v1 "github.com/containerd/containerd/runtime/v1"
40 41
 	"github.com/containerd/containerd/runtime/v1/shim"
41 42
 	shimapi "github.com/containerd/containerd/runtime/v1/shim/v1"
42 43
 	"github.com/containerd/containerd/sys"
... ...
@@ -62,7 +63,24 @@ func WithStart(binary, address, daemonAddress, cgroup string, debug bool, exitHa
62 62
 		}
63 63
 		defer f.Close()
64 64
 
65
-		cmd, err := newCommand(binary, daemonAddress, debug, config, f)
65
+		var stdoutLog io.ReadWriteCloser
66
+		var stderrLog io.ReadWriteCloser
67
+		if debug {
68
+			stdoutLog, err = v1.OpenShimStdoutLog(ctx, config.WorkDir)
69
+			if err != nil {
70
+				return nil, nil, errors.Wrapf(err, "failed to create stdout log")
71
+			}
72
+
73
+			stderrLog, err = v1.OpenShimStderrLog(ctx, config.WorkDir)
74
+			if err != nil {
75
+				return nil, nil, errors.Wrapf(err, "failed to create stderr log")
76
+			}
77
+
78
+			go io.Copy(os.Stdout, stdoutLog)
79
+			go io.Copy(os.Stderr, stderrLog)
80
+		}
81
+
82
+		cmd, err := newCommand(binary, daemonAddress, debug, config, f, stdoutLog, stderrLog)
66 83
 		if err != nil {
67 84
 			return nil, nil, err
68 85
 		}
... ...
@@ -77,6 +95,12 @@ func WithStart(binary, address, daemonAddress, cgroup string, debug bool, exitHa
77 77
 		go func() {
78 78
 			cmd.Wait()
79 79
 			exitHandler()
80
+			if stdoutLog != nil {
81
+				stderrLog.Close()
82
+			}
83
+			if stdoutLog != nil {
84
+				stderrLog.Close()
85
+			}
80 86
 		}()
81 87
 		log.G(ctx).WithFields(logrus.Fields{
82 88
 			"pid":     cmd.Process.Pid,
... ...
@@ -104,7 +128,7 @@ func WithStart(binary, address, daemonAddress, cgroup string, debug bool, exitHa
104 104
 	}
105 105
 }
106 106
 
107
-func newCommand(binary, daemonAddress string, debug bool, config shim.Config, socket *os.File) (*exec.Cmd, error) {
107
+func newCommand(binary, daemonAddress string, debug bool, config shim.Config, socket *os.File, stdout, stderr io.Writer) (*exec.Cmd, error) {
108 108
 	selfExe, err := os.Executable()
109 109
 	if err != nil {
110 110
 		return nil, err
... ...
@@ -137,10 +161,8 @@ func newCommand(binary, daemonAddress string, debug bool, config shim.Config, so
137 137
 	cmd.SysProcAttr = getSysProcAttr()
138 138
 	cmd.ExtraFiles = append(cmd.ExtraFiles, socket)
139 139
 	cmd.Env = append(os.Environ(), "GOMAXPROCS=2")
140
-	if debug {
141
-		cmd.Stdout = os.Stdout
142
-		cmd.Stderr = os.Stderr
143
-	}
140
+	cmd.Stdout = stdout
141
+	cmd.Stderr = stderr
144 142
 	return cmd, nil
145 143
 }
146 144
 
... ...
@@ -448,6 +448,7 @@ func (s *Service) Checkpoint(ctx context.Context, r *shimapi.CheckpointTaskReque
448 448
 		AllowTerminal:            options.Terminal,
449 449
 		FileLocks:                options.FileLocks,
450 450
 		EmptyNamespaces:          options.EmptyNamespaces,
451
+		WorkDir:                  options.WorkPath,
451 452
 	}); err != nil {
452 453
 		return nil, errdefs.ToGRPC(err)
453 454
 	}
... ...
@@ -657,5 +658,11 @@ func newInit(ctx context.Context, path, workDir, runtimeRoot, namespace, criu st
657 657
 	p.IoGID = int(options.IoGid)
658 658
 	p.NoPivotRoot = options.NoPivotRoot
659 659
 	p.NoNewKeyring = options.NoNewKeyring
660
+	p.CriuWorkPath = options.CriuWorkPath
661
+	if p.CriuWorkPath == "" {
662
+		// if criu work path not set, use container WorkDir
663
+		p.CriuWorkPath = p.WorkDir
664
+	}
665
+
660 666
 	return p, nil
661 667
 }
662 668
new file mode 100644
... ...
@@ -0,0 +1,195 @@
0
+# Runtime v2
1
+
2
+Runtime v2 introduces a first class shim API for runtime authors to integrate with containerd.
3
+The shim API is minimal and scoped to the execution lifecycle of a container.
4
+
5
+## Binary Naming
6
+
7
+Users specify the runtime they wish to use when creating a container.
8
+The runtime can also be changed via a container update.
9
+
10
+```bash
11
+> ctr run --runtime io.containerd.runc.v1
12
+```
13
+
14
+When a user specifies a runtime name, `io.containerd.runc.v1`, they will specify the name and version of the runtime.
15
+This will be translated by containerd into a binary name for the shim.
16
+
17
+`io.containerd.runc.v1` -> `containerd-shim-runc-v1`
18
+
19
+containerd keeps the `containerd-shim-*` prefix so that users can `ps aux | grep containerd-shim` to see running shims on their system.
20
+
21
+## Shim Authoring
22
+
23
+This section is dedicated to runtime authors wishing to build a shim.
24
+It will detail how the API works and different considerations when building shim.
25
+
26
+### Commands
27
+
28
+Container information is provided to a shim in two ways.
29
+The OCI Runtime Bundle and on the `Create` rpc request.
30
+
31
+#### `start`
32
+
33
+Each shim MUST implement a `start` subcommand.
34
+This command will launch new shims.
35
+The start command MUST accept the following flags:
36
+
37
+* `-namespace` the namespace for the container
38
+* `-address` the address of the containerd's main socket
39
+* `-publish-binary` the binary path to publish events back to containerd
40
+* `-id` the id of the container
41
+
42
+The start command, as well as all binary calls to the shim, has the bundle for the container set as the `cwd`.
43
+
44
+The start command MUST return an address to a shim for containerd to issue API requests for container operations.
45
+
46
+The start command can either start a new shim or return an address to an existing shim based on the shim's logic.
47
+
48
+#### `delete`
49
+
50
+Each shim MUST implement a `delete` subcommand.
51
+This command allows containerd to delete any container resources created, mounted, and/or run by a shim when containerd can no longer communicate over rpc.
52
+This happens if a shim is SIGKILL'd with a running container.
53
+These resources will need to be cleaned up when containerd looses the connection to a shim.
54
+This is also used when containerd boots and reconnects to shims.
55
+If a bundle is still on disk but containerd cannot connect to a shim, the delete command is invoked.
56
+
57
+The delete command MUST accept the following flags:
58
+
59
+* `-namespace` the namespace for the container
60
+* `-address` the address of the containerd's main socket
61
+* `-publish-binary` the binary path to publish events back to containerd
62
+* `-id` the id of the container
63
+* `-bundle` the path to the bundle to delete. On non-Windows platforms this will match `cwd`
64
+
65
+The delete command will be executed in the container's bundle as its `cwd` except for on the Windows platform.
66
+
67
+### Host Level Shim Configuration
68
+
69
+containerd does not provide any host level configuration for shims via the API.
70
+If a shim needs configuration from the user with host level information across all instances, a shim specific configuration file can be setup.
71
+
72
+### Container Level Shim Configuration
73
+
74
+On the create request, there is a generic `*protobuf.Any` that allows a user to specify container level configuration for the shim.
75
+
76
+```proto
77
+message CreateTaskRequest {
78
+	string id = 1;
79
+	...
80
+	google.protobuf.Any options = 10;
81
+}
82
+```
83
+
84
+A shim author can create their own protobuf message for configuration and clients can import and provide this information is needed.
85
+
86
+### I/O
87
+
88
+I/O for a container is provided by the client to the shim via fifo on Linux, named pipes on Windows, or log files on disk.
89
+The paths to these files are provided on the `Create` rpc for the initial creation and on the `Exec` rpc for additional processes.
90
+
91
+```proto
92
+message CreateTaskRequest {
93
+	string id = 1;
94
+	bool terminal = 4;
95
+	string stdin = 5;
96
+	string stdout = 6;
97
+	string stderr = 7;
98
+}
99
+```
100
+
101
+```proto
102
+message ExecProcessRequest {
103
+	string id = 1;
104
+	string exec_id = 2;
105
+	bool terminal = 3;
106
+	string stdin = 4;
107
+	string stdout = 5;
108
+	string stderr = 6;
109
+}
110
+```
111
+
112
+Containers that are to be launched with an interactive terminal will have the `terminal` field set to `true`, data is still copied over the files(fifos,pipes) in the same way as non interactive containers.
113
+
114
+### Root Filesystems
115
+
116
+The root filesystem for the containers is provided by on the `Create` rpc.
117
+Shims are responsible for managing the lifecycle of the filesystem mount during the lifecycle of a container.
118
+
119
+```proto
120
+message CreateTaskRequest {
121
+	string id = 1;
122
+	string bundle = 2;
123
+	repeated containerd.types.Mount rootfs = 3;
124
+	...
125
+}
126
+```
127
+
128
+The mount protobuf message is:
129
+
130
+```proto
131
+message Mount {
132
+	// Type defines the nature of the mount.
133
+	string type = 1;
134
+	// Source specifies the name of the mount. Depending on mount type, this
135
+	// may be a volume name or a host path, or even ignored.
136
+	string source = 2;
137
+	// Target path in container
138
+	string target = 3;
139
+	// Options specifies zero or more fstab style mount options.
140
+	repeated string options = 4;
141
+}
142
+```
143
+
144
+Shims are responsible for mounting the filesystem into the `rootfs/` directory of the bundle.
145
+Shims are also responsible for unmounting of the filesystem.
146
+During a `delete` binary call, the shim MUST ensure that filesystem is also unmounted.
147
+Filesystems are provided by the containerd snapshotters.
148
+
149
+### Events
150
+
151
+The Runtime v2 supports an async event model. In order for the an upstream caller (such as Docker) to get these events in the correct order a Runtime v2 shim MUST implement the following events where `Compliance=MUST`. This avoids race conditions between the shim and shim client where for example a call to `Start` can signal a `TaskExitEventTopic` before even returning the results from the `Start` call. With these guarantees of a Runtime v2 shim a call to `Start` is required to have published the async event `TaskStartEventTopic` before the shim can publish the `TaskExitEventTopic`.
152
+
153
+#### Tasks
154
+
155
+| Topic | Compliance | Description |
156
+| ----- | ---------- | ----------- |
157
+| `runtime.TaskCreateEventTopic`       | MUST                                                                          | When a task is successfully created |
158
+| `runtime.TaskStartEventTopic`        | MUST (follow `TaskCreateEventTopic`)                                          | When a task is successfully started |
159
+| `runtime.TaskExitEventTopic`         | MUST (follow `TaskStartEventTopic`)                                           | When a task exits expected or unexpected |
160
+| `runtime.TaskDeleteEventTopic`       | MUST (follow `TaskExitEventTopic` or `TaskCreateEventTopic` if never started) | When a task is removed from a shim |
161
+| `runtime.TaskPausedEventTopic`       | SHOULD                                                                        | When a task is successfully paused |
162
+| `runtime.TaskResumedEventTopic`      | SHOULD (follow `TaskPausedEventTopic`)                                        | When a task is successfully resumed |
163
+| `runtime.TaskCheckpointedEventTopic` | SHOULD                                                                        | When a task is checkpointed |
164
+| `runtime.TaskOOMEventTopic`          | SHOULD                                                                        | If the shim collects Out of Memory events |
165
+
166
+#### Execs
167
+
168
+| Topic | Compliance | Description |
169
+| ----- | ---------- | ----------- |
170
+| `runtime.TaskExecAddedEventTopic`   | MUST (follow `TaskCreateEventTopic` )     | When an exec is successfully added |
171
+| `runtime.TaskExecStartedEventTopic` | MUST (follow `TaskExecAddedEventTopic`)   | When an exec is successfully started |
172
+| `runtime.TaskExitEventTopic`        | MUST (follow `TaskExecStartedEventTopic`) | When an exec (other than the init exec) exits expected or unexpected |
173
+| `runtime.TaskDeleteEventTopic`      | SHOULD (follow `TaskExitEventTopic` or `TaskExecAddedEventTopic` if never started) | When an exec is removed from a shim |
174
+
175
+### Other
176
+
177
+#### Unsupported rpcs
178
+
179
+If a shim does not or cannot implement an rpc call, it MUST return a `github.com/containerd/containerd/errdefs.ErrNotImplemented` error.
180
+
181
+#### Debugging and Shim Logs
182
+
183
+A fifo on unix or named pipe on Windows will be provided to the shim.
184
+It can be located inside the `cwd` of the shim named "log".
185
+The shims can use the existing `github.com/containerd/containerd/log` package to log debug messages.
186
+Messages will automatically be output in the containerd's daemon logs with the correct fields and runtime set.
187
+
188
+#### ttrpc
189
+
190
+[ttrpc](https://github.com/containerd/ttrpc) is the only currently supported protocol for shims.
191
+It works with standard protobufs and GRPC services as well as generating clients.
192
+The only difference between grpc and ttrpc is the wire protocol.
193
+ttrpc removes the http stack in order to save memory and binary size to keep shims small.
194
+It is recommended to use ttrpc in your shim but grpc support is also in development.
0 195
new file mode 100644
... ...
@@ -0,0 +1,17 @@
0
+/*
1
+   Copyright The containerd Authors.
2
+
3
+   Licensed under the Apache License, Version 2.0 (the "License");
4
+   you may not use this file except in compliance with the License.
5
+   You may obtain a copy of the License at
6
+
7
+       http://www.apache.org/licenses/LICENSE-2.0
8
+
9
+   Unless required by applicable law or agreed to in writing, software
10
+   distributed under the License is distributed on an "AS IS" BASIS,
11
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+   See the License for the specific language governing permissions and
13
+   limitations under the License.
14
+*/
15
+
16
+package options
0 17
new file mode 100644
... ...
@@ -0,0 +1,1313 @@
0
+// Code generated by protoc-gen-gogo. DO NOT EDIT.
1
+// source: github.com/containerd/containerd/runtime/v2/runc/options/oci.proto
2
+
3
+/*
4
+	Package options is a generated protocol buffer package.
5
+
6
+	It is generated from these files:
7
+		github.com/containerd/containerd/runtime/v2/runc/options/oci.proto
8
+
9
+	It has these top-level messages:
10
+		Options
11
+		CheckpointOptions
12
+		ProcessDetails
13
+*/
14
+package options
15
+
16
+import proto "github.com/gogo/protobuf/proto"
17
+import fmt "fmt"
18
+import math "math"
19
+
20
+// skipping weak import gogoproto "github.com/gogo/protobuf/gogoproto"
21
+
22
+import strings "strings"
23
+import reflect "reflect"
24
+
25
+import io "io"
26
+
27
+// Reference imports to suppress errors if they are not otherwise used.
28
+var _ = proto.Marshal
29
+var _ = fmt.Errorf
30
+var _ = math.Inf
31
+
32
+// This is a compile-time assertion to ensure that this generated file
33
+// is compatible with the proto package it is being compiled against.
34
+// A compilation error at this line likely means your copy of the
35
+// proto package needs to be updated.
36
+const _ = proto.GoGoProtoPackageIsVersion2 // please upgrade the proto package
37
+
38
+type Options struct {
39
+	// disable pivot root when creating a container
40
+	NoPivotRoot bool `protobuf:"varint,1,opt,name=no_pivot_root,json=noPivotRoot,proto3" json:"no_pivot_root,omitempty"`
41
+	// create a new keyring for the container
42
+	NoNewKeyring bool `protobuf:"varint,2,opt,name=no_new_keyring,json=noNewKeyring,proto3" json:"no_new_keyring,omitempty"`
43
+	// place the shim in a cgroup
44
+	ShimCgroup string `protobuf:"bytes,3,opt,name=shim_cgroup,json=shimCgroup,proto3" json:"shim_cgroup,omitempty"`
45
+	// set the I/O's pipes uid
46
+	IoUid uint32 `protobuf:"varint,4,opt,name=io_uid,json=ioUid,proto3" json:"io_uid,omitempty"`
47
+	// set the I/O's pipes gid
48
+	IoGid uint32 `protobuf:"varint,5,opt,name=io_gid,json=ioGid,proto3" json:"io_gid,omitempty"`
49
+	// binary name of the runc binary
50
+	BinaryName string `protobuf:"bytes,6,opt,name=binary_name,json=binaryName,proto3" json:"binary_name,omitempty"`
51
+	// runc root directory
52
+	Root string `protobuf:"bytes,7,opt,name=root,proto3" json:"root,omitempty"`
53
+	// criu binary path
54
+	CriuPath string `protobuf:"bytes,8,opt,name=criu_path,json=criuPath,proto3" json:"criu_path,omitempty"`
55
+	// enable systemd cgroups
56
+	SystemdCgroup bool `protobuf:"varint,9,opt,name=systemd_cgroup,json=systemdCgroup,proto3" json:"systemd_cgroup,omitempty"`
57
+	// criu image path
58
+	CriuImagePath string `protobuf:"bytes,10,opt,name=criu_image_path,json=criuImagePath,proto3" json:"criu_image_path,omitempty"`
59
+	// criu work path
60
+	CriuWorkPath string `protobuf:"bytes,11,opt,name=criu_work_path,json=criuWorkPath,proto3" json:"criu_work_path,omitempty"`
61
+}
62
+
63
+func (m *Options) Reset()                    { *m = Options{} }
64
+func (*Options) ProtoMessage()               {}
65
+func (*Options) Descriptor() ([]byte, []int) { return fileDescriptorOci, []int{0} }
66
+
67
+type CheckpointOptions struct {
68
+	// exit the container after a checkpoint
69
+	Exit bool `protobuf:"varint,1,opt,name=exit,proto3" json:"exit,omitempty"`
70
+	// checkpoint open tcp connections
71
+	OpenTcp bool `protobuf:"varint,2,opt,name=open_tcp,json=openTcp,proto3" json:"open_tcp,omitempty"`
72
+	// checkpoint external unix sockets
73
+	ExternalUnixSockets bool `protobuf:"varint,3,opt,name=external_unix_sockets,json=externalUnixSockets,proto3" json:"external_unix_sockets,omitempty"`
74
+	// checkpoint terminals (ptys)
75
+	Terminal bool `protobuf:"varint,4,opt,name=terminal,proto3" json:"terminal,omitempty"`
76
+	// allow checkpointing of file locks
77
+	FileLocks bool `protobuf:"varint,5,opt,name=file_locks,json=fileLocks,proto3" json:"file_locks,omitempty"`
78
+	// restore provided namespaces as empty namespaces
79
+	EmptyNamespaces []string `protobuf:"bytes,6,rep,name=empty_namespaces,json=emptyNamespaces" json:"empty_namespaces,omitempty"`
80
+	// set the cgroups mode, soft, full, strict
81
+	CgroupsMode string `protobuf:"bytes,7,opt,name=cgroups_mode,json=cgroupsMode,proto3" json:"cgroups_mode,omitempty"`
82
+	// checkpoint image path
83
+	ImagePath string `protobuf:"bytes,8,opt,name=image_path,json=imagePath,proto3" json:"image_path,omitempty"`
84
+	// checkpoint work path
85
+	WorkPath string `protobuf:"bytes,9,opt,name=work_path,json=workPath,proto3" json:"work_path,omitempty"`
86
+}
87
+
88
+func (m *CheckpointOptions) Reset()                    { *m = CheckpointOptions{} }
89
+func (*CheckpointOptions) ProtoMessage()               {}
90
+func (*CheckpointOptions) Descriptor() ([]byte, []int) { return fileDescriptorOci, []int{1} }
91
+
92
+type ProcessDetails struct {
93
+	// exec process id if the process is managed by a shim
94
+	ExecID string `protobuf:"bytes,1,opt,name=exec_id,json=execId,proto3" json:"exec_id,omitempty"`
95
+}
96
+
97
+func (m *ProcessDetails) Reset()                    { *m = ProcessDetails{} }
98
+func (*ProcessDetails) ProtoMessage()               {}
99
+func (*ProcessDetails) Descriptor() ([]byte, []int) { return fileDescriptorOci, []int{2} }
100
+
101
+func init() {
102
+	proto.RegisterType((*Options)(nil), "containerd.runc.v1.Options")
103
+	proto.RegisterType((*CheckpointOptions)(nil), "containerd.runc.v1.CheckpointOptions")
104
+	proto.RegisterType((*ProcessDetails)(nil), "containerd.runc.v1.ProcessDetails")
105
+}
106
+func (m *Options) Marshal() (dAtA []byte, err error) {
107
+	size := m.Size()
108
+	dAtA = make([]byte, size)
109
+	n, err := m.MarshalTo(dAtA)
110
+	if err != nil {
111
+		return nil, err
112
+	}
113
+	return dAtA[:n], nil
114
+}
115
+
116
+func (m *Options) MarshalTo(dAtA []byte) (int, error) {
117
+	var i int
118
+	_ = i
119
+	var l int
120
+	_ = l
121
+	if m.NoPivotRoot {
122
+		dAtA[i] = 0x8
123
+		i++
124
+		if m.NoPivotRoot {
125
+			dAtA[i] = 1
126
+		} else {
127
+			dAtA[i] = 0
128
+		}
129
+		i++
130
+	}
131
+	if m.NoNewKeyring {
132
+		dAtA[i] = 0x10
133
+		i++
134
+		if m.NoNewKeyring {
135
+			dAtA[i] = 1
136
+		} else {
137
+			dAtA[i] = 0
138
+		}
139
+		i++
140
+	}
141
+	if len(m.ShimCgroup) > 0 {
142
+		dAtA[i] = 0x1a
143
+		i++
144
+		i = encodeVarintOci(dAtA, i, uint64(len(m.ShimCgroup)))
145
+		i += copy(dAtA[i:], m.ShimCgroup)
146
+	}
147
+	if m.IoUid != 0 {
148
+		dAtA[i] = 0x20
149
+		i++
150
+		i = encodeVarintOci(dAtA, i, uint64(m.IoUid))
151
+	}
152
+	if m.IoGid != 0 {
153
+		dAtA[i] = 0x28
154
+		i++
155
+		i = encodeVarintOci(dAtA, i, uint64(m.IoGid))
156
+	}
157
+	if len(m.BinaryName) > 0 {
158
+		dAtA[i] = 0x32
159
+		i++
160
+		i = encodeVarintOci(dAtA, i, uint64(len(m.BinaryName)))
161
+		i += copy(dAtA[i:], m.BinaryName)
162
+	}
163
+	if len(m.Root) > 0 {
164
+		dAtA[i] = 0x3a
165
+		i++
166
+		i = encodeVarintOci(dAtA, i, uint64(len(m.Root)))
167
+		i += copy(dAtA[i:], m.Root)
168
+	}
169
+	if len(m.CriuPath) > 0 {
170
+		dAtA[i] = 0x42
171
+		i++
172
+		i = encodeVarintOci(dAtA, i, uint64(len(m.CriuPath)))
173
+		i += copy(dAtA[i:], m.CriuPath)
174
+	}
175
+	if m.SystemdCgroup {
176
+		dAtA[i] = 0x48
177
+		i++
178
+		if m.SystemdCgroup {
179
+			dAtA[i] = 1
180
+		} else {
181
+			dAtA[i] = 0
182
+		}
183
+		i++
184
+	}
185
+	if len(m.CriuImagePath) > 0 {
186
+		dAtA[i] = 0x52
187
+		i++
188
+		i = encodeVarintOci(dAtA, i, uint64(len(m.CriuImagePath)))
189
+		i += copy(dAtA[i:], m.CriuImagePath)
190
+	}
191
+	if len(m.CriuWorkPath) > 0 {
192
+		dAtA[i] = 0x5a
193
+		i++
194
+		i = encodeVarintOci(dAtA, i, uint64(len(m.CriuWorkPath)))
195
+		i += copy(dAtA[i:], m.CriuWorkPath)
196
+	}
197
+	return i, nil
198
+}
199
+
200
+func (m *CheckpointOptions) Marshal() (dAtA []byte, err error) {
201
+	size := m.Size()
202
+	dAtA = make([]byte, size)
203
+	n, err := m.MarshalTo(dAtA)
204
+	if err != nil {
205
+		return nil, err
206
+	}
207
+	return dAtA[:n], nil
208
+}
209
+
210
+func (m *CheckpointOptions) MarshalTo(dAtA []byte) (int, error) {
211
+	var i int
212
+	_ = i
213
+	var l int
214
+	_ = l
215
+	if m.Exit {
216
+		dAtA[i] = 0x8
217
+		i++
218
+		if m.Exit {
219
+			dAtA[i] = 1
220
+		} else {
221
+			dAtA[i] = 0
222
+		}
223
+		i++
224
+	}
225
+	if m.OpenTcp {
226
+		dAtA[i] = 0x10
227
+		i++
228
+		if m.OpenTcp {
229
+			dAtA[i] = 1
230
+		} else {
231
+			dAtA[i] = 0
232
+		}
233
+		i++
234
+	}
235
+	if m.ExternalUnixSockets {
236
+		dAtA[i] = 0x18
237
+		i++
238
+		if m.ExternalUnixSockets {
239
+			dAtA[i] = 1
240
+		} else {
241
+			dAtA[i] = 0
242
+		}
243
+		i++
244
+	}
245
+	if m.Terminal {
246
+		dAtA[i] = 0x20
247
+		i++
248
+		if m.Terminal {
249
+			dAtA[i] = 1
250
+		} else {
251
+			dAtA[i] = 0
252
+		}
253
+		i++
254
+	}
255
+	if m.FileLocks {
256
+		dAtA[i] = 0x28
257
+		i++
258
+		if m.FileLocks {
259
+			dAtA[i] = 1
260
+		} else {
261
+			dAtA[i] = 0
262
+		}
263
+		i++
264
+	}
265
+	if len(m.EmptyNamespaces) > 0 {
266
+		for _, s := range m.EmptyNamespaces {
267
+			dAtA[i] = 0x32
268
+			i++
269
+			l = len(s)
270
+			for l >= 1<<7 {
271
+				dAtA[i] = uint8(uint64(l)&0x7f | 0x80)
272
+				l >>= 7
273
+				i++
274
+			}
275
+			dAtA[i] = uint8(l)
276
+			i++
277
+			i += copy(dAtA[i:], s)
278
+		}
279
+	}
280
+	if len(m.CgroupsMode) > 0 {
281
+		dAtA[i] = 0x3a
282
+		i++
283
+		i = encodeVarintOci(dAtA, i, uint64(len(m.CgroupsMode)))
284
+		i += copy(dAtA[i:], m.CgroupsMode)
285
+	}
286
+	if len(m.ImagePath) > 0 {
287
+		dAtA[i] = 0x42
288
+		i++
289
+		i = encodeVarintOci(dAtA, i, uint64(len(m.ImagePath)))
290
+		i += copy(dAtA[i:], m.ImagePath)
291
+	}
292
+	if len(m.WorkPath) > 0 {
293
+		dAtA[i] = 0x4a
294
+		i++
295
+		i = encodeVarintOci(dAtA, i, uint64(len(m.WorkPath)))
296
+		i += copy(dAtA[i:], m.WorkPath)
297
+	}
298
+	return i, nil
299
+}
300
+
301
+func (m *ProcessDetails) Marshal() (dAtA []byte, err error) {
302
+	size := m.Size()
303
+	dAtA = make([]byte, size)
304
+	n, err := m.MarshalTo(dAtA)
305
+	if err != nil {
306
+		return nil, err
307
+	}
308
+	return dAtA[:n], nil
309
+}
310
+
311
+func (m *ProcessDetails) MarshalTo(dAtA []byte) (int, error) {
312
+	var i int
313
+	_ = i
314
+	var l int
315
+	_ = l
316
+	if len(m.ExecID) > 0 {
317
+		dAtA[i] = 0xa
318
+		i++
319
+		i = encodeVarintOci(dAtA, i, uint64(len(m.ExecID)))
320
+		i += copy(dAtA[i:], m.ExecID)
321
+	}
322
+	return i, nil
323
+}
324
+
325
+func encodeVarintOci(dAtA []byte, offset int, v uint64) int {
326
+	for v >= 1<<7 {
327
+		dAtA[offset] = uint8(v&0x7f | 0x80)
328
+		v >>= 7
329
+		offset++
330
+	}
331
+	dAtA[offset] = uint8(v)
332
+	return offset + 1
333
+}
334
+func (m *Options) Size() (n int) {
335
+	var l int
336
+	_ = l
337
+	if m.NoPivotRoot {
338
+		n += 2
339
+	}
340
+	if m.NoNewKeyring {
341
+		n += 2
342
+	}
343
+	l = len(m.ShimCgroup)
344
+	if l > 0 {
345
+		n += 1 + l + sovOci(uint64(l))
346
+	}
347
+	if m.IoUid != 0 {
348
+		n += 1 + sovOci(uint64(m.IoUid))
349
+	}
350
+	if m.IoGid != 0 {
351
+		n += 1 + sovOci(uint64(m.IoGid))
352
+	}
353
+	l = len(m.BinaryName)
354
+	if l > 0 {
355
+		n += 1 + l + sovOci(uint64(l))
356
+	}
357
+	l = len(m.Root)
358
+	if l > 0 {
359
+		n += 1 + l + sovOci(uint64(l))
360
+	}
361
+	l = len(m.CriuPath)
362
+	if l > 0 {
363
+		n += 1 + l + sovOci(uint64(l))
364
+	}
365
+	if m.SystemdCgroup {
366
+		n += 2
367
+	}
368
+	l = len(m.CriuImagePath)
369
+	if l > 0 {
370
+		n += 1 + l + sovOci(uint64(l))
371
+	}
372
+	l = len(m.CriuWorkPath)
373
+	if l > 0 {
374
+		n += 1 + l + sovOci(uint64(l))
375
+	}
376
+	return n
377
+}
378
+
379
+func (m *CheckpointOptions) Size() (n int) {
380
+	var l int
381
+	_ = l
382
+	if m.Exit {
383
+		n += 2
384
+	}
385
+	if m.OpenTcp {
386
+		n += 2
387
+	}
388
+	if m.ExternalUnixSockets {
389
+		n += 2
390
+	}
391
+	if m.Terminal {
392
+		n += 2
393
+	}
394
+	if m.FileLocks {
395
+		n += 2
396
+	}
397
+	if len(m.EmptyNamespaces) > 0 {
398
+		for _, s := range m.EmptyNamespaces {
399
+			l = len(s)
400
+			n += 1 + l + sovOci(uint64(l))
401
+		}
402
+	}
403
+	l = len(m.CgroupsMode)
404
+	if l > 0 {
405
+		n += 1 + l + sovOci(uint64(l))
406
+	}
407
+	l = len(m.ImagePath)
408
+	if l > 0 {
409
+		n += 1 + l + sovOci(uint64(l))
410
+	}
411
+	l = len(m.WorkPath)
412
+	if l > 0 {
413
+		n += 1 + l + sovOci(uint64(l))
414
+	}
415
+	return n
416
+}
417
+
418
+func (m *ProcessDetails) Size() (n int) {
419
+	var l int
420
+	_ = l
421
+	l = len(m.ExecID)
422
+	if l > 0 {
423
+		n += 1 + l + sovOci(uint64(l))
424
+	}
425
+	return n
426
+}
427
+
428
+func sovOci(x uint64) (n int) {
429
+	for {
430
+		n++
431
+		x >>= 7
432
+		if x == 0 {
433
+			break
434
+		}
435
+	}
436
+	return n
437
+}
438
+func sozOci(x uint64) (n int) {
439
+	return sovOci(uint64((x << 1) ^ uint64((int64(x) >> 63))))
440
+}
441
+func (this *Options) String() string {
442
+	if this == nil {
443
+		return "nil"
444
+	}
445
+	s := strings.Join([]string{`&Options{`,
446
+		`NoPivotRoot:` + fmt.Sprintf("%v", this.NoPivotRoot) + `,`,
447
+		`NoNewKeyring:` + fmt.Sprintf("%v", this.NoNewKeyring) + `,`,
448
+		`ShimCgroup:` + fmt.Sprintf("%v", this.ShimCgroup) + `,`,
449
+		`IoUid:` + fmt.Sprintf("%v", this.IoUid) + `,`,
450
+		`IoGid:` + fmt.Sprintf("%v", this.IoGid) + `,`,
451
+		`BinaryName:` + fmt.Sprintf("%v", this.BinaryName) + `,`,
452
+		`Root:` + fmt.Sprintf("%v", this.Root) + `,`,
453
+		`CriuPath:` + fmt.Sprintf("%v", this.CriuPath) + `,`,
454
+		`SystemdCgroup:` + fmt.Sprintf("%v", this.SystemdCgroup) + `,`,
455
+		`CriuImagePath:` + fmt.Sprintf("%v", this.CriuImagePath) + `,`,
456
+		`CriuWorkPath:` + fmt.Sprintf("%v", this.CriuWorkPath) + `,`,
457
+		`}`,
458
+	}, "")
459
+	return s
460
+}
461
+func (this *CheckpointOptions) String() string {
462
+	if this == nil {
463
+		return "nil"
464
+	}
465
+	s := strings.Join([]string{`&CheckpointOptions{`,
466
+		`Exit:` + fmt.Sprintf("%v", this.Exit) + `,`,
467
+		`OpenTcp:` + fmt.Sprintf("%v", this.OpenTcp) + `,`,
468
+		`ExternalUnixSockets:` + fmt.Sprintf("%v", this.ExternalUnixSockets) + `,`,
469
+		`Terminal:` + fmt.Sprintf("%v", this.Terminal) + `,`,
470
+		`FileLocks:` + fmt.Sprintf("%v", this.FileLocks) + `,`,
471
+		`EmptyNamespaces:` + fmt.Sprintf("%v", this.EmptyNamespaces) + `,`,
472
+		`CgroupsMode:` + fmt.Sprintf("%v", this.CgroupsMode) + `,`,
473
+		`ImagePath:` + fmt.Sprintf("%v", this.ImagePath) + `,`,
474
+		`WorkPath:` + fmt.Sprintf("%v", this.WorkPath) + `,`,
475
+		`}`,
476
+	}, "")
477
+	return s
478
+}
479
+func (this *ProcessDetails) String() string {
480
+	if this == nil {
481
+		return "nil"
482
+	}
483
+	s := strings.Join([]string{`&ProcessDetails{`,
484
+		`ExecID:` + fmt.Sprintf("%v", this.ExecID) + `,`,
485
+		`}`,
486
+	}, "")
487
+	return s
488
+}
489
+func valueToStringOci(v interface{}) string {
490
+	rv := reflect.ValueOf(v)
491
+	if rv.IsNil() {
492
+		return "nil"
493
+	}
494
+	pv := reflect.Indirect(rv).Interface()
495
+	return fmt.Sprintf("*%v", pv)
496
+}
497
+func (m *Options) Unmarshal(dAtA []byte) error {
498
+	l := len(dAtA)
499
+	iNdEx := 0
500
+	for iNdEx < l {
501
+		preIndex := iNdEx
502
+		var wire uint64
503
+		for shift := uint(0); ; shift += 7 {
504
+			if shift >= 64 {
505
+				return ErrIntOverflowOci
506
+			}
507
+			if iNdEx >= l {
508
+				return io.ErrUnexpectedEOF
509
+			}
510
+			b := dAtA[iNdEx]
511
+			iNdEx++
512
+			wire |= (uint64(b) & 0x7F) << shift
513
+			if b < 0x80 {
514
+				break
515
+			}
516
+		}
517
+		fieldNum := int32(wire >> 3)
518
+		wireType := int(wire & 0x7)
519
+		if wireType == 4 {
520
+			return fmt.Errorf("proto: Options: wiretype end group for non-group")
521
+		}
522
+		if fieldNum <= 0 {
523
+			return fmt.Errorf("proto: Options: illegal tag %d (wire type %d)", fieldNum, wire)
524
+		}
525
+		switch fieldNum {
526
+		case 1:
527
+			if wireType != 0 {
528
+				return fmt.Errorf("proto: wrong wireType = %d for field NoPivotRoot", wireType)
529
+			}
530
+			var v int
531
+			for shift := uint(0); ; shift += 7 {
532
+				if shift >= 64 {
533
+					return ErrIntOverflowOci
534
+				}
535
+				if iNdEx >= l {
536
+					return io.ErrUnexpectedEOF
537
+				}
538
+				b := dAtA[iNdEx]
539
+				iNdEx++
540
+				v |= (int(b) & 0x7F) << shift
541
+				if b < 0x80 {
542
+					break
543
+				}
544
+			}
545
+			m.NoPivotRoot = bool(v != 0)
546
+		case 2:
547
+			if wireType != 0 {
548
+				return fmt.Errorf("proto: wrong wireType = %d for field NoNewKeyring", wireType)
549
+			}
550
+			var v int
551
+			for shift := uint(0); ; shift += 7 {
552
+				if shift >= 64 {
553
+					return ErrIntOverflowOci
554
+				}
555
+				if iNdEx >= l {
556
+					return io.ErrUnexpectedEOF
557
+				}
558
+				b := dAtA[iNdEx]
559
+				iNdEx++
560
+				v |= (int(b) & 0x7F) << shift
561
+				if b < 0x80 {
562
+					break
563
+				}
564
+			}
565
+			m.NoNewKeyring = bool(v != 0)
566
+		case 3:
567
+			if wireType != 2 {
568
+				return fmt.Errorf("proto: wrong wireType = %d for field ShimCgroup", wireType)
569
+			}
570
+			var stringLen uint64
571
+			for shift := uint(0); ; shift += 7 {
572
+				if shift >= 64 {
573
+					return ErrIntOverflowOci
574
+				}
575
+				if iNdEx >= l {
576
+					return io.ErrUnexpectedEOF
577
+				}
578
+				b := dAtA[iNdEx]
579
+				iNdEx++
580
+				stringLen |= (uint64(b) & 0x7F) << shift
581
+				if b < 0x80 {
582
+					break
583
+				}
584
+			}
585
+			intStringLen := int(stringLen)
586
+			if intStringLen < 0 {
587
+				return ErrInvalidLengthOci
588
+			}
589
+			postIndex := iNdEx + intStringLen
590
+			if postIndex > l {
591
+				return io.ErrUnexpectedEOF
592
+			}
593
+			m.ShimCgroup = string(dAtA[iNdEx:postIndex])
594
+			iNdEx = postIndex
595
+		case 4:
596
+			if wireType != 0 {
597
+				return fmt.Errorf("proto: wrong wireType = %d for field IoUid", wireType)
598
+			}
599
+			m.IoUid = 0
600
+			for shift := uint(0); ; shift += 7 {
601
+				if shift >= 64 {
602
+					return ErrIntOverflowOci
603
+				}
604
+				if iNdEx >= l {
605
+					return io.ErrUnexpectedEOF
606
+				}
607
+				b := dAtA[iNdEx]
608
+				iNdEx++
609
+				m.IoUid |= (uint32(b) & 0x7F) << shift
610
+				if b < 0x80 {
611
+					break
612
+				}
613
+			}
614
+		case 5:
615
+			if wireType != 0 {
616
+				return fmt.Errorf("proto: wrong wireType = %d for field IoGid", wireType)
617
+			}
618
+			m.IoGid = 0
619
+			for shift := uint(0); ; shift += 7 {
620
+				if shift >= 64 {
621
+					return ErrIntOverflowOci
622
+				}
623
+				if iNdEx >= l {
624
+					return io.ErrUnexpectedEOF
625
+				}
626
+				b := dAtA[iNdEx]
627
+				iNdEx++
628
+				m.IoGid |= (uint32(b) & 0x7F) << shift
629
+				if b < 0x80 {
630
+					break
631
+				}
632
+			}
633
+		case 6:
634
+			if wireType != 2 {
635
+				return fmt.Errorf("proto: wrong wireType = %d for field BinaryName", wireType)
636
+			}
637
+			var stringLen uint64
638
+			for shift := uint(0); ; shift += 7 {
639
+				if shift >= 64 {
640
+					return ErrIntOverflowOci
641
+				}
642
+				if iNdEx >= l {
643
+					return io.ErrUnexpectedEOF
644
+				}
645
+				b := dAtA[iNdEx]
646
+				iNdEx++
647
+				stringLen |= (uint64(b) & 0x7F) << shift
648
+				if b < 0x80 {
649
+					break
650
+				}
651
+			}
652
+			intStringLen := int(stringLen)
653
+			if intStringLen < 0 {
654
+				return ErrInvalidLengthOci
655
+			}
656
+			postIndex := iNdEx + intStringLen
657
+			if postIndex > l {
658
+				return io.ErrUnexpectedEOF
659
+			}
660
+			m.BinaryName = string(dAtA[iNdEx:postIndex])
661
+			iNdEx = postIndex
662
+		case 7:
663
+			if wireType != 2 {
664
+				return fmt.Errorf("proto: wrong wireType = %d for field Root", wireType)
665
+			}
666
+			var stringLen uint64
667
+			for shift := uint(0); ; shift += 7 {
668
+				if shift >= 64 {
669
+					return ErrIntOverflowOci
670
+				}
671
+				if iNdEx >= l {
672
+					return io.ErrUnexpectedEOF
673
+				}
674
+				b := dAtA[iNdEx]
675
+				iNdEx++
676
+				stringLen |= (uint64(b) & 0x7F) << shift
677
+				if b < 0x80 {
678
+					break
679
+				}
680
+			}
681
+			intStringLen := int(stringLen)
682
+			if intStringLen < 0 {
683
+				return ErrInvalidLengthOci
684
+			}
685
+			postIndex := iNdEx + intStringLen
686
+			if postIndex > l {
687
+				return io.ErrUnexpectedEOF
688
+			}
689
+			m.Root = string(dAtA[iNdEx:postIndex])
690
+			iNdEx = postIndex
691
+		case 8:
692
+			if wireType != 2 {
693
+				return fmt.Errorf("proto: wrong wireType = %d for field CriuPath", wireType)
694
+			}
695
+			var stringLen uint64
696
+			for shift := uint(0); ; shift += 7 {
697
+				if shift >= 64 {
698
+					return ErrIntOverflowOci
699
+				}
700
+				if iNdEx >= l {
701
+					return io.ErrUnexpectedEOF
702
+				}
703
+				b := dAtA[iNdEx]
704
+				iNdEx++
705
+				stringLen |= (uint64(b) & 0x7F) << shift
706
+				if b < 0x80 {
707
+					break
708
+				}
709
+			}
710
+			intStringLen := int(stringLen)
711
+			if intStringLen < 0 {
712
+				return ErrInvalidLengthOci
713
+			}
714
+			postIndex := iNdEx + intStringLen
715
+			if postIndex > l {
716
+				return io.ErrUnexpectedEOF
717
+			}
718
+			m.CriuPath = string(dAtA[iNdEx:postIndex])
719
+			iNdEx = postIndex
720
+		case 9:
721
+			if wireType != 0 {
722
+				return fmt.Errorf("proto: wrong wireType = %d for field SystemdCgroup", wireType)
723
+			}
724
+			var v int
725
+			for shift := uint(0); ; shift += 7 {
726
+				if shift >= 64 {
727
+					return ErrIntOverflowOci
728
+				}
729
+				if iNdEx >= l {
730
+					return io.ErrUnexpectedEOF
731
+				}
732
+				b := dAtA[iNdEx]
733
+				iNdEx++
734
+				v |= (int(b) & 0x7F) << shift
735
+				if b < 0x80 {
736
+					break
737
+				}
738
+			}
739
+			m.SystemdCgroup = bool(v != 0)
740
+		case 10:
741
+			if wireType != 2 {
742
+				return fmt.Errorf("proto: wrong wireType = %d for field CriuImagePath", wireType)
743
+			}
744
+			var stringLen uint64
745
+			for shift := uint(0); ; shift += 7 {
746
+				if shift >= 64 {
747
+					return ErrIntOverflowOci
748
+				}
749
+				if iNdEx >= l {
750
+					return io.ErrUnexpectedEOF
751
+				}
752
+				b := dAtA[iNdEx]
753
+				iNdEx++
754
+				stringLen |= (uint64(b) & 0x7F) << shift
755
+				if b < 0x80 {
756
+					break
757
+				}
758
+			}
759
+			intStringLen := int(stringLen)
760
+			if intStringLen < 0 {
761
+				return ErrInvalidLengthOci
762
+			}
763
+			postIndex := iNdEx + intStringLen
764
+			if postIndex > l {
765
+				return io.ErrUnexpectedEOF
766
+			}
767
+			m.CriuImagePath = string(dAtA[iNdEx:postIndex])
768
+			iNdEx = postIndex
769
+		case 11:
770
+			if wireType != 2 {
771
+				return fmt.Errorf("proto: wrong wireType = %d for field CriuWorkPath", wireType)
772
+			}
773
+			var stringLen uint64
774
+			for shift := uint(0); ; shift += 7 {
775
+				if shift >= 64 {
776
+					return ErrIntOverflowOci
777
+				}
778
+				if iNdEx >= l {
779
+					return io.ErrUnexpectedEOF
780
+				}
781
+				b := dAtA[iNdEx]
782
+				iNdEx++
783
+				stringLen |= (uint64(b) & 0x7F) << shift
784
+				if b < 0x80 {
785
+					break
786
+				}
787
+			}
788
+			intStringLen := int(stringLen)
789
+			if intStringLen < 0 {
790
+				return ErrInvalidLengthOci
791
+			}
792
+			postIndex := iNdEx + intStringLen
793
+			if postIndex > l {
794
+				return io.ErrUnexpectedEOF
795
+			}
796
+			m.CriuWorkPath = string(dAtA[iNdEx:postIndex])
797
+			iNdEx = postIndex
798
+		default:
799
+			iNdEx = preIndex
800
+			skippy, err := skipOci(dAtA[iNdEx:])
801
+			if err != nil {
802
+				return err
803
+			}
804
+			if skippy < 0 {
805
+				return ErrInvalidLengthOci
806
+			}
807
+			if (iNdEx + skippy) > l {
808
+				return io.ErrUnexpectedEOF
809
+			}
810
+			iNdEx += skippy
811
+		}
812
+	}
813
+
814
+	if iNdEx > l {
815
+		return io.ErrUnexpectedEOF
816
+	}
817
+	return nil
818
+}
819
+func (m *CheckpointOptions) Unmarshal(dAtA []byte) error {
820
+	l := len(dAtA)
821
+	iNdEx := 0
822
+	for iNdEx < l {
823
+		preIndex := iNdEx
824
+		var wire uint64
825
+		for shift := uint(0); ; shift += 7 {
826
+			if shift >= 64 {
827
+				return ErrIntOverflowOci
828
+			}
829
+			if iNdEx >= l {
830
+				return io.ErrUnexpectedEOF
831
+			}
832
+			b := dAtA[iNdEx]
833
+			iNdEx++
834
+			wire |= (uint64(b) & 0x7F) << shift
835
+			if b < 0x80 {
836
+				break
837
+			}
838
+		}
839
+		fieldNum := int32(wire >> 3)
840
+		wireType := int(wire & 0x7)
841
+		if wireType == 4 {
842
+			return fmt.Errorf("proto: CheckpointOptions: wiretype end group for non-group")
843
+		}
844
+		if fieldNum <= 0 {
845
+			return fmt.Errorf("proto: CheckpointOptions: illegal tag %d (wire type %d)", fieldNum, wire)
846
+		}
847
+		switch fieldNum {
848
+		case 1:
849
+			if wireType != 0 {
850
+				return fmt.Errorf("proto: wrong wireType = %d for field Exit", wireType)
851
+			}
852
+			var v int
853
+			for shift := uint(0); ; shift += 7 {
854
+				if shift >= 64 {
855
+					return ErrIntOverflowOci
856
+				}
857
+				if iNdEx >= l {
858
+					return io.ErrUnexpectedEOF
859
+				}
860
+				b := dAtA[iNdEx]
861
+				iNdEx++
862
+				v |= (int(b) & 0x7F) << shift
863
+				if b < 0x80 {
864
+					break
865
+				}
866
+			}
867
+			m.Exit = bool(v != 0)
868
+		case 2:
869
+			if wireType != 0 {
870
+				return fmt.Errorf("proto: wrong wireType = %d for field OpenTcp", wireType)
871
+			}
872
+			var v int
873
+			for shift := uint(0); ; shift += 7 {
874
+				if shift >= 64 {
875
+					return ErrIntOverflowOci
876
+				}
877
+				if iNdEx >= l {
878
+					return io.ErrUnexpectedEOF
879
+				}
880
+				b := dAtA[iNdEx]
881
+				iNdEx++
882
+				v |= (int(b) & 0x7F) << shift
883
+				if b < 0x80 {
884
+					break
885
+				}
886
+			}
887
+			m.OpenTcp = bool(v != 0)
888
+		case 3:
889
+			if wireType != 0 {
890
+				return fmt.Errorf("proto: wrong wireType = %d for field ExternalUnixSockets", wireType)
891
+			}
892
+			var v int
893
+			for shift := uint(0); ; shift += 7 {
894
+				if shift >= 64 {
895
+					return ErrIntOverflowOci
896
+				}
897
+				if iNdEx >= l {
898
+					return io.ErrUnexpectedEOF
899
+				}
900
+				b := dAtA[iNdEx]
901
+				iNdEx++
902
+				v |= (int(b) & 0x7F) << shift
903
+				if b < 0x80 {
904
+					break
905
+				}
906
+			}
907
+			m.ExternalUnixSockets = bool(v != 0)
908
+		case 4:
909
+			if wireType != 0 {
910
+				return fmt.Errorf("proto: wrong wireType = %d for field Terminal", wireType)
911
+			}
912
+			var v int
913
+			for shift := uint(0); ; shift += 7 {
914
+				if shift >= 64 {
915
+					return ErrIntOverflowOci
916
+				}
917
+				if iNdEx >= l {
918
+					return io.ErrUnexpectedEOF
919
+				}
920
+				b := dAtA[iNdEx]
921
+				iNdEx++
922
+				v |= (int(b) & 0x7F) << shift
923
+				if b < 0x80 {
924
+					break
925
+				}
926
+			}
927
+			m.Terminal = bool(v != 0)
928
+		case 5:
929
+			if wireType != 0 {
930
+				return fmt.Errorf("proto: wrong wireType = %d for field FileLocks", wireType)
931
+			}
932
+			var v int
933
+			for shift := uint(0); ; shift += 7 {
934
+				if shift >= 64 {
935
+					return ErrIntOverflowOci
936
+				}
937
+				if iNdEx >= l {
938
+					return io.ErrUnexpectedEOF
939
+				}
940
+				b := dAtA[iNdEx]
941
+				iNdEx++
942
+				v |= (int(b) & 0x7F) << shift
943
+				if b < 0x80 {
944
+					break
945
+				}
946
+			}
947
+			m.FileLocks = bool(v != 0)
948
+		case 6:
949
+			if wireType != 2 {
950
+				return fmt.Errorf("proto: wrong wireType = %d for field EmptyNamespaces", wireType)
951
+			}
952
+			var stringLen uint64
953
+			for shift := uint(0); ; shift += 7 {
954
+				if shift >= 64 {
955
+					return ErrIntOverflowOci
956
+				}
957
+				if iNdEx >= l {
958
+					return io.ErrUnexpectedEOF
959
+				}
960
+				b := dAtA[iNdEx]
961
+				iNdEx++
962
+				stringLen |= (uint64(b) & 0x7F) << shift
963
+				if b < 0x80 {
964
+					break
965
+				}
966
+			}
967
+			intStringLen := int(stringLen)
968
+			if intStringLen < 0 {
969
+				return ErrInvalidLengthOci
970
+			}
971
+			postIndex := iNdEx + intStringLen
972
+			if postIndex > l {
973
+				return io.ErrUnexpectedEOF
974
+			}
975
+			m.EmptyNamespaces = append(m.EmptyNamespaces, string(dAtA[iNdEx:postIndex]))
976
+			iNdEx = postIndex
977
+		case 7:
978
+			if wireType != 2 {
979
+				return fmt.Errorf("proto: wrong wireType = %d for field CgroupsMode", wireType)
980
+			}
981
+			var stringLen uint64
982
+			for shift := uint(0); ; shift += 7 {
983
+				if shift >= 64 {
984
+					return ErrIntOverflowOci
985
+				}
986
+				if iNdEx >= l {
987
+					return io.ErrUnexpectedEOF
988
+				}
989
+				b := dAtA[iNdEx]
990
+				iNdEx++
991
+				stringLen |= (uint64(b) & 0x7F) << shift
992
+				if b < 0x80 {
993
+					break
994
+				}
995
+			}
996
+			intStringLen := int(stringLen)
997
+			if intStringLen < 0 {
998
+				return ErrInvalidLengthOci
999
+			}
1000
+			postIndex := iNdEx + intStringLen
1001
+			if postIndex > l {
1002
+				return io.ErrUnexpectedEOF
1003
+			}
1004
+			m.CgroupsMode = string(dAtA[iNdEx:postIndex])
1005
+			iNdEx = postIndex
1006
+		case 8:
1007
+			if wireType != 2 {
1008
+				return fmt.Errorf("proto: wrong wireType = %d for field ImagePath", wireType)
1009
+			}
1010
+			var stringLen uint64
1011
+			for shift := uint(0); ; shift += 7 {
1012
+				if shift >= 64 {
1013
+					return ErrIntOverflowOci
1014
+				}
1015
+				if iNdEx >= l {
1016
+					return io.ErrUnexpectedEOF
1017
+				}
1018
+				b := dAtA[iNdEx]
1019
+				iNdEx++
1020
+				stringLen |= (uint64(b) & 0x7F) << shift
1021
+				if b < 0x80 {
1022
+					break
1023
+				}
1024
+			}
1025
+			intStringLen := int(stringLen)
1026
+			if intStringLen < 0 {
1027
+				return ErrInvalidLengthOci
1028
+			}
1029
+			postIndex := iNdEx + intStringLen
1030
+			if postIndex > l {
1031
+				return io.ErrUnexpectedEOF
1032
+			}
1033
+			m.ImagePath = string(dAtA[iNdEx:postIndex])
1034
+			iNdEx = postIndex
1035
+		case 9:
1036
+			if wireType != 2 {
1037
+				return fmt.Errorf("proto: wrong wireType = %d for field WorkPath", wireType)
1038
+			}
1039
+			var stringLen uint64
1040
+			for shift := uint(0); ; shift += 7 {
1041
+				if shift >= 64 {
1042
+					return ErrIntOverflowOci
1043
+				}
1044
+				if iNdEx >= l {
1045
+					return io.ErrUnexpectedEOF
1046
+				}
1047
+				b := dAtA[iNdEx]
1048
+				iNdEx++
1049
+				stringLen |= (uint64(b) & 0x7F) << shift
1050
+				if b < 0x80 {
1051
+					break
1052
+				}
1053
+			}
1054
+			intStringLen := int(stringLen)
1055
+			if intStringLen < 0 {
1056
+				return ErrInvalidLengthOci
1057
+			}
1058
+			postIndex := iNdEx + intStringLen
1059
+			if postIndex > l {
1060
+				return io.ErrUnexpectedEOF
1061
+			}
1062
+			m.WorkPath = string(dAtA[iNdEx:postIndex])
1063
+			iNdEx = postIndex
1064
+		default:
1065
+			iNdEx = preIndex
1066
+			skippy, err := skipOci(dAtA[iNdEx:])
1067
+			if err != nil {
1068
+				return err
1069
+			}
1070
+			if skippy < 0 {
1071
+				return ErrInvalidLengthOci
1072
+			}
1073
+			if (iNdEx + skippy) > l {
1074
+				return io.ErrUnexpectedEOF
1075
+			}
1076
+			iNdEx += skippy
1077
+		}
1078
+	}
1079
+
1080
+	if iNdEx > l {
1081
+		return io.ErrUnexpectedEOF
1082
+	}
1083
+	return nil
1084
+}
1085
+func (m *ProcessDetails) Unmarshal(dAtA []byte) error {
1086
+	l := len(dAtA)
1087
+	iNdEx := 0
1088
+	for iNdEx < l {
1089
+		preIndex := iNdEx
1090
+		var wire uint64
1091
+		for shift := uint(0); ; shift += 7 {
1092
+			if shift >= 64 {
1093
+				return ErrIntOverflowOci
1094
+			}
1095
+			if iNdEx >= l {
1096
+				return io.ErrUnexpectedEOF
1097
+			}
1098
+			b := dAtA[iNdEx]
1099
+			iNdEx++
1100
+			wire |= (uint64(b) & 0x7F) << shift
1101
+			if b < 0x80 {
1102
+				break
1103
+			}
1104
+		}
1105
+		fieldNum := int32(wire >> 3)
1106
+		wireType := int(wire & 0x7)
1107
+		if wireType == 4 {
1108
+			return fmt.Errorf("proto: ProcessDetails: wiretype end group for non-group")
1109
+		}
1110
+		if fieldNum <= 0 {
1111
+			return fmt.Errorf("proto: ProcessDetails: illegal tag %d (wire type %d)", fieldNum, wire)
1112
+		}
1113
+		switch fieldNum {
1114
+		case 1:
1115
+			if wireType != 2 {
1116
+				return fmt.Errorf("proto: wrong wireType = %d for field ExecID", wireType)
1117
+			}
1118
+			var stringLen uint64
1119
+			for shift := uint(0); ; shift += 7 {
1120
+				if shift >= 64 {
1121
+					return ErrIntOverflowOci
1122
+				}
1123
+				if iNdEx >= l {
1124
+					return io.ErrUnexpectedEOF
1125
+				}
1126
+				b := dAtA[iNdEx]
1127
+				iNdEx++
1128
+				stringLen |= (uint64(b) & 0x7F) << shift
1129
+				if b < 0x80 {
1130
+					break
1131
+				}
1132
+			}
1133
+			intStringLen := int(stringLen)
1134
+			if intStringLen < 0 {
1135
+				return ErrInvalidLengthOci
1136
+			}
1137
+			postIndex := iNdEx + intStringLen
1138
+			if postIndex > l {
1139
+				return io.ErrUnexpectedEOF
1140
+			}
1141
+			m.ExecID = string(dAtA[iNdEx:postIndex])
1142
+			iNdEx = postIndex
1143
+		default:
1144
+			iNdEx = preIndex
1145
+			skippy, err := skipOci(dAtA[iNdEx:])
1146
+			if err != nil {
1147
+				return err
1148
+			}
1149
+			if skippy < 0 {
1150
+				return ErrInvalidLengthOci
1151
+			}
1152
+			if (iNdEx + skippy) > l {
1153
+				return io.ErrUnexpectedEOF
1154
+			}
1155
+			iNdEx += skippy
1156
+		}
1157
+	}
1158
+
1159
+	if iNdEx > l {
1160
+		return io.ErrUnexpectedEOF
1161
+	}
1162
+	return nil
1163
+}
1164
+func skipOci(dAtA []byte) (n int, err error) {
1165
+	l := len(dAtA)
1166
+	iNdEx := 0
1167
+	for iNdEx < l {
1168
+		var wire uint64
1169
+		for shift := uint(0); ; shift += 7 {
1170
+			if shift >= 64 {
1171
+				return 0, ErrIntOverflowOci
1172
+			}
1173
+			if iNdEx >= l {
1174
+				return 0, io.ErrUnexpectedEOF
1175
+			}
1176
+			b := dAtA[iNdEx]
1177
+			iNdEx++
1178
+			wire |= (uint64(b) & 0x7F) << shift
1179
+			if b < 0x80 {
1180
+				break
1181
+			}
1182
+		}
1183
+		wireType := int(wire & 0x7)
1184
+		switch wireType {
1185
+		case 0:
1186
+			for shift := uint(0); ; shift += 7 {
1187
+				if shift >= 64 {
1188
+					return 0, ErrIntOverflowOci
1189
+				}
1190
+				if iNdEx >= l {
1191
+					return 0, io.ErrUnexpectedEOF
1192
+				}
1193
+				iNdEx++
1194
+				if dAtA[iNdEx-1] < 0x80 {
1195
+					break
1196
+				}
1197
+			}
1198
+			return iNdEx, nil
1199
+		case 1:
1200
+			iNdEx += 8
1201
+			return iNdEx, nil
1202
+		case 2:
1203
+			var length int
1204
+			for shift := uint(0); ; shift += 7 {
1205
+				if shift >= 64 {
1206
+					return 0, ErrIntOverflowOci
1207
+				}
1208
+				if iNdEx >= l {
1209
+					return 0, io.ErrUnexpectedEOF
1210
+				}
1211
+				b := dAtA[iNdEx]
1212
+				iNdEx++
1213
+				length |= (int(b) & 0x7F) << shift
1214
+				if b < 0x80 {
1215
+					break
1216
+				}
1217
+			}
1218
+			iNdEx += length
1219
+			if length < 0 {
1220
+				return 0, ErrInvalidLengthOci
1221
+			}
1222
+			return iNdEx, nil
1223
+		case 3:
1224
+			for {
1225
+				var innerWire uint64
1226
+				var start int = iNdEx
1227
+				for shift := uint(0); ; shift += 7 {
1228
+					if shift >= 64 {
1229
+						return 0, ErrIntOverflowOci
1230
+					}
1231
+					if iNdEx >= l {
1232
+						return 0, io.ErrUnexpectedEOF
1233
+					}
1234
+					b := dAtA[iNdEx]
1235
+					iNdEx++
1236
+					innerWire |= (uint64(b) & 0x7F) << shift
1237
+					if b < 0x80 {
1238
+						break
1239
+					}
1240
+				}
1241
+				innerWireType := int(innerWire & 0x7)
1242
+				if innerWireType == 4 {
1243
+					break
1244
+				}
1245
+				next, err := skipOci(dAtA[start:])
1246
+				if err != nil {
1247
+					return 0, err
1248
+				}
1249
+				iNdEx = start + next
1250
+			}
1251
+			return iNdEx, nil
1252
+		case 4:
1253
+			return iNdEx, nil
1254
+		case 5:
1255
+			iNdEx += 4
1256
+			return iNdEx, nil
1257
+		default:
1258
+			return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
1259
+		}
1260
+	}
1261
+	panic("unreachable")
1262
+}
1263
+
1264
+var (
1265
+	ErrInvalidLengthOci = fmt.Errorf("proto: negative length found during unmarshaling")
1266
+	ErrIntOverflowOci   = fmt.Errorf("proto: integer overflow")
1267
+)
1268
+
1269
+func init() {
1270
+	proto.RegisterFile("github.com/containerd/containerd/runtime/v2/runc/options/oci.proto", fileDescriptorOci)
1271
+}
1272
+
1273
+var fileDescriptorOci = []byte{
1274
+	// 587 bytes of a gzipped FileDescriptorProto
1275
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x93, 0xcf, 0x6e, 0xd3, 0x40,
1276
+	0x10, 0x87, 0xeb, 0xfe, 0x49, 0xec, 0x4d, 0x93, 0xc2, 0x42, 0x25, 0xd3, 0x8a, 0x34, 0x94, 0x82,
1277
+	0xc2, 0x25, 0x11, 0x45, 0x9c, 0xb8, 0xa0, 0xb6, 0x08, 0x55, 0x40, 0xa9, 0x0c, 0x15, 0xa8, 0x97,
1278
+	0x95, 0xbb, 0x1e, 0x9c, 0x51, 0xe2, 0x1d, 0xcb, 0xbb, 0x69, 0xd2, 0x1b, 0xef, 0xc5, 0x0b, 0xf4,
1279
+	0xc8, 0x91, 0x13, 0xa2, 0xb9, 0xf1, 0x16, 0x68, 0xd7, 0x4e, 0xdb, 0x33, 0x27, 0xcf, 0x7e, 0xf3,
1280
+	0xf3, 0x78, 0xfd, 0xad, 0x96, 0xed, 0xa5, 0x68, 0x06, 0xe3, 0xb3, 0x9e, 0xa4, 0xac, 0x2f, 0x49,
1281
+	0x99, 0x18, 0x15, 0x14, 0xc9, 0xed, 0xb2, 0x18, 0x2b, 0x83, 0x19, 0xf4, 0xcf, 0x77, 0x6d, 0x29,
1282
+	0xfb, 0x94, 0x1b, 0x24, 0xa5, 0xfb, 0x24, 0xb1, 0x97, 0x17, 0x64, 0x88, 0xf3, 0x9b, 0x74, 0xcf,
1283
+	0x46, 0x7a, 0xe7, 0xcf, 0x37, 0xee, 0xa7, 0x94, 0x92, 0x6b, 0xf7, 0x6d, 0x55, 0x26, 0xb7, 0xff,
1284
+	0x2e, 0xb2, 0xfa, 0xc7, 0xf2, 0x7d, 0xbe, 0xcd, 0x9a, 0x8a, 0x44, 0x8e, 0xe7, 0x64, 0x44, 0x41,
1285
+	0x64, 0x42, 0xaf, 0xe3, 0x75, 0xfd, 0xa8, 0xa1, 0xe8, 0xd8, 0xb2, 0x88, 0xc8, 0xf0, 0x1d, 0xd6,
1286
+	0x52, 0x24, 0x14, 0x4c, 0xc4, 0x10, 0x2e, 0x0a, 0x54, 0x69, 0xb8, 0xe8, 0x42, 0xab, 0x8a, 0x8e,
1287
+	0x60, 0xf2, 0xae, 0x64, 0x7c, 0x8b, 0x35, 0xf4, 0x00, 0x33, 0x21, 0xd3, 0x82, 0xc6, 0x79, 0xb8,
1288
+	0xd4, 0xf1, 0xba, 0x41, 0xc4, 0x2c, 0xda, 0x77, 0x84, 0xaf, 0xb3, 0x1a, 0x92, 0x18, 0x63, 0x12,
1289
+	0x2e, 0x77, 0xbc, 0x6e, 0x33, 0x5a, 0x41, 0x3a, 0xc1, 0xa4, 0xc2, 0x29, 0x26, 0xe1, 0xca, 0x1c,
1290
+	0xbf, 0xc5, 0xc4, 0x8e, 0x3b, 0x43, 0x15, 0x17, 0x17, 0x42, 0xc5, 0x19, 0x84, 0xb5, 0x72, 0x5c,
1291
+	0x89, 0x8e, 0xe2, 0x0c, 0x38, 0x67, 0xcb, 0x6e, 0xc3, 0x75, 0xd7, 0x71, 0x35, 0xdf, 0x64, 0x81,
1292
+	0x2c, 0x70, 0x2c, 0xf2, 0xd8, 0x0c, 0x42, 0xdf, 0x35, 0x7c, 0x0b, 0x8e, 0x63, 0x33, 0xe0, 0x4f,
1293
+	0x58, 0x4b, 0x5f, 0x68, 0x03, 0x59, 0x32, 0xdf, 0x63, 0xe0, 0x7e, 0xa3, 0x59, 0xd1, 0x6a, 0x9b,
1294
+	0x4f, 0xd9, 0x9a, 0x9b, 0x81, 0x59, 0x9c, 0x42, 0x39, 0x89, 0xb9, 0x49, 0x4d, 0x8b, 0x0f, 0x2d,
1295
+	0x75, 0xe3, 0x76, 0x58, 0xcb, 0xe5, 0x26, 0x54, 0x0c, 0xcb, 0x58, 0xc3, 0xc5, 0x56, 0x2d, 0xfd,
1296
+	0x42, 0xc5, 0xd0, 0xa6, 0xb6, 0x7f, 0x2c, 0xb2, 0xbb, 0xfb, 0x03, 0x90, 0xc3, 0x9c, 0x50, 0x99,
1297
+	0xb9, 0x75, 0xce, 0x96, 0x61, 0x8a, 0x73, 0xd9, 0xae, 0xe6, 0x0f, 0x98, 0x4f, 0x39, 0x28, 0x61,
1298
+	0x64, 0x5e, 0xf9, 0xad, 0xdb, 0xf5, 0x67, 0x99, 0xf3, 0x5d, 0xb6, 0x0e, 0x53, 0x03, 0x85, 0x8a,
1299
+	0x47, 0x62, 0xac, 0x70, 0x2a, 0x34, 0xc9, 0x21, 0x18, 0xed, 0x24, 0xfb, 0xd1, 0xbd, 0x79, 0xf3,
1300
+	0x44, 0xe1, 0xf4, 0x53, 0xd9, 0xe2, 0x1b, 0xcc, 0x37, 0x50, 0x64, 0xa8, 0xe2, 0x91, 0xf3, 0xed,
1301
+	0x47, 0xd7, 0x6b, 0xfe, 0x90, 0xb1, 0x6f, 0x38, 0x02, 0x31, 0x22, 0x39, 0xd4, 0x4e, 0xbb, 0x1f,
1302
+	0x05, 0x96, 0xbc, 0xb7, 0x80, 0x3f, 0x63, 0x77, 0x20, 0xcb, 0x4d, 0x69, 0x5e, 0xe7, 0xb1, 0x04,
1303
+	0x1d, 0xd6, 0x3a, 0x4b, 0xdd, 0x20, 0x5a, 0x73, 0xfc, 0xe8, 0x1a, 0xf3, 0x47, 0x6c, 0xb5, 0x74,
1304
+	0xa9, 0x45, 0x46, 0x09, 0x54, 0x87, 0xd1, 0xa8, 0xd8, 0x07, 0x4a, 0xc0, 0x7e, 0xec, 0x96, 0xca,
1305
+	0xf2, 0x50, 0x02, 0xbc, 0xd6, 0xb8, 0xc9, 0x82, 0x1b, 0x83, 0x41, 0x79, 0x64, 0x93, 0xb9, 0xbd,
1306
+	0x97, 0xac, 0x75, 0x5c, 0x90, 0x04, 0xad, 0x0f, 0xc0, 0xc4, 0x38, 0xd2, 0xfc, 0x31, 0xab, 0xc3,
1307
+	0x14, 0xa4, 0xc0, 0xc4, 0xc9, 0x0b, 0xf6, 0xd8, 0xec, 0xf7, 0x56, 0xed, 0xcd, 0x14, 0xe4, 0xe1,
1308
+	0x41, 0x54, 0xb3, 0xad, 0xc3, 0x64, 0xef, 0xf4, 0xf2, 0xaa, 0xbd, 0xf0, 0xeb, 0xaa, 0xbd, 0xf0,
1309
+	0x7d, 0xd6, 0xf6, 0x2e, 0x67, 0x6d, 0xef, 0xe7, 0xac, 0xed, 0xfd, 0x99, 0xb5, 0xbd, 0xd3, 0xd7,
1310
+	0xff, 0x7b, 0xd1, 0x5e, 0x55, 0xcf, 0xaf, 0x0b, 0x67, 0x35, 0x77, 0x8b, 0x5e, 0xfc, 0x0b, 0x00,
1311
+	0x00, 0xff, 0xff, 0x90, 0x50, 0x79, 0xf2, 0xb5, 0x03, 0x00, 0x00,
1312
+}
0 1313
new file mode 100644
... ...
@@ -0,0 +1,58 @@
0
+syntax = "proto3";
1
+
2
+package containerd.runc.v1;
3
+
4
+import weak "gogoproto/gogo.proto";
5
+
6
+option go_package = "github.com/containerd/containerd/runtime/v2/runc/options;options";
7
+
8
+message Options {
9
+	// disable pivot root when creating a container
10
+	bool no_pivot_root = 1;
11
+	// create a new keyring for the container
12
+	bool no_new_keyring = 2;
13
+	// place the shim in a cgroup
14
+	string shim_cgroup = 3;
15
+	// set the I/O's pipes uid
16
+	uint32 io_uid = 4;
17
+	// set the I/O's pipes gid
18
+	uint32 io_gid = 5;
19
+	// binary name of the runc binary
20
+	string binary_name = 6;
21
+	// runc root directory
22
+	string root = 7;
23
+	// criu binary path
24
+	string criu_path = 8;
25
+	// enable systemd cgroups
26
+	bool systemd_cgroup = 9;
27
+	// criu image path
28
+	string criu_image_path = 10;
29
+	// criu work path
30
+	string criu_work_path = 11;
31
+}
32
+
33
+message CheckpointOptions {
34
+	// exit the container after a checkpoint
35
+	bool exit = 1;
36
+	// checkpoint open tcp connections
37
+	bool open_tcp = 2;
38
+	// checkpoint external unix sockets
39
+	bool external_unix_sockets = 3;
40
+	// checkpoint terminals (ptys)
41
+	bool terminal = 4;
42
+	// allow checkpointing of file locks
43
+	bool file_locks = 5;
44
+	// restore provided namespaces as empty namespaces
45
+	repeated string empty_namespaces = 6;
46
+	// set the cgroups mode, soft, full, strict
47
+	string cgroups_mode = 7;
48
+	// checkpoint image path
49
+	string image_path = 8;
50
+	// checkpoint work path
51
+	string work_path = 9;
52
+}
53
+
54
+message ProcessDetails {
55
+	// exec process id if the process is managed by a shim
56
+	string exec_id = 1;
57
+}
... ...
@@ -83,6 +83,44 @@ type ProxyPlugin struct {
83 83
 	Address string `toml:"address"`
84 84
 }
85 85
 
86
+// BoltConfig defines the configuration values for the bolt plugin, which is
87
+// loaded here, rather than back registered in the metadata package.
88
+type BoltConfig struct {
89
+	// ContentSharingPolicy sets the sharing policy for content between
90
+	// namespaces.
91
+	//
92
+	// The default mode "shared" will make blobs available in all
93
+	// namespaces once it is pulled into any namespace. The blob will be pulled
94
+	// into the namespace if a writer is opened with the "Expected" digest that
95
+	// is already present in the backend.
96
+	//
97
+	// The alternative mode, "isolated" requires that clients prove they have
98
+	// access to the content by providing all of the content to the ingest
99
+	// before the blob is added to the namespace.
100
+	//
101
+	// Both modes share backing data, while "shared" will reduce total
102
+	// bandwidth across namespaces, at the cost of allowing access to any blob
103
+	// just by knowing its digest.
104
+	ContentSharingPolicy string `toml:"content_sharing_policy"`
105
+}
106
+
107
+const (
108
+	// SharingPolicyShared represents the "shared" sharing policy
109
+	SharingPolicyShared = "shared"
110
+	// SharingPolicyIsolated represents the "isolated" sharing policy
111
+	SharingPolicyIsolated = "isolated"
112
+)
113
+
114
+// Validate validates if BoltConfig is valid
115
+func (bc *BoltConfig) Validate() error {
116
+	switch bc.ContentSharingPolicy {
117
+	case SharingPolicyShared, SharingPolicyIsolated:
118
+		return nil
119
+	default:
120
+		return errors.Wrapf(errdefs.ErrInvalidArgument, "unknown policy: %s", bc.ContentSharingPolicy)
121
+	}
122
+}
123
+
86 124
 // Decode unmarshals a plugin specific configuration by plugin id
87 125
 func (c *Config) Decode(id string, v interface{}) (interface{}, error) {
88 126
 	data, ok := c.Plugins[id]
89 127
deleted file mode 100644
... ...
@@ -1,60 +0,0 @@
1
-/*
2
-   Copyright The containerd Authors.
3
-
4
-   Licensed under the Apache License, Version 2.0 (the "License");
5
-   you may not use this file except in compliance with the License.
6
-   You may obtain a copy of the License at
7
-
8
-       http://www.apache.org/licenses/LICENSE-2.0
9
-
10
-   Unless required by applicable law or agreed to in writing, software
11
-   distributed under the License is distributed on an "AS IS" BASIS,
12
-   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
-   See the License for the specific language governing permissions and
14
-   limitations under the License.
15
-*/
16
-
17
-package containerd
18
-
19
-import (
20
-	"syscall"
21
-
22
-	"golang.org/x/sys/unix"
23
-)
24
-
25
-var signalMap = map[string]syscall.Signal{
26
-	"ABRT":   unix.SIGABRT,
27
-	"ALRM":   unix.SIGALRM,
28
-	"BUS":    unix.SIGBUS,
29
-	"CHLD":   unix.SIGCHLD,
30
-	"CLD":    unix.SIGCLD,
31
-	"CONT":   unix.SIGCONT,
32
-	"FPE":    unix.SIGFPE,
33
-	"HUP":    unix.SIGHUP,
34
-	"ILL":    unix.SIGILL,
35
-	"INT":    unix.SIGINT,
36
-	"IO":     unix.SIGIO,
37
-	"IOT":    unix.SIGIOT,
38
-	"KILL":   unix.SIGKILL,
39
-	"PIPE":   unix.SIGPIPE,
40
-	"POLL":   unix.SIGPOLL,
41
-	"PROF":   unix.SIGPROF,
42
-	"PWR":    unix.SIGPWR,
43
-	"QUIT":   unix.SIGQUIT,
44
-	"SEGV":   unix.SIGSEGV,
45
-	"STKFLT": unix.SIGSTKFLT,
46
-	"STOP":   unix.SIGSTOP,
47
-	"SYS":    unix.SIGSYS,
48
-	"TERM":   unix.SIGTERM,
49
-	"TRAP":   unix.SIGTRAP,
50
-	"TSTP":   unix.SIGTSTP,
51
-	"TTIN":   unix.SIGTTIN,
52
-	"TTOU":   unix.SIGTTOU,
53
-	"URG":    unix.SIGURG,
54
-	"USR1":   unix.SIGUSR1,
55
-	"USR2":   unix.SIGUSR2,
56
-	"VTALRM": unix.SIGVTALRM,
57
-	"WINCH":  unix.SIGWINCH,
58
-	"XCPU":   unix.SIGXCPU,
59
-	"XFSZ":   unix.SIGXFSZ,
60
-}
61 1
deleted file mode 100644
... ...
@@ -1,58 +0,0 @@
1
-// +build darwin freebsd solaris
2
-
3
-/*
4
-   Copyright The containerd Authors.
5
-
6
-   Licensed under the Apache License, Version 2.0 (the "License");
7
-   you may not use this file except in compliance with the License.
8
-   You may obtain a copy of the License at
9
-
10
-       http://www.apache.org/licenses/LICENSE-2.0
11
-
12
-   Unless required by applicable law or agreed to in writing, software
13
-   distributed under the License is distributed on an "AS IS" BASIS,
14
-   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
-   See the License for the specific language governing permissions and
16
-   limitations under the License.
17
-*/
18
-
19
-package containerd
20
-
21
-import (
22
-	"syscall"
23
-
24
-	"golang.org/x/sys/unix"
25
-)
26
-
27
-var signalMap = map[string]syscall.Signal{
28
-	"ABRT":   unix.SIGABRT,
29
-	"ALRM":   unix.SIGALRM,
30
-	"BUS":    unix.SIGBUS,
31
-	"CHLD":   unix.SIGCHLD,
32
-	"CONT":   unix.SIGCONT,
33
-	"FPE":    unix.SIGFPE,
34
-	"HUP":    unix.SIGHUP,
35
-	"ILL":    unix.SIGILL,
36
-	"INT":    unix.SIGINT,
37
-	"IO":     unix.SIGIO,
38
-	"IOT":    unix.SIGIOT,
39
-	"KILL":   unix.SIGKILL,
40
-	"PIPE":   unix.SIGPIPE,
41
-	"PROF":   unix.SIGPROF,
42
-	"QUIT":   unix.SIGQUIT,
43
-	"SEGV":   unix.SIGSEGV,
44
-	"STOP":   unix.SIGSTOP,
45
-	"SYS":    unix.SIGSYS,
46
-	"TERM":   unix.SIGTERM,
47
-	"TRAP":   unix.SIGTRAP,
48
-	"TSTP":   unix.SIGTSTP,
49
-	"TTIN":   unix.SIGTTIN,
50
-	"TTOU":   unix.SIGTTOU,
51
-	"URG":    unix.SIGURG,
52
-	"USR1":   unix.SIGUSR1,
53
-	"USR2":   unix.SIGUSR2,
54
-	"VTALRM": unix.SIGVTALRM,
55
-	"WINCH":  unix.SIGWINCH,
56
-	"XCPU":   unix.SIGXCPU,
57
-	"XFSZ":   unix.SIGXFSZ,
58
-}
59 1
deleted file mode 100644
... ...
@@ -1,39 +0,0 @@
1
-/*
2
-   Copyright The containerd Authors.
3
-
4
-   Licensed under the Apache License, Version 2.0 (the "License");
5
-   you may not use this file except in compliance with the License.
6
-   You may obtain a copy of the License at
7
-
8
-       http://www.apache.org/licenses/LICENSE-2.0
9
-
10
-   Unless required by applicable law or agreed to in writing, software
11
-   distributed under the License is distributed on an "AS IS" BASIS,
12
-   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
-   See the License for the specific language governing permissions and
14
-   limitations under the License.
15
-*/
16
-
17
-package containerd
18
-
19
-import (
20
-	"syscall"
21
-
22
-	"golang.org/x/sys/windows"
23
-)
24
-
25
-var signalMap = map[string]syscall.Signal{
26
-	"HUP":    syscall.Signal(windows.SIGHUP),
27
-	"INT":    syscall.Signal(windows.SIGINT),
28
-	"QUIT":   syscall.Signal(windows.SIGQUIT),
29
-	"SIGILL": syscall.Signal(windows.SIGILL),
30
-	"TRAP":   syscall.Signal(windows.SIGTRAP),
31
-	"ABRT":   syscall.Signal(windows.SIGABRT),
32
-	"BUS":    syscall.Signal(windows.SIGBUS),
33
-	"FPE":    syscall.Signal(windows.SIGFPE),
34
-	"KILL":   syscall.Signal(windows.SIGKILL),
35
-	"SEGV":   syscall.Signal(windows.SIGSEGV),
36
-	"PIPE":   syscall.Signal(windows.SIGPIPE),
37
-	"ALRM":   syscall.Signal(windows.SIGALRM),
38
-	"TERM":   syscall.Signal(windows.SIGTERM),
39
-}
... ...
@@ -20,13 +20,11 @@ import (
20 20
 	"context"
21 21
 	"encoding/json"
22 22
 	"fmt"
23
-	"strconv"
24
-	"strings"
25 23
 	"syscall"
26 24
 
27 25
 	"github.com/containerd/containerd/content"
28 26
 	"github.com/containerd/containerd/images"
29
-	"github.com/opencontainers/image-spec/specs-go/v1"
27
+	v1 "github.com/opencontainers/image-spec/specs-go/v1"
30 28
 )
31 29
 
32 30
 // StopSignalLabel is a well-known containerd label for storing the stop
... ...
@@ -83,23 +81,3 @@ func GetOCIStopSignal(ctx context.Context, image Image, defaultSignal string) (s
83 83
 
84 84
 	return config.StopSignal, nil
85 85
 }
86
-
87
-// ParseSignal parses a given string into a syscall.Signal
88
-// it checks that the signal exists in the platform-appropriate signalMap
89
-func ParseSignal(rawSignal string) (syscall.Signal, error) {
90
-	s, err := strconv.Atoi(rawSignal)
91
-	if err == nil {
92
-		sig := syscall.Signal(s)
93
-		for _, msig := range signalMap {
94
-			if sig == msig {
95
-				return sig, nil
96
-			}
97
-		}
98
-		return -1, fmt.Errorf("unknown signal %q", rawSignal)
99
-	}
100
-	signal, ok := signalMap[strings.TrimPrefix(strings.ToUpper(rawSignal), "SIG")]
101
-	if !ok {
102
-		return -1, fmt.Errorf("unknown signal %q", rawSignal)
103
-	}
104
-	return signal, nil
105
-}
106 86
new file mode 100644
... ...
@@ -0,0 +1,47 @@
0
+// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris
1
+
2
+/*
3
+   Copyright The containerd Authors.
4
+
5
+   Licensed under the Apache License, Version 2.0 (the "License");
6
+   you may not use this file except in compliance with the License.
7
+   You may obtain a copy of the License at
8
+
9
+       http://www.apache.org/licenses/LICENSE-2.0
10
+
11
+   Unless required by applicable law or agreed to in writing, software
12
+   distributed under the License is distributed on an "AS IS" BASIS,
13
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+   See the License for the specific language governing permissions and
15
+   limitations under the License.
16
+*/
17
+
18
+package containerd
19
+
20
+import (
21
+	"fmt"
22
+	"strconv"
23
+	"strings"
24
+	"syscall"
25
+
26
+	"golang.org/x/sys/unix"
27
+)
28
+
29
+// ParseSignal parses a given string into a syscall.Signal
30
+// the rawSignal can be a string with "SIG" prefix,
31
+// or a signal number in string format.
32
+func ParseSignal(rawSignal string) (syscall.Signal, error) {
33
+	s, err := strconv.Atoi(rawSignal)
34
+	if err == nil {
35
+		signal := syscall.Signal(s)
36
+		if unix.SignalName(signal) != "" {
37
+			return signal, nil
38
+		}
39
+		return -1, fmt.Errorf("unknown signal %q", rawSignal)
40
+	}
41
+	signal := unix.SignalNum(strings.ToUpper(rawSignal))
42
+	if signal == 0 {
43
+		return -1, fmt.Errorf("unknown signal %q", rawSignal)
44
+	}
45
+	return signal, nil
46
+}
0 47
new file mode 100644
... ...
@@ -0,0 +1,63 @@
0
+/*
1
+   Copyright The containerd Authors.
2
+
3
+   Licensed under the Apache License, Version 2.0 (the "License");
4
+   you may not use this file except in compliance with the License.
5
+   You may obtain a copy of the License at
6
+
7
+       http://www.apache.org/licenses/LICENSE-2.0
8
+
9
+   Unless required by applicable law or agreed to in writing, software
10
+   distributed under the License is distributed on an "AS IS" BASIS,
11
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+   See the License for the specific language governing permissions and
13
+   limitations under the License.
14
+*/
15
+
16
+package containerd
17
+
18
+import (
19
+	"fmt"
20
+	"strconv"
21
+	"strings"
22
+	"syscall"
23
+
24
+	"golang.org/x/sys/windows"
25
+)
26
+
27
+var signalMap = map[string]syscall.Signal{
28
+	"HUP":    syscall.Signal(windows.SIGHUP),
29
+	"INT":    syscall.Signal(windows.SIGINT),
30
+	"QUIT":   syscall.Signal(windows.SIGQUIT),
31
+	"SIGILL": syscall.Signal(windows.SIGILL),
32
+	"TRAP":   syscall.Signal(windows.SIGTRAP),
33
+	"ABRT":   syscall.Signal(windows.SIGABRT),
34
+	"BUS":    syscall.Signal(windows.SIGBUS),
35
+	"FPE":    syscall.Signal(windows.SIGFPE),
36
+	"KILL":   syscall.Signal(windows.SIGKILL),
37
+	"SEGV":   syscall.Signal(windows.SIGSEGV),
38
+	"PIPE":   syscall.Signal(windows.SIGPIPE),
39
+	"ALRM":   syscall.Signal(windows.SIGALRM),
40
+	"TERM":   syscall.Signal(windows.SIGTERM),
41
+}
42
+
43
+// ParseSignal parses a given string into a syscall.Signal
44
+// the rawSignal can be a string with "SIG" prefix,
45
+// or a signal number in string format.
46
+func ParseSignal(rawSignal string) (syscall.Signal, error) {
47
+	s, err := strconv.Atoi(rawSignal)
48
+	if err == nil {
49
+		sig := syscall.Signal(s)
50
+		for _, msig := range signalMap {
51
+			if sig == msig {
52
+				return sig, nil
53
+			}
54
+		}
55
+		return -1, fmt.Errorf("unknown signal %q", rawSignal)
56
+	}
57
+	signal, ok := signalMap[strings.TrimPrefix(strings.ToUpper(rawSignal), "SIG")]
58
+	if !ok {
59
+		return -1, fmt.Errorf("unknown signal %q", rawSignal)
60
+	}
61
+	return signal, nil
62
+}
... ...
@@ -160,9 +160,13 @@ func (u *Usage) Add(other Usage) {
160 160
 //	layerPath, tmpDir := getLayerPath(), mkTmpDir() // just a path to layer tar file.
161 161
 //
162 162
 // We start by using a Snapshotter to Prepare a new snapshot transaction, using a
163
-// key and descending from the empty parent "":
163
+// key and descending from the empty parent "". To prevent our layer from being
164
+// garbage collected during unpacking, we add the `containerd.io/gc.root` label:
164 165
 //
165
-//	mounts, err := snapshotter.Prepare(ctx, key, "")
166
+//	noGcOpt := snapshots.WithLabels(map[string]string{
167
+//		"containerd.io/gc.root": time.Now().UTC().Format(time.RFC3339),
168
+//	})
169
+//	mounts, err := snapshotter.Prepare(ctx, key, "", noGcOpt)
166 170
 // 	if err != nil { ... }
167 171
 //
168 172
 // We get back a list of mounts from Snapshotter.Prepare, with the key identifying
... ...
@@ -191,15 +195,13 @@ func (u *Usage) Add(other Usage) {
191 191
 //
192 192
 // Now that we've verified and unpacked our layer, we commit the active
193 193
 // snapshot to a name. For this example, we are just going to use the layer
194
-// digest, but in practice, this will probably be the ChainID:
194
+// digest, but in practice, this will probably be the ChainID. This also removes
195
+// the active snapshot:
195 196
 //
196
-//	if err := snapshotter.Commit(ctx, digest.String(), key); err != nil { ... }
197
+//	if err := snapshotter.Commit(ctx, digest.String(), key, noGcOpt); err != nil { ... }
197 198
 //
198 199
 // Now, we have a layer in the Snapshotter that can be accessed with the digest
199
-// provided during commit. Once you have committed the snapshot, the active
200
-// snapshot can be removed with the following:
201
-//
202
-// 	snapshotter.Remove(ctx, key)
200
+// provided during commit.
203 201
 //
204 202
 // Importing the Next Layer
205 203
 //
... ...
@@ -207,7 +209,7 @@ func (u *Usage) Add(other Usage) {
207 207
 // above except that the parent is provided as parent when calling
208 208
 // Manager.Prepare, assuming a clean, unique key identifier:
209 209
 //
210
-// 	mounts, err := snapshotter.Prepare(ctx, key, parentDigest)
210
+// 	mounts, err := snapshotter.Prepare(ctx, key, parentDigest, noGcOpt)
211 211
 //
212 212
 // We then mount, apply and commit, as we did above. The new snapshot will be
213 213
 // based on the content of the previous one.
... ...
@@ -37,11 +37,13 @@ import (
37 37
 	"github.com/containerd/containerd/mount"
38 38
 	"github.com/containerd/containerd/plugin"
39 39
 	"github.com/containerd/containerd/rootfs"
40
+	"github.com/containerd/containerd/runtime/linux/runctypes"
41
+	"github.com/containerd/containerd/runtime/v2/runc/options"
40 42
 	"github.com/containerd/typeurl"
41 43
 	google_protobuf "github.com/gogo/protobuf/types"
42 44
 	digest "github.com/opencontainers/go-digest"
43 45
 	is "github.com/opencontainers/image-spec/specs-go"
44
-	"github.com/opencontainers/image-spec/specs-go/v1"
46
+	v1 "github.com/opencontainers/image-spec/specs-go/v1"
45 47
 	specs "github.com/opencontainers/runtime-spec/specs-go"
46 48
 	"github.com/pkg/errors"
47 49
 )
... ...
@@ -115,6 +117,13 @@ type CheckpointTaskInfo struct {
115 115
 	ParentCheckpoint digest.Digest
116 116
 	// Options hold runtime specific settings for checkpointing a task
117 117
 	Options interface{}
118
+
119
+	runtime string
120
+}
121
+
122
+// Runtime name for the container
123
+func (i *CheckpointTaskInfo) Runtime() string {
124
+	return i.runtime
118 125
 }
119 126
 
120 127
 // CheckpointTaskOpts allows the caller to set checkpoint options
... ...
@@ -129,6 +138,12 @@ type TaskInfo struct {
129 129
 	RootFS []mount.Mount
130 130
 	// Options hold runtime specific settings for task creation
131 131
 	Options interface{}
132
+	runtime string
133
+}
134
+
135
+// Runtime name for the container
136
+func (i *TaskInfo) Runtime() string {
137
+	return i.runtime
132 138
 }
133 139
 
134 140
 // Task is the executable object within containerd
... ...
@@ -147,6 +162,8 @@ type Task interface {
147 147
 	// OCI Index that can be push and pulled from a remote resource.
148 148
 	//
149 149
 	// Additional software like CRIU maybe required to checkpoint and restore tasks
150
+	// NOTE: Checkpoint supports to dump task information to a directory, in this way,
151
+	// an empty OCI Index will be returned.
150 152
 	Checkpoint(context.Context, ...CheckpointTaskOpts) (Image, error)
151 153
 	// Update modifies executing tasks with updated settings
152 154
 	Update(context.Context, ...UpdateTaskOpts) error
... ...
@@ -389,17 +406,25 @@ func (t *task) Resize(ctx context.Context, w, h uint32) error {
389 389
 	return errdefs.FromGRPC(err)
390 390
 }
391 391
 
392
+// NOTE: Checkpoint supports to dump task information to a directory, in this way, an empty
393
+// OCI Index will be returned.
392 394
 func (t *task) Checkpoint(ctx context.Context, opts ...CheckpointTaskOpts) (Image, error) {
393 395
 	ctx, done, err := t.client.WithLease(ctx)
394 396
 	if err != nil {
395 397
 		return nil, err
396 398
 	}
397 399
 	defer done(ctx)
400
+	cr, err := t.client.ContainerService().Get(ctx, t.id)
401
+	if err != nil {
402
+		return nil, err
403
+	}
398 404
 
399 405
 	request := &tasks.CheckpointTaskRequest{
400 406
 		ContainerID: t.id,
401 407
 	}
402
-	var i CheckpointTaskInfo
408
+	i := CheckpointTaskInfo{
409
+		runtime: cr.Runtime.Name,
410
+	}
403 411
 	for _, o := range opts {
404 412
 		if err := o(&i); err != nil {
405 413
 			return nil, err
... ...
@@ -422,10 +447,6 @@ func (t *task) Checkpoint(ctx context.Context, opts ...CheckpointTaskOpts) (Imag
422 422
 		return nil, err
423 423
 	}
424 424
 	defer t.Resume(ctx)
425
-	cr, err := t.client.ContainerService().Get(ctx, t.id)
426
-	if err != nil {
427
-		return nil, err
428
-	}
429 425
 	index := v1.Index{
430 426
 		Versioned: is.Versioned{
431 427
 			SchemaVersion: 2,
... ...
@@ -435,6 +456,12 @@ func (t *task) Checkpoint(ctx context.Context, opts ...CheckpointTaskOpts) (Imag
435 435
 	if err := t.checkpointTask(ctx, &index, request); err != nil {
436 436
 		return nil, err
437 437
 	}
438
+	// if checkpoint image path passed, jump checkpoint image,
439
+	// return an empty image
440
+	if isCheckpointPathExist(cr.Runtime.Name, i.Options) {
441
+		return NewImage(t.client, images.Image{}), nil
442
+	}
443
+
438 444
 	if cr.Image != "" {
439 445
 		if err := t.checkpointImage(ctx, &index, cr.Image); err != nil {
440 446
 			return nil, err
... ...
@@ -544,6 +571,7 @@ func (t *task) checkpointTask(ctx context.Context, index *v1.Index, request *tas
544 544
 	if err != nil {
545 545
 		return errdefs.FromGRPC(err)
546 546
 	}
547
+	// NOTE: response.Descriptors can be an empty slice if checkpoint image is jumped
547 548
 	// add the checkpoint descriptors to the index
548 549
 	for _, d := range response.Descriptors {
549 550
 		index.Manifests = append(index.Manifests, v1.Descriptor{
... ...
@@ -621,3 +649,24 @@ func writeContent(ctx context.Context, store content.Ingester, mediaType, ref st
621 621
 		Size:      size,
622 622
 	}, nil
623 623
 }
624
+
625
+// isCheckpointPathExist only suitable for runc runtime now
626
+func isCheckpointPathExist(runtime string, v interface{}) bool {
627
+	if v == nil {
628
+		return false
629
+	}
630
+
631
+	switch runtime {
632
+	case plugin.RuntimeRuncV1, plugin.RuntimeRuncV2:
633
+		if opts, ok := v.(*options.CheckpointOptions); ok && opts.ImagePath != "" {
634
+			return true
635
+		}
636
+
637
+	case plugin.RuntimeLinuxV1:
638
+		if opts, ok := v.(*runctypes.CheckpointOptions); ok && opts.ImagePath != "" {
639
+			return true
640
+		}
641
+	}
642
+
643
+	return false
644
+}
... ...
@@ -27,6 +27,8 @@ import (
27 27
 	"github.com/containerd/containerd/errdefs"
28 28
 	"github.com/containerd/containerd/images"
29 29
 	"github.com/containerd/containerd/mount"
30
+	"github.com/containerd/containerd/runtime/linux/runctypes"
31
+	"github.com/containerd/containerd/runtime/v2/runc/options"
30 32
 	imagespec "github.com/opencontainers/image-spec/specs-go/v1"
31 33
 	"github.com/opencontainers/runtime-spec/specs-go"
32 34
 	"github.com/pkg/errors"
... ...
@@ -89,6 +91,58 @@ func WithCheckpointName(name string) CheckpointTaskOpts {
89 89
 	}
90 90
 }
91 91
 
92
+// WithCheckpointImagePath sets image path for checkpoint option
93
+func WithCheckpointImagePath(path string) CheckpointTaskOpts {
94
+	return func(r *CheckpointTaskInfo) error {
95
+		if CheckRuntime(r.Runtime(), "io.containerd.runc") {
96
+			if r.Options == nil {
97
+				r.Options = &options.CheckpointOptions{}
98
+			}
99
+			opts, ok := r.Options.(*options.CheckpointOptions)
100
+			if !ok {
101
+				return errors.New("invalid v2 shim checkpoint options format")
102
+			}
103
+			opts.ImagePath = path
104
+		} else {
105
+			if r.Options == nil {
106
+				r.Options = &runctypes.CheckpointOptions{}
107
+			}
108
+			opts, ok := r.Options.(*runctypes.CheckpointOptions)
109
+			if !ok {
110
+				return errors.New("invalid v1 shim checkpoint options format")
111
+			}
112
+			opts.ImagePath = path
113
+		}
114
+		return nil
115
+	}
116
+}
117
+
118
+// WithRestoreImagePath sets image path for create option
119
+func WithRestoreImagePath(path string) NewTaskOpts {
120
+	return func(ctx context.Context, c *Client, ti *TaskInfo) error {
121
+		if CheckRuntime(ti.Runtime(), "io.containerd.runc") {
122
+			if ti.Options == nil {
123
+				ti.Options = &options.Options{}
124
+			}
125
+			opts, ok := ti.Options.(*options.Options)
126
+			if !ok {
127
+				return errors.New("invalid v2 shim create options format")
128
+			}
129
+			opts.CriuImagePath = path
130
+		} else {
131
+			if ti.Options == nil {
132
+				ti.Options = &runctypes.CreateOptions{}
133
+			}
134
+			opts, ok := ti.Options.(*runctypes.CreateOptions)
135
+			if !ok {
136
+				return errors.New("invalid v1 shim create options format")
137
+			}
138
+			opts.CriuImagePath = path
139
+		}
140
+		return nil
141
+	}
142
+}
143
+
92 144
 // ProcessDeleteOpts allows the caller to set options for the deletion of a task
93 145
 type ProcessDeleteOpts func(context.Context, Process) error
94 146
 
... ...
@@ -22,36 +22,58 @@ import (
22 22
 	"context"
23 23
 
24 24
 	"github.com/containerd/containerd/runtime/linux/runctypes"
25
+	"github.com/containerd/containerd/runtime/v2/runc/options"
25 26
 	"github.com/pkg/errors"
26 27
 )
27 28
 
28 29
 // WithNoNewKeyring causes tasks not to be created with a new keyring for secret storage.
29 30
 // There is an upper limit on the number of keyrings in a linux system
30 31
 func WithNoNewKeyring(ctx context.Context, c *Client, ti *TaskInfo) error {
31
-	if ti.Options == nil {
32
-		ti.Options = &runctypes.CreateOptions{}
33
-	}
34
-	opts, ok := ti.Options.(*runctypes.CreateOptions)
35
-	if !ok {
36
-		return errors.New("could not cast TaskInfo Options to CreateOptions")
32
+	if CheckRuntime(ti.Runtime(), "io.containerd.runc") {
33
+		if ti.Options == nil {
34
+			ti.Options = &options.Options{}
35
+		}
36
+		opts, ok := ti.Options.(*options.Options)
37
+		if !ok {
38
+			return errors.New("invalid v2 shim create options format")
39
+		}
40
+		opts.NoNewKeyring = true
41
+	} else {
42
+		if ti.Options == nil {
43
+			ti.Options = &runctypes.CreateOptions{}
44
+		}
45
+		opts, ok := ti.Options.(*runctypes.CreateOptions)
46
+		if !ok {
47
+			return errors.New("could not cast TaskInfo Options to CreateOptions")
48
+		}
49
+		opts.NoNewKeyring = true
37 50
 	}
38
-
39
-	opts.NoNewKeyring = true
40 51
 	return nil
41 52
 }
42 53
 
43 54
 // WithNoPivotRoot instructs the runtime not to you pivot_root
44
-func WithNoPivotRoot(_ context.Context, _ *Client, info *TaskInfo) error {
45
-	if info.Options == nil {
46
-		info.Options = &runctypes.CreateOptions{
47
-			NoPivotRoot: true,
55
+func WithNoPivotRoot(_ context.Context, _ *Client, ti *TaskInfo) error {
56
+	if CheckRuntime(ti.Runtime(), "io.containerd.runc") {
57
+		if ti.Options == nil {
58
+			ti.Options = &options.Options{}
48 59
 		}
49
-		return nil
50
-	}
51
-	opts, ok := info.Options.(*runctypes.CreateOptions)
52
-	if !ok {
53
-		return errors.New("invalid options type, expected runctypes.CreateOptions")
60
+		opts, ok := ti.Options.(*options.Options)
61
+		if !ok {
62
+			return errors.New("invalid v2 shim create options format")
63
+		}
64
+		opts.NoPivotRoot = true
65
+	} else {
66
+		if ti.Options == nil {
67
+			ti.Options = &runctypes.CreateOptions{
68
+				NoPivotRoot: true,
69
+			}
70
+			return nil
71
+		}
72
+		opts, ok := ti.Options.(*runctypes.CreateOptions)
73
+		if !ok {
74
+			return errors.New("invalid options type, expected runctypes.CreateOptions")
75
+		}
76
+		opts.NoPivotRoot = true
54 77
 	}
55
-	opts.NoPivotRoot = true
56 78
 	return nil
57 79
 }
... ...
@@ -19,31 +19,32 @@ github.com/matttproud/golang_protobuf_extensions v1.0.0
19 19
 github.com/gogo/protobuf v1.0.0
20 20
 github.com/gogo/googleapis 08a7655d27152912db7aaf4f983275eaf8d128ef
21 21
 github.com/golang/protobuf v1.1.0
22
-github.com/opencontainers/runtime-spec eba862dc2470385a233c7507392675cbeadf7353 # v1.0.1-45-geba862d
22
+github.com/opencontainers/runtime-spec 29686dbc5559d93fb1ef402eeda3e35c38d75af4 # v1.0.1-59-g29686db
23 23
 github.com/opencontainers/runc 2b18fe1d885ee5083ef9f0838fee39b62d653e30
24
-github.com/sirupsen/logrus v1.0.0
24
+github.com/konsorten/go-windows-terminal-sequences v1.0.1
25
+github.com/sirupsen/logrus v1.3.0
25 26
 github.com/urfave/cli 7bc6a0acffa589f415f88aca16cc1de5ffd66f9c
26 27
 golang.org/x/net b3756b4b77d7b13260a0a2ec658753cf48922eac
27 28
 google.golang.org/grpc v1.12.0
28 29
 github.com/pkg/errors v0.8.0
29 30
 github.com/opencontainers/go-digest c9281466c8b2f606084ac71339773efd177436e7
30
-golang.org/x/sys 41f3e6584952bb034a481797859f6ab34b6803bd https://github.com/golang/sys
31
+golang.org/x/sys d455e41777fca6e8a5a79e34a14b8368bc11d9ba https://github.com/golang/sys
31 32
 github.com/opencontainers/image-spec v1.0.1
32
-golang.org/x/sync 450f422ab23cf9881c94e2db30cac0eb1b7cf80c
33
+golang.org/x/sync 42b317875d0fa942474b76e1b46a6060d720ae6e
33 34
 github.com/BurntSushi/toml a368813c5e648fee92e5f6c30e3944ff9d5e8895
34 35
 github.com/grpc-ecosystem/go-grpc-prometheus 6b7015e65d366bf3f19b2b2a000a831940f0f7e0
35
-github.com/Microsoft/go-winio v0.4.11
36
-github.com/Microsoft/hcsshim v0.8.1
36
+github.com/Microsoft/go-winio v0.4.12
37
+github.com/Microsoft/hcsshim v0.8.5
37 38
 google.golang.org/genproto d80a6e20e776b0b17a324d0ba1ab50a39c8e8944
38 39
 golang.org/x/text 19e51611da83d6be54ddafce4a4af510cb3e9ea4
39
-github.com/containerd/ttrpc 2a805f71863501300ae1976d29f0454ae003e85a
40
+github.com/containerd/ttrpc f02858b1457c5ca3aaec3a0803eb0d59f96e41d6
40 41
 github.com/syndtr/gocapability db04d3cc01c8b54962a58ec7e491717d06cfcc16
41 42
 gotest.tools v2.1.0
42 43
 github.com/google/go-cmp v0.1.0
43
-go.etcd.io/bbolt v1.3.1-etcd.8
44
+go.etcd.io/bbolt v1.3.2
44 45
 
45 46
 # cri dependencies
46
-github.com/containerd/cri a92c40017473cbe0239ce180125f12669757e44f # release/1.2 branch
47
+github.com/containerd/cri 4dd6735020f5596dd41738f8c4f5cb07fa804c5e # master
47 48
 github.com/containerd/go-cni 40bcf8ec8acd7372be1d77031d585d5d8e561c90
48 49
 github.com/blang/semver v3.1.0
49 50
 github.com/containernetworking/cni v0.6.0
... ...
@@ -53,8 +54,6 @@ github.com/docker/distribution 0d3efadf0154c2b8a4e7b6621fff9809655cc580
53 53
 github.com/docker/docker 86f080cff0914e9694068ed78d503701667c4c00
54 54
 github.com/docker/spdystream 449fdfce4d962303d702fec724ef0ad181c92528
55 55
 github.com/emicklei/go-restful v2.2.1
56
-github.com/ghodss/yaml v1.0.0
57
-github.com/golang/glog 44145f04b68cf362d9c4df2182967c2275eaefed
58 56
 github.com/google/gofuzz 44d81051d367757e1c7c6a5a86423ece9afcf63c
59 57
 github.com/hashicorp/errwrap 7554cd9344cec97297fa6649b055a8c98c2a1e55
60 58
 github.com/hashicorp/go-multierror ed905158d87462226a13fe39ddf685ea65f1c11f
... ...
@@ -73,17 +72,19 @@ golang.org/x/oauth2 a6bd8cefa1811bd24b86f8902872e4e8225f74c4
73 73
 golang.org/x/time f51c12702a4d776e4c1fa9b0fabab841babae631
74 74
 gopkg.in/inf.v0 3887ee99ecf07df5b447e9b00d9c0b2adaa9f3e4
75 75
 gopkg.in/yaml.v2 v2.2.1
76
-k8s.io/api kubernetes-1.12.0
77
-k8s.io/apimachinery kubernetes-1.12.0
78
-k8s.io/apiserver kubernetes-1.12.0
79
-k8s.io/client-go kubernetes-1.12.0
80
-k8s.io/kubernetes v1.12.0
81
-k8s.io/utils cd34563cd63c2bd7c6fe88a73c4dcf34ed8a67cb
76
+k8s.io/api kubernetes-1.13.0
77
+k8s.io/apimachinery kubernetes-1.13.0
78
+k8s.io/apiserver kubernetes-1.13.0
79
+k8s.io/client-go kubernetes-1.13.0
80
+k8s.io/klog 8139d8cb77af419532b33dfa7dd09fbc5f1d344f
81
+k8s.io/kubernetes v1.13.0
82
+k8s.io/utils 0d26856f57b32ec3398579285e5c8a2bfe8c5243
83
+sigs.k8s.io/yaml v1.1.0
82 84
 
83 85
 # zfs dependencies
84
-github.com/containerd/zfs 9a0b8b8b5982014b729cd34eb7cd7a11062aa6ec
86
+github.com/containerd/zfs 9f6ef3b1fe5144bd91fe5855b4eba81bc0d17d03
85 87
 github.com/mistifyio/go-zfs 166add352731e515512690329794ee593f1aaff2
86 88
 github.com/pborman/uuid c65b2f87fee37d1c7854c9164a450713c28d50cd
87 89
 
88 90
 # aufs dependencies
89
-github.com/containerd/aufs ffa39970e26ad01d81f540b21e65f9c1841a5f92
91
+github.com/containerd/aufs da3cf16bfbe68ba8f114f1536a05c01528a25434
90 92
new file mode 100644
... ...
@@ -0,0 +1,29 @@
0
+/*
1
+   Copyright The containerd Authors.
2
+
3
+   Licensed under the Apache License, Version 2.0 (the "License");
4
+   you may not use this file except in compliance with the License.
5
+   You may obtain a copy of the License at
6
+
7
+       http://www.apache.org/licenses/LICENSE-2.0
8
+
9
+   Unless required by applicable law or agreed to in writing, software
10
+   distributed under the License is distributed on an "AS IS" BASIS,
11
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+   See the License for the specific language governing permissions and
13
+   limitations under the License.
14
+*/
15
+
16
+package version
17
+
18
+var (
19
+	// Package is filled at linking time
20
+	Package = "github.com/containerd/containerd"
21
+
22
+	// Version holds the complete version number. Filled in at linking time.
23
+	Version = "1.2.0+unknown"
24
+
25
+	// Revision is filled with the VCS (e.g. git) revision being used to build
26
+	// the program at linking time.
27
+	Revision = ""
28
+)
... ...
@@ -50,3 +50,13 @@ TODO:
50 50
 - [ ] Document protocol layout
51 51
 - [ ] Add testing under concurrent load to ensure
52 52
 - [ ] Verify connection error handling
53
+
54
+# Project details
55
+
56
+ttrpc is a containerd sub-project, licensed under the [Apache 2.0 license](./LICENSE).
57
+As a containerd sub-project, you will find the:
58
+ * [Project governance](https://github.com/containerd/project/blob/master/GOVERNANCE.md),
59
+ * [Maintainers](https://github.com/containerd/project/blob/master/MAINTAINERS),
60
+ * and [Contributing guidelines](https://github.com/containerd/project/blob/master/CONTRIBUTING.md)
61
+
62
+information in our [`containerd/project`](https://github.com/containerd/project) repository.
... ...
@@ -24,6 +24,7 @@ import (
24 24
 	"strings"
25 25
 	"sync"
26 26
 	"syscall"
27
+	"time"
27 28
 
28 29
 	"github.com/gogo/protobuf/proto"
29 30
 	"github.com/pkg/errors"
... ...
@@ -86,6 +87,10 @@ func (c *Client) Call(ctx context.Context, service, method string, req, resp int
86 86
 		cresp = &Response{}
87 87
 	)
88 88
 
89
+	if dl, ok := ctx.Deadline(); ok {
90
+		creq.TimeoutNano = dl.Sub(time.Now()).Nanoseconds()
91
+	}
92
+
89 93
 	if err := c.dispatch(ctx, creq, cresp); err != nil {
90 94
 		return err
91 95
 	}
... ...
@@ -104,6 +109,7 @@ func (c *Client) Call(ctx context.Context, service, method string, req, resp int
104 104
 func (c *Client) dispatch(ctx context.Context, req *Request, resp *Response) error {
105 105
 	errs := make(chan error, 1)
106 106
 	call := &callRequest{
107
+		ctx:  ctx,
107 108
 		req:  req,
108 109
 		resp: resp,
109 110
 		errs: errs,
... ...
@@ -414,6 +414,9 @@ func (c *serverConn) run(sctx context.Context) {
414 414
 		case request := <-requests:
415 415
 			active++
416 416
 			go func(id uint32) {
417
+				ctx, cancel := getRequestContext(ctx, request.req)
418
+				defer cancel()
419
+
417 420
 				p, status := c.server.services.call(ctx, request.req.Service, request.req.Method, request.req.Payload)
418 421
 				resp := &Response{
419 422
 					Status:  status.Proto(),
... ...
@@ -454,3 +457,15 @@ func (c *serverConn) run(sctx context.Context) {
454 454
 		}
455 455
 	}
456 456
 }
457
+
458
+var noopFunc = func() {}
459
+
460
+func getRequestContext(ctx context.Context, req *Request) (retCtx context.Context, cancel func()) {
461
+	cancel = noopFunc
462
+	if req.TimeoutNano == 0 {
463
+		return ctx, cancel
464
+	}
465
+
466
+	ctx, cancel = context.WithTimeout(ctx, time.Duration(req.TimeoutNano))
467
+	return ctx, cancel
468
+}
... ...
@@ -23,9 +23,10 @@ import (
23 23
 )
24 24
 
25 25
 type Request struct {
26
-	Service string `protobuf:"bytes,1,opt,name=service,proto3"`
27
-	Method  string `protobuf:"bytes,2,opt,name=method,proto3"`
28
-	Payload []byte `protobuf:"bytes,3,opt,name=payload,proto3"`
26
+	Service     string `protobuf:"bytes,1,opt,name=service,proto3"`
27
+	Method      string `protobuf:"bytes,2,opt,name=method,proto3"`
28
+	Payload     []byte `protobuf:"bytes,3,opt,name=payload,proto3"`
29
+	TimeoutNano int64  `protobuf:"varint,4,opt,name=timeout_nano,proto3"`
29 30
 }
30 31
 
31 32
 func (r *Request) Reset()         { *r = Request{} }
32 33
new file mode 100644
... ...
@@ -0,0 +1,30 @@
0
+// Copyright 2019 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 cpu
5
+
6
+import (
7
+	"encoding/binary"
8
+	"runtime"
9
+)
10
+
11
+// hostByteOrder returns binary.LittleEndian on little-endian machines and
12
+// binary.BigEndian on big-endian machines.
13
+func hostByteOrder() binary.ByteOrder {
14
+	switch runtime.GOARCH {
15
+	case "386", "amd64", "amd64p32",
16
+		"arm", "arm64",
17
+		"mipsle", "mips64le", "mips64p32le",
18
+		"ppc64le",
19
+		"riscv", "riscv64":
20
+		return binary.LittleEndian
21
+	case "armbe", "arm64be",
22
+		"mips", "mips64", "mips64p32",
23
+		"ppc", "ppc64",
24
+		"s390", "s390x",
25
+		"sparc", "sparc64":
26
+		return binary.BigEndian
27
+	}
28
+	panic("unknown architecture")
29
+}
... ...
@@ -6,6 +6,13 @@
6 6
 // various CPU architectures.
7 7
 package cpu
8 8
 
9
+// Initialized reports whether the CPU features were initialized.
10
+//
11
+// For some GOOS/GOARCH combinations initialization of the CPU features depends
12
+// on reading an operating specific file, e.g. /proc/self/auxv on linux/arm
13
+// Initialized will report false if reading the file fails.
14
+var Initialized bool
15
+
9 16
 // CacheLinePad is used to pad structs to avoid false sharing.
10 17
 type CacheLinePad struct{ _ [cacheLineSize]byte }
11 18
 
... ...
@@ -87,3 +94,33 @@ var PPC64 struct {
87 87
 	IsPOWER9 bool // ISA v3.00 (POWER9)
88 88
 	_        CacheLinePad
89 89
 }
90
+
91
+// S390X contains the supported CPU features of the current IBM Z
92
+// (s390x) platform. If the current platform is not IBM Z then all
93
+// feature flags are false.
94
+//
95
+// S390X is padded to avoid false sharing. Further HasVX is only set
96
+// if the OS supports vector registers in addition to the STFLE
97
+// feature bit being set.
98
+var S390X struct {
99
+	_         CacheLinePad
100
+	HasZARCH  bool // z/Architecture mode is active [mandatory]
101
+	HasSTFLE  bool // store facility list extended
102
+	HasLDISP  bool // long (20-bit) displacements
103
+	HasEIMM   bool // 32-bit immediates
104
+	HasDFP    bool // decimal floating point
105
+	HasETF3EH bool // ETF-3 enhanced
106
+	HasMSA    bool // message security assist (CPACF)
107
+	HasAES    bool // KM-AES{128,192,256} functions
108
+	HasAESCBC bool // KMC-AES{128,192,256} functions
109
+	HasAESCTR bool // KMCTR-AES{128,192,256} functions
110
+	HasAESGCM bool // KMA-GCM-AES{128,192,256} functions
111
+	HasGHASH  bool // KIMD-GHASH function
112
+	HasSHA1   bool // K{I,L}MD-SHA-1 functions
113
+	HasSHA256 bool // K{I,L}MD-SHA-256 functions
114
+	HasSHA512 bool // K{I,L}MD-SHA-512 functions
115
+	HasSHA3   bool // K{I,L}MD-SHA3-{224,256,384,512} and K{I,L}MD-SHAKE-{128,256} functions
116
+	HasVX     bool // vector facility
117
+	HasVXE    bool // vector-enhancements facility 1
118
+	_         CacheLinePad
119
+}
90 120
deleted file mode 100644
... ...
@@ -1,67 +0,0 @@
1
-// Copyright 2018 The Go Authors. All rights reserved.
2
-// Use of this source code is governed by a BSD-style
3
-// license that can be found in the LICENSE file.
4
-
5
-package cpu
6
-
7
-const cacheLineSize = 64
8
-
9
-// HWCAP/HWCAP2 bits. These are exposed by Linux.
10
-const (
11
-	hwcap_FP       = 1 << 0
12
-	hwcap_ASIMD    = 1 << 1
13
-	hwcap_EVTSTRM  = 1 << 2
14
-	hwcap_AES      = 1 << 3
15
-	hwcap_PMULL    = 1 << 4
16
-	hwcap_SHA1     = 1 << 5
17
-	hwcap_SHA2     = 1 << 6
18
-	hwcap_CRC32    = 1 << 7
19
-	hwcap_ATOMICS  = 1 << 8
20
-	hwcap_FPHP     = 1 << 9
21
-	hwcap_ASIMDHP  = 1 << 10
22
-	hwcap_CPUID    = 1 << 11
23
-	hwcap_ASIMDRDM = 1 << 12
24
-	hwcap_JSCVT    = 1 << 13
25
-	hwcap_FCMA     = 1 << 14
26
-	hwcap_LRCPC    = 1 << 15
27
-	hwcap_DCPOP    = 1 << 16
28
-	hwcap_SHA3     = 1 << 17
29
-	hwcap_SM3      = 1 << 18
30
-	hwcap_SM4      = 1 << 19
31
-	hwcap_ASIMDDP  = 1 << 20
32
-	hwcap_SHA512   = 1 << 21
33
-	hwcap_SVE      = 1 << 22
34
-	hwcap_ASIMDFHM = 1 << 23
35
-)
36
-
37
-func doinit() {
38
-	// HWCAP feature bits
39
-	ARM64.HasFP = isSet(HWCap, hwcap_FP)
40
-	ARM64.HasASIMD = isSet(HWCap, hwcap_ASIMD)
41
-	ARM64.HasEVTSTRM = isSet(HWCap, hwcap_EVTSTRM)
42
-	ARM64.HasAES = isSet(HWCap, hwcap_AES)
43
-	ARM64.HasPMULL = isSet(HWCap, hwcap_PMULL)
44
-	ARM64.HasSHA1 = isSet(HWCap, hwcap_SHA1)
45
-	ARM64.HasSHA2 = isSet(HWCap, hwcap_SHA2)
46
-	ARM64.HasCRC32 = isSet(HWCap, hwcap_CRC32)
47
-	ARM64.HasATOMICS = isSet(HWCap, hwcap_ATOMICS)
48
-	ARM64.HasFPHP = isSet(HWCap, hwcap_FPHP)
49
-	ARM64.HasASIMDHP = isSet(HWCap, hwcap_ASIMDHP)
50
-	ARM64.HasCPUID = isSet(HWCap, hwcap_CPUID)
51
-	ARM64.HasASIMDRDM = isSet(HWCap, hwcap_ASIMDRDM)
52
-	ARM64.HasJSCVT = isSet(HWCap, hwcap_JSCVT)
53
-	ARM64.HasFCMA = isSet(HWCap, hwcap_FCMA)
54
-	ARM64.HasLRCPC = isSet(HWCap, hwcap_LRCPC)
55
-	ARM64.HasDCPOP = isSet(HWCap, hwcap_DCPOP)
56
-	ARM64.HasSHA3 = isSet(HWCap, hwcap_SHA3)
57
-	ARM64.HasSM3 = isSet(HWCap, hwcap_SM3)
58
-	ARM64.HasSM4 = isSet(HWCap, hwcap_SM4)
59
-	ARM64.HasASIMDDP = isSet(HWCap, hwcap_ASIMDDP)
60
-	ARM64.HasSHA512 = isSet(HWCap, hwcap_SHA512)
61
-	ARM64.HasSVE = isSet(HWCap, hwcap_SVE)
62
-	ARM64.HasASIMDFHM = isSet(HWCap, hwcap_ASIMDFHM)
63
-}
64
-
65
-func isSet(hwc uint, value uint) bool {
66
-	return hwc&value != 0
67
-}
68 1
new file mode 100644
... ...
@@ -0,0 +1,21 @@
0
+// Copyright 2019 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
+package cpu
7
+
8
+// haveAsmFunctions reports whether the other functions in this file can
9
+// be safely called.
10
+func haveAsmFunctions() bool { return true }
11
+
12
+// The following feature detection functions are defined in cpu_s390x.s.
13
+// They are likely to be expensive to call so the results should be cached.
14
+func stfle() facilityList
15
+func kmQuery() queryResult
16
+func kmcQuery() queryResult
17
+func kmctrQuery() queryResult
18
+func kmaQuery() queryResult
19
+func kimdQuery() queryResult
20
+func klmdQuery() queryResult
0 21
new file mode 100644
... ...
@@ -0,0 +1,22 @@
0
+// Copyright 2019 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
+package cpu
7
+
8
+// haveAsmFunctions reports whether the other functions in this file can
9
+// be safely called.
10
+func haveAsmFunctions() bool { return false }
11
+
12
+// TODO(mundaym): the following feature detection functions are currently
13
+// stubs. See https://golang.org/cl/162887 for how to fix this.
14
+// They are likely to be expensive to call so the results should be cached.
15
+func stfle() facilityList     { panic("not implemented for gccgo") }
16
+func kmQuery() queryResult    { panic("not implemented for gccgo") }
17
+func kmcQuery() queryResult   { panic("not implemented for gccgo") }
18
+func kmctrQuery() queryResult { panic("not implemented for gccgo") }
19
+func kmaQuery() queryResult   { panic("not implemented for gccgo") }
20
+func kimdQuery() queryResult  { panic("not implemented for gccgo") }
21
+func klmdQuery() queryResult  { panic("not implemented for gccgo") }
... ...
@@ -7,9 +7,7 @@
7 7
 package cpu
8 8
 
9 9
 import (
10
-	"encoding/binary"
11 10
 	"io/ioutil"
12
-	"runtime"
13 11
 )
14 12
 
15 13
 const (
... ...
@@ -18,44 +16,44 @@ const (
18 18
 
19 19
 	procAuxv = "/proc/self/auxv"
20 20
 
21
-	uintSize uint = 32 << (^uint(0) >> 63)
21
+	uintSize = int(32 << (^uint(0) >> 63))
22 22
 )
23 23
 
24 24
 // For those platforms don't have a 'cpuid' equivalent we use HWCAP/HWCAP2
25 25
 // These are initialized in cpu_$GOARCH.go
26 26
 // and should not be changed after they are initialized.
27
-var HWCap uint
28
-var HWCap2 uint
27
+var hwCap uint
28
+var hwCap2 uint
29 29
 
30 30
 func init() {
31 31
 	buf, err := ioutil.ReadFile(procAuxv)
32 32
 	if err != nil {
33
-		panic("read proc auxv failed: " + err.Error())
33
+		// e.g. on android /proc/self/auxv is not accessible, so silently
34
+		// ignore the error and leave Initialized = false
35
+		return
34 36
 	}
35 37
 
36
-	pb := int(uintSize / 8)
37
-
38
-	for i := 0; i < len(buf)-pb*2; i += pb * 2 {
38
+	bo := hostByteOrder()
39
+	for len(buf) >= 2*(uintSize/8) {
39 40
 		var tag, val uint
40 41
 		switch uintSize {
41 42
 		case 32:
42
-			tag = uint(binary.LittleEndian.Uint32(buf[i:]))
43
-			val = uint(binary.LittleEndian.Uint32(buf[i+pb:]))
43
+			tag = uint(bo.Uint32(buf[0:]))
44
+			val = uint(bo.Uint32(buf[4:]))
45
+			buf = buf[8:]
44 46
 		case 64:
45
-			if runtime.GOARCH == "ppc64" {
46
-				tag = uint(binary.BigEndian.Uint64(buf[i:]))
47
-				val = uint(binary.BigEndian.Uint64(buf[i+pb:]))
48
-			} else {
49
-				tag = uint(binary.LittleEndian.Uint64(buf[i:]))
50
-				val = uint(binary.LittleEndian.Uint64(buf[i+pb:]))
51
-			}
47
+			tag = uint(bo.Uint64(buf[0:]))
48
+			val = uint(bo.Uint64(buf[8:]))
49
+			buf = buf[16:]
52 50
 		}
53 51
 		switch tag {
54 52
 		case _AT_HWCAP:
55
-			HWCap = val
53
+			hwCap = val
56 54
 		case _AT_HWCAP2:
57
-			HWCap2 = val
55
+			hwCap2 = val
58 56
 		}
59 57
 	}
60 58
 	doinit()
59
+
60
+	Initialized = true
61 61
 }
62 62
new file mode 100644
... ...
@@ -0,0 +1,67 @@
0
+// Copyright 2018 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 cpu
5
+
6
+const cacheLineSize = 64
7
+
8
+// HWCAP/HWCAP2 bits. These are exposed by Linux.
9
+const (
10
+	hwcap_FP       = 1 << 0
11
+	hwcap_ASIMD    = 1 << 1
12
+	hwcap_EVTSTRM  = 1 << 2
13
+	hwcap_AES      = 1 << 3
14
+	hwcap_PMULL    = 1 << 4
15
+	hwcap_SHA1     = 1 << 5
16
+	hwcap_SHA2     = 1 << 6
17
+	hwcap_CRC32    = 1 << 7
18
+	hwcap_ATOMICS  = 1 << 8
19
+	hwcap_FPHP     = 1 << 9
20
+	hwcap_ASIMDHP  = 1 << 10
21
+	hwcap_CPUID    = 1 << 11
22
+	hwcap_ASIMDRDM = 1 << 12
23
+	hwcap_JSCVT    = 1 << 13
24
+	hwcap_FCMA     = 1 << 14
25
+	hwcap_LRCPC    = 1 << 15
26
+	hwcap_DCPOP    = 1 << 16
27
+	hwcap_SHA3     = 1 << 17
28
+	hwcap_SM3      = 1 << 18
29
+	hwcap_SM4      = 1 << 19
30
+	hwcap_ASIMDDP  = 1 << 20
31
+	hwcap_SHA512   = 1 << 21
32
+	hwcap_SVE      = 1 << 22
33
+	hwcap_ASIMDFHM = 1 << 23
34
+)
35
+
36
+func doinit() {
37
+	// HWCAP feature bits
38
+	ARM64.HasFP = isSet(hwCap, hwcap_FP)
39
+	ARM64.HasASIMD = isSet(hwCap, hwcap_ASIMD)
40
+	ARM64.HasEVTSTRM = isSet(hwCap, hwcap_EVTSTRM)
41
+	ARM64.HasAES = isSet(hwCap, hwcap_AES)
42
+	ARM64.HasPMULL = isSet(hwCap, hwcap_PMULL)
43
+	ARM64.HasSHA1 = isSet(hwCap, hwcap_SHA1)
44
+	ARM64.HasSHA2 = isSet(hwCap, hwcap_SHA2)
45
+	ARM64.HasCRC32 = isSet(hwCap, hwcap_CRC32)
46
+	ARM64.HasATOMICS = isSet(hwCap, hwcap_ATOMICS)
47
+	ARM64.HasFPHP = isSet(hwCap, hwcap_FPHP)
48
+	ARM64.HasASIMDHP = isSet(hwCap, hwcap_ASIMDHP)
49
+	ARM64.HasCPUID = isSet(hwCap, hwcap_CPUID)
50
+	ARM64.HasASIMDRDM = isSet(hwCap, hwcap_ASIMDRDM)
51
+	ARM64.HasJSCVT = isSet(hwCap, hwcap_JSCVT)
52
+	ARM64.HasFCMA = isSet(hwCap, hwcap_FCMA)
53
+	ARM64.HasLRCPC = isSet(hwCap, hwcap_LRCPC)
54
+	ARM64.HasDCPOP = isSet(hwCap, hwcap_DCPOP)
55
+	ARM64.HasSHA3 = isSet(hwCap, hwcap_SHA3)
56
+	ARM64.HasSM3 = isSet(hwCap, hwcap_SM3)
57
+	ARM64.HasSM4 = isSet(hwCap, hwcap_SM4)
58
+	ARM64.HasASIMDDP = isSet(hwCap, hwcap_ASIMDDP)
59
+	ARM64.HasSHA512 = isSet(hwCap, hwcap_SHA512)
60
+	ARM64.HasSVE = isSet(hwCap, hwcap_SVE)
61
+	ARM64.HasASIMDFHM = isSet(hwCap, hwcap_ASIMDFHM)
62
+}
63
+
64
+func isSet(hwc uint, value uint) bool {
65
+	return hwc&value != 0
66
+}
0 67
new file mode 100644
... ...
@@ -0,0 +1,33 @@
0
+// Copyright 2018 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 linux
5
+// +build ppc64 ppc64le
6
+
7
+package cpu
8
+
9
+const cacheLineSize = 128
10
+
11
+// HWCAP/HWCAP2 bits. These are exposed by the kernel.
12
+const (
13
+	// ISA Level
14
+	_PPC_FEATURE2_ARCH_2_07 = 0x80000000
15
+	_PPC_FEATURE2_ARCH_3_00 = 0x00800000
16
+
17
+	// CPU features
18
+	_PPC_FEATURE2_DARN = 0x00200000
19
+	_PPC_FEATURE2_SCV  = 0x00100000
20
+)
21
+
22
+func doinit() {
23
+	// HWCAP2 feature bits
24
+	PPC64.IsPOWER8 = isSet(hwCap2, _PPC_FEATURE2_ARCH_2_07)
25
+	PPC64.IsPOWER9 = isSet(hwCap2, _PPC_FEATURE2_ARCH_3_00)
26
+	PPC64.HasDARN = isSet(hwCap2, _PPC_FEATURE2_DARN)
27
+	PPC64.HasSCV = isSet(hwCap2, _PPC_FEATURE2_SCV)
28
+}
29
+
30
+func isSet(hwc uint, value uint) bool {
31
+	return hwc&value != 0
32
+}
0 33
new file mode 100644
... ...
@@ -0,0 +1,161 @@
0
+// Copyright 2019 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 cpu
5
+
6
+const cacheLineSize = 256
7
+
8
+const (
9
+	// bit mask values from /usr/include/bits/hwcap.h
10
+	hwcap_ZARCH  = 2
11
+	hwcap_STFLE  = 4
12
+	hwcap_MSA    = 8
13
+	hwcap_LDISP  = 16
14
+	hwcap_EIMM   = 32
15
+	hwcap_DFP    = 64
16
+	hwcap_ETF3EH = 256
17
+	hwcap_VX     = 2048
18
+	hwcap_VXE    = 8192
19
+)
20
+
21
+// bitIsSet reports whether the bit at index is set. The bit index
22
+// is in big endian order, so bit index 0 is the leftmost bit.
23
+func bitIsSet(bits []uint64, index uint) bool {
24
+	return bits[index/64]&((1<<63)>>(index%64)) != 0
25
+}
26
+
27
+// function is the code for the named cryptographic function.
28
+type function uint8
29
+
30
+const (
31
+	// KM{,A,C,CTR} function codes
32
+	aes128 function = 18 // AES-128
33
+	aes192 function = 19 // AES-192
34
+	aes256 function = 20 // AES-256
35
+
36
+	// K{I,L}MD function codes
37
+	sha1     function = 1  // SHA-1
38
+	sha256   function = 2  // SHA-256
39
+	sha512   function = 3  // SHA-512
40
+	sha3_224 function = 32 // SHA3-224
41
+	sha3_256 function = 33 // SHA3-256
42
+	sha3_384 function = 34 // SHA3-384
43
+	sha3_512 function = 35 // SHA3-512
44
+	shake128 function = 36 // SHAKE-128
45
+	shake256 function = 37 // SHAKE-256
46
+
47
+	// KLMD function codes
48
+	ghash function = 65 // GHASH
49
+)
50
+
51
+// queryResult contains the result of a Query function
52
+// call. Bits are numbered in big endian order so the
53
+// leftmost bit (the MSB) is at index 0.
54
+type queryResult struct {
55
+	bits [2]uint64
56
+}
57
+
58
+// Has reports whether the given functions are present.
59
+func (q *queryResult) Has(fns ...function) bool {
60
+	if len(fns) == 0 {
61
+		panic("no function codes provided")
62
+	}
63
+	for _, f := range fns {
64
+		if !bitIsSet(q.bits[:], uint(f)) {
65
+			return false
66
+		}
67
+	}
68
+	return true
69
+}
70
+
71
+// facility is a bit index for the named facility.
72
+type facility uint8
73
+
74
+const (
75
+	// cryptography facilities
76
+	msa4 facility = 77  // message-security-assist extension 4
77
+	msa8 facility = 146 // message-security-assist extension 8
78
+)
79
+
80
+// facilityList contains the result of an STFLE call.
81
+// Bits are numbered in big endian order so the
82
+// leftmost bit (the MSB) is at index 0.
83
+type facilityList struct {
84
+	bits [4]uint64
85
+}
86
+
87
+// Has reports whether the given facilities are present.
88
+func (s *facilityList) Has(fs ...facility) bool {
89
+	if len(fs) == 0 {
90
+		panic("no facility bits provided")
91
+	}
92
+	for _, f := range fs {
93
+		if !bitIsSet(s.bits[:], uint(f)) {
94
+			return false
95
+		}
96
+	}
97
+	return true
98
+}
99
+
100
+func doinit() {
101
+	// test HWCAP bit vector
102
+	has := func(featureMask uint) bool {
103
+		return hwCap&featureMask == featureMask
104
+	}
105
+
106
+	// mandatory
107
+	S390X.HasZARCH = has(hwcap_ZARCH)
108
+
109
+	// optional
110
+	S390X.HasSTFLE = has(hwcap_STFLE)
111
+	S390X.HasLDISP = has(hwcap_LDISP)
112
+	S390X.HasEIMM = has(hwcap_EIMM)
113
+	S390X.HasETF3EH = has(hwcap_ETF3EH)
114
+	S390X.HasDFP = has(hwcap_DFP)
115
+	S390X.HasMSA = has(hwcap_MSA)
116
+	S390X.HasVX = has(hwcap_VX)
117
+	if S390X.HasVX {
118
+		S390X.HasVXE = has(hwcap_VXE)
119
+	}
120
+
121
+	// We need implementations of stfle, km and so on
122
+	// to detect cryptographic features.
123
+	if !haveAsmFunctions() {
124
+		return
125
+	}
126
+
127
+	// optional cryptographic functions
128
+	if S390X.HasMSA {
129
+		aes := []function{aes128, aes192, aes256}
130
+
131
+		// cipher message
132
+		km, kmc := kmQuery(), kmcQuery()
133
+		S390X.HasAES = km.Has(aes...)
134
+		S390X.HasAESCBC = kmc.Has(aes...)
135
+		if S390X.HasSTFLE {
136
+			facilities := stfle()
137
+			if facilities.Has(msa4) {
138
+				kmctr := kmctrQuery()
139
+				S390X.HasAESCTR = kmctr.Has(aes...)
140
+			}
141
+			if facilities.Has(msa8) {
142
+				kma := kmaQuery()
143
+				S390X.HasAESGCM = kma.Has(aes...)
144
+			}
145
+		}
146
+
147
+		// compute message digest
148
+		kimd := kimdQuery() // intermediate (no padding)
149
+		klmd := klmdQuery() // last (padding)
150
+		S390X.HasSHA1 = kimd.Has(sha1) && klmd.Has(sha1)
151
+		S390X.HasSHA256 = kimd.Has(sha256) && klmd.Has(sha256)
152
+		S390X.HasSHA512 = kimd.Has(sha512) && klmd.Has(sha512)
153
+		S390X.HasGHASH = kimd.Has(ghash) // KLMD-GHASH does not exist
154
+		sha3 := []function{
155
+			sha3_224, sha3_256, sha3_384, sha3_512,
156
+			shake128, shake256,
157
+		}
158
+		S390X.HasSHA3 = kimd.Has(sha3...) && klmd.Has(sha3...)
159
+	}
160
+}
0 161
new file mode 100644
... ...
@@ -0,0 +1,11 @@
0
+// Copyright 2019 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 !linux,arm64
5
+
6
+package cpu
7
+
8
+const cacheLineSize = 64
9
+
10
+func doinit() {}
0 11
new file mode 100644
... ...
@@ -0,0 +1,12 @@
0
+// Copyright 2019 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 !linux
5
+// +build ppc64 ppc64le
6
+
7
+package cpu
8
+
9
+const cacheLineSize = 128
10
+
11
+func doinit() {}
0 12
deleted file mode 100644
... ...
@@ -1,32 +0,0 @@
1
-// Copyright 2018 The Go Authors. All rights reserved.
2
-// Use of this source code is governed by a BSD-style
3
-// license that can be found in the LICENSE file.
4
-
5
-// +build ppc64 ppc64le
6
-
7
-package cpu
8
-
9
-const cacheLineSize = 128
10
-
11
-// HWCAP/HWCAP2 bits. These are exposed by the kernel.
12
-const (
13
-	// ISA Level
14
-	_PPC_FEATURE2_ARCH_2_07 = 0x80000000
15
-	_PPC_FEATURE2_ARCH_3_00 = 0x00800000
16
-
17
-	// CPU features
18
-	_PPC_FEATURE2_DARN = 0x00200000
19
-	_PPC_FEATURE2_SCV  = 0x00100000
20
-)
21
-
22
-func doinit() {
23
-	// HWCAP2 feature bits
24
-	PPC64.IsPOWER8 = isSet(HWCap2, _PPC_FEATURE2_ARCH_2_07)
25
-	PPC64.IsPOWER9 = isSet(HWCap2, _PPC_FEATURE2_ARCH_3_00)
26
-	PPC64.HasDARN = isSet(HWCap2, _PPC_FEATURE2_DARN)
27
-	PPC64.HasSCV = isSet(HWCap2, _PPC_FEATURE2_SCV)
28
-}
29
-
30
-func isSet(hwc uint, value uint) bool {
31
-	return hwc&value != 0
32
-}
33 1
deleted file mode 100644
... ...
@@ -1,9 +0,0 @@
1
-// Copyright 2018 The Go Authors. All rights reserved.
2
-// Use of this source code is governed by a BSD-style
3
-// license that can be found in the LICENSE file.
4
-
5
-package cpu
6
-
7
-const cacheLineSize = 256
8
-
9
-func doinit() {}
10 1
new file mode 100644
... ...
@@ -0,0 +1,57 @@
0
+// Copyright 2019 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
+// func stfle() facilityList
9
+TEXT ·stfle(SB), NOSPLIT|NOFRAME, $0-32
10
+	MOVD $ret+0(FP), R1
11
+	MOVD $3, R0          // last doubleword index to store
12
+	XC   $32, (R1), (R1) // clear 4 doublewords (32 bytes)
13
+	WORD $0xb2b01000     // store facility list extended (STFLE)
14
+	RET
15
+
16
+// func kmQuery() queryResult
17
+TEXT ·kmQuery(SB), NOSPLIT|NOFRAME, $0-16
18
+	MOVD $0, R0         // set function code to 0 (KM-Query)
19
+	MOVD $ret+0(FP), R1 // address of 16-byte return value
20
+	WORD $0xB92E0024    // cipher message (KM)
21
+	RET
22
+
23
+// func kmcQuery() queryResult
24
+TEXT ·kmcQuery(SB), NOSPLIT|NOFRAME, $0-16
25
+	MOVD $0, R0         // set function code to 0 (KMC-Query)
26
+	MOVD $ret+0(FP), R1 // address of 16-byte return value
27
+	WORD $0xB92F0024    // cipher message with chaining (KMC)
28
+	RET
29
+
30
+// func kmctrQuery() queryResult
31
+TEXT ·kmctrQuery(SB), NOSPLIT|NOFRAME, $0-16
32
+	MOVD $0, R0         // set function code to 0 (KMCTR-Query)
33
+	MOVD $ret+0(FP), R1 // address of 16-byte return value
34
+	WORD $0xB92D4024    // cipher message with counter (KMCTR)
35
+	RET
36
+
37
+// func kmaQuery() queryResult
38
+TEXT ·kmaQuery(SB), NOSPLIT|NOFRAME, $0-16
39
+	MOVD $0, R0         // set function code to 0 (KMA-Query)
40
+	MOVD $ret+0(FP), R1 // address of 16-byte return value
41
+	WORD $0xb9296024    // cipher message with authentication (KMA)
42
+	RET
43
+
44
+// func kimdQuery() queryResult
45
+TEXT ·kimdQuery(SB), NOSPLIT|NOFRAME, $0-16
46
+	MOVD $0, R0         // set function code to 0 (KIMD-Query)
47
+	MOVD $ret+0(FP), R1 // address of 16-byte return value
48
+	WORD $0xB93E0024    // compute intermediate message digest (KIMD)
49
+	RET
50
+
51
+// func klmdQuery() queryResult
52
+TEXT ·klmdQuery(SB), NOSPLIT|NOFRAME, $0-16
53
+	MOVD $0, R0         // set function code to 0 (KLMD-Query)
54
+	MOVD $ret+0(FP), R1 // address of 16-byte return value
55
+	WORD $0xB93F0024    // compute last message digest (KLMD)
56
+	RET
... ...
@@ -9,6 +9,8 @@ package cpu
9 9
 const cacheLineSize = 64
10 10
 
11 11
 func init() {
12
+	Initialized = true
13
+
12 14
 	maxID, _, _, _ := cpuid(0, 0)
13 15
 
14 16
 	if maxID < 1 {
... ...
@@ -32,7 +32,7 @@ To build the files for your current OS and architecture, make sure GOOS and
32 32
 GOARCH are set correctly and run `mkall.sh`. This will generate the files for
33 33
 your specific system. Running `mkall.sh -n` shows the commands that will be run.
34 34
 
35
-Requirements: bash, perl, go
35
+Requirements: bash, go
36 36
 
37 37
 ### New Build System (currently for `GOOS == "linux"`)
38 38
 
... ...
@@ -52,14 +52,14 @@ system and have your GOOS and GOARCH set accordingly. Running `mkall.sh` will
52 52
 then generate all of the files for all of the GOOS/GOARCH pairs in the new build
53 53
 system. Running `mkall.sh -n` shows the commands that will be run.
54 54
 
55
-Requirements: bash, perl, go, docker
55
+Requirements: bash, go, docker
56 56
 
57 57
 ## Component files
58 58
 
59 59
 This section describes the various files used in the code generation process.
60 60
 It also contains instructions on how to modify these files to add a new
61 61
 architecture/OS or to add additional syscalls, types, or constants. Note that
62
-if you are using the new build system, the scripts cannot be called normally.
62
+if you are using the new build system, the scripts/programs cannot be called normally.
63 63
 They must be called from within the docker container.
64 64
 
65 65
 ### asm files
... ...
@@ -81,8 +81,8 @@ each GOOS/GOARCH pair.
81 81
 
82 82
 ### mksysnum
83 83
 
84
-Mksysnum is a script located at `${GOOS}/mksysnum.pl` (or `mksysnum_${GOOS}.pl`
85
-for the old system). This script takes in a list of header files containing the
84
+Mksysnum is a Go program located at `${GOOS}/mksysnum.go` (or `mksysnum_${GOOS}.go`
85
+for the old system). This program takes in a list of header files containing the
86 86
 syscall number declarations and parses them to produce the corresponding list of
87 87
 Go numeric constants. See `zsysnum_${GOOS}_${GOARCH}.go` for the generated
88 88
 constants.
... ...
@@ -92,14 +92,14 @@ new installation of the target OS (or updating the source checkouts for the
92 92
 new build system). However, depending on the OS, you make need to update the
93 93
 parsing in mksysnum.
94 94
 
95
-### mksyscall.pl
95
+### mksyscall.go
96 96
 
97 97
 The `syscall.go`, `syscall_${GOOS}.go`, `syscall_${GOOS}_${GOARCH}.go` are
98 98
 hand-written Go files which implement system calls (for unix, the specific OS,
99 99
 or the specific OS/Architecture pair respectively) that need special handling
100 100
 and list `//sys` comments giving prototypes for ones that can be generated.
101 101
 
102
-The mksyscall.pl script takes the `//sys` and `//sysnb` comments and converts
102
+The mksyscall.go program takes the `//sys` and `//sysnb` comments and converts
103 103
 them into syscalls. This requires the name of the prototype in the comment to
104 104
 match a syscall number in the `zsysnum_${GOOS}_${GOARCH}.go` file. The function
105 105
 prototype can be exported (capitalized) or not.
... ...
@@ -160,7 +160,7 @@ signal numbers, and constants. Generated by `mkerrors.sh` (see above).
160 160
 ### `zsyscall_${GOOS}_${GOARCH}.go`
161 161
 
162 162
 A file containing all the generated syscalls for a specific GOOS and GOARCH.
163
-Generated by `mksyscall.pl` (see above).
163
+Generated by `mksyscall.go` (see above).
164 164
 
165 165
 ### `zsysnum_${GOOS}_${GOARCH}.go`
166 166
 
... ...
@@ -25,8 +25,8 @@ func cmsgAlignOf(salen int) int {
25 25
 		if SizeofPtr == 8 {
26 26
 			salign = 4
27 27
 		}
28
-	case "openbsd":
29
-		// OpenBSD armv7 requires 64-bit alignment.
28
+	case "netbsd", "openbsd":
29
+		// NetBSD and OpenBSD armv7 require 64-bit alignment.
30 30
 		if runtime.GOARCH == "arm" {
31 31
 			salign = 8
32 32
 		}
... ...
@@ -416,6 +416,7 @@ func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err e
416 416
 //sys	Chmod(path string, mode uint32) (err error)
417 417
 //sys	Chown(path string, uid int, gid int) (err error)
418 418
 //sys	Chroot(path string) (err error)
419
+//sys	ClockGettime(clockid int32, time *Timespec) (err error)
419 420
 //sys	Close(fd int) (err error)
420 421
 //sys	Dup(fd int) (nfd int, err error)
421 422
 //sys	Dup2(from int, to int) (err error)
... ...
@@ -994,6 +994,20 @@ func SetsockoptIPMreqn(fd, level, opt int, mreq *IPMreqn) (err error) {
994 994
 	return setsockopt(fd, level, opt, unsafe.Pointer(mreq), unsafe.Sizeof(*mreq))
995 995
 }
996 996
 
997
+// SetsockoptSockFprog attaches a classic BPF or an extended BPF program to a
998
+// socket to filter incoming packets.  See 'man 7 socket' for usage information.
999
+func SetsockoptSockFprog(fd, level, opt int, fprog *SockFprog) error {
1000
+	return setsockopt(fd, level, opt, unsafe.Pointer(fprog), unsafe.Sizeof(*fprog))
1001
+}
1002
+
1003
+func SetsockoptCanRawFilter(fd, level, opt int, filter []CanFilter) error {
1004
+	var p unsafe.Pointer
1005
+	if len(filter) > 0 {
1006
+		p = unsafe.Pointer(&filter[0])
1007
+	}
1008
+	return setsockopt(fd, level, opt, p, uintptr(len(filter)*SizeofCanFilter))
1009
+}
1010
+
997 1011
 // Keyctl Commands (http://man7.org/linux/man-pages/man2/keyctl.2.html)
998 1012
 
999 1013
 // KeyctlInt calls keyctl commands in which each argument is an int.
... ...
@@ -28,6 +28,11 @@ var (
28 28
 	errENOENT error = syscall.ENOENT
29 29
 )
30 30
 
31
+var (
32
+	signalNameMapOnce sync.Once
33
+	signalNameMap     map[string]syscall.Signal
34
+)
35
+
31 36
 // errnoErr returns common boxed Errno values, to prevent
32 37
 // allocations at runtime.
33 38
 func errnoErr(e syscall.Errno) error {
... ...
@@ -66,6 +71,19 @@ func SignalName(s syscall.Signal) string {
66 66
 	return ""
67 67
 }
68 68
 
69
+// SignalNum returns the syscall.Signal for signal named s,
70
+// or 0 if a signal with such name is not found.
71
+// The signal name should start with "SIG".
72
+func SignalNum(s string) syscall.Signal {
73
+	signalNameMapOnce.Do(func() {
74
+		signalNameMap = make(map[string]syscall.Signal)
75
+		for _, signal := range signalList {
76
+			signalNameMap[signal.name] = signal.num
77
+		}
78
+	})
79
+	return signalNameMap[s]
80
+}
81
+
69 82
 // clen returns the index of the first NULL byte in n or len(n) if n contains no NULL byte.
70 83
 func clen(n []byte) int {
71 84
 	i := bytes.IndexByte(n, 0)
... ...
@@ -943,6 +943,21 @@ func libc_chroot_trampoline()
943 943
 
944 944
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
945 945
 
946
+func ClockGettime(clockid int32, time *Timespec) (err error) {
947
+	_, _, e1 := syscall_syscall(funcPC(libc_clock_gettime_trampoline), uintptr(clockid), uintptr(unsafe.Pointer(time)), 0)
948
+	if e1 != 0 {
949
+		err = errnoErr(e1)
950
+	}
951
+	return
952
+}
953
+
954
+func libc_clock_gettime_trampoline()
955
+
956
+//go:linkname libc_clock_gettime libc_clock_gettime
957
+//go:cgo_import_dynamic libc_clock_gettime clock_gettime "/usr/lib/libSystem.B.dylib"
958
+
959
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
960
+
946 961
 func Close(fd int) (err error) {
947 962
 	_, _, e1 := syscall_syscall(funcPC(libc_close_trampoline), uintptr(fd), 0, 0)
948 963
 	if e1 != 0 {
... ...
@@ -108,6 +108,8 @@ TEXT ·libc_chown_trampoline(SB),NOSPLIT,$0-0
108 108
 	JMP	libc_chown(SB)
109 109
 TEXT ·libc_chroot_trampoline(SB),NOSPLIT,$0-0
110 110
 	JMP	libc_chroot(SB)
111
+TEXT ·libc_clock_gettime_trampoline(SB),NOSPLIT,$0-0
112
+	JMP	libc_clock_gettime(SB)
111 113
 TEXT ·libc_close_trampoline(SB),NOSPLIT,$0-0
112 114
 	JMP	libc_close(SB)
113 115
 TEXT ·libc_dup_trampoline(SB),NOSPLIT,$0-0
... ...
@@ -1,4 +1,4 @@
1
-// mksyscall_solaris.pl -tags solaris,amd64 syscall_solaris.go syscall_solaris_amd64.go
1
+// go run mksyscall_solaris.go -tags solaris,amd64 syscall_solaris.go syscall_solaris_amd64.go
2 2
 // Code generated by the command above; see README.md. DO NOT EDIT.
3 3
 
4 4
 // +build solaris,amd64
... ...
@@ -1,4 +1,4 @@
1
-// go run mksysnum.go /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.13.sdk/usr/include/sys/syscall.h
1
+// go run mksysnum.go /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.14.sdk/usr/include/sys/syscall.h
2 2
 // Code generated by the command above; see README.md. DO NOT EDIT.
3 3
 
4 4
 // +build amd64,darwin
... ...
@@ -431,6 +431,8 @@ const (
431 431
 	SYS_NTP_ADJTIME                    = 527
432 432
 	SYS_NTP_GETTIME                    = 528
433 433
 	SYS_OS_FAULT_WITH_PAYLOAD          = 529
434
-	SYS_MAXSYSCALL                     = 530
434
+	SYS_KQUEUE_WORKLOOP_CTL            = 530
435
+	SYS___MACH_BRIDGE_REMOTE_TIME      = 531
436
+	SYS_MAXSYSCALL                     = 532
435 437
 	SYS_INVALID                        = 63
436 438
 )
... ...
@@ -405,6 +405,11 @@ type TCPInfo struct {
405 405
 	Total_retrans  uint32
406 406
 }
407 407
 
408
+type CanFilter struct {
409
+	Id   uint32
410
+	Mask uint32
411
+}
412
+
408 413
 const (
409 414
 	SizeofSockaddrInet4     = 0x10
410 415
 	SizeofSockaddrInet6     = 0x1c
... ...
@@ -434,6 +439,7 @@ const (
434 434
 	SizeofICMPv6Filter      = 0x20
435 435
 	SizeofUcred             = 0xc
436 436
 	SizeofTCPInfo           = 0x68
437
+	SizeofCanFilter         = 0x8
437 438
 )
438 439
 
439 440
 const (
... ...
@@ -569,6 +575,7 @@ const (
569 569
 	SizeofIfAddrmsg      = 0x8
570 570
 	SizeofRtMsg          = 0xc
571 571
 	SizeofRtNexthop      = 0x8
572
+	SizeofNdUseroptmsg   = 0x10
572 573
 )
573 574
 
574 575
 type NlMsghdr struct {
... ...
@@ -634,6 +641,17 @@ type RtNexthop struct {
634 634
 	Ifindex int32
635 635
 }
636 636
 
637
+type NdUseroptmsg struct {
638
+	Family    uint8
639
+	Pad1      uint8
640
+	Opts_len  uint16
641
+	Ifindex   int32
642
+	Icmp_type uint8
643
+	Icmp_code uint8
644
+	Pad2      uint16
645
+	Pad3      uint32
646
+}
647
+
637 648
 const (
638 649
 	SizeofSockFilter = 0x8
639 650
 	SizeofSockFprog  = 0x8
... ...
@@ -406,6 +406,11 @@ type TCPInfo struct {
406 406
 	Total_retrans  uint32
407 407
 }
408 408
 
409
+type CanFilter struct {
410
+	Id   uint32
411
+	Mask uint32
412
+}
413
+
409 414
 const (
410 415
 	SizeofSockaddrInet4     = 0x10
411 416
 	SizeofSockaddrInet6     = 0x1c
... ...
@@ -435,6 +440,7 @@ const (
435 435
 	SizeofICMPv6Filter      = 0x20
436 436
 	SizeofUcred             = 0xc
437 437
 	SizeofTCPInfo           = 0x68
438
+	SizeofCanFilter         = 0x8
438 439
 )
439 440
 
440 441
 const (
... ...
@@ -570,6 +576,7 @@ const (
570 570
 	SizeofIfAddrmsg      = 0x8
571 571
 	SizeofRtMsg          = 0xc
572 572
 	SizeofRtNexthop      = 0x8
573
+	SizeofNdUseroptmsg   = 0x10
573 574
 )
574 575
 
575 576
 type NlMsghdr struct {
... ...
@@ -635,6 +642,17 @@ type RtNexthop struct {
635 635
 	Ifindex int32
636 636
 }
637 637
 
638
+type NdUseroptmsg struct {
639
+	Family    uint8
640
+	Pad1      uint8
641
+	Opts_len  uint16
642
+	Ifindex   int32
643
+	Icmp_type uint8
644
+	Icmp_code uint8
645
+	Pad2      uint16
646
+	Pad3      uint32
647
+}
648
+
638 649
 const (
639 650
 	SizeofSockFilter = 0x8
640 651
 	SizeofSockFprog  = 0x10
... ...
@@ -409,6 +409,11 @@ type TCPInfo struct {
409 409
 	Total_retrans  uint32
410 410
 }
411 411
 
412
+type CanFilter struct {
413
+	Id   uint32
414
+	Mask uint32
415
+}
416
+
412 417
 const (
413 418
 	SizeofSockaddrInet4     = 0x10
414 419
 	SizeofSockaddrInet6     = 0x1c
... ...
@@ -438,6 +443,7 @@ const (
438 438
 	SizeofICMPv6Filter      = 0x20
439 439
 	SizeofUcred             = 0xc
440 440
 	SizeofTCPInfo           = 0x68
441
+	SizeofCanFilter         = 0x8
441 442
 )
442 443
 
443 444
 const (
... ...
@@ -573,6 +579,7 @@ const (
573 573
 	SizeofIfAddrmsg      = 0x8
574 574
 	SizeofRtMsg          = 0xc
575 575
 	SizeofRtNexthop      = 0x8
576
+	SizeofNdUseroptmsg   = 0x10
576 577
 )
577 578
 
578 579
 type NlMsghdr struct {
... ...
@@ -638,6 +645,17 @@ type RtNexthop struct {
638 638
 	Ifindex int32
639 639
 }
640 640
 
641
+type NdUseroptmsg struct {
642
+	Family    uint8
643
+	Pad1      uint8
644
+	Opts_len  uint16
645
+	Ifindex   int32
646
+	Icmp_type uint8
647
+	Icmp_code uint8
648
+	Pad2      uint16
649
+	Pad3      uint32
650
+}
651
+
641 652
 const (
642 653
 	SizeofSockFilter = 0x8
643 654
 	SizeofSockFprog  = 0x8
... ...
@@ -407,6 +407,11 @@ type TCPInfo struct {
407 407
 	Total_retrans  uint32
408 408
 }
409 409
 
410
+type CanFilter struct {
411
+	Id   uint32
412
+	Mask uint32
413
+}
414
+
410 415
 const (
411 416
 	SizeofSockaddrInet4     = 0x10
412 417
 	SizeofSockaddrInet6     = 0x1c
... ...
@@ -436,6 +441,7 @@ const (
436 436
 	SizeofICMPv6Filter      = 0x20
437 437
 	SizeofUcred             = 0xc
438 438
 	SizeofTCPInfo           = 0x68
439
+	SizeofCanFilter         = 0x8
439 440
 )
440 441
 
441 442
 const (
... ...
@@ -571,6 +577,7 @@ const (
571 571
 	SizeofIfAddrmsg      = 0x8
572 572
 	SizeofRtMsg          = 0xc
573 573
 	SizeofRtNexthop      = 0x8
574
+	SizeofNdUseroptmsg   = 0x10
574 575
 )
575 576
 
576 577
 type NlMsghdr struct {
... ...
@@ -636,6 +643,17 @@ type RtNexthop struct {
636 636
 	Ifindex int32
637 637
 }
638 638
 
639
+type NdUseroptmsg struct {
640
+	Family    uint8
641
+	Pad1      uint8
642
+	Opts_len  uint16
643
+	Ifindex   int32
644
+	Icmp_type uint8
645
+	Icmp_code uint8
646
+	Pad2      uint16
647
+	Pad3      uint32
648
+}
649
+
639 650
 const (
640 651
 	SizeofSockFilter = 0x8
641 652
 	SizeofSockFprog  = 0x10
... ...
@@ -408,6 +408,11 @@ type TCPInfo struct {
408 408
 	Total_retrans  uint32
409 409
 }
410 410
 
411
+type CanFilter struct {
412
+	Id   uint32
413
+	Mask uint32
414
+}
415
+
411 416
 const (
412 417
 	SizeofSockaddrInet4     = 0x10
413 418
 	SizeofSockaddrInet6     = 0x1c
... ...
@@ -437,6 +442,7 @@ const (
437 437
 	SizeofICMPv6Filter      = 0x20
438 438
 	SizeofUcred             = 0xc
439 439
 	SizeofTCPInfo           = 0x68
440
+	SizeofCanFilter         = 0x8
440 441
 )
441 442
 
442 443
 const (
... ...
@@ -572,6 +578,7 @@ const (
572 572
 	SizeofIfAddrmsg      = 0x8
573 573
 	SizeofRtMsg          = 0xc
574 574
 	SizeofRtNexthop      = 0x8
575
+	SizeofNdUseroptmsg   = 0x10
575 576
 )
576 577
 
577 578
 type NlMsghdr struct {
... ...
@@ -637,6 +644,17 @@ type RtNexthop struct {
637 637
 	Ifindex int32
638 638
 }
639 639
 
640
+type NdUseroptmsg struct {
641
+	Family    uint8
642
+	Pad1      uint8
643
+	Opts_len  uint16
644
+	Ifindex   int32
645
+	Icmp_type uint8
646
+	Icmp_code uint8
647
+	Pad2      uint16
648
+	Pad3      uint32
649
+}
650
+
640 651
 const (
641 652
 	SizeofSockFilter = 0x8
642 653
 	SizeofSockFprog  = 0x8
... ...
@@ -407,6 +407,11 @@ type TCPInfo struct {
407 407
 	Total_retrans  uint32
408 408
 }
409 409
 
410
+type CanFilter struct {
411
+	Id   uint32
412
+	Mask uint32
413
+}
414
+
410 415
 const (
411 416
 	SizeofSockaddrInet4     = 0x10
412 417
 	SizeofSockaddrInet6     = 0x1c
... ...
@@ -436,6 +441,7 @@ const (
436 436
 	SizeofICMPv6Filter      = 0x20
437 437
 	SizeofUcred             = 0xc
438 438
 	SizeofTCPInfo           = 0x68
439
+	SizeofCanFilter         = 0x8
439 440
 )
440 441
 
441 442
 const (
... ...
@@ -571,6 +577,7 @@ const (
571 571
 	SizeofIfAddrmsg      = 0x8
572 572
 	SizeofRtMsg          = 0xc
573 573
 	SizeofRtNexthop      = 0x8
574
+	SizeofNdUseroptmsg   = 0x10
574 575
 )
575 576
 
576 577
 type NlMsghdr struct {
... ...
@@ -636,6 +643,17 @@ type RtNexthop struct {
636 636
 	Ifindex int32
637 637
 }
638 638
 
639
+type NdUseroptmsg struct {
640
+	Family    uint8
641
+	Pad1      uint8
642
+	Opts_len  uint16
643
+	Ifindex   int32
644
+	Icmp_type uint8
645
+	Icmp_code uint8
646
+	Pad2      uint16
647
+	Pad3      uint32
648
+}
649
+
639 650
 const (
640 651
 	SizeofSockFilter = 0x8
641 652
 	SizeofSockFprog  = 0x10
... ...
@@ -407,6 +407,11 @@ type TCPInfo struct {
407 407
 	Total_retrans  uint32
408 408
 }
409 409
 
410
+type CanFilter struct {
411
+	Id   uint32
412
+	Mask uint32
413
+}
414
+
410 415
 const (
411 416
 	SizeofSockaddrInet4     = 0x10
412 417
 	SizeofSockaddrInet6     = 0x1c
... ...
@@ -436,6 +441,7 @@ const (
436 436
 	SizeofICMPv6Filter      = 0x20
437 437
 	SizeofUcred             = 0xc
438 438
 	SizeofTCPInfo           = 0x68
439
+	SizeofCanFilter         = 0x8
439 440
 )
440 441
 
441 442
 const (
... ...
@@ -571,6 +577,7 @@ const (
571 571
 	SizeofIfAddrmsg      = 0x8
572 572
 	SizeofRtMsg          = 0xc
573 573
 	SizeofRtNexthop      = 0x8
574
+	SizeofNdUseroptmsg   = 0x10
574 575
 )
575 576
 
576 577
 type NlMsghdr struct {
... ...
@@ -636,6 +643,17 @@ type RtNexthop struct {
636 636
 	Ifindex int32
637 637
 }
638 638
 
639
+type NdUseroptmsg struct {
640
+	Family    uint8
641
+	Pad1      uint8
642
+	Opts_len  uint16
643
+	Ifindex   int32
644
+	Icmp_type uint8
645
+	Icmp_code uint8
646
+	Pad2      uint16
647
+	Pad3      uint32
648
+}
649
+
639 650
 const (
640 651
 	SizeofSockFilter = 0x8
641 652
 	SizeofSockFprog  = 0x10
... ...
@@ -408,6 +408,11 @@ type TCPInfo struct {
408 408
 	Total_retrans  uint32
409 409
 }
410 410
 
411
+type CanFilter struct {
412
+	Id   uint32
413
+	Mask uint32
414
+}
415
+
411 416
 const (
412 417
 	SizeofSockaddrInet4     = 0x10
413 418
 	SizeofSockaddrInet6     = 0x1c
... ...
@@ -437,6 +442,7 @@ const (
437 437
 	SizeofICMPv6Filter      = 0x20
438 438
 	SizeofUcred             = 0xc
439 439
 	SizeofTCPInfo           = 0x68
440
+	SizeofCanFilter         = 0x8
440 441
 )
441 442
 
442 443
 const (
... ...
@@ -572,6 +578,7 @@ const (
572 572
 	SizeofIfAddrmsg      = 0x8
573 573
 	SizeofRtMsg          = 0xc
574 574
 	SizeofRtNexthop      = 0x8
575
+	SizeofNdUseroptmsg   = 0x10
575 576
 )
576 577
 
577 578
 type NlMsghdr struct {
... ...
@@ -637,6 +644,17 @@ type RtNexthop struct {
637 637
 	Ifindex int32
638 638
 }
639 639
 
640
+type NdUseroptmsg struct {
641
+	Family    uint8
642
+	Pad1      uint8
643
+	Opts_len  uint16
644
+	Ifindex   int32
645
+	Icmp_type uint8
646
+	Icmp_code uint8
647
+	Pad2      uint16
648
+	Pad3      uint32
649
+}
650
+
640 651
 const (
641 652
 	SizeofSockFilter = 0x8
642 653
 	SizeofSockFprog  = 0x8
... ...
@@ -408,6 +408,11 @@ type TCPInfo struct {
408 408
 	Total_retrans  uint32
409 409
 }
410 410
 
411
+type CanFilter struct {
412
+	Id   uint32
413
+	Mask uint32
414
+}
415
+
411 416
 const (
412 417
 	SizeofSockaddrInet4     = 0x10
413 418
 	SizeofSockaddrInet6     = 0x1c
... ...
@@ -437,6 +442,7 @@ const (
437 437
 	SizeofICMPv6Filter      = 0x20
438 438
 	SizeofUcred             = 0xc
439 439
 	SizeofTCPInfo           = 0x68
440
+	SizeofCanFilter         = 0x8
440 441
 )
441 442
 
442 443
 const (
... ...
@@ -572,6 +578,7 @@ const (
572 572
 	SizeofIfAddrmsg      = 0x8
573 573
 	SizeofRtMsg          = 0xc
574 574
 	SizeofRtNexthop      = 0x8
575
+	SizeofNdUseroptmsg   = 0x10
575 576
 )
576 577
 
577 578
 type NlMsghdr struct {
... ...
@@ -637,6 +644,17 @@ type RtNexthop struct {
637 637
 	Ifindex int32
638 638
 }
639 639
 
640
+type NdUseroptmsg struct {
641
+	Family    uint8
642
+	Pad1      uint8
643
+	Opts_len  uint16
644
+	Ifindex   int32
645
+	Icmp_type uint8
646
+	Icmp_code uint8
647
+	Pad2      uint16
648
+	Pad3      uint32
649
+}
650
+
640 651
 const (
641 652
 	SizeofSockFilter = 0x8
642 653
 	SizeofSockFprog  = 0x10
... ...
@@ -408,6 +408,11 @@ type TCPInfo struct {
408 408
 	Total_retrans  uint32
409 409
 }
410 410
 
411
+type CanFilter struct {
412
+	Id   uint32
413
+	Mask uint32
414
+}
415
+
411 416
 const (
412 417
 	SizeofSockaddrInet4     = 0x10
413 418
 	SizeofSockaddrInet6     = 0x1c
... ...
@@ -437,6 +442,7 @@ const (
437 437
 	SizeofICMPv6Filter      = 0x20
438 438
 	SizeofUcred             = 0xc
439 439
 	SizeofTCPInfo           = 0x68
440
+	SizeofCanFilter         = 0x8
440 441
 )
441 442
 
442 443
 const (
... ...
@@ -572,6 +578,7 @@ const (
572 572
 	SizeofIfAddrmsg      = 0x8
573 573
 	SizeofRtMsg          = 0xc
574 574
 	SizeofRtNexthop      = 0x8
575
+	SizeofNdUseroptmsg   = 0x10
575 576
 )
576 577
 
577 578
 type NlMsghdr struct {
... ...
@@ -637,6 +644,17 @@ type RtNexthop struct {
637 637
 	Ifindex int32
638 638
 }
639 639
 
640
+type NdUseroptmsg struct {
641
+	Family    uint8
642
+	Pad1      uint8
643
+	Opts_len  uint16
644
+	Ifindex   int32
645
+	Icmp_type uint8
646
+	Icmp_code uint8
647
+	Pad2      uint16
648
+	Pad3      uint32
649
+}
650
+
640 651
 const (
641 652
 	SizeofSockFilter = 0x8
642 653
 	SizeofSockFprog  = 0x10
... ...
@@ -407,6 +407,11 @@ type TCPInfo struct {
407 407
 	Total_retrans  uint32
408 408
 }
409 409
 
410
+type CanFilter struct {
411
+	Id   uint32
412
+	Mask uint32
413
+}
414
+
410 415
 const (
411 416
 	SizeofSockaddrInet4     = 0x10
412 417
 	SizeofSockaddrInet6     = 0x1c
... ...
@@ -436,6 +441,7 @@ const (
436 436
 	SizeofICMPv6Filter      = 0x20
437 437
 	SizeofUcred             = 0xc
438 438
 	SizeofTCPInfo           = 0x68
439
+	SizeofCanFilter         = 0x8
439 440
 )
440 441
 
441 442
 const (
... ...
@@ -571,6 +577,7 @@ const (
571 571
 	SizeofIfAddrmsg      = 0x8
572 572
 	SizeofRtMsg          = 0xc
573 573
 	SizeofRtNexthop      = 0x8
574
+	SizeofNdUseroptmsg   = 0x10
574 575
 )
575 576
 
576 577
 type NlMsghdr struct {
... ...
@@ -636,6 +643,17 @@ type RtNexthop struct {
636 636
 	Ifindex int32
637 637
 }
638 638
 
639
+type NdUseroptmsg struct {
640
+	Family    uint8
641
+	Pad1      uint8
642
+	Opts_len  uint16
643
+	Ifindex   int32
644
+	Icmp_type uint8
645
+	Icmp_code uint8
646
+	Pad2      uint16
647
+	Pad3      uint32
648
+}
649
+
639 650
 const (
640 651
 	SizeofSockFilter = 0x8
641 652
 	SizeofSockFprog  = 0x10
... ...
@@ -406,6 +406,11 @@ type TCPInfo struct {
406 406
 	Total_retrans  uint32
407 407
 }
408 408
 
409
+type CanFilter struct {
410
+	Id   uint32
411
+	Mask uint32
412
+}
413
+
409 414
 const (
410 415
 	SizeofSockaddrInet4     = 0x10
411 416
 	SizeofSockaddrInet6     = 0x1c
... ...
@@ -435,6 +440,7 @@ const (
435 435
 	SizeofICMPv6Filter      = 0x20
436 436
 	SizeofUcred             = 0xc
437 437
 	SizeofTCPInfo           = 0x68
438
+	SizeofCanFilter         = 0x8
438 439
 )
439 440
 
440 441
 const (
... ...
@@ -570,6 +576,7 @@ const (
570 570
 	SizeofIfAddrmsg      = 0x8
571 571
 	SizeofRtMsg          = 0xc
572 572
 	SizeofRtNexthop      = 0x8
573
+	SizeofNdUseroptmsg   = 0x10
573 574
 )
574 575
 
575 576
 type NlMsghdr struct {
... ...
@@ -635,6 +642,17 @@ type RtNexthop struct {
635 635
 	Ifindex int32
636 636
 }
637 637
 
638
+type NdUseroptmsg struct {
639
+	Family    uint8
640
+	Pad1      uint8
641
+	Opts_len  uint16
642
+	Ifindex   int32
643
+	Icmp_type uint8
644
+	Icmp_code uint8
645
+	Pad2      uint16
646
+	Pad3      uint32
647
+}
648
+
638 649
 const (
639 650
 	SizeofSockFilter = 0x8
640 651
 	SizeofSockFprog  = 0x10
... ...
@@ -410,6 +410,11 @@ type TCPInfo struct {
410 410
 	Total_retrans  uint32
411 411
 }
412 412
 
413
+type CanFilter struct {
414
+	Id   uint32
415
+	Mask uint32
416
+}
417
+
413 418
 const (
414 419
 	SizeofSockaddrInet4     = 0x10
415 420
 	SizeofSockaddrInet6     = 0x1c
... ...
@@ -439,6 +444,7 @@ const (
439 439
 	SizeofICMPv6Filter      = 0x20
440 440
 	SizeofUcred             = 0xc
441 441
 	SizeofTCPInfo           = 0x68
442
+	SizeofCanFilter         = 0x8
442 443
 )
443 444
 
444 445
 const (
... ...
@@ -574,6 +580,7 @@ const (
574 574
 	SizeofIfAddrmsg      = 0x8
575 575
 	SizeofRtMsg          = 0xc
576 576
 	SizeofRtNexthop      = 0x8
577
+	SizeofNdUseroptmsg   = 0x10
577 578
 )
578 579
 
579 580
 type NlMsghdr struct {
... ...
@@ -639,6 +646,17 @@ type RtNexthop struct {
639 639
 	Ifindex int32
640 640
 }
641 641
 
642
+type NdUseroptmsg struct {
643
+	Family    uint8
644
+	Pad1      uint8
645
+	Opts_len  uint16
646
+	Ifindex   int32
647
+	Icmp_type uint8
648
+	Icmp_code uint8
649
+	Pad2      uint16
650
+	Pad3      uint32
651
+}
652
+
642 653
 const (
643 654
 	SizeofSockFilter = 0x8
644 655
 	SizeofSockFprog  = 0x10
... ...
@@ -149,7 +149,7 @@ const (
149 149
 	DOMAIN_ALIAS_RID_REMOTE_DESKTOP_USERS           = 0x22b
150 150
 	DOMAIN_ALIAS_RID_NETWORK_CONFIGURATION_OPS      = 0x22c
151 151
 	DOMAIN_ALIAS_RID_INCOMING_FOREST_TRUST_BUILDERS = 0x22d
152
-	DOMAIN_ALIAS_RID_MONITORING_USERS               = 0X22e
152
+	DOMAIN_ALIAS_RID_MONITORING_USERS               = 0x22e
153 153
 	DOMAIN_ALIAS_RID_LOGGING_USERS                  = 0x22f
154 154
 	DOMAIN_ALIAS_RID_AUTHORIZATIONACCESS            = 0x230
155 155
 	DOMAIN_ALIAS_RID_TS_LICENSE_SERVERS             = 0x231
... ...
@@ -80,6 +80,7 @@ type ChangeRequest struct {
80 80
 	EventType     uint32
81 81
 	EventData     uintptr
82 82
 	CurrentStatus Status
83
+	Context       uintptr
83 84
 }
84 85
 
85 86
 // Handler is the interface that must be implemented to build Windows service.
... ...
@@ -121,12 +122,11 @@ func init() {
121 121
 	cRegisterServiceCtrlHandlerExW = a.MustFindProc("RegisterServiceCtrlHandlerExW").Addr()
122 122
 }
123 123
 
124
-// The HandlerEx prototype also has a context pointer but since we don't use
125
-// it at start-up time we don't have to pass it over either.
126 124
 type ctlEvent struct {
127 125
 	cmd       Cmd
128 126
 	eventType uint32
129 127
 	eventData uintptr
128
+	context   uintptr
130 129
 	errno     uint32
131 130
 }
132 131
 
... ...
@@ -238,13 +238,12 @@ func (s *service) run() {
238 238
 		exitFromHandler <- exitCode{ss, errno}
239 239
 	}()
240 240
 
241
-	status := Status{State: Stopped}
242 241
 	ec := exitCode{isSvcSpecific: true, errno: 0}
242
+	outcr := ChangeRequest{
243
+		CurrentStatus: Status{State: Stopped},
244
+	}
243 245
 	var outch chan ChangeRequest
244 246
 	inch := s.c
245
-	var cmd Cmd
246
-	var evtype uint32
247
-	var evdata uintptr
248 247
 loop:
249 248
 	for {
250 249
 		select {
... ...
@@ -255,10 +254,11 @@ loop:
255 255
 			}
256 256
 			inch = nil
257 257
 			outch = cmdsToHandler
258
-			cmd = r.cmd
259
-			evtype = r.eventType
260
-			evdata = r.eventData
261
-		case outch <- ChangeRequest{cmd, evtype, evdata, status}:
258
+			outcr.Cmd = r.cmd
259
+			outcr.EventType = r.eventType
260
+			outcr.EventData = r.eventData
261
+			outcr.Context = r.context
262
+		case outch <- outcr:
262 263
 			inch = s.c
263 264
 			outch = nil
264 265
 		case c := <-changesFromHandler:
... ...
@@ -271,7 +271,7 @@ loop:
271 271
 				}
272 272
 				break loop
273 273
 			}
274
-			status = c
274
+			outcr.CurrentStatus = c
275 275
 		case ec = <-exitFromHandler:
276 276
 			break loop
277 277
 		}
... ...
@@ -315,8 +315,8 @@ func Run(name string, handler Handler) error {
315 315
 		return err
316 316
 	}
317 317
 
318
-	ctlHandler := func(ctl uint32, evtype uint32, evdata uintptr, context uintptr) uintptr {
319
-		e := ctlEvent{cmd: Cmd(ctl), eventType: evtype, eventData: evdata}
318
+	ctlHandler := func(ctl, evtype, evdata, context uintptr) uintptr {
319
+		e := ctlEvent{cmd: Cmd(ctl), eventType: uint32(evtype), eventData: evdata, context: context}
320 320
 		// We assume that this callback function is running on
321 321
 		// the same thread as Run. Nowhere in MS documentation
322 322
 		// I could find statement to guarantee that. So putting
... ...
@@ -22,7 +22,8 @@ TEXT ·servicemain(SB),7,$0
22 22
 	MOVL	AX, (SP)
23 23
 	MOVL	$·servicectlhandler(SB), AX
24 24
 	MOVL	AX, 4(SP)
25
-	MOVL	$0, 8(SP)
25
+	// Set context to 123456 to test issue #25660.
26
+	MOVL	$123456, 8(SP)
26 27
 	MOVL	·cRegisterServiceCtrlHandlerExW(SB), AX
27 28
 	MOVL	SP, BP
28 29
 	CALL	AX
... ...
@@ -14,6 +14,8 @@ TEXT ·servicemain(SB),7,$0
14 14
 	MOVQ	·sName(SB), CX
15 15
 	MOVQ	$·servicectlhandler(SB), DX
16 16
 	// BUG(pastarmovj): Figure out a way to pass in context in R8.
17
+	// Set context to 123456 to test issue #25660.
18
+	MOVQ	$123456, R8
17 19
 	MOVQ	·cRegisterServiceCtrlHandlerExW(SB), AX
18 20
 	CALL	AX
19 21
 	CMPQ	AX, $0