github.com/apptainer/singularity@v3.1.1+incompatible/internal/pkg/client/cache/dir.go (about)

     1  // Copyright (c) 2018-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 cache provides support for automatic caching of any image supported by containers/image
     7  package cache
     8  
     9  import (
    10  	"fmt"
    11  	"os"
    12  	"os/user"
    13  	"path"
    14  	"path/filepath"
    15  
    16  	"github.com/sylabs/singularity/internal/pkg/sylog"
    17  	"github.com/sylabs/singularity/internal/pkg/util/fs"
    18  )
    19  
    20  const (
    21  	// DirEnv specifies the environment variable which can set the directory
    22  	// for image downloads to be cached in
    23  	DirEnv = "SINGULARITY_CACHEDIR"
    24  
    25  	// RootDefault specifies the directory inside of ${HOME} that images are
    26  	// cached in by default.
    27  	// Uses "~/.singularity/cache" which will not clash with any 2.x cache
    28  	// directory.
    29  	RootDefault = ".singularity/cache"
    30  )
    31  
    32  var root string
    33  
    34  // Root is the root location where all of singularity caching happens. Library, Shub,
    35  // and oci image formats supported by containers/image repository will be cached inside
    36  //
    37  // Defaults to ${HOME}/.singularity/cache
    38  func Root() string {
    39  	updateCacheRoot()
    40  
    41  	return root
    42  }
    43  
    44  // Clean : wipes all files in the cache directory, will return a error if one occurs
    45  func Clean() error {
    46  	sylog.Debugf("Removing: %v", Root())
    47  
    48  	if err := os.RemoveAll(Root()); err != nil {
    49  		return fmt.Errorf("unable to clean all cache: %s", err)
    50  	}
    51  
    52  	return nil
    53  }
    54  
    55  func updateCacheRoot() {
    56  	usr, err := user.Current()
    57  	if err != nil {
    58  		sylog.Fatalf("Couldn't determine user home directory: %v", err)
    59  	}
    60  
    61  	if d := os.Getenv(DirEnv); d != "" {
    62  		root = d
    63  	} else {
    64  		root = path.Join(usr.HomeDir, RootDefault)
    65  	}
    66  
    67  	if err := initCacheDir(root); err != nil {
    68  		sylog.Fatalf("Unable to initialize caching directory: %v", err)
    69  	}
    70  }
    71  
    72  func updateCacheSubdir(subdir string) string {
    73  	updateCacheRoot()
    74  
    75  	absdir, err := filepath.Abs(filepath.Join(root, subdir))
    76  	if err != nil {
    77  		sylog.Fatalf("Unable to get abs filepath: %v", err)
    78  	}
    79  
    80  	if err := initCacheDir(absdir); err != nil {
    81  		sylog.Fatalf("Unable to initialize caching directory: %v", err)
    82  	}
    83  
    84  	sylog.Debugf("Caching directory set to %s", absdir)
    85  	return absdir
    86  }
    87  
    88  func initCacheDir(dir string) error {
    89  	if _, err := os.Stat(dir); os.IsNotExist(err) {
    90  		sylog.Debugf("Creating cache directory: %s", dir)
    91  		if err := fs.MkdirAll(dir, 0755); err != nil {
    92  			return fmt.Errorf("couldn't create cache directory %v: %v", dir, err)
    93  		}
    94  	} else if err != nil {
    95  		return fmt.Errorf("unable to stat %s: %s", dir, err)
    96  	}
    97  
    98  	return nil
    99  }