github.com/containerd/containerd@v22.0.0-20200918172823-438c87b8e050+incompatible/rootfs/init_linux.go (about)

     1  /*
     2     Copyright The containerd Authors.
     3  
     4     Licensed under the Apache License, Version 2.0 (the "License");
     5     you may not use this file except in compliance with the License.
     6     You may obtain a copy of the License at
     7  
     8         http://www.apache.org/licenses/LICENSE-2.0
     9  
    10     Unless required by applicable law or agreed to in writing, software
    11     distributed under the License is distributed on an "AS IS" BASIS,
    12     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13     See the License for the specific language governing permissions and
    14     limitations under the License.
    15  */
    16  
    17  package rootfs
    18  
    19  import (
    20  	"os"
    21  	"path/filepath"
    22  	"syscall"
    23  )
    24  
    25  const (
    26  	defaultInitializer = "linux-init"
    27  )
    28  
    29  func init() {
    30  	initializers[defaultInitializer] = initFS
    31  }
    32  
    33  func createDirectory(name string, uid, gid int) initializerFunc {
    34  	return func(root string) error {
    35  		dname := filepath.Join(root, name)
    36  		st, err := os.Stat(dname)
    37  		if err != nil && !os.IsNotExist(err) {
    38  			return err
    39  		} else if err == nil {
    40  			if st.IsDir() {
    41  				stat := st.Sys().(*syscall.Stat_t)
    42  				if int(stat.Gid) == gid && int(stat.Uid) == uid {
    43  					return nil
    44  				}
    45  			} else {
    46  				if err := os.Remove(dname); err != nil {
    47  					return err
    48  				}
    49  				if err := os.Mkdir(dname, 0755); err != nil {
    50  					return err
    51  				}
    52  			}
    53  		} else {
    54  			if err := os.Mkdir(dname, 0755); err != nil {
    55  				return err
    56  			}
    57  		}
    58  
    59  		return os.Chown(dname, uid, gid)
    60  	}
    61  }
    62  
    63  func touchFile(name string, uid, gid int) initializerFunc {
    64  	return func(root string) error {
    65  		fname := filepath.Join(root, name)
    66  
    67  		st, err := os.Stat(fname)
    68  		if err != nil && !os.IsNotExist(err) {
    69  			return err
    70  		} else if err == nil {
    71  			stat := st.Sys().(*syscall.Stat_t)
    72  			if int(stat.Gid) == gid && int(stat.Uid) == uid {
    73  				return nil
    74  			}
    75  			return os.Chown(fname, uid, gid)
    76  		}
    77  
    78  		f, err := os.OpenFile(fname, os.O_CREATE, 0644)
    79  		if err != nil {
    80  			return err
    81  		}
    82  		defer f.Close()
    83  
    84  		return f.Chown(uid, gid)
    85  	}
    86  }
    87  
    88  func symlink(oldname, newname string) initializerFunc {
    89  	return func(root string) error {
    90  		linkName := filepath.Join(root, newname)
    91  		if _, err := os.Stat(linkName); err != nil && !os.IsNotExist(err) {
    92  			return err
    93  		} else if err == nil {
    94  			return nil
    95  		}
    96  		return os.Symlink(oldname, linkName)
    97  	}
    98  }
    99  
   100  func initFS(root string) error {
   101  	st, err := os.Stat(root)
   102  	if err != nil {
   103  		return err
   104  	}
   105  	stat := st.Sys().(*syscall.Stat_t)
   106  	uid := int(stat.Uid)
   107  	gid := int(stat.Gid)
   108  
   109  	initFuncs := []initializerFunc{
   110  		createDirectory("/dev", uid, gid),
   111  		createDirectory("/dev/pts", uid, gid),
   112  		createDirectory("/dev/shm", uid, gid),
   113  		touchFile("/dev/console", uid, gid),
   114  		createDirectory("/proc", uid, gid),
   115  		createDirectory("/sys", uid, gid),
   116  		createDirectory("/etc", uid, gid),
   117  		touchFile("/etc/resolv.conf", uid, gid),
   118  		touchFile("/etc/hosts", uid, gid),
   119  		touchFile("/etc/hostname", uid, gid),
   120  		symlink("/proc/mounts", "/etc/mtab"),
   121  	}
   122  
   123  	for _, fn := range initFuncs {
   124  		if err := fn(root); err != nil {
   125  			return err
   126  		}
   127  	}
   128  
   129  	return nil
   130  }