mirror of
https://github.com/Myzel394/config-lsp.git
synced 2025-06-18 23:15:26 +02:00
fix(fstab): Improve fstab parser
This commit is contained in:
parent
afec5e896d
commit
3f102e283d
11
handlers/fstab/documentation/documentation-freq.go
Normal file
11
handlers/fstab/documentation/documentation-freq.go
Normal file
@ -0,0 +1,11 @@
|
||||
package fstabdocumentation
|
||||
|
||||
import docvalues "config-lsp/doc-values"
|
||||
|
||||
var minValue = 0
|
||||
var maxValue = 9
|
||||
|
||||
var FreqField = docvalues.NumberValue{
|
||||
Min: &minValue,
|
||||
Max: &maxValue,
|
||||
}
|
23
handlers/fstab/documentation/documentation-mount-point.go
Normal file
23
handlers/fstab/documentation/documentation-mount-point.go
Normal file
@ -0,0 +1,23 @@
|
||||
package fstabdocumentation
|
||||
|
||||
import (
|
||||
docvalues "config-lsp/doc-values"
|
||||
"regexp"
|
||||
)
|
||||
|
||||
var MountPointField = docvalues.OrValue{
|
||||
Values: []docvalues.Value{
|
||||
docvalues.EnumValue{
|
||||
Values: []docvalues.EnumString{
|
||||
{
|
||||
InsertText: "none",
|
||||
DescriptionText: "none",
|
||||
Documentation: "Specify that the filesystem should be treated as swap space",
|
||||
},
|
||||
},
|
||||
},
|
||||
docvalues.RegexValue{
|
||||
Regex: *regexp.MustCompile(`\S+`),
|
||||
},
|
||||
},
|
||||
}
|
@ -1,9 +1,8 @@
|
||||
package fstab
|
||||
package fstabdocumentation
|
||||
|
||||
import (
|
||||
commondocumentation "config-lsp/common-documentation/filesystems"
|
||||
commondocumentation "config-lsp/common-documentation/filesystems/mountoptions"
|
||||
docvalues "config-lsp/doc-values"
|
||||
"config-lsp/utils"
|
||||
"strings"
|
||||
)
|
||||
|
||||
@ -199,67 +198,40 @@ type assignOption struct {
|
||||
Handler func(context docvalues.KeyValueAssignmentContext) docvalues.Value
|
||||
}
|
||||
|
||||
var defaultAssignOptions = map[string]commondocumentation.AssignableOption{
|
||||
"context": {
|
||||
Documentation: "The context= option is useful when mounting filesystems that do not support extended attributes, such as a floppy or hard disk formatted with VFAT, or systems that are not normally running under SELinux, such as an ext3 or ext4 formatted disk from a non-SELinux workstation. You can also use context= on filesystems you do not trust, such as a floppy. It also helps in compatibility with xattr-supporting filesystems on earlier 2.4.<x> kernel versions. Even where xattrs are supported, you can save time not having to label every file by assigning the entire disk one security context. A commonly used option for removable media is context=\"system_u:object_r:removable_t\".",
|
||||
Handler: func(_ docvalues.KeyValueAssignmentContext) docvalues.Value {
|
||||
return docvalues.StringValue{}
|
||||
},
|
||||
},
|
||||
"fscontext": {
|
||||
Documentation: "The fscontext= option works for all filesystems, regardless of their xattr support. The fscontext option sets the overarching filesystem label to a specific security context. This filesystem label is separate from the individual labels on the files. It represents the entire filesystem for certain kinds of permission checks, such as during mount or file creation. Individual file labels are still obtained from the xattrs on the files themselves. The context option actually sets the aggregate context that fscontext provides, in addition to supplying the same label for individual files.",
|
||||
Handler: func(_ docvalues.KeyValueAssignmentContext) docvalues.Value {
|
||||
return docvalues.StringValue{}
|
||||
},
|
||||
},
|
||||
"defcontext": {
|
||||
Documentation: "You can set the default security context for unlabeled files using defcontext= option. This overrides the value set for unlabeled files in the policy and requires a filesystem that supports xattr labeling.",
|
||||
Handler: func(_ docvalues.KeyValueAssignmentContext) docvalues.Value {
|
||||
return docvalues.StringValue{}
|
||||
},
|
||||
},
|
||||
"rootcontext": {
|
||||
Documentation: "The rootcontext= option allows you to explicitly label the root inode of a FS being mounted before that FS or inode becomes visible to userspace. This was found to be useful for things like stateless Linux. The special value @target can be used to assign the current context of the target mountpoint location.",
|
||||
Handler: func(_ docvalues.KeyValueAssignmentContext) docvalues.Value {
|
||||
return docvalues.StringValue{}
|
||||
},
|
||||
},
|
||||
var defaultAssignOptions = map[docvalues.EnumString]docvalues.Value{
|
||||
docvalues.CreateEnumStringWithDoc(
|
||||
"context",
|
||||
"The context= option is useful when mounting filesystems that do not support extended attributes, such as a floppy or hard disk formatted with VFAT, or systems that are not normally running under SELinux, such as an ext3 or ext4 formatted disk from a non-SELinux workstation. You can also use context= on filesystems you do not trust, such as a floppy. It also helps in compatibility with xattr-supporting filesystems on earlier 2.4.<x> kernel versions. Even where xattrs are supported, you can save time not having to label every file by assigning the entire disk one security context. A commonly used option for removable media is context=\"system_u:object_r:removable_t\".",
|
||||
): docvalues.StringValue{},
|
||||
docvalues.CreateEnumStringWithDoc(
|
||||
"fscontext",
|
||||
"The fscontext= option works for all filesystems, regardless of their xattr support. The fscontext option sets the overarching filesystem label to a specific security context. This filesystem label is separate from the individual labels on the files. It represents the entire filesystem for certain kinds of permission checks, such as during mount or file creation. Individual file labels are still obtained from the xattrs on the files themselves. The context option actually sets the aggregate context that fscontext provides, in addition to supplying the same label for individual files.",
|
||||
): docvalues.StringValue{},
|
||||
docvalues.CreateEnumStringWithDoc(
|
||||
"defcontext",
|
||||
"You can set the default security context for unlabeled files using defcontext= option. This overrides the value set for unlabeled files in the policy and requires a filesystem that supports xattr labeling.",
|
||||
): docvalues.StringValue{},
|
||||
docvalues.CreateEnumStringWithDoc(
|
||||
"rootcontext",
|
||||
"The rootcontext= option allows you to explicitly label the root inode of a FS being mounted before that FS or inode becomes visible to userspace. This was found to be useful for things like stateless Linux. The special value @target can be used to assign the current context of the target mountpoint location.",
|
||||
): docvalues.StringValue{},
|
||||
}
|
||||
|
||||
func createMountOptionField(
|
||||
options []docvalues.EnumString,
|
||||
assignOption map[string]commondocumentation.AssignableOption,
|
||||
assignOption map[docvalues.EnumString]docvalues.Value,
|
||||
) docvalues.Value {
|
||||
dynamicOptions := utils.MergeMaps(defaultAssignOptions, assignOption)
|
||||
dynamicOptions := docvalues.MergeKeyEnumAssignmentMaps(defaultAssignOptions, assignOption)
|
||||
|
||||
return docvalues.ArrayValue{
|
||||
Separator: ",",
|
||||
DuplicatesExtractor: &mountOptionsExtractor,
|
||||
SubValue: docvalues.OrValue{
|
||||
Values: []docvalues.Value{
|
||||
docvalues.KeyValueAssignmentValue{
|
||||
Separator: "=",
|
||||
docvalues.KeyEnumAssignmentValue{
|
||||
Values: dynamicOptions,
|
||||
ValueIsOptional: false,
|
||||
Key: docvalues.EnumValue{
|
||||
EnforceValues: true,
|
||||
Values: utils.Map(
|
||||
utils.KeysOfMap(dynamicOptions),
|
||||
func(key string) docvalues.EnumString {
|
||||
return docvalues.CreateEnumStringWithDoc(
|
||||
key,
|
||||
dynamicOptions[key].Documentation,
|
||||
)
|
||||
},
|
||||
),
|
||||
},
|
||||
Value: docvalues.CustomValue{
|
||||
FetchValue: func(rawContext docvalues.CustomValueContext) docvalues.Value {
|
||||
context := rawContext.(docvalues.KeyValueAssignmentContext)
|
||||
option := dynamicOptions[context.SelectedKey]
|
||||
|
||||
return option.Handler(context)
|
||||
},
|
||||
},
|
||||
Separator: "=",
|
||||
},
|
||||
docvalues.EnumValue{
|
||||
EnforceValues: true,
|
||||
@ -270,30 +242,38 @@ func createMountOptionField(
|
||||
}
|
||||
}
|
||||
|
||||
var defaultMountOptionsField = createMountOptionField([]docvalues.EnumString{}, map[string]commondocumentation.AssignableOption{})
|
||||
var DefaultMountOptionsField = createMountOptionField([]docvalues.EnumString{}, map[docvalues.EnumString]docvalues.Value{})
|
||||
|
||||
var mountOptionsMapField = map[string]docvalues.Value{
|
||||
"adfs": createMountOptionField(
|
||||
[]docvalues.EnumString{},
|
||||
map[string]commondocumentation.AssignableOption{
|
||||
"uid": {
|
||||
Documentation: "Set the owner of the files in the filesystem",
|
||||
Handler: func(context docvalues.KeyValueAssignmentContext) docvalues.Value {
|
||||
min := 0
|
||||
return docvalues.NumberValue{Min: &min}
|
||||
},
|
||||
},
|
||||
"gid": {
|
||||
Documentation: "Set the group of the files in the filesystem",
|
||||
Handler: func(context docvalues.KeyValueAssignmentContext) docvalues.Value {
|
||||
min := 0
|
||||
return docvalues.NumberValue{Min: &min}
|
||||
},
|
||||
},
|
||||
},
|
||||
),
|
||||
var MountOptionsMapField = map[string]docvalues.Value{
|
||||
// "adfs": createMountOptionField(
|
||||
// []docvalues.EnumString{},
|
||||
// map[string]commondocumentation.AssignableOption{
|
||||
// "uid": {
|
||||
// Documentation: "Set the owner of the files in the filesystem",
|
||||
// Handler: func(context docvalues.KeyValueAssignmentContext) docvalues.Value {
|
||||
// min := 0
|
||||
// return docvalues.NumberValue{Min: &min}
|
||||
// },
|
||||
// },
|
||||
// "gid": {
|
||||
// Documentation: "Set the group of the files in the filesystem",
|
||||
// Handler: func(context docvalues.KeyValueAssignmentContext) docvalues.Value {
|
||||
// min := 0
|
||||
// return docvalues.NumberValue{Min: &min}
|
||||
// },
|
||||
// },
|
||||
// },
|
||||
// ),
|
||||
"ext2": createMountOptionField(
|
||||
commondocumentation.Ext2DocumentationEnums,
|
||||
commondocumentation.Ext2DocumentationAssignable,
|
||||
),
|
||||
"ext3": createMountOptionField(
|
||||
append(commondocumentation.Ext2DocumentationEnums, commondocumentation.Ext3DocumentationEnums...),
|
||||
docvalues.MergeKeyEnumAssignmentMaps(commondocumentation.Ext2DocumentationAssignable, commondocumentation.Ext3DocumentationAssignable),
|
||||
),
|
||||
"ext4": createMountOptionField(
|
||||
append(append(commondocumentation.Ext2DocumentationEnums, commondocumentation.Ext3DocumentationEnums...), commondocumentation.Ext4DocumentationEnums...),
|
||||
docvalues.MergeKeyEnumAssignmentMaps(commondocumentation.Ext2DocumentationAssignable, docvalues.MergeKeyEnumAssignmentMaps(commondocumentation.Ext3DocumentationAssignable, commondocumentation.Ext4DocumentationAssignable)),
|
||||
),
|
||||
}
|
26
handlers/fstab/documentation/documentation-pass.go
Normal file
26
handlers/fstab/documentation/documentation-pass.go
Normal file
@ -0,0 +1,26 @@
|
||||
package fstabdocumentation
|
||||
|
||||
import docvalues "config-lsp/doc-values"
|
||||
|
||||
var PassField = docvalues.OrValue{
|
||||
Values: []docvalues.Value{
|
||||
docvalues.EnumValue{
|
||||
EnforceValues: false,
|
||||
Values: []docvalues.EnumString{
|
||||
docvalues.CreateEnumStringWithDoc(
|
||||
"0",
|
||||
"Defaults to zero (don’t check the filesystem) if not present.",
|
||||
),
|
||||
docvalues.CreateEnumStringWithDoc(
|
||||
"1",
|
||||
"The root filesystem should be specified with a fs_passno of 1.",
|
||||
),
|
||||
docvalues.CreateEnumStringWithDoc(
|
||||
"2",
|
||||
"Other filesystems [than the root filesystem] should have a fs_passno of 2.",
|
||||
),
|
||||
},
|
||||
},
|
||||
docvalues.NumberValue{},
|
||||
},
|
||||
}
|
@ -1,18 +1,18 @@
|
||||
package fstab
|
||||
package fstabdocumentation
|
||||
|
||||
import (
|
||||
docvalues "config-lsp/doc-values"
|
||||
"regexp"
|
||||
)
|
||||
|
||||
var uuidField = docvalues.RegexValue{
|
||||
var UuidField = docvalues.RegexValue{
|
||||
Regex: *regexp.MustCompile(`[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}`),
|
||||
}
|
||||
var labelField = docvalues.RegexValue{
|
||||
var LabelField = docvalues.RegexValue{
|
||||
Regex: *regexp.MustCompile(`\S+`),
|
||||
}
|
||||
|
||||
var specField = docvalues.OrValue{
|
||||
var SpecField = docvalues.OrValue{
|
||||
Values: []docvalues.Value{
|
||||
// docvalues.PathValue{
|
||||
// RequiredType: docvalues.PathTypeFile & docvalues.PathTypeExistenceOptional,
|
||||
@ -36,10 +36,10 @@ var specField = docvalues.OrValue{
|
||||
switch context.SelectedKey {
|
||||
case "UUID":
|
||||
case "PARTUUID":
|
||||
return uuidField
|
||||
return UuidField
|
||||
case "LABEL":
|
||||
case "PARTLABEL":
|
||||
return labelField
|
||||
return LabelField
|
||||
}
|
||||
|
||||
return docvalues.StringValue{}
|
||||
@ -48,20 +48,3 @@ var specField = docvalues.OrValue{
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
var mountPointField = docvalues.OrValue{
|
||||
Values: []docvalues.Value{
|
||||
docvalues.EnumValue{
|
||||
Values: []docvalues.EnumString{
|
||||
{
|
||||
InsertText: "none",
|
||||
DescriptionText: "none",
|
||||
Documentation: "Specify that the filesystem should be treated as swap space",
|
||||
},
|
||||
},
|
||||
},
|
||||
docvalues.RegexValue{
|
||||
Regex: *regexp.MustCompile(`\S+`),
|
||||
},
|
||||
},
|
||||
}
|
@ -1,8 +1,8 @@
|
||||
package fstab
|
||||
package fstabdocumentation
|
||||
|
||||
import docvalues "config-lsp/doc-values"
|
||||
|
||||
var fileSystemTypeField = docvalues.ArrayValue{
|
||||
var FileSystemTypeField = docvalues.ArrayValue{
|
||||
Separator: ",",
|
||||
DuplicatesExtractor: &docvalues.SimpleDuplicatesExtractor,
|
||||
SubValue: docvalues.EnumValue{
|
@ -3,6 +3,7 @@ package fstab
|
||||
import (
|
||||
"config-lsp/common"
|
||||
docvalues "config-lsp/doc-values"
|
||||
fstabdocumentation "config-lsp/handlers/fstab/documentation"
|
||||
"fmt"
|
||||
"regexp"
|
||||
"slices"
|
||||
@ -62,45 +63,40 @@ type FstabEntry struct {
|
||||
}
|
||||
|
||||
func (e *FstabEntry) CheckIsValid() []protocol.Diagnostic {
|
||||
println(fmt.Sprintf("Checking entry at line %d; fields: %v", e.Line, e.Fields))
|
||||
diagnostics := make([]protocol.Diagnostic, 0)
|
||||
severity := protocol.DiagnosticSeverityError
|
||||
|
||||
if e.Fields.Spec != nil {
|
||||
err := specField.CheckIsValid(e.Fields.Spec.Value)
|
||||
errors := fstabdocumentation.SpecField.CheckIsValid(e.Fields.Spec.Value)
|
||||
|
||||
if err != nil {
|
||||
diagnostics = append(diagnostics, protocol.Diagnostic{
|
||||
Range: e.Fields.Spec.CreateRange(e.Line),
|
||||
Message: err.Error(),
|
||||
Severity: &severity,
|
||||
})
|
||||
if len(errors) > 0 {
|
||||
diagnostics = append(
|
||||
diagnostics,
|
||||
docvalues.InvalidValuesToErrorDiagnostics(e.Line, e.Fields.Spec.Start, errors)...,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
if e.Fields.MountPoint != nil {
|
||||
err := mountPointField.CheckIsValid(e.Fields.MountPoint.Value)
|
||||
errors := fstabdocumentation.MountPointField.CheckIsValid(e.Fields.MountPoint.Value)
|
||||
|
||||
if err != nil {
|
||||
diagnostics = append(diagnostics, protocol.Diagnostic{
|
||||
Range: e.Fields.Spec.CreateRange(e.Line),
|
||||
Message: err.Error(),
|
||||
Severity: &severity,
|
||||
})
|
||||
if len(errors) > 0 {
|
||||
diagnostics = append(
|
||||
diagnostics,
|
||||
docvalues.InvalidValuesToErrorDiagnostics(e.Line, e.Fields.MountPoint.Start, errors)...,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
var fileSystemType string = ""
|
||||
|
||||
if e.Fields.FilesystemType != nil {
|
||||
err := fileSystemTypeField.CheckIsValid(e.Fields.FilesystemType.Value)
|
||||
errors := fstabdocumentation.FileSystemTypeField.CheckIsValid(e.Fields.FilesystemType.Value)
|
||||
|
||||
if err != nil {
|
||||
diagnostics = append(diagnostics, protocol.Diagnostic{
|
||||
Range: e.Fields.FilesystemType.CreateRange(e.Line),
|
||||
Message: err.Error(),
|
||||
Severity: &severity,
|
||||
})
|
||||
if len(errors) > 0 {
|
||||
diagnostics = append(
|
||||
diagnostics,
|
||||
docvalues.InvalidValuesToErrorDiagnostics(e.Line, e.Fields.FilesystemType.Start, errors)...,
|
||||
)
|
||||
} else {
|
||||
fileSystemType = e.Fields.FilesystemType.Value
|
||||
}
|
||||
@ -109,22 +105,41 @@ func (e *FstabEntry) CheckIsValid() []protocol.Diagnostic {
|
||||
if e.Fields.Options != nil && fileSystemType != "" {
|
||||
var optionsField docvalues.Value
|
||||
|
||||
if foundField, found := mountOptionsMapField[fileSystemType]; found {
|
||||
if foundField, found := fstabdocumentation.MountOptionsMapField[fileSystemType]; found {
|
||||
optionsField = foundField
|
||||
} else {
|
||||
optionsField = defaultMountOptionsField
|
||||
optionsField = fstabdocumentation.DefaultMountOptionsField
|
||||
}
|
||||
|
||||
println(fmt.Sprintf("Checking options for %s", fileSystemType))
|
||||
errors := optionsField.CheckIsValid(e.Fields.Options.Value)
|
||||
|
||||
err := optionsField.CheckIsValid(e.Fields.Options.Value)
|
||||
if len(errors) > 0 {
|
||||
diagnostics = append(
|
||||
diagnostics,
|
||||
docvalues.InvalidValuesToErrorDiagnostics(e.Line, e.Fields.Options.Start, errors)...,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
diagnostics = append(diagnostics, protocol.Diagnostic{
|
||||
Range: e.Fields.Options.CreateRange(e.Line),
|
||||
Message: err.Error(),
|
||||
Severity: &severity,
|
||||
})
|
||||
if e.Fields.Freq != nil {
|
||||
errors := fstabdocumentation.FreqField.CheckIsValid(e.Fields.Freq.Value)
|
||||
|
||||
if len(errors) > 0 {
|
||||
diagnostics = append(
|
||||
diagnostics,
|
||||
docvalues.InvalidValuesToErrorDiagnostics(e.Line, e.Fields.Freq.Start, errors)...,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
if e.Fields.Pass != nil {
|
||||
errors := fstabdocumentation.PassField.CheckIsValid(e.Fields.Pass.Value)
|
||||
|
||||
if len(errors) > 0 {
|
||||
diagnostics = append(
|
||||
diagnostics,
|
||||
docvalues.InvalidValuesToErrorDiagnostics(e.Line, e.Fields.Pass.Start, errors)...,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user