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