1/*  File:    sysfs/sysfs.pl
    2    Author:  Roy Ratcliffe
    3    Created: Dec  9 2024
    4    Purpose: Sysfs Virtual File System
    5
    6Copyright (c) 2026, Roy Ratcliffe, Northumberland, United Kingdom
    7
    8Permission is hereby granted, free of charge,  to any person obtaining a
    9copy  of  this  software  and    associated   documentation  files  (the
   10"Software"), to deal in  the   Software  without  restriction, including
   11without limitation the rights to  use,   copy,  modify,  merge, publish,
   12distribute, sub-license, and/or sell copies  of   the  Software,  and to
   13permit persons to whom the Software is   furnished  to do so, subject to
   14the following conditions:
   15
   16    The above copyright notice and this permission notice shall be
   17    included in all copies or substantial portions of the Software.
   18
   19THE SOFTWARE IS PROVIDED "AS IS", WITHOUT  WARRANTY OF ANY KIND, EXPRESS
   20OR  IMPLIED,  INCLUDING  BUT  NOT   LIMITED    TO   THE   WARRANTIES  OF
   21MERCHANTABILITY, FITNESS FOR A PARTICULAR   PURPOSE AND NONINFRINGEMENT.
   22IN NO EVENT SHALL THE AUTHORS  OR   COPYRIGHT  HOLDERS BE LIABLE FOR ANY
   23CLAIM, DAMAGES OR OTHER LIABILITY,  WHETHER   IN  AN ACTION OF CONTRACT,
   24TORT OR OTHERWISE, ARISING FROM,  OUT  OF   OR  IN  CONNECTION  WITH THE
   25SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
   26
   27*/
   28
   29:- module(sysfs,
   30          [ sysfs_entry/3 % +Class, -Entry, ?Entries:list
   31          , sysfs_exported_with_time_limit/3 % +File, -Abs, +Options:list
   32          ]).   33:- use_module(library(settings)).   34:- use_module(library(time)).   35:- use_module(library(sysfs/dcg_files)).

Sysfs Virtual File System

This module provides predicates to access the sysfs virtual file system in Linux. It allows developers to find the path to sysfs class directories and files in those directories. The predicates are designed to be flexible and can be used in various ways to access sysfs information.

author
- Roy Ratcliffe
version
- 1.0
license
- MIT
   50% The line encoding setting specifies the   encoding to use when reading
   51% and writing files. The default is  ASCII,   but  it  can be changed to
   52% UTF-8 if needed. This  setting  is   used  by  the  read_file_as/2 and
   53% write_file_as/3 predicates to determine how  to interpret the contents
   54% of the file being read or written.
   55:- setting(line_encoding, oneof([ascii, utf8]), ascii, 'Line encoding for reading and writing files.').
 sysfs_entry(+Class, -Entry, ?Entries:list) is nondet
True when Entry is a directory entry in the sysfs class Class, and Entries is the list of all nested directory entries in that class. For example, sysfs_entry(gpio, Entry, Entries) will unify Entry with each entry in the /sys/class/gpio directory, and Entries with the list of all nested entries in that directory.

Spans the sysfs virtual file system to find directory entries for a given class non-deterministically. Leaves a choice point even after finding an entry, so that backtracking can find all entries in the class.

Arguments:
Class- is the name of the sysfs class, such as gpio, block, net, etc.
Entry- is a directory entry in the specified class.
Entries- is the list of all nested directory entries in the specified class.
   78sysfs_entry(Class, Entry, Entries) :-
   79    absolute_file_name(sysfs_class(Class), Directory),
   80    (   ground(Entries)
   81    ->  phrase(directory_entry(Directory, Entry), Entries),
   82        % Cut to prevent backtracking after finding a matching entry, since only
   83        % one possible path exists for a given Entry in a given Class. This is
   84        % because the sysfs virtual file system, like other file systems, has a
   85        % unique path for each file or directory. Therefore, once a matching
   86        % entry is found, there is no need to continue searching for other
   87        % entries in the same class, as they will not match the specified Entry.
   88        !
   89    ;   phrase(directory_entry(Directory, Entry), Entries)
   90    ).
   91
   92:- setting(exported_time_limit, number, 1, 'Time limit for sysfs exported calls in seconds').   93:- setting(exported_delay_time, number, 0.01, 'Delay time between sysfs exported call retries in seconds').
 sysfs_exported_with_time_limit(+File, -Abs, +Options:list) is semidet
True when File is a file in the sysfs virtual file system that is exported and accessible, and Abs is the absolute path of that file. The predicate will sleep for the specified delay time and retry until the time limit is reached.

This predicate amounts to absolute_file_name/3 with a time limit and delay time. It is useful for checking if a file in the sysfs virtual file system is exported and accessible, without blocking indefinitely.

Arguments:
File- is the name of the file to check.
Abs- is the absolute path of the file if it exists and is accessible.
Options- is a list of options to pass to absolute_file_name/3. If the file exists and is accessible, sysfs_exported_with_time_limit will succeed. If the file does not exist or is not accessible, it will sleep for the specified delay time and retry until the time limit is reached.
  118sysfs_exported_with_time_limit(File, Abs, Options) :-
  119    setting(exported_time_limit, TimeLimit),
  120    setting(exported_delay_time, DelayTime),
  121    call_with_time_limit(TimeLimit,
  122                         (   repeat,
  123                             absolute_file_name(File, Abs, [file_errors(fail)|Options])
  124                         ->  !
  125                         ;   sleep(DelayTime),
  126                             fail
  127                         )).
  128
  129:- multifile user:file_search_path/2.  130
  131% This only works on Linux. It may  work on other Unix-like systems, but
  132% it is not tested. It does not work on Windows because Windows does not
  133% have a sysfs virtual file system.
  134%
  135% Sysfs is a virtual file system that   provides  a view of the kernel's
  136% device model. It is typically mounted at /sys and contains a hierarchy
  137% of  directories  and  files  that  represent  the  devices  and  their
  138% attributes. The file paths in sysfs are   not  real files on disk, but
  139% rather virtual files that the kernel   generates  on-the-fly when they
  140% are accessed. The contents of  these  files   can  be  read  to obtain
  141% information about the devices, and some of   them can be written to in
  142% order to change the state of the devices.
  143%
  144%   sysfs on /sys type sysfs (ro,nosuid,nodev,noexec,relatime)
  145%
  146user:file_search_path(sysfs, '/sys').
  147user:file_search_path(sysfs_class, sysfs(class))