/* * Copyright (C) 2011 Andrea Mazzoleni * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef __PORTABLE_H #define __PORTABLE_H #if HAVE_CONFIG_H #include "config.h" /* Use " to include first in the same directory of this file */ #endif /***************************************************************************/ /* Config */ #ifdef __MINGW32__ /** * Enable the GNU printf functions instead of using the MSVCRT ones. * * Note that this is the default if _POSIX is also defined. * To disable it you have to set it to 0. */ #define __USE_MINGW_ANSI_STDIO 1 /** * Define the MSVCRT version targeting Windows Vista. */ #define __MSVCRT_VERSION__ 0x0600 /** * Include Windows Vista headers. * * Like for InitializeCriticalSection(). */ #define _WIN32_WINNT 0x600 /** * Enable the rand_s() function.l */ #define _CRT_RAND_S #include #endif /** * Specify the format attribute for printf. */ #ifdef __MINGW32__ #if defined(__USE_MINGW_ANSI_STDIO) && __USE_MINGW_ANSI_STDIO == 1 #define attribute_printf gnu_printf /* GNU format */ #else #define attribute_printf ms_printf /* MSVCRT format */ #endif #else #define attribute_printf printf /* GNU format is the default one */ #endif /** * Compiler extension */ #ifndef __always_inline #define __always_inline inline __attribute__((always_inline)) #endif #ifndef __noreturn #define __noreturn __attribute__((noreturn)) #endif /** * Architecture for inline assembly. */ #if HAVE_ASSEMBLY #if defined(__i386__) #define CONFIG_X86 1 #define CONFIG_X86_32 1 #endif #if defined(__x86_64__) #define CONFIG_X86 1 #define CONFIG_X86_64 1 #endif #endif /** * Includes some platform specific headers. */ #if HAVE_SYS_PARAM_H #include #endif #if HAVE_SYS_MOUNT_H #include #endif #if HAVE_SYS_VFS_H #include #endif #if HAVE_SYS_STATFS_H #include #endif #if HAVE_SYS_FILE_H #include #endif #if HAVE_SYS_IOCTL_H #include #endif #if HAVE_LINUX_FS_H #include #endif #if HAVE_LINUX_FIEMAP_H #include #endif #if HAVE_BLKID_BLKID_H #include #if HAVE_BLKID_DEVNO_TO_DEVNAME && HAVE_BLKID_GET_TAG_VALUE #define HAVE_BLKID 1 #endif #endif /** * Includes some standard headers. */ #include #include /* On many systems (e.g., Darwin), `stdio.h' is a prerequisite. */ #include #include #include #include #include #include #include #include #if HAVE_STDINT_H #include #endif #if HAVE_INTTYPES_H #include #endif #if HAVE_UNISTD_H #include #endif #if TIME_WITH_SYS_TIME #include #include #else #if HAVE_SYS_TIME_H #include #else #include #endif #endif #if HAVE_MACH_MACH_TIME_H #include #endif #if HAVE_DIRENT_H #include #define NAMLEN(dirent) strlen((dirent)->d_name) #else #define dirent direct #define NAMLEN(dirent) (dirent)->d_namlen #if HAVE_SYS_NDIR_H #include #endif #if HAVE_SYS_DIR_H #include #endif #if HAVE_NDIR_H #include #endif #endif #if HAVE_SYS_TYPES_H #include #endif #if HAVE_SYS_MKDEV #include #endif #if HAVE_SYS_SYSMACROS_H #include #endif #if HAVE_SYS_STAT_H #include #endif #if HAVE_SYS_WAIT_H #include #endif #ifndef WEXITSTATUS #define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8) #endif #ifndef WIFEXITED #define WIFEXITED(stat_val) (((stat_val) & 255) == 0) #endif #if HAVE_GETOPT_H #include #endif #if HAVE_FNMATCH_H #include #else #include "fnmatch.h" #endif #if HAVE_MATH_H #include #endif #if HAVE_EXECINFO_H #include #endif /** * Enable thread use. */ #ifdef _WIN32 #define HAVE_THREAD 1 typedef void* windows_thread_t; typedef CRITICAL_SECTION windows_mutex_t; typedef CONDITION_VARIABLE windows_cond_t; typedef void* windows_key_t; /* remap to pthread */ #define thread_id_t windows_thread_t #define thread_mutex_t windows_mutex_t #define thread_cond_t windows_cond_t #define pthread_mutex_init windows_mutex_init #define pthread_mutex_destroy windows_mutex_destroy #define pthread_mutex_lock windows_mutex_lock #define pthread_mutex_unlock windows_mutex_unlock #define pthread_cond_init windows_cond_init #define pthread_cond_destroy windows_cond_destroy #define pthread_cond_signal windows_cond_signal #define pthread_cond_broadcast windows_cond_broadcast #define pthread_cond_wait windows_cond_wait #define pthread_create windows_create #define pthread_join windows_join #else #if HAVE_PTHREAD_H #include #endif #if HAVE_PTHREAD_CREATE #define HAVE_THREAD 1 typedef pthread_t thread_id_t; typedef pthread_mutex_t thread_mutex_t; typedef pthread_cond_t thread_cond_t; #endif #endif /** * Disable case check in Windows. */ #ifdef _WIN32 #define FNM_CASEINSENSITIVE_FOR_WIN FNM_CASEFOLD #else #define FNM_CASEINSENSITIVE_FOR_WIN 0 #endif #if HAVE_IO_H #include #endif #if HAVE_GETOPT_LONG #define SWITCH_GETOPT_LONG(a, b) a #else #define SWITCH_GETOPT_LONG(a, b) b #endif /** * Enables lock file support. */ #if HAVE_FLOCK && HAVE_FTRUNCATE #define HAVE_LOCKFILE 1 #endif /** * Basic block position type. * With 32 bits and 128k blocks you can address 256 TB. */ typedef uint32_t block_off_t; /** * Basic data position type. * It's signed as file size and offset are usually signed. */ typedef int64_t data_off_t; /** * Includes specific support for Windows or Linux. */ #ifdef __MINGW32__ #include "mingw.h" #else #include "unix.h" #endif /** * Include list support to have tommy_node. */ #include "tommyds/tommylist.h" /** * Another name for link() to avoid confusion with local variables called "link". */ static inline int hardlink(const char* a, const char* b) { return link(a, b); } /** * Get the device UUID. * Return 0 on success. */ int devuuid(uint64_t device, char* uuid, size_t size); /** * Physical offset not yet read. */ #define FILEPHY_UNREAD_OFFSET 0 /** * Special value returned when the file-system doesn't report any offset for unknown reason. */ #define FILEPHY_UNREPORTED_OFFSET 1 /** * Special value returned when the file doesn't have a real offset. * For example, because it's stored in the NTFS MFT. */ #define FILEPHY_WITHOUT_OFFSET 2 /** * Value indicating real offsets. All offsets greater or equal at this one are real. */ #define FILEPHY_REAL_OFFSET 3 /** * Get the physical address of the specified file. * This is expected to be just a hint and not necessarily correct or unique. * Return 0 on success. */ int filephy(const char* path, uint64_t size, uint64_t* physical); /** * Check if the underline file-system support persistent inodes. * Return -1 on error, 0 on success. */ int fsinfo(const char* path, int* has_persistent_inode, int* has_syncronized_hardlinks, uint64_t* total_space, uint64_t* free_space); /** * Get the tick counter value. * * Note that the frequency is unspecified, because the time measure * is meant to be used to compare the ratio between usage times. */ uint64_t tick(void); /** * Get the tick counter value in millisecond. */ uint64_t tick_ms(void); /** * Initializes the system. */ void os_init(int opt); /** * Deinitialize the system. */ void os_done(void); /** * Abort the process with a stacktrace. */ void os_abort(void) __noreturn; /** * Clear the screen. */ void os_clear(void); /** * Log file. * * This stream if fully buffered. * * If no log file is selected, it's 0. */ extern FILE* stdlog; /** * Exit codes for testing. */ extern int exit_success; extern int exit_failure; extern int exit_sync_needed; #undef EXIT_SUCCESS #undef EXIT_FAILURE #define EXIT_SUCCESS exit_success #define EXIT_FAILURE exit_failure #define EXIT_SYNC_NEEDED exit_sync_needed /** * Fill memory with pseudo-random values. */ int randomize(void* ptr, size_t size); /** * Standard SMART attributes. */ #define SMART_START_STOP_COUNT 4 #define SMART_REALLOCATED_SECTOR_COUNT 5 #define SMART_POWER_ON_HOURS 9 #define SMART_AIRFLOW_TEMPERATURE_CELSIUS 190 #define SMART_LOAD_CYCLE_COUNT 193 #define SMART_TEMPERATURE_CELSIUS 194 /** * Additional SMART attributes. */ #define SMART_ERROR 256 /**< ATA Error count. */ #define SMART_SIZE 257 /**< Size in bytes. */ #define SMART_ROTATION_RATE 258 /**< Rotation speed. 0 for SSD. */ #define SMART_FLAGS 259 /**< Flags returned by smartctl. */ /** * SMART attributes count. */ #define SMART_COUNT 260 /** * Flags returned by smartctl. */ #define SMARTCTL_FLAG_UNSUPPORTED (1 << 0) /**< Device not recognized, requiring the -d option. */ #define SMARTCTL_FLAG_OPEN (1 << 1) /**< Device open or identification failed. */ #define SMARTCTL_FLAG_COMMAND (1 << 2) /**< Some SMART or ATA commands failed. This is a common error, also happening with full info gathering. */ #define SMARTCTL_FLAG_FAIL (1 << 3) /**< SMART status check returned "DISK FAILING". */ #define SMARTCTL_FLAG_PREFAIL (1 << 4) /**< We found prefail Attributes <= threshold. */ #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. */ #define SMARTCTL_FLAG_ERROR (1 << 6) /**< The device error log contains records of errors. */ #define SMARTCTL_FLAG_ERROR_LOGGED (1 << 7) /**< The device self-test log contains records of errors. */ /** * SMART max attribute length. */ #define SMART_MAX 64 /** * Value for unassigned SMART attribute. */ #define SMART_UNASSIGNED 0xFFFFFFFFFFFFFFFFULL /** * Device info entry. */ struct devinfo_struct { uint64_t device; /**< Device ID. */ char name[PATH_MAX]; /**< Name of the disk. */ char mount[PATH_MAX]; /**< Mount point or other contained directory. */ char smartctl[PATH_MAX]; /**< Options for smartctl. */ char file[PATH_MAX]; /**< File device. */ #ifdef _WIN32 char wfile[PATH_MAX]; /**< File device in Windows format. Like \\.\PhysicalDriveX, or \\?\Volume{X}. */ #endif struct devinfo_struct* parent; /**< Pointer at the parent if any. */ uint64_t smart[SMART_COUNT]; /**< SMART raw attributes. */ char smart_serial[SMART_MAX]; /**< SMART serial number. */ char smart_vendor[SMART_MAX]; /**< SMART vendor. */ char smart_model[SMART_MAX]; /**< SMART model. */ #if HAVE_THREAD thread_id_t thread; #endif tommy_node node; }; typedef struct devinfo_struct devinfo_t; #define DEVICE_LIST 0 #define DEVICE_DOWN 1 #define DEVICE_UP 2 #define DEVICE_SMART 3 /** * Query all the "high" level devices with the specified operation, * and produces a list of "low" level devices to operate on. * * The passed "low" device list must be already initialized. */ int devquery(tommy_list* high, tommy_list* low, int operation, int others); #endif