github.com/apptainer/singularity@v3.1.1+incompatible/pkg/ocibundle/tools/overlay.go (about) 1 // Copyright (c) 2019, Sylabs Inc. All rights reserved. 2 // This software is licensed under a 3-clause BSD license. Please consult the 3 // LICENSE.md file distributed with the sources of this project regarding your 4 // rights to use or distribute this software. 5 6 package tools 7 8 import ( 9 "fmt" 10 "os" 11 "path/filepath" 12 "syscall" 13 ) 14 15 // CreateOverlay creates a writable overlay 16 func CreateOverlay(bundlePath string) error { 17 var err error 18 19 oldumask := syscall.Umask(0) 20 defer syscall.Umask(oldumask) 21 22 overlayDir := filepath.Join(bundlePath, "overlay") 23 if err = os.Mkdir(overlayDir, 0700); err != nil { 24 return fmt.Errorf("failed to create %s: %s", overlayDir, err) 25 } 26 // delete overlay directory in case of error 27 defer func() { 28 if err != nil { 29 os.RemoveAll(overlayDir) 30 } 31 }() 32 33 err = syscall.Mount(overlayDir, overlayDir, "", syscall.MS_BIND, "") 34 if err != nil { 35 return fmt.Errorf("failed to bind %s: %s", overlayDir, err) 36 } 37 // best effort to cleanup mount 38 defer func() { 39 if err != nil { 40 syscall.Unmount(overlayDir, syscall.MNT_DETACH) 41 } 42 }() 43 44 if err = syscall.Mount("", overlayDir, "", syscall.MS_REMOUNT|syscall.MS_BIND, ""); err != nil { 45 return fmt.Errorf("failed to remount %s: %s", overlayDir, err) 46 } 47 48 upperDir := filepath.Join(overlayDir, "upper") 49 if err = os.Mkdir(upperDir, 0755); err != nil { 50 return fmt.Errorf("failed to create %s: %s", upperDir, err) 51 } 52 workDir := filepath.Join(overlayDir, "work") 53 if err = os.Mkdir(workDir, 0700); err != nil { 54 return fmt.Errorf("failed to create %s: %s", workDir, err) 55 } 56 rootFsDir := RootFs(bundlePath).Path() 57 58 options := fmt.Sprintf("lowerdir=%s,upperdir=%s,workdir=%s", rootFsDir, upperDir, workDir) 59 if err = syscall.Mount("overlay", rootFsDir, "overlay", 0, options); err != nil { 60 return fmt.Errorf("failed to mount %s: %s", overlayDir, err) 61 } 62 return nil 63 } 64 65 // DeleteOverlay deletes overlay 66 func DeleteOverlay(bundlePath string) error { 67 overlayDir := filepath.Join(bundlePath, "overlay") 68 rootFsDir := RootFs(bundlePath).Path() 69 70 if err := syscall.Unmount(rootFsDir, syscall.MNT_DETACH); err != nil { 71 return fmt.Errorf("failed to unmount %s: %s", rootFsDir, err) 72 } 73 if err := syscall.Unmount(overlayDir, syscall.MNT_DETACH); err != nil { 74 return fmt.Errorf("failed to unmount %s: %s", overlayDir, err) 75 } 76 if err := os.RemoveAll(overlayDir); err != nil { 77 return fmt.Errorf("failed to remove %s: %s", overlayDir, err) 78 } 79 return nil 80 }