//go:build linux /* * ============================================================================ * Projekt.....: rs2322tcp * Datei.......: internal/client/virtual_port_validation_linux.go * Copyright (C) 2026 Dieter Lang * * SPDX-License-Identifier: GPL-3.0-or-later * * Beschreibung: * Linux-spezifische Ermittlung der lokal vorhandenen virtuellen * rs2322tcp-Schnittstellen. * * Die öffentliche /dev/ttyUSBxxx-Schnittstelle wird ausschließlich gelesen. * Der Client verändert diese Schnittstellen hier nicht. * ============================================================================ */ package client import ( "fmt" "os" "path/filepath" "git.lang-dieter.de/rs2322tcp/internal/config" ) /////////////////////////////////////////////////////////////////////////////// // Existing virtual ports /////////////////////////////////////////////////////////////////////////////// // existingVirtualPortLinks returns all public virtual-port paths that // currently exist as symbolic links. // // Only ports inside the configured virtual-port range are considered. // The public /dev/ttyUSBxxx links are only inspected; they are never // created, changed, or removed by this function. // // This check only requires read access and therefore does not require // root privileges. func existingVirtualPortLinks( cfg config.VirtualPortRangeConfig, ) ([]string, error) { return existingVirtualPortLinksInDirectory( cfg, "/dev", ) } /////////////////////////////////////////////////////////////////////////////// // Existing virtual ports in directory /////////////////////////////////////////////////////////////////////////////// // existingVirtualPortLinksInDirectory returns all virtual-port paths in // directory that currently exist as symbolic links. // // This helper is deliberately separated from existingVirtualPortLinks so // the filesystem inspection can be tested without modifying /dev. func existingVirtualPortLinksInDirectory( cfg config.VirtualPortRangeConfig, directory string, ) ([]string, error) { if directory == "" { return nil, fmt.Errorf("virtual port directory is empty") } manager := NewVirtualPortManager(cfg) if manager == nil { return nil, fmt.Errorf("virtual port manager is nil") } links := make([]string, 0) for number := cfg.First; number <= cfg.Last; number++ { portName := filepath.Base( manager.PortPath(number), ) portPath := filepath.Join(directory, portName) info, err := os.Lstat(portPath) if err != nil { if os.IsNotExist(err) { continue } return nil, fmt.Errorf( "inspect virtual port %q: %w", portPath, err, ) } if info.Mode()&os.ModeSymlink == 0 { continue } links = append( links, filepath.Join(directory, portName), ) } return links, nil }