Skip to content

Commit 2d7a567

Browse files
committed
image/layout/tar: Add a CreateTarFile helper
The NewEngine commands for the tar-backed image-layout engines (both the CAS and refs engines) open files O_RDWR and expect image-layout compatible content in the tarball. That makes sense, but for folks who *don't* have such a tarball, a helper like CreateTarFile makes it easy to explicitly create an empty one. The 0666 file modes and 0777 directory modes rely on the caller's umask to appropriately limit user/group/other permissions for the tarball itself and any content extracted to the filesystem from the tarball. The trailing slashes are based on part of libarchive's description of old-style archives [1]: name Pathname, stored as a null-terminated string. Early tar implementations only stored regular files (including hardlinks to those files). One common early convention used a trailing "/" character to indicate a directory name, allowing directory permissions and owner information to be archived and restored. and POSIX ustar archives [2]: name, prefix ... The standard does not require a trailing / character on directory names, though most implementations still include this for compatibility reasons. Expose this new functionality on the command line as: $ oci-image-init image-layout PATH where 'image-layout' is a separate level in case we support initializing additional types of repositories in the future. [1]: https://github.com/libarchive/libarchive/wiki/ManPageTar5#old-style-archive-format [2]: https://github.com/libarchive/libarchive/wiki/ManPageTar5#posix-ustar-archives Signed-off-by: W. Trevor King <[email protected]>
1 parent cc6c7b0 commit 2d7a567

File tree

5 files changed

+143
-0
lines changed

5 files changed

+143
-0
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
/oci-cas
22
/oci-create-runtime-bundle
3+
/oci-image-init
34
/oci-image-validate
45
/oci-refs
56
/oci-unpack

Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ EPOCH_TEST_COMMIT ?= v0.2.0
55
TOOLS := \
66
oci-cas \
77
oci-create-runtime-bundle \
8+
oci-image-init \
89
oci-image-validate \
910
oci-refs \
1011
oci-unpack

cmd/oci-image-init/image_layout.go

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
// Copyright 2016 The Linux Foundation
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package main
16+
17+
import (
18+
"fmt"
19+
"os"
20+
21+
"github.com/opencontainers/image-tools/image/layout"
22+
"github.com/spf13/cobra"
23+
"golang.org/x/net/context"
24+
)
25+
26+
type imageLayout struct{}
27+
28+
func newImageLayoutCmd() *cobra.Command {
29+
state := &imageLayout{}
30+
31+
return &cobra.Command{
32+
Use: "image-layout PATH",
33+
Short: "Initialize an OCI image-layout repository",
34+
Run: state.Run,
35+
}
36+
}
37+
38+
func (state *imageLayout) Run(cmd *cobra.Command, args []string) {
39+
if len(args) != 1 {
40+
if err := cmd.Usage(); err != nil {
41+
fmt.Fprintln(os.Stderr, err)
42+
}
43+
os.Exit(1)
44+
}
45+
46+
path := args[0]
47+
48+
ctx := context.Background()
49+
50+
err := layout.CreateTarFile(ctx, path)
51+
if err != nil {
52+
fmt.Fprintln(os.Stderr, err)
53+
os.Exit(1)
54+
}
55+
56+
os.Exit(0)
57+
}

cmd/oci-image-init/main.go

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
// Copyright 2016 The Linux Foundation
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package main
16+
17+
import (
18+
"fmt"
19+
"os"
20+
21+
"github.com/spf13/cobra"
22+
)
23+
24+
func main() {
25+
cmd := &cobra.Command{
26+
Use: "oci-image-init",
27+
Short: "Initialize an OCI image",
28+
}
29+
30+
cmd.AddCommand(newImageLayoutCmd())
31+
32+
err := cmd.Execute()
33+
if err != nil {
34+
fmt.Fprintln(os.Stderr, err)
35+
os.Exit(1)
36+
}
37+
}

image/layout/tar.go

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,3 +218,50 @@ func CheckTarVersion(ctx context.Context, reader io.ReadSeeker) (err error) {
218218

219219
return nil
220220
}
221+
222+
// CreateTarFile creates a new image-layout tar file at the given path.
223+
func CreateTarFile(ctx context.Context, path string) (err error) {
224+
file, err := os.OpenFile(path, os.O_RDWR|os.O_CREATE|os.O_EXCL, 0666)
225+
if err != nil {
226+
return err
227+
}
228+
defer file.Close()
229+
230+
tarWriter := tar.NewWriter(file)
231+
defer tarWriter.Close()
232+
233+
now := time.Now()
234+
for _, name := range []string{"./blobs/", "./refs/"} {
235+
header := &tar.Header{
236+
Name: name,
237+
Mode: 0777,
238+
ModTime: now,
239+
Typeflag: tar.TypeDir,
240+
}
241+
err = tarWriter.WriteHeader(header)
242+
if err != nil {
243+
return err
244+
}
245+
}
246+
247+
imageLayoutVersion := ImageLayoutVersion{
248+
Version: "1.0.0",
249+
}
250+
imageLayoutVersionBytes, err := json.Marshal(imageLayoutVersion)
251+
if err != nil {
252+
return err
253+
}
254+
header := &tar.Header{
255+
Name: "./oci-layout",
256+
Mode: 0666,
257+
Size: int64(len(imageLayoutVersionBytes)),
258+
ModTime: now,
259+
Typeflag: tar.TypeReg,
260+
}
261+
err = tarWriter.WriteHeader(header)
262+
if err != nil {
263+
return err
264+
}
265+
_, err = tarWriter.Write(imageLayoutVersionBytes)
266+
return err
267+
}

0 commit comments

Comments
 (0)