Branch data Line data Source code
1 : : /**
2 : : *
3 : : * @file precizer.c
4 : : * @brief Main file
5 : : *
6 : : */
7 : : #include "precizer.h"
8 : :
9 : : /**
10 : : * Global definitions
11 : : *
12 : : */
13 : :
14 : : // Global variable controls signals to interrupt execution
15 : : // Atomic variable is very fast and will be called very often
16 : : _Atomic bool global_interrupt_flag = false;
17 : :
18 : : // The global structure Config where all runtime settings will be stored
19 : : Config _config;
20 : : Config *config = &_config;
21 : :
22 : : /**
23 : : * @mainpage
24 : : * @brief precizer is a CLI application designed to verify the integrity of files after synchronization.
25 : : * The program recursively traverses directories and creates a database
26 : : * of files and their checksums, followed by a quick comparison.
27 : : *
28 : : * @author Dennis Razumovsky
29 : : * @details precizer specializes in managing vast file systems.
30 : : * The program identifies synchronization errors by cross-referencing
31 : : * data and checksums from various sources. Alternatively, it can be
32 : : * used to crawl historical changes by comparing databases from the
33 : : * same sources over different times
34 : : */
35 : : /**
36 : : * @brief Program entry point for normal and TESTITALL builds
37 : : *
38 : : * @details Initializes runtime state, executes the main workflow, prints final
39 : : * diagnostics, and returns the shell exit status. In TESTITALL builds the same
40 : : * implementation is exposed as `test_main()`
41 : : *
42 : : * @param argc Number of CLI arguments
43 : : * @param argv CLI argument vector
44 : : * @return Process exit status for the completed run
45 : : */
46 : : #ifndef TESTITALL // Unit testing library
47 : 284 : int main(
48 : : int argc,
49 : : char **argv)
50 : : #else
51 : 273 : int test_main(
52 : : int argc,
53 : : char **argv)
54 : : #endif // TESTITALL
55 : : {
56 : : /* This function was reviewed line by line by a human and is not AI-generated
57 : : Any change to this function requires separate explicit approval */
58 : :
59 : : /* Status returned by this function through provide()
60 : : Default value assumes successful completion */
61 : 557 : Return status = SUCCESS;
62 : :
63 : : // Stack storage for traversal stats, zero-initialized.
64 : 557 : TraversalSummary _summary = {0};
65 : : // Use pointer form for consistency.
66 : 557 : TraversalSummary *summary = &_summary;
67 : :
68 : : // Initialize configuration with values
69 : 557 : init_config();
70 : :
71 : : // Fill Config structure
72 : : // parsing command line arguments
73 : 557 : run(parse_arguments(argc,argv));
74 : :
75 : : // Print program identity before starting the main workflow
76 : 557 : about();
77 : :
78 : : // Compile PCRE2 patterns from --ignore, --include, --lock-checksum once
79 : : // so that file traversal reuses compiled objects instead of recompiling per file
80 : 557 : run(compile_patterns());
81 : :
82 : : // Verify that the provided paths exist and
83 : : // are directories
84 : 557 : run(paths_detect());
85 : :
86 : : // Initialize signals interception like Ctrl+C
87 : 557 : run(init_signals());
88 : :
89 : : // Generate DB file name if
90 : : // not passed as an argument
91 : 557 : run(db_determine_name());
92 : :
93 : : // Validate database file existence and set up existence flag
94 : 557 : run(db_primary_file_validate_existence());
95 : :
96 : : // Define the database operation mode
97 : 557 : run(db_determine_mode());
98 : :
99 : : // Primary database file integrity check
100 : 557 : run(db_primary_file_test());
101 : :
102 : : // Initialize SQLite database
103 : 557 : run(db_init());
104 : :
105 : : // Compare databases
106 : 557 : run(db_compare());
107 : :
108 : : // Check whether the database already exists or not yet
109 : 557 : run(db_contains_data());
110 : :
111 : : // Verify that the provided path arguments match
112 : : // the paths stored in the database
113 : 557 : run(db_validate_paths());
114 : :
115 : : // Save normalized traversal root prefixes
116 : 557 : run(db_save_prefixes());
117 : :
118 : : // Just get a statistic
119 : 557 : summary->stats_only_pass = true;
120 : 557 : run(file_list(summary));
121 : :
122 : : // Get file list and their checksums
123 : 557 : summary->stats_only_pass = false;
124 : 557 : run(file_list(summary));
125 : :
126 : : // Update the database. Remove files that
127 : : // no longer exist.
128 : 554 : run(db_delete_missing_metadata());
129 : :
130 : : // Print remembered warning and error lines when delayed output is enabled
131 : 554 : call(show_remembered_messages());
132 : :
133 : : // Print final totals and runtime metrics after delayed warnings/errors.
134 : : // This runs only for successful execution flow.
135 [ + + ]: 554 : if((SUCCESS|WARNING) & status)
136 : : {
137 : 518 : show_statistics(summary);
138 : 518 : show_elapsed(summary);
139 : : }
140 : :
141 : : // Disable journaling, flush the journal to the main database,
142 : : // clear the cache, and close the database
143 : 554 : call(db_close(config->db,&config->db_primary_file_modified));
144 : :
145 : : // Optimizing the space occupied by a database file.
146 : 554 : run(db_primary_consider_vacuum());
147 : :
148 : : // Print out whether there have been changes to
149 : : // the file system and accordingly against the database
150 : : // since the last research
151 : 554 : run(status_of_changes());
152 : :
153 : : // Free allocated memory
154 : : // for arrays and variables
155 : 554 : free_config();
156 : :
157 : 554 : return(exit_status(status,argv));
158 : : }
|