Download
41 lines 1.2 KiBGoModified 2026-10-31 raw
1234567891011121314151617181920212223242526272829303132333435363738394041
package sandbox

import (
	"bytes"
	"strings"
	"syscall"
)

// listOverlayAttrs reads the overlay's extended attributes of a directory
// or regular file, by name without the prefix: "user.overlay." for an
// overlay mounted in a user namespace, as bubblewrap's are, or
// "trusted.overlay." otherwise.
func listOverlayAttrs(path string) (map[string]string, error) {
	size, err := syscall.Listxattr(path, nil)
	if err != nil || size == 0 {
		return nil, err
	}
	names := make([]byte, size)
	if size, err = syscall.Listxattr(path, names); err != nil {
		return nil, err
	}
	attrs := map[string]string{}
	for _, name := range bytes.Split(bytes.TrimSuffix(names[:size], []byte{0}), []byte{0}) {
		short, ok := strings.CutPrefix(string(name), "user.overlay.")
		if !ok {
			if short, ok = strings.CutPrefix(string(name), "trusted.overlay."); !ok {
				continue // the file's own, which a preview does not carry over
			}
		}
		n, err := syscall.Getxattr(path, string(name), nil)
		if err != nil {
			return nil, err
		}
		value := make([]byte, n)
		if n, err = syscall.Getxattr(path, string(name), value); err != nil {
			return nil, err
		}
		attrs[short] = string(value[:n])
	}
	return attrs, nil
}