Merge pull request #420 from mtrmac/manifest-lists

Support copying a single image from manifest lists
This commit is contained in:
Miloslav Trmač 2017-11-16 17:05:08 +01:00 committed by GitHub
commit eb43d93b57
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
94 changed files with 1388 additions and 491 deletions

View File

@ -24,11 +24,15 @@ var layersCmd = cli.Command{
if c.NArg() == 0 { if c.NArg() == 0 {
return errors.New("Usage: layers imageReference [layer...]") return errors.New("Usage: layers imageReference [layer...]")
} }
ctx, err := contextFromGlobalOptions(c, "")
if err != nil {
return err
}
rawSource, err := parseImageSource(c, c.Args()[0]) rawSource, err := parseImageSource(c, c.Args()[0])
if err != nil { if err != nil {
return err return err
} }
src, err := image.FromSource(rawSource) src, err := image.FromSource(ctx, rawSource)
if err != nil { if err != nil {
if closeErr := rawSource.Close(); closeErr != nil { if closeErr := rawSource.Close(); closeErr != nil {
return errors.Wrapf(err, " (close error: %v)", closeErr) return errors.Wrapf(err, " (close error: %v)", closeErr)

View File

@ -50,6 +50,16 @@ func createApp() *cli.App {
Value: "", Value: "",
Usage: "use registry configuration files in `DIR` (e.g. for container signature storage)", Usage: "use registry configuration files in `DIR` (e.g. for container signature storage)",
}, },
cli.StringFlag{
Name: "override-arch",
Value: "",
Usage: "use `ARCH` instead of the architecture of the machine for choosing images",
},
cli.StringFlag{
Name: "override-os",
Value: "",
Usage: "use `OS` instead of the running OS for choosing images",
},
} }
app.Before = func(c *cli.Context) error { app.Before = func(c *cli.Context) error {
if c.GlobalBool("debug") { if c.GlobalBool("debug") {

View File

@ -11,8 +11,10 @@ import (
func contextFromGlobalOptions(c *cli.Context, flagPrefix string) (*types.SystemContext, error) { func contextFromGlobalOptions(c *cli.Context, flagPrefix string) (*types.SystemContext, error) {
ctx := &types.SystemContext{ ctx := &types.SystemContext{
RegistriesDirPath: c.GlobalString("registries.d"), RegistriesDirPath: c.GlobalString("registries.d"),
DockerCertPath: c.String(flagPrefix + "cert-dir"), ArchitectureChoice: c.GlobalString("override-arch"),
OSChoice: c.GlobalString("override-os"),
DockerCertPath: c.String(flagPrefix + "cert-dir"),
// DEPRECATED: keep this here for backward compatibility, but override // DEPRECATED: keep this here for backward compatibility, but override
// them if per subcommand flags are provided (see below). // them if per subcommand flags are provided (see below).
DockerInsecureSkipTLSVerify: !c.GlobalBoolT("tls-verify"), DockerInsecureSkipTLSVerify: !c.GlobalBoolT("tls-verify"),
@ -59,8 +61,8 @@ func getDockerAuth(creds string) (*types.DockerAuthConfig, error) {
} }
// parseImage converts image URL-like string to an initialized handler for that image. // parseImage converts image URL-like string to an initialized handler for that image.
// The caller must call .Close() on the returned Image. // The caller must call .Close() on the returned ImageCloser.
func parseImage(c *cli.Context) (types.Image, error) { func parseImage(c *cli.Context) (types.ImageCloser, error) {
imgName := c.Args().First() imgName := c.Args().First()
ref, err := alltransports.ParseImageName(imgName) ref, err := alltransports.ParseImageName(imgName)
if err != nil { if err != nil {

View File

@ -103,6 +103,8 @@ _skopeo_skopeo() {
local options_with_args=" local options_with_args="
--policy --policy
--registries.d --registries.d
--override-arch
--override-os
" "
local boolean_options=" local boolean_options="
--insecure-policy --insecure-policy

View File

@ -43,6 +43,10 @@ Most commands refer to container images, using a _transport_`:`_details_ format.
**--registries.d** _dir_ use registry configuration files in _dir_ (e.g. for container signature storage), overriding the default path. **--registries.d** _dir_ use registry configuration files in _dir_ (e.g. for container signature storage), overriding the default path.
**--override-arch** _arch_ Use _arch_ instead of the architecture of the machine for choosing images.
**--override-os** _OS_ Use _OS_ instead of the running OS for choosing images.
**--help**|**-h** Show help **--help**|**-h** Show help
**--version**|**-v** print the version number **--version**|**-v** print the version number

View File

@ -90,9 +90,11 @@ func (s *CopySuite) TearDownSuite(c *check.C) {
} }
} }
func (s *CopySuite) TestCopyFailsWithManifestList(c *check.C) { func (s *CopySuite) TestCopyWithManifestList(c *check.C) {
c.ExpectFailure("manifest-list-hotfix sacrificed hotfixes for being able to copy images") dir, err := ioutil.TempDir("", "copy-manifest-list")
assertSkopeoFails(c, ".*can not copy docker://estesp/busybox:latest: manifest contains multiple images.*", "copy", "docker://estesp/busybox:latest", "dir:somedir") c.Assert(err, check.IsNil)
defer os.RemoveAll(dir)
assertSkopeoSucceeds(c, "", "copy", "docker://estesp/busybox:latest", "dir:"+dir)
} }
func (s *CopySuite) TestCopyFailsWhenImageOSDoesntMatchRuntimeOS(c *check.C) { func (s *CopySuite) TestCopyFailsWhenImageOSDoesntMatchRuntimeOS(c *check.C) {

View File

@ -1,5 +1,5 @@
github.com/urfave/cli v1.17.0 github.com/urfave/cli v1.17.0
github.com/containers/image f950aa3529148eb0dea90888c24b6682da641b13 github.com/containers/image master
github.com/opencontainers/go-digest master github.com/opencontainers/go-digest master
gopkg.in/cheggaaa/pb.v1 ad4efe000aa550bb54918c06ebbadc0ff17687b9 https://github.com/cheggaaa/pb gopkg.in/cheggaaa/pb.v1 ad4efe000aa550bb54918c06ebbadc0ff17687b9 https://github.com/cheggaaa/pb
github.com/containers/storage master github.com/containers/storage master

View File

@ -30,23 +30,6 @@ type digestingReader struct {
validationFailed bool validationFailed bool
} }
// imageCopier allows us to keep track of diffID values for blobs, and other
// data, that we're copying between images, and cache other information that
// might allow us to take some shortcuts
type imageCopier struct {
copiedBlobs map[digest.Digest]digest.Digest
cachedDiffIDs map[digest.Digest]digest.Digest
manifestUpdates *types.ManifestUpdateOptions
dest types.ImageDestination
src types.Image
rawSource types.ImageSource
diffIDsAreNeeded bool
canModifyManifest bool
reportWriter io.Writer
progressInterval time.Duration
progress chan types.ProgressProperties
}
// newDigestingReader returns an io.Reader implementation with contents of source, which will eventually return a non-EOF error // newDigestingReader returns an io.Reader implementation with contents of source, which will eventually return a non-EOF error
// and set validationFailed to true if the source stream does not match expectedDigest. // and set validationFailed to true if the source stream does not match expectedDigest.
func newDigestingReader(source io.Reader, expectedDigest digest.Digest) (*digestingReader, error) { func newDigestingReader(source io.Reader, expectedDigest digest.Digest) (*digestingReader, error) {
@ -85,6 +68,27 @@ func (d *digestingReader) Read(p []byte) (int, error) {
return n, err return n, err
} }
// copier allows us to keep track of diffID values for blobs, and other
// data shared across one or more images in a possible manifest list.
type copier struct {
copiedBlobs map[digest.Digest]digest.Digest
cachedDiffIDs map[digest.Digest]digest.Digest
dest types.ImageDestination
rawSource types.ImageSource
reportWriter io.Writer
progressInterval time.Duration
progress chan types.ProgressProperties
}
// imageCopier tracks state specific to a single image (possibly an item of a manifest list)
type imageCopier struct {
c *copier
manifestUpdates *types.ManifestUpdateOptions
src types.Image
diffIDsAreNeeded bool
canModifyManifest bool
}
// Options allows supplying non-default configuration modifying the behavior of CopyImage. // Options allows supplying non-default configuration modifying the behavior of CopyImage.
type Options struct { type Options struct {
RemoveSignatures bool // Remove any pre-existing signatures. SignBy will still add a new signature. RemoveSignatures bool // Remove any pre-existing signatures. SignBy will still add a new signature.
@ -116,10 +120,6 @@ func Image(policyContext *signature.PolicyContext, destRef, srcRef types.ImageRe
reportWriter = options.ReportWriter reportWriter = options.ReportWriter
} }
writeReport := func(f string, a ...interface{}) {
fmt.Fprintf(reportWriter, f, a...)
}
dest, err := destRef.NewImageDestination(options.DestinationCtx) dest, err := destRef.NewImageDestination(options.DestinationCtx)
if err != nil { if err != nil {
return errors.Wrapf(err, "Error initializing destination %s", transports.ImageName(destRef)) return errors.Wrapf(err, "Error initializing destination %s", transports.ImageName(destRef))
@ -134,43 +134,89 @@ func Image(policyContext *signature.PolicyContext, destRef, srcRef types.ImageRe
if err != nil { if err != nil {
return errors.Wrapf(err, "Error initializing source %s", transports.ImageName(srcRef)) return errors.Wrapf(err, "Error initializing source %s", transports.ImageName(srcRef))
} }
unparsedImage := image.UnparsedFromSource(rawSource)
defer func() { defer func() {
if unparsedImage != nil { if err := rawSource.Close(); err != nil {
if err := unparsedImage.Close(); err != nil { retErr = errors.Wrapf(retErr, " (src: %v)", err)
retErr = errors.Wrapf(retErr, " (unparsed: %v)", err)
}
} }
}() }()
c := &copier{
copiedBlobs: make(map[digest.Digest]digest.Digest),
cachedDiffIDs: make(map[digest.Digest]digest.Digest),
dest: dest,
rawSource: rawSource,
reportWriter: reportWriter,
progressInterval: options.ProgressInterval,
progress: options.Progress,
}
unparsedToplevel := image.UnparsedInstance(rawSource, nil)
multiImage, err := isMultiImage(unparsedToplevel)
if err != nil {
return errors.Wrapf(err, "Error determining manifest MIME type for %s", transports.ImageName(srcRef))
}
if !multiImage {
// The simple case: Just copy a single image.
if err := c.copyOneImage(policyContext, options, unparsedToplevel); err != nil {
return err
}
} else {
// This is a manifest list. Choose a single image and copy it.
// FIXME: Copy to destinations which support manifest lists, one image at a time.
instanceDigest, err := image.ChooseManifestInstanceFromManifestList(options.SourceCtx, unparsedToplevel)
if err != nil {
return errors.Wrapf(err, "Error choosing an image from manifest list %s", transports.ImageName(srcRef))
}
logrus.Debugf("Source is a manifest list; copying (only) instance %s", instanceDigest)
unparsedInstance := image.UnparsedInstance(rawSource, &instanceDigest)
if err := c.copyOneImage(policyContext, options, unparsedInstance); err != nil {
return err
}
}
if err := c.dest.Commit(); err != nil {
return errors.Wrap(err, "Error committing the finished image")
}
return nil
}
// Image copies a single (on-manifest-list) image unparsedImage, using policyContext to validate
// source image admissibility.
func (c *copier) copyOneImage(policyContext *signature.PolicyContext, options *Options, unparsedImage *image.UnparsedImage) (retErr error) {
// The caller is handling manifest lists; this could happen only if a manifest list contains a manifest list.
// Make sure we fail cleanly in such cases.
multiImage, err := isMultiImage(unparsedImage)
if err != nil {
// FIXME FIXME: How to name a reference for the sub-image?
return errors.Wrapf(err, "Error determining manifest MIME type for %s", transports.ImageName(unparsedImage.Reference()))
}
if multiImage {
return fmt.Errorf("Unexpectedly received a manifest list instead of a manifest for a single image")
}
// Please keep this policy check BEFORE reading any other information about the image. // Please keep this policy check BEFORE reading any other information about the image.
// (the multiImage check above only matches the MIME type, which we have received anyway.
// Actual parsing of anything should be deferred.)
if allowed, err := policyContext.IsRunningImageAllowed(unparsedImage); !allowed || err != nil { // Be paranoid and fail if either return value indicates so. if allowed, err := policyContext.IsRunningImageAllowed(unparsedImage); !allowed || err != nil { // Be paranoid and fail if either return value indicates so.
return errors.Wrap(err, "Source image rejected") return errors.Wrap(err, "Source image rejected")
} }
src, err := image.FromUnparsedImage(unparsedImage) src, err := image.FromUnparsedImage(options.SourceCtx, unparsedImage)
if err != nil { if err != nil {
return errors.Wrapf(err, "Error initializing image from source %s", transports.ImageName(srcRef)) return errors.Wrapf(err, "Error initializing image from source %s", transports.ImageName(c.rawSource.Reference()))
} }
unparsedImage = nil
defer func() {
if err := src.Close(); err != nil {
retErr = errors.Wrapf(retErr, " (source: %v)", err)
}
}()
if err := checkImageDestinationForCurrentRuntimeOS(src, dest); err != nil { if err := checkImageDestinationForCurrentRuntimeOS(options.DestinationCtx, src, c.dest); err != nil {
return err return err
} }
if src.IsMultiImage() {
return errors.Errorf("can not copy %s: manifest contains multiple images", transports.ImageName(srcRef))
}
var sigs [][]byte var sigs [][]byte
if options.RemoveSignatures { if options.RemoveSignatures {
sigs = [][]byte{} sigs = [][]byte{}
} else { } else {
writeReport("Getting image source signatures\n") c.Printf("Getting image source signatures\n")
s, err := src.Signatures(context.TODO()) s, err := src.Signatures(context.TODO())
if err != nil { if err != nil {
return errors.Wrap(err, "Error reading signatures") return errors.Wrap(err, "Error reading signatures")
@ -178,41 +224,33 @@ func Image(policyContext *signature.PolicyContext, destRef, srcRef types.ImageRe
sigs = s sigs = s
} }
if len(sigs) != 0 { if len(sigs) != 0 {
writeReport("Checking if image destination supports signatures\n") c.Printf("Checking if image destination supports signatures\n")
if err := dest.SupportsSignatures(); err != nil { if err := c.dest.SupportsSignatures(); err != nil {
return errors.Wrap(err, "Can not copy signatures") return errors.Wrap(err, "Can not copy signatures")
} }
} }
canModifyManifest := len(sigs) == 0 ic := imageCopier{
manifestUpdates := types.ManifestUpdateOptions{} c: c,
manifestUpdates.InformationOnly.Destination = dest manifestUpdates: &types.ManifestUpdateOptions{InformationOnly: types.ManifestUpdateInformation{Destination: c.dest}},
src: src,
// diffIDsAreNeeded is computed later
canModifyManifest: len(sigs) == 0,
}
if err := updateEmbeddedDockerReference(&manifestUpdates, dest, src, canModifyManifest); err != nil { if err := ic.updateEmbeddedDockerReference(); err != nil {
return err return err
} }
// We compute preferredManifestMIMEType only to show it in error messages. // We compute preferredManifestMIMEType only to show it in error messages.
// Without having to add this context in an error message, we would be happy enough to know only that no conversion is needed. // Without having to add this context in an error message, we would be happy enough to know only that no conversion is needed.
preferredManifestMIMEType, otherManifestMIMETypeCandidates, err := determineManifestConversion(&manifestUpdates, src, dest.SupportedManifestMIMETypes(), canModifyManifest, options.ForceManifestMIMEType) preferredManifestMIMEType, otherManifestMIMETypeCandidates, err := ic.determineManifestConversion(c.dest.SupportedManifestMIMETypes(), options.ForceManifestMIMEType)
if err != nil { if err != nil {
return err return err
} }
// If src.UpdatedImageNeedsLayerDiffIDs(manifestUpdates) will be true, it needs to be true by the time we get here. // If src.UpdatedImageNeedsLayerDiffIDs(ic.manifestUpdates) will be true, it needs to be true by the time we get here.
ic := imageCopier{ ic.diffIDsAreNeeded = src.UpdatedImageNeedsLayerDiffIDs(*ic.manifestUpdates)
copiedBlobs: make(map[digest.Digest]digest.Digest),
cachedDiffIDs: make(map[digest.Digest]digest.Digest),
manifestUpdates: &manifestUpdates,
dest: dest,
src: src,
rawSource: rawSource,
diffIDsAreNeeded: src.UpdatedImageNeedsLayerDiffIDs(manifestUpdates),
canModifyManifest: canModifyManifest,
reportWriter: reportWriter,
progressInterval: options.ProgressInterval,
progress: options.Progress,
}
if err := ic.copyLayers(); err != nil { if err := ic.copyLayers(); err != nil {
return err return err
@ -234,9 +272,9 @@ func Image(policyContext *signature.PolicyContext, destRef, srcRef types.ImageRe
} }
// If the original MIME type is acceptable, determineManifestConversion always uses it as preferredManifestMIMEType. // If the original MIME type is acceptable, determineManifestConversion always uses it as preferredManifestMIMEType.
// So if we are here, we will definitely be trying to convert the manifest. // So if we are here, we will definitely be trying to convert the manifest.
// With !canModifyManifest, that would just be a string of repeated failures for the same reason, // With !ic.canModifyManifest, that would just be a string of repeated failures for the same reason,
// so lets bail out early and with a better error message. // so lets bail out early and with a better error message.
if !canModifyManifest { if !ic.canModifyManifest {
return errors.Wrap(err, "Writing manifest failed (and converting it is not possible)") return errors.Wrap(err, "Writing manifest failed (and converting it is not possible)")
} }
@ -244,7 +282,7 @@ func Image(policyContext *signature.PolicyContext, destRef, srcRef types.ImageRe
errs := []string{fmt.Sprintf("%s(%v)", preferredManifestMIMEType, err)} errs := []string{fmt.Sprintf("%s(%v)", preferredManifestMIMEType, err)}
for _, manifestMIMEType := range otherManifestMIMETypeCandidates { for _, manifestMIMEType := range otherManifestMIMETypeCandidates {
logrus.Debugf("Trying to use manifest type %s…", manifestMIMEType) logrus.Debugf("Trying to use manifest type %s…", manifestMIMEType)
manifestUpdates.ManifestMIMEType = manifestMIMEType ic.manifestUpdates.ManifestMIMEType = manifestMIMEType
attemptedManifest, err := ic.copyUpdatedConfigAndManifest() attemptedManifest, err := ic.copyUpdatedConfigAndManifest()
if err != nil { if err != nil {
logrus.Debugf("Upload of manifest type %s failed: %v", manifestMIMEType, err) logrus.Debugf("Upload of manifest type %s failed: %v", manifestMIMEType, err)
@ -263,35 +301,44 @@ func Image(policyContext *signature.PolicyContext, destRef, srcRef types.ImageRe
} }
if options.SignBy != "" { if options.SignBy != "" {
newSig, err := createSignature(dest, manifest, options.SignBy, reportWriter) newSig, err := c.createSignature(manifest, options.SignBy)
if err != nil { if err != nil {
return err return err
} }
sigs = append(sigs, newSig) sigs = append(sigs, newSig)
} }
writeReport("Storing signatures\n") c.Printf("Storing signatures\n")
if err := dest.PutSignatures(sigs); err != nil { if err := c.dest.PutSignatures(sigs); err != nil {
return errors.Wrap(err, "Error writing signatures") return errors.Wrap(err, "Error writing signatures")
} }
if err := dest.Commit(); err != nil {
return errors.Wrap(err, "Error committing the finished image")
}
return nil return nil
} }
func checkImageDestinationForCurrentRuntimeOS(src types.Image, dest types.ImageDestination) error { // Printf writes a formatted string to c.reportWriter.
// Note that the method name Printf is not entirely arbitrary: (go tool vet)
// has a built-in list of functions/methods (whatever object they are for)
// which have their format strings checked; for other names we would have
// to pass a parameter to every (go tool vet) invocation.
func (c *copier) Printf(format string, a ...interface{}) {
fmt.Fprintf(c.reportWriter, format, a...)
}
func checkImageDestinationForCurrentRuntimeOS(ctx *types.SystemContext, src types.Image, dest types.ImageDestination) error {
if dest.MustMatchRuntimeOS() { if dest.MustMatchRuntimeOS() {
wantedOS := runtime.GOOS
if ctx != nil && ctx.OSChoice != "" {
wantedOS = ctx.OSChoice
}
c, err := src.OCIConfig() c, err := src.OCIConfig()
if err != nil { if err != nil {
return errors.Wrapf(err, "Error parsing image configuration") return errors.Wrapf(err, "Error parsing image configuration")
} }
osErr := fmt.Errorf("image operating system %q cannot be used on %q", c.OS, runtime.GOOS) osErr := fmt.Errorf("image operating system %q cannot be used on %q", c.OS, wantedOS)
if runtime.GOOS == "windows" && c.OS == "linux" { if wantedOS == "windows" && c.OS == "linux" {
return osErr return osErr
} else if runtime.GOOS != "windows" && c.OS == "windows" { } else if wantedOS != "windows" && c.OS == "windows" {
return osErr return osErr
} }
} }
@ -299,24 +346,24 @@ func checkImageDestinationForCurrentRuntimeOS(src types.Image, dest types.ImageD
} }
// updateEmbeddedDockerReference handles the Docker reference embedded in Docker schema1 manifests. // updateEmbeddedDockerReference handles the Docker reference embedded in Docker schema1 manifests.
func updateEmbeddedDockerReference(manifestUpdates *types.ManifestUpdateOptions, dest types.ImageDestination, src types.Image, canModifyManifest bool) error { func (ic *imageCopier) updateEmbeddedDockerReference() error {
destRef := dest.Reference().DockerReference() destRef := ic.c.dest.Reference().DockerReference()
if destRef == nil { if destRef == nil {
return nil // Destination does not care about Docker references return nil // Destination does not care about Docker references
} }
if !src.EmbeddedDockerReferenceConflicts(destRef) { if !ic.src.EmbeddedDockerReferenceConflicts(destRef) {
return nil // No reference embedded in the manifest, or it matches destRef already. return nil // No reference embedded in the manifest, or it matches destRef already.
} }
if !canModifyManifest { if !ic.canModifyManifest {
return errors.Errorf("Copying a schema1 image with an embedded Docker reference to %s (Docker reference %s) would invalidate existing signatures. Explicitly enable signature removal to proceed anyway", return errors.Errorf("Copying a schema1 image with an embedded Docker reference to %s (Docker reference %s) would invalidate existing signatures. Explicitly enable signature removal to proceed anyway",
transports.ImageName(dest.Reference()), destRef.String()) transports.ImageName(ic.c.dest.Reference()), destRef.String())
} }
manifestUpdates.EmbeddedDockerReference = destRef ic.manifestUpdates.EmbeddedDockerReference = destRef
return nil return nil
} }
// copyLayers copies layers from src/rawSource to dest, using and updating ic.manifestUpdates if necessary and ic.canModifyManifest. // copyLayers copies layers from ic.src/ic.c.rawSource to dest, using and updating ic.manifestUpdates if necessary and ic.canModifyManifest.
func (ic *imageCopier) copyLayers() error { func (ic *imageCopier) copyLayers() error {
srcInfos := ic.src.LayerInfos() srcInfos := ic.src.LayerInfos()
destInfos := []types.BlobInfo{} destInfos := []types.BlobInfo{}
@ -327,7 +374,7 @@ func (ic *imageCopier) copyLayers() error {
diffID digest.Digest diffID digest.Digest
err error err error
) )
if ic.dest.AcceptsForeignLayerURLs() && len(srcLayer.URLs) != 0 { if ic.c.dest.AcceptsForeignLayerURLs() && len(srcLayer.URLs) != 0 {
// DiffIDs are, currently, needed only when converting from schema1. // DiffIDs are, currently, needed only when converting from schema1.
// In which case src.LayerInfos will not have URLs because schema1 // In which case src.LayerInfos will not have URLs because schema1
// does not support them. // does not support them.
@ -335,7 +382,7 @@ func (ic *imageCopier) copyLayers() error {
return errors.New("getting DiffID for foreign layers is unimplemented") return errors.New("getting DiffID for foreign layers is unimplemented")
} }
destInfo = srcLayer destInfo = srcLayer
fmt.Fprintf(ic.reportWriter, "Skipping foreign layer %q copy to %s\n", destInfo.Digest, ic.dest.Reference().Transport().Name()) ic.c.Printf("Skipping foreign layer %q copy to %s\n", destInfo.Digest, ic.c.dest.Reference().Transport().Name())
} else { } else {
destInfo, diffID, err = ic.copyLayer(srcLayer) destInfo, diffID, err = ic.copyLayer(srcLayer)
if err != nil { if err != nil {
@ -380,7 +427,7 @@ func (ic *imageCopier) copyUpdatedConfigAndManifest() ([]byte, error) {
// We have set ic.diffIDsAreNeeded based on the preferred MIME type returned by determineManifestConversion. // We have set ic.diffIDsAreNeeded based on the preferred MIME type returned by determineManifestConversion.
// So, this can only happen if we are trying to upload using one of the other MIME type candidates. // So, this can only happen if we are trying to upload using one of the other MIME type candidates.
// Because UpdatedImageNeedsLayerDiffIDs is true only when converting from s1 to s2, this case should only arise // Because UpdatedImageNeedsLayerDiffIDs is true only when converting from s1 to s2, this case should only arise
// when ic.dest.SupportedManifestMIMETypes() includes both s1 and s2, the upload using s1 failed, and we are now trying s2. // when ic.c.dest.SupportedManifestMIMETypes() includes both s1 and s2, the upload using s1 failed, and we are now trying s2.
// Supposedly s2-only registries do not exist or are extremely rare, so failing with this error message is good enough for now. // Supposedly s2-only registries do not exist or are extremely rare, so failing with this error message is good enough for now.
// If handling such registries turns out to be necessary, we could compute ic.diffIDsAreNeeded based on the full list of manifest MIME type candidates. // If handling such registries turns out to be necessary, we could compute ic.diffIDsAreNeeded based on the full list of manifest MIME type candidates.
return nil, errors.Errorf("Can not convert image to %s, preparing DiffIDs for this case is not supported", ic.manifestUpdates.ManifestMIMEType) return nil, errors.Errorf("Can not convert image to %s, preparing DiffIDs for this case is not supported", ic.manifestUpdates.ManifestMIMEType)
@ -396,27 +443,27 @@ func (ic *imageCopier) copyUpdatedConfigAndManifest() ([]byte, error) {
return nil, errors.Wrap(err, "Error reading manifest") return nil, errors.Wrap(err, "Error reading manifest")
} }
if err := ic.copyConfig(pendingImage); err != nil { if err := ic.c.copyConfig(pendingImage); err != nil {
return nil, err return nil, err
} }
fmt.Fprintf(ic.reportWriter, "Writing manifest to image destination\n") ic.c.Printf("Writing manifest to image destination\n")
if err := ic.dest.PutManifest(manifest); err != nil { if err := ic.c.dest.PutManifest(manifest); err != nil {
return nil, errors.Wrap(err, "Error writing manifest") return nil, errors.Wrap(err, "Error writing manifest")
} }
return manifest, nil return manifest, nil
} }
// copyConfig copies config.json, if any, from src to dest. // copyConfig copies config.json, if any, from src to dest.
func (ic *imageCopier) copyConfig(src types.Image) error { func (c *copier) copyConfig(src types.Image) error {
srcInfo := src.ConfigInfo() srcInfo := src.ConfigInfo()
if srcInfo.Digest != "" { if srcInfo.Digest != "" {
fmt.Fprintf(ic.reportWriter, "Copying config %s\n", srcInfo.Digest) c.Printf("Copying config %s\n", srcInfo.Digest)
configBlob, err := src.ConfigBlob() configBlob, err := src.ConfigBlob()
if err != nil { if err != nil {
return errors.Wrapf(err, "Error reading config blob %s", srcInfo.Digest) return errors.Wrapf(err, "Error reading config blob %s", srcInfo.Digest)
} }
destInfo, err := ic.copyBlobFromStream(bytes.NewReader(configBlob), srcInfo, nil, false) destInfo, err := c.copyBlobFromStream(bytes.NewReader(configBlob), srcInfo, nil, false)
if err != nil { if err != nil {
return err return err
} }
@ -438,12 +485,12 @@ type diffIDResult struct {
// and returns a complete blobInfo of the copied layer, and a value for LayerDiffIDs if diffIDIsNeeded // and returns a complete blobInfo of the copied layer, and a value for LayerDiffIDs if diffIDIsNeeded
func (ic *imageCopier) copyLayer(srcInfo types.BlobInfo) (types.BlobInfo, digest.Digest, error) { func (ic *imageCopier) copyLayer(srcInfo types.BlobInfo) (types.BlobInfo, digest.Digest, error) {
// Check if we already have a blob with this digest // Check if we already have a blob with this digest
haveBlob, extantBlobSize, err := ic.dest.HasBlob(srcInfo) haveBlob, extantBlobSize, err := ic.c.dest.HasBlob(srcInfo)
if err != nil { if err != nil {
return types.BlobInfo{}, "", errors.Wrapf(err, "Error checking for blob %s at destination", srcInfo.Digest) return types.BlobInfo{}, "", errors.Wrapf(err, "Error checking for blob %s at destination", srcInfo.Digest)
} }
// If we already have a cached diffID for this blob, we don't need to compute it // If we already have a cached diffID for this blob, we don't need to compute it
diffIDIsNeeded := ic.diffIDsAreNeeded && (ic.cachedDiffIDs[srcInfo.Digest] == "") diffIDIsNeeded := ic.diffIDsAreNeeded && (ic.c.cachedDiffIDs[srcInfo.Digest] == "")
// If we already have the blob, and we don't need to recompute the diffID, then we might be able to avoid reading it again // If we already have the blob, and we don't need to recompute the diffID, then we might be able to avoid reading it again
if haveBlob && !diffIDIsNeeded { if haveBlob && !diffIDIsNeeded {
// Check the blob sizes match, if we were given a size this time // Check the blob sizes match, if we were given a size this time
@ -452,17 +499,17 @@ func (ic *imageCopier) copyLayer(srcInfo types.BlobInfo) (types.BlobInfo, digest
} }
srcInfo.Size = extantBlobSize srcInfo.Size = extantBlobSize
// Tell the image destination that this blob's delta is being applied again. For some image destinations, this can be faster than using GetBlob/PutBlob // Tell the image destination that this blob's delta is being applied again. For some image destinations, this can be faster than using GetBlob/PutBlob
blobinfo, err := ic.dest.ReapplyBlob(srcInfo) blobinfo, err := ic.c.dest.ReapplyBlob(srcInfo)
if err != nil { if err != nil {
return types.BlobInfo{}, "", errors.Wrapf(err, "Error reapplying blob %s at destination", srcInfo.Digest) return types.BlobInfo{}, "", errors.Wrapf(err, "Error reapplying blob %s at destination", srcInfo.Digest)
} }
fmt.Fprintf(ic.reportWriter, "Skipping fetch of repeat blob %s\n", srcInfo.Digest) ic.c.Printf("Skipping fetch of repeat blob %s\n", srcInfo.Digest)
return blobinfo, ic.cachedDiffIDs[srcInfo.Digest], err return blobinfo, ic.c.cachedDiffIDs[srcInfo.Digest], err
} }
// Fallback: copy the layer, computing the diffID if we need to do so // Fallback: copy the layer, computing the diffID if we need to do so
fmt.Fprintf(ic.reportWriter, "Copying blob %s\n", srcInfo.Digest) ic.c.Printf("Copying blob %s\n", srcInfo.Digest)
srcStream, srcBlobSize, err := ic.rawSource.GetBlob(srcInfo) srcStream, srcBlobSize, err := ic.c.rawSource.GetBlob(srcInfo)
if err != nil { if err != nil {
return types.BlobInfo{}, "", errors.Wrapf(err, "Error reading blob %s", srcInfo.Digest) return types.BlobInfo{}, "", errors.Wrapf(err, "Error reading blob %s", srcInfo.Digest)
} }
@ -480,7 +527,7 @@ func (ic *imageCopier) copyLayer(srcInfo types.BlobInfo) (types.BlobInfo, digest
return types.BlobInfo{}, "", errors.Wrap(diffIDResult.err, "Error computing layer DiffID") return types.BlobInfo{}, "", errors.Wrap(diffIDResult.err, "Error computing layer DiffID")
} }
logrus.Debugf("Computed DiffID %s for layer %s", diffIDResult.digest, srcInfo.Digest) logrus.Debugf("Computed DiffID %s for layer %s", diffIDResult.digest, srcInfo.Digest)
ic.cachedDiffIDs[srcInfo.Digest] = diffIDResult.digest ic.c.cachedDiffIDs[srcInfo.Digest] = diffIDResult.digest
} }
return blobInfo, diffIDResult.digest, nil return blobInfo, diffIDResult.digest, nil
} }
@ -514,7 +561,7 @@ func (ic *imageCopier) copyLayerFromStream(srcStream io.Reader, srcInfo types.Bl
return pipeWriter return pipeWriter
} }
} }
blobInfo, err := ic.copyBlobFromStream(srcStream, srcInfo, getDiffIDRecorder, ic.canModifyManifest) // Sets err to nil on success blobInfo, err := ic.c.copyBlobFromStream(srcStream, srcInfo, getDiffIDRecorder, ic.canModifyManifest) // Sets err to nil on success
return blobInfo, diffIDChan, err return blobInfo, diffIDChan, err
// We need the defer … pipeWriter.CloseWithError() to happen HERE so that the caller can block on reading from diffIDChan // We need the defer … pipeWriter.CloseWithError() to happen HERE so that the caller can block on reading from diffIDChan
} }
@ -548,7 +595,7 @@ func computeDiffID(stream io.Reader, decompressor compression.DecompressorFunc)
// perhaps sending a copy to an io.Writer if getOriginalLayerCopyWriter != nil, // perhaps sending a copy to an io.Writer if getOriginalLayerCopyWriter != nil,
// perhaps compressing it if canCompress, // perhaps compressing it if canCompress,
// and returns a complete blobInfo of the copied blob. // and returns a complete blobInfo of the copied blob.
func (ic *imageCopier) copyBlobFromStream(srcStream io.Reader, srcInfo types.BlobInfo, func (c *copier) copyBlobFromStream(srcStream io.Reader, srcInfo types.BlobInfo,
getOriginalLayerCopyWriter func(decompressor compression.DecompressorFunc) io.Writer, getOriginalLayerCopyWriter func(decompressor compression.DecompressorFunc) io.Writer,
canCompress bool) (types.BlobInfo, error) { canCompress bool) (types.BlobInfo, error) {
// The copying happens through a pipeline of connected io.Readers. // The copying happens through a pipeline of connected io.Readers.
@ -576,7 +623,7 @@ func (ic *imageCopier) copyBlobFromStream(srcStream io.Reader, srcInfo types.Blo
// === Report progress using a pb.Reader. // === Report progress using a pb.Reader.
bar := pb.New(int(srcInfo.Size)).SetUnits(pb.U_BYTES) bar := pb.New(int(srcInfo.Size)).SetUnits(pb.U_BYTES)
bar.Output = ic.reportWriter bar.Output = c.reportWriter
bar.SetMaxWidth(80) bar.SetMaxWidth(80)
bar.ShowTimeLeft = false bar.ShowTimeLeft = false
bar.ShowPercent = false bar.ShowPercent = false
@ -593,7 +640,7 @@ func (ic *imageCopier) copyBlobFromStream(srcStream io.Reader, srcInfo types.Blo
// === Compress the layer if it is uncompressed and compression is desired // === Compress the layer if it is uncompressed and compression is desired
var inputInfo types.BlobInfo var inputInfo types.BlobInfo
if !canCompress || isCompressed || !ic.dest.ShouldCompressLayers() { if !canCompress || isCompressed || !c.dest.ShouldCompressLayers() {
logrus.Debugf("Using original blob without modification") logrus.Debugf("Using original blob without modification")
inputInfo = srcInfo inputInfo = srcInfo
} else { } else {
@ -610,19 +657,19 @@ func (ic *imageCopier) copyBlobFromStream(srcStream io.Reader, srcInfo types.Blo
inputInfo.Size = -1 inputInfo.Size = -1
} }
// === Report progress using the ic.progress channel, if required. // === Report progress using the c.progress channel, if required.
if ic.progress != nil && ic.progressInterval > 0 { if c.progress != nil && c.progressInterval > 0 {
destStream = &progressReader{ destStream = &progressReader{
source: destStream, source: destStream,
channel: ic.progress, channel: c.progress,
interval: ic.progressInterval, interval: c.progressInterval,
artifact: srcInfo, artifact: srcInfo,
lastTime: time.Now(), lastTime: time.Now(),
} }
} }
// === Finally, send the layer stream to dest. // === Finally, send the layer stream to dest.
uploadedInfo, err := ic.dest.PutBlob(destStream, inputInfo) uploadedInfo, err := c.dest.PutBlob(destStream, inputInfo)
if err != nil { if err != nil {
return types.BlobInfo{}, errors.Wrap(err, "Error writing blob") return types.BlobInfo{}, errors.Wrap(err, "Error writing blob")
} }

View File

@ -37,12 +37,12 @@ func (os *orderedSet) append(s string) {
} }
} }
// determineManifestConversion updates manifestUpdates to convert manifest to a supported MIME type, if necessary and canModifyManifest. // determineManifestConversion updates ic.manifestUpdates to convert manifest to a supported MIME type, if necessary and ic.canModifyManifest.
// Note that the conversion will only happen later, through src.UpdatedImage // Note that the conversion will only happen later, through ic.src.UpdatedImage
// Returns the preferred manifest MIME type (whether we are converting to it or using it unmodified), // Returns the preferred manifest MIME type (whether we are converting to it or using it unmodified),
// and a list of other possible alternatives, in order. // and a list of other possible alternatives, in order.
func determineManifestConversion(manifestUpdates *types.ManifestUpdateOptions, src types.Image, destSupportedManifestMIMETypes []string, canModifyManifest bool, forceManifestMIMEType string) (string, []string, error) { func (ic *imageCopier) determineManifestConversion(destSupportedManifestMIMETypes []string, forceManifestMIMEType string) (string, []string, error) {
_, srcType, err := src.Manifest() _, srcType, err := ic.src.Manifest()
if err != nil { // This should have been cached?! if err != nil { // This should have been cached?!
return "", nil, errors.Wrap(err, "Error reading manifest") return "", nil, errors.Wrap(err, "Error reading manifest")
} }
@ -71,10 +71,10 @@ func determineManifestConversion(manifestUpdates *types.ManifestUpdateOptions, s
if _, ok := supportedByDest[srcType]; ok { if _, ok := supportedByDest[srcType]; ok {
prioritizedTypes.append(srcType) prioritizedTypes.append(srcType)
} }
if !canModifyManifest { if !ic.canModifyManifest {
// We could also drop the !canModifyManifest parameter and have the caller // We could also drop the !ic.canModifyManifest check and have the caller
// make the choice; it is already doing that to an extent, to improve error // make the choice; it is already doing that to an extent, to improve error
// messages. But it is nice to hide the “if !canModifyManifest, do no conversion” // messages. But it is nice to hide the “if !ic.canModifyManifest, do no conversion”
// special case in here; the caller can then worry (or not) only about a good UI. // special case in here; the caller can then worry (or not) only about a good UI.
logrus.Debugf("We can't modify the manifest, hoping for the best...") logrus.Debugf("We can't modify the manifest, hoping for the best...")
return srcType, []string{}, nil // Take our chances - FIXME? Or should we fail without trying? return srcType, []string{}, nil // Take our chances - FIXME? Or should we fail without trying?
@ -98,9 +98,18 @@ func determineManifestConversion(manifestUpdates *types.ManifestUpdateOptions, s
} }
preferredType := prioritizedTypes.list[0] preferredType := prioritizedTypes.list[0]
if preferredType != srcType { if preferredType != srcType {
manifestUpdates.ManifestMIMEType = preferredType ic.manifestUpdates.ManifestMIMEType = preferredType
} else { } else {
logrus.Debugf("... will first try using the original manifest unmodified") logrus.Debugf("... will first try using the original manifest unmodified")
} }
return preferredType, prioritizedTypes.list[1:], nil return preferredType, prioritizedTypes.list[1:], nil
} }
// isMultiImage returns true if img is a list of images
func isMultiImage(img types.UnparsedImage) (bool, error) {
_, mt, err := img.Manifest()
if err != nil {
return false, err
}
return manifest.MIMETypeIsMultiImage(mt), nil
}

View File

@ -1,17 +1,13 @@
package copy package copy
import ( import (
"fmt"
"io"
"github.com/containers/image/signature" "github.com/containers/image/signature"
"github.com/containers/image/transports" "github.com/containers/image/transports"
"github.com/containers/image/types"
"github.com/pkg/errors" "github.com/pkg/errors"
) )
// createSignature creates a new signature of manifest at (identified by) dest using keyIdentity. // createSignature creates a new signature of manifest using keyIdentity.
func createSignature(dest types.ImageDestination, manifest []byte, keyIdentity string, reportWriter io.Writer) ([]byte, error) { func (c *copier) createSignature(manifest []byte, keyIdentity string) ([]byte, error) {
mech, err := signature.NewGPGSigningMechanism() mech, err := signature.NewGPGSigningMechanism()
if err != nil { if err != nil {
return nil, errors.Wrap(err, "Error initializing GPG") return nil, errors.Wrap(err, "Error initializing GPG")
@ -21,12 +17,12 @@ func createSignature(dest types.ImageDestination, manifest []byte, keyIdentity s
return nil, errors.Wrap(err, "Signing not supported") return nil, errors.Wrap(err, "Signing not supported")
} }
dockerReference := dest.Reference().DockerReference() dockerReference := c.dest.Reference().DockerReference()
if dockerReference == nil { if dockerReference == nil {
return nil, errors.Errorf("Cannot determine canonical Docker reference for destination %s", transports.ImageName(dest.Reference())) return nil, errors.Errorf("Cannot determine canonical Docker reference for destination %s", transports.ImageName(c.dest.Reference()))
} }
fmt.Fprintf(reportWriter, "Signing manifest\n") c.Printf("Signing manifest\n")
newSig, err := signature.SignDockerManifest(manifest, dockerReference.String(), mech, keyIdentity) newSig, err := signature.SignDockerManifest(manifest, dockerReference.String(), mech, keyIdentity)
if err != nil { if err != nil {
return nil, errors.Wrap(err, "Error creating signature") return nil, errors.Wrap(err, "Error creating signature")

View File

@ -35,7 +35,12 @@ func (s *dirImageSource) Close() error {
// GetManifest returns the image's manifest along with its MIME type (which may be empty when it can't be determined but the manifest is available). // GetManifest returns the image's manifest along with its MIME type (which may be empty when it can't be determined but the manifest is available).
// It may use a remote (= slow) service. // It may use a remote (= slow) service.
func (s *dirImageSource) GetManifest() ([]byte, string, error) { // If instanceDigest is not nil, it contains a digest of the specific manifest instance to retrieve (when the primary manifest is a manifest list);
// this never happens if the primary manifest is not a manifest list (e.g. if the source never returns manifest lists).
func (s *dirImageSource) GetManifest(instanceDigest *digest.Digest) ([]byte, string, error) {
if instanceDigest != nil {
return nil, "", errors.Errorf(`Getting target manifest not supported by "dir:"`)
}
m, err := ioutil.ReadFile(s.ref.manifestPath()) m, err := ioutil.ReadFile(s.ref.manifestPath())
if err != nil { if err != nil {
return nil, "", err return nil, "", err
@ -43,10 +48,6 @@ func (s *dirImageSource) GetManifest() ([]byte, string, error) {
return m, manifest.GuessMIMEType(m), err return m, manifest.GuessMIMEType(m), err
} }
func (s *dirImageSource) GetTargetManifest(digest digest.Digest) ([]byte, string, error) {
return nil, "", errors.Errorf(`Getting target manifest not supported by "dir:"`)
}
// GetBlob returns a stream for the specified blob, and the blobs size (or -1 if unknown). // GetBlob returns a stream for the specified blob, and the blobs size (or -1 if unknown).
func (s *dirImageSource) GetBlob(info types.BlobInfo) (io.ReadCloser, int64, error) { func (s *dirImageSource) GetBlob(info types.BlobInfo) (io.ReadCloser, int64, error) {
r, err := os.Open(s.ref.layerPath(info.Digest)) r, err := os.Open(s.ref.layerPath(info.Digest))
@ -60,7 +61,14 @@ func (s *dirImageSource) GetBlob(info types.BlobInfo) (io.ReadCloser, int64, err
return r, fi.Size(), nil return r, fi.Size(), nil
} }
func (s *dirImageSource) GetSignatures(ctx context.Context) ([][]byte, error) { // GetSignatures returns the image's signatures. It may use a remote (= slow) service.
// If instanceDigest is not nil, it contains a digest of the specific manifest instance to retrieve signatures for
// (when the primary manifest is a manifest list); this never happens if the primary manifest is not a manifest list
// (e.g. if the source never returns manifest lists).
func (s *dirImageSource) GetSignatures(ctx context.Context, instanceDigest *digest.Digest) ([][]byte, error) {
if instanceDigest != nil {
return nil, errors.Errorf(`Manifests lists are not supported by "dir:"`)
}
signatures := [][]byte{} signatures := [][]byte{}
for i := 0; ; i++ { for i := 0; ; i++ {
signature, err := ioutil.ReadFile(s.ref.signaturePath(i)) signature, err := ioutil.ReadFile(s.ref.signaturePath(i))

View File

@ -134,13 +134,14 @@ func (ref dirReference) PolicyConfigurationNamespaces() []string {
return res return res
} }
// NewImage returns a types.Image for this reference, possibly specialized for this ImageTransport. // NewImage returns a types.ImageCloser for this reference, possibly specialized for this ImageTransport.
// The caller must call .Close() on the returned Image. // The caller must call .Close() on the returned ImageCloser.
// NOTE: If any kind of signature verification should happen, build an UnparsedImage from the value returned by NewImageSource, // NOTE: If any kind of signature verification should happen, build an UnparsedImage from the value returned by NewImageSource,
// verify that UnparsedImage, and convert it into a real Image via image.FromUnparsedImage. // verify that UnparsedImage, and convert it into a real Image via image.FromUnparsedImage.
func (ref dirReference) NewImage(ctx *types.SystemContext) (types.Image, error) { // WARNING: This may not do the right thing for a manifest list, see image.FromSource for details.
func (ref dirReference) NewImage(ctx *types.SystemContext) (types.ImageCloser, error) {
src := newImageSource(ref) src := newImageSource(ref)
return image.FromSource(src) return image.FromSource(ctx, src)
} }
// NewImageSource returns a types.ImageSource for this reference. // NewImageSource returns a types.ImageSource for this reference.

View File

@ -125,13 +125,14 @@ func (ref archiveReference) PolicyConfigurationNamespaces() []string {
return []string{} return []string{}
} }
// NewImage returns a types.Image for this reference, possibly specialized for this ImageTransport. // NewImage returns a types.ImageCloser for this reference, possibly specialized for this ImageTransport.
// The caller must call .Close() on the returned Image. // The caller must call .Close() on the returned ImageCloser.
// NOTE: If any kind of signature verification should happen, build an UnparsedImage from the value returned by NewImageSource, // NOTE: If any kind of signature verification should happen, build an UnparsedImage from the value returned by NewImageSource,
// verify that UnparsedImage, and convert it into a real Image via image.FromUnparsedImage. // verify that UnparsedImage, and convert it into a real Image via image.FromUnparsedImage.
func (ref archiveReference) NewImage(ctx *types.SystemContext) (types.Image, error) { // WARNING: This may not do the right thing for a manifest list, see image.FromSource for details.
func (ref archiveReference) NewImage(ctx *types.SystemContext) (types.ImageCloser, error) {
src := newImageSource(ctx, ref) src := newImageSource(ctx, ref)
return ctrImage.FromSource(src) return ctrImage.FromSource(ctx, src)
} }
// NewImageSource returns a types.ImageSource for this reference. // NewImageSource returns a types.ImageSource for this reference.

View File

@ -151,14 +151,17 @@ func (ref daemonReference) PolicyConfigurationNamespaces() []string {
return []string{} return []string{}
} }
// NewImage returns a types.Image for this reference. // NewImage returns a types.ImageCloser for this reference, possibly specialized for this ImageTransport.
// The caller must call .Close() on the returned Image. // The caller must call .Close() on the returned ImageCloser.
func (ref daemonReference) NewImage(ctx *types.SystemContext) (types.Image, error) { // NOTE: If any kind of signature verification should happen, build an UnparsedImage from the value returned by NewImageSource,
// verify that UnparsedImage, and convert it into a real Image via image.FromUnparsedImage.
// WARNING: This may not do the right thing for a manifest list, see image.FromSource for details.
func (ref daemonReference) NewImage(ctx *types.SystemContext) (types.ImageCloser, error) {
src, err := newImageSource(ctx, ref) src, err := newImageSource(ctx, ref)
if err != nil { if err != nil {
return nil, err return nil, err
} }
return image.FromSource(src) return image.FromSource(ctx, src)
} }
// NewImageSource returns a types.ImageSource for this reference. // NewImageSource returns a types.ImageSource for this reference.

View File

@ -12,26 +12,26 @@ import (
"github.com/pkg/errors" "github.com/pkg/errors"
) )
// Image is a Docker-specific implementation of types.Image with a few extra methods // Image is a Docker-specific implementation of types.ImageCloser with a few extra methods
// which are specific to Docker. // which are specific to Docker.
type Image struct { type Image struct {
types.Image types.ImageCloser
src *dockerImageSource src *dockerImageSource
} }
// newImage returns a new Image interface type after setting up // newImage returns a new Image interface type after setting up
// a client to the registry hosting the given image. // a client to the registry hosting the given image.
// The caller must call .Close() on the returned Image. // The caller must call .Close() on the returned Image.
func newImage(ctx *types.SystemContext, ref dockerReference) (types.Image, error) { func newImage(ctx *types.SystemContext, ref dockerReference) (types.ImageCloser, error) {
s, err := newImageSource(ctx, ref) s, err := newImageSource(ctx, ref)
if err != nil { if err != nil {
return nil, err return nil, err
} }
img, err := image.FromSource(s) img, err := image.FromSource(ctx, s)
if err != nil { if err != nil {
return nil, err return nil, err
} }
return &Image{Image: img, src: s}, nil return &Image{ImageCloser: img, src: s}, nil
} }
// SourceRefFullName returns a fully expanded name for the repository this image is in. // SourceRefFullName returns a fully expanded name for the repository this image is in.

View File

@ -67,7 +67,12 @@ func simplifyContentType(contentType string) string {
// GetManifest returns the image's manifest along with its MIME type (which may be empty when it can't be determined but the manifest is available). // GetManifest returns the image's manifest along with its MIME type (which may be empty when it can't be determined but the manifest is available).
// It may use a remote (= slow) service. // It may use a remote (= slow) service.
func (s *dockerImageSource) GetManifest() ([]byte, string, error) { // If instanceDigest is not nil, it contains a digest of the specific manifest instance to retrieve (when the primary manifest is a manifest list);
// this never happens if the primary manifest is not a manifest list (e.g. if the source never returns manifest lists).
func (s *dockerImageSource) GetManifest(instanceDigest *digest.Digest) ([]byte, string, error) {
if instanceDigest != nil {
return s.fetchManifest(context.TODO(), instanceDigest.String())
}
err := s.ensureManifestIsLoaded(context.TODO()) err := s.ensureManifestIsLoaded(context.TODO())
if err != nil { if err != nil {
return nil, "", err return nil, "", err
@ -94,18 +99,12 @@ func (s *dockerImageSource) fetchManifest(ctx context.Context, tagOrDigest strin
return manblob, simplifyContentType(res.Header.Get("Content-Type")), nil return manblob, simplifyContentType(res.Header.Get("Content-Type")), nil
} }
// GetTargetManifest returns an image's manifest given a digest.
// This is mainly used to retrieve a single image's manifest out of a manifest list.
func (s *dockerImageSource) GetTargetManifest(digest digest.Digest) ([]byte, string, error) {
return s.fetchManifest(context.TODO(), digest.String())
}
// ensureManifestIsLoaded sets s.cachedManifest and s.cachedManifestMIMEType // ensureManifestIsLoaded sets s.cachedManifest and s.cachedManifestMIMEType
// //
// ImageSource implementations are not required or expected to do any caching, // ImageSource implementations are not required or expected to do any caching,
// but because our signatures are “attached” to the manifest digest, // but because our signatures are “attached” to the manifest digest,
// we need to ensure that the digest of the manifest returned by GetManifest // we need to ensure that the digest of the manifest returned by GetManifest(nil)
// and used by GetSignatures are consistent, otherwise we would get spurious // and used by GetSignatures(ctx, nil) are consistent, otherwise we would get spurious
// signature verification failures when pulling while a tag is being updated. // signature verification failures when pulling while a tag is being updated.
func (s *dockerImageSource) ensureManifestIsLoaded(ctx context.Context) error { func (s *dockerImageSource) ensureManifestIsLoaded(ctx context.Context) error {
if s.cachedManifest != nil { if s.cachedManifest != nil {
@ -176,22 +175,30 @@ func (s *dockerImageSource) GetBlob(info types.BlobInfo) (io.ReadCloser, int64,
return res.Body, getBlobSize(res), nil return res.Body, getBlobSize(res), nil
} }
func (s *dockerImageSource) GetSignatures(ctx context.Context) ([][]byte, error) { // GetSignatures returns the image's signatures. It may use a remote (= slow) service.
// If instanceDigest is not nil, it contains a digest of the specific manifest instance to retrieve signatures for
// (when the primary manifest is a manifest list); this never happens if the primary manifest is not a manifest list
// (e.g. if the source never returns manifest lists).
func (s *dockerImageSource) GetSignatures(ctx context.Context, instanceDigest *digest.Digest) ([][]byte, error) {
if err := s.c.detectProperties(ctx); err != nil { if err := s.c.detectProperties(ctx); err != nil {
return nil, err return nil, err
} }
switch { switch {
case s.c.signatureBase != nil: case s.c.signatureBase != nil:
return s.getSignaturesFromLookaside(ctx) return s.getSignaturesFromLookaside(ctx, instanceDigest)
case s.c.supportsSignatures: case s.c.supportsSignatures:
return s.getSignaturesFromAPIExtension(ctx) return s.getSignaturesFromAPIExtension(ctx, instanceDigest)
default: default:
return [][]byte{}, nil return [][]byte{}, nil
} }
} }
// manifestDigest returns a digest of the manifest, either from the supplied reference or from a fetched manifest. // manifestDigest returns a digest of the manifest, from instanceDigest if non-nil; or from the supplied reference,
func (s *dockerImageSource) manifestDigest(ctx context.Context) (digest.Digest, error) { // or finally, from a fetched manifest.
func (s *dockerImageSource) manifestDigest(ctx context.Context, instanceDigest *digest.Digest) (digest.Digest, error) {
if instanceDigest != nil {
return *instanceDigest, nil
}
if digested, ok := s.ref.ref.(reference.Digested); ok { if digested, ok := s.ref.ref.(reference.Digested); ok {
d := digested.Digest() d := digested.Digest()
if d.Algorithm() == digest.Canonical { if d.Algorithm() == digest.Canonical {
@ -206,8 +213,8 @@ func (s *dockerImageSource) manifestDigest(ctx context.Context) (digest.Digest,
// getSignaturesFromLookaside implements GetSignatures() from the lookaside location configured in s.c.signatureBase, // getSignaturesFromLookaside implements GetSignatures() from the lookaside location configured in s.c.signatureBase,
// which is not nil. // which is not nil.
func (s *dockerImageSource) getSignaturesFromLookaside(ctx context.Context) ([][]byte, error) { func (s *dockerImageSource) getSignaturesFromLookaside(ctx context.Context, instanceDigest *digest.Digest) ([][]byte, error) {
manifestDigest, err := s.manifestDigest(ctx) manifestDigest, err := s.manifestDigest(ctx, instanceDigest)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -276,8 +283,8 @@ func (s *dockerImageSource) getOneSignature(ctx context.Context, url *url.URL) (
} }
// getSignaturesFromAPIExtension implements GetSignatures() using the X-Registry-Supports-Signatures API extension. // getSignaturesFromAPIExtension implements GetSignatures() using the X-Registry-Supports-Signatures API extension.
func (s *dockerImageSource) getSignaturesFromAPIExtension(ctx context.Context) ([][]byte, error) { func (s *dockerImageSource) getSignaturesFromAPIExtension(ctx context.Context, instanceDigest *digest.Digest) ([][]byte, error) {
manifestDigest, err := s.manifestDigest(ctx) manifestDigest, err := s.manifestDigest(ctx, instanceDigest)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@ -122,11 +122,12 @@ func (ref dockerReference) PolicyConfigurationNamespaces() []string {
return policyconfiguration.DockerReferenceNamespaces(ref.ref) return policyconfiguration.DockerReferenceNamespaces(ref.ref)
} }
// NewImage returns a types.Image for this reference, possibly specialized for this ImageTransport. // NewImage returns a types.ImageCloser for this reference, possibly specialized for this ImageTransport.
// The caller must call .Close() on the returned Image. // The caller must call .Close() on the returned ImageCloser.
// NOTE: If any kind of signature verification should happen, build an UnparsedImage from the value returned by NewImageSource, // NOTE: If any kind of signature verification should happen, build an UnparsedImage from the value returned by NewImageSource,
// verify that UnparsedImage, and convert it into a real Image via image.FromUnparsedImage. // verify that UnparsedImage, and convert it into a real Image via image.FromUnparsedImage.
func (ref dockerReference) NewImage(ctx *types.SystemContext) (types.Image, error) { // WARNING: This may not do the right thing for a manifest list, see image.FromSource for details.
func (ref dockerReference) NewImage(ctx *types.SystemContext) (types.ImageCloser, error) {
return newImage(ctx, ref) return newImage(ctx, ref)
} }

View File

@ -249,7 +249,13 @@ func (s *Source) prepareLayerData(tarManifest *ManifestItem, parsedConfig *image
// GetManifest returns the image's manifest along with its MIME type (which may be empty when it can't be determined but the manifest is available). // GetManifest returns the image's manifest along with its MIME type (which may be empty when it can't be determined but the manifest is available).
// It may use a remote (= slow) service. // It may use a remote (= slow) service.
func (s *Source) GetManifest() ([]byte, string, error) { // If instanceDigest is not nil, it contains a digest of the specific manifest instance to retrieve (when the primary manifest is a manifest list);
// this never happens if the primary manifest is not a manifest list (e.g. if the source never returns manifest lists).
func (s *Source) GetManifest(instanceDigest *digest.Digest) ([]byte, string, error) {
if instanceDigest != nil {
// How did we even get here? GetManifest(nil) has returned a manifest.DockerV2Schema2MediaType.
return nil, "", errors.Errorf(`Manifest lists are not supported by "docker-daemon:"`)
}
if s.generatedManifest == nil { if s.generatedManifest == nil {
if err := s.ensureCachedDataIsPresent(); err != nil { if err := s.ensureCachedDataIsPresent(); err != nil {
return nil, "", err return nil, "", err
@ -284,13 +290,6 @@ func (s *Source) GetManifest() ([]byte, string, error) {
return s.generatedManifest, manifest.DockerV2Schema2MediaType, nil return s.generatedManifest, manifest.DockerV2Schema2MediaType, nil
} }
// GetTargetManifest returns an image's manifest given a digest. This is mainly used to retrieve a single image's manifest
// out of a manifest list.
func (s *Source) GetTargetManifest(digest digest.Digest) ([]byte, string, error) {
// How did we even get here? GetManifest() above has returned a manifest.DockerV2Schema2MediaType.
return nil, "", errors.Errorf(`Manifest lists are not supported by "docker-daemon:"`)
}
type readCloseWrapper struct { type readCloseWrapper struct {
io.Reader io.Reader
closeFunc func() error closeFunc func() error
@ -355,6 +354,13 @@ func (s *Source) GetBlob(info types.BlobInfo) (io.ReadCloser, int64, error) {
} }
// GetSignatures returns the image's signatures. It may use a remote (= slow) service. // GetSignatures returns the image's signatures. It may use a remote (= slow) service.
func (s *Source) GetSignatures(ctx context.Context) ([][]byte, error) { // If instanceDigest is not nil, it contains a digest of the specific manifest instance to retrieve signatures for
// (when the primary manifest is a manifest list); this never happens if the primary manifest is not a manifest list
// (e.g. if the source never returns manifest lists).
func (s *Source) GetSignatures(ctx context.Context, instanceDigest *digest.Digest) ([][]byte, error) {
if instanceDigest != nil {
// How did we even get here? GetManifest(nil) has returned a manifest.DockerV2Schema2MediaType.
return nil, errors.Errorf(`Manifest lists are not supported by "docker-daemon:"`)
}
return [][]byte{}, nil return [][]byte{}, nil
} }

View File

@ -2,6 +2,7 @@ package image
import ( import (
"encoding/json" "encoding/json"
"fmt"
"runtime" "runtime"
"github.com/containers/image/manifest" "github.com/containers/image/manifest"
@ -31,22 +32,36 @@ type manifestList struct {
Manifests []manifestDescriptor `json:"manifests"` Manifests []manifestDescriptor `json:"manifests"`
} }
func manifestSchema2FromManifestList(src types.ImageSource, manblob []byte) (genericManifest, error) { // chooseDigestFromManifestList parses blob as a schema2 manifest list,
list := manifestList{} // and returns the digest of the image appropriate for the current environment.
if err := json.Unmarshal(manblob, &list); err != nil { func chooseDigestFromManifestList(ctx *types.SystemContext, blob []byte) (digest.Digest, error) {
return nil, err wantedArch := runtime.GOARCH
if ctx != nil && ctx.ArchitectureChoice != "" {
wantedArch = ctx.ArchitectureChoice
}
wantedOS := runtime.GOOS
if ctx != nil && ctx.OSChoice != "" {
wantedOS = ctx.OSChoice
}
list := manifestList{}
if err := json.Unmarshal(blob, &list); err != nil {
return "", err
} }
var targetManifestDigest digest.Digest
for _, d := range list.Manifests { for _, d := range list.Manifests {
if d.Platform.Architecture == runtime.GOARCH && d.Platform.OS == runtime.GOOS { if d.Platform.Architecture == wantedArch && d.Platform.OS == wantedOS {
targetManifestDigest = d.Digest return d.Digest, nil
break
} }
} }
if targetManifestDigest == "" { return "", fmt.Errorf("no image found in manifest list for architecture %s, OS %s", wantedArch, wantedOS)
return nil, errors.New("no supported platform found in manifest list") }
func manifestSchema2FromManifestList(ctx *types.SystemContext, src types.ImageSource, manblob []byte) (genericManifest, error) {
targetManifestDigest, err := chooseDigestFromManifestList(ctx, manblob)
if err != nil {
return nil, err
} }
manblob, mt, err := src.GetTargetManifest(targetManifestDigest) manblob, mt, err := src.GetManifest(&targetManifestDigest)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -59,5 +74,20 @@ func manifestSchema2FromManifestList(src types.ImageSource, manblob []byte) (gen
return nil, errors.Errorf("Manifest image does not match selected manifest digest %s", targetManifestDigest) return nil, errors.Errorf("Manifest image does not match selected manifest digest %s", targetManifestDigest)
} }
return manifestInstanceFromBlob(src, manblob, mt) return manifestInstanceFromBlob(ctx, src, manblob, mt)
}
// ChooseManifestInstanceFromManifestList returns a digest of a manifest appropriate
// for the current system from the manifest available from src.
func ChooseManifestInstanceFromManifestList(ctx *types.SystemContext, src types.UnparsedImage) (digest.Digest, error) {
// For now this only handles manifest.DockerV2ListMediaType; we can generalize it later,
// probably along with manifest list editing.
blob, mt, err := src.Manifest()
if err != nil {
return "", err
}
if mt != manifest.DockerV2ListMediaType {
return "", fmt.Errorf("Internal error: Trying to select an image from a non-manifest-list manifest type %s", mt)
}
return chooseDigestFromManifestList(ctx, blob)
} }

View File

@ -212,7 +212,21 @@ func (m *manifestSchema1) UpdatedImage(options types.ManifestUpdateOptions) (typ
// We have 2 MIME types for schema 1, which are basically equivalent (even the un-"Signed" MIME type will be rejected if there isnt a signature; so, // We have 2 MIME types for schema 1, which are basically equivalent (even the un-"Signed" MIME type will be rejected if there isnt a signature; so,
// handle conversions between them by doing nothing. // handle conversions between them by doing nothing.
case manifest.DockerV2Schema2MediaType: case manifest.DockerV2Schema2MediaType:
return copy.convertToManifestSchema2(options.InformationOnly.LayerInfos, options.InformationOnly.LayerDiffIDs) m2, err := copy.convertToManifestSchema2(options.InformationOnly.LayerInfos, options.InformationOnly.LayerDiffIDs)
if err != nil {
return nil, err
}
return memoryImageFromManifest(m2), nil
case imgspecv1.MediaTypeImageManifest:
// We can't directly convert to OCI, but we can transitively convert via a Docker V2.2 Distribution manifest
m2, err := copy.convertToManifestSchema2(options.InformationOnly.LayerInfos, options.InformationOnly.LayerDiffIDs)
if err != nil {
return nil, err
}
return m2.UpdatedImage(types.ManifestUpdateOptions{
ManifestMIMEType: imgspecv1.MediaTypeImageManifest,
InformationOnly: options.InformationOnly,
})
default: default:
return nil, errors.Errorf("Conversion of image manifest from %s to %s is not implemented", manifest.DockerV2Schema1SignedMediaType, options.ManifestMIMEType) return nil, errors.Errorf("Conversion of image manifest from %s to %s is not implemented", manifest.DockerV2Schema1SignedMediaType, options.ManifestMIMEType)
} }
@ -279,7 +293,7 @@ func validateV1ID(id string) error {
} }
// Based on github.com/docker/docker/distribution/pull_v2.go // Based on github.com/docker/docker/distribution/pull_v2.go
func (m *manifestSchema1) convertToManifestSchema2(uploadedLayerInfos []types.BlobInfo, layerDiffIDs []digest.Digest) (types.Image, error) { func (m *manifestSchema1) convertToManifestSchema2(uploadedLayerInfos []types.BlobInfo, layerDiffIDs []digest.Digest) (genericManifest, error) {
if len(m.History) == 0 { if len(m.History) == 0 {
// What would this even mean?! Anyhow, the rest of the code depends on fsLayers[0] and history[0] existing. // What would this even mean?! Anyhow, the rest of the code depends on fsLayers[0] and history[0] existing.
return nil, errors.Errorf("Cannot convert an image with 0 history entries to %s", manifest.DockerV2Schema2MediaType) return nil, errors.Errorf("Cannot convert an image with 0 history entries to %s", manifest.DockerV2Schema2MediaType)
@ -343,8 +357,7 @@ func (m *manifestSchema1) convertToManifestSchema2(uploadedLayerInfos []types.Bl
Digest: digest.FromBytes(configJSON), Digest: digest.FromBytes(configJSON),
} }
m2 := manifestSchema2FromComponents(configDescriptor, nil, configJSON, layers) return manifestSchema2FromComponents(configDescriptor, nil, configJSON, layers), nil
return memoryImageFromManifest(m2), nil
} }
func configJSONFromV1Config(v1ConfigJSON []byte, rootFS rootFS, history []imageHistory) ([]byte, error) { func configJSONFromV1Config(v1ConfigJSON []byte, rootFS rootFS, history []imageHistory) ([]byte, error) {

View File

@ -87,7 +87,9 @@ type genericManifest interface {
UpdatedImage(options types.ManifestUpdateOptions) (types.Image, error) UpdatedImage(options types.ManifestUpdateOptions) (types.Image, error)
} }
func manifestInstanceFromBlob(src types.ImageSource, manblob []byte, mt string) (genericManifest, error) { // manifestInstanceFromBlob returns a genericManifest implementation for (manblob, mt) in src.
// If manblob is a manifest list, it implicitly chooses an appropriate image from the list.
func manifestInstanceFromBlob(ctx *types.SystemContext, src types.ImageSource, manblob []byte, mt string) (genericManifest, error) {
switch mt { switch mt {
// "application/json" is a valid v2s1 value per https://github.com/docker/distribution/blob/master/docs/spec/manifest-v2-1.md . // "application/json" is a valid v2s1 value per https://github.com/docker/distribution/blob/master/docs/spec/manifest-v2-1.md .
// This works for now, when nothing else seems to return "application/json"; if that were not true, the mapping/detection might // This works for now, when nothing else seems to return "application/json"; if that were not true, the mapping/detection might
@ -99,7 +101,7 @@ func manifestInstanceFromBlob(src types.ImageSource, manblob []byte, mt string)
case manifest.DockerV2Schema2MediaType: case manifest.DockerV2Schema2MediaType:
return manifestSchema2FromManifest(src, manblob) return manifestSchema2FromManifest(src, manblob)
case manifest.DockerV2ListMediaType: case manifest.DockerV2ListMediaType:
return manifestSchema2FromManifestList(src, manblob) return manifestSchema2FromManifestList(ctx, src, manblob)
default: default:
// If it's not a recognized manifest media type, or we have failed determining the type, we'll try one last time // If it's not a recognized manifest media type, or we have failed determining the type, we'll try one last time
// to deserialize using v2s1 as per https://github.com/docker/distribution/blob/master/manifests.go#L108 // to deserialize using v2s1 as per https://github.com/docker/distribution/blob/master/manifests.go#L108

View File

@ -33,11 +33,6 @@ func (i *memoryImage) Reference() types.ImageReference {
return nil return nil
} }
// Close removes resources associated with an initialized UnparsedImage, if any.
func (i *memoryImage) Close() error {
return nil
}
// Size returns the size of the image as stored, if known, or -1 if not. // Size returns the size of the image as stored, if known, or -1 if not.
func (i *memoryImage) Size() (int64, error) { func (i *memoryImage) Size() (int64, error) {
return -1, nil return -1, nil
@ -66,8 +61,3 @@ func (i *memoryImage) Signatures(ctx context.Context) ([][]byte, error) {
func (i *memoryImage) Inspect() (*types.ImageInspectInfo, error) { func (i *memoryImage) Inspect() (*types.ImageInspectInfo, error) {
return inspectManifest(i.genericManifest) return inspectManifest(i.genericManifest)
} }
// IsMultiImage returns true if the image's manifest is a list of images, false otherwise.
func (i *memoryImage) IsMultiImage() bool {
return false
}

View File

@ -4,12 +4,22 @@
package image package image
import ( import (
"github.com/containers/image/manifest"
"github.com/containers/image/types" "github.com/containers/image/types"
) )
// FromSource returns a types.Image implementation for source. // imageCloser implements types.ImageCloser, perhaps allowing simple users
// The caller must call .Close() on the returned Image. // to use a single object without having keep a reference to a types.ImageSource
// only to call types.ImageSource.Close().
type imageCloser struct {
types.Image
src types.ImageSource
}
// FromSource returns a types.ImageCloser implementation for the default instance of source.
// If source is a manifest list, .Manifest() still returns the manifest list,
// but other methods transparently return data from an appropriate image instance.
//
// The caller must call .Close() on the returned ImageCloser.
// //
// FromSource “takes ownership” of the input ImageSource and will call src.Close() // FromSource “takes ownership” of the input ImageSource and will call src.Close()
// when the image is closed. (This does not prevent callers from using both the // when the image is closed. (This does not prevent callers from using both the
@ -18,8 +28,19 @@ import (
// //
// NOTE: If any kind of signature verification should happen, build an UnparsedImage from the value returned by NewImageSource, // NOTE: If any kind of signature verification should happen, build an UnparsedImage from the value returned by NewImageSource,
// verify that UnparsedImage, and convert it into a real Image via image.FromUnparsedImage instead of calling this function. // verify that UnparsedImage, and convert it into a real Image via image.FromUnparsedImage instead of calling this function.
func FromSource(src types.ImageSource) (types.Image, error) { func FromSource(ctx *types.SystemContext, src types.ImageSource) (types.ImageCloser, error) {
return FromUnparsedImage(UnparsedFromSource(src)) img, err := FromUnparsedImage(ctx, UnparsedInstance(src, nil))
if err != nil {
return nil, err
}
return &imageCloser{
Image: img,
src: src,
}, nil
}
func (ic *imageCloser) Close() error {
return ic.src.Close()
} }
// sourcedImage is a general set of utilities for working with container images, // sourcedImage is a general set of utilities for working with container images,
@ -38,27 +59,22 @@ type sourcedImage struct {
} }
// FromUnparsedImage returns a types.Image implementation for unparsed. // FromUnparsedImage returns a types.Image implementation for unparsed.
// The caller must call .Close() on the returned Image. // If unparsed represents a manifest list, .Manifest() still returns the manifest list,
// but other methods transparently return data from an appropriate single image.
// //
// FromSource “takes ownership” of the input UnparsedImage and will call uparsed.Close() // The Image must not be used after the underlying ImageSource is Close()d.
// when the image is closed. (This does not prevent callers from using both the func FromUnparsedImage(ctx *types.SystemContext, unparsed *UnparsedImage) (types.Image, error) {
// UnparsedImage and ImageSource objects simultaneously, but it means that they only need to
// keep a reference to the Image.)
func FromUnparsedImage(unparsed *UnparsedImage) (types.Image, error) {
// Note that the input parameter above is specifically *image.UnparsedImage, not types.UnparsedImage: // Note that the input parameter above is specifically *image.UnparsedImage, not types.UnparsedImage:
// we want to be able to use unparsed.src. We could make that an explicit interface, but, well, // we want to be able to use unparsed.src. We could make that an explicit interface, but, well,
// this is the only UnparsedImage implementation around, anyway. // this is the only UnparsedImage implementation around, anyway.
// Also, we do not explicitly implement types.Image.Close; we let the implementation fall through to
// unparsed.Close.
// NOTE: It is essential for signature verification that all parsing done in this object happens on the same manifest which is returned by unparsed.Manifest(). // NOTE: It is essential for signature verification that all parsing done in this object happens on the same manifest which is returned by unparsed.Manifest().
manifestBlob, manifestMIMEType, err := unparsed.Manifest() manifestBlob, manifestMIMEType, err := unparsed.Manifest()
if err != nil { if err != nil {
return nil, err return nil, err
} }
parsedManifest, err := manifestInstanceFromBlob(unparsed.src, manifestBlob, manifestMIMEType) parsedManifest, err := manifestInstanceFromBlob(ctx, unparsed.src, manifestBlob, manifestMIMEType)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -84,7 +100,3 @@ func (i *sourcedImage) Manifest() ([]byte, string, error) {
func (i *sourcedImage) Inspect() (*types.ImageInspectInfo, error) { func (i *sourcedImage) Inspect() (*types.ImageInspectInfo, error) {
return inspectManifest(i.genericManifest) return inspectManifest(i.genericManifest)
} }
func (i *sourcedImage) IsMultiImage() bool {
return i.manifestMIMEType == manifest.DockerV2ListMediaType
}

View File

@ -11,8 +11,10 @@ import (
) )
// UnparsedImage implements types.UnparsedImage . // UnparsedImage implements types.UnparsedImage .
// An UnparsedImage is a pair of (ImageSource, instance digest); it can represent either a manifest list or a single image instance.
type UnparsedImage struct { type UnparsedImage struct {
src types.ImageSource src types.ImageSource
instanceDigest *digest.Digest
cachedManifest []byte // A private cache for Manifest(); nil if not yet known. cachedManifest []byte // A private cache for Manifest(); nil if not yet known.
// A private cache for Manifest(), may be the empty string if guessing failed. // A private cache for Manifest(), may be the empty string if guessing failed.
// Valid iff cachedManifest is not nil. // Valid iff cachedManifest is not nil.
@ -20,49 +22,41 @@ type UnparsedImage struct {
cachedSignatures [][]byte // A private cache for Signatures(); nil if not yet known. cachedSignatures [][]byte // A private cache for Signatures(); nil if not yet known.
} }
// UnparsedFromSource returns a types.UnparsedImage implementation for source. // UnparsedInstance returns a types.UnparsedImage implementation for (source, instanceDigest).
// The caller must call .Close() on the returned UnparsedImage. // If instanceDigest is not nil, it contains a digest of the specific manifest instance to retrieve (when the primary manifest is a manifest list).
// //
// UnparsedFromSource “takes ownership” of the input ImageSource and will call src.Close() // The UnparsedImage must not be used after the underlying ImageSource is Close()d.
// when the image is closed. (This does not prevent callers from using both the func UnparsedInstance(src types.ImageSource, instanceDigest *digest.Digest) *UnparsedImage {
// UnparsedImage and ImageSource objects simultaneously, but it means that they only need to return &UnparsedImage{
// keep a reference to the UnparsedImage.) src: src,
func UnparsedFromSource(src types.ImageSource) *UnparsedImage { instanceDigest: instanceDigest,
return &UnparsedImage{src: src} }
} }
// Reference returns the reference used to set up this source, _as specified by the user_ // Reference returns the reference used to set up this source, _as specified by the user_
// (not as the image itself, or its underlying storage, claims). This can be used e.g. to determine which public keys are trusted for this image. // (not as the image itself, or its underlying storage, claims). This can be used e.g. to determine which public keys are trusted for this image.
func (i *UnparsedImage) Reference() types.ImageReference { func (i *UnparsedImage) Reference() types.ImageReference {
// Note that this does not depend on instanceDigest; e.g. all instances within a manifest list need to be signed with the manifest list identity.
return i.src.Reference() return i.src.Reference()
} }
// Close removes resources associated with an initialized UnparsedImage, if any.
func (i *UnparsedImage) Close() error {
return i.src.Close()
}
// Manifest is like ImageSource.GetManifest, but the result is cached; it is OK to call this however often you need. // Manifest is like ImageSource.GetManifest, but the result is cached; it is OK to call this however often you need.
func (i *UnparsedImage) Manifest() ([]byte, string, error) { func (i *UnparsedImage) Manifest() ([]byte, string, error) {
if i.cachedManifest == nil { if i.cachedManifest == nil {
m, mt, err := i.src.GetManifest() m, mt, err := i.src.GetManifest(i.instanceDigest)
if err != nil { if err != nil {
return nil, "", err return nil, "", err
} }
// ImageSource.GetManifest does not do digest verification, but we do; // ImageSource.GetManifest does not do digest verification, but we do;
// this immediately protects also any user of types.Image. // this immediately protects also any user of types.Image.
ref := i.Reference().DockerReference() if digest, haveDigest := i.expectedManifestDigest(); haveDigest {
if ref != nil { matches, err := manifest.MatchesDigest(m, digest)
if canonical, ok := ref.(reference.Canonical); ok { if err != nil {
digest := digest.Digest(canonical.Digest()) return nil, "", errors.Wrap(err, "Error computing manifest digest")
matches, err := manifest.MatchesDigest(m, digest) }
if err != nil { if !matches {
return nil, "", errors.Wrap(err, "Error computing manifest digest") return nil, "", errors.Errorf("Manifest does not match provided manifest digest %s", digest)
}
if !matches {
return nil, "", errors.Errorf("Manifest does not match provided manifest digest %s", digest)
}
} }
} }
@ -72,10 +66,26 @@ func (i *UnparsedImage) Manifest() ([]byte, string, error) {
return i.cachedManifest, i.cachedManifestMIMEType, nil return i.cachedManifest, i.cachedManifestMIMEType, nil
} }
// expectedManifestDigest returns a the expected value of the manifest digest, and an indicator whether it is known.
// The bool return value seems redundant with digest != ""; it is used explicitly
// to refuse (unexpected) situations when the digest exists but is "".
func (i *UnparsedImage) expectedManifestDigest() (digest.Digest, bool) {
if i.instanceDigest != nil {
return *i.instanceDigest, true
}
ref := i.Reference().DockerReference()
if ref != nil {
if canonical, ok := ref.(reference.Canonical); ok {
return canonical.Digest(), true
}
}
return "", false
}
// Signatures is like ImageSource.GetSignatures, but the result is cached; it is OK to call this however often you need. // Signatures is like ImageSource.GetSignatures, but the result is cached; it is OK to call this however often you need.
func (i *UnparsedImage) Signatures(ctx context.Context) ([][]byte, error) { func (i *UnparsedImage) Signatures(ctx context.Context) ([][]byte, error) {
if i.cachedSignatures == nil { if i.cachedSignatures == nil {
sigs, err := i.src.GetSignatures(ctx) sigs, err := i.src.GetSignatures(ctx, i.instanceDigest)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@ -35,7 +35,7 @@ var DefaultRequestedManifestMIMETypes = []string{
DockerV2Schema2MediaType, DockerV2Schema2MediaType,
DockerV2Schema1SignedMediaType, DockerV2Schema1SignedMediaType,
DockerV2Schema1MediaType, DockerV2Schema1MediaType,
// DockerV2ListMediaType, // FIXME: Restore this ASAP DockerV2ListMediaType,
} }
// GuessMIMEType guesses MIME type of a manifest and returns it _if it is recognized_, or "" if unknown or unrecognized. // GuessMIMEType guesses MIME type of a manifest and returns it _if it is recognized_, or "" if unknown or unrecognized.
@ -142,3 +142,8 @@ func AddDummyV2S1Signature(manifest []byte) ([]byte, error) {
} }
return js.PrettySignature("signatures") return js.PrettySignature("signatures")
} }
// MIMETypeIsMultiImage returns true if mimeType is a list of images
func MIMETypeIsMultiImage(mimeType string) bool {
return mimeType == DockerV2ListMediaType
}

View File

@ -68,14 +68,12 @@ func (s *ociArchiveImageSource) Close() error {
return s.unpackedSrc.Close() return s.unpackedSrc.Close()
} }
// GetManifest returns the image's manifest along with its MIME type // GetManifest returns the image's manifest along with its MIME type (which may be empty when it can't be determined but the manifest is available).
// (which may be empty when it can't be determined but the manifest is available). // It may use a remote (= slow) service.
func (s *ociArchiveImageSource) GetManifest() ([]byte, string, error) { // If instanceDigest is not nil, it contains a digest of the specific manifest instance to retrieve (when the primary manifest is a manifest list);
return s.unpackedSrc.GetManifest() // this never happens if the primary manifest is not a manifest list (e.g. if the source never returns manifest lists).
} func (s *ociArchiveImageSource) GetManifest(instanceDigest *digest.Digest) ([]byte, string, error) {
return s.unpackedSrc.GetManifest(instanceDigest)
func (s *ociArchiveImageSource) GetTargetManifest(digest digest.Digest) ([]byte, string, error) {
return s.unpackedSrc.GetTargetManifest(digest)
} }
// GetBlob returns a stream for the specified blob, and the blob's size. // GetBlob returns a stream for the specified blob, and the blob's size.
@ -83,6 +81,10 @@ func (s *ociArchiveImageSource) GetBlob(info types.BlobInfo) (io.ReadCloser, int
return s.unpackedSrc.GetBlob(info) return s.unpackedSrc.GetBlob(info)
} }
func (s *ociArchiveImageSource) GetSignatures(c context.Context) ([][]byte, error) { // GetSignatures returns the image's signatures. It may use a remote (= slow) service.
return s.unpackedSrc.GetSignatures(c) // If instanceDigest is not nil, it contains a digest of the specific manifest instance to retrieve signatures for
// (when the primary manifest is a manifest list); this never happens if the primary manifest is not a manifest list
// (e.g. if the source never returns manifest lists).
func (s *ociArchiveImageSource) GetSignatures(ctx context.Context, instanceDigest *digest.Digest) ([][]byte, error) {
return s.unpackedSrc.GetSignatures(ctx, instanceDigest)
} }

View File

@ -154,14 +154,17 @@ func (ref ociArchiveReference) PolicyConfigurationNamespaces() []string {
return res return res
} }
// NewImage returns a types.Image for this reference, possibly specialized for this ImageTransport. // NewImage returns a types.ImageCloser for this reference, possibly specialized for this ImageTransport.
// The caller must call .Close() on the returned Image. // The caller must call .Close() on the returned ImageCloser.
func (ref ociArchiveReference) NewImage(ctx *types.SystemContext) (types.Image, error) { // NOTE: If any kind of signature verification should happen, build an UnparsedImage from the value returned by NewImageSource,
// verify that UnparsedImage, and convert it into a real Image via image.FromUnparsedImage.
// WARNING: This may not do the right thing for a manifest list, see image.FromSource for details.
func (ref ociArchiveReference) NewImage(ctx *types.SystemContext) (types.ImageCloser, error) {
src, err := newImageSource(ctx, ref) src, err := newImageSource(ctx, ref)
if err != nil { if err != nil {
return nil, err return nil, err
} }
return image.FromSource(src) return image.FromSource(ctx, src)
} }
// NewImageSource returns a types.ImageSource for this reference. // NewImageSource returns a types.ImageSource for this reference.

View File

@ -61,8 +61,26 @@ func (s *ociImageSource) Close() error {
// GetManifest returns the image's manifest along with its MIME type (which may be empty when it can't be determined but the manifest is available). // GetManifest returns the image's manifest along with its MIME type (which may be empty when it can't be determined but the manifest is available).
// It may use a remote (= slow) service. // It may use a remote (= slow) service.
func (s *ociImageSource) GetManifest() ([]byte, string, error) { // If instanceDigest is not nil, it contains a digest of the specific manifest instance to retrieve (when the primary manifest is a manifest list);
manifestPath, err := s.ref.blobPath(digest.Digest(s.descriptor.Digest), s.sharedBlobDir) // this never happens if the primary manifest is not a manifest list (e.g. if the source never returns manifest lists).
func (s *ociImageSource) GetManifest(instanceDigest *digest.Digest) ([]byte, string, error) {
var dig digest.Digest
var mimeType string
if instanceDigest == nil {
dig = digest.Digest(s.descriptor.Digest)
mimeType = s.descriptor.MediaType
} else {
dig = *instanceDigest
// XXX: instanceDigest means that we don't immediately have the context of what
// mediaType the manifest has. In OCI this means that we don't know
// what reference it came from, so we just *assume* that its
// MediaTypeImageManifest.
// FIXME: We should actually be able to look up the manifest in the index,
// and see the MIME type there.
mimeType = imgspecv1.MediaTypeImageManifest
}
manifestPath, err := s.ref.blobPath(dig, s.sharedBlobDir)
if err != nil { if err != nil {
return nil, "", err return nil, "", err
} }
@ -71,25 +89,7 @@ func (s *ociImageSource) GetManifest() ([]byte, string, error) {
return nil, "", err return nil, "", err
} }
return m, s.descriptor.MediaType, nil return m, mimeType, nil
}
func (s *ociImageSource) GetTargetManifest(digest digest.Digest) ([]byte, string, error) {
manifestPath, err := s.ref.blobPath(digest, s.sharedBlobDir)
if err != nil {
return nil, "", err
}
m, err := ioutil.ReadFile(manifestPath)
if err != nil {
return nil, "", err
}
// XXX: GetTargetManifest means that we don't have the context of what
// mediaType the manifest has. In OCI this means that we don't know
// what reference it came from, so we just *assume* that its
// MediaTypeImageManifest.
return m, imgspecv1.MediaTypeImageManifest, nil
} }
// GetBlob returns a stream for the specified blob, and the blob's size. // GetBlob returns a stream for the specified blob, and the blob's size.
@ -114,7 +114,11 @@ func (s *ociImageSource) GetBlob(info types.BlobInfo) (io.ReadCloser, int64, err
return r, fi.Size(), nil return r, fi.Size(), nil
} }
func (s *ociImageSource) GetSignatures(context.Context) ([][]byte, error) { // GetSignatures returns the image's signatures. It may use a remote (= slow) service.
// If instanceDigest is not nil, it contains a digest of the specific manifest instance to retrieve signatures for
// (when the primary manifest is a manifest list); this never happens if the primary manifest is not a manifest list
// (e.g. if the source never returns manifest lists).
func (s *ociImageSource) GetSignatures(ctx context.Context, instanceDigest *digest.Digest) ([][]byte, error) {
return [][]byte{}, nil return [][]byte{}, nil
} }

View File

@ -177,16 +177,17 @@ func (ref ociReference) PolicyConfigurationNamespaces() []string {
return res return res
} }
// NewImage returns a types.Image for this reference, possibly specialized for this ImageTransport. // NewImage returns a types.ImageCloser for this reference, possibly specialized for this ImageTransport.
// The caller must call .Close() on the returned Image. // The caller must call .Close() on the returned ImageCloser.
// NOTE: If any kind of signature verification should happen, build an UnparsedImage from the value returned by NewImageSource, // NOTE: If any kind of signature verification should happen, build an UnparsedImage from the value returned by NewImageSource,
// verify that UnparsedImage, and convert it into a real Image via image.FromUnparsedImage. // verify that UnparsedImage, and convert it into a real Image via image.FromUnparsedImage.
func (ref ociReference) NewImage(ctx *types.SystemContext) (types.Image, error) { // WARNING: This may not do the right thing for a manifest list, see image.FromSource for details.
func (ref ociReference) NewImage(ctx *types.SystemContext) (types.ImageCloser, error) {
src, err := newImageSource(ctx, ref) src, err := newImageSource(ctx, ref)
if err != nil { if err != nil {
return nil, err return nil, err
} }
return image.FromSource(src) return image.FromSource(ctx, src)
} }
// getIndex returns a pointer to the index references by this ociReference. If an error occurs opening an index nil is returned together // getIndex returns a pointer to the index references by this ociReference. If an error occurs opening an index nil is returned together

View File

@ -200,20 +200,15 @@ func (s *openshiftImageSource) Close() error {
return nil return nil
} }
func (s *openshiftImageSource) GetTargetManifest(digest digest.Digest) ([]byte, string, error) {
if err := s.ensureImageIsResolved(context.TODO()); err != nil {
return nil, "", err
}
return s.docker.GetTargetManifest(digest)
}
// GetManifest returns the image's manifest along with its MIME type (which may be empty when it can't be determined but the manifest is available). // GetManifest returns the image's manifest along with its MIME type (which may be empty when it can't be determined but the manifest is available).
// It may use a remote (= slow) service. // It may use a remote (= slow) service.
func (s *openshiftImageSource) GetManifest() ([]byte, string, error) { // If instanceDigest is not nil, it contains a digest of the specific manifest instance to retrieve (when the primary manifest is a manifest list);
// this never happens if the primary manifest is not a manifest list (e.g. if the source never returns manifest lists).
func (s *openshiftImageSource) GetManifest(instanceDigest *digest.Digest) ([]byte, string, error) {
if err := s.ensureImageIsResolved(context.TODO()); err != nil { if err := s.ensureImageIsResolved(context.TODO()); err != nil {
return nil, "", err return nil, "", err
} }
return s.docker.GetManifest() return s.docker.GetManifest(instanceDigest)
} }
// GetBlob returns a stream for the specified blob, and the blobs size (or -1 if unknown). // GetBlob returns a stream for the specified blob, and the blobs size (or -1 if unknown).
@ -224,12 +219,21 @@ func (s *openshiftImageSource) GetBlob(info types.BlobInfo) (io.ReadCloser, int6
return s.docker.GetBlob(info) return s.docker.GetBlob(info)
} }
func (s *openshiftImageSource) GetSignatures(ctx context.Context) ([][]byte, error) { // GetSignatures returns the image's signatures. It may use a remote (= slow) service.
if err := s.ensureImageIsResolved(ctx); err != nil { // If instanceDigest is not nil, it contains a digest of the specific manifest instance to retrieve signatures for
return nil, err // (when the primary manifest is a manifest list); this never happens if the primary manifest is not a manifest list
// (e.g. if the source never returns manifest lists).
func (s *openshiftImageSource) GetSignatures(ctx context.Context, instanceDigest *digest.Digest) ([][]byte, error) {
var imageName string
if instanceDigest == nil {
if err := s.ensureImageIsResolved(ctx); err != nil {
return nil, err
}
imageName = s.imageStreamImageName
} else {
imageName = instanceDigest.String()
} }
image, err := s.client.getImage(ctx, imageName)
image, err := s.client.getImage(ctx, s.imageStreamImageName)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@ -125,16 +125,17 @@ func (ref openshiftReference) PolicyConfigurationNamespaces() []string {
return policyconfiguration.DockerReferenceNamespaces(ref.dockerReference) return policyconfiguration.DockerReferenceNamespaces(ref.dockerReference)
} }
// NewImage returns a types.Image for this reference, possibly specialized for this ImageTransport. // NewImage returns a types.ImageCloser for this reference, possibly specialized for this ImageTransport.
// The caller must call .Close() on the returned Image. // The caller must call .Close() on the returned ImageCloser.
// NOTE: If any kind of signature verification should happen, build an UnparsedImage from the value returned by NewImageSource, // NOTE: If any kind of signature verification should happen, build an UnparsedImage from the value returned by NewImageSource,
// verify that UnparsedImage, and convert it into a real Image via image.FromUnparsedImage. // verify that UnparsedImage, and convert it into a real Image via image.FromUnparsedImage.
func (ref openshiftReference) NewImage(ctx *types.SystemContext) (types.Image, error) { // WARNING: This may not do the right thing for a manifest list, see image.FromSource for details.
func (ref openshiftReference) NewImage(ctx *types.SystemContext) (types.ImageCloser, error) {
src, err := newImageSource(ctx, ref) src, err := newImageSource(ctx, ref)
if err != nil { if err != nil {
return nil, err return nil, err
} }
return genericImage.FromSource(src) return genericImage.FromSource(ctx, src)
} }
// NewImageSource returns a types.ImageSource for this reference. // NewImageSource returns a types.ImageSource for this reference.

View File

@ -168,11 +168,12 @@ func (ref ostreeReference) PolicyConfigurationNamespaces() []string {
return res return res
} }
// NewImage returns a types.Image for this reference, possibly specialized for this ImageTransport. // NewImage returns a types.ImageCloser for this reference, possibly specialized for this ImageTransport.
// The caller must call .Close() on the returned Image. // The caller must call .Close() on the returned ImageCloser.
// NOTE: If any kind of signature verification should happen, build an UnparsedImage from the value returned by NewImageSource, // NOTE: If any kind of signature verification should happen, build an UnparsedImage from the value returned by NewImageSource,
// verify that UnparsedImage, and convert it into a real Image via image.FromUnparsedImage. // verify that UnparsedImage, and convert it into a real Image via image.FromUnparsedImage.
func (ref ostreeReference) NewImage(ctx *types.SystemContext) (types.Image, error) { // WARNING: This may not do the right thing for a manifest list, see image.FromSource for details.
func (ref ostreeReference) NewImage(ctx *types.SystemContext) (types.ImageCloser, error) {
return nil, errors.New("Reading ostree: images is currently not supported") return nil, errors.New("Reading ostree: images is currently not supported")
} }

View File

@ -29,8 +29,8 @@ var (
// ErrBlobSizeMismatch is returned when PutBlob() is given a blob // ErrBlobSizeMismatch is returned when PutBlob() is given a blob
// with an expected size that doesn't match the reader. // with an expected size that doesn't match the reader.
ErrBlobSizeMismatch = errors.New("blob size mismatch") ErrBlobSizeMismatch = errors.New("blob size mismatch")
// ErrNoManifestLists is returned when GetTargetManifest() is // ErrNoManifestLists is returned when GetManifest() is called.
// called. // with a non-nil instanceDigest.
ErrNoManifestLists = errors.New("manifest lists are not supported by this transport") ErrNoManifestLists = errors.New("manifest lists are not supported by this transport")
// ErrNoSuchImage is returned when we attempt to access an image which // ErrNoSuchImage is returned when we attempt to access an image which
// doesn't exist in the storage area. // doesn't exist in the storage area.
@ -67,8 +67,8 @@ type storageLayerMetadata struct {
CompressedSize int64 `json:"compressed-size,omitempty"` CompressedSize int64 `json:"compressed-size,omitempty"`
} }
type storageImage struct { type storageImageCloser struct {
types.Image types.ImageCloser
size int64 size int64
} }
@ -531,16 +531,26 @@ func diffLayer(store storage.Store, layerID string) (rc io.ReadCloser, n int64,
return diff, n, nil return diff, n, nil
} }
func (s *storageImageSource) GetManifest() (manifestBlob []byte, MIMEType string, err error) { // GetManifest returns the image's manifest along with its MIME type (which may be empty when it can't be determined but the manifest is available).
// It may use a remote (= slow) service.
// If instanceDigest is not nil, it contains a digest of the specific manifest instance to retrieve (when the primary manifest is a manifest list);
// this never happens if the primary manifest is not a manifest list (e.g. if the source never returns manifest lists).
func (s *storageImageSource) GetManifest(instanceDigest *ddigest.Digest) (manifestBlob []byte, MIMEType string, err error) {
if instanceDigest != nil {
return nil, "", ErrNoManifestLists
}
manifestBlob, err = s.imageRef.transport.store.ImageBigData(s.ID, "manifest") manifestBlob, err = s.imageRef.transport.store.ImageBigData(s.ID, "manifest")
return manifestBlob, manifest.GuessMIMEType(manifestBlob), err return manifestBlob, manifest.GuessMIMEType(manifestBlob), err
} }
func (s *storageImageSource) GetTargetManifest(digest ddigest.Digest) (manifestBlob []byte, MIMEType string, err error) { // GetSignatures returns the image's signatures. It may use a remote (= slow) service.
return nil, "", ErrNoManifestLists // If instanceDigest is not nil, it contains a digest of the specific manifest instance to retrieve signatures for
} // (when the primary manifest is a manifest list); this never happens if the primary manifest is not a manifest list
// (e.g. if the source never returns manifest lists).
func (s *storageImageSource) GetSignatures(ctx context.Context) (signatures [][]byte, err error) { func (s *storageImageSource) GetSignatures(ctx context.Context, instanceDigest *ddigest.Digest) ([][]byte, error) {
if instanceDigest != nil {
return nil, ErrNoManifestLists
}
var offset int var offset int
signature, err := s.imageRef.transport.store.ImageBigData(s.ID, "signatures") signature, err := s.imageRef.transport.store.ImageBigData(s.ID, "signatures")
if err != nil { if err != nil {
@ -552,7 +562,7 @@ func (s *storageImageSource) GetSignatures(ctx context.Context) (signatures [][]
offset += length offset += length
} }
if offset != len(signature) { if offset != len(signature) {
return nil, errors.Errorf("signatures data contained %d extra bytes", len(signatures)-offset) return nil, errors.Errorf("signatures data contained %d extra bytes", len(signature)-offset)
} }
return sigslice, nil return sigslice, nil
} }
@ -596,17 +606,17 @@ func (s *storageImageSource) getSize() (int64, error) {
return sum, nil return sum, nil
} }
func (s *storageImage) Size() (int64, error) { func (s *storageImageCloser) Size() (int64, error) {
return s.size, nil return s.size, nil
} }
// newImage creates an image that also knows its size // newImage creates an ImageCloser that also knows its size
func newImage(s storageReference) (types.Image, error) { func newImage(ctx *types.SystemContext, s storageReference) (types.ImageCloser, error) {
src, err := newImageSource(s) src, err := newImageSource(s)
if err != nil { if err != nil {
return nil, err return nil, err
} }
img, err := image.FromSource(src) img, err := image.FromSource(ctx, src)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -614,5 +624,5 @@ func newImage(s storageReference) (types.Image, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
return &storageImage{Image: img, size: size}, nil return &storageImageCloser{ImageCloser: img, size: size}, nil
} }

View File

@ -137,8 +137,13 @@ func (s storageReference) PolicyConfigurationNamespaces() []string {
return namespaces return namespaces
} }
func (s storageReference) NewImage(ctx *types.SystemContext) (types.Image, error) { // NewImage returns a types.ImageCloser for this reference, possibly specialized for this ImageTransport.
return newImage(s) // The caller must call .Close() on the returned ImageCloser.
// NOTE: If any kind of signature verification should happen, build an UnparsedImage from the value returned by NewImageSource,
// verify that UnparsedImage, and convert it into a real Image via image.FromUnparsedImage.
// WARNING: This may not do the right thing for a manifest list, see image.FromSource for details.
func (s storageReference) NewImage(ctx *types.SystemContext) (types.ImageCloser, error) {
return newImage(ctx, s)
} }
func (s storageReference) DeleteImage(ctx *types.SystemContext) error { func (s storageReference) DeleteImage(ctx *types.SystemContext) error {

View File

@ -61,12 +61,17 @@ func (r *tarballReference) PolicyConfigurationNamespaces() []string {
return nil return nil
} }
func (r *tarballReference) NewImage(ctx *types.SystemContext) (types.Image, error) { // NewImage returns a types.ImageCloser for this reference, possibly specialized for this ImageTransport.
// The caller must call .Close() on the returned ImageCloser.
// NOTE: If any kind of signature verification should happen, build an UnparsedImage from the value returned by NewImageSource,
// verify that UnparsedImage, and convert it into a real Image via image.FromUnparsedImage.
// WARNING: This may not do the right thing for a manifest list, see image.FromSource for details.
func (r *tarballReference) NewImage(ctx *types.SystemContext) (types.ImageCloser, error) {
src, err := r.NewImageSource(ctx) src, err := r.NewImageSource(ctx)
if err != nil { if err != nil {
return nil, err return nil, err
} }
img, err := image.FromSource(src) img, err := image.FromSource(ctx, src)
if err != nil { if err != nil {
src.Close() src.Close()
return nil, err return nil, err

View File

@ -228,18 +228,28 @@ func (is *tarballImageSource) GetBlob(blobinfo types.BlobInfo) (io.ReadCloser, i
return nil, -1, fmt.Errorf("no blob with digest %q found", blobinfo.Digest.String()) return nil, -1, fmt.Errorf("no blob with digest %q found", blobinfo.Digest.String())
} }
func (is *tarballImageSource) GetManifest() ([]byte, string, error) { // GetManifest returns the image's manifest along with its MIME type (which may be empty when it can't be determined but the manifest is available).
// It may use a remote (= slow) service.
// If instanceDigest is not nil, it contains a digest of the specific manifest instance to retrieve (when the primary manifest is a manifest list);
// this never happens if the primary manifest is not a manifest list (e.g. if the source never returns manifest lists).
func (is *tarballImageSource) GetManifest(instanceDigest *digest.Digest) ([]byte, string, error) {
if instanceDigest != nil {
return nil, "", fmt.Errorf("manifest lists are not supported by the %q transport", transportName)
}
return is.manifest, imgspecv1.MediaTypeImageManifest, nil return is.manifest, imgspecv1.MediaTypeImageManifest, nil
} }
func (*tarballImageSource) GetSignatures(context.Context) ([][]byte, error) { // GetSignatures returns the image's signatures. It may use a remote (= slow) service.
// If instanceDigest is not nil, it contains a digest of the specific manifest instance to retrieve signatures for
// (when the primary manifest is a manifest list); this never happens if the primary manifest is not a manifest list
// (e.g. if the source never returns manifest lists).
func (*tarballImageSource) GetSignatures(ctx context.Context, instanceDigest *digest.Digest) ([][]byte, error) {
if instanceDigest != nil {
return nil, fmt.Errorf("manifest lists are not supported by the %q transport", transportName)
}
return nil, nil return nil, nil
} }
func (*tarballImageSource) GetTargetManifest(digest.Digest) ([]byte, string, error) {
return nil, "", fmt.Errorf("manifest lists are not supported by the %q transport", transportName)
}
func (is *tarballImageSource) Reference() types.ImageReference { func (is *tarballImageSource) Reference() types.ImageReference {
return &is.reference return &is.reference
} }

View File

@ -73,11 +73,12 @@ type ImageReference interface {
// and each following element to be a prefix of the element preceding it. // and each following element to be a prefix of the element preceding it.
PolicyConfigurationNamespaces() []string PolicyConfigurationNamespaces() []string
// NewImage returns a types.Image for this reference, possibly specialized for this ImageTransport. // NewImage returns a types.ImageCloser for this reference, possibly specialized for this ImageTransport.
// The caller must call .Close() on the returned Image. // The caller must call .Close() on the returned ImageCloser.
// NOTE: If any kind of signature verification should happen, build an UnparsedImage from the value returned by NewImageSource, // NOTE: If any kind of signature verification should happen, build an UnparsedImage from the value returned by NewImageSource,
// verify that UnparsedImage, and convert it into a real Image via image.FromUnparsedImage. // verify that UnparsedImage, and convert it into a real Image via image.FromUnparsedImage.
NewImage(ctx *SystemContext) (Image, error) // WARNING: This may not do the right thing for a manifest list, see image.FromSource for details.
NewImage(ctx *SystemContext) (ImageCloser, error)
// NewImageSource returns a types.ImageSource for this reference. // NewImageSource returns a types.ImageSource for this reference.
// The caller must call .Close() on the returned ImageSource. // The caller must call .Close() on the returned ImageSource.
NewImageSource(ctx *SystemContext) (ImageSource, error) NewImageSource(ctx *SystemContext) (ImageSource, error)
@ -99,7 +100,7 @@ type BlobInfo struct {
MediaType string MediaType string
} }
// ImageSource is a service, possibly remote (= slow), to download components of a single image. // ImageSource is a service, possibly remote (= slow), to download components of a single image or a named image set (manifest list).
// This is primarily useful for copying images around; for examining their properties, Image (below) // This is primarily useful for copying images around; for examining their properties, Image (below)
// is usually more useful. // is usually more useful.
// Each ImageSource should eventually be closed by calling Close(). // Each ImageSource should eventually be closed by calling Close().
@ -114,15 +115,17 @@ type ImageSource interface {
Close() error Close() error
// GetManifest returns the image's manifest along with its MIME type (which may be empty when it can't be determined but the manifest is available). // GetManifest returns the image's manifest along with its MIME type (which may be empty when it can't be determined but the manifest is available).
// It may use a remote (= slow) service. // It may use a remote (= slow) service.
GetManifest() ([]byte, string, error) // If instanceDigest is not nil, it contains a digest of the specific manifest instance to retrieve (when the primary manifest is a manifest list);
// GetTargetManifest returns an image's manifest given a digest. This is mainly used to retrieve a single image's manifest // this never happens if the primary manifest is not a manifest list (e.g. if the source never returns manifest lists).
// out of a manifest list. GetManifest(instanceDigest *digest.Digest) ([]byte, string, error)
GetTargetManifest(digest digest.Digest) ([]byte, string, error)
// GetBlob returns a stream for the specified blob, and the blobs size (or -1 if unknown). // GetBlob returns a stream for the specified blob, and the blobs size (or -1 if unknown).
// The Digest field in BlobInfo is guaranteed to be provided, Size may be -1 and MediaType may be optionally provided. // The Digest field in BlobInfo is guaranteed to be provided, Size may be -1 and MediaType may be optionally provided.
GetBlob(BlobInfo) (io.ReadCloser, int64, error) GetBlob(BlobInfo) (io.ReadCloser, int64, error)
// GetSignatures returns the image's signatures. It may use a remote (= slow) service. // GetSignatures returns the image's signatures. It may use a remote (= slow) service.
GetSignatures(context.Context) ([][]byte, error) // If instanceDigest is not nil, it contains a digest of the specific manifest instance to retrieve signatures for
// (when the primary manifest is a manifest list); this never happens if the primary manifest is not a manifest list
// (e.g. if the source never returns manifest lists).
GetSignatures(ctx context.Context, instanceDigest *digest.Digest) ([][]byte, error)
} }
// ImageDestination is a service, possibly remote (= slow), to store components of a single image. // ImageDestination is a service, possibly remote (= slow), to store components of a single image.
@ -196,13 +199,14 @@ func (e ManifestTypeRejectedError) Error() string {
// Thus, an UnparsedImage can be created from an ImageSource simply by fetching blobs without interpreting them, // Thus, an UnparsedImage can be created from an ImageSource simply by fetching blobs without interpreting them,
// allowing cryptographic signature verification to happen first, before even fetching the manifest, or parsing anything else. // allowing cryptographic signature verification to happen first, before even fetching the manifest, or parsing anything else.
// This also makes the UnparsedImage→Image conversion an explicitly visible step. // This also makes the UnparsedImage→Image conversion an explicitly visible step.
// Each UnparsedImage should eventually be closed by calling Close(). //
// An UnparsedImage is a pair of (ImageSource, instance digest); it can represent either a manifest list or a single image instance.
//
// The UnparsedImage must not be used after the underlying ImageSource is Close()d.
type UnparsedImage interface { type UnparsedImage interface {
// Reference returns the reference used to set up this source, _as specified by the user_ // Reference returns the reference used to set up this source, _as specified by the user_
// (not as the image itself, or its underlying storage, claims). This can be used e.g. to determine which public keys are trusted for this image. // (not as the image itself, or its underlying storage, claims). This can be used e.g. to determine which public keys are trusted for this image.
Reference() ImageReference Reference() ImageReference
// Close removes resources associated with an initialized UnparsedImage, if any.
Close() error
// Manifest is like ImageSource.GetManifest, but the result is cached; it is OK to call this however often you need. // Manifest is like ImageSource.GetManifest, but the result is cached; it is OK to call this however often you need.
Manifest() ([]byte, string, error) Manifest() ([]byte, string, error)
// Signatures is like ImageSource.GetSignatures, but the result is cached; it is OK to call this however often you need. // Signatures is like ImageSource.GetSignatures, but the result is cached; it is OK to call this however often you need.
@ -210,7 +214,9 @@ type UnparsedImage interface {
} }
// Image is the primary API for inspecting properties of images. // Image is the primary API for inspecting properties of images.
// Each Image should eventually be closed by calling Close(). // An Image is based on a pair of (ImageSource, instance digest); it can represent either a manifest list or a single image instance.
//
// The Image must not be used after the underlying ImageSource is Close()d.
type Image interface { type Image interface {
// Note that Reference may return nil in the return value of UpdatedImage! // Note that Reference may return nil in the return value of UpdatedImage!
UnparsedImage UnparsedImage
@ -242,13 +248,20 @@ type Image interface {
// Everything in options.InformationOnly should be provided, other fields should be set only if a modification is desired. // Everything in options.InformationOnly should be provided, other fields should be set only if a modification is desired.
// This does not change the state of the original Image object. // This does not change the state of the original Image object.
UpdatedImage(options ManifestUpdateOptions) (Image, error) UpdatedImage(options ManifestUpdateOptions) (Image, error)
// IsMultiImage returns true if the image's manifest is a list of images, false otherwise.
IsMultiImage() bool
// Size returns an approximation of the amount of disk space which is consumed by the image in its current // Size returns an approximation of the amount of disk space which is consumed by the image in its current
// location. If the size is not known, -1 will be returned. // location. If the size is not known, -1 will be returned.
Size() (int64, error) Size() (int64, error)
} }
// ImageCloser is an Image with a Close() method which must be called by the user.
// This is returned by ImageReference.NewImage, which transparently instantiates a types.ImageSource,
// to ensure that the ImageSource is closed.
type ImageCloser interface {
Image
// Close removes resources associated with an initialized ImageCloser.
Close() error
}
// ManifestUpdateOptions is a way to pass named optional arguments to Image.UpdatedManifest // ManifestUpdateOptions is a way to pass named optional arguments to Image.UpdatedManifest
type ManifestUpdateOptions struct { type ManifestUpdateOptions struct {
LayerInfos []BlobInfo // Complete BlobInfos (size+digest+urls+annotations) which should replace the originals, in order (the root layer first, and then successive layered layers). BlobInfos' MediaType fields are ignored. LayerInfos []BlobInfo // Complete BlobInfos (size+digest+urls+annotations) which should replace the originals, in order (the root layer first, and then successive layered layers). BlobInfos' MediaType fields are ignored.
@ -308,6 +321,10 @@ type SystemContext struct {
SystemRegistriesConfPath string SystemRegistriesConfPath string
// If not "", overrides the default path for the authentication file // If not "", overrides the default path for the authentication file
AuthFilePath string AuthFilePath string
// If not "", overrides the use of platform.GOARCH when choosing an image or verifying architecture match.
ArchitectureChoice string
// If not "", overrides the use of platform.GOOS when choosing an image or verifying OS match.
OSChoice string
// === OCI.Transport overrides === // === OCI.Transport overrides ===
// If not "", a directory containing a CA certificate (ending with ".crt"), // If not "", a directory containing a CA certificate (ending with ".crt"),

View File

@ -227,20 +227,20 @@ func parseOptions(options []string) (*overlayOptions, error) {
} }
key = strings.ToLower(key) key = strings.ToLower(key)
switch key { switch key {
case "overlay.override_kernel_check", "overlay2.override_kernel_check": case ".override_kernel_check", "overlay.override_kernel_check", "overlay2.override_kernel_check":
logrus.Debugf("overlay: override_kernelcheck=%s", val) logrus.Debugf("overlay: override_kernelcheck=%s", val)
o.overrideKernelCheck, err = strconv.ParseBool(val) o.overrideKernelCheck, err = strconv.ParseBool(val)
if err != nil { if err != nil {
return nil, err return nil, err
} }
case "overlay.size", "overlay2.size": case ".size", "overlay.size", "overlay2.size":
logrus.Debugf("overlay: size=%s", val) logrus.Debugf("overlay: size=%s", val)
size, err := units.RAMInBytes(val) size, err := units.RAMInBytes(val)
if err != nil { if err != nil {
return nil, err return nil, err
} }
o.quota.Size = uint64(size) o.quota.Size = uint64(size)
case "overlay.imagestore", "overlay2.imagestore": case ".imagestore", "overlay.imagestore", "overlay2.imagestore":
logrus.Debugf("overlay: imagestore=%s", val) logrus.Debugf("overlay: imagestore=%s", val)
// Additional read only image stores to use for lower paths // Additional read only image stores to use for lower paths
for _, store := range strings.Split(val, ",") { for _, store := range strings.Split(val, ",") {

View File

@ -36,6 +36,11 @@ func Init(home string, options []string, uidMaps, gidMaps []idtools.IDMap) (grap
for _, option := range options { for _, option := range options {
if strings.HasPrefix(option, "vfs.imagestore=") { if strings.HasPrefix(option, "vfs.imagestore=") {
d.homes = append(d.homes, strings.Split(option[15:], ",")...) d.homes = append(d.homes, strings.Split(option[15:], ",")...)
continue
}
if strings.HasPrefix(option, ".imagestore=") {
d.homes = append(d.homes, strings.Split(option[12:], ",")...)
continue
} }
} }
return graphdriver.NewNaiveDiffDriver(d, uidMaps, gidMaps), nil return graphdriver.NewNaiveDiffDriver(d, uidMaps, gidMaps), nil

View File

@ -15,7 +15,7 @@ github.com/pmezard/go-difflib v1.0.0
github.com/sirupsen/logrus v1.0.0 github.com/sirupsen/logrus v1.0.0
github.com/stretchr/testify 4d4bfba8f1d1027c4fdbe371823030df51419987 github.com/stretchr/testify 4d4bfba8f1d1027c4fdbe371823030df51419987
github.com/tchap/go-patricia v2.2.6 github.com/tchap/go-patricia v2.2.6
github.com/vbatts/tar-split bd4c5d64c3e9297f410025a3b1bd0c58f659e721 github.com/vbatts/tar-split v0.10.2
golang.org/x/net 7dcfb8076726a3fdd9353b6b8a1f1b6be6811bd6 golang.org/x/net 7dcfb8076726a3fdd9353b6b8a1f1b6be6811bd6
golang.org/x/sys 07c182904dbd53199946ba614a412c61d3c548f5 golang.org/x/sys 07c182904dbd53199946ba614a412c61d3c548f5
github.com/pquerna/ffjson d49c2bc1aa135aad0c6f4fc2056623ec78f5d5ac github.com/pquerna/ffjson d49c2bc1aa135aad0c6f4fc2056623ec78f5d5ac

60
vendor/github.com/docker/docker/hack/README.md generated vendored Normal file
View File

@ -0,0 +1,60 @@
## About
This directory contains a collection of scripts used to build and manage this
repository. If there are any issues regarding the intention of a particular
script (or even part of a certain script), please reach out to us.
It may help us either refine our current scripts, or add on new ones
that are appropriate for a given use case.
## DinD (dind.sh)
DinD is a wrapper script which allows Docker to be run inside a Docker
container. DinD requires the container to
be run with privileged mode enabled.
## Generate Authors (generate-authors.sh)
Generates AUTHORS; a file with all the names and corresponding emails of
individual contributors. AUTHORS can be found in the home directory of
this repository.
## Make
There are two make files, each with different extensions. Neither are supposed
to be called directly; only invoke `make`. Both scripts run inside a Docker
container.
### make.ps1
- The Windows native build script that uses PowerShell semantics; it is limited
unlike `hack\make.sh` since it does not provide support for the full set of
operations provided by the Linux counterpart, `make.sh`. However, `make.ps1`
does provide support for local Windows development and Windows to Windows CI.
More information is found within `make.ps1` by the author, @jhowardmsft
### make.sh
- Referenced via `make test` when running tests on a local machine,
or directly referenced when running tests inside a Docker development container.
- When running on a local machine, `make test` to run all tests found in
`test`, `test-unit`, `test-integration`, and `test-docker-py` on
your local machine. The default timeout is set in `make.sh` to 60 minutes
(`${TIMEOUT:=60m}`), since it currently takes up to an hour to run
all of the tests.
- When running inside a Docker development container, `hack/make.sh` does
not have a single target that runs all the tests. You need to provide a
single command line with multiple targets that performs the same thing.
An example referenced from [Run targets inside a development container](https://docs.docker.com/opensource/project/test-and-docs/#run-targets-inside-a-development-container): `root@5f8630b873fe:/go/src/github.com/moby/moby# hack/make.sh dynbinary binary cross test-unit test-integration test-docker-py`
- For more information related to testing outside the scope of this README,
refer to
[Run tests and test documentation](https://docs.docker.com/opensource/project/test-and-docs/)
## Release (release.sh)
Releases any bundles built by `make` on a public AWS S3 bucket.
For information regarding configuration, please view `release.sh`.
## Vendor (vendor.sh)
A shell script that is a wrapper around Vndr. For information on how to use
this, please refer to [vndr's README](https://github.com/LK4D4/vndr/blob/master/README.md)

View File

@ -0,0 +1,69 @@
# Integration Testing on Swarm
IT on Swarm allows you to execute integration test in parallel across a Docker Swarm cluster
## Architecture
### Master service
- Works as a funker caller
- Calls a worker funker (`-worker-service`) with a chunk of `-check.f` filter strings (passed as a file via `-input` flag, typically `/mnt/input`)
### Worker service
- Works as a funker callee
- Executes an equivalent of `TESTFLAGS=-check.f TestFoo|TestBar|TestBaz ... make test-integration-cli` using the bind-mounted API socket (`docker.sock`)
### Client
- Controls master and workers via `docker stack`
- No need to have a local daemon
Typically, the master and workers are supposed to be running on a cloud environment,
while the client is supposed to be running on a laptop, e.g. Docker for Mac/Windows.
## Requirement
- Docker daemon 1.13 or later
- Private registry for distributed execution with multiple nodes
## Usage
### Step 1: Prepare images
$ make build-integration-cli-on-swarm
Following environment variables are known to work in this step:
- `BUILDFLAGS`
- `DOCKER_INCREMENTAL_BINARY`
Note: during the transition into Moby Project, you might need to create a symbolic link `$GOPATH/src/github.com/docker/docker` to `$GOPATH/src/github.com/moby/moby`.
### Step 2: Execute tests
$ ./hack/integration-cli-on-swarm/integration-cli-on-swarm -replicas 40 -push-worker-image YOUR_REGISTRY.EXAMPLE.COM/integration-cli-worker:latest
Following environment variables are known to work in this step:
- `DOCKER_GRAPHDRIVER`
- `DOCKER_EXPERIMENTAL`
#### Flags
Basic flags:
- `-replicas N`: the number of worker service replicas. i.e. degree of parallelism.
- `-chunks N`: the number of chunks. By default, `chunks` == `replicas`.
- `-push-worker-image REGISTRY/IMAGE:TAG`: push the worker image to the registry. Note that if you have only single node and hence you do not need a private registry, you do not need to specify `-push-worker-image`.
Experimental flags for mitigating makespan nonuniformity:
- `-shuffle`: Shuffle the test filter strings
Flags for debugging IT on Swarm itself:
- `-rand-seed N`: the random seed. This flag is useful for deterministic replaying. By default(0), the timestamp is used.
- `-filters-file FILE`: the file contains `-check.f` strings. By default, the file is automatically generated.
- `-dry-run`: skip the actual workload
- `keep-executor`: do not auto-remove executor containers, which is used for running privileged programs on Swarm

View File

@ -0,0 +1,2 @@
# dependencies specific to worker (i.e. github.com/docker/docker/...) are not vendored here
github.com/bfirsh/funker-go eaa0a2e06f30e72c9a0b7f858951e581e26ef773

View File

@ -15,7 +15,7 @@ github.com/coreos/pkg v3
github.com/godbus/dbus v3 github.com/godbus/dbus v3
github.com/golang/protobuf 18c9bb3261723cd5401db4d0c9fbc5c3b6c70fe8 github.com/golang/protobuf 18c9bb3261723cd5401db4d0c9fbc5c3b6c70fe8
# Command-line interface. # Command-line interface.
github.com/docker/docker 0f5c9d301b9b1cca66b3ea0f9dec3b5317d3686d github.com/cyphar/filepath-securejoin v0.2.1
github.com/docker/go-units v0.2.0 github.com/docker/go-units v0.2.0
github.com/urfave/cli d53eb991652b1d438abdd34ce4bfa3ef1539108e github.com/urfave/cli d53eb991652b1d438abdd34ce4bfa3ef1539108e
golang.org/x/sys 7ddbeae9ae08c6a06a59597f0c9edbc5ff2444ce https://github.com/golang/sys golang.org/x/sys 7ddbeae9ae08c6a06a59597f0c9edbc5ff2444ce https://github.com/golang/sys

View File

@ -220,12 +220,15 @@ func ConfigureServer(s *http.Server, conf *Server) error {
} else if s.TLSConfig.CipherSuites != nil { } else if s.TLSConfig.CipherSuites != nil {
// If they already provided a CipherSuite list, return // If they already provided a CipherSuite list, return
// an error if it has a bad order or is missing // an error if it has a bad order or is missing
// ECDHE_RSA_WITH_AES_128_GCM_SHA256. // ECDHE_RSA_WITH_AES_128_GCM_SHA256 or ECDHE_ECDSA_WITH_AES_128_GCM_SHA256.
const requiredCipher = tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
haveRequired := false haveRequired := false
sawBad := false sawBad := false
for i, cs := range s.TLSConfig.CipherSuites { for i, cs := range s.TLSConfig.CipherSuites {
if cs == requiredCipher { switch cs {
case tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
// Alternative MTI cipher to not discourage ECDSA-only servers.
// See http://golang.org/cl/30721 for further information.
tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256:
haveRequired = true haveRequired = true
} }
if isBadCipher(cs) { if isBadCipher(cs) {
@ -235,7 +238,7 @@ func ConfigureServer(s *http.Server, conf *Server) error {
} }
} }
if !haveRequired { if !haveRequired {
return fmt.Errorf("http2: TLSConfig.CipherSuites is missing HTTP/2-required TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256") return fmt.Errorf("http2: TLSConfig.CipherSuites is missing an HTTP/2-required AES_128_GCM_SHA256 cipher.")
} }
} }

View File

@ -1,27 +0,0 @@
// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package unix
import (
"os"
"syscall"
)
// FIXME: unexported function from os
// syscallMode returns the syscall-specific mode bits from Go's portable mode bits.
func syscallMode(i os.FileMode) (o uint32) {
o |= uint32(i.Perm())
if i&os.ModeSetuid != 0 {
o |= syscall.S_ISUID
}
if i&os.ModeSetgid != 0 {
o |= syscall.S_ISGID
}
if i&os.ModeSticky != 0 {
o |= syscall.S_ISVTX
}
// No mapping for Go's ModeTemporary (plan9 only).
return
}

View File

@ -270,6 +270,52 @@ func IoctlGetTermios(fd int, req uint) (*Termios, error) {
return &value, err return &value, err
} }
func Uname(uname *Utsname) error {
mib := []_C_int{CTL_KERN, KERN_OSTYPE}
n := unsafe.Sizeof(uname.Sysname)
if err := sysctl(mib, &uname.Sysname[0], &n, nil, 0); err != nil {
return err
}
mib = []_C_int{CTL_KERN, KERN_HOSTNAME}
n = unsafe.Sizeof(uname.Nodename)
if err := sysctl(mib, &uname.Nodename[0], &n, nil, 0); err != nil {
return err
}
mib = []_C_int{CTL_KERN, KERN_OSRELEASE}
n = unsafe.Sizeof(uname.Release)
if err := sysctl(mib, &uname.Release[0], &n, nil, 0); err != nil {
return err
}
mib = []_C_int{CTL_KERN, KERN_VERSION}
n = unsafe.Sizeof(uname.Version)
if err := sysctl(mib, &uname.Version[0], &n, nil, 0); err != nil {
return err
}
// The version might have newlines or tabs in it, convert them to
// spaces.
for i, b := range uname.Version {
if b == '\n' || b == '\t' {
if i == len(uname.Version)-1 {
uname.Version[i] = 0
} else {
uname.Version[i] = ' '
}
}
}
mib = []_C_int{CTL_HW, HW_MACHINE}
n = unsafe.Sizeof(uname.Machine)
if err := sysctl(mib, &uname.Machine[0], &n, nil, 0); err != nil {
return err
}
return nil
}
/* /*
* Exposed directly * Exposed directly
*/ */

View File

@ -130,6 +130,45 @@ func setattrlistTimes(path string, times []Timespec, flags int) error {
return ENOSYS return ENOSYS
} }
//sys ioctl(fd int, req uint, arg uintptr) (err error)
// ioctl itself should not be exposed directly, but additional get/set
// functions for specific types are permissible.
// IoctlSetInt performs an ioctl operation which sets an integer value
// on fd, using the specified request number.
func IoctlSetInt(fd int, req uint, value int) error {
return ioctl(fd, req, uintptr(value))
}
func IoctlSetWinsize(fd int, req uint, value *Winsize) error {
return ioctl(fd, req, uintptr(unsafe.Pointer(value)))
}
func IoctlSetTermios(fd int, req uint, value *Termios) error {
return ioctl(fd, req, uintptr(unsafe.Pointer(value)))
}
// IoctlGetInt performs an ioctl operation which gets an integer value
// from fd, using the specified request number.
func IoctlGetInt(fd int, req uint) (int, error) {
var value int
err := ioctl(fd, req, uintptr(unsafe.Pointer(&value)))
return value, err
}
func IoctlGetWinsize(fd int, req uint) (*Winsize, error) {
var value Winsize
err := ioctl(fd, req, uintptr(unsafe.Pointer(&value)))
return &value, err
}
func IoctlGetTermios(fd int, req uint) (*Termios, error) {
var value Termios
err := ioctl(fd, req, uintptr(unsafe.Pointer(&value)))
return &value, err
}
/* /*
* Exposed directly * Exposed directly
*/ */
@ -230,7 +269,6 @@ func setattrlistTimes(path string, times []Timespec, flags int) error {
// Getlogin // Getlogin
// Sigpending // Sigpending
// Sigaltstack // Sigaltstack
// Ioctl
// Reboot // Reboot
// Execve // Execve
// Vfork // Vfork

View File

@ -1125,6 +1125,10 @@ func PtracePokeData(pid int, addr uintptr, data []byte) (count int, err error) {
return ptracePoke(PTRACE_POKEDATA, PTRACE_PEEKDATA, pid, addr, data) return ptracePoke(PTRACE_POKEDATA, PTRACE_PEEKDATA, pid, addr, data)
} }
func PtracePokeUser(pid int, addr uintptr, data []byte) (count int, err error) {
return ptracePoke(PTRACE_POKEUSR, PTRACE_PEEKUSR, pid, addr, data)
}
func PtraceGetRegs(pid int, regsout *PtraceRegs) (err error) { func PtraceGetRegs(pid int, regsout *PtraceRegs) (err error) {
return ptrace(PTRACE_GETREGS, pid, 0, uintptr(unsafe.Pointer(regsout))) return ptrace(PTRACE_GETREGS, pid, 0, uintptr(unsafe.Pointer(regsout)))
} }

View File

@ -55,7 +55,6 @@ func sysctlNodes(mib []_C_int) (nodes []Sysctlnode, err error) {
} }
func nametomib(name string) (mib []_C_int, err error) { func nametomib(name string) (mib []_C_int, err error) {
// Split name into components. // Split name into components.
var parts []string var parts []string
last := 0 last := 0
@ -129,6 +128,45 @@ func setattrlistTimes(path string, times []Timespec, flags int) error {
return ENOSYS return ENOSYS
} }
//sys ioctl(fd int, req uint, arg uintptr) (err error)
// ioctl itself should not be exposed directly, but additional get/set
// functions for specific types are permissible.
// IoctlSetInt performs an ioctl operation which sets an integer value
// on fd, using the specified request number.
func IoctlSetInt(fd int, req uint, value int) error {
return ioctl(fd, req, uintptr(value))
}
func IoctlSetWinsize(fd int, req uint, value *Winsize) error {
return ioctl(fd, req, uintptr(unsafe.Pointer(value)))
}
func IoctlSetTermios(fd int, req uint, value *Termios) error {
return ioctl(fd, req, uintptr(unsafe.Pointer(value)))
}
// IoctlGetInt performs an ioctl operation which gets an integer value
// from fd, using the specified request number.
func IoctlGetInt(fd int, req uint) (int, error) {
var value int
err := ioctl(fd, req, uintptr(unsafe.Pointer(&value)))
return value, err
}
func IoctlGetWinsize(fd int, req uint) (*Winsize, error) {
var value Winsize
err := ioctl(fd, req, uintptr(unsafe.Pointer(&value)))
return &value, err
}
func IoctlGetTermios(fd int, req uint) (*Termios, error) {
var value Termios
err := ioctl(fd, req, uintptr(unsafe.Pointer(&value)))
return &value, err
}
/* /*
* Exposed directly * Exposed directly
*/ */
@ -389,7 +427,6 @@ func setattrlistTimes(path string, times []Timespec, flags int) error {
// getitimer // getitimer
// getvfsstat // getvfsstat
// getxattr // getxattr
// ioctl
// ktrace // ktrace
// lchflags // lchflags
// lchmod // lchmod

View File

@ -13,6 +13,7 @@
package unix package unix
import ( import (
"sort"
"syscall" "syscall"
"unsafe" "unsafe"
) )
@ -32,23 +33,11 @@ type SockaddrDatalink struct {
func Syscall9(trap, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err syscall.Errno) func Syscall9(trap, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err syscall.Errno)
func nametomib(name string) (mib []_C_int, err error) { func nametomib(name string) (mib []_C_int, err error) {
i := sort.Search(len(sysctlMib), func(i int) bool {
// Perform lookup via a binary search return sysctlMib[i].ctlname >= name
left := 0 })
right := len(sysctlMib) - 1 if i < len(sysctlMib) && sysctlMib[i].ctlname == name {
for { return sysctlMib[i].ctloid, nil
idx := left + (right-left)/2
switch {
case name == sysctlMib[idx].ctlname:
return sysctlMib[idx].ctloid, nil
case name > sysctlMib[idx].ctlname:
left = idx + 1
default:
right = idx - 1
}
if left > right {
break
}
} }
return nil, EINVAL return nil, EINVAL
} }
@ -107,6 +96,45 @@ func setattrlistTimes(path string, times []Timespec, flags int) error {
return ENOSYS return ENOSYS
} }
//sys ioctl(fd int, req uint, arg uintptr) (err error)
// ioctl itself should not be exposed directly, but additional get/set
// functions for specific types are permissible.
// IoctlSetInt performs an ioctl operation which sets an integer value
// on fd, using the specified request number.
func IoctlSetInt(fd int, req uint, value int) error {
return ioctl(fd, req, uintptr(value))
}
func IoctlSetWinsize(fd int, req uint, value *Winsize) error {
return ioctl(fd, req, uintptr(unsafe.Pointer(value)))
}
func IoctlSetTermios(fd int, req uint, value *Termios) error {
return ioctl(fd, req, uintptr(unsafe.Pointer(value)))
}
// IoctlGetInt performs an ioctl operation which gets an integer value
// from fd, using the specified request number.
func IoctlGetInt(fd int, req uint) (int, error) {
var value int
err := ioctl(fd, req, uintptr(unsafe.Pointer(&value)))
return value, err
}
func IoctlGetWinsize(fd int, req uint) (*Winsize, error) {
var value Winsize
err := ioctl(fd, req, uintptr(unsafe.Pointer(&value)))
return &value, err
}
func IoctlGetTermios(fd int, req uint) (*Termios, error) {
var value Termios
err := ioctl(fd, req, uintptr(unsafe.Pointer(&value)))
return &value, err
}
/* /*
* Exposed directly * Exposed directly
*/ */
@ -227,7 +255,6 @@ func setattrlistTimes(path string, times []Timespec, flags int) error {
// getresuid // getresuid
// getrtable // getrtable
// getthrid // getthrid
// ioctl
// ktrace // ktrace
// lfs_bmapv // lfs_bmapv
// lfs_markv // lfs_markv

View File

@ -249,6 +249,8 @@ const (
CSTOP = 0x13 CSTOP = 0x13
CSTOPB = 0x400 CSTOPB = 0x400
CSUSP = 0x1a CSUSP = 0x1a
CTL_HW = 0x6
CTL_KERN = 0x1
CTL_MAXNAME = 0xc CTL_MAXNAME = 0xc
CTL_NET = 0x4 CTL_NET = 0x4
DLT_A429 = 0xb8 DLT_A429 = 0xb8
@ -510,6 +512,7 @@ const (
F_PATHPKG_CHECK = 0x34 F_PATHPKG_CHECK = 0x34
F_PEOFPOSMODE = 0x3 F_PEOFPOSMODE = 0x3
F_PREALLOCATE = 0x2a F_PREALLOCATE = 0x2a
F_PUNCHHOLE = 0x63
F_RDADVISE = 0x2c F_RDADVISE = 0x2c
F_RDAHEAD = 0x2d F_RDAHEAD = 0x2d
F_RDLCK = 0x1 F_RDLCK = 0x1
@ -526,10 +529,12 @@ const (
F_SINGLE_WRITER = 0x4c F_SINGLE_WRITER = 0x4c
F_THAW_FS = 0x36 F_THAW_FS = 0x36
F_TRANSCODEKEY = 0x4b F_TRANSCODEKEY = 0x4b
F_TRIM_ACTIVE_FILE = 0x64
F_UNLCK = 0x2 F_UNLCK = 0x2
F_VOLPOSMODE = 0x4 F_VOLPOSMODE = 0x4
F_WRLCK = 0x3 F_WRLCK = 0x3
HUPCL = 0x4000 HUPCL = 0x4000
HW_MACHINE = 0x1
ICANON = 0x100 ICANON = 0x100
ICMP6_FILTER = 0x12 ICMP6_FILTER = 0x12
ICRNL = 0x100 ICRNL = 0x100
@ -766,6 +771,7 @@ const (
IPV6_FAITH = 0x1d IPV6_FAITH = 0x1d
IPV6_FLOWINFO_MASK = 0xffffff0f IPV6_FLOWINFO_MASK = 0xffffff0f
IPV6_FLOWLABEL_MASK = 0xffff0f00 IPV6_FLOWLABEL_MASK = 0xffff0f00
IPV6_FLOW_ECN_MASK = 0x300
IPV6_FRAGTTL = 0x3c IPV6_FRAGTTL = 0x3c
IPV6_FW_ADD = 0x1e IPV6_FW_ADD = 0x1e
IPV6_FW_DEL = 0x1f IPV6_FW_DEL = 0x1f
@ -856,6 +862,7 @@ const (
IP_RECVOPTS = 0x5 IP_RECVOPTS = 0x5
IP_RECVPKTINFO = 0x1a IP_RECVPKTINFO = 0x1a
IP_RECVRETOPTS = 0x6 IP_RECVRETOPTS = 0x6
IP_RECVTOS = 0x1b
IP_RECVTTL = 0x18 IP_RECVTTL = 0x18
IP_RETOPTS = 0x8 IP_RETOPTS = 0x8
IP_RF = 0x8000 IP_RF = 0x8000
@ -874,6 +881,10 @@ const (
IXANY = 0x800 IXANY = 0x800
IXOFF = 0x400 IXOFF = 0x400
IXON = 0x200 IXON = 0x200
KERN_HOSTNAME = 0xa
KERN_OSRELEASE = 0x2
KERN_OSTYPE = 0x1
KERN_VERSION = 0x4
LOCK_EX = 0x2 LOCK_EX = 0x2
LOCK_NB = 0x4 LOCK_NB = 0x4
LOCK_SH = 0x1 LOCK_SH = 0x1

View File

@ -249,6 +249,8 @@ const (
CSTOP = 0x13 CSTOP = 0x13
CSTOPB = 0x400 CSTOPB = 0x400
CSUSP = 0x1a CSUSP = 0x1a
CTL_HW = 0x6
CTL_KERN = 0x1
CTL_MAXNAME = 0xc CTL_MAXNAME = 0xc
CTL_NET = 0x4 CTL_NET = 0x4
DLT_A429 = 0xb8 DLT_A429 = 0xb8
@ -510,6 +512,7 @@ const (
F_PATHPKG_CHECK = 0x34 F_PATHPKG_CHECK = 0x34
F_PEOFPOSMODE = 0x3 F_PEOFPOSMODE = 0x3
F_PREALLOCATE = 0x2a F_PREALLOCATE = 0x2a
F_PUNCHHOLE = 0x63
F_RDADVISE = 0x2c F_RDADVISE = 0x2c
F_RDAHEAD = 0x2d F_RDAHEAD = 0x2d
F_RDLCK = 0x1 F_RDLCK = 0x1
@ -526,10 +529,12 @@ const (
F_SINGLE_WRITER = 0x4c F_SINGLE_WRITER = 0x4c
F_THAW_FS = 0x36 F_THAW_FS = 0x36
F_TRANSCODEKEY = 0x4b F_TRANSCODEKEY = 0x4b
F_TRIM_ACTIVE_FILE = 0x64
F_UNLCK = 0x2 F_UNLCK = 0x2
F_VOLPOSMODE = 0x4 F_VOLPOSMODE = 0x4
F_WRLCK = 0x3 F_WRLCK = 0x3
HUPCL = 0x4000 HUPCL = 0x4000
HW_MACHINE = 0x1
ICANON = 0x100 ICANON = 0x100
ICMP6_FILTER = 0x12 ICMP6_FILTER = 0x12
ICRNL = 0x100 ICRNL = 0x100
@ -766,6 +771,7 @@ const (
IPV6_FAITH = 0x1d IPV6_FAITH = 0x1d
IPV6_FLOWINFO_MASK = 0xffffff0f IPV6_FLOWINFO_MASK = 0xffffff0f
IPV6_FLOWLABEL_MASK = 0xffff0f00 IPV6_FLOWLABEL_MASK = 0xffff0f00
IPV6_FLOW_ECN_MASK = 0x300
IPV6_FRAGTTL = 0x3c IPV6_FRAGTTL = 0x3c
IPV6_FW_ADD = 0x1e IPV6_FW_ADD = 0x1e
IPV6_FW_DEL = 0x1f IPV6_FW_DEL = 0x1f
@ -856,6 +862,7 @@ const (
IP_RECVOPTS = 0x5 IP_RECVOPTS = 0x5
IP_RECVPKTINFO = 0x1a IP_RECVPKTINFO = 0x1a
IP_RECVRETOPTS = 0x6 IP_RECVRETOPTS = 0x6
IP_RECVTOS = 0x1b
IP_RECVTTL = 0x18 IP_RECVTTL = 0x18
IP_RETOPTS = 0x8 IP_RETOPTS = 0x8
IP_RF = 0x8000 IP_RF = 0x8000
@ -874,6 +881,10 @@ const (
IXANY = 0x800 IXANY = 0x800
IXOFF = 0x400 IXOFF = 0x400
IXON = 0x200 IXON = 0x200
KERN_HOSTNAME = 0xa
KERN_OSRELEASE = 0x2
KERN_OSTYPE = 0x1
KERN_VERSION = 0x4
LOCK_EX = 0x2 LOCK_EX = 0x2
LOCK_NB = 0x4 LOCK_NB = 0x4
LOCK_SH = 0x1 LOCK_SH = 0x1

View File

@ -249,6 +249,8 @@ const (
CSTOP = 0x13 CSTOP = 0x13
CSTOPB = 0x400 CSTOPB = 0x400
CSUSP = 0x1a CSUSP = 0x1a
CTL_HW = 0x6
CTL_KERN = 0x1
CTL_MAXNAME = 0xc CTL_MAXNAME = 0xc
CTL_NET = 0x4 CTL_NET = 0x4
DLT_A429 = 0xb8 DLT_A429 = 0xb8
@ -510,6 +512,7 @@ const (
F_PATHPKG_CHECK = 0x34 F_PATHPKG_CHECK = 0x34
F_PEOFPOSMODE = 0x3 F_PEOFPOSMODE = 0x3
F_PREALLOCATE = 0x2a F_PREALLOCATE = 0x2a
F_PUNCHHOLE = 0x63
F_RDADVISE = 0x2c F_RDADVISE = 0x2c
F_RDAHEAD = 0x2d F_RDAHEAD = 0x2d
F_RDLCK = 0x1 F_RDLCK = 0x1
@ -526,10 +529,12 @@ const (
F_SINGLE_WRITER = 0x4c F_SINGLE_WRITER = 0x4c
F_THAW_FS = 0x36 F_THAW_FS = 0x36
F_TRANSCODEKEY = 0x4b F_TRANSCODEKEY = 0x4b
F_TRIM_ACTIVE_FILE = 0x64
F_UNLCK = 0x2 F_UNLCK = 0x2
F_VOLPOSMODE = 0x4 F_VOLPOSMODE = 0x4
F_WRLCK = 0x3 F_WRLCK = 0x3
HUPCL = 0x4000 HUPCL = 0x4000
HW_MACHINE = 0x1
ICANON = 0x100 ICANON = 0x100
ICMP6_FILTER = 0x12 ICMP6_FILTER = 0x12
ICRNL = 0x100 ICRNL = 0x100
@ -766,6 +771,7 @@ const (
IPV6_FAITH = 0x1d IPV6_FAITH = 0x1d
IPV6_FLOWINFO_MASK = 0xffffff0f IPV6_FLOWINFO_MASK = 0xffffff0f
IPV6_FLOWLABEL_MASK = 0xffff0f00 IPV6_FLOWLABEL_MASK = 0xffff0f00
IPV6_FLOW_ECN_MASK = 0x300
IPV6_FRAGTTL = 0x3c IPV6_FRAGTTL = 0x3c
IPV6_FW_ADD = 0x1e IPV6_FW_ADD = 0x1e
IPV6_FW_DEL = 0x1f IPV6_FW_DEL = 0x1f
@ -856,6 +862,7 @@ const (
IP_RECVOPTS = 0x5 IP_RECVOPTS = 0x5
IP_RECVPKTINFO = 0x1a IP_RECVPKTINFO = 0x1a
IP_RECVRETOPTS = 0x6 IP_RECVRETOPTS = 0x6
IP_RECVTOS = 0x1b
IP_RECVTTL = 0x18 IP_RECVTTL = 0x18
IP_RETOPTS = 0x8 IP_RETOPTS = 0x8
IP_RF = 0x8000 IP_RF = 0x8000
@ -874,6 +881,10 @@ const (
IXANY = 0x800 IXANY = 0x800
IXOFF = 0x400 IXOFF = 0x400
IXON = 0x200 IXON = 0x200
KERN_HOSTNAME = 0xa
KERN_OSRELEASE = 0x2
KERN_OSTYPE = 0x1
KERN_VERSION = 0x4
LOCK_EX = 0x2 LOCK_EX = 0x2
LOCK_NB = 0x4 LOCK_NB = 0x4
LOCK_SH = 0x1 LOCK_SH = 0x1

View File

@ -249,6 +249,8 @@ const (
CSTOP = 0x13 CSTOP = 0x13
CSTOPB = 0x400 CSTOPB = 0x400
CSUSP = 0x1a CSUSP = 0x1a
CTL_HW = 0x6
CTL_KERN = 0x1
CTL_MAXNAME = 0xc CTL_MAXNAME = 0xc
CTL_NET = 0x4 CTL_NET = 0x4
DLT_A429 = 0xb8 DLT_A429 = 0xb8
@ -510,6 +512,7 @@ const (
F_PATHPKG_CHECK = 0x34 F_PATHPKG_CHECK = 0x34
F_PEOFPOSMODE = 0x3 F_PEOFPOSMODE = 0x3
F_PREALLOCATE = 0x2a F_PREALLOCATE = 0x2a
F_PUNCHHOLE = 0x63
F_RDADVISE = 0x2c F_RDADVISE = 0x2c
F_RDAHEAD = 0x2d F_RDAHEAD = 0x2d
F_RDLCK = 0x1 F_RDLCK = 0x1
@ -526,10 +529,12 @@ const (
F_SINGLE_WRITER = 0x4c F_SINGLE_WRITER = 0x4c
F_THAW_FS = 0x36 F_THAW_FS = 0x36
F_TRANSCODEKEY = 0x4b F_TRANSCODEKEY = 0x4b
F_TRIM_ACTIVE_FILE = 0x64
F_UNLCK = 0x2 F_UNLCK = 0x2
F_VOLPOSMODE = 0x4 F_VOLPOSMODE = 0x4
F_WRLCK = 0x3 F_WRLCK = 0x3
HUPCL = 0x4000 HUPCL = 0x4000
HW_MACHINE = 0x1
ICANON = 0x100 ICANON = 0x100
ICMP6_FILTER = 0x12 ICMP6_FILTER = 0x12
ICRNL = 0x100 ICRNL = 0x100
@ -766,6 +771,7 @@ const (
IPV6_FAITH = 0x1d IPV6_FAITH = 0x1d
IPV6_FLOWINFO_MASK = 0xffffff0f IPV6_FLOWINFO_MASK = 0xffffff0f
IPV6_FLOWLABEL_MASK = 0xffff0f00 IPV6_FLOWLABEL_MASK = 0xffff0f00
IPV6_FLOW_ECN_MASK = 0x300
IPV6_FRAGTTL = 0x3c IPV6_FRAGTTL = 0x3c
IPV6_FW_ADD = 0x1e IPV6_FW_ADD = 0x1e
IPV6_FW_DEL = 0x1f IPV6_FW_DEL = 0x1f
@ -856,6 +862,7 @@ const (
IP_RECVOPTS = 0x5 IP_RECVOPTS = 0x5
IP_RECVPKTINFO = 0x1a IP_RECVPKTINFO = 0x1a
IP_RECVRETOPTS = 0x6 IP_RECVRETOPTS = 0x6
IP_RECVTOS = 0x1b
IP_RECVTTL = 0x18 IP_RECVTTL = 0x18
IP_RETOPTS = 0x8 IP_RETOPTS = 0x8
IP_RF = 0x8000 IP_RF = 0x8000
@ -874,6 +881,10 @@ const (
IXANY = 0x800 IXANY = 0x800
IXOFF = 0x400 IXOFF = 0x400
IXON = 0x200 IXON = 0x200
KERN_HOSTNAME = 0xa
KERN_OSRELEASE = 0x2
KERN_OSTYPE = 0x1
KERN_VERSION = 0x4
LOCK_EX = 0x2 LOCK_EX = 0x2
LOCK_NB = 0x4 LOCK_NB = 0x4
LOCK_SH = 0x1 LOCK_SH = 0x1

View File

@ -623,6 +623,7 @@ const (
IN_OPEN = 0x20 IN_OPEN = 0x20
IN_Q_OVERFLOW = 0x4000 IN_Q_OVERFLOW = 0x4000
IN_UNMOUNT = 0x2000 IN_UNMOUNT = 0x2000
IOCTL_VM_SOCKETS_GET_LOCAL_CID = 0x7b9
IPPROTO_AH = 0x33 IPPROTO_AH = 0x33
IPPROTO_BEETPH = 0x5e IPPROTO_BEETPH = 0x5e
IPPROTO_COMP = 0x6c IPPROTO_COMP = 0x6c

View File

@ -623,6 +623,7 @@ const (
IN_OPEN = 0x20 IN_OPEN = 0x20
IN_Q_OVERFLOW = 0x4000 IN_Q_OVERFLOW = 0x4000
IN_UNMOUNT = 0x2000 IN_UNMOUNT = 0x2000
IOCTL_VM_SOCKETS_GET_LOCAL_CID = 0x7b9
IPPROTO_AH = 0x33 IPPROTO_AH = 0x33
IPPROTO_BEETPH = 0x5e IPPROTO_BEETPH = 0x5e
IPPROTO_COMP = 0x6c IPPROTO_COMP = 0x6c

View File

@ -623,6 +623,7 @@ const (
IN_OPEN = 0x20 IN_OPEN = 0x20
IN_Q_OVERFLOW = 0x4000 IN_Q_OVERFLOW = 0x4000
IN_UNMOUNT = 0x2000 IN_UNMOUNT = 0x2000
IOCTL_VM_SOCKETS_GET_LOCAL_CID = 0x7b9
IPPROTO_AH = 0x33 IPPROTO_AH = 0x33
IPPROTO_BEETPH = 0x5e IPPROTO_BEETPH = 0x5e
IPPROTO_COMP = 0x6c IPPROTO_COMP = 0x6c

View File

@ -625,6 +625,7 @@ const (
IN_OPEN = 0x20 IN_OPEN = 0x20
IN_Q_OVERFLOW = 0x4000 IN_Q_OVERFLOW = 0x4000
IN_UNMOUNT = 0x2000 IN_UNMOUNT = 0x2000
IOCTL_VM_SOCKETS_GET_LOCAL_CID = 0x7b9
IPPROTO_AH = 0x33 IPPROTO_AH = 0x33
IPPROTO_BEETPH = 0x5e IPPROTO_BEETPH = 0x5e
IPPROTO_COMP = 0x6c IPPROTO_COMP = 0x6c

View File

@ -623,6 +623,7 @@ const (
IN_OPEN = 0x20 IN_OPEN = 0x20
IN_Q_OVERFLOW = 0x4000 IN_Q_OVERFLOW = 0x4000
IN_UNMOUNT = 0x2000 IN_UNMOUNT = 0x2000
IOCTL_VM_SOCKETS_GET_LOCAL_CID = 0x200007b9
IPPROTO_AH = 0x33 IPPROTO_AH = 0x33
IPPROTO_BEETPH = 0x5e IPPROTO_BEETPH = 0x5e
IPPROTO_COMP = 0x6c IPPROTO_COMP = 0x6c

View File

@ -623,6 +623,7 @@ const (
IN_OPEN = 0x20 IN_OPEN = 0x20
IN_Q_OVERFLOW = 0x4000 IN_Q_OVERFLOW = 0x4000
IN_UNMOUNT = 0x2000 IN_UNMOUNT = 0x2000
IOCTL_VM_SOCKETS_GET_LOCAL_CID = 0x200007b9
IPPROTO_AH = 0x33 IPPROTO_AH = 0x33
IPPROTO_BEETPH = 0x5e IPPROTO_BEETPH = 0x5e
IPPROTO_COMP = 0x6c IPPROTO_COMP = 0x6c

View File

@ -623,6 +623,7 @@ const (
IN_OPEN = 0x20 IN_OPEN = 0x20
IN_Q_OVERFLOW = 0x4000 IN_Q_OVERFLOW = 0x4000
IN_UNMOUNT = 0x2000 IN_UNMOUNT = 0x2000
IOCTL_VM_SOCKETS_GET_LOCAL_CID = 0x200007b9
IPPROTO_AH = 0x33 IPPROTO_AH = 0x33
IPPROTO_BEETPH = 0x5e IPPROTO_BEETPH = 0x5e
IPPROTO_COMP = 0x6c IPPROTO_COMP = 0x6c

View File

@ -623,6 +623,7 @@ const (
IN_OPEN = 0x20 IN_OPEN = 0x20
IN_Q_OVERFLOW = 0x4000 IN_Q_OVERFLOW = 0x4000
IN_UNMOUNT = 0x2000 IN_UNMOUNT = 0x2000
IOCTL_VM_SOCKETS_GET_LOCAL_CID = 0x200007b9
IPPROTO_AH = 0x33 IPPROTO_AH = 0x33
IPPROTO_BEETPH = 0x5e IPPROTO_BEETPH = 0x5e
IPPROTO_COMP = 0x6c IPPROTO_COMP = 0x6c

View File

@ -623,6 +623,7 @@ const (
IN_OPEN = 0x20 IN_OPEN = 0x20
IN_Q_OVERFLOW = 0x4000 IN_Q_OVERFLOW = 0x4000
IN_UNMOUNT = 0x2000 IN_UNMOUNT = 0x2000
IOCTL_VM_SOCKETS_GET_LOCAL_CID = 0x200007b9
IPPROTO_AH = 0x33 IPPROTO_AH = 0x33
IPPROTO_BEETPH = 0x5e IPPROTO_BEETPH = 0x5e
IPPROTO_COMP = 0x6c IPPROTO_COMP = 0x6c

View File

@ -623,6 +623,7 @@ const (
IN_OPEN = 0x20 IN_OPEN = 0x20
IN_Q_OVERFLOW = 0x4000 IN_Q_OVERFLOW = 0x4000
IN_UNMOUNT = 0x2000 IN_UNMOUNT = 0x2000
IOCTL_VM_SOCKETS_GET_LOCAL_CID = 0x200007b9
IPPROTO_AH = 0x33 IPPROTO_AH = 0x33
IPPROTO_BEETPH = 0x5e IPPROTO_BEETPH = 0x5e
IPPROTO_COMP = 0x6c IPPROTO_COMP = 0x6c

View File

@ -623,6 +623,7 @@ const (
IN_OPEN = 0x20 IN_OPEN = 0x20
IN_Q_OVERFLOW = 0x4000 IN_Q_OVERFLOW = 0x4000
IN_UNMOUNT = 0x2000 IN_UNMOUNT = 0x2000
IOCTL_VM_SOCKETS_GET_LOCAL_CID = 0x7b9
IPPROTO_AH = 0x33 IPPROTO_AH = 0x33
IPPROTO_BEETPH = 0x5e IPPROTO_BEETPH = 0x5e
IPPROTO_COMP = 0x6c IPPROTO_COMP = 0x6c

View File

@ -266,6 +266,17 @@ func fcntl(fd int, cmd int, arg int) (val int, err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func poll(fds *PollFd, nfds int, timeout int) (n int, err error) {
r0, _, e1 := Syscall(SYS_POLL, uintptr(unsafe.Pointer(fds)), uintptr(nfds), uintptr(timeout))
n = int(r0)
if e1 != 0 {
err = errnoErr(e1)
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Madvise(b []byte, behav int) (err error) { func Madvise(b []byte, behav int) (err error) {
var _p0 unsafe.Pointer var _p0 unsafe.Pointer
if len(b) > 0 { if len(b) > 0 {
@ -408,17 +419,6 @@ func ioctl(fd int, req uint, arg uintptr) (err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func poll(fds *PollFd, nfds int, timeout int) (n int, err error) {
r0, _, e1 := Syscall(SYS_POLL, uintptr(unsafe.Pointer(fds)), uintptr(nfds), uintptr(timeout))
n = int(r0)
if e1 != 0 {
err = errnoErr(e1)
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Access(path string, mode uint32) (err error) { func Access(path string, mode uint32) (err error) {
var _p0 *byte var _p0 *byte
_p0, err = BytePtrFromString(path) _p0, err = BytePtrFromString(path)

View File

@ -266,6 +266,17 @@ func fcntl(fd int, cmd int, arg int) (val int, err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func poll(fds *PollFd, nfds int, timeout int) (n int, err error) {
r0, _, e1 := Syscall(SYS_POLL, uintptr(unsafe.Pointer(fds)), uintptr(nfds), uintptr(timeout))
n = int(r0)
if e1 != 0 {
err = errnoErr(e1)
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Madvise(b []byte, behav int) (err error) { func Madvise(b []byte, behav int) (err error) {
var _p0 unsafe.Pointer var _p0 unsafe.Pointer
if len(b) > 0 { if len(b) > 0 {
@ -408,17 +419,6 @@ func ioctl(fd int, req uint, arg uintptr) (err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func poll(fds *PollFd, nfds int, timeout int) (n int, err error) {
r0, _, e1 := Syscall(SYS_POLL, uintptr(unsafe.Pointer(fds)), uintptr(nfds), uintptr(timeout))
n = int(r0)
if e1 != 0 {
err = errnoErr(e1)
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Access(path string, mode uint32) (err error) { func Access(path string, mode uint32) (err error) {
var _p0 *byte var _p0 *byte
_p0, err = BytePtrFromString(path) _p0, err = BytePtrFromString(path)

View File

@ -221,7 +221,7 @@ func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr)
} else { } else {
_p0 = unsafe.Pointer(&_zero) _p0 = unsafe.Pointer(&_zero)
} }
_, _, e1 := Syscall6(SYS_SYSCTL, uintptr(_p0), uintptr(len(mib)), uintptr(unsafe.Pointer(old)), uintptr(unsafe.Pointer(oldlen)), uintptr(unsafe.Pointer(new)), uintptr(newlen)) _, _, e1 := Syscall6(SYS___SYSCTL, uintptr(_p0), uintptr(len(mib)), uintptr(unsafe.Pointer(old)), uintptr(unsafe.Pointer(oldlen)), uintptr(unsafe.Pointer(new)), uintptr(newlen))
if e1 != 0 { if e1 != 0 {
err = errnoErr(e1) err = errnoErr(e1)
} }
@ -266,6 +266,17 @@ func fcntl(fd int, cmd int, arg int) (val int, err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func poll(fds *PollFd, nfds int, timeout int) (n int, err error) {
r0, _, e1 := Syscall(SYS_POLL, uintptr(unsafe.Pointer(fds)), uintptr(nfds), uintptr(timeout))
n = int(r0)
if e1 != 0 {
err = errnoErr(e1)
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Madvise(b []byte, behav int) (err error) { func Madvise(b []byte, behav int) (err error) {
var _p0 unsafe.Pointer var _p0 unsafe.Pointer
if len(b) > 0 { if len(b) > 0 {
@ -408,17 +419,6 @@ func ioctl(fd int, req uint, arg uintptr) (err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func poll(fds *PollFd, nfds int, timeout int) (n int, err error) {
r0, _, e1 := Syscall(SYS_POLL, uintptr(unsafe.Pointer(fds)), uintptr(nfds), uintptr(timeout))
n = int(r0)
if e1 != 0 {
err = errnoErr(e1)
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Access(path string, mode uint32) (err error) { func Access(path string, mode uint32) (err error) {
var _p0 *byte var _p0 *byte
_p0, err = BytePtrFromString(path) _p0, err = BytePtrFromString(path)

View File

@ -266,6 +266,17 @@ func fcntl(fd int, cmd int, arg int) (val int, err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func poll(fds *PollFd, nfds int, timeout int) (n int, err error) {
r0, _, e1 := Syscall(SYS_POLL, uintptr(unsafe.Pointer(fds)), uintptr(nfds), uintptr(timeout))
n = int(r0)
if e1 != 0 {
err = errnoErr(e1)
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Madvise(b []byte, behav int) (err error) { func Madvise(b []byte, behav int) (err error) {
var _p0 unsafe.Pointer var _p0 unsafe.Pointer
if len(b) > 0 { if len(b) > 0 {
@ -408,17 +419,6 @@ func ioctl(fd int, req uint, arg uintptr) (err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func poll(fds *PollFd, nfds int, timeout int) (n int, err error) {
r0, _, e1 := Syscall(SYS_POLL, uintptr(unsafe.Pointer(fds)), uintptr(nfds), uintptr(timeout))
n = int(r0)
if e1 != 0 {
err = errnoErr(e1)
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Access(path string, mode uint32) (err error) { func Access(path string, mode uint32) (err error) {
var _p0 *byte var _p0 *byte
_p0, err = BytePtrFromString(path) _p0, err = BytePtrFromString(path)

View File

@ -423,6 +423,16 @@ func extpwrite(fd int, p []byte, flags int, offset int64) (n int, err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func ioctl(fd int, req uint, arg uintptr) (err error) {
_, _, e1 := Syscall(SYS_IOCTL, uintptr(fd), uintptr(req), uintptr(arg))
if e1 != 0 {
err = errnoErr(e1)
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Access(path string, mode uint32) (err error) { func Access(path string, mode uint32) (err error) {
var _p0 *byte var _p0 *byte
_p0, err = BytePtrFromString(path) _p0, err = BytePtrFromString(path)

View File

@ -406,6 +406,16 @@ func getdents(fd int, buf []byte) (n int, err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func ioctl(fd int, req uint, arg uintptr) (err error) {
_, _, e1 := Syscall(SYS_IOCTL, uintptr(fd), uintptr(req), uintptr(arg))
if e1 != 0 {
err = errnoErr(e1)
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Access(path string, mode uint32) (err error) { func Access(path string, mode uint32) (err error) {
var _p0 *byte var _p0 *byte
_p0, err = BytePtrFromString(path) _p0, err = BytePtrFromString(path)

View File

@ -406,6 +406,16 @@ func getdents(fd int, buf []byte) (n int, err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func ioctl(fd int, req uint, arg uintptr) (err error) {
_, _, e1 := Syscall(SYS_IOCTL, uintptr(fd), uintptr(req), uintptr(arg))
if e1 != 0 {
err = errnoErr(e1)
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Access(path string, mode uint32) (err error) { func Access(path string, mode uint32) (err error) {
var _p0 *byte var _p0 *byte
_p0, err = BytePtrFromString(path) _p0, err = BytePtrFromString(path)

View File

@ -406,6 +406,16 @@ func getdents(fd int, buf []byte) (n int, err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func ioctl(fd int, req uint, arg uintptr) (err error) {
_, _, e1 := Syscall(SYS_IOCTL, uintptr(fd), uintptr(req), uintptr(arg))
if e1 != 0 {
err = errnoErr(e1)
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Access(path string, mode uint32) (err error) { func Access(path string, mode uint32) (err error) {
var _p0 *byte var _p0 *byte
_p0, err = BytePtrFromString(path) _p0, err = BytePtrFromString(path)

View File

@ -404,6 +404,16 @@ func getdents(fd int, buf []byte) (n int, err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func ioctl(fd int, req uint, arg uintptr) (err error) {
_, _, e1 := Syscall(SYS_IOCTL, uintptr(fd), uintptr(req), uintptr(arg))
if e1 != 0 {
err = errnoErr(e1)
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Access(path string, mode uint32) (err error) { func Access(path string, mode uint32) (err error) {
var _p0 *byte var _p0 *byte
_p0, err = BytePtrFromString(path) _p0, err = BytePtrFromString(path)

View File

@ -404,6 +404,16 @@ func getdents(fd int, buf []byte) (n int, err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func ioctl(fd int, req uint, arg uintptr) (err error) {
_, _, e1 := Syscall(SYS_IOCTL, uintptr(fd), uintptr(req), uintptr(arg))
if e1 != 0 {
err = errnoErr(e1)
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Access(path string, mode uint32) (err error) { func Access(path string, mode uint32) (err error) {
var _p0 *byte var _p0 *byte
_p0, err = BytePtrFromString(path) _p0, err = BytePtrFromString(path)

View File

@ -404,6 +404,16 @@ func getdents(fd int, buf []byte) (n int, err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func ioctl(fd int, req uint, arg uintptr) (err error) {
_, _, e1 := Syscall(SYS_IOCTL, uintptr(fd), uintptr(req), uintptr(arg))
if e1 != 0 {
err = errnoErr(e1)
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Access(path string, mode uint32) (err error) { func Access(path string, mode uint32) (err error) {
var _p0 *byte var _p0 *byte
_p0, err = BytePtrFromString(path) _p0, err = BytePtrFromString(path)

View File

@ -1,5 +1,5 @@
// mksysnum_darwin.pl /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.10.sdk/usr/include/sys/syscall.h // mksysnum_darwin.pl /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.13.sdk/usr/include/sys/syscall.h
// MACHINE GENERATED BY THE ABOVE COMMAND; DO NOT EDIT // Code generated by the command above; see README.md. DO NOT EDIT.
// +build 386,darwin // +build 386,darwin
@ -121,13 +121,15 @@ const (
SYS_CSOPS = 169 SYS_CSOPS = 169
SYS_CSOPS_AUDITTOKEN = 170 SYS_CSOPS_AUDITTOKEN = 170
SYS_WAITID = 173 SYS_WAITID = 173
SYS_KDEBUG_TYPEFILTER = 177
SYS_KDEBUG_TRACE_STRING = 178
SYS_KDEBUG_TRACE64 = 179 SYS_KDEBUG_TRACE64 = 179
SYS_KDEBUG_TRACE = 180 SYS_KDEBUG_TRACE = 180
SYS_SETGID = 181 SYS_SETGID = 181
SYS_SETEGID = 182 SYS_SETEGID = 182
SYS_SETEUID = 183 SYS_SETEUID = 183
SYS_SIGRETURN = 184 SYS_SIGRETURN = 184
SYS_CHUD = 185 SYS_THREAD_SELFCOUNTS = 186
SYS_FDATASYNC = 187 SYS_FDATASYNC = 187
SYS_STAT = 188 SYS_STAT = 188
SYS_FSTAT = 189 SYS_FSTAT = 189
@ -278,7 +280,6 @@ const (
SYS_KQUEUE = 362 SYS_KQUEUE = 362
SYS_KEVENT = 363 SYS_KEVENT = 363
SYS_LCHOWN = 364 SYS_LCHOWN = 364
SYS_STACK_SNAPSHOT = 365
SYS_BSDTHREAD_REGISTER = 366 SYS_BSDTHREAD_REGISTER = 366
SYS_WORKQ_OPEN = 367 SYS_WORKQ_OPEN = 367
SYS_WORKQ_KERNRETURN = 368 SYS_WORKQ_KERNRETURN = 368
@ -287,6 +288,8 @@ const (
SYS___OLD_SEMWAIT_SIGNAL_NOCANCEL = 371 SYS___OLD_SEMWAIT_SIGNAL_NOCANCEL = 371
SYS_THREAD_SELFID = 372 SYS_THREAD_SELFID = 372
SYS_LEDGER = 373 SYS_LEDGER = 373
SYS_KEVENT_QOS = 374
SYS_KEVENT_ID = 375
SYS___MAC_EXECVE = 380 SYS___MAC_EXECVE = 380
SYS___MAC_SYSCALL = 381 SYS___MAC_SYSCALL = 381
SYS___MAC_GET_FILE = 382 SYS___MAC_GET_FILE = 382
@ -298,11 +301,8 @@ const (
SYS___MAC_GET_FD = 388 SYS___MAC_GET_FD = 388
SYS___MAC_SET_FD = 389 SYS___MAC_SET_FD = 389
SYS___MAC_GET_PID = 390 SYS___MAC_GET_PID = 390
SYS___MAC_GET_LCID = 391 SYS_PSELECT = 394
SYS___MAC_GET_LCTX = 392 SYS_PSELECT_NOCANCEL = 395
SYS___MAC_SET_LCTX = 393
SYS_SETLCID = 394
SYS_GETLCID = 395
SYS_READ_NOCANCEL = 396 SYS_READ_NOCANCEL = 396
SYS_WRITE_NOCANCEL = 397 SYS_WRITE_NOCANCEL = 397
SYS_OPEN_NOCANCEL = 398 SYS_OPEN_NOCANCEL = 398
@ -351,6 +351,7 @@ const (
SYS_GUARDED_CLOSE_NP = 442 SYS_GUARDED_CLOSE_NP = 442
SYS_GUARDED_KQUEUE_NP = 443 SYS_GUARDED_KQUEUE_NP = 443
SYS_CHANGE_FDGUARD_NP = 444 SYS_CHANGE_FDGUARD_NP = 444
SYS_USRCTL = 445
SYS_PROC_RLIMIT_CONTROL = 446 SYS_PROC_RLIMIT_CONTROL = 446
SYS_CONNECTX = 447 SYS_CONNECTX = 447
SYS_DISCONNECTX = 448 SYS_DISCONNECTX = 448
@ -367,6 +368,7 @@ const (
SYS_COALITION_INFO = 459 SYS_COALITION_INFO = 459
SYS_NECP_MATCH_POLICY = 460 SYS_NECP_MATCH_POLICY = 460
SYS_GETATTRLISTBULK = 461 SYS_GETATTRLISTBULK = 461
SYS_CLONEFILEAT = 462
SYS_OPENAT = 463 SYS_OPENAT = 463
SYS_OPENAT_NOCANCEL = 464 SYS_OPENAT_NOCANCEL = 464
SYS_RENAMEAT = 465 SYS_RENAMEAT = 465
@ -392,7 +394,43 @@ const (
SYS_GUARDED_WRITE_NP = 485 SYS_GUARDED_WRITE_NP = 485
SYS_GUARDED_PWRITE_NP = 486 SYS_GUARDED_PWRITE_NP = 486
SYS_GUARDED_WRITEV_NP = 487 SYS_GUARDED_WRITEV_NP = 487
SYS_RENAME_EXT = 488 SYS_RENAMEATX_NP = 488
SYS_MREMAP_ENCRYPTED = 489 SYS_MREMAP_ENCRYPTED = 489
SYS_MAXSYSCALL = 490 SYS_NETAGENT_TRIGGER = 490
SYS_STACK_SNAPSHOT_WITH_CONFIG = 491
SYS_MICROSTACKSHOT = 492
SYS_GRAB_PGO_DATA = 493
SYS_PERSONA = 494
SYS_WORK_INTERVAL_CTL = 499
SYS_GETENTROPY = 500
SYS_NECP_OPEN = 501
SYS_NECP_CLIENT_ACTION = 502
SYS___NEXUS_OPEN = 503
SYS___NEXUS_REGISTER = 504
SYS___NEXUS_DEREGISTER = 505
SYS___NEXUS_CREATE = 506
SYS___NEXUS_DESTROY = 507
SYS___NEXUS_GET_OPT = 508
SYS___NEXUS_SET_OPT = 509
SYS___CHANNEL_OPEN = 510
SYS___CHANNEL_GET_INFO = 511
SYS___CHANNEL_SYNC = 512
SYS___CHANNEL_GET_OPT = 513
SYS___CHANNEL_SET_OPT = 514
SYS_ULOCK_WAIT = 515
SYS_ULOCK_WAKE = 516
SYS_FCLONEFILEAT = 517
SYS_FS_SNAPSHOT = 518
SYS_TERMINATE_WITH_PAYLOAD = 520
SYS_ABORT_WITH_PAYLOAD = 521
SYS_NECP_SESSION_OPEN = 522
SYS_NECP_SESSION_ACTION = 523
SYS_SETATTRLISTAT = 524
SYS_NET_QOS_GUIDELINE = 525
SYS_FMOUNT = 526
SYS_NTP_ADJTIME = 527
SYS_NTP_GETTIME = 528
SYS_OS_FAULT_WITH_PAYLOAD = 529
SYS_MAXSYSCALL = 530
SYS_INVALID = 63
) )

View File

@ -1,5 +1,5 @@
// mksysnum_darwin.pl /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.10.sdk/usr/include/sys/syscall.h // mksysnum_darwin.pl /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.13.sdk/usr/include/sys/syscall.h
// MACHINE GENERATED BY THE ABOVE COMMAND; DO NOT EDIT // Code generated by the command above; see README.md. DO NOT EDIT.
// +build amd64,darwin // +build amd64,darwin
@ -121,13 +121,15 @@ const (
SYS_CSOPS = 169 SYS_CSOPS = 169
SYS_CSOPS_AUDITTOKEN = 170 SYS_CSOPS_AUDITTOKEN = 170
SYS_WAITID = 173 SYS_WAITID = 173
SYS_KDEBUG_TYPEFILTER = 177
SYS_KDEBUG_TRACE_STRING = 178
SYS_KDEBUG_TRACE64 = 179 SYS_KDEBUG_TRACE64 = 179
SYS_KDEBUG_TRACE = 180 SYS_KDEBUG_TRACE = 180
SYS_SETGID = 181 SYS_SETGID = 181
SYS_SETEGID = 182 SYS_SETEGID = 182
SYS_SETEUID = 183 SYS_SETEUID = 183
SYS_SIGRETURN = 184 SYS_SIGRETURN = 184
SYS_CHUD = 185 SYS_THREAD_SELFCOUNTS = 186
SYS_FDATASYNC = 187 SYS_FDATASYNC = 187
SYS_STAT = 188 SYS_STAT = 188
SYS_FSTAT = 189 SYS_FSTAT = 189
@ -278,7 +280,6 @@ const (
SYS_KQUEUE = 362 SYS_KQUEUE = 362
SYS_KEVENT = 363 SYS_KEVENT = 363
SYS_LCHOWN = 364 SYS_LCHOWN = 364
SYS_STACK_SNAPSHOT = 365
SYS_BSDTHREAD_REGISTER = 366 SYS_BSDTHREAD_REGISTER = 366
SYS_WORKQ_OPEN = 367 SYS_WORKQ_OPEN = 367
SYS_WORKQ_KERNRETURN = 368 SYS_WORKQ_KERNRETURN = 368
@ -287,6 +288,8 @@ const (
SYS___OLD_SEMWAIT_SIGNAL_NOCANCEL = 371 SYS___OLD_SEMWAIT_SIGNAL_NOCANCEL = 371
SYS_THREAD_SELFID = 372 SYS_THREAD_SELFID = 372
SYS_LEDGER = 373 SYS_LEDGER = 373
SYS_KEVENT_QOS = 374
SYS_KEVENT_ID = 375
SYS___MAC_EXECVE = 380 SYS___MAC_EXECVE = 380
SYS___MAC_SYSCALL = 381 SYS___MAC_SYSCALL = 381
SYS___MAC_GET_FILE = 382 SYS___MAC_GET_FILE = 382
@ -298,11 +301,8 @@ const (
SYS___MAC_GET_FD = 388 SYS___MAC_GET_FD = 388
SYS___MAC_SET_FD = 389 SYS___MAC_SET_FD = 389
SYS___MAC_GET_PID = 390 SYS___MAC_GET_PID = 390
SYS___MAC_GET_LCID = 391 SYS_PSELECT = 394
SYS___MAC_GET_LCTX = 392 SYS_PSELECT_NOCANCEL = 395
SYS___MAC_SET_LCTX = 393
SYS_SETLCID = 394
SYS_GETLCID = 395
SYS_READ_NOCANCEL = 396 SYS_READ_NOCANCEL = 396
SYS_WRITE_NOCANCEL = 397 SYS_WRITE_NOCANCEL = 397
SYS_OPEN_NOCANCEL = 398 SYS_OPEN_NOCANCEL = 398
@ -351,6 +351,7 @@ const (
SYS_GUARDED_CLOSE_NP = 442 SYS_GUARDED_CLOSE_NP = 442
SYS_GUARDED_KQUEUE_NP = 443 SYS_GUARDED_KQUEUE_NP = 443
SYS_CHANGE_FDGUARD_NP = 444 SYS_CHANGE_FDGUARD_NP = 444
SYS_USRCTL = 445
SYS_PROC_RLIMIT_CONTROL = 446 SYS_PROC_RLIMIT_CONTROL = 446
SYS_CONNECTX = 447 SYS_CONNECTX = 447
SYS_DISCONNECTX = 448 SYS_DISCONNECTX = 448
@ -367,6 +368,7 @@ const (
SYS_COALITION_INFO = 459 SYS_COALITION_INFO = 459
SYS_NECP_MATCH_POLICY = 460 SYS_NECP_MATCH_POLICY = 460
SYS_GETATTRLISTBULK = 461 SYS_GETATTRLISTBULK = 461
SYS_CLONEFILEAT = 462
SYS_OPENAT = 463 SYS_OPENAT = 463
SYS_OPENAT_NOCANCEL = 464 SYS_OPENAT_NOCANCEL = 464
SYS_RENAMEAT = 465 SYS_RENAMEAT = 465
@ -392,7 +394,43 @@ const (
SYS_GUARDED_WRITE_NP = 485 SYS_GUARDED_WRITE_NP = 485
SYS_GUARDED_PWRITE_NP = 486 SYS_GUARDED_PWRITE_NP = 486
SYS_GUARDED_WRITEV_NP = 487 SYS_GUARDED_WRITEV_NP = 487
SYS_RENAME_EXT = 488 SYS_RENAMEATX_NP = 488
SYS_MREMAP_ENCRYPTED = 489 SYS_MREMAP_ENCRYPTED = 489
SYS_MAXSYSCALL = 490 SYS_NETAGENT_TRIGGER = 490
SYS_STACK_SNAPSHOT_WITH_CONFIG = 491
SYS_MICROSTACKSHOT = 492
SYS_GRAB_PGO_DATA = 493
SYS_PERSONA = 494
SYS_WORK_INTERVAL_CTL = 499
SYS_GETENTROPY = 500
SYS_NECP_OPEN = 501
SYS_NECP_CLIENT_ACTION = 502
SYS___NEXUS_OPEN = 503
SYS___NEXUS_REGISTER = 504
SYS___NEXUS_DEREGISTER = 505
SYS___NEXUS_CREATE = 506
SYS___NEXUS_DESTROY = 507
SYS___NEXUS_GET_OPT = 508
SYS___NEXUS_SET_OPT = 509
SYS___CHANNEL_OPEN = 510
SYS___CHANNEL_GET_INFO = 511
SYS___CHANNEL_SYNC = 512
SYS___CHANNEL_GET_OPT = 513
SYS___CHANNEL_SET_OPT = 514
SYS_ULOCK_WAIT = 515
SYS_ULOCK_WAKE = 516
SYS_FCLONEFILEAT = 517
SYS_FS_SNAPSHOT = 518
SYS_TERMINATE_WITH_PAYLOAD = 520
SYS_ABORT_WITH_PAYLOAD = 521
SYS_NECP_SESSION_OPEN = 522
SYS_NECP_SESSION_ACTION = 523
SYS_SETATTRLISTAT = 524
SYS_NET_QOS_GUIDELINE = 525
SYS_FMOUNT = 526
SYS_NTP_ADJTIME = 527
SYS_NTP_GETTIME = 528
SYS_OS_FAULT_WITH_PAYLOAD = 529
SYS_MAXSYSCALL = 530
SYS_INVALID = 63
) )

View File

@ -1,4 +1,4 @@
// mksysnum_darwin.pl /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS10.2.sdk/usr/include/sys/syscall.h // mksysnum_darwin.pl /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS11.1.sdk/usr/include/sys/syscall.h
// Code generated by the command above; see README.md. DO NOT EDIT. // Code generated by the command above; see README.md. DO NOT EDIT.
// +build arm,darwin // +build arm,darwin
@ -129,6 +129,7 @@ const (
SYS_SETEGID = 182 SYS_SETEGID = 182
SYS_SETEUID = 183 SYS_SETEUID = 183
SYS_SIGRETURN = 184 SYS_SIGRETURN = 184
SYS_THREAD_SELFCOUNTS = 186
SYS_FDATASYNC = 187 SYS_FDATASYNC = 187
SYS_STAT = 188 SYS_STAT = 188
SYS_FSTAT = 189 SYS_FSTAT = 189
@ -288,6 +289,7 @@ const (
SYS_THREAD_SELFID = 372 SYS_THREAD_SELFID = 372
SYS_LEDGER = 373 SYS_LEDGER = 373
SYS_KEVENT_QOS = 374 SYS_KEVENT_QOS = 374
SYS_KEVENT_ID = 375
SYS___MAC_EXECVE = 380 SYS___MAC_EXECVE = 380
SYS___MAC_SYSCALL = 381 SYS___MAC_SYSCALL = 381
SYS___MAC_GET_FILE = 382 SYS___MAC_GET_FILE = 382
@ -421,6 +423,14 @@ const (
SYS_FS_SNAPSHOT = 518 SYS_FS_SNAPSHOT = 518
SYS_TERMINATE_WITH_PAYLOAD = 520 SYS_TERMINATE_WITH_PAYLOAD = 520
SYS_ABORT_WITH_PAYLOAD = 521 SYS_ABORT_WITH_PAYLOAD = 521
SYS_MAXSYSCALL = 522 SYS_NECP_SESSION_OPEN = 522
SYS_NECP_SESSION_ACTION = 523
SYS_SETATTRLISTAT = 524
SYS_NET_QOS_GUIDELINE = 525
SYS_FMOUNT = 526
SYS_NTP_ADJTIME = 527
SYS_NTP_GETTIME = 528
SYS_OS_FAULT_WITH_PAYLOAD = 529
SYS_MAXSYSCALL = 530
SYS_INVALID = 63 SYS_INVALID = 63
) )

View File

@ -1,4 +1,4 @@
// mksysnum_darwin.pl /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS10.2.sdk/usr/include/sys/syscall.h // mksysnum_darwin.pl /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS11.1.sdk/usr/include/sys/syscall.h
// Code generated by the command above; see README.md. DO NOT EDIT. // Code generated by the command above; see README.md. DO NOT EDIT.
// +build arm64,darwin // +build arm64,darwin
@ -129,6 +129,7 @@ const (
SYS_SETEGID = 182 SYS_SETEGID = 182
SYS_SETEUID = 183 SYS_SETEUID = 183
SYS_SIGRETURN = 184 SYS_SIGRETURN = 184
SYS_THREAD_SELFCOUNTS = 186
SYS_FDATASYNC = 187 SYS_FDATASYNC = 187
SYS_STAT = 188 SYS_STAT = 188
SYS_FSTAT = 189 SYS_FSTAT = 189
@ -288,6 +289,7 @@ const (
SYS_THREAD_SELFID = 372 SYS_THREAD_SELFID = 372
SYS_LEDGER = 373 SYS_LEDGER = 373
SYS_KEVENT_QOS = 374 SYS_KEVENT_QOS = 374
SYS_KEVENT_ID = 375
SYS___MAC_EXECVE = 380 SYS___MAC_EXECVE = 380
SYS___MAC_SYSCALL = 381 SYS___MAC_SYSCALL = 381
SYS___MAC_GET_FILE = 382 SYS___MAC_GET_FILE = 382
@ -421,6 +423,14 @@ const (
SYS_FS_SNAPSHOT = 518 SYS_FS_SNAPSHOT = 518
SYS_TERMINATE_WITH_PAYLOAD = 520 SYS_TERMINATE_WITH_PAYLOAD = 520
SYS_ABORT_WITH_PAYLOAD = 521 SYS_ABORT_WITH_PAYLOAD = 521
SYS_MAXSYSCALL = 522 SYS_NECP_SESSION_OPEN = 522
SYS_NECP_SESSION_ACTION = 523
SYS_SETATTRLISTAT = 524
SYS_NET_QOS_GUIDELINE = 525
SYS_FMOUNT = 526
SYS_NTP_ADJTIME = 527
SYS_NTP_GETTIME = 528
SYS_OS_FAULT_WITH_PAYLOAD = 529
SYS_MAXSYSCALL = 530
SYS_INVALID = 63 SYS_INVALID = 63
) )

View File

@ -479,3 +479,11 @@ const (
POLLWRBAND = 0x100 POLLWRBAND = 0x100
POLLWRNORM = 0x4 POLLWRNORM = 0x4
) )
type Utsname struct {
Sysname [256]byte
Nodename [256]byte
Release [256]byte
Version [256]byte
Machine [256]byte
}

View File

@ -489,3 +489,11 @@ const (
POLLWRBAND = 0x100 POLLWRBAND = 0x100
POLLWRNORM = 0x4 POLLWRNORM = 0x4
) )
type Utsname struct {
Sysname [256]byte
Nodename [256]byte
Release [256]byte
Version [256]byte
Machine [256]byte
}

View File

@ -480,3 +480,11 @@ const (
POLLWRBAND = 0x100 POLLWRBAND = 0x100
POLLWRNORM = 0x4 POLLWRNORM = 0x4
) )
type Utsname struct {
Sysname [256]byte
Nodename [256]byte
Release [256]byte
Version [256]byte
Machine [256]byte
}

View File

@ -489,3 +489,11 @@ const (
POLLWRBAND = 0x100 POLLWRBAND = 0x100
POLLWRNORM = 0x4 POLLWRNORM = 0x4
) )
type Utsname struct {
Sysname [256]byte
Nodename [256]byte
Release [256]byte
Version [256]byte
Machine [256]byte
}

View File

@ -442,6 +442,13 @@ type Termios struct {
Ospeed uint32 Ospeed uint32
} }
type Winsize struct {
Row uint16
Col uint16
Xpixel uint16
Ypixel uint16
}
const ( const (
AT_FDCWD = 0xfffafdcd AT_FDCWD = 0xfffafdcd
AT_SYMLINK_NOFOLLOW = 0x1 AT_SYMLINK_NOFOLLOW = 0x1

View File

@ -382,6 +382,13 @@ type Termios struct {
Ospeed int32 Ospeed int32
} }
type Winsize struct {
Row uint16
Col uint16
Xpixel uint16
Ypixel uint16
}
const ( const (
AT_FDCWD = -0x64 AT_FDCWD = -0x64
AT_SYMLINK_NOFOLLOW = 0x200 AT_SYMLINK_NOFOLLOW = 0x200

View File

@ -389,6 +389,13 @@ type Termios struct {
Ospeed int32 Ospeed int32
} }
type Winsize struct {
Row uint16
Col uint16
Xpixel uint16
Ypixel uint16
}
const ( const (
AT_FDCWD = -0x64 AT_FDCWD = -0x64
AT_SYMLINK_NOFOLLOW = 0x200 AT_SYMLINK_NOFOLLOW = 0x200

View File

@ -387,6 +387,13 @@ type Termios struct {
Ospeed int32 Ospeed int32
} }
type Winsize struct {
Row uint16
Col uint16
Xpixel uint16
Ypixel uint16
}
const ( const (
AT_FDCWD = -0x64 AT_FDCWD = -0x64
AT_SYMLINK_NOFOLLOW = 0x200 AT_SYMLINK_NOFOLLOW = 0x200

View File

@ -440,6 +440,13 @@ type Termios struct {
Ospeed int32 Ospeed int32
} }
type Winsize struct {
Row uint16
Col uint16
Xpixel uint16
Ypixel uint16
}
const ( const (
AT_FDCWD = -0x64 AT_FDCWD = -0x64
AT_SYMLINK_NOFOLLOW = 0x2 AT_SYMLINK_NOFOLLOW = 0x2

View File

@ -447,6 +447,13 @@ type Termios struct {
Ospeed int32 Ospeed int32
} }
type Winsize struct {
Row uint16
Col uint16
Xpixel uint16
Ypixel uint16
}
const ( const (
AT_FDCWD = -0x64 AT_FDCWD = -0x64
AT_SYMLINK_NOFOLLOW = 0x2 AT_SYMLINK_NOFOLLOW = 0x2

View File

@ -433,6 +433,13 @@ type Termios struct {
Ospeed int32 Ospeed int32
} }
type Winsize struct {
Row uint16
Col uint16
Xpixel uint16
Ypixel uint16
}
const ( const (
AT_FDCWD = -0x64 AT_FDCWD = -0x64
AT_SYMLINK_NOFOLLOW = 0x2 AT_SYMLINK_NOFOLLOW = 0x2

View File

@ -796,6 +796,75 @@ func ConnectEx(fd Handle, sa Sockaddr, sendBuf *byte, sendDataLen uint32, bytesS
return connectEx(fd, ptr, n, sendBuf, sendDataLen, bytesSent, overlapped) return connectEx(fd, ptr, n, sendBuf, sendDataLen, bytesSent, overlapped)
} }
var sendRecvMsgFunc struct {
once sync.Once
sendAddr uintptr
recvAddr uintptr
err error
}
func loadWSASendRecvMsg() error {
sendRecvMsgFunc.once.Do(func() {
var s Handle
s, sendRecvMsgFunc.err = Socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)
if sendRecvMsgFunc.err != nil {
return
}
defer CloseHandle(s)
var n uint32
sendRecvMsgFunc.err = WSAIoctl(s,
SIO_GET_EXTENSION_FUNCTION_POINTER,
(*byte)(unsafe.Pointer(&WSAID_WSARECVMSG)),
uint32(unsafe.Sizeof(WSAID_WSARECVMSG)),
(*byte)(unsafe.Pointer(&sendRecvMsgFunc.recvAddr)),
uint32(unsafe.Sizeof(sendRecvMsgFunc.recvAddr)),
&n, nil, 0)
if sendRecvMsgFunc.err != nil {
return
}
sendRecvMsgFunc.err = WSAIoctl(s,
SIO_GET_EXTENSION_FUNCTION_POINTER,
(*byte)(unsafe.Pointer(&WSAID_WSASENDMSG)),
uint32(unsafe.Sizeof(WSAID_WSASENDMSG)),
(*byte)(unsafe.Pointer(&sendRecvMsgFunc.sendAddr)),
uint32(unsafe.Sizeof(sendRecvMsgFunc.sendAddr)),
&n, nil, 0)
})
return sendRecvMsgFunc.err
}
func WSASendMsg(fd Handle, msg *WSAMsg, flags uint32, bytesSent *uint32, overlapped *Overlapped, croutine *byte) error {
err := loadWSASendRecvMsg()
if err != nil {
return err
}
r1, _, e1 := syscall.Syscall6(sendRecvMsgFunc.sendAddr, 6, uintptr(fd), uintptr(unsafe.Pointer(msg)), uintptr(flags), uintptr(unsafe.Pointer(bytesSent)), uintptr(unsafe.Pointer(overlapped)), uintptr(unsafe.Pointer(croutine)))
if r1 == socket_error {
if e1 != 0 {
err = errnoErr(e1)
} else {
err = syscall.EINVAL
}
}
return err
}
func WSARecvMsg(fd Handle, msg *WSAMsg, bytesReceived *uint32, overlapped *Overlapped, croutine *byte) error {
err := loadWSASendRecvMsg()
if err != nil {
return err
}
r1, _, e1 := syscall.Syscall6(sendRecvMsgFunc.recvAddr, 5, uintptr(fd), uintptr(unsafe.Pointer(msg)), uintptr(unsafe.Pointer(bytesReceived)), uintptr(unsafe.Pointer(overlapped)), uintptr(unsafe.Pointer(croutine)), 0)
if r1 == socket_error {
if e1 != 0 {
err = errnoErr(e1)
} else {
err = syscall.EINVAL
}
}
return err
}
// Invented structures to support what package os expects. // Invented structures to support what package os expects.
type Rusage struct { type Rusage struct {
CreationTime Filetime CreationTime Filetime

View File

@ -29,6 +29,7 @@ const (
ERROR_NOT_FOUND syscall.Errno = 1168 ERROR_NOT_FOUND syscall.Errno = 1168
ERROR_PRIVILEGE_NOT_HELD syscall.Errno = 1314 ERROR_PRIVILEGE_NOT_HELD syscall.Errno = 1314
WSAEACCES syscall.Errno = 10013 WSAEACCES syscall.Errno = 10013
WSAEMSGSIZE syscall.Errno = 10040
WSAECONNRESET syscall.Errno = 10054 WSAECONNRESET syscall.Errno = 10054
) )
@ -567,6 +568,16 @@ const (
IPV6_JOIN_GROUP = 0xc IPV6_JOIN_GROUP = 0xc
IPV6_LEAVE_GROUP = 0xd IPV6_LEAVE_GROUP = 0xd
MSG_OOB = 0x1
MSG_PEEK = 0x2
MSG_DONTROUTE = 0x4
MSG_WAITALL = 0x8
MSG_TRUNC = 0x0100
MSG_CTRUNC = 0x0200
MSG_BCAST = 0x0400
MSG_MCAST = 0x0800
SOMAXCONN = 0x7fffffff SOMAXCONN = 0x7fffffff
TCP_NODELAY = 1 TCP_NODELAY = 1
@ -584,6 +595,15 @@ type WSABuf struct {
Buf *byte Buf *byte
} }
type WSAMsg struct {
Name *syscall.RawSockaddrAny
Namelen int32
Buffers *WSABuf
BufferCount uint32
Control WSABuf
Flags uint32
}
// Invented values to support what package os expects. // Invented values to support what package os expects.
const ( const (
S_IFMT = 0x1f000 S_IFMT = 0x1f000
@ -1011,6 +1031,20 @@ var WSAID_CONNECTEX = GUID{
[8]byte{0x8e, 0xe9, 0x76, 0xe5, 0x8c, 0x74, 0x06, 0x3e}, [8]byte{0x8e, 0xe9, 0x76, 0xe5, 0x8c, 0x74, 0x06, 0x3e},
} }
var WSAID_WSASENDMSG = GUID{
0xa441e712,
0x754f,
0x43ca,
[8]byte{0x84, 0xa7, 0x0d, 0xee, 0x44, 0xcf, 0x60, 0x6d},
}
var WSAID_WSARECVMSG = GUID{
0xf689d7c8,
0x6f1f,
0x436b,
[8]byte{0x8a, 0x53, 0xe5, 0x4f, 0xe3, 0x51, 0xc3, 0x22},
}
const ( const (
FILE_SKIP_COMPLETION_PORT_ON_SUCCESS = 1 FILE_SKIP_COMPLETION_PORT_ON_SUCCESS = 1
FILE_SKIP_SET_EVENT_ON_HANDLE = 2 FILE_SKIP_SET_EVENT_ON_HANDLE = 2