github.com/apptainer/singularity@v3.1.1+incompatible/internal/pkg/util/fs/mount/system.go (about)

     1  // Copyright (c) 2018, 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 mount
     7  
     8  import (
     9  	"fmt"
    10  )
    11  
    12  // hookFn describes function prototype for function
    13  // to be called before/after mounting a tag list
    14  type hookFn func(*System) error
    15  
    16  // mountFn describes function prototype for function responsible
    17  // of mount operation
    18  type mountFn func(*Point) error
    19  
    20  // System defines a mount system allowing to register before/after
    21  // hook functions for specific tag during mount phase
    22  type System struct {
    23  	Points         *Points
    24  	Mount          mountFn
    25  	beforeTagHooks map[AuthorizedTag][]hookFn
    26  	afterTagHooks  map[AuthorizedTag][]hookFn
    27  }
    28  
    29  func (b *System) init() {
    30  	if b.beforeTagHooks == nil {
    31  		b.beforeTagHooks = make(map[AuthorizedTag][]hookFn, 0)
    32  	}
    33  	if b.afterTagHooks == nil {
    34  		b.afterTagHooks = make(map[AuthorizedTag][]hookFn, 0)
    35  	}
    36  }
    37  
    38  // RunBeforeTag registers a hook function executed before mounting points
    39  // of tag list
    40  func (b *System) RunBeforeTag(tag AuthorizedTag, fn hookFn) error {
    41  	if _, ok := authorizedTags[tag]; !ok {
    42  		return fmt.Errorf("tag %s is not an authorized tag", tag)
    43  	}
    44  	b.init()
    45  	b.beforeTagHooks[tag] = append(b.beforeTagHooks[tag], fn)
    46  	return nil
    47  }
    48  
    49  // RunAfterTag registers a hook function executed after mounting points
    50  // of tag list
    51  func (b *System) RunAfterTag(tag AuthorizedTag, fn hookFn) error {
    52  	if _, ok := authorizedTags[tag]; !ok {
    53  		return fmt.Errorf("tag %s is not an authorized tag", tag)
    54  	}
    55  	b.init()
    56  	b.afterTagHooks[tag] = append(b.afterTagHooks[tag], fn)
    57  	return nil
    58  }
    59  
    60  // MountAll iterates over mount point list and mounts every point
    61  // by calling hook before/after hook functions
    62  func (b *System) MountAll() error {
    63  	b.init()
    64  	for _, tag := range GetTagList() {
    65  		for _, fn := range b.beforeTagHooks[tag] {
    66  			if err := fn(b); err != nil {
    67  				return fmt.Errorf("hook function for tag %s returns error: %s", tag, err)
    68  			}
    69  		}
    70  		for _, point := range b.Points.GetByTag(tag) {
    71  			if b.Mount != nil {
    72  				if err := b.Mount(&point); err != nil {
    73  					return fmt.Errorf("mount %s->%s error: %s", point.Source, point.Destination, err)
    74  				}
    75  			}
    76  		}
    77  		for _, fn := range b.afterTagHooks[tag] {
    78  			if err := fn(b); err != nil {
    79  				return fmt.Errorf("hook function for tag %s returns error: %s", tag, err)
    80  			}
    81  		}
    82  	}
    83  	return nil
    84  }