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-03-15 15:58:19 Functions: 1 1 100.0 %

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

Generated by: LCOV version 1.0