package storage import ( "fmt" "strings" ) // renderMountUnit builds the systemd .mount unit content for a (already-validated) spec. // Keyed by fs-UUID via What=/dev/disk/by-uuid/ so it survives /dev/sdX renumbering; // WantedBy=multi-user.target so `enable` makes it persist across reboot. // // All interpolated values are pre-validated by the caller (ValidateUUID / ValidateMountPath // / validateUnitOpt), so no value here can carry a newline or inject an extra directive. func renderMountUnit(spec MountSpec) string { what := byUUIDDir + "/" + spec.UUID var b strings.Builder b.WriteString("# Managed by felhom-agent — do not edit by hand.\n") b.WriteString("[Unit]\n") fmt.Fprintf(&b, "Description=Felhom storage mount %s\n", sanitizeDesc(spec.Name)) b.WriteString("After=local-fs-pre.target\n") b.WriteString("\n[Mount]\n") fmt.Fprintf(&b, "What=%s\n", what) fmt.Fprintf(&b, "Where=%s\n", spec.Where) if spec.FSType != "" { fmt.Fprintf(&b, "Type=%s\n", spec.FSType) } if spec.Options != "" { fmt.Fprintf(&b, "Options=%s\n", spec.Options) } b.WriteString("\n[Install]\n") b.WriteString("WantedBy=multi-user.target\n") return b.String() } // sanitizeDesc keeps the Description line single-line and harmless (it is cosmetic; the // name is already a Proxmox storage id, but be defensive against any newline). func sanitizeDesc(name string) string { name = strings.ReplaceAll(name, "\n", " ") name = strings.ReplaceAll(name, "\r", " ") if name == "" { return "(unnamed)" } return name }