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 : * Enable the rand_s() function.l 51 : */ 52 : #define _CRT_RAND_S 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 : #ifndef WEXITSTATUS 217 : #define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8) 218 : #endif 219 : #ifndef WIFEXITED 220 : #define WIFEXITED(stat_val) (((stat_val) & 255) == 0) 221 : #endif 222 : 223 : #if HAVE_GETOPT_H 224 : #include <getopt.h> 225 : #endif 226 : 227 : #if HAVE_FNMATCH_H 228 : #include <fnmatch.h> 229 : #else 230 : #include "fnmatch.h" 231 : #endif 232 : 233 : #if HAVE_MATH_H 234 : #include <math.h> 235 : #endif 236 : 237 : #if HAVE_EXECINFO_H 238 : #include <execinfo.h> 239 : #endif 240 : 241 : #ifdef __APPLE__ 242 : #include <CoreFoundation/CoreFoundation.h> 243 : #include <DiskArbitration/DiskArbitration.h> 244 : #endif 245 : 246 : /** 247 : * Enable thread use. 248 : */ 249 : #ifdef _WIN32 250 : #define HAVE_THREAD 1 251 : typedef void* windows_thread_t; 252 : typedef CRITICAL_SECTION windows_mutex_t; 253 : typedef CONDITION_VARIABLE windows_cond_t; 254 : typedef void* windows_key_t; 255 : /* remap to pthread */ 256 : #define thread_id_t windows_thread_t 257 : #define thread_mutex_t windows_mutex_t 258 : #define thread_cond_t windows_cond_t 259 : #define pthread_mutex_init windows_mutex_init 260 : #define pthread_mutex_destroy windows_mutex_destroy 261 : #define pthread_mutex_lock windows_mutex_lock 262 : #define pthread_mutex_unlock windows_mutex_unlock 263 : #define pthread_cond_init windows_cond_init 264 : #define pthread_cond_destroy windows_cond_destroy 265 : #define pthread_cond_signal windows_cond_signal 266 : #define pthread_cond_broadcast windows_cond_broadcast 267 : #define pthread_cond_wait windows_cond_wait 268 : #define pthread_create windows_create 269 : #define pthread_join windows_join 270 : #else 271 : #if HAVE_PTHREAD_H 272 : #include <pthread.h> 273 : #endif 274 : #if HAVE_PTHREAD_CREATE 275 : #define HAVE_THREAD 1 276 : typedef pthread_t thread_id_t; 277 : typedef pthread_mutex_t thread_mutex_t; 278 : typedef pthread_cond_t thread_cond_t; 279 : #endif 280 : #endif 281 : 282 : /** 283 : * Disable case check in Windows. 284 : */ 285 : #ifdef _WIN32 286 : #define FNM_CASEINSENSITIVE_FOR_WIN FNM_CASEFOLD 287 : #else 288 : #define FNM_CASEINSENSITIVE_FOR_WIN 0 289 : #endif 290 : 291 : #if HAVE_IO_H 292 : #include <io.h> 293 : #endif 294 : 295 : #if HAVE_GETOPT_LONG 296 : #define SWITCH_GETOPT_LONG(a, b) a 297 : #else 298 : #define SWITCH_GETOPT_LONG(a, b) b 299 : #endif 300 : 301 : /** 302 : * Enables lock file support. 303 : */ 304 : #if HAVE_FLOCK && HAVE_FTRUNCATE 305 : #define HAVE_LOCKFILE 1 306 : #endif 307 : 308 : /** 309 : * Basic block position type. 310 : * With 32 bits and 128k blocks you can address 256 TB. 311 : */ 312 : typedef uint32_t block_off_t; 313 : 314 : /** 315 : * Basic data position type. 316 : * It's signed as file size and offset are usually signed. 317 : */ 318 : typedef int64_t data_off_t; 319 : 320 : /** 321 : * Includes specific support for Windows or Linux. 322 : */ 323 : #ifdef __MINGW32__ 324 : #include "mingw.h" 325 : #else 326 : #include "unix.h" 327 : #endif 328 : 329 : /** 330 : * Include list support to have tommy_node. 331 : */ 332 : #include "tommyds/tommylist.h" 333 : 334 : /** 335 : * Another name for link() to avoid confusion with local variables called "link". 336 : */ 337 12 : static inline int hardlink(const char* a, const char* b) 338 : { 339 12 : return link(a, b); 340 : } 341 : 342 : /** 343 : * Get the device UUID. 344 : * Return 0 on success. 345 : */ 346 : int devuuid(uint64_t device, const char* path, char* uuid, size_t size); 347 : 348 : /** 349 : * Physical offset not yet read. 350 : */ 351 : #define FILEPHY_UNREAD_OFFSET 0 352 : 353 : /** 354 : * Special value returned when the file-system doesn't report any offset for unknown reason. 355 : */ 356 : #define FILEPHY_UNREPORTED_OFFSET 1 357 : 358 : /** 359 : * Special value returned when the file doesn't have a real offset. 360 : * For example, because it's stored in the NTFS MFT. 361 : */ 362 : #define FILEPHY_WITHOUT_OFFSET 2 363 : 364 : /** 365 : * Value indicating real offsets. All offsets greater or equal at this one are real. 366 : */ 367 : #define FILEPHY_REAL_OFFSET 3 368 : 369 : /** 370 : * Get the physical address of the specified file. 371 : * This is expected to be just a hint and not necessarily correct or unique. 372 : * Return 0 on success. 373 : */ 374 : int filephy(const char* path, uint64_t size, uint64_t* physical); 375 : 376 : /** 377 : * Check if the underline file-system support persistent inodes. 378 : * Return -1 on error, 0 on success. 379 : */ 380 : int fsinfo(const char* path, int* has_persistent_inode, int* has_syncronized_hardlinks, uint64_t* total_space, uint64_t* free_space); 381 : 382 : /** 383 : * Get the tick counter value. 384 : * 385 : * Note that the frequency is unspecified, because the time measure 386 : * is meant to be used to compare the ratio between usage times. 387 : */ 388 : uint64_t tick(void); 389 : 390 : /** 391 : * Get the tick counter value in millisecond. 392 : */ 393 : uint64_t tick_ms(void); 394 : 395 : /** 396 : * Initializes the system. 397 : */ 398 : void os_init(int opt); 399 : 400 : /** 401 : * Deinitialize the system. 402 : */ 403 : void os_done(void); 404 : 405 : /** 406 : * Abort the process with a stacktrace. 407 : */ 408 : void os_abort(void) __noreturn; 409 : 410 : /** 411 : * Clear the screen. 412 : */ 413 : void os_clear(void); 414 : 415 : /** 416 : * Log file. 417 : * 418 : * This stream if fully buffered. 419 : * 420 : * If no log file is selected, it's 0. 421 : */ 422 : extern FILE* stdlog; 423 : 424 : /** 425 : * Exit codes for testing. 426 : */ 427 : extern int exit_success; 428 : extern int exit_failure; 429 : extern int exit_sync_needed; 430 : #undef EXIT_SUCCESS 431 : #undef EXIT_FAILURE 432 : #define EXIT_SUCCESS exit_success 433 : #define EXIT_FAILURE exit_failure 434 : #define EXIT_SYNC_NEEDED exit_sync_needed 435 : 436 : /** 437 : * Fill memory with pseudo-random values. 438 : */ 439 : int randomize(void* ptr, size_t size); 440 : 441 : /** 442 : * Standard SMART attributes. 443 : */ 444 : #define SMART_START_STOP_COUNT 4 445 : #define SMART_REALLOCATED_SECTOR_COUNT 5 446 : #define SMART_POWER_ON_HOURS 9 447 : #define SMART_AIRFLOW_TEMPERATURE_CELSIUS 190 448 : #define SMART_TEMPERATURE_CELSIUS 194 449 : 450 : /** 451 : * Additional SMART attributes. 452 : */ 453 : #define SMART_ERROR 256 /**< ATA Error count. */ 454 : #define SMART_SIZE 257 /**< Size in bytes. */ 455 : #define SMART_ROTATION_RATE 258 /**< Rotation speed. 0 for SSD. */ 456 : #define SMART_FLAGS 259 /**< Flags returned by smartctl. */ 457 : 458 : /** 459 : * SMART attributes count. 460 : */ 461 : #define SMART_COUNT 260 462 : 463 : #define SMART_IGNORE_MAX 4 /**< Max number of ignored smart attributes */ 464 : 465 : /** 466 : * Flags returned by smartctl. 467 : */ 468 : #define SMARTCTL_FLAG_UNSUPPORTED (1 << 0) /**< Device not recognized, requiring the -d option. */ 469 : #define SMARTCTL_FLAG_OPEN (1 << 1) /**< Device open or identification failed. */ 470 : #define SMARTCTL_FLAG_COMMAND (1 << 2) /**< Some SMART or ATA commands failed. This is a common error, also happening with full info gathering. */ 471 : #define SMARTCTL_FLAG_FAIL (1 << 3) /**< SMART status check returned "DISK FAILING". */ 472 : #define SMARTCTL_FLAG_PREFAIL (1 << 4) /**< We found prefail Attributes <= threshold. */ 473 : #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. */ 474 : #define SMARTCTL_FLAG_ERROR (1 << 6) /**< The device error log contains records of errors. */ 475 : #define SMARTCTL_FLAG_ERROR_LOGGED (1 << 7) /**< The device self-test log contains records of errors. */ 476 : 477 : /** 478 : * SMART max attribute length. 479 : */ 480 : #define SMART_MAX 64 481 : 482 : /** 483 : * Value for unassigned SMART attribute. 484 : */ 485 : #define SMART_UNASSIGNED 0xFFFFFFFFFFFFFFFFULL 486 : 487 : 488 : /** 489 : * Power mode 490 : */ 491 : #define POWER_STANDBY 0 492 : #define POWER_ACTIVE 1 493 : #define POWER_UNKNOWN -1 494 : 495 : /** 496 : * Device info entry. 497 : */ 498 : struct devinfo_struct { 499 : uint64_t device; /**< Device ID. */ 500 : char name[PATH_MAX]; /**< Name of the disk. */ 501 : char mount[PATH_MAX]; /**< Mount point or other contained directory. */ 502 : char smartctl[PATH_MAX]; /**< Options for smartctl. */ 503 : int smartignore[SMART_IGNORE_MAX]; /**< Attribues to ignore */ 504 : char file[PATH_MAX]; /**< File device. */ 505 : #ifdef _WIN32 506 : char wfile[PATH_MAX]; /**< File device in Windows format. Like \\.\PhysicalDriveX, or \\?\Volume{X}. */ 507 : #endif 508 : struct devinfo_struct* parent; /**< Pointer at the parent if any. */ 509 : uint64_t smart[SMART_COUNT]; /**< SMART raw attributes. */ 510 : char smart_serial[SMART_MAX]; /**< SMART serial number. */ 511 : char smart_vendor[SMART_MAX]; /**< SMART vendor. */ 512 : char smart_model[SMART_MAX]; /**< SMART model. */ 513 : int power; /**< POWER mode. */ 514 : #if HAVE_THREAD 515 : thread_id_t thread; 516 : #endif 517 : tommy_node node; 518 : }; 519 : typedef struct devinfo_struct devinfo_t; 520 : 521 : #define DEVICE_LIST 0 522 : #define DEVICE_DOWN 1 523 : #define DEVICE_UP 2 524 : #define DEVICE_SMART 3 525 : #define DEVICE_PROBE 4 526 : #define DEVICE_DOWNIFUP 5 527 : 528 : /** 529 : * Query all the "high" level devices with the specified operation, 530 : * and produces a list of "low" level devices to operate on. 531 : * 532 : * The passed "low" device list must be already initialized. 533 : */ 534 : int devquery(tommy_list* high, tommy_list* low, int operation, int others); 535 : 536 : /** 537 : * Fill with fake data the device list. 538 : */ 539 : int devtest(tommy_list* high, tommy_list* low, int operation); 540 : 541 : /** 542 : * Get the ambient temperature in degree 543 : * 544 : * Return 0 if not available. 545 : */ 546 : int ambient_temperature(void); 547 : 548 : /** 549 : * Global variable to identify if Ctrl+C is pressed. 550 : */ 551 : extern volatile int global_interrupt; 552 : 553 : #endif 554 :