Reputation: 13378
On Mac OS X, using C and/or C++, I want to change the creation time of a file to an arbitrary date/time. I have found a number of solutions, notably this StackOverflow answer, that allow to set the creation time to an older date, but this is not sufficient for me - I also want to be able to set a newer date. Using the utimes()
function therefore is not the solution I am looking for.
I know that setting a newer creation time must be possible somehow, because the SetFile
utility from Apple's developer command line tools can do it, but so far my search-fu has failed to uncover any hints that bring me closer to a solution.
Does anyone know of a way how I can achieve my goal?
Why do I want to do this myself, why can't I use SetFile
?
SetFile
command line utility is deprecated (see man SetFile
), so it's bound to go away some time in the futureSetFile
utility does not have any convenient command line arguments to do this.Upvotes: 1
Views: 1991
Reputation: 90531
Haven't tried it, but according to the docs, the NSURL
resource value under the key NSURLCreationDateKey
is read-write. Since you specified C or C++, you'd use the corresponding CFURL
API. So, you'd call:
CFURLRef url = /* ... */
CFDateRef date = /* ... */
CFErrorRef error;
if (!CFURLSetResourcePropertyForKey(url, kCFURLCreationDateKey, date, &error))
/* handle error */;
EDIT: A minimal example
const char* fileName = "/path/to/file";
size_t fileNameStringLength = strlen(fileName);
Boolean isDirectory = false;
CFURLRef url = CFURLCreateFromFileSystemRepresentation(
kCFAllocatorDefault,
(const UInt8*)fileName,
fileNameStringLength,
isDirectory);
// Seconds since 1 January, 2001 00:00:00 GMT
CFAbsoluteTime absTime = CFAbsoluteTimeGetCurrent();
CFAbsoluteTime adjustedCreationTime = absTime - 3600;
CFDateRef date = CFDateCreate(
kCFAllocatorDefault,
adjustedCreationTime);
CFErrorRef error;
if (!CFURLSetResourcePropertyForKey(url, kCFURLCreationDateKey, date, &error))
{
fprintf(stderr, "an error occurred\n");
exit(1);
}
CFRelease(url);
CFRelease(date);
Upvotes: 2
Reputation: 7435
BTW, I have no idea if this is safe, secure, whatever. So, do this at your own risk.
On OS X, you can sort of do this by setting the time of the day to the future and then copying the file (and renaming it back). It is not the same file with its creation time modified; it is a copy with the creation time you set.
Some code (I got the code to set the time of the day from here):
#include <sys/time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <stdlib.h>
#include <copyfile.h>
#include <unistd.h>
int main(int argc, char *argv[]) {
struct timeval tv_now, tv_set;
copyfile_state_t s;
struct stat st;
// retrieve original stat
if (stat(argv[2], &st) < 0)
perror("stat");
// get current time of day
if (gettimeofday(&tv_now, 0) == -1)
perror("gettimeofday");
// set time of day to +argv[1] days
tv_set = tv_now;
tv_set.tv_sec += 86400 * atoi(argv[1]);
if (settimeofday(&tv_set, 0) == -1)
perror("settimeofday to future");
// copy the file to a temporary, copy everythig except stat
s = copyfile_state_alloc();
if (copyfile(argv[2], ".eighty_eight_miles_per_hour", s, COPYFILE_ACL | COPYFILE_XATTR | COPYFILE_DATA) < 0)
perror("copy file");
copyfile_state_free(s);
// rename it back to original name
if (rename(".eighty_eight_miles_per_hour", argv[2]) < 0)
perror("rename file");
// restore file owner, group, and mode
if (chown(argv[2], st.st_uid, st.st_gid) < 0)
perror("chown");
if (chmod(argv[2], st.st_mode) < 0)
perror("chmod");
// reset current time of day
if (settimeofday(&tv_now, 0) == -1)
perror("settimeofday back to now");
return 0;
}
I call this program the flux_capacitor
. The first command line argument is the number of days forward to set the file's creation date, and the second argument is the file name. You have to run this program as root
to set the time.
Observe, as I send the delorean
forward in time by 2 days.
[ronin:~/Documents/CPP] aichao% touch delorean
[ronin:~/Documents/CPP] aichao% ls -l delorean
-rw-r--r-- 1 aichao staff 0 Aug 10 11:43 delorean
[ronin:~/Documents/CPP] aichao% su
Password:
sh-3.2# ./flux_capacitor 2 delorean
sh-3.2# exit
exit
[ronin:~/Documents/CPP] aichao% ls -l delorean
-rw-r--r-- 1 aichao staff 0 Aug 12 2016 delorean
[ronin:~/Documents/CPP] aichao% date
Wed Aug 10 11:43:47 EDT 2016
and in the Finder:
Note that I only restore the original owner, group, and mode from the stat
for the file. I don't think you can or want to do more than that, but I don't know. Obviously, links to the file will be broken.
Upvotes: 0