LCOV - code coverage report
Current view: top level - cmdline - portable.h (source / functions) Hit Total Coverage
Test: lcov.info Lines: 2 2 100.0 %
Date: 2026-04-29 15:04:44 Functions: 1 1 100.0 %

          Line data    Source code
       1             : // SPDX-License-Identifier: GPL-3.0-or-later
       2             : // Copyright (C) 2011 Andrea Mazzoleni
       3             : 
       4             : #ifndef __PORTABLE_H
       5             : #define __PORTABLE_H
       6             : 
       7             : #if HAVE_CONFIG_H
       8             : #include "config.h" /* Use " to include first in the same directory of this file */
       9             : #endif
      10             : 
      11             : /***************************************************************************/
      12             : /* Config */
      13             : 
      14             : #ifdef __MINGW32__
      15             : /**
      16             :  * Enable the GNU printf functions instead of using the MSVCRT ones.
      17             :  *
      18             :  * Note that this is the default if _POSIX is also defined.
      19             :  * To disable it you have to set it to 0.
      20             :  */
      21             : #define __USE_MINGW_ANSI_STDIO 1
      22             : 
      23             : /**
      24             :  * Define the MSVCRT version targeting Windows Vista.
      25             :  */
      26             : #define __MSVCRT_VERSION__ 0x0600
      27             : 
      28             : /**
      29             :  * Include Windows Vista headers.
      30             :  *
      31             :  * Like for InitializeCriticalSection().
      32             :  */
      33             : #define _WIN32_WINNT 0x600
      34             : 
      35             : /**
      36             :  * Undef as it clashes with windows.h declarations
      37             :  */
      38             : #undef DATADIR
      39             : 
      40             : #include <windows.h>
      41             : #endif
      42             : 
      43             : /**
      44             :  * Specify the format attribute for printf.
      45             :  */
      46             : #ifdef __MINGW32__
      47             : #if defined(__USE_MINGW_ANSI_STDIO) && __USE_MINGW_ANSI_STDIO == 1
      48             : #define attribute_printf gnu_printf /* GNU format */
      49             : #else
      50             : #define attribute_printf ms_printf /* MSVCRT format */
      51             : #endif
      52             : #else
      53             : #define attribute_printf printf /* GNU format is the default one */
      54             : #endif
      55             : 
      56             : /**
      57             :  * Compiler extension
      58             :  */
      59             : #ifndef __always_inline
      60             : #define __always_inline inline __attribute__((always_inline))
      61             : #endif
      62             : 
      63             : #ifndef __noreturn
      64             : #define __noreturn __attribute__((noreturn))
      65             : #endif
      66             : 
      67             : 
      68             : /**
      69             :  * Architecture for inline assembly.
      70             :  */
      71             : #if HAVE_ASSEMBLY
      72             : #if defined(__i386__)
      73             : #define CONFIG_X86 1
      74             : #define CONFIG_X86_32 1
      75             : #endif
      76             : 
      77             : #if defined(__x86_64__)
      78             : #define CONFIG_X86 1
      79             : #define CONFIG_X86_64 1
      80             : #endif
      81             : #endif
      82             : 
      83             : /**
      84             :  * Includes some platform specific headers.
      85             :  */
      86             : #if HAVE_SYS_PARAM_H
      87             : #include <sys/param.h>
      88             : #endif
      89             : 
      90             : #if HAVE_SYS_MOUNT_H
      91             : #include <sys/mount.h>
      92             : #endif
      93             : 
      94             : #if HAVE_SYS_VFS_H
      95             : #include <sys/vfs.h>
      96             : #endif
      97             : 
      98             : #if HAVE_SYS_STATFS_H
      99             : #include <sys/statfs.h>
     100             : #endif
     101             : 
     102             : #if HAVE_SYS_FILE_H
     103             : #include <sys/file.h>
     104             : #endif
     105             : 
     106             : #if HAVE_SYS_IOCTL_H
     107             : #include <sys/ioctl.h>
     108             : #endif
     109             : 
     110             : #if HAVE_LINUX_FS_H
     111             : #include <linux/fs.h>
     112             : #endif
     113             : 
     114             : #if HAVE_LINUX_BTRFS_H
     115             : #include <linux/btrfs.h>
     116             : #endif
     117             : 
     118             : #if HAVE_LINUX_FIEMAP_H
     119             : #include <linux/fiemap.h>
     120             : #endif
     121             : 
     122             : #if HAVE_BLKID_BLKID_H
     123             : #include <blkid/blkid.h>
     124             : #if HAVE_BLKID_DEVNO_TO_DEVNAME && HAVE_BLKID_GET_TAG_VALUE
     125             : #define HAVE_BLKID 1
     126             : #endif
     127             : #endif
     128             : 
     129             : /**
     130             :  * Includes some standard headers.
     131             :  */
     132             : #include <stdio.h>
     133             : #include <stdlib.h> /* On many systems (e.g., Darwin), `stdio.h' is a prerequisite. */
     134             : #include <stdarg.h>
     135             : #include <string.h>
     136             : #include <ctype.h>
     137             : #include <fcntl.h>
     138             : #include <assert.h>
     139             : #include <errno.h>
     140             : #include <signal.h>
     141             : #include <limits.h>
     142             : 
     143             : #if HAVE_STDINT_H
     144             : #include <stdint.h>
     145             : #endif
     146             : 
     147             : #if HAVE_INTTYPES_H
     148             : #include <inttypes.h>
     149             : #endif
     150             : 
     151             : #if HAVE_UNISTD_H
     152             : #include <unistd.h>
     153             : #endif
     154             : 
     155             : #if TIME_WITH_SYS_TIME
     156             : #include <sys/time.h>
     157             : #include <time.h>
     158             : #else
     159             : #if HAVE_SYS_TIME_H
     160             : #include <sys/time.h>
     161             : #else
     162             : #include <time.h>
     163             : #endif
     164             : #endif
     165             : 
     166             : #if HAVE_MACH_MACH_TIME_H
     167             : #include <mach/mach_time.h>
     168             : #endif
     169             : 
     170             : #if HAVE_DIRENT_H
     171             : #include <dirent.h>
     172             : #define NAMLEN(dirent) strlen((dirent)->d_name)
     173             : #else
     174             : #define dirent direct
     175             : #define NAMLEN(dirent) (dirent)->d_namlen
     176             : #if HAVE_SYS_NDIR_H
     177             : #include <sys/ndir.h>
     178             : #endif
     179             : #if HAVE_SYS_DIR_H
     180             : #include <sys/dir.h>
     181             : #endif
     182             : #if HAVE_NDIR_H
     183             : #include <ndir.h>
     184             : #endif
     185             : #endif
     186             : 
     187             : #if HAVE_SYS_TYPES_H
     188             : #include <sys/types.h>
     189             : #endif
     190             : 
     191             : #if HAVE_SYS_MKDEV
     192             : #include <sys/mkdev.h>
     193             : #endif
     194             : 
     195             : #if HAVE_SYS_SYSMACROS_H
     196             : #include <sys/sysmacros.h>
     197             : #endif
     198             : 
     199             : #if HAVE_SYS_STAT_H
     200             : #include <sys/stat.h>
     201             : #endif
     202             : 
     203             : #if HAVE_SYS_WAIT_H
     204             : #include <sys/wait.h>
     205             : #endif
     206             : 
     207             : #if HAVE_GETOPT_H
     208             : #include <getopt.h>
     209             : #endif
     210             : 
     211             : #if HAVE_MATH_H
     212             : #include <math.h>
     213             : #endif
     214             : 
     215             : #if HAVE_EXECINFO_H
     216             : #include <execinfo.h>
     217             : #endif
     218             : 
     219             : #ifdef __APPLE__
     220             : #include <CoreFoundation/CoreFoundation.h>
     221             : #include <DiskArbitration/DiskArbitration.h>
     222             : #include <mach-o/dyld.h>
     223             : #endif
     224             : 
     225             : #if HAVE_IO_H
     226             : #include <io.h>
     227             : #endif
     228             : 
     229             : #if HAVE_GETOPT_LONG
     230             : #define SWITCH_GETOPT_LONG(a, b) a
     231             : #else
     232             : #define SWITCH_GETOPT_LONG(a, b) b
     233             : #endif
     234             : 
     235             : /**
     236             :  * Enables lock file support.
     237             :  */
     238             : #if HAVE_FLOCK && HAVE_FTRUNCATE
     239             : #define HAVE_LOCKFILE 1
     240             : #endif
     241             : 
     242             : /**
     243             :  * Includes specific support for Windows or Linux.
     244             :  */
     245             : #ifdef __MINGW32__
     246             : #include "mingw.h"
     247             : #else
     248             : #include "unix.h"
     249             : #endif
     250             : 
     251             : /****************************************************************************/
     252             : /* os */
     253             : 
     254             : /**
     255             :  * Get the os_tick counter value.
     256             :  *
     257             :  * Note that the frequency is unspecified, because the time measure
     258             :  * is meant to be used to compare the ratio between usage times.
     259             :  */
     260             : uint64_t os_tick(void);
     261             : 
     262             : /**
     263             :  * Get the os_tick counter value in millisecond.
     264             :  */
     265             : uint64_t os_tick_ms(void);
     266             : 
     267             : /**
     268             :  * Initializes the system.
     269             :  */
     270             : void os_init(int opt);
     271             : 
     272             : /**
     273             :  * Deinitialize the system.
     274             :  */
     275             : void os_done(void);
     276             : 
     277             : /**
     278             :  * Abort the process with a stacktrace.
     279             :  */
     280             : void os_abort(void) __noreturn;
     281             : 
     282             : /**
     283             :  * Clear the screen.
     284             :  */
     285             : void os_clear(void);
     286             : 
     287             : /**
     288             :  * Global variable to identify if Ctrl+C is pressed.
     289             :  */
     290             : extern volatile int global_interrupt;
     291             : 
     292             : /****************************************************************************/
     293             : /* app */
     294             : 
     295             : /**
     296             :  * Include list support to have tommy_node.
     297             :  */
     298             : #include "tommyds/tommylist.h"
     299             : 
     300             : /**
     301             :  * Basic block position type.
     302             :  * With 32 bits and 128k blocks you can address 256 TB.
     303             :  */
     304             : typedef uint32_t block_off_t;
     305             : 
     306             : /**
     307             :  * Basic data position type.
     308             :  * It's signed as file size and offset are usually signed.
     309             :  */
     310             : typedef int64_t data_off_t;
     311             : 
     312             : /**
     313             :  * Another name for link() to avoid confusion with local variables called "link".
     314             :  */
     315          12 : static inline int hardlink(const char* a, const char* b)
     316             : {
     317          12 :         return link(a, b);
     318             : }
     319             : 
     320             : /**
     321             :  * Get the device UUID.
     322             :  * Return 0 on success.
     323             :  */
     324             : int devuuid(uint64_t device_id, const char* device_path, char* uuid, size_t size);
     325             : 
     326             : /**
     327             :  * Physical offset not yet read.
     328             :  */
     329             : #define FILEPHY_UNREAD_OFFSET 0
     330             : 
     331             : /**
     332             :  * Special value returned when the file-system doesn't report any offset for unknown reason.
     333             :  */
     334             : #define FILEPHY_UNREPORTED_OFFSET 1
     335             : 
     336             : /**
     337             :  * Special value returned when the file doesn't have a real offset.
     338             :  * For example, because it's stored in the NTFS MFT.
     339             :  */
     340             : #define FILEPHY_WITHOUT_OFFSET 2
     341             : 
     342             : /**
     343             :  * Value indicating real offsets. All offsets greater or equal at this one are real.
     344             :  */
     345             : #define FILEPHY_REAL_OFFSET 3
     346             : 
     347             : /**
     348             :  * Get the physical address of the specified file.
     349             :  * This is expected to be just a hint and not necessarily correct or unique.
     350             :  * Return 0 on success.
     351             :  */
     352             : int filephy(const char* path, uint64_t size, uint64_t* physical);
     353             : 
     354             : /**
     355             :  * Check if the underline file-system support persistent inodes.
     356             :  * Return -1 on error, 0 on success.
     357             :  */
     358             : int fsinfo(const char* path, int* has_persistent_inode, int* has_syncronized_hardlinks, uint64_t* total_space, uint64_t* free_space, char* fstype, size_t fstype_size, char* fslabel, size_t fslabel_size);
     359             : 
     360             : /**
     361             :  * Get the subvolume directory if the underline filesystem support it
     362             :  * @param path Full path of the mount point to check. It must end with /
     363             :  * @param root The full path of the subvolume root that contains the specified path. It will end with /.
     364             :  */
     365             : int fssnapshot(const char* path, char* root, size_t root_size);
     366             : 
     367             : /**
     368             :  * Creates a snapshot of a subvolume.
     369             :  * @param source Path to the source subvolume.
     370             :  * @param parent_dir Directory where the snapshot should be created.
     371             :  * @param name Name of snapshot.
     372             :  * @return 0 on success, -1 on failure.
     373             :  */
     374             : int fssnapshot_create(const char* source, const char* parent_dir, const char* name);
     375             : 
     376             : /**
     377             :  * Deletes a subvolume/snapshot.
     378             :  * @param parent_dir Directory where the snapshot is.
     379             :  * @param name Name of snapshot.
     380             :  * @return 0 on success, -1 on failure.
     381             :  */
     382             : int fssnapshot_delete(const char* parent_dir, const char* name);
     383             : 
     384             : /**
     385             :  * Renames a subvolume.
     386             :  * @return 0 on success, -1 on failure.
     387             :  */
     388             : int fssnapshot_rename(const char* parent_dir, const char* old_name, const char* new_name);
     389             : 
     390             : /*
     391             :  * Log file.
     392             :  *
     393             :  * This stream if fully buffered.
     394             :  *
     395             :  * If no log file is selected, it's 0.
     396             :  */
     397             : extern FILE* stdlog;
     398             : 
     399             : /**
     400             :  * Exit codes for testing.
     401             :  */
     402             : extern int exit_success;
     403             : extern int exit_failure;
     404             : extern int exit_sync_needed;
     405             : #undef EXIT_SUCCESS
     406             : #undef EXIT_FAILURE
     407             : #define EXIT_SUCCESS exit_success
     408             : #define EXIT_FAILURE exit_failure
     409             : #define EXIT_SYNC_NEEDED exit_sync_needed
     410             : 
     411             : /**
     412             :  * Fill memory with pseudo-random values.
     413             :  */
     414             : int randomize(void* ptr, size_t size);
     415             : 
     416             : /**
     417             :  * Standard SMART attributes.
     418             :  */
     419             : #define SMART_REALLOCATED_SECTOR_COUNT 5
     420             : #define SMART_POWER_ON_HOURS 9
     421             : #define SMART_POWER_CYCLE_COUNT 12
     422             : #define SMART_UNCORRECTABLE_ERROR_CNT 187
     423             : #define SMART_COMMAND_TIMEOUT 188
     424             : #define SMART_CURRENT_PENDING_SECTOR 197
     425             : #define SMART_OFFLINE_UNCORRECTABLE 198
     426             : #define SMART_START_STOP_COUNT 4
     427             : #define SMART_POWER_ON_HOURS 9
     428             : #define SMART_AIRFLOW_TEMPERATURE_CELSIUS 190
     429             : #define SMART_LOAD_CYCLE_COUNT 193
     430             : #define SMART_TEMPERATURE_CELSIUS 194
     431             : 
     432             : /**
     433             :  * Flags returned by smartctl via exit code
     434             :  */
     435             : #define SMART_FLAGS 256
     436             : 
     437             : /*
     438             :  * Counts command, transport, or controller-level errors reported by the device.
     439             :  * These reflect failed I/O operations not directly caused by media defects
     440             :  * (for example interface, firmware, or power-related errors).
     441             :  * This counter is cumulative and never resets to zero, even if the underlying
     442             :  * error condition is resolved.
     443             :  */
     444             : #define SMART_ERROR_PROTOCOL 257
     445             : 
     446             : /*
     447             :  * Counts media-level errors where data could not be reliably read or written.
     448             :  * These indicate actual storage surface or flash failures and may imply data loss.
     449             :  * This counter is cumulative and never resets to zero, even if the underlying
     450             :  * error condition is resolved.
     451             :  */
     452             : #define SMART_ERROR_MEDIUM 258
     453             : 
     454             : /**
     455             :  * Unified Wear Level Metric (0-100)
     456             :  *
     457             :  * Represents the remaining life of an SSD.
     458             :  * - 0:   Brand new drive (0% wear).
     459             :  * - 100: Drive has reached or exceeded its manufacturer-rated design life.
     460             :  */
     461             : #define SMART_WEAR_LEVEL 259
     462             : 
     463             : /**
     464             :  * SMART attributes count.
     465             :  */
     466             : #define SMART_COUNT 260
     467             : 
     468             : /**
     469             :  * NVME custom SMART attributes
     470             :  *
     471             :  * The numbers are just arbitrary to put them in unused space
     472             :  */
     473             : #define SMART_NVME_CRITICAL_WARNING 100
     474             : #define SMART_NVME_AVAILABLE_SPARE 101
     475             : #define SMART_NVME_DATA_UNITS_READ 102
     476             : #define SMART_NVME_DATA_UNITS_WRITTEN 103
     477             : #define SMART_NVME_HOST_READ_COMMANDS 104
     478             : #define SMART_NVME_HOST_WRITE_COMMANDS 105
     479             : #define SMART_NVME_CONTROLLER_BUSY_TIME 106
     480             : #define SMART_NVME_UNSAFE_SHUTDOWNS 107
     481             : #define SMART_NVME_WARNING_COMP_TEMPERATURE_TIME 108
     482             : #define SMART_NVME_CRITICAL_COMP_TEMPERATURE_TIME 109
     483             : 
     484             : /**
     485             :  * Info attributes.
     486             :  */
     487             : #define INFO_SIZE 0 /**< Size in bytes. */
     488             : #define INFO_ROTATION_RATE 1 /**< Rotation speed. 0 for SSD. */
     489             : 
     490             : /**
     491             :  * Info attributes count.
     492             :  */
     493             : #define INFO_COUNT 2
     494             : 
     495             : /**
     496             :  * Max number of ignored smart attributes
     497             :  */
     498             : #define SMART_IGNORE_MAX 4
     499             : 
     500             : /**
     501             :  * Flags returned by smartctl.
     502             :  */
     503             : #define SMARTCTL_FLAG_UNSUPPORTED (1 << 0) /**< Device not recognized, requiring the -d option. */
     504             : #define SMARTCTL_FLAG_OPEN (1 << 1) /**< Device open or identification failed. */
     505             : #define SMARTCTL_FLAG_COMMAND (1 << 2) /**< Some SMART or ATA commands failed. This is a common error, also happening with full info gathering. */
     506             : #define SMARTCTL_FLAG_FAIL (1 << 3) /**< SMART status check returned "DISK FAILING". */
     507             : #define SMARTCTL_FLAG_PREFAIL (1 << 4) /**< We found prefail Attributes <= threshold. */
     508             : #define SMARTCTL_FLAG_PREFAIL_LOGGED (1 << 5) /**< SMART status check returned "DISK OK" but we found that some (usage or prefail) Attributes have been <= threshold at some time in the past. */
     509             : #define SMARTCTL_FLAG_ERROR_LOGGED (1 << 6) /**< The device error log contains records of errors. */
     510             : #define SMARTCTL_FLAG_SELFERROR_LOGGED (1 << 7) /**< The device self-test log contains records of errors. */
     511             : 
     512             : /**
     513             :  * SMART max attribute length.
     514             :  */
     515             : #define SMART_MAX 64
     516             : 
     517             : /**
     518             :  * Value for unassigned SMART attribute.
     519             :  */
     520             : #define SMART_UNASSIGNED 0xFFFFFFFFFFFFFFFFULL
     521             : 
     522             : /**
     523             :  * SMART Attribute flags
     524             :  */
     525             : #define SMART_ATTR_TYPE_PREFAIL 1
     526             : #define SMART_ATTR_TYPE_OLDAGE 2
     527             : #define SMART_ATTR_UPDATE_ALWAYS 4
     528             : #define SMART_ATTR_UPDATE_OFFLINE 8
     529             : #define SMART_ATTR_WHEN_FAILED_NOW 16
     530             : #define SMART_ATTR_WHEN_FAILED_PAST 32
     531             : #define SMART_ATTR_WHEN_FAILED_NEVER 64
     532             : 
     533             : struct smart_attr {
     534             :         char name[128]; /**< SMART attribute name. */
     535             :         uint64_t raw; /**< SMART attributes raw. */
     536             :         uint64_t norm; /**< SMART attributes normalized. */
     537             :         uint64_t worst; /**< SMART attributes worst. */
     538             :         uint64_t thresh; /**< SMART attributes threshold. */
     539             :         int flags; /**< SMART_ATTR_* flags */
     540             : };
     541             : 
     542             : /**
     543             :  * Power mode
     544             :  */
     545             : #define POWER_STANDBY 0
     546             : #define POWER_ACTIVE 1
     547             : #define POWER_UNKNOWN -1
     548             : 
     549             : /**
     550             :  * Device info entry.
     551             :  */
     552             : struct devinfo_struct {
     553             :         uint64_t device; /**< Device ID. */
     554             :         char name[PATH_MAX]; /**< Name of the disk combined with the split index if any */
     555             :         char mount[PATH_MAX]; /**< Mount point or other contained directory. */
     556             :         char smartctl[PATH_MAX]; /**< Options for smartctl. */
     557             :         int smartignore[SMART_IGNORE_MAX]; /**< Attribues to ignore */
     558             :         char file[PATH_MAX]; /**< File device. */
     559             : #ifdef _WIN32
     560             :         char wfile[PATH_MAX]; /**< File device in Windows format. Like \\.\PhysicalDriveX, or \\?\Volume{X}. */
     561             : #endif
     562             :         struct devinfo_struct* parent; /**< Pointer at the parent if any. */
     563             :         struct devinfo_struct* split; /**< Pointer at first split if this one is not the first. */
     564             :         struct smart_attr smart[SMART_COUNT]; /**< All smart values. */
     565             :         uint64_t info[INFO_COUNT]; /**< Informational attributes not related to SMART telemetry. */
     566             :         uint64_t access_stat; /**< Access stat info. */
     567             :         char serial[SMART_MAX]; /**< Serial number. */
     568             :         char family[SMART_MAX]; /**< Family. */
     569             :         char model[SMART_MAX]; /**< Model. */
     570             :         char interf[SMART_MAX]; /**< Interface of the device: ata, sata, pata, nvme, usb */
     571             :         int power; /**< POWER mode. */
     572             : #if HAVE_THREAD
     573             :         thread_id_t thread;
     574             : #endif
     575             :         tommy_node node;
     576             : };
     577             : typedef struct devinfo_struct devinfo_t;
     578             : 
     579             : void device_name_set(devinfo_t* dev, const char* name, int index);
     580             : 
     581             : #define DEVICE_LIST 0
     582             : #define DEVICE_DOWN 1
     583             : #define DEVICE_UP 2
     584             : #define DEVICE_SMART 3
     585             : #define DEVICE_PROBE 4
     586             : #define DEVICE_DOWNIFUP 5
     587             : 
     588             : /**
     589             :  * Query all the "high" level devices with the specified operation,
     590             :  * and produces a list of "low" level devices to operate on.
     591             :  *
     592             :  * The passed "low" device list must be already initialized.
     593             :  */
     594             : int devquery(tommy_list* high, tommy_list* low, int operation);
     595             : 
     596             : /**
     597             :  * Fill with fake data the device list.
     598             :  */
     599             : int devtest(tommy_list* high, tommy_list* low, int operation);
     600             : 
     601             : /**
     602             :  * Query all the "low" devices and log their unique identifiers
     603             :  */
     604             : int devmap(void);
     605             : 
     606             : /**
     607             :  * Get the ambient temperature in degree
     608             :  *
     609             :  * Return 0 if not available.
     610             :  */
     611             : int ambient_temperature(void);
     612             : 
     613             : /**
     614             :  * Size of the spaceholder file for Windows to avoid the message of low disk space
     615             :  */
     616             : #define WINDOWS_SPACEHOLDER_SIZE (256 * 1024 * 1024)
     617             : 
     618             : /**
     619             :  * Generic errors
     620             :  */
     621             : #define EINTERNAL EFAULT /**< Internal assertion failed. */
     622             : #define EDATA EIO /**< Silent data corruption. */
     623             : #define ESOFT EINVAL /**< Software error, like permission denied. */
     624             : #define EUSER EINVAL /**< Invalid value specified by the user. */
     625             : #define EEXTERNAL EINVAL /**< Invalid external interface behaviour. */
     626             : #define ECONTENT EINVAL /**< Invalid content file. */
     627             : #define EENVIRONMENT EINVAL /**< Invalid physical environment, like temperature too high. */
     628             : 
     629             : #endif
     630             : 

Generated by: LCOV version 1.0