]> ruderich.org/simon Gitweb - safcm/safcm.git/blob - cmd/safcm/config/files.go
Use SPDX license identifiers
[safcm/safcm.git] / cmd / safcm / config / files.go
1 // Config: load files/ directory tree
2
3 // SPDX-License-Identifier: GPL-3.0-or-later
4 // Copyright (C) 2021-2024  Simon Ruderich
5
6 package config
7
8 import (
9         "fmt"
10         "io/fs"
11         "os"
12         slashpath "path"
13         "path/filepath"
14         "runtime"
15
16         "ruderich.org/simon/safcm"
17 )
18
19 func LoadFiles(group string) (map[string]*safcm.File, error) {
20         basePath := filepath.Join(group, "files")
21
22         const errMsg = `
23
24 The actual permissions and user/group of files and directories are not used
25 (except for +x on files). 0644/0755 and current remote user/group is used per
26 default. Apply different file permissions via permissions.yaml. To prevent
27 confusion files must be manually chmodded 0644/0755 and directories 0755 or
28 via "safcm fixperms".
29 `
30
31         // No permission checks on windows which doesn't track them.
32         windows := runtime.GOOS == "windows"
33
34         files := make(map[string]*safcm.File)
35         err := filepath.WalkDir(basePath, func(path string, d fs.DirEntry,
36                 err error) error {
37
38                 if err != nil {
39                         return err
40                 }
41
42                 info, err := d.Info()
43                 if err != nil {
44                         return err
45                 }
46                 typ := info.Mode().Type()
47                 perm := FileModeToFullPerm(info.Mode())
48
49                 var data []byte
50                 // See errMsg above. If a user stores a file with stricter
51                 // permissions they could assume that these permissions are
52                 // respected. This is not the case.
53                 if typ == 0 /* regular file */ {
54                         if windows {
55                                 perm = 0644
56                                 // 0755 must be set via permissions.yaml if
57                                 // windows is used
58                         }
59                         if perm != 0644 && perm != 0755 {
60                                 return fmt.Errorf(
61                                         "%q: invalid permissions %#o%s",
62                                         path, perm, errMsg)
63                         }
64                         data, err = os.ReadFile(path)
65                         if err != nil {
66                                 return err
67                         }
68                 } else if typ == fs.ModeDir {
69                         if windows {
70                                 perm = 0755
71                         }
72                         if perm != 0755 {
73                                 return fmt.Errorf(
74                                         "%q: invalid permissions %#o%s",
75                                         path, perm, errMsg)
76                         }
77                 } else if typ == fs.ModeSymlink {
78                         x, err := os.Readlink(path)
79                         if err != nil {
80                                 return err
81                         }
82                         data = []byte(x)
83                         perm |= 0777 // see cmd/safcm-remote/sync/files.go
84                 } else {
85                         return fmt.Errorf("%q: file type not supported", path)
86                 }
87
88                 // Convert to absolute and slash-separated path as used on the
89                 // target host
90                 x, err := filepath.Rel(basePath, path)
91                 if err != nil {
92                         return err
93                 }
94                 x = slashpath.Join("/", filepath.ToSlash(x))
95
96                 files[x] = &safcm.File{
97                         Path: x,
98                         Mode: typ | (fs.FileMode(perm) & fs.ModePerm),
99                         Uid:  -1,
100                         Gid:  -1,
101                         Data: data,
102                 }
103                 return nil
104         })
105         if err != nil {
106                 if os.IsNotExist(err) {
107                         return nil, nil
108                 }
109                 return nil, fmt.Errorf("%s: %v", group, err)
110         }
111         return files, nil
112 }