github.com/rkt/rkt@v1.30.1-0.20200224141603-171c416fac02/common/overlay/overlay.go (about)

     1  // Copyright 2016 The rkt Authors
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package overlay
    16  
    17  import (
    18  	"fmt"
    19  	"strings"
    20  	"syscall"
    21  
    22  	"github.com/hashicorp/errwrap"
    23  	"github.com/opencontainers/selinux/go-selinux/label"
    24  )
    25  
    26  // sanitizer defines a string translator used to escape colon and comma
    27  // characters in the directories names.
    28  var sanitizer = strings.NewReplacer(`:`, `\:`, `,`, `\,`)
    29  
    30  // MountCfg contains the needed data to construct the overlay mount syscall.
    31  // The Lower and Upper fields are paths to the filesystems to be merged. The
    32  // Work field should be an empty directory. Dest is where the mount will be
    33  // located. Lbl is an SELinux label.
    34  type MountCfg struct {
    35  	Lower,
    36  	Upper,
    37  	Work,
    38  	Dest,
    39  	Lbl string
    40  }
    41  
    42  // sanitize escapes the colon and comma symbols in order to support the dir
    43  // names with these characters, otherwise they will be treated as separators
    44  // between the directory names.
    45  func sanitize(dir string) string {
    46  	return sanitizer.Replace(dir)
    47  }
    48  
    49  // Opts returns options for mount system call.
    50  func (cfg *MountCfg) Opts() string {
    51  	opts := fmt.Sprintf(
    52  		"lowerdir=%s,upperdir=%s,workdir=%s",
    53  		sanitize(cfg.Lower), sanitize(cfg.Upper), sanitize(cfg.Work),
    54  	)
    55  
    56  	return label.FormatMountLabel(opts, cfg.Lbl)
    57  }
    58  
    59  // Mount mounts the upper and lower directories to the destination directory.
    60  // The MountCfg struct supplies information required to build the mount system
    61  // call.
    62  func Mount(cfg *MountCfg) error {
    63  	err := syscall.Mount("overlay", cfg.Dest, "overlay", 0, cfg.Opts())
    64  	if err != nil {
    65  		const text = "error mounting overlay with options '%s' and dest '%s'"
    66  		return errwrap.Wrap(fmt.Errorf(text, cfg.Opts(), cfg.Dest), err)
    67  	}
    68  
    69  	return nil
    70  }