In many cases, we compile a C program and execute the binary without concern for changes in the original source file. However, I'm curious:
Is it possible for a running C program to detect if its own .c
source file has been modified after compilation?
Some constraints to consider:
a.out
)md5sum
or stat
via system()
calls.Would this require reading the source file at runtime and comparing timestamps or hashes, or is there a more elegant way to achieve this?
Is it possible for a running C program to detect if its own .c source file has been modified after compilation?
Not without making assumptions about what file(s) those are. There is no enduring connection between compiled binaries and the C source files (and there can be many contributing to a single program) from which the binaries were built. Before the program could even attempt such a check, it would need somehow to determine what files needed to be checked.
And not reliably. At best, the program could check whether the source files selected for testing have the same attributes and contents as the sources it was built from, but it could not rule out some of those having been altered and then changed back between build and run.
And even if the information can be determined, it is not very useful, because it is immediately stale. The program might be able to determine whether certain files it can observe at runtime match files it was built from, but then it knows only that they matched (or not) at the time they were tested. It's not safe to assume that they continue to match for any amount of time after the test, nor even that the result of the test is correct at the time it is initially determined. For instance, perhaps the file is being modified at the same time that it is being tested, such that the state read by the test is already different by the time the test completes.
Would this require reading the source file at runtime and comparing timestamps or hashes, or is there a more elegant way to achieve this?
Having identified the files to be tested -- which is not at all trivial -- there is a question of what information you really want to know.
You can test the current timestamp against one recorded in the binary, but that tells you only whether the timestamps match. That can be your criterion, but it's a very weak one, because timestamps are easily manipulated. On the other hand, it is quick and easy, as it requires reading only the files' metadata, not their contents.
You can compute a hash or checksum of the files, either individually or collectively, and compare that to an expected value stored in the binary. That requires reading every byte of every one of the files, and it delivers a probabilistic result, not a certain one. However, it requires only a hash or checksum value to be stored in the executable. (Or stored in an external file, but then that presents another way in which the test could be confounded.)
You can read every byte of every one of the files, and compare to a copy stored somewhere. C itself does not provide a means for this "somewhere" to be inside the binary, but there are ways to make linkers do that sort of thing. If the storage is external then this approach is only as good as the source copies against which the program tests. If internal, then the copies will take up a fair amount of space in the binary.
I'm not sure what kind of "more elegant" solution you imagine there might be. If you want to learn something about the state of certain files at runtime then you have to examine those files at runtime.